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
This commit is contained in:
oleg 2006-08-24 14:41:16 +00:00
parent 9db068b977
commit 6a84fb6ac0

View File

@ -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