diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2017-01-18 15:30:51 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2017-01-30 05:05:04 -0500 |
commit | a06393ed03167771246c4c43192d9c264bc48412 (patch) | |
tree | 31a3d03c374065a64e12f25cf628b7aa8edb8159 | |
parent | d1156b489fa734d1af763d6a07b1637c01bb0aed (diff) |
can: bcm: fix hrtimer/tasklet termination in bcm op removal
When removing a bcm tx operation either a hrtimer or a tasklet might run.
As the hrtimer triggers its associated tasklet and vice versa we need to
take care to mutually terminate both handlers.
Reported-by: Michael Josenhans <michael.josenhans@web.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Tested-by: Michael Josenhans <michael.josenhans@web.de>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | net/can/bcm.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c index 5c9407181918..95d13b233c65 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -734,14 +734,23 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, | |||
734 | 734 | ||
735 | static void bcm_remove_op(struct bcm_op *op) | 735 | static void bcm_remove_op(struct bcm_op *op) |
736 | { | 736 | { |
737 | hrtimer_cancel(&op->timer); | 737 | if (op->tsklet.func) { |
738 | hrtimer_cancel(&op->thrtimer); | 738 | while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) || |
739 | 739 | test_bit(TASKLET_STATE_RUN, &op->tsklet.state) || | |
740 | if (op->tsklet.func) | 740 | hrtimer_active(&op->timer)) { |
741 | tasklet_kill(&op->tsklet); | 741 | hrtimer_cancel(&op->timer); |
742 | tasklet_kill(&op->tsklet); | ||
743 | } | ||
744 | } | ||
742 | 745 | ||
743 | if (op->thrtsklet.func) | 746 | if (op->thrtsklet.func) { |
744 | tasklet_kill(&op->thrtsklet); | 747 | while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) || |
748 | test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) || | ||
749 | hrtimer_active(&op->thrtimer)) { | ||
750 | hrtimer_cancel(&op->thrtimer); | ||
751 | tasklet_kill(&op->thrtsklet); | ||
752 | } | ||
753 | } | ||
745 | 754 | ||
746 | if ((op->frames) && (op->frames != &op->sframe)) | 755 | if ((op->frames) && (op->frames != &op->sframe)) |
747 | kfree(op->frames); | 756 | kfree(op->frames); |