1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2019, Linaro Limited, All rights reserved.
4 * Author: Mike Leach <mike.leach@linaro.org>
7 #include <linux/device.h>
8 #include <linux/kernel.h>
10 #include "coresight-priv.h"
13 * Connections group - links attribute.
14 * Count of created links between coresight components in the group.
16 static ssize_t
nr_links_show(struct device
*dev
,
17 struct device_attribute
*attr
,
20 struct coresight_device
*csdev
= to_coresight_device(dev
);
22 return sprintf(buf
, "%d\n", csdev
->nr_links
);
24 static DEVICE_ATTR_RO(nr_links
);
26 static struct attribute
*coresight_conns_attrs
[] = {
27 &dev_attr_nr_links
.attr
,
31 static struct attribute_group coresight_conns_group
= {
32 .attrs
= coresight_conns_attrs
,
33 .name
= "connections",
37 * Create connections group for CoreSight devices.
38 * This group will then be used to collate the sysfs links between
41 int coresight_create_conns_sysfs_group(struct coresight_device
*csdev
)
48 ret
= sysfs_create_group(&csdev
->dev
.kobj
, &coresight_conns_group
);
52 csdev
->has_conns_grp
= true;
56 void coresight_remove_conns_sysfs_group(struct coresight_device
*csdev
)
61 if (csdev
->has_conns_grp
) {
62 sysfs_remove_group(&csdev
->dev
.kobj
, &coresight_conns_group
);
63 csdev
->has_conns_grp
= false;
67 int coresight_add_sysfs_link(struct coresight_sysfs_link
*info
)
73 if (!info
->orig
|| !info
->target
||
74 !info
->orig_name
|| !info
->target_name
)
76 if (!info
->orig
->has_conns_grp
|| !info
->target
->has_conns_grp
)
79 /* first link orig->target */
80 ret
= sysfs_add_link_to_group(&info
->orig
->dev
.kobj
,
81 coresight_conns_group
.name
,
82 &info
->target
->dev
.kobj
,
87 /* second link target->orig */
88 ret
= sysfs_add_link_to_group(&info
->target
->dev
.kobj
,
89 coresight_conns_group
.name
,
90 &info
->orig
->dev
.kobj
,
93 /* error in second link - remove first - otherwise inc counts */
95 sysfs_remove_link_from_group(&info
->orig
->dev
.kobj
,
96 coresight_conns_group
.name
,
99 info
->orig
->nr_links
++;
100 info
->target
->nr_links
++;
105 EXPORT_SYMBOL_GPL(coresight_add_sysfs_link
);
107 void coresight_remove_sysfs_link(struct coresight_sysfs_link
*info
)
111 if (!info
->orig
|| !info
->target
||
112 !info
->orig_name
|| !info
->target_name
)
115 sysfs_remove_link_from_group(&info
->orig
->dev
.kobj
,
116 coresight_conns_group
.name
,
119 sysfs_remove_link_from_group(&info
->target
->dev
.kobj
,
120 coresight_conns_group
.name
,
123 info
->orig
->nr_links
--;
124 info
->target
->nr_links
--;
126 EXPORT_SYMBOL_GPL(coresight_remove_sysfs_link
);
129 * coresight_make_links: Make a link for a connection from a @orig
130 * device to @target, represented by @conn.
132 * e.g, for devOrig[output_X] -> devTarget[input_Y] is represented
133 * as two symbolic links :
135 * /sys/.../devOrig/out:X -> /sys/.../devTarget/
136 * /sys/.../devTarget/in:Y -> /sys/.../devOrig/
138 * The link names are allocated for a device where it appears. i.e, the
139 * "out" link on the master and "in" link on the slave device.
140 * The link info is stored in the connection record for avoiding
141 * the reconstruction of names for removal.
143 int coresight_make_links(struct coresight_device
*orig
,
144 struct coresight_connection
*conn
,
145 struct coresight_device
*target
)
148 char *outs
= NULL
, *ins
= NULL
;
149 struct coresight_sysfs_link
*link
= NULL
;
152 outs
= devm_kasprintf(&orig
->dev
, GFP_KERNEL
,
153 "out:%d", conn
->outport
);
156 ins
= devm_kasprintf(&target
->dev
, GFP_KERNEL
,
157 "in:%d", conn
->child_port
);
160 link
= devm_kzalloc(&orig
->dev
,
161 sizeof(struct coresight_sysfs_link
),
167 link
->target
= target
;
168 link
->orig_name
= outs
;
169 link
->target_name
= ins
;
171 ret
= coresight_add_sysfs_link(link
);
178 * Install the device connection. This also indicates that
179 * the links are operational on both ends.
181 conn
->child_dev
= target
;
189 * coresight_remove_links: Remove the sysfs links for a given connection @conn,
190 * from @orig device to @target device. See coresight_make_links() for more
193 void coresight_remove_links(struct coresight_device
*orig
,
194 struct coresight_connection
*conn
)
196 if (!orig
|| !conn
->link
)
199 coresight_remove_sysfs_link(conn
->link
);
201 devm_kfree(&conn
->child_dev
->dev
, conn
->link
->target_name
);
202 devm_kfree(&orig
->dev
, conn
->link
->orig_name
);
203 devm_kfree(&orig
->dev
, conn
->link
);
205 conn
->child_dev
= NULL
;