diff options
author | Jubin John <jubin.john@intel.com> | 2016-04-14 15:31:53 (GMT) |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-04-28 20:32:29 (GMT) |
commit | d35cf74492c5ba0d8e1c08755c78be4ef3af650e (patch) | |
tree | 0ff2d6ffff27edf2af8185ece0e9770e30c13f63 /drivers/staging/rdma/hfi1/init.c | |
parent | 1cbaa670355e4a4e339ac97167fb8ecf536045d3 (diff) | |
download | linux-d35cf74492c5ba0d8e1c08755c78be4ef3af650e.tar.xz |
IB/hfi1: Serialize hrtimer function calls
hrtimer functions do not guarantee serialization, so we extend the
cca_timer_lock to cover the hrtimer_forward_now() in the hrtimer
callback handler and the hrtimer_start() in process_becn(). This
prevents races between these 2 functions to update the hrtimer state
leading to problems such as:
kernel BUG at kernel/hrtimer.c:1282!
encountered during validation of the CCA feature.
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/staging/rdma/hfi1/init.c')
-rw-r--r-- | drivers/staging/rdma/hfi1/init.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/drivers/staging/rdma/hfi1/init.c b/drivers/staging/rdma/hfi1/init.c index b1582b5..502b7cf 100644 --- a/drivers/staging/rdma/hfi1/init.c +++ b/drivers/staging/rdma/hfi1/init.c @@ -422,9 +422,10 @@ static enum hrtimer_restart cca_timer_fn(struct hrtimer *t) struct cca_timer *cca_timer; struct hfi1_pportdata *ppd; int sl; - u16 ccti, ccti_timer, ccti_min; + u16 ccti_timer, ccti_min; struct cc_state *cc_state; unsigned long flags; + enum hrtimer_restart ret = HRTIMER_NORESTART; cca_timer = container_of(t, struct cca_timer, hrtimer); ppd = cca_timer->ppd; @@ -450,24 +451,21 @@ static enum hrtimer_restart cca_timer_fn(struct hrtimer *t) spin_lock_irqsave(&ppd->cca_timer_lock, flags); - ccti = cca_timer->ccti; - - if (ccti > ccti_min) { + if (cca_timer->ccti > ccti_min) { cca_timer->ccti--; set_link_ipg(ppd); } - spin_unlock_irqrestore(&ppd->cca_timer_lock, flags); - - rcu_read_unlock(); - - if (ccti > ccti_min) { + if (cca_timer->ccti > ccti_min) { unsigned long nsec = 1024 * ccti_timer; /* ccti_timer is in units of 1.024 usec */ hrtimer_forward_now(t, ns_to_ktime(nsec)); - return HRTIMER_RESTART; + ret = HRTIMER_RESTART; } - return HRTIMER_NORESTART; + + spin_unlock_irqrestore(&ppd->cca_timer_lock, flags); + rcu_read_unlock(); + return ret; } /* |