diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-09-23 13:26:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-26 22:04:07 -0400 |
commit | 1b4bf461f05d56ced6d6b8f3b4831adc7076f565 (patch) | |
tree | 632708e37f7f9ccdef2a774b38904c5dfd6a8ecc /net/core/dev.c | |
parent | 7a91b434e2bad554b709265db7603b1aa52dd92e (diff) |
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>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index e0c0b86f57a1..72e99835e5b8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4964,6 +4964,34 @@ void netif_stacked_transfer_operstate(const struct net_device *rootdev, | |||
4964 | } | 4964 | } |
4965 | EXPORT_SYMBOL(netif_stacked_transfer_operstate); | 4965 | EXPORT_SYMBOL(netif_stacked_transfer_operstate); |
4966 | 4966 | ||
4967 | static int netif_alloc_rx_queues(struct net_device *dev) | ||
4968 | { | ||
4969 | #ifdef CONFIG_RPS | ||
4970 | unsigned int i, count = dev->num_rx_queues; | ||
4971 | |||
4972 | if (count) { | ||
4973 | struct netdev_rx_queue *rx; | ||
4974 | |||
4975 | rx = kcalloc(count, sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
4976 | if (!rx) { | ||
4977 | pr_err("netdev: Unable to allocate %u rx queues.\n", | ||
4978 | count); | ||
4979 | return -ENOMEM; | ||
4980 | } | ||
4981 | dev->_rx = rx; | ||
4982 | atomic_set(&rx->count, count); | ||
4983 | |||
4984 | /* | ||
4985 | * Set a pointer to first element in the array which holds the | ||
4986 | * reference count. | ||
4987 | */ | ||
4988 | for (i = 0; i < count; i++) | ||
4989 | rx[i].first = rx; | ||
4990 | } | ||
4991 | #endif | ||
4992 | return 0; | ||
4993 | } | ||
4994 | |||
4967 | /** | 4995 | /** |
4968 | * register_netdevice - register a network device | 4996 | * register_netdevice - register a network device |
4969 | * @dev: device to register | 4997 | * @dev: device to register |
@@ -5001,24 +5029,10 @@ int register_netdevice(struct net_device *dev) | |||
5001 | 5029 | ||
5002 | dev->iflink = -1; | 5030 | dev->iflink = -1; |
5003 | 5031 | ||
5004 | #ifdef CONFIG_RPS | 5032 | ret = netif_alloc_rx_queues(dev); |
5005 | if (!dev->num_rx_queues) { | 5033 | if (ret) |
5006 | /* | 5034 | goto out; |
5007 | * Allocate a single RX queue if driver never called | ||
5008 | * alloc_netdev_mq | ||
5009 | */ | ||
5010 | |||
5011 | dev->_rx = kzalloc(sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
5012 | if (!dev->_rx) { | ||
5013 | ret = -ENOMEM; | ||
5014 | goto out; | ||
5015 | } | ||
5016 | 5035 | ||
5017 | dev->_rx->first = dev->_rx; | ||
5018 | atomic_set(&dev->_rx->count, 1); | ||
5019 | dev->num_rx_queues = 1; | ||
5020 | } | ||
5021 | #endif | ||
5022 | /* Init, if this function is available */ | 5036 | /* Init, if this function is available */ |
5023 | if (dev->netdev_ops->ndo_init) { | 5037 | if (dev->netdev_ops->ndo_init) { |
5024 | ret = dev->netdev_ops->ndo_init(dev); | 5038 | ret = dev->netdev_ops->ndo_init(dev); |
@@ -5415,10 +5429,6 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5415 | struct net_device *dev; | 5429 | struct net_device *dev; |
5416 | size_t alloc_size; | 5430 | size_t alloc_size; |
5417 | struct net_device *p; | 5431 | struct net_device *p; |
5418 | #ifdef CONFIG_RPS | ||
5419 | struct netdev_rx_queue *rx; | ||
5420 | int i; | ||
5421 | #endif | ||
5422 | 5432 | ||
5423 | BUG_ON(strlen(name) >= sizeof(dev->name)); | 5433 | BUG_ON(strlen(name) >= sizeof(dev->name)); |
5424 | 5434 | ||
@@ -5444,29 +5454,12 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5444 | goto free_p; | 5454 | goto free_p; |
5445 | } | 5455 | } |
5446 | 5456 | ||
5447 | #ifdef CONFIG_RPS | ||
5448 | rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
5449 | if (!rx) { | ||
5450 | printk(KERN_ERR "alloc_netdev: Unable to allocate " | ||
5451 | "rx queues.\n"); | ||
5452 | goto free_tx; | ||
5453 | } | ||
5454 | |||
5455 | atomic_set(&rx->count, queue_count); | ||
5456 | |||
5457 | /* | ||
5458 | * Set a pointer to first element in the array which holds the | ||
5459 | * reference count. | ||
5460 | */ | ||
5461 | for (i = 0; i < queue_count; i++) | ||
5462 | rx[i].first = rx; | ||
5463 | #endif | ||
5464 | 5457 | ||
5465 | dev = PTR_ALIGN(p, NETDEV_ALIGN); | 5458 | dev = PTR_ALIGN(p, NETDEV_ALIGN); |
5466 | dev->padded = (char *)dev - (char *)p; | 5459 | dev->padded = (char *)dev - (char *)p; |
5467 | 5460 | ||
5468 | if (dev_addr_init(dev)) | 5461 | if (dev_addr_init(dev)) |
5469 | goto free_rx; | 5462 | goto free_tx; |
5470 | 5463 | ||
5471 | dev_mc_init(dev); | 5464 | dev_mc_init(dev); |
5472 | dev_uc_init(dev); | 5465 | dev_uc_init(dev); |
@@ -5478,7 +5471,6 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5478 | dev->real_num_tx_queues = queue_count; | 5471 | dev->real_num_tx_queues = queue_count; |
5479 | 5472 | ||
5480 | #ifdef CONFIG_RPS | 5473 | #ifdef CONFIG_RPS |
5481 | dev->_rx = rx; | ||
5482 | dev->num_rx_queues = queue_count; | 5474 | dev->num_rx_queues = queue_count; |
5483 | #endif | 5475 | #endif |
5484 | 5476 | ||
@@ -5496,11 +5488,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5496 | strcpy(dev->name, name); | 5488 | strcpy(dev->name, name); |
5497 | return dev; | 5489 | return dev; |
5498 | 5490 | ||
5499 | free_rx: | ||
5500 | #ifdef CONFIG_RPS | ||
5501 | kfree(rx); | ||
5502 | free_tx: | 5491 | free_tx: |
5503 | #endif | ||
5504 | kfree(tx); | 5492 | kfree(tx); |
5505 | free_p: | 5493 | free_p: |
5506 | kfree(p); | 5494 | kfree(p); |