summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_xl.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2005-05-20 07:16:09 +0000
committerglebius <glebius@FreeBSD.org>2005-05-20 07:16:09 +0000
commita74a3160f2b77dde29853a0366d865e72c4cb828 (patch)
treef165b80121d201f329e45da3a6b38af0aeaa167c /sys/pci/if_xl.c
parentac2cc57f35ae2ef77a63981087121b4033447d27 (diff)
downloadFreeBSD-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.c20
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);
OpenPOWER on IntegriCloud