aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/gro_cells.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/gro_cells.h')
-rw-r--r--include/net/gro_cells.h29
1 files changed, 12 insertions, 17 deletions
diff --git a/include/net/gro_cells.h b/include/net/gro_cells.h
index 734d9b5f577a..0f712c0bc0bf 100644
--- a/include/net/gro_cells.h
+++ b/include/net/gro_cells.h
@@ -8,25 +8,23 @@
8struct gro_cell { 8struct gro_cell {
9 struct sk_buff_head napi_skbs; 9 struct sk_buff_head napi_skbs;
10 struct napi_struct napi; 10 struct napi_struct napi;
11} ____cacheline_aligned_in_smp; 11};
12 12
13struct gro_cells { 13struct gro_cells {
14 unsigned int gro_cells_mask; 14 struct gro_cell __percpu *cells;
15 struct gro_cell *cells;
16}; 15};
17 16
18static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) 17static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
19{ 18{
20 struct gro_cell *cell = gcells->cells; 19 struct gro_cell *cell;
21 struct net_device *dev = skb->dev; 20 struct net_device *dev = skb->dev;
22 21
23 if (!cell || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) { 22 if (!gcells->cells || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) {
24 netif_rx(skb); 23 netif_rx(skb);
25 return; 24 return;
26 } 25 }
27 26
28 if (skb_rx_queue_recorded(skb)) 27 cell = this_cpu_ptr(gcells->cells);
29 cell += skb_get_rx_queue(skb) & gcells->gro_cells_mask;
30 28
31 if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) { 29 if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) {
32 atomic_long_inc(&dev->rx_dropped); 30 atomic_long_inc(&dev->rx_dropped);
@@ -72,15 +70,12 @@ static inline int gro_cells_init(struct gro_cells *gcells, struct net_device *de
72{ 70{
73 int i; 71 int i;
74 72
75 gcells->gro_cells_mask = roundup_pow_of_two(netif_get_num_default_rss_queues()) - 1; 73 gcells->cells = alloc_percpu(struct gro_cell);
76 gcells->cells = kcalloc(gcells->gro_cells_mask + 1,
77 sizeof(struct gro_cell),
78 GFP_KERNEL);
79 if (!gcells->cells) 74 if (!gcells->cells)
80 return -ENOMEM; 75 return -ENOMEM;
81 76
82 for (i = 0; i <= gcells->gro_cells_mask; i++) { 77 for_each_possible_cpu(i) {
83 struct gro_cell *cell = gcells->cells + i; 78 struct gro_cell *cell = per_cpu_ptr(gcells->cells, i);
84 79
85 skb_queue_head_init(&cell->napi_skbs); 80 skb_queue_head_init(&cell->napi_skbs);
86 netif_napi_add(dev, &cell->napi, gro_cell_poll, 64); 81 netif_napi_add(dev, &cell->napi, gro_cell_poll, 64);
@@ -91,16 +86,16 @@ static inline int gro_cells_init(struct gro_cells *gcells, struct net_device *de
91 86
92static inline void gro_cells_destroy(struct gro_cells *gcells) 87static inline void gro_cells_destroy(struct gro_cells *gcells)
93{ 88{
94 struct gro_cell *cell = gcells->cells;
95 int i; 89 int i;
96 90
97 if (!cell) 91 if (!gcells->cells)
98 return; 92 return;
99 for (i = 0; i <= gcells->gro_cells_mask; i++,cell++) { 93 for_each_possible_cpu(i) {
94 struct gro_cell *cell = per_cpu_ptr(gcells->cells, i);
100 netif_napi_del(&cell->napi); 95 netif_napi_del(&cell->napi);
101 skb_queue_purge(&cell->napi_skbs); 96 skb_queue_purge(&cell->napi_skbs);
102 } 97 }
103 kfree(gcells->cells); 98 free_percpu(gcells->cells);
104 gcells->cells = NULL; 99 gcells->cells = NULL;
105} 100}
106 101