Skip to content

Commit

Permalink
thunderbolt: debugfs: Add write capability to path config space
Browse files Browse the repository at this point in the history
Currently debugfs interface allows writing of router, adapter and
counters config spaces but not for paths. However, it can be useful
during debugging to modify path config space so for this reason add this
support to the debugfs interface as well.

Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
  • Loading branch information
Gil Fine authored and Mika Westerberg committed Jan 3, 2025
1 parent 4bbf902 commit 398da8e
Showing 1 changed file with 55 additions and 10 deletions.
65 changes: 55 additions & 10 deletions drivers/thunderbolt/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,13 @@ static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len,
* offset relative_offset cap_id vs_cap_id value\n
* v[0] v[1] v[2] v[3] v[4]
*
* For Path configuration space:
* Short format is: offset value\n
* v[0] v[1]
* Long format as produced from the read side:
* offset relative_offset in_hop_id value\n
* v[0] v[1] v[2] v[3]
*
* For Counter configuration space:
* Short format is: offset\n
* v[0]
Expand All @@ -191,14 +198,33 @@ static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len,
}

#if IS_ENABLED(CONFIG_USB4_DEBUGFS_WRITE)
/*
* Path registers need to be written in double word pairs and they both must be
* read before written. This writes one double word in patch config space
* following the spec flow.
*/
static int path_write_one(struct tb_port *port, u32 val, u32 offset)
{
u32 index = offset % PATH_LEN;
u32 offs = offset - index;
u32 data[PATH_LEN];
int ret;

ret = tb_port_read(port, data, TB_CFG_HOPS, offs, PATH_LEN);
if (ret)
return ret;
data[index] = val;
return tb_port_write(port, data, TB_CFG_HOPS, offs, PATH_LEN);
}

static ssize_t regs_write(struct tb_switch *sw, struct tb_port *port,
const char __user *user_buf, size_t count,
loff_t *ppos)
enum tb_cfg_space space, const char __user *user_buf,
size_t count, loff_t *ppos)
{
int long_fmt_len, ret = 0;
struct tb *tb = sw->tb;
char *line, *buf;
u32 val, offset;
int ret = 0;

buf = validate_and_copy_from_user(user_buf, &count);
if (IS_ERR(buf))
Expand All @@ -214,12 +240,21 @@ static ssize_t regs_write(struct tb_switch *sw, struct tb_port *port,
/* User did hardware changes behind the driver's back */
add_taint(TAINT_USER, LOCKDEP_STILL_OK);

if (space == TB_CFG_HOPS)
long_fmt_len = 4;
else
long_fmt_len = 5;

line = buf;
while (parse_line(&line, &offset, &val, 2, 5)) {
if (port)
ret = tb_port_write(port, &val, TB_CFG_PORT, offset, 1);
else
while (parse_line(&line, &offset, &val, 2, long_fmt_len)) {
if (port) {
if (space == TB_CFG_HOPS)
ret = path_write_one(port, val, offset);
else
ret = tb_port_write(port, &val, space, offset, 1);
} else {
ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1);
}
if (ret)
break;
}
Expand All @@ -240,7 +275,16 @@ static ssize_t port_regs_write(struct file *file, const char __user *user_buf,
struct seq_file *s = file->private_data;
struct tb_port *port = s->private;

return regs_write(port->sw, port, user_buf, count, ppos);
return regs_write(port->sw, port, TB_CFG_PORT, user_buf, count, ppos);
}

static ssize_t path_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct tb_port *port = s->private;

return regs_write(port->sw, port, TB_CFG_HOPS, user_buf, count, ppos);
}

static ssize_t switch_regs_write(struct file *file, const char __user *user_buf,
Expand All @@ -249,7 +293,7 @@ static ssize_t switch_regs_write(struct file *file, const char __user *user_buf,
struct seq_file *s = file->private_data;
struct tb_switch *sw = s->private;

return regs_write(sw, NULL, user_buf, count, ppos);
return regs_write(sw, NULL, TB_CFG_SWITCH, user_buf, count, ppos);
}

static bool parse_sb_line(char **line, u8 *reg, u8 *data, size_t data_size,
Expand Down Expand Up @@ -401,6 +445,7 @@ static ssize_t retimer_sb_regs_write(struct file *file,
#define DEBUGFS_MODE 0600
#else
#define port_regs_write NULL
#define path_write NULL
#define switch_regs_write NULL
#define port_sb_regs_write NULL
#define retimer_sb_regs_write NULL
Expand Down Expand Up @@ -2243,7 +2288,7 @@ static int path_show(struct seq_file *s, void *not_used)

return ret;
}
DEBUGFS_ATTR_RO(path);
DEBUGFS_ATTR_RW(path);

static int counter_set_regs_show(struct tb_port *port, struct seq_file *s,
int counter)
Expand Down

0 comments on commit 398da8e

Please sign in to comment.