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