- Placing the request on a circular queue from ISR ( Also call tasklet_schedule).
- The tasklet can pick the request from queue which will be protected by spin_lock.
This e-mail, including any attachments, may be confidential, privileged or otherwise legally protected. It is intended only for the addressee. If you received this e-mail in error or from someone who was not authorized to send it to you, do not disseminate, copy or otherwise use this e-mail or its attachments. Please notify the sender immediately by reply e-mail and delete the e-mail from your system.
From: kernelnewbies-bounce@xxxxxxxxxxxx [mailto:kernelnewbies-bounce@xxxxxxxxxxxx] On Behalf Of Olav Torheim
Sent: Thursday, September 15, 2005 12:25 PM
To: kernelnewbies@xxxxxxxxxxxx
Subject: Interrupt problems
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
};/* 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);};
Thanks for answering. Do you have any concrete code examples of how this can be done?
Olav
On 9/15/05, Aggarwal, Vikas (OFT) <Vikas.Aggarwal@xxxxxxxxxxxxxxx> wrote: