[Intel-wired-lan] [net-next PATCH 2/3] net: Refactor removal of queues from XPS map and apply on num_tc changes
Tom Herbert
tom at herbertland.com
Fri Oct 28 02:35:13 UTC 2016
On Thu, Oct 27, 2016 at 8:40 AM, Alexander Duyck
<alexander.h.duyck at intel.com> wrote:
> This patch updates the code for removing queues from the XPS map and makes
> it so that we can apply the code any time we change either the number of
> traffic classes or the mapping of a given block of queues. This way we
> avoid having queues pulling traffic from a foreign traffic class.
>
> Signed-off-by: Alexander Duyck <alexander.h.duyck at intel.com>
> ---
> net/core/dev.c | 79 ++++++++++++++++++++++++++++++++++++++++----------------
> 1 file changed, 56 insertions(+), 23 deletions(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index d4d45bf..d124081 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -1953,32 +1953,56 @@ static void netif_setup_tc(struct net_device *dev, unsigned int txq)
> #define xmap_dereference(P) \
> rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
>
> -static struct xps_map *remove_xps_queue(struct xps_dev_maps *dev_maps,
> - int cpu, u16 index)
> +static bool remove_xps_queue(struct xps_dev_maps *dev_maps,
> + int tci, u16 index)
> {
> struct xps_map *map = NULL;
> int pos;
>
> if (dev_maps)
> - map = xmap_dereference(dev_maps->cpu_map[cpu]);
> + map = xmap_dereference(dev_maps->cpu_map[tci]);
> + if (!map)
> + return false;
>
> - 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[cpu], NULL);
> - kfree_rcu(map, rcu);
> - map = NULL;
> - }
> + for (pos = map->len; pos--;) {
> + if (map->queues[pos] != index)
> + continue;
> +
> + if (map->len > 1) {
> + map->queues[pos] = map->queues[--map->len];
> break;
> }
> +
> + RCU_INIT_POINTER(dev_maps->cpu_map[tci], NULL);
> + kfree_rcu(map, rcu);
> + return false;
> }
>
> - return map;
> + return true;
> }
>
> -static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
> +static bool remove_xps_queue_cpu(struct net_device *dev,
> + struct xps_dev_maps *dev_maps,
> + int cpu, u16 offset, u16 count)
> +{
> + bool active = false;
> + int i;
> +
> + count += offset;
> + i = count;
> +
> + do {
> + if (i-- == offset) {
> + active = true;
> + break;
> + }
> + } while (remove_xps_queue(dev_maps, cpu, i));
> +
IMO do/while's are hard to read. Does something like this work:
static bool remove_xps_queue_cpu(struct net_device *dev,
struct xps_dev_maps *dev_maps,
int cpu, u16 offset, u16 count)
{
int i;
for (i = count + offset; i > offset; i--)
if (!remove_xps_queue(dev_maps, cpu, i - 1))
break;
return (i == offset);
}
> + return active;
> +}
> +
> +static void netif_reset_xps_queues(struct net_device *dev, u16 offset,
> + u16 count)
> {
> struct xps_dev_maps *dev_maps;
> int cpu, i;
> @@ -1990,21 +2014,16 @@ static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
> if (!dev_maps)
> goto out_no_maps;
>
> - for_each_possible_cpu(cpu) {
> - 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;
> - }
> + for_each_possible_cpu(cpu)
> + active |= remove_xps_queue_cpu(dev, dev_maps, cpu, offset,
> + count);
Maybe just do dumb "if (remove_xps...) active = true;"
>
> if (!active) {
> RCU_INIT_POINTER(dev->xps_maps, NULL);
> kfree_rcu(dev_maps, rcu);
> }
>
> - for (i = index; i < dev->num_tx_queues; i++)
> + for (i = offset + (count - 1); count--; i--)
> netdev_queue_numa_node_write(netdev_get_tx_queue(dev, i),
> NUMA_NO_NODE);
>
> @@ -2012,6 +2031,11 @@ static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
> mutex_unlock(&xps_map_mutex);
> }
>
> +static void netif_reset_xps_queues_gt(struct net_device *dev, u16 index)
> +{
> + netif_reset_xps_queues(dev, index, dev->num_tx_queues - index);
> +}
> +
> static struct xps_map *expand_xps_map(struct xps_map *map,
> int cpu, u16 index)
> {
> @@ -2175,6 +2199,9 @@ int netif_set_xps_queue(struct net_device *dev, const struct cpumask *mask,
> #endif
> void netdev_reset_tc(struct net_device *dev)
> {
> +#ifdef CONFIG_XPS
> + netif_reset_xps_queues_gt(dev, 0);
> +#endif
> dev->num_tc = 0;
> memset(dev->tc_to_txq, 0, sizeof(dev->tc_to_txq));
> memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
> @@ -2186,6 +2213,9 @@ int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)
> if (tc >= dev->num_tc)
> return -EINVAL;
>
> +#ifdef CONFIG_XPS
> + netif_reset_xps_queues(dev, offset, count);
> +#endif
> dev->tc_to_txq[tc].count = count;
> dev->tc_to_txq[tc].offset = offset;
> return 0;
> @@ -2197,6 +2227,9 @@ int netdev_set_num_tc(struct net_device *dev, u8 num_tc)
> if (num_tc > TC_MAX_QUEUE)
> return -EINVAL;
>
> +#ifdef CONFIG_XPS
> + netif_reset_xps_queues_gt(dev, 0);
> +#endif
> dev->num_tc = num_tc;
> return 0;
> }
>
More information about the Intel-wired-lan
mailing list