@@ -119,6 +119,163 @@ static void mlx5_fw_tracer_ownership_release(struct mlx5_fw_tracer *tracer)
119
119
tracer -> owner = false;
120
120
}
121
121
122
+ static int mlx5_fw_tracer_create_log_buf (struct mlx5_fw_tracer * tracer )
123
+ {
124
+ struct mlx5_core_dev * dev = tracer -> dev ;
125
+ struct device * ddev = & dev -> pdev -> dev ;
126
+ dma_addr_t dma ;
127
+ void * buff ;
128
+ gfp_t gfp ;
129
+ int err ;
130
+
131
+ tracer -> buff .size = TRACE_BUFFER_SIZE_BYTE ;
132
+
133
+ gfp = GFP_KERNEL | __GFP_ZERO ;
134
+ buff = (void * )__get_free_pages (gfp ,
135
+ get_order (tracer -> buff .size ));
136
+ if (!buff ) {
137
+ err = - ENOMEM ;
138
+ mlx5_core_warn (dev , "FWTracer: Failed to allocate pages, %d\n" , err );
139
+ return err ;
140
+ }
141
+ tracer -> buff .log_buf = buff ;
142
+
143
+ dma = dma_map_single (ddev , buff , tracer -> buff .size , DMA_FROM_DEVICE );
144
+ if (dma_mapping_error (ddev , dma )) {
145
+ mlx5_core_warn (dev , "FWTracer: Unable to map DMA: %d\n" ,
146
+ dma_mapping_error (ddev , dma ));
147
+ err = - ENOMEM ;
148
+ goto free_pages ;
149
+ }
150
+ tracer -> buff .dma = dma ;
151
+
152
+ return 0 ;
153
+
154
+ free_pages :
155
+ free_pages ((unsigned long )tracer -> buff .log_buf , get_order (tracer -> buff .size ));
156
+
157
+ return err ;
158
+ }
159
+
160
+ static void mlx5_fw_tracer_destroy_log_buf (struct mlx5_fw_tracer * tracer )
161
+ {
162
+ struct mlx5_core_dev * dev = tracer -> dev ;
163
+ struct device * ddev = & dev -> pdev -> dev ;
164
+
165
+ if (!tracer -> buff .log_buf )
166
+ return ;
167
+
168
+ dma_unmap_single (ddev , tracer -> buff .dma , tracer -> buff .size , DMA_FROM_DEVICE );
169
+ free_pages ((unsigned long )tracer -> buff .log_buf , get_order (tracer -> buff .size ));
170
+ }
171
+
172
+ static void mlx5_fw_tracer_free_strings_db (struct mlx5_fw_tracer * tracer )
173
+ {
174
+ u32 num_string_db = tracer -> str_db .num_string_db ;
175
+ int i ;
176
+
177
+ for (i = 0 ; i < num_string_db ; i ++ ) {
178
+ kfree (tracer -> str_db .buffer [i ]);
179
+ tracer -> str_db .buffer [i ] = NULL ;
180
+ }
181
+ }
182
+
183
+ static int mlx5_fw_tracer_allocate_strings_db (struct mlx5_fw_tracer * tracer )
184
+ {
185
+ u32 * string_db_size_out = tracer -> str_db .size_out ;
186
+ u32 num_string_db = tracer -> str_db .num_string_db ;
187
+ int i ;
188
+
189
+ for (i = 0 ; i < num_string_db ; i ++ ) {
190
+ tracer -> str_db .buffer [i ] = kzalloc (string_db_size_out [i ], GFP_KERNEL );
191
+ if (!tracer -> str_db .buffer [i ])
192
+ goto free_strings_db ;
193
+ }
194
+
195
+ return 0 ;
196
+
197
+ free_strings_db :
198
+ mlx5_fw_tracer_free_strings_db (tracer );
199
+ return - ENOMEM ;
200
+ }
201
+
202
+ static void mlx5_tracer_read_strings_db (struct work_struct * work )
203
+ {
204
+ struct mlx5_fw_tracer * tracer = container_of (work , struct mlx5_fw_tracer ,
205
+ read_fw_strings_work );
206
+ u32 num_of_reads , num_string_db = tracer -> str_db .num_string_db ;
207
+ struct mlx5_core_dev * dev = tracer -> dev ;
208
+ u32 in [MLX5_ST_SZ_DW (mtrc_cap )] = {0 };
209
+ u32 leftovers , offset ;
210
+ int err = 0 , i , j ;
211
+ u32 * out , outlen ;
212
+ void * out_value ;
213
+
214
+ outlen = MLX5_ST_SZ_BYTES (mtrc_stdb ) + STRINGS_DB_READ_SIZE_BYTES ;
215
+ out = kzalloc (outlen , GFP_KERNEL );
216
+ if (!out ) {
217
+ err = - ENOMEM ;
218
+ goto out ;
219
+ }
220
+
221
+ for (i = 0 ; i < num_string_db ; i ++ ) {
222
+ offset = 0 ;
223
+ MLX5_SET (mtrc_stdb , in , string_db_index , i );
224
+ num_of_reads = tracer -> str_db .size_out [i ] /
225
+ STRINGS_DB_READ_SIZE_BYTES ;
226
+ leftovers = (tracer -> str_db .size_out [i ] %
227
+ STRINGS_DB_READ_SIZE_BYTES ) /
228
+ STRINGS_DB_LEFTOVER_SIZE_BYTES ;
229
+
230
+ MLX5_SET (mtrc_stdb , in , read_size , STRINGS_DB_READ_SIZE_BYTES );
231
+ for (j = 0 ; j < num_of_reads ; j ++ ) {
232
+ MLX5_SET (mtrc_stdb , in , start_offset , offset );
233
+
234
+ err = mlx5_core_access_reg (dev , in , sizeof (in ), out ,
235
+ outlen , MLX5_REG_MTRC_STDB ,
236
+ 0 , 1 );
237
+ if (err ) {
238
+ mlx5_core_dbg (dev , "FWTracer: Failed to read strings DB %d\n" ,
239
+ err );
240
+ goto out_free ;
241
+ }
242
+
243
+ out_value = MLX5_ADDR_OF (mtrc_stdb , out , string_db_data );
244
+ memcpy (tracer -> str_db .buffer [i ] + offset , out_value ,
245
+ STRINGS_DB_READ_SIZE_BYTES );
246
+ offset += STRINGS_DB_READ_SIZE_BYTES ;
247
+ }
248
+
249
+ /* Strings database is aligned to 64, need to read leftovers*/
250
+ MLX5_SET (mtrc_stdb , in , read_size ,
251
+ STRINGS_DB_LEFTOVER_SIZE_BYTES );
252
+ for (j = 0 ; j < leftovers ; j ++ ) {
253
+ MLX5_SET (mtrc_stdb , in , start_offset , offset );
254
+
255
+ err = mlx5_core_access_reg (dev , in , sizeof (in ), out ,
256
+ outlen , MLX5_REG_MTRC_STDB ,
257
+ 0 , 1 );
258
+ if (err ) {
259
+ mlx5_core_dbg (dev , "FWTracer: Failed to read strings DB %d\n" ,
260
+ err );
261
+ goto out_free ;
262
+ }
263
+
264
+ out_value = MLX5_ADDR_OF (mtrc_stdb , out , string_db_data );
265
+ memcpy (tracer -> str_db .buffer [i ] + offset , out_value ,
266
+ STRINGS_DB_LEFTOVER_SIZE_BYTES );
267
+ offset += STRINGS_DB_LEFTOVER_SIZE_BYTES ;
268
+ }
269
+ }
270
+
271
+ tracer -> str_db .loaded = true;
272
+
273
+ out_free :
274
+ kfree (out );
275
+ out :
276
+ return ;
277
+ }
278
+
122
279
static void mlx5_fw_tracer_ownership_change (struct work_struct * work )
123
280
{
124
281
struct mlx5_fw_tracer * tracer = container_of (work , struct mlx5_fw_tracer ,
@@ -161,17 +318,30 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
161
318
tracer -> dev = dev ;
162
319
163
320
INIT_WORK (& tracer -> ownership_change_work , mlx5_fw_tracer_ownership_change );
321
+ INIT_WORK (& tracer -> read_fw_strings_work , mlx5_tracer_read_strings_db );
164
322
165
323
err = mlx5_query_mtrc_caps (tracer );
166
324
if (err ) {
167
325
mlx5_core_dbg (dev , "FWTracer: Failed to query capabilities %d\n" , err );
168
326
goto destroy_workqueue ;
169
327
}
170
328
171
- mlx5_fw_tracer_ownership_change (& tracer -> ownership_change_work );
329
+ err = mlx5_fw_tracer_create_log_buf (tracer );
330
+ if (err ) {
331
+ mlx5_core_warn (dev , "FWTracer: Create log buffer failed %d\n" , err );
332
+ goto destroy_workqueue ;
333
+ }
334
+
335
+ err = mlx5_fw_tracer_allocate_strings_db (tracer );
336
+ if (err ) {
337
+ mlx5_core_warn (dev , "FWTracer: Allocate strings database failed %d\n" , err );
338
+ goto free_log_buf ;
339
+ }
172
340
173
341
return tracer ;
174
342
343
+ free_log_buf :
344
+ mlx5_fw_tracer_destroy_log_buf (tracer );
175
345
destroy_workqueue :
176
346
tracer -> dev = NULL ;
177
347
destroy_workqueue (tracer -> work_queue );
@@ -180,17 +350,50 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
180
350
return ERR_PTR (err );
181
351
}
182
352
183
- void mlx5_fw_tracer_destroy (struct mlx5_fw_tracer * tracer )
353
+ int mlx5_fw_tracer_init (struct mlx5_fw_tracer * tracer )
184
354
{
185
- if (!tracer )
355
+ struct mlx5_core_dev * dev ;
356
+ int err ;
357
+
358
+ if (IS_ERR_OR_NULL (tracer ))
359
+ return 0 ;
360
+
361
+ dev = tracer -> dev ;
362
+
363
+ if (!tracer -> str_db .loaded )
364
+ queue_work (tracer -> work_queue , & tracer -> read_fw_strings_work );
365
+
366
+ err = mlx5_fw_tracer_ownership_acquire (tracer );
367
+ if (err ) {
368
+ mlx5_core_dbg (dev , "FWTracer: Ownership was not granted %d\n" , err );
369
+ return 0 ; /* return 0 since ownership can be acquired on a later FW event */
370
+ }
371
+
372
+ return 0 ;
373
+ }
374
+
375
+ void mlx5_fw_tracer_cleanup (struct mlx5_fw_tracer * tracer )
376
+ {
377
+ if (IS_ERR_OR_NULL (tracer ))
186
378
return ;
187
379
188
380
cancel_work_sync (& tracer -> ownership_change_work );
189
381
190
382
if (tracer -> owner )
191
383
mlx5_fw_tracer_ownership_release (tracer );
384
+ }
192
385
386
+ void mlx5_fw_tracer_destroy (struct mlx5_fw_tracer * tracer )
387
+ {
388
+ if (IS_ERR_OR_NULL (tracer ))
389
+ return ;
390
+
391
+ cancel_work_sync (& tracer -> read_fw_strings_work );
392
+ mlx5_fw_tracer_free_strings_db (tracer );
393
+ mlx5_fw_tracer_destroy_log_buf (tracer );
193
394
flush_workqueue (tracer -> work_queue );
194
395
destroy_workqueue (tracer -> work_queue );
195
396
kfree (tracer );
196
397
}
398
+
399
+ EXPORT_TRACEPOINT_SYMBOL (mlx5_fw );
0 commit comments