Module Name: src Committed By: msaitoh Date: Fri Nov 2 08:04:42 UTC 2018
Modified Files: src/sys/dev/pci: if_wm.c Log Message: Fix a PCH2 specific bug that wrong register value can be read when boot. When a wrong value is read when boot, the read device ID was incorrect and ukphy(3) is attached instead of ihphy(4). The bug might also result in MDIC read/write error. How to reproduce: 0) Boot Windows. 1) Leave some minutes. 2) Reboot to NetBSD. To fix this problem, adding extra 100us delay at the end of wm_gmii_mdic_{read,write}reg() on PCH2. Same as FreeBSD and linux. Reported by David Brownlee a few days ago and also reported by jmcneill a half year ago. Tested with my own Thinkpad X220. XXX pullup-[78] To generate a diff of this commit: cvs rdiff -u -r1.591 -r1.592 src/sys/dev/pci/if_wm.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_wm.c diff -u src/sys/dev/pci/if_wm.c:1.591 src/sys/dev/pci/if_wm.c:1.592 --- src/sys/dev/pci/if_wm.c:1.591 Fri Nov 2 03:22:19 2018 +++ src/sys/dev/pci/if_wm.c Fri Nov 2 08:04:42 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.591 2018/11/02 03:22:19 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.592 2018/11/02 08:04:42 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -83,7 +83,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.591 2018/11/02 03:22:19 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.592 2018/11/02 08:04:42 msaitoh Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -10096,19 +10096,26 @@ wm_gmii_mdic_readreg(device_t dev, int p if ((mdic & MDIC_READY) == 0) { log(LOG_WARNING, "%s: MDIC read timed out: phy %d reg %d\n", device_xname(dev), phy, reg); - rv = 0; + return 0; } else if (mdic & MDIC_E) { #if 0 /* This is normal if no PHY is present. */ log(LOG_WARNING, "%s: MDIC read error: phy %d reg %d\n", device_xname(dev), phy, reg); #endif - rv = 0; + return 0; } else { rv = MDIC_DATA(mdic); if (rv == 0xffff) rv = 0; } + /* + * Allow some time after each MDIC transaction to avoid + * reading duplicate data in the next MDIC transaction. + */ + if (sc->sc_type == WM_T_PCH2) + delay(100); + return rv; } @@ -10140,12 +10147,22 @@ wm_gmii_mdic_writereg(device_t dev, int delay(50); } - if ((mdic & MDIC_READY) == 0) + if ((mdic & MDIC_READY) == 0) { log(LOG_WARNING, "%s: MDIC write timed out: phy %d reg %d\n", device_xname(dev), phy, reg); - else if (mdic & MDIC_E) + return; + } else if (mdic & MDIC_E) { log(LOG_WARNING, "%s: MDIC write error: phy %d reg %d\n", device_xname(dev), phy, reg); + return; + } + + /* + * Allow some time after each MDIC transaction to avoid + * reading duplicate data in the next MDIC transaction. + */ + if (sc->sc_type == WM_T_PCH2) + delay(100); } /*