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.
This commit is contained in:
Bill Paul 2004-01-04 21:22:25 +00:00
parent 2b19680751
commit 137bcec3f9
4 changed files with 41 additions and 6 deletions

View File

@ -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>

View File

@ -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);
}
/*

View File

@ -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);
@ -822,6 +829,25 @@ ndis_linksts_done(adapter)
return;
}
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;
}

View File

@ -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;