diff options
Diffstat (limited to 'include/net/gro_cells.h')
-rw-r--r-- | include/net/gro_cells.h | 29 |
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 @@ | |||
8 | struct gro_cell { | 8 | struct 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 | ||
13 | struct gro_cells { | 13 | struct gro_cells { |
14 | unsigned int gro_cells_mask; | 14 | struct gro_cell __percpu *cells; |
15 | struct gro_cell *cells; | ||
16 | }; | 15 | }; |
17 | 16 | ||
18 | static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) | 17 | static 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 | ||
92 | static inline void gro_cells_destroy(struct gro_cells *gcells) | 87 | static 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 | ||