Skip to content

Commit 43d8470

Browse files
committed
thunderbolt: Expose router DROM through debugfs
Router DROM contains information that might be usable for development and debugging purposes. For example when new entries are added to the USB4 spec it is useful to be able to look for them without need to change the kernel. For this reason expose the DROM through debugfs. Signed-off-by: Mika Westerberg <[email protected]>
1 parent d6d458d commit 43d8470

File tree

3 files changed

+51
-34
lines changed

3 files changed

+51
-34
lines changed

drivers/thunderbolt/debugfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,6 +2413,8 @@ void tb_switch_debugfs_init(struct tb_switch *sw)
24132413
sw->debugfs_dir = debugfs_dir;
24142414
debugfs_create_file("regs", DEBUGFS_MODE, debugfs_dir, sw,
24152415
&switch_regs_fops);
2416+
if (sw->drom)
2417+
debugfs_create_blob("drom", 0400, debugfs_dir, &sw->drom_blob);
24162418

24172419
tb_switch_for_each_port(sw, port) {
24182420
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/tb.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef TB_H_
1010
#define TB_H_
1111

12+
#include <linux/debugfs.h>
1213
#include <linux/nvmem-provider.h>
1314
#include <linux/pci.h>
1415
#include <linux/thunderbolt.h>
@@ -160,6 +161,7 @@ struct tb_switch_tmu {
160161
* @max_pcie_credits: Router preferred number of buffers for PCIe
161162
* @max_dma_credits: Router preferred number of buffers for DMA/P2P
162163
* @clx: CLx states on the upstream link of the router
164+
* @drom_blob: DROM debugfs blob wrapper
163165
*
164166
* When the switch is being added or removed to the domain (other
165167
* switches) you need to have domain lock held.
@@ -212,6 +214,9 @@ struct tb_switch {
212214
unsigned int max_pcie_credits;
213215
unsigned int max_dma_credits;
214216
unsigned int clx;
217+
#ifdef CONFIG_DEBUG_FS
218+
struct debugfs_blob_wrapper drom_blob;
219+
#endif
215220
};
216221

217222
/**

0 commit comments

Comments
 (0)