summaryrefslogtreecommitdiffstats
path: root/net/can
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2019-08-12 08:57:14 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2019-08-13 11:32:20 -0400
commitbf74aa86e111aa3b2fbb25db37e3a3fab71b5b68 (patch)
tree435e301cd5df88ec612cf73ed7063c29ad541b94 /net/can
parent9989f6333c58e5068abf65384b05de3847b07ce1 (diff)
can: bcm: switch timer to HRTIMER_MODE_SOFT and remove hrtimer_tasklet
This patch switches the timer to HRTIMER_MODE_SOFT, which executed the timer callback in softirq context and removes the hrtimer_tasklet. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de> Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'net/can')
-rw-r--r--net/can/bcm.c156
1 files changed, 52 insertions, 104 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c
index eb1d28b8c46a..28fd1a1c8487 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -106,7 +106,6 @@ struct bcm_op {
106 unsigned long frames_abs, frames_filtered; 106 unsigned long frames_abs, frames_filtered;
107 struct bcm_timeval ival1, ival2; 107 struct bcm_timeval ival1, ival2;
108 struct hrtimer timer, thrtimer; 108 struct hrtimer timer, thrtimer;
109 struct tasklet_struct tsklet, thrtsklet;
110 ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg; 109 ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
111 int rx_ifindex; 110 int rx_ifindex;
112 int cfsiz; 111 int cfsiz;
@@ -371,25 +370,34 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
371 } 370 }
372} 371}
373 372
374static void bcm_tx_start_timer(struct bcm_op *op) 373static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
375{ 374{
375 ktime_t ival;
376
376 if (op->kt_ival1 && op->count) 377 if (op->kt_ival1 && op->count)
377 hrtimer_start(&op->timer, 378 ival = op->kt_ival1;
378 ktime_add(ktime_get(), op->kt_ival1),
379 HRTIMER_MODE_ABS);
380 else if (op->kt_ival2) 379 else if (op->kt_ival2)
381 hrtimer_start(&op->timer, 380 ival = op->kt_ival2;
382 ktime_add(ktime_get(), op->kt_ival2), 381 else
383 HRTIMER_MODE_ABS); 382 return false;
383
384 hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
385 return true;
384} 386}
385 387
386static void bcm_tx_timeout_tsklet(unsigned long data) 388static void bcm_tx_start_timer(struct bcm_op *op)
387{ 389{
388 struct bcm_op *op = (struct bcm_op *)data; 390 if (bcm_tx_set_expiry(op, &op->timer))
391 hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS_SOFT);
392}
393
394/* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */
395static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
396{
397 struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
389 struct bcm_msg_head msg_head; 398 struct bcm_msg_head msg_head;
390 399
391 if (op->kt_ival1 && (op->count > 0)) { 400 if (op->kt_ival1 && (op->count > 0)) {
392
393 op->count--; 401 op->count--;
394 if (!op->count && (op->flags & TX_COUNTEVT)) { 402 if (!op->count && (op->flags & TX_COUNTEVT)) {
395 403
@@ -406,22 +414,12 @@ static void bcm_tx_timeout_tsklet(unsigned long data)
406 } 414 }
407 bcm_can_tx(op); 415 bcm_can_tx(op);
408 416
409 } else if (op->kt_ival2) 417 } else if (op->kt_ival2) {
410 bcm_can_tx(op); 418 bcm_can_tx(op);
419 }
411 420
412 bcm_tx_start_timer(op); 421 return bcm_tx_set_expiry(op, &op->timer) ?
413} 422 HRTIMER_RESTART : HRTIMER_NORESTART;
414
415/*
416 * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions
417 */
418static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
419{
420 struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
421
422 tasklet_schedule(&op->tsklet);
423
424 return HRTIMER_NORESTART;
425} 423}
426 424
427/* 425/*
@@ -487,7 +485,7 @@ static void bcm_rx_update_and_send(struct bcm_op *op,
487 /* do not send the saved data - only start throttle timer */ 485 /* do not send the saved data - only start throttle timer */
488 hrtimer_start(&op->thrtimer, 486 hrtimer_start(&op->thrtimer,
489 ktime_add(op->kt_lastmsg, op->kt_ival2), 487 ktime_add(op->kt_lastmsg, op->kt_ival2),
490 HRTIMER_MODE_ABS); 488 HRTIMER_MODE_ABS_SOFT);
491 return; 489 return;
492 } 490 }
493 491
@@ -546,14 +544,21 @@ static void bcm_rx_starttimer(struct bcm_op *op)
546 return; 544 return;
547 545
548 if (op->kt_ival1) 546 if (op->kt_ival1)
549 hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL); 547 hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL_SOFT);
550} 548}
551 549
552static void bcm_rx_timeout_tsklet(unsigned long data) 550/* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */
551static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
553{ 552{
554 struct bcm_op *op = (struct bcm_op *)data; 553 struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
555 struct bcm_msg_head msg_head; 554 struct bcm_msg_head msg_head;
556 555
556 /* if user wants to be informed, when cyclic CAN-Messages come back */
557 if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
558 /* clear received CAN frames to indicate 'nothing received' */
559 memset(op->last_frames, 0, op->nframes * op->cfsiz);
560 }
561
557 /* create notification to user */ 562 /* create notification to user */
558 msg_head.opcode = RX_TIMEOUT; 563 msg_head.opcode = RX_TIMEOUT;
559 msg_head.flags = op->flags; 564 msg_head.flags = op->flags;
@@ -564,25 +569,6 @@ static void bcm_rx_timeout_tsklet(unsigned long data)
564 msg_head.nframes = 0; 569 msg_head.nframes = 0;
565 570
566 bcm_send_to_user(op, &msg_head, NULL, 0); 571 bcm_send_to_user(op, &msg_head, NULL, 0);
567}
568
569/*
570 * bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out
571 */
572static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
573{
574 struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
575
576 /* schedule before NET_RX_SOFTIRQ */
577 tasklet_hi_schedule(&op->tsklet);
578
579 /* no restart of the timer is done here! */
580
581 /* if user wants to be informed, when cyclic CAN-Messages come back */
582 if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
583 /* clear received CAN frames to indicate 'nothing received' */
584 memset(op->last_frames, 0, op->nframes * op->cfsiz);
585 }
586 572
587 return HRTIMER_NORESTART; 573 return HRTIMER_NORESTART;
588} 574}
@@ -590,14 +576,12 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
590/* 576/*
591 * bcm_rx_do_flush - helper for bcm_rx_thr_flush 577 * bcm_rx_do_flush - helper for bcm_rx_thr_flush
592 */ 578 */
593static inline int bcm_rx_do_flush(struct bcm_op *op, int update, 579static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index)
594 unsigned int index)
595{ 580{
596 struct canfd_frame *lcf = op->last_frames + op->cfsiz * index; 581 struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
597 582
598 if ((op->last_frames) && (lcf->flags & RX_THR)) { 583 if ((op->last_frames) && (lcf->flags & RX_THR)) {
599 if (update) 584 bcm_rx_changed(op, lcf);
600 bcm_rx_changed(op, lcf);
601 return 1; 585 return 1;
602 } 586 }
603 return 0; 587 return 0;
@@ -605,11 +589,8 @@ static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
605 589
606/* 590/*
607 * bcm_rx_thr_flush - Check for throttled data and send it to the userspace 591 * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
608 *
609 * update == 0 : just check if throttled data is available (any irq context)
610 * update == 1 : check and send throttled data to userspace (soft_irq context)
611 */ 592 */
612static int bcm_rx_thr_flush(struct bcm_op *op, int update) 593static int bcm_rx_thr_flush(struct bcm_op *op)
613{ 594{
614 int updated = 0; 595 int updated = 0;
615 596
@@ -618,24 +599,16 @@ static int bcm_rx_thr_flush(struct bcm_op *op, int update)
618 599
619 /* for MUX filter we start at index 1 */ 600 /* for MUX filter we start at index 1 */
620 for (i = 1; i < op->nframes; i++) 601 for (i = 1; i < op->nframes; i++)
621 updated += bcm_rx_do_flush(op, update, i); 602 updated += bcm_rx_do_flush(op, i);
622 603
623 } else { 604 } else {
624 /* for RX_FILTER_ID and simple filter */ 605 /* for RX_FILTER_ID and simple filter */
625 updated += bcm_rx_do_flush(op, update, 0); 606 updated += bcm_rx_do_flush(op, 0);
626 } 607 }
627 608
628 return updated; 609 return updated;
629} 610}
630 611
631static void bcm_rx_thr_tsklet(unsigned long data)
632{
633 struct bcm_op *op = (struct bcm_op *)data;
634
635 /* push the changed data to the userspace */
636 bcm_rx_thr_flush(op, 1);
637}
638
639/* 612/*
640 * bcm_rx_thr_handler - the time for blocked content updates is over now: 613 * bcm_rx_thr_handler - the time for blocked content updates is over now:
641 * Check for throttled data and send it to the userspace 614 * Check for throttled data and send it to the userspace
@@ -644,9 +617,7 @@ static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
644{ 617{
645 struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer); 618 struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
646 619
647 tasklet_schedule(&op->thrtsklet); 620 if (bcm_rx_thr_flush(op)) {
648
649 if (bcm_rx_thr_flush(op, 0)) {
650 hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2); 621 hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
651 return HRTIMER_RESTART; 622 return HRTIMER_RESTART;
652 } else { 623 } else {
@@ -742,23 +713,8 @@ static struct bcm_op *bcm_find_op(struct list_head *ops,
742 713
743static void bcm_remove_op(struct bcm_op *op) 714static void bcm_remove_op(struct bcm_op *op)
744{ 715{
745 if (op->tsklet.func) { 716 hrtimer_cancel(&op->timer);
746 while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) || 717 hrtimer_cancel(&op->thrtimer);
747 test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
748 hrtimer_active(&op->timer)) {
749 hrtimer_cancel(&op->timer);
750 tasklet_kill(&op->tsklet);
751 }
752 }
753
754 if (op->thrtsklet.func) {
755 while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
756 test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
757 hrtimer_active(&op->thrtimer)) {
758 hrtimer_cancel(&op->thrtimer);
759 tasklet_kill(&op->thrtsklet);
760 }
761 }
762 718
763 if ((op->frames) && (op->frames != &op->sframe)) 719 if ((op->frames) && (op->frames != &op->sframe))
764 kfree(op->frames); 720 kfree(op->frames);
@@ -991,15 +947,13 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
991 op->ifindex = ifindex; 947 op->ifindex = ifindex;
992 948
993 /* initialize uninitialized (kzalloc) structure */ 949 /* initialize uninitialized (kzalloc) structure */
994 hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 950 hrtimer_init(&op->timer, CLOCK_MONOTONIC,
951 HRTIMER_MODE_REL_SOFT);
995 op->timer.function = bcm_tx_timeout_handler; 952 op->timer.function = bcm_tx_timeout_handler;
996 953
997 /* initialize tasklet for tx countevent notification */
998 tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet,
999 (unsigned long) op);
1000
1001 /* currently unused in tx_ops */ 954 /* currently unused in tx_ops */
1002 hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 955 hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
956 HRTIMER_MODE_REL_SOFT);
1003 957
1004 /* add this bcm_op to the list of the tx_ops */ 958 /* add this bcm_op to the list of the tx_ops */
1005 list_add(&op->list, &bo->tx_ops); 959 list_add(&op->list, &bo->tx_ops);
@@ -1168,20 +1122,14 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1168 op->rx_ifindex = ifindex; 1122 op->rx_ifindex = ifindex;
1169 1123
1170 /* initialize uninitialized (kzalloc) structure */ 1124 /* initialize uninitialized (kzalloc) structure */
1171 hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 1125 hrtimer_init(&op->timer, CLOCK_MONOTONIC,
1126 HRTIMER_MODE_REL_SOFT);
1172 op->timer.function = bcm_rx_timeout_handler; 1127 op->timer.function = bcm_rx_timeout_handler;
1173 1128
1174 /* initialize tasklet for rx timeout notification */ 1129 hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
1175 tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet, 1130 HRTIMER_MODE_REL_SOFT);
1176 (unsigned long) op);
1177
1178 hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
1179 op->thrtimer.function = bcm_rx_thr_handler; 1131 op->thrtimer.function = bcm_rx_thr_handler;
1180 1132
1181 /* initialize tasklet for rx throttle handling */
1182 tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet,
1183 (unsigned long) op);
1184
1185 /* add this bcm_op to the list of the rx_ops */ 1133 /* add this bcm_op to the list of the rx_ops */
1186 list_add(&op->list, &bo->rx_ops); 1134 list_add(&op->list, &bo->rx_ops);
1187 1135
@@ -1227,12 +1175,12 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1227 */ 1175 */
1228 op->kt_lastmsg = 0; 1176 op->kt_lastmsg = 0;
1229 hrtimer_cancel(&op->thrtimer); 1177 hrtimer_cancel(&op->thrtimer);
1230 bcm_rx_thr_flush(op, 1); 1178 bcm_rx_thr_flush(op);
1231 } 1179 }
1232 1180
1233 if ((op->flags & STARTTIMER) && op->kt_ival1) 1181 if ((op->flags & STARTTIMER) && op->kt_ival1)
1234 hrtimer_start(&op->timer, op->kt_ival1, 1182 hrtimer_start(&op->timer, op->kt_ival1,
1235 HRTIMER_MODE_REL); 1183 HRTIMER_MODE_REL_SOFT);
1236 } 1184 }
1237 1185
1238 /* now we can register for can_ids, if we added a new bcm_op */ 1186 /* now we can register for can_ids, if we added a new bcm_op */