aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChangli Gao <xiaosuo@gmail.com>2010-03-30 16:16:22 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-01 21:41:40 -0400
commit152102c7f2bf191690f1069bae292ea3925adf14 (patch)
tree093ce1204a81acd76623a567b821661c504bc575 /net
parent630b943c182d1aed69f244405131902fbcba7ec6 (diff)
rps: keep the old behavior on SMP without rps
keep the old behavior on SMP without rps RPS introduces a lock operation to per cpu variable input_pkt_queue on SMP whenever rps is enabled or not. On SMP without RPS, this lock isn't needed at all. Signed-off-by: Changli Gao <xiaosuo@gmail.com> ---- net/core/dev.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 887aa84fcd46..427cd53c118d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -206,6 +206,20 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
206 return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)]; 206 return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)];
207} 207}
208 208
209static inline void rps_lock(struct softnet_data *queue)
210{
211#ifdef CONFIG_RPS
212 spin_lock(&queue->input_pkt_queue.lock);
213#endif
214}
215
216static inline void rps_unlock(struct softnet_data *queue)
217{
218#ifdef CONFIG_RPS
219 spin_unlock(&queue->input_pkt_queue.lock);
220#endif
221}
222
209/* Device list insertion */ 223/* Device list insertion */
210static int list_netdevice(struct net_device *dev) 224static int list_netdevice(struct net_device *dev)
211{ 225{
@@ -2313,13 +2327,13 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu)
2313 local_irq_save(flags); 2327 local_irq_save(flags);
2314 __get_cpu_var(netdev_rx_stat).total++; 2328 __get_cpu_var(netdev_rx_stat).total++;
2315 2329
2316 spin_lock(&queue->input_pkt_queue.lock); 2330 rps_lock(queue);
2317 if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { 2331 if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
2318 if (queue->input_pkt_queue.qlen) { 2332 if (queue->input_pkt_queue.qlen) {
2319enqueue: 2333enqueue:
2320 __skb_queue_tail(&queue->input_pkt_queue, skb); 2334 __skb_queue_tail(&queue->input_pkt_queue, skb);
2321 spin_unlock_irqrestore(&queue->input_pkt_queue.lock, 2335 rps_unlock(queue);
2322 flags); 2336 local_irq_restore(flags);
2323 return NET_RX_SUCCESS; 2337 return NET_RX_SUCCESS;
2324 } 2338 }
2325 2339
@@ -2341,7 +2355,7 @@ enqueue:
2341 goto enqueue; 2355 goto enqueue;
2342 } 2356 }
2343 2357
2344 spin_unlock(&queue->input_pkt_queue.lock); 2358 rps_unlock(queue);
2345 2359
2346 __get_cpu_var(netdev_rx_stat).dropped++; 2360 __get_cpu_var(netdev_rx_stat).dropped++;
2347 local_irq_restore(flags); 2361 local_irq_restore(flags);
@@ -2766,19 +2780,19 @@ int netif_receive_skb(struct sk_buff *skb)
2766EXPORT_SYMBOL(netif_receive_skb); 2780EXPORT_SYMBOL(netif_receive_skb);
2767 2781
2768/* Network device is going away, flush any packets still pending */ 2782/* Network device is going away, flush any packets still pending */
2769static void flush_backlog(struct net_device *dev, int cpu) 2783static void flush_backlog(void *arg)
2770{ 2784{
2771 struct softnet_data *queue = &per_cpu(softnet_data, cpu); 2785 struct net_device *dev = arg;
2786 struct softnet_data *queue = &__get_cpu_var(softnet_data);
2772 struct sk_buff *skb, *tmp; 2787 struct sk_buff *skb, *tmp;
2773 unsigned long flags;
2774 2788
2775 spin_lock_irqsave(&queue->input_pkt_queue.lock, flags); 2789 rps_lock(queue);
2776 skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) 2790 skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp)
2777 if (skb->dev == dev) { 2791 if (skb->dev == dev) {
2778 __skb_unlink(skb, &queue->input_pkt_queue); 2792 __skb_unlink(skb, &queue->input_pkt_queue);
2779 kfree_skb(skb); 2793 kfree_skb(skb);
2780 } 2794 }
2781 spin_unlock_irqrestore(&queue->input_pkt_queue.lock, flags); 2795 rps_unlock(queue);
2782} 2796}
2783 2797
2784static int napi_gro_complete(struct sk_buff *skb) 2798static int napi_gro_complete(struct sk_buff *skb)
@@ -3091,14 +3105,16 @@ static int process_backlog(struct napi_struct *napi, int quota)
3091 do { 3105 do {
3092 struct sk_buff *skb; 3106 struct sk_buff *skb;
3093 3107
3094 spin_lock_irq(&queue->input_pkt_queue.lock); 3108 local_irq_disable();
3109 rps_lock(queue);
3095 skb = __skb_dequeue(&queue->input_pkt_queue); 3110 skb = __skb_dequeue(&queue->input_pkt_queue);
3096 if (!skb) { 3111 if (!skb) {
3097 __napi_complete(napi); 3112 __napi_complete(napi);
3098 spin_unlock_irq(&queue->input_pkt_queue.lock); 3113 spin_unlock_irq(&queue->input_pkt_queue.lock);
3099 break; 3114 break;
3100 } 3115 }
3101 spin_unlock_irq(&queue->input_pkt_queue.lock); 3116 rps_unlock(queue);
3117 local_irq_enable();
3102 3118
3103 __netif_receive_skb(skb); 3119 __netif_receive_skb(skb);
3104 } while (++work < quota && jiffies == start_time); 3120 } while (++work < quota && jiffies == start_time);
@@ -5548,7 +5564,6 @@ void netdev_run_todo(void)
5548 while (!list_empty(&list)) { 5564 while (!list_empty(&list)) {
5549 struct net_device *dev 5565 struct net_device *dev
5550 = list_first_entry(&list, struct net_device, todo_list); 5566 = list_first_entry(&list, struct net_device, todo_list);
5551 int i;
5552 list_del(&dev->todo_list); 5567 list_del(&dev->todo_list);
5553 5568
5554 if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { 5569 if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) {
@@ -5560,8 +5575,7 @@ void netdev_run_todo(void)
5560 5575
5561 dev->reg_state = NETREG_UNREGISTERED; 5576 dev->reg_state = NETREG_UNREGISTERED;
5562 5577
5563 for_each_online_cpu(i) 5578 on_each_cpu(flush_backlog, dev, 1);
5564 flush_backlog(dev, i);
5565 5579
5566 netdev_wait_allrefs(dev); 5580 netdev_wait_allrefs(dev);
5567 5581