rps: allocate rx queues in register_netdevice only
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>
This commit is contained in:
committed by
David S. Miller
parent
7a91b434e2
commit
1b4bf461f0
@@ -4964,6 +4964,34 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(netif_stacked_transfer_operstate);
|
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
|
* register_netdevice - register a network device
|
||||||
* @dev: device to register
|
* @dev: device to register
|
||||||
@@ -5001,24 +5029,10 @@ int register_netdevice(struct net_device *dev)
|
|||||||
|
|
||||||
dev->iflink = -1;
|
dev->iflink = -1;
|
||||||
|
|
||||||
#ifdef CONFIG_RPS
|
ret = netif_alloc_rx_queues(dev);
|
||||||
if (!dev->num_rx_queues) {
|
if (ret)
|
||||||
/*
|
goto out;
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->_rx->first = dev->_rx;
|
|
||||||
atomic_set(&dev->_rx->count, 1);
|
|
||||||
dev->num_rx_queues = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Init, if this function is available */
|
/* Init, if this function is available */
|
||||||
if (dev->netdev_ops->ndo_init) {
|
if (dev->netdev_ops->ndo_init) {
|
||||||
ret = dev->netdev_ops->ndo_init(dev);
|
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;
|
struct net_device *dev;
|
||||||
size_t alloc_size;
|
size_t alloc_size;
|
||||||
struct net_device *p;
|
struct net_device *p;
|
||||||
#ifdef CONFIG_RPS
|
|
||||||
struct netdev_rx_queue *rx;
|
|
||||||
int i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BUG_ON(strlen(name) >= sizeof(dev->name));
|
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;
|
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 = PTR_ALIGN(p, NETDEV_ALIGN);
|
||||||
dev->padded = (char *)dev - (char *)p;
|
dev->padded = (char *)dev - (char *)p;
|
||||||
|
|
||||||
if (dev_addr_init(dev))
|
if (dev_addr_init(dev))
|
||||||
goto free_rx;
|
goto free_tx;
|
||||||
|
|
||||||
dev_mc_init(dev);
|
dev_mc_init(dev);
|
||||||
dev_uc_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;
|
dev->real_num_tx_queues = queue_count;
|
||||||
|
|
||||||
#ifdef CONFIG_RPS
|
#ifdef CONFIG_RPS
|
||||||
dev->_rx = rx;
|
|
||||||
dev->num_rx_queues = queue_count;
|
dev->num_rx_queues = queue_count;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -5496,11 +5488,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
|
|||||||
strcpy(dev->name, name);
|
strcpy(dev->name, name);
|
||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
free_rx:
|
|
||||||
#ifdef CONFIG_RPS
|
|
||||||
kfree(rx);
|
|
||||||
free_tx:
|
free_tx:
|
||||||
#endif
|
|
||||||
kfree(tx);
|
kfree(tx);
|
||||||
free_p:
|
free_p:
|
||||||
kfree(p);
|
kfree(p);
|
||||||
|
Reference in New Issue
Block a user