summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2004-01-04 21:22:25 +0000
committerwpaul <wpaul@FreeBSD.org>2004-01-04 21:22:25 +0000
commit389bb3f2740d927f4df014cafb327e374ba754f2 (patch)
tree22f4c945c9ab9acae545b55eb3a4bb09cce9f538
parentd6c42f745d60bfd8defbb5aa613bfa4dd51e2731 (diff)
downloadFreeBSD-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.
-rw-r--r--sys/compat/ndis/kern_ndis.c1
-rw-r--r--sys/compat/ndis/subr_ndis.c11
-rw-r--r--sys/dev/if_ndis/if_ndis.c33
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h2
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;
OpenPOWER on IntegriCloud