Reputation: 25
Is there any side-effects of calling enable_irq()
from workqueues ? I see exceptions reported when this is done through workqueue.
static void mmxx_irq_worker(struct work_struct *work)
{
struct mmxx_data *mma = container_of(work, struct mmxx_data, accel_work);
if (unlikely(read_and_report_abs(mmxx) != 0))
dev_err(&mmxx_i2c_client->dev, "read_and_report failed\n");
enable_irq(mmxx->irq);
}
[ 2029.755981] Exception stack(0xd51fbe70 to 0xd51fbeb8)
[ 2029.761718] be60: c09cee10 600b0113 00000001 00000000
[ 2029.771057] be80: c09cedc0 00000001 000002bf d508bb4c 000002d6 c09b3ac0 fffffffe d51fbec4
[ 2029.780426] bea0: d51fbec8 d51fbeb8 c00b6458 c06e5b28 400b0113 ffffffff
[ 2029.787841] r6:ffffffff r5:400b0113 r4:c06e5b28 r3:c00b6458
[ 2029.795379] [<c06e5b04>] (_raw_spin_unlock_irqrestore+0x0/0x50) from [<c00b6458>] (__irq_put_desc_unlock+0x1c/0x40)
[ 2029.807189] [<c00b643c>] (__irq_put_desc_unlock+0x0/0x40) from [<c00b7c2c>] (enable_irq+0x54/0x7c)
[ 2029.817352] r5:000001e5 r4:c09cedc0
[ 2029.821990] [<c00b7bd8>] (enable_irq+0x0/0x7c) from [<c0357394>] (mmxx_irq_worker+0x1b8/0x238)
[ 2029.832061] r5:c0a1d8b4 r4:c0abb340
[ 2029.836700] [<c03571dc>] (mmxx_irq_worker+0x0/0x238) from [<c0063e70>] (process_one_work+0x134/0x4ac)
[ 2029.847442] [<c0063d3c>] (process_one_work+0x0/0x4ac) from [<c0064374>] (worker_thread+0x18c/0x3d8)
[ 2029.857757] [<c00641e8>] (worker_thread+0x0/0x3d8) from [<c0068df8>] (kthread+0x90/0x9c)
[ 2029.866790] [<c0068d68>] (kthread+0x0/0x9c) from [<c004c9f4>] (do_exit+0x0/0x81c)
[ 2029.875366] r6:c004c9f4 r5:c0068d68 r4:d699dec4
Upvotes: 1
Views: 279
Reputation: 14743
Workqueue is running in process context with IRQs enabled. So you should not do enable_irq()
in workqueue handler, unless you disabled this IRQ earlier.
But you also shouldn't get that error. Probably mmxx->irq
number is wrong or not requested. Pay attention to this line in your backtrace:
(__irq_put_desc_unlock) from (enable_irq)
It's happening in enable_irq() function:
void enable_irq(unsigned int irq)
{
unsigned long flags;
struct irq_desc *desc = irq_get_desc_buslock(irq, &flags,
IRQ_GET_DESC_CHECK_GLOBAL);
if (!desc)
return;
if (WARN(!desc->irq_data.chip,
KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
goto out;
__enable_irq(desc, irq);
out:
irq_put_desc_busunlock(desc, flags);
}
Where irq_put_desc_busunlock()
is basically __irq_put_desc_unlock()
.
Now you can see that the only way this chain is executed is when your desc->irq_data.chip
is NULL
. Also you should observe output like this in your backtrace:
"enable_irq before setup/request_irq: irq %u\n"
From here I would say your mmxx->irq
number you are passing to enable_irq()
is wrong (0
?) or this IRQ wasn't requested earlier. Try to check what exactly value you have in mmxx->irq
and make sure have requested it before your workqueue handler is called first time.
Anyway, removing enable_irq()
line from your code should fix the problem (as you probably don't really need to do this).
Upvotes: 1