LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Interrupt Handler: identifying source... (https://www.linuxquestions.org/questions/programming-9/interrupt-handler-identifying-source-353307/)

Elric of Grans 08-14-2005 09:19 PM

Interrupt Handler: identifying source...
 
G'Day,

I am writing some code for a system device, and most parts seem to be working fine now, however, up to this point I have stepped around an issue with the interrupt handler: I really need to address it now.

There are actually 8 identical devices on this system, any of which could trigger the interrupt: they all use the same interrupt line, and logically should use the same handler. All the handler needs to do is write a 1 to a register field, but the address of that register varies depending on which of the 8 devices requested it. For testing, I have only used a single device, however, I now need it to be able to identify which of the 8 triggered it. Is there a way to do this?

If I look at the arguments of a handler, they receive:
int irq,
void *dev_id, and
struct pt_regs *regs

int irq is likely useless here, and I am not sure struct pt_regs *regs would be of any use either, but what about void *dev_id? I have not been able to identify what it is, or what it is for, so perhaps that is what I need? Or is there another way I should go about this? If worst comes to worst, I could poll all 8 registers to identify which one asserted the interrupt, but that is a tad inefficient. If possible, I would like to take a more elegant solution.

Thanks for any advice!

PS
There is also an oddity I have observed that I cannot explain. I am exporting some values to sysfs, however two of them are returning illogical values. They are both reading the same register (value = 0x42). One of the files returns:
sprintf(buffer, "%lu\n", (value & (1 << 6)))
the other
sprintf(buffer, "%lu\n", (value & (1 << 2)))
The former actually returns 64, while the latter 2: I was expecting 1 in both cases. Am I mading some stupid oversight here? It just seems *too* simple to get wrong...
Interestingly enough, in a different case, (value & (1 << 1)) works fine: no matter the value of the register, it always correctly returns 0 or 1.

Elric of Grans 08-14-2005 09:25 PM

Err... actually, foget the PS: I just realised what was wrong! Can I plead Monday? ;)

sundialsvcs 08-16-2005 09:35 AM

For some devices, all that you can do is to poll, and sometimes what you need to do ... is poll. If "eight identical devices" are rigged on just one board, it may well raise the interrupt just one time to signal that one-or-more of the devices need attention. If they are separate boards all sharing the same IRQ, then if you can "poll" all of them and thus avoid "X" consecutive interrupts, you also come out ahead. Even though interrupts happen constantly, they are disruptive to the processor's attempts at pipelining .. which is where modern processors get their phenomenal rated speeds. Once you find yourself in a first-level interrupt handler, "you're there, make the most of it."

An interrupt-handler is not necessarily the time to try to be "efficient." Interrupts are not like software signals. What you need to think of, instead, is being thorough. Make sure that an interrupt does not wander by, trying to tell you something, and you "efficiently" don't notice. :jawa:

You also need to consider that perhaps the interrupt does not belong to you at all. It may belong to another device, unrelated to yours. Or, by some unhappy luck of the draw, the interrupts could pile-up so that both your device and another device have signaled for attention at precisely the same nano-bleem, so that the interrupt is for (or can be treated as) both your device and someone else's, at the same time. It can get strange. You can never predict it. That's why you need to be conservative. And in any case, the time that you spend inside the routine is a lot less costly than the time the kernel and the CPU have already spent in getting you there.

The only purpose of the "upper half" (initial interrupt-response) processing should be to notice what needs to be done and queue-up the appropriate "lower half" routines to actually do the work... then get out and let the next upper-half routine do its thing. But you will come out ahead if you happen to detect that several identical devices all need servicing and can, by polling their status-registers, stop them from all generating (consecutive, redundant) interrupts.

rstewart 08-16-2005 11:29 AM

Quote:

An interrupt-handler is not necessarily the time to try to be "efficient." Interrupts are not like software signals. What you need to think of, instead, is being thorough. Make sure that an interrupt does not wander by, trying to tell you something, and you "efficiently" don't notice. :jawa:
Uh,

Writing inefficient ISRs is definitely a cause for poor latency issues. In an ISR you definitely do want to be as efficient as possible, but I do agree that you also want to be thorough. You want to come in, process everything that needs to be processed in order to completely service the interrupt, and get out of Dodge - writing the most efficient and optimized code that you can write. The longer you stay in an ISR, the longer you are holding off lower priority events.

Elric of Grans 08-16-2005 09:03 PM

Thanks for the advice. I have observed interrupts working for any device I select now.

ISR do need to be efficient, however, especially for embedded systems, such as this one. If I make this ISR much longer than it is now, then the whole thing falls over under certain situations.


All times are GMT -5. The time now is 09:31 AM.