aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/de
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2005-07-27 13:51:01 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2005-07-27 13:51:01 +0000
commitd0e98e85f8a08582b68fc494e75dff451a10c038 (patch)
tree64adba91a8e6fd65c24aaabdec7ea2fe0fad3dc1 /sys/dev/de
parent8bc92074e836b81e600253a826c304e6a45f66ef (diff)
downloadsrc-d0e98e85f8a08582b68fc494e75dff451a10c038.tar.gz
src-d0e98e85f8a08582b68fc494e75dff451a10c038.zip
- 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
Notes
Notes: svn path=/head/; revision=148445
Diffstat (limited to 'sys/dev/de')
-rw-r--r--sys/dev/de/if_de.c189
-rw-r--r--sys/dev/de/if_devar.h7
2 files changed, 156 insertions, 40 deletions
diff --git a/sys/dev/de/if_de.c b/sys/dev/de/if_de.c
index d11601550d5d..5fdff821db2d 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 2d429de13081..46ff1ea81f52 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 */