Browse Source

[intel] Forcibly skip PHY reset on some models

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>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
fff9281b84
2 changed files with 19 additions and 8 deletions
  1. 17
    8
      src/drivers/net/intel.c
  2. 2
    0
      src/drivers/net/intel.h

+ 17
- 8
src/drivers/net/intel.c View File

@@ -295,14 +295,23 @@ static int intel_reset ( struct intel_nic *intel ) {
295 295
 	writel ( ctrl, intel->regs + INTEL_CTRL );
296 296
 	mdelay ( INTEL_RESET_DELAY_MS );
297 297
 
298
-	/* If link is already up, do not attempt to reset the PHY.  On
299
-	 * some models (notably ICH), performing a PHY reset seems to
300
-	 * drop the link speed to 10Mbps.
298
+	/* On some models (notably ICH), the PHY reset mechanism
299
+	 * appears to be broken.  In particular, the PHY_CTRL register
300
+	 * will be correctly loaded from NVM but the values will not
301
+	 * be propagated to the "OEM bits" PHY register.  This
302
+	 * typically has the effect of dropping the link speed to
303
+	 * 10Mbps.
304
+	 *
305
+	 * Work around this problem by skipping the PHY reset if
306
+	 * either (a) the link is already up, or (b) this particular
307
+	 * NIC is known to be broken.
301 308
 	 */
302 309
 	status = readl ( intel->regs + INTEL_STATUS );
303
-	if ( status & INTEL_STATUS_LU ) {
304
-		DBGC ( intel, "INTEL %p MAC reset (ctrl %08x)\n",
305
-		       intel, ctrl );
310
+	if ( ( intel->flags & INTEL_NO_PHY_RST ) ||
311
+	     ( status & INTEL_STATUS_LU ) ) {
312
+		DBGC ( intel, "INTEL %p %sMAC reset (ctrl %08x)\n", intel,
313
+		       ( ( intel->flags & INTEL_NO_PHY_RST ) ? "forced " : "" ),
314
+		       ctrl );
306 315
 		return 0;
307 316
 	}
308 317
 
@@ -1029,7 +1038,7 @@ static struct pci_device_id intel_nics[] = {
1029 1038
 	PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ),
1030 1039
 	PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ),
1031 1040
 	PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", INTEL_PBS_ERRATA ),
1032
-	PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ),
1041
+	PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", INTEL_NO_PHY_RST ),
1033 1042
 	PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ),
1034 1043
 	PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ),
1035 1044
 	PCI_ROM ( 0x8086, 0x150c, "82583v", "82583V", 0 ),
@@ -1057,7 +1066,7 @@ static struct pci_device_id intel_nics[] = {
1057 1066
 	PCI_ROM ( 0x8086, 0x15a0, "i218lm-2", "I218-LM", 0 ),
1058 1067
 	PCI_ROM ( 0x8086, 0x15a1, "i218v-2", "I218-V", 0 ),
1059 1068
 	PCI_ROM ( 0x8086, 0x15a2, "i218lm-3", "I218-LM", 0 ),
1060
-	PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", 0 ),
1069
+	PCI_ROM ( 0x8086, 0x15a3, "i218v-3", "I218-V", INTEL_NO_PHY_RST ),
1061 1070
 	PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ),
1062 1071
 	PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ),
1063 1072
 };

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

@@ -301,6 +301,8 @@ enum intel_flags {
301 301
 	INTEL_PBS_ERRATA = 0x0001,
302 302
 	/** VMware missing interrupt workaround required */
303 303
 	INTEL_VMWARE = 0x0002,
304
+	/** PHY reset is broken */
305
+	INTEL_NO_PHY_RST = 0x0004,
304 306
 };
305 307
 
306 308
 /**

Loading…
Cancel
Save