diff options
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_qp.c')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_qp.c | 35 |
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 | } |