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

rio-sysfs.c (7924B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * RapidIO sysfs attributes and support
      4 *
      5 * Copyright 2005 MontaVista Software, Inc.
      6 * Matt Porter <mporter@kernel.crashing.org>
      7 */
      8
      9#include <linux/kernel.h>
     10#include <linux/rio.h>
     11#include <linux/rio_drv.h>
     12#include <linux/stat.h>
     13#include <linux/capability.h>
     14
     15#include "rio.h"
     16
     17/* Sysfs support */
     18#define rio_config_attr(field, format_string)					\
     19static ssize_t								\
     20field##_show(struct device *dev, struct device_attribute *attr, char *buf)			\
     21{									\
     22	struct rio_dev *rdev = to_rio_dev(dev);				\
     23									\
     24	return sprintf(buf, format_string, rdev->field);		\
     25}									\
     26static DEVICE_ATTR_RO(field);
     27
     28rio_config_attr(did, "0x%04x\n");
     29rio_config_attr(vid, "0x%04x\n");
     30rio_config_attr(device_rev, "0x%08x\n");
     31rio_config_attr(asm_did, "0x%04x\n");
     32rio_config_attr(asm_vid, "0x%04x\n");
     33rio_config_attr(asm_rev, "0x%04x\n");
     34rio_config_attr(destid, "0x%04x\n");
     35rio_config_attr(hopcount, "0x%02x\n");
     36
     37static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf)
     38{
     39	struct rio_dev *rdev = to_rio_dev(dev);
     40	char *str = buf;
     41	int i;
     42
     43	for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
     44			i++) {
     45		if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
     46			continue;
     47		str +=
     48		    sprintf(str, "%04x %02x\n", i,
     49			    rdev->rswitch->route_table[i]);
     50	}
     51
     52	return (str - buf);
     53}
     54static DEVICE_ATTR_RO(routes);
     55
     56static ssize_t lprev_show(struct device *dev,
     57			  struct device_attribute *attr, char *buf)
     58{
     59	struct rio_dev *rdev = to_rio_dev(dev);
     60
     61	return sprintf(buf, "%s\n",
     62			(rdev->prev) ? rio_name(rdev->prev) : "root");
     63}
     64static DEVICE_ATTR_RO(lprev);
     65
     66static ssize_t lnext_show(struct device *dev,
     67			  struct device_attribute *attr, char *buf)
     68{
     69	struct rio_dev *rdev = to_rio_dev(dev);
     70	char *str = buf;
     71	int i;
     72
     73	if (rdev->pef & RIO_PEF_SWITCH) {
     74		for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) {
     75			if (rdev->rswitch->nextdev[i])
     76				str += sprintf(str, "%s\n",
     77					rio_name(rdev->rswitch->nextdev[i]));
     78			else
     79				str += sprintf(str, "null\n");
     80		}
     81	}
     82
     83	return str - buf;
     84}
     85static DEVICE_ATTR_RO(lnext);
     86
     87static ssize_t modalias_show(struct device *dev,
     88			     struct device_attribute *attr, char *buf)
     89{
     90	struct rio_dev *rdev = to_rio_dev(dev);
     91
     92	return sprintf(buf, "rapidio:v%04Xd%04Xav%04Xad%04X\n",
     93		       rdev->vid, rdev->did, rdev->asm_vid, rdev->asm_did);
     94}
     95static DEVICE_ATTR_RO(modalias);
     96
     97static struct attribute *rio_dev_attrs[] = {
     98	&dev_attr_did.attr,
     99	&dev_attr_vid.attr,
    100	&dev_attr_device_rev.attr,
    101	&dev_attr_asm_did.attr,
    102	&dev_attr_asm_vid.attr,
    103	&dev_attr_asm_rev.attr,
    104	&dev_attr_lprev.attr,
    105	&dev_attr_destid.attr,
    106	&dev_attr_modalias.attr,
    107
    108	/* Switch-only attributes */
    109	&dev_attr_routes.attr,
    110	&dev_attr_lnext.attr,
    111	&dev_attr_hopcount.attr,
    112	NULL,
    113};
    114
    115static ssize_t
    116rio_read_config(struct file *filp, struct kobject *kobj,
    117		struct bin_attribute *bin_attr,
    118		char *buf, loff_t off, size_t count)
    119{
    120	struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
    121	unsigned int size = 0x100;
    122	loff_t init_off = off;
    123	u8 *data = (u8 *) buf;
    124
    125	/* Several chips lock up trying to read undefined config space */
    126	if (capable(CAP_SYS_ADMIN))
    127		size = RIO_MAINT_SPACE_SZ;
    128
    129	if (off >= size)
    130		return 0;
    131	if (off + count > size) {
    132		size -= off;
    133		count = size;
    134	} else {
    135		size = count;
    136	}
    137
    138	if ((off & 1) && size) {
    139		u8 val;
    140		rio_read_config_8(dev, off, &val);
    141		data[off - init_off] = val;
    142		off++;
    143		size--;
    144	}
    145
    146	if ((off & 3) && size > 2) {
    147		u16 val;
    148		rio_read_config_16(dev, off, &val);
    149		data[off - init_off] = (val >> 8) & 0xff;
    150		data[off - init_off + 1] = val & 0xff;
    151		off += 2;
    152		size -= 2;
    153	}
    154
    155	while (size > 3) {
    156		u32 val;
    157		rio_read_config_32(dev, off, &val);
    158		data[off - init_off] = (val >> 24) & 0xff;
    159		data[off - init_off + 1] = (val >> 16) & 0xff;
    160		data[off - init_off + 2] = (val >> 8) & 0xff;
    161		data[off - init_off + 3] = val & 0xff;
    162		off += 4;
    163		size -= 4;
    164	}
    165
    166	if (size >= 2) {
    167		u16 val;
    168		rio_read_config_16(dev, off, &val);
    169		data[off - init_off] = (val >> 8) & 0xff;
    170		data[off - init_off + 1] = val & 0xff;
    171		off += 2;
    172		size -= 2;
    173	}
    174
    175	if (size > 0) {
    176		u8 val;
    177		rio_read_config_8(dev, off, &val);
    178		data[off - init_off] = val;
    179		off++;
    180		--size;
    181	}
    182
    183	return count;
    184}
    185
    186static ssize_t
    187rio_write_config(struct file *filp, struct kobject *kobj,
    188		 struct bin_attribute *bin_attr,
    189		 char *buf, loff_t off, size_t count)
    190{
    191	struct rio_dev *dev = to_rio_dev(kobj_to_dev(kobj));
    192	unsigned int size = count;
    193	loff_t init_off = off;
    194	u8 *data = (u8 *) buf;
    195
    196	if (off >= RIO_MAINT_SPACE_SZ)
    197		return 0;
    198	if (off + count > RIO_MAINT_SPACE_SZ) {
    199		size = RIO_MAINT_SPACE_SZ - off;
    200		count = size;
    201	}
    202
    203	if ((off & 1) && size) {
    204		rio_write_config_8(dev, off, data[off - init_off]);
    205		off++;
    206		size--;
    207	}
    208
    209	if ((off & 3) && (size > 2)) {
    210		u16 val = data[off - init_off + 1];
    211		val |= (u16) data[off - init_off] << 8;
    212		rio_write_config_16(dev, off, val);
    213		off += 2;
    214		size -= 2;
    215	}
    216
    217	while (size > 3) {
    218		u32 val = data[off - init_off + 3];
    219		val |= (u32) data[off - init_off + 2] << 8;
    220		val |= (u32) data[off - init_off + 1] << 16;
    221		val |= (u32) data[off - init_off] << 24;
    222		rio_write_config_32(dev, off, val);
    223		off += 4;
    224		size -= 4;
    225	}
    226
    227	if (size >= 2) {
    228		u16 val = data[off - init_off + 1];
    229		val |= (u16) data[off - init_off] << 8;
    230		rio_write_config_16(dev, off, val);
    231		off += 2;
    232		size -= 2;
    233	}
    234
    235	if (size) {
    236		rio_write_config_8(dev, off, data[off - init_off]);
    237		off++;
    238		--size;
    239	}
    240
    241	return count;
    242}
    243
    244static struct bin_attribute rio_config_attr = {
    245	.attr = {
    246		 .name = "config",
    247		 .mode = S_IRUGO | S_IWUSR,
    248		 },
    249	.size = RIO_MAINT_SPACE_SZ,
    250	.read = rio_read_config,
    251	.write = rio_write_config,
    252};
    253
    254static struct bin_attribute *rio_dev_bin_attrs[] = {
    255	&rio_config_attr,
    256	NULL,
    257};
    258
    259static umode_t rio_dev_is_attr_visible(struct kobject *kobj,
    260				       struct attribute *attr, int n)
    261{
    262	struct rio_dev *rdev = to_rio_dev(kobj_to_dev(kobj));
    263	umode_t mode = attr->mode;
    264
    265	if (!(rdev->pef & RIO_PEF_SWITCH) &&
    266	    (attr == &dev_attr_routes.attr ||
    267	     attr == &dev_attr_lnext.attr ||
    268	     attr == &dev_attr_hopcount.attr)) {
    269		/*
    270		 * Hide switch-specific attributes for a non-switch device.
    271		 */
    272		mode = 0;
    273	}
    274
    275	return mode;
    276}
    277
    278static const struct attribute_group rio_dev_group = {
    279	.attrs		= rio_dev_attrs,
    280	.is_visible	= rio_dev_is_attr_visible,
    281	.bin_attrs	= rio_dev_bin_attrs,
    282};
    283
    284const struct attribute_group *rio_dev_groups[] = {
    285	&rio_dev_group,
    286	NULL,
    287};
    288
    289static ssize_t scan_store(struct bus_type *bus, const char *buf, size_t count)
    290{
    291	long val;
    292	int rc;
    293
    294	if (kstrtol(buf, 0, &val) < 0)
    295		return -EINVAL;
    296
    297	if (val == RIO_MPORT_ANY) {
    298		rc = rio_init_mports();
    299		goto exit;
    300	}
    301
    302	if (val < 0 || val >= RIO_MAX_MPORTS)
    303		return -EINVAL;
    304
    305	rc = rio_mport_scan((int)val);
    306exit:
    307	if (!rc)
    308		rc = count;
    309
    310	return rc;
    311}
    312static BUS_ATTR_WO(scan);
    313
    314static struct attribute *rio_bus_attrs[] = {
    315	&bus_attr_scan.attr,
    316	NULL,
    317};
    318
    319static const struct attribute_group rio_bus_group = {
    320	.attrs = rio_bus_attrs,
    321};
    322
    323const struct attribute_group *rio_bus_groups[] = {
    324	&rio_bus_group,
    325	NULL,
    326};
    327
    328static ssize_t
    329port_destid_show(struct device *dev, struct device_attribute *attr,
    330		 char *buf)
    331{
    332	struct rio_mport *mport = to_rio_mport(dev);
    333
    334	if (mport)
    335		return sprintf(buf, "0x%04x\n", mport->host_deviceid);
    336	else
    337		return -ENODEV;
    338}
    339static DEVICE_ATTR_RO(port_destid);
    340
    341static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr,
    342			   char *buf)
    343{
    344	struct rio_mport *mport = to_rio_mport(dev);
    345
    346	if (mport)
    347		return sprintf(buf, "%u\n", mport->sys_size);
    348	else
    349		return -ENODEV;
    350}
    351static DEVICE_ATTR_RO(sys_size);
    352
    353static struct attribute *rio_mport_attrs[] = {
    354	&dev_attr_port_destid.attr,
    355	&dev_attr_sys_size.attr,
    356	NULL,
    357};
    358
    359static const struct attribute_group rio_mport_group = {
    360	.attrs = rio_mport_attrs,
    361};
    362
    363const struct attribute_group *rio_mport_groups[] = {
    364	&rio_mport_group,
    365	NULL,
    366};