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
 	}
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
  * Network device interface
413
  * Network device interface
457
 
518
 
458
 		/* Populate receive descriptor */
519
 		/* Populate receive descriptor */
459
 		address = virt_to_bus ( iobuf->data );
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
 		/* Record I/O buffer */
523
 		/* Record I/O buffer */
466
 		assert ( intel->rx_iobuf[rx_idx] == NULL );
524
 		assert ( intel->rx_iobuf[rx_idx] == NULL );
602
 	unsigned int tx_idx;
660
 	unsigned int tx_idx;
603
 	unsigned int tx_tail;
661
 	unsigned int tx_tail;
604
 	physaddr_t address;
662
 	physaddr_t address;
663
+	size_t len;
605
 
664
 
606
 	/* Get next transmit descriptor */
665
 	/* Get next transmit descriptor */
607
 	if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_TX_FILL ) {
666
 	if ( ( intel->tx.prod - intel->tx.cons ) >= INTEL_TX_FILL ) {
614
 
673
 
615
 	/* Populate transmit descriptor */
674
 	/* Populate transmit descriptor */
616
 	address = virt_to_bus ( iobuf->data );
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
 	wmb();
678
 	wmb();
623
 
679
 
624
 	/* Notify card that there are packets ready to transmit */
680
 	/* Notify card that there are packets ready to transmit */
629
 
685
 
630
 	DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx,
686
 	DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx,
631
 		( ( unsigned long long ) address ),
687
 		( ( unsigned long long ) address ),
632
-		( ( unsigned long long ) address + iob_len ( iobuf ) ) );
688
+		( ( unsigned long long ) address + len ) );
633
 
689
 
634
 	return 0;
690
 	return 0;
635
 }
691
 }
652
 		tx = &intel->tx.desc[tx_idx];
708
 		tx = &intel->tx.desc[tx_idx];
653
 
709
 
654
 		/* Stop if descriptor is still in use */
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
 			return;
712
 			return;
657
 
713
 
658
 		DBGC2 ( intel, "INTEL %p TX %d complete\n", intel, tx_idx );
714
 		DBGC2 ( intel, "INTEL %p TX %d complete\n", intel, tx_idx );
683
 		rx = &intel->rx.desc[rx_idx];
739
 		rx = &intel->rx.desc[rx_idx];
684
 
740
 
685
 		/* Stop if descriptor is still in use */
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
 			return;
743
 			return;
688
 
744
 
689
 		/* Populate I/O buffer */
745
 		/* Populate I/O buffer */
693
 		iob_put ( iobuf, len );
749
 		iob_put ( iobuf, len );
694
 
750
 
695
 		/* Hand off to network stack */
751
 		/* Hand off to network stack */
696
-		if ( rx->errors ) {
752
+		if ( rx->status & cpu_to_le32 ( INTEL_DESC_STATUS_RXE ) ) {
697
 			DBGC ( intel, "INTEL %p RX %d error (length %zd, "
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
 			netdev_rx_err ( netdev, iobuf, -EIO );
756
 			netdev_rx_err ( netdev, iobuf, -EIO );
701
 		} else {
757
 		} else {
702
 			DBGC2 ( intel, "INTEL %p RX %d complete (length %zd)\n",
758
 			DBGC2 ( intel, "INTEL %p RX %d complete (length %zd)\n",
811
 	memset ( intel, 0, sizeof ( *intel ) );
867
 	memset ( intel, 0, sizeof ( *intel ) );
812
 	intel->port = PCI_FUNC ( pci->busdevfn );
868
 	intel->port = PCI_FUNC ( pci->busdevfn );
813
 	intel->flags = pci->id->driver_data;
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
 	/* Fix up PCI device */
875
 	/* Fix up PCI device */
818
 	adjust_pci_device ( pci );
876
 	adjust_pci_device ( pci );

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

22
 	uint64_t address;
22
 	uint64_t address;
23
 	/** Length */
23
 	/** Length */
24
 	uint16_t length;
24
 	uint16_t length;
25
-	/** Reserved */
26
-	uint8_t reserved_a;
25
+	/** Flags */
26
+	uint8_t flags;
27
 	/** Command */
27
 	/** Command */
28
 	uint8_t command;
28
 	uint8_t command;
29
 	/** Status */
29
 	/** Status */
30
-	uint8_t status;
31
-	/** Errors */
32
-	uint8_t errors;
33
-	/** Reserved */
34
-	uint16_t reserved_b;
30
+	uint32_t status;
35
 } __attribute__ (( packed ));
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
 /** Device Control Register */
58
 /** Device Control Register */
54
 #define INTEL_CTRL 0x00000UL
59
 #define INTEL_CTRL 0x00000UL
209
 	unsigned int reg;
214
 	unsigned int reg;
210
 	/** Length (in bytes) */
215
 	/** Length (in bytes) */
211
 	size_t len;
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
  * @v ring		Descriptor ring
231
  * @v ring		Descriptor ring
218
  * @v count		Number of descriptors
232
  * @v count		Number of descriptors
219
  * @v reg		Descriptor register block
233
  * @v reg		Descriptor register block
234
+ * @v describe		Method to populate descriptor
220
  */
235
  */
221
 static inline __attribute__ (( always_inline)) void
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
 	ring->len = ( count * sizeof ( ring->desc[0] ) );
241
 	ring->len = ( count * sizeof ( ring->desc[0] ) );
225
 	ring->reg = reg;
242
 	ring->reg = reg;
243
+	ring->describe = describe;
226
 }
244
 }
227
 
245
 
228
 /** An Intel network card */
246
 /** An Intel network card */
278
 	       readl ( intel->regs + intel->rx.reg + INTEL_xDT ) );
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
 extern int intel_create_ring ( struct intel_nic *intel,
305
 extern int intel_create_ring ( struct intel_nic *intel,
282
 			       struct intel_ring *ring );
306
 			       struct intel_ring *ring );
283
 extern void intel_destroy_ring ( struct intel_nic *intel,
307
 extern void intel_destroy_ring ( struct intel_nic *intel,

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

396
 	netdev->dev = &pci->dev;
396
 	netdev->dev = &pci->dev;
397
 	memset ( intel, 0, sizeof ( *intel ) );
397
 	memset ( intel, 0, sizeof ( *intel ) );
398
 	intel->port = PCI_FUNC ( pci->busdevfn );
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
 	/* Fix up PCI device */
404
 	/* Fix up PCI device */
403
 	adjust_pci_device ( pci );
405
 	adjust_pci_device ( pci );

Loading…
Cancel
Save