net: Add support for XPS without sysfs being defined
authorAlexander Duyck <alexander.h.duyck@intel.com>
Thu, 10 Jan 2013 08:57:46 +0000 (08:57 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 11 Jan 2013 06:47:04 +0000 (22:47 -0800)
This patch makes it so that we can support transmit packet steering without
sysfs needing to be enabled.  The reason for making this change is to make
it so that a driver can make use of the XPS even while the sysfs portion of
the interface is not present.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
net/Kconfig
net/core/dev.c
net/core/net-sysfs.c

index 59fe9da4e31558bdde86f636a4c388062912ae54..aa7ad8a96e7016ce379499f5dca81af452daa5a8 100644 (file)
@@ -2104,7 +2104,6 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
 }
 
 #ifdef CONFIG_XPS
-extern void netif_reset_xps_queue(struct net_device *dev, u16 index);
 extern int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask,
                               u16 index);
 #else
index 30b48f523135be8f00025f32b887b51f0f7000c3..3cc5be0fe420458f7a435126b1bb135a99437f5f 100644 (file)
@@ -232,7 +232,7 @@ config RFS_ACCEL
 
 config XPS
        boolean
-       depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS
+       depends on SMP && USE_GENERIC_SMP_HELPERS
        default y
 
 config NETPRIO_CGROUP
index 41d5120df4695558f9b30155ab656d304082b002..95de4c0118088fa61b89cdd4fcc5b1f990fc270f 100644 (file)
@@ -1887,10 +1887,10 @@ static struct xps_map *remove_xps_queue(struct xps_dev_maps *dev_maps,
        return map;
 }
 
-void netif_reset_xps_queue(struct net_device *dev, u16 index)
+static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
 {
        struct xps_dev_maps *dev_maps;
-       int cpu;
+       int cpu, i;
        bool active = false;
 
        mutex_lock(&xps_map_mutex);
@@ -1900,7 +1900,11 @@ void netif_reset_xps_queue(struct net_device *dev, u16 index)
                goto out_no_maps;
 
        for_each_possible_cpu(cpu) {
-               if (remove_xps_queue(dev_maps, cpu, index))
+               for (i = index; i < dev->num_tx_queues; i++) {
+                       if (!remove_xps_queue(dev_maps, cpu, i))
+                               break;
+               }
+               if (i == dev->num_tx_queues)
                        active = true;
        }
 
@@ -1909,8 +1913,10 @@ void netif_reset_xps_queue(struct net_device *dev, u16 index)
                kfree_rcu(dev_maps, rcu);
        }
 
-       netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
-                                    NUMA_NO_NODE);
+       for (i = index; i < dev->num_tx_queues; i++)
+               netdev_queue_numa_node_write(netdev_get_tx_queue(dev, i),
+                                            NUMA_NO_NODE);
+
 out_no_maps:
        mutex_unlock(&xps_map_mutex);
 }
@@ -2096,8 +2102,12 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
                if (dev->num_tc)
                        netif_setup_tc(dev, txq);
 
-               if (txq < dev->real_num_tx_queues)
+               if (txq < dev->real_num_tx_queues) {
                        qdisc_reset_all_tx_gt(dev, txq);
+#ifdef CONFIG_XPS
+                       netif_reset_xps_queues_gt(dev, txq);
+#endif
+               }
        }
 
        dev->real_num_tx_queues = txq;
@@ -5919,6 +5929,10 @@ static void rollback_registered_many(struct list_head *head)
 
                /* Remove entries from kobject tree */
                netdev_unregister_kobject(dev);
+#ifdef CONFIG_XPS
+               /* Remove XPS queueing entries */
+               netif_reset_xps_queues_gt(dev, 0);
+#endif
        }
 
        synchronize_net();
index 5ad489d5d06245ef28445ac09859309d11dfc5ae..a5b89a6fec6d990bd49caf4fa258fc916a11ed14 100644 (file)
@@ -1002,16 +1002,6 @@ static ssize_t show_xps_map(struct netdev_queue *queue,
        return len;
 }
 
-static void xps_queue_release(struct netdev_queue *queue)
-{
-       struct net_device *dev = queue->dev;
-       unsigned long index;
-
-       index = get_netdev_queue_index(queue);
-
-       netif_reset_xps_queue(dev, index);
-}
-
 static ssize_t store_xps_map(struct netdev_queue *queue,
                      struct netdev_queue_attribute *attribute,
                      const char *buf, size_t len)
@@ -1058,10 +1048,6 @@ static void netdev_queue_release(struct kobject *kobj)
 {
        struct netdev_queue *queue = to_netdev_queue(kobj);
 
-#ifdef CONFIG_XPS
-       xps_queue_release(queue);
-#endif
-
        memset(kobj, 0, sizeof(*kobj));
        dev_put(queue->dev);
 }