Browse Source

[intel] Allow for the use of advanced TX descriptors

Intel virtual function NICs almost work with the use of "legacy"
transmit and receive descriptors (which are backwards compatible right
back to the original Intel Gigabit NICs).

Unfortunately the "TX switching" feature (which allows for VM<->VM
traffic to be looped back within the NIC itself) does not work when a
legacy TX descriptor is used: the packet is instead sent onto the
wire.

Fix by allowing for the use of an "advanced" TX descriptor (containing
exactly the same information as is found in the "legacy" descriptor).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
9e2121be0d
3 changed files with 126 additions and 42 deletions
  1. 75
    17
      src/drivers/net/intel.c
  2. 47
    23
      src/drivers/net/intel.h
  3. 4
    2
      src/drivers/net/intelx.c

+ 75
- 17
src/drivers/net/intel.c View File

@@ -347,6 +347,67 @@ static void intel_check_link ( struct net_device *netdev ) {
347 347
 	}
348 348
 }
349 349
 
350
+/******************************************************************************
351
+ *
352
+ * Descriptors
353
+ *
354
+ ******************************************************************************
355
+ */
356
+
357
+/**
358
+ * Populate transmit descriptor
359
+ *
360
+ * @v tx		Transmit descriptor
361
+ * @v addr		Data buffer address
362
+ * @v len		Length of data
363
+ */
364
+void intel_describe_tx ( struct intel_descriptor *tx, physaddr_t addr,
365
+			 size_t len ) {
366
+
367
+	/* Populate transmit descriptor */
368
+	tx->address = cpu_to_le64 ( addr );
369
+	tx->length = cpu_to_le16 ( len );
370
+	tx->flags = 0;
371
+	tx->command = ( INTEL_DESC_CMD_RS | INTEL_DESC_CMD_IFCS |
372
+			INTEL_DESC_CMD_EOP );
373
+	tx->status = 0;
374
+}
375
+
376
+/**
377
+ * Populate advanced transmit descriptor
378
+ *
379
+ * @v tx		Transmit descriptor
380
+ * @v addr		Data buffer address
381
+ * @v len		Length of data
382
+ */
383
+void intel_describe_tx_adv ( struct intel_descriptor *tx, physaddr_t addr,
384
+			     size_t len ) {
385
+
386
+	/* Populate advanced transmit descriptor */
387
+	tx->address = cpu_to_le64 ( addr );
388
+	tx->length = cpu_to_le16 ( len );
389
+	tx->flags = INTEL_DESC_FL_DTYP_DATA;
390
+	tx->command = ( INTEL_DESC_CMD_DEXT | INTEL_DESC_CMD_RS |
391
+			INTEL_DESC_CMD_IFCS | INTEL_DESC_CMD_EOP );
392
+	tx->status = cpu_to_le32 ( INTEL_DESC_STATUS_PAYLEN ( len ) );
393
+}
394
+
395
+/**
396
+ * Populate receive descriptor
397
+ *
398
+ * @v rx		Receive descriptor
399
+ * @v addr		Data buffer address
400
+ * @v len		Length of data
401
+ */
402
+void intel_describe_rx ( struct intel_descriptor *rx, physaddr_t addr,
403
+			 size_t len __unused ) {
404
+
405
+	/* Populate transmit descriptor */
406
+	rx->address = cpu_to_le64 ( addr );
407
+	rx->length = 0;
408
+	rx->status = 0;
409
+}
410
+
350 411
 /******************************************************************************
351 412
  *
352 413
  * Network device interface
@@ -457,10 +518,7 @@ void intel_refill_rx ( struct intel_nic *intel ) {
457 518
 
458 519
 		/* Populate receive descriptor */
459 520
 		address = virt_to_bus ( iobuf->data );
460
-		rx->address = cpu_to_le64 ( address );
461
-		rx->length = 0;
462
-		rx->status = 0;
463
-		rx->errors = 0;
521
+		intel->rx.describe ( rx, address, 0 );
464 522
 
465 523
 		/* Record I/O buffer */
466 524
 		assert ( intel->rx_iobuf[rx_idx] == NULL );
@@ -602,6 +660,7 @@ int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
602 660
 	unsigned int tx_idx;
603 661
 	unsigned int tx_tail;
604 662
 	physaddr_t address;
663
+	size_t len;
605 664
 
606 665
 	/* Get next transmit descriptor */
607 666
 	if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_TX_FILL ) {
@@ -614,11 +673,8 @@ int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
614 673
 
615 674
 	/* Populate transmit descriptor */
616 675
 	address = virt_to_bus ( iobuf->data );
617
-	tx->address = cpu_to_le64 ( address );
618
-	tx->length = cpu_to_le16 ( iob_len ( iobuf ) );
619
-	tx->command = ( INTEL_DESC_CMD_RS | INTEL_DESC_CMD_IFCS |
620
-			INTEL_DESC_CMD_EOP );
621
-	tx->status = 0;
676
+	len = iob_len ( iobuf );
677
+	intel->tx.describe ( tx, address, len );
622 678
 	wmb();
623 679
 
624 680
 	/* Notify card that there are packets ready to transmit */
@@ -629,7 +685,7 @@ int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
629 685
 
630 686
 	DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx,
631 687
 		( ( unsigned long long ) address ),
632
-		( ( unsigned long long ) address + iob_len ( iobuf ) ) );
688
+		( ( unsigned long long ) address + len ) );
633 689
 
634 690
 	return 0;
635 691
 }
@@ -652,7 +708,7 @@ void intel_poll_tx ( struct net_device *netdev ) {
652 708
 		tx = &intel->tx.desc[tx_idx];
653 709
 
654 710
 		/* Stop if descriptor is still in use */
655
-		if ( ! ( tx->status & INTEL_DESC_STATUS_DD ) )
711
+		if ( ! ( tx->status & cpu_to_le32 ( INTEL_DESC_STATUS_DD ) ) )
656 712
 			return;
657 713
 
658 714
 		DBGC2 ( intel, "INTEL %p TX %d complete\n", intel, tx_idx );
@@ -683,7 +739,7 @@ void intel_poll_rx ( struct net_device *netdev ) {
683 739
 		rx = &intel->rx.desc[rx_idx];
684 740
 
685 741
 		/* Stop if descriptor is still in use */
686
-		if ( ! ( rx->status & INTEL_DESC_STATUS_DD ) )
742
+		if ( ! ( rx->status & cpu_to_le32 ( INTEL_DESC_STATUS_DD ) ) )
687 743
 			return;
688 744
 
689 745
 		/* Populate I/O buffer */
@@ -693,10 +749,10 @@ void intel_poll_rx ( struct net_device *netdev ) {
693 749
 		iob_put ( iobuf, len );
694 750
 
695 751
 		/* Hand off to network stack */
696
-		if ( rx->errors ) {
752
+		if ( rx->status & cpu_to_le32 ( INTEL_DESC_STATUS_RXE ) ) {
697 753
 			DBGC ( intel, "INTEL %p RX %d error (length %zd, "
698
-			       "errors %02x)\n",
699
-			       intel, rx_idx, len, rx->errors );
754
+			       "status %08x)\n", intel, rx_idx, len,
755
+			       le32_to_cpu ( rx->status ) );
700 756
 			netdev_rx_err ( netdev, iobuf, -EIO );
701 757
 		} else {
702 758
 			DBGC2 ( intel, "INTEL %p RX %d complete (length %zd)\n",
@@ -811,8 +867,10 @@ static int intel_probe ( struct pci_device *pci ) {
811 867
 	memset ( intel, 0, sizeof ( *intel ) );
812 868
 	intel->port = PCI_FUNC ( pci->busdevfn );
813 869
 	intel->flags = pci->id->driver_data;
814
-	intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD );
815
-	intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD );
870
+	intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD,
871
+			  intel_describe_tx );
872
+	intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD,
873
+			  intel_describe_rx );
816 874
 
817 875
 	/* Fix up PCI device */
818 876
 	adjust_pci_device ( pci );

+ 47
- 23
src/drivers/net/intel.h View File

@@ -22,33 +22,38 @@ struct intel_descriptor {
22 22
 	uint64_t address;
23 23
 	/** Length */
24 24
 	uint16_t length;
25
-	/** Reserved */
26
-	uint8_t reserved_a;
25
+	/** Flags */
26
+	uint8_t flags;
27 27
 	/** Command */
28 28
 	uint8_t command;
29 29
 	/** Status */
30
-	uint8_t status;
31
-	/** Errors */
32
-	uint8_t errors;
33
-	/** Reserved */
34
-	uint16_t reserved_b;
30
+	uint32_t status;
35 31
 } __attribute__ (( packed ));
36 32
 
37
-/** Packet descriptor command bits */
38
-enum intel_descriptor_command {
39
-	/** Report status */
40
-	INTEL_DESC_CMD_RS = 0x08,
41
-	/** Insert frame checksum (CRC) */
42
-	INTEL_DESC_CMD_IFCS = 0x02,
43
-	/** End of packet */
44
-	INTEL_DESC_CMD_EOP = 0x01,
45
-};
33
+/** Descriptor type */
34
+#define INTEL_DESC_FL_DTYP( dtyp ) ( (dtyp) << 4 )
35
+#define INTEL_DESC_FL_DTYP_DATA INTEL_DESC_FL_DTYP ( 0x03 )
46 36
 
47
-/** Packet descriptor status bits */
48
-enum intel_descriptor_status {
49
-	/** Descriptor done */
50
-	INTEL_DESC_STATUS_DD = 0x01,
51
-};
37
+/** Descriptor extension */
38
+#define INTEL_DESC_CMD_DEXT 0x20
39
+
40
+/** Report status */
41
+#define INTEL_DESC_CMD_RS 0x08
42
+
43
+/** Insert frame checksum (CRC) */
44
+#define INTEL_DESC_CMD_IFCS 0x02
45
+
46
+/** End of packet */
47
+#define INTEL_DESC_CMD_EOP 0x01
48
+
49
+/** Descriptor done */
50
+#define INTEL_DESC_STATUS_DD 0x00000001UL
51
+
52
+/** Receive error */
53
+#define INTEL_DESC_STATUS_RXE 0x00000100UL
54
+
55
+/** Payload length */
56
+#define INTEL_DESC_STATUS_PAYLEN( len ) ( (len) << 14 )
52 57
 
53 58
 /** Device Control Register */
54 59
 #define INTEL_CTRL 0x00000UL
@@ -209,6 +214,15 @@ struct intel_ring {
209 214
 	unsigned int reg;
210 215
 	/** Length (in bytes) */
211 216
 	size_t len;
217
+
218
+	/** Populate descriptor
219
+	 *
220
+	 * @v desc		Descriptor
221
+	 * @v addr		Data buffer address
222
+	 * @v len		Length of data
223
+	 */
224
+	void ( * describe ) ( struct intel_descriptor *desc, physaddr_t addr,
225
+			      size_t len );
212 226
 };
213 227
 
214 228
 /**
@@ -217,12 +231,16 @@ struct intel_ring {
217 231
  * @v ring		Descriptor ring
218 232
  * @v count		Number of descriptors
219 233
  * @v reg		Descriptor register block
234
+ * @v describe		Method to populate descriptor
220 235
  */
221 236
 static inline __attribute__ (( always_inline)) void
222
-intel_init_ring ( struct intel_ring *ring, unsigned int count,
223
-		  unsigned int reg ) {
237
+intel_init_ring ( struct intel_ring *ring, unsigned int count, unsigned int reg,
238
+		  void ( * describe ) ( struct intel_descriptor *desc,
239
+					physaddr_t addr, size_t len ) ) {
240
+
224 241
 	ring->len = ( count * sizeof ( ring->desc[0] ) );
225 242
 	ring->reg = reg;
243
+	ring->describe = describe;
226 244
 }
227 245
 
228 246
 /** An Intel network card */
@@ -278,6 +296,12 @@ static inline void intel_diag ( struct intel_nic *intel ) {
278 296
 	       readl ( intel->regs + intel->rx.reg + INTEL_xDT ) );
279 297
 }
280 298
 
299
+extern void intel_describe_tx ( struct intel_descriptor *tx,
300
+				physaddr_t addr, size_t len );
301
+extern void intel_describe_tx_adv ( struct intel_descriptor *tx,
302
+				    physaddr_t addr, size_t len );
303
+extern void intel_describe_rx ( struct intel_descriptor *rx,
304
+				physaddr_t addr, size_t len );
281 305
 extern int intel_create_ring ( struct intel_nic *intel,
282 306
 			       struct intel_ring *ring );
283 307
 extern void intel_destroy_ring ( struct intel_nic *intel,

+ 4
- 2
src/drivers/net/intelx.c View File

@@ -396,8 +396,10 @@ static int intelx_probe ( struct pci_device *pci ) {
396 396
 	netdev->dev = &pci->dev;
397 397
 	memset ( intel, 0, sizeof ( *intel ) );
398 398
 	intel->port = PCI_FUNC ( pci->busdevfn );
399
-	intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELX_TD );
400
-	intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELX_RD );
399
+	intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELX_TD,
400
+			  intel_describe_tx );
401
+	intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELX_RD,
402
+			  intel_describe_rx );
401 403
 
402 404
 	/* Fix up PCI device */
403 405
 	adjust_pci_device ( pci );

Loading…
Cancel
Save