- 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
This commit is contained in:
jhb 2005-07-27 13:51:01 +00:00
parent 53b633e139
commit d675d9c68f
4 changed files with 316 additions and 84 deletions

View File

@ -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,25 +4492,35 @@ 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 ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
tulip_txput_setup(sc);
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;
}
}
if (ifp->if_flags & IFF_RUNNING) {
TULIP_LOCK(sc);
tulip_start(sc);
TULIP_UNLOCK(sc);
}
TULIP_PERFEND(ifstart);
}
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;
}
}
}
/*
* Even though this routine runs at device spl, it does not break
@ -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 = sc->tulip_dbg.dbg_rxintrs - sc->tulip_dbg.dbg_last_rxintrs;
u_int32_t rxintrs;
#endif
TULIP_LOCK(sc);
#if defined(TULIP_DEBUG)
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;
}

View File

@ -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 */

View File

@ -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,25 +4492,35 @@ 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 ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP)
tulip_txput_setup(sc);
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;
}
}
if (ifp->if_flags & IFF_RUNNING) {
TULIP_LOCK(sc);
tulip_start(sc);
TULIP_UNLOCK(sc);
}
TULIP_PERFEND(ifstart);
}
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;
}
}
}
/*
* Even though this routine runs at device spl, it does not break
@ -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 = sc->tulip_dbg.dbg_rxintrs - sc->tulip_dbg.dbg_last_rxintrs;
u_int32_t rxintrs;
#endif
TULIP_LOCK(sc);
#if defined(TULIP_DEBUG)
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;
}

View File

@ -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 */