43
43
44
44
#include "mlx4_en.h"
45
45
46
+ static int mlx4_alloc_pages (struct mlx4_en_priv * priv ,
47
+ struct mlx4_en_rx_alloc * page_alloc ,
48
+ const struct mlx4_en_frag_info * frag_info ,
49
+ gfp_t _gfp )
50
+ {
51
+ int order ;
52
+ struct page * page ;
53
+ dma_addr_t dma ;
54
+
55
+ for (order = MLX4_EN_ALLOC_PREFER_ORDER ; ;) {
56
+ gfp_t gfp = _gfp ;
57
+
58
+ if (order )
59
+ gfp |= __GFP_COMP | __GFP_NOWARN ;
60
+ page = alloc_pages (gfp , order );
61
+ if (likely (page ))
62
+ break ;
63
+ if (-- order < 0 ||
64
+ ((PAGE_SIZE << order ) < frag_info -> frag_size ))
65
+ return - ENOMEM ;
66
+ }
67
+ dma = dma_map_page (priv -> ddev , page , 0 , PAGE_SIZE << order ,
68
+ PCI_DMA_FROMDEVICE );
69
+ if (dma_mapping_error (priv -> ddev , dma )) {
70
+ put_page (page );
71
+ return - ENOMEM ;
72
+ }
73
+ page_alloc -> size = PAGE_SIZE << order ;
74
+ page_alloc -> page = page ;
75
+ page_alloc -> dma = dma ;
76
+ page_alloc -> offset = frag_info -> frag_align ;
77
+ /* Not doing get_page() for each frag is a big win
78
+ * on asymetric workloads.
79
+ */
80
+ atomic_set (& page -> _count , page_alloc -> size / frag_info -> frag_stride );
81
+ return 0 ;
82
+ }
83
+
46
84
static int mlx4_en_alloc_frags (struct mlx4_en_priv * priv ,
47
85
struct mlx4_en_rx_desc * rx_desc ,
48
86
struct mlx4_en_rx_alloc * frags ,
49
- struct mlx4_en_rx_alloc * ring_alloc )
87
+ struct mlx4_en_rx_alloc * ring_alloc ,
88
+ gfp_t gfp )
50
89
{
51
90
struct mlx4_en_rx_alloc page_alloc [MLX4_EN_MAX_RX_FRAGS ];
52
- struct mlx4_en_frag_info * frag_info ;
91
+ const struct mlx4_en_frag_info * frag_info ;
53
92
struct page * page ;
54
93
dma_addr_t dma ;
55
94
int i ;
56
95
57
96
for (i = 0 ; i < priv -> num_frags ; i ++ ) {
58
97
frag_info = & priv -> frag_info [i ];
59
- if (ring_alloc [i ].offset == frag_info -> last_offset ) {
60
- page = alloc_pages (GFP_ATOMIC | __GFP_COMP ,
61
- MLX4_EN_ALLOC_ORDER );
62
- if (!page )
63
- goto out ;
64
- dma = dma_map_page (priv -> ddev , page , 0 ,
65
- MLX4_EN_ALLOC_SIZE , PCI_DMA_FROMDEVICE );
66
- if (dma_mapping_error (priv -> ddev , dma )) {
67
- put_page (page );
68
- goto out ;
69
- }
70
- page_alloc [i ].page = page ;
71
- page_alloc [i ].dma = dma ;
72
- page_alloc [i ].offset = frag_info -> frag_align ;
73
- } else {
74
- page_alloc [i ].page = ring_alloc [i ].page ;
75
- get_page (ring_alloc [i ].page );
76
- page_alloc [i ].dma = ring_alloc [i ].dma ;
77
- page_alloc [i ].offset = ring_alloc [i ].offset +
78
- frag_info -> frag_stride ;
79
- }
98
+ page_alloc [i ] = ring_alloc [i ];
99
+ page_alloc [i ].offset += frag_info -> frag_stride ;
100
+ if (page_alloc [i ].offset + frag_info -> frag_stride <= ring_alloc [i ].size )
101
+ continue ;
102
+ if (mlx4_alloc_pages (priv , & page_alloc [i ], frag_info , gfp ))
103
+ goto out ;
80
104
}
81
105
82
106
for (i = 0 ; i < priv -> num_frags ; i ++ ) {
@@ -88,14 +112,16 @@ static int mlx4_en_alloc_frags(struct mlx4_en_priv *priv,
88
112
89
113
return 0 ;
90
114
91
-
92
115
out :
93
116
while (i -- ) {
94
117
frag_info = & priv -> frag_info [i ];
95
- if (ring_alloc [i ].offset == frag_info -> last_offset )
118
+ if (page_alloc [i ].page != ring_alloc [ i ]. page ) {
96
119
dma_unmap_page (priv -> ddev , page_alloc [i ].dma ,
97
- MLX4_EN_ALLOC_SIZE , PCI_DMA_FROMDEVICE );
98
- put_page (page_alloc [i ].page );
120
+ page_alloc [i ].size , PCI_DMA_FROMDEVICE );
121
+ page = page_alloc [i ].page ;
122
+ atomic_set (& page -> _count , 1 );
123
+ put_page (page );
124
+ }
99
125
}
100
126
return - ENOMEM ;
101
127
}
@@ -104,48 +130,41 @@ static void mlx4_en_free_frag(struct mlx4_en_priv *priv,
104
130
struct mlx4_en_rx_alloc * frags ,
105
131
int i )
106
132
{
107
- struct mlx4_en_frag_info * frag_info = & priv -> frag_info [i ];
133
+ const struct mlx4_en_frag_info * frag_info = & priv -> frag_info [i ];
108
134
109
- if (frags [i ].offset == frag_info -> last_offset ) {
110
- dma_unmap_page (priv -> ddev , frags [i ].dma , MLX4_EN_ALLOC_SIZE ,
135
+ if (frags [i ].offset + frag_info -> frag_stride > frags [ i ]. size )
136
+ dma_unmap_page (priv -> ddev , frags [i ].dma , frags [ i ]. size ,
111
137
PCI_DMA_FROMDEVICE );
112
- }
138
+
113
139
if (frags [i ].page )
114
140
put_page (frags [i ].page );
115
141
}
116
142
117
143
static int mlx4_en_init_allocator (struct mlx4_en_priv * priv ,
118
144
struct mlx4_en_rx_ring * ring )
119
145
{
120
- struct mlx4_en_rx_alloc * page_alloc ;
121
146
int i ;
147
+ struct mlx4_en_rx_alloc * page_alloc ;
122
148
123
149
for (i = 0 ; i < priv -> num_frags ; i ++ ) {
124
- page_alloc = & ring -> page_alloc [i ];
125
- page_alloc -> page = alloc_pages (GFP_ATOMIC | __GFP_COMP ,
126
- MLX4_EN_ALLOC_ORDER );
127
- if (!page_alloc -> page )
128
- goto out ;
150
+ const struct mlx4_en_frag_info * frag_info = & priv -> frag_info [i ];
129
151
130
- page_alloc -> dma = dma_map_page (priv -> ddev , page_alloc -> page , 0 ,
131
- MLX4_EN_ALLOC_SIZE , PCI_DMA_FROMDEVICE );
132
- if (dma_mapping_error (priv -> ddev , page_alloc -> dma )) {
133
- put_page (page_alloc -> page );
134
- page_alloc -> page = NULL ;
152
+ if (mlx4_alloc_pages (priv , & ring -> page_alloc [i ],
153
+ frag_info , GFP_KERNEL ))
135
154
goto out ;
136
- }
137
- page_alloc -> offset = priv -> frag_info [i ].frag_align ;
138
- en_dbg (DRV , priv , "Initialized allocator:%d with page:%p\n" ,
139
- i , page_alloc -> page );
140
155
}
141
156
return 0 ;
142
157
143
158
out :
144
159
while (i -- ) {
160
+ struct page * page ;
161
+
145
162
page_alloc = & ring -> page_alloc [i ];
146
163
dma_unmap_page (priv -> ddev , page_alloc -> dma ,
147
- MLX4_EN_ALLOC_SIZE , PCI_DMA_FROMDEVICE );
148
- put_page (page_alloc -> page );
164
+ page_alloc -> size , PCI_DMA_FROMDEVICE );
165
+ page = page_alloc -> page ;
166
+ atomic_set (& page -> _count , 1 );
167
+ put_page (page );
149
168
page_alloc -> page = NULL ;
150
169
}
151
170
return - ENOMEM ;
@@ -158,13 +177,18 @@ static void mlx4_en_destroy_allocator(struct mlx4_en_priv *priv,
158
177
int i ;
159
178
160
179
for (i = 0 ; i < priv -> num_frags ; i ++ ) {
180
+ const struct mlx4_en_frag_info * frag_info = & priv -> frag_info [i ];
181
+
161
182
page_alloc = & ring -> page_alloc [i ];
162
183
en_dbg (DRV , priv , "Freeing allocator:%d count:%d\n" ,
163
184
i , page_count (page_alloc -> page ));
164
185
165
186
dma_unmap_page (priv -> ddev , page_alloc -> dma ,
166
- MLX4_EN_ALLOC_SIZE , PCI_DMA_FROMDEVICE );
167
- put_page (page_alloc -> page );
187
+ page_alloc -> size , PCI_DMA_FROMDEVICE );
188
+ while (page_alloc -> offset + frag_info -> frag_stride < page_alloc -> size ) {
189
+ put_page (page_alloc -> page );
190
+ page_alloc -> offset += frag_info -> frag_stride ;
191
+ }
168
192
page_alloc -> page = NULL ;
169
193
}
170
194
}
@@ -195,13 +219,14 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
195
219
}
196
220
197
221
static int mlx4_en_prepare_rx_desc (struct mlx4_en_priv * priv ,
198
- struct mlx4_en_rx_ring * ring , int index )
222
+ struct mlx4_en_rx_ring * ring , int index ,
223
+ gfp_t gfp )
199
224
{
200
225
struct mlx4_en_rx_desc * rx_desc = ring -> buf + (index * ring -> stride );
201
226
struct mlx4_en_rx_alloc * frags = ring -> rx_info +
202
227
(index << priv -> log_rx_info );
203
228
204
- return mlx4_en_alloc_frags (priv , rx_desc , frags , ring -> page_alloc );
229
+ return mlx4_en_alloc_frags (priv , rx_desc , frags , ring -> page_alloc , gfp );
205
230
}
206
231
207
232
static inline void mlx4_en_update_rx_prod_db (struct mlx4_en_rx_ring * ring )
@@ -235,7 +260,8 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
235
260
ring = & priv -> rx_ring [ring_ind ];
236
261
237
262
if (mlx4_en_prepare_rx_desc (priv , ring ,
238
- ring -> actual_size )) {
263
+ ring -> actual_size ,
264
+ GFP_KERNEL )) {
239
265
if (ring -> actual_size < MLX4_EN_MIN_RX_SIZE ) {
240
266
en_err (priv , "Failed to allocate "
241
267
"enough rx buffers\n" );
@@ -450,11 +476,11 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
450
476
DMA_FROM_DEVICE );
451
477
452
478
/* Save page reference in skb */
453
- get_page (frags [nr ].page );
454
479
__skb_frag_set_page (& skb_frags_rx [nr ], frags [nr ].page );
455
480
skb_frag_size_set (& skb_frags_rx [nr ], frag_info -> frag_size );
456
481
skb_frags_rx [nr ].page_offset = frags [nr ].offset ;
457
482
skb -> truesize += frag_info -> frag_stride ;
483
+ frags [nr ].page = NULL ;
458
484
}
459
485
/* Adjust size of last fragment to match actual length */
460
486
if (nr > 0 )
@@ -547,7 +573,7 @@ static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
547
573
int index = ring -> prod & ring -> size_mask ;
548
574
549
575
while ((u32 ) (ring -> prod - ring -> cons ) < ring -> actual_size ) {
550
- if (mlx4_en_prepare_rx_desc (priv , ring , index ))
576
+ if (mlx4_en_prepare_rx_desc (priv , ring , index , GFP_ATOMIC ))
551
577
break ;
552
578
ring -> prod ++ ;
553
579
index = ring -> prod & ring -> size_mask ;
@@ -805,21 +831,7 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
805
831
return done ;
806
832
}
807
833
808
-
809
- /* Calculate the last offset position that accommodates a full fragment
810
- * (assuming fagment size = stride-align) */
811
- static int mlx4_en_last_alloc_offset (struct mlx4_en_priv * priv , u16 stride , u16 align )
812
- {
813
- u16 res = MLX4_EN_ALLOC_SIZE % stride ;
814
- u16 offset = MLX4_EN_ALLOC_SIZE - stride - res + align ;
815
-
816
- en_dbg (DRV , priv , "Calculated last offset for stride:%d align:%d "
817
- "res:%d offset:%d\n" , stride , align , res , offset );
818
- return offset ;
819
- }
820
-
821
-
822
- static int frag_sizes [] = {
834
+ static const int frag_sizes [] = {
823
835
FRAG_SZ0 ,
824
836
FRAG_SZ1 ,
825
837
FRAG_SZ2 ,
@@ -847,9 +859,6 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
847
859
priv -> frag_info [i ].frag_stride =
848
860
ALIGN (frag_sizes [i ], SMP_CACHE_BYTES );
849
861
}
850
- priv -> frag_info [i ].last_offset = mlx4_en_last_alloc_offset (
851
- priv , priv -> frag_info [i ].frag_stride ,
852
- priv -> frag_info [i ].frag_align );
853
862
buf_size += priv -> frag_info [i ].frag_size ;
854
863
i ++ ;
855
864
}
@@ -861,13 +870,13 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
861
870
en_dbg (DRV , priv , "Rx buffer scatter-list (effective-mtu:%d "
862
871
"num_frags:%d):\n" , eff_mtu , priv -> num_frags );
863
872
for (i = 0 ; i < priv -> num_frags ; i ++ ) {
864
- en_dbg ( DRV , priv , " frag:%d - size:%d prefix:%d align:%d "
865
- "stride :%d last_offset :%d\n", i ,
866
- priv -> frag_info [ i ]. frag_size ,
867
- priv -> frag_info [i ].frag_prefix_size ,
868
- priv -> frag_info [i ].frag_align ,
869
- priv -> frag_info [i ].frag_stride ,
870
- priv -> frag_info [i ].last_offset );
873
+ en_err ( priv ,
874
+ " frag :%d - size :%d prefix:%d align:%d stride:%d \n" ,
875
+ i ,
876
+ priv -> frag_info [i ].frag_size ,
877
+ priv -> frag_info [i ].frag_prefix_size ,
878
+ priv -> frag_info [i ].frag_align ,
879
+ priv -> frag_info [i ].frag_stride );
871
880
}
872
881
}
873
882
0 commit comments