1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 #include <linux/debugfs.h> 6 #include <linux/interconnect.h> 7 #include <linux/platform_device.h> 8 9 #include "internal.h" 10 11 /* 12 * This can be dangerous, therefore don't provide any real compile time 13 * configuration option for this feature. 14 * People who want to use this will need to modify the source code directly. 15 */ 16 #undef INTERCONNECT_ALLOW_WRITE_DEBUGFS 17 18 #if defined(INTERCONNECT_ALLOW_WRITE_DEBUGFS) && defined(CONFIG_DEBUG_FS) 19 20 static LIST_HEAD(debugfs_paths); 21 static DEFINE_MUTEX(debugfs_lock); 22 23 static struct platform_device *pdev; 24 static struct icc_path *cur_path; 25 26 static char *src_node; 27 static char *dst_node; 28 static u32 avg_bw; 29 static u32 peak_bw; 30 static u32 tag; 31 32 struct debugfs_path { 33 const char *src; 34 const char *dst; 35 struct icc_path *path; 36 struct list_head list; 37 }; 38 39 static struct icc_path *get_path(const char *src, const char *dst) 40 { 41 struct debugfs_path *path; 42 43 list_for_each_entry(path, &debugfs_paths, list) { 44 if (!strcmp(path->src, src) && !strcmp(path->dst, dst)) 45 return path->path; 46 } 47 48 return NULL; 49 } 50 51 static int icc_get_set(void *data, u64 val) 52 { 53 struct debugfs_path *debugfs_path; 54 char *src, *dst; 55 int ret = 0; 56 57 mutex_lock(&debugfs_lock); 58 59 rcu_read_lock(); 60 src = rcu_dereference(src_node); 61 dst = rcu_dereference(dst_node); 62 63 /* 64 * If we've already looked up a path, then use the existing one instead 65 * of calling icc_get() again. This allows for updating previous BW 66 * votes when "get" is written to multiple times for multiple paths. 67 */ 68 cur_path = get_path(src, dst); 69 if (cur_path) { 70 rcu_read_unlock(); 71 goto out; 72 } 73 74 src = kstrdup(src, GFP_ATOMIC); 75 dst = kstrdup(dst, GFP_ATOMIC); 76 rcu_read_unlock(); 77 78 if (!src || !dst) { 79 ret = -ENOMEM; 80 goto err_free; 81 } 82 83 cur_path = icc_get(&pdev->dev, src, dst); 84 if (IS_ERR(cur_path)) { 85 ret = PTR_ERR(cur_path); 86 goto err_free; 87 } 88 89 debugfs_path = kzalloc(sizeof(*debugfs_path), GFP_KERNEL); 90 if (!debugfs_path) { 91 ret = -ENOMEM; 92 goto err_put; 93 } 94 95 debugfs_path->path = cur_path; 96 debugfs_path->src = src; 97 debugfs_path->dst = dst; 98 list_add_tail(&debugfs_path->list, &debugfs_paths); 99 100 goto out; 101 102 err_put: 103 icc_put(cur_path); 104 err_free: 105 kfree(src); 106 kfree(dst); 107 out: 108 mutex_unlock(&debugfs_lock); 109 return ret; 110 } 111 112 DEFINE_DEBUGFS_ATTRIBUTE(icc_get_fops, NULL, icc_get_set, "%llu\n"); 113 114 static int icc_commit_set(void *data, u64 val) 115 { 116 int ret; 117 118 mutex_lock(&debugfs_lock); 119 120 if (IS_ERR_OR_NULL(cur_path)) { 121 ret = PTR_ERR(cur_path); 122 goto out; 123 } 124 125 icc_set_tag(cur_path, tag); 126 ret = icc_set_bw(cur_path, avg_bw, peak_bw); 127 out: 128 mutex_unlock(&debugfs_lock); 129 return ret; 130 } 131 132 DEFINE_DEBUGFS_ATTRIBUTE(icc_commit_fops, NULL, icc_commit_set, "%llu\n"); 133 134 int icc_debugfs_client_init(struct dentry *icc_dir) 135 { 136 struct dentry *client_dir; 137 int ret; 138 139 pdev = platform_device_alloc("icc-debugfs-client", PLATFORM_DEVID_NONE); 140 141 ret = platform_device_add(pdev); 142 if (ret) { 143 pr_err("%s: failed to add platform device: %d\n", __func__, ret); 144 platform_device_put(pdev); 145 return ret; 146 } 147 148 client_dir = debugfs_create_dir("test_client", icc_dir); 149 150 debugfs_create_str("src_node", 0600, client_dir, &src_node); 151 debugfs_create_str("dst_node", 0600, client_dir, &dst_node); 152 debugfs_create_file("get", 0200, client_dir, NULL, &icc_get_fops); 153 debugfs_create_u32("avg_bw", 0600, client_dir, &avg_bw); 154 debugfs_create_u32("peak_bw", 0600, client_dir, &peak_bw); 155 debugfs_create_u32("tag", 0600, client_dir, &tag); 156 debugfs_create_file("commit", 0200, client_dir, NULL, &icc_commit_fops); 157 158 return 0; 159 } 160 161 #else 162 163 int icc_debugfs_client_init(struct dentry *icc_dir) 164 { 165 return 0; 166 } 167 168 #endif 169