- 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.
This commit is contained in:
Marius Strobl 2006-12-06 02:18:41 +00:00
parent 49d5157434
commit 3541d6d881
2 changed files with 27 additions and 22 deletions

View File

@ -245,7 +245,7 @@ static int xl_ioctl(struct ifnet *, u_long, caddr_t);
static void xl_init(void *); static void xl_init(void *);
static void xl_init_locked(struct xl_softc *); static void xl_init_locked(struct xl_softc *);
static void xl_stop(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 void xl_shutdown(device_t);
static int xl_suspend(device_t); static int xl_suspend(device_t);
static int xl_resume(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 * All of our lists are allocated as a contiguous block
* of memory. * 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, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
XL_RX_LIST_SZ, 1, XL_RX_LIST_SZ, 0, NULL, NULL, XL_RX_LIST_SZ, 1, XL_RX_LIST_SZ, 0, NULL, NULL,
&sc->xl_ldata.xl_rx_tag); &sc->xl_ldata.xl_rx_tag);
@ -1412,7 +1412,7 @@ xl_attach(device_t dev)
goto fail; 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, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
XL_TX_LIST_SZ, 1, XL_TX_LIST_SZ, 0, NULL, NULL, XL_TX_LIST_SZ, 1, XL_TX_LIST_SZ, 0, NULL, NULL,
&sc->xl_ldata.xl_tx_tag); &sc->xl_ldata.xl_tx_tag);
@ -1447,7 +1447,7 @@ xl_attach(device_t dev)
/* /*
* Allocate a DMA tag for the mapping of mbufs. * 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, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
MCLBYTES * XL_MAXFRAGS, XL_MAXFRAGS, MCLBYTES, 0, NULL, MCLBYTES * XL_MAXFRAGS, XL_MAXFRAGS, MCLBYTES, 0, NULL,
NULL, &sc->xl_mtag); NULL, &sc->xl_mtag);
@ -1481,7 +1481,6 @@ xl_attach(device_t dev)
/* Set the TX start threshold for best performance. */ /* Set the TX start threshold for best performance. */
sc->xl_tx_thresh = XL_MIN_FRAMELEN; sc->xl_tx_thresh = XL_MIN_FRAMELEN;
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = xl_ioctl; ifp->if_ioctl = xl_ioctl;
ifp->if_capabilities = IFCAP_VLAN_MTU; ifp->if_capabilities = IFCAP_VLAN_MTU;
@ -1498,7 +1497,6 @@ xl_attach(device_t dev)
ifp->if_capabilities |= IFCAP_POLLING; ifp->if_capabilities |= IFCAP_POLLING;
#endif #endif
ifp->if_start = xl_start; ifp->if_start = xl_start;
ifp->if_watchdog = xl_watchdog;
ifp->if_init = xl_init; ifp->if_init = xl_init;
IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1); IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1);
ifp->if_snd.ifq_drv_maxlen = 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) { if (sc->xl_cdata.xl_tx_head == NULL) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
/* Clear the timeout timer. */ /* Clear the timeout timer. */
ifp->if_timer = 0; sc->xl_wdog_timer = 0;
sc->xl_cdata.xl_tx_tail = NULL; sc->xl_cdata.xl_tx_tail = NULL;
} else { } else {
if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED || 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, CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
sc->xl_cdata.xl_tx_head->xl_phys); sc->xl_cdata.xl_tx_head->xl_phys);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL); 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); XL_INC(idx, XL_TX_LIST_CNT);
} }
if (sc->xl_cdata.xl_tx_cnt == 0) sc->xl_wdog_timer = sc->xl_cdata.xl_tx_cnt == 0 ? 0 : 5;
ifp->if_timer = 0;
sc->xl_cdata.xl_tx_cons = idx; sc->xl_cdata.xl_tx_cons = idx;
if (cur_tx != NULL) if (cur_tx != NULL)
@ -2411,6 +2409,10 @@ xl_stats_update(void *xsc)
struct xl_softc *sc = xsc; struct xl_softc *sc = xsc;
XL_LOCK_ASSERT(sc); XL_LOCK_ASSERT(sc);
if (xl_watchdog(sc) == EJUSTRETURN)
return;
xl_stats_update_locked(sc); 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. * 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 * 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. * Set a timeout in case the chip goes out to lunch.
*/ */
ifp->if_timer = 5; sc->xl_wdog_timer = 5;
} }
static void 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_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->xl_wdog_timer = 0;
callout_reset(&sc->xl_stat_callout, hz, xl_stats_update, sc); 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); return (error);
} }
/* static int
* XXX: Invoked from ifnet slow timer. Lock coverage needed. xl_watchdog(struct xl_softc *sc)
*/
static void
xl_watchdog(struct ifnet *ifp)
{ {
struct xl_softc *sc = ifp->if_softc; struct ifnet *ifp = sc->xl_ifp;
u_int16_t status = 0; 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++; ifp->if_oerrors++;
XL_SEL_WIN(4); XL_SEL_WIN(4);
status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS); 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 (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_txeoc(sc);
xl_txeof(sc); xl_txeof(sc);
@ -3263,7 +3267,7 @@ xl_watchdog(struct ifnet *ifp)
xl_start_locked(ifp); xl_start_locked(ifp);
} }
XL_UNLOCK(sc); return (EJUSTRETURN);
} }
/* /*
@ -3278,7 +3282,7 @@ xl_stop(struct xl_softc *sc)
XL_LOCK_ASSERT(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_RX_DISABLE);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);

View File

@ -603,6 +603,7 @@ struct xl_softc {
struct xl_list_data xl_ldata; struct xl_list_data xl_ldata;
struct xl_chain_data xl_cdata; struct xl_chain_data xl_cdata;
struct callout xl_stat_callout; struct callout xl_stat_callout;
int xl_wdog_timer;
int xl_flags; int xl_flags;
struct resource *xl_fres; struct resource *xl_fres;
bus_space_handle_t xl_fhandle; bus_space_handle_t xl_fhandle;