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:
parent
2b19680751
commit
137bcec3f9
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user