Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: arm_scmi: Populate a common SCMI debugfs root

Create a common SCMI debugfs root directory and populate it with some
common SCMI data for each discovered SCMI platform instance if SCMI
debugfs is needed by any configured SCMI facility.

Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
Tested-by: Vincent Guittot <vincent.guittot@linaro.org>
Link: https://lore.kernel.org/r/20230118121426.492864-11-cristian.marussi@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

authored by

Cristian Marussi and committed by
Sudeep Holla
c3d4aed7 d60b59b9

+127
+7
drivers/firmware/arm_scmi/Kconfig
··· 23 23 24 24 if ARM_SCMI_PROTOCOL 25 25 26 + config ARM_SCMI_NEED_DEBUGFS 27 + bool 28 + help 29 + This declares whether at least one SCMI facility is configured 30 + which needs debugfs support. When selected causess the creation 31 + of a common SCMI debugfs root directory. 32 + 26 33 config ARM_SCMI_HAVE_TRANSPORT 27 34 bool 28 35 help
+120
drivers/firmware/arm_scmi/driver.c
··· 17 17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 18 18 19 19 #include <linux/bitmap.h> 20 + #include <linux/debugfs.h> 20 21 #include <linux/device.h> 21 22 #include <linux/export.h> 22 23 #include <linux/idr.h> ··· 51 50 static DEFINE_MUTEX(scmi_list_mutex); 52 51 /* Track the unique id for the transfers for debug & profiling purpose */ 53 52 static atomic_t transfer_last_id; 53 + 54 + static struct dentry *scmi_top_dentry; 54 55 55 56 /** 56 57 * struct scmi_xfers_info - Structure to manage transfer information ··· 101 98 #define ph_to_pi(h) container_of(h, struct scmi_protocol_instance, ph) 102 99 103 100 /** 101 + * struct scmi_debug_info - Debug common info 102 + * @top_dentry: A reference to the top debugfs dentry 103 + * @name: Name of this SCMI instance 104 + * @type: Type of this SCMI instance 105 + * @is_atomic: Flag to state if the transport of this instance is atomic 106 + */ 107 + struct scmi_debug_info { 108 + struct dentry *top_dentry; 109 + const char *name; 110 + const char *type; 111 + bool is_atomic; 112 + }; 113 + 114 + /** 104 115 * struct scmi_info - Structure representing a SCMI instance 105 116 * 106 117 * @id: A sequence number starting from zero identifying this instance ··· 149 132 * @dev_req_nb: A notifier to listen for device request/unrequest on the scmi 150 133 * bus 151 134 * @devreq_mtx: A mutex to serialize device creation for this SCMI instance 135 + * @dbg: A pointer to debugfs related data (if any) 152 136 */ 153 137 struct scmi_info { 154 138 int id; ··· 174 156 struct notifier_block dev_req_nb; 175 157 /* Serialize device creation process for this instance */ 176 158 struct mutex devreq_mtx; 159 + struct scmi_debug_info *dbg; 177 160 }; 178 161 179 162 #define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle) ··· 2497 2478 return NOTIFY_OK; 2498 2479 } 2499 2480 2481 + static void scmi_debugfs_common_cleanup(void *d) 2482 + { 2483 + struct scmi_debug_info *dbg = d; 2484 + 2485 + if (!dbg) 2486 + return; 2487 + 2488 + debugfs_remove_recursive(dbg->top_dentry); 2489 + kfree(dbg->name); 2490 + kfree(dbg->type); 2491 + } 2492 + 2493 + static struct scmi_debug_info *scmi_debugfs_common_setup(struct scmi_info *info) 2494 + { 2495 + char top_dir[16]; 2496 + struct dentry *trans, *top_dentry; 2497 + struct scmi_debug_info *dbg; 2498 + const char *c_ptr = NULL; 2499 + 2500 + dbg = devm_kzalloc(info->dev, sizeof(*dbg), GFP_KERNEL); 2501 + if (!dbg) 2502 + return NULL; 2503 + 2504 + dbg->name = kstrdup(of_node_full_name(info->dev->of_node), GFP_KERNEL); 2505 + if (!dbg->name) { 2506 + devm_kfree(info->dev, dbg); 2507 + return NULL; 2508 + } 2509 + 2510 + of_property_read_string(info->dev->of_node, "compatible", &c_ptr); 2511 + dbg->type = kstrdup(c_ptr, GFP_KERNEL); 2512 + if (!dbg->type) { 2513 + kfree(dbg->name); 2514 + devm_kfree(info->dev, dbg); 2515 + return NULL; 2516 + } 2517 + 2518 + snprintf(top_dir, 16, "%d", info->id); 2519 + top_dentry = debugfs_create_dir(top_dir, scmi_top_dentry); 2520 + trans = debugfs_create_dir("transport", top_dentry); 2521 + 2522 + dbg->is_atomic = info->desc->atomic_enabled && 2523 + is_transport_polling_capable(info->desc); 2524 + 2525 + debugfs_create_str("instance_name", 0400, top_dentry, 2526 + (char **)&dbg->name); 2527 + 2528 + debugfs_create_u32("atomic_threshold_us", 0400, top_dentry, 2529 + &info->atomic_threshold); 2530 + 2531 + debugfs_create_str("type", 0400, trans, (char **)&dbg->type); 2532 + 2533 + debugfs_create_bool("is_atomic", 0400, trans, &dbg->is_atomic); 2534 + 2535 + debugfs_create_u32("max_rx_timeout_ms", 0400, trans, 2536 + (u32 *)&info->desc->max_rx_timeout_ms); 2537 + 2538 + debugfs_create_u32("max_msg_size", 0400, trans, 2539 + (u32 *)&info->desc->max_msg_size); 2540 + 2541 + debugfs_create_u32("tx_max_msg", 0400, trans, 2542 + (u32 *)&info->tx_minfo.max_msg); 2543 + 2544 + debugfs_create_u32("rx_max_msg", 0400, trans, 2545 + (u32 *)&info->rx_minfo.max_msg); 2546 + 2547 + dbg->top_dentry = top_dentry; 2548 + 2549 + if (devm_add_action_or_reset(info->dev, 2550 + scmi_debugfs_common_cleanup, dbg)) { 2551 + scmi_debugfs_common_cleanup(dbg); 2552 + return NULL; 2553 + } 2554 + 2555 + return dbg; 2556 + } 2557 + 2500 2558 static int scmi_probe(struct platform_device *pdev) 2501 2559 { 2502 2560 int ret; ··· 2647 2551 ret = scmi_xfer_info_init(info); 2648 2552 if (ret) 2649 2553 goto clear_dev_req_notifier; 2554 + 2555 + if (scmi_top_dentry) { 2556 + info->dbg = scmi_debugfs_common_setup(info); 2557 + if (!info->dbg) 2558 + dev_warn(dev, "Failed to setup SCMI debugfs.\n"); 2559 + } 2650 2560 2651 2561 if (scmi_notification_init(handle)) 2652 2562 dev_err(dev, "SCMI Notifications NOT available.\n"); ··· 2883 2781 __scmi_transports_setup(false); 2884 2782 } 2885 2783 2784 + static struct dentry *scmi_debugfs_init(void) 2785 + { 2786 + struct dentry *d; 2787 + 2788 + d = debugfs_create_dir("scmi", NULL); 2789 + if (IS_ERR(d)) { 2790 + pr_err("Could NOT create SCMI top dentry.\n"); 2791 + return NULL; 2792 + } 2793 + 2794 + return d; 2795 + } 2796 + 2886 2797 static int __init scmi_driver_init(void) 2887 2798 { 2888 2799 int ret; ··· 2908 2793 ret = scmi_transports_init(); 2909 2794 if (ret) 2910 2795 return ret; 2796 + 2797 + if (IS_ENABLED(CONFIG_ARM_SCMI_NEED_DEBUGFS)) 2798 + scmi_top_dentry = scmi_debugfs_init(); 2911 2799 2912 2800 scmi_base_register(); 2913 2801 ··· 2943 2825 scmi_transports_exit(); 2944 2826 2945 2827 platform_driver_unregister(&scmi_driver); 2828 + 2829 + debugfs_remove_recursive(scmi_top_dentry); 2946 2830 } 2947 2831 module_exit(scmi_driver_exit); 2948 2832