xref: /freebsd/sys/dev/mlx5/mlx5_core/mlx5_diag_cnt.c (revision aa7bbdab)
1 /*-
2  * Copyright (c) 2018, Mellanox Technologies, Ltd.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <dev/mlx5/mlx5_core/diag_cnt.h>
27 
28 static int get_supported_cnt_ids(struct mlx5_core_dev *dev);
29 static int enable_cnt_id(struct mlx5_core_dev *dev, u16 id);
30 static void reset_cnt_id(struct mlx5_core_dev *dev);
31 static void reset_params(struct mlx5_diag_cnt *diag_cnt);
32 
33 static int
mlx5_sysctl_counter_id(SYSCTL_HANDLER_ARGS)34 mlx5_sysctl_counter_id(SYSCTL_HANDLER_ARGS)
35 {
36 	struct mlx5_diag_cnt *diag_cnt;
37 	struct mlx5_core_dev *dev;
38 	uint16_t *ptr;
39 	size_t max;
40 	size_t num;
41 	size_t x;
42 	int err;
43 
44 	dev = arg1;
45 	diag_cnt = &dev->diag_cnt;
46 
47 	max = MLX5_CAP_GEN(dev, num_of_diagnostic_counters);
48 
49 	ptr = kmalloc(sizeof(ptr[0]) * max, GFP_KERNEL);
50 
51 	DIAG_LOCK(diag_cnt);
52 
53 	for (x = num = 0; x != max; x++) {
54 		if (diag_cnt->cnt_id[x].enabled)
55 			ptr[num++] = diag_cnt->cnt_id[x].id;
56 	}
57 
58 	err = SYSCTL_OUT(req, ptr, sizeof(ptr[0]) * num);
59 	if (err || !req->newptr)
60 		goto done;
61 
62 	num = req->newlen / sizeof(ptr[0]);
63 	if (num > max) {
64 		err = ENOMEM;
65 		goto done;
66 	}
67 
68 	err = SYSCTL_IN(req, ptr, sizeof(ptr[0]) * num);
69 
70 	reset_cnt_id(dev);
71 
72 	for (x = 0; x != num; x++) {
73 		err = enable_cnt_id(dev, ptr[x]);
74 		if (err)
75 			goto done;
76 	}
77 
78 	diag_cnt->num_cnt_id = num;
79 done:
80 	kfree(ptr);
81 
82 	if (err != 0 && req->newptr != NULL)
83 		reset_cnt_id(dev);
84 
85 	DIAG_UNLOCK(diag_cnt);
86 
87 	return (err);
88 }
89 
90 #define	NUM_OF_DIAG_PARAMS 5
91 
92 static int
mlx5_sysctl_params(SYSCTL_HANDLER_ARGS)93 mlx5_sysctl_params(SYSCTL_HANDLER_ARGS)
94 {
95 	struct mlx5_diag_cnt *diag_cnt;
96 	struct mlx5_core_dev *dev;
97 	uint32_t temp[NUM_OF_DIAG_PARAMS];
98 	int err;
99 
100 	dev = arg1;
101 	diag_cnt = &dev->diag_cnt;
102 
103 	DIAG_LOCK(diag_cnt);
104 
105 	temp[0] = diag_cnt->log_num_of_samples;
106 	temp[1] = diag_cnt->log_sample_period;
107 	temp[2] = diag_cnt->flag;
108 	temp[3] = diag_cnt->num_of_samples;
109 	temp[4] = diag_cnt->sample_index;
110 
111 	err = SYSCTL_OUT(req, temp, sizeof(temp));
112 	if (err || !req->newptr)
113 		goto done;
114 
115 	err = SYSCTL_IN(req, temp, sizeof(temp));
116 	if (err)
117 		goto done;
118 
119 	reset_params(&dev->diag_cnt);
120 
121 	if (temp[0] > MLX5_CAP_DEBUG(dev, log_max_samples) ||
122 	    (1U << (MLX5_CAP_DEBUG(dev, log_max_samples) - temp[0])) <
123 	    diag_cnt->num_cnt_id) {
124 		err = ERANGE;
125 		goto done;
126 	} else if (temp[1] < MLX5_CAP_DEBUG(dev, log_min_sample_period)) {
127 		err = ERANGE;
128 		goto done;
129 	} else if (temp[2] >= 0x100) {
130 		err = ERANGE;
131 		goto done;
132 	} else if (temp[3] > (1U << diag_cnt->log_num_of_samples)) {
133 		err = ERANGE;
134 		goto done;
135 	} else if (temp[4] > (1U << diag_cnt->log_num_of_samples)) {
136 		err = ERANGE;
137 		goto done;
138 	}
139 
140 	diag_cnt->log_num_of_samples = temp[0];
141 	diag_cnt->log_sample_period = temp[1];
142 	diag_cnt->flag = temp[2];
143 	diag_cnt->num_of_samples = temp[3];
144 	diag_cnt->sample_index = temp[4];
145 done:
146 	DIAG_UNLOCK(diag_cnt);
147 
148 	return (err);
149 }
150 
151 static void
decode_cnt_buffer(u32 num_of_samples,u8 * out,struct sbuf * sbuf)152 decode_cnt_buffer(u32 num_of_samples, u8 *out, struct sbuf *sbuf)
153 {
154 	void *cnt;
155 	u64 temp;
156 	u32 i;
157 
158 	for (i = 0; i != num_of_samples; i++) {
159 		cnt = MLX5_ADDR_OF(query_diagnostic_counters_out,
160 		    out, diag_counter[i]);
161 		temp = MLX5_GET(diagnostic_cntr_struct, cnt, counter_value_h);
162 		temp = (temp << 32) |
163 		    MLX5_GET(diagnostic_cntr_struct, cnt, counter_value_l);
164 		sbuf_printf(sbuf,
165 		    "0x%04x,0x%04x,0x%08x,0x%016llx\n",
166 		    MLX5_GET(diagnostic_cntr_struct, cnt, counter_id),
167 		    MLX5_GET(diagnostic_cntr_struct, cnt, sample_id),
168 		    MLX5_GET(diagnostic_cntr_struct, cnt, time_stamp_31_0),
169 		    (unsigned long long)temp);
170 	}
171 }
172 
173 static int
mlx5_sysctl_dump_set(SYSCTL_HANDLER_ARGS)174 mlx5_sysctl_dump_set(SYSCTL_HANDLER_ARGS)
175 {
176 	struct mlx5_diag_cnt *diag_cnt;
177 	struct mlx5_core_dev *dev;
178 	uint8_t temp;
179 	int err;
180 
181 	dev = arg1;
182 	diag_cnt = &dev->diag_cnt;
183 
184 	DIAG_LOCK(diag_cnt);
185 
186 	err = SYSCTL_OUT(req, &diag_cnt->ready, sizeof(diag_cnt->ready));
187 	if (err || !req->newptr)
188 		goto done;
189 
190 	err = SYSCTL_IN(req, &temp, sizeof(temp));
191 	if (err)
192 		goto done;
193 
194 	diag_cnt->ready = (temp != 0);
195 	if (diag_cnt->ready != 0)
196 		err = -mlx5_diag_set_params(dev);
197 done:
198 	DIAG_UNLOCK(diag_cnt);
199 
200 	return (err);
201 }
202 
203 static int
mlx5_sysctl_dump_get(SYSCTL_HANDLER_ARGS)204 mlx5_sysctl_dump_get(SYSCTL_HANDLER_ARGS)
205 {
206 	struct mlx5_diag_cnt *diag_cnt;
207 	struct mlx5_core_dev *dev;
208 	struct sbuf sbuf;
209 	u8 *out;
210 	int err;
211 
212 	dev = arg1;
213 	diag_cnt = &dev->diag_cnt;
214 
215 	err = sysctl_wire_old_buffer(req, 0);
216 	if (err != 0)
217 		return (err);
218 
219 	DIAG_LOCK(diag_cnt);
220 
221 	sbuf_new_for_sysctl(&sbuf, NULL, 65536, req);
222 
223 	if (diag_cnt->ready != 0) {
224 		err = -mlx5_diag_query_counters(dev, &out);
225 		if (err) {
226 			sbuf_printf(&sbuf, "\nCould not query counters: %d\n", err);
227 		} else {
228 			sbuf_printf(&sbuf, "\n");
229 			decode_cnt_buffer(diag_cnt->num_of_samples *
230 			    diag_cnt->num_cnt_id, out, &sbuf);
231 			kfree(out);
232 		}
233 	} else {
234 		sbuf_printf(&sbuf, "\nDump was not set.\n");
235 	}
236 
237 	err = sbuf_finish(&sbuf);
238 
239 	sbuf_delete(&sbuf);
240 
241 	DIAG_UNLOCK(diag_cnt);
242 
243 	return (err);
244 }
245 
246 static int
mlx5_sysctl_cap_read(SYSCTL_HANDLER_ARGS)247 mlx5_sysctl_cap_read(SYSCTL_HANDLER_ARGS)
248 {
249 	struct mlx5_diag_cnt *diag_cnt;
250 	struct mlx5_core_dev *dev;
251 	struct sbuf sbuf;
252 	int err;
253 	u32 i;
254 
255 	dev = arg1;
256 	diag_cnt = &dev->diag_cnt;
257 
258 	err = sysctl_wire_old_buffer(req, 0);
259 	if (err != 0)
260 		return (err);
261 
262 	DIAG_LOCK(diag_cnt);
263 
264 	sbuf_new_for_sysctl(&sbuf, NULL, 8192, req);
265 
266 	sbuf_printf(&sbuf, "\n");
267 
268 	/* print cap */
269 	sbuf_printf(&sbuf, "log_max_samples=%d\n",
270 	    MLX5_CAP_DEBUG(dev, log_max_samples));
271 	sbuf_printf(&sbuf, "log_min_sample_period=%d\n",
272 	    MLX5_CAP_DEBUG(dev, log_min_sample_period));
273 	sbuf_printf(&sbuf, "repetitive=%d\n",
274 	    MLX5_CAP_DEBUG(dev, repetitive));
275 	sbuf_printf(&sbuf, "single=%d\n",
276 	    MLX5_CAP_DEBUG(dev, single));
277 	sbuf_printf(&sbuf, "num_of_diagnostic_counters=%d\n",
278 	    MLX5_CAP_GEN(dev, num_of_diagnostic_counters));
279 
280 	/* print list of supported counter */
281 	sbuf_printf(&sbuf, "supported counter id:\n");
282 	for (i = 0; i != MLX5_CAP_GEN(dev, num_of_diagnostic_counters); i++)
283 		sbuf_printf(&sbuf, "0x%04x,", diag_cnt->cnt_id[i].id);
284 	sbuf_printf(&sbuf, "\n");
285 
286 	err = sbuf_finish(&sbuf);
287 	sbuf_delete(&sbuf);
288 
289 	DIAG_UNLOCK(diag_cnt);
290 
291 	return (err);
292 }
293 
294 static int
get_supported_cnt_ids(struct mlx5_core_dev * dev)295 get_supported_cnt_ids(struct mlx5_core_dev *dev)
296 {
297 	u32 num_counters = MLX5_CAP_GEN(dev, num_of_diagnostic_counters);
298 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
299 	u32 i;
300 
301 	diag_cnt->cnt_id = kzalloc(sizeof(*diag_cnt->cnt_id) * num_counters,
302 	    GFP_KERNEL);
303 	if (!diag_cnt->cnt_id)
304 		return (-ENOMEM);
305 
306 	for (i = 0; i != num_counters; i++) {
307 		diag_cnt->cnt_id[i].id =
308 		    MLX5_CAP_DEBUG(dev, diagnostic_counter[i].counter_id);
309 	}
310 	return (0);
311 }
312 
313 static void
reset_cnt_id(struct mlx5_core_dev * dev)314 reset_cnt_id(struct mlx5_core_dev *dev)
315 {
316 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
317 	u32 i;
318 
319 	diag_cnt->num_cnt_id = 0;
320 	for (i = 0; i != MLX5_CAP_GEN(dev, num_of_diagnostic_counters); i++)
321 		diag_cnt->cnt_id[i].enabled = false;
322 }
323 
324 static int
enable_cnt_id(struct mlx5_core_dev * dev,u16 id)325 enable_cnt_id(struct mlx5_core_dev *dev, u16 id)
326 {
327 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
328 	u32 i;
329 
330 	for (i = 0; i != MLX5_CAP_GEN(dev, num_of_diagnostic_counters); i++) {
331 		if (diag_cnt->cnt_id[i].id == id) {
332 			if (diag_cnt->cnt_id[i].enabled)
333 				return (EINVAL);
334 
335 			diag_cnt->cnt_id[i].enabled = true;
336 			break;
337 		}
338 	}
339 
340 	if (i == MLX5_CAP_GEN(dev, num_of_diagnostic_counters))
341 		return (ENOENT);
342 	else
343 		return (0);
344 }
345 
346 static void
reset_params(struct mlx5_diag_cnt * diag_cnt)347 reset_params(struct mlx5_diag_cnt *diag_cnt)
348 {
349 	diag_cnt->log_num_of_samples = 0;
350 	diag_cnt->log_sample_period = 0;
351 	diag_cnt->flag = 0;
352 	diag_cnt->num_of_samples = 0;
353 	diag_cnt->sample_index = 0;
354 }
355 
356 int
mlx5_diag_set_params(struct mlx5_core_dev * dev)357 mlx5_diag_set_params(struct mlx5_core_dev *dev)
358 {
359 	u8 out[MLX5_ST_SZ_BYTES(set_diagnostic_params_out)] = {0};
360 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
361 	void *cnt_id;
362 	void *ctx;
363 	u16 in_sz;
364 	int err;
365 	u8 *in;
366 	u32 i;
367 	u32 j;
368 
369 	if (!diag_cnt->num_cnt_id)
370 		return (-EINVAL);
371 
372 	in_sz = MLX5_ST_SZ_BYTES(set_diagnostic_params_in) +
373 	    diag_cnt->num_cnt_id * MLX5_ST_SZ_BYTES(counter_id);
374 	in = kzalloc(in_sz, GFP_KERNEL);
375 	if (!in)
376 		return (-ENOMEM);
377 
378 	MLX5_SET(set_diagnostic_params_in, in, opcode,
379 	    MLX5_CMD_OP_SET_DIAGNOSTICS);
380 
381 	ctx = MLX5_ADDR_OF(set_diagnostic_params_in, in,
382 	    diagnostic_params_ctx);
383 	MLX5_SET(diagnostic_params_context, ctx, num_of_counters,
384 	    diag_cnt->num_cnt_id);
385 	MLX5_SET(diagnostic_params_context, ctx, log_num_of_samples,
386 	    diag_cnt->log_num_of_samples);
387 
388 	MLX5_SET(diagnostic_params_context, ctx, single,
389 	    (diag_cnt->flag >> 7) & 1);
390 	MLX5_SET(diagnostic_params_context, ctx, repetitive,
391 	    (diag_cnt->flag >> 6) & 1);
392 	MLX5_SET(diagnostic_params_context, ctx, sync,
393 	    (diag_cnt->flag >> 5) & 1);
394 	MLX5_SET(diagnostic_params_context, ctx, clear,
395 	    (diag_cnt->flag >> 4) & 1);
396 	MLX5_SET(diagnostic_params_context, ctx, on_demand,
397 	    (diag_cnt->flag >> 3) & 1);
398 	MLX5_SET(diagnostic_params_context, ctx, enable,
399 	    (diag_cnt->flag >> 2) & 1);
400 	MLX5_SET(diagnostic_params_context, ctx, log_sample_period,
401 	    diag_cnt->log_sample_period);
402 
403 	for (i = j = 0; i != MLX5_CAP_GEN(dev, num_of_diagnostic_counters); i++) {
404 		if (diag_cnt->cnt_id[i].enabled) {
405 			cnt_id = MLX5_ADDR_OF(diagnostic_params_context,
406 			    ctx, counter_id[j]);
407 			MLX5_SET(counter_id, cnt_id, counter_id,
408 			    diag_cnt->cnt_id[i].id);
409 			j++;
410 		}
411 	}
412 
413 	err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
414 
415 	kfree(in);
416 	return (err);
417 }
418 
419 /* This function is for debug purpose */
420 int
mlx5_diag_query_params(struct mlx5_core_dev * dev)421 mlx5_diag_query_params(struct mlx5_core_dev *dev)
422 {
423 	u8 in[MLX5_ST_SZ_BYTES(query_diagnostic_params_in)] = {0};
424 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
425 	void *cnt_id;
426 	u16 out_sz;
427 	void *ctx;
428 	int err;
429 	u8 *out;
430 	u32 i;
431 
432 	out_sz = MLX5_ST_SZ_BYTES(query_diagnostic_params_out) +
433 	    diag_cnt->num_cnt_id * MLX5_ST_SZ_BYTES(counter_id);
434 
435 	out = kzalloc(out_sz, GFP_KERNEL);
436 	if (!out)
437 		return (-ENOMEM);
438 
439 	MLX5_SET(query_diagnostic_params_in, in, opcode,
440 	    MLX5_CMD_OP_QUERY_DIAGNOSTIC_PARAMS);
441 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
442 	if (err)
443 		goto out;
444 
445 	ctx = MLX5_ADDR_OF(query_diagnostic_params_out, out,
446 	    diagnostic_params_ctx);
447 	mlx5_core_dbg(dev, "single=%x\n",
448 	    MLX5_GET(diagnostic_params_context, ctx, single));
449 	mlx5_core_dbg(dev, "repetitive=%x\n",
450 	    MLX5_GET(diagnostic_params_context, ctx, repetitive));
451 	mlx5_core_dbg(dev, "sync=%x\n",
452 	    MLX5_GET(diagnostic_params_context, ctx, sync));
453 	mlx5_core_dbg(dev, "clear=%x\n",
454 	    MLX5_GET(diagnostic_params_context, ctx, clear));
455 	mlx5_core_dbg(dev, "on_demand=%x\n",
456 	    MLX5_GET(diagnostic_params_context, ctx, on_demand));
457 	mlx5_core_dbg(dev, "enable=%x\n",
458 	    MLX5_GET(diagnostic_params_context, ctx, enable));
459 	mlx5_core_dbg(dev, "log_sample_period=%x\n",
460 	    MLX5_GET(diagnostic_params_context, ctx,
461 	    log_sample_period));
462 
463 	for (i = 0; i != diag_cnt->num_cnt_id; i++) {
464 		cnt_id = MLX5_ADDR_OF(diagnostic_params_context,
465 		    ctx, counter_id[i]);
466 		mlx5_core_dbg(dev, "counter_id[%d]=%x\n", i,
467 		    MLX5_GET(counter_id, cnt_id, counter_id));
468 	}
469 out:
470 	kfree(out);
471 	return (err);
472 }
473 
474 int
mlx5_diag_query_counters(struct mlx5_core_dev * dev,u8 ** out_buffer)475 mlx5_diag_query_counters(struct mlx5_core_dev *dev, u8 **out_buffer)
476 {
477 	u8 in[MLX5_ST_SZ_BYTES(query_diagnostic_counters_in)] = {0};
478 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
479 	u16 out_sz;
480 	u8 *out;
481 	int err;
482 
483 	out_sz = MLX5_ST_SZ_BYTES(query_diagnostic_counters_out) +
484 	    diag_cnt->num_of_samples * diag_cnt->num_cnt_id *
485 	    MLX5_ST_SZ_BYTES(diagnostic_cntr_struct);
486 
487 	out = kzalloc(out_sz, GFP_KERNEL);
488 	if (!out)
489 		return (-ENOMEM);
490 
491 	MLX5_SET(query_diagnostic_counters_in, in, opcode,
492 	    MLX5_CMD_OP_QUERY_DIAGNOSTICS);
493 	MLX5_SET(query_diagnostic_counters_in, in, num_of_samples,
494 	    diag_cnt->num_of_samples);
495 	MLX5_SET(query_diagnostic_counters_in, in, sample_index,
496 	    diag_cnt->sample_index);
497 
498 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz);
499 
500 	if (!err)
501 		*out_buffer = out;
502 	else
503 		kfree(out);
504 
505 	return (err);
506 }
507 
508 int
mlx5_diag_cnt_init(struct mlx5_core_dev * dev)509 mlx5_diag_cnt_init(struct mlx5_core_dev *dev)
510 {
511 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
512 	struct sysctl_oid *diag_cnt_sysctl_node;
513 	int err;
514 
515 	if (!MLX5_DIAG_CNT_SUPPORTED(dev))
516 		return (0);
517 
518 	mutex_init(&diag_cnt->lock);
519 
520 	/* Build private data */
521 	err = get_supported_cnt_ids(dev);
522 	if (err)
523 		return (err);
524 
525 	sysctl_ctx_init(&diag_cnt->sysctl_ctx);
526 
527 	diag_cnt_sysctl_node = SYSCTL_ADD_NODE(&diag_cnt->sysctl_ctx,
528 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev->pdev->dev.bsddev)),
529 	    OID_AUTO, "diag_cnt", CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
530 	    "Diagnostics counters");
531 
532 	if (diag_cnt_sysctl_node == NULL)
533 		return (-ENOMEM);
534 
535 	SYSCTL_ADD_PROC(&diag_cnt->sysctl_ctx, SYSCTL_CHILDREN(diag_cnt_sysctl_node),
536 	    OID_AUTO, "counter_id", CTLTYPE_U16 | CTLFLAG_RW | CTLFLAG_MPSAFE,
537 	    dev, 0, mlx5_sysctl_counter_id, "SU", "Selected counter IDs");
538 
539 	SYSCTL_ADD_PROC(&diag_cnt->sysctl_ctx, SYSCTL_CHILDREN(diag_cnt_sysctl_node),
540 	    OID_AUTO, "params", CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_MPSAFE,
541 	    dev, 0, mlx5_sysctl_params, "IU",
542 	    "Counter parameters: log_num_of_samples, log_sample_perios, flag, num_of_samples, sample_index");
543 
544 	SYSCTL_ADD_PROC(&diag_cnt->sysctl_ctx, SYSCTL_CHILDREN(diag_cnt_sysctl_node),
545 	    OID_AUTO, "dump_set", CTLTYPE_U8 | CTLFLAG_RW | CTLFLAG_MPSAFE,
546 	    dev, 0, mlx5_sysctl_dump_set, "CU",
547 	    "Set dump parameters by writing 1 and enable dump_get. Write 0 to disable dump.");
548 
549 	SYSCTL_ADD_PROC(&diag_cnt->sysctl_ctx, SYSCTL_CHILDREN(diag_cnt_sysctl_node),
550 	    OID_AUTO, "dump_get", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
551 	    dev, 0, mlx5_sysctl_dump_get, "A",
552 	    "Get dump parameters.");
553 
554 	SYSCTL_ADD_PROC(&diag_cnt->sysctl_ctx, SYSCTL_CHILDREN(diag_cnt_sysctl_node),
555 	    OID_AUTO, "cap", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
556 	    dev, 0, mlx5_sysctl_cap_read, "A",
557 	    "Read capabilities.");
558 
559 	return (0);
560 }
561 
562 void
mlx5_diag_cnt_cleanup(struct mlx5_core_dev * dev)563 mlx5_diag_cnt_cleanup(struct mlx5_core_dev *dev)
564 {
565 	struct mlx5_diag_cnt *diag_cnt = &dev->diag_cnt;
566 	void *ptr;
567 
568 	if (!MLX5_DIAG_CNT_SUPPORTED(dev))
569 		return;
570 
571 	sysctl_ctx_free(&diag_cnt->sysctl_ctx);
572 
573 	ptr = diag_cnt->cnt_id;
574 	diag_cnt->cnt_id = NULL;
575 
576 	kfree(ptr);
577 
578 	reset_params(diag_cnt);
579 }
580