aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/qib/qib_qp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_qp.c')
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 693041b076f0..4850d03870c2 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. 2 * Copyright (c) 2012 Intel Corporation. All rights reserved.
3 * All rights reserved. 3 * Copyright (c) 2006 - 2012 QLogic Corporation. * All rights reserved.
4 * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. 4 * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
5 * 5 *
6 * This software is available to you under a choice of one of two 6 * This software is available to you under a choice of one of two
@@ -250,23 +250,33 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
250 250
251 spin_lock_irqsave(&dev->qpt_lock, flags); 251 spin_lock_irqsave(&dev->qpt_lock, flags);
252 252
253 if (ibp->qp0 == qp) { 253 if (rcu_dereference_protected(ibp->qp0,
254 lockdep_is_held(&dev->qpt_lock)) == qp) {
254 atomic_dec(&qp->refcount); 255 atomic_dec(&qp->refcount);
255 rcu_assign_pointer(ibp->qp0, NULL); 256 rcu_assign_pointer(ibp->qp0, NULL);
256 } else if (ibp->qp1 == qp) { 257 } else if (rcu_dereference_protected(ibp->qp1,
258 lockdep_is_held(&dev->qpt_lock)) == qp) {
257 atomic_dec(&qp->refcount); 259 atomic_dec(&qp->refcount);
258 rcu_assign_pointer(ibp->qp1, NULL); 260 rcu_assign_pointer(ibp->qp1, NULL);
259 } else { 261 } else {
260 struct qib_qp *q, **qpp; 262 struct qib_qp *q;
263 struct qib_qp __rcu **qpp;
261 264
262 qpp = &dev->qp_table[n]; 265 qpp = &dev->qp_table[n];
263 for (; (q = *qpp) != NULL; qpp = &q->next) 266 q = rcu_dereference_protected(*qpp,
267 lockdep_is_held(&dev->qpt_lock));
268 for (; q; qpp = &q->next) {
264 if (q == qp) { 269 if (q == qp) {
265 atomic_dec(&qp->refcount); 270 atomic_dec(&qp->refcount);
266 rcu_assign_pointer(*qpp, qp->next); 271 *qpp = qp->next;
267 qp->next = NULL; 272 rcu_assign_pointer(qp->next, NULL);
273 q = rcu_dereference_protected(*qpp,
274 lockdep_is_held(&dev->qpt_lock));
268 break; 275 break;
269 } 276 }
277 q = rcu_dereference_protected(*qpp,
278 lockdep_is_held(&dev->qpt_lock));
279 }
270 } 280 }
271 281
272 spin_unlock_irqrestore(&dev->qpt_lock, flags); 282 spin_unlock_irqrestore(&dev->qpt_lock, flags);
@@ -302,10 +312,12 @@ unsigned qib_free_all_qps(struct qib_devdata *dd)
302 312
303 spin_lock_irqsave(&dev->qpt_lock, flags); 313 spin_lock_irqsave(&dev->qpt_lock, flags);
304 for (n = 0; n < dev->qp_table_size; n++) { 314 for (n = 0; n < dev->qp_table_size; n++) {
305 qp = dev->qp_table[n]; 315 qp = rcu_dereference_protected(dev->qp_table[n],
316 lockdep_is_held(&dev->qpt_lock));
306 rcu_assign_pointer(dev->qp_table[n], NULL); 317 rcu_assign_pointer(dev->qp_table[n], NULL);
307 318
308 for (; qp; qp = qp->next) 319 for (; qp; qp = rcu_dereference_protected(qp->next,
320 lockdep_is_held(&dev->qpt_lock)))
309 qp_inuse++; 321 qp_inuse++;
310 } 322 }
311 spin_unlock_irqrestore(&dev->qpt_lock, flags); 323 spin_unlock_irqrestore(&dev->qpt_lock, flags);
@@ -337,7 +349,8 @@ struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
337 unsigned n = qpn_hash(dev, qpn); 349 unsigned n = qpn_hash(dev, qpn);
338 350
339 rcu_read_lock(); 351 rcu_read_lock();
340 for (qp = dev->qp_table[n]; rcu_dereference(qp); qp = qp->next) 352 for (qp = rcu_dereference(dev->qp_table[n]); qp;
353 qp = rcu_dereference(qp->next))
341 if (qp->ibqp.qp_num == qpn) 354 if (qp->ibqp.qp_num == qpn)
342 break; 355 break;
343 } 356 }