Module Name: src
Committed By: msaitoh
Date: Wed Nov 14 03:41:21 UTC 2018
Modified Files:
src/sys/dev/pci: if_wm.c
Log Message:
- Add new wm_gmii_{hv,i82544}_{read,write}reg_locked() and use them in
wm_gmii_{hv,i82544}_{read,write}reg(). *_locked() functions are not
mii(4) API functions, so it's not required to keep the mii API. Change
the PHY register type from int to uint16_t. It also change the usage of
return value. It returns zero on success and non-zero on error.
- Check the return value of *_locked() function and treat it.
- Use *writereg_locked() function to reduce race condition in
wm_init_lcd_from_nvm().
- Add comment.
To generate a diff of this commit:
cvs rdiff -u -r1.596 -r1.597 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.596 src/sys/dev/pci/if_wm.c:1.597
--- src/sys/dev/pci/if_wm.c:1.596 Sat Nov 3 21:39:10 2018
+++ src/sys/dev/pci/if_wm.c Wed Nov 14 03:41:20 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: if_wm.c,v 1.596 2018/11/03 21:39:10 christos Exp $ */
+/* $NetBSD: if_wm.c,v 1.597 2018/11/14 03:41:20 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.596 2018/11/03 21:39:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.597 2018/11/14 03:41:20 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_net_mpsafe.h"
@@ -463,6 +463,8 @@ struct wm_queue {
struct wm_phyop {
int (*acquire)(struct wm_softc *);
void (*release)(struct wm_softc *);
+ int (*readreg_locked)(device_t, int, int, uint16_t *);
+ int (*writereg_locked)(device_t, int, int, uint16_t);
int reset_delay_us;
};
@@ -716,7 +718,7 @@ static void wm_get_auto_rd_done(struct w
static void wm_lan_init_done(struct wm_softc *);
static void wm_get_cfg_done(struct wm_softc *);
static void wm_phy_post_reset(struct wm_softc *);
-static void wm_write_smbus_addr(struct wm_softc *);
+static int wm_write_smbus_addr(struct wm_softc *);
static void wm_init_lcd_from_nvm(struct wm_softc *);
static void wm_initialize_hardware_bits(struct wm_softc *);
static uint32_t wm_rxpbs_adjust_82580(uint32_t);
@@ -819,16 +821,18 @@ static void wm_gmii_i82543_writereg(devi
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 int wm_gmii_i82544_readreg_locked(device_t, int, int, uint16_t *);
static void wm_gmii_i82544_writereg(device_t, int, int, int);
+static int wm_gmii_i82544_writereg_locked(device_t, int, int, uint16_t);
static int wm_gmii_i80003_readreg(device_t, int, int);
static void wm_gmii_i80003_writereg(device_t, int, int, int);
static int wm_gmii_bm_readreg(device_t, int, int);
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 int wm_gmii_hv_readreg_locked(device_t, int, int, uint16_t *);
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_hv_writereg_locked(device_t, int, int, uint16_t);
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);
@@ -948,7 +952,7 @@ static void wm_smbustopci(struct wm_soft
static void wm_init_manageability(struct wm_softc *);
static void wm_release_manageability(struct wm_softc *);
static void wm_get_wakeup(struct wm_softc *);
-static void wm_ulp_disable(struct wm_softc *);
+static int wm_ulp_disable(struct wm_softc *);
static void wm_enable_phy_wakeup(struct wm_softc *);
static void wm_igp3_phy_powerdown_workaround_ich8lan(struct wm_softc *);
static void wm_enable_wakeup(struct wm_softc *);
@@ -3826,6 +3830,7 @@ wm_get_cfg_done(struct wm_softc *sc)
else
wm_get_auto_rd_done(sc);
+ /* Clear PHY Reset Asserted bit */
reg = CSR_READ(sc, WMREG_STATUS);
if ((reg & STATUS_PHYRA) != 0)
CSR_WRITE(sc, WMREG_STATUS, reg & ~STATUS_PHYRA);
@@ -3886,19 +3891,23 @@ wm_phy_post_reset(struct wm_softc *sc)
}
/* Only for PCH and newer */
-static void
+static int
wm_write_smbus_addr(struct wm_softc *sc)
{
uint32_t strap, freq;
- uint32_t phy_data;
+ uint16_t phy_data;
+ int rv;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
+ KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP);
strap = CSR_READ(sc, WMREG_STRAP);
freq = __SHIFTOUT(strap, STRAP_FREQ);
- phy_data = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, HV_SMB_ADDR);
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, HV_SMB_ADDR, &phy_data);
+ if (rv != 0)
+ return -1;
phy_data &= ~HV_SMB_ADDR_ADDR;
phy_data |= __SHIFTOUT(strap, STRAP_SMBUSADDR);
@@ -3920,7 +3929,8 @@ wm_write_smbus_addr(struct wm_softc *sc)
}
}
- wm_gmii_hv_writereg_locked(sc->sc_dev, 2, HV_SMB_ADDR, phy_data);
+ return wm_gmii_hv_writereg_locked(sc->sc_dev, 2, HV_SMB_ADDR,
+ phy_data);
}
void
@@ -4012,9 +4022,8 @@ wm_init_lcd_from_nvm(struct wm_softc *sc
reg_addr &= IGPHY_MAXREGADDR;
reg_addr |= phy_page;
- sc->phy.release(sc); /* XXX */
- sc->sc_mii.mii_writereg(sc->sc_dev, 1, reg_addr, reg_data);
- sc->phy.acquire(sc); /* XXX */
+ KASSERT(sc->phy.writereg_locked != NULL);
+ sc->phy.writereg_locked(sc->sc_dev, 1, reg_addr, reg_data);
}
release:
@@ -9708,6 +9717,13 @@ wm_gmii_setup_phytype(struct wm_softc *s
sc->sc_phytype = new_phytype;
mii->mii_readreg = new_readreg;
mii->mii_writereg = new_writereg;
+ if (new_readreg == wm_gmii_hv_readreg) {
+ sc->phy.readreg_locked = wm_gmii_hv_readreg_locked;
+ sc->phy.writereg_locked = wm_gmii_hv_writereg_locked;
+ } else if (new_readreg == wm_gmii_i82544_readreg) {
+ sc->phy.readreg_locked = wm_gmii_i82544_readreg_locked;
+ sc->phy.writereg_locked = wm_gmii_i82544_writereg_locked;
+ }
}
/*
@@ -10189,13 +10205,25 @@ static int
wm_gmii_i82544_readreg(device_t dev, int phy, int reg)
{
struct wm_softc *sc = device_private(dev);
- int rv;
+ uint16_t val;
if (sc->phy.acquire(sc)) {
device_printf(dev, "%s: failed to get semaphore\n", __func__);
return 0;
}
+ wm_gmii_i82544_readreg_locked(dev, phy, reg, &val);
+
+ sc->phy.release(sc);
+
+ return val;
+}
+
+static int
+wm_gmii_i82544_readreg_locked(device_t dev, int phy, int reg, uint16_t *val)
+{
+ struct wm_softc *sc = device_private(dev);
+
if (reg > BME1000_MAX_MULTI_PAGE_REG) {
switch (sc->sc_phytype) {
case WMPHY_IGP:
@@ -10213,10 +10241,9 @@ wm_gmii_i82544_readreg(device_t dev, int
}
}
- rv = wm_gmii_mdic_readreg(dev, phy, reg & MII_ADDRMASK);
- sc->phy.release(sc);
+ *val = wm_gmii_mdic_readreg(dev, phy, reg & MII_ADDRMASK);
- return rv;
+ return 0;
}
/*
@@ -10234,6 +10261,15 @@ wm_gmii_i82544_writereg(device_t dev, in
return;
}
+ wm_gmii_i82544_writereg_locked(dev, phy, reg & MII_ADDRMASK, val);
+ sc->phy.release(sc);
+}
+
+static int
+wm_gmii_i82544_writereg_locked(device_t dev, int phy, int reg, uint16_t val)
+{
+ struct wm_softc *sc = device_private(dev);
+
if (reg > BME1000_MAX_MULTI_PAGE_REG) {
switch (sc->sc_phytype) {
case WMPHY_IGP:
@@ -10252,7 +10288,8 @@ wm_gmii_i82544_writereg(device_t dev, in
}
wm_gmii_mdic_writereg(dev, phy, reg & MII_ADDRMASK, val);
- sc->phy.release(sc);
+
+ return 0;
}
/*
@@ -10522,7 +10559,7 @@ static int
wm_gmii_hv_readreg(device_t dev, int phy, int reg)
{
struct wm_softc *sc = device_private(dev);
- int rv;
+ uint16_t val;
DPRINTF(WM_DEBUG_GMII, ("%s: %s called\n",
device_xname(dev), __func__));
@@ -10531,25 +10568,23 @@ wm_gmii_hv_readreg(device_t dev, int phy
return 0;
}
- rv = wm_gmii_hv_readreg_locked(dev, phy, reg);
+ wm_gmii_hv_readreg_locked(dev, phy, reg, &val);
sc->phy.release(sc);
- return rv;
+ return val;
}
static int
-wm_gmii_hv_readreg_locked(device_t dev, int phy, int reg)
+wm_gmii_hv_readreg_locked(device_t dev, int phy, int reg, uint16_t *val)
{
uint16_t page = BM_PHY_REG_PAGE(reg);
uint16_t regnum = BM_PHY_REG_NUM(reg);
- uint16_t val;
- int rv;
phy = (page >= HV_INTC_FC_PAGE_START) ? 1 : phy;
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
- wm_access_phy_wakeup_reg_bm(dev, reg, &val, 1);
- return val;
+ wm_access_phy_wakeup_reg_bm(dev, reg, val, 1);
+ return 0;
}
/*
@@ -10573,8 +10608,8 @@ wm_gmii_hv_readreg_locked(device_t dev,
page << BME1000_PAGE_SHIFT);
}
- rv = wm_gmii_mdic_readreg(dev, phy, regnum & MII_ADDRMASK);
- return rv;
+ *val = wm_gmii_mdic_readreg(dev, phy, regnum & MII_ADDRMASK);
+ return 0;
}
/*
@@ -10601,8 +10636,8 @@ wm_gmii_hv_writereg(device_t dev, int ph
sc->phy.release(sc);
}
-static void
-wm_gmii_hv_writereg_locked(device_t dev, int phy, int reg, int val)
+static int
+wm_gmii_hv_writereg_locked(device_t dev, int phy, int reg, uint16_t val)
{
struct wm_softc *sc = device_private(dev);
uint16_t page = BM_PHY_REG_PAGE(reg);
@@ -10616,7 +10651,7 @@ wm_gmii_hv_writereg_locked(device_t dev,
tmp = val;
wm_access_phy_wakeup_reg_bm(dev, reg, &tmp, 0);
- return;
+ return 0;
}
/*
@@ -10625,7 +10660,7 @@ wm_gmii_hv_writereg_locked(device_t dev,
*/
if ((page > 0) && (page < HV_INTC_FC_PAGE_START)) {
printf("gmii_hv_writereg!!!\n");
- return;
+ return -1;
}
{
@@ -10659,6 +10694,8 @@ wm_gmii_hv_writereg_locked(device_t dev,
}
wm_gmii_mdic_writereg(dev, phy, regnum & MII_ADDRMASK, val);
+
+ return 0;
}
/*
@@ -13898,11 +13935,12 @@ wm_get_wakeup(struct wm_softc *sc)
* Unconfigure Ultra Low Power mode.
* Only for I217 and newer (see below).
*/
-static void
+static int
wm_ulp_disable(struct wm_softc *sc)
{
uint32_t reg;
- int i = 0;
+ uint16_t phyreg;
+ int i = 0, rv = 0;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
@@ -13912,7 +13950,7 @@ wm_ulp_disable(struct wm_softc *sc)
|| (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I217_V)
|| (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_LM2)
|| (sc->sc_pcidevid == PCI_PRODUCT_INTEL_I218_V2))
- return;
+ return 0;
if ((CSR_READ(sc, WMREG_FWSM) & FWSM_FW_VALID) != 0) {
/* Request ME un-configure ULP mode in the PHY */
@@ -13925,7 +13963,7 @@ wm_ulp_disable(struct wm_softc *sc)
while ((CSR_READ(sc, WMREG_FWSM) & FWSM_ULP_CFG_DONE) != 0) {
if (i++ == 30) {
printf("%s timed out\n", __func__);
- return;
+ return -1;
}
delay(10 * 1000);
}
@@ -13933,7 +13971,7 @@ wm_ulp_disable(struct wm_softc *sc)
reg &= ~H2ME_ENFORCE_SETTINGS;
CSR_WRITE(sc, WMREG_H2ME, reg);
- return;
+ return 0;
}
/* Acquire semaphore */
@@ -13943,8 +13981,8 @@ wm_ulp_disable(struct wm_softc *sc)
wm_toggle_lanphypc_pch_lpt(sc);
/* Unforce SMBus mode in PHY */
- reg = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, CV_SMB_CTRL);
- if (reg == 0x0000 || reg == 0xffff) {
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, CV_SMB_CTRL, &phyreg);
+ if (rv != 0) {
uint32_t reg2;
printf("%s: Force SMBus first.\n", __func__);
@@ -13953,22 +13991,30 @@ wm_ulp_disable(struct wm_softc *sc)
CSR_WRITE(sc, WMREG_CTRL_EXT, reg2);
delay(50 * 1000);
- reg = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, CV_SMB_CTRL);
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, CV_SMB_CTRL,
+ &phyreg);
+ if (rv != 0)
+ goto release;
}
- reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
- wm_gmii_hv_writereg_locked(sc->sc_dev, 2, CV_SMB_CTRL, reg);
+ phyreg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ wm_gmii_hv_writereg_locked(sc->sc_dev, 2, CV_SMB_CTRL, phyreg);
/* Unforce SMBus mode in MAC */
reg = CSR_READ(sc, WMREG_CTRL_EXT);
reg &= ~CTRL_EXT_FORCE_SMBUS;
CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
- reg = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, HV_PM_CTRL);
- reg |= HV_PM_CTRL_K1_ENA;
- wm_gmii_hv_writereg_locked(sc->sc_dev, 2, HV_PM_CTRL, reg);
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, HV_PM_CTRL, &phyreg);
+ if (rv != 0)
+ goto release;
+ phyreg |= HV_PM_CTRL_K1_ENA;
+ wm_gmii_hv_writereg_locked(sc->sc_dev, 2, HV_PM_CTRL, phyreg);
- reg = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, I218_ULP_CONFIG1);
- reg &= ~(I218_ULP_CONFIG1_IND
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, I218_ULP_CONFIG1,
+ &phyreg);
+ if (rv != 0)
+ goto release;
+ phyreg &= ~(I218_ULP_CONFIG1_IND
| I218_ULP_CONFIG1_STICKY_ULP
| I218_ULP_CONFIG1_RESET_TO_SMBUS
| I218_ULP_CONFIG1_WOL_HOST
@@ -13976,18 +14022,21 @@ wm_ulp_disable(struct wm_softc *sc)
| I218_ULP_CONFIG1_EN_ULP_LANPHYPC
| I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST
| I218_ULP_CONFIG1_DIS_SMB_PERST);
- wm_gmii_hv_writereg_locked(sc->sc_dev, 2, I218_ULP_CONFIG1, reg);
- reg |= I218_ULP_CONFIG1_START;
- wm_gmii_hv_writereg_locked(sc->sc_dev, 2, I218_ULP_CONFIG1, reg);
+ wm_gmii_hv_writereg_locked(sc->sc_dev, 2, I218_ULP_CONFIG1, phyreg);
+ phyreg |= I218_ULP_CONFIG1_START;
+ wm_gmii_hv_writereg_locked(sc->sc_dev, 2, I218_ULP_CONFIG1, phyreg);
reg = CSR_READ(sc, WMREG_FEXTNVM7);
reg &= ~FEXTNVM7_DIS_SMB_PERST;
CSR_WRITE(sc, WMREG_FEXTNVM7, reg);
+release:
/* Release semaphore */
sc->phy.release(sc);
wm_gmii_reset(sc);
delay(50 * 1000);
+
+ return rv;
}
/* WOL in the newer chipset interfaces (pchlan) */
@@ -14530,6 +14579,8 @@ wm_configure_k1_ich8lan(struct wm_softc
uint16_t kmreg;
int rv;
+ KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP);
+
rv = wm_kmrn_readreg_locked(sc, KUMCTRLSTA_OFFSET_K1_CONFIG, &kmreg);
if (rv != 0)
return;
@@ -14628,25 +14679,33 @@ wm_reset_mdicnfg_82580(struct wm_softc *
static bool
wm_phy_is_accessible_pchlan(struct wm_softc *sc)
{
- int i;
uint32_t reg;
uint16_t id1, id2;
+ int i, rv;
DPRINTF(WM_DEBUG_INIT, ("%s: %s called\n",
device_xname(sc->sc_dev), __func__));
+ KASSERT(CSR_READ(sc, WMREG_EXTCNFCTR) & EXTCNFCTR_MDIO_SW_OWNERSHIP);
+
id1 = id2 = 0xffff;
for (i = 0; i < 2; i++) {
- id1 = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, MII_PHYIDR1);
- if (MII_INVALIDID(id1))
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, MII_PHYIDR1,
+ &id1);
+ if ((rv != 0) || MII_INVALIDID(id1))
continue;
- id2 = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, MII_PHYIDR2);
- if (MII_INVALIDID(id2))
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2, MII_PHYIDR2,
+ &id2);
+ if ((rv != 0) || MII_INVALIDID(id2))
continue;
break;
}
if (!MII_INVALIDID(id1) && !MII_INVALIDID(id2))
goto out;
+ /*
+ * In case the PHY needs to be in mdio slow mode,
+ * set slow mode and try to get the PHY id again.
+ */
if (sc->sc_type < WM_T_PCH_LPT) {
sc->phy.release(sc);
wm_set_mdio_slow_mode_hv(sc);
@@ -14662,12 +14721,14 @@ out:
if (sc->sc_type >= WM_T_PCH_LPT) {
/* Only unforce SMBus if ME is not active */
if ((CSR_READ(sc, WMREG_FWSM) & FWSM_FW_VALID) == 0) {
+ uint16_t phyreg;
+
/* Unforce SMBus mode in PHY */
- reg = wm_gmii_hv_readreg_locked(sc->sc_dev, 2,
- CV_SMB_CTRL);
- reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ rv = wm_gmii_hv_readreg_locked(sc->sc_dev, 2,
+ CV_SMB_CTRL, &phyreg);
+ phyreg &= ~CV_SMB_CTRL_FORCE_SMBUS;
wm_gmii_hv_writereg_locked(sc->sc_dev, 2,
- CV_SMB_CTRL, reg);
+ CV_SMB_CTRL, phyreg);
/* Unforce SMBus mode in MAC */
reg = CSR_READ(sc, WMREG_CTRL_EXT);