rps: allocate rx queues in register_netdevice only
Eric Dumazet [Thu, 23 Sep 2010 17:26:35 +0000 (17:26 +0000)]
Instead of having two places were we allocate dev->_rx, introduce
netif_alloc_rx_queues() helper and call it only from
register_netdevice(), not from alloc_netdev_mq()

Goal is to let drivers change dev->num_rx_queues after allocating netdev
and before registering it.

This also removes a lot of ifdefs in net/core/dev.c

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

net/core/dev.c

index e0c0b86..72e9983 100644 (file)
@@ -4964,6 +4964,34 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 }
 EXPORT_SYMBOL(netif_stacked_transfer_operstate);
 
+static int netif_alloc_rx_queues(struct net_device *dev)
+{
+#ifdef CONFIG_RPS
+       unsigned int i, count = dev->num_rx_queues;
+
+       if (count) {
+               struct netdev_rx_queue *rx;
+
+               rx = kcalloc(count, sizeof(struct netdev_rx_queue), GFP_KERNEL);
+               if (!rx) {
+                       pr_err("netdev: Unable to allocate %u rx queues.\n",
+                              count);
+                       return -ENOMEM;
+               }
+               dev->_rx = rx;
+               atomic_set(&rx->count, count);
+
+               /*
+                * Set a pointer to first element in the array which holds the
+                * reference count.
+                */
+               for (i = 0; i < count; i++)
+                       rx[i].first = rx;
+       }
+#endif
+       return 0;
+}
+
 /**
  *     register_netdevice      - register a network device
  *     @dev: device to register
@@ -5001,24 +5029,10 @@ int register_netdevice(struct net_device *dev)
 
        dev->iflink = -1;
 
-#ifdef CONFIG_RPS
-       if (!dev->num_rx_queues) {
-               /*
-                * Allocate a single RX queue if driver never called
-                * alloc_netdev_mq
-                */
-
-               dev->_rx = kzalloc(sizeof(struct netdev_rx_queue), GFP_KERNEL);
-               if (!dev->_rx) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+       ret = netif_alloc_rx_queues(dev);
+       if (ret)
+               goto out;
 
-               dev->_rx->first = dev->_rx;
-               atomic_set(&dev->_rx->count, 1);
-               dev->num_rx_queues = 1;
-       }
-#endif
        /* Init, if this function is available */
        if (dev->netdev_ops->ndo_init) {
                ret = dev->netdev_ops->ndo_init(dev);
@@ -5415,10 +5429,6 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
        struct net_device *dev;
        size_t alloc_size;
        struct net_device *p;
-#ifdef CONFIG_RPS
-       struct netdev_rx_queue *rx;
-       int i;
-#endif
 
        BUG_ON(strlen(name) >= sizeof(dev->name));
 
@@ -5444,29 +5454,12 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
                goto free_p;
        }
 
-#ifdef CONFIG_RPS
-       rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL);
-       if (!rx) {
-               printk(KERN_ERR "alloc_netdev: Unable to allocate "
-                      "rx queues.\n");
-               goto free_tx;
-       }
-
-       atomic_set(&rx->count, queue_count);
-
-       /*
-        * Set a pointer to first element in the array which holds the
-        * reference count.
-        */
-       for (i = 0; i < queue_count; i++)
-               rx[i].first = rx;
-#endif
 
        dev = PTR_ALIGN(p, NETDEV_ALIGN);
        dev->padded = (char *)dev - (char *)p;
 
        if (dev_addr_init(dev))
-               goto free_rx;
+               goto free_tx;
 
        dev_mc_init(dev);
        dev_uc_init(dev);
@@ -5478,7 +5471,6 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
        dev->real_num_tx_queues = queue_count;
 
 #ifdef CONFIG_RPS
-       dev->_rx = rx;
        dev->num_rx_queues = queue_count;
 #endif
 
@@ -5496,11 +5488,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
        strcpy(dev->name, name);
        return dev;
 
-free_rx:
-#ifdef CONFIG_RPS
-       kfree(rx);
 free_tx:
-#endif
        kfree(tx);
 free_p:
        kfree(p);