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:
parent
c4dd6db19b
commit
eaecffb942
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user