Tests with my dual Opteron system have shown that it's possible

for code to start out on one CPU when thunking into Windows
mode in ctxsw_utow(), and then be pre-empted and migrated to another
CPU before thunking back to UNIX mode in ctxsw_wtou(). This is
bad, because then we can end up looking at the wrong 'thread environment
block' when trying to come back to UNIX mode. To avoid this, we now
pin ourselves to the current CPU when thunking into Windows code.

Few other cleanups, since I'm here:

- Get rid of the ndis_isr(), ndis_enable_interrupt() and
  ndis_disable_interrupt() wrappers from kern_ndis.c and just invoke
  the miniport's methods directly in the interrupt handling routines
  in subr_ndis.c. We may as well lose the function call overhead,
  since we don't need to export these things outside of ndis.ko
  now anyway.

- Remove call to ndis_enable_interrupt() from ndis_init() in if_ndis.c.
  We don't need to do it there anyway (the miniport init routine handles
  it, if needed).

- Fix the logic in NdisWriteErrorLogEntry() a little.

- Change some NDIS_STATUS_xxx codes in subr_ntoskrnl.c into STATUS_xxx
  codes.

- Handle kthread_create() failure correctly in PsCreateSystemThread().
This commit is contained in:
Bill Paul 2005-11-02 18:01:04 +00:00
parent 56a4e45ab3
commit a91395a9d0
7 changed files with 55 additions and 99 deletions

View File

@ -717,7 +717,11 @@ ndis_ptom(m0, p)
for (buf = priv->npp_head; buf != NULL; buf = buf->mdl_next) {
if (buf == priv->npp_head)
#ifdef MT_HEADER
MGETHDR(m, M_DONTWAIT, MT_HEADER);
#else
MGETHDR(m, M_DONTWAIT, MT_DATA);
#endif
else
MGET(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
@ -1250,72 +1254,6 @@ ndis_init_nic(arg)
return(0);
}
void
ndis_enable_intr(arg)
void *arg;
{
struct ndis_softc *sc;
ndis_handle adapter;
ndis_enable_interrupts_handler intrenbfunc;
sc = arg;
adapter = sc->ndis_block->nmb_miniportadapterctx;
intrenbfunc = sc->ndis_chars->nmc_enable_interrupts_func;
if (adapter == NULL || intrenbfunc == NULL)
return;
MSCALL1(intrenbfunc, adapter);
return;
}
void
ndis_disable_intr(arg)
void *arg;
{
struct ndis_softc *sc;
ndis_handle adapter;
ndis_disable_interrupts_handler intrdisfunc;
sc = arg;
adapter = sc->ndis_block->nmb_miniportadapterctx;
intrdisfunc = sc->ndis_chars->nmc_disable_interrupts_func;
if (adapter == NULL || intrdisfunc == NULL)
return;
MSCALL1(intrdisfunc, adapter);
return;
}
int
ndis_isr(arg, ourintr, callhandler)
void *arg;
int *ourintr;
int *callhandler;
{
struct ndis_softc *sc;
ndis_handle adapter;
ndis_isr_handler isrfunc;
uint8_t accepted, queue;
if (arg == NULL || ourintr == NULL || callhandler == NULL)
return(EINVAL);
sc = arg;
adapter = sc->ndis_block->nmb_miniportadapterctx;
isrfunc = sc->ndis_chars->nmc_isr_func;
if (adapter == NULL || isrfunc == NULL)
return(ENXIO);
MSCALL3(isrfunc, &accepted, &queue, adapter);
*ourintr = accepted;
*callhandler = queue;
return(0);
}
static void
ndis_intrsetup(dpc, dobj, ip, sc)
kdpc *dpc;

View File

@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$");
#include <compat/ndis/hal_var.h>
#include <compat/ndis/usbd_var.h>
struct mtx drvdb_mtx;
static struct mtx drvdb_mtx;
static STAILQ_HEAD(drvdb, drvdb_ent) drvdb_head;
static driver_object fake_pci_driver; /* serves both PCI and cardbus */
@ -680,10 +680,12 @@ ctxsw_utow(void)
if (t->tid_self != t)
x86_newldt(NULL);
x86_critical_enter();
t->tid_oldfs = x86_getfs();
t->tid_cpu = curthread->td_oncpu;
sched_pin();
x86_setfs(SEL_TO_FS(t->tid_selector));
x86_critical_exit();
/* Now entering Windows land, population: you. */
@ -701,8 +703,11 @@ ctxsw_wtou(void)
{
struct tid *t;
x86_critical_enter();
t = x86_gettid();
x86_setfs(t->tid_oldfs);
sched_unpin();
x86_critical_exit();
/* Welcome back to UNIX land, we missed you. */

View File

@ -1740,10 +1740,7 @@ extern int ndis_reset_nic(void *);
extern int ndis_halt_nic(void *);
extern int ndis_shutdown_nic(void *);
extern int ndis_init_nic(void *);
extern int ndis_isr(void *, int *, int *);
extern void ndis_return_packet(void *, void *);
extern void ndis_enable_intr(void *);
extern void ndis_disable_intr(void *);
extern int ndis_init_dma(void *);
extern int ndis_destroy_dma(void *);
extern int ndis_create_sysctls(void *);

View File

@ -1064,16 +1064,20 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
sc = device_get_softc(dev);
ifp = sc->ifp;
error = pe_get_message((vm_offset_t)drv->dro_driverstart,
code, &str, &i, &flags);
if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE &&
ifp->if_flags & IFF_DEBUG) {
RtlInitUnicodeString(&us, (uint16_t *)str);
if (RtlUnicodeStringToAnsiString(&as, &us, TRUE))
return;
str = as.as_buf;
} else
str = NULL;
if (ifp->if_flags & IFF_DEBUG) {
error = pe_get_message((vm_offset_t)drv->dro_driverstart,
code, &str, &i, &flags);
if (error == 0) {
if (flags & MESSAGE_RESOURCE_UNICODE) {
RtlInitUnicodeString(&us, (uint16_t *)str);
if (RtlUnicodeStringToAnsiString(&as,
&us, TRUE) == STATUS_SUCCESS)
str = as.as_buf;
else
str = NULL;
}
}
}
device_printf (dev, "NDIS ERROR: %x (%s)\n", code,
str == NULL ? "unknown error" : str);
@ -2335,9 +2339,11 @@ ndis_intr(arg)
return;
if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE)
ndis_isr(sc, &is_our_intr, &call_isr);
MSCALL3(intr->ni_isrfunc, &is_our_intr, &call_isr,
sc->ndis_block->nmb_miniportadapterctx);
else {
ndis_disable_intr(sc);
MSCALL1(sc->ndis_chars->nmc_disable_interrupts_func,
sc->ndis_block->nmb_miniportadapterctx);
call_isr = 1;
}
@ -2365,11 +2371,12 @@ ndis_intrhand(dpc, intr, sysarg1, sysarg2)
if (NDIS_SERIALIZED(sc->ndis_block))
KeAcquireSpinLockAtDpcLevel(&block->nmb_lock);
MSCALL1(intr->ni_isrfunc, adapter);
MSCALL1(intr->ni_dpcfunc, adapter);
/* If there's a MiniportEnableInterrupt() routine, call it. */
ndis_enable_intr(sc);
if (sc->ndis_chars->nmc_enable_interrupts_func != NULL)
MSCALL1(sc->ndis_chars->nmc_enable_interrupts_func, adapter);
if (NDIS_SERIALIZED(sc->ndis_block))
KeReleaseSpinLockFromDpcLevel(&block->nmb_lock);
@ -2417,8 +2424,8 @@ NdisMRegisterInterrupt(intr, adapter, ivec, ilevel, reqisr, shared, imode)
intr->ni_isrreq = reqisr;
intr->ni_shared = shared;
intr->ni_dpccnt = 0;
intr->ni_isrfunc = ch->nmc_interrupt_func;
intr->ni_dpcfunc = ch->nmc_isr_func;
intr->ni_isrfunc = ch->nmc_isr_func;
intr->ni_dpcfunc = ch->nmc_interrupt_func;
KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE);
KeInitializeDpc(&intr->ni_dpc,

View File

@ -533,8 +533,7 @@ RtlUnicodeStringToAnsiString(dest, src, allocate)
uint8_t allocate;
{
if (dest == NULL || src == NULL)
return(NDIS_STATUS_FAILURE);
return(STATUS_INVALID_PARAMETER);
dest->as_len = src->us_len / 2;
if (dest->as_maxlen < dest->as_len)
@ -565,7 +564,7 @@ RtlAnsiStringToUnicodeString(dest, src, allocate)
uint8_t allocate;
{
if (dest == NULL || src == NULL)
return(NDIS_STATUS_FAILURE);
return(STATUS_INVALID_PARAMETER);
if (allocate == TRUE) {
dest->us_buf = ExAllocatePoolWithTag(NonPagedPool,
@ -3012,7 +3011,7 @@ RtlUnicodeStringToInteger(ustr, base, val)
ntoskrnl_unicode_to_ascii(uchr, astr, len);
*val = strtoul(abuf, NULL, base);
return(NDIS_STATUS_SUCCESS);
return(STATUS_SUCCESS);
}
void
@ -3303,7 +3302,7 @@ ObReferenceObjectByHandle(handle, reqaccess, otype,
nr = malloc(sizeof(nt_objref), M_DEVBUF, M_NOWAIT|M_ZERO);
if (nr == NULL)
return(NDIS_STATUS_FAILURE);
return(STATUS_INSUFFICIENT_RESOURCES);
InitializeListHead((&nr->no_dh.dh_waitlisthead));
nr->no_obj = handle;
@ -3314,7 +3313,7 @@ ObReferenceObjectByHandle(handle, reqaccess, otype,
TAILQ_INSERT_TAIL(&ntoskrnl_reflist, nr, link);
*object = nr;
return(NDIS_STATUS_SUCCESS);
return(STATUS_SUCCESS);
}
static void
@ -3379,7 +3378,7 @@ PsCreateSystemThread(handle, reqaccess, objattrs, phandle,
tc = malloc(sizeof(thread_context), M_TEMP, M_NOWAIT);
if (tc == NULL)
return(NDIS_STATUS_FAILURE);
return(STATUS_INSUFFICIENT_RESOURCES);
tc->tc_thrctx = thrctx;
tc->tc_thrfunc = thrfunc;
@ -3387,11 +3386,16 @@ PsCreateSystemThread(handle, reqaccess, objattrs, phandle,
sprintf(tname, "windows kthread %d", ntoskrnl_kth);
error = kthread_create(ntoskrnl_thrfunc, tc, &p,
RFHIGHPID, NDIS_KSTACK_PAGES, tname);
*handle = p;
if (error) {
free(tc, M_TEMP);
return(STATUS_INSUFFICIENT_RESOURCES);
}
*handle = p;
ntoskrnl_kth++;
return(error);
return(STATUS_SUCCESS);
}
/*

View File

@ -370,3 +370,11 @@ ENTRY(x86_setfs)
ENTRY(x86_gettid)
mov %fs:12,%eax
ret
ENTRY(x86_critical_enter)
cli
ret
ENTRY(x86_critical_exit)
sti
ret

View File

@ -1914,9 +1914,6 @@ ndis_init(xsc)
/* Setup task offload. */
ndis_set_offload(sc);
/* Enable interrupts. */
ndis_enable_intr(sc);
if (sc->ndis_80211)
ndis_setstate_80211(sc);