Hi All,
On my current work, I have been dealing with workq.
In my ISR I am scheduling a workq to read interrupt status registers. Before scheduling I have a check if(!work_pending(work)).
This is because, even in case of different interrupt, already scheduled workq can serve. But if currently scheduled workq is running, then we will schedule another one to ensure no interrupt is missed.
Now, I have observed, when we queuing a work i.e insert_work(), linux set WORK_STRUCT_PENDING bit of work->data. And in run_workqueue() it clears the same. Which theoretically means, whenever a work is within queue its WORK_STRUCT_PENDING will be set and once it will get the CPU to run WORK_STRUCT_PENDING will be cleared.
As per this logic, my if(!work_pending(work)) should work good, but I have seen, if interrupts are generated very fast, say if I continuously generate any interrupt (which are placed at initial positions of interrupt status register) for 30-40 sec, my interrupt bits will be unread (those are read and clear bits). and so further these interrupt wont be generated until some other interrupt occurred and cause to schedule a workq to read all status registers.
I am using I2C to read the status registers.
Any, reason for this behavior???
my demo code
Code:
static void my_workq(struct work_struct *work)
{
for MAX_NUM_STATUS_REGISTER
read all and store in a local variable
for all set bit in local variable call corresponding handler
}
static irqreturn_t my_isr(int irq, void *dev_id)
{
if(!work_pending(mywork))
schedule_work(mywork);
}