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