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

device_sysfs.c (16519B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.
      4 *
      5 * Copyright (C) 2015, Intel Corp.
      6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
      7 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
      8 *
      9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     10 *
     11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     12 */
     13
     14#include <linux/acpi.h>
     15#include <linux/device.h>
     16#include <linux/export.h>
     17#include <linux/nls.h>
     18
     19#include "internal.h"
     20
     21static ssize_t acpi_object_path(acpi_handle handle, char *buf)
     22{
     23	struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
     24	int result;
     25
     26	result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path);
     27	if (result)
     28		return result;
     29
     30	result = sprintf(buf, "%s\n", (char *)path.pointer);
     31	kfree(path.pointer);
     32	return result;
     33}
     34
     35struct acpi_data_node_attr {
     36	struct attribute attr;
     37	ssize_t (*show)(struct acpi_data_node *, char *);
     38	ssize_t (*store)(struct acpi_data_node *, const char *, size_t count);
     39};
     40
     41#define DATA_NODE_ATTR(_name)			\
     42	static struct acpi_data_node_attr data_node_##_name =	\
     43		__ATTR(_name, 0444, data_node_show_##_name, NULL)
     44
     45static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf)
     46{
     47	return dn->handle ? acpi_object_path(dn->handle, buf) : 0;
     48}
     49
     50DATA_NODE_ATTR(path);
     51
     52static struct attribute *acpi_data_node_default_attrs[] = {
     53	&data_node_path.attr,
     54	NULL
     55};
     56ATTRIBUTE_GROUPS(acpi_data_node_default);
     57
     58#define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
     59#define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)
     60
     61static ssize_t acpi_data_node_attr_show(struct kobject *kobj,
     62					struct attribute *attr, char *buf)
     63{
     64	struct acpi_data_node *dn = to_data_node(kobj);
     65	struct acpi_data_node_attr *dn_attr = to_attr(attr);
     66
     67	return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO;
     68}
     69
     70static const struct sysfs_ops acpi_data_node_sysfs_ops = {
     71	.show	= acpi_data_node_attr_show,
     72};
     73
     74static void acpi_data_node_release(struct kobject *kobj)
     75{
     76	struct acpi_data_node *dn = to_data_node(kobj);
     77
     78	complete(&dn->kobj_done);
     79}
     80
     81static struct kobj_type acpi_data_node_ktype = {
     82	.sysfs_ops = &acpi_data_node_sysfs_ops,
     83	.default_groups = acpi_data_node_default_groups,
     84	.release = acpi_data_node_release,
     85};
     86
     87static void acpi_expose_nondev_subnodes(struct kobject *kobj,
     88					struct acpi_device_data *data)
     89{
     90	struct list_head *list = &data->subnodes;
     91	struct acpi_data_node *dn;
     92
     93	if (list_empty(list))
     94		return;
     95
     96	list_for_each_entry(dn, list, sibling) {
     97		int ret;
     98
     99		init_completion(&dn->kobj_done);
    100		ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
    101					   kobj, "%s", dn->name);
    102		if (!ret)
    103			acpi_expose_nondev_subnodes(&dn->kobj, &dn->data);
    104		else if (dn->handle)
    105			acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
    106	}
    107}
    108
    109static void acpi_hide_nondev_subnodes(struct acpi_device_data *data)
    110{
    111	struct list_head *list = &data->subnodes;
    112	struct acpi_data_node *dn;
    113
    114	if (list_empty(list))
    115		return;
    116
    117	list_for_each_entry_reverse(dn, list, sibling) {
    118		acpi_hide_nondev_subnodes(&dn->data);
    119		kobject_put(&dn->kobj);
    120	}
    121}
    122
    123/**
    124 * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
    125 * @acpi_dev: ACPI device object.
    126 * @modalias: Buffer to print into.
    127 * @size: Size of the buffer.
    128 *
    129 * Creates hid/cid(s) string needed for modalias and uevent
    130 * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
    131 * char *modalias: "acpi:IBM0001:ACPI0001"
    132 * Return: 0: no _HID and no _CID
    133 *         -EINVAL: output error
    134 *         -ENOMEM: output is truncated
    135 */
    136static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
    137			       int size)
    138{
    139	int len;
    140	int count;
    141	struct acpi_hardware_id *id;
    142
    143	/* Avoid unnecessarily loading modules for non present devices. */
    144	if (!acpi_device_is_present(acpi_dev))
    145		return 0;
    146
    147	/*
    148	 * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
    149	 * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
    150	 * device's list.
    151	 */
    152	count = 0;
    153	list_for_each_entry(id, &acpi_dev->pnp.ids, list)
    154		if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
    155			count++;
    156
    157	if (!count)
    158		return 0;
    159
    160	len = snprintf(modalias, size, "acpi:");
    161	if (len <= 0)
    162		return len;
    163
    164	size -= len;
    165
    166	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
    167		if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
    168			continue;
    169
    170		count = snprintf(&modalias[len], size, "%s:", id->id);
    171		if (count < 0)
    172			return -EINVAL;
    173
    174		if (count >= size)
    175			return -ENOMEM;
    176
    177		len += count;
    178		size -= count;
    179	}
    180	modalias[len] = '\0';
    181	return len;
    182}
    183
    184/**
    185 * create_of_modalias - Creates DT compatible string for modalias and uevent
    186 * @acpi_dev: ACPI device object.
    187 * @modalias: Buffer to print into.
    188 * @size: Size of the buffer.
    189 *
    190 * Expose DT compatible modalias as of:NnameTCcompatible.  This function should
    191 * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
    192 * ACPI/PNP IDs.
    193 */
    194static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
    195			      int size)
    196{
    197	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
    198	const union acpi_object *of_compatible, *obj;
    199	acpi_status status;
    200	int len, count;
    201	int i, nval;
    202	char *c;
    203
    204	status = acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
    205	if (ACPI_FAILURE(status))
    206		return -ENODEV;
    207
    208	/* DT strings are all in lower case */
    209	for (c = buf.pointer; *c != '\0'; c++)
    210		*c = tolower(*c);
    211
    212	len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
    213	ACPI_FREE(buf.pointer);
    214
    215	if (len <= 0)
    216		return len;
    217
    218	of_compatible = acpi_dev->data.of_compatible;
    219	if (of_compatible->type == ACPI_TYPE_PACKAGE) {
    220		nval = of_compatible->package.count;
    221		obj = of_compatible->package.elements;
    222	} else { /* Must be ACPI_TYPE_STRING. */
    223		nval = 1;
    224		obj = of_compatible;
    225	}
    226	for (i = 0; i < nval; i++, obj++) {
    227		count = snprintf(&modalias[len], size, "C%s",
    228				 obj->string.pointer);
    229		if (count < 0)
    230			return -EINVAL;
    231
    232		if (count >= size)
    233			return -ENOMEM;
    234
    235		len += count;
    236		size -= count;
    237	}
    238	modalias[len] = '\0';
    239	return len;
    240}
    241
    242int __acpi_device_uevent_modalias(struct acpi_device *adev,
    243				  struct kobj_uevent_env *env)
    244{
    245	int len;
    246
    247	if (!adev)
    248		return -ENODEV;
    249
    250	if (list_empty(&adev->pnp.ids))
    251		return 0;
    252
    253	if (add_uevent_var(env, "MODALIAS="))
    254		return -ENOMEM;
    255
    256	if (adev->data.of_compatible)
    257		len = create_of_modalias(adev, &env->buf[env->buflen - 1],
    258					 sizeof(env->buf) - env->buflen);
    259	else
    260		len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
    261					  sizeof(env->buf) - env->buflen);
    262	if (len < 0)
    263		return len;
    264
    265	env->buflen += len;
    266
    267	return 0;
    268}
    269
    270/**
    271 * acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.
    272 * @dev: Struct device to get ACPI device node.
    273 * @env: Environment variables of the kobject uevent.
    274 *
    275 * Create the uevent modalias field for ACPI-enumerated devices.
    276 *
    277 * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
    278 * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
    279 */
    280int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
    281{
    282	return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
    283}
    284EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
    285
    286static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
    287{
    288	int len, count;
    289
    290	if (!adev)
    291		return -ENODEV;
    292
    293	if (list_empty(&adev->pnp.ids))
    294		return 0;
    295
    296	len = create_pnp_modalias(adev, buf, size - 1);
    297	if (len < 0) {
    298		return len;
    299	} else if (len > 0) {
    300		buf[len++] = '\n';
    301		size -= len;
    302	}
    303	if (!adev->data.of_compatible)
    304		return len;
    305
    306	count = create_of_modalias(adev, buf + len, size - 1);
    307	if (count < 0) {
    308		return count;
    309	} else if (count > 0) {
    310		len += count;
    311		buf[len++] = '\n';
    312	}
    313
    314	return len;
    315}
    316
    317/**
    318 * acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.
    319 * @dev: Struct device to get ACPI device node.
    320 * @buf: The buffer to save pnp_modalias and of_modalias.
    321 * @size: Size of buffer.
    322 *
    323 * Create the modalias sysfs attribute for ACPI-enumerated devices.
    324 *
    325 * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
    326 * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
    327 */
    328int acpi_device_modalias(struct device *dev, char *buf, int size)
    329{
    330	return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
    331}
    332EXPORT_SYMBOL_GPL(acpi_device_modalias);
    333
    334static ssize_t
    335modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
    336{
    337	return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
    338}
    339static DEVICE_ATTR_RO(modalias);
    340
    341static ssize_t real_power_state_show(struct device *dev,
    342				     struct device_attribute *attr, char *buf)
    343{
    344	struct acpi_device *adev = to_acpi_device(dev);
    345	int state;
    346	int ret;
    347
    348	ret = acpi_device_get_power(adev, &state);
    349	if (ret)
    350		return ret;
    351
    352	return sprintf(buf, "%s\n", acpi_power_state_string(state));
    353}
    354
    355static DEVICE_ATTR_RO(real_power_state);
    356
    357static ssize_t power_state_show(struct device *dev,
    358				struct device_attribute *attr, char *buf)
    359{
    360	struct acpi_device *adev = to_acpi_device(dev);
    361
    362	return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
    363}
    364
    365static DEVICE_ATTR_RO(power_state);
    366
    367static ssize_t
    368eject_store(struct device *d, struct device_attribute *attr,
    369	    const char *buf, size_t count)
    370{
    371	struct acpi_device *acpi_device = to_acpi_device(d);
    372	acpi_object_type not_used;
    373	acpi_status status;
    374
    375	if (!count || buf[0] != '1')
    376		return -EINVAL;
    377
    378	if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
    379	    && !acpi_device->driver)
    380		return -ENODEV;
    381
    382	status = acpi_get_type(acpi_device->handle, &not_used);
    383	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
    384		return -ENODEV;
    385
    386	acpi_dev_get(acpi_device);
    387	status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
    388	if (ACPI_SUCCESS(status))
    389		return count;
    390
    391	acpi_dev_put(acpi_device);
    392	acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
    393			  ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
    394	return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
    395}
    396
    397static DEVICE_ATTR_WO(eject);
    398
    399static ssize_t
    400hid_show(struct device *dev, struct device_attribute *attr, char *buf)
    401{
    402	struct acpi_device *acpi_dev = to_acpi_device(dev);
    403
    404	return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
    405}
    406static DEVICE_ATTR_RO(hid);
    407
    408static ssize_t uid_show(struct device *dev,
    409			struct device_attribute *attr, char *buf)
    410{
    411	struct acpi_device *acpi_dev = to_acpi_device(dev);
    412
    413	return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
    414}
    415static DEVICE_ATTR_RO(uid);
    416
    417static ssize_t adr_show(struct device *dev,
    418			struct device_attribute *attr, char *buf)
    419{
    420	struct acpi_device *acpi_dev = to_acpi_device(dev);
    421
    422	if (acpi_dev->pnp.bus_address > U32_MAX)
    423		return sprintf(buf, "0x%016llx\n", acpi_dev->pnp.bus_address);
    424	else
    425		return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
    426}
    427static DEVICE_ATTR_RO(adr);
    428
    429static ssize_t path_show(struct device *dev,
    430			 struct device_attribute *attr, char *buf)
    431{
    432	struct acpi_device *acpi_dev = to_acpi_device(dev);
    433
    434	return acpi_object_path(acpi_dev->handle, buf);
    435}
    436static DEVICE_ATTR_RO(path);
    437
    438/* sysfs file that shows description text from the ACPI _STR method */
    439static ssize_t description_show(struct device *dev,
    440				struct device_attribute *attr,
    441				char *buf)
    442{
    443	struct acpi_device *acpi_dev = to_acpi_device(dev);
    444	int result;
    445
    446	if (acpi_dev->pnp.str_obj == NULL)
    447		return 0;
    448
    449	/*
    450	 * The _STR object contains a Unicode identifier for a device.
    451	 * We need to convert to utf-8 so it can be displayed.
    452	 */
    453	result = utf16s_to_utf8s(
    454		(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
    455		acpi_dev->pnp.str_obj->buffer.length,
    456		UTF16_LITTLE_ENDIAN, buf,
    457		PAGE_SIZE - 1);
    458
    459	buf[result++] = '\n';
    460
    461	return result;
    462}
    463static DEVICE_ATTR_RO(description);
    464
    465static ssize_t
    466sun_show(struct device *dev, struct device_attribute *attr,
    467	 char *buf)
    468{
    469	struct acpi_device *acpi_dev = to_acpi_device(dev);
    470	acpi_status status;
    471	unsigned long long sun;
    472
    473	status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
    474	if (ACPI_FAILURE(status))
    475		return -EIO;
    476
    477	return sprintf(buf, "%llu\n", sun);
    478}
    479static DEVICE_ATTR_RO(sun);
    480
    481static ssize_t
    482hrv_show(struct device *dev, struct device_attribute *attr,
    483	 char *buf)
    484{
    485	struct acpi_device *acpi_dev = to_acpi_device(dev);
    486	acpi_status status;
    487	unsigned long long hrv;
    488
    489	status = acpi_evaluate_integer(acpi_dev->handle, "_HRV", NULL, &hrv);
    490	if (ACPI_FAILURE(status))
    491		return -EIO;
    492
    493	return sprintf(buf, "%llu\n", hrv);
    494}
    495static DEVICE_ATTR_RO(hrv);
    496
    497static ssize_t status_show(struct device *dev, struct device_attribute *attr,
    498				char *buf)
    499{
    500	struct acpi_device *acpi_dev = to_acpi_device(dev);
    501	acpi_status status;
    502	unsigned long long sta;
    503
    504	status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
    505	if (ACPI_FAILURE(status))
    506		return -EIO;
    507
    508	return sprintf(buf, "%llu\n", sta);
    509}
    510static DEVICE_ATTR_RO(status);
    511
    512/**
    513 * acpi_device_setup_files - Create sysfs attributes of an ACPI device.
    514 * @dev: ACPI device object.
    515 */
    516int acpi_device_setup_files(struct acpi_device *dev)
    517{
    518	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
    519	acpi_status status;
    520	int result = 0;
    521
    522	/*
    523	 * Devices gotten from FADT don't have a "path" attribute
    524	 */
    525	if (dev->handle) {
    526		result = device_create_file(&dev->dev, &dev_attr_path);
    527		if (result)
    528			goto end;
    529	}
    530
    531	if (!list_empty(&dev->pnp.ids)) {
    532		result = device_create_file(&dev->dev, &dev_attr_hid);
    533		if (result)
    534			goto end;
    535
    536		result = device_create_file(&dev->dev, &dev_attr_modalias);
    537		if (result)
    538			goto end;
    539	}
    540
    541	/*
    542	 * If device has _STR, 'description' file is created
    543	 */
    544	if (acpi_has_method(dev->handle, "_STR")) {
    545		status = acpi_evaluate_object(dev->handle, "_STR",
    546					NULL, &buffer);
    547		if (ACPI_FAILURE(status))
    548			buffer.pointer = NULL;
    549		dev->pnp.str_obj = buffer.pointer;
    550		result = device_create_file(&dev->dev, &dev_attr_description);
    551		if (result)
    552			goto end;
    553	}
    554
    555	if (dev->pnp.type.bus_address)
    556		result = device_create_file(&dev->dev, &dev_attr_adr);
    557	if (dev->pnp.unique_id)
    558		result = device_create_file(&dev->dev, &dev_attr_uid);
    559
    560	if (acpi_has_method(dev->handle, "_SUN")) {
    561		result = device_create_file(&dev->dev, &dev_attr_sun);
    562		if (result)
    563			goto end;
    564	}
    565
    566	if (acpi_has_method(dev->handle, "_HRV")) {
    567		result = device_create_file(&dev->dev, &dev_attr_hrv);
    568		if (result)
    569			goto end;
    570	}
    571
    572	if (acpi_has_method(dev->handle, "_STA")) {
    573		result = device_create_file(&dev->dev, &dev_attr_status);
    574		if (result)
    575			goto end;
    576	}
    577
    578	/*
    579	 * If device has _EJ0, 'eject' file is created that is used to trigger
    580	 * hot-removal function from userland.
    581	 */
    582	if (acpi_has_method(dev->handle, "_EJ0")) {
    583		result = device_create_file(&dev->dev, &dev_attr_eject);
    584		if (result)
    585			return result;
    586	}
    587
    588	if (dev->flags.power_manageable) {
    589		result = device_create_file(&dev->dev, &dev_attr_power_state);
    590		if (result)
    591			return result;
    592
    593		if (dev->power.flags.power_resources)
    594			result = device_create_file(&dev->dev,
    595						    &dev_attr_real_power_state);
    596	}
    597
    598	acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
    599
    600end:
    601	return result;
    602}
    603
    604/**
    605 * acpi_device_remove_files - Remove sysfs attributes of an ACPI device.
    606 * @dev: ACPI device object.
    607 */
    608void acpi_device_remove_files(struct acpi_device *dev)
    609{
    610	acpi_hide_nondev_subnodes(&dev->data);
    611
    612	if (dev->flags.power_manageable) {
    613		device_remove_file(&dev->dev, &dev_attr_power_state);
    614		if (dev->power.flags.power_resources)
    615			device_remove_file(&dev->dev,
    616					   &dev_attr_real_power_state);
    617	}
    618
    619	/*
    620	 * If device has _STR, remove 'description' file
    621	 */
    622	if (acpi_has_method(dev->handle, "_STR")) {
    623		kfree(dev->pnp.str_obj);
    624		device_remove_file(&dev->dev, &dev_attr_description);
    625	}
    626	/*
    627	 * If device has _EJ0, remove 'eject' file.
    628	 */
    629	if (acpi_has_method(dev->handle, "_EJ0"))
    630		device_remove_file(&dev->dev, &dev_attr_eject);
    631
    632	if (acpi_has_method(dev->handle, "_SUN"))
    633		device_remove_file(&dev->dev, &dev_attr_sun);
    634
    635	if (acpi_has_method(dev->handle, "_HRV"))
    636		device_remove_file(&dev->dev, &dev_attr_hrv);
    637
    638	if (dev->pnp.unique_id)
    639		device_remove_file(&dev->dev, &dev_attr_uid);
    640	if (dev->pnp.type.bus_address)
    641		device_remove_file(&dev->dev, &dev_attr_adr);
    642	device_remove_file(&dev->dev, &dev_attr_modalias);
    643	device_remove_file(&dev->dev, &dev_attr_hid);
    644	if (acpi_has_method(dev->handle, "_STA"))
    645		device_remove_file(&dev->dev, &dev_attr_status);
    646	if (dev->handle)
    647		device_remove_file(&dev->dev, &dev_attr_path);
    648}