cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

coresight-sysfs.c (5051B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2019, Linaro Limited, All rights reserved.
      4 * Author: Mike Leach <mike.leach@linaro.org>
      5 */
      6
      7#include <linux/device.h>
      8#include <linux/kernel.h>
      9
     10#include "coresight-priv.h"
     11
     12/*
     13 * Connections group - links attribute.
     14 * Count of created links between coresight components in the group.
     15 */
     16static ssize_t nr_links_show(struct device *dev,
     17			     struct device_attribute *attr,
     18			     char *buf)
     19{
     20	struct coresight_device *csdev = to_coresight_device(dev);
     21
     22	return sprintf(buf, "%d\n", csdev->nr_links);
     23}
     24static DEVICE_ATTR_RO(nr_links);
     25
     26static struct attribute *coresight_conns_attrs[] = {
     27	&dev_attr_nr_links.attr,
     28	NULL,
     29};
     30
     31static struct attribute_group coresight_conns_group = {
     32	.attrs = coresight_conns_attrs,
     33	.name = "connections",
     34};
     35
     36/*
     37 * Create connections group for CoreSight devices.
     38 * This group will then be used to collate the sysfs links between
     39 * devices.
     40 */
     41int coresight_create_conns_sysfs_group(struct coresight_device *csdev)
     42{
     43	int ret = 0;
     44
     45	if (!csdev)
     46		return -EINVAL;
     47
     48	ret = sysfs_create_group(&csdev->dev.kobj, &coresight_conns_group);
     49	if (ret)
     50		return ret;
     51
     52	csdev->has_conns_grp = true;
     53	return ret;
     54}
     55
     56void coresight_remove_conns_sysfs_group(struct coresight_device *csdev)
     57{
     58	if (!csdev)
     59		return;
     60
     61	if (csdev->has_conns_grp) {
     62		sysfs_remove_group(&csdev->dev.kobj, &coresight_conns_group);
     63		csdev->has_conns_grp = false;
     64	}
     65}
     66
     67int coresight_add_sysfs_link(struct coresight_sysfs_link *info)
     68{
     69	int ret = 0;
     70
     71	if (!info)
     72		return -EINVAL;
     73	if (!info->orig || !info->target ||
     74	    !info->orig_name || !info->target_name)
     75		return -EINVAL;
     76	if (!info->orig->has_conns_grp || !info->target->has_conns_grp)
     77		return -EINVAL;
     78
     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,
     83				      info->orig_name);
     84	if (ret)
     85		return ret;
     86
     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,
     91				      info->target_name);
     92
     93	/* error in second link - remove first - otherwise inc counts */
     94	if (ret) {
     95		sysfs_remove_link_from_group(&info->orig->dev.kobj,
     96					     coresight_conns_group.name,
     97					     info->orig_name);
     98	} else {
     99		info->orig->nr_links++;
    100		info->target->nr_links++;
    101	}
    102
    103	return ret;
    104}
    105EXPORT_SYMBOL_GPL(coresight_add_sysfs_link);
    106
    107void coresight_remove_sysfs_link(struct coresight_sysfs_link *info)
    108{
    109	if (!info)
    110		return;
    111	if (!info->orig || !info->target ||
    112	    !info->orig_name || !info->target_name)
    113		return;
    114
    115	sysfs_remove_link_from_group(&info->orig->dev.kobj,
    116				     coresight_conns_group.name,
    117				     info->orig_name);
    118
    119	sysfs_remove_link_from_group(&info->target->dev.kobj,
    120				     coresight_conns_group.name,
    121				     info->target_name);
    122
    123	info->orig->nr_links--;
    124	info->target->nr_links--;
    125}
    126EXPORT_SYMBOL_GPL(coresight_remove_sysfs_link);
    127
    128/*
    129 * coresight_make_links: Make a link for a connection from a @orig
    130 * device to @target, represented by @conn.
    131 *
    132 *   e.g, for devOrig[output_X] -> devTarget[input_Y] is represented
    133 *   as two symbolic links :
    134 *
    135 *	/sys/.../devOrig/out:X	-> /sys/.../devTarget/
    136 *	/sys/.../devTarget/in:Y	-> /sys/.../devOrig/
    137 *
    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.
    142 */
    143int coresight_make_links(struct coresight_device *orig,
    144			 struct coresight_connection *conn,
    145			 struct coresight_device *target)
    146{
    147	int ret = -ENOMEM;
    148	char *outs = NULL, *ins = NULL;
    149	struct coresight_sysfs_link *link = NULL;
    150
    151	do {
    152		outs = devm_kasprintf(&orig->dev, GFP_KERNEL,
    153				      "out:%d", conn->outport);
    154		if (!outs)
    155			break;
    156		ins = devm_kasprintf(&target->dev, GFP_KERNEL,
    157				     "in:%d", conn->child_port);
    158		if (!ins)
    159			break;
    160		link = devm_kzalloc(&orig->dev,
    161				    sizeof(struct coresight_sysfs_link),
    162				    GFP_KERNEL);
    163		if (!link)
    164			break;
    165
    166		link->orig = orig;
    167		link->target = target;
    168		link->orig_name = outs;
    169		link->target_name = ins;
    170
    171		ret = coresight_add_sysfs_link(link);
    172		if (ret)
    173			break;
    174
    175		conn->link = link;
    176
    177		/*
    178		 * Install the device connection. This also indicates that
    179		 * the links are operational on both ends.
    180		 */
    181		conn->child_dev = target;
    182		return 0;
    183	} while (0);
    184
    185	return ret;
    186}
    187
    188/*
    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
    191 * details.
    192 */
    193void coresight_remove_links(struct coresight_device *orig,
    194			    struct coresight_connection *conn)
    195{
    196	if (!orig || !conn->link)
    197		return;
    198
    199	coresight_remove_sysfs_link(conn->link);
    200
    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);
    204	conn->link = NULL;
    205	conn->child_dev = NULL;
    206}