When force_irqthreads is true, the top halve is already threaded. There's no need to spread the work over 2 threads in such case. Signed-off-by: Kurt Van Dijck <dev.kurt@xxxxxxxxxxxxxxxxxxxxxx> --- drivers/net/can/c_can/c_can.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index d25a0b7..3dea83e 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -1099,6 +1099,16 @@ static irqreturn_t c_can_isr(int irq, void *dev_id) return IRQ_WAKE_THREAD; } +static irqreturn_t c_can_isr_force_threaded(int irq, void *dev_id) +{ + irqreturn_t result; + + result = c_can_isr(irq, dev_id); + if (result == IRQ_WAKE_THREAD) + result = c_can_thrd(irq, dev_id); + return result; +} + static int c_can_open(struct net_device *dev) { int err; @@ -1115,8 +1125,17 @@ static int c_can_open(struct net_device *dev) } /* register interrupt handler */ - err = request_threaded_irq(dev->irq, &c_can_isr, c_can_thrd, - IRQF_SHARED, dev->name, dev); + if (force_irqthreads) + /* in case of forced irq threading, the top-halve is already + * a thread, so the bottom halve could be appended directly. + * For code re-use, the combined handler calls top & bottom + * rather than recoding everything from scratch + */ + err = request_threaded_irq(dev->irq, &c_can_isr_force_threaded, + NULL, IRQF_SHARED, dev->name, dev); + else + err = request_threaded_irq(dev->irq, &c_can_isr, + c_can_thrd, IRQF_SHARED, dev->name, dev); if (err < 0) { netdev_err(dev, "failed to request interrupt\n"); goto exit_irq_fail; -- 1.8.5.rc3