Re: HEADS UP: interrupt filtering & newbus API breakage

From: Paolo Pisati <piso_at_freebsd.org>
Date: Thu, 22 Feb 2007 00:31:24 +0100
On Tue, Feb 20, 2007 at 10:17:21AM -0800, Doug Barton wrote:
> Paolo Pisati wrote:
> 
> > So, if none as anything against it, i'm going to commit this work on
> > Friday 23 around 14:00 UTC, so speak now or forever hold your peace.
> 
> With any kind of luck this is redundant information for you, but I
> feel compelled to ask if you have both tested your patch with the
> latest HEAD, and run 'make universe' with the latest HEAD?

yes, it survives a 'make universe' with a recent HEAD (2 days old).

Moreover, someone asked me in private email what exactly was interrupt
filtering, so here is a brief overview:

take a normal handler, logically divide it in 2 pieces (the filter and
the handler), and let the filter run in the context of the interrupted
process (like a fast handler), while the handler will run in a
per driver private ithread context.

Every time a device triggers an interrupt, all the filters registered 
on that irq line will execute, and in case any of them recognize the 
event it can chose to:

1) serve the interrupt by itself if no potentially blocking actions
have to be carried on

2) ask the system to schedule the handler in the ithread, so it can
block, etcetc

The advantages of this model are:

1) no more masking of irq at the controller level, cause we can mask
   the interrupt at the device level in the filter and ack the event
   at the controller -> this should fix the interrupt
   storming/aliasing problems we had in the past

2) less contention for shared irq lines

3) the os has some feedback from filters, and thus can react in case 
   no filters were registered or none recognize the event

4) not stricly connected to interrupt filtering, but while working
   on this i turned much of the interrupt handling MD code into MI
   code

AFAIK darwin, NT and vxworks work this way.

Implementation details:

To support a 2 functions device driver, bus_setup_intr() had to grow a
new filter_t argument, and thus the prototype changed to:

int
bus_setup_intr(device_t dev, struct resource *r, int flags,
    driver_filter_t filter, driver_intr_t handler, void *arg, 
    void **cookiep)

where driver_filter_t is:

typedef int driver_filter_t(void*);

and thus i had to fix all the instances of bus_setup_intr() in our tree.

Moreover, all the fast handlers became filters and thus a return code
reflecting the interrupt handling status was added to them, and the 
return code can be:

FILTER_STRAY              -> i don't recognize this event
FILTER_HANDLED            -> i recognize this event
FILTER_SCHEDULE_THREAD    -> schedule my ithread (not used now)

To attach a filter/fast handler we do now:

bus_setup_intr(dev, r, flags, filter, NULL, softc, cookie)

where flags DOESN'T contain INTR_FAST -> if an handler is attached as
a filter, it will always run in the context of the interrupted process
so we don't need to explicit it anymore.

To to attach a normal ithread handler we do:

bus_setup_intr(dev, r, flags, NULL, handler, softc, cookie)

while a filtered handlers will look like:

bus_setup_intr(dev, r, flags, filter, handler, softc, cookie)

when both the filter and the handler functions are used.

In my first patch i just address the bus_setup_intr() modification and
it's the first and mandatory step before i commit the real interrupt
handling mechanism: with these modifications in the tree the rest can
be commited in #ifdef ... #endif without affecting the usual
interrupt mechanism and that means, we can ship 7.0 with a dormient 
implementation (at least for i386 and amd64), and developers can
convert their drivers during the entire 7.x life span.

bye, 
P.
Received on Wed Feb 21 2007 - 22:31:33 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:05 UTC