]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - drivers/infiniband/ulp/ipoib/ipoib_main.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[linux-3.10.git] / drivers / infiniband / ulp / ipoib / ipoib_main.c
index 894b1dcdf3eb31ff0e326aaf9a0b9b793303b8ff..a03a65ebcf0c0a95d31903b17d448be3dd26ed85 100644 (file)
@@ -98,16 +98,20 @@ int ipoib_open(struct net_device *dev)
 
        ipoib_dbg(priv, "bringing up interface\n");
 
+       napi_enable(&priv->napi);
        set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
 
        if (ipoib_pkey_dev_delay_open(dev))
                return 0;
 
-       if (ipoib_ib_dev_open(dev))
+       if (ipoib_ib_dev_open(dev)) {
+               napi_disable(&priv->napi);
                return -EINVAL;
+       }
 
        if (ipoib_ib_dev_up(dev)) {
                ipoib_ib_dev_stop(dev, 1);
+               napi_disable(&priv->napi);
                return -EINVAL;
        }
 
@@ -140,11 +144,10 @@ static int ipoib_stop(struct net_device *dev)
        ipoib_dbg(priv, "stopping interface\n");
 
        clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
+       napi_disable(&priv->napi);
 
        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.
@@ -468,9 +471,10 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
        INIT_LIST_HEAD(&path->neigh_list);
 
        memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid));
-       path->pathrec.sgid      = priv->local_gid;
-       path->pathrec.pkey      = cpu_to_be16(priv->pkey);
-       path->pathrec.numb_path = 1;
+       path->pathrec.sgid          = priv->local_gid;
+       path->pathrec.pkey          = cpu_to_be16(priv->pkey);
+       path->pathrec.numb_path     = 1;
+       path->pathrec.traffic_class = priv->broadcast->mcmember.traffic_class;
 
        return path;
 }
@@ -491,6 +495,7 @@ static int path_rec_start(struct net_device *dev,
                                   IB_SA_PATH_REC_DGID          |
                                   IB_SA_PATH_REC_SGID          |
                                   IB_SA_PATH_REC_NUMB_PATH     |
+                                  IB_SA_PATH_REC_TRAFFIC_CLASS |
                                   IB_SA_PATH_REC_PKEY,
                                   1000, GFP_ATOMIC,
                                   path_rec_completion,
@@ -510,9 +515,9 @@ 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) {
-               ++priv->stats.tx_dropped;
+               ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
                return;
        }
@@ -577,7 +582,7 @@ err_list:
 err_path:
        ipoib_neigh_free(dev, neigh);
 err_drop:
-       ++priv->stats.tx_dropped;
+       ++dev->stats.tx_dropped;
        dev_kfree_skb_any(skb);
 
        spin_unlock(&priv->lock);
@@ -626,7 +631,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
                        } else
                                __path_add(dev, path);
                } else {
-                       ++priv->stats.tx_dropped;
+                       ++dev->stats.tx_dropped;
                        dev_kfree_skb_any(skb);
                }
 
@@ -645,7 +650,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
                skb_push(skb, sizeof *phdr);
                __skb_queue_tail(&path->queue, skb);
        } else {
-               ++priv->stats.tx_dropped;
+               ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
        }
 
@@ -685,9 +690,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
@@ -713,7 +719,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        __skb_queue_tail(&neigh->queue, skb);
                        spin_unlock(&priv->lock);
                } else {
-                       ++priv->stats.tx_dropped;
+                       ++dev->stats.tx_dropped;
                        dev_kfree_skb_any(skb);
                }
        } else {
@@ -739,7 +745,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                           IPOIB_QPN(phdr->hwaddr),
                                           IPOIB_GID_RAW_ARG(phdr->hwaddr + 4));
                                dev_kfree_skb_any(skb);
-                               ++priv->stats.tx_dropped;
+                               ++dev->stats.tx_dropped;
                                goto out;
                        }
 
@@ -753,13 +759,6 @@ out:
        return NETDEV_TX_OK;
 }
 
-static struct net_device_stats *ipoib_get_stats(struct net_device *dev)
-{
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
-
-       return &priv->stats;
-}
-
 static void ipoib_timeout(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -775,7 +774,7 @@ static void ipoib_timeout(struct net_device *dev)
 static int ipoib_hard_header(struct sk_buff *skb,
                             struct net_device *dev,
                             unsigned short type,
-                            void *daddr, void *saddr, unsigned len)
+                            const void *daddr, const void *saddr, unsigned len)
 {
        struct ipoib_header *header;
 
@@ -817,6 +816,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 +830,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 +841,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 +851,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);
@@ -856,11 +861,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
 
 void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh)
 {
-       struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct sk_buff *skb;
        *to_ipoib_neigh(neigh->neighbour) = NULL;
        while ((skb = __skb_dequeue(&neigh->queue))) {
-               ++priv->stats.tx_dropped;
+               ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
        }
        if (ipoib_cm_get(neigh))
@@ -896,7 +900,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;
@@ -935,6 +939,10 @@ void ipoib_dev_cleanup(struct net_device *dev)
        priv->tx_ring = NULL;
 }
 
+static const struct header_ops ipoib_header_ops = {
+       .create = ipoib_hard_header,
+};
+
 static void ipoib_setup(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -943,13 +951,12 @@ static void ipoib_setup(struct net_device *dev)
        dev->stop                = ipoib_stop;
        dev->change_mtu          = ipoib_change_mtu;
        dev->hard_start_xmit     = ipoib_start_xmit;
-       dev->get_stats           = ipoib_get_stats;
        dev->tx_timeout          = ipoib_timeout;
-       dev->hard_header         = ipoib_hard_header;
+       dev->header_ops          = &ipoib_header_ops;
        dev->set_multicast_list  = ipoib_set_mcast_list;
        dev->neigh_setup         = ipoib_neigh_setup_dev;
-       dev->poll                = ipoib_poll;
-       dev->weight              = 100;
+
+       netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
 
        dev->watchdog_timeo      = HZ;
 
@@ -973,8 +980,6 @@ static void ipoib_setup(struct net_device *dev)
 
        netif_carrier_off(dev);
 
-       SET_MODULE_OWNER(dev);
-
        priv->dev = dev;
 
        spin_lock_init(&priv->lock);
@@ -1017,6 +1022,37 @@ static ssize_t show_pkey(struct device *dev,
 }
 static DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL);
 
+static ssize_t show_umcast(struct device *dev,
+                          struct device_attribute *attr, char *buf)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev));
+
+       return sprintf(buf, "%d\n", test_bit(IPOIB_FLAG_UMCAST, &priv->flags));
+}
+
+static ssize_t set_umcast(struct device *dev,
+                         struct device_attribute *attr,
+                         const char *buf, size_t count)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(to_net_dev(dev));
+       unsigned long umcast_val = simple_strtoul(buf, NULL, 0);
+
+       if (umcast_val > 0) {
+               set_bit(IPOIB_FLAG_UMCAST, &priv->flags);
+               ipoib_warn(priv, "ignoring multicast groups joined directly "
+                               "by userspace\n");
+       } else
+               clear_bit(IPOIB_FLAG_UMCAST, &priv->flags);
+
+       return count;
+}
+static DEVICE_ATTR(umcast, S_IWUSR | S_IRUGO, show_umcast, set_umcast);
+
+int ipoib_add_umcast_attr(struct net_device *dev)
+{
+       return device_create_file(&dev->dev, &dev_attr_umcast);
+}
+
 static ssize_t create_child(struct device *dev,
                            struct device_attribute *attr,
                            const char *buf, size_t count)
@@ -1083,7 +1119,7 @@ static struct net_device *ipoib_add_port(const char *format,
        if (result) {
                printk(KERN_WARNING "%s: ib_query_pkey port %d failed (ret = %d)\n",
                       hca->name, port, result);
-               goto alloc_mem_failed;
+               goto device_init_failed;
        }
 
        /*
@@ -1099,7 +1135,7 @@ static struct net_device *ipoib_add_port(const char *format,
        if (result) {
                printk(KERN_WARNING "%s: ib_query_gid port %d failed (ret = %d)\n",
                       hca->name, port, result);
-               goto alloc_mem_failed;
+               goto device_init_failed;
        } else
                memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));
 
@@ -1134,6 +1170,8 @@ static struct net_device *ipoib_add_port(const char *format,
                goto sysfs_failed;
        if (ipoib_add_pkey_attr(priv->dev))
                goto sysfs_failed;
+       if (ipoib_add_umcast_attr(priv->dev))
+               goto sysfs_failed;
        if (device_create_file(&priv->dev->dev, &dev_attr_create_child))
                goto sysfs_failed;
        if (device_create_file(&priv->dev->dev, &dev_attr_delete_child))