summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-08-18 19:10:07 +0000
committerjhb <jhb@FreeBSD.org>2005-08-18 19:10:07 +0000
commit43f80b5f8e6c84ef9838d1bed98cf883a5999018 (patch)
treee9372f0bf6169de5d6982a3f1bd766997e53a5bc /sys
parentdc54325556b0b6220baeac66edf106ef84071307 (diff)
downloadFreeBSD-src-43f80b5f8e6c84ef9838d1bed98cf883a5999018.zip
FreeBSD-src-43f80b5f8e6c84ef9838d1bed98cf883a5999018.tar.gz
Fixup locking and mark MPSAFE:
- Add locked versions of start and init. The SRM_MEDIA code in dc_init() stayed in dc_init() instead of moving to dc_init_locked() to make the locking saner. - Use callout_init_mtx(). - Fixup locking in detach and ioctl. - Lock the driver in the ifmedia callouts. - Don't recurse on the driver lock. - De-spl. MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/dc/if_dc.c147
-rw-r--r--sys/pci/if_dc.c147
2 files changed, 154 insertions, 140 deletions
diff --git a/sys/dev/dc/if_dc.c b/sys/dev/dc/if_dc.c
index 4daa230..fce20b4 100644
--- a/sys/dev/dc/if_dc.c
+++ b/sys/dev/dc/if_dc.c
@@ -235,8 +235,10 @@ static void dc_tick(void *);
static void dc_tx_underrun(struct dc_softc *);
static void dc_intr(void *);
static void dc_start(struct ifnet *);
+static void dc_start_locked(struct ifnet *);
static int dc_ioctl(struct ifnet *, u_long, caddr_t);
static void dc_init(void *);
+static void dc_init_locked(struct dc_softc *);
static void dc_stop(struct dc_softc *);
static void dc_watchdog(struct ifnet *);
static void dc_shutdown(device_t);
@@ -343,8 +345,6 @@ DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
-#define IS_MPSAFE 0
-
static void
dc_delay(struct dc_softc *sc)
{
@@ -670,8 +670,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
int i, ack;
- DC_LOCK(sc);
-
/*
* Set up frame for RX.
*/
@@ -724,8 +722,6 @@ fail:
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
- DC_UNLOCK(sc);
-
if (ack)
return (1);
return (0);
@@ -738,7 +734,6 @@ static int
dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
- DC_LOCK(sc);
/*
* Set up frame for TX.
*/
@@ -763,8 +758,6 @@ dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
- DC_UNLOCK(sc);
-
return (0);
}
@@ -1844,7 +1837,7 @@ dc_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF | MTX_RECURSE);
+ MTX_DEF);
/*
* Map control/status registers.
@@ -2194,8 +2187,6 @@ dc_attach(device_t dev)
/* XXX: bleah, MTU gets overwritten in ether_ifattach() */
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- if (!IS_MPSAFE)
- ifp->if_flags |= IFF_NEEDSGIANT;
ifp->if_ioctl = dc_ioctl;
ifp->if_start = dc_start;
ifp->if_watchdog = dc_watchdog;
@@ -2276,7 +2267,7 @@ dc_attach(device_t dev)
#endif
ifp->if_capenable = ifp->if_capabilities;
- callout_init(&sc->dc_stat_ch, IS_MPSAFE ? CALLOUT_MPSAFE : 0);
+ callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
#ifdef SRM_MEDIA
sc->dc_srm_media = 0;
@@ -2310,8 +2301,7 @@ dc_attach(device_t dev)
ether_ifattach(ifp, eaddr);
/* Hook interrupt last to avoid having to lock softc */
- error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET |
- (IS_MPSAFE ? INTR_MPSAFE : 0),
+ error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE,
dc_intr, sc, &sc->dc_intrhand);
if (error) {
@@ -2344,13 +2334,15 @@ dc_detach(device_t dev)
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
- DC_LOCK(sc);
ifp = sc->dc_ifp;
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
+ DC_LOCK(sc);
dc_stop(sc);
+ DC_UNLOCK(sc);
+ callout_drain(&sc->dc_stat_ch);
ether_ifdetach(ifp);
if_free(ifp);
}
@@ -2390,7 +2382,6 @@ dc_detach(device_t dev)
}
free(sc->dc_srom, M_DEVBUF);
- DC_UNLOCK(sc);
mtx_destroy(&sc->dc_mtx);
return (0);
@@ -2751,7 +2742,7 @@ dc_rxeof(struct dc_softc *sc)
DC_INC(i, DC_RX_LIST_CNT);
continue;
} else {
- dc_init(sc);
+ dc_init_locked(sc);
return;
}
}
@@ -2879,7 +2870,7 @@ dc_txeof(struct dc_softc *sc)
if (txstat & DC_TXSTAT_LATECOLL)
ifp->if_collisions++;
if (!(txstat & DC_TXSTAT_UNDERRUN)) {
- dc_init(sc);
+ dc_init_locked(sc);
return;
}
}
@@ -2918,7 +2909,7 @@ dc_tick(void *xsc)
u_int32_t r;
sc = xsc;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
mii = device_get_softc(sc->dc_miibus);
@@ -2972,15 +2963,13 @@ dc_tick(void *xsc)
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
sc->dc_link++;
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start(ifp);
+ dc_start_locked(ifp);
}
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
-
- DC_UNLOCK(sc);
}
/*
@@ -2994,7 +2983,7 @@ dc_tx_underrun(struct dc_softc *sc)
int i;
if (DC_IS_DAVICOM(sc))
- dc_init(sc);
+ dc_init_locked(sc);
if (DC_IS_INTEL(sc)) {
/*
@@ -3013,7 +3002,7 @@ dc_tx_underrun(struct dc_softc *sc)
if (i == DC_TIMEOUT) {
if_printf(sc->dc_ifp,
"failed to force tx to idle state\n");
- dc_init(sc);
+ dc_init_locked(sc);
}
}
@@ -3055,7 +3044,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
dc_txeof(sc);
if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
- dc_start(ifp);
+ dc_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
u_int32_t status;
@@ -3088,7 +3077,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (status & DC_ISR_BUS_ERR) {
if_printf(ifp, "dc_poll: bus error\n");
dc_reset(sc);
- dc_init(sc);
+ dc_init_locked(sc);
}
}
DC_UNLOCK(sc);
@@ -3175,7 +3164,7 @@ dc_intr(void *arg)
if (status & DC_ISR_BUS_ERR) {
dc_reset(sc);
- dc_init(sc);
+ dc_init_locked(sc);
}
}
@@ -3183,7 +3172,7 @@ dc_intr(void *arg)
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start(ifp);
+ dc_start_locked(ifp);
#ifdef DEVICE_POLLING
done:
@@ -3312,23 +3301,30 @@ static void
dc_start(struct ifnet *ifp)
{
struct dc_softc *sc;
+
+ sc = ifp->if_softc;
+ DC_LOCK(sc);
+ dc_start_locked(ifp);
+ DC_UNLOCK(sc);
+}
+
+static void
+dc_start_locked(struct ifnet *ifp)
+{
+ struct dc_softc *sc;
struct mbuf *m_head = NULL, *m;
unsigned int queued = 0;
int idx;
sc = ifp->if_softc;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
- if (!sc->dc_link && ifp->if_snd.ifq_len < 10) {
- DC_UNLOCK(sc);
+ if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
return;
- }
- if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
- DC_UNLOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
return;
- }
idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
@@ -3380,18 +3376,37 @@ dc_start(struct ifnet *ifp)
*/
ifp->if_timer = 5;
}
-
- DC_UNLOCK(sc);
}
static void
dc_init(void *xsc)
{
struct dc_softc *sc = xsc;
+
+ DC_LOCK(sc);
+ dc_init_locked(sc);
+#ifdef SRM_MEDIA
+ if(sc->dc_srm_media) {
+ struct ifreq ifr;
+ struct mii_data *mii;
+
+ ifr.ifr_media = sc->dc_srm_media;
+ sc->dc_srm_media = 0;
+ DC_UNLOCK(sc);
+ mii = device_get_softc(sc->dc_miibus);
+ ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
+ } else
+#endif
+ DC_UNLOCK(sc);
+}
+
+static void
+dc_init_locked(struct dc_softc *sc)
+{
struct ifnet *ifp = sc->dc_ifp;
struct mii_data *mii;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
mii = device_get_softc(sc->dc_miibus);
@@ -3487,7 +3502,6 @@ dc_init(void *xsc)
if_printf(ifp,
"initialization failed: no memory for rx buffers\n");
dc_stop(sc);
- DC_UNLOCK(sc);
return;
}
@@ -3559,17 +3573,6 @@ dc_init(void *xsc)
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
-
-#ifdef SRM_MEDIA
- if(sc->dc_srm_media) {
- struct ifreq ifr;
-
- ifr.ifr_media = sc->dc_srm_media;
- ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
- sc->dc_srm_media = 0;
- }
-#endif
- DC_UNLOCK(sc);
}
/*
@@ -3584,6 +3587,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
+ DC_LOCK(sc);
mii_mediachg(mii);
ifm = &mii->mii_media;
@@ -3592,6 +3596,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
dc_setcfg(sc, ifm->ifm_media);
else
sc->dc_link = 0;
+ DC_UNLOCK(sc);
return (0);
}
@@ -3608,6 +3613,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
+ DC_LOCK(sc);
mii_pollstat(mii);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc)) {
@@ -3619,6 +3625,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
}
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
+ DC_UNLOCK(sc);
}
static int
@@ -3629,10 +3636,9 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct mii_data *mii;
int error = 0;
- DC_LOCK(sc);
-
switch (command) {
case SIOCSIFFLAGS:
+ DC_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI);
@@ -3642,18 +3648,21 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
dc_setfilt(sc);
} else {
sc->dc_txthresh = 0;
- dc_init(sc);
+ dc_init_locked(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
dc_stop(sc);
}
sc->dc_if_flags = ifp->if_flags;
+ DC_UNLOCK(sc);
error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
+ DC_LOCK(sc);
dc_setfilt(sc);
+ DC_UNLOCK(sc);
error = 0;
break;
case SIOCGIFMEDIA:
@@ -3661,21 +3670,23 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
#ifdef SRM_MEDIA
+ DC_LOCK(sc);
if (sc->dc_srm_media)
sc->dc_srm_media = 0;
+ DC_UNLOCK(sc);
#endif
break;
case SIOCSIFCAP:
+ DC_LOCK(sc);
ifp->if_capenable &= ~IFCAP_POLLING;
ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
+ DC_UNLOCK(sc);
break;
default:
error = ether_ioctl(ifp, command, data);
break;
}
- DC_UNLOCK(sc);
-
return (error);
}
@@ -3693,10 +3704,10 @@ dc_watchdog(struct ifnet *ifp)
dc_stop(sc);
dc_reset(sc);
- dc_init(sc);
+ dc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start(ifp);
+ dc_start_locked(ifp);
DC_UNLOCK(sc);
}
@@ -3714,7 +3725,7 @@ dc_stop(struct dc_softc *sc)
int i;
u_int32_t ctl;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
ifp->if_timer = 0;
@@ -3762,8 +3773,6 @@ dc_stop(struct dc_softc *sc)
}
}
bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
-
- DC_UNLOCK(sc);
}
/*
@@ -3775,15 +3784,13 @@ static int
dc_suspend(device_t dev)
{
struct dc_softc *sc;
- int s;
-
- s = splimp();
sc = device_get_softc(dev);
+ DC_LOCK(sc);
dc_stop(sc);
sc->suspended = 1;
+ DC_UNLOCK(sc);
- splx(s);
return (0);
}
@@ -3797,20 +3804,18 @@ dc_resume(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
- int s;
-
- s = splimp();
sc = device_get_softc(dev);
ifp = sc->dc_ifp;
/* reinitialize interface if necessary */
+ DC_LOCK(sc);
if (ifp->if_flags & IFF_UP)
- dc_init(sc);
+ dc_init_locked(sc);
sc->suspended = 0;
+ DC_UNLOCK(sc);
- splx(s);
return (0);
}
@@ -3825,5 +3830,7 @@ dc_shutdown(device_t dev)
sc = device_get_softc(dev);
+ DC_LOCK(sc);
dc_stop(sc);
+ DC_UNLOCK(sc);
}
diff --git a/sys/pci/if_dc.c b/sys/pci/if_dc.c
index 4daa230..fce20b4 100644
--- a/sys/pci/if_dc.c
+++ b/sys/pci/if_dc.c
@@ -235,8 +235,10 @@ static void dc_tick(void *);
static void dc_tx_underrun(struct dc_softc *);
static void dc_intr(void *);
static void dc_start(struct ifnet *);
+static void dc_start_locked(struct ifnet *);
static int dc_ioctl(struct ifnet *, u_long, caddr_t);
static void dc_init(void *);
+static void dc_init_locked(struct dc_softc *);
static void dc_stop(struct dc_softc *);
static void dc_watchdog(struct ifnet *);
static void dc_shutdown(device_t);
@@ -343,8 +345,6 @@ DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
-#define IS_MPSAFE 0
-
static void
dc_delay(struct dc_softc *sc)
{
@@ -670,8 +670,6 @@ dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
int i, ack;
- DC_LOCK(sc);
-
/*
* Set up frame for RX.
*/
@@ -724,8 +722,6 @@ fail:
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
- DC_UNLOCK(sc);
-
if (ack)
return (1);
return (0);
@@ -738,7 +734,6 @@ static int
dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
- DC_LOCK(sc);
/*
* Set up frame for TX.
*/
@@ -763,8 +758,6 @@ dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
- DC_UNLOCK(sc);
-
return (0);
}
@@ -1844,7 +1837,7 @@ dc_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF | MTX_RECURSE);
+ MTX_DEF);
/*
* Map control/status registers.
@@ -2194,8 +2187,6 @@ dc_attach(device_t dev)
/* XXX: bleah, MTU gets overwritten in ether_ifattach() */
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- if (!IS_MPSAFE)
- ifp->if_flags |= IFF_NEEDSGIANT;
ifp->if_ioctl = dc_ioctl;
ifp->if_start = dc_start;
ifp->if_watchdog = dc_watchdog;
@@ -2276,7 +2267,7 @@ dc_attach(device_t dev)
#endif
ifp->if_capenable = ifp->if_capabilities;
- callout_init(&sc->dc_stat_ch, IS_MPSAFE ? CALLOUT_MPSAFE : 0);
+ callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
#ifdef SRM_MEDIA
sc->dc_srm_media = 0;
@@ -2310,8 +2301,7 @@ dc_attach(device_t dev)
ether_ifattach(ifp, eaddr);
/* Hook interrupt last to avoid having to lock softc */
- error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET |
- (IS_MPSAFE ? INTR_MPSAFE : 0),
+ error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE,
dc_intr, sc, &sc->dc_intrhand);
if (error) {
@@ -2344,13 +2334,15 @@ dc_detach(device_t dev)
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
- DC_LOCK(sc);
ifp = sc->dc_ifp;
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
+ DC_LOCK(sc);
dc_stop(sc);
+ DC_UNLOCK(sc);
+ callout_drain(&sc->dc_stat_ch);
ether_ifdetach(ifp);
if_free(ifp);
}
@@ -2390,7 +2382,6 @@ dc_detach(device_t dev)
}
free(sc->dc_srom, M_DEVBUF);
- DC_UNLOCK(sc);
mtx_destroy(&sc->dc_mtx);
return (0);
@@ -2751,7 +2742,7 @@ dc_rxeof(struct dc_softc *sc)
DC_INC(i, DC_RX_LIST_CNT);
continue;
} else {
- dc_init(sc);
+ dc_init_locked(sc);
return;
}
}
@@ -2879,7 +2870,7 @@ dc_txeof(struct dc_softc *sc)
if (txstat & DC_TXSTAT_LATECOLL)
ifp->if_collisions++;
if (!(txstat & DC_TXSTAT_UNDERRUN)) {
- dc_init(sc);
+ dc_init_locked(sc);
return;
}
}
@@ -2918,7 +2909,7 @@ dc_tick(void *xsc)
u_int32_t r;
sc = xsc;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
mii = device_get_softc(sc->dc_miibus);
@@ -2972,15 +2963,13 @@ dc_tick(void *xsc)
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
sc->dc_link++;
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start(ifp);
+ dc_start_locked(ifp);
}
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
-
- DC_UNLOCK(sc);
}
/*
@@ -2994,7 +2983,7 @@ dc_tx_underrun(struct dc_softc *sc)
int i;
if (DC_IS_DAVICOM(sc))
- dc_init(sc);
+ dc_init_locked(sc);
if (DC_IS_INTEL(sc)) {
/*
@@ -3013,7 +3002,7 @@ dc_tx_underrun(struct dc_softc *sc)
if (i == DC_TIMEOUT) {
if_printf(sc->dc_ifp,
"failed to force tx to idle state\n");
- dc_init(sc);
+ dc_init_locked(sc);
}
}
@@ -3055,7 +3044,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
dc_txeof(sc);
if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
- dc_start(ifp);
+ dc_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
u_int32_t status;
@@ -3088,7 +3077,7 @@ dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (status & DC_ISR_BUS_ERR) {
if_printf(ifp, "dc_poll: bus error\n");
dc_reset(sc);
- dc_init(sc);
+ dc_init_locked(sc);
}
}
DC_UNLOCK(sc);
@@ -3175,7 +3164,7 @@ dc_intr(void *arg)
if (status & DC_ISR_BUS_ERR) {
dc_reset(sc);
- dc_init(sc);
+ dc_init_locked(sc);
}
}
@@ -3183,7 +3172,7 @@ dc_intr(void *arg)
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start(ifp);
+ dc_start_locked(ifp);
#ifdef DEVICE_POLLING
done:
@@ -3312,23 +3301,30 @@ static void
dc_start(struct ifnet *ifp)
{
struct dc_softc *sc;
+
+ sc = ifp->if_softc;
+ DC_LOCK(sc);
+ dc_start_locked(ifp);
+ DC_UNLOCK(sc);
+}
+
+static void
+dc_start_locked(struct ifnet *ifp)
+{
+ struct dc_softc *sc;
struct mbuf *m_head = NULL, *m;
unsigned int queued = 0;
int idx;
sc = ifp->if_softc;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
- if (!sc->dc_link && ifp->if_snd.ifq_len < 10) {
- DC_UNLOCK(sc);
+ if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
return;
- }
- if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
- DC_UNLOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
return;
- }
idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
@@ -3380,18 +3376,37 @@ dc_start(struct ifnet *ifp)
*/
ifp->if_timer = 5;
}
-
- DC_UNLOCK(sc);
}
static void
dc_init(void *xsc)
{
struct dc_softc *sc = xsc;
+
+ DC_LOCK(sc);
+ dc_init_locked(sc);
+#ifdef SRM_MEDIA
+ if(sc->dc_srm_media) {
+ struct ifreq ifr;
+ struct mii_data *mii;
+
+ ifr.ifr_media = sc->dc_srm_media;
+ sc->dc_srm_media = 0;
+ DC_UNLOCK(sc);
+ mii = device_get_softc(sc->dc_miibus);
+ ifmedia_ioctl(sc->dc_ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
+ } else
+#endif
+ DC_UNLOCK(sc);
+}
+
+static void
+dc_init_locked(struct dc_softc *sc)
+{
struct ifnet *ifp = sc->dc_ifp;
struct mii_data *mii;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
mii = device_get_softc(sc->dc_miibus);
@@ -3487,7 +3502,6 @@ dc_init(void *xsc)
if_printf(ifp,
"initialization failed: no memory for rx buffers\n");
dc_stop(sc);
- DC_UNLOCK(sc);
return;
}
@@ -3559,17 +3573,6 @@ dc_init(void *xsc)
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
-
-#ifdef SRM_MEDIA
- if(sc->dc_srm_media) {
- struct ifreq ifr;
-
- ifr.ifr_media = sc->dc_srm_media;
- ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA);
- sc->dc_srm_media = 0;
- }
-#endif
- DC_UNLOCK(sc);
}
/*
@@ -3584,6 +3587,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
+ DC_LOCK(sc);
mii_mediachg(mii);
ifm = &mii->mii_media;
@@ -3592,6 +3596,7 @@ dc_ifmedia_upd(struct ifnet *ifp)
dc_setcfg(sc, ifm->ifm_media);
else
sc->dc_link = 0;
+ DC_UNLOCK(sc);
return (0);
}
@@ -3608,6 +3613,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
+ DC_LOCK(sc);
mii_pollstat(mii);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc)) {
@@ -3619,6 +3625,7 @@ dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
}
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
+ DC_UNLOCK(sc);
}
static int
@@ -3629,10 +3636,9 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct mii_data *mii;
int error = 0;
- DC_LOCK(sc);
-
switch (command) {
case SIOCSIFFLAGS:
+ DC_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI);
@@ -3642,18 +3648,21 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
dc_setfilt(sc);
} else {
sc->dc_txthresh = 0;
- dc_init(sc);
+ dc_init_locked(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
dc_stop(sc);
}
sc->dc_if_flags = ifp->if_flags;
+ DC_UNLOCK(sc);
error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
+ DC_LOCK(sc);
dc_setfilt(sc);
+ DC_UNLOCK(sc);
error = 0;
break;
case SIOCGIFMEDIA:
@@ -3661,21 +3670,23 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
#ifdef SRM_MEDIA
+ DC_LOCK(sc);
if (sc->dc_srm_media)
sc->dc_srm_media = 0;
+ DC_UNLOCK(sc);
#endif
break;
case SIOCSIFCAP:
+ DC_LOCK(sc);
ifp->if_capenable &= ~IFCAP_POLLING;
ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
+ DC_UNLOCK(sc);
break;
default:
error = ether_ioctl(ifp, command, data);
break;
}
- DC_UNLOCK(sc);
-
return (error);
}
@@ -3693,10 +3704,10 @@ dc_watchdog(struct ifnet *ifp)
dc_stop(sc);
dc_reset(sc);
- dc_init(sc);
+ dc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start(ifp);
+ dc_start_locked(ifp);
DC_UNLOCK(sc);
}
@@ -3714,7 +3725,7 @@ dc_stop(struct dc_softc *sc)
int i;
u_int32_t ctl;
- DC_LOCK(sc);
+ DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
ifp->if_timer = 0;
@@ -3762,8 +3773,6 @@ dc_stop(struct dc_softc *sc)
}
}
bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
-
- DC_UNLOCK(sc);
}
/*
@@ -3775,15 +3784,13 @@ static int
dc_suspend(device_t dev)
{
struct dc_softc *sc;
- int s;
-
- s = splimp();
sc = device_get_softc(dev);
+ DC_LOCK(sc);
dc_stop(sc);
sc->suspended = 1;
+ DC_UNLOCK(sc);
- splx(s);
return (0);
}
@@ -3797,20 +3804,18 @@ dc_resume(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
- int s;
-
- s = splimp();
sc = device_get_softc(dev);
ifp = sc->dc_ifp;
/* reinitialize interface if necessary */
+ DC_LOCK(sc);
if (ifp->if_flags & IFF_UP)
- dc_init(sc);
+ dc_init_locked(sc);
sc->suspended = 0;
+ DC_UNLOCK(sc);
- splx(s);
return (0);
}
@@ -3825,5 +3830,7 @@ dc_shutdown(device_t dev)
sc = device_get_softc(dev);
+ DC_LOCK(sc);
dc_stop(sc);
+ DC_UNLOCK(sc);
}
OpenPOWER on IntegriCloud