diff options
author | Tom Herbert <therbert@google.com> | 2010-11-09 05:47:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-11-15 13:57:28 -0500 |
commit | fe8222406c8277a21172479d3a8283d31c209028 (patch) | |
tree | 89876457391fba73e3c2c9fdbf9c28a980ad4ffc /net/core | |
parent | ed9af2e839c06c18f721da2c768fbb444c4a10e5 (diff) |
net: Simplify RX queue allocation
This patch move RX queue allocation to alloc_netdev_mq and freeing of
the queues to free_netdev (symmetric to TX queue allocation). Each
kobject RX queue takes a reference to the queue's device so that the
device can't be freed before all the kobjects have been released-- this
obviates the need for reference counts specific to RX queues.
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 19 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 7 |
2 files changed, 12 insertions, 14 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 75490670e0a9..8725d168d1f5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -5051,12 +5051,8 @@ static int netif_alloc_rx_queues(struct net_device *dev) | |||
5051 | } | 5051 | } |
5052 | dev->_rx = rx; | 5052 | dev->_rx = rx; |
5053 | 5053 | ||
5054 | /* | ||
5055 | * Set a pointer to first element in the array which holds the | ||
5056 | * reference count. | ||
5057 | */ | ||
5058 | for (i = 0; i < count; i++) | 5054 | for (i = 0; i < count; i++) |
5059 | rx[i].first = rx; | 5055 | rx[i].dev = dev; |
5060 | #endif | 5056 | #endif |
5061 | return 0; | 5057 | return 0; |
5062 | } | 5058 | } |
@@ -5132,10 +5128,6 @@ int register_netdevice(struct net_device *dev) | |||
5132 | 5128 | ||
5133 | dev->iflink = -1; | 5129 | dev->iflink = -1; |
5134 | 5130 | ||
5135 | ret = netif_alloc_rx_queues(dev); | ||
5136 | if (ret) | ||
5137 | goto out; | ||
5138 | |||
5139 | netdev_init_queues(dev); | 5131 | netdev_init_queues(dev); |
5140 | 5132 | ||
5141 | /* Init, if this function is available */ | 5133 | /* Init, if this function is available */ |
@@ -5601,6 +5593,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5601 | #ifdef CONFIG_RPS | 5593 | #ifdef CONFIG_RPS |
5602 | dev->num_rx_queues = queue_count; | 5594 | dev->num_rx_queues = queue_count; |
5603 | dev->real_num_rx_queues = queue_count; | 5595 | dev->real_num_rx_queues = queue_count; |
5596 | if (netif_alloc_rx_queues(dev)) | ||
5597 | goto free_pcpu; | ||
5604 | #endif | 5598 | #endif |
5605 | 5599 | ||
5606 | dev->gso_max_size = GSO_MAX_SIZE; | 5600 | dev->gso_max_size = GSO_MAX_SIZE; |
@@ -5618,6 +5612,10 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5618 | free_pcpu: | 5612 | free_pcpu: |
5619 | free_percpu(dev->pcpu_refcnt); | 5613 | free_percpu(dev->pcpu_refcnt); |
5620 | kfree(dev->_tx); | 5614 | kfree(dev->_tx); |
5615 | #ifdef CONFIG_RPS | ||
5616 | kfree(dev->_rx); | ||
5617 | #endif | ||
5618 | |||
5621 | free_p: | 5619 | free_p: |
5622 | kfree(p); | 5620 | kfree(p); |
5623 | return NULL; | 5621 | return NULL; |
@@ -5639,6 +5637,9 @@ void free_netdev(struct net_device *dev) | |||
5639 | release_net(dev_net(dev)); | 5637 | release_net(dev_net(dev)); |
5640 | 5638 | ||
5641 | kfree(dev->_tx); | 5639 | kfree(dev->_tx); |
5640 | #ifdef CONFIG_RPS | ||
5641 | kfree(dev->_rx); | ||
5642 | #endif | ||
5642 | 5643 | ||
5643 | kfree(rcu_dereference_raw(dev->ingress_queue)); | 5644 | kfree(rcu_dereference_raw(dev->ingress_queue)); |
5644 | 5645 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index a5ff5a89f376..3ba526b56fe3 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -706,7 +706,6 @@ static struct attribute *rx_queue_default_attrs[] = { | |||
706 | static void rx_queue_release(struct kobject *kobj) | 706 | static void rx_queue_release(struct kobject *kobj) |
707 | { | 707 | { |
708 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | 708 | struct netdev_rx_queue *queue = to_rx_queue(kobj); |
709 | struct netdev_rx_queue *first = queue->first; | ||
710 | struct rps_map *map; | 709 | struct rps_map *map; |
711 | struct rps_dev_flow_table *flow_table; | 710 | struct rps_dev_flow_table *flow_table; |
712 | 711 | ||
@@ -719,8 +718,7 @@ static void rx_queue_release(struct kobject *kobj) | |||
719 | if (flow_table) | 718 | if (flow_table) |
720 | call_rcu(&flow_table->rcu, rps_dev_flow_table_release); | 719 | call_rcu(&flow_table->rcu, rps_dev_flow_table_release); |
721 | 720 | ||
722 | if (atomic_dec_and_test(&first->count)) | 721 | dev_put(queue->dev); |
723 | kfree(first); | ||
724 | } | 722 | } |
725 | 723 | ||
726 | static struct kobj_type rx_queue_ktype = { | 724 | static struct kobj_type rx_queue_ktype = { |
@@ -732,7 +730,6 @@ static struct kobj_type rx_queue_ktype = { | |||
732 | static int rx_queue_add_kobject(struct net_device *net, int index) | 730 | static int rx_queue_add_kobject(struct net_device *net, int index) |
733 | { | 731 | { |
734 | struct netdev_rx_queue *queue = net->_rx + index; | 732 | struct netdev_rx_queue *queue = net->_rx + index; |
735 | struct netdev_rx_queue *first = queue->first; | ||
736 | struct kobject *kobj = &queue->kobj; | 733 | struct kobject *kobj = &queue->kobj; |
737 | int error = 0; | 734 | int error = 0; |
738 | 735 | ||
@@ -745,7 +742,7 @@ static int rx_queue_add_kobject(struct net_device *net, int index) | |||
745 | } | 742 | } |
746 | 743 | ||
747 | kobject_uevent(kobj, KOBJ_ADD); | 744 | kobject_uevent(kobj, KOBJ_ADD); |
748 | atomic_inc(&first->count); | 745 | dev_hold(queue->dev); |
749 | 746 | ||
750 | return error; | 747 | return error; |
751 | } | 748 | } |