Skip to content

Commit 48967ff

Browse files
ferasdSaeed Mahameed
authored andcommitted
net/mlx5: FW tracer, create trace buffer and copy strings database
For each PF do the following: 1- Allocate memory for the tracer strings database and read the strings from the FW to the SW. These strings will be used later for parsing traces. 2- Allocate and dma map tracer buffers. Traces that will be written into the buffer will be parsed as a group of one or more traces, referred to as trace message. The trace message represents a C-like printf string. First trace of a message holds the pointer to the correct string in strings database. The following traces holds the variables of the message. Signed-off-by: Feras Daoud <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent f53aaa3 commit 48967ff

File tree

2 files changed

+224
-3
lines changed

2 files changed

+224
-3
lines changed

drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c

Lines changed: 206 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,163 @@ static void mlx5_fw_tracer_ownership_release(struct mlx5_fw_tracer *tracer)
119119
tracer->owner = false;
120120
}
121121

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+
122279
static void mlx5_fw_tracer_ownership_change(struct work_struct *work)
123280
{
124281
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)
161318
tracer->dev = dev;
162319

163320
INIT_WORK(&tracer->ownership_change_work, mlx5_fw_tracer_ownership_change);
321+
INIT_WORK(&tracer->read_fw_strings_work, mlx5_tracer_read_strings_db);
164322

165323
err = mlx5_query_mtrc_caps(tracer);
166324
if (err) {
167325
mlx5_core_dbg(dev, "FWTracer: Failed to query capabilities %d\n", err);
168326
goto destroy_workqueue;
169327
}
170328

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+
}
172340

173341
return tracer;
174342

343+
free_log_buf:
344+
mlx5_fw_tracer_destroy_log_buf(tracer);
175345
destroy_workqueue:
176346
tracer->dev = NULL;
177347
destroy_workqueue(tracer->work_queue);
@@ -180,17 +350,50 @@ struct mlx5_fw_tracer *mlx5_fw_tracer_create(struct mlx5_core_dev *dev)
180350
return ERR_PTR(err);
181351
}
182352

183-
void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
353+
int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
184354
{
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))
186378
return;
187379

188380
cancel_work_sync(&tracer->ownership_change_work);
189381

190382
if (tracer->owner)
191383
mlx5_fw_tracer_ownership_release(tracer);
384+
}
192385

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);
193394
flush_workqueue(tracer->work_queue);
194395
destroy_workqueue(tracer->work_queue);
195396
kfree(tracer);
196397
}
398+
399+
EXPORT_TRACEPOINT_SYMBOL(mlx5_fw);

drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,19 @@
3737
#include "mlx5_core.h"
3838

3939
#define STRINGS_DB_SECTIONS_NUM 8
40+
#define STRINGS_DB_READ_SIZE_BYTES 256
41+
#define STRINGS_DB_LEFTOVER_SIZE_BYTES 64
42+
#define TRACER_BUFFER_PAGE_NUM 64
43+
#define TRACER_BUFFER_CHUNK 4096
44+
#define TRACE_BUFFER_SIZE_BYTE (TRACER_BUFFER_PAGE_NUM * TRACER_BUFFER_CHUNK)
4045

4146
struct mlx5_fw_tracer {
4247
struct mlx5_core_dev *dev;
4348
bool owner;
4449
u8 trc_ver;
4550
struct workqueue_struct *work_queue;
4651
struct work_struct ownership_change_work;
52+
struct work_struct read_fw_strings_work;
4753

4854
/* Strings DB */
4955
struct {
@@ -52,7 +58,19 @@ struct mlx5_fw_tracer {
5258
u32 num_string_db;
5359
u32 base_address_out[STRINGS_DB_SECTIONS_NUM];
5460
u32 size_out[STRINGS_DB_SECTIONS_NUM];
61+
void *buffer[STRINGS_DB_SECTIONS_NUM];
62+
bool loaded;
5563
} str_db;
64+
65+
/* Log Buffer */
66+
struct {
67+
u32 pdn;
68+
void *log_buf;
69+
dma_addr_t dma;
70+
u32 size;
71+
struct mlx5_core_mkey mkey;
72+
73+
} buff;
5674
};
5775

5876
enum mlx5_fw_tracer_ownership_state {

0 commit comments

Comments
 (0)