summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2005-11-02 18:01:04 +0000
committerwpaul <wpaul@FreeBSD.org>2005-11-02 18:01:04 +0000
commitc104267c1a97cafb9b2e7707382601a452ced831 (patch)
tree2f760970c94cf94b930470434ca4054a9ae096c5 /sys/compat
parentb53d0a6c803e7602549b842ef5a0491dfb45d5a1 (diff)
downloadFreeBSD-src-c104267c1a97cafb9b2e7707382601a452ced831.zip
FreeBSD-src-c104267c1a97cafb9b2e7707382601a452ced831.tar.gz
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().
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/ndis/kern_ndis.c70
-rw-r--r--sys/compat/ndis/kern_windrv.c9
-rw-r--r--sys/compat/ndis/ndis_var.h3
-rw-r--r--sys/compat/ndis/subr_ndis.c39
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c22
-rw-r--r--sys/compat/ndis/winx32_wrap.S8
6 files changed, 55 insertions, 96 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index 8baa011..98f49cf 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -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;
diff --git a/sys/compat/ndis/kern_windrv.c b/sys/compat/ndis/kern_windrv.c
index 9202911..79ec7395 100644
--- a/sys/compat/ndis/kern_windrv.c
+++ b/sys/compat/ndis/kern_windrv.c
@@ -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. */
diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h
index 6f3772d..99baa18 100644
--- a/sys/compat/ndis/ndis_var.h
+++ b/sys/compat/ndis/ndis_var.h
@@ -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 *);
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index eb2ae66..f2e1dc3 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -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,
diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
index 143c1bc..d3500b9 100644
--- a/sys/compat/ndis/subr_ntoskrnl.c
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -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);
}
/*
diff --git a/sys/compat/ndis/winx32_wrap.S b/sys/compat/ndis/winx32_wrap.S
index f5d24ba..9a6b3cd 100644
--- a/sys/compat/ndis/winx32_wrap.S
+++ b/sys/compat/ndis/winx32_wrap.S
@@ -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
OpenPOWER on IntegriCloud