Commit f7cf9a61 authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Roland Dreier

IB/qib: Remove atomic_inc_not_zero() from QP RCU

Follow Documentation/RCU/rcuref.txt guidance in removing
atomic_inc_not_zero() from QP RCU implementation.

This patch also removes an unneeded synchronize_rcu() in the add path.
Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarMike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 8469ba39
/* /*
* Copyright (c) 2012 Intel Corporation. All rights reserved. * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved.
* Copyright (c) 2006 - 2012 QLogic Corporation. * All rights reserved. * Copyright (c) 2006 - 2012 QLogic Corporation. * All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
* *
...@@ -222,8 +222,8 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp) ...@@ -222,8 +222,8 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
unsigned long flags; unsigned long flags;
unsigned n = qpn_hash(dev, qp->ibqp.qp_num); unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
spin_lock_irqsave(&dev->qpt_lock, flags);
atomic_inc(&qp->refcount); atomic_inc(&qp->refcount);
spin_lock_irqsave(&dev->qpt_lock, flags);
if (qp->ibqp.qp_num == 0) if (qp->ibqp.qp_num == 0)
rcu_assign_pointer(ibp->qp0, qp); rcu_assign_pointer(ibp->qp0, qp);
...@@ -235,7 +235,6 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp) ...@@ -235,7 +235,6 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
} }
spin_unlock_irqrestore(&dev->qpt_lock, flags); spin_unlock_irqrestore(&dev->qpt_lock, flags);
synchronize_rcu();
} }
/* /*
...@@ -247,36 +246,39 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp) ...@@ -247,36 +246,39 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp)
struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num); struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
unsigned n = qpn_hash(dev, qp->ibqp.qp_num); unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
unsigned long flags; unsigned long flags;
int removed = 1;
spin_lock_irqsave(&dev->qpt_lock, flags); spin_lock_irqsave(&dev->qpt_lock, flags);
if (rcu_dereference_protected(ibp->qp0, if (rcu_dereference_protected(ibp->qp0,
lockdep_is_held(&dev->qpt_lock)) == qp) { lockdep_is_held(&dev->qpt_lock)) == qp) {
atomic_dec(&qp->refcount);
rcu_assign_pointer(ibp->qp0, NULL); rcu_assign_pointer(ibp->qp0, NULL);
} else if (rcu_dereference_protected(ibp->qp1, } else if (rcu_dereference_protected(ibp->qp1,
lockdep_is_held(&dev->qpt_lock)) == qp) { lockdep_is_held(&dev->qpt_lock)) == qp) {
atomic_dec(&qp->refcount);
rcu_assign_pointer(ibp->qp1, NULL); rcu_assign_pointer(ibp->qp1, NULL);
} else { } else {
struct qib_qp *q; struct qib_qp *q;
struct qib_qp __rcu **qpp; struct qib_qp __rcu **qpp;
removed = 0;
qpp = &dev->qp_table[n]; qpp = &dev->qp_table[n];
for (; (q = rcu_dereference_protected(*qpp, for (; (q = rcu_dereference_protected(*qpp,
lockdep_is_held(&dev->qpt_lock))) != NULL; lockdep_is_held(&dev->qpt_lock))) != NULL;
qpp = &q->next) qpp = &q->next)
if (q == qp) { if (q == qp) {
atomic_dec(&qp->refcount);
rcu_assign_pointer(*qpp, rcu_assign_pointer(*qpp,
rcu_dereference_protected(qp->next, rcu_dereference_protected(qp->next,
lockdep_is_held(&dev->qpt_lock))); lockdep_is_held(&dev->qpt_lock)));
removed = 1;
break; break;
} }
} }
spin_unlock_irqrestore(&dev->qpt_lock, flags); spin_unlock_irqrestore(&dev->qpt_lock, flags);
synchronize_rcu(); if (removed) {
synchronize_rcu();
atomic_dec(&qp->refcount);
}
} }
/** /**
...@@ -334,26 +336,25 @@ struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn) ...@@ -334,26 +336,25 @@ struct qib_qp *qib_lookup_qpn(struct qib_ibport *ibp, u32 qpn)
{ {
struct qib_qp *qp = NULL; struct qib_qp *qp = NULL;
rcu_read_lock();
if (unlikely(qpn <= 1)) { if (unlikely(qpn <= 1)) {
rcu_read_lock();
if (qpn == 0) if (qpn == 0)
qp = rcu_dereference(ibp->qp0); qp = rcu_dereference(ibp->qp0);
else else
qp = rcu_dereference(ibp->qp1); qp = rcu_dereference(ibp->qp1);
if (qp)
atomic_inc(&qp->refcount);
} else { } else {
struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev; struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
unsigned n = qpn_hash(dev, qpn); unsigned n = qpn_hash(dev, qpn);
rcu_read_lock();
for (qp = rcu_dereference(dev->qp_table[n]); qp; for (qp = rcu_dereference(dev->qp_table[n]); qp;
qp = rcu_dereference(qp->next)) qp = rcu_dereference(qp->next))
if (qp->ibqp.qp_num == qpn) if (qp->ibqp.qp_num == qpn) {
atomic_inc(&qp->refcount);
break; break;
}
} }
if (qp)
if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
qp = NULL;
rcu_read_unlock(); rcu_read_unlock();
return qp; return qp;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment