summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Parrella <parrella.matthew@gmail.com>2023-03-14 14:43:19 +0000
committerMichael Brown <mcb30@ipxe.org>2023-03-14 14:44:32 +0000
commitbf25e23d07f16be62825650c0826c4eadf2699b6 (patch)
tree477d472293978b0d41252513b2eec4fbe59db885
parent8f1c1201199a924eeba31494be5aa6bf13eb3fa0 (diff)
downloadqemu-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.c16
-rw-r--r--src/drivers/net/intel.h10
2 files changed, 24 insertions, 2 deletions
diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c
index df73c424..46527bdb 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 4f51a80f..29cf3a7d 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 */