summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-08-08 21:03:54 +0000
committerjhb <jhb@FreeBSD.org>2005-08-08 21:03:54 +0000
commitba589db4851a78d7a0fdfc6e4a6a79496a2b3341 (patch)
treead0d7329056f3d2eec9bd9f58e02dec3446e8f3b
parent7d8af51fdcf9b077da486bdb2f6d70ba885d1aab (diff)
downloadFreeBSD-src-ba589db4851a78d7a0fdfc6e4a6a79496a2b3341.zip
FreeBSD-src-ba589db4851a78d7a0fdfc6e4a6a79496a2b3341.tar.gz
- Use callout_init_mtx() to close a small race between callout_stop() and
the timeout routine. - Fix locking in detach. - Add locking in shutdown. - Don't mess with the PCI command register in resume, the PCI bus driver already does this for us. - Add locking to the non-serial ifmedia routines. - Fix locking in ioctl. - Remove spls and support for 4.x. MFC after: 1 week
-rw-r--r--sys/dev/fxp/if_fxp.c84
-rw-r--r--sys/dev/fxp/if_fxpvar.h12
2 files changed, 25 insertions, 71 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index b0c3b7a..6575283 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -376,19 +376,17 @@ fxp_attach(device_t dev)
uint16_t data, myea[ETHER_ADDR_LEN / 2];
u_char eaddr[ETHER_ADDR_LEN];
int i, rid, m1, m2, prefer_iomap;
- int error, s;
+ int error;
error = 0;
sc = device_get_softc(dev);
sc->dev = dev;
- callout_init(&sc->stat_ch, CALLOUT_MPSAFE);
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
+ callout_init_mtx(&sc->stat_ch, &sc->sc_mtx, 0);
ifmedia_init(&sc->sc_media, 0, fxp_serial_ifmedia_upd,
fxp_serial_ifmedia_sts);
- s = splimp();
-
ifp = sc->ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
@@ -811,7 +809,6 @@ fxp_attach(device_t dev)
}
fail:
- splx(s);
if (error)
fxp_release(sc);
return (error);
@@ -895,18 +892,10 @@ static int
fxp_detach(device_t dev)
{
struct fxp_softc *sc = device_get_softc(dev);
- int s;
FXP_LOCK(sc);
- s = splimp();
-
sc->suspended = 1; /* Do same thing as we do for suspend */
/*
- * Close down routes etc.
- */
- ether_ifdetach(sc->ifp);
-
- /*
* Stop DMA and drop transmit queue, but disable interrupts first.
*/
CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);
@@ -914,14 +903,17 @@ fxp_detach(device_t dev)
FXP_UNLOCK(sc);
/*
+ * Close down routes etc.
+ */
+ ether_ifdetach(sc->ifp);
+
+ /*
* Unhook interrupt before dropping lock. This is to prevent
* races with fxp_intr().
*/
bus_teardown_intr(sc->dev, sc->irq, sc->ih);
sc->ih = NULL;
- splx(s);
-
/* Release our allocated resources. */
fxp_release(sc);
return (0);
@@ -935,12 +927,16 @@ fxp_detach(device_t dev)
static int
fxp_shutdown(device_t dev)
{
+ struct fxp_softc *sc = device_get_softc(dev);
+
/*
* Make sure that DMA is disabled prior to reboot. Not doing
* do could allow DMA to corrupt kernel memory during the
* reboot before the driver initializes.
*/
- fxp_stop((struct fxp_softc *) device_get_softc(dev));
+ FXP_LOCK(sc);
+ fxp_stop(sc);
+ FXP_UNLOCK(sc);
return (0);
}
@@ -953,17 +949,14 @@ static int
fxp_suspend(device_t dev)
{
struct fxp_softc *sc = device_get_softc(dev);
- int s;
FXP_LOCK(sc);
- s = splimp();
fxp_stop(sc);
sc->suspended = 1;
FXP_UNLOCK(sc);
- splx(s);
return (0);
}
@@ -976,16 +969,8 @@ fxp_resume(device_t dev)
{
struct fxp_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->ifp;
- uint16_t pci_command;
- int s;
FXP_LOCK(sc);
- s = splimp();
-
- /* reenable busmastering */
- pci_command = pci_read_config(dev, PCIR_COMMAND, 2);
- pci_command |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
- pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
DELAY(10);
@@ -997,7 +982,6 @@ fxp_resume(device_t dev)
sc->suspended = 0;
FXP_UNLOCK(sc);
- splx(s);
return (0);
}
@@ -1752,10 +1736,8 @@ fxp_tick(void *xsc)
struct fxp_softc *sc = xsc;
struct ifnet *ifp = sc->ifp;
struct fxp_stats *sp = sc->fxp_stats;
- int s;
- FXP_LOCK(sc);
- s = splimp();
+ FXP_LOCK_ASSERT(sc, MA_OWNED);
bus_dmamap_sync(sc->fxp_stag, sc->fxp_smap, BUS_DMASYNC_POSTREAD);
ifp->if_opackets += le32toh(sp->tx_good);
ifp->if_collisions += le32toh(sp->tx_total_collisions);
@@ -1840,8 +1822,6 @@ fxp_tick(void *xsc)
* Schedule another timeout one second from now.
*/
callout_reset(&sc->stat_ch, hz, fxp_tick, sc);
- FXP_UNLOCK(sc);
- splx(s);
}
/*
@@ -1941,10 +1921,9 @@ fxp_init_body(struct fxp_softc *sc)
struct fxp_cb_tx *tcbp;
struct fxp_tx *txp;
struct fxp_cb_mcs *mcsp;
- int i, prm, s;
+ int i, prm;
FXP_LOCK_ASSERT(sc, MA_OWNED);
- s = splimp();
/*
* Cancel any pending I/O
*/
@@ -2195,7 +2174,6 @@ fxp_init_body(struct fxp_softc *sc)
* Start stats updater.
*/
callout_reset(&sc->stat_ch, hz, fxp_tick, sc);
- splx(s);
}
static int
@@ -2222,7 +2200,9 @@ fxp_ifmedia_upd(struct ifnet *ifp)
struct mii_data *mii;
mii = device_get_softc(sc->miibus);
+ FXP_LOCK(sc);
mii_mediachg(mii);
+ FXP_UNLOCK(sc);
return (0);
}
@@ -2236,6 +2216,7 @@ fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
struct mii_data *mii;
mii = device_get_softc(sc->miibus);
+ FXP_LOCK(sc);
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
@@ -2244,6 +2225,7 @@ fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
sc->cu_resume_bug = 1;
else
sc->cu_resume_bug = 0;
+ FXP_UNLOCK(sc);
}
/*
@@ -2377,20 +2359,11 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct fxp_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct mii_data *mii;
- int flag, mask, s, error = 0;
-
- /*
- * Detaching causes us to call ioctl with the mutex owned. Preclude
- * that by saying we're busy if the lock is already held.
- */
- if (FXP_LOCKED(sc))
- return (EBUSY);
-
- FXP_LOCK(sc);
- s = splimp();
+ int flag, mask, error = 0;
switch (command) {
case SIOCSIFFLAGS:
+ FXP_LOCK(sc);
if (ifp->if_flags & IFF_ALLMULTI)
sc->flags |= FXP_FLAG_ALL_MCAST;
else
@@ -2408,10 +2381,12 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_RUNNING)
fxp_stop(sc);
}
+ FXP_UNLOCK(sc);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
+ FXP_LOCK(sc);
if (ifp->if_flags & IFF_ALLMULTI)
sc->flags |= FXP_FLAG_ALL_MCAST;
else
@@ -2428,6 +2403,7 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
*/
if (sc->flags & FXP_FLAG_ALL_MCAST)
fxp_init_body(sc);
+ FXP_UNLOCK(sc);
error = 0;
break;
@@ -2443,6 +2419,7 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCSIFCAP:
+ FXP_LOCK(sc);
mask = ifp->if_capenable ^ ifr->ifr_reqcap;
if (mask & IFCAP_POLLING)
ifp->if_capenable ^= IFCAP_POLLING;
@@ -2456,19 +2433,12 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_UP)
fxp_init_body(sc);
}
+ FXP_UNLOCK(sc);
break;
default:
- /*
- * ether_ioctl() will eventually call fxp_start() which
- * will result in mutex recursion so drop it first.
- */
- FXP_UNLOCK(sc);
error = ether_ioctl(ifp, command, data);
}
- if (FXP_LOCKED(sc))
- FXP_UNLOCK(sc);
- splx(s);
return (error);
}
@@ -2486,11 +2456,7 @@ fxp_mc_addrs(struct fxp_softc *sc)
nmcasts = 0;
if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) {
IF_ADDR_LOCK(ifp);
-#if __FreeBSD_version < 500000
- LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-#else
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-#endif
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (nmcasts >= MAXMCADDR) {
diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h
index 15471ae..f8da987 100644
--- a/sys/dev/fxp/if_fxpvar.h
+++ b/sys/dev/fxp/if_fxpvar.h
@@ -101,21 +101,9 @@
*/
#define TUNABLE_BUNDLE_MAX 6
-#if __FreeBSD_version < 500000
-#define FXP_LOCK(_sc)
-#define FXP_UNLOCK(_sc)
-#define FXP_LOCKED(_sc)
-#define FXP_LOCK_ASSERT(_sc, _what)
-#define INTR_MPSAFE 0
-#define mtx_init(a, b, c, d)
-#define mtx_destroy(a)
-struct mtx { int dummy; };
-#else
#define FXP_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define FXP_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
-#define FXP_LOCKED(_sc) mtx_owned(&(_sc)->sc_mtx)
#define FXP_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_mtx, (_what))
-#endif
/*
* Structures to handle TX and RX descriptors.
OpenPOWER on IntegriCloud