Skip to content

Commit c53a6ee

Browse files
Oliver Hartkoppdavem330
authored andcommitted
can: fix slowpath issue in hrtimer callback function
Due to the loopback functionality in can_send() we can not invoke it from hardirq context which was done inside the bcm_tx_timeout_handler() hrtimer callback: [ 700.361154] [<c012228c>] warn_slowpath+0x80/0xb6 [ 700.361163] [<c013d559>] valid_state+0x125/0x136 [ 700.361171] [<c013d858>] mark_lock+0x18e/0x332 [ 700.361180] [<c013e300>] __lock_acquire+0x12e/0xb1e [ 700.361189] [<f8ab5915>] bcm_tx_timeout_handler+0x0/0xbc [can_bcm] [ 700.361198] [<c031e20a>] dev_queue_xmit+0x191/0x479 [ 700.361206] [<c01262a7>] __local_bh_disable+0x2b/0x64 [ 700.361213] [<c031e20a>] dev_queue_xmit+0x191/0x479 [ 700.361225] [<f8aa69a1>] can_send+0xd7/0x11a [can] [ 700.361235] [<f8ab522b>] bcm_can_tx+0x9d/0xd9 [can_bcm] [ 700.361245] [<f8ab597f>] bcm_tx_timeout_handler+0x6a/0xbc [can_bcm] [ 700.361255] [<f8ab5915>] bcm_tx_timeout_handler+0x0/0xbc [can_bcm] [ 700.361263] [<c0134143>] __run_hrtimer+0x5a/0x86 [ 700.361273] [<f8ab5915>] bcm_tx_timeout_handler+0x0/0xbc [can_bcm] [ 700.361282] [<c0134a50>] hrtimer_interrupt+0xb9/0x110 This patch moves the rest of the functionality from the hrtimer callback to the already existing tasklet to fix this slowpath problem. Signed-off-by: Oliver Hartkopp <oliver@hartkopp.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d57bc36 commit c53a6ee

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

net/can/bcm.c

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -347,51 +347,54 @@ static void bcm_tx_timeout_tsklet(unsigned long data)
347347
struct bcm_op *op = (struct bcm_op *)data;
348348
struct bcm_msg_head msg_head;
349349

350-
/* create notification to user */
351-
msg_head.opcode = TX_EXPIRED;
352-
msg_head.flags = op->flags;
353-
msg_head.count = op->count;
354-
msg_head.ival1 = op->ival1;
355-
msg_head.ival2 = op->ival2;
356-
msg_head.can_id = op->can_id;
357-
msg_head.nframes = 0;
358-
359-
bcm_send_to_user(op, &msg_head, NULL, 0);
360-
}
361-
362-
/*
363-
* bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
364-
*/
365-
static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
366-
{
367-
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
368-
enum hrtimer_restart ret = HRTIMER_NORESTART;
369-
370350
if (op->kt_ival1.tv64 && (op->count > 0)) {
371351

372352
op->count--;
373-
if (!op->count && (op->flags & TX_COUNTEVT))
374-
tasklet_schedule(&op->tsklet);
353+
if (!op->count && (op->flags & TX_COUNTEVT)) {
354+
355+
/* create notification to user */
356+
msg_head.opcode = TX_EXPIRED;
357+
msg_head.flags = op->flags;
358+
msg_head.count = op->count;
359+
msg_head.ival1 = op->ival1;
360+
msg_head.ival2 = op->ival2;
361+
msg_head.can_id = op->can_id;
362+
msg_head.nframes = 0;
363+
364+
bcm_send_to_user(op, &msg_head, NULL, 0);
365+
}
375366
}
376367

377368
if (op->kt_ival1.tv64 && (op->count > 0)) {
378369

379370
/* send (next) frame */
380371
bcm_can_tx(op);
381-
hrtimer_forward(hrtimer, ktime_get(), op->kt_ival1);
382-
ret = HRTIMER_RESTART;
372+
hrtimer_start(&op->timer,
373+
ktime_add(ktime_get(), op->kt_ival1),
374+
HRTIMER_MODE_ABS);
383375

384376
} else {
385377
if (op->kt_ival2.tv64) {
386378

387379
/* send (next) frame */
388380
bcm_can_tx(op);
389-
hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
390-
ret = HRTIMER_RESTART;
381+
hrtimer_start(&op->timer,
382+
ktime_add(ktime_get(), op->kt_ival2),
383+
HRTIMER_MODE_ABS);
391384
}
392385
}
386+
}
393387

394-
return ret;
388+
/*
389+
* bcm_tx_timeout_handler - performes cyclic CAN frame transmissions
390+
*/
391+
static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
392+
{
393+
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
394+
395+
tasklet_schedule(&op->tsklet);
396+
397+
return HRTIMER_NORESTART;
395398
}
396399

397400
/*

0 commit comments

Comments
 (0)