rk: revert 20f3d0b+v3.0.66 to v3.0
[firefly-linux-kernel-4.4.55.git] / drivers / infiniband / ulp / ipoib / ipoib_main.c
index 6ea960015e0a1454f547bdf927cb9103761f11ff..86addca9ddf6f9c035dd633ae7d2d88cafcb85e3 100644 (file)
@@ -148,7 +148,7 @@ static int ipoib_stop(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-       ipoib_ib_dev_down(dev, 1);
+       ipoib_ib_dev_down(dev, 0);
        ipoib_ib_dev_stop(dev, 0);
 
        if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
@@ -555,17 +555,14 @@ static int path_rec_start(struct net_device *dev,
        return 0;
 }
 
-/* called with rcu_read_lock */
 static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_path *path;
        struct ipoib_neigh *neigh;
-       struct neighbour *n;
        unsigned long flags;
 
-       n = dst_get_neighbour(skb_dst(skb));
-       neigh = ipoib_neigh_alloc(n, skb->dev);
+       neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
        if (!neigh) {
                ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
@@ -574,9 +571,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       path = __path_find(dev, n->ha + 4);
+       path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
        if (!path) {
-               path = path_rec_create(dev, n->ha + 4);
+               path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
                if (!path)
                        goto err_path;
 
@@ -610,7 +607,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
                        }
                } else {
                        spin_unlock_irqrestore(&priv->lock, flags);
-                       ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
+                       ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
                        return;
                }
        } else {
@@ -637,28 +634,24 @@ err_drop:
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
-/* called with rcu_read_lock */
 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
-       struct dst_entry *dst = skb_dst(skb);
-       struct neighbour *n;
 
        /* Look up path record for unicasts */
-       n = dst_get_neighbour(dst);
-       if (n->ha[4] != 0xff) {
+       if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
                neigh_add_path(skb, dev);
                return;
        }
 
        /* Add in the P_Key for multicasts */
-       n->ha[8] = (priv->pkey >> 8) & 0xff;
-       n->ha[9] = priv->pkey & 0xff;
-       ipoib_mcast_send(dev, n->ha + 4, skb);
+       skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
+       skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
+       ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
-                            struct ipoib_cb *cb)
+                            struct ipoib_pseudoheader *phdr)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_path *path;
@@ -666,15 +659,17 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       path = __path_find(dev, cb->hwaddr + 4);
+       path = __path_find(dev, phdr->hwaddr + 4);
        if (!path || !path->valid) {
                int new_path = 0;
 
                if (!path) {
-                       path = path_rec_create(dev, cb->hwaddr + 4);
+                       path = path_rec_create(dev, phdr->hwaddr + 4);
                        new_path = 1;
                }
                if (path) {
+                       /* put pseudoheader back on for next time */
+                       skb_push(skb, sizeof *phdr);
                        __skb_queue_tail(&path->queue, skb);
 
                        if (!path->query && path_rec_start(dev, path)) {
@@ -698,10 +693,12 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
                          be16_to_cpu(path->pathrec.dlid));
 
                spin_unlock_irqrestore(&priv->lock, flags);
-               ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));
+               ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
                return;
        } else if ((path->query || !path_rec_start(dev, path)) &&
                   skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+               /* put pseudoheader back on for next time */
+               skb_push(skb, sizeof *phdr);
                __skb_queue_tail(&path->queue, skb);
        } else {
                ++dev->stats.tx_dropped;
@@ -715,23 +712,18 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct ipoib_neigh *neigh;
-       struct neighbour *n = NULL;
        unsigned long flags;
 
-       rcu_read_lock();
-       if (likely(skb_dst(skb)))
-               n = dst_get_neighbour(skb_dst(skb));
-
-       if (likely(n)) {
-               if (unlikely(!*to_ipoib_neigh(n))) {
+       if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
+               if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
                        ipoib_path_lookup(skb, dev);
-                       goto unlock;
+                       return NETDEV_TX_OK;
                }
 
-               neigh = *to_ipoib_neigh(n);
+               neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
 
                if (unlikely((memcmp(&neigh->dgid.raw,
-                                    n->ha + 4,
+                                    skb_dst(skb)->neighbour->ha + 4,
                                     sizeof(union ib_gid))) ||
                             (neigh->dev != dev))) {
                        spin_lock_irqsave(&priv->lock, flags);
@@ -748,17 +740,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        ipoib_neigh_free(dev, neigh);
                        spin_unlock_irqrestore(&priv->lock, flags);
                        ipoib_path_lookup(skb, dev);
-                       goto unlock;
+                       return NETDEV_TX_OK;
                }
 
                if (ipoib_cm_get(neigh)) {
                        if (ipoib_cm_up(neigh)) {
                                ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
-                               goto unlock;
+                               return NETDEV_TX_OK;
                        }
                } else if (neigh->ah) {
-                       ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
-                       goto unlock;
+                       ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+                       return NETDEV_TX_OK;
                }
 
                if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -770,14 +762,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        dev_kfree_skb_any(skb);
                }
        } else {
-               struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
+               struct ipoib_pseudoheader *phdr =
+                       (struct ipoib_pseudoheader *) skb->data;
+               skb_pull(skb, sizeof *phdr);
 
-               if (cb->hwaddr[4] == 0xff) {
+               if (phdr->hwaddr[4] == 0xff) {
                        /* Add in the P_Key for multicast*/
-                       cb->hwaddr[8] = (priv->pkey >> 8) & 0xff;
-                       cb->hwaddr[9] = priv->pkey & 0xff;
+                       phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+                       phdr->hwaddr[9] = priv->pkey & 0xff;
 
-                       ipoib_mcast_send(dev, cb->hwaddr + 4, skb);
+                       ipoib_mcast_send(dev, phdr->hwaddr + 4, skb);
                } else {
                        /* unicast GID -- should be ARP or RARP reply */
 
@@ -786,18 +780,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
                                           skb_dst(skb) ? "neigh" : "dst",
                                           be16_to_cpup((__be16 *) skb->data),
-                                          IPOIB_QPN(cb->hwaddr),
-                                          cb->hwaddr + 4);
+                                          IPOIB_QPN(phdr->hwaddr),
+                                          phdr->hwaddr + 4);
                                dev_kfree_skb_any(skb);
                                ++dev->stats.tx_dropped;
-                               goto unlock;
+                               return NETDEV_TX_OK;
                        }
 
-                       unicast_arp_send(skb, dev, cb);
+                       unicast_arp_send(skb, dev, phdr);
                }
        }
-unlock:
-       rcu_read_unlock();
+
        return NETDEV_TX_OK;
 }
 
@@ -826,13 +819,14 @@ static int ipoib_hard_header(struct sk_buff *skb,
        header->reserved = 0;
 
        /*
-        * If we don't have a dst_entry structure, stuff the
-        * destination address into skb->cb so we can figure out where
-        * to send the packet later.
+        * If we don't have a neighbour structure, stuff the
+        * destination address onto the front of the skb so we can
+        * figure out where to send the packet later.
         */
-       if (!skb_dst(skb)) {
-               struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
-               memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
+       if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
+               struct ipoib_pseudoheader *phdr =
+                       (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
+               memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
        }
 
        return 0;
@@ -1008,7 +1002,11 @@ static void ipoib_setup(struct net_device *dev)
 
        dev->flags              |= IFF_BROADCAST | IFF_MULTICAST;
 
-       dev->hard_header_len     = IPOIB_ENCAP_LEN;
+       /*
+        * We add in INFINIBAND_ALEN to allow for the destination
+        * address "pseudoheader" for skbs without neighbour struct.
+        */
+       dev->hard_header_len     = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
        dev->addr_len            = INFINIBAND_ALEN;
        dev->type                = ARPHRD_INFINIBAND;
        dev->tx_queue_len        = ipoib_sendq_size * 2;