Commit Graph

856 Commits

Author SHA1 Message Date
Bruce M Simpson
cc5f91ee35 Add stub for Linux SOUND_MIXER_READ_RECMASK, required by some Linux sound
applications.

PR:		misc/27471
Submitted by:	Gavin Atkinson (with cleanups)
2004-06-18 14:36:24 +00:00
Bruce M Simpson
bf4f8992cd Add a stub for the Linux SOUND_MIXER_INFO ioctl (even though we don't
actually implement it), as some applications, such as RealProducer,
expect to be able to use it.

PR:		kern/65971
Submitted by:	Matt Wright
2004-06-18 14:25:44 +00:00
Bruce M Simpson
3f77a2b479 Linux applications expect to be able to call SIOCGIFCONF with an
NULL ifc.ifc_buf pointer, to determine the expected buffer size.

The submitted fix only takes account of interfaces with an AF_INET
address configured. This could no doubt be improved.

PR:		kern/45753
Submitted by:	Jacques Garrigue (with cleanups)
2004-06-18 14:06:46 +00:00
Bruce M Simpson
36db02ff0b Fix the VT_SETMODE/CDROMIOCTOCENTRY problem correctly.
Reviewed by:	tjr
2004-06-18 13:36:30 +00:00
Bruce M Simpson
e41fce295e Fix two attempts to use an unchecked NULL pointer provided from the
userland, for the CDIOREADTOCENTRY and VT_SETMODE cases respectively.

Noticed by: tjr
2004-06-18 09:13:35 +00:00
Poul-Henning Kamp
f3732fd15b Second half of the dev_t cleanup.
The big lines are:
	NODEV -> NULL
	NOUDEV -> NODEV
	udev_t -> dev_t
	udev2dev() -> findcdev()

Various minor adjustments including handling of userland access to kernel
space struct cdev etc.
2004-06-17 17:16:53 +00:00
Poul-Henning Kamp
89c9c53da0 Do the dreaded s/dev_t/struct cdev */
Bump __FreeBSD_version accordingly.
2004-06-16 09:47:26 +00:00
Poul-Henning Kamp
71e9d5f9c8 Add support for more linux ioctls.
I've had this sitting in my tree for a long time and I can't seem to
find who sent it to me in the first place, apologies to whoever is
missing out on a Contributed by: line here.

I belive it works as it should.
2004-06-14 07:26:23 +00:00
Robert Watson
310e7ceb94 Socket MAC labels so_label and so_peerlabel are now protected by
SOCK_LOCK(so):

- Hold socket lock over calls to MAC entry points reading or
  manipulating socket labels.

- Assert socket lock in MAC entry point implementations.

- When externalizing the socket label, first make a thread-local
  copy while holding the socket lock, then release the socket lock
  to externalize to userspace.
2004-06-13 02:50:07 +00:00
Poul-Henning Kamp
1930e303cf Deorbit COMPAT_SUNOS.
We inherited this from the sparc32 port of BSD4.4-Lite1.  We have neither
a sparc32 port nor a SunOS4.x compatibility desire these days.
2004-06-11 11:16:26 +00:00
Bill Paul
bd610e47e2 Add another 5.2.1 source compatibility tweak: acquire Giant before calling
kthread_exit() if FreeBSD_version is old enough.
2004-06-07 01:22:48 +00:00
Tim J. Robbins
f99619a0dc Change the types of vn_rdwr_inchunks()'s len and aresid arguments to
size_t and size_t *, respectively. Update callers for the new interface.
This is a better fix for overflows that occurred when dumping segments
larger than 2GB to core files.
2004-06-05 02:18:28 +00:00
Dag-Erling Smørgrav
63eaecc921 Take advantage of the dev sysctl tree.
Approved by:	wpaul
2004-06-04 22:24:46 +00:00
Bill Paul
38f0f45fb5 Grrr. Really check subr_ndis.c in this time. (fixed my_strcasecmp()) 2004-06-04 04:45:38 +00:00
Bill Paul
8c2dd02b27 Explicitly #include <sys/module.h> instead of depending on <sys/kernel.h>
to do it for us.
2004-06-01 23:24:17 +00:00
Bill Paul
3a7dc24c44 Fix build with ndisulator: Add prototype for my_strcasecmp(). 2004-05-29 22:34:08 +00:00
Bill Paul
d1a5f43855 In subr_ndis.c, when searching for keys in our make-pretend registry,
make the key name matching case-insensitive. There are some drivers
and .inf files that have mismatched cases, e.g. the driver will look
for "AdhocBand" whereas the .inf file specifies a registry key to be
created called "AdHocBand." The mismatch is probably a typo that went
undetected (so much for QA), but since Windows seems to be case-insensitive,
we should be too.

In if_ndis.c, initialize rates and channels correctly so that specify
frequences correctly when trying to set channels in the 5Ghz band, and
so that 802.11b rates show up for some a/b/g cards (which otherwise
appear to have no 802.11b modes).

Also, when setting OID_802_11_CONFIGURATION in ndis_80211_setstate(),
provide default values for the beacon interval, ATIM window and dwelltime.
The Atheros "Aries" driver will crash if you try to select ad-hoc mode
and leave the beacon interval set to 0: it blindly uses this value and
does a division by 0 in the interrupt handler, causing an integer
divide trap.
2004-05-29 06:41:17 +00:00
Bill Paul
a1788fb41e Small timer cleanups:
- Use the dh_inserted member of the dispatch header in the Windows
  timer structure to indicate that the timer has been "inserted into
  the timer queue" (i.e. armed via timeout()). Use this as the value
  to return to the caller in KeCancelTimer(). Previously, I was using
  callout_pending(), but you can't use that with timeout()/untimeout()
  without creating a potential race condition.

- Make ntoskrnl_init_timer() just a wrapper around ntoskrnl_init_timer_ex()
  (reduces some code duplication).

- Drop Giant when entering if_ndis.c:ndis_tick() and
  subr_ntorkrnl.c:ntoskrnl_timercall(). At the moment, I'm forced to
  use system callwheel via timeout()/untimeout() to handle timers rather
  than the callout API (struct callout is too big to fit inside the
  Windows struct KTIMER, so I'm kind of hosed). Unfortunately, all
  the callouts in the callwhere are not marked as MPSAFE, so when
  one of them fires, it implicitly acquires Giant before invoking the
  callback routine (and releases it when it returns). I don't need to
  hold Giant, but there's no way to stop the callout code from acquiring
  it as long as I'm using timeout()/untimeout(), so for now we cheat
  by just dropping Giant right away (and re-acquiring it right before
  the routine returns so keep the callout code happy). At some point,
  I will need to solve this better, but for now this should be a suitable
  workaround.
2004-04-30 20:51:55 +00:00
Marcel Moolenaar
c050455eac Fix build for non-COMPAT_FREEBSD4 configurations. Make the FreeBSD 4
statfs functions conditional upon the option.
2004-04-24 04:31:59 +00:00
Bill Paul
b1084a1e96 Ok, _really_ fix the Intel 2100B Centrino deadlock problems this time.
(I hope.)

My original instinct to make ndis_return_packet() asynchronous was correct.
Making ndis_rxeof() submit packets to the stack asynchronously fixes
one recursive spinlock acquisition, but it's also possible for it to
happen via the ndis_txeof() path too. So:

- In if_ndis.c, revert ndis_rxeof() to its old behavior (and don't bother
  putting ndis_rxeof_serial() back since we don't need it anymore).

- In kern_ndis.c, make ndis_return_packet() submit the call to the
  MiniportReturnPacket() function to the "ndis swi" thread so that
  it always happens in another context no matter who calls it.
2004-04-22 07:08:39 +00:00
Bill Paul
e3a62f4d54 Correct the AT_DISPATCH_LEVEL() macro to match earlier changes. 2004-04-20 02:27:38 +00:00
Bill Paul
1906853bd2 Try to handle recursive attempts to raise IRQL to DISPATCH_LEVEL better
(among other things).
2004-04-19 22:39:04 +00:00
Bill Paul
e1c0113ffd In ntoskrnl_unlock_dpc(), use atomic_store instead of atomic_cmpset
to give up the spinlock.

Suggested by: bde
2004-04-18 18:38:59 +00:00
Bill Paul
ef617c0842 - Use memory barrier with atomic operations in ntoskrnl_lock_dpc() and
ntoskrnl_unlocl_dpc().
- hal_raise_irql(), hal_lower_irql() and hal_irql() didn't work right
  on SMP (priority inheritance makes things... interesting). For now,
  use only two states: DISPATCH_LEVEL (PI_REALTIME) and PASSIVE_LEVEL
  (everything else). Tested on a dual PIII box.
- Use ndis_thsuspend() in ndis_sleep() instead of tsleep(). (I added
  ndis_thsuspend() and ndis_thresume() to replace kthread_suspend()
  and kthread_resume(); the former will preserve a thread's priority
  when it wakes up, the latter will not.)
- Change use of tsleep() in ndis_stop_thread() to prevent priority
  change on wakeup.
2004-04-16 00:04:28 +00:00
Peter Wemm
5027176b20 Check in structure definitions for the FreeBSD-3.x signal syscall stuff.
Nothing uses these yet, but I dont want to lose them.
2004-04-14 23:20:14 +00:00
Peter Wemm
5b3283b084 Regen 2004-04-14 23:17:57 +00:00
Peter Wemm
0c70bced57 Catch up to the not-so-recent statfs(2) changes. 2004-04-14 23:17:37 +00:00
Bill Paul
2b94c69d1d Continue my efforts to imitate Windows as closely as possible by
attempting to duplicate Windows spinlocks. Windows spinlocks differ
from FreeBSD spinlocks in the way they block preemption. FreeBSD
spinlocks use critical_enter(), which masks off _all_ interrupts.
This prevents any other threads from being scheduled, but it also
prevents ISRs from running. In Windows, preemption is achieved by
raising the processor IRQL to DISPATCH_LEVEL, which prevents other
threads from preempting you, but does _not_ prevent device ISRs
from running. (This is essentially what Solaris calls dispatcher
locks.) The Windows spinlock itself (kspin_lock) is just an integer
value which is atomically set when you acquire the lock and atomically
cleared when you release it.

FreeBSD doesn't have IRQ levels, so we have to cheat a little by
using thread priorities: normal thread priority is PASSIVE_LEVEL,
lowest interrupt thread priority is DISPATCH_LEVEL, highest thread
priority is DEVICE_LEVEL (PI_REALTIME) and critical_enter() is
HIGH_LEVEL. In practice, only PASSIVE_LEVEL and DISPATCH_LEVEL
matter to us. The immediate benefit of all this is that I no
longer have to rely on a mutex pool.

Now, I'm sure many people will be seized by the urge to criticize
me for doing an end run around our own spinlock implementation, but
it makes more sense to do it this way. Well, it does to me anyway.

Overview of the changes:

- Properly implement hal_lock(), hal_unlock(), hal_irql(),
  hal_raise_irql() and hal_lower_irql() so that they more closely
  resemble their Windows counterparts. The IRQL is determined by
  thread priority.

- Make ntoskrnl_lock_dpc() and ntoskrnl_unlock_dpc() do what they do
  in Windows, which is to atomically set/clear the lock value. These
  routines are designed to be called from DISPATCH_LEVEL, and are
  actually half of the work involved in acquiring/releasing spinlocks.

- Add FASTCALL1(), FASTCALL2() and FASTCALL3() macros/wrappers
  that allow us to call a _fastcall function in spite of the fact
  that our version of gcc doesn't support __attribute__((__fastcall__))
  yet. The macros take 1, 2 or 3 arguments, respectively. We need
  to call hal_lock(), hal_unlock() etc... ourselves, but can't really
  invoke the function directly. I could have just made the underlying
  functions native routines and put _fastcall wrappers around them for
  the benefit of Windows binaries, but that would create needless bloat.

- Remove ndis_mtxpool and all references to it. We don't need it
  anymore.

- Re-implement the NdisSpinLock routines so that they use hal_lock()
  and friends like they do in Windows.

- Use the new spinlock methods for handling lookaside lists and
  linked list updates in place of the mutex locks that were there
  before.

- Remove mutex locking from ndis_isr() and ndis_intrhand() since they're
  already called with ndis_intrmtx held in if_ndis.c.

- Put ndis_destroy_lock() code under explicit #ifdef notdef/#endif.
  It turns out there are some drivers which stupidly free the memory
  in which their spinlocks reside before calling ndis_destroy_lock()
  on them (touch-after-free bug). The ADMtek wireless driver
  is guilty of this faux pas. (Why this doesn't clobber Windows I
  have no idea.)

- Make NdisDprAcquireSpinLock() and NdisDprReleaseSpinLock() into
  real functions instead of aliasing them to NdisAcaquireSpinLock()
  and NdisReleaseSpinLock(). The Dpr routines use
  KeAcquireSpinLockAtDpcLevel() level and KeReleaseSpinLockFromDpcLevel(),
  which acquires the lock without twiddling the IRQL.

- In ndis_linksts_done(), do _not_ call ndis_80211_getstate(). Some
  drivers may call the status/status done callbacks as the result of
  setting an OID: ndis_80211_getstate() gets OIDs, which means we
  might cause the driver to recursively access some of its internal
  structures unexpectedly. The ndis_ticktask() routine will call
  ndis_80211_getstate() for us eventually anyway.

- Fix the channel setting code a little in ndis_80211_setstate(),
  and initialize the channel to IEEE80211_CHAN_ANYC. (The Microsoft
  spec says you're not supposed to twiddle the channel in BSS mode;
  I may need to enforce this later.) This fixes the problems I was
  having with the ADMtek adm8211 driver: we were setting the channel
  to a non-standard default, which would cause it to fail to associate
  in BSS mode.

- Use hal_raise_irql() to raise our IRQL to DISPATCH_LEVEL when
  calling certain miniport routines, per the Microsoft documentation.

I think that's everything. Hopefully, other than fixing the ADMtek
driver, there should be no apparent change in behavior.
2004-04-14 07:48:03 +00:00
Bill Paul
7b764c37e4 In ndis_convert_res(), initialize the head of our temporary list
before calling BUS_GET_RESOURCE_LIST(). Previously, the list head would
only be initialized if BUS_GET_RESOURCE_LIST() succeeded; it needs to
be initialized unconditionally so that the list cleanup code won't
trip over potential stack garbage.
2004-04-07 17:02:55 +00:00
Bill Paul
6a50285516 - The MiniportReset() function can return NDIS_STATUS_PENDING, in which
case we should wait for the resetdone handler to be called before
  returning.

- When providing resources via ndis_query_resources(), uses the
  computed rsclen when using bcopy() to copy out the resource data
  rather than the caller-supplied buffer length.

- Avoid using ndis_reset_nic() in if_ndis.c unless we really need
  to reset the NIC because of a problem.

- Allow interrupts to be fielded during ndis_attach(), at least
  as far as allowing ndis_isr() and ndis_intrhand() to run.

- Use ndis_80211_rates_ex when probing for supported rates. Technically,
  this isn't supposed to work since, although Microsoft added the extended
  rate structure with the NDIS 5.1 update, the spec still says that
  the OID_802_11_SUPPORTED_RATES OID uses ndis_80211_rates. In spite of
  this, it appears some drivers use it anyway.

- When adding in our guessed rates, check to see if they already exist
  so that we avoid any duplicates.

- Add a printf() to ndis_open_file() that alerts the user when a
  driver attempts to open a file under /compat/ndis.

With these changes, I can get the driver for the SMC 2802W 54g PCI
card to load and run. This board uses a Prism54G chip. Note that in
order for this driver to work, you must place the supplied smc2802w.arm
firmware image under /compat/ndis. (The firmware is not resident on
the device.)

Note that this should also allow the 3Com 3CRWE154G72 card to work
as well; as far as I can tell, these cards also use a Prism54G chip.
2004-04-05 08:26:52 +00:00
Pawel Jakub Dawidek
c5b7c33bc8 Remove ps_argsopen from this check, because of two reasons:
1. This check if wrong, because it is true by default
   (kern.ps_argsopen is 1 by default) (p_cansee() is not even checked).
2. Sysctl kern.ps_argsopen is going away.
2004-04-01 00:04:23 +00:00
Bill Paul
6ea748c0f1 Add missing cprd_flags member to partial resource structure in
resource_var.h.

In kern_ndis.c:ndis_convert_res(), fill in the cprd_flags and
cprd_sharedisp fields as best we can.

In if_ndis.c:ndis_setmulti(), don't bother updating the multicast
filter if our multicast address list is empty.

Add some missing updates to ndis_var.h and ntoskrnl_var.h that I
forgot to check in when I added the KeDpc stuff.
2004-03-29 02:15:29 +00:00
Bill Paul
60a6006b6c Apparently, some atheros drivers want rand(), so implement it (in terms
of random()).

Requested by: juli
Bribe offered: tacos
2004-03-27 20:38:43 +00:00
Mike Makonnen
a73027fee9 Regen for libthr thread synchronization syscalls. 2004-03-27 14:34:17 +00:00
Mike Makonnen
1713a51661 Separate thread synchronization from signals in libthr. Instead
use msleep() and wakeup_one().

Discussed with: jhb, peter, tjr
2004-03-27 14:30:43 +00:00
Bill Paul
5d3b74e4c1 - In subr_ndis.c:ndis_init_event(), initialize events as notification
objects rather than synchronization objects. When a sync object is
  signaled, only the first thread waiting on it is woken up, and then
  it's automatically reset to the not-signaled state. When a
  notification object is signaled, all threads waiting on it will
  be woken up, and it remains in the signaled state until someone
  resets it manually. We want the latter behavior for NDIS events.

- In kern_ndis.c:ndis_convert_res(), we have to create a temporary
  copy of the list returned by BUS_GET_RESOURCE_LIST(). When the PCI
  bus code probes resources for a given device, it enters them into
  a singly linked list, head first. The result is that traversing
  this list gives you the resources in reverse order. This means when
  we create the Windows resource list, it will be in reverse order too.
  Unfortunately, this can hose drivers for devices with multiple I/O
  ranges of the same type, like, say, two memory mapped I/O regions (one
  for registers, one to map the NVRAM/bootrom/whatever). Some drivers
  test the range size to figure out which region is which, but others
  just assume that the resources will be listed in ascending order from
  lowest numbered BAR to highest. Reversing the order means such drivers
  will choose the wrong resource as their I/O register range.

  Since we can't traverse the resource SLIST backwards, we have to
  make a temporary copy of the list in the right order and then build
  the Windows resource list from that. I suppose we could just fix
  the PCI bus code to use a TAILQ instead, but then I'd have to track
  down all the consumers of the BUS_GET_RESOURCE_LIST() and fix them
  too.
2004-03-25 18:31:52 +00:00
Bill Paul
52bfac6de0 - In kern_ndis.c, implement ndis_unsched(), the complement to ndis_sched(),
which pulls a job off a thread work queue (assuming it hasn't run yet).
  This is needed for KeRemoveQueueDpc().

- In subr_ntoskrnl.c, implement KeInsertQueueDpc() and KeRemoveQueueDpc(),
  to go with KeInitializeDpc() to round out the API. Also change the
  KeTimer implementation to use this API instead of the private
  timer callout scheduler. Functionality of the timer API remains
  unchanged, but we get a couple new Windows kernel API routines and
  more closely imitate the way thing works in Windows. (As of yet
  I haven't encountered any drivers that use KeInsertQueueDpc() or
  KeRemoveQueueDpc(), but it doesn't hurt to have them.)
2004-03-25 08:23:08 +00:00
Bill Paul
150514c0eb Remove another case of grabbing Giant before doing a kthread_exit()
which is now no longer needed.
2004-03-22 22:46:22 +00:00
Bill Paul
c5d019ec55 I'm a dumbass: the test in the MOD_SHUTDOWN case in ndis_modevent()
that checks to see if any devices are still in the devlist was reversed.
2004-03-22 18:34:37 +00:00
Bill Paul
e34e2a168a The Intel 2200BG NDIS driver does an alloca() of about 5000 bytes
when it associates with a net. Because FreeBSD's kstack size is only
2 pages by default, this blows the stack and causes a double fault.

To deal with this, we now create all our kthreads with 8 stack pages.
Also, we now run all timer callouts in the ndis swi thread (since
they would otherwise run in the clock ithread, whose stack is too
small). It happens that the alloca() in this case was occuring within
the interrupt handler, which was already running in the ndis swi
thread, but I want to deal with the callouts too just to be extra
safe.

NOTE: this will only work if you update vm_machdep.c with the change
I just committed. If you don't include this fix, setting the number
of stack pages with kthread_create() has essentially no effect.
2004-03-22 00:41:41 +00:00
Peter Wemm
95c6291685 Change (yet again, sorry!) the path of the 32 bit ld-elf.so.1. 2004-03-21 01:22:24 +00:00
Bill Paul
f6159e042d - Rewrite the timer and event API routines in subr_ndis.c so that they
are actually layered on top of the KeTimer API in subr_ntoskrnl.c, just
  as it is in Windows. This reduces code duplication and more closely
  imitates the way things are done in Windows.

- Modify ndis_encode_parm() to deal with the case where we have
  a registry key expressed as a hex value ("0x1") which is being
  read via NdisReadConfiguration() as an int. Previously, we tried
  to decode things like "0x1" with strtol() using a base of 10, which
  would always yield 0. This is what was causing problems with the
  Intel 2200BG Centrino 802.11g driver: the .inf file that comes
  with it has a key called RadioEnable with a value of 0x1. We
  incorrectly decoded this value to '0' when it was queried, hence
  the driver thought we wanted the radio turned off.

- In if_ndis.c, most drivers don't accept NDIS_80211_AUTHMODE_AUTO,
  but NDIS_80211_AUTHMODE_SHARED may not be right in some cases,
  so for now always use NDIS_80211_AUTHMODE_OPEN.

NOTE: There is still one problem with the Intel 2200BG driver: it
happens that the kernel stack in Windows is larger than the kernel
stack in FreeBSD. The 2200BG driver sometimes eats up more than 2
pages of stack space, which can lead to a double fault panic.
For the moment, I got things to work by adding the following to
my kernel config file:

options         KSTACK_PAGES=8

I'm pretty sure 8 is too big; I just picked this value out of a hat
as a test, and it happened to work, so I left it. 4 pages might be
enough. Unfortunately, I don't think you can dynamically give a
thread a larger stack, so I'm not sure how to handle this short of
putting a note in the man page about it and dealing with the flood
of mail from people who never read man pages.
2004-03-20 23:39:43 +00:00
John Baldwin
b7e23e826c - Replace wait1() with a kern_wait() function that accepts the pid,
options, status pointer and rusage pointer as arguments.  It is up to
  the caller to copyout the status and rusage to userland if needed.  This
  lets us axe the 'compat' argument and hide all that functionality in
  owait(), by the way.  This also cleans up some locking in kern_wait()
  since it no longer has to drop locks around copyout() since all the
  copyout()'s are deferred.
- Convert owait(), wait4(), and the various ABI compat wait() syscalls to
  use kern_wait() rather than wait1() or wait4().  This removes a bit
  more stackgap usage.

Tested on:	i386
Compiled on:	i386, alpha, amd64
2004-03-17 20:00:00 +00:00
Tim J. Robbins
7b0d017245 Use vfs_nmount() to mount linprocfs filesystems in linux_mount();
linprocfs doesn't support the old mount interface.
2004-03-16 09:05:56 +00:00
Tim J. Robbins
2ba9b76668 Correct size argument passed to copyinstr() in linux_mount(): mntfromname
and mntonname are both MNAMELEN characters long, not MFSNAMELEN.
2004-03-16 08:37:19 +00:00
Bill Paul
f79e9df73b Add vectors for _snprintf() and _vsnprintf() (redirected straight to
snprintf() and vsnprintf() in FreeBSD kernel land).

This is needed by the Intel Centrino 2200BG driver. Unfortunately, this
driver still doesn't work right with Project Evil even with this tweak,
but I'm unable to diagnose the problem since I don't have access to a
sample card.
2004-03-15 16:39:03 +00:00
Peter Wemm
73f3495386 Move the non-MD machine/dvcfg.h and machine/physio_proc.h to a common
MI area before they proliferate more.
2004-03-13 19:46:27 +00:00
Poul-Henning Kamp
651b11eaf2 Remove unused second arg to vfinddev().
Don't call addaliasu() on VBLK nodes.
2004-03-11 16:33:11 +00:00
Bill Paul
0bf7b204e3 Fix mind-o: sanity check in ndis_disable_ndis() is not sane. 2004-03-11 09:50:00 +00:00
Bill Paul
1e35c8564a Fix the problem with the Cisco Aironet 340 PCMCIA card. Most newer drivers
for Windows are deserialized miniports. Such drivers maintain their own
queues and do their own locking. This particular driver is not deserialized
though, and we need special support to handle it correctly.

Typically, in the ndis_rxeof() handler, we pass all incoming packets
directly to (*ifp->if_input)(). This in turn may cause another thread
to run and preempt us, and the packet may actually be processed and
then released before we even exit the ndis_rxeof() routine. The
problem with this is that releasing a packet calls the ndis_return_packet()
function, which hands the packet and its buffers back to the driver.
Calling ndis_return_packet() before ndis_rxeof() returns will screw
up the driver's internal queues since, not being deserialized,
it does no locking.

To avoid this problem, if we detect a serialized driver (by checking
the attribute flags passed to NdisSetAttributesEx(), we use an alternate
ndis_rxeof() handler, ndis_rxeof_serial(), which puts the call to
(*ifp->if_input)() on the NDIS SWI work queue. This guarantees the
packet won't be processed until after ndis_rxeof_serial() returns.

Note that another approach is to always copy the packet data into
another mbuf and just let the driver retain ownership of the ndis_packet
structure (ndis_return_packet() never needs to be called in this
case). I'm not sure which method is faster.
2004-03-11 09:40:00 +00:00