Subject: Re: USB spl problem
To: Lennart Augustsson <augustss@cs.chalmers.se>
From: Terry Moore <tmm@mcci.com>
List: tech-kern
Date: 07/23/1998 21:45:22
One way to do this is to take the interrupt at whatever the hardware
priority happens to be (eg spltty), and then generate a softint to
do the work.  This is how network cards work -- the data comes in at
highprio, and then they call setsoftnet() (from <machine/cpu.h>) to
schedule the appropriate interrupt as the machine lowers its priority
on its way back to the fully-enabled state.

There are a number of software interrrupt routines that get called in this
way:  setsoftnet(), setsoftclock(), etc.  Unfortunately it appears that
to add a new one you have to visit all the ports.

splbio is not generally lower than 'everything else', it depends on the
port.  You really want to run either at splsoftnet() or splsoftclock(),
I think.

You'd synchronize the kernel code to the USB async code by calling splsoftnet() 
at the appropriate times.  This doesnt disable any interrupts at all; it
just defers USB software interrupt processing until you block, return from 
the system call.

You might want to consider, if you are visiting all the ports, suggesting
something akin to the old RSX/VMS 'fork routine' mechanism. Rather than
hard-coding in the routine to call, you'd have a dynamic list of things to
do (pointer to fn, argument, next in list).  In my experience, these blocks
can be preallocated, and with careful semantics you can be pretty care-free
about requeueing them.  The "DPC" mechanism in NT suffers from not having
worried about boundary conditions, potential reuse, etc.  The BSD kernel
splsoftnet()/softclock() scheme, because it uses a bit, is trouble-free
by comparison.  It's possible to have a mechanism that is as easy to use
as the BSD kernel mechanism, without embedding knowledge of all the 
possible soft interrupts in every port....  I can provide some sample code,
if you'd like.

--Terry

> I have a problem with the USB interrupt level.  The problem is that a
> USB interrupt may need differnet levels depending on which device it
> was that caused the interrupt.  USB devices can be of many different
> kinds:
>         communication   (spltty)
>         network device  (splnet)
>         audio           (splaudio)
>         disks           (splbio)
>         ...
> 
> My proposed solution is that the USB interrupt level should be lower
> than all other hardware levels.  This way we can ensure that it will
> not interrupt in a bad place.  Each USB device driver will the raise
> the level in its interrupt routine if needed.  E.g., the USB com driver
> will do an spltty() before running any critical code in the interrupt
> routine, the USB audio driver will do an splaudio() etc.
> 
> First question, will this work?
> 
> Second question, how can I find a level that is lower than all
> others?  splbio() is the lowest one according to the spl(9) man
> page (and this is what I use right now), but I would feel
> better if there was a proper splusb() that was lower than all
> others.
> 
>         -- Lennart
> 
>