]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[intel] Forcibly skip PHY reset on some models
authorMichael Brown <mcb30@ipxe.org>
Sun, 22 Nov 2015 18:35:50 +0000 (18:35 +0000)
committerMichael Brown <mcb30@ipxe.org>
Sun, 22 Nov 2015 19:08:09 +0000 (19:08 +0000)
On some models (notably ICH), the PHY reset mechanism appears to be
broken.  In particular, the PHY_CTRL register will be correctly loaded
from NVM but the values will not be propagated to the "OEM bits" PHY
register.  This typically has the effect of dropping the link speed to
10Mbps.

Since the original version of this driver in commit 945e428 ("[intel]
Replace driver for Intel Gigabit NICs"), we have always worked around
this problem by skipping the PHY reset if the link is already up.
Enhance this workaround by explicitly checking for known-broken PCI
IDs.

Reported-by: Robin Smidsrød <robin@smidsrod.no>
Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/net/intel.c
src/drivers/net/intel.h

index 2326bc5287e4403de8c0526fadf9e11c8cf24b96..e155b644dd5129561509789ac64e7d28342e374e 100644 (file)
@@ -295,14 +295,23 @@ static int intel_reset ( struct intel_nic *intel ) {
        writel ( ctrl, intel->regs + INTEL_CTRL );
        mdelay ( INTEL_RESET_DELAY_MS );
 
-       /* If link is already up, do not attempt to reset the PHY.  On
-        * some models (notably ICH), performing a PHY reset seems to
-        * drop the link speed to 10Mbps.
+       /* On some models (notably ICH), the PHY reset mechanism
+        * appears to be broken.  In particular, the PHY_CTRL register
+        * will be correctly loaded from NVM but the values will not
+        * be propagated to the "OEM bits" PHY register.  This
+        * typically has the effect of dropping the link speed to
+        * 10Mbps.
+        *
+        * Work around this problem by skipping the PHY reset if
+        * either (a) the link is already up, or (b) this particular
+        * NIC is known to be broken.
         */
        status = readl ( intel->regs + INTEL_STATUS );
-       if ( status & INTEL_STATUS_LU ) {
-               DBGC ( intel, "INTEL %p MAC reset (ctrl %08x)\n",
-                      intel, ctrl );
+       if ( ( intel->flags & INTEL_NO_PHY_RST ) ||
+            ( status & INTEL_STATUS_LU ) ) {
+               DBGC ( intel, "INTEL %p %sMAC reset (ctrl %08x)\n", intel,
+                      ( ( intel->flags & INTEL_NO_PHY_RST ) ? "forced " : "" ),
+                      ctrl );
                return 0;
        }
 
@@ -1029,7 +1038,7 @@ static struct pci_device_id intel_nics[] = {
        PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ),
        PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ),
        PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", INTEL_PBS_ERRATA ),
-       PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ),
+       PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", INTEL_NO_PHY_RST ),
        PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ),
        PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ),
        PCI_ROM ( 0x8086, 0x150c, "82583v", "82583V", 0 ),
@@ -1057,7 +1066,7 @@ static struct pci_device_id intel_nics[] = {
        PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", 0 ),
        PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ),
        PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", 0 ),
-       PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", 0 ),
+       PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", INTEL_NO_PHY_RST ),
        PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ),
        PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ),
 };
index ce9e3f467d414d0131eab872df546df42043f739..436229ef601af8d32e632af57d14c3b49c3157e1 100644 (file)
@@ -301,6 +301,8 @@ enum intel_flags {
        INTEL_PBS_ERRATA = 0x0001,
        /** VMware missing interrupt workaround required */
        INTEL_VMWARE = 0x0002,
+       /** PHY reset is broken */
+       INTEL_NO_PHY_RST = 0x0004,
 };
 
 /**