IB/qib: Remove atomic_inc_not_zero() from QP RCU
authorMike Marciniszyn <mike.marciniszyn@intel.com>
Sat, 15 Jun 2013 21:06:58 +0000 (17:06 -0400)
committerRoland Dreier <roland@purestorage.com>
Sat, 22 Jun 2013 00:19:46 +0000 (17:19 -0700)
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: Dean Luick <dean.luick@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
drivers/infiniband/hw/qib/qib_qp.c

index a6a2cc2ba260ddd80ca6e23982864ec8e969e9b4..c1f573a331c7f04ea78d203f8135bab8a93523d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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) 2005, 2006 PathScale, Inc. All rights reserved.
  *
@@ -222,8 +222,8 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
        unsigned long flags;
        unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
 
-       spin_lock_irqsave(&dev->qpt_lock, flags);
        atomic_inc(&qp->refcount);
+       spin_lock_irqsave(&dev->qpt_lock, flags);
 
        if (qp->ibqp.qp_num == 0)
                rcu_assign_pointer(ibp->qp0, qp);
@@ -235,7 +235,6 @@ static void insert_qp(struct qib_ibdev *dev, struct qib_qp *qp)
        }
 
        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)
        struct qib_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
        unsigned n = qpn_hash(dev, qp->ibqp.qp_num);
        unsigned long flags;
+       int removed = 1;
 
        spin_lock_irqsave(&dev->qpt_lock, flags);
 
        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 (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;
                struct qib_qp __rcu **qpp;
 
+               removed = 0;
                qpp = &dev->qp_table[n];
                for (; (q = rcu_dereference_protected(*qpp,
                                lockdep_is_held(&dev->qpt_lock))) != NULL;
                                qpp = &q->next)
                        if (q == qp) {
-                               atomic_dec(&qp->refcount);
                                rcu_assign_pointer(*qpp,
                                        rcu_dereference_protected(qp->next,
                                         lockdep_is_held(&dev->qpt_lock)));
+                               removed = 1;
                                break;
                        }
        }
 
        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)
 {
        struct qib_qp *qp = NULL;
 
+       rcu_read_lock();
        if (unlikely(qpn <= 1)) {
-               rcu_read_lock();
                if (qpn == 0)
                        qp = rcu_dereference(ibp->qp0);
                else
                        qp = rcu_dereference(ibp->qp1);
+               if (qp)
+                       atomic_inc(&qp->refcount);
        } else {
                struct qib_ibdev *dev = &ppd_from_ibp(ibp)->dd->verbs_dev;
                unsigned n = qpn_hash(dev, qpn);
 
-               rcu_read_lock();
                for (qp = rcu_dereference(dev->qp_table[n]); qp;
                        qp = rcu_dereference(qp->next))
-                       if (qp->ibqp.qp_num == qpn)
+                       if (qp->ibqp.qp_num == qpn) {
+                               atomic_inc(&qp->refcount);
                                break;
+                       }
        }
-       if (qp)
-               if (unlikely(!atomic_inc_not_zero(&qp->refcount)))
-                       qp = NULL;
-
        rcu_read_unlock();
        return qp;
 }