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