From d675d9c68fc46a791701a318b0c4035d0ce8e66a Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 27 Jul 2005 13:51:01 +0000 Subject: - Use callout_*() rather than timeout() to periodically poll the media. - Add locking to protect the softc and mark this driver as MP safe. There are still some edge cases with multiport cards that need more locking work. MFC after: 1 week Tested on: alpha --- sys/dev/de/if_de.c | 189 +++++++++++++++++++++++++++++++++++++++----------- sys/dev/de/if_devar.h | 7 ++ 2 files changed, 156 insertions(+), 40 deletions(-) (limited to 'sys/dev/de') diff --git a/sys/dev/de/if_de.c b/sys/dev/de/if_de.c index d116015..5fdff82 100644 --- a/sys/dev/de/if_de.c +++ b/sys/dev/de/if_de.c @@ -128,6 +128,7 @@ static void tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr, static void tulip_reset(tulip_softc_t * const sc); static void tulip_rx_intr(tulip_softc_t * const sc); static int tulip_srom_decode(tulip_softc_t * const sc); +static void tulip_start(tulip_softc_t * const sc); static struct mbuf * tulip_txput(tulip_softc_t * const sc, struct mbuf *m); static void tulip_txput_setup(tulip_softc_t * const sc); @@ -137,26 +138,28 @@ tulip_timeout_callback( void *arg) { tulip_softc_t * const sc = arg; - int s = splimp(); TULIP_PERFSTART(timeout) + TULIP_LOCK(sc); sc->tulip_flags &= ~TULIP_TIMEOUTPENDING; sc->tulip_probe_timeout -= 1000 / TULIP_HZ; (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER); TULIP_PERFEND(timeout); - splx(s); + TULIP_UNLOCK(sc); } static void tulip_timeout( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); if (sc->tulip_flags & TULIP_TIMEOUTPENDING) return; sc->tulip_flags |= TULIP_TIMEOUTPENDING; - timeout(tulip_timeout_callback, sc, (hz + TULIP_HZ / 2) / TULIP_HZ); + callout_reset(&sc->tulip_callout, (hz + TULIP_HZ / 2) / TULIP_HZ, + tulip_timeout_callback, sc); } @@ -172,6 +175,7 @@ tulip_txprobe( * either is connected so the transmit is the only way * to verify the connectivity. */ + TULIP_LOCK_ASSERT(sc); MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return 0; @@ -207,6 +211,7 @@ tulip_media_set( { const tulip_media_info_t *mi = sc->tulip_mediums[media]; + TULIP_LOCK_ASSERT(sc); if (mi == NULL) return; @@ -299,6 +304,7 @@ tulip_linkup( tulip_softc_t * const sc, tulip_media_t media) { + TULIP_LOCK_ASSERT(sc); if ((sc->tulip_flags & TULIP_LINKUP) == 0) sc->tulip_flags |= TULIP_PRINTLINKUP; sc->tulip_flags |= TULIP_LINKUP; @@ -354,6 +360,7 @@ tulip_media_print( { struct ifnet *ifp = sc->tulip_ifp; + TULIP_LOCK_ASSERT(sc); if ((sc->tulip_flags & TULIP_LINKUP) == 0) return; if (sc->tulip_flags & TULIP_PRINTMEDIA) { @@ -376,6 +383,8 @@ tulip_21140_gpr_media_sense( tulip_media_t last_media = TULIP_MEDIA_UNKNOWN; tulip_media_t media; + TULIP_LOCK_ASSERT(sc); + /* * If one of the media blocks contained a default media flag, * use that. @@ -438,6 +447,7 @@ tulip_media_link_monitor( const tulip_media_info_t * const mi = sc->tulip_mediums[sc->tulip_media]; tulip_link_status_t linkup = TULIP_LINK_DOWN; + TULIP_LOCK_ASSERT(sc); if (mi == NULL) { #if defined(DIAGNOSTIC) || defined(TULIP_DEBUG) panic("tulip_media_link_monitor: %s: botch at line %d\n", @@ -548,6 +558,7 @@ tulip_media_poll( { struct ifnet *ifp = sc->tulip_ifp; + TULIP_LOCK_ASSERT(sc); #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_events[event]++; #endif @@ -835,6 +846,7 @@ static void tulip_media_select( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); if (sc->tulip_features & TULIP_HAVE_GPR) { TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_PINSET|sc->tulip_gpinit); DELAY(10); @@ -859,6 +871,7 @@ tulip_21040_mediainfo_init( tulip_softc_t * const sc, tulip_media_t media) { + TULIP_LOCK_ASSERT(sc); sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_THRSHLD160 |TULIP_CMD_BACKOFFCTR; sc->tulip_ifp->if_baudrate = 10000000; @@ -882,6 +895,7 @@ static void tulip_21040_media_probe( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); tulip_21040_mediainfo_init(sc, TULIP_MEDIA_UNKNOWN); return; } @@ -890,6 +904,7 @@ static void tulip_21040_10baset_only_media_probe( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); tulip_21040_mediainfo_init(sc, TULIP_MEDIA_10BASET); tulip_media_set(sc, TULIP_MEDIA_10BASET); sc->tulip_media = TULIP_MEDIA_10BASET; @@ -899,6 +914,7 @@ static void tulip_21040_10baset_only_media_select( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); sc->tulip_flags |= TULIP_LINKUP; if (sc->tulip_media == TULIP_MEDIA_10BASET_FD) { sc->tulip_cmdmode |= TULIP_CMD_FULLDUPLEX; @@ -914,6 +930,7 @@ static void tulip_21040_auibnc_only_media_probe( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); tulip_21040_mediainfo_init(sc, TULIP_MEDIA_AUIBNC); sc->tulip_flags |= TULIP_SQETEST|TULIP_LINKUP; tulip_media_set(sc, TULIP_MEDIA_AUIBNC); @@ -924,6 +941,7 @@ static void tulip_21040_auibnc_only_media_select( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); tulip_media_set(sc, TULIP_MEDIA_AUIBNC); sc->tulip_cmdmode &= ~TULIP_CMD_FULLDUPLEX; } @@ -955,6 +973,7 @@ tulip_21041_mediainfo_init( { tulip_media_info_t * const mi = sc->tulip_mediainfo; + TULIP_LOCK_ASSERT(sc); #ifdef notyet if (sc->tulip_revinfo >= 0x20) { TULIP_MEDIAINFO_SIA_INIT(sc, &mi[0], 21041P2, 10BASET); @@ -974,6 +993,7 @@ static void tulip_21041_media_probe( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); sc->tulip_ifp->if_baudrate = 10000000; sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT |TULIP_CMD_THRSHLD160|TULIP_CMD_BACKOFFCTR; @@ -988,6 +1008,7 @@ tulip_21041_media_poll( { u_int32_t sia_status; + TULIP_LOCK_ASSERT(sc); #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_events[event]++; #endif @@ -1209,6 +1230,8 @@ tulip_mii_phy_readspecific( TULIP_MEDIA_UNKNOWN }; + TULIP_LOCK_ASSERT(sc); + /* * Don't read phy specific registers if link is not up. */ @@ -1258,6 +1281,7 @@ tulip_mii_get_phyaddr( { unsigned phyaddr; + TULIP_LOCK_ASSERT(sc); for (phyaddr = 1; phyaddr < 32; phyaddr++) { unsigned status = tulip_mii_readreg(sc, phyaddr, PHYREG_STATUS); if (status == 0 || status == 0xFFFF || status < PHYSTS_10BASET) @@ -1280,6 +1304,7 @@ tulip_mii_map_abilities( tulip_softc_t * const sc, unsigned abilities) { + TULIP_LOCK_ASSERT(sc); sc->tulip_abilities = abilities; if (abilities & PHYSTS_100BASETX_FD) { sc->tulip_probe_media = TULIP_MEDIA_100BASETX_FD; @@ -1306,6 +1331,7 @@ tulip_mii_autonegotiate( { struct ifnet *ifp = sc->tulip_ifp; + TULIP_LOCK_ASSERT(sc); switch (sc->tulip_probe_state) { case TULIP_PROBE_MEDIATEST: case TULIP_PROBE_INACTIVE: { @@ -1406,6 +1432,7 @@ tulip_2114x_media_preset( const tulip_media_info_t *mi = NULL; tulip_media_t media = sc->tulip_media; + TULIP_LOCK_ASSERT(sc); if (sc->tulip_probe_state == TULIP_PROBE_INACTIVE) media = sc->tulip_media; else @@ -1496,6 +1523,7 @@ tulip_21140_mediainit( unsigned gpdata, unsigned cmdmode) { + TULIP_LOCK_ASSERT(sc); sc->tulip_mediums[media] = mip; mip->mi_type = TULIP_MEDIAINFO_GPR; mip->mi_cmdmode = cmdmode; @@ -1508,6 +1536,7 @@ tulip_21140_evalboard_media_probe( { tulip_media_info_t *mip = sc->tulip_mediainfo; + TULIP_LOCK_ASSERT(sc); sc->tulip_gpinit = TULIP_GP_EB_PINS; sc->tulip_gpdata = TULIP_GP_EB_INIT; TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS); @@ -1554,6 +1583,7 @@ tulip_21140_accton_media_probe( tulip_media_info_t *mip = sc->tulip_mediainfo; unsigned gpdata; + TULIP_LOCK_ASSERT(sc); sc->tulip_gpinit = TULIP_GP_EB_PINS; sc->tulip_gpdata = TULIP_GP_EB_INIT; TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EB_PINS); @@ -1608,6 +1638,7 @@ tulip_21140_smc9332_media_probe( tulip_media_info_t *mip = sc->tulip_mediainfo; int idx, cnt = 0; + TULIP_LOCK_ASSERT(sc); TULIP_CSR_WRITE(sc, csr_command, TULIP_CMD_PORTSELECT|TULIP_CMD_MUSTBEONE); TULIP_CSR_WRITE(sc, csr_busmode, TULIP_BUSMODE_SWRESET); DELAY(10); /* Wait 10 microseconds (actually 50 PCI cycles but at @@ -1664,6 +1695,7 @@ tulip_21140_cogent_em100_media_probe( tulip_media_info_t *mip = sc->tulip_mediainfo; u_int32_t cmdmode = TULIP_CSR_READ(sc, csr_command); + TULIP_LOCK_ASSERT(sc); sc->tulip_gpinit = TULIP_GP_EM100_PINS; sc->tulip_gpdata = TULIP_GP_EM100_INIT; TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_EM100_PINS); @@ -1711,6 +1743,7 @@ tulip_21140_znyx_zx34x_media_probe( tulip_media_info_t *mip = sc->tulip_mediainfo; int cnt10 = 0, cnt100 = 0, idx; + TULIP_LOCK_ASSERT(sc); sc->tulip_gpinit = TULIP_GP_ZX34X_PINS; sc->tulip_gpdata = TULIP_GP_ZX34X_INIT; TULIP_CSR_WRITE(sc, csr_gp, TULIP_GP_ZX34X_PINS); @@ -1765,6 +1798,7 @@ static void tulip_2114x_media_probe( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); sc->tulip_cmdmode |= TULIP_CMD_MUSTBEONE |TULIP_CMD_BACKOFFCTR|TULIP_CMD_THRSHLD72; } @@ -1869,6 +1903,7 @@ tulip_mii_writebits( unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK); unsigned lastbit = (csr & MII_DOUT) ? msb : 0; + TULIP_LOCK_ASSERT(sc); csr |= MII_WR; MII_EMIT; /* clock low; assert write */ for (; bits > 0; bits--, data <<= 1) { @@ -1889,6 +1924,7 @@ tulip_mii_turnaround( { unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK); + TULIP_LOCK_ASSERT(sc); if (cmd == MII_WRCMD) { csr |= MII_DOUT; MII_EMIT; /* clock low; change data */ csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */ @@ -1909,6 +1945,7 @@ tulip_mii_readbits( unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK); int idx; + TULIP_LOCK_ASSERT(sc); for (idx = 0, data = 0; idx < 16; idx++) { data <<= 1; /* this is NOOP on the first pass through */ csr ^= MII_CLKON; MII_EMIT; /* clock high; data valid */ @@ -1930,6 +1967,7 @@ tulip_mii_readreg( unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK); unsigned data; + TULIP_LOCK_ASSERT(sc); csr &= ~(MII_RD|MII_CLK); MII_EMIT; tulip_mii_writebits(sc, MII_PREAMBLE, 32); tulip_mii_writebits(sc, MII_RDCMD, 8); @@ -1953,6 +1991,8 @@ tulip_mii_writereg( unsigned data) { unsigned csr = TULIP_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK); + + TULIP_LOCK_ASSERT(sc); csr &= ~(MII_RD|MII_CLK); MII_EMIT; tulip_mii_writebits(sc, MII_PREAMBLE, 32); tulip_mii_writebits(sc, MII_WRCMD, 8); @@ -1975,6 +2015,7 @@ static void tulip_identify_dec_nic( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "DEC "); #define D0 4 if (sc->tulip_chipid <= TULIP_21040) @@ -1992,6 +2033,8 @@ tulip_identify_znyx_nic( tulip_softc_t * const sc) { unsigned id = 0; + + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "ZNYX ZX3XX "); if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) { unsigned znyx_ptr; @@ -2088,6 +2131,7 @@ tulip_identify_smc_nic( int auibnc = 0, utp = 0; char *cp; + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "SMC "); if (sc->tulip_chipid == TULIP_21041) return; @@ -2133,6 +2177,7 @@ static void tulip_identify_cogent_nic( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "Cogent "); if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) { if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100TX_ID) { @@ -2169,6 +2214,7 @@ static void tulip_identify_accton_nic( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "ACCTON "); switch (sc->tulip_chipid) { case TULIP_21140A: @@ -2199,6 +2245,7 @@ static void tulip_identify_asante_nic( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "Asante "); if ((sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) && sc->tulip_boardsw != &tulip_2114x_isv_boardsw) { @@ -2255,6 +2302,7 @@ static void tulip_identify_compex_nic( tulip_softc_t * const sc) { + TULIP_LOCK_ASSERT(sc); strcpy(sc->tulip_boardid, "COMPEX "); if (sc->tulip_chipid == TULIP_21140A) { int root_unit; @@ -2303,6 +2351,7 @@ tulip_srom_decode( const u_int8_t *dp; u_int32_t leaf_offset, blocks, data; + TULIP_LOCK_ASSERT(sc); for (idx1 = 0; idx1 < shp->sh_adapter_count; idx1++, saip++) { if (shp->sh_adapter_count == 1) break; @@ -2882,6 +2931,7 @@ tulip_ifmedia_add( tulip_media_t media; int medias = 0; + TULIP_LOCK_ASSERT(sc); for (media = TULIP_MEDIA_UNKNOWN; media < TULIP_MEDIA_MAX; media++) { if (sc->tulip_mediums[media] != NULL) { ifmedia_add(&sc->tulip_ifmedia, tulip_media_to_ifmedia[media], @@ -2909,6 +2959,7 @@ tulip_ifmedia_change( { tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc; + TULIP_LOCK(sc); sc->tulip_flags |= TULIP_NEEDRESET; sc->tulip_probe_state = TULIP_PROBE_INACTIVE; sc->tulip_media = TULIP_MEDIA_UNKNOWN; @@ -2920,6 +2971,7 @@ tulip_ifmedia_change( sc->tulip_flags |= TULIP_PRINTMEDIA; sc->tulip_flags &= ~TULIP_DIDNWAY; tulip_linkup(sc, media); + TULIP_UNLOCK(sc); return 0; } } @@ -2927,6 +2979,7 @@ tulip_ifmedia_change( sc->tulip_flags &= ~(TULIP_TXPROBE_ACTIVE|TULIP_WANTRXACT); tulip_reset(sc); tulip_init(sc); + TULIP_UNLOCK(sc); return 0; } @@ -2940,14 +2993,18 @@ tulip_ifmedia_status( { tulip_softc_t *sc = (tulip_softc_t *)ifp->if_softc; - if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) + TULIP_LOCK(sc); + if (sc->tulip_media == TULIP_MEDIA_UNKNOWN) { + TULIP_UNLOCK(sc); return; + } req->ifm_status = IFM_AVALID; if (sc->tulip_flags & TULIP_LINKUP) req->ifm_status |= IFM_ACTIVE; req->ifm_active = tulip_media_to_ifmedia[sc->tulip_media]; + TULIP_UNLOCK(sc); } static void @@ -2958,6 +3015,7 @@ tulip_addr_filter( u_char *addrp; int multicnt; + TULIP_LOCK_ASSERT(sc); sc->tulip_flags &= ~(TULIP_WANTHASHPERFECT|TULIP_WANTHASHONLY|TULIP_ALLMULTI); sc->tulip_flags |= TULIP_WANTSETUP|TULIP_WANTTXSTART; sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; @@ -3103,6 +3161,8 @@ tulip_reset( tulip_desc_t *di; u_int32_t inreset = (sc->tulip_flags & TULIP_INRESET); + TULIP_LOCK_ASSERT(sc); + /* * Brilliant. Simply brilliant. When switching modes/speeds * on a 2114*, you need to set the appriopriate MII/PCS/SCL/PS @@ -3242,9 +3302,13 @@ tulip_reset( static void tulip_ifinit( - void * sc) + void *arg) { - tulip_init((tulip_softc_t *)sc); + tulip_softc_t *sc = (tulip_softc_t *)arg; + + TULIP_LOCK(sc); + tulip_init(sc); + TULIP_UNLOCK(sc); } static void @@ -3302,6 +3366,7 @@ tulip_rx_intr( int cnt = 0; #endif + TULIP_LOCK_ASSERT(sc); for (;;) { TULIP_PERFSTART(rxget) tulip_desc_t *eop = ri->ri_nextin; @@ -3499,6 +3564,7 @@ tulip_rx_intr( && m0 != NULL #endif ) { + TULIP_UNLOCK(sc); #if !defined(TULIP_COPY_RXDATA) ms->m_pkthdr.len = total_len; ms->m_pkthdr.rcvif = ifp; @@ -3511,6 +3577,7 @@ tulip_rx_intr( (*ifp->if_input)(ifp, m0); m0 = ms; #endif /* ! TULIP_COPY_RXDATA */ + TULIP_LOCK(sc); } ms = m0; } @@ -3597,6 +3664,7 @@ tulip_tx_intr( int xmits = 0; int descs = 0; + TULIP_LOCK_ASSERT(sc); while (ri->ri_free < ri->ri_max) { u_int32_t d_flag; @@ -3729,6 +3797,7 @@ tulip_print_abnormal_interrupt( u_int32_t mask; const char thrsh[] = "72|128\0\0\0" "96|256\0\0\0" "128|512\0\0" "160|1024"; + TULIP_LOCK_ASSERT(sc); csr &= (1 << (sizeof(tulip_status_bits)/sizeof(tulip_status_bits[0]))) - 1; if_printf(sc->tulip_ifp, "abnormal interrupt:"); for (sep = " ", mask = 1; mask <= csr; mask <<= 1, msgp++) { @@ -3756,6 +3825,7 @@ tulip_intr_handler( TULIP_PERFSTART(intr) u_int32_t csr; + TULIP_LOCK_ASSERT(sc); while ((csr = TULIP_CSR_READ(sc, csr_status)) & sc->tulip_intrmask) { TULIP_CSR_WRITE(sc, csr_status, csr); @@ -3852,10 +3922,12 @@ tulip_intr_shared( tulip_softc_t * sc = arg; for (; sc != NULL; sc = sc->tulip_slaves) { + TULIP_LOCK(sc); #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_intrs++; #endif tulip_intr_handler(sc); + TULIP_UNLOCK(sc); } } @@ -3865,10 +3937,12 @@ tulip_intr_normal( { tulip_softc_t * sc = (tulip_softc_t *) arg; + TULIP_LOCK(sc); #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_intrs++; #endif tulip_intr_handler(sc); + TULIP_UNLOCK(sc); } static struct mbuf * @@ -3946,6 +4020,7 @@ tulip_txput( struct mbuf *m0; #endif + TULIP_LOCK_ASSERT(sc); #if defined(TULIP_DEBUG) if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) { if_printf(sc->tulip_ifp, "txput%s: tx not running\n", @@ -4254,7 +4329,9 @@ tulip_txput_setup( { tulip_ringinfo_t * const ri = &sc->tulip_txinfo; tulip_desc_t *nextout; - + + TULIP_LOCK_ASSERT(sc); + /* * We will transmit, at most, one setup packet per call to ifstart. */ @@ -4343,14 +4420,14 @@ tulip_ifioctl( TULIP_PERFSTART(ifioctl) tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; - int s; int error = 0; - s = splimp(); switch (cmd) { case SIOCSIFFLAGS: { + TULIP_LOCK(sc); tulip_addr_filter(sc); /* reinit multicast filter */ tulip_init(sc); + TULIP_UNLOCK(sc); break; } @@ -4365,8 +4442,10 @@ tulip_ifioctl( /* * Update multicast listeners */ + TULIP_LOCK(sc); tulip_addr_filter(sc); /* reset multicast filtering */ tulip_init(sc); + TULIP_UNLOCK(sc); error = 0; break; } @@ -4375,11 +4454,13 @@ tulip_ifioctl( /* * Set the interface MTU. */ + TULIP_LOCK(sc); if (ifr->ifr_mtu > ETHERMTU) { error = EINVAL; break; } ifp->if_mtu = ifr->ifr_mtu; + TULIP_UNLOCK(sc); break; #ifdef SIOCGADDRROM @@ -4400,7 +4481,6 @@ tulip_ifioctl( } } - splx(s); TULIP_PERFEND(ifioctl); return error; } @@ -4412,24 +4492,34 @@ tulip_ifstart( TULIP_PERFSTART(ifstart) tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc; - if (sc->tulip_ifp->if_flags & IFF_RUNNING) { + if (ifp->if_flags & IFF_RUNNING) { + TULIP_LOCK(sc); + tulip_start(sc); + TULIP_UNLOCK(sc); + } - if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) - tulip_txput_setup(sc); + TULIP_PERFEND(ifstart); +} - while (!IFQ_DRV_IS_EMPTY(&sc->tulip_ifp->if_snd)) { - struct mbuf *m; - IFQ_DRV_DEQUEUE(&sc->tulip_ifp->if_snd, m); - if(m == NULL) - break; - if ((m = tulip_txput(sc, m)) != NULL) { - IFQ_DRV_PREPEND(&sc->tulip_ifp->if_snd, m); - break; - } +static void +tulip_start(tulip_softc_t * const sc) +{ + struct mbuf *m; + + TULIP_LOCK_ASSERT(sc); + + if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) + tulip_txput_setup(sc); + + while (!IFQ_DRV_IS_EMPTY(&sc->tulip_ifp->if_snd)) { + IFQ_DRV_DEQUEUE(&sc->tulip_ifp->if_snd, m); + if(m == NULL) + break; + if ((m = tulip_txput(sc, m)) != NULL) { + IFQ_DRV_PREPEND(&sc->tulip_ifp->if_snd, m); + break; } } - - TULIP_PERFEND(ifstart); } /* @@ -4445,9 +4535,13 @@ tulip_ifwatchdog( { TULIP_PERFSTART(ifwatchdog) tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc; +#if defined(TULIP_DEBUG) + u_int32_t rxintrs; +#endif + TULIP_LOCK(sc); #if defined(TULIP_DEBUG) - u_int32_t rxintrs = sc->tulip_dbg.dbg_rxintrs - sc->tulip_dbg.dbg_last_rxintrs; + rxintrs = sc->tulip_dbg.dbg_rxintrs - sc->tulip_dbg.dbg_last_rxintrs; if (rxintrs > sc->tulip_dbg.dbg_high_rxintrs_hz) sc->tulip_dbg.dbg_high_rxintrs_hz = rxintrs; sc->tulip_dbg.dbg_last_rxintrs = sc->tulip_dbg.dbg_rxintrs; @@ -4512,6 +4606,7 @@ tulip_ifwatchdog( TULIP_PERFMERGE(sc, perf_txintr); TULIP_PERFMERGE(sc, perf_rxintr); TULIP_PERFMERGE(sc, perf_rxget); + TULIP_UNLOCK(sc); } /* @@ -4532,12 +4627,15 @@ tulip_attach( /* XXX: driver name/unit should be set some other way */ if_initname(ifp, "de", sc->tulip_unit); ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_NEEDSGIANT; + ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST; ifp->if_ioctl = tulip_ifioctl; ifp->if_start = tulip_ifstart; ifp->if_watchdog = tulip_ifwatchdog; ifp->if_timer = 1; ifp->if_init = tulip_ifinit; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; + IFQ_SET_READY(&ifp->if_snd); if_printf(ifp, "%s%s pass %d.%d%s\n", sc->tulip_boardid, @@ -4547,6 +4645,7 @@ tulip_attach( (sc->tulip_features & (TULIP_HAVE_ISVSROM|TULIP_HAVE_OKSROM)) == TULIP_HAVE_ISVSROM ? " (invalid EESPROM checksum)" : ""); + TULIP_LOCK(sc); #if defined(__alpha__) /* * In case the SRM console told us about a bogus media, @@ -4564,11 +4663,9 @@ tulip_attach( tulip_ifmedia_add(sc); tulip_reset(sc); + TULIP_UNLOCK(sc); ether_ifattach(sc->tulip_ifp, sc->tulip_enaddr); - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); } #if defined(TULIP_BUS_DMA) @@ -4916,6 +5013,9 @@ tulip_pci_attach(device_t dev) sc->tulip_csrs_bsh = rman_get_bushandle(res); csr_base = 0; + mtx_init(TULIP_MUTEX(sc), MTX_NETWORK_LOCK, device_get_nameunit(dev), + MTX_DEF); + callout_init(&sc->tulip_callout, CALLOUT_MPSAFE); tulips[unit] = sc; tulip_initcsrs(sc, csr_base + csroffset, csrsize); @@ -4923,6 +5023,7 @@ tulip_pci_attach(device_t dev) #if defined(TULIP_BUS_DMA) if ((retval = tulip_busdma_init(sc)) != 0) { printf("error initing bus_dma: %d\n", retval); + mtx_destroy(TULIP_MUTEX(sc)); return ENXIO; } #else @@ -4934,6 +5035,7 @@ tulip_pci_attach(device_t dev) free((caddr_t) sc->tulip_rxdescs, M_DEVBUF); if (sc->tulip_txdescs) free((caddr_t) sc->tulip_txdescs, M_DEVBUF); + mtx_destroy(TULIP_MUTEX(sc)); return ENXIO; } #endif @@ -4949,7 +5051,10 @@ tulip_pci_attach(device_t dev) 33MHz that comes to two microseconds but wait a bit longer anyways) */ - if ((retval = tulip_read_macaddr(sc)) < 0) { + TULIP_LOCK(sc); + retval = tulip_read_macaddr(sc); + TULIP_UNLOCK(sc); + if (retval < 0) { device_printf(dev, "can't read ENET ROM (why=%d) (", retval); for (idx = 0; idx < 32; idx++) printf("%02x", sc->tulip_rombuf[idx]); @@ -4959,37 +5064,41 @@ tulip_pci_attach(device_t dev) (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F); device_printf(dev, "address unknown\n"); } else { - int s; void (*intr_rtn)(void *) = tulip_intr_normal; if (sc->tulip_features & TULIP_HAVE_SHAREDINTR) intr_rtn = tulip_intr_shared; +#if defined(__alpha__) + sc->tulip_media = media; +#endif + tulip_attach(sc); + + /* Setup interrupt last. */ if ((sc->tulip_features & TULIP_HAVE_SLAVEDINTR) == 0) { void *ih; rid = 0; res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); - if (res == 0 || bus_setup_intr(dev, res, INTR_TYPE_NET, - intr_rtn, sc, &ih)) { + if (res == 0 || bus_setup_intr(dev, res, INTR_TYPE_NET | + INTR_MPSAFE, intr_rtn, sc, &ih)) { device_printf(dev, "couldn't map interrupt\n"); free((caddr_t) sc->tulip_rxdescs, M_DEVBUF); free((caddr_t) sc->tulip_txdescs, M_DEVBUF); + ether_ifdetach(sc->tulip_ifp); + if_free(sc->tulip_ifp); + mtx_destroy(TULIP_MUTEX(sc)); return ENXIO; } } - s = splimp(); -#if defined(__alpha__) - sc->tulip_media = media; -#endif - tulip_attach(sc); -#if defined(__alpha__) +#if defined(__alpha__) + TULIP_LOCK(sc); if (sc->tulip_media != TULIP_MEDIA_UNKNOWN) tulip_linkup(sc, media); + TULIP_UNLOCK(sc); #endif - splx(s); } return 0; } diff --git a/sys/dev/de/if_devar.h b/sys/dev/de/if_devar.h index 2d429de..46ff1ea 100644 --- a/sys/dev/de/if_devar.h +++ b/sys/dev/de/if_devar.h @@ -582,6 +582,8 @@ struct tulip_softc { tulip_srom_connection_t tulip_conntype; tulip_desc_t *tulip_rxdescs; tulip_desc_t *tulip_txdescs; + struct callout tulip_callout; + struct mtx tulip_mutex; }; #define tulip_curperfstats tulip_perfstats[TULIP_PERF_CURRENT] @@ -975,4 +977,9 @@ TULIP_PERFREAD(void) && ((u_int16_t *)a1)[1] == 0xFFFFU \ && ((u_int16_t *)a1)[2] == 0xFFFFU) +#define TULIP_MUTEX(sc) (&(sc)->tulip_mutex) +#define TULIP_LOCK(sc) mtx_lock(TULIP_MUTEX(sc)) +#define TULIP_UNLOCK(sc) mtx_unlock(TULIP_MUTEX(sc)) +#define TULIP_LOCK_ASSERT(sc) mtx_assert(TULIP_MUTEX(sc), MA_OWNED) + #endif /* _DEVAR_H */ -- cgit v1.1