diff options
author | Matt Parrella <parrella.matthew@gmail.com> | 2023-03-14 14:43:19 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-03-14 14:44:32 +0000 |
commit | bf25e23d07f16be62825650c0826c4eadf2699b6 (patch) | |
tree | 477d472293978b0d41252513b2eec4fbe59db885 | |
parent | 8f1c1201199a924eeba31494be5aa6bf13eb3fa0 (diff) | |
download | ipxe-bf25e23d07f16be62825650c0826c4eadf2699b6.tar.gz |
[intel] Add workaround for I210 reset hardware bugs
The Intel I210's packet buffer size registers reset only on power up,
not when a reset signal is asserted. This can lead to the inability
to pass traffic in the event that the DMA TX Maximum Packet Size
(which does reset to its default value on reset) is bigger than the TX
Packet Buffer Size.
For example, an operating system may be using the time sensitive
networking features of the I210 and the registers may be programmed
correctly, but then a reset signal is asserted and iPXE on the next
boot will be unable to use the I210.
Mimic what Linux does and forcibly set the registers to their default
values.
Signed-off-by: Matt Parrella <parrella.matthew@gmail.com>
-rw-r--r-- | src/drivers/net/intel.c | 16 | ||||
-rw-r--r-- | src/drivers/net/intel.h | 10 |
2 files changed, 24 insertions, 2 deletions
diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index df73c4249..46527bdbb 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -290,6 +290,18 @@ static int intel_reset ( struct intel_nic *intel ) { pba, readl ( intel->regs + INTEL_PBA ) ); } + /* The Intel I210's packet buffer size registers reset only on + * power up. If an operating system changes these but then + * the computer recieves a reset signal without losing power, + * the registers will stay the same (but be incompatible with + * other register defaults), thus making the device unable to + * pass traffic. + */ + if ( intel->flags & INTEL_PBSIZE_RST ) { + writel ( INTEL_RXPBS_I210, intel->regs + INTEL_RXPBS ); + writel ( INTEL_TXPBS_I210, intel->regs + INTEL_TXPBS ); + } + /* Always reset MAC. Required to reset the TX and RX rings. */ writel ( ( ctrl | INTEL_CTRL_RST ), intel->regs + INTEL_CTRL ); mdelay ( INTEL_RESET_DELAY_MS ); @@ -1139,7 +1151,7 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x1525, "82567v-4", "82567V-4", 0 ), PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ), PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ), - PCI_ROM ( 0x8086, 0x1533, "i210", "I210", 0 ), + PCI_ROM ( 0x8086, 0x1533, "i210", "I210", INTEL_PBSIZE_RST ), PCI_ROM ( 0x8086, 0x1539, "i211", "I211", 0 ), PCI_ROM ( 0x8086, 0x153a, "i217lm", "I217-LM", INTEL_NO_PHY_RST ), PCI_ROM ( 0x8086, 0x153b, "i217v", "I217-V", 0 ), @@ -1147,7 +1159,7 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x155a, "i218lm", "I218-LM", INTEL_NO_PHY_RST ), PCI_ROM ( 0x8086, 0x156f, "i219lm", "I219-LM", INTEL_I219 ), PCI_ROM ( 0x8086, 0x1570, "i219v", "I219-V", INTEL_I219 ), - PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", 0 ), + PCI_ROM ( 0x8086, 0x157b, "i210-2", "I210", INTEL_PBSIZE_RST ), PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", INTEL_NO_PHY_RST ), PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ), PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", INTEL_NO_PHY_RST ), diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h index 4f51a80f6..29cf3a7d8 100644 --- a/src/drivers/net/intel.h +++ b/src/drivers/net/intel.h @@ -138,6 +138,10 @@ struct intel_descriptor { /** Packet Buffer Size */ #define INTEL_PBS 0x01008UL +/** Receive packet buffer size */ +#define INTEL_RXPBS 0x02404UL +#define INTEL_RXPBS_I210 0x000000a2UL /**< I210 power-up default */ + /** Receive Descriptor register block */ #define INTEL_RD 0x02800UL @@ -154,6 +158,10 @@ struct intel_descriptor { /** Receive buffer length */ #define INTEL_RX_MAX_LEN 2048 +/** Transmit packet buffer size */ +#define INTEL_TXPBS 0x03404UL +#define INTEL_TXPBS_I210 0x04000014UL /**< I210 power-up default */ + /** Transmit Descriptor register block */ #define INTEL_TD 0x03800UL @@ -319,6 +327,8 @@ enum intel_flags { INTEL_NO_ASDE = 0x0008, /** Reset may cause a complete device hang */ INTEL_RST_HANG = 0x0010, + /** PBSIZE registers must be explicitly reset */ + INTEL_PBSIZE_RST = 0x0020, }; /** The i219 has a seriously broken reset mechanism */ |