Commit | Line | Data |
---|---|---|
e126ba97 | 1 | /* |
302bdf68 | 2 | * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved. |
e126ba97 EC |
3 | * |
4 | * This software is available to you under a choice of one of two | |
5 | * licenses. You may choose to be licensed under the terms of the GNU | |
6 | * General Public License (GPL) Version 2, available from the file | |
7 | * COPYING in the main directory of this source tree, or the | |
8 | * OpenIB.org BSD license below: | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or | |
11 | * without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistributions of source code must retain the above | |
15 | * copyright notice, this list of conditions and the following | |
16 | * disclaimer. | |
17 | * | |
18 | * - Redistributions in binary form must reproduce the above | |
19 | * copyright notice, this list of conditions and the following | |
20 | * disclaimer in the documentation and/or other materials | |
21 | * provided with the distribution. | |
22 | * | |
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
30 | * SOFTWARE. | |
31 | */ | |
32 | ||
e126ba97 EC |
33 | #include <linux/debugfs.h> |
34 | #include <linux/mlx5/qp.h> | |
35 | #include <linux/mlx5/cq.h> | |
36 | #include <linux/mlx5/driver.h> | |
37 | #include "mlx5_core.h" | |
f2f3df55 | 38 | #include "lib/eq.h" |
e126ba97 EC |
39 | |
40 | enum { | |
41 | QP_PID, | |
42 | QP_STATE, | |
43 | QP_XPORT, | |
44 | QP_MTU, | |
45 | QP_N_RECV, | |
46 | QP_RECV_SZ, | |
47 | QP_N_SEND, | |
48 | QP_LOG_PG_SZ, | |
49 | QP_RQPN, | |
50 | }; | |
51 | ||
52 | static char *qp_fields[] = { | |
53 | [QP_PID] = "pid", | |
54 | [QP_STATE] = "state", | |
55 | [QP_XPORT] = "transport", | |
56 | [QP_MTU] = "mtu", | |
57 | [QP_N_RECV] = "num_recv", | |
58 | [QP_RECV_SZ] = "rcv_wqe_sz", | |
59 | [QP_N_SEND] = "num_send", | |
60 | [QP_LOG_PG_SZ] = "log2_page_sz", | |
61 | [QP_RQPN] = "remote_qpn", | |
62 | }; | |
63 | ||
64 | enum { | |
65 | EQ_NUM_EQES, | |
66 | EQ_INTR, | |
67 | EQ_LOG_PG_SZ, | |
68 | }; | |
69 | ||
70 | static char *eq_fields[] = { | |
71 | [EQ_NUM_EQES] = "num_eqes", | |
72 | [EQ_INTR] = "intr", | |
73 | [EQ_LOG_PG_SZ] = "log_page_size", | |
74 | }; | |
75 | ||
76 | enum { | |
77 | CQ_PID, | |
78 | CQ_NUM_CQES, | |
79 | CQ_LOG_PG_SZ, | |
80 | }; | |
81 | ||
82 | static char *cq_fields[] = { | |
83 | [CQ_PID] = "pid", | |
84 | [CQ_NUM_CQES] = "num_cqes", | |
85 | [CQ_LOG_PG_SZ] = "log_page_size", | |
86 | }; | |
87 | ||
88 | struct dentry *mlx5_debugfs_root; | |
89 | EXPORT_SYMBOL(mlx5_debugfs_root); | |
90 | ||
91 | void mlx5_register_debugfs(void) | |
92 | { | |
93 | mlx5_debugfs_root = debugfs_create_dir("mlx5", NULL); | |
e126ba97 EC |
94 | } |
95 | ||
96 | void mlx5_unregister_debugfs(void) | |
97 | { | |
98 | debugfs_remove(mlx5_debugfs_root); | |
99 | } | |
100 | ||
66771a1c MS |
101 | struct dentry *mlx5_debugfs_get_dev_root(struct mlx5_core_dev *dev) |
102 | { | |
103 | return dev->priv.dbg.dbg_root; | |
104 | } | |
105 | EXPORT_SYMBOL(mlx5_debugfs_get_dev_root); | |
106 | ||
9f818c8a | 107 | void mlx5_qp_debugfs_init(struct mlx5_core_dev *dev) |
e126ba97 | 108 | { |
66771a1c | 109 | dev->priv.dbg.qp_debugfs = debugfs_create_dir("QPs", dev->priv.dbg.dbg_root); |
e126ba97 | 110 | } |
333fbaa0 | 111 | EXPORT_SYMBOL(mlx5_qp_debugfs_init); |
e126ba97 EC |
112 | |
113 | void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev) | |
114 | { | |
66771a1c | 115 | debugfs_remove_recursive(dev->priv.dbg.qp_debugfs); |
e126ba97 | 116 | } |
333fbaa0 | 117 | EXPORT_SYMBOL(mlx5_qp_debugfs_cleanup); |
e126ba97 | 118 | |
9f818c8a | 119 | void mlx5_eq_debugfs_init(struct mlx5_core_dev *dev) |
e126ba97 | 120 | { |
66771a1c | 121 | dev->priv.dbg.eq_debugfs = debugfs_create_dir("EQs", dev->priv.dbg.dbg_root); |
e126ba97 EC |
122 | } |
123 | ||
124 | void mlx5_eq_debugfs_cleanup(struct mlx5_core_dev *dev) | |
125 | { | |
66771a1c | 126 | debugfs_remove_recursive(dev->priv.dbg.eq_debugfs); |
e126ba97 EC |
127 | } |
128 | ||
129 | static ssize_t average_read(struct file *filp, char __user *buf, size_t count, | |
130 | loff_t *pos) | |
131 | { | |
132 | struct mlx5_cmd_stats *stats; | |
133 | u64 field = 0; | |
134 | int ret; | |
e126ba97 EC |
135 | char tbuf[22]; |
136 | ||
e126ba97 | 137 | stats = filp->private_data; |
746b5583 | 138 | spin_lock_irq(&stats->lock); |
e126ba97 | 139 | if (stats->n) |
9a0f06fe | 140 | field = div64_u64(stats->sum, stats->n); |
746b5583 | 141 | spin_unlock_irq(&stats->lock); |
e126ba97 | 142 | ret = snprintf(tbuf, sizeof(tbuf), "%llu\n", field); |
31e33a5b | 143 | return simple_read_from_buffer(buf, count, pos, tbuf, ret); |
e126ba97 EC |
144 | } |
145 | ||
e126ba97 EC |
146 | static ssize_t average_write(struct file *filp, const char __user *buf, |
147 | size_t count, loff_t *pos) | |
148 | { | |
149 | struct mlx5_cmd_stats *stats; | |
150 | ||
151 | stats = filp->private_data; | |
746b5583 | 152 | spin_lock_irq(&stats->lock); |
e126ba97 EC |
153 | stats->sum = 0; |
154 | stats->n = 0; | |
746b5583 | 155 | spin_unlock_irq(&stats->lock); |
e126ba97 EC |
156 | |
157 | *pos += count; | |
158 | ||
159 | return count; | |
160 | } | |
161 | ||
162 | static const struct file_operations stats_fops = { | |
163 | .owner = THIS_MODULE, | |
164 | .open = simple_open, | |
165 | .read = average_read, | |
166 | .write = average_write, | |
167 | }; | |
168 | ||
e723f866 TT |
169 | static ssize_t slots_read(struct file *filp, char __user *buf, size_t count, |
170 | loff_t *pos) | |
171 | { | |
172 | struct mlx5_cmd *cmd; | |
173 | char tbuf[6]; | |
174 | int weight; | |
175 | int field; | |
176 | int ret; | |
177 | ||
178 | cmd = filp->private_data; | |
179 | weight = bitmap_weight(&cmd->bitmask, cmd->max_reg_cmds); | |
180 | field = cmd->max_reg_cmds - weight; | |
181 | ret = snprintf(tbuf, sizeof(tbuf), "%d\n", field); | |
182 | return simple_read_from_buffer(buf, count, pos, tbuf, ret); | |
183 | } | |
184 | ||
185 | static const struct file_operations slots_fops = { | |
186 | .owner = THIS_MODULE, | |
187 | .open = simple_open, | |
188 | .read = slots_read, | |
189 | }; | |
190 | ||
9f818c8a | 191 | void mlx5_cmdif_debugfs_init(struct mlx5_core_dev *dev) |
e126ba97 EC |
192 | { |
193 | struct mlx5_cmd_stats *stats; | |
194 | struct dentry **cmd; | |
195 | const char *namep; | |
e126ba97 EC |
196 | int i; |
197 | ||
66771a1c MS |
198 | cmd = &dev->priv.dbg.cmdif_debugfs; |
199 | *cmd = debugfs_create_dir("commands", dev->priv.dbg.dbg_root); | |
e126ba97 | 200 | |
e723f866 TT |
201 | debugfs_create_file("slots_inuse", 0400, *cmd, &dev->cmd, &slots_fops); |
202 | ||
2553f421 | 203 | for (i = 0; i < MLX5_CMD_OP_MAX; i++) { |
e126ba97 EC |
204 | stats = &dev->cmd.stats[i]; |
205 | namep = mlx5_command_str(i); | |
206 | if (strcmp(namep, "unknown command opcode")) { | |
207 | stats->root = debugfs_create_dir(namep, *cmd); | |
9f818c8a GKH |
208 | |
209 | debugfs_create_file("average", 0400, stats->root, stats, | |
210 | &stats_fops); | |
211 | debugfs_create_u64("n", 0400, stats->root, &stats->n); | |
34f46ae0 MS |
212 | debugfs_create_u64("failed", 0400, stats->root, &stats->failed); |
213 | debugfs_create_u64("failed_mbox_status", 0400, stats->root, | |
214 | &stats->failed_mbox_status); | |
215 | debugfs_create_u32("last_failed_errno", 0400, stats->root, | |
216 | &stats->last_failed_errno); | |
217 | debugfs_create_u8("last_failed_mbox_status", 0400, stats->root, | |
218 | &stats->last_failed_mbox_status); | |
1d2c717b MS |
219 | debugfs_create_x32("last_failed_syndrome", 0400, stats->root, |
220 | &stats->last_failed_syndrome); | |
e126ba97 EC |
221 | } |
222 | } | |
e126ba97 EC |
223 | } |
224 | ||
225 | void mlx5_cmdif_debugfs_cleanup(struct mlx5_core_dev *dev) | |
226 | { | |
66771a1c | 227 | debugfs_remove_recursive(dev->priv.dbg.cmdif_debugfs); |
e126ba97 EC |
228 | } |
229 | ||
9f818c8a | 230 | void mlx5_cq_debugfs_init(struct mlx5_core_dev *dev) |
e126ba97 | 231 | { |
66771a1c | 232 | dev->priv.dbg.cq_debugfs = debugfs_create_dir("CQs", dev->priv.dbg.dbg_root); |
e126ba97 EC |
233 | } |
234 | ||
235 | void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev) | |
236 | { | |
66771a1c | 237 | debugfs_remove_recursive(dev->priv.dbg.cq_debugfs); |
e126ba97 EC |
238 | } |
239 | ||
4e05cbf0 MS |
240 | void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev) |
241 | { | |
242 | struct dentry *pages; | |
243 | ||
244 | dev->priv.dbg.pages_debugfs = debugfs_create_dir("pages", dev->priv.dbg.dbg_root); | |
245 | pages = dev->priv.dbg.pages_debugfs; | |
246 | ||
247 | debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages); | |
c3bdbaea | 248 | debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]); |
395ccd6e | 249 | debugfs_create_u32("fw_pages_ec_vfs", 0400, pages, &dev->priv.page_counters[MLX5_EC_VF]); |
9965bbeb | 250 | debugfs_create_u32("fw_pages_sfs", 0400, pages, &dev->priv.page_counters[MLX5_SF]); |
c3bdbaea | 251 | debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.page_counters[MLX5_HOST_PF]); |
32071187 MS |
252 | debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed); |
253 | debugfs_create_u32("fw_pages_give_dropped", 0400, pages, &dev->priv.give_pages_dropped); | |
254 | debugfs_create_u32("fw_pages_reclaim_discard", 0400, pages, | |
255 | &dev->priv.reclaim_pages_discard); | |
4e05cbf0 MS |
256 | } |
257 | ||
258 | void mlx5_pages_debugfs_cleanup(struct mlx5_core_dev *dev) | |
259 | { | |
260 | debugfs_remove_recursive(dev->priv.dbg.pages_debugfs); | |
261 | } | |
262 | ||
e126ba97 | 263 | static u64 qp_read_field(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp, |
db81a5c3 | 264 | int index, int *is_str) |
e126ba97 | 265 | { |
e1167e16 | 266 | int outlen = MLX5_ST_SZ_BYTES(query_qp_out); |
57a6c5e9 | 267 | u32 in[MLX5_ST_SZ_DW(query_qp_in)] = {}; |
e126ba97 | 268 | u64 param = 0; |
e1167e16 | 269 | u32 *out; |
57a6c5e9 LR |
270 | int state; |
271 | u32 *qpc; | |
e126ba97 | 272 | int err; |
e126ba97 | 273 | |
e1167e16 AB |
274 | out = kzalloc(outlen, GFP_KERNEL); |
275 | if (!out) | |
276 | return 0; | |
277 | ||
57a6c5e9 LR |
278 | MLX5_SET(query_qp_in, in, opcode, MLX5_CMD_OP_QUERY_QP); |
279 | MLX5_SET(query_qp_in, in, qpn, qp->qpn); | |
280 | err = mlx5_cmd_exec_inout(dev, query_qp, in, out); | |
281 | if (err) | |
e1167e16 | 282 | goto out; |
e126ba97 | 283 | |
db81a5c3 | 284 | *is_str = 0; |
09a7d9ec | 285 | |
57a6c5e9 | 286 | qpc = MLX5_ADDR_OF(query_qp_out, out, qpc); |
e126ba97 EC |
287 | switch (index) { |
288 | case QP_PID: | |
289 | param = qp->pid; | |
290 | break; | |
291 | case QP_STATE: | |
57a6c5e9 LR |
292 | state = MLX5_GET(qpc, qpc, state); |
293 | param = (unsigned long)mlx5_qp_state_str(state); | |
db81a5c3 | 294 | *is_str = 1; |
e126ba97 EC |
295 | break; |
296 | case QP_XPORT: | |
57a6c5e9 | 297 | param = (unsigned long)mlx5_qp_type_str(MLX5_GET(qpc, qpc, st)); |
db81a5c3 | 298 | *is_str = 1; |
e126ba97 EC |
299 | break; |
300 | case QP_MTU: | |
57a6c5e9 | 301 | switch (MLX5_GET(qpc, qpc, mtu)) { |
db81a5c3 EC |
302 | case IB_MTU_256: |
303 | param = 256; | |
304 | break; | |
305 | case IB_MTU_512: | |
306 | param = 512; | |
307 | break; | |
308 | case IB_MTU_1024: | |
309 | param = 1024; | |
310 | break; | |
311 | case IB_MTU_2048: | |
312 | param = 2048; | |
313 | break; | |
314 | case IB_MTU_4096: | |
315 | param = 4096; | |
316 | break; | |
317 | default: | |
318 | param = 0; | |
319 | } | |
e126ba97 EC |
320 | break; |
321 | case QP_N_RECV: | |
57a6c5e9 | 322 | param = 1 << MLX5_GET(qpc, qpc, log_rq_size); |
e126ba97 EC |
323 | break; |
324 | case QP_RECV_SZ: | |
57a6c5e9 | 325 | param = 1 << (MLX5_GET(qpc, qpc, log_rq_stride) + 4); |
e126ba97 EC |
326 | break; |
327 | case QP_N_SEND: | |
57a6c5e9 LR |
328 | if (!MLX5_GET(qpc, qpc, no_sq)) |
329 | param = 1 << MLX5_GET(qpc, qpc, log_sq_size); | |
e126ba97 EC |
330 | break; |
331 | case QP_LOG_PG_SZ: | |
57a6c5e9 | 332 | param = MLX5_GET(qpc, qpc, log_page_size) + 12; |
e126ba97 EC |
333 | break; |
334 | case QP_RQPN: | |
57a6c5e9 | 335 | param = MLX5_GET(qpc, qpc, remote_qpn); |
e126ba97 EC |
336 | break; |
337 | } | |
e1167e16 AB |
338 | out: |
339 | kfree(out); | |
e126ba97 EC |
340 | return param; |
341 | } | |
342 | ||
343 | static u64 eq_read_field(struct mlx5_core_dev *dev, struct mlx5_eq *eq, | |
344 | int index) | |
345 | { | |
73b626c1 | 346 | int outlen = MLX5_ST_SZ_BYTES(query_eq_out); |
e36fb468 | 347 | u32 in[MLX5_ST_SZ_DW(query_eq_in)] = {}; |
e126ba97 | 348 | u64 param = 0; |
73b626c1 SM |
349 | void *ctx; |
350 | u32 *out; | |
e126ba97 EC |
351 | int err; |
352 | ||
73b626c1 | 353 | out = kzalloc(outlen, GFP_KERNEL); |
e126ba97 EC |
354 | if (!out) |
355 | return param; | |
356 | ||
e36fb468 LR |
357 | MLX5_SET(query_eq_in, in, opcode, MLX5_CMD_OP_QUERY_EQ); |
358 | MLX5_SET(query_eq_in, in, eq_number, eq->eqn); | |
359 | err = mlx5_cmd_exec_inout(dev, query_eq, in, out); | |
e126ba97 EC |
360 | if (err) { |
361 | mlx5_core_warn(dev, "failed to query eq\n"); | |
362 | goto out; | |
363 | } | |
73b626c1 | 364 | ctx = MLX5_ADDR_OF(query_eq_out, out, eq_context_entry); |
e126ba97 EC |
365 | |
366 | switch (index) { | |
367 | case EQ_NUM_EQES: | |
73b626c1 | 368 | param = 1 << MLX5_GET(eqc, ctx, log_eq_size); |
e126ba97 EC |
369 | break; |
370 | case EQ_INTR: | |
73b626c1 | 371 | param = MLX5_GET(eqc, ctx, intr); |
e126ba97 EC |
372 | break; |
373 | case EQ_LOG_PG_SZ: | |
73b626c1 | 374 | param = MLX5_GET(eqc, ctx, log_page_size) + 12; |
e126ba97 EC |
375 | break; |
376 | } | |
377 | ||
378 | out: | |
379 | kfree(out); | |
380 | return param; | |
381 | } | |
382 | ||
383 | static u64 cq_read_field(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq, | |
384 | int index) | |
385 | { | |
27827786 | 386 | int outlen = MLX5_ST_SZ_BYTES(query_cq_out); |
e126ba97 | 387 | u64 param = 0; |
27827786 SM |
388 | void *ctx; |
389 | u32 *out; | |
e126ba97 EC |
390 | int err; |
391 | ||
1b9a07ee | 392 | out = kvzalloc(outlen, GFP_KERNEL); |
e126ba97 EC |
393 | if (!out) |
394 | return param; | |
395 | ||
d1f62050 | 396 | err = mlx5_core_query_cq(dev, cq, out); |
e126ba97 EC |
397 | if (err) { |
398 | mlx5_core_warn(dev, "failed to query cq\n"); | |
399 | goto out; | |
400 | } | |
27827786 | 401 | ctx = MLX5_ADDR_OF(query_cq_out, out, cq_context); |
e126ba97 EC |
402 | |
403 | switch (index) { | |
404 | case CQ_PID: | |
405 | param = cq->pid; | |
406 | break; | |
407 | case CQ_NUM_CQES: | |
27827786 | 408 | param = 1 << MLX5_GET(cqc, ctx, log_cq_size); |
e126ba97 EC |
409 | break; |
410 | case CQ_LOG_PG_SZ: | |
27827786 | 411 | param = MLX5_GET(cqc, ctx, log_page_size); |
e126ba97 EC |
412 | break; |
413 | } | |
414 | ||
415 | out: | |
27827786 | 416 | kvfree(out); |
e126ba97 EC |
417 | return param; |
418 | } | |
419 | ||
420 | static ssize_t dbg_read(struct file *filp, char __user *buf, size_t count, | |
421 | loff_t *pos) | |
422 | { | |
423 | struct mlx5_field_desc *desc; | |
424 | struct mlx5_rsc_debug *d; | |
425 | char tbuf[18]; | |
db81a5c3 | 426 | int is_str = 0; |
e126ba97 EC |
427 | u64 field; |
428 | int ret; | |
e126ba97 | 429 | |
e126ba97 EC |
430 | desc = filp->private_data; |
431 | d = (void *)(desc - desc->i) - sizeof(*d); | |
432 | switch (d->type) { | |
433 | case MLX5_DBG_RSC_QP: | |
db81a5c3 | 434 | field = qp_read_field(d->dev, d->object, desc->i, &is_str); |
e126ba97 EC |
435 | break; |
436 | ||
437 | case MLX5_DBG_RSC_EQ: | |
438 | field = eq_read_field(d->dev, d->object, desc->i); | |
439 | break; | |
440 | ||
441 | case MLX5_DBG_RSC_CQ: | |
442 | field = cq_read_field(d->dev, d->object, desc->i); | |
443 | break; | |
444 | ||
445 | default: | |
446 | mlx5_core_warn(d->dev, "invalid resource type %d\n", d->type); | |
447 | return -EINVAL; | |
448 | } | |
449 | ||
db81a5c3 | 450 | if (is_str) |
065bd8c2 | 451 | ret = snprintf(tbuf, sizeof(tbuf), "%s\n", (const char *)(unsigned long)field); |
db81a5c3 EC |
452 | else |
453 | ret = snprintf(tbuf, sizeof(tbuf), "0x%llx\n", field); | |
454 | ||
31e33a5b | 455 | return simple_read_from_buffer(buf, count, pos, tbuf, ret); |
e126ba97 EC |
456 | } |
457 | ||
458 | static const struct file_operations fops = { | |
459 | .owner = THIS_MODULE, | |
460 | .open = simple_open, | |
461 | .read = dbg_read, | |
462 | }; | |
463 | ||
464 | static int add_res_tree(struct mlx5_core_dev *dev, enum dbg_rsc_type type, | |
465 | struct dentry *root, struct mlx5_rsc_debug **dbg, | |
466 | int rsn, char **field, int nfile, void *data) | |
467 | { | |
468 | struct mlx5_rsc_debug *d; | |
469 | char resn[32]; | |
e126ba97 EC |
470 | int i; |
471 | ||
acafe7e3 | 472 | d = kzalloc(struct_size(d, fields, nfile), GFP_KERNEL); |
e126ba97 EC |
473 | if (!d) |
474 | return -ENOMEM; | |
475 | ||
476 | d->dev = dev; | |
477 | d->object = data; | |
478 | d->type = type; | |
479 | sprintf(resn, "0x%x", rsn); | |
480 | d->root = debugfs_create_dir(resn, root); | |
e126ba97 EC |
481 | |
482 | for (i = 0; i < nfile; i++) { | |
483 | d->fields[i].i = i; | |
9f818c8a GKH |
484 | debugfs_create_file(field[i], 0400, d->root, &d->fields[i], |
485 | &fops); | |
e126ba97 EC |
486 | } |
487 | *dbg = d; | |
488 | ||
489 | return 0; | |
e126ba97 EC |
490 | } |
491 | ||
492 | static void rem_res_tree(struct mlx5_rsc_debug *d) | |
493 | { | |
494 | debugfs_remove_recursive(d->root); | |
495 | kfree(d); | |
496 | } | |
497 | ||
498 | int mlx5_debug_qp_add(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp) | |
499 | { | |
500 | int err; | |
501 | ||
502 | if (!mlx5_debugfs_root) | |
503 | return 0; | |
504 | ||
66771a1c | 505 | err = add_res_tree(dev, MLX5_DBG_RSC_QP, dev->priv.dbg.qp_debugfs, |
e126ba97 EC |
506 | &qp->dbg, qp->qpn, qp_fields, |
507 | ARRAY_SIZE(qp_fields), qp); | |
508 | if (err) | |
509 | qp->dbg = NULL; | |
510 | ||
511 | return err; | |
512 | } | |
333fbaa0 | 513 | EXPORT_SYMBOL(mlx5_debug_qp_add); |
e126ba97 EC |
514 | |
515 | void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp) | |
516 | { | |
c023b61a | 517 | if (!mlx5_debugfs_root || !qp->dbg) |
e126ba97 EC |
518 | return; |
519 | ||
c023b61a PH |
520 | rem_res_tree(qp->dbg); |
521 | qp->dbg = NULL; | |
e126ba97 | 522 | } |
333fbaa0 | 523 | EXPORT_SYMBOL(mlx5_debug_qp_remove); |
e126ba97 | 524 | |
e126ba97 EC |
525 | int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq) |
526 | { | |
527 | int err; | |
528 | ||
529 | if (!mlx5_debugfs_root) | |
530 | return 0; | |
531 | ||
66771a1c | 532 | err = add_res_tree(dev, MLX5_DBG_RSC_EQ, dev->priv.dbg.eq_debugfs, |
e126ba97 EC |
533 | &eq->dbg, eq->eqn, eq_fields, |
534 | ARRAY_SIZE(eq_fields), eq); | |
535 | if (err) | |
536 | eq->dbg = NULL; | |
537 | ||
538 | return err; | |
539 | } | |
540 | ||
541 | void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq) | |
542 | { | |
543 | if (!mlx5_debugfs_root) | |
544 | return; | |
545 | ||
546 | if (eq->dbg) | |
547 | rem_res_tree(eq->dbg); | |
548 | } | |
549 | ||
550 | int mlx5_debug_cq_add(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) | |
551 | { | |
552 | int err; | |
553 | ||
554 | if (!mlx5_debugfs_root) | |
555 | return 0; | |
556 | ||
66771a1c | 557 | err = add_res_tree(dev, MLX5_DBG_RSC_CQ, dev->priv.dbg.cq_debugfs, |
e126ba97 EC |
558 | &cq->dbg, cq->cqn, cq_fields, |
559 | ARRAY_SIZE(cq_fields), cq); | |
560 | if (err) | |
561 | cq->dbg = NULL; | |
562 | ||
563 | return err; | |
564 | } | |
565 | ||
566 | void mlx5_debug_cq_remove(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq) | |
567 | { | |
568 | if (!mlx5_debugfs_root) | |
569 | return; | |
570 | ||
76ded29d | 571 | if (cq->dbg) { |
e126ba97 | 572 | rem_res_tree(cq->dbg); |
76ded29d VF |
573 | cq->dbg = NULL; |
574 | } | |
e126ba97 | 575 | } |