diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-03-10 07:43:11 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-03-10 07:43:11 +0000 |
commit | dab75fac6b16faec6e60df4a6fcd6a2e2cdd4515 (patch) | |
tree | 6b864ba874e12e8ab8127bbc74071c49356f74c3 /sys | |
parent | cd800560cfd64f550b1a4e6b03b9441aba0b4d24 (diff) | |
download | FreeBSD-src-dab75fac6b16faec6e60df4a6fcd6a2e2cdd4515.zip FreeBSD-src-dab75fac6b16faec6e60df4a6fcd6a2e2cdd4515.tar.gz |
Fix several issues related to the KeInitializeTimer() etc... API stuff
that I added recently:
- When a periodic timer fires, it's automatically re-armed. We must
make sure to re-arm the timer _before_ invoking any caller-supplied
defered procedure call: the DPC may choose to call KeCancelTimer(),
and re-arming the timer after the DPC un-does the effect of the
cancel.
- Fix similar issue with periodic timers in subr_ndis.c.
- When calling KeSetTimer() or KeSetTimerEx(), if the timer is
already pending, untimeout() it first before timeout()ing
it again.
- The old Atheros driver for the 5211 seems to use KeSetTimerEx()
incorrectly, or at the very least in a very strange way that
doesn't quite follow the Microsoft documentation. In one case,
it calls KeSetTimerEx() with a duetime of 0 and a period of 5000.
The Microsoft documentation says that negative duetime values
are relative to the current time and positive values are absolute.
But it doesn't say what's supposed to happen with positive values
that less than the current time, i.e. absolute values that are
in the past.
Lacking any further information, I have decided that timers with
positive duetimes that are in the past should fire right away (or
in our case, after only 1 tick). This also takes care of the other
strange usage in the Atheros driver, where the duetime is
specified as 500000 and the period is 50. I think someone may
have meant to use -500000 and misinterpreted the documentation.
- Also modified KeWaitForSingleObject() and KeWaitForMultipleObjects()
to make the same duetime adjustment, since they have the same rules
regarding timeout values.
- Cosmetic: change name of 'timeout' variable in KeWaitForSingleObject()
and KeWaitForMultipleObjects() to 'duetime' to avoid senseless
(though harmless) overlap with timeout() function name.
With these fixes, I can get the 5211 card to associate properly with
my adhoc net using driver AR5211.SYS version 2.4.1.6.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 8 | ||||
-rw-r--r-- | sys/compat/ndis/subr_ntoskrnl.c | 87 |
2 files changed, 56 insertions, 39 deletions
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index df6a39a..80f5180 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -1045,10 +1045,6 @@ ndis_tick(arg) timer = arg; - timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc; - timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL); - ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header); - /* Automatically reload timer. */ tv.tv_sec = 0; @@ -1058,6 +1054,10 @@ ndis_tick(arg) timer->nmt_dpc.nk_sysarg2 = ndis_tick; callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); + timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc; + timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL); + ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header); + return; } diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index 556de35..cb7de09 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -431,12 +431,12 @@ ntoskrnl_time(tval) */ __stdcall static uint32_t -ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout) +ntoskrnl_waitforobj(obj, reason, mode, alertable, duetime) nt_dispatch_header *obj; uint32_t reason; uint32_t mode; uint8_t alertable; - int64_t *timeout; + int64_t *duetime; { struct thread *td = curthread; kmutant *km; @@ -485,22 +485,26 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout) /* * The timeout value is specified in 100 nanosecond units * and can be a positive or negative number. If it's positive, - * then the timeout is absolute, and we need to convert it + * then the duetime is absolute, and we need to convert it * to an absolute offset relative to now in order to use it. - * If it's negative, then the timeout is relative and we + * If it's negative, then the duetime is relative and we * just have to convert the units. */ - if (timeout != NULL) { - if (*timeout < 0) { - tv.tv_sec = - (*timeout) / 10000000 ; - tv.tv_usec = (- (*timeout) / 10) - + if (duetime != NULL) { + if (*duetime < 0) { + tv.tv_sec = - (*duetime) / 10000000; + tv.tv_usec = (- (*duetime) / 10) - (tv.tv_sec * 1000000); } else { ntoskrnl_time(&curtime); - tv.tv_sec = ((*timeout) - curtime) / 10000000 ; - tv.tv_usec = ((*timeout) - curtime) / 10 - - (tv.tv_sec * 1000000); + if (*duetime < curtime) + tv.tv_sec = tv.tv_usec = 0; + else { + tv.tv_sec = ((*duetime) - curtime) / 10000000; + tv.tv_usec = ((*duetime) - curtime) / 10 - + (tv.tv_sec * 1000000); + } } } @@ -508,10 +512,10 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout) if (td->td_proc->p_flag & P_KTHREAD) error = kthread_suspend(td->td_proc, - timeout == NULL ? 0 : tvtohz(&tv)); + duetime == NULL ? 0 : tvtohz(&tv)); else error = tsleep(td, PPAUSE|PDROP, "ndisws", - timeout == NULL ? 0 : tvtohz(&tv)); + duetime == NULL ? 0 : tvtohz(&tv)); mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock); @@ -549,14 +553,14 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout) __stdcall static uint32_t ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode, - alertable, timeout, wb_array) + alertable, duetime, wb_array) uint32_t cnt; nt_dispatch_header *obj[]; uint32_t wtype; uint32_t reason; uint32_t mode; uint8_t alertable; - int64_t *timeout; + int64_t *duetime; wait_block *wb_array; { struct thread *td = curthread; @@ -622,16 +626,20 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode, wcnt++; } - if (timeout != NULL) { - if (*timeout < 0) { - tv.tv_sec = - (*timeout) / 10000000 ; - tv.tv_usec = (- (*timeout) / 10) - + if (duetime != NULL) { + if (*duetime < 0) { + tv.tv_sec = - (*duetime) / 10000000; + tv.tv_usec = (- (*duetime) / 10) - (tv.tv_sec * 1000000); } else { ntoskrnl_time(&curtime); - tv.tv_sec = ((*timeout) - curtime) / 10000000 ; - tv.tv_usec = ((*timeout) - curtime) / 10 - - (tv.tv_sec * 1000000); + if (*duetime < curtime) + tv.tv_sec = tv.tv_usec = 0; + else { + tv.tv_sec = ((*duetime) - curtime) / 10000000; + tv.tv_usec = ((*duetime) - curtime) / 10 - + (tv.tv_sec * 1000000); + } } } @@ -641,10 +649,10 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode, if (td->td_proc->p_flag & P_KTHREAD) error = kthread_suspend(td->td_proc, - timeout == NULL ? 0 : tvtohz(&tv)); + duetime == NULL ? 0 : tvtohz(&tv)); else error = tsleep(td, PPAUSE|PDROP, "ndisws", - timeout == NULL ? 0 : tvtohz(&tv)); + duetime == NULL ? 0 : tvtohz(&tv)); mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock); nanotime(&t2); @@ -670,7 +678,7 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode, if (error || wtype == WAITTYPE_ANY) break; - if (timeout != NULL) { + if (duetime != NULL) { tv.tv_sec -= (t2.tv_sec - t1.tv_sec); tv.tv_usec -= (t2.tv_nsec - t1.tv_nsec) / 1000; } @@ -1658,10 +1666,6 @@ ntoskrnl_timercall(arg) timer = arg; dpc = timer->k_dpc; - timerfunc = (kdpc_func)dpc->k_deferedfunc; - timerfunc(dpc, dpc->k_deferredctx, dpc->k_sysarg1, dpc->k_sysarg2); - - ntoskrnl_wakeup(&timer->k_header); /* * If this is a periodic timer, re-arm it @@ -1675,6 +1679,14 @@ ntoskrnl_timercall(arg) timeout(ntoskrnl_timercall, timer, tvtohz(&tv)); } + if (dpc != NULL) { + timerfunc = (kdpc_func)dpc->k_deferedfunc; + timerfunc(dpc, dpc->k_deferredctx, + dpc->k_sysarg1, dpc->k_sysarg2); + } + + ntoskrnl_wakeup(&timer->k_header); + return; } @@ -1741,9 +1753,10 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc) return(FALSE); if (timer->k_handle.callout != NULL && - callout_pending(timer->k_handle.callout)) + callout_pending(timer->k_handle.callout)) { + untimeout(ntoskrnl_timercall, timer, timer->k_handle); pending = TRUE; - else + } else pending = FALSE; timer->k_duetime = duetime; @@ -1752,14 +1765,18 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc) timer->k_dpc = dpc; if (duetime < 0) { - tv.tv_sec = - (duetime) / 10000000 ; + tv.tv_sec = - (duetime) / 10000000; tv.tv_usec = (- (duetime) / 10) - (tv.tv_sec * 1000000); } else { ntoskrnl_time(&curtime); - tv.tv_sec = ((duetime) - curtime) / 10000000 ; - tv.tv_usec = ((duetime) - curtime) / 10 - - (tv.tv_sec * 1000000); + if (duetime < curtime) + tv.tv_sec = tv.tv_usec = 0; + else { + tv.tv_sec = ((duetime) - curtime) / 10000000; + tv.tv_usec = ((duetime) - curtime) / 10 - + (tv.tv_sec * 1000000); + } } timer->k_handle = timeout(ntoskrnl_timercall, timer, tvtohz(&tv)); |