diff options
author | sam <sam@FreeBSD.org> | 2003-11-11 17:57:03 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-11-11 17:57:03 +0000 |
commit | 8a2a14a55f653c024428bc2f1267bf1e1771de20 (patch) | |
tree | a8ad5256f780fc0fcd236e6344703fcf5570fc98 /sys | |
parent | f6943f86fdd8bac9d73691ab487cdc0a38d6f28a (diff) | |
download | FreeBSD-src-8a2a14a55f653c024428bc2f1267bf1e1771de20.zip FreeBSD-src-8a2a14a55f653c024428bc2f1267bf1e1771de20.tar.gz |
o add locking
o mark isr MPSAFE
Supported by: FreeBSD Foundation
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/bge/if_bge.c | 166 | ||||
-rw-r--r-- | sys/dev/bge/if_bgereg.h | 10 |
2 files changed, 115 insertions, 61 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index dcb289e..3a2321a 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -186,6 +186,7 @@ static void bge_dma_free (struct bge_softc *); static void bge_txeof (struct bge_softc *); static void bge_rxeof (struct bge_softc *); +static void bge_tick_locked (struct bge_softc *); static void bge_tick (void *); static void bge_stats_update (struct bge_softc *); static void bge_stats_update_regs @@ -194,8 +195,10 @@ static int bge_encap (struct bge_softc *, struct mbuf *, u_int32_t *); static void bge_intr (void *); +static void bge_start_locked (struct ifnet *); static void bge_start (struct ifnet *); static int bge_ioctl (struct ifnet *, u_long, caddr_t); +static void bge_init_locked (struct bge_softc *); static void bge_init (void *); static void bge_stop (struct bge_softc *); static void bge_watchdog (struct ifnet *); @@ -1156,6 +1159,8 @@ bge_setmulti(sc) u_int32_t hashes[4] = { 0, 0, 0, 0 }; int h, i; + BGE_LOCK_ASSERT(sc); + ifp = &sc->arpcom.ac_if; if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { @@ -2227,15 +2232,12 @@ static int bge_attach(dev) device_t dev; { - int s; struct ifnet *ifp; struct bge_softc *sc; u_int32_t hwcfg = 0; u_int32_t mac_addr = 0; int unit, error = 0, rid; - s = splimp(); - sc = device_get_softc(dev); unit = device_get_unit(dev); sc->bge_dev = dev; @@ -2272,17 +2274,10 @@ bge_attach(dev) goto fail; } - error = bus_setup_intr(dev, sc->bge_irq, INTR_TYPE_NET, - bge_intr, sc, &sc->bge_intrhand); - - if (error) { - bge_release_resources(sc); - printf("bge%d: couldn't set up irq\n", unit); - goto fail; - } - sc->bge_unit = unit; + BGE_LOCK_INIT(sc, device_get_nameunit(dev)); + /* Try to reset the chip. */ bge_reset(sc); @@ -2450,11 +2445,20 @@ bge_attach(dev) * Call MI attach routine. */ ether_ifattach(ifp, sc->arpcom.ac_enaddr); - callout_handle_init(&sc->bge_stat_ch); + callout_init(&sc->bge_stat_ch, CALLOUT_MPSAFE); -fail: - splx(s); + /* + * Hookup IRQ last. + */ + error = bus_setup_intr(dev, sc->bge_irq, INTR_TYPE_NET | INTR_MPSAFE, + bge_intr, sc, &sc->bge_intrhand); + + if (error) { + bge_release_resources(sc); + printf("bge%d: couldn't set up irq\n", unit); + } +fail: return(error); } @@ -2464,16 +2468,16 @@ bge_detach(dev) { struct bge_softc *sc; struct ifnet *ifp; - int s; - - s = splimp(); sc = device_get_softc(dev); ifp = &sc->arpcom.ac_if; - ether_ifdetach(ifp); + BGE_LOCK(sc); bge_stop(sc); bge_reset(sc); + BGE_UNLOCK(sc); + + ether_ifdetach(ifp); if (sc->bge_tbi) { ifmedia_removeall(&sc->bge_ifmedia); @@ -2486,8 +2490,6 @@ bge_detach(dev) if (sc->bge_asicrev != BGE_ASICREV_BCM5705) bge_free_jumbo_mem(sc); - splx(s); - return(0); } @@ -2517,6 +2519,9 @@ bge_release_resources(sc) bge_dma_free(sc); + if (mtx_initialized(&sc->bge_mtx)) /* XXX */ + BGE_LOCK_DESTROY(sc); + return; } @@ -2621,6 +2626,8 @@ bge_rxeof(sc) struct ifnet *ifp; int stdcnt = 0, jumbocnt = 0; + BGE_LOCK_ASSERT(sc); + ifp = &sc->arpcom.ac_if; bus_dmamap_sync(sc->bge_cdata.bge_rx_return_ring_tag, @@ -2733,7 +2740,9 @@ bge_rxeof(sc) if (have_tag) VLAN_INPUT_TAG(ifp, m, vlan_tag, continue); + BGE_UNLOCK(sc); (*ifp->if_input)(ifp, m); + BGE_LOCK(sc); } bus_dmamap_sync(sc->bge_cdata.bge_rx_return_ring_tag, @@ -2763,6 +2772,8 @@ bge_txeof(sc) struct bge_tx_bd *cur_tx = NULL; struct ifnet *ifp; + BGE_LOCK_ASSERT(sc); + ifp = &sc->arpcom.ac_if; /* @@ -2806,6 +2817,8 @@ bge_intr(xsc) sc = xsc; ifp = &sc->arpcom.ac_if; + BGE_LOCK(sc); + bus_dmamap_sync(sc->bge_cdata.bge_status_tag, sc->bge_cdata.bge_status_map, BUS_DMASYNC_POSTWRITE); @@ -2838,8 +2851,8 @@ bge_intr(xsc) status = CSR_READ_4(sc, BGE_MAC_STS); if (status & BGE_MACSTAT_MI_INTERRUPT) { sc->bge_link = 0; - untimeout(bge_tick, sc, sc->bge_stat_ch); - bge_tick(sc); + callout_stop(&sc->bge_stat_ch); + bge_tick_locked(sc); /* Clear the interrupt */ CSR_WRITE_4(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_MI_INTERRUPT); @@ -2865,8 +2878,8 @@ bge_intr(xsc) if (!(status & (BGE_MACSTAT_PORT_DECODE_ERROR| BGE_MACSTAT_MI_COMPLETE))) { sc->bge_link = 0; - untimeout(bge_tick, sc, sc->bge_stat_ch); - bge_tick(sc); + callout_stop(&sc->bge_stat_ch); + bge_tick_locked(sc); } /* Clear the interrupt */ CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED| @@ -2895,35 +2908,32 @@ bge_intr(xsc) CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0); if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL) - bge_start(ifp); + bge_start_locked(ifp); + + BGE_UNLOCK(sc); return; } static void -bge_tick(xsc) - void *xsc; -{ +bge_tick_locked(sc) struct bge_softc *sc; +{ struct mii_data *mii = NULL; struct ifmedia *ifm = NULL; struct ifnet *ifp; - int s; - sc = xsc; ifp = &sc->arpcom.ac_if; - s = splimp(); + BGE_LOCK_ASSERT(sc); if (sc->bge_asicrev == BGE_ASICREV_BCM5705) bge_stats_update_regs(sc); else bge_stats_update(sc); - sc->bge_stat_ch = timeout(bge_tick, sc, hz); - if (sc->bge_link) { - splx(s); + callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc); + if (sc->bge_link) return; - } if (sc->bge_tbi) { ifm = &sc->bge_ifmedia; @@ -2933,9 +2943,8 @@ bge_tick(xsc) CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF); printf("bge%d: gigabit link up\n", sc->bge_unit); if (ifp->if_snd.ifq_head != NULL) - bge_start(ifp); + bge_start_locked(ifp); } - splx(s); return; } @@ -2950,15 +2959,26 @@ bge_tick(xsc) printf("bge%d: gigabit link up\n", sc->bge_unit); if (ifp->if_snd.ifq_head != NULL) - bge_start(ifp); + bge_start_locked(ifp); } - splx(s); - return; } static void +bge_tick(xsc) + void *xsc; +{ + struct bge_softc *sc; + + sc = xsc; + + BGE_LOCK(sc); + bge_tick_locked(sc); + BGE_UNLOCK(sc); +} + +static void bge_stats_update_regs(sc) struct bge_softc *sc; { @@ -3094,7 +3114,7 @@ bge_encap(sc, m_head, txidx) * to the mbuf data regions directly in the transmit descriptors. */ static void -bge_start(ifp) +bge_start_locked(ifp) struct ifnet *ifp; { struct bge_softc *sc; @@ -3163,23 +3183,35 @@ bge_start(ifp) return; } +/* + * Main transmit routine. To avoid having to do mbuf copies, we put pointers + * to the mbuf data regions directly in the transmit descriptors. + */ static void -bge_init(xsc) - void *xsc; +bge_start(ifp) + struct ifnet *ifp; +{ + struct bge_softc *sc; + + sc = ifp->if_softc; + BGE_LOCK(sc); + bge_start_locked(ifp); + BGE_UNLOCK(sc); +} + +static void +bge_init_locked(sc) + struct bge_softc *sc; { - struct bge_softc *sc = xsc; struct ifnet *ifp; u_int16_t *m; - int s; - s = splimp(); + BGE_LOCK_ASSERT(sc); ifp = &sc->arpcom.ac_if; - if (ifp->if_flags & IFF_RUNNING) { - splx(s); + if (ifp->if_flags & IFF_RUNNING) return; - } /* Cancel pending I/O and flush buffers. */ bge_stop(sc); @@ -3192,7 +3224,6 @@ bge_init(xsc) */ if (bge_blockinit(sc)) { printf("bge%d: initialization failure\n", sc->bge_unit); - splx(s); return; } @@ -3267,9 +3298,20 @@ bge_init(xsc) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - splx(s); + callout_reset(&sc->bge_stat_ch, hz, bge_tick, sc); + + return; +} + +static void +bge_init(xsc) + void *xsc; +{ + struct bge_softc *sc = xsc; - sc->bge_stat_ch = timeout(bge_tick, sc, hz); + BGE_LOCK(sc); + bge_init_locked(sc); + BGE_UNLOCK(sc); return; } @@ -3366,11 +3408,9 @@ bge_ioctl(ifp, command, data) { struct bge_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; - int s, mask, error = 0; + int mask, error = 0; struct mii_data *mii; - s = splimp(); - switch(command) { case SIOCSIFMTU: /* Disallow jumbo frames on 5705. */ @@ -3384,6 +3424,7 @@ bge_ioctl(ifp, command, data) } break; case SIOCSIFFLAGS: + BGE_LOCK(sc); if (ifp->if_flags & IFF_UP) { /* * If only the state of the PROMISC flag changed, @@ -3404,19 +3445,22 @@ bge_ioctl(ifp, command, data) BGE_CLRBIT(sc, BGE_RX_MODE, BGE_RXMODE_RX_PROMISC); } else - bge_init(sc); + bge_init_locked(sc); } else { if (ifp->if_flags & IFF_RUNNING) { bge_stop(sc); } } sc->bge_if_flags = ifp->if_flags; + BGE_UNLOCK(sc); error = 0; break; case SIOCADDMULTI: case SIOCDELMULTI: if (ifp->if_flags & IFF_RUNNING) { + BGE_LOCK(sc); bge_setmulti(sc); + BGE_UNLOCK(sc); error = 0; } break; @@ -3446,8 +3490,6 @@ bge_ioctl(ifp, command, data) break; } - (void)splx(s); - return(error); } @@ -3482,12 +3524,14 @@ bge_stop(sc) struct mii_data *mii = NULL; int mtmp, itmp; + BGE_LOCK_ASSERT(sc); + ifp = &sc->arpcom.ac_if; if (!sc->bge_tbi) mii = device_get_softc(sc->bge_miibus); - untimeout(bge_tick, sc, sc->bge_stat_ch); + callout_stop(&sc->bge_stat_ch); /* * Disable all of the receiver blocks @@ -3584,8 +3628,10 @@ bge_shutdown(dev) sc = device_get_softc(dev); + BGE_LOCK(sc); bge_stop(sc); bge_reset(sc); + BGE_UNLOCK(sc); return; } diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h index b19ad65..89225d3 100644 --- a/sys/dev/bge/if_bgereg.h +++ b/sys/dev/bge/if_bgereg.h @@ -2259,6 +2259,7 @@ struct bge_bcom_hack { struct bge_softc { struct arpcom arpcom; /* interface info */ device_t bge_dev; + struct mtx bge_mtx; device_t bge_miibus; bus_space_handle_t bge_bhandle; vm_offset_t bge_vhandle; @@ -2294,7 +2295,14 @@ struct bge_softc { int bge_if_flags; int bge_txcnt; int bge_link; - struct callout_handle bge_stat_ch; + struct callout bge_stat_ch; char *bge_vpd_prodname; char *bge_vpd_readonly; }; + +#define BGE_LOCK_INIT(_sc, _name) \ + mtx_init(&(_sc)->bge_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) +#define BGE_LOCK(_sc) mtx_lock(&(_sc)->bge_mtx) +#define BGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->bge_mtx, MA_OWNED) +#define BGE_UNLOCK(_sc) mtx_unlock(&(_sc)->bge_mtx) +#define BGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->bge_mtx) |