Browse Source

[intel] Work around broken reset mechanism in i219 devices

The i219 appears to have a seriously broken reset mechanism.  After
any transmit or receive activity, resetting the card will break both
the transmit and receive datapaths until the next PCI bus reset.

The Linux and BSD drivers include a convoluted workaround authored by
Intel which involves setting a bit in the undocumented FEXTNVM11
register, then transmitting a dummy 512-byte packet containing garbage
data, then reconfiguring the receive descriptor prefetch thresholds
and temporarily reenabling the receive datapath.  The comments in the
Intel fix do not even remotely match what the code actually does, and
the code accidentally leaves the transmitter enabled after use.

Experimentation suggests that an equivalent fix is to simply set the
undocumented bit in FEXTNVM11 before enabling the transmit or receive
descriptor rings.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 6 years ago
parent
commit
546dd51de8
2 changed files with 31 additions and 9 deletions
  1. 22
    9
      src/drivers/net/intel.c
  2. 9
    0
      src/drivers/net/intel.h

+ 22
- 9
src/drivers/net/intel.c View File

@@ -635,10 +635,23 @@ void intel_empty_rx ( struct intel_nic *intel ) {
635 635
 static int intel_open ( struct net_device *netdev ) {
636 636
 	struct intel_nic *intel = netdev->priv;
637 637
 	union intel_receive_address mac;
638
+	uint32_t fextnvm11;
638 639
 	uint32_t tctl;
639 640
 	uint32_t rctl;
640 641
 	int rc;
641 642
 
643
+	/* Set undocumented bit in FEXTNVM11 to work around an errata
644
+	 * in i219 devices that will otherwise cause a complete
645
+	 * datapath hang at the next device reset.
646
+	 */
647
+	if ( intel->flags & INTEL_RST_HANG ) {
648
+		DBGC ( intel, "INTEL %p WARNING: applying reset hang "
649
+		       "workaround\n", intel );
650
+		fextnvm11 = readl ( intel->regs + INTEL_FEXTNVM11 );
651
+		fextnvm11 |= INTEL_FEXTNVM11_WTF;
652
+		writel ( fextnvm11, intel->regs + INTEL_FEXTNVM11 );
653
+	}
654
+
642 655
 	/* Create transmit descriptor ring */
643 656
 	if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
644 657
 		goto err_create_tx;
@@ -1123,20 +1136,20 @@ static struct pci_device_id intel_nics[] = {
1123 1136
 	PCI_ROM ( 0x8086, 0x153b, "i217v", "I217-V", 0 ),
1124 1137
 	PCI_ROM ( 0x8086, 0x1559, "i218v", "I218-V", 0),
1125 1138
 	PCI_ROM ( 0x8086, 0x155a, "i218lm", "I218-LM", 0),
1126
-	PCI_ROM ( 0x8086, 0x156f, "i219lm", "I219-LM", 0 ),
1127
-	PCI_ROM ( 0x8086, 0x1570, "i219v", "I219-V", INTEL_NO_PHY_RST ),
1139
+	PCI_ROM ( 0x8086, 0x156f, "i219lm", "I219-LM", INTEL_I219 ),
1140
+	PCI_ROM ( 0x8086, 0x1570, "i219v", "I219-V", INTEL_I219 ),
1128 1141
 	PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", 0 ),
1129 1142
 	PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", INTEL_NO_PHY_RST ),
1130 1143
 	PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ),
1131 1144
 	PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", INTEL_NO_PHY_RST ),
1132 1145
 	PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", INTEL_NO_PHY_RST ),
1133
-	PCI_ROM ( 0x8086, 0x15b7, "i219lm-2", "I219-LM (2)", INTEL_NO_PHY_RST ),
1134
-	PCI_ROM ( 0x8086, 0x15b8, "i219v-2", "I219-V (2)", 0 ),
1135
-	PCI_ROM ( 0x8086, 0x15b9, "i219lm-3", "I219-LM (3)", INTEL_NO_PHY_RST ),
1136
-	PCI_ROM ( 0x8086, 0x15d6, "i219v-5", "I219-V (5)", INTEL_NO_PHY_RST ),
1137
-	PCI_ROM ( 0x8086, 0x15d7, "i219lm-4", "I219-LM (4)", INTEL_NO_PHY_RST ),
1138
-	PCI_ROM ( 0x8086, 0x15d8, "i219v-4", "I219-V (4)", INTEL_NO_PHY_RST ),
1139
-	PCI_ROM ( 0x8086, 0x15e3, "i219lm-5", "I219-LM (5)", INTEL_NO_PHY_RST ),
1146
+	PCI_ROM ( 0x8086, 0x15b7, "i219lm-2", "I219-LM (2)", INTEL_I219 ),
1147
+	PCI_ROM ( 0x8086, 0x15b8, "i219v-2", "I219-V (2)", INTEL_I219 ),
1148
+	PCI_ROM ( 0x8086, 0x15b9, "i219lm-3", "I219-LM (3)", INTEL_I219 ),
1149
+	PCI_ROM ( 0x8086, 0x15d6, "i219v-5", "I219-V (5)", INTEL_I219 ),
1150
+	PCI_ROM ( 0x8086, 0x15d7, "i219lm-4", "I219-LM (4)", INTEL_I219 ),
1151
+	PCI_ROM ( 0x8086, 0x15d8, "i219v-4", "I219-V (4)", INTEL_I219 ),
1152
+	PCI_ROM ( 0x8086, 0x15e3, "i219lm-5", "I219-LM (5)", INTEL_I219 ),
1140 1153
 	PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ),
1141 1154
 	PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ),
1142 1155
 };

+ 9
- 0
src/drivers/net/intel.h View File

@@ -195,6 +195,10 @@ struct intel_descriptor {
195 195
 #define INTEL_RAH0 0x05404UL
196 196
 #define INTEL_RAH0_AV		0x80000000UL	/**< Address valid */
197 197
 
198
+/** Future Extended NVM register 11 */
199
+#define INTEL_FEXTNVM11 0x05bbcUL
200
+#define INTEL_FEXTNVM11_WTF	0x00002000UL	/**< Don't ask */
201
+
198 202
 /** Receive address */
199 203
 union intel_receive_address {
200 204
 	struct {
@@ -308,8 +312,13 @@ enum intel_flags {
308 312
 	INTEL_NO_PHY_RST = 0x0004,
309 313
 	/** ASDE is broken */
310 314
 	INTEL_NO_ASDE = 0x0008,
315
+	/** Reset may cause a complete device hang */
316
+	INTEL_RST_HANG = 0x0010,
311 317
 };
312 318
 
319
+/** The i219 has a seriously broken reset mechanism */
320
+#define INTEL_I219 ( INTEL_NO_PHY_RST | INTEL_RST_HANG )
321
+
313 322
 /**
314 323
  * Dump diagnostic information
315 324
  *

Loading…
Cancel
Save