Skip to content

Commit 8a7365c

Browse files
Suzuki K Poulosegregkh
authored andcommitted
coresight: Expose device connections via sysfs
Coresight device connections are a bit complicated and is not exposed currently to the user. One has to look at the platform descriptions (DT bindings or ACPI bindings) to make an understanding. Given the new naming scheme, it will be helpful to have this information to choose the appropriate devices for tracing. This patch exposes the device connections via links in the sysfs directories. e.g, for a connection devA[OutputPort_X] -> devB[InputPort_Y] is represented as two symlinks: /sys/bus/coresight/.../devA/out:X -> /sys/bus/coresight/.../devB /sys/bus/coresight/.../devB/in:Y -> /sys/bus/coresight/.../devA Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> [Revised to use the generic sysfs links functions & link structures. Provides a connections sysfs group in each device to hold the links.] Co-developed-by: Mike Leach <mike.leach@linaro.org> Signed-off-by: Mike Leach <mike.leach@linaro.org> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Link: https://lore.kernel.org/r/20200518180242.7916-5-mathieu.poirier@linaro.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8096152 commit 8a7365c

File tree

4 files changed

+121
-12
lines changed

4 files changed

+121
-12
lines changed

drivers/hwtracing/coresight/coresight-priv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ int coresight_add_sysfs_link(struct coresight_sysfs_link *info);
157157
void coresight_remove_sysfs_link(struct coresight_sysfs_link *info);
158158
int coresight_create_conns_sysfs_group(struct coresight_device *csdev);
159159
void coresight_remove_conns_sysfs_group(struct coresight_device *csdev);
160+
int coresight_make_links(struct coresight_device *orig,
161+
struct coresight_connection *conn,
162+
struct coresight_device *target);
163+
void coresight_remove_links(struct coresight_device *orig,
164+
struct coresight_connection *conn);
160165

161166
#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
162167
extern int etm_readl_cp14(u32 off, unsigned int *val);

drivers/hwtracing/coresight/coresight-sysfs.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,83 @@ void coresight_remove_sysfs_link(struct coresight_sysfs_link *info)
122122
info->orig->nr_links--;
123123
info->target->nr_links--;
124124
}
125+
126+
/*
127+
* coresight_make_links: Make a link for a connection from a @orig
128+
* device to @target, represented by @conn.
129+
*
130+
* e.g, for devOrig[output_X] -> devTarget[input_Y] is represented
131+
* as two symbolic links :
132+
*
133+
* /sys/.../devOrig/out:X -> /sys/.../devTarget/
134+
* /sys/.../devTarget/in:Y -> /sys/.../devOrig/
135+
*
136+
* The link names are allocated for a device where it appears. i.e, the
137+
* "out" link on the master and "in" link on the slave device.
138+
* The link info is stored in the connection record for avoiding
139+
* the reconstruction of names for removal.
140+
*/
141+
int coresight_make_links(struct coresight_device *orig,
142+
struct coresight_connection *conn,
143+
struct coresight_device *target)
144+
{
145+
int ret = -ENOMEM;
146+
char *outs = NULL, *ins = NULL;
147+
struct coresight_sysfs_link *link = NULL;
148+
149+
do {
150+
outs = devm_kasprintf(&orig->dev, GFP_KERNEL,
151+
"out:%d", conn->outport);
152+
if (!outs)
153+
break;
154+
ins = devm_kasprintf(&target->dev, GFP_KERNEL,
155+
"in:%d", conn->child_port);
156+
if (!ins)
157+
break;
158+
link = devm_kzalloc(&orig->dev,
159+
sizeof(struct coresight_sysfs_link),
160+
GFP_KERNEL);
161+
if (!link)
162+
break;
163+
164+
link->orig = orig;
165+
link->target = target;
166+
link->orig_name = outs;
167+
link->target_name = ins;
168+
169+
ret = coresight_add_sysfs_link(link);
170+
if (ret)
171+
break;
172+
173+
conn->link = link;
174+
175+
/*
176+
* Install the device connection. This also indicates that
177+
* the links are operational on both ends.
178+
*/
179+
conn->child_dev = target;
180+
return 0;
181+
} while (0);
182+
183+
return ret;
184+
}
185+
186+
/*
187+
* coresight_remove_links: Remove the sysfs links for a given connection @conn,
188+
* from @orig device to @target device. See coresight_make_links() for more
189+
* details.
190+
*/
191+
void coresight_remove_links(struct coresight_device *orig,
192+
struct coresight_connection *conn)
193+
{
194+
if (!orig || !conn->link)
195+
return;
196+
197+
coresight_remove_sysfs_link(conn->link);
198+
199+
devm_kfree(&conn->child_dev->dev, conn->link->target_name);
200+
devm_kfree(&orig->dev, conn->link->orig_name);
201+
devm_kfree(&orig->dev, conn->link);
202+
conn->link = NULL;
203+
conn->child_dev = NULL;
204+
}

drivers/hwtracing/coresight/coresight.c

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ static void coresight_device_release(struct device *dev)
10311031

10321032
static int coresight_orphan_match(struct device *dev, void *data)
10331033
{
1034-
int i;
1034+
int i, ret = 0;
10351035
bool still_orphan = false;
10361036
struct coresight_device *csdev, *i_csdev;
10371037
struct coresight_connection *conn;
@@ -1056,19 +1056,23 @@ static int coresight_orphan_match(struct device *dev, void *data)
10561056
/* We have found at least one orphan connection */
10571057
if (conn->child_dev == NULL) {
10581058
/* Does it match this newly added device? */
1059-
if (conn->child_fwnode == csdev->dev.fwnode)
1060-
conn->child_dev = csdev;
1061-
else
1059+
if (conn->child_fwnode == csdev->dev.fwnode) {
1060+
ret = coresight_make_links(i_csdev,
1061+
conn, csdev);
1062+
if (ret)
1063+
return ret;
1064+
} else {
10621065
/* This component still has an orphan */
10631066
still_orphan = true;
1067+
}
10641068
}
10651069
}
10661070

10671071
i_csdev->orphan = still_orphan;
10681072

10691073
/*
1070-
* Returning '0' ensures that all known component on the
1071-
* bus will be checked.
1074+
* Returning '0' in case we didn't encounter any error,
1075+
* ensures that all known component on the bus will be checked.
10721076
*/
10731077
return 0;
10741078
}
@@ -1082,15 +1086,21 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev)
10821086

10831087
static int coresight_fixup_device_conns(struct coresight_device *csdev)
10841088
{
1085-
int i;
1089+
int i, ret = 0;
10861090

10871091
for (i = 0; i < csdev->pdata->nr_outport; i++) {
10881092
struct coresight_connection *conn = &csdev->pdata->conns[i];
10891093

10901094
conn->child_dev =
10911095
coresight_find_csdev_by_fwnode(conn->child_fwnode);
1092-
if (!conn->child_dev)
1096+
if (conn->child_dev) {
1097+
ret = coresight_make_links(csdev, conn,
1098+
conn->child_dev);
1099+
if (ret)
1100+
break;
1101+
} else {
10931102
csdev->orphan = true;
1103+
}
10941104
}
10951105

10961106
return 0;
@@ -1121,7 +1131,7 @@ static int coresight_remove_match(struct device *dev, void *data)
11211131

11221132
if (csdev->dev.fwnode == conn->child_fwnode) {
11231133
iterator->orphan = true;
1124-
conn->child_dev = NULL;
1134+
coresight_remove_links(iterator, conn);
11251135
/*
11261136
* Drop the reference to the handle for the remote
11271137
* device acquired in parsing the connections from
@@ -1215,13 +1225,23 @@ void coresight_release_platform_data(struct coresight_device *csdev,
12151225
struct coresight_platform_data *pdata)
12161226
{
12171227
int i;
1228+
struct coresight_connection *conns = pdata->conns;
12181229

12191230
for (i = 0; i < pdata->nr_outport; i++) {
1220-
if (pdata->conns[i].child_fwnode) {
1221-
fwnode_handle_put(pdata->conns[i].child_fwnode);
1231+
/* If we have made the links, remove them now */
1232+
if (csdev && conns[i].child_dev)
1233+
coresight_remove_links(csdev, &conns[i]);
1234+
/*
1235+
* Drop the refcount and clear the handle as this device
1236+
* is going away
1237+
*/
1238+
if (conns[i].child_fwnode) {
1239+
fwnode_handle_put(conns[i].child_fwnode);
12221240
pdata->conns[i].child_fwnode = NULL;
12231241
}
12241242
}
1243+
if (csdev)
1244+
coresight_remove_conns_sysfs_group(csdev);
12251245
}
12261246

12271247
struct coresight_device *coresight_register(struct coresight_desc *desc)
@@ -1303,7 +1323,9 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
13031323

13041324
mutex_lock(&coresight_mutex);
13051325

1306-
ret = coresight_fixup_device_conns(csdev);
1326+
ret = coresight_create_conns_sysfs_group(csdev);
1327+
if (!ret)
1328+
ret = coresight_fixup_device_conns(csdev);
13071329
if (!ret)
13081330
ret = coresight_fixup_orphan_conns(csdev);
13091331
if (!ret)

include/linux/coresight.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,14 @@ struct coresight_desc {
140140
* @chid_fwnode: remote component's fwnode handle.
141141
* @child_dev: a @coresight_device representation of the component
142142
connected to @outport.
143+
* @link: Representation of the connection as a sysfs link.
143144
*/
144145
struct coresight_connection {
145146
int outport;
146147
int child_port;
147148
struct fwnode_handle *child_fwnode;
148149
struct coresight_device *child_dev;
150+
struct coresight_sysfs_link *link;
149151
};
150152

151153
/**

0 commit comments

Comments
 (0)