Skip to content

Commit 546dd51

Browse files
committedFeb 3, 2018
[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>
1 parent c900751 commit 546dd51

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed
 

‎src/drivers/net/intel.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -635,10 +635,23 @@ void intel_empty_rx ( struct intel_nic *intel ) {
635635
static int intel_open ( struct net_device *netdev ) {
636636
struct intel_nic *intel = netdev->priv;
637637
union intel_receive_address mac;
638+
uint32_t fextnvm11;
638639
uint32_t tctl;
639640
uint32_t rctl;
640641
int rc;
641642

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+
642655
/* Create transmit descriptor ring */
643656
if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 )
644657
goto err_create_tx;
@@ -1123,20 +1136,20 @@ static struct pci_device_id intel_nics[] = {
11231136
PCI_ROM ( 0x8086, 0x153b, "i217v", "I217-V", 0 ),
11241137
PCI_ROM ( 0x8086, 0x1559, "i218v", "I218-V", 0),
11251138
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 ),
11281141
PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", 0 ),
11291142
PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", INTEL_NO_PHY_RST ),
11301143
PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ),
11311144
PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", INTEL_NO_PHY_RST ),
11321145
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 ),
11401153
PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ),
11411154
PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ),
11421155
};

‎src/drivers/net/intel.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ struct intel_descriptor {
195195
#define INTEL_RAH0 0x05404UL
196196
#define INTEL_RAH0_AV 0x80000000UL /**< Address valid */
197197

198+
/** Future Extended NVM register 11 */
199+
#define INTEL_FEXTNVM11 0x05bbcUL
200+
#define INTEL_FEXTNVM11_WTF 0x00002000UL /**< Don't ask */
201+
198202
/** Receive address */
199203
union intel_receive_address {
200204
struct {
@@ -308,8 +312,13 @@ enum intel_flags {
308312
INTEL_NO_PHY_RST = 0x0004,
309313
/** ASDE is broken */
310314
INTEL_NO_ASDE = 0x0008,
315+
/** Reset may cause a complete device hang */
316+
INTEL_RST_HANG = 0x0010,
311317
};
312318

319+
/** The i219 has a seriously broken reset mechanism */
320+
#define INTEL_I219 ( INTEL_NO_PHY_RST | INTEL_RST_HANG )
321+
313322
/**
314323
* Dump diagnostic information
315324
*

0 commit comments

Comments
 (0)