aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2010-11-09 05:47:38 -0500
committerDavid S. Miller <davem@davemloft.net>2010-11-15 13:57:28 -0500
commitfe8222406c8277a21172479d3a8283d31c209028 (patch)
tree89876457391fba73e3c2c9fdbf9c28a980ad4ffc
parented9af2e839c06c18f721da2c768fbb444c4a10e5 (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>
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--net/core/dev.c19
-rw-r--r--net/core/net-sysfs.c7
3 files changed, 13 insertions, 16 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6e4cfbc53d4c..fccb11f879e5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -592,8 +592,7 @@ struct netdev_rx_queue {
592 struct rps_map __rcu *rps_map; 592 struct rps_map __rcu *rps_map;
593 struct rps_dev_flow_table __rcu *rps_flow_table; 593 struct rps_dev_flow_table __rcu *rps_flow_table;
594 struct kobject kobj; 594 struct kobject kobj;
595 struct netdev_rx_queue *first; 595 struct net_device *dev;
596 atomic_t count;
597} ____cacheline_aligned_in_smp; 596} ____cacheline_aligned_in_smp;
598#endif /* CONFIG_RPS */ 597#endif /* CONFIG_RPS */
599 598
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,
5618free_pcpu: 5612free_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
5621free_p: 5619free_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[] = {
706static void rx_queue_release(struct kobject *kobj) 706static 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
726static struct kobj_type rx_queue_ktype = { 724static struct kobj_type rx_queue_ktype = {
@@ -732,7 +730,6 @@ static struct kobj_type rx_queue_ktype = {
732static int rx_queue_add_kobject(struct net_device *net, int index) 730static 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}