summaryrefslogtreecommitdiffstats
path: root/sys/compat/ndis/kern_ndis.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2005-05-05 03:56:09 +0000
committerwpaul <wpaul@FreeBSD.org>2005-05-05 03:56:09 +0000
commite9bace5ba16735b4fd2dbe727166b3720fbf5101 (patch)
tree30ee12e28c23fde2935b1a325aa64886d934d365 /sys/compat/ndis/kern_ndis.c
parente5184a989dd8bb5df40b429933d7a7222b058dfd (diff)
downloadFreeBSD-src-e9bace5ba16735b4fd2dbe727166b3720fbf5101.zip
FreeBSD-src-e9bace5ba16735b4fd2dbe727166b3720fbf5101.tar.gz
This commit makes a bunch of changes, some big, some not so big.
- Remove the old task threads from kern_ndis.c and reimplement them in subr_ntoskrnl.c, in order to more properly emulate the Windows DPC API. Each CPU gets its own DPC queue/thread, and each queue can have low, medium and high importance DPCs. New APIs implemented: KeSetTargetProcessorDpc(), KeSetImportanceDpc() and KeFlushQueuedDpcs(). (This is the biggest change.) - Fix a bug in NdisMInitializeTimer(): the k_dpc pointer in the nmt_timer embedded in the ndis_miniport_timer struct must be set to point to the DPC, also embedded in the struct. Failing to do this breaks dequeueing of DPCs submitted via timers, and in turn breaks cancelling timers. - Fix a bug in KeCancelTimer(): if the timer is interted in the timer queue (i.e. the timeout callback is still pending), we have to both untimeout() the timer _and_ call KeRemoveQueueDpc() to nuke the DPC that might be pending. Failing to do this breaks cancellation of periodic timers, which always appear to be inserted in the timer queue. - Make use of the nmt_nexttimer field in ndis_miniport_timer: keep a queue of pending timers and cancel them all in ndis_halt_nic(), prior to calling MiniportHalt(). Also call KeFlushQueuedDpcs() to make sure any DPCs queued by the timers have expired. - Modify NdisMAllocateSharedMemory() and NdisMFreeSharedMemory() to keep track of both the virtual and physical addresses of the shared memory buffers that get handed out. The AirGo MIMO driver appears to have a bug in it: for one of the segments is allocates, it returns the wrong virtual address. This would confuse NdisMFreeSharedMemory() and cause a crash. Why it doesn't crash Windows too I have no idea (from reading the documentation for NdisMFreeSharedMemory(), it appears to be a violation of the API). - Implement strstr(), strchr() and MmIsAddressValid(). - Implement IoAllocateWorkItem(), IoFreeWorkItem(), IoQueueWorkItem() and ExQueueWorkItem(). (This is the second biggest change.) - Make NdisScheduleWorkItem() call ExQueueWorkItem(). (Note that the ExQueueWorkItem() API is deprecated by Microsoft, but NDIS still uses it, since NdisScheduleWorkItem() is incompatible with the IoXXXWorkItem() API.) - Change if_ndis.c to use the NdisScheduleWorkItem() interface for scheduling tasks. With all these changes and fixes, the AirGo MIMO driver for the Belkin F5D8010 Pre-N card now works. Special thanks to Paul Robinson (paul dawt robinson at pwermedia dawt net) for the loan of a card for testing.
Diffstat (limited to 'sys/compat/ndis/kern_ndis.c')
-rw-r--r--sys/compat/ndis/kern_ndis.c447
1 files changed, 78 insertions, 369 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index 56832ea..0dfcb53 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -84,6 +84,7 @@ static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t);
static void ndis_sendrsrcavail_func(ndis_handle);
static void ndis_intrhand(kdpc *, device_object *,
irp *, struct ndis_softc *);
+static void ndis_return(kdpc *, void *, void *, void *);
static image_patch_table kernndis_functbl[] = {
IMPORT_SFUNC(ndis_status_func, 4),
@@ -93,42 +94,14 @@ static image_patch_table kernndis_functbl[] = {
IMPORT_SFUNC(ndis_resetdone_func, 3),
IMPORT_SFUNC(ndis_sendrsrcavail_func, 1),
IMPORT_SFUNC(ndis_intrhand, 4),
+ IMPORT_SFUNC(ndis_return, 1),
{ NULL, NULL, NULL }
};
struct nd_head ndis_devhead;
-struct ndis_req {
- void (*nr_func)(void *);
- void *nr_arg;
- int nr_exit;
- STAILQ_ENTRY(ndis_req) link;
-};
-
-struct ndisproc {
- struct ndisqhead *np_q;
- struct proc *np_p;
- int np_state;
-};
-
-static void ndis_return(void *);
-static int ndis_create_kthreads(void);
-static void ndis_destroy_kthreads(void);
-static void ndis_stop_thread(int);
-static int ndis_enlarge_thrqueue(int);
-static int ndis_shrink_thrqueue(int);
-static void ndis_runq(void *);
-
-static struct mtx ndis_thr_mtx;
static struct mtx ndis_req_mtx;
-static STAILQ_HEAD(ndisqhead, ndis_req) ndis_ttodo;
-static struct ndisqhead ndis_itodo;
-static struct ndisqhead ndis_free;
-static int ndis_jobs = 32;
-
-static struct ndisproc ndis_tproc;
-static struct ndisproc ndis_iproc;
/*
* This allows us to export our symbols to other modules.
@@ -160,14 +133,13 @@ ndis_modevent(module_t mod, int cmd, void *arg)
patch++;
}
- ndis_create_kthreads();
-
TAILQ_INIT(&ndis_devhead);
+ mtx_init(&ndis_req_mtx, "NDIS request lock",
+ MTX_NDIS_LOCK, MTX_DEF);
+
break;
case MOD_SHUTDOWN:
- /* stop kthreads */
- ndis_destroy_kthreads();
if (TAILQ_FIRST(&ndis_devhead) == NULL) {
/* Shut down subsystems */
hal_libfini();
@@ -181,12 +153,10 @@ ndis_modevent(module_t mod, int cmd, void *arg)
windrv_unwrap(patch->ipt_wrap);
patch++;
}
+ mtx_destroy(&ndis_req_mtx);
}
break;
case MOD_UNLOAD:
- /* stop kthreads */
- ndis_destroy_kthreads();
-
/* Shut down subsystems */
hal_libfini();
ndis_libfini();
@@ -200,6 +170,8 @@ ndis_modevent(module_t mod, int cmd, void *arg)
patch++;
}
+ mtx_destroy(&ndis_req_mtx);
+
break;
default:
error = EINVAL;
@@ -211,326 +183,6 @@ ndis_modevent(module_t mod, int cmd, void *arg)
DEV_MODULE(ndisapi, ndis_modevent, NULL);
MODULE_VERSION(ndisapi, 1);
-/*
- * We create two kthreads for the NDIS subsystem. One of them is a task
- * queue for performing various odd jobs. The other is an swi thread
- * reserved exclusively for running interrupt handlers. The reason we
- * have our own task queue is that there are some cases where we may
- * need to sleep for a significant amount of time, and if we were to
- * use one of the taskqueue threads, we might delay the processing
- * of other pending tasks which might need to run right away. We have
- * a separate swi thread because we don't want our interrupt handling
- * to be delayed either.
- *
- * By default there are 32 jobs available to start, and another 8
- * are added to the free list each time a new device is created.
- */
-
-static void
-ndis_runq(arg)
- void *arg;
-{
- struct ndis_req *r = NULL, *die = NULL;
- struct ndisproc *p;
-
- p = arg;
-
- while (1) {
-
- /* Sleep, but preserve our original priority. */
- ndis_thsuspend(p->np_p, NULL, 0);
-
- /* Look for any jobs on the work queue. */
-
- mtx_lock_spin(&ndis_thr_mtx);
- p->np_state = NDIS_PSTATE_RUNNING;
- while(STAILQ_FIRST(p->np_q) != NULL) {
- r = STAILQ_FIRST(p->np_q);
- STAILQ_REMOVE_HEAD(p->np_q, link);
- mtx_unlock_spin(&ndis_thr_mtx);
-
- /* Do the work. */
-
- if (r->nr_func != NULL)
- (*r->nr_func)(r->nr_arg);
-
- mtx_lock_spin(&ndis_thr_mtx);
- STAILQ_INSERT_HEAD(&ndis_free, r, link);
-
- /* Check for a shutdown request */
-
- if (r->nr_exit == TRUE)
- die = r;
- }
- p->np_state = NDIS_PSTATE_SLEEPING;
- mtx_unlock_spin(&ndis_thr_mtx);
-
- /* Bail if we were told to shut down. */
-
- if (die != NULL)
- break;
- }
-
- wakeup(die);
-#if __FreeBSD_version < 502113
- mtx_lock(&Giant);
-#endif
- kthread_exit(0);
- return; /* notreached */
-}
-
-static int
-ndis_create_kthreads()
-{
- struct ndis_req *r;
- int i, error = 0;
-
- mtx_init(&ndis_thr_mtx, "NDIS thread lock", NULL, MTX_SPIN);
- mtx_init(&ndis_req_mtx, "NDIS request lock", MTX_NDIS_LOCK, MTX_DEF);
-
- STAILQ_INIT(&ndis_ttodo);
- STAILQ_INIT(&ndis_itodo);
- STAILQ_INIT(&ndis_free);
-
- for (i = 0; i < ndis_jobs; i++) {
- r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK);
- if (r == NULL) {
- error = ENOMEM;
- break;
- }
- STAILQ_INSERT_HEAD(&ndis_free, r, link);
- }
-
- if (error == 0) {
- ndis_tproc.np_q = &ndis_ttodo;
- ndis_tproc.np_state = NDIS_PSTATE_SLEEPING;
- error = kthread_create(ndis_runq, &ndis_tproc,
- &ndis_tproc.np_p, RFHIGHPID,
- NDIS_KSTACK_PAGES, "ndis taskqueue");
- }
-
- if (error == 0) {
- ndis_iproc.np_q = &ndis_itodo;
- ndis_iproc.np_state = NDIS_PSTATE_SLEEPING;
- error = kthread_create(ndis_runq, &ndis_iproc,
- &ndis_iproc.np_p, RFHIGHPID,
- NDIS_KSTACK_PAGES, "ndis swi");
- }
-
- if (error) {
- while ((r = STAILQ_FIRST(&ndis_free)) != NULL) {
- STAILQ_REMOVE_HEAD(&ndis_free, link);
- free(r, M_DEVBUF);
- }
- return(error);
- }
-
- return(0);
-}
-
-static void
-ndis_destroy_kthreads()
-{
- struct ndis_req *r;
-
- /* Stop the threads. */
-
- ndis_stop_thread(NDIS_TASKQUEUE);
- ndis_stop_thread(NDIS_SWI);
-
- /* Destroy request structures. */
-
- while ((r = STAILQ_FIRST(&ndis_free)) != NULL) {
- STAILQ_REMOVE_HEAD(&ndis_free, link);
- free(r, M_DEVBUF);
- }
-
- mtx_destroy(&ndis_req_mtx);
- mtx_destroy(&ndis_thr_mtx);
-
- return;
-}
-
-static void
-ndis_stop_thread(t)
- int t;
-{
- struct ndis_req *r;
- struct ndisqhead *q;
- struct proc *p;
-
- if (t == NDIS_TASKQUEUE) {
- q = &ndis_ttodo;
- p = ndis_tproc.np_p;
- } else {
- q = &ndis_itodo;
- p = ndis_iproc.np_p;
- }
-
- /* Create and post a special 'exit' job. */
-
- mtx_lock_spin(&ndis_thr_mtx);
- r = STAILQ_FIRST(&ndis_free);
- STAILQ_REMOVE_HEAD(&ndis_free, link);
- r->nr_func = NULL;
- r->nr_arg = NULL;
- r->nr_exit = TRUE;
- STAILQ_INSERT_TAIL(q, r, link);
- mtx_unlock_spin(&ndis_thr_mtx);
-
- ndis_thresume(p);
-
- /* wait for thread exit */
-
- tsleep(r, curthread->td_priority|PCATCH, "ndisthexit", hz * 60);
-
- /* Now empty the job list. */
-
- mtx_lock_spin(&ndis_thr_mtx);
- while ((r = STAILQ_FIRST(q)) != NULL) {
- STAILQ_REMOVE_HEAD(q, link);
- STAILQ_INSERT_HEAD(&ndis_free, r, link);
- }
- mtx_unlock_spin(&ndis_thr_mtx);
-
- return;
-}
-
-static int
-ndis_enlarge_thrqueue(cnt)
- int cnt;
-{
- struct ndis_req *r;
- int i;
-
- for (i = 0; i < cnt; i++) {
- r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK);
- if (r == NULL)
- return(ENOMEM);
- mtx_lock_spin(&ndis_thr_mtx);
- STAILQ_INSERT_HEAD(&ndis_free, r, link);
- ndis_jobs++;
- mtx_unlock_spin(&ndis_thr_mtx);
- }
-
- return(0);
-}
-
-static int
-ndis_shrink_thrqueue(cnt)
- int cnt;
-{
- struct ndis_req *r;
- int i;
-
- for (i = 0; i < cnt; i++) {
- mtx_lock_spin(&ndis_thr_mtx);
- r = STAILQ_FIRST(&ndis_free);
- if (r == NULL) {
- mtx_unlock_spin(&ndis_thr_mtx);
- return(ENOMEM);
- }
- STAILQ_REMOVE_HEAD(&ndis_free, link);
- ndis_jobs--;
- mtx_unlock_spin(&ndis_thr_mtx);
- free(r, M_DEVBUF);
- }
-
- return(0);
-}
-
-int
-ndis_unsched(func, arg, t)
- void (*func)(void *);
- void *arg;
- int t;
-{
- struct ndis_req *r;
- struct ndisqhead *q;
- struct proc *p;
-
- if (t == NDIS_TASKQUEUE) {
- q = &ndis_ttodo;
- p = ndis_tproc.np_p;
- } else {
- q = &ndis_itodo;
- p = ndis_iproc.np_p;
- }
-
- mtx_lock_spin(&ndis_thr_mtx);
- STAILQ_FOREACH(r, q, link) {
- if (r->nr_func == func && r->nr_arg == arg) {
- STAILQ_REMOVE(q, r, ndis_req, link);
- STAILQ_INSERT_HEAD(&ndis_free, r, link);
- mtx_unlock_spin(&ndis_thr_mtx);
- return(0);
- }
- }
-
- mtx_unlock_spin(&ndis_thr_mtx);
-
- return(ENOENT);
-}
-
-int
-ndis_sched(func, arg, t)
- void (*func)(void *);
- void *arg;
- int t;
-{
- struct ndis_req *r;
- struct ndisqhead *q;
- struct proc *p;
- int s;
-
- if (t == NDIS_TASKQUEUE) {
- q = &ndis_ttodo;
- p = ndis_tproc.np_p;
- } else {
- q = &ndis_itodo;
- p = ndis_iproc.np_p;
- }
-
- mtx_lock_spin(&ndis_thr_mtx);
- /*
- * Check to see if an instance of this job is already
- * pending. If so, don't bother queuing it again.
- */
- STAILQ_FOREACH(r, q, link) {
- if (r->nr_func == func && r->nr_arg == arg) {
- mtx_unlock_spin(&ndis_thr_mtx);
- return(0);
- }
- }
- r = STAILQ_FIRST(&ndis_free);
- if (r == NULL) {
- mtx_unlock_spin(&ndis_thr_mtx);
- return(EAGAIN);
- }
- STAILQ_REMOVE_HEAD(&ndis_free, link);
- r->nr_func = func;
- r->nr_arg = arg;
- r->nr_exit = FALSE;
- STAILQ_INSERT_TAIL(q, r, link);
- if (t == NDIS_TASKQUEUE)
- s = ndis_tproc.np_state;
- else
- s = ndis_iproc.np_state;
- mtx_unlock_spin(&ndis_thr_mtx);
-
- /*
- * Post the job, but only if the thread is actually blocked
- * on its own suspend call. If a driver queues up a job with
- * NdisScheduleWorkItem() which happens to do a KeWaitForObject(),
- * it may suspend there, and in that case we don't want to wake
- * it up until KeWaitForObject() gets woken up on its own.
- */
- if (s == NDIS_PSTATE_SLEEPING)
- ndis_thresume(p);
-
- return(0);
-}
-
int
ndis_thsuspend(p, m, timo)
struct proc *p;
@@ -680,6 +332,7 @@ ndis_create_sysctls(arg)
while(1) {
if (vals->nc_cfgkey == NULL)
break;
+
if (vals->nc_idx != sc->ndis_devidx) {
vals++;
continue;
@@ -814,8 +467,11 @@ ndis_flush_sysctls(arg)
}
static void
-ndis_return(arg)
+ndis_return(dpc, arg, sysarg1, sysarg2)
+ kdpc *dpc;
void *arg;
+ void *sysarg1;
+ void *sysarg2;
{
struct ndis_softc *sc;
ndis_return_handler returnfunc;
@@ -858,7 +514,8 @@ ndis_return_packet(buf, arg)
if (p->np_refcnt)
return;
- ndis_sched(ndis_return, p, NDIS_TASKQUEUE);
+ KeInitializeDpc(&p->np_dpc, kernndis_functbl[7].ipt_wrap, p);
+ KeInsertQueueDpc(&p->np_dpc, NULL, NULL);
return;
}
@@ -948,6 +605,7 @@ ndis_convert_res(arg)
* in order to fix this, we have to create our own
* temporary list with the entries in reverse order.
*/
+
SLIST_FOREACH(brle, brl, link) {
n = malloc(sizeof(struct resource_list_entry),
M_TEMP, M_NOWAIT);
@@ -1180,6 +838,8 @@ ndis_set_info(arg, oid, buf, buflen)
sc = arg;
+ mtx_lock(&ndis_req_mtx);
+
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
if (sc->ndis_block->nmb_pendingreq != NULL)
@@ -1193,6 +853,7 @@ ndis_set_info(arg, oid, buf, buflen)
if (adapter == NULL || setfunc == NULL) {
sc->ndis_block->nmb_pendingreq = NULL;
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ mtx_unlock(&ndis_req_mtx);
return(ENXIO);
}
@@ -1204,13 +865,13 @@ ndis_set_info(arg, oid, buf, buflen)
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
if (rval == NDIS_STATUS_PENDING) {
- mtx_lock(&ndis_req_mtx);
error = msleep(&sc->ndis_block->nmb_setstat,
&ndis_req_mtx,
curthread->td_priority|PDROP,
"ndisset", 5 * hz);
rval = sc->ndis_block->nmb_setstat;
- }
+ } else
+ mtx_unlock(&ndis_req_mtx);
if (byteswritten)
@@ -1396,6 +1057,8 @@ ndis_reset_nic(arg)
if (adapter == NULL || resetfunc == NULL)
return(EIO);
+ mtx_lock(&ndis_req_mtx);
+
if (NDIS_SERIALIZED(sc->ndis_block))
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
@@ -1405,14 +1068,16 @@ ndis_reset_nic(arg)
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
if (rval == NDIS_STATUS_PENDING) {
- mtx_lock(&ndis_req_mtx);
msleep(sc, &ndis_req_mtx,
curthread->td_priority|PDROP, "ndisrst", 0);
- }
+ } else
+ mtx_unlock(&ndis_req_mtx);
return(0);
}
+#define NDIS_REAP_TIMERS
+
int
ndis_halt_nic(arg)
void *arg;
@@ -1421,6 +1086,10 @@ ndis_halt_nic(arg)
ndis_handle adapter;
ndis_halt_handler haltfunc;
struct ifnet *ifp;
+#ifdef NDIS_REAP_TIMERS
+ ndis_miniport_timer *t, *n;
+ uint8_t irql;
+#endif
sc = arg;
ifp = &sc->arpcom.ac_if;
@@ -1432,6 +1101,28 @@ ndis_halt_nic(arg)
return(EIO);
}
+#ifdef NDIS_REAP_TIMERS
+ /*
+ * Drivers are sometimes very lax about cancelling all
+ * their timers. Cancel them all ourselves, just to be
+ * safe. We must do this before invoking MiniportHalt(),
+ * since if we wait until after, the memory in which
+ * the timers reside will no longer be valid.
+ */
+
+ KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
+ t = sc->ndis_block->nmb_timerlist;
+ while (t != NULL) {
+ KeCancelTimer(&t->nmt_ktimer);
+ n = t;
+ t = t->nmt_nexttimer;
+ n->nmt_nexttimer = NULL;
+ }
+ sc->ndis_block->nmb_timerlist = NULL;
+ KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ KeFlushQueuedDpcs();
+#endif
+
/*
* The adapter context is only valid after the init
* handler has been called, and is invalid once the
@@ -1441,7 +1132,9 @@ ndis_halt_nic(arg)
haltfunc = sc->ndis_chars->nmc_halt_func;
NDIS_UNLOCK(sc);
+ mtx_lock(&ndis_req_mtx);
MSCALL1(haltfunc, adapter);
+ mtx_unlock(&ndis_req_mtx);
NDIS_LOCK(sc);
sc->ndis_block->nmb_miniportadapterctx = NULL;
@@ -1471,7 +1164,6 @@ ndis_shutdown_nic(arg)
else
MSCALL1(shutdownfunc, sc->ndis_chars->nmc_rsvd0);
- ndis_shrink_thrqueue(8);
TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
return(0);
@@ -1497,11 +1189,15 @@ ndis_init_nic(arg)
initfunc = sc->ndis_chars->nmc_init_func;
NDIS_UNLOCK(sc);
+ sc->ndis_block->nmb_timerlist = NULL;
+
for (i = 0; i < NdisMediumMax; i++)
mediumarray[i] = i;
+ mtx_lock(&ndis_req_mtx);
status = MSCALL6(initfunc, &openstatus, &chosenmedium,
mediumarray, NdisMediumMax, block, block);
+ mtx_unlock(&ndis_req_mtx);
/*
* If the init fails, blow away the other exported routines
@@ -1515,6 +1211,18 @@ ndis_init_nic(arg)
return(ENXIO);
}
+ /*
+ * This may look really goofy, but apparently it is possible
+ * to halt a miniport too soon after it's been initialized.
+ * After MiniportInitialize() finishes, pause for 1 second
+ * to give the chip a chance to handle any short-lived timers
+ * that were set in motion. If we call MiniportHalt() too soon,
+ * some of the timers may not be cancelled, because the driver
+ * expects them to fire before the halt is called.
+ */
+
+ ndis_thsuspend(curthread->td_proc, NULL, hz);
+
return(0);
}
@@ -1630,8 +1338,9 @@ ndis_get_info(arg, oid, buf, buflen)
uint32_t byteswritten = 0, bytesneeded = 0;
int error;
uint8_t irql;
-
+
sc = arg;
+ mtx_lock(&ndis_req_mtx);
KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
if (sc->ndis_block->nmb_pendingreq != NULL)
@@ -1645,6 +1354,7 @@ ndis_get_info(arg, oid, buf, buflen)
if (adapter == NULL || queryfunc == NULL) {
sc->ndis_block->nmb_pendingreq = NULL;
KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
+ mtx_unlock(&ndis_req_mtx);
return(ENXIO);
}
@@ -1658,13 +1368,13 @@ ndis_get_info(arg, oid, buf, buflen)
/* Wait for requests that block. */
if (rval == NDIS_STATUS_PENDING) {
- mtx_lock(&ndis_req_mtx);
error = msleep(&sc->ndis_block->nmb_getstat,
&ndis_req_mtx,
curthread->td_priority|PDROP,
"ndisget", 5 * hz);
rval = sc->ndis_block->nmb_getstat;
- }
+ } else
+ mtx_unlock(&ndis_req_mtx);
if (byteswritten)
*buflen = byteswritten;
@@ -1719,7 +1429,9 @@ NdisAddDevice(drv, pdo)
sc->ndis_block = block;
sc->ndis_chars = IoGetDriverObjectExtension(drv, (void *)1);
+ /* Give interrupt handling priority over timers. */
IoInitializeDpcRequest(fdo, kernndis_functbl[6].ipt_wrap);
+ KeSetImportanceDpc(&fdo->do_dpc, KDPC_IMPORTANCE_HIGH);
/* Finish up BSD-specific setup. */
@@ -1732,8 +1444,6 @@ NdisAddDevice(drv, pdo)
block->nmb_sendrsrc_func = kernndis_functbl[5].ipt_wrap;
block->nmb_pendingreq = NULL;
- ndis_enlarge_thrqueue(8);
-
TAILQ_INSERT_TAIL(&ndis_devhead, block, link);
return (STATUS_SUCCESS);
@@ -1753,7 +1463,6 @@ ndis_unload_driver(arg)
ndis_flush_sysctls(sc);
- ndis_shrink_thrqueue(8);
TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
fdo = sc->ndis_block->nmb_deviceobj;
OpenPOWER on IntegriCloud