summaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRam Vepa <ram.vepa@qlogic.com>2011-05-27 13:41:55 +0000
committerRoland Dreier <roland@purestorage.com>2011-07-18 12:09:23 -0700
commit4356d0b64b9be53c507f66c572c1e275b4529239 (patch)
tree58c15fe0987ae06873f2fe8a1b188db73fbaf796 /drivers/infiniband
parent2df4f7579d212e8e0df7c8a24f57bf90f23fd516 (diff)
downloadlinux-4356d0b64b9be53c507f66c572c1e275b4529239.tar.gz
linux-4356d0b64b9be53c507f66c572c1e275b4529239.tar.bz2
linux-4356d0b64b9be53c507f66c572c1e275b4529239.zip
IB/qib: Fix potential deadlock with link down interrupt
There is a possibility of a deadlock due to the way locks are acquired and released in qib_set_uevent_bits(). The function qib_set_uevent_bits() is called in process context and it uses spin_lock() and spin_unlock(). This same lock is acquired/released in interrupt context which can lead to a deadlock when running on the same cpu. The fix is to replace spin_lock() and spin_unlock() with spin_lock_irqsave() and spin_unlock_irqrestore() respectively in qib_set_uevent_bits(). 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_file_ops.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index a94a46001745..26253039d2c7 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -1905,8 +1905,9 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
struct qib_ctxtdata *rcd;
unsigned ctxt;
int ret = 0;
+ unsigned long flags;
- spin_lock(&ppd->dd->uctxt_lock);
+ spin_lock_irqsave(&ppd->dd->uctxt_lock, flags);
for (ctxt = ppd->dd->first_user_ctxt; ctxt < ppd->dd->cfgctxts;
ctxt++) {
rcd = ppd->dd->rcd[ctxt];
@@ -1925,7 +1926,7 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)
ret = 1;
break;
}
- spin_unlock(&ppd->dd->uctxt_lock);
+ spin_unlock_irqrestore(&ppd->dd->uctxt_lock, flags);
return ret;
}