Module Name: src Committed By: msaitoh Date: Mon Sep 1 16:42:27 UTC 2014
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h Log Message: Fix a bug that wm_get_swsm_semaphore() timed out when attaching device on some machines. - Calculate NVM word size correctly. - Determine timeout value based on the NVM word size. To generate a diff of this commit: cvs rdiff -u -r1.293 -r1.294 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.61 -r1.62 src/sys/dev/pci/if_wmreg.h 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.293 src/sys/dev/pci/if_wm.c:1.294 --- src/sys/dev/pci/if_wm.c:1.293 Fri Aug 29 12:14:29 2014 +++ src/sys/dev/pci/if_wm.c Mon Sep 1 16:42:27 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.293 2014/08/29 12:14:29 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.294 2014/09/01 16:42:27 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -82,7 +82,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.293 2014/08/29 12:14:29 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.294 2014/09/01 16:42:27 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -287,7 +287,8 @@ struct wm_softc { callout_t sc_tick_ch; /* tick callout */ bool sc_stopping; - int sc_ee_addrbits; /* EEPROM address bits */ + int sc_nvm_addrbits; /* NVM address bits */ + unsigned int sc_nvm_wordsize; /* NVM word size */ int sc_ich8_flash_base; int sc_ich8_flash_bank_size; int sc_nvm_k1_enabled; @@ -629,13 +630,13 @@ static uint32_t wm_get_sfp_media_type(st * NVM related. * Microwire, SPI (w/wo EERD) and Flash. */ -/* Both spi and uwire */ +/* Misc functions */ static void wm_eeprom_sendbits(struct wm_softc *, uint32_t, int); static void wm_eeprom_recvbits(struct wm_softc *, uint32_t *, int); +static int wm_nvm_set_addrbits_size_eecd(struct wm_softc *); /* Microwire */ static int wm_nvm_read_uwire(struct wm_softc *, int, int, uint16_t *); /* SPI */ -static void wm_set_spiaddrbits(struct wm_softc *); static int wm_nvm_ready_spi(struct wm_softc *); static int wm_nvm_read_spi(struct wm_softc *, int, int, uint16_t *); /* Using with EERD */ @@ -1648,7 +1649,8 @@ wm_attach(device_t parent, device_t self case WM_T_82543: case WM_T_82544: /* Microwire */ - sc->sc_ee_addrbits = 6; + sc->sc_nvm_wordsize = 64; + sc->sc_nvm_addrbits = 6; break; case WM_T_82540: case WM_T_82545: @@ -1657,10 +1659,13 @@ wm_attach(device_t parent, device_t self case WM_T_82546_3: /* Microwire */ reg = CSR_READ(sc, WMREG_EECD); - if (reg & EECD_EE_SIZE) - sc->sc_ee_addrbits = 8; - else - sc->sc_ee_addrbits = 6; + if (reg & EECD_EE_SIZE) { + sc->sc_nvm_wordsize = 256; + sc->sc_nvm_addrbits = 8; + } else { + sc->sc_nvm_wordsize = 64; + sc->sc_nvm_addrbits = 6; + } sc->sc_flags |= WM_F_LOCK_EECD; break; case WM_T_82541: @@ -1670,16 +1675,25 @@ wm_attach(device_t parent, device_t self reg = CSR_READ(sc, WMREG_EECD); if (reg & EECD_EE_TYPE) { /* SPI */ - wm_set_spiaddrbits(sc); - } else + sc->sc_flags |= WM_F_EEPROM_SPI; + wm_nvm_set_addrbits_size_eecd(sc); + } else { /* Microwire */ - sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 8 : 6; + if ((reg & EECD_EE_ABITS) != 0) { + sc->sc_nvm_wordsize = 256; + sc->sc_nvm_addrbits = 8; + } else { + sc->sc_nvm_wordsize = 64; + sc->sc_nvm_addrbits = 6; + } + } sc->sc_flags |= WM_F_LOCK_EECD; break; case WM_T_82571: case WM_T_82572: /* SPI */ - wm_set_spiaddrbits(sc); + sc->sc_flags |= WM_F_EEPROM_SPI; + wm_nvm_set_addrbits_size_eecd(sc); sc->sc_flags |= WM_F_LOCK_EECD | WM_F_LOCK_SWSM; break; case WM_T_82573: @@ -1687,11 +1701,13 @@ wm_attach(device_t parent, device_t self /* FALLTHROUGH */ case WM_T_82574: case WM_T_82583: - if (wm_nvm_is_onboard_eeprom(sc) == 0) + if (wm_nvm_is_onboard_eeprom(sc) == 0) { sc->sc_flags |= WM_F_EEPROM_FLASH; - else { + sc->sc_nvm_wordsize = 2048; + } else { /* SPI */ - wm_set_spiaddrbits(sc); + sc->sc_flags |= WM_F_EEPROM_SPI; + wm_nvm_set_addrbits_size_eecd(sc); } sc->sc_flags |= WM_F_EEPROM_EERDEEWR; break; @@ -1703,7 +1719,8 @@ wm_attach(device_t parent, device_t self case WM_T_I354: case WM_T_80003: /* SPI */ - wm_set_spiaddrbits(sc); + sc->sc_flags |= WM_F_EEPROM_SPI; + wm_nvm_set_addrbits_size_eecd(sc); sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW | WM_F_LOCK_SWSM; break; @@ -1715,6 +1732,7 @@ wm_attach(device_t parent, device_t self case WM_T_PCH_LPT: /* FLASH */ sc->sc_flags |= WM_F_EEPROM_FLASH | WM_F_LOCK_EXTCNF; + sc->sc_nvm_wordsize = 2048; memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WM_ICH8_FLASH); if (pci_mapreg_map(pa, WM_ICH8_FLASH, memtype, 0, &sc->sc_flasht, &sc->sc_flashh, NULL, NULL)) { @@ -1734,6 +1752,7 @@ wm_attach(device_t parent, device_t self break; case WM_T_I210: case WM_T_I211: + wm_nvm_set_addrbits_size_eecd(sc); sc->sc_flags |= WM_F_EEPROM_FLASH_HW; sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW; break; @@ -1792,19 +1811,21 @@ wm_attach(device_t parent, device_t self if (sc->sc_flags & WM_F_EEPROM_INVALID) aprint_verbose_dev(sc->sc_dev, "No EEPROM\n"); - else if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) { - aprint_verbose_dev(sc->sc_dev, "FLASH(HW)\n"); - } else if (sc->sc_flags & WM_F_EEPROM_FLASH) { - aprint_verbose_dev(sc->sc_dev, "FLASH\n"); - } else { - if (sc->sc_flags & WM_F_EEPROM_SPI) - eetype = "SPI"; - else - eetype = "MicroWire"; - aprint_verbose_dev(sc->sc_dev, - "%u word (%d address bits) %s EEPROM\n", - 1U << sc->sc_ee_addrbits, - sc->sc_ee_addrbits, eetype); + else { + aprint_verbose_dev(sc->sc_dev, "%u words ", + sc->sc_nvm_wordsize); + if (sc->sc_flags & WM_F_EEPROM_FLASH_HW) { + aprint_verbose("FLASH(HW)\n"); + } else if (sc->sc_flags & WM_F_EEPROM_FLASH) { + aprint_verbose("FLASH\n"); + } else { + if (sc->sc_flags & WM_F_EEPROM_SPI) + eetype = "SPI"; + else + eetype = "MicroWire"; + aprint_verbose("(%d address bits) %s EEPROM\n", + sc->sc_nvm_addrbits, eetype); + } } switch (sc->sc_type) { @@ -7673,7 +7694,7 @@ wm_nvm_read_uwire(struct wm_softc *sc, i wm_eeprom_sendbits(sc, UWIRE_OPC_READ, 3); /* Shift in address. */ - wm_eeprom_sendbits(sc, word + i, sc->sc_ee_addrbits); + wm_eeprom_sendbits(sc, word + i, sc->sc_nvm_addrbits); /* Shift out the data. */ wm_eeprom_recvbits(sc, &val, 16); @@ -7691,15 +7712,69 @@ wm_nvm_read_uwire(struct wm_softc *sc, i /* SPI */ -/* Set SPI related information */ -static void -wm_set_spiaddrbits(struct wm_softc *sc) +/* + * Set SPI and FLASH related information from the EECD register. + * For 82541 and 82547, the word size is taken from EEPROM. + */ +static int +wm_nvm_set_addrbits_size_eecd(struct wm_softc *sc) { + int size; uint32_t reg; + uint16_t data; - sc->sc_flags |= WM_F_EEPROM_SPI; reg = CSR_READ(sc, WMREG_EECD); - sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 16 : 8; + sc->sc_nvm_addrbits = (reg & EECD_EE_ABITS) ? 16 : 8; + + /* Read the size of NVM from EECD by default */ + size = __SHIFTOUT(reg, EECD_EE_SIZE_EX_MASK); + switch (sc->sc_type) { + case WM_T_82541: + case WM_T_82541_2: + case WM_T_82547: + case WM_T_82547_2: + /* Set dummy value to access EEPROM */ + sc->sc_nvm_wordsize = 64; + wm_nvm_read(sc, NVM_OFF_EEPROM_SIZE, 1, &data); + reg = data; + size = __SHIFTOUT(reg, EECD_EE_SIZE_EX_MASK); + if (size == 0) + size = 6; /* 64 word size */ + else + size += NVM_WORD_SIZE_BASE_SHIFT + 1; + break; + case WM_T_80003: + case WM_T_82571: + case WM_T_82572: + case WM_T_82573: /* SPI case */ + case WM_T_82574: /* SPI case */ + case WM_T_82583: /* SPI case */ + size += NVM_WORD_SIZE_BASE_SHIFT; + if (size > 14) + size = 14; + break; + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: + case WM_T_I350: + case WM_T_I354: + case WM_T_I210: + case WM_T_I211: + size += NVM_WORD_SIZE_BASE_SHIFT; + if (size > 15) + size = 15; + break; + default: + aprint_error_dev(sc->sc_dev, + "%s: unknown device(%d)?\n", __func__, sc->sc_type); + return -1; + break; + } + + sc->sc_nvm_wordsize = 1 << size; + + return 0; } /* @@ -7756,11 +7831,11 @@ wm_nvm_read_spi(struct wm_softc *sc, int delay(2); opc = SPI_OPC_READ; - if (sc->sc_ee_addrbits == 8 && word >= 128) + if (sc->sc_nvm_addrbits == 8 && word >= 128) opc |= SPI_OPC_A8; wm_eeprom_sendbits(sc, opc, 8); - wm_eeprom_sendbits(sc, word << 1, sc->sc_ee_addrbits); + wm_eeprom_sendbits(sc, word << 1, sc->sc_nvm_addrbits); for (i = 0; i < wordcnt; i++) { wm_eeprom_recvbits(sc, &val, 16); @@ -8377,7 +8452,7 @@ wm_get_swsm_semaphore(struct wm_softc *s if (sc->sc_flags & WM_F_LOCK_SWSM) { /* Get the SW semaphore. */ - timeout = 1000 + 1; /* XXX */ + timeout = sc->sc_nvm_wordsize + 1; while (timeout) { swsm = CSR_READ(sc, WMREG_SWSM); @@ -8396,7 +8471,7 @@ wm_get_swsm_semaphore(struct wm_softc *s } /* Get the FW semaphore. */ - timeout = 1000 + 1; /* XXX */ + timeout = sc->sc_nvm_wordsize + 1; while (timeout) { swsm = CSR_READ(sc, WMREG_SWSM); swsm |= SWSM_SWESMBI; Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.61 src/sys/dev/pci/if_wmreg.h:1.62 --- src/sys/dev/pci/if_wmreg.h:1.61 Fri Aug 29 12:14:29 2014 +++ src/sys/dev/pci/if_wmreg.h Mon Sep 1 16:42:27 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.61 2014/08/29 12:14:29 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.62 2014/09/01 16:42:27 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -286,6 +286,7 @@ struct livengood_tcpip_ctxdesc { #define EECD_EE_AUTORD (1U << 9) /* auto read done */ #define EECD_EE_ABITS (1U << 10) /* EEPROM address bits (based on type) */ +#define EECD_EE_SIZE_EX_MASK __BITS(14,11) /* EEPROM size for new devices */ #define EECD_EE_TYPE (1U << 13) /* EEPROM type (0 = Microwire, 1 = SPI) */ #define EECD_SEC1VAL (1U << 22) /* Sector One Valid */ @@ -900,11 +901,13 @@ struct livengood_tcpip_ctxdesc { #define NVM_CHECKSUM 0xBABA #define NVM_SIZE 0x0040 +#define NVM_WORD_SIZE_BASE_SHIFT 6 #define NVM_OFF_MACADDR 0x0000 /* MAC address offset */ #define NVM_OFF_COMPAT 0x0003 #define NVM_OFF_CFG1 0x000a /* config word 1 */ #define NVM_OFF_CFG2 0x000f /* config word 2 */ +#define NVM_OFF_EEPROM_SIZE 0x0012 /* NVM SIZE */ #define NVM_OFF_CFG3_PORTB 0x0014 /* config word 3 */ #define NVM_OFF_FUTURE_INIT_WORD1 0x0019 #define NVM_OFF_INIT_3GIO_3 0x001a /* PCIe Initial Configuration Word 3 */