From eaecffb942bce562198b2eddea16b9225d0da63f Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Mon, 16 Feb 2004 02:50:03 +0000 Subject: [PATCH] More cleanups/fixes for the AMD Am1771 driver: - When adding new waiting threads to the waitlist for an object, use INSERT_LIST_TAIL() instead of INSERT_LIST_HEAD() so that new waiters go at the end of the list instead of the beginning. When we wake up a synchronization object, only the first waiter is awakened, and this needs to be the first thread that actually waited on the object. - Correct missing semicolon in INSERT_LIST_TAIL() macro. - Implement lookaside lists correctly. Note that the Am1771 driver uses lookaside lists to manage shared memory (i.e. DMAable) buffers by specifying its own alloc and free routines. The Microsoft documentation says you should avoid doing this, but apparently this did not deter the developers at AMD from doing it anyway. With these changes (which are the result of two straight days of almost non-stop debugging), I think I finally have the object/thread handling semantics implemented correctly. The Am1771 driver no longer crashes unexpectedly during association or bringing the interface up. --- sys/compat/ndis/ntoskrnl_var.h | 4 +- sys/compat/ndis/subr_ndis.c | 2 +- sys/compat/ndis/subr_ntoskrnl.c | 96 ++++++++++++++++++++++++++------- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index dd7bc9aec8a..3ff4a732ee1 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -150,7 +150,7 @@ typedef struct list_entry list_entry; list_entry *b; \ \ b = l->nle_blink; \ - e->nle_flink = l \ + e->nle_flink = l; \ e->nle_blink = b; \ b->nle_flink = e; \ l->nle_blink = e; \ @@ -265,6 +265,8 @@ struct kmutant { typedef struct kmutant kmutant; +#define LOOKASIDE_DEPTH 256 + struct general_lookaside { slist_header gl_listhead; uint16_t gl_depth; diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index ec61024e47f..5e93f894247 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -1961,7 +1961,7 @@ ndis_wait_event(event, msecs) return(TRUE); } - INSERT_LIST_HEAD((&event->ne_event.nk_header.dh_waitlisthead), + INSERT_LIST_TAIL((&event->ne_event.nk_header.dh_waitlisthead), (&w.wb_waitlist)); tv.tv_sec = 0; diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index f0aa088c0c8..8d187a2fe96 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -108,6 +108,8 @@ __regparm static uint64_t _aullshr(uint64_t, uint8_t); __regparm static uint64_t _aullshl(uint64_t, uint8_t); __stdcall static void *ntoskrnl_allocfunc(uint32_t, size_t, uint32_t); __stdcall static void ntoskrnl_freefunc(void *); +static slist_entry *ntoskrnl_pushsl(slist_header *, slist_entry *); +static slist_entry *ntoskrnl_popsl(slist_header *); __stdcall static void ntoskrnl_init_lookaside(paged_lookaside_list *, lookaside_alloc_func *, lookaside_free_func *, uint32_t, size_t, uint32_t, uint16_t); @@ -116,12 +118,12 @@ __stdcall static void ntoskrnl_init_nplookaside(npaged_lookaside_list *, lookaside_alloc_func *, lookaside_free_func *, uint32_t, size_t, uint32_t, uint16_t); __stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *); -__stdcall static slist_entry *ntoskrnl_push_slist(/*slist_entry *, +__stdcall static slist_entry *ntoskrnl_push_slist(/*slist_header *, slist_entry * */ void); -__stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_entry * */ void); -__stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_entry *, +__stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_header * */ void); +__stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_header *, slist_entry *,*/ kspin_lock *); -__stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_entry *, +__stdcall static slist_entry *ntoskrnl_pop_slist_ex(/*slist_header *, kspin_lock * */void); __stdcall static void ntoskrnl_lock_dpc(/*kspin_lock * */ void); __stdcall static void ntoskrnl_unlock_dpc(/*kspin_lock * */ void); @@ -465,7 +467,7 @@ ntoskrnl_waitforobj(obj, reason, mode, alertable, timeout) w.wb_object = obj; w.wb_kthread = td; - INSERT_LIST_HEAD((&obj->dh_waitlisthead), (&w.wb_waitlist)); + INSERT_LIST_TAIL((&obj->dh_waitlisthead), (&w.wb_waitlist)); /* * The timeout value is specified in 100 nanosecond units @@ -600,7 +602,7 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode, for (i = 0; i < cnt; i++) { if (obj[i]->dh_sigstate == TRUE) continue; - INSERT_LIST_HEAD((&obj[i]->dh_waitlisthead), + INSERT_LIST_TAIL((&obj[i]->dh_waitlisthead), (&w[i].wb_waitlist)); w[i].wb_kthread = td; w[i].wb_object = obj[i]; @@ -628,7 +630,7 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode, error = kthread_suspend(td->td_proc, timeout == NULL ? 0 : tvtohz(&tv)); else - error = tsleep(td, PPAUSE|PCATCH, "ndisws", + error = tsleep(td, PPAUSE|PDROP, "ndisws", timeout == NULL ? 0 : tvtohz(&tv)); mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock); @@ -809,6 +811,38 @@ _aullshr(a, b) return (a >> b); } +static slist_entry * +ntoskrnl_pushsl(head, entry) + slist_header *head; + slist_entry *entry; +{ + slist_entry *oldhead; + + oldhead = head->slh_list.slh_next; + entry->sl_next = head->slh_list.slh_next; + head->slh_list.slh_next = entry; + head->slh_list.slh_depth++; + head->slh_list.slh_seq++; + + return(oldhead); +} + +static slist_entry * +ntoskrnl_popsl(head) + slist_header *head; +{ + slist_entry *first; + + first = head->slh_list.slh_next; + if (first != NULL) { + head->slh_list.slh_next = first->sl_next; + head->slh_list.slh_depth--; + head->slh_list.slh_seq++; + } + + return(first); +} + __stdcall static void * ntoskrnl_allocfunc(pooltype, size, tag) uint32_t pooltype; @@ -823,6 +857,7 @@ ntoskrnl_freefunc(buf) void *buf; { free(buf, M_DEVBUF); + return; } __stdcall static void @@ -853,6 +888,9 @@ ntoskrnl_init_lookaside(lookaside, allocfunc, freefunc, mtx = mtx_pool_alloc(ndis_mtxpool); lookaside->nll_obsoletelock = (kspin_lock)mtx; + lookaside->nll_l.gl_depth = LOOKASIDE_DEPTH; + lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH; + return; } @@ -860,6 +898,13 @@ __stdcall static void ntoskrnl_delete_lookaside(lookaside) paged_lookaside_list *lookaside; { + void *buf; + __stdcall void (*freefunc)(void *); + + freefunc = lookaside->nll_l.gl_freefunc; + while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL) + freefunc(buf); + return; } @@ -876,7 +921,12 @@ ntoskrnl_init_nplookaside(lookaside, allocfunc, freefunc, { struct mtx *mtx; - lookaside->nll_l.gl_size = size; + bzero((char *)lookaside, sizeof(npaged_lookaside_list)); + + if (size < sizeof(slist_entry)) + lookaside->nll_l.gl_size = sizeof(slist_entry); + else + lookaside->nll_l.gl_size = size; lookaside->nll_l.gl_tag = tag; if (allocfunc == NULL) lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc; @@ -891,6 +941,9 @@ ntoskrnl_init_nplookaside(lookaside, allocfunc, freefunc, mtx = mtx_pool_alloc(ndis_mtxpool); lookaside->nll_obsoletelock = (kspin_lock)mtx; + lookaside->nll_l.gl_depth = LOOKASIDE_DEPTH; + lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH; + return; } @@ -898,6 +951,13 @@ __stdcall static void ntoskrnl_delete_nplookaside(lookaside) npaged_lookaside_list *lookaside; { + void *buf; + __stdcall void (*freefunc)(void *); + + freefunc = lookaside->nll_l.gl_freefunc; + while((buf = ntoskrnl_popsl(&lookaside->nll_l.gl_listhead)) != NULL) + freefunc(buf); + return; } @@ -919,10 +979,9 @@ ntoskrnl_push_slist(/*head, entry*/ void) __asm__ __volatile__ ("" : "=c" (head), "=d" (entry)); mtx_pool_lock(ndis_mtxpool, ntoskrnl_interlock); - oldhead = head->slh_list.slh_next; - entry->sl_next = head->slh_list.slh_next; - head->slh_list.slh_next = entry; + oldhead = ntoskrnl_pushsl(head, entry); mtx_pool_unlock(ndis_mtxpool, ntoskrnl_interlock); + return(oldhead); } @@ -935,10 +994,9 @@ ntoskrnl_pop_slist(/*head*/ void) __asm__ __volatile__ ("" : "=c" (head)); mtx_pool_lock(ndis_mtxpool, ntoskrnl_interlock); - first = head->slh_list.slh_next; - if (first != NULL) - head->slh_list.slh_next = first->sl_next; + first = ntoskrnl_popsl(head); mtx_pool_unlock(ndis_mtxpool, ntoskrnl_interlock); + return(first); } @@ -953,10 +1011,9 @@ ntoskrnl_push_slist_ex(/*head, entry,*/ lock) __asm__ __volatile__ ("" : "=c" (head), "=d" (entry)); mtx_pool_lock(ndis_mtxpool, (struct mtx *)*lock); - oldhead = head->slh_list.slh_next; - entry->sl_next = head->slh_list.slh_next; - head->slh_list.slh_next = entry; + oldhead = ntoskrnl_pushsl(head, entry); mtx_pool_unlock(ndis_mtxpool, (struct mtx *)*lock); + return(oldhead); } @@ -970,10 +1027,9 @@ ntoskrnl_pop_slist_ex(/*head, lock*/ void) __asm__ __volatile__ ("" : "=c" (head), "=d" (lock)); mtx_pool_lock(ndis_mtxpool, (struct mtx *)*lock); - first = head->slh_list.slh_next; - if (first != NULL) - head->slh_list.slh_next = first->sl_next; + first = ntoskrnl_popsl(head); mtx_pool_unlock(ndis_mtxpool, (struct mtx *)*lock); + return(first); }