Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pci Fix a bug that wm_get_swsm_semaphore() timed out...
details: https://anonhg.NetBSD.org/src/rev/8b2f942d24c9
branches: trunk
changeset: 331948:8b2f942d24c9
user: msaitoh <msaitoh%NetBSD.org@localhost>
date: Mon Sep 01 16:42:27 2014 +0000
description:
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.
diffstat:
sys/dev/pci/if_wm.c | 161 +++++++++++++++++++++++++++++++++++-------------
sys/dev/pci/if_wmreg.h | 5 +-
2 files changed, 122 insertions(+), 44 deletions(-)
diffs (truncated from 329 to 300 lines):
diff -r e82e744f81ea -r 8b2f942d24c9 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c Mon Sep 01 16:33:20 2014 +0000
+++ b/sys/dev/pci/if_wm.c Mon Sep 01 16:42:27 2014 +0000
@@ -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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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_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 @@
/* 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;
-
- sc->sc_flags |= WM_F_EEPROM_SPI;
+ uint16_t data;
+
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 @@
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 @@
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 @@
}
/* 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;
diff -r e82e744f81ea -r 8b2f942d24c9 sys/dev/pci/if_wmreg.h
--- a/sys/dev/pci/if_wmreg.h Mon Sep 01 16:33:20 2014 +0000
Home |
Main Index |
Thread Index |
Old Index