IB/qib: Fix QP RCU sparse warnings
Commit af061a644a0e ("IB/qib: Use RCU for qpn lookup") introduced sparse
warnings.
This patch corrects those issues.
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 693041b..4850d03 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
- * All rights reserved.
+ * Copyright (c) 2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2012 QLogic Corporation. * All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -250,23 +250,33 @@
spin_lock_irqsave(&dev->qpt_lock, flags);
- if (ibp->qp0 == qp) {
+ if (rcu_dereference_protected(ibp->qp0,
+ lockdep_is_held(&dev->qpt_lock)) == qp) {
atomic_dec(&qp->refcount);
rcu_assign_pointer(ibp->qp0, NULL);
- } else if (ibp->qp1 == qp) {
+ } else if (rcu_dereference_protected(ibp->qp1,
+ lockdep_is_held(&dev->qpt_lock)) == qp) {
atomic_dec(&qp->refcount);
rcu_assign_pointer(ibp->qp1, NULL);
} else {
- struct qib_qp *q, **qpp;
+ struct qib_qp *q;
+ struct qib_qp __rcu **qpp;
qpp = &dev->qp_table[n];
- for (; (q = *qpp) != NULL; qpp = &q->next)
+ q = rcu_dereference_protected(*qpp,
+ lockdep_is_held(&dev->qpt_lock));
+ for (; q; qpp = &q->next) {
if (q == qp) {
atomic_dec(&qp->refcount);
- rcu_assign_pointer(*qpp, qp->next);
- qp->next = NULL;
+ *qpp = qp->next;
+ rcu_assign_pointer(qp->next, NULL);
+ q = rcu_dereference_protected(*qpp,
+ lockdep_is_held(&dev->qpt_lock));
break;
}
+ q = rcu_dereference_protected(*qpp,
+ lockdep_is_held(&dev->qpt_lock));
+ }
}
spin_unlock_irqrestore(&dev->qpt_lock, flags);
@@ -302,10 +312,12 @@
spin_lock_irqsave(&dev->qpt_lock, flags);
for (n = 0; n < dev->qp_table_size; n++) {
- qp = dev->qp_table[n];
+ qp = rcu_dereference_protected(dev->qp_table[n],
+ lockdep_is_held(&dev->qpt_lock));
rcu_assign_pointer(dev->qp_table[n], NULL);
- for (; qp; qp = qp->next)
+ for (; qp; qp = rcu_dereference_protected(qp->next,
+ lockdep_is_held(&dev->qpt_lock)))
qp_inuse++;
}
spin_unlock_irqrestore(&dev->qpt_lock, flags);
@@ -337,7 +349,8 @@
unsigned n = qpn_hash(dev, qpn);
rcu_read_lock();
- for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next)
+ for (qp = rcu_dereference(dev->qp_table[n]); qp;
+ qp = rcu_dereference(qp->next))
if (qp->ibqp.qp_num == qpn)
break;
}