Commit Graph

1023 Commits

Author SHA1 Message Date
wpaul
51b4d0ab71 More fixes for multibus drivers. When calling out to the match
function in if_ndis_pci.c and if_ndis_pccard.c, provide the bustype
too so the stubs can ignore devlists that don't concern them.
2005-05-08 23:19:20 +00:00
wpaul
ebc77ad893 Fix support for Windows drivers that support both PCI and PCMCIA devices at
the same time.

Fix if_ndis_pccard.c so that it sets sc->ndis_dobj and sc->ndis_regvals.

Correct IMPORT_SFUNC() macros for the READ_PORT_BUFFER_xxx() routines,
which take 3 arguments, not 2.

This fixes it so that the Windows driver for my Cisco Aironet 340 PCMCIA
card works again. (Yes, I know the an(4) driver supports this card natively,
but it's the only PCMCIA device I have with a Windows XP driver.)
2005-05-08 23:07:51 +00:00
wpaul
36f8fdfd36 Correct the patch table entries for the 64-bit intrinsic math
routines (_alldiv(), _allmul(), _alludiv(), _aullmul(), etc...)
that use the _stdcall calling convention.

These routines all take two arguments, but the arguments are 64 bits wide.
On the i386 this means they each consume two 32-bit slots on the stack.
Consequently, when we specify the argument count in the IMPORT_SFUNC()
macro, we have to lie and claim there are 4 arguments instead of two.
This will cause the resulting i386 assembly wrapper to push the right
number of longwords onto the stack.

This fixes a crash I discovered with the RealTek 8180 driver, which
uses these routines a lot during initialization.
2005-05-08 09:16:33 +00:00
wpaul
d2ae5c8a71 Cast 64 bit quantity to uintmax_t to print it with %jx. This is
technically a no-op since uintmax_t is uint64_t on all currently
supported architectures, but we should use an explicit cast instead
of depending on this obscure coincidence.
2005-05-05 22:33:06 +00:00
wpaul
819bac8d1e Use %jx instead of %qx to silence compiler warning on amd64. 2005-05-05 15:56:41 +00:00
wpaul
077b71e0fa Avoid sleeping with mutex held in kern_ndis.c.
Remove unused fields from ndis_miniport_block.

Fix a bug in KeFlushQueuedDpcs() (we weren't calculating the kq pointer
correctly).

In if_ndis.c, clear the IFF_RUNNING flag before calling ndis_halt_nic().

Add some guards in kern_ndis.c to avoid letting anyone invoke ndis_get_info()
or ndis_set_info() if the NIC isn't fully initialized. Apparently, mdnsd
will sometimes try to invoke the ndis_ioctl() routine at exactly the
wrong moment (to futz with its multicast filters) when the interface
comes up, and can trigger a crash unless we guard against it.
2005-05-05 06:14:59 +00:00
wpaul
bb2b136388 Remove extranaous free() of ASCII filename from NdisOpenFile().
Oh, one additional change I forgot to mention in the last commit:
NdisOpenFile() was broken in the case for firmware files that were
pre-loaded as modules. When searching for the module in NdisOpenFile(),
we would match against a symbol name, which would contain the string
we were looking for, then save a pointer to the linker file handle.
Later, in NdisMapFile(), we would refer to the filename hung off
this handle when trying to find the starting address symbol. Only
problem is, this filename is different from the embedded symbol
name we're searching for, so the mapping would fail. I found this
problem while testing the AirGo driver, which requires a small
firmware file.
2005-05-05 04:16:13 +00:00
wpaul
e9bace5ba1 This commit makes a bunch of changes, some big, some not so big.
- Remove the old task threads from kern_ndis.c and reimplement them in
  subr_ntoskrnl.c, in order to more properly emulate the Windows DPC
  API. Each CPU gets its own DPC queue/thread, and each queue can
  have low, medium and high importance DPCs. New APIs implemented:
  KeSetTargetProcessorDpc(), KeSetImportanceDpc() and KeFlushQueuedDpcs().
  (This is the biggest change.)

- Fix a bug in NdisMInitializeTimer(): the k_dpc pointer in the
  nmt_timer embedded in the ndis_miniport_timer struct must be set
  to point to the DPC, also embedded in the struct. Failing to do
  this breaks dequeueing of DPCs submitted via timers, and in turn
  breaks cancelling timers.

- Fix a bug in KeCancelTimer(): if the timer is interted in the timer
  queue (i.e. the timeout callback is still pending), we have to both
  untimeout() the timer _and_ call KeRemoveQueueDpc() to nuke the DPC
  that might be pending. Failing to do this breaks cancellation of
  periodic timers, which always appear to be inserted in the timer queue.

- Make use of the nmt_nexttimer field in ndis_miniport_timer: keep a
  queue of pending timers and cancel them all in ndis_halt_nic(), prior
  to calling MiniportHalt(). Also call KeFlushQueuedDpcs() to make sure
  any DPCs queued by the timers have expired.

- Modify NdisMAllocateSharedMemory() and NdisMFreeSharedMemory() to keep
  track of both the virtual and physical addresses of the shared memory
  buffers that get handed out. The AirGo MIMO driver appears to have a bug
  in it: for one of the segments is allocates, it returns the wrong
  virtual address. This would confuse NdisMFreeSharedMemory() and cause
  a crash. Why it doesn't crash Windows too I have no idea (from reading
  the documentation for NdisMFreeSharedMemory(), it appears to be a violation
  of the API).

- Implement strstr(), strchr() and MmIsAddressValid().

- Implement IoAllocateWorkItem(), IoFreeWorkItem(), IoQueueWorkItem() and
  ExQueueWorkItem(). (This is the second biggest change.)

- Make NdisScheduleWorkItem() call ExQueueWorkItem(). (Note that the
  ExQueueWorkItem() API is deprecated by Microsoft, but NDIS still uses
  it, since NdisScheduleWorkItem() is incompatible with the IoXXXWorkItem()
  API.)

- Change if_ndis.c to use the NdisScheduleWorkItem() interface for scheduling
  tasks.

With all these changes and fixes, the AirGo MIMO driver for the Belkin
F5D8010 Pre-N card now works. Special thanks to Paul Robinson
(paul dawt robinson at pwermedia dawt net) for the loan of a card
for testing.
2005-05-05 03:56:09 +00:00
jeff
f869be5c72 - Pass the ISOPEN flag to namei so filesystems will know we're about to
open them or otherwise access the data.
2005-04-27 09:05:19 +00:00
wpaul
b493dd59e2 Throw the switch on the new driver generation/loading mechanism. From
here on in, if_ndis.ko will be pre-built as a module, and can be built
into a static kernel (though it's not part of GENERIC). Drivers are
created using the new ndisgen(8) script, which uses ndiscvt(8) under
the covers, along with a few other tools. The result is a driver module
that can be kldloaded into the kernel.

A driver with foo.inf and foo.sys files will be converted into
foo_sys.ko (and foo_sys.o, for those who want/need to make static
kernels). This module contains all of the necessary info from the
.INF file and the driver binary image, converted into an ELF module.
You can kldload this module (or add it to /boot/loader.conf) to have
it loaded automatically. Any required firmware files can be bundled
into the module as well (or converted/loaded separately).

Also, add a workaround for a problem in NdisMSleep(). During system
bootstrap (cold == 1), msleep() always returns 0 without actually
sleeping. The Intel 2200BG driver uses NdisMSleep() to wait for
the NIC's firmware to come to life, and fails to load if NdisMSleep()
doesn't actually delay. As a workaround, if msleep() (and hence
ndis_thsuspend()) returns 0, use a hard DELAY() to sleep instead).
This is not really the right thing to do, but we can't really do much
else. At the very least, this makes the Intel driver happy.

There are probably other drivers that fail in this way during bootstrap.
Unfortunately, the only workaround for those is to avoid pre-loading
them and kldload them once the system is running instead.
2005-04-24 20:21:22 +00:00
wpaul
637643a433 Now that the GDT has been reorganized and GNDIS_SEL has been reserved
for us, use it if it's available, otherwise default to using slot 7
as before.
2005-04-17 19:36:08 +00:00
wpaul
f2f41f37b1 When setting up the new stack for a function in x86_64_wrap(), make
sure to make it 16-byte aligned, in keeping with amd64 calling
convention requirements.

Submitted by:	Mikore Li at sun dot com
2005-04-16 04:47:15 +00:00
jeff
afab3762a0 - Change all filesystems and vfs_cache to relock the dvp once the child is
locked in the ISDOTDOT case.  Se vfs_lookup.c r1.79 for details.

Sponsored by:	Isilon Systems, Inc.
2005-04-13 10:59:09 +00:00
mdodd
91ee5f450f Implement SOUND_MIXER_INFO ioctl in compat layer. 2005-04-13 04:33:06 +00:00
mdodd
6f940cf20f Add support for O_NOFOLLOW and O_DIRECT to Linux fcntl() F_GETFL/F_SETFL. 2005-04-13 04:31:43 +00:00
wpaul
a5aab37b5d In winx32_wrap.S, preserve return values in the fastcall and regparm
wrappers by pushing them onto the stack rather than keeping them in %esi
and %edi.
2005-04-11 17:04:49 +00:00
wpaul
a3b2d3191d Create new i386 windows/bsd thunking layer, similar to the amd64 thunking
layer, but with a twist.

The twist has to do with the fact that Microsoft supports structured
exception handling in kernel mode. On the i386 arch, exception handling
is implemented by hanging an exception registration list off the
Thread Environment Block (TEB), and the TEB is accessed via the %fs
register. The problem is, we use %fs as a pointer to the pcpu stucture,
which means any driver that tries to write through %fs:0 will overwrite
the curthread pointer and make a serious mess of things.

To get around this, Project Evil now creates a special entry in
the GDT on each processor. When we call into Windows code, a context
switch routine will fix up %fs so it points to our new descriptor,
which in turn points to a fake TEB. When the Windows code returns,
or calls out to an external routine, we swap %fs back again. Currently,
Project Evil makes use of GDT slot 7, which is all 0s by default.
I fully expect someone to jump up and say I can't do that, but I
couldn't find any code that makes use of this entry anywhere. Sadly,
this was the only method I could come up with that worked on both
UP and SMP. (Modifying the LDT works on UP, but becomes incredibly
complicated on SMP.) If necessary, the context switching stuff can
be yanked out while preserving the convention calling wrappers.

(Fortunately, it looks like Microsoft uses some special epilog/prolog
code on amd64 to implement exception handling, so the same nastiness
won't be necessary on that arch.)

The advantages are:

- Any driver that uses %fs as though it were a TEB pointer won't
  clobber pcpu.
- All the __stdcall/__fastcall/__regparm stuff that's specific to
  gcc goes away.

Also, while I'm here, switch NdisGetSystemUpTime() back to using
nanouptime() again. It turns out nanouptime() is way more accurate
than just using ticks(). On slower machines, the Atheros drivers
I tested seem to take a long time to associate due to the loss
in accuracy.
2005-04-11 02:02:35 +00:00
peter
0cf2f68921 Fix 32 bit signals on amd64. It turns out that I was sign extending
the register values coming back from sigreturn(2).  Normally this wouldn't
matter because the 32 bit environment would truncate the upper 32 bits
and re-save the truncated values at the next trap.  However, if we got
a fast second signal and it was pending while we were returning from
sigreturn(2) in the signal trampoline, we'd never have had a chance to
truncate the bogus values in 32 bit mode, and the new sendsig would get
an EFAULT when trying to write to the bogus user stack address.
2005-04-05 22:41:49 +00:00
jhb
a3c6b782c3 - Change the vm_mmap() function to accept an objtype_t parameter specifying
the type of object represented by the handle argument.
- Allow vm_mmap() to map device memory via cdev objects in addition to
  vnodes and anonymous memory.  Note that mmaping a cdev directly does not
  currently perform any MAC checks like mapping a vnode does.
- Unbreak the DRM getbufs ioctl by having it call vm_mmap() directly on the
  cdev the ioctl is acting on rather than trying to find a suitable vnode
  to map from.

Reviewed by:	alc, arch@
2005-04-01 20:00:11 +00:00
wpaul
5f091f4a37 Fix another KeInitializeDpc()/amd64 calling convention issue:
ndis_intrhand() has to be wrapped for the same reason as ndis_timercall().
2005-04-01 16:40:22 +00:00
jhb
38bfdc988f - Use a custom version of copyinuio() to implement readv/writev using
kern_readv/writev.
- Use kern_settimeofday() and kern_adjtime() rather than stackgapping it.
2005-03-31 22:58:13 +00:00
wpaul
6848972c73 Apparently I'm cursed. ndis_findwrap() should be searching ndis_functbl,
not ntoskrnl_functbl.
2005-03-31 21:20:19 +00:00
wpaul
123cbe5f9b Fix an amd64 issue I overlooked. When setting up a callout to
ndis_timercall() in NdisMInitializeTimer(), we can't use the raw
function pointer. This is because ntoskrnl_run_dpc() expects to
invoke a function with Microsoft calling conventions. On i386,
this works because ndis_timercall() is declared with the __stdcall
attribute, but this is a no-op on amd64. To do it correctly, we
have to generate a wrapper for ndis_timercall() and us the wrapper
instead of of the raw function pointer.

Fix this by adding ndis_timercall() to the funcptr table in subr_ndis.c,
and create ndis_findwrap() to extract the wrapped function from the
table in NdisMInitializeTimer() instead of just passing ndis_timercall()
to KeInitializeDpc() directly.
2005-03-31 16:38:48 +00:00
wpaul
2e83169800 Fix a possible mutex leak in KeSetTimerEx(): if timer is NULL, we
bail out without releasing the dispatcher lock. Move the lock acquisition
after the pointer test to avoid this.
2005-03-30 16:22:48 +00:00
wpaul
0257351eba Remove a couple of #ifdef 0'ed code blocks left over from Atheros debugging.
Remember to reset ndis_pendingreq to NULL when bailing out of
ndis_set_info() or ndis_get_info() due to miniportadapterctx not
being set.
2005-03-30 02:50:06 +00:00
jeff
bcbda3d771 - Initial cn_lkflags to LK_EXCLUSIVE.
Sponsored by:	Isilon Systems, Inc.
2005-03-29 10:16:12 +00:00
wpaul
bb3714b327 The filehandle allocated in NdisOpenFile() is allocated using
ExAllocatePoolWithTag(), not malloc(), so it should be released
with ExFreePool(), not free(). Fix a couple if instances of
free(fh, ...) that got overlooked.
2005-03-28 22:03:47 +00:00
wpaul
9920f4f146 Another Coverity fix from Sam: add NULL pointer test in
NdisMFreeSharedMemory() (if the list is already empty, just bail).
2005-03-28 21:09:00 +00:00
wpaul
3e1273271d More additions for amd64:
- On amd64, InterlockedPushEntrySList() and InterlockedPopEntrySList()
  are mapped to ExpInterlockedPushEntrySList and
  ExpInterlockedPopEntrySList() via macros (which do the same thing).
  Add IMPORT_FUNC_MAP()s for these.

- Implement ExQueryDepthSList().
2005-03-28 20:46:08 +00:00
wpaul
386c0634e4 Fix resource leak found by Coverity (via Sam Leffler). 2005-03-28 20:16:26 +00:00
wpaul
7f6e70f819 Fix for amd64. 2005-03-28 20:13:14 +00:00
wpaul
b1238bf60e Fix another amd64 issue with lookaside lists: we initialize the
alloc and free routine pointers in the lookaside list with pointers
to ExAllocatePoolWithTag() and ExFreePool() (in the case where the
driver does not provide its own alloc and free routines). For amd64,
this is wrong: we have to use pointers to the wrapped versions of these
functions, not the originals.
2005-03-28 19:27:58 +00:00
wpaul
12c3eeb4fa Tweak to hopefully make lookaside lists work on amd64: in Windows, the
nll_obsoletelock field in the lookaside list structure is only defined
for the i386 arch. For amd64, the field is gone, and different list
update routines are used which do their locking internally. Apparently
the Inprocomm amd64 driver uses lookaside lists. I'm not positive this
will make it work yet since I don't have an Inprocomm NIC to test, but
this needs to be fixed anyway.
2005-03-28 17:36:06 +00:00
wpaul
913253e3c7 Spell '0' as 'FALSE' when initializing npp_validcounts. (Doesn't change
the code, but emphasises that this field is used as a boolean.)
2005-03-28 17:06:47 +00:00
wpaul
a8513e48c5 Unbreak the build: correct the resource list traversal code for
__FreeBSD_version >= 600022.
2005-03-28 16:49:27 +00:00
wpaul
74837aa85b Argh. PCI resource list became an STAILQ instead of an SLIST. Try to
deal with this while maintaining backards source compatibility with
stable.
2005-03-27 10:35:07 +00:00
wpaul
e41bbf9219 Check in ntoskrnl_var.h, which should have been included in the
previous commit.
2005-03-27 10:16:45 +00:00
wpaul
959879757b Finally bring an end to the great "make the Atheros NDIS driver
work on SMP" saga. After several weeks and much gnashing of teeth,
I have finally tracked down all the problems, despite their best
efforts to confound and annoy me.

Problem nunmber one: the Atheros windows driver is _NOT_ a de-serialized
miniport! It used to be that NDIS drivers relied on the NDIS library
itself for all their locking and serialization needs. Transmit packet
queues were all handled internally by NDIS, and all calls to
MiniportXXX() routines were guaranteed to be appropriately serialized.
This proved to be a performance problem however, and Microsoft
introduced de-serialized miniports with the NDIS 5.x spec. Microsoft
still supports serialized miniports, but recommends that all new drivers
written for Windows XP and later be deserialized. Apparently Atheros
wasn't listening when they said this.

This means (among other things) that we have to serialize calls to
MiniportSendPackets(). We also have to serialize calls to MiniportTimer()
that are triggered via the NdisMInitializeTimer() routine. It finally
dawned on me why NdisMInitializeTimer() takes a special
NDIS_MINIPORT_TIMER structure and a pointer to the miniport block:
the timer callback must be serialized, and it's only by saving the
miniport block handle that we can get access to the serialization
lock during the timer callback.

Problem number two: haunted hardware. The thing that was _really_
driving me absolutely bonkers for the longest time is that, for some
reason I couldn't understand, my test machine would occasionally freeze
or more frustratingly, reset completely. That's reset and in *pow!*
back to the BIOS startup. No panic, no crashdump, just a reset. This
appeared to happen most often when MiniportReset() was called. (As
to why MiniportReset() was being called, see problem three below.)
I thought maybe I had created some sort of horrible deadlock
condition in the process of adding the serialization, but after three
weeks, at least 6 different locking implementations and heroic efforts
to debug the spinlock code, the machine still kept resetting. Finally,
I started single stepping through the MiniportReset() routine in
the driver using the kernel debugger, and this ultimately led me to
the source of the problem.

One of the last things the Atheros MiniportReset() routine does is
call NdisReadPciSlotInformation() several times to inspect a portion
of the device's PCI config space. It reads the same chunk of config
space repeatedly, in rapid succession. Presumeably, it's polling
the hardware for some sort of event. The reset occurs partway through
this process. I discovered that when I single-stepped through this
portion of the routine, the reset didn't occur. So I inserted a 1
microsecond delay into the read loop in NdisReadPciSlotInformation().
Suddenly, the reset was gone!!

I'm still very puzzled by the whole thing. What I suspect is happening
is that reading the PCI config space so quickly is causing a severe
PCI bus error. My test system is a Sun w2100z dual Opteron system,
and the NIC is a miniPCI card mounted in a miniPCI-to-PCI carrier card,
plugged into a 100Mhz PCI slot. It's possible that this combination of
hardware causes a bus protocol violation in this scenario which leads
to a fatal machine check. This is pure speculation though. Really all I
know for sure is that inserting the delay makes the problem go away.
(To quote Homer Simpson: "I don't know how it works, but fire makes
it good!")

Problem number three: NdisAllocatePacket() needs to make sure to
initialize the npp_validcounts field in the 'private' section of
the NDIS_PACKET structure. The reason if_ndis was calling the
MiniportReset() routine in the first place is that packet transmits
were sometimes hanging. When sending a packet, an NDIS driver will
call NdisQueryPacket() to learn how many physical buffers the packet
resides in. NdisQueryPacket() is actually a macro, which traverses
the NDIS_BUFFER list attached to the NDIS_PACKET and stashes some
of the results in the 'private' section of the NDIS_PACKET. It also
sets the npp_validcounts field to TRUE To indicate that the results are
now valid. The problem is, now that if_ndis creates a pool of transmit
packets via NdisAllocatePacketPool(), it's important that each time
a new packet is allocated via NdisAllocatePacket() that validcounts
be initialized to FALSE. If it isn't, and a previously transmitted
NDIS_PACKET is pulled out of the pool, it may contain stale data
from a previous transmission which won't get updated by NdisQueryPacket().
This would cause the driver to miscompute the number of fragments
for a given packet, and botch the transmission.

Fixing these three problems seems to make the Atheros driver happy
on SMP, which hopefully means other serialized miniports will be
happy too.

And there was much rejoicing.

Other stuff fixed along the way:

- Modified ndis_thsuspend() to take a mutex as an argument. This
  allows KeWaitForSingleObject() and KeWaitForMultipleObjects() to
  avoid any possible race conditions with other routines that
  use the dispatcher lock.

- Fixed KeCancelTimer() so that it returns the correct value for
  'pending' according to the Microsoft documentation

- Modfied NdisGetSystemUpTime() to use ticks and hz rather than
  calling nanouptime(). Also added comment that this routine wraps
  after 49.7 days.

- Added macros for KeAcquireSpinLock()/KeReleaseSpinLock() to hide
  all the MSCALL() goop.

- For x86, KeAcquireSpinLockRaiseToDpc() needs to be a separate
  function. This is because it's supposed to be _stdcall on the x86
  arch, whereas KeAcquireSpinLock() is supposed to be _fastcall.
  On amd64, all routines use the same calling convention so we can
  just map KeAcquireSpinLockRaiseToDpc() directly to KfAcquireSpinLock()
  and it will work. (The _fastcall attribute is a no-op on amd64.)

- Implement and use IoInitializeDpcRequest() and IoRequestDpc() (they're
  just macros) and use them for interrupt handling. This allows us to
  move the ndis_intrtask() routine from if_ndis.c to kern_ndis.c.

- Fix the MmInitializeMdl() macro so that is uses sizeof(vm_offset_t)
  when computing mdl_size instead of uint32_t, so that it matches the
  MmSizeOfMdl() routine.

- Change a could of M_WAITOKs to M_NOWAITs in the unicode routines in
  subr_ndis.c.

- Use the dispatcher lock a little more consistently in subr_ntoskrnl.c.

- Get rid of the "wait for link event" hack in ndis_init(). Now that
  I fixed NdisReadPciSlotInformation(), it seems I don't need it anymore.
  This should fix the witness panic a couple of people have reported.

- Use MSCALL1() when calling the MiniportHangCheck() function in
  ndis_ticktask(). I accidentally missed this one when adding the
  wrapping for amd64.
2005-03-27 10:14:36 +00:00
brooks
f16c448930 Use the CTASSERT() macro instead of rolling my own, non-portable one
using #error.

Suggested by:	jhb
2005-03-24 19:26:50 +00:00
brooks
b25337dcb4 Compile errors are way more useful then panics later.
Replace a KASSERT of LINUX_IFNAMSIZ == IFNAMSIZ with a preprocessor
check and #error message.  This will prevent nasty suprises if users
change IFNAMSIZ without updating the linux code appropriatly.
2005-03-24 17:51:15 +00:00
das
6a2a1d9492 Bounds check the user-supplied length used in a copyout() in
svr4_do_getmsg().  In principle this bug could disclose data from
kernel memory, but in practice, the SVR4 emulation layer is probably
not functional enough to cause the relevant code path to be executed.
In any case, the emulator has been disconnected from the build since
5.0-RELEASE.

Found by:	Coverity Prevent analysis tool
2005-03-23 08:28:06 +00:00
das
fbf7a9b2ee Reject packets larger than IP_MAXPACKET in linux_sendto() for sockets
with the IP_HDRINCL option set.  Without this change, a Linux process
with access to a raw socket could cause a kernel panic.  Raw sockets
must be created by root, and are generally not consigned to untrusted
applications; hence, the security implications of this bug are
minimal.  I believe this only affects 6-CURRENT on or after 2005-01-30.

Found by:	Coverity Prevent analysis tool
Security:	Local DOS
2005-03-23 08:28:00 +00:00
phk
00a6eab3e5 s/SLIST/STAILQ/
/imp/a\
pointy hat
.
2005-03-18 11:57:44 +00:00
phk
9cea99e06b Neuter the duplicated disk-device magic code for now. Somebody with
serious linux-clue is necessary to fix this properly.
2005-03-15 11:58:40 +00:00
sobomax
b795e2430a Add kernel-only flag MSG_NOSIGNAL to be used in emulation layers to surpress
SIGPIPE signal for the duration of the sento-family syscalls. Use it to
replace previously added hack in Linux layer based on temporarily setting
SO_NOSIGPIPE flag.

Suggested by:	alfred
2005-03-08 16:11:41 +00:00
sobomax
a5d845fec6 Handle MSG_NOSIGNAL flag in linux_send() by setting SO_NOSIGPIPE on socket
for the duration of the send() call. Such approach may be less than ideal
in threading environment, when several threads share the same socket and it
might happen that several of them are calling linux_send() at the same time
with and without SO_NOSIGPIPE set.

However, such race condition is very unlikely in practice, therefore this
change provides practical improvement compared to the previous behaviour.

PR:		kern/76426
Submitted by:	Steven Hartland <killing@multiplay.co.uk>
MFC after:	3 days
2005-03-07 07:26:42 +00:00
wpaul
a72168b811 When you call MiniportInitialize() for an 802.11 driver, it will
at some point result in a status event being triggered (it should
be a link down event: the Microsoft driver design guide says you
should generate one when the NIC is initialized). Some drivers
generate the event during MiniportInitialize(), such that by the
time MiniportInitialize() completes, the NIC is ready to go. But
some drivers, in particular the ones for Atheros wireless NICs,
don't generate the event until after a device interrupt occurs
at some point after MiniportInitialize() has completed.

The gotcha is that you have to wait until the link status event
occurs one way or the other before you try to fiddle with any
settings (ssid, channel, etc...). For the drivers that set the
event sycnhronously this isn't a problem, but for the others
we have to pause after calling ndis_init_nic() and wait for the event
to arrive before continuing. Failing to wait can cause big trouble:
on my SMP system, calling ndis_setstate_80211() after ndis_init_nic()
completes, but _before_ the link event arrives, will lock up or
reset the system.

What we do now is check to see if a link event arrived while
ndis_init_nic() was running, and if it didn't we msleep() until
it does.

Along the way, I discovered a few other problems:

- Defered procedure calls run at PASSIVE_LEVEL, not DISPATCH_LEVEL.
  ntoskrnl_run_dpc() has been fixed accordingly. (I read the documentation
  wrong.)

- Similarly, the NDIS interrupt handler, which is essentially a
  DPC, also doesn't need to run at DISPATCH_LEVEL. ndis_intrtask()
  has been fixed accordingly.

- MiniportQueryInformation() and MiniportSetInformation() run at
  DISPATCH_LEVEL, and each request must complete before another
  can be submitted. ndis_get_info() and ndis_set_info() have been
  fixed accordingly.

- Turned the sleep lock that guards the NDIS thread job list into
  a spin lock. We never do anything with this lock held except manage
  the job list (no other locks are held), so it's safe to do this,
  and it's possible that ndis_sched() and ndis_unsched() can be
  called from DISPATCH_LEVEL, so using a sleep lock here is
  semantically incorrect. Also updated subr_witness.c to add the
  lock to the order list.
2005-03-07 03:05:31 +00:00
sobomax
f706f4bce8 Handle unimplemented syscall by instantly returning ENOSYS instead of sending
signal first and only then returning ENOSYS to match what real linux does.

PR:		kern/74302
Submitted by:	Travis Poppe <tlp@LiquidX.org>
2005-03-07 00:18:06 +00:00
sobomax
6f0b5d23e8 Always produce cpuX entries, even in the case when there is only one CPU
in the system. This is consistent with what real linuxes do.

PR:		kern/75848
Submitted by:	Andriy Gapon <avg@icyb.net.ua>
MFC after:	3 days
2005-03-06 22:28:14 +00:00
wpaul
593ae58297 MAXPATHLEN is 1024, which means NdisOpenFile() and ndis_find_sym() were
both consuming 1K of stack space. This is unfriendly. Allocate the buffers
off the heap instead. It's a little slower, but these aren't performance
critical routines.

Also, add a spinlock to NdisAllocatePacketPool(), NdisAllocatePacket(),
NdisFreePacketPool() and NdisFreePacket(). The pool is maintained as a
linked list. I don't know for a fact that it can be corrupted, but why
take chances.
2005-03-03 03:51:02 +00:00