diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/vx/if_vx.c | 425 | ||||
-rw-r--r-- | sys/dev/vx/if_vx_eisa.c | 19 | ||||
-rw-r--r-- | sys/dev/vx/if_vx_pci.c | 29 | ||||
-rw-r--r-- | sys/dev/vx/if_vxvar.h | 47 |
4 files changed, 287 insertions, 233 deletions
diff --git a/sys/dev/vx/if_vx.c b/sys/dev/vx/if_vx.c index 142f174..abc8091 100644 --- a/sys/dev/vx/if_vx.c +++ b/sys/dev/vx/if_vx.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/sockio.h> +#include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/socket.h> @@ -121,42 +122,46 @@ static struct connector_entry { } }; -/* int vxattach(struct vx_softc *); */ -static void vxtxstat(struct vx_softc *); -static int vxstatus(struct vx_softc *); -static void vxinit(void *); -static int vxioctl(struct ifnet *, u_long, caddr_t); -static void vxstart(struct ifnet *); -static void vxwatchdog(struct ifnet *); -static void vxreset(struct vx_softc *); -static void vxread(struct vx_softc *); -static struct mbuf *vxget(struct vx_softc *, u_int); -static void vxmbuffill(void *); -static void vxmbufempty(struct vx_softc *); -static void vxsetfilter(struct vx_softc *); -static void vxgetlink(struct vx_softc *); -static void vxsetlink(struct vx_softc *); +static void vx_txstat(struct vx_softc *); +static int vx_status(struct vx_softc *); +static void vx_init(void *); +static void vx_init_locked(struct vx_softc *); +static int vx_ioctl(struct ifnet *, u_long, caddr_t); +static void vx_start(struct ifnet *); +static void vx_start_locked(struct ifnet *); +static void vx_watchdog(struct ifnet *); +static void vx_reset(struct vx_softc *); +static void vx_read(struct vx_softc *); +static struct mbuf *vx_get(struct vx_softc *, u_int); +static void vx_mbuf_fill(void *); +static void vx_mbuf_empty(struct vx_softc *); +static void vx_setfilter(struct vx_softc *); +static void vx_getlink(struct vx_softc *); +static void vx_setlink(struct vx_softc *); int -vxattach(device_t dev) +vx_attach(device_t dev) { struct vx_softc *sc = device_get_softc(dev); struct ifnet *ifp; int i; u_char eaddr[6]; - ifp = sc->ifp = if_alloc(IFT_ETHER); + ifp = sc->vx_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "can not if_alloc()\n"); return 0; } + if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - callout_handle_init(&sc->ch); + mtx_init(&sc->vx_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, + MTX_DEF); + callout_init_mtx(&sc->vx_callout, &sc->vx_mtx, 0); GO_WINDOW(0); CSR_WRITE_2(sc, VX_COMMAND, GLOBAL_RESET); VX_BUSY_WAIT; - vxgetlink(sc); + vx_getlink(sc); /* * Read the station address from the eeprom @@ -165,33 +170,37 @@ vxattach(device_t dev) for (i = 0; i < 3; i++) { int x; - if (vxbusyeeprom(sc)) + if (vx_busy_eeprom(sc)) { + mtx_destroy(&sc->vx_mtx); + if_free(ifp); return 0; + } CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD | (EEPROM_OEM_ADDR0 + i)); - if (vxbusyeeprom(sc)) + if (vx_busy_eeprom(sc)) { + mtx_destroy(&sc->vx_mtx); + if_free(ifp); return 0; + } x = CSR_READ_2(sc, VX_W0_EEPROM_DATA); eaddr[(i << 1)] = x >> 8; eaddr[(i << 1) + 1] = x; } - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_mtu = ETHERMTU; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSGIANT; - ifp->if_start = vxstart; - ifp->if_ioctl = vxioctl; - ifp->if_init = vxinit; - ifp->if_watchdog = vxwatchdog; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_start = vx_start; + ifp->if_ioctl = vx_ioctl; + ifp->if_init = vx_init; + ifp->if_watchdog = vx_watchdog; ifp->if_softc = sc; ether_ifattach(ifp, eaddr); - sc->tx_start_thresh = 20; /* probably a good starting point. */ + sc->vx_tx_start_thresh = 20; /* probably a good starting point. */ - vxstop(sc); + vx_stop(sc); return 1; } @@ -201,18 +210,29 @@ vxattach(device_t dev) * interrupts. ?! */ static void -vxinit(void *xsc) +vx_init(void *xsc) { struct vx_softc *sc = (struct vx_softc *)xsc; - struct ifnet *ifp = sc->ifp; + + VX_LOCK(sc); + vx_init_locked(sc); + VX_UNLOCK(sc); +} + +static void +vx_init_locked(struct vx_softc *sc) +{ + struct ifnet *ifp = sc->vx_ifp; int i; + VX_LOCK_ASSERT(sc); + VX_BUSY_WAIT; GO_WINDOW(2); for (i = 0; i < 6; i++) /* Reload the ether_addr. */ - CSR_WRITE_1(sc, VX_W2_ADDR_0 + i, IFP2ENADDR(sc->ifp)[i]); + CSR_WRITE_1(sc, VX_W2_ADDR_0 + i, IFP2ENADDR(sc->vx_ifp)[i]); CSR_WRITE_2(sc, VX_COMMAND, RX_RESET); VX_BUSY_WAIT; @@ -236,27 +256,28 @@ vxinit(void *xsc) */ CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | 0xff); - vxsetfilter(sc); - vxsetlink(sc); + vx_setfilter(sc); + vx_setlink(sc); CSR_WRITE_2(sc, VX_COMMAND, RX_ENABLE); CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE); - vxmbuffill((caddr_t) sc); + vx_mbuf_fill(sc); /* Interface is now `running', with no output active. */ ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* Attempt to start output, if any. */ - vxstart(ifp); + vx_start_locked(ifp); } static void -vxsetfilter(struct vx_softc *sc) +vx_setfilter(struct vx_softc *sc) { - register struct ifnet *ifp = sc->ifp; + struct ifnet *ifp = sc->vx_ifp; + VX_LOCK_ASSERT(sc); GO_WINDOW(1); /* Window 1 is operating window */ CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST | FIL_MULTICAST | @@ -264,7 +285,7 @@ vxsetfilter(struct vx_softc *sc) } static void -vxgetlink(struct vx_softc *sc) +vx_getlink(struct vx_softc *sc) { int n, k; @@ -296,14 +317,15 @@ vxgetlink(struct vx_softc *sc) } static void -vxsetlink(struct vx_softc *sc) +vx_setlink(struct vx_softc *sc) { - register struct ifnet *ifp = sc->ifp; + struct ifnet *ifp = sc->vx_ifp; int i, j, k; char *reason, *warning; static int prev_flags; static signed char prev_conn = -1; + VX_LOCK_ASSERT(sc); if (prev_conn == -1) prev_conn = sc->vx_connector; @@ -356,11 +378,9 @@ vxsetlink(struct vx_softc *sc) /* Avoid unnecessary message. */ k = (prev_flags ^ ifp->if_flags) & (IFF_LINK0 | IFF_LINK1 | IFF_LINK2); if ((k != 0) || (prev_conn != i)) { - if (warning != 0) { - printf("vx%d: warning: %s\n", sc->unit, warning); - } - printf("vx%d: selected %s. (%s)\n", - sc->unit, conn_tab[i].name, reason); + if (warning != NULL) + if_printf(ifp, "warning: %s\n", warning); + if_printf(ifp, "selected %s. (%s)\n", conn_tab[i].name, reason); } /* Set the selected connector. */ GO_WINDOW(3); @@ -398,14 +418,26 @@ vxsetlink(struct vx_softc *sc) } static void -vxstart(struct ifnet *ifp) +vx_start(struct ifnet *ifp) +{ + struct vx_softc *sc = ifp->if_softc; + + VX_LOCK(sc); + vx_start_locked(ifp); + VX_UNLOCK(sc); +} + +static void +vx_start_locked(struct ifnet *ifp) { - register struct vx_softc *sc = ifp->if_softc; - register struct mbuf *m; - int sh, len, pad; + struct vx_softc *sc = ifp->if_softc; + struct mbuf *m; + int len, pad; + + VX_LOCK_ASSERT(sc); /* Don't transmit if interface is busy or not running */ - if ((sc->ifp->if_drv_flags & + if ((sc->vx_ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) return; @@ -451,25 +483,26 @@ startagain: VX_BUSY_WAIT; CSR_WRITE_2(sc, VX_COMMAND, SET_TX_START_THRESH | - ((len / 4 + sc->tx_start_thresh) >> 2)); + ((len / 4 + sc->vx_tx_start_thresh) >> 2)); - BPF_MTAP(sc->ifp, m); + BPF_MTAP(sc->vx_ifp, m); /* * Do the output at splhigh() so that an interrupt from another device * won't cause a FIFO underrun. + * + * XXX: Can't enforce that anymore. */ - sh = splhigh(); CSR_WRITE_4(sc, VX_W1_TX_PIO_WR_1, len | TX_INDICATE); while (m) { if (m->m_len > 3) - bus_space_write_multi_4(sc->bst, sc->bsh, + bus_space_write_multi_4(sc->vx_bst, sc->vx_bsh, VX_W1_TX_PIO_WR_1, (u_int32_t *)mtod(m, caddr_t), m->m_len / 4); if (m->m_len & 3) - bus_space_write_multi_1(sc->bst, sc->bsh, + bus_space_write_multi_1(sc->vx_bst, sc->vx_bsh, VX_W1_TX_PIO_WR_1, mtod(m, caddr_t) + (m->m_len & ~3), m->m_len & 3); m = m_free(m); @@ -477,8 +510,6 @@ startagain: while (pad--) CSR_WRITE_1(sc, VX_W1_TX_PIO_WR_1, 0); /* Padding */ - splx(sh); - ++ifp->if_opackets; ifp->if_timer = 1; @@ -492,7 +523,7 @@ readcheck: * Is this supposed to happen? Is my motherboard * completely busted? */ - vxread(sc); + vx_read(sc); } else /* * Got an interrupt, return so that it gets @@ -501,10 +532,10 @@ readcheck: return; } else { /* Check if we are stuck and reset [see XXX comment] */ - if (vxstatus(sc)) { + if (vx_status(sc)) { if (ifp->if_flags & IFF_DEBUG) if_printf(ifp, "adapter reset\n"); - vxreset(sc); + vx_reset(sc); } } @@ -519,10 +550,13 @@ readcheck: * on the cable (once in a blue moon). */ static int -vxstatus(struct vx_softc *sc) +vx_status(struct vx_softc *sc) { + struct ifnet *ifp; int fifost; + VX_LOCK_ASSERT(sc); + /* * Check the FIFO status and act accordingly */ @@ -530,74 +564,81 @@ vxstatus(struct vx_softc *sc) fifost = CSR_READ_2(sc, VX_W4_FIFO_DIAG); GO_WINDOW(1); + ifp = sc->vx_ifp; if (fifost & FIFOS_RX_UNDERRUN) { - if (sc->ifp->if_flags & IFF_DEBUG) - printf("vx%d: RX underrun\n", sc->unit); - vxreset(sc); + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "RX underrun\n"); + vx_reset(sc); return 0; } if (fifost & FIFOS_RX_STATUS_OVERRUN) { - if (sc->ifp->if_flags & IFF_DEBUG) - printf("vx%d: RX Status overrun\n", sc->unit); + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "RX Status overrun\n"); return 1; } if (fifost & FIFOS_RX_OVERRUN) { - if (sc->ifp->if_flags & IFF_DEBUG) - printf("vx%d: RX overrun\n", sc->unit); + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "RX overrun\n"); return 1; } if (fifost & FIFOS_TX_OVERRUN) { - if (sc->ifp->if_flags & IFF_DEBUG) - printf("vx%d: TX overrun\n", sc->unit); - vxreset(sc); + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "TX overrun\n"); + vx_reset(sc); return 0; } return 0; } static void -vxtxstat(struct vx_softc *sc) +vx_txstat(struct vx_softc *sc) { + struct ifnet *ifp; int i; + VX_LOCK_ASSERT(sc); + /* * We need to read+write TX_STATUS until we get a 0 status * in order to turn off the interrupt flag. */ + ifp = sc->vx_ifp; while ((i = CSR_READ_1(sc, VX_W1_TX_STATUS)) & TXS_COMPLETE) { CSR_WRITE_1(sc, VX_W1_TX_STATUS, 0x0); if (i & TXS_JABBER) { - ++sc->ifp->if_oerrors; - if (sc->ifp->if_flags & IFF_DEBUG) - printf("vx%d: jabber (%x)\n", sc->unit, i); - vxreset(sc); + ++ifp->if_oerrors; + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "jabber (%x)\n", i); + vx_reset(sc); } else if (i & TXS_UNDERRUN) { - ++sc->ifp->if_oerrors; - if (sc->ifp->if_flags & IFF_DEBUG) - printf("vx%d: fifo underrun (%x) @%d\n", - sc->unit, i, sc->tx_start_thresh); - if (sc->tx_succ_ok < 100) - sc->tx_start_thresh = - min(ETHER_MAX_LEN,sc->tx_start_thresh + 20); - sc->tx_succ_ok = 0; - vxreset(sc); + ++ifp->if_oerrors; + if (ifp->if_flags & IFF_DEBUG) + if_printf(ifp, "fifo underrun (%x) @%d\n", i, + sc->vx_tx_start_thresh); + if (sc->vx_tx_succ_ok < 100) + sc->vx_tx_start_thresh = + min(ETHER_MAX_LEN, + sc->vx_tx_start_thresh + 20); + sc->vx_tx_succ_ok = 0; + vx_reset(sc); } else if (i & TXS_MAX_COLLISION) { - ++sc->ifp->if_collisions; + ++ifp->if_collisions; CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE); - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } else - sc->tx_succ_ok = (sc->tx_succ_ok + 1) & 127; + sc->vx_tx_succ_ok = (sc->vx_tx_succ_ok + 1) & 127; } } void -vxintr(void *voidsc) +vx_intr(void *voidsc) { - register short status; + short status; struct vx_softc *sc = voidsc; - struct ifnet *ifp = sc->ifp; + struct ifnet *ifp = sc->vx_ifp; + VX_LOCK(sc); for (;;) { CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH); @@ -616,40 +657,40 @@ vxintr(void *voidsc) CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | status); if (status & S_RX_COMPLETE) - vxread(sc); + vx_read(sc); if (status & S_TX_AVAIL) { ifp->if_timer = 0; - sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - vxstart(sc->ifp); + sc->vx_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + vx_start_locked(sc->vx_ifp); } if (status & S_CARD_FAILURE) { - printf("vx%d: adapter failure (%x)\n", - sc->unit, status); + if_printf(ifp, "adapter failure (%x)\n", status); ifp->if_timer = 0; - vxreset(sc); - return; + vx_reset(sc); + break; } if (status & S_TX_COMPLETE) { ifp->if_timer = 0; - vxtxstat(sc); - vxstart(ifp); + vx_txstat(sc); + vx_start_locked(ifp); } } + VX_UNLOCK(sc); /* no more interrupts */ return; } static void -vxread(struct vx_softc *sc) +vx_read(struct vx_softc *sc) { - struct ifnet *ifp = sc->ifp; + struct ifnet *ifp = sc->vx_ifp; struct mbuf *m; struct ether_header *eh; u_int len; + VX_LOCK_ASSERT(sc); len = CSR_READ_2(sc, VX_W1_RX_STATUS); - again: if (ifp->if_flags & IFF_DEBUG) { @@ -672,7 +713,7 @@ again: s = "dribble bits"; if (s) - printf("vx%d: %s\n", sc->unit, s); + if_printf(ifp, "%s\n", s); } if (len & ERR_INCOMPLETE) return; @@ -684,7 +725,7 @@ again: len &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */ /* Pull packet off interface. */ - m = vxget(sc, len); + m = vx_get(sc, len); if (m == 0) { ifp->if_ierrors++; goto abort; @@ -694,7 +735,8 @@ again: { struct mbuf *m0; - m0 = m_devget(mtod(m, char *), m->m_pkthdr.len, ETHER_ALIGN, ifp, NULL); + m0 = m_devget(mtod(m, char *), m->m_pkthdr.len, ETHER_ALIGN, + ifp, NULL); if (m0 == NULL) { ifp->if_ierrors++; goto abort; @@ -714,11 +756,14 @@ again: if (!(ifp->if_flags & IFF_PROMISC) && (eh->ether_dhost[0] & 1) == 0 /* !mcast and !bcast */ - && bcmp(eh->ether_dhost, IFP2ENADDR(sc->ifp), ETHER_ADDR_LEN)!=0) { + && bcmp(eh->ether_dhost, IFP2ENADDR(sc->vx_ifp), + ETHER_ADDR_LEN) != 0) { m_freem(m); return; } - (*ifp->if_input) (ifp, m); + VX_UNLOCK(sc); + (*ifp->if_input)(ifp, m); + VX_LOCK(sc); /* * In periods of high traffic we can actually receive enough @@ -726,7 +771,7 @@ again: * even though we just read a packet. In this case we * are not going to receive any more interrupts. We check for * this condition and read again until the fifo is not full. - * We could simplify this test by not using vxstatus(), but + * We could simplify this test by not using vx_status(), but * rechecking the RX_STATUS register directly. This test could * result in unnecessary looping in cases where there is a new * packet but the fifo is not full, but it will not fix the @@ -734,15 +779,15 @@ again: * * Even with this improvement, we still get packet overrun errors * which are hurting performance. Maybe when I get some more time - * I'll modify vxread() so that it can handle RX_EARLY interrupts. + * I'll modify vx_read() so that it can handle RX_EARLY interrupts. */ - if (vxstatus(sc)) { + if (vx_status(sc)) { len = CSR_READ_2(sc, VX_W1_RX_STATUS); /* Check if we are stuck and reset [see XXX comment] */ if (len & ERR_INCOMPLETE) { if (ifp->if_flags & IFF_DEBUG) - printf("vx%d: adapter reset\n", sc->unit); - vxreset(sc); + if_printf(ifp, "adapter reset\n"); + vx_reset(sc); return; } goto again; @@ -754,27 +799,29 @@ abort: } static struct mbuf * -vxget(struct vx_softc *sc, u_int totlen) +vx_get(struct vx_softc *sc, u_int totlen) { - struct ifnet *ifp = sc->ifp; + struct ifnet *ifp = sc->vx_ifp; struct mbuf *top, **mp, *m; int len; - int sh; - m = sc->mb[sc->next_mb]; - sc->mb[sc->next_mb] = 0; - if (m == 0) { + VX_LOCK_ASSERT(sc); + m = sc->vx_mb[sc->vx_next_mb]; + sc->vx_mb[sc->vx_next_mb] = NULL; + if (m == NULL) { MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) - return 0; + if (m == NULL) + return NULL; } else { /* If the queue is no longer full, refill. */ - if (sc->last_mb == sc->next_mb && sc->buffill_pending == 0) { - sc->ch = timeout(vxmbuffill, sc, 1); - sc->buffill_pending = 1; + if (sc->vx_last_mb == sc->vx_next_mb && + sc->vx_buffill_pending == 0) { + callout_reset(&sc->vx_callout, hz / 100, vx_mbuf_fill, + sc); + sc->vx_buffill_pending = 1; } /* Convert one of our saved mbuf's. */ - sc->next_mb = (sc->next_mb + 1) % MAX_MBS; + sc->vx_next_mb = (sc->vx_next_mb + 1) % MAX_MBS; m->m_data = m->m_pktdat; m->m_flags = M_PKTHDR; bzero(&m->m_pkthdr, sizeof(m->m_pkthdr)); @@ -782,15 +829,16 @@ vxget(struct vx_softc *sc, u_int totlen) m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; len = MHLEN; - top = 0; + top = NULL; mp = ⊤ /* * We read the packet at splhigh() so that an interrupt from another * device doesn't cause the card's buffer to overflow while we're * reading it. We may still lose packets at other times. + * + * XXX: Can't enforce this anymore. */ - sh = splhigh(); /* * Since we don't set allowLargePackets bit in MacControl register, @@ -800,17 +848,16 @@ vxget(struct vx_softc *sc, u_int totlen) */ while (totlen > 0) { if (top) { - m = sc->mb[sc->next_mb]; - sc->mb[sc->next_mb] = 0; - if (m == 0) { + m = sc->vx_mb[sc->vx_next_mb]; + sc->vx_mb[sc->vx_next_mb] = NULL; + if (m == NULL) { MGET(m, M_DONTWAIT, MT_DATA); - if (m == 0) { - splx(sh); + if (m == NULL) { m_freem(top); - return 0; + return NULL; } } else { - sc->next_mb = (sc->next_mb + 1) % MAX_MBS; + sc->vx_next_mb = (sc->vx_next_mb + 1) % MAX_MBS; } len = MLEN; } @@ -821,10 +868,10 @@ vxget(struct vx_softc *sc, u_int totlen) } len = min(totlen, len); if (len > 3) - bus_space_read_multi_4(sc->bst, sc->bsh, + bus_space_read_multi_4(sc->vx_bst, sc->vx_bsh, VX_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), len / 4); if (len & 3) { - bus_space_read_multi_1(sc->bst, sc->bsh, + bus_space_read_multi_1(sc->vx_bst, sc->vx_bsh, VX_W1_RX_PIO_RD_1, mtod(m, u_int8_t *) + (len & ~3), len & 3); } @@ -836,30 +883,27 @@ vxget(struct vx_softc *sc, u_int totlen) CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK); - splx(sh); - return top; } static int -vxioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) +vx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct vx_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; - int s, error = 0; - - s = splimp(); + int error = 0; switch (cmd) { case SIOCSIFFLAGS: + VX_LOCK(sc); if ((ifp->if_flags & IFF_UP) == 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { /* * If interface is marked up and it is stopped, then * start it. */ - vxstop(sc); + vx_stop(sc); ifp->if_drv_flags &= ~IFF_DRV_RUNNING; } else if ((ifp->if_flags & IFF_UP) != 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { @@ -867,27 +911,30 @@ vxioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) * If interface is marked up and it is stopped, then * start it. */ - vxinit(sc); + vx_init_locked(sc); } else { /* * deal with flags changes: * IFF_MULTICAST, IFF_PROMISC, * IFF_LINK0, IFF_LINK1, */ - vxsetfilter(sc); - vxsetlink(sc); + vx_setfilter(sc); + vx_setlink(sc); } + VX_UNLOCK(sc); break; case SIOCSIFMTU: /* * Set the interface MTU. */ + VX_LOCK(sc); if (ifr->ifr_mtu > ETHERMTU) { error = EINVAL; } else { ifp->if_mtu = ifr->ifr_mtu; } + VX_UNLOCK(sc); break; case SIOCADDMULTI: @@ -896,7 +943,9 @@ vxioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) * Multicast list has changed; set the hardware filter * accordingly. */ - vxreset(sc); + VX_LOCK(sc); + vx_reset(sc); + VX_UNLOCK(sc); error = 0; break; @@ -906,40 +955,38 @@ vxioctl(register struct ifnet *ifp, u_long cmd, caddr_t data) break; } - splx(s); - return (error); } static void -vxreset(struct vx_softc *sc) +vx_reset(struct vx_softc *sc) { - int s; - - s = splimp(); - vxstop(sc); - vxinit(sc); - splx(s); + VX_LOCK_ASSERT(sc); + vx_stop(sc); + vx_init_locked(sc); } static void -vxwatchdog(struct ifnet *ifp) +vx_watchdog(struct ifnet *ifp) { struct vx_softc *sc = ifp->if_softc; + VX_LOCK(sc); if (ifp->if_flags & IFF_DEBUG) if_printf(ifp, "device timeout\n"); ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - vxstart(ifp); - vxintr(sc); + vx_start_locked(ifp); + vx_intr(sc); + VX_UNLOCK(sc); } void -vxstop(struct vx_softc *sc) +vx_stop(struct vx_softc *sc) { - struct ifnet *ifp = sc->ifp; + struct ifnet *ifp = sc->vx_ifp; + VX_LOCK_ASSERT(sc); ifp->if_timer = 0; CSR_WRITE_2(sc, VX_COMMAND, RX_DISABLE); @@ -957,11 +1004,11 @@ vxstop(struct vx_softc *sc) CSR_WRITE_2(sc, VX_COMMAND, SET_INTR_MASK); CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER); - vxmbufempty(sc); + vx_mbuf_empty(sc); } int -vxbusyeeprom(struct vx_softc *sc) +vx_busy_eeprom(struct vx_softc *sc) { int j, i = 100; @@ -973,52 +1020,50 @@ vxbusyeeprom(struct vx_softc *sc) break; } if (!i) { - printf("vx%d: eeprom failed to come ready\n", sc->unit); + if_printf(sc->vx_ifp, "eeprom failed to come ready\n"); return (1); } return (0); } static void -vxmbuffill(void *sp) +vx_mbuf_fill(void *sp) { struct vx_softc *sc = (struct vx_softc *)sp; - int s, i; + int i; - s = splimp(); - i = sc->last_mb; + VX_LOCK_ASSERT(sc); + i = sc->vx_last_mb; do { - if (sc->mb[i] == NULL) - MGET(sc->mb[i], M_DONTWAIT, MT_DATA); - if (sc->mb[i] == NULL) + if (sc->vx_mb[i] == NULL) + MGET(sc->vx_mb[i], M_DONTWAIT, MT_DATA); + if (sc->vx_mb[i] == NULL) break; i = (i + 1) % MAX_MBS; - } while (i != sc->next_mb); - sc->last_mb = i; + } while (i != sc->vx_next_mb); + sc->vx_last_mb = i; /* If the queue was not filled, try again. */ - if (sc->last_mb != sc->next_mb) { - sc->ch = timeout(vxmbuffill, sc, 1); - sc->buffill_pending = 1; + if (sc->vx_last_mb != sc->vx_next_mb) { + callout_reset(&sc->vx_callout, hz / 100, vx_mbuf_fill, sc); + sc->vx_buffill_pending = 1; } else { - sc->buffill_pending = 0; + sc->vx_buffill_pending = 0; } - splx(s); } static void -vxmbufempty(struct vx_softc *sc) +vx_mbuf_empty(struct vx_softc *sc) { - int s, i; + int i; - s = splimp(); + VX_LOCK_ASSERT(sc); for (i = 0; i < MAX_MBS; i++) { - if (sc->mb[i]) { - m_freem(sc->mb[i]); - sc->mb[i] = NULL; + if (sc->vx_mb[i]) { + m_freem(sc->vx_mb[i]); + sc->vx_mb[i] = NULL; } } - sc->last_mb = sc->next_mb = 0; - if (sc->buffill_pending != 0) - untimeout(vxmbuffill, sc, sc->ch); - splx(s); + sc->vx_last_mb = sc->vx_next_mb = 0; + if (sc->vx_buffill_pending != 0) + callout_stop(&sc->vx_callout); } diff --git a/sys/dev/vx/if_vx_eisa.c b/sys/dev/vx/if_vx_eisa.c index bbccb5b..ec67e26 100644 --- a/sys/dev/vx/if_vx_eisa.c +++ b/sys/dev/vx/if_vx_eisa.c @@ -114,7 +114,6 @@ vx_eisa_attach(device_t dev) struct resource *eisa_io = 0; struct resource *irq = 0; int rid; - void *ih; /* * The addresses are sorted in increasing order @@ -136,8 +135,8 @@ vx_eisa_attach(device_t dev) sc = device_get_softc(dev); sc->vx_res = io; - sc->bst = rman_get_bustag(io); - sc->bsh = rman_get_bushandle(io); + sc->vx_bst = rman_get_bustag(io); + sc->vx_bsh = rman_get_bushandle(io); rid = 0; irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); @@ -149,15 +148,17 @@ vx_eisa_attach(device_t dev) /* Now the registers are availible through the lower ioport */ - vxattach(dev); - - if (bus_setup_intr(dev, irq, INTR_TYPE_NET, vxintr, sc, &ih)) + if (vx_attach(dev) == 0) goto bad; - sc->vx_intrhand = ih; + if (bus_setup_intr(dev, irq, INTR_TYPE_NET | INTR_MPSAFE, vx_intr, sc, + &sc->vx_intrhand)) + goto bad_mtx; - return 0; + return (0); +bad_mtx: + mtx_destroy(&sc->vx_mtx); bad: if (io) bus_release_resource(dev, SYS_RES_IOPORT, 0, io); @@ -165,7 +166,7 @@ bad: bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io); if (irq) bus_release_resource(dev, SYS_RES_IRQ, 0, irq); - return -1; + return (ENXIO); } static device_method_t vx_eisa_methods[] = { diff --git a/sys/dev/vx/if_vx_pci.c b/sys/dev/vx/if_vx_pci.c index c0694f1..2e358d5 100644 --- a/sys/dev/vx/if_vx_pci.c +++ b/sys/dev/vx/if_vx_pci.c @@ -81,7 +81,9 @@ vx_pci_shutdown(device_t dev) struct vx_softc *sc; sc = device_get_softc(dev); - vxstop(sc); + VX_LOCK(sc); + vx_stop(sc); + VX_UNLOCK(sc); } static int @@ -131,8 +133,8 @@ vx_pci_attach(device_t dev) if (sc->vx_res == NULL) goto bad; - sc->bst = rman_get_bustag(sc->vx_res); - sc->bsh = rman_get_bushandle(sc->vx_res); + sc->vx_bst = rman_get_bustag(sc->vx_res); + sc->vx_bsh = rman_get_bushandle(sc->vx_res); rid = 0; sc->vx_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, @@ -141,27 +143,30 @@ vx_pci_attach(device_t dev) if (sc->vx_irq == NULL) goto bad; - if (bus_setup_intr(dev, sc->vx_irq, INTR_TYPE_NET, - vxintr, sc, &sc->vx_intrhand)) + if (vx_attach(dev) == 0) goto bad; - if (vxattach(dev) == 0) - goto bad; + if (bus_setup_intr(dev, sc->vx_irq, INTR_TYPE_NET | INTR_MPSAFE, + vx_intr, sc, &sc->vx_intrhand)) + goto bad_mtx; /* defect check for 3C590 */ if ((pci_read_config(dev, PCIR_DEVVENDOR, 4) >> 16) == 0x5900) { GO_WINDOW(0); - if (vxbusyeeprom(sc)) - goto bad; + if (vx_busy_eeprom(sc)) + goto bad_mtx; CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD | EEPROM_SOFTINFO2); - if (vxbusyeeprom(sc)) - goto bad; + if (vx_busy_eeprom(sc)) + goto bad_mtx; if (!(CSR_READ_2(sc, VX_W0_EEPROM_DATA) & NO_RX_OVN_ANOMALY)) - printf("Warning! Defective early revision adapter!\n"); + device_printf(dev, + "Warning! Defective early revision adapter!\n"); } return (0); +bad_mtx: + mtx_destroy(&sc->vx_mtx); bad: if (sc->vx_intrhand != NULL) bus_teardown_intr(dev, sc->vx_irq, sc->vx_intrhand); diff --git a/sys/dev/vx/if_vxvar.h b/sys/dev/vx/if_vxvar.h index 014d058..ec20a3f 100644 --- a/sys/dev/vx/if_vxvar.h +++ b/sys/dev/vx/if_vxvar.h @@ -35,42 +35,45 @@ * Ethernet software status per interface. */ struct vx_softc { - struct ifnet *ifp; - int unit; /* unit number */ - bus_space_tag_t bst; - bus_space_handle_t bsh; + struct ifnet *vx_ifp; + bus_space_tag_t vx_bst; + bus_space_handle_t vx_bsh; void *vx_intrhand; struct resource *vx_irq; struct resource *vx_res; #define MAX_MBS 8 /* # of mbufs we keep around */ - struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */ - int next_mb; /* Which mbuf to use next. */ - int last_mb; /* Last mbuf. */ + struct mbuf *vx_mb[MAX_MBS]; /* spare mbuf storage. */ + int vx_next_mb; /* Which mbuf to use next. */ + int vx_last_mb; /* Last mbuf. */ char vx_connectors; /* Connectors on this card. */ char vx_connector; /* Connector to use. */ - short tx_start_thresh; /* Current TX_start_thresh. */ - int tx_succ_ok; /* # packets sent in sequence */ + short vx_tx_start_thresh; /* Current TX_start_thresh. */ + int vx_tx_succ_ok; /* # packets sent in sequence */ /* w/o underrun */ - struct callout_handle ch; /* Callout handle for timeouts */ - int buffill_pending; + struct callout vx_callout; /* Callout for timeouts */ + struct mtx vx_mtx; + int vx_buffill_pending; }; #define CSR_WRITE_4(sc, reg, val) \ - bus_space_write_4(sc->bst, sc->bsh, reg, val) + bus_space_write_4(sc->vx_bst, sc->vx_bsh, reg, val) #define CSR_WRITE_2(sc, reg, val) \ - bus_space_write_2(sc->bst, sc->bsh, reg, val) + bus_space_write_2(sc->vx_bst, sc->vx_bsh, reg, val) #define CSR_WRITE_1(sc, reg, val) \ - bus_space_write_1(sc->bst, sc->bsh, reg, val) + bus_space_write_1(sc->vx_bst, sc->vx_bsh, reg, val) #define CSR_READ_4(sc, reg) \ - bus_space_read_4(sc->bst, sc->bsh, reg) + bus_space_read_4(sc->vx_bst, sc->vx_bsh, reg) #define CSR_READ_2(sc, reg) \ - bus_space_read_2(sc->bst, sc->bsh, reg) + bus_space_read_2(sc->vx_bst, sc->vx_bsh, reg) #define CSR_READ_1(sc, reg) \ - bus_space_read_1(sc->bst, sc->bsh, reg) + bus_space_read_1(sc->vx_bst, sc->vx_bsh, reg) -extern void vxfree(struct vx_softc *); -extern int vxattach(device_t); -extern void vxstop(struct vx_softc *); -extern void vxintr(void *); -extern int vxbusyeeprom(struct vx_softc *); +#define VX_LOCK(sc) mtx_lock(&(sc)->vx_mtx) +#define VX_UNLOCK(sc) mtx_unlock(&(sc)->vx_mtx) +#define VX_LOCK_ASSERT(sc) mtx_assert(&(sc)->vx_mtx, MA_OWNED) + +int vx_attach(device_t); +void vx_stop(struct vx_softc *); +void vx_intr(void *); +int vx_busy_eeprom(struct vx_softc *); |