summaryrefslogtreecommitdiffstats
path: root/sys/dev/bge
diff options
context:
space:
mode:
authoroleg <oleg@FreeBSD.org>2006-08-24 14:41:16 +0000
committeroleg <oleg@FreeBSD.org>2006-08-24 14:41:16 +0000
commit6a84fb6ac0714a5581271822053eb301f43e76e2 (patch)
tree0b02fc5c4e61afeb79be4846fce6bb19ce41b5b7 /sys/dev/bge
parent9db068b977aea7bd4da4bed4946186746814284a (diff)
downloadFreeBSD-src-6a84fb6ac0714a5581271822053eb301f43e76e2.zip
FreeBSD-src-6a84fb6ac0714a5581271822053eb301f43e76e2.tar.gz
Properly lock ifmedia callbacks. This should prevent concurrent access to PHY.
Following issues should be resolved: - random watchdog timeouts (caused by concurrent phy access) - some link state issues - non working TX if media type was set explicitly PR: kern/98738 Approved by: glebius (mentor) MFC after: 2 weeks
Diffstat (limited to 'sys/dev/bge')
-rw-r--r--sys/dev/bge/if_bge.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 5931a35..0d00770 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -341,6 +341,7 @@ static void bge_init(void *);
static void bge_stop(struct bge_softc *);
static void bge_watchdog(struct ifnet *);
static void bge_shutdown(device_t);
+static int bge_ifmedia_upd_locked(struct ifnet *);
static int bge_ifmedia_upd(struct ifnet *);
static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
@@ -3206,7 +3207,7 @@ bge_init_locked(struct bge_softc *sc)
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
}
- bge_ifmedia_upd(ifp);
+ bge_ifmedia_upd_locked(ifp);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -3230,11 +3231,25 @@ bge_init(void *xsc)
static int
bge_ifmedia_upd(struct ifnet *ifp)
{
- struct bge_softc *sc;
+ struct bge_softc *sc = ifp->if_softc;
+ int res;
+
+ BGE_LOCK(sc);
+ res = bge_ifmedia_upd_locked(ifp);
+ BGE_UNLOCK(sc);
+
+ return (res);
+}
+
+static int
+bge_ifmedia_upd_locked(struct ifnet *ifp)
+{
+ struct bge_softc *sc = ifp->if_softc;
struct mii_data *mii;
struct ifmedia *ifm;
- sc = ifp->if_softc;
+ BGE_LOCK_ASSERT(sc);
+
ifm = &sc->bge_ifmedia;
/* If this is a 1000baseX NIC, enable the TBI port. */
@@ -3296,10 +3311,10 @@ bge_ifmedia_upd(struct ifnet *ifp)
static void
bge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
- struct bge_softc *sc;
+ struct bge_softc *sc = ifp->if_softc;
struct mii_data *mii;
- sc = ifp->if_softc;
+ BGE_LOCK(sc);
if (sc->bge_flags & BGE_FLAG_TBI) {
ifmr->ifm_status = IFM_AVALID;
@@ -3309,6 +3324,7 @@ bge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
ifmr->ifm_status |= IFM_ACTIVE;
else {
ifmr->ifm_active |= IFM_NONE;
+ BGE_UNLOCK(sc);
return;
}
ifmr->ifm_active |= IFM_1000_SX;
@@ -3316,6 +3332,7 @@ bge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
ifmr->ifm_active |= IFM_HDX;
else
ifmr->ifm_active |= IFM_FDX;
+ BGE_UNLOCK(sc);
return;
}
@@ -3323,6 +3340,8 @@ bge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
+
+ BGE_UNLOCK(sc);
}
static int
OpenPOWER on IntegriCloud