]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/thunderbolt/debugfs.c
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2020, Intel Corporation
6 * Authors: Gil Fine <gil.fine@intel.com>
7 * Mika Westerberg <mika.westerberg@linux.intel.com>
10 #include <linux/debugfs.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/uaccess.h>
16 #define PORT_CAP_PCIE_LEN 1
17 #define PORT_CAP_POWER_LEN 2
18 #define PORT_CAP_LANE_LEN 3
19 #define PORT_CAP_USB3_LEN 5
20 #define PORT_CAP_DP_LEN 8
21 #define PORT_CAP_TMU_LEN 8
22 #define PORT_CAP_BASIC_LEN 9
23 #define PORT_CAP_USB4_LEN 20
25 #define SWITCH_CAP_TMU_LEN 26
26 #define SWITCH_CAP_BASIC_LEN 27
30 #define COUNTER_SET_LEN 3
32 #define DEBUGFS_ATTR(__space, __write) \
33 static int __space ## _open(struct inode *inode, struct file *file) \
35 return single_open(file, __space ## _show, inode->i_private); \
38 static const struct file_operations __space ## _fops = { \
39 .owner = THIS_MODULE, \
40 .open = __space ## _open, \
41 .release = single_release, \
44 .llseek = seq_lseek, \
47 #define DEBUGFS_ATTR_RO(__space) \
48 DEBUGFS_ATTR(__space, NULL)
50 #define DEBUGFS_ATTR_RW(__space) \
51 DEBUGFS_ATTR(__space, __space ## _write)
53 static struct dentry
*tb_debugfs_root
;
55 static void *validate_and_copy_from_user(const void __user
*user_buf
,
62 return ERR_PTR(-EINVAL
);
64 if (!access_ok(user_buf
, *count
))
65 return ERR_PTR(-EFAULT
);
67 buf
= (void *)get_zeroed_page(GFP_KERNEL
);
69 return ERR_PTR(-ENOMEM
);
71 nbytes
= min_t(size_t, *count
, PAGE_SIZE
);
72 if (copy_from_user(buf
, user_buf
, nbytes
)) {
73 free_page((unsigned long)buf
);
74 return ERR_PTR(-EFAULT
);
81 static bool parse_line(char **line
, u32
*offs
, u32
*val
, int short_fmt_len
,
88 token
= strsep(line
, "\n");
93 * For Adapter/Router configuration space:
94 * Short format is: offset value\n
96 * Long format as produced from the read side:
97 * offset relative_offset cap_id vs_cap_id value\n
98 * v[0] v[1] v[2] v[3] v[4]
100 * For Counter configuration space:
101 * Short format is: offset\n
103 * Long format as produced from the read side:
104 * offset relative_offset counter_id value\n
105 * v[0] v[1] v[2] v[3]
107 ret
= sscanf(token
, "%i %i %i %i %i", &v
[0], &v
[1], &v
[2], &v
[3], &v
[4]);
108 /* In case of Counters, clear counter, "val" content is NA */
109 if (ret
== short_fmt_len
) {
111 *val
= v
[short_fmt_len
- 1];
113 } else if (ret
== long_fmt_len
) {
115 *val
= v
[long_fmt_len
- 1];
122 #if IS_ENABLED(CONFIG_USB4_DEBUGFS_WRITE)
123 static ssize_t
regs_write(struct tb_switch
*sw
, struct tb_port
*port
,
124 const char __user
*user_buf
, size_t count
,
127 struct tb
*tb
= sw
->tb
;
132 buf
= validate_and_copy_from_user(user_buf
, &count
);
136 pm_runtime_get_sync(&sw
->dev
);
138 if (mutex_lock_interruptible(&tb
->lock
)) {
143 /* User did hardware changes behind the driver's back */
144 add_taint(TAINT_USER
, LOCKDEP_STILL_OK
);
147 while (parse_line(&line
, &offset
, &val
, 2, 5)) {
149 ret
= tb_port_write(port
, &val
, TB_CFG_PORT
, offset
, 1);
151 ret
= tb_sw_write(sw
, &val
, TB_CFG_SWITCH
, offset
, 1);
156 mutex_unlock(&tb
->lock
);
159 pm_runtime_mark_last_busy(&sw
->dev
);
160 pm_runtime_put_autosuspend(&sw
->dev
);
161 free_page((unsigned long)buf
);
163 return ret
< 0 ? ret
: count
;
166 static ssize_t
port_regs_write(struct file
*file
, const char __user
*user_buf
,
167 size_t count
, loff_t
*ppos
)
169 struct seq_file
*s
= file
->private_data
;
170 struct tb_port
*port
= s
->private;
172 return regs_write(port
->sw
, port
, user_buf
, count
, ppos
);
175 static ssize_t
switch_regs_write(struct file
*file
, const char __user
*user_buf
,
176 size_t count
, loff_t
*ppos
)
178 struct seq_file
*s
= file
->private_data
;
179 struct tb_switch
*sw
= s
->private;
181 return regs_write(sw
, NULL
, user_buf
, count
, ppos
);
183 #define DEBUGFS_MODE 0600
185 #define port_regs_write NULL
186 #define switch_regs_write NULL
187 #define DEBUGFS_MODE 0400
190 static int port_clear_all_counters(struct tb_port
*port
)
195 buf
= kcalloc(COUNTER_SET_LEN
* port
->config
.max_counters
, sizeof(u32
),
200 ret
= tb_port_write(port
, buf
, TB_CFG_COUNTERS
, 0,
201 COUNTER_SET_LEN
* port
->config
.max_counters
);
207 static ssize_t
counters_write(struct file
*file
, const char __user
*user_buf
,
208 size_t count
, loff_t
*ppos
)
210 struct seq_file
*s
= file
->private_data
;
211 struct tb_port
*port
= s
->private;
212 struct tb_switch
*sw
= port
->sw
;
213 struct tb
*tb
= port
->sw
->tb
;
217 buf
= validate_and_copy_from_user(user_buf
, &count
);
221 pm_runtime_get_sync(&sw
->dev
);
223 if (mutex_lock_interruptible(&tb
->lock
)) {
228 /* If written delimiter only, clear all counters in one shot */
229 if (buf
[0] == '\n') {
230 ret
= port_clear_all_counters(port
);
236 while (parse_line(&line
, &offset
, &val
, 1, 4)) {
237 ret
= tb_port_write(port
, &val
, TB_CFG_COUNTERS
,
244 mutex_unlock(&tb
->lock
);
247 pm_runtime_mark_last_busy(&sw
->dev
);
248 pm_runtime_put_autosuspend(&sw
->dev
);
249 free_page((unsigned long)buf
);
251 return ret
< 0 ? ret
: count
;
254 static void cap_show_by_dw(struct seq_file
*s
, struct tb_switch
*sw
,
255 struct tb_port
*port
, unsigned int cap
,
256 unsigned int offset
, u8 cap_id
, u8 vsec_id
,
262 for (i
= 0; i
< dwords
; i
++) {
264 ret
= tb_port_read(port
, &data
, TB_CFG_PORT
, cap
+ offset
+ i
, 1);
266 ret
= tb_sw_read(sw
, &data
, TB_CFG_SWITCH
, cap
+ offset
+ i
, 1);
268 seq_printf(s
, "0x%04x <not accessible>\n", cap
+ offset
+ i
);
272 seq_printf(s
, "0x%04x %4d 0x%02x 0x%02x 0x%08x\n", cap
+ offset
+ i
,
273 offset
+ i
, cap_id
, vsec_id
, data
);
277 static void cap_show(struct seq_file
*s
, struct tb_switch
*sw
,
278 struct tb_port
*port
, unsigned int cap
, u8 cap_id
,
279 u8 vsec_id
, int length
)
284 int i
, dwords
= min(length
, TB_MAX_CONFIG_RW_LENGTH
);
285 u32 data
[TB_MAX_CONFIG_RW_LENGTH
];
288 ret
= tb_port_read(port
, data
, TB_CFG_PORT
, cap
+ offset
,
291 ret
= tb_sw_read(sw
, data
, TB_CFG_SWITCH
, cap
+ offset
, dwords
);
293 cap_show_by_dw(s
, sw
, port
, cap
, offset
, cap_id
, vsec_id
, length
);
297 for (i
= 0; i
< dwords
; i
++) {
298 seq_printf(s
, "0x%04x %4d 0x%02x 0x%02x 0x%08x\n",
299 cap
+ offset
+ i
, offset
+ i
,
300 cap_id
, vsec_id
, data
[i
]);
308 static void port_cap_show(struct tb_port
*port
, struct seq_file
*s
,
311 struct tb_cap_any header
;
316 ret
= tb_port_read(port
, &header
, TB_CFG_PORT
, cap
, 1);
318 seq_printf(s
, "0x%04x <capability read failed>\n", cap
);
322 switch (header
.basic
.cap
) {
323 case TB_PORT_CAP_PHY
:
324 length
= PORT_CAP_LANE_LEN
;
327 case TB_PORT_CAP_TIME1
:
328 length
= PORT_CAP_TMU_LEN
;
331 case TB_PORT_CAP_POWER
:
332 length
= PORT_CAP_POWER_LEN
;
335 case TB_PORT_CAP_ADAP
:
336 if (tb_port_is_pcie_down(port
) || tb_port_is_pcie_up(port
)) {
337 length
= PORT_CAP_PCIE_LEN
;
338 } else if (tb_port_is_dpin(port
) || tb_port_is_dpout(port
)) {
339 length
= PORT_CAP_DP_LEN
;
340 } else if (tb_port_is_usb3_down(port
) ||
341 tb_port_is_usb3_up(port
)) {
342 length
= PORT_CAP_USB3_LEN
;
344 seq_printf(s
, "0x%04x <unsupported capability 0x%02x>\n",
345 cap
, header
.basic
.cap
);
350 case TB_PORT_CAP_VSE
:
351 if (!header
.extended_short
.length
) {
352 ret
= tb_port_read(port
, (u32
*)&header
+ 1, TB_CFG_PORT
,
355 seq_printf(s
, "0x%04x <capability read failed>\n",
359 length
= header
.extended_long
.length
;
360 vsec_id
= header
.extended_short
.vsec_id
;
362 length
= header
.extended_short
.length
;
363 vsec_id
= header
.extended_short
.vsec_id
;
367 case TB_PORT_CAP_USB4
:
368 length
= PORT_CAP_USB4_LEN
;
372 seq_printf(s
, "0x%04x <unsupported capability 0x%02x>\n",
373 cap
, header
.basic
.cap
);
377 cap_show(s
, NULL
, port
, cap
, header
.basic
.cap
, vsec_id
, length
);
380 static void port_caps_show(struct tb_port
*port
, struct seq_file
*s
)
384 cap
= tb_port_next_cap(port
, 0);
386 port_cap_show(port
, s
, cap
);
387 cap
= tb_port_next_cap(port
, cap
);
391 static int port_basic_regs_show(struct tb_port
*port
, struct seq_file
*s
)
393 u32 data
[PORT_CAP_BASIC_LEN
];
396 ret
= tb_port_read(port
, data
, TB_CFG_PORT
, 0, ARRAY_SIZE(data
));
400 for (i
= 0; i
< ARRAY_SIZE(data
); i
++)
401 seq_printf(s
, "0x%04x %4d 0x00 0x00 0x%08x\n", i
, i
, data
[i
]);
406 static int port_regs_show(struct seq_file
*s
, void *not_used
)
408 struct tb_port
*port
= s
->private;
409 struct tb_switch
*sw
= port
->sw
;
410 struct tb
*tb
= sw
->tb
;
413 pm_runtime_get_sync(&sw
->dev
);
415 if (mutex_lock_interruptible(&tb
->lock
)) {
420 seq_puts(s
, "# offset relative_offset cap_id vs_cap_id value\n");
422 ret
= port_basic_regs_show(port
, s
);
426 port_caps_show(port
, s
);
429 mutex_unlock(&tb
->lock
);
431 pm_runtime_mark_last_busy(&sw
->dev
);
432 pm_runtime_put_autosuspend(&sw
->dev
);
436 DEBUGFS_ATTR_RW(port_regs
);
438 static void switch_cap_show(struct tb_switch
*sw
, struct seq_file
*s
,
441 struct tb_cap_any header
;
445 ret
= tb_sw_read(sw
, &header
, TB_CFG_SWITCH
, cap
, 1);
447 seq_printf(s
, "0x%04x <capability read failed>\n", cap
);
451 if (header
.basic
.cap
== TB_SWITCH_CAP_VSE
) {
452 if (!header
.extended_short
.length
) {
453 ret
= tb_sw_read(sw
, (u32
*)&header
+ 1, TB_CFG_SWITCH
,
456 seq_printf(s
, "0x%04x <capability read failed>\n",
460 length
= header
.extended_long
.length
;
462 length
= header
.extended_short
.length
;
464 vsec_id
= header
.extended_short
.vsec_id
;
466 if (header
.basic
.cap
== TB_SWITCH_CAP_TMU
) {
467 length
= SWITCH_CAP_TMU_LEN
;
469 seq_printf(s
, "0x%04x <unknown capability 0x%02x>\n",
470 cap
, header
.basic
.cap
);
475 cap_show(s
, sw
, NULL
, cap
, header
.basic
.cap
, vsec_id
, length
);
478 static void switch_caps_show(struct tb_switch
*sw
, struct seq_file
*s
)
482 cap
= tb_switch_next_cap(sw
, 0);
484 switch_cap_show(sw
, s
, cap
);
485 cap
= tb_switch_next_cap(sw
, cap
);
489 static int switch_basic_regs_show(struct tb_switch
*sw
, struct seq_file
*s
)
491 u32 data
[SWITCH_CAP_BASIC_LEN
];
495 /* Only USB4 has the additional registers */
496 if (tb_switch_is_usb4(sw
))
497 dwords
= ARRAY_SIZE(data
);
501 ret
= tb_sw_read(sw
, data
, TB_CFG_SWITCH
, 0, dwords
);
505 for (i
= 0; i
< dwords
; i
++)
506 seq_printf(s
, "0x%04x %4d 0x00 0x00 0x%08x\n", i
, i
, data
[i
]);
511 static int switch_regs_show(struct seq_file
*s
, void *not_used
)
513 struct tb_switch
*sw
= s
->private;
514 struct tb
*tb
= sw
->tb
;
517 pm_runtime_get_sync(&sw
->dev
);
519 if (mutex_lock_interruptible(&tb
->lock
)) {
524 seq_puts(s
, "# offset relative_offset cap_id vs_cap_id value\n");
526 ret
= switch_basic_regs_show(sw
, s
);
530 switch_caps_show(sw
, s
);
533 mutex_unlock(&tb
->lock
);
535 pm_runtime_mark_last_busy(&sw
->dev
);
536 pm_runtime_put_autosuspend(&sw
->dev
);
540 DEBUGFS_ATTR_RW(switch_regs
);
542 static int path_show_one(struct tb_port
*port
, struct seq_file
*s
, int hopid
)
547 ret
= tb_port_read(port
, data
, TB_CFG_HOPS
, hopid
* PATH_LEN
,
550 seq_printf(s
, "0x%04x <not accessible>\n", hopid
* PATH_LEN
);
554 for (i
= 0; i
< ARRAY_SIZE(data
); i
++) {
555 seq_printf(s
, "0x%04x %4d 0x%02x 0x%08x\n",
556 hopid
* PATH_LEN
+ i
, i
, hopid
, data
[i
]);
562 static int path_show(struct seq_file
*s
, void *not_used
)
564 struct tb_port
*port
= s
->private;
565 struct tb_switch
*sw
= port
->sw
;
566 struct tb
*tb
= sw
->tb
;
567 int start
, i
, ret
= 0;
569 pm_runtime_get_sync(&sw
->dev
);
571 if (mutex_lock_interruptible(&tb
->lock
)) {
576 seq_puts(s
, "# offset relative_offset in_hop_id value\n");
578 /* NHI and lane adapters have entry for path 0 */
579 if (tb_port_is_null(port
) || tb_port_is_nhi(port
)) {
580 ret
= path_show_one(port
, s
, 0);
585 start
= tb_port_is_nhi(port
) ? 1 : TB_PATH_MIN_HOPID
;
587 for (i
= start
; i
<= port
->config
.max_in_hop_id
; i
++) {
588 ret
= path_show_one(port
, s
, i
);
594 mutex_unlock(&tb
->lock
);
596 pm_runtime_mark_last_busy(&sw
->dev
);
597 pm_runtime_put_autosuspend(&sw
->dev
);
601 DEBUGFS_ATTR_RO(path
);
603 static int counter_set_regs_show(struct tb_port
*port
, struct seq_file
*s
,
606 u32 data
[COUNTER_SET_LEN
];
609 ret
= tb_port_read(port
, data
, TB_CFG_COUNTERS
,
610 counter
* COUNTER_SET_LEN
, ARRAY_SIZE(data
));
612 seq_printf(s
, "0x%04x <not accessible>\n",
613 counter
* COUNTER_SET_LEN
);
617 for (i
= 0; i
< ARRAY_SIZE(data
); i
++) {
618 seq_printf(s
, "0x%04x %4d 0x%02x 0x%08x\n",
619 counter
* COUNTER_SET_LEN
+ i
, i
, counter
, data
[i
]);
625 static int counters_show(struct seq_file
*s
, void *not_used
)
627 struct tb_port
*port
= s
->private;
628 struct tb_switch
*sw
= port
->sw
;
629 struct tb
*tb
= sw
->tb
;
632 pm_runtime_get_sync(&sw
->dev
);
634 if (mutex_lock_interruptible(&tb
->lock
)) {
639 seq_puts(s
, "# offset relative_offset counter_id value\n");
641 for (i
= 0; i
< port
->config
.max_counters
; i
++) {
642 ret
= counter_set_regs_show(port
, s
, i
);
647 mutex_unlock(&tb
->lock
);
650 pm_runtime_mark_last_busy(&sw
->dev
);
651 pm_runtime_put_autosuspend(&sw
->dev
);
655 DEBUGFS_ATTR_RW(counters
);
658 * tb_switch_debugfs_init() - Add debugfs entries for router
659 * @sw: Pointer to the router
661 * Adds debugfs directories and files for given router.
663 void tb_switch_debugfs_init(struct tb_switch
*sw
)
665 struct dentry
*debugfs_dir
;
666 struct tb_port
*port
;
668 debugfs_dir
= debugfs_create_dir(dev_name(&sw
->dev
), tb_debugfs_root
);
669 sw
->debugfs_dir
= debugfs_dir
;
670 debugfs_create_file("regs", DEBUGFS_MODE
, debugfs_dir
, sw
,
673 tb_switch_for_each_port(sw
, port
) {
674 struct dentry
*debugfs_dir
;
679 if (port
->config
.type
== TB_TYPE_INACTIVE
)
682 snprintf(dir_name
, sizeof(dir_name
), "port%d", port
->port
);
683 debugfs_dir
= debugfs_create_dir(dir_name
, sw
->debugfs_dir
);
684 debugfs_create_file("regs", DEBUGFS_MODE
, debugfs_dir
,
685 port
, &port_regs_fops
);
686 debugfs_create_file("path", 0400, debugfs_dir
, port
,
688 if (port
->config
.counters_support
)
689 debugfs_create_file("counters", 0600, debugfs_dir
, port
,
695 * tb_switch_debugfs_remove() - Remove all router debugfs entries
696 * @sw: Pointer to the router
698 * Removes all previously added debugfs entries under this router.
700 void tb_switch_debugfs_remove(struct tb_switch
*sw
)
702 debugfs_remove_recursive(sw
->debugfs_dir
);
706 * tb_service_debugfs_init() - Add debugfs directory for service
707 * @svc: Thunderbolt service pointer
709 * Adds debugfs directory for service.
711 void tb_service_debugfs_init(struct tb_service
*svc
)
713 svc
->debugfs_dir
= debugfs_create_dir(dev_name(&svc
->dev
),
718 * tb_service_debugfs_remove() - Remove service debugfs directory
719 * @svc: Thunderbolt service pointer
721 * Removes the previously created debugfs directory for @svc.
723 void tb_service_debugfs_remove(struct tb_service
*svc
)
725 debugfs_remove_recursive(svc
->debugfs_dir
);
726 svc
->debugfs_dir
= NULL
;
729 void tb_debugfs_init(void)
731 tb_debugfs_root
= debugfs_create_dir("thunderbolt", NULL
);
734 void tb_debugfs_exit(void)
736 debugfs_remove_recursive(tb_debugfs_root
);