Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[sfrench/cifs-2.6.git] / drivers / infiniband / ulp / ipoib / ipoib_main.c
index e072f3c32ce6f307aa3bdaf7935557b4bc5a53d0..c9f6077b615eb62db39dae44f385976c50018865 100644 (file)
@@ -148,8 +148,6 @@ static int ipoib_stop(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       clear_bit(IPOIB_FLAG_NETIF_STOPPED, &priv->flags);
-
        /*
         * Now flush workqueue to make sure a scheduled task doesn't
         * bring our internal state back up.
@@ -462,6 +460,9 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_path *path;
 
+       if (!priv->broadcast)
+               return NULL;
+
        path = kzalloc(sizeof *path, GFP_ATOMIC);
        if (!path)
                return NULL;
@@ -517,7 +518,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
        struct ipoib_path *path;
        struct ipoib_neigh *neigh;
 
-       neigh = ipoib_neigh_alloc(skb->dst->neighbour);
+       neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
        if (!neigh) {
                ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
@@ -692,9 +693,10 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                goto out;
                        }
                } else if (neigh->ah) {
-                       if (unlikely(memcmp(&neigh->dgid.raw,
+                       if (unlikely((memcmp(&neigh->dgid.raw,
                                            skb->dst->neighbour->ha + 4,
-                                           sizeof(union ib_gid)))) {
+                                           sizeof(union ib_gid))) ||
+                                        (neigh->dev != dev))) {
                                spin_lock(&priv->lock);
                                /*
                                 * It's safe to call ipoib_put_ah() inside
@@ -817,6 +819,13 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
        unsigned long flags;
        struct ipoib_ah *ah = NULL;
 
+       neigh = *to_ipoib_neigh(n);
+       if (neigh) {
+               priv = netdev_priv(neigh->dev);
+               ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n",
+                         n->dev->name);
+       } else
+               return;
        ipoib_dbg(priv,
                  "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
                  IPOIB_QPN(n->ha),
@@ -824,13 +833,10 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       neigh = *to_ipoib_neigh(n);
-       if (neigh) {
-               if (neigh->ah)
-                       ah = neigh->ah;
-               list_del(&neigh->list);
-               ipoib_neigh_free(n->dev, neigh);
-       }
+       if (neigh->ah)
+               ah = neigh->ah;
+       list_del(&neigh->list);
+       ipoib_neigh_free(n->dev, neigh);
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -838,7 +844,8 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
                ipoib_put_ah(ah);
 }
 
-struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour,
+                                     struct net_device *dev)
 {
        struct ipoib_neigh *neigh;
 
@@ -847,6 +854,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
                return NULL;
 
        neigh->neighbour = neighbour;
+       neigh->dev = dev;
        *to_ipoib_neigh(neighbour) = neigh;
        skb_queue_head_init(&neigh->queue);
        ipoib_cm_set(neigh, NULL);
@@ -895,7 +903,7 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
                goto out_rx_ring_cleanup;
        }
 
-       /* priv->tx_head & tx_tail are already 0 */
+       /* priv->tx_head, tx_tail & tx_outstanding are already 0 */
 
        if (ipoib_ib_dev_init(dev, ca, port))
                goto out_tx_ring_cleanup;