diff options
Diffstat (limited to 'drivers/hwtracing/coresight/coresight-sysfs.c')
-rw-r--r-- | drivers/hwtracing/coresight/coresight-sysfs.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c new file mode 100644 index 000000000000..6759f78733ab --- /dev/null +++ b/drivers/hwtracing/coresight/coresight-sysfs.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Linaro Limited, All rights reserved. + * Author: Mike Leach <mike.leach@linaro.org> + */ + +#include <linux/device.h> +#include <linux/kernel.h> + +#include "coresight-priv.h" + +/* + * Connections group - links attribute. + * Count of created links between coresight components in the group. + */ +static ssize_t nr_links_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct coresight_device *csdev = to_coresight_device(dev); + + return sprintf(buf, "%d\n", csdev->nr_links); +} +static DEVICE_ATTR_RO(nr_links); + +static struct attribute *coresight_conns_attrs[] = { + &dev_attr_nr_links.attr, + NULL, +}; + +static struct attribute_group coresight_conns_group = { + .attrs = coresight_conns_attrs, + .name = "connections", +}; + +/* + * Create connections group for CoreSight devices. + * This group will then be used to collate the sysfs links between + * devices. + */ +int coresight_create_conns_sysfs_group(struct coresight_device *csdev) +{ + int ret = 0; + + if (!csdev) + return -EINVAL; + + ret = sysfs_create_group(&csdev->dev.kobj, &coresight_conns_group); + if (ret) + return ret; + + csdev->has_conns_grp = true; + return ret; +} + +void coresight_remove_conns_sysfs_group(struct coresight_device *csdev) +{ + if (!csdev) + return; + + if (csdev->has_conns_grp) { + sysfs_remove_group(&csdev->dev.kobj, &coresight_conns_group); + csdev->has_conns_grp = false; + } +} + +int coresight_add_sysfs_link(struct coresight_sysfs_link *info) +{ + int ret = 0; + + if (!info) + return -EINVAL; + if (!info->orig || !info->target || + !info->orig_name || !info->target_name) + return -EINVAL; + if (!info->orig->has_conns_grp || !info->target->has_conns_grp) + return -EINVAL; + + /* first link orig->target */ + ret = sysfs_add_link_to_group(&info->orig->dev.kobj, + coresight_conns_group.name, + &info->target->dev.kobj, + info->orig_name); + if (ret) + return ret; + + /* second link target->orig */ + ret = sysfs_add_link_to_group(&info->target->dev.kobj, + coresight_conns_group.name, + &info->orig->dev.kobj, + info->target_name); + + /* error in second link - remove first - otherwise inc counts */ + if (ret) { + sysfs_remove_link_from_group(&info->orig->dev.kobj, + coresight_conns_group.name, + info->orig_name); + } else { + info->orig->nr_links++; + info->target->nr_links++; + } + + return ret; +} + +void coresight_remove_sysfs_link(struct coresight_sysfs_link *info) +{ + if (!info) + return; + if (!info->orig || !info->target || + !info->orig_name || !info->target_name) + return; + + sysfs_remove_link_from_group(&info->orig->dev.kobj, + coresight_conns_group.name, + info->orig_name); + + sysfs_remove_link_from_group(&info->target->dev.kobj, + coresight_conns_group.name, + info->target_name); + + info->orig->nr_links--; + info->target->nr_links--; +} |