Forums

properly handling shared-interrupts in hardware and linux-driver

Started by markus schorer January 7, 2004
hi all,

i have an interrupt-related problem on a self-designed pc104-board:

i have several int-sources connected to a register and an edge-detector.
if an edge is detected an int is raised. the shared isr's then check
the register to see if they need to service their device. the int is 
cleared by writing to the register.

my problem: sometimes no more ints are generated. reloading a driver
(and thus clearing the int-request) cures this.
the problem seems to be, that every isr clears the int-request (i want
the drivers to be totally independent) and a new int arrives while being 
in the int-context. this way the int request is raised but never 
serviced in the system isr. with resetting the int req as late as 
possible in the isr's, i can reduce the window for this bug.

a solution i can think of is a state machine that queues interrupts.
states would be:

idle	goto wait when int raised else stay idle

wait	raise int-req,
	wait for some cycles for a clear-int, if expiring goto
	idle (deactivate int),
	if another int-req is received goto queued

queued  deassert int-req,
	wait for some cycles for a clear-int, if expiring raise int
	and goto wait, if another int is received stay queued and
	retrigger wait-time

this should queue and delay the int requests. the delay needs to be 
longer than every isr's start to clear-req time.

any other ideas?

btw, the above logic is (will) be integrated in an isplsi 1016 from
lattice.

regards,

markus



Markus schorer wrote:

> i have an interrupt-related problem on a self-designed pc104-board: > > i have several int-sources connected to a register and an edge-detector. > if an edge is detected an int is raised. the shared isr's then check > the register to see if they need to service their device. the int is > cleared by writing to the register.
Level detect is more robust than edge detect when interrupts are shared. Can you use level detect interrupts? I am not familiar with Linux, but if you are using it, I presume that it would include some code to support shared interrupts. If you need to write your own, can you use something like this? InterruptDispatch: repeat acknowledge interrupt -- allows new interrupts to be latched anynew = false for all attached devices if device service request anynew = true handle device interrupt reset device request end for until not anynew return from interrupt end Basically this stays in the dispatcher until a scan has been made with no new interrupts. The interrupt is acknowledged before testing, so that if a new request occurs after the associated device has been tested, it will trigger a new interrupt. When you exit, you know that the interrupt line has been cleared since the interrupt was acknowledged, thereby triggering a new interrupt on a new request. Thad
hi,

Thad Smith wrote:
> > Level detect is more robust than edge detect when interrupts are > shared. Can you use level detect interrupts?
the problem is, that i'm mixing an int from a ir-remote (that i can clear immediately) and i2c-devices (that i can not even service in int-context nor clear the int request). therefore i need to get an int on every edge of the int requests to be able to decide which int has been triggered and which one is queued for service. all of this is connected to a single pc104/isa interrupt.
> > I am not familiar with Linux, but if you are using it, I presume that it > would include some code to support shared interrupts.
there is support. you register several int-handlers for a single interrupt. but i can not control (nor do i know) in what sequence the handlers are executed (and who is the last one). i can not loop over all int handlers. i believe i have to get the int-reqs delayed (in hardware) until the cpu has left int-context.
> If you need to write your own, can you use something like this? > > InterruptDispatch: > repeat > acknowledge interrupt -- allows new interrupts to be latched > anynew = false > for all attached devices > if device service request > anynew = true > handle device interrupt > reset device request > end for > until not anynew > return from interrupt > end
this is not possible. the kernel does call every registered drivers int-handler once for every hw-int. even your code (a far as i can see) does not handle all cases: if you get an int on device 1 while device 3 is checked ("if device service request") you won't get "anynew=true", nor receive another interrupt (as you still are in int context). markus
markus schorer wrote:

> > If you need to write your own, can you use something like this? > > > > InterruptDispatch: > > repeat > > acknowledge interrupt -- allows new interrupts to be latched > > anynew = false > > for all attached devices > > if device service request > > anynew = true > > handle device interrupt > > reset device request > > end for > > until not anynew > > return from interrupt > > end > > this is not possible. the kernel does call every registered drivers > int-handler once for every hw-int. > > even your code (a far as i can see) does not handle all cases: > if you get an int on device 1 while device 3 is checked ("if device > service request") you won't get "anynew=true", nor receive another > interrupt (as you still are in int context).
The repeat loop will stay active until all devices report no service needed. In what scenario do you envision a failure? I don't see any. Let's say that you get a request for device 1, service it, then get another request for device 1 when checking other devices. Since device 1 was originally serviced, anynew=true was set for that occurrence and the devices are rescanned. It is possible to exit the repeat loop with an interrupt request, but since by then the interrupt has been acknowledged and determined to have been clear, any new request will generate a new interrupt request which will cause the interrupt handler to be reentered as soon as it exits, so you won't loose the request. As far as solving the problem in your original context, see if you can find a Linux driver guru. ;-) Thad
>>even your code (a far as i can see) does not handle all cases:
i should have stressed "afaics" a bit more. you're right. ;-)
> > needed. In what scenario do you envision a failure? I don't see any. > > Thad