diff options
author | marius <marius@FreeBSD.org> | 2006-12-06 02:18:41 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2006-12-06 02:18:41 +0000 |
commit | a5878e15cf129593dc7e00da508adbbd01fd98f0 (patch) | |
tree | 9a379eaa927decab6fa3aee4825dd3a9fd8c3869 /sys/pci | |
parent | 17d1a5f84e80a69f2a8b2156001c5862f7c00afa (diff) | |
download | FreeBSD-src-a5878e15cf129593dc7e00da508adbbd01fd98f0.zip FreeBSD-src-a5878e15cf129593dc7e00da508adbbd01fd98f0.tar.gz |
- Use the xl_stats_update() callout instead of if_slowtimo() for
driving xl_watchdog() in order to avoid races accessing if_timer.
While at it relax the watchdog a bit by reloading it in xl_txeof()/
xl_txeof_90xB() if there are still packets enqueued.
- Use bus_get_dma_tag() so xl(4) works on platforms requiring it.
- Don't bother to set if_mtu to ETHERMTU, ether_ifattach() does that.
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_xl.c | 48 | ||||
-rw-r--r-- | sys/pci/if_xlreg.h | 1 |
2 files changed, 27 insertions, 22 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index 3d019c7..a5ac0eb 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -245,7 +245,7 @@ static int xl_ioctl(struct ifnet *, u_long, caddr_t); static void xl_init(void *); static void xl_init_locked(struct xl_softc *); static void xl_stop(struct xl_softc *); -static void xl_watchdog(struct ifnet *); +static int xl_watchdog(struct xl_softc *); static void xl_shutdown(device_t); static int xl_suspend(device_t); static int xl_resume(device_t); @@ -1380,7 +1380,7 @@ xl_attach(device_t dev) * All of our lists are allocated as a contiguous block * of memory. */ - error = bus_dma_tag_create(NULL, 8, 0, + error = bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, XL_RX_LIST_SZ, 1, XL_RX_LIST_SZ, 0, NULL, NULL, &sc->xl_ldata.xl_rx_tag); @@ -1412,7 +1412,7 @@ xl_attach(device_t dev) goto fail; } - error = bus_dma_tag_create(NULL, 8, 0, + error = bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, XL_TX_LIST_SZ, 1, XL_TX_LIST_SZ, 0, NULL, NULL, &sc->xl_ldata.xl_tx_tag); @@ -1447,7 +1447,7 @@ xl_attach(device_t dev) /* * Allocate a DMA tag for the mapping of mbufs. */ - error = bus_dma_tag_create(NULL, 1, 0, + error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * XL_MAXFRAGS, XL_MAXFRAGS, MCLBYTES, 0, NULL, NULL, &sc->xl_mtag); @@ -1481,7 +1481,6 @@ xl_attach(device_t dev) /* Set the TX start threshold for best performance. */ sc->xl_tx_thresh = XL_MIN_FRAMELEN; - ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = xl_ioctl; ifp->if_capabilities = IFCAP_VLAN_MTU; @@ -1498,7 +1497,6 @@ xl_attach(device_t dev) ifp->if_capabilities |= IFCAP_POLLING; #endif ifp->if_start = xl_start; - ifp->if_watchdog = xl_watchdog; ifp->if_init = xl_init; IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1); ifp->if_snd.ifq_drv_maxlen = XL_TX_LIST_CNT - 1; @@ -2154,7 +2152,7 @@ xl_txeof(struct xl_softc *sc) if (sc->xl_cdata.xl_tx_head == NULL) { ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; /* Clear the timeout timer. */ - ifp->if_timer = 0; + sc->xl_wdog_timer = 0; sc->xl_cdata.xl_tx_tail = NULL; } else { if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED || @@ -2162,6 +2160,7 @@ xl_txeof(struct xl_softc *sc) CSR_WRITE_4(sc, XL_DOWNLIST_PTR, sc->xl_cdata.xl_tx_head->xl_phys); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL); + sc->xl_wdog_timer = 5; } } } @@ -2200,8 +2199,7 @@ xl_txeof_90xB(struct xl_softc *sc) XL_INC(idx, XL_TX_LIST_CNT); } - if (sc->xl_cdata.xl_tx_cnt == 0) - ifp->if_timer = 0; + sc->xl_wdog_timer = sc->xl_cdata.xl_tx_cnt == 0 ? 0 : 5; sc->xl_cdata.xl_tx_cons = idx; if (cur_tx != NULL) @@ -2411,6 +2409,10 @@ xl_stats_update(void *xsc) struct xl_softc *sc = xsc; XL_LOCK_ASSERT(sc); + + if (xl_watchdog(sc) == EJUSTRETURN) + return; + xl_stats_update_locked(sc); } @@ -2666,7 +2668,7 @@ xl_start_locked(struct ifnet *ifp) /* * Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; + sc->xl_wdog_timer = 5; /* * XXX Under certain conditions, usually on slower machines @@ -2764,7 +2766,7 @@ xl_start_90xB_locked(struct ifnet *ifp) /* * Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; + sc->xl_wdog_timer = 5; } static void @@ -2999,6 +3001,7 @@ xl_init_locked(struct xl_softc *sc) ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + sc->xl_wdog_timer = 0; callout_reset(&sc->xl_stat_callout, hz, xl_stats_update, sc); } @@ -3231,24 +3234,25 @@ xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) return (error); } -/* - * XXX: Invoked from ifnet slow timer. Lock coverage needed. - */ -static void -xl_watchdog(struct ifnet *ifp) +static int +xl_watchdog(struct xl_softc *sc) { - struct xl_softc *sc = ifp->if_softc; + struct ifnet *ifp = sc->xl_ifp; u_int16_t status = 0; - XL_LOCK(sc); + XL_LOCK_ASSERT(sc); + + if (sc->xl_wdog_timer == 0 || --sc->xl_wdog_timer != 0) + return (0); ifp->if_oerrors++; XL_SEL_WIN(4); status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS); - if_printf(ifp, "watchdog timeout\n"); + device_printf(sc->xl_dev, "watchdog timeout\n"); if (status & XL_MEDIASTAT_CARRIER) - if_printf(ifp, "no carrier - transceiver cable problem?\n"); + device_printf(sc->xl_dev, + "no carrier - transceiver cable problem?\n"); xl_txeoc(sc); xl_txeof(sc); @@ -3263,7 +3267,7 @@ xl_watchdog(struct ifnet *ifp) xl_start_locked(ifp); } - XL_UNLOCK(sc); + return (EJUSTRETURN); } /* @@ -3278,7 +3282,7 @@ xl_stop(struct xl_softc *sc) XL_LOCK_ASSERT(sc); - ifp->if_timer = 0; + sc->xl_wdog_timer = 0; CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE); diff --git a/sys/pci/if_xlreg.h b/sys/pci/if_xlreg.h index eba21e6..ca393f3 100644 --- a/sys/pci/if_xlreg.h +++ b/sys/pci/if_xlreg.h @@ -603,6 +603,7 @@ struct xl_softc { struct xl_list_data xl_ldata; struct xl_chain_data xl_cdata; struct callout xl_stat_callout; + int xl_wdog_timer; int xl_flags; struct resource *xl_fres; bus_space_handle_t xl_fhandle; |