All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] Make XPS usable within ixgbe
@ 2012-06-30  0:16 Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx Alexander Duyck
                   ` (10 more replies)
  0 siblings, 11 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

The following patch series makes it so that the ixgbe driver can support
ATR even when the number of queues is less than the number of CPUs.  To do
this I have updated the kernel to support letting drivers set their own XPS
configuration.  To do this it was necessary to move the code out of the
sysfs specific code and into the dev specific regions.

I am still working out a few issues such as the fact that with routing I
only ever seem to be able to get the first queue that is mapped to the CPU
when XPS is enabled.

Also I am looking for input on if it is acceptable to only let the
set_channels/get_channels calls report/set the number of queues per traffic
class as I implemented the code this way to avoid any significant conflicts
between the DCB traffic classes code and these functions.

---

Alexander Duyck (10):
      ixgbe: Add support for set_channels ethtool operation
      ixgbe: Add support for displaying the number of Tx/Rx channels
      ixgbe: Update ixgbe driver to use __dev_pick_tx in ixgbe_select_queue
      ixgbe: Add function for setting XPS queue mapping
      ixgbe: Define FCoE and Flow director limits much sooner to allow for changes
      net: Add support for XPS without SYSFS being defined
      net: Rewrite netif_set_xps_queues to address several issues
      net: Rewrite netif_reset_xps_queue to allow for better code reuse
      net: Add functions netif_reset_xps_queue and netif_set_xps_queue
      net: Split core bits of dev_pick_tx into __dev_pick_tx


 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |  112 +++++++++
 drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c     |   10 -
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c    |   48 +++-
 include/linux/netdevice.h                        |   15 +
 net/Kconfig                                      |    2 
 net/core/dev.c                                   |  283 ++++++++++++++++++++--
 net/core/net-sysfs.c                             |  160 ------------
 7 files changed, 428 insertions(+), 202 deletions(-)

-- 
Thanks,

Alex

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-07-07  0:03   ` Ben Hutchings
  2012-06-30  0:16 ` [RFC PATCH 02/10] net: Add functions netif_reset_xps_queue and netif_set_xps_queue Alexander Duyck
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This change splits the core bits of dev_pick_tx into a separate function.
The main idea behind this is to make this code accessible to select queue
functions when they decide to process the standard path instead of their
own custom path in their select queue routine.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 include/linux/netdevice.h |    3 +++
 net/core/dev.c            |   51 ++++++++++++++++++++++++++-------------------
 2 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2c2ecea..3329d70 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2082,6 +2082,9 @@ static inline u16 skb_tx_hash(const struct net_device *dev,
 	return __skb_tx_hash(dev, skb, dev->real_num_tx_queues);
 }
 
+extern int __dev_pick_tx(const struct net_device *dev,
+			 const struct sk_buff *skb);
+
 /**
  *	netif_is_multiqueue - test if device has multiple transmit queues
  *	@dev: network device
diff --git a/net/core/dev.c b/net/core/dev.c
index 57c4f9b..b31a9ff 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2301,7 +2301,8 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index)
 	return queue_index;
 }
 
-static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
+static inline int get_xps_queue(const struct net_device *dev,
+				const struct sk_buff *skb)
 {
 #ifdef CONFIG_XPS
 	struct xps_dev_maps *dev_maps;
@@ -2339,11 +2340,37 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb)
 #endif
 }
 
+int __dev_pick_tx(const struct net_device *dev, const struct sk_buff *skb)
+{
+	struct sock *sk = skb->sk;
+	int queue_index = sk_tx_queue_get(sk);
+
+	if (queue_index < 0 || skb->ooo_okay ||
+	    queue_index >= dev->real_num_tx_queues) {
+		int old_index = queue_index;
+
+		queue_index = get_xps_queue(dev, skb);
+		if (queue_index < 0)
+			queue_index = skb_tx_hash(dev, skb);
+
+		if (queue_index != old_index && sk) {
+			struct dst_entry *dst =
+			    rcu_dereference_check(sk->sk_dst_cache, 1);
+
+			if (dst && skb_dst(skb) == dst)
+				sk_tx_queue_set(sk, queue_index);
+		}
+	}
+
+	return queue_index;
+}
+EXPORT_SYMBOL(__dev_pick_tx);
+
 static struct netdev_queue *dev_pick_tx(struct net_device *dev,
 					struct sk_buff *skb)
 {
-	int queue_index;
 	const struct net_device_ops *ops = dev->netdev_ops;
+	int queue_index;
 
 	if (dev->real_num_tx_queues == 1)
 		queue_index = 0;
@@ -2351,25 +2378,7 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
 		queue_index = ops->ndo_select_queue(dev, skb);
 		queue_index = dev_cap_txqueue(dev, queue_index);
 	} else {
-		struct sock *sk = skb->sk;
-		queue_index = sk_tx_queue_get(sk);
-
-		if (queue_index < 0 || skb->ooo_okay ||
-		    queue_index >= dev->real_num_tx_queues) {
-			int old_index = queue_index;
-
-			queue_index = get_xps_queue(dev, skb);
-			if (queue_index < 0)
-				queue_index = skb_tx_hash(dev, skb);
-
-			if (queue_index != old_index && sk) {
-				struct dst_entry *dst =
-				    rcu_dereference_check(sk->sk_dst_cache, 1);
-
-				if (dst && skb_dst(skb) == dst)
-					sk_tx_queue_set(sk, queue_index);
-			}
-		}
+		queue_index = __dev_pick_tx(dev, skb);
 	}
 
 	skb_set_queue_mapping(skb, queue_index);

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 02/10] net: Add functions netif_reset_xps_queue and netif_set_xps_queue
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 03/10] net: Rewrite netif_reset_xps_queue to allow for better code reuse Alexander Duyck
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This patch adds two functions, netif_reset_xps_queue and
netif_set_xps_queue.  The main idea behind these to functions is to provide
a mechanism through which drivers can update their defaults in regards to
XPS.

Currently no such mechanism exists and as a result we cannot use XPS for
things such as ATR which would require a basic configuration to start in
which the Tx queues are mapped to CPUs via a 1:1 mapping.  With this change
I am making it possible for drivers such as ixgbe to be able to use the XPS
feature by controlling the default configuration.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 include/linux/netdevice.h |   13 ++++
 net/core/dev.c            |  155 +++++++++++++++++++++++++++++++++++++++++++++
 net/core/net-sysfs.c      |  148 +------------------------------------------
 3 files changed, 173 insertions(+), 143 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3329d70..e9e74b7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2072,6 +2072,19 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
 		__netif_schedule(txq->qdisc);
 }
 
+#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
+static inline int netif_set_xps_queue(struct net_device *dev,
+				      struct cpumask *mask,
+				      u16 index)
+{
+	return 0;
+}
+#endif
+
 /*
  * Returns a Tx hash for the given packet when dev->real_num_tx_queues is used
  * as a distribution range limit for the returned value.
diff --git a/net/core/dev.c b/net/core/dev.c
index b31a9ff..4c0981b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1728,6 +1728,161 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
 	}
 }
 
+#ifdef CONFIG_XPS
+static DEFINE_MUTEX(xps_map_mutex);
+#define xmap_dereference(P)		\
+	rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
+
+void netif_reset_xps_queue(struct net_device *dev, u16 index)
+{
+	struct xps_dev_maps *dev_maps;
+	struct xps_map *map;
+	int i, pos, nonempty = 0;
+
+	mutex_lock(&xps_map_mutex);
+	dev_maps = xmap_dereference(dev->xps_maps);
+
+	if (!dev_maps)
+		goto out_no_maps;
+
+	for_each_possible_cpu(i) {
+		map = xmap_dereference(dev_maps->cpu_map[i]);
+		if (!map)
+			continue;
+
+		for (pos = 0; pos < map->len; pos++)
+			if (map->queues[pos] == index)
+				break;
+
+		if (pos < map->len) {
+			if (map->len > 1) {
+				map->queues[pos] = map->queues[--map->len];
+			} else {
+				RCU_INIT_POINTER(dev_maps->cpu_map[i], NULL);
+				kfree_rcu(map, rcu);
+				map = NULL;
+			}
+		}
+		if (map)
+			nonempty = 1;
+	}
+
+	if (!nonempty) {
+		RCU_INIT_POINTER(dev->xps_maps, NULL);
+		kfree_rcu(dev_maps, rcu);
+	}
+
+out_no_maps:
+	mutex_unlock(&xps_map_mutex);
+}
+
+int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index)
+{
+	int i, cpu, pos, map_len, alloc_len, need_set;
+	struct xps_map *map, *new_map;
+	struct xps_dev_maps *dev_maps, *new_dev_maps;
+	int nonempty = 0;
+	int numa_node_id = -2;
+	int maps_sz = max_t(unsigned int, XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES);
+
+	new_dev_maps = kzalloc(maps_sz, GFP_KERNEL);
+	if (!new_dev_maps)
+		return -ENOMEM;
+
+	mutex_lock(&xps_map_mutex);
+
+	dev_maps = xmap_dereference(dev->xps_maps);
+
+	for_each_possible_cpu(cpu) {
+		map = dev_maps ?
+			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
+		new_map = map;
+		if (map) {
+			for (pos = 0; pos < map->len; pos++)
+				if (map->queues[pos] == index)
+					break;
+			map_len = map->len;
+			alloc_len = map->alloc_len;
+		} else
+			pos = map_len = alloc_len = 0;
+
+		need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu);
+#ifdef CONFIG_NUMA
+		if (need_set) {
+			if (numa_node_id == -2)
+				numa_node_id = cpu_to_node(cpu);
+			else if (numa_node_id != cpu_to_node(cpu))
+				numa_node_id = -1;
+		}
+#endif
+		if (need_set && pos >= map_len) {
+			/* Need to add queue to this CPU's map */
+			if (map_len >= alloc_len) {
+				alloc_len = alloc_len ?
+				    2 * alloc_len : XPS_MIN_MAP_ALLOC;
+				new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len),
+						       GFP_KERNEL,
+						       cpu_to_node(cpu));
+				if (!new_map)
+					goto error;
+				new_map->alloc_len = alloc_len;
+				for (i = 0; i < map_len; i++)
+					new_map->queues[i] = map->queues[i];
+				new_map->len = map_len;
+			}
+			new_map->queues[new_map->len++] = index;
+		} else if (!need_set && pos < map_len) {
+			/* Need to remove queue from this CPU's map */
+			if (map_len > 1)
+				new_map->queues[pos] =
+				    new_map->queues[--new_map->len];
+			else
+				new_map = NULL;
+		}
+		RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], new_map);
+	}
+
+	/* Cleanup old maps */
+	for_each_possible_cpu(cpu) {
+		map = dev_maps ?
+			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
+		if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map)
+			kfree_rcu(map, rcu);
+		if (new_dev_maps->cpu_map[cpu])
+			nonempty = 1;
+	}
+
+	if (nonempty) {
+		rcu_assign_pointer(dev->xps_maps, new_dev_maps);
+	} else {
+		kfree(new_dev_maps);
+		RCU_INIT_POINTER(dev->xps_maps, NULL);
+	}
+
+	if (dev_maps)
+		kfree_rcu(dev_maps, rcu);
+
+	netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
+				     (numa_node_id >= 0) ? numa_node_id :
+				     NUMA_NO_NODE);
+
+	mutex_unlock(&xps_map_mutex);
+
+	return 0;
+error:
+	mutex_unlock(&xps_map_mutex);
+
+	if (new_dev_maps)
+		for_each_possible_cpu(i)
+			kfree(rcu_dereference_protected(
+				new_dev_maps->cpu_map[i],
+				1));
+	kfree(new_dev_maps);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(netif_set_xps_queue);
+
+#endif
 /*
  * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues
  * greater then real_num_tx_queues stale skbs on the qdisc must be flushed.
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 7260717..092d338 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -963,54 +963,14 @@ static ssize_t show_xps_map(struct netdev_queue *queue,
 	return len;
 }
 
-static DEFINE_MUTEX(xps_map_mutex);
-#define xmap_dereference(P)		\
-	rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
-
 static void xps_queue_release(struct netdev_queue *queue)
 {
 	struct net_device *dev = queue->dev;
-	struct xps_dev_maps *dev_maps;
-	struct xps_map *map;
 	unsigned long index;
-	int i, pos, nonempty = 0;
 
 	index = get_netdev_queue_index(queue);
 
-	mutex_lock(&xps_map_mutex);
-	dev_maps = xmap_dereference(dev->xps_maps);
-
-	if (dev_maps) {
-		for_each_possible_cpu(i) {
-			map = xmap_dereference(dev_maps->cpu_map[i]);
-			if (!map)
-				continue;
-
-			for (pos = 0; pos < map->len; pos++)
-				if (map->queues[pos] == index)
-					break;
-
-			if (pos < map->len) {
-				if (map->len > 1)
-					map->queues[pos] =
-					    map->queues[--map->len];
-				else {
-					RCU_INIT_POINTER(dev_maps->cpu_map[i],
-					    NULL);
-					kfree_rcu(map, rcu);
-					map = NULL;
-				}
-			}
-			if (map)
-				nonempty = 1;
-		}
-
-		if (!nonempty) {
-			RCU_INIT_POINTER(dev->xps_maps, NULL);
-			kfree_rcu(dev_maps, rcu);
-		}
-	}
-	mutex_unlock(&xps_map_mutex);
+	netif_reset_xps_queue(dev, index);
 }
 
 static ssize_t store_xps_map(struct netdev_queue *queue,
@@ -1018,13 +978,9 @@ static ssize_t store_xps_map(struct netdev_queue *queue,
 		      const char *buf, size_t len)
 {
 	struct net_device *dev = queue->dev;
-	cpumask_var_t mask;
-	int err, i, cpu, pos, map_len, alloc_len, need_set;
 	unsigned long index;
-	struct xps_map *map, *new_map;
-	struct xps_dev_maps *dev_maps, *new_dev_maps;
-	int nonempty = 0;
-	int numa_node_id = -2;
+	cpumask_var_t mask;
+	int err;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -1040,105 +996,11 @@ static ssize_t store_xps_map(struct netdev_queue *queue,
 		return err;
 	}
 
-	new_dev_maps = kzalloc(max_t(unsigned int,
-	    XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES), GFP_KERNEL);
-	if (!new_dev_maps) {
-		free_cpumask_var(mask);
-		return -ENOMEM;
-	}
-
-	mutex_lock(&xps_map_mutex);
-
-	dev_maps = xmap_dereference(dev->xps_maps);
-
-	for_each_possible_cpu(cpu) {
-		map = dev_maps ?
-			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
-		new_map = map;
-		if (map) {
-			for (pos = 0; pos < map->len; pos++)
-				if (map->queues[pos] == index)
-					break;
-			map_len = map->len;
-			alloc_len = map->alloc_len;
-		} else
-			pos = map_len = alloc_len = 0;
-
-		need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu);
-#ifdef CONFIG_NUMA
-		if (need_set) {
-			if (numa_node_id == -2)
-				numa_node_id = cpu_to_node(cpu);
-			else if (numa_node_id != cpu_to_node(cpu))
-				numa_node_id = -1;
-		}
-#endif
-		if (need_set && pos >= map_len) {
-			/* Need to add queue to this CPU's map */
-			if (map_len >= alloc_len) {
-				alloc_len = alloc_len ?
-				    2 * alloc_len : XPS_MIN_MAP_ALLOC;
-				new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len),
-						       GFP_KERNEL,
-						       cpu_to_node(cpu));
-				if (!new_map)
-					goto error;
-				new_map->alloc_len = alloc_len;
-				for (i = 0; i < map_len; i++)
-					new_map->queues[i] = map->queues[i];
-				new_map->len = map_len;
-			}
-			new_map->queues[new_map->len++] = index;
-		} else if (!need_set && pos < map_len) {
-			/* Need to remove queue from this CPU's map */
-			if (map_len > 1)
-				new_map->queues[pos] =
-				    new_map->queues[--new_map->len];
-			else
-				new_map = NULL;
-		}
-		RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], new_map);
-	}
-
-	/* Cleanup old maps */
-	for_each_possible_cpu(cpu) {
-		map = dev_maps ?
-			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
-		if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map)
-			kfree_rcu(map, rcu);
-		if (new_dev_maps->cpu_map[cpu])
-			nonempty = 1;
-	}
-
-	if (nonempty) {
-		rcu_assign_pointer(dev->xps_maps, new_dev_maps);
-	} else {
-		kfree(new_dev_maps);
-		RCU_INIT_POINTER(dev->xps_maps, NULL);
-	}
-
-	if (dev_maps)
-		kfree_rcu(dev_maps, rcu);
-
-	netdev_queue_numa_node_write(queue, (numa_node_id >= 0) ? numa_node_id :
-					    NUMA_NO_NODE);
-
-	mutex_unlock(&xps_map_mutex);
+	err = netif_set_xps_queue(dev, mask, index);
 
 	free_cpumask_var(mask);
-	return len;
 
-error:
-	mutex_unlock(&xps_map_mutex);
-
-	if (new_dev_maps)
-		for_each_possible_cpu(i)
-			kfree(rcu_dereference_protected(
-				new_dev_maps->cpu_map[i],
-				1));
-	kfree(new_dev_maps);
-	free_cpumask_var(mask);
-	return -ENOMEM;
+	return err ? : len;
 }
 
 static struct netdev_queue_attribute xps_cpus_attribute =

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 03/10] net: Rewrite netif_reset_xps_queue to allow for better code reuse
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 02/10] net: Add functions netif_reset_xps_queue and netif_set_xps_queue Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 04/10] net: Rewrite netif_set_xps_queues to address several issues Alexander Duyck
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This patch does a minor refactor on netif_reset_xps_queue to address a few
items I noticed.

First is the fact that we are doing removal of queues in both
netif_reset_xps_queue and netif_set_xps_queue.  Since there is no need to
have the code in two places I am pushing it out into a separate function
and will come back in another patch and reuse the code in
netif_set_xps_queue.

The second item this change addresses is the fact that the Tx queues were
not getting their numa_node value cleared as a part of the XPS queue reset.
This patch resolves that by resetting the numa_node value if the dev_maps
value is set.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 net/core/dev.c |   56 +++++++++++++++++++++++++++++++++-----------------------
 1 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 4c0981b..8e259d4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1733,45 +1733,55 @@ static DEFINE_MUTEX(xps_map_mutex);
 #define xmap_dereference(P)		\
 	rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
 
-void netif_reset_xps_queue(struct net_device *dev, u16 index)
+static struct xps_map *remove_xps_queue(struct xps_dev_maps *dev_maps,
+					int cpu, u16 index)
 {
-	struct xps_dev_maps *dev_maps;
-	struct xps_map *map;
-	int i, pos, nonempty = 0;
-
-	mutex_lock(&xps_map_mutex);
-	dev_maps = xmap_dereference(dev->xps_maps);
-
-	if (!dev_maps)
-		goto out_no_maps;
+	struct xps_map *map = NULL;
+	int pos;
 
-	for_each_possible_cpu(i) {
-		map = xmap_dereference(dev_maps->cpu_map[i]);
-		if (!map)
-			continue;
-
-		for (pos = 0; pos < map->len; pos++)
-			if (map->queues[pos] == index)
-				break;
+	if (dev_maps)
+		map = xmap_dereference(dev_maps->cpu_map[cpu]);
 
-		if (pos < map->len) {
+	for (pos = 0; map && pos < map->len; pos++) {
+		if (map->queues[pos] == index) {
 			if (map->len > 1) {
 				map->queues[pos] = map->queues[--map->len];
 			} else {
-				RCU_INIT_POINTER(dev_maps->cpu_map[i], NULL);
+				RCU_INIT_POINTER(dev_maps->cpu_map[cpu], NULL);
 				kfree_rcu(map, rcu);
 				map = NULL;
 			}
+			break;
 		}
-		if (map)
-			nonempty = 1;
 	}
 
-	if (!nonempty) {
+	return map;
+}
+
+void netif_reset_xps_queue(struct net_device *dev, u16 index)
+{
+	struct xps_dev_maps *dev_maps;
+	int cpu;
+	bool active = false;
+
+	mutex_lock(&xps_map_mutex);
+	dev_maps = xmap_dereference(dev->xps_maps);
+
+	if (!dev_maps)
+		goto out_no_maps;
+
+	for_each_possible_cpu(cpu) {
+		if (remove_xps_queue(dev_maps, cpu, index))
+			active = true;
+	}
+
+	if (!active) {
 		RCU_INIT_POINTER(dev->xps_maps, NULL);
 		kfree_rcu(dev_maps, rcu);
 	}
 
+	netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
+				     NUMA_NO_NODE);
 out_no_maps:
 	mutex_unlock(&xps_map_mutex);
 }

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 04/10] net: Rewrite netif_set_xps_queues to address several issues
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (2 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 03/10] net: Rewrite netif_reset_xps_queue to allow for better code reuse Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 05/10] net: Add support for XPS without SYSFS being defined Alexander Duyck
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This change is meant to address several issues I found within the
netif_set_xps_queues function.

If the allocation of one of the maps to be assigned to new_dev_maps failed
we could end up with the device map in an inconsistent state since we had
already worked through a number of CPUs and removed or added the queue.  To
address that I split the process into several steps.  The first of which is
just the allocation of updated maps for CPUs that will need larger maps to
store the queue.  By doing this we can fail gracefully without actually
altering the contents of the current device map.

The second issue I found was the fact that we were always allocating a new
device map even if we were not adding any queues.  I have updated the code
so that we only allocate a new device map if we are adding queues,
otherwise if we are not adding any queues to CPUs we just skip to the
removal process.

The last change I made was to reuse the code from remove_xps_queue to remove
the queue from the CPU.  By making this change we can be consistent in how
we go about adding and removing the queues from the CPUs.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 net/core/dev.c |  183 ++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 117 insertions(+), 66 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 8e259d4..5f0550b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1786,107 +1786,158 @@ out_no_maps:
 	mutex_unlock(&xps_map_mutex);
 }
 
+static struct xps_map *expand_xps_map(struct xps_map *map,
+				      int cpu, u16 index)
+{
+	struct xps_map *new_map;
+	int alloc_len = XPS_MIN_MAP_ALLOC;
+	int i, pos;
+
+	for (pos = 0; map && pos < map->len; pos++) {
+		if (map->queues[pos] != index)
+			continue;
+		return map;
+	}
+
+	/* Need to add queue to this CPU's existing map */
+	if (map) {
+		if (pos < map->alloc_len)
+			return map;
+
+		alloc_len = map->alloc_len * 2;
+	}
+
+	/* Need to allocate new map to store queue on this CPU's map */
+	new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len), GFP_KERNEL,
+			       cpu_to_node(cpu));
+	if (!new_map)
+		return NULL;
+
+	for (i = 0; i < pos; i++)
+		new_map->queues[i] = map->queues[i];
+	new_map->alloc_len = alloc_len;
+	new_map->len = pos;
+
+	return new_map;
+}
+
 int netif_set_xps_queue(struct net_device *dev, struct cpumask *mask, u16 index)
 {
-	int i, cpu, pos, map_len, alloc_len, need_set;
+	struct xps_dev_maps *dev_maps, *new_dev_maps = NULL;
 	struct xps_map *map, *new_map;
-	struct xps_dev_maps *dev_maps, *new_dev_maps;
-	int nonempty = 0;
-	int numa_node_id = -2;
 	int maps_sz = max_t(unsigned int, XPS_DEV_MAPS_SIZE, L1_CACHE_BYTES);
-
-	new_dev_maps = kzalloc(maps_sz, GFP_KERNEL);
-	if (!new_dev_maps)
-		return -ENOMEM;
+	int cpu, numa_node_id = -2;
+	bool active = false;
 
 	mutex_lock(&xps_map_mutex);
 
 	dev_maps = xmap_dereference(dev->xps_maps);
 
+	/* allocate memory for queue storage */
+	for_each_online_cpu(cpu) {
+		if (!cpumask_test_cpu(cpu, mask))
+			continue;
+
+		if (!new_dev_maps)
+			new_dev_maps = kzalloc(maps_sz, GFP_KERNEL);
+		if (!new_dev_maps)
+			return -ENOMEM;
+
+		map = dev_maps ? xmap_dereference(dev_maps->cpu_map[cpu]) :
+				 NULL;
+
+		map = expand_xps_map(map, cpu, index);
+		if (!map)
+			goto error;
+
+		RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], map);
+	}
+
+	if (!new_dev_maps)
+		goto out_no_new_maps;
+
 	for_each_possible_cpu(cpu) {
-		map = dev_maps ?
-			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
-		new_map = map;
-		if (map) {
-			for (pos = 0; pos < map->len; pos++)
-				if (map->queues[pos] == index)
-					break;
-			map_len = map->len;
-			alloc_len = map->alloc_len;
-		} else
-			pos = map_len = alloc_len = 0;
+		if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu)) {
+			/* add queue to CPU maps */
+			int pos = 0;
 
-		need_set = cpumask_test_cpu(cpu, mask) && cpu_online(cpu);
+			map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
+			while ((pos < map->len) && (map->queues[pos] != index))
+				pos++;
+
+			if (pos == map->len)
+				map->queues[map->len++] = index;
 #ifdef CONFIG_NUMA
-		if (need_set) {
 			if (numa_node_id == -2)
 				numa_node_id = cpu_to_node(cpu);
 			else if (numa_node_id != cpu_to_node(cpu))
 				numa_node_id = -1;
-		}
 #endif
-		if (need_set && pos >= map_len) {
-			/* Need to add queue to this CPU's map */
-			if (map_len >= alloc_len) {
-				alloc_len = alloc_len ?
-				    2 * alloc_len : XPS_MIN_MAP_ALLOC;
-				new_map = kzalloc_node(XPS_MAP_SIZE(alloc_len),
-						       GFP_KERNEL,
-						       cpu_to_node(cpu));
-				if (!new_map)
-					goto error;
-				new_map->alloc_len = alloc_len;
-				for (i = 0; i < map_len; i++)
-					new_map->queues[i] = map->queues[i];
-				new_map->len = map_len;
-			}
-			new_map->queues[new_map->len++] = index;
-		} else if (!need_set && pos < map_len) {
-			/* Need to remove queue from this CPU's map */
-			if (map_len > 1)
-				new_map->queues[pos] =
-				    new_map->queues[--new_map->len];
-			else
-				new_map = NULL;
+		} else if (dev_maps) {
+			/* fill in the new device map from the old device map */
+			map = xmap_dereference(dev_maps->cpu_map[cpu]);
+			RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], map);
 		}
-		RCU_INIT_POINTER(new_dev_maps->cpu_map[cpu], new_map);
+
 	}
 
+	rcu_assign_pointer(dev->xps_maps, new_dev_maps);
+
 	/* Cleanup old maps */
-	for_each_possible_cpu(cpu) {
-		map = dev_maps ?
-			xmap_dereference(dev_maps->cpu_map[cpu]) : NULL;
-		if (map && xmap_dereference(new_dev_maps->cpu_map[cpu]) != map)
-			kfree_rcu(map, rcu);
-		if (new_dev_maps->cpu_map[cpu])
-			nonempty = 1;
-	}
+	if (dev_maps) {
+		for_each_possible_cpu(cpu) {
+			new_map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
+			map = xmap_dereference(dev_maps->cpu_map[cpu]);
+			if (map && map != new_map)
+				kfree_rcu(map, rcu);
+		}
 
-	if (nonempty) {
-		rcu_assign_pointer(dev->xps_maps, new_dev_maps);
-	} else {
-		kfree(new_dev_maps);
-		RCU_INIT_POINTER(dev->xps_maps, NULL);
+		kfree_rcu(dev_maps, rcu);
 	}
 
-	if (dev_maps)
-		kfree_rcu(dev_maps, rcu);
+	dev_maps = new_dev_maps;
+	active = true;
 
+out_no_new_maps:
+	/* update Tx queue numa node */
 	netdev_queue_numa_node_write(netdev_get_tx_queue(dev, index),
 				     (numa_node_id >= 0) ? numa_node_id :
 				     NUMA_NO_NODE);
 
+	if (!dev_maps)
+		goto out_no_maps;
+
+	/* removes queue from unused CPUs */
+	for_each_possible_cpu(cpu) {
+		if (cpumask_test_cpu(cpu, mask) && cpu_online(cpu))
+			continue;
+
+		if (remove_xps_queue(dev_maps, cpu, index))
+			active = true;
+	}
+
+	/* free map if not active */
+	if (!active) {
+		RCU_INIT_POINTER(dev->xps_maps, NULL);
+		kfree_rcu(dev_maps, rcu);
+	}
+
+out_no_maps:
 	mutex_unlock(&xps_map_mutex);
 
 	return 0;
 error:
+	/* remove any maps that we added */
+	for_each_possible_cpu(cpu) {
+		new_map = xmap_dereference(new_dev_maps->cpu_map[cpu]);
+		map = dev_maps ? xmap_dereference(dev_maps->cpu_map[cpu]) :
+				 NULL;
+		if (new_map && new_map != map)
+			kfree(new_map);
+	}
+
 	mutex_unlock(&xps_map_mutex);
 
-	if (new_dev_maps)
-		for_each_possible_cpu(i)
-			kfree(rcu_dereference_protected(
-				new_dev_maps->cpu_map[i],
-				1));
 	kfree(new_dev_maps);
 	return -ENOMEM;
 }

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 05/10] net: Add support for XPS without SYSFS being defined
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (3 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 04/10] net: Rewrite netif_set_xps_queues to address several issues Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 06/10] ixgbe: Define FCoE and Flow director limits much sooner to allow for changes Alexander Duyck
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

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>
---

 include/linux/netdevice.h |    1 -
 net/Kconfig               |    2 +-
 net/core/dev.c            |   26 ++++++++++++++++++++------
 net/core/net-sysfs.c      |   14 --------------
 4 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e9e74b7..db27be2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2073,7 +2073,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
diff --git a/net/Kconfig b/net/Kconfig
index 245831b..fcc5657 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -230,7 +230,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
diff --git a/net/core/dev.c b/net/core/dev.c
index 5f0550b..894faf1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1758,10 +1758,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);
@@ -1771,7 +1771,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;
 	}
 
@@ -1780,8 +1784,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);
 }
@@ -1967,8 +1973,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;
@@ -5460,6 +5470,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
 	}
 
 	/* Process any work delayed until the end of the batch */
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 092d338..42bb496 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -963,16 +963,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)
@@ -1019,10 +1009,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);
 }

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 06/10] ixgbe: Define FCoE and Flow director limits much sooner to allow for changes
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (4 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 05/10] net: Add support for XPS without SYSFS being defined Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping Alexander Duyck
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

Instead of adjusting the FCoE and Flow director limits based on the number
of CPUs we can define them much sooner.  This allows the user to come
through later and adjust them once we have updated the code to support the
set_channels ethtool operation.

I am still allowing for FCoE and RSS queues to be separated if the number
queues is less than the number of CPUs.  This essentially treats the two
groupings like they are two separate traffic classes.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c  |    7 +------
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |   12 ++++++++----
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 24acd53..72386fb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -386,7 +386,6 @@ static bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter)
 		fcoe = &adapter->ring_feature[RING_F_FCOE];
 
 		/* limit ourselves based on feature limits */
-		fcoe_i = min_t(u16, fcoe_i, num_online_cpus());
 		fcoe_i = min_t(u16, fcoe_i, fcoe->limit);
 
 		if (fcoe_i) {
@@ -562,9 +561,6 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
 		fcoe_i = min_t(u16, fcoe_i, fcoe->limit);
 
 		if (vmdq_i > 1 && fcoe_i) {
-			/* reserve no more than number of CPUs */
-			fcoe_i = min_t(u16, fcoe_i, num_online_cpus());
-
 			/* alloc queues for FCoE separately */
 			fcoe->indices = fcoe_i;
 			fcoe->offset = vmdq_i * rss_i;
@@ -623,8 +619,7 @@ static bool ixgbe_set_rss_queues(struct ixgbe_adapter *adapter)
 	if (rss_i > 1 && adapter->atr_sample_rate) {
 		f = &adapter->ring_feature[RING_F_FDIR];
 
-		f->indices = min_t(u16, num_online_cpus(), f->limit);
-		rss_i = max_t(u16, rss_i, f->indices);
+		rss_i = f->indices = f->limit;
 
 		if (!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
 			adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 5217b6d..dedb412 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4433,7 +4433,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
-	unsigned int rss;
+	unsigned int rss, fdir;
 #ifdef CONFIG_IXGBE_DCB
 	int j;
 	struct tc_configuration *tc;
@@ -4466,8 +4466,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 			adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
 		/* Flow Director hash filters enabled */
 		adapter->atr_sample_rate = 20;
-		adapter->ring_feature[RING_F_FDIR].limit =
-							 IXGBE_MAX_FDIR_INDICES;
+		fdir = min_t(int, IXGBE_MAX_FDIR_INDICES, num_online_cpus());
+		adapter->ring_feature[RING_F_FDIR].limit = fdir;
 		adapter->fdir_pballoc = IXGBE_FDIR_PBALLOC_64K;
 #ifdef IXGBE_FCOE
 		adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
@@ -7324,13 +7324,17 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
 #ifdef IXGBE_FCOE
 	if (adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) {
+		unsigned int fcoe_l;
+
 		if (hw->mac.ops.get_device_caps) {
 			hw->mac.ops.get_device_caps(hw, &device_caps);
 			if (device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)
 				adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
 		}
 
-		adapter->ring_feature[RING_F_FCOE].limit = IXGBE_FCRETA_SIZE;
+
+		fcoe_l = min_t(int, IXGBE_FCRETA_SIZE, num_online_cpus());
+		adapter->ring_feature[RING_F_FCOE].limit = fcoe_l;
 
 		netdev->features |= NETIF_F_FSO |
 				    NETIF_F_FCOE_CRC;

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (5 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 06/10] ixgbe: Define FCoE and Flow director limits much sooner to allow for changes Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-07-11 18:15   ` Ben Hutchings
  2012-06-30  0:16 ` [RFC PATCH 08/10] ixgbe: Update ixgbe driver to use __dev_pick_tx in ixgbe_select_queue Alexander Duyck
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This change adds support for ixgbe to configure the XPS queue mapping on
load.  The result of this change is that on open we will now be resetting
the number of Tx queues, and then setting the default configuration for XPS
based on if ATR is enabled or disabled.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c  |    3 +--
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |   18 ++++++++++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 72386fb..a43dae0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -797,8 +797,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
 	/* setup affinity mask and node */
 	if (cpu != -1)
 		cpumask_set_cpu(cpu, &q_vector->affinity_mask);
-	else
-		cpumask_copy(&q_vector->affinity_mask, cpu_online_mask);
+
 	q_vector->numa_node = node;
 
 	/* initialize CPU for DCA */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index dedb412..06641ea 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -4848,6 +4848,22 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 	return 0;
 }
 
+static void ixgbe_set_xps_mapping(struct net_device *netdev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_q_vector *q_vector;
+	u16 i;
+
+	for (i = 0; i < adapter->num_tx_queues; i++) {
+		q_vector = adapter->tx_ring[i]->q_vector;
+
+		if (!q_vector)
+			continue;
+
+		netif_set_xps_queue(netdev, &q_vector->affinity_mask, i);
+	}
+}
+
 /**
  * ixgbe_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -4894,6 +4910,8 @@ static int ixgbe_open(struct net_device *netdev)
 	if (err)
 		goto err_set_queues;
 
+	/* update the Tx mapping */
+	ixgbe_set_xps_mapping(netdev);
 
 	err = netif_set_real_num_rx_queues(netdev,
 					   adapter->num_rx_pools > 1 ? 1 :

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 08/10] ixgbe: Update ixgbe driver to use __dev_pick_tx in ixgbe_select_queue
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (6 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-06-30  0:16 ` [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels Alexander Duyck
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This change updates the ixgbe driver to use __dev_pick_tx instead of the
current logic it is using to select a queue.  The main result of this
change is that ixgbe can now fully support XPS.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c |   18 +++++++-----------
 1 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 06641ea..0b35ec3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6336,18 +6336,18 @@ static inline int ixgbe_maybe_stop_tx(struct ixgbe_ring *tx_ring, u16 size)
 	return __ixgbe_maybe_stop_tx(tx_ring, size);
 }
 
+#ifdef IXGBE_FCOE
 static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
-	int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
-					       smp_processor_id();
-#ifdef IXGBE_FCOE
 	__be16 protocol = vlan_get_protocol(skb);
 
 	if (((protocol == htons(ETH_P_FCOE)) ||
 	    (protocol == htons(ETH_P_FIP))) &&
 	    (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
 		struct ixgbe_ring_feature *f;
+		int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
+						       smp_processor_id();
 
 		f = &adapter->ring_feature[RING_F_FCOE];
 
@@ -6357,17 +6357,11 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 
 		return txq;
 	}
-#endif
-
-	if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
-		while (unlikely(txq >= dev->real_num_tx_queues))
-			txq -= dev->real_num_tx_queues;
-		return txq;
-	}
 
-	return skb_tx_hash(dev, skb);
+	return __dev_pick_tx(dev, skb);
 }
 
+#endif
 netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 			  struct ixgbe_adapter *adapter,
 			  struct ixgbe_ring *tx_ring)
@@ -7013,7 +7007,9 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_open		= ixgbe_open,
 	.ndo_stop		= ixgbe_close,
 	.ndo_start_xmit		= ixgbe_xmit_frame,
+#ifdef IXGBE_FCOE
 	.ndo_select_queue	= ixgbe_select_queue,
+#endif
 	.ndo_set_rx_mode	= ixgbe_set_rx_mode,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= ixgbe_set_mac,

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (7 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 08/10] ixgbe: Update ixgbe driver to use __dev_pick_tx in ixgbe_select_queue Alexander Duyck
@ 2012-06-30  0:16 ` Alexander Duyck
  2012-07-11 18:21   ` Ben Hutchings
  2012-06-30  0:17 ` [RFC PATCH 10/10] ixgbe: Add support for set_channels ethtool operation Alexander Duyck
  2012-07-03 22:30 ` [RFC PATCH 00/10] Make XPS usable within ixgbe Tom Herbert
  10 siblings, 1 reply; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:16 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This patch adds support for the ethtool get_channels operation.

Since the ixgbe driver has to support DCB as well as the other modes the
assumption I made here is that the number of channels in DCB modes refers
to the number of queues per traffic class, not the number of queues total.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |   72 ++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 4104ea2..03e369f 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2703,6 +2703,77 @@ static int ixgbe_get_ts_info(struct net_device *dev,
 	return 0;
 }
 
+static unsigned int ixgbe_max_channels(struct ixgbe_adapter *adapter)
+{
+	unsigned int max_combined;
+	u8 tcs = netdev_get_num_tc(adapter->netdev);
+
+	if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+		/* We only support one q_vector without MSI-X */
+		max_combined = 1;
+	} else if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+		/* SR-IOV currently only allows one queue on the PF */
+		max_combined = 1;
+	} else if (tcs > 1) {
+		/* For DCB report channels per traffic class */
+		if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+			/* 8 TC w/ 4 queues per TC */
+			max_combined = 4;
+		} else if (tcs > 4) {
+			/* 8 TC w/ 8 queues per TC */
+			max_combined = 8;
+		} else {
+			/* 4 TC w/ 16 queues per TC */
+			max_combined = 16;
+		}
+	} else if (adapter->atr_sample_rate) {
+		/* support up to 64 queues with ATR */
+		max_combined = IXGBE_MAX_FDIR_INDICES;
+	} else {
+		/* support up to 16 queues with RSS */
+		max_combined = IXGBE_MAX_RSS_INDICES;
+	}
+
+	return max_combined;
+}
+
+static void ixgbe_get_channels(struct net_device *dev,
+			       struct ethtool_channels *ch)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+	/* report maximum channels */
+	ch->max_combined = ixgbe_max_channels(adapter);
+
+	/* report info for other vector */
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+		ch->max_other = NON_Q_VECTORS;
+		ch->other_count = NON_Q_VECTORS;
+	}
+
+	/* record RSS queues */
+	ch->combined_count = adapter->ring_feature[RING_F_RSS].indices;
+
+	/* nothing else to report if RSS is disabled */
+	if (ch->combined_count == 1)
+		return;
+
+	/* we do not support ATR queueing if SR-IOV is enabled */
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+		return;
+
+	/* same thing goes for being DCB enabled */
+	if (netdev_get_num_tc(dev) > 1)
+		return;
+
+	/* if ATR is disabled we can exit */
+	if (!adapter->atr_sample_rate)
+		return;
+
+	/* report flow director queues as maximum channels */
+	ch->combined_count = adapter->ring_feature[RING_F_FDIR].indices;
+}
+
 static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_settings           = ixgbe_get_settings,
 	.set_settings           = ixgbe_set_settings,
@@ -2732,6 +2803,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_rxnfc		= ixgbe_get_rxnfc,
 	.set_rxnfc		= ixgbe_set_rxnfc,
 	.get_ts_info		= ixgbe_get_ts_info,
+	.get_channels		= ixgbe_get_channels,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [RFC PATCH 10/10] ixgbe: Add support for set_channels ethtool operation
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (8 preceding siblings ...)
  2012-06-30  0:16 ` [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels Alexander Duyck
@ 2012-06-30  0:17 ` Alexander Duyck
  2012-07-03 22:30 ` [RFC PATCH 00/10] Make XPS usable within ixgbe Tom Herbert
  10 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-06-30  0:17 UTC (permalink / raw)
  To: netdev
  Cc: davem, jeffrey.t.kirsher, edumazet, bhutchings, therbert,
	alexander.duyck

This change adds support for the ethtool set_channels operation.

Since the ixgbe driver has to support DCB as well as the other modes the
assumption I made here is that the number of channels in DCB modes refers
to the number of queues per traffic class, not the number of queues total.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---

 drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |   40 ++++++++++++++++++++++
 1 files changed, 40 insertions(+), 0 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 03e369f..ec49afb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -2774,6 +2774,45 @@ static void ixgbe_get_channels(struct net_device *dev,
 	ch->combined_count = adapter->ring_feature[RING_F_FDIR].indices;
 }
 
+static int ixgbe_set_channels(struct net_device *dev,
+			      struct ethtool_channels *ch)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	unsigned int count = ch->combined_count;
+
+	/* verify they are not requesting separate vectors */
+	if (ch->rx_count || ch->tx_count)
+		return -EINVAL;
+
+	/* ignore other_count since it is not changeable */
+
+	/* verify we have at least one channel requested */
+	if (!count)
+		return -EINVAL;
+
+	/* verify the number of channels does not exceed hardware limits */
+	if (count > ixgbe_max_channels(adapter))
+		return -EINVAL;
+
+	/* update feature limits from largest to smallest supported values */
+	adapter->ring_feature[RING_F_FDIR].limit = count;
+
+	/* cap RSS limit at 16 */
+	if (count > IXGBE_MAX_RSS_INDICES)
+		count = IXGBE_MAX_RSS_INDICES;
+	adapter->ring_feature[RING_F_RSS].limit = count;
+
+#ifdef IXGBE_FCOE
+	/* cap FCoE limit at 8 */
+	if (count > IXGBE_FCRETA_SIZE)
+		count = IXGBE_FCRETA_SIZE;
+	adapter->ring_feature[RING_F_FCOE].limit = count;
+
+#endif
+	/* use setup TC to update any traffic class queue mapping */
+	return ixgbe_setup_tc(dev, netdev_get_num_tc(dev));
+}
+
 static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.get_settings           = ixgbe_get_settings,
 	.set_settings           = ixgbe_set_settings,
@@ -2804,6 +2843,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.set_rxnfc		= ixgbe_set_rxnfc,
 	.get_ts_info		= ixgbe_get_ts_info,
 	.get_channels		= ixgbe_get_channels,
+	.set_channels		= ixgbe_set_channels,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 00/10] Make XPS usable within ixgbe
  2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
                   ` (9 preceding siblings ...)
  2012-06-30  0:17 ` [RFC PATCH 10/10] ixgbe: Add support for set_channels ethtool operation Alexander Duyck
@ 2012-07-03 22:30 ` Tom Herbert
  2012-07-03 22:41   ` John Fastabend
  10 siblings, 1 reply; 19+ messages in thread
From: Tom Herbert @ 2012-07-03 22:30 UTC (permalink / raw)
  To: Alexander Duyck
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, bhutchings, alexander.duyck

Hi Alexander,

Thanks for this work!

Some general comments:

1) skb_tx_hash is called from a handful of drivers (bnx2x, ixgbe,
mlx4, and bonding).  Would it make sent to call xps_get_cpu from that
function (unfortunately the use of ndo_select_queue is likely
bypassing xps unnecessarily in these drivers).
2) Instead of (or maybe in addition to) allowing driver to program xps
maps, we could parameterize get_xps_cpu to optionally include a bit
map of acceptable queues.  This would be useful to define a
hierarchical queue selection (like first choose a set for QoS, then
amongst those chose one base on xps).

Tom

On Fri, Jun 29, 2012 at 5:16 PM, Alexander Duyck
<alexander.h.duyck@intel.com> wrote:
> The following patch series makes it so that the ixgbe driver can support
> ATR even when the number of queues is less than the number of CPUs.  To do
> this I have updated the kernel to support letting drivers set their own XPS
> configuration.  To do this it was necessary to move the code out of the
> sysfs specific code and into the dev specific regions.
>
> I am still working out a few issues such as the fact that with routing I
> only ever seem to be able to get the first queue that is mapped to the CPU
> when XPS is enabled.
>
> Also I am looking for input on if it is acceptable to only let the
> set_channels/get_channels calls report/set the number of queues per traffic
> class as I implemented the code this way to avoid any significant conflicts
> between the DCB traffic classes code and these functions.
>
> ---
>
> Alexander Duyck (10):
>       ixgbe: Add support for set_channels ethtool operation
>       ixgbe: Add support for displaying the number of Tx/Rx channels
>       ixgbe: Update ixgbe driver to use __dev_pick_tx in ixgbe_select_queue
>       ixgbe: Add function for setting XPS queue mapping
>       ixgbe: Define FCoE and Flow director limits much sooner to allow for changes
>       net: Add support for XPS without SYSFS being defined
>       net: Rewrite netif_set_xps_queues to address several issues
>       net: Rewrite netif_reset_xps_queue to allow for better code reuse
>       net: Add functions netif_reset_xps_queue and netif_set_xps_queue
>       net: Split core bits of dev_pick_tx into __dev_pick_tx
>
>
>  drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c |  112 +++++++++
>  drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c     |   10 -
>  drivers/net/ethernet/intel/ixgbe/ixgbe_main.c    |   48 +++-
>  include/linux/netdevice.h                        |   15 +
>  net/Kconfig                                      |    2
>  net/core/dev.c                                   |  283 ++++++++++++++++++++--
>  net/core/net-sysfs.c                             |  160 ------------
>  7 files changed, 428 insertions(+), 202 deletions(-)
>
> --
> Thanks,
>
> Alex

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 00/10] Make XPS usable within ixgbe
  2012-07-03 22:30 ` [RFC PATCH 00/10] Make XPS usable within ixgbe Tom Herbert
@ 2012-07-03 22:41   ` John Fastabend
  0 siblings, 0 replies; 19+ messages in thread
From: John Fastabend @ 2012-07-03 22:41 UTC (permalink / raw)
  To: Tom Herbert, Alexander Duyck
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, bhutchings, alexander.duyck

On 7/3/2012 3:30 PM, Tom Herbert wrote:
> Hi Alexander,
>
> Thanks for this work!
>
> Some general comments:
>
> 1) skb_tx_hash is called from a handful of drivers (bnx2x, ixgbe,
> mlx4, and bonding).  Would it make sent to call xps_get_cpu from that
> function (unfortunately the use of ndo_select_queue is likely
> bypassing xps unnecessarily in these drivers).

I suspect we can get rid of the select_queue cases for at least
bnx2x, ixgbe, and mlx4. We might need to be a bit clever to resolve
the mlx4 case but should be doable.

Anyways I would like to see these cases refactored away.

> 2) Instead of (or maybe in addition to) allowing driver to program xps
> maps, we could parameterize get_xps_cpu to optionally include a bit
> map of acceptable queues.  This would be useful to define a
> hierarchical queue selection (like first choose a set for QoS, then
> amongst those chose one base on xps).
>

Agreed.

We likely need something like (2) to get this to work with mqprio and
other QOS schemes in use.

.John

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx
  2012-06-30  0:16 ` [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx Alexander Duyck
@ 2012-07-07  0:03   ` Ben Hutchings
       [not found]     ` <CAL1qit_mpmVYQ3D4HQsii5LJ+Nu5=ftFWAWVnfPiDbmW5eWa0Q@mail.gmail.com>
  0 siblings, 1 reply; 19+ messages in thread
From: Ben Hutchings @ 2012-07-07  0:03 UTC (permalink / raw)
  To: Alexander Duyck
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, therbert, alexander.duyck

On Fri, 2012-06-29 at 17:16 -0700, Alexander Duyck wrote:
> This change splits the core bits of dev_pick_tx into a separate function.
> The main idea behind this is to make this code accessible to select queue
> functions when they decide to process the standard path instead of their
> own custom path in their select queue routine.
[...]

I like this.  Uninlining that code is going to cost some cycles, but
hopefully not enough to worry about.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping
  2012-06-30  0:16 ` [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping Alexander Duyck
@ 2012-07-11 18:15   ` Ben Hutchings
  2012-07-11 21:12     ` Alexander Duyck
  0 siblings, 1 reply; 19+ messages in thread
From: Ben Hutchings @ 2012-07-11 18:15 UTC (permalink / raw)
  To: Alexander Duyck
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, therbert, alexander.duyck

On Fri, 2012-06-29 at 17:16 -0700, Alexander Duyck wrote:
> This change adds support for ixgbe to configure the XPS queue mapping on
> load.  The result of this change is that on open we will now be resetting
> the number of Tx queues, and then setting the default configuration for XPS
> based on if ATR is enabled or disabled.
[...]

I didn't see where you're resetting the number of TX queues; was that
actually added in an earlier patch?

It seems strange to be resetting XPS configuration on open; normally net
device configuration persists as long as the device is registered.
Maybe only do this if the number of TX queues has to change?

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels
  2012-06-30  0:16 ` [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels Alexander Duyck
@ 2012-07-11 18:21   ` Ben Hutchings
  2012-07-11 21:00     ` Alexander Duyck
  0 siblings, 1 reply; 19+ messages in thread
From: Ben Hutchings @ 2012-07-11 18:21 UTC (permalink / raw)
  To: Alexander Duyck
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, therbert, alexander.duyck

On Fri, 2012-06-29 at 17:16 -0700, Alexander Duyck wrote:
> This patch adds support for the ethtool get_channels operation.
> 
> Since the ixgbe driver has to support DCB as well as the other modes the
> assumption I made here is that the number of channels in DCB modes refers
> to the number of queues per traffic class, not the number of queues total.
[...]

When MSI-X is enabled, a 'channel' is an MSI-X vector and the associated
queues, i.e. total number of channels reported should be the total
number of MSI-X vectors in use.  (That was my intended interpretation,
anyway.  It may be that there is too much variation in the way queues
and interrupts are associated for these operations to be defined in a
general way.)

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels
  2012-07-11 18:21   ` Ben Hutchings
@ 2012-07-11 21:00     ` Alexander Duyck
  0 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-07-11 21:00 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, therbert, alexander.duyck

On 07/11/2012 11:21 AM, Ben Hutchings wrote:
> On Fri, 2012-06-29 at 17:16 -0700, Alexander Duyck wrote:
>> This patch adds support for the ethtool get_channels operation.
>>
>> Since the ixgbe driver has to support DCB as well as the other modes the
>> assumption I made here is that the number of channels in DCB modes refers
>> to the number of queues per traffic class, not the number of queues total.
> [...]
>
> When MSI-X is enabled, a 'channel' is an MSI-X vector and the associated
> queues, i.e. total number of channels reported should be the total
> number of MSI-X vectors in use.  (That was my intended interpretation,
> anyway.  It may be that there is too much variation in the way queues
> and interrupts are associated for these operations to be defined in a
> general way.)
>
> Ben.
>
The problem with the MSI-X interpretation is that ixgbe has that type of
control reversed.  We base everything on the number of queues, and then
from that you can end up determining the number of MSI-X vectors.  So
for example we could tell ixgbe via this interface to generate 64
queues, but if the system only has 8 CPUs we would end up with 8 MSI-X
vectors each with 8 queues.

Also as I mentioned in the case of DCB things get even more
complicated.  We need to have a symmetric number of queues per traffic
class based on the way we currently have DCB implemented.  The way I saw
it I could go two routes, the first being to force channels to be a
multiple of TCs which would have been complicated to deal with, or the
simpler approach I chose which was to apply 'channel' to be per TC. 
This way if DCB is then disabled we can easily revert to the standard
interpretation which would mean we would only have as many queues as the
channels specified.

Thanks,

Alex

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping
  2012-07-11 18:15   ` Ben Hutchings
@ 2012-07-11 21:12     ` Alexander Duyck
  0 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-07-11 21:12 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: netdev, davem, jeffrey.t.kirsher, edumazet, therbert, alexander.duyck

On 07/11/2012 11:15 AM, Ben Hutchings wrote:
> On Fri, 2012-06-29 at 17:16 -0700, Alexander Duyck wrote:
>> This change adds support for ixgbe to configure the XPS queue mapping on
>> load.  The result of this change is that on open we will now be resetting
>> the number of Tx queues, and then setting the default configuration for XPS
>> based on if ATR is enabled or disabled.
> [...]
>
> I didn't see where you're resetting the number of TX queues; was that
> actually added in an earlier patch?
>
> It seems strange to be resetting XPS configuration on open; normally net
> device configuration persists as long as the device is registered.
> Maybe only do this if the number of TX queues has to change?
>
> Ben.
>
Actually I am working on top of a set of patches for ixgbe that haven't
been submitted upstream.  In one of those patches I moved our call to
netif_set_real_num_tx_queues into ixgbe_open.  The call is only one or
two lines above the call I make to ixgbe_set_xps_mapping.

I will see what I can do about resetting the settings only when we
change the number of queues.

Thanks,

Alex

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx
       [not found]     ` <CAL1qit_mpmVYQ3D4HQsii5LJ+Nu5=ftFWAWVnfPiDbmW5eWa0Q@mail.gmail.com>
@ 2012-08-02 15:45       ` Alexander Duyck
  0 siblings, 0 replies; 19+ messages in thread
From: Alexander Duyck @ 2012-08-02 15:45 UTC (permalink / raw)
  To: Ying Cai
  Cc: Ben Hutchings, netdev, davem, jeffrey.t.kirsher, edumazet,
	therbert, alexander.duyck

On 08/01/2012 08:51 PM, Ying Cai wrote:
> I liked this patch too. It enabled Ethernet NIC drivers to use
> the __dev_pick_tx() in their ndo_select_queue() to use XPS. I have
> data showing XPS helps performances of bnx2x driver significantly.
>
> Acked-by: Ying Cai <ycai@ <mailto:jg1.han@samsung.com>google.com
> <http://google.com>>
This was an RFC so there is no need to ack it.

I will try to get these patches cleaned up and ready for submission. 
Hopefully I will have something to submit to net-next in the next couple
of weeks.

Thanks,

Alex

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-08-02 15:45 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-30  0:16 [RFC PATCH 00/10] Make XPS usable within ixgbe Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 01/10] net: Split core bits of dev_pick_tx into __dev_pick_tx Alexander Duyck
2012-07-07  0:03   ` Ben Hutchings
     [not found]     ` <CAL1qit_mpmVYQ3D4HQsii5LJ+Nu5=ftFWAWVnfPiDbmW5eWa0Q@mail.gmail.com>
2012-08-02 15:45       ` Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 02/10] net: Add functions netif_reset_xps_queue and netif_set_xps_queue Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 03/10] net: Rewrite netif_reset_xps_queue to allow for better code reuse Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 04/10] net: Rewrite netif_set_xps_queues to address several issues Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 05/10] net: Add support for XPS without SYSFS being defined Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 06/10] ixgbe: Define FCoE and Flow director limits much sooner to allow for changes Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 07/10] ixgbe: Add function for setting XPS queue mapping Alexander Duyck
2012-07-11 18:15   ` Ben Hutchings
2012-07-11 21:12     ` Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 08/10] ixgbe: Update ixgbe driver to use __dev_pick_tx in ixgbe_select_queue Alexander Duyck
2012-06-30  0:16 ` [RFC PATCH 09/10] ixgbe: Add support for displaying the number of Tx/Rx channels Alexander Duyck
2012-07-11 18:21   ` Ben Hutchings
2012-07-11 21:00     ` Alexander Duyck
2012-06-30  0:17 ` [RFC PATCH 10/10] ixgbe: Add support for set_channels ethtool operation Alexander Duyck
2012-07-03 22:30 ` [RFC PATCH 00/10] Make XPS usable within ixgbe Tom Herbert
2012-07-03 22:41   ` John Fastabend

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.