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

coresight: dummy: Add static trace id support for dummy source

Some dummy source has static trace id configured in HW and it cannot
be changed via software programming. Configure the trace id in device
tree and reserve the id when device probe.

Signed-off-by: Mao Jinlong <quic_jinlmao@quicinc.com>
Link: https://lore.kernel.org/r/20241121062829.11571-4-quic_jinlmao@quicinc.com
[ Fix Date and Version to December 2024, v6.14 ]
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>

authored by

Mao Jinlong and committed by
Suzuki K Poulose
f7d74546 fd9b7e8e

+87 -9
+15
Documentation/ABI/testing/sysfs-bus-coresight-devices-dummy-source
··· 1 + What: /sys/bus/coresight/devices/dummy_source<N>/enable_source 2 + Date: Dec 2024 3 + KernelVersion: 6.14 4 + Contact: Mao Jinlong <quic_jinlmao@quicinc.com> 5 + Description: (RW) Enable/disable tracing of dummy source. A sink should be activated 6 + before enabling the source. The path of coresight components linking 7 + the source to the sink is configured and managed automatically by the 8 + coresight framework. 9 + 10 + What: /sys/bus/coresight/devices/dummy_source<N>/traceid 11 + Date: Dec 2024 12 + KernelVersion: 6.14 13 + Contact: Mao Jinlong <quic_jinlmao@quicinc.com> 14 + Description: (R) Show the trace ID that will appear in the trace stream 15 + coming from this trace entity.
+72 -9
drivers/hwtracing/coresight/coresight-dummy.c
··· 11 11 #include <linux/pm_runtime.h> 12 12 13 13 #include "coresight-priv.h" 14 + #include "coresight-trace-id.h" 14 15 15 16 struct dummy_drvdata { 16 17 struct device *dev; 17 18 struct coresight_device *csdev; 19 + u8 traceid; 18 20 }; 19 21 20 22 DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source"); ··· 74 72 .sink_ops = &dummy_sink_ops, 75 73 }; 76 74 75 + /* User can get the trace id of dummy source from this node. */ 76 + static ssize_t traceid_show(struct device *dev, 77 + struct device_attribute *attr, char *buf) 78 + { 79 + unsigned long val; 80 + struct dummy_drvdata *drvdata = dev_get_drvdata(dev->parent); 81 + 82 + val = drvdata->traceid; 83 + return sysfs_emit(buf, "%#lx\n", val); 84 + } 85 + static DEVICE_ATTR_RO(traceid); 86 + 87 + static struct attribute *coresight_dummy_attrs[] = { 88 + &dev_attr_traceid.attr, 89 + NULL, 90 + }; 91 + 92 + static const struct attribute_group coresight_dummy_group = { 93 + .attrs = coresight_dummy_attrs, 94 + }; 95 + 96 + static const struct attribute_group *coresight_dummy_groups[] = { 97 + &coresight_dummy_group, 98 + NULL, 99 + }; 100 + 77 101 static int dummy_probe(struct platform_device *pdev) 78 102 { 79 103 struct device *dev = &pdev->dev; ··· 107 79 struct coresight_platform_data *pdata; 108 80 struct dummy_drvdata *drvdata; 109 81 struct coresight_desc desc = { 0 }; 82 + int ret = 0, trace_id = 0; 83 + 84 + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 85 + if (!drvdata) 86 + return -ENOMEM; 110 87 111 88 if (of_device_is_compatible(node, "arm,coresight-dummy-source")) { 112 89 ··· 123 90 desc.subtype.source_subtype = 124 91 CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS; 125 92 desc.ops = &dummy_source_cs_ops; 93 + desc.groups = coresight_dummy_groups; 94 + 95 + ret = coresight_get_static_trace_id(dev, &trace_id); 96 + if (!ret) { 97 + /* Get the static id if id is set in device tree. */ 98 + ret = coresight_trace_id_get_static_system_id(trace_id); 99 + if (ret < 0) { 100 + dev_err(dev, "Fail to get static id.\n"); 101 + return ret; 102 + } 103 + } else { 104 + /* Get next available id if id is not set in device tree. */ 105 + trace_id = coresight_trace_id_get_system_id(); 106 + if (trace_id < 0) { 107 + ret = trace_id; 108 + return ret; 109 + } 110 + } 111 + drvdata->traceid = (u8)trace_id; 112 + 126 113 } else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) { 127 114 desc.name = coresight_alloc_device_name(&sink_devs, dev); 128 115 if (!desc.name) ··· 157 104 } 158 105 159 106 pdata = coresight_get_platform_data(dev); 160 - if (IS_ERR(pdata)) 161 - return PTR_ERR(pdata); 107 + if (IS_ERR(pdata)) { 108 + ret = PTR_ERR(pdata); 109 + goto free_id; 110 + } 162 111 pdev->dev.platform_data = pdata; 163 - 164 - drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); 165 - if (!drvdata) 166 - return -ENOMEM; 167 112 168 113 drvdata->dev = &pdev->dev; 169 114 platform_set_drvdata(pdev, drvdata); ··· 169 118 desc.pdata = pdev->dev.platform_data; 170 119 desc.dev = &pdev->dev; 171 120 drvdata->csdev = coresight_register(&desc); 172 - if (IS_ERR(drvdata->csdev)) 173 - return PTR_ERR(drvdata->csdev); 121 + if (IS_ERR(drvdata->csdev)) { 122 + ret = PTR_ERR(drvdata->csdev); 123 + goto free_id; 124 + } 174 125 175 126 pm_runtime_enable(dev); 176 127 dev_dbg(dev, "Dummy device initialized\n"); 177 128 178 - return 0; 129 + ret = 0; 130 + goto out; 131 + 132 + free_id: 133 + if (IS_VALID_CS_TRACE_ID(drvdata->traceid)) 134 + coresight_trace_id_put_system_id(drvdata->traceid); 135 + 136 + out: 137 + return ret; 179 138 } 180 139 181 140 static void dummy_remove(struct platform_device *pdev) ··· 193 132 struct dummy_drvdata *drvdata = platform_get_drvdata(pdev); 194 133 struct device *dev = &pdev->dev; 195 134 135 + if (IS_VALID_CS_TRACE_ID(drvdata->traceid)) 136 + coresight_trace_id_put_system_id(drvdata->traceid); 196 137 pm_runtime_disable(dev); 197 138 coresight_unregister(drvdata->csdev); 198 139 }