struct ipoib_neigh *neigh;
        unsigned long flags;
 
+       spin_lock_irqsave(&priv->lock, flags);
        neigh = ipoib_neigh_alloc(daddr, dev);
        if (!neigh) {
+               spin_unlock_irqrestore(&priv->lock, flags);
                ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
                return;
        }
 
-       spin_lock_irqsave(&priv->lock, flags);
-
        path = __path_find(dev, daddr + 4);
        if (!path) {
                path = path_rec_create(dev, daddr + 4);
        if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
                return;
 
-       write_lock_bh(&ntbl->rwlock);
+       spin_lock_irqsave(&priv->lock, flags);
 
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                        lockdep_is_held(&ntbl->rwlock));
+                                        lockdep_is_held(&priv->lock));
 
        if (!htbl)
                goto out_unlock;
                struct ipoib_neigh __rcu **np = &htbl->buckets[i];
 
                while ((neigh = rcu_dereference_protected(*np,
-                                                         lockdep_is_held(&ntbl->rwlock))) != NULL) {
+                                                         lockdep_is_held(&priv->lock))) != NULL) {
                        /* was the neigh idle for two GC periods */
                        if (time_after(neigh_obsolete, neigh->alive)) {
                                rcu_assign_pointer(*np,
                                                   rcu_dereference_protected(neigh->hnext,
-                                                                            lockdep_is_held(&ntbl->rwlock)));
+                                                                            lockdep_is_held(&priv->lock)));
                                /* remove from path/mc list */
-                               spin_lock_irqsave(&priv->lock, flags);
                                list_del(&neigh->list);
-                               spin_unlock_irqrestore(&priv->lock, flags);
                                call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
                        } else {
                                np = &neigh->hnext;
        }
 
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static void ipoib_reap_neigh(struct work_struct *work)
        struct ipoib_neigh *neigh;
        u32 hash_val;
 
-       write_lock_bh(&ntbl->rwlock);
-
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                        lockdep_is_held(&ntbl->rwlock));
+                                        lockdep_is_held(&priv->lock));
        if (!htbl) {
                neigh = NULL;
                goto out_unlock;
         */
        hash_val = ipoib_addr_hash(htbl, daddr);
        for (neigh = rcu_dereference_protected(htbl->buckets[hash_val],
-                                              lockdep_is_held(&ntbl->rwlock));
+                                              lockdep_is_held(&priv->lock));
             neigh != NULL;
             neigh = rcu_dereference_protected(neigh->hnext,
-                                              lockdep_is_held(&ntbl->rwlock))) {
+                                              lockdep_is_held(&priv->lock))) {
                if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
                        /* found, take one ref on behalf of the caller */
                        if (!atomic_inc_not_zero(&neigh->refcnt)) {
        /* put in hash */
        rcu_assign_pointer(neigh->hnext,
                           rcu_dereference_protected(htbl->buckets[hash_val],
-                                                    lockdep_is_held(&ntbl->rwlock)));
+                                                    lockdep_is_held(&priv->lock)));
        rcu_assign_pointer(htbl->buckets[hash_val], neigh);
        atomic_inc(&ntbl->entries);
 
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
 
        return neigh;
 }
        struct ipoib_neigh *n;
        u32 hash_val;
 
-       write_lock_bh(&ntbl->rwlock);
-
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                       lockdep_is_held(&ntbl->rwlock));
+                                       lockdep_is_held(&priv->lock));
        if (!htbl)
-               goto out_unlock;
+               return;
 
        hash_val = ipoib_addr_hash(htbl, neigh->daddr);
        np = &htbl->buckets[hash_val];
        for (n = rcu_dereference_protected(*np,
-                                           lockdep_is_held(&ntbl->rwlock));
+                                           lockdep_is_held(&priv->lock));
             n != NULL;
             n = rcu_dereference_protected(*np,
-                                       lockdep_is_held(&ntbl->rwlock))) {
+                                       lockdep_is_held(&priv->lock))) {
                if (n == neigh) {
                        /* found */
                        rcu_assign_pointer(*np,
                                           rcu_dereference_protected(neigh->hnext,
-                                                                    lockdep_is_held(&ntbl->rwlock)));
+                                                                    lockdep_is_held(&priv->lock)));
                        call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
-                       goto out_unlock;
+                       return;
                } else {
                        np = &n->hnext;
                }
        }
-
-out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
-
 }
 
 static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
 
        clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
        ntbl->htbl = NULL;
-       rwlock_init(&ntbl->rwlock);
        htbl = kzalloc(sizeof(*htbl), GFP_KERNEL);
        if (!htbl)
                return -ENOMEM;
        int i;
 
        /* remove all neigh connected to a given path or mcast */
-       write_lock_bh(&ntbl->rwlock);
+       spin_lock_irqsave(&priv->lock, flags);
 
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                        lockdep_is_held(&ntbl->rwlock));
+                                        lockdep_is_held(&priv->lock));
 
        if (!htbl)
                goto out_unlock;
                struct ipoib_neigh __rcu **np = &htbl->buckets[i];
 
                while ((neigh = rcu_dereference_protected(*np,
-                                                         lockdep_is_held(&ntbl->rwlock))) != NULL) {
+                                                         lockdep_is_held(&priv->lock))) != NULL) {
                        /* delete neighs belong to this parent */
                        if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) {
                                rcu_assign_pointer(*np,
                                                   rcu_dereference_protected(neigh->hnext,
-                                                                            lockdep_is_held(&ntbl->rwlock)));
+                                                                            lockdep_is_held(&priv->lock)));
                                /* remove from parent list */
-                               spin_lock_irqsave(&priv->lock, flags);
                                list_del(&neigh->list);
-                               spin_unlock_irqrestore(&priv->lock, flags);
                                call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
                        } else {
                                np = &neigh->hnext;
                }
        }
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static void ipoib_flush_neighs(struct ipoib_dev_priv *priv)
 
        init_completion(&priv->ntbl.flushed);
 
-       write_lock_bh(&ntbl->rwlock);
+       spin_lock_irqsave(&priv->lock, flags);
 
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                       lockdep_is_held(&ntbl->rwlock));
+                                       lockdep_is_held(&priv->lock));
        if (!htbl)
                goto out_unlock;
 
                struct ipoib_neigh __rcu **np = &htbl->buckets[i];
 
                while ((neigh = rcu_dereference_protected(*np,
-                                                         lockdep_is_held(&ntbl->rwlock))) != NULL) {
+                                      lockdep_is_held(&priv->lock))) != NULL) {
                        rcu_assign_pointer(*np,
                                           rcu_dereference_protected(neigh->hnext,
-                                                                    lockdep_is_held(&ntbl->rwlock)));
+                                                                    lockdep_is_held(&priv->lock)));
                        /* remove from path/mc list */
-                       spin_lock_irqsave(&priv->lock, flags);
                        list_del(&neigh->list);
-                       spin_unlock_irqrestore(&priv->lock, flags);
                        call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
                }
        }
        call_rcu(&htbl->rcu, neigh_hash_free_rcu);
 
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
+       spin_unlock_irqrestore(&priv->lock, flags);
        if (wait_flushed)
                wait_for_completion(&priv->ntbl.flushed);
 }