diff options
author | Sai Gurrappadi <sgurrappadi@nvidia.com> | 2014-07-17 23:46:56 -0700 |
---|---|---|
committer | Manish Tuteja <mtuteja@nvidia.com> | 2014-07-23 21:43:08 -0700 |
commit | 702870feba175554099e181419e871cace19be27 (patch) | |
tree | d6af683c30b7d74def99f86e89cbae0c88fea251 | |
parent | 53268560ddb085ad2fdabd5efaffe2daff91a940 (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.c | 1 |
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)); |