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>
This commit is contained in:
parent
1cbaa67035
commit
d35cf74492
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -2021,8 +2021,6 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
|
|||
if (sl >= OPA_MAX_SLS)
|
||||
return;
|
||||
|
||||
cca_timer = &ppd->cca_timer[sl];
|
||||
|
||||
cc_state = get_cc_state(ppd);
|
||||
|
||||
if (!cc_state)
|
||||
|
@ -2041,6 +2039,7 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
|
|||
|
||||
spin_lock_irqsave(&ppd->cca_timer_lock, flags);
|
||||
|
||||
cca_timer = &ppd->cca_timer[sl];
|
||||
if (cca_timer->ccti < ccti_limit) {
|
||||
if (cca_timer->ccti + ccti_incr <= ccti_limit)
|
||||
cca_timer->ccti += ccti_incr;
|
||||
|
@ -2049,8 +2048,6 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
|
|||
set_link_ipg(ppd);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ppd->cca_timer_lock, flags);
|
||||
|
||||
ccti = cca_timer->ccti;
|
||||
|
||||
if (!hrtimer_active(&cca_timer->hrtimer)) {
|
||||
|
@ -2061,6 +2058,8 @@ void process_becn(struct hfi1_pportdata *ppd, u8 sl, u16 rlid, u32 lqpn,
|
|||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ppd->cca_timer_lock, flags);
|
||||
|
||||
if ((trigger_threshold != 0) && (ccti >= trigger_threshold))
|
||||
log_cca_event(ppd, sl, rlid, lqpn, rqpn, svc_type);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue