diff options
author | glebius <glebius@FreeBSD.org> | 2005-05-20 07:16:09 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-05-20 07:16:09 +0000 |
commit | a74a3160f2b77dde29853a0366d865e72c4cb828 (patch) | |
tree | f165b80121d201f329e45da3a6b38af0aeaa167c /sys/pci/if_xl.c | |
parent | ac2cc57f35ae2ef77a63981087121b4033447d27 (diff) | |
download | FreeBSD-src-a74a3160f2b77dde29853a0366d865e72c4cb828.zip FreeBSD-src-a74a3160f2b77dde29853a0366d865e72c4cb828.tar.gz |
Calling xl_rxeof() at the end of xl_start_locked() leads to recursion
in case of IP fast forwarding. Enqueue a taskqueue(9) task instead of
calling xl_rxeof() directly.
Reported & tested by: Slava Alpatov
Reviewed by: wpaul
MFC after: 1 week
Diffstat (limited to 'sys/pci/if_xl.c')
-rw-r--r-- | sys/pci/if_xl.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index 498e1c4..0741667 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -109,6 +109,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/socket.h> +#include <sys/taskqueue.h> #include <net/if.h> #include <net/if_arp.h> @@ -228,6 +229,7 @@ static void xl_stats_update(void *); static void xl_stats_update_locked(struct xl_softc *); static int xl_encap(struct xl_softc *, struct xl_chain *, struct mbuf *); static void xl_rxeof(struct xl_softc *); +static void xl_rxeof_task(void *, int); static int xl_rx_resync(struct xl_softc *); static void xl_txeof(struct xl_softc *); static void xl_txeof_90xB(struct xl_softc *); @@ -1368,6 +1370,7 @@ xl_attach(device_t dev) sc->xl_unit = unit; callout_handle_init(&sc->xl_stat_ch); + TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc); bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); /* @@ -2085,6 +2088,19 @@ again: } /* + * Taskqueue wrapper for xl_rxeof(). + */ +static void +xl_rxeof_task(void *arg, int pending) +{ + struct xl_softc *sc = (struct xl_softc *)arg; + + XL_LOCK(sc); + xl_rxeof(sc); + XL_UNLOCK(sc); +} + +/* * A frame was downloaded to the chip. It's safe for us to clean up * the list buffers. */ @@ -2683,7 +2699,7 @@ xl_start_locked(struct ifnet *ifp) * nature of their chips in all their marketing literature; * we may as well take advantage of it. :) */ - xl_rxeof(sc); + taskqueue_enqueue(taskqueue_swi, &sc->xl_task); } static void @@ -3254,6 +3270,8 @@ xl_stop(struct xl_softc *sc) ether_poll_deregister(ifp); #endif /* DEVICE_POLLING */ + taskqueue_drain(taskqueue_swi, &sc->xl_task); + 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_INTR_ENB); |