diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2017-01-18 15:30:51 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-09 02:08:28 -0500 |
commit | a150e08704b24311a4d6215aade46691d6a7006a (patch) | |
tree | fa985d429a48e8368e152f5eb3e9321d2f85b336 /net/can | |
parent | a93ae8dccc3c723ed7a629dab37a3392387acd79 (diff) |
can: bcm: fix hrtimer/tasklet termination in bcm op removal
commit a06393ed03167771246c4c43192d9c264bc48412 upstream.
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>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/can')
-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 436a7537e6a9..5e9ed5ec2860 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); |