summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSai Gurrappadi <sgurrappadi@nvidia.com>2014-07-17 23:46:56 -0700
committerManish Tuteja <mtuteja@nvidia.com>2014-07-23 21:43:08 -0700
commit702870feba175554099e181419e871cace19be27 (patch)
treed6af683c30b7d74def99f86e89cbae0c88fea251
parent53268560ddb085ad2fdabd5efaffe2daff91a940 (diff)
staging: ozwpan: Cancel hrtimer before expiry set
Currently oz_timer_add sets the new expiry time before calling hrtimer_start_expires where the timer is actually updated in the timerqueue. However, this update to expiry time is racy because the the hrtimer_set_expires call is being performed from a softirq or a thread's context. The CPU could recieve a hrtimer_interrupt before the hrtimer_start_expires call but after hrtimer_set_expires. This would leave the hrtimer with a new expiry value but with the same position in the rbtree which a subsequent hrtimer_interrupt could use to perform its timerqueue add/del operations with. Leaving the rbtree in this stale/bad state causes some timers to never get serviced. Fix this by first removing the timer from the timerqueue by calling hrtimer_cancel and then updating the expiry time. Bug 200016188 Change-Id: Ib8acb9f2977580e077bbe968a32c6deba992d000 Signed-off-by: Sai Gurrappadi <sgurrappadi@nvidia.com> Reviewed-on: http://git-master/r/439729 Reviewed-by: Peter Boonstoppel <pboonstoppel@nvidia.com> Reviewed-by: Mitch Luban <mluban@nvidia.com> Reviewed-by: Vinayak Pane <vpane@nvidia.com> (cherry picked from commit bad282f7a9bf0cdbef32a6353e1a0154277eaaa7) Reviewed-on: http://git-master/r/440902 Reviewed-by: Anshul Jain (SW) <anshulj@nvidia.com> Tested-by: Anshul Jain (SW) <anshulj@nvidia.com> (cherry picked from commit aa4e6917c9a17ddfed3f14d1128f47d373e85097) Reviewed-on: http://git-master/r/441373
-rw-r--r--drivers/staging/ozwpan/ozproto.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
index 0677386d7f9b..839c3bd81d64 100644
--- a/drivers/staging/ozwpan/ozproto.c
+++ b/drivers/staging/ozwpan/ozproto.c
@@ -592,6 +592,7 @@ void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time)
case OZ_TIMER_TOUT:
case OZ_TIMER_STOP:
if (hrtimer_active(&pd->timeout)) {
+ hrtimer_cancel(&pd->timeout);
hrtimer_set_expires(&pd->timeout, ktime_set(due_time /
MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
NSEC_PER_MSEC));