Skip to content

Commit 47a836d

Browse files
committed
Merge tag 'thunderbolt-for-v6.14-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-next
Pull Thunderbolt updates from Mika: thunderbolt: Changes for v6.14 merge window This includes following USB4/Thunderbolt changes for the v6.14 merge window: - Add debugfs write capability to path config spaces. - Expose router DROM through debugfs. - Increase DPRX capabilities read timeout to support runtime suspending of graphics driver. - Handle DisplayPort tunnel activation asynchronously. - Small cleanups. All these have been in linux-next with no reported issues. * tag 'thunderbolt-for-v6.14-rc1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt: thunderbolt: Expose router DROM through debugfs thunderbolt: Handle DisplayPort tunnel activation asynchronously thunderbolt: Rework tb_tunnel_consumed_bandwidth() thunderbolt: Move forward declarations in one place thunderbolt: Pass reason to tb_dp_resource_unavailable() thunderbolt: Drop tb_tunnel_restart() thunderbolt: Rework how tunnel->[init|deinit] hooks are called thunderbolt: Show path name in debug log when path is deactivated thunderbolt: Make tb_tunnel_one_dp() return void thunderbolt: Increase DPRX capabilities read timeout thunderbolt: Debug log an invalid config space reply just once thunderbolt: Log config space when invalid config space reply is received thunderbolt: Drop doubled empty line from ctl.h thunderbolt: debugfs: Add write capability to path config space
2 parents 26a6cc1 + 43d8470 commit 47a836d

File tree

10 files changed

+600
-319
lines changed

10 files changed

+600
-319
lines changed

drivers/thunderbolt/ctl.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ struct tb_ctl {
7070
#define tb_ctl_dbg(ctl, format, arg...) \
7171
dev_dbg(&(ctl)->nhi->pdev->dev, format, ## arg)
7272

73+
#define tb_ctl_dbg_once(ctl, format, arg...) \
74+
dev_dbg_once(&(ctl)->nhi->pdev->dev, format, ## arg)
75+
7376
static DECLARE_WAIT_QUEUE_HEAD(tb_cfg_request_cancel_queue);
7477
/* Serializes access to request kref_get/put */
7578
static DEFINE_MUTEX(tb_cfg_request_lock);
@@ -265,7 +268,7 @@ static struct tb_cfg_result parse_header(const struct ctl_pkg *pkg, u32 len,
265268
return res;
266269
}
267270

268-
static void tb_cfg_print_error(struct tb_ctl *ctl,
271+
static void tb_cfg_print_error(struct tb_ctl *ctl, enum tb_cfg_space space,
269272
const struct tb_cfg_result *res)
270273
{
271274
WARN_ON(res->err != 1);
@@ -279,8 +282,8 @@ static void tb_cfg_print_error(struct tb_ctl *ctl,
279282
* Invalid cfg_space/offset/length combination in
280283
* cfg_read/cfg_write.
281284
*/
282-
tb_ctl_dbg(ctl, "%llx:%x: invalid config space or offset\n",
283-
res->response_route, res->response_port);
285+
tb_ctl_dbg_once(ctl, "%llx:%x: invalid config space (%u) or offset\n",
286+
res->response_route, res->response_port, space);
284287
return;
285288
case TB_CFG_ERROR_NO_SUCH_PORT:
286289
/*
@@ -1072,7 +1075,7 @@ static int tb_cfg_get_error(struct tb_ctl *ctl, enum tb_cfg_space space,
10721075
res->tb_error == TB_CFG_ERROR_INVALID_CONFIG_SPACE)
10731076
return -ENODEV;
10741077

1075-
tb_cfg_print_error(ctl, res);
1078+
tb_cfg_print_error(ctl, space, res);
10761079

10771080
if (res->tb_error == TB_CFG_ERROR_LOCK)
10781081
return -EACCES;

drivers/thunderbolt/ctl.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,4 @@ int tb_cfg_write(struct tb_ctl *ctl, const void *buffer, u64 route, u32 port,
140140
enum tb_cfg_space space, u32 offset, u32 length);
141141
int tb_cfg_get_upstream_port(struct tb_ctl *ctl, u64 route);
142142

143-
144143
#endif

drivers/thunderbolt/debugfs.c

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len,
168168
* offset relative_offset cap_id vs_cap_id value\n
169169
* v[0] v[1] v[2] v[3] v[4]
170170
*
171+
* For Path configuration space:
172+
* Short format is: offset value\n
173+
* v[0] v[1]
174+
* Long format as produced from the read side:
175+
* offset relative_offset in_hop_id value\n
176+
* v[0] v[1] v[2] v[3]
177+
*
171178
* For Counter configuration space:
172179
* Short format is: offset\n
173180
* v[0]
@@ -191,14 +198,33 @@ static bool parse_line(char **line, u32 *offs, u32 *val, int short_fmt_len,
191198
}
192199

193200
#if IS_ENABLED(CONFIG_USB4_DEBUGFS_WRITE)
201+
/*
202+
* Path registers need to be written in double word pairs and they both must be
203+
* read before written. This writes one double word in patch config space
204+
* following the spec flow.
205+
*/
206+
static int path_write_one(struct tb_port *port, u32 val, u32 offset)
207+
{
208+
u32 index = offset % PATH_LEN;
209+
u32 offs = offset - index;
210+
u32 data[PATH_LEN];
211+
int ret;
212+
213+
ret = tb_port_read(port, data, TB_CFG_HOPS, offs, PATH_LEN);
214+
if (ret)
215+
return ret;
216+
data[index] = val;
217+
return tb_port_write(port, data, TB_CFG_HOPS, offs, PATH_LEN);
218+
}
219+
194220
static ssize_t regs_write(struct tb_switch *sw, struct tb_port *port,
195-
const char __user *user_buf, size_t count,
196-
loff_t *ppos)
221+
enum tb_cfg_space space, const char __user *user_buf,
222+
size_t count, loff_t *ppos)
197223
{
224+
int long_fmt_len, ret = 0;
198225
struct tb *tb = sw->tb;
199226
char *line, *buf;
200227
u32 val, offset;
201-
int ret = 0;
202228

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

243+
if (space == TB_CFG_HOPS)
244+
long_fmt_len = 4;
245+
else
246+
long_fmt_len = 5;
247+
217248
line = buf;
218-
while (parse_line(&line, &offset, &val, 2, 5)) {
219-
if (port)
220-
ret = tb_port_write(port, &val, TB_CFG_PORT, offset, 1);
221-
else
249+
while (parse_line(&line, &offset, &val, 2, long_fmt_len)) {
250+
if (port) {
251+
if (space == TB_CFG_HOPS)
252+
ret = path_write_one(port, val, offset);
253+
else
254+
ret = tb_port_write(port, &val, space, offset, 1);
255+
} else {
222256
ret = tb_sw_write(sw, &val, TB_CFG_SWITCH, offset, 1);
257+
}
223258
if (ret)
224259
break;
225260
}
@@ -240,7 +275,16 @@ static ssize_t port_regs_write(struct file *file, const char __user *user_buf,
240275
struct seq_file *s = file->private_data;
241276
struct tb_port *port = s->private;
242277

243-
return regs_write(port->sw, port, user_buf, count, ppos);
278+
return regs_write(port->sw, port, TB_CFG_PORT, user_buf, count, ppos);
279+
}
280+
281+
static ssize_t path_write(struct file *file, const char __user *user_buf,
282+
size_t count, loff_t *ppos)
283+
{
284+
struct seq_file *s = file->private_data;
285+
struct tb_port *port = s->private;
286+
287+
return regs_write(port->sw, port, TB_CFG_HOPS, user_buf, count, ppos);
244288
}
245289

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

252-
return regs_write(sw, NULL, user_buf, count, ppos);
296+
return regs_write(sw, NULL, TB_CFG_SWITCH, user_buf, count, ppos);
253297
}
254298

255299
static bool parse_sb_line(char **line, u8 *reg, u8 *data, size_t data_size,
@@ -401,6 +445,7 @@ static ssize_t retimer_sb_regs_write(struct file *file,
401445
#define DEBUGFS_MODE 0600
402446
#else
403447
#define port_regs_write NULL
448+
#define path_write NULL
404449
#define switch_regs_write NULL
405450
#define port_sb_regs_write NULL
406451
#define retimer_sb_regs_write NULL
@@ -2243,7 +2288,7 @@ static int path_show(struct seq_file *s, void *not_used)
22432288

22442289
return ret;
22452290
}
2246-
DEBUGFS_ATTR_RO(path);
2291+
DEBUGFS_ATTR_RW(path);
22472292

22482293
static int counter_set_regs_show(struct tb_port *port, struct seq_file *s,
22492294
int counter)
@@ -2368,6 +2413,8 @@ void tb_switch_debugfs_init(struct tb_switch *sw)
23682413
sw->debugfs_dir = debugfs_dir;
23692414
debugfs_create_file("regs", DEBUGFS_MODE, debugfs_dir, sw,
23702415
&switch_regs_fops);
2416+
if (sw->drom)
2417+
debugfs_create_blob("drom", 0400, debugfs_dir, &sw->drom_blob);
23712418

23722419
tb_switch_for_each_port(sw, port) {
23732420
struct dentry *debugfs_dir;

drivers/thunderbolt/eeprom.c

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,29 @@ static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size)
435435
return 0;
436436
}
437437

438+
static int tb_switch_drom_alloc(struct tb_switch *sw, size_t size)
439+
{
440+
sw->drom = kzalloc(size, GFP_KERNEL);
441+
if (!sw->drom)
442+
return -ENOMEM;
443+
444+
#ifdef CONFIG_DEBUG_FS
445+
sw->drom_blob.data = sw->drom;
446+
sw->drom_blob.size = size;
447+
#endif
448+
return 0;
449+
}
450+
451+
static void tb_switch_drom_free(struct tb_switch *sw)
452+
{
453+
#ifdef CONFIG_DEBUG_FS
454+
sw->drom_blob.data = NULL;
455+
sw->drom_blob.size = 0;
456+
#endif
457+
kfree(sw->drom);
458+
sw->drom = NULL;
459+
}
460+
438461
/*
439462
* tb_drom_copy_efi - copy drom supplied by EFI to sw->drom if present
440463
*/
@@ -447,9 +470,9 @@ static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
447470
if (len < 0 || len < sizeof(struct tb_drom_header))
448471
return -EINVAL;
449472

450-
sw->drom = kmalloc(len, GFP_KERNEL);
451-
if (!sw->drom)
452-
return -ENOMEM;
473+
res = tb_switch_drom_alloc(sw, len);
474+
if (res)
475+
return res;
453476

454477
res = device_property_read_u8_array(dev, "ThunderboltDROM", sw->drom,
455478
len);
@@ -464,8 +487,7 @@ static int tb_drom_copy_efi(struct tb_switch *sw, u16 *size)
464487
return 0;
465488

466489
err:
467-
kfree(sw->drom);
468-
sw->drom = NULL;
490+
tb_switch_drom_free(sw);
469491
return -EINVAL;
470492
}
471493

@@ -491,25 +513,22 @@ static int tb_drom_copy_nvm(struct tb_switch *sw, u16 *size)
491513

492514
/* Size includes CRC8 + UID + CRC32 */
493515
*size += 1 + 8 + 4;
494-
sw->drom = kzalloc(*size, GFP_KERNEL);
495-
if (!sw->drom)
496-
return -ENOMEM;
516+
ret = tb_switch_drom_alloc(sw, *size);
517+
if (ret)
518+
return ret;
497519

498520
ret = dma_port_flash_read(sw->dma_port, drom_offset, sw->drom, *size);
499-
if (ret)
500-
goto err_free;
521+
if (ret) {
522+
tb_switch_drom_free(sw);
523+
return ret;
524+
}
501525

502526
/*
503527
* Read UID from the minimal DROM because the one in NVM is just
504528
* a placeholder.
505529
*/
506530
tb_drom_read_uid_only(sw, &sw->uid);
507531
return 0;
508-
509-
err_free:
510-
kfree(sw->drom);
511-
sw->drom = NULL;
512-
return ret;
513532
}
514533

515534
static int usb4_copy_drom(struct tb_switch *sw, u16 *size)
@@ -522,15 +541,13 @@ static int usb4_copy_drom(struct tb_switch *sw, u16 *size)
522541

523542
/* Size includes CRC8 + UID + CRC32 */
524543
*size += 1 + 8 + 4;
525-
sw->drom = kzalloc(*size, GFP_KERNEL);
526-
if (!sw->drom)
527-
return -ENOMEM;
544+
ret = tb_switch_drom_alloc(sw, *size);
545+
if (ret)
546+
return ret;
528547

529548
ret = usb4_switch_drom_read(sw, 0, sw->drom, *size);
530-
if (ret) {
531-
kfree(sw->drom);
532-
sw->drom = NULL;
533-
}
549+
if (ret)
550+
tb_switch_drom_free(sw);
534551

535552
return ret;
536553
}
@@ -552,19 +569,14 @@ static int tb_drom_bit_bang(struct tb_switch *sw, u16 *size)
552569
return -EIO;
553570
}
554571

555-
sw->drom = kzalloc(*size, GFP_KERNEL);
556-
if (!sw->drom)
557-
return -ENOMEM;
572+
ret = tb_switch_drom_alloc(sw, *size);
573+
if (ret)
574+
return ret;
558575

559576
ret = tb_eeprom_read_n(sw, 0, sw->drom, *size);
560577
if (ret)
561-
goto err;
562-
563-
return 0;
578+
tb_switch_drom_free(sw);
564579

565-
err:
566-
kfree(sw->drom);
567-
sw->drom = NULL;
568580
return ret;
569581
}
570582

@@ -646,9 +658,7 @@ static int tb_drom_parse(struct tb_switch *sw, u16 size)
646658
return 0;
647659

648660
err:
649-
kfree(sw->drom);
650-
sw->drom = NULL;
651-
661+
tb_switch_drom_free(sw);
652662
return ret;
653663
}
654664

drivers/thunderbolt/path.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,10 +581,10 @@ int tb_path_activate(struct tb_path *path)
581581
}
582582
}
583583
path->activated = true;
584-
tb_dbg(path->tb, "path activation complete\n");
584+
tb_dbg(path->tb, "%s path activation complete\n", path->name);
585585
return 0;
586586
err:
587-
tb_WARN(path->tb, "path activation failed\n");
587+
tb_WARN(path->tb, "%s path activation failed\n", path->name);
588588
return res;
589589
}
590590

0 commit comments

Comments
 (0)