diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-01-04 21:22:25 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-01-04 21:22:25 +0000 |
commit | 389bb3f2740d927f4df014cafb327e374ba754f2 (patch) | |
tree | 22f4c945c9ab9acae545b55eb3a4bb09cce9f538 /sys | |
parent | d6c42f745d60bfd8defbb5aa613bfa4dd51e2731 (diff) | |
download | FreeBSD-src-389bb3f2740d927f4df014cafb327e374ba754f2.zip FreeBSD-src-389bb3f2740d927f4df014cafb327e374ba754f2.tar.gz |
Modify if_ndis.c so that the MiniportISR function runs in ndis_intr()
and MiniportHandleInterrupt() is fired off later via a task queue in
ndis_intrtask(). This more accurately follows the NDIS interrupt handling
model, where the ISR does a minimal amount of work in interrupt context
and the handler is defered and run at a lower priority.
Create a separate ndis_intrmtx mutex just for the guarding the ISR.
Modify NdisSynchronizeWithInterrupt() to aquire the ndis_intrmtx
mutex before invoking the synchronized procedure. (The purpose of
this function is to provide mutual exclusion for code that shares
variables with the ISR.)
Modify NdisMRegisterInterrupt() to save a pointer to the miniport
block in the ndis_miniport_interrupt structure so that
NdisSynchronizeWithInterrupt() can grab it later and derive
ndis_intrmtx from it.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 1 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 11 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 33 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndisvar.h | 2 |
4 files changed, 41 insertions, 6 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 02d107b..4e0ce26 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/conf.h> +#include <sys/taskqueue.h> #include <sys/kernel.h> #include <machine/bus.h> diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 03ab318..218445a 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -1894,7 +1894,7 @@ ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) uint8_t shared; ndis_interrupt_mode imode; { - + intr->ni_block = adapter; return(NDIS_STATUS_SUCCESS); } @@ -2124,13 +2124,20 @@ ndis_sync_with_intr(intr, syncfunc, syncctx) void *syncfunc; void *syncctx; { + struct ndis_softc *sc; __stdcall uint8_t (*sync)(void *); + uint8_t rval; if (syncfunc == NULL || syncctx == NULL) return(0); + sc = (struct ndis_softc *)intr->ni_block->nmb_ifp; sync = syncfunc; - return(sync(syncctx)); + mtx_lock(&sc->ndis_intrmtx); + rval = sync(syncctx); + mtx_unlock(&sc->ndis_intrmtx); + + return(rval); } /* diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 96dd832..e4436d3 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <sys/queue.h> #include <sys/sysctl.h> +#include <sys/taskqueue.h> #include <net/if.h> #include <net/if_arp.h> @@ -105,6 +106,7 @@ static __stdcall void ndis_linksts (ndis_handle, static __stdcall void ndis_linksts_done (ndis_handle); static void ndis_intr (void *); +static void ndis_intrtask (void *, int); static void ndis_tick (void *); static void ndis_start (struct ifnet *); static int ndis_ioctl (struct ifnet *, u_long, caddr_t); @@ -327,6 +329,10 @@ ndis_attach(dev) goto fail; } + mtx_init(&sc->ndis_intrmtx, device_get_nameunit(dev), "ndisisrlock", + MTX_DEF | MTX_RECURSE); + TASK_INIT(&sc->ndis_intrtask, 0, ndis_intrtask, sc); + /* * Allocate the parent bus DMA tag appropriate for PCI. */ @@ -656,6 +662,7 @@ ndis_detach(dev) sysctl_ctx_free(&sc->ndis_ctx); + mtx_destroy(&sc->ndis_intrmtx); mtx_destroy(&sc->ndis_mtx); return(0); @@ -823,6 +830,25 @@ ndis_linksts_done(adapter) } static void +ndis_intrtask(arg, pending) + void *arg; + int pending; +{ + struct ndis_softc *sc; + struct ifnet *ifp; + + sc = arg; + ifp = &sc->arpcom.ac_if; + + ndis_intrhand(sc); + + if (ifp->if_snd.ifq_head != NULL) + ndis_start(ifp); + + return; +} + +static void ndis_intr(arg) void *arg; { @@ -837,13 +863,12 @@ ndis_intr(arg) if (!(ifp->if_flags & IFF_UP)) return; + mtx_lock(&sc->ndis_intrmtx); ndis_isr(sc, &is_our_intr, &call_isr); + mtx_unlock(&sc->ndis_intrmtx); if (is_our_intr || call_isr) - ndis_intrhand(sc); - - if (ifp->if_snd.ifq_head != NULL) - ndis_start(ifp); + taskqueue_enqueue(taskqueue_swi, &sc->ndis_intrtask); return; } diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h index 8d92759..01d8491 100644 --- a/sys/dev/if_ndis/if_ndisvar.h +++ b/sys/dev/if_ndis/if_ndisvar.h @@ -91,6 +91,8 @@ struct ndis_softc { struct resource *ndis_res_cm; /* common mem (pccard) */ int ndis_rescnt; struct mtx ndis_mtx; + struct mtx ndis_intrmtx; + struct task ndis_intrtask; device_t ndis_dev; int ndis_unit; ndis_miniport_block ndis_block; |