Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci - Rewrite PHY related lock stuff. Almost the sam...



details:   https://anonhg.NetBSD.org/src/rev/5b29c730daf0
branches:  trunk
changeset: 818647:5b29c730daf0
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Fri Oct 21 04:41:09 2016 +0000

description:
- Rewrite PHY related lock stuff. Almost the same as FreeBSD.
  This change will fix a bug that PHY read/write fail on some cases.
- Increase delay in wm_phy_resetisblocked(). Same as FreeBSD.
- Use semaphore in wm_hv_phy_workaround_ich8lan() and wm_k1_gig_workaround_hv()

diffstat:

 sys/dev/pci/if_wm.c |  626 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 386 insertions(+), 240 deletions(-)

diffs (truncated from 1221 to 300 lines):

diff -r 696dbe272c4d -r 5b29c730daf0 sys/dev/pci/if_wm.c
--- a/sys/dev/pci/if_wm.c       Fri Oct 21 03:04:33 2016 +0000
+++ b/sys/dev/pci/if_wm.c       Fri Oct 21 04:41:09 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_wm.c,v 1.423 2016/10/20 08:03:13 msaitoh Exp $      */
+/*     $NetBSD: if_wm.c,v 1.424 2016/10/21 04:41:09 msaitoh Exp $      */
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.423 2016/10/20 08:03:13 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.424 2016/10/21 04:41:09 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -389,6 +389,11 @@
        struct wm_rxqueue wmq_rxq;
 };
 
+struct wm_phyop {
+       int (*acquire)(struct wm_softc *);
+       void (*release)(struct wm_softc *);
+};
+
 /*
  * Software state per device.
  */
@@ -494,10 +499,17 @@
 
        krndsource_t rnd_source;        /* random source */
 
+       struct if_percpuq *sc_ipq;      /* softint-based input queues */
+
        kmutex_t *sc_core_lock;         /* lock for softc operations */
+       kmutex_t *sc_ich_phymtx;        /*
+                                        * 82574/82583/ICH/PCH specific PHY
+                                        * mutex. For 82574/82583, the mutex
+                                        * is used for both PHY and NVM.
+                                        */
        kmutex_t *sc_ich_nvmmtx;        /* ICH/PCH specific NVM mutex */
 
-       struct if_percpuq *sc_ipq;      /* softint-based input queues */
+       struct wm_phyop phy;
 };
 
 #define WM_CORE_LOCK(_sc)      if ((_sc)->sc_core_lock) mutex_enter((_sc)->sc_core_lock)
@@ -699,6 +711,8 @@
 static uint32_t        wm_i82543_mii_recvbits(struct wm_softc *);
 static int     wm_gmii_i82543_readreg(device_t, int, int);
 static void    wm_gmii_i82543_writereg(device_t, int, int, int);
+static int     wm_gmii_mdic_readreg(device_t, int, int);
+static void    wm_gmii_mdic_writereg(device_t, int, int, int);
 static int     wm_gmii_i82544_readreg(device_t, int, int);
 static void    wm_gmii_i82544_writereg(device_t, int, int, int);
 static int     wm_gmii_i80003_readreg(device_t, int, int);
@@ -707,14 +721,18 @@
 static void    wm_gmii_bm_writereg(device_t, int, int, int);
 static void    wm_access_phy_wakeup_reg_bm(device_t, int, int16_t *, int);
 static int     wm_gmii_hv_readreg(device_t, int, int);
+static int     wm_gmii_hv_readreg_locked(device_t, int, int);
 static void    wm_gmii_hv_writereg(device_t, int, int, int);
+static void    wm_gmii_hv_writereg_locked(device_t, int, int, int);
 static int     wm_gmii_82580_readreg(device_t, int, int);
 static void    wm_gmii_82580_writereg(device_t, int, int, int);
 static int     wm_gmii_gs40g_readreg(device_t, int, int);
 static void    wm_gmii_gs40g_writereg(device_t, int, int, int);
 static void    wm_gmii_statchg(struct ifnet *);
 static int     wm_kmrn_readreg(struct wm_softc *, int);
+static int     wm_kmrn_readreg_locked(struct wm_softc *, int);
 static void    wm_kmrn_writereg(struct wm_softc *, int, int);
+static void    wm_kmrn_writereg_locked(struct wm_softc *, int, int);
 /* SGMII */
 static bool    wm_sgmii_uses_mdio(struct wm_softc *);
 static int     wm_sgmii_readreg(device_t, int, int);
@@ -779,12 +797,18 @@
  * Hardware semaphores.
  * Very complexed...
  */
-static int     wm_get_swsm_semaphore(struct wm_softc *);
+static int     wm_get_null(struct wm_softc *);
+static void    wm_put_null(struct wm_softc *);
+static int     wm_get_swsm_semaphore(struct wm_softc *); /* 8257[123] */
 static void    wm_put_swsm_semaphore(struct wm_softc *);
 static int     wm_get_swfw_semaphore(struct wm_softc *, uint16_t);
 static void    wm_put_swfw_semaphore(struct wm_softc *, uint16_t);
-static int     wm_get_swfwhw_semaphore(struct wm_softc *);
+static int     wm_get_phy_82575(struct wm_softc *);
+static void    wm_put_phy_82575(struct wm_softc *);
+static int     wm_get_swfwhw_semaphore(struct wm_softc *); /* For 574/583 */
 static void    wm_put_swfwhw_semaphore(struct wm_softc *);
+static int     wm_get_swflag_ich8lan(struct wm_softc *);       /* For PHY */
+static void    wm_put_swflag_ich8lan(struct wm_softc *);
 static int     wm_get_nvm_ich8lan(struct wm_softc *);          /* For NVM */
 static void    wm_put_nvm_ich8lan(struct wm_softc *);
 static int     wm_get_hw_semaphore_82573(struct wm_softc *);
@@ -828,7 +852,7 @@
 static void    wm_gig_downshift_workaround_ich8lan(struct wm_softc *);
 static void    wm_hv_phy_workaround_ich8lan(struct wm_softc *);
 static void    wm_lv_phy_workaround_ich8lan(struct wm_softc *);
-static void    wm_k1_gig_workaround_hv(struct wm_softc *, int);
+static int     wm_k1_gig_workaround_hv(struct wm_softc *, int);
 static void    wm_set_mdio_slow_mode_hv(struct wm_softc *);
 static void    wm_configure_k1_ich8lan(struct wm_softc *, int);
 static void    wm_reset_init_script_82575(struct wm_softc *);
@@ -1596,6 +1620,11 @@
        pci_aprint_devinfo_fancy(pa, "Ethernet controller", wmp->wmp_name, 1);
 
        sc->sc_type = wmp->wmp_type;
+
+       /* Set default function pointers */
+       sc->phy.acquire = wm_get_null;
+       sc->phy.release = wm_put_null;
+
        if (sc->sc_type < WM_T_82543) {
                if (sc->sc_rev < 2) {
                        aprint_error_dev(sc->sc_dev,
@@ -1899,6 +1928,9 @@
            || (sc->sc_type == WM_T_PCH_LPT) || (sc->sc_type == WM_T_PCH_SPT))
                wm_smbustopci(sc);
 
+       if ((sc->sc_type == WM_T_82574) || (sc->sc_type == WM_T_82583)
+           || (sc->sc_type >= WM_T_ICH8))
+               sc->sc_ich_phymtx = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
        if (sc->sc_type >= WM_T_ICH8)
                sc->sc_ich_nvmmtx = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
 
@@ -1955,12 +1987,24 @@
                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;
+               sc->phy.acquire = wm_get_swsm_semaphore;
+               sc->phy.release = wm_put_swsm_semaphore;
                break;
        case WM_T_82573:
-               sc->sc_flags |= WM_F_LOCK_SWSM;
-               /* FALLTHROUGH */
        case WM_T_82574:
        case WM_T_82583:
+               if (sc->sc_type == WM_T_82573) {
+                       sc->sc_flags |= WM_F_LOCK_SWSM;
+                       sc->phy.acquire = wm_get_swsm_semaphore;
+                       sc->phy.release = wm_put_swsm_semaphore;
+               } else {
+                       sc->sc_flags |= WM_F_LOCK_EXTCNF;
+                       /* Both PHY and NVM use the same semaphore. */
+                       sc->phy.acquire
+                           = wm_get_swfwhw_semaphore;
+                       sc->phy.release
+                           = wm_put_swfwhw_semaphore;
+               }
                if (wm_nvm_is_onboard_eeprom(sc) == 0) {
                        sc->sc_flags |= WM_F_EEPROM_FLASH;
                        sc->sc_nvm_wordsize = 2048;
@@ -1982,6 +2026,8 @@
                wm_nvm_set_addrbits_size_eecd(sc);
                sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_LOCK_SWFW
                    | WM_F_LOCK_SWSM;
+               sc->phy.acquire = wm_get_phy_82575;
+               sc->phy.release = wm_put_phy_82575;
                break;
        case WM_T_ICH8:
        case WM_T_ICH9:
@@ -2008,6 +2054,8 @@
                sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE;
                sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t);
                sc->sc_flashreg_offset = 0;
+               sc->phy.acquire = wm_get_swflag_ich8lan;
+               sc->phy.release = wm_put_swflag_ich8lan;
                break;
        case WM_T_PCH_SPT:
                /* SPT has no GFPREG; flash registers mapped through BAR0 */
@@ -2023,18 +2071,22 @@
                /* assume 2 banks */
                sc->sc_ich8_flash_bank_size = sc->sc_nvm_wordsize / 2;
                sc->sc_flashreg_offset = WM_PCH_SPT_FLASHOFFSET;
+               sc->phy.acquire = wm_get_swflag_ich8lan;
+               sc->phy.release = wm_put_swflag_ich8lan;
                break;
        case WM_T_I210:
        case WM_T_I211:
                if (wm_nvm_get_flash_presence_i210(sc)) {
                        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;
+                       sc->sc_flags |= WM_F_EEPROM_EERDEEWR;
                } else {
                        sc->sc_nvm_wordsize = INVM_SIZE;
                        sc->sc_flags |= WM_F_EEPROM_INVM;
-                       sc->sc_flags |= WM_F_LOCK_SWFW;
-               }
+               }
+               sc->sc_flags |= WM_F_LOCK_SWFW | WM_F_LOCK_SWSM;
+               sc->phy.acquire = wm_get_phy_82575;
+               sc->phy.release = wm_put_phy_82575;
                break;
        default:
                break;
@@ -2667,6 +2719,8 @@
 
        if (sc->sc_core_lock)
                mutex_obj_free(sc->sc_core_lock);
+       if (sc->sc_ich_phymtx)
+               mutex_obj_free(sc->sc_ich_phymtx);
        if (sc->sc_ich_nvmmtx)
                mutex_obj_free(sc->sc_ich_nvmmtx);
 
@@ -3016,8 +3070,7 @@
                break;
        }
 
-       if (wm_nvm_read(sc, offset, sizeof(myea) / sizeof(myea[0]),
-               myea) != 0)
+       if (wm_nvm_read(sc, offset, sizeof(myea) / sizeof(myea[0]), myea) != 0)
                goto bad;
 
        enaddr[0] = myea[0] & 0xff;
@@ -3687,7 +3740,7 @@
 {
        int phy_reset = 0;
        int i, error = 0;
-       uint32_t reg, mask;
+       uint32_t reg;
 
        DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                device_xname(sc->sc_dev), __func__));
@@ -3861,11 +3914,10 @@
                CSR_WRITE(sc, WMREG_CTRL_SHADOW, CTRL_RST);
                break;
        case WM_T_80003:
-               mask = swfwphysem[sc->sc_funcid];
                reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST;
-               wm_get_swfw_semaphore(sc, mask);
+               sc->phy.acquire(sc);
                CSR_WRITE(sc, WMREG_CTRL, reg);
-               wm_put_swfw_semaphore(sc, mask);
+               sc->phy.release(sc);
                break;
        case WM_T_ICH8:
        case WM_T_ICH9:
@@ -3889,11 +3941,11 @@
                        phy_reset = 1;
                } else
                        printf("XXX reset is blocked!!!\n");
-               wm_get_swfwhw_semaphore(sc);
+               sc->phy.acquire(sc);
                CSR_WRITE(sc, WMREG_CTRL, reg);
                /* Don't insert a completion barrier when reset */
                delay(20*1000);
-               wm_put_swfwhw_semaphore(sc);
+               mutex_exit(sc->sc_ich_phymtx);
                break;
        case WM_T_82580:
        case WM_T_I350:
@@ -7805,40 +7857,7 @@
        DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
                device_xname(sc->sc_dev), __func__));
 
-       /* Get phy semaphore */
-       switch (sc->sc_type) {
-       case WM_T_82571:
-       case WM_T_82572:
-       case WM_T_82573:
-       case WM_T_82574:
-       case WM_T_82583:
-                /* XXX should get sw semaphore, too */
-               rv = wm_get_swsm_semaphore(sc);
-               break;
-       case WM_T_82575:
-       case WM_T_82576:
-       case WM_T_82580:
-       case WM_T_I350:
-       case WM_T_I354:
-       case WM_T_I210:
-       case WM_T_I211:
-       case WM_T_80003:
-               rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]);
-               break;
-       case WM_T_ICH8:
-       case WM_T_ICH9:
-       case WM_T_ICH10:
-       case WM_T_PCH:
-       case WM_T_PCH2:
-       case WM_T_PCH_LPT:
-       case WM_T_PCH_SPT:
-               rv = wm_get_swfwhw_semaphore(sc);
-               break;
-       default:
-               /* nothing to do*/
-               rv = 0;
-               break;
-       }
+       rv = sc->phy.acquire(sc);
        if (rv != 0) {
                aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n",
                    __func__);
@@ -7938,40 +7957,7 @@
                break;



Home | Main Index | Thread Index | Old Index