properly handling shared-interrupts in hardware and linux-driver

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
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




Re: properly handling shared-interrupts in hardware and linux-driver

Quoted text here. Click to load it

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

Re: properly handling shared-interrupts in hardware and linux-driver
hi,

Quoted text here. Click to load it

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.

Quoted text here. Click to load it

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.

Quoted text here. Click to load it

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


Re: properly handling shared-interrupts in hardware and linux-driver

Quoted text here. Click to load it

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

Re: properly handling shared-interrupts in hardware and linux-driver

Quoted text here. Click to load it

i should have stressed "afaics" a bit more. you're right. ;-)

Quoted text here. Click to load it


Site Timeline