Hi all
Right now I am trying to create a driver for a PCI card. The PCI card uses interrupt to report back to the processor when a DMA transfer has occured. When the the interrupt service routine is fired, it checks the interrupt status register on the device. If the status register equals anything else than 0, the service routine goes on placing a new task on the kerneld task queue with the return value from the interrupt status register as part of the task context.
So far so good. My only problem is, what if the device fires another interrupt while the scheduled task is waiting in the task queue. Interrupts are still enabled in my current design, so I am afraid that the interrupt service routine is simply going to change the context of the waiting task and the former interrupt request will be "forgotten" by the device...
What is the best solution to this problem? Disable interrupts while waiting for the scheduled task to run? Adding more logic to the interrupt service routine, for example a counter keeping track of how many interrupt requests have been detected since the last time the task was scheduled? Invoking a separate task for each interrupt request?
I hope somebody can give me some advice.
Olav Torheim
Source code is shown below:
/* Setup the task structure for the rorcdriver_dispatcher routine.
This task will be scheduled by the interrupt handler: rorcdriver_interrupt
*/
struct tq_struct rorcdriver_dispatcher_task =
{
LIST_HEAD_INIT(rorcdriver_dispatcher_task.list),
0,
&rorcdriver_dispatcher,
NULL
};
This task will be scheduled by the interrupt handler: rorcdriver_interrupt
*/
struct tq_struct rorcdriver_dispatcher_task =
{
LIST_HEAD_INIT(rorcdriver_dispatcher_task.list),
0,
&rorcdriver_dispatcher,
NULL
};
/* The interrupt service routine schedules the dispatcher to service the request from the device.
*/
u32 ireg;
void rorcdriver_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
if ((ireg = readl(baseptr+0x54)) ==0) // Not our interrupt
return;
rorcdriver_dispatcher_task.data = "" // Send the interrupt status register as input data to the dispatcher.
schedule_task(&rorcdriver_dispatcher_task);
};