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.
This commit is contained in:
Bill Paul 2004-02-16 02:50:03 +00:00
parent c4dd6db19b
commit eaecffb942
3 changed files with 80 additions and 22 deletions

View File

@ -150,7 +150,7 @@ typedef struct list_entry list_entry;
list_entry *b; \ list_entry *b; \
\ \
b = l->nle_blink; \ b = l->nle_blink; \
e->nle_flink = l \ e->nle_flink = l; \
e->nle_blink = b; \ e->nle_blink = b; \
b->nle_flink = e; \ b->nle_flink = e; \
l->nle_blink = e; \ l->nle_blink = e; \
@ -265,6 +265,8 @@ struct kmutant {
typedef struct kmutant kmutant; typedef struct kmutant kmutant;
#define LOOKASIDE_DEPTH 256
struct general_lookaside { struct general_lookaside {
slist_header gl_listhead; slist_header gl_listhead;
uint16_t gl_depth; uint16_t gl_depth;

View File

@ -1961,7 +1961,7 @@ ndis_wait_event(event, msecs)
return(TRUE); 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)); (&w.wb_waitlist));
tv.tv_sec = 0; tv.tv_sec = 0;

View File

@ -108,6 +108,8 @@ __regparm static uint64_t _aullshr(uint64_t, uint8_t);
__regparm static uint64_t _aullshl(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_allocfunc(uint32_t, size_t, uint32_t);
__stdcall static void ntoskrnl_freefunc(void *); __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 *, __stdcall static void ntoskrnl_init_lookaside(paged_lookaside_list *,
lookaside_alloc_func *, lookaside_free_func *, lookaside_alloc_func *, lookaside_free_func *,
uint32_t, size_t, uint32_t, uint16_t); 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 *, lookaside_alloc_func *, lookaside_free_func *,
uint32_t, size_t, uint32_t, uint16_t); uint32_t, size_t, uint32_t, uint16_t);
__stdcall static void ntoskrnl_delete_nplookaside(npaged_lookaside_list *); __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); slist_entry * */ void);
__stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_entry * */ void); __stdcall static slist_entry *ntoskrnl_pop_slist(/*slist_header * */ void);
__stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_entry *, __stdcall static slist_entry *ntoskrnl_push_slist_ex(/*slist_header *,
slist_entry *,*/ kspin_lock *); 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); kspin_lock * */void);
__stdcall static void ntoskrnl_lock_dpc(/*kspin_lock * */ void); __stdcall static void ntoskrnl_lock_dpc(/*kspin_lock * */ void);
__stdcall static void ntoskrnl_unlock_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_object = obj;
w.wb_kthread = td; 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 * 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++) { for (i = 0; i < cnt; i++) {
if (obj[i]->dh_sigstate == TRUE) if (obj[i]->dh_sigstate == TRUE)
continue; continue;
INSERT_LIST_HEAD((&obj[i]->dh_waitlisthead), INSERT_LIST_TAIL((&obj[i]->dh_waitlisthead),
(&w[i].wb_waitlist)); (&w[i].wb_waitlist));
w[i].wb_kthread = td; w[i].wb_kthread = td;
w[i].wb_object = obj[i]; w[i].wb_object = obj[i];
@ -628,7 +630,7 @@ ntoskrnl_waitforobjs(cnt, obj, wtype, reason, mode,
error = kthread_suspend(td->td_proc, error = kthread_suspend(td->td_proc,
timeout == NULL ? 0 : tvtohz(&tv)); timeout == NULL ? 0 : tvtohz(&tv));
else else
error = tsleep(td, PPAUSE|PCATCH, "ndisws", error = tsleep(td, PPAUSE|PDROP, "ndisws",
timeout == NULL ? 0 : tvtohz(&tv)); timeout == NULL ? 0 : tvtohz(&tv));
mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock); mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock);
@ -809,6 +811,38 @@ _aullshr(a, b)
return (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 * __stdcall static void *
ntoskrnl_allocfunc(pooltype, size, tag) ntoskrnl_allocfunc(pooltype, size, tag)
uint32_t pooltype; uint32_t pooltype;
@ -823,6 +857,7 @@ ntoskrnl_freefunc(buf)
void *buf; void *buf;
{ {
free(buf, M_DEVBUF); free(buf, M_DEVBUF);
return;
} }
__stdcall static void __stdcall static void
@ -853,6 +888,9 @@ ntoskrnl_init_lookaside(lookaside, allocfunc, freefunc,
mtx = mtx_pool_alloc(ndis_mtxpool); mtx = mtx_pool_alloc(ndis_mtxpool);
lookaside->nll_obsoletelock = (kspin_lock)mtx; lookaside->nll_obsoletelock = (kspin_lock)mtx;
lookaside->nll_l.gl_depth = LOOKASIDE_DEPTH;
lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH;
return; return;
} }
@ -860,6 +898,13 @@ __stdcall static void
ntoskrnl_delete_lookaside(lookaside) ntoskrnl_delete_lookaside(lookaside)
paged_lookaside_list *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; return;
} }
@ -876,7 +921,12 @@ ntoskrnl_init_nplookaside(lookaside, allocfunc, freefunc,
{ {
struct mtx *mtx; 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; lookaside->nll_l.gl_tag = tag;
if (allocfunc == NULL) if (allocfunc == NULL)
lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc; lookaside->nll_l.gl_allocfunc = ntoskrnl_allocfunc;
@ -891,6 +941,9 @@ ntoskrnl_init_nplookaside(lookaside, allocfunc, freefunc,
mtx = mtx_pool_alloc(ndis_mtxpool); mtx = mtx_pool_alloc(ndis_mtxpool);
lookaside->nll_obsoletelock = (kspin_lock)mtx; lookaside->nll_obsoletelock = (kspin_lock)mtx;
lookaside->nll_l.gl_depth = LOOKASIDE_DEPTH;
lookaside->nll_l.gl_maxdepth = LOOKASIDE_DEPTH;
return; return;
} }
@ -898,6 +951,13 @@ __stdcall static void
ntoskrnl_delete_nplookaside(lookaside) ntoskrnl_delete_nplookaside(lookaside)
npaged_lookaside_list *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; return;
} }
@ -919,10 +979,9 @@ ntoskrnl_push_slist(/*head, entry*/ void)
__asm__ __volatile__ ("" : "=c" (head), "=d" (entry)); __asm__ __volatile__ ("" : "=c" (head), "=d" (entry));
mtx_pool_lock(ndis_mtxpool, ntoskrnl_interlock); mtx_pool_lock(ndis_mtxpool, ntoskrnl_interlock);
oldhead = head->slh_list.slh_next; oldhead = ntoskrnl_pushsl(head, entry);
entry->sl_next = head->slh_list.slh_next;
head->slh_list.slh_next = entry;
mtx_pool_unlock(ndis_mtxpool, ntoskrnl_interlock); mtx_pool_unlock(ndis_mtxpool, ntoskrnl_interlock);
return(oldhead); return(oldhead);
} }
@ -935,10 +994,9 @@ ntoskrnl_pop_slist(/*head*/ void)
__asm__ __volatile__ ("" : "=c" (head)); __asm__ __volatile__ ("" : "=c" (head));
mtx_pool_lock(ndis_mtxpool, ntoskrnl_interlock); mtx_pool_lock(ndis_mtxpool, ntoskrnl_interlock);
first = head->slh_list.slh_next; first = ntoskrnl_popsl(head);
if (first != NULL)
head->slh_list.slh_next = first->sl_next;
mtx_pool_unlock(ndis_mtxpool, ntoskrnl_interlock); mtx_pool_unlock(ndis_mtxpool, ntoskrnl_interlock);
return(first); return(first);
} }
@ -953,10 +1011,9 @@ ntoskrnl_push_slist_ex(/*head, entry,*/ lock)
__asm__ __volatile__ ("" : "=c" (head), "=d" (entry)); __asm__ __volatile__ ("" : "=c" (head), "=d" (entry));
mtx_pool_lock(ndis_mtxpool, (struct mtx *)*lock); mtx_pool_lock(ndis_mtxpool, (struct mtx *)*lock);
oldhead = head->slh_list.slh_next; oldhead = ntoskrnl_pushsl(head, entry);
entry->sl_next = head->slh_list.slh_next;
head->slh_list.slh_next = entry;
mtx_pool_unlock(ndis_mtxpool, (struct mtx *)*lock); mtx_pool_unlock(ndis_mtxpool, (struct mtx *)*lock);
return(oldhead); return(oldhead);
} }
@ -970,10 +1027,9 @@ ntoskrnl_pop_slist_ex(/*head, lock*/ void)
__asm__ __volatile__ ("" : "=c" (head), "=d" (lock)); __asm__ __volatile__ ("" : "=c" (head), "=d" (lock));
mtx_pool_lock(ndis_mtxpool, (struct mtx *)*lock); mtx_pool_lock(ndis_mtxpool, (struct mtx *)*lock);
first = head->slh_list.slh_next; first = ntoskrnl_popsl(head);
if (first != NULL)
head->slh_list.slh_next = first->sl_next;
mtx_pool_unlock(ndis_mtxpool, (struct mtx *)*lock); mtx_pool_unlock(ndis_mtxpool, (struct mtx *)*lock);
return(first); return(first);
} }