aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@qlogic.com>2011-02-10 09:11:28 -0500
committerRoland Dreier <roland@purestorage.com>2011-02-10 14:24:08 -0500
commit414ed90cee32486c50f91b28990443e0dc21c868 (patch)
treebcb6fc2551b3bb230c6aa9ebf18502728f573228 /drivers/infiniband
parent831d52bc153971b70e64eccfbed2b232394f22f8 (diff)
IB/qib: Fix double add_timer()
The following panic BUG_ON occurs during qib testing: Kernel BUG at include/linux/timer.h:82 RIP [<ffffffff881f7109>] :ib_qib:start_timer+0x73/0x89 RSP <ffffffff80425bd0> <0>Kernel panic - not syncing: Fatal exception <0>Dumping qib trace buffer from panic qib_set_lid INFO: IB0:1 got a lid: 0xf8 Done dumping qib trace buffer BUG: warning at kernel/panic.c:137/panic() (Tainted: G The flaw is due to a missing state test when processing responses that results in an add_timer() call when the same timer is already queued. This code was executing in parallel with a QP destroy on another CPU that had changed the state to reset, but the missing test caused to response handling code to run on into the panic. Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/qib/qib_rc.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c
index 8245237b67ce..31e09b05a1a7 100644
--- a/drivers/infiniband/hw/qib/qib_rc.c
+++ b/drivers/infiniband/hw/qib/qib_rc.c
@@ -1439,6 +1439,8 @@ static void qib_rc_rcv_resp(struct qib_ibport *ibp,
1439 } 1439 }
1440 1440
1441 spin_lock_irqsave(&qp->s_lock, flags); 1441 spin_lock_irqsave(&qp->s_lock, flags);
1442 if (!(ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK))
1443 goto ack_done;
1442 1444
1443 /* Ignore invalid responses. */ 1445 /* Ignore invalid responses. */
1444 if (qib_cmp24(psn, qp->s_next_psn) >= 0) 1446 if (qib_cmp24(psn, qp->s_next_psn) >= 0)