xref: /openbmc/linux/drivers/acpi/device_sysfs.c (revision 60c874a7)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c2efefb3SRafael J. Wysocki /*
3c2efefb3SRafael J. Wysocki  * drivers/acpi/device_sysfs.c - ACPI device sysfs attributes and modalias.
4c2efefb3SRafael J. Wysocki  *
5c2efefb3SRafael J. Wysocki  * Copyright (C) 2015, Intel Corp.
6c2efefb3SRafael J. Wysocki  * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
7c2efefb3SRafael J. Wysocki  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
8c2efefb3SRafael J. Wysocki  *
9c2efefb3SRafael J. Wysocki  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10c2efefb3SRafael J. Wysocki  *
11c2efefb3SRafael J. Wysocki  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12c2efefb3SRafael J. Wysocki  */
13c2efefb3SRafael J. Wysocki 
14c2efefb3SRafael J. Wysocki #include <linux/acpi.h>
15c2efefb3SRafael J. Wysocki #include <linux/device.h>
16c2efefb3SRafael J. Wysocki #include <linux/export.h>
17c2efefb3SRafael J. Wysocki #include <linux/nls.h>
18c2efefb3SRafael J. Wysocki 
19c2efefb3SRafael J. Wysocki #include "internal.h"
20c2efefb3SRafael J. Wysocki 
acpi_object_path(acpi_handle handle,char * buf)21263b4c1aSRafael J. Wysocki static ssize_t acpi_object_path(acpi_handle handle, char *buf)
22263b4c1aSRafael J. Wysocki {
23263b4c1aSRafael J. Wysocki 	struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
24263b4c1aSRafael J. Wysocki 	int result;
25263b4c1aSRafael J. Wysocki 
26263b4c1aSRafael J. Wysocki 	result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path);
27263b4c1aSRafael J. Wysocki 	if (result)
28263b4c1aSRafael J. Wysocki 		return result;
29263b4c1aSRafael J. Wysocki 
30263b4c1aSRafael J. Wysocki 	result = sprintf(buf, "%s\n", (char *)path.pointer);
31263b4c1aSRafael J. Wysocki 	kfree(path.pointer);
32263b4c1aSRafael J. Wysocki 	return result;
33263b4c1aSRafael J. Wysocki }
34263b4c1aSRafael J. Wysocki 
35263b4c1aSRafael J. Wysocki struct acpi_data_node_attr {
36263b4c1aSRafael J. Wysocki 	struct attribute attr;
37263b4c1aSRafael J. Wysocki 	ssize_t (*show)(struct acpi_data_node *, char *);
38263b4c1aSRafael J. Wysocki 	ssize_t (*store)(struct acpi_data_node *, const char *, size_t count);
39263b4c1aSRafael J. Wysocki };
40263b4c1aSRafael J. Wysocki 
41263b4c1aSRafael J. Wysocki #define DATA_NODE_ATTR(_name)			\
42263b4c1aSRafael J. Wysocki 	static struct acpi_data_node_attr data_node_##_name =	\
43263b4c1aSRafael J. Wysocki 		__ATTR(_name, 0444, data_node_show_##_name, NULL)
44263b4c1aSRafael J. Wysocki 
data_node_show_path(struct acpi_data_node * dn,char * buf)45263b4c1aSRafael J. Wysocki static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf)
46263b4c1aSRafael J. Wysocki {
4799db5ff7SRafael J. Wysocki 	return dn->handle ? acpi_object_path(dn->handle, buf) : 0;
48263b4c1aSRafael J. Wysocki }
49263b4c1aSRafael J. Wysocki 
50263b4c1aSRafael J. Wysocki DATA_NODE_ATTR(path);
51263b4c1aSRafael J. Wysocki 
52263b4c1aSRafael J. Wysocki static struct attribute *acpi_data_node_default_attrs[] = {
53263b4c1aSRafael J. Wysocki 	&data_node_path.attr,
54263b4c1aSRafael J. Wysocki 	NULL
55263b4c1aSRafael J. Wysocki };
5617f18417SGreg Kroah-Hartman ATTRIBUTE_GROUPS(acpi_data_node_default);
57263b4c1aSRafael J. Wysocki 
58263b4c1aSRafael J. Wysocki #define to_data_node(k) container_of(k, struct acpi_data_node, kobj)
59263b4c1aSRafael J. Wysocki #define to_attr(a) container_of(a, struct acpi_data_node_attr, attr)
60263b4c1aSRafael J. Wysocki 
acpi_data_node_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)61263b4c1aSRafael J. Wysocki static ssize_t acpi_data_node_attr_show(struct kobject *kobj,
62263b4c1aSRafael J. Wysocki 					struct attribute *attr, char *buf)
63263b4c1aSRafael J. Wysocki {
64263b4c1aSRafael J. Wysocki 	struct acpi_data_node *dn = to_data_node(kobj);
65263b4c1aSRafael J. Wysocki 	struct acpi_data_node_attr *dn_attr = to_attr(attr);
66263b4c1aSRafael J. Wysocki 
67263b4c1aSRafael J. Wysocki 	return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO;
68263b4c1aSRafael J. Wysocki }
69263b4c1aSRafael J. Wysocki 
70263b4c1aSRafael J. Wysocki static const struct sysfs_ops acpi_data_node_sysfs_ops = {
71263b4c1aSRafael J. Wysocki 	.show	= acpi_data_node_attr_show,
72263b4c1aSRafael J. Wysocki };
73263b4c1aSRafael J. Wysocki 
acpi_data_node_release(struct kobject * kobj)74263b4c1aSRafael J. Wysocki static void acpi_data_node_release(struct kobject *kobj)
75263b4c1aSRafael J. Wysocki {
76263b4c1aSRafael J. Wysocki 	struct acpi_data_node *dn = to_data_node(kobj);
77d0fb66e9SXiaofei Tan 
78263b4c1aSRafael J. Wysocki 	complete(&dn->kobj_done);
79263b4c1aSRafael J. Wysocki }
80263b4c1aSRafael J. Wysocki 
81a527b011SThomas Weißschuh static const struct kobj_type acpi_data_node_ktype = {
82263b4c1aSRafael J. Wysocki 	.sysfs_ops = &acpi_data_node_sysfs_ops,
8317f18417SGreg Kroah-Hartman 	.default_groups = acpi_data_node_default_groups,
84263b4c1aSRafael J. Wysocki 	.release = acpi_data_node_release,
85263b4c1aSRafael J. Wysocki };
86263b4c1aSRafael J. Wysocki 
acpi_expose_nondev_subnodes(struct kobject * kobj,struct acpi_device_data * data)87263b4c1aSRafael J. Wysocki static void acpi_expose_nondev_subnodes(struct kobject *kobj,
88263b4c1aSRafael J. Wysocki 					struct acpi_device_data *data)
89263b4c1aSRafael J. Wysocki {
90263b4c1aSRafael J. Wysocki 	struct list_head *list = &data->subnodes;
91263b4c1aSRafael J. Wysocki 	struct acpi_data_node *dn;
92263b4c1aSRafael J. Wysocki 
93263b4c1aSRafael J. Wysocki 	if (list_empty(list))
94263b4c1aSRafael J. Wysocki 		return;
95263b4c1aSRafael J. Wysocki 
96263b4c1aSRafael J. Wysocki 	list_for_each_entry(dn, list, sibling) {
97263b4c1aSRafael J. Wysocki 		int ret;
98263b4c1aSRafael J. Wysocki 
99263b4c1aSRafael J. Wysocki 		init_completion(&dn->kobj_done);
100263b4c1aSRafael J. Wysocki 		ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
1019db22d92SKees Cook 					   kobj, "%s", dn->name);
10299db5ff7SRafael J. Wysocki 		if (!ret)
103263b4c1aSRafael J. Wysocki 			acpi_expose_nondev_subnodes(&dn->kobj, &dn->data);
10499db5ff7SRafael J. Wysocki 		else if (dn->handle)
10599db5ff7SRafael J. Wysocki 			acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
106263b4c1aSRafael J. Wysocki 	}
107263b4c1aSRafael J. Wysocki }
108263b4c1aSRafael J. Wysocki 
acpi_hide_nondev_subnodes(struct acpi_device_data * data)109263b4c1aSRafael J. Wysocki static void acpi_hide_nondev_subnodes(struct acpi_device_data *data)
110263b4c1aSRafael J. Wysocki {
111263b4c1aSRafael J. Wysocki 	struct list_head *list = &data->subnodes;
112263b4c1aSRafael J. Wysocki 	struct acpi_data_node *dn;
113263b4c1aSRafael J. Wysocki 
114263b4c1aSRafael J. Wysocki 	if (list_empty(list))
115263b4c1aSRafael J. Wysocki 		return;
116263b4c1aSRafael J. Wysocki 
117263b4c1aSRafael J. Wysocki 	list_for_each_entry_reverse(dn, list, sibling) {
118263b4c1aSRafael J. Wysocki 		acpi_hide_nondev_subnodes(&dn->data);
119263b4c1aSRafael J. Wysocki 		kobject_put(&dn->kobj);
120263b4c1aSRafael J. Wysocki 	}
121263b4c1aSRafael J. Wysocki }
122263b4c1aSRafael J. Wysocki 
123c2efefb3SRafael J. Wysocki /**
124c2efefb3SRafael J. Wysocki  * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
125c2efefb3SRafael J. Wysocki  * @acpi_dev: ACPI device object.
126c2efefb3SRafael J. Wysocki  * @modalias: Buffer to print into.
127c2efefb3SRafael J. Wysocki  * @size: Size of the buffer.
128c2efefb3SRafael J. Wysocki  *
129c2efefb3SRafael J. Wysocki  * Creates hid/cid(s) string needed for modalias and uevent
130c2efefb3SRafael J. Wysocki  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
131c2efefb3SRafael J. Wysocki  * char *modalias: "acpi:IBM0001:ACPI0001"
132c2efefb3SRafael J. Wysocki  * Return: 0: no _HID and no _CID
133c2efefb3SRafael J. Wysocki  *         -EINVAL: output error
134c2efefb3SRafael J. Wysocki  *         -ENOMEM: output is truncated
135c2efefb3SRafael J. Wysocki  */
create_pnp_modalias(const struct acpi_device * acpi_dev,char * modalias,int size)136162736b0SGreg Kroah-Hartman static int create_pnp_modalias(const struct acpi_device *acpi_dev, char *modalias,
137c2efefb3SRafael J. Wysocki 			       int size)
138c2efefb3SRafael J. Wysocki {
139c2efefb3SRafael J. Wysocki 	int len;
140c2efefb3SRafael J. Wysocki 	int count;
141c2efefb3SRafael J. Wysocki 	struct acpi_hardware_id *id;
142c2efefb3SRafael J. Wysocki 
14310809bb9SHans de Goede 	/* Avoid unnecessarily loading modules for non present devices. */
14410809bb9SHans de Goede 	if (!acpi_device_is_present(acpi_dev))
14510809bb9SHans de Goede 		return 0;
14610809bb9SHans de Goede 
147c2efefb3SRafael J. Wysocki 	/*
148c2efefb3SRafael J. Wysocki 	 * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
149c2efefb3SRafael J. Wysocki 	 * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
150c2efefb3SRafael J. Wysocki 	 * device's list.
151c2efefb3SRafael J. Wysocki 	 */
152c2efefb3SRafael J. Wysocki 	count = 0;
153c2efefb3SRafael J. Wysocki 	list_for_each_entry(id, &acpi_dev->pnp.ids, list)
154c2efefb3SRafael J. Wysocki 		if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
155c2efefb3SRafael J. Wysocki 			count++;
156c2efefb3SRafael J. Wysocki 
157c2efefb3SRafael J. Wysocki 	if (!count)
158c2efefb3SRafael J. Wysocki 		return 0;
159c2efefb3SRafael J. Wysocki 
160c2efefb3SRafael J. Wysocki 	len = snprintf(modalias, size, "acpi:");
161*60c874a7SChristophe JAILLET 	if (len >= size)
162*60c874a7SChristophe JAILLET 		return -ENOMEM;
163c2efefb3SRafael J. Wysocki 
164c2efefb3SRafael J. Wysocki 	size -= len;
165c2efefb3SRafael J. Wysocki 
166c2efefb3SRafael J. Wysocki 	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
167c2efefb3SRafael J. Wysocki 		if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
168c2efefb3SRafael J. Wysocki 			continue;
169c2efefb3SRafael J. Wysocki 
170c2efefb3SRafael J. Wysocki 		count = snprintf(&modalias[len], size, "%s:", id->id);
171c2efefb3SRafael J. Wysocki 		if (count < 0)
172c2efefb3SRafael J. Wysocki 			return -EINVAL;
173c2efefb3SRafael J. Wysocki 
174c2efefb3SRafael J. Wysocki 		if (count >= size)
175c2efefb3SRafael J. Wysocki 			return -ENOMEM;
176c2efefb3SRafael J. Wysocki 
177c2efefb3SRafael J. Wysocki 		len += count;
178c2efefb3SRafael J. Wysocki 		size -= count;
179c2efefb3SRafael J. Wysocki 	}
180c2efefb3SRafael J. Wysocki 	modalias[len] = '\0';
181c2efefb3SRafael J. Wysocki 	return len;
182c2efefb3SRafael J. Wysocki }
183c2efefb3SRafael J. Wysocki 
184c2efefb3SRafael J. Wysocki /**
185c2efefb3SRafael J. Wysocki  * create_of_modalias - Creates DT compatible string for modalias and uevent
186c2efefb3SRafael J. Wysocki  * @acpi_dev: ACPI device object.
187c2efefb3SRafael J. Wysocki  * @modalias: Buffer to print into.
188c2efefb3SRafael J. Wysocki  * @size: Size of the buffer.
189c2efefb3SRafael J. Wysocki  *
190c2efefb3SRafael J. Wysocki  * Expose DT compatible modalias as of:NnameTCcompatible.  This function should
191c2efefb3SRafael J. Wysocki  * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
192c2efefb3SRafael J. Wysocki  * ACPI/PNP IDs.
193c2efefb3SRafael J. Wysocki  */
create_of_modalias(const struct acpi_device * acpi_dev,char * modalias,int size)194162736b0SGreg Kroah-Hartman static int create_of_modalias(const struct acpi_device *acpi_dev, char *modalias,
195c2efefb3SRafael J. Wysocki 			      int size)
196c2efefb3SRafael J. Wysocki {
197c2efefb3SRafael J. Wysocki 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
198c2efefb3SRafael J. Wysocki 	const union acpi_object *of_compatible, *obj;
199f16eb8a4SAndy Shevchenko 	acpi_status status;
200c2efefb3SRafael J. Wysocki 	int len, count;
201c2efefb3SRafael J. Wysocki 	int i, nval;
202c2efefb3SRafael J. Wysocki 	char *c;
203c2efefb3SRafael J. Wysocki 
204f16eb8a4SAndy Shevchenko 	status = acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
205f16eb8a4SAndy Shevchenko 	if (ACPI_FAILURE(status))
206f16eb8a4SAndy Shevchenko 		return -ENODEV;
207f16eb8a4SAndy Shevchenko 
208c2efefb3SRafael J. Wysocki 	/* DT strings are all in lower case */
209c2efefb3SRafael J. Wysocki 	for (c = buf.pointer; *c != '\0'; c++)
210c2efefb3SRafael J. Wysocki 		*c = tolower(*c);
211c2efefb3SRafael J. Wysocki 
212c2efefb3SRafael J. Wysocki 	len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
213c2efefb3SRafael J. Wysocki 	ACPI_FREE(buf.pointer);
214c2efefb3SRafael J. Wysocki 
215*60c874a7SChristophe JAILLET 	if (len >= size)
216*60c874a7SChristophe JAILLET 		return -ENOMEM;
217*60c874a7SChristophe JAILLET 
218*60c874a7SChristophe JAILLET 	size -= len;
219c2efefb3SRafael J. Wysocki 
220c2efefb3SRafael J. Wysocki 	of_compatible = acpi_dev->data.of_compatible;
221c2efefb3SRafael J. Wysocki 	if (of_compatible->type == ACPI_TYPE_PACKAGE) {
222c2efefb3SRafael J. Wysocki 		nval = of_compatible->package.count;
223c2efefb3SRafael J. Wysocki 		obj = of_compatible->package.elements;
224c2efefb3SRafael J. Wysocki 	} else { /* Must be ACPI_TYPE_STRING. */
225c2efefb3SRafael J. Wysocki 		nval = 1;
226c2efefb3SRafael J. Wysocki 		obj = of_compatible;
227c2efefb3SRafael J. Wysocki 	}
228c2efefb3SRafael J. Wysocki 	for (i = 0; i < nval; i++, obj++) {
229c2efefb3SRafael J. Wysocki 		count = snprintf(&modalias[len], size, "C%s",
230c2efefb3SRafael J. Wysocki 				 obj->string.pointer);
231c2efefb3SRafael J. Wysocki 		if (count < 0)
232c2efefb3SRafael J. Wysocki 			return -EINVAL;
233c2efefb3SRafael J. Wysocki 
234c2efefb3SRafael J. Wysocki 		if (count >= size)
235c2efefb3SRafael J. Wysocki 			return -ENOMEM;
236c2efefb3SRafael J. Wysocki 
237c2efefb3SRafael J. Wysocki 		len += count;
238c2efefb3SRafael J. Wysocki 		size -= count;
239c2efefb3SRafael J. Wysocki 	}
240c2efefb3SRafael J. Wysocki 	modalias[len] = '\0';
241c2efefb3SRafael J. Wysocki 	return len;
242c2efefb3SRafael J. Wysocki }
243c2efefb3SRafael J. Wysocki 
__acpi_device_uevent_modalias(const struct acpi_device * adev,struct kobj_uevent_env * env)244162736b0SGreg Kroah-Hartman int __acpi_device_uevent_modalias(const struct acpi_device *adev,
245c2efefb3SRafael J. Wysocki 				  struct kobj_uevent_env *env)
246c2efefb3SRafael J. Wysocki {
247c2efefb3SRafael J. Wysocki 	int len;
248c2efefb3SRafael J. Wysocki 
249c2efefb3SRafael J. Wysocki 	if (!adev)
250c2efefb3SRafael J. Wysocki 		return -ENODEV;
251c2efefb3SRafael J. Wysocki 
252c2efefb3SRafael J. Wysocki 	if (list_empty(&adev->pnp.ids))
253c2efefb3SRafael J. Wysocki 		return 0;
254c2efefb3SRafael J. Wysocki 
255c2efefb3SRafael J. Wysocki 	if (add_uevent_var(env, "MODALIAS="))
256c2efefb3SRafael J. Wysocki 		return -ENOMEM;
257c2efefb3SRafael J. Wysocki 
25836af2d5cSKai-Heng Feng 	if (adev->data.of_compatible)
259c2efefb3SRafael J. Wysocki 		len = create_of_modalias(adev, &env->buf[env->buflen - 1],
260c2efefb3SRafael J. Wysocki 					 sizeof(env->buf) - env->buflen);
26136af2d5cSKai-Heng Feng 	else
26236af2d5cSKai-Heng Feng 		len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
26336af2d5cSKai-Heng Feng 					  sizeof(env->buf) - env->buflen);
264c2efefb3SRafael J. Wysocki 	if (len < 0)
265c2efefb3SRafael J. Wysocki 		return len;
266c2efefb3SRafael J. Wysocki 
267c2efefb3SRafael J. Wysocki 	env->buflen += len;
268c2efefb3SRafael J. Wysocki 
269c2efefb3SRafael J. Wysocki 	return 0;
270c2efefb3SRafael J. Wysocki }
271c2efefb3SRafael J. Wysocki 
272c2efefb3SRafael J. Wysocki /**
273c2efefb3SRafael J. Wysocki  * acpi_device_uevent_modalias - uevent modalias for ACPI-enumerated devices.
2746f2f92c6SBaokun Li  * @dev: Struct device to get ACPI device node.
2756f2f92c6SBaokun Li  * @env: Environment variables of the kobject uevent.
276c2efefb3SRafael J. Wysocki  *
277c2efefb3SRafael J. Wysocki  * Create the uevent modalias field for ACPI-enumerated devices.
278c2efefb3SRafael J. Wysocki  *
279c2efefb3SRafael J. Wysocki  * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
280c2efefb3SRafael J. Wysocki  * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
281c2efefb3SRafael J. Wysocki  */
acpi_device_uevent_modalias(const struct device * dev,struct kobj_uevent_env * env)282162736b0SGreg Kroah-Hartman int acpi_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env)
283c2efefb3SRafael J. Wysocki {
284c2efefb3SRafael J. Wysocki 	return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
285c2efefb3SRafael J. Wysocki }
286c2efefb3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
287c2efefb3SRafael J. Wysocki 
__acpi_device_modalias(const struct acpi_device * adev,char * buf,int size)28886fca926SAndy Shevchenko static int __acpi_device_modalias(const struct acpi_device *adev, char *buf, int size)
289c2efefb3SRafael J. Wysocki {
290c2efefb3SRafael J. Wysocki 	int len, count;
291c2efefb3SRafael J. Wysocki 
292c2efefb3SRafael J. Wysocki 	if (!adev)
293c2efefb3SRafael J. Wysocki 		return -ENODEV;
294c2efefb3SRafael J. Wysocki 
295c2efefb3SRafael J. Wysocki 	if (list_empty(&adev->pnp.ids))
296c2efefb3SRafael J. Wysocki 		return 0;
297c2efefb3SRafael J. Wysocki 
298c2efefb3SRafael J. Wysocki 	len = create_pnp_modalias(adev, buf, size - 1);
299c2efefb3SRafael J. Wysocki 	if (len < 0) {
300c2efefb3SRafael J. Wysocki 		return len;
301c2efefb3SRafael J. Wysocki 	} else if (len > 0) {
302c2efefb3SRafael J. Wysocki 		buf[len++] = '\n';
303c2efefb3SRafael J. Wysocki 		size -= len;
304c2efefb3SRafael J. Wysocki 	}
305c2efefb3SRafael J. Wysocki 	if (!adev->data.of_compatible)
306c2efefb3SRafael J. Wysocki 		return len;
307c2efefb3SRafael J. Wysocki 
308c2efefb3SRafael J. Wysocki 	count = create_of_modalias(adev, buf + len, size - 1);
309c2efefb3SRafael J. Wysocki 	if (count < 0) {
310c2efefb3SRafael J. Wysocki 		return count;
311c2efefb3SRafael J. Wysocki 	} else if (count > 0) {
312c2efefb3SRafael J. Wysocki 		len += count;
313c2efefb3SRafael J. Wysocki 		buf[len++] = '\n';
314c2efefb3SRafael J. Wysocki 	}
315c2efefb3SRafael J. Wysocki 
316c2efefb3SRafael J. Wysocki 	return len;
317c2efefb3SRafael J. Wysocki }
318c2efefb3SRafael J. Wysocki 
319c2efefb3SRafael J. Wysocki /**
320c2efefb3SRafael J. Wysocki  * acpi_device_modalias - modalias sysfs attribute for ACPI-enumerated devices.
3216f2f92c6SBaokun Li  * @dev: Struct device to get ACPI device node.
3226f2f92c6SBaokun Li  * @buf: The buffer to save pnp_modalias and of_modalias.
3236f2f92c6SBaokun Li  * @size: Size of buffer.
324c2efefb3SRafael J. Wysocki  *
325c2efefb3SRafael J. Wysocki  * Create the modalias sysfs attribute for ACPI-enumerated devices.
326c2efefb3SRafael J. Wysocki  *
327c2efefb3SRafael J. Wysocki  * Because other buses do not support ACPI HIDs & CIDs, e.g. for a device with
328c2efefb3SRafael J. Wysocki  * hid:IBM0001 and cid:ACPI0001 you get: "acpi:IBM0001:ACPI0001".
329c2efefb3SRafael J. Wysocki  */
acpi_device_modalias(struct device * dev,char * buf,int size)330c2efefb3SRafael J. Wysocki int acpi_device_modalias(struct device *dev, char *buf, int size)
331c2efefb3SRafael J. Wysocki {
332c2efefb3SRafael J. Wysocki 	return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
333c2efefb3SRafael J. Wysocki }
334c2efefb3SRafael J. Wysocki EXPORT_SYMBOL_GPL(acpi_device_modalias);
335c2efefb3SRafael J. Wysocki 
336c2efefb3SRafael J. Wysocki static ssize_t
modalias_show(struct device * dev,struct device_attribute * attr,char * buf)3370f39ee83SDwaipayan Ray modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
338a508d954SBetty Dall {
339c2efefb3SRafael J. Wysocki 	return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
340c2efefb3SRafael J. Wysocki }
3410f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(modalias);
342c2efefb3SRafael J. Wysocki 
real_power_state_show(struct device * dev,struct device_attribute * attr,char * buf)343c2efefb3SRafael J. Wysocki static ssize_t real_power_state_show(struct device *dev,
344c2efefb3SRafael J. Wysocki 				     struct device_attribute *attr, char *buf)
345c2efefb3SRafael J. Wysocki {
346c2efefb3SRafael J. Wysocki 	struct acpi_device *adev = to_acpi_device(dev);
347c2efefb3SRafael J. Wysocki 	int state;
348c2efefb3SRafael J. Wysocki 	int ret;
349c2efefb3SRafael J. Wysocki 
350c2efefb3SRafael J. Wysocki 	ret = acpi_device_get_power(adev, &state);
351c2efefb3SRafael J. Wysocki 	if (ret)
352c2efefb3SRafael J. Wysocki 		return ret;
353c2efefb3SRafael J. Wysocki 
354c2efefb3SRafael J. Wysocki 	return sprintf(buf, "%s\n", acpi_power_state_string(state));
355c2efefb3SRafael J. Wysocki }
356c2efefb3SRafael J. Wysocki 
357c828a892SJoe Perches static DEVICE_ATTR_RO(real_power_state);
358c2efefb3SRafael J. Wysocki 
power_state_show(struct device * dev,struct device_attribute * attr,char * buf)359c2efefb3SRafael J. Wysocki static ssize_t power_state_show(struct device *dev,
360c2efefb3SRafael J. Wysocki 				struct device_attribute *attr, char *buf)
361c2efefb3SRafael J. Wysocki {
362c2efefb3SRafael J. Wysocki 	struct acpi_device *adev = to_acpi_device(dev);
363c2efefb3SRafael J. Wysocki 
364c2efefb3SRafael J. Wysocki 	return sprintf(buf, "%s\n", acpi_power_state_string(adev->power.state));
365c2efefb3SRafael J. Wysocki }
366c2efefb3SRafael J. Wysocki 
367c828a892SJoe Perches static DEVICE_ATTR_RO(power_state);
368c2efefb3SRafael J. Wysocki 
369c2efefb3SRafael J. Wysocki static ssize_t
eject_store(struct device * d,struct device_attribute * attr,const char * buf,size_t count)3700f39ee83SDwaipayan Ray eject_store(struct device *d, struct device_attribute *attr,
371c2efefb3SRafael J. Wysocki 	    const char *buf, size_t count)
372c2efefb3SRafael J. Wysocki {
373c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_device = to_acpi_device(d);
374c2efefb3SRafael J. Wysocki 	acpi_object_type not_used;
375c2efefb3SRafael J. Wysocki 	acpi_status status;
376c2efefb3SRafael J. Wysocki 
377c2efefb3SRafael J. Wysocki 	if (!count || buf[0] != '1')
378c2efefb3SRafael J. Wysocki 		return -EINVAL;
379c2efefb3SRafael J. Wysocki 
380c2efefb3SRafael J. Wysocki 	if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
381d6fb6ee1SUwe Kleine-König 	    && !d->driver)
382c2efefb3SRafael J. Wysocki 		return -ENODEV;
383c2efefb3SRafael J. Wysocki 
384c2efefb3SRafael J. Wysocki 	status = acpi_get_type(acpi_device->handle, &not_used);
385c2efefb3SRafael J. Wysocki 	if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
386c2efefb3SRafael J. Wysocki 		return -ENODEV;
387c2efefb3SRafael J. Wysocki 
3884cbaba4eSAndy Shevchenko 	acpi_dev_get(acpi_device);
389c2efefb3SRafael J. Wysocki 	status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT);
390c2efefb3SRafael J. Wysocki 	if (ACPI_SUCCESS(status))
391c2efefb3SRafael J. Wysocki 		return count;
392c2efefb3SRafael J. Wysocki 
3934cbaba4eSAndy Shevchenko 	acpi_dev_put(acpi_device);
394c2efefb3SRafael J. Wysocki 	acpi_evaluate_ost(acpi_device->handle, ACPI_OST_EC_OSPM_EJECT,
395c2efefb3SRafael J. Wysocki 			  ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
396c2efefb3SRafael J. Wysocki 	return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
397c2efefb3SRafael J. Wysocki }
398c2efefb3SRafael J. Wysocki 
3990f39ee83SDwaipayan Ray static DEVICE_ATTR_WO(eject);
400c2efefb3SRafael J. Wysocki 
401c2efefb3SRafael J. Wysocki static ssize_t
hid_show(struct device * dev,struct device_attribute * attr,char * buf)4020f39ee83SDwaipayan Ray hid_show(struct device *dev, struct device_attribute *attr, char *buf)
403a508d954SBetty Dall {
404c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
405c2efefb3SRafael J. Wysocki 
406c2efefb3SRafael J. Wysocki 	return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
407c2efefb3SRafael J. Wysocki }
4080f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(hid);
409c2efefb3SRafael J. Wysocki 
uid_show(struct device * dev,struct device_attribute * attr,char * buf)4100f39ee83SDwaipayan Ray static ssize_t uid_show(struct device *dev,
411c2efefb3SRafael J. Wysocki 			struct device_attribute *attr, char *buf)
412c2efefb3SRafael J. Wysocki {
413c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
414c2efefb3SRafael J. Wysocki 
415c2efefb3SRafael J. Wysocki 	return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
416c2efefb3SRafael J. Wysocki }
4170f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(uid);
418c2efefb3SRafael J. Wysocki 
adr_show(struct device * dev,struct device_attribute * attr,char * buf)4190f39ee83SDwaipayan Ray static ssize_t adr_show(struct device *dev,
420c2efefb3SRafael J. Wysocki 			struct device_attribute *attr, char *buf)
421c2efefb3SRafael J. Wysocki {
422c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
423c2efefb3SRafael J. Wysocki 
424ca6f998cSPierre-Louis Bossart 	if (acpi_dev->pnp.bus_address > U32_MAX)
425ca6f998cSPierre-Louis Bossart 		return sprintf(buf, "0x%016llx\n", acpi_dev->pnp.bus_address);
426ca6f998cSPierre-Louis Bossart 	else
427ca6f998cSPierre-Louis Bossart 		return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
428c2efefb3SRafael J. Wysocki }
4290f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(adr);
430c2efefb3SRafael J. Wysocki 
path_show(struct device * dev,struct device_attribute * attr,char * buf)4310f39ee83SDwaipayan Ray static ssize_t path_show(struct device *dev,
432263b4c1aSRafael J. Wysocki 			 struct device_attribute *attr, char *buf)
433263b4c1aSRafael J. Wysocki {
434c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
435c2efefb3SRafael J. Wysocki 
436263b4c1aSRafael J. Wysocki 	return acpi_object_path(acpi_dev->handle, buf);
437c2efefb3SRafael J. Wysocki }
4380f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(path);
439c2efefb3SRafael J. Wysocki 
440c2efefb3SRafael J. Wysocki /* sysfs file that shows description text from the ACPI _STR method */
description_show(struct device * dev,struct device_attribute * attr,char * buf)441c2efefb3SRafael J. Wysocki static ssize_t description_show(struct device *dev,
442c2efefb3SRafael J. Wysocki 				struct device_attribute *attr,
443d0fb66e9SXiaofei Tan 				char *buf)
444d0fb66e9SXiaofei Tan {
445c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
446c2efefb3SRafael J. Wysocki 	int result;
447c2efefb3SRafael J. Wysocki 
448c2efefb3SRafael J. Wysocki 	if (acpi_dev->pnp.str_obj == NULL)
449c2efefb3SRafael J. Wysocki 		return 0;
450c2efefb3SRafael J. Wysocki 
451c2efefb3SRafael J. Wysocki 	/*
452c2efefb3SRafael J. Wysocki 	 * The _STR object contains a Unicode identifier for a device.
453c2efefb3SRafael J. Wysocki 	 * We need to convert to utf-8 so it can be displayed.
454c2efefb3SRafael J. Wysocki 	 */
455c2efefb3SRafael J. Wysocki 	result = utf16s_to_utf8s(
456c2efefb3SRafael J. Wysocki 		(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
457c2efefb3SRafael J. Wysocki 		acpi_dev->pnp.str_obj->buffer.length,
458c2efefb3SRafael J. Wysocki 		UTF16_LITTLE_ENDIAN, buf,
459888be606SKrzysztof Wilczyński 		PAGE_SIZE - 1);
460c2efefb3SRafael J. Wysocki 
461c2efefb3SRafael J. Wysocki 	buf[result++] = '\n';
462c2efefb3SRafael J. Wysocki 
463c2efefb3SRafael J. Wysocki 	return result;
464c2efefb3SRafael J. Wysocki }
465c828a892SJoe Perches static DEVICE_ATTR_RO(description);
466c2efefb3SRafael J. Wysocki 
467c2efefb3SRafael J. Wysocki static ssize_t
sun_show(struct device * dev,struct device_attribute * attr,char * buf)4680f39ee83SDwaipayan Ray sun_show(struct device *dev, struct device_attribute *attr,
469d0fb66e9SXiaofei Tan 	 char *buf)
470d0fb66e9SXiaofei Tan {
471c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
472c2efefb3SRafael J. Wysocki 	acpi_status status;
473c2efefb3SRafael J. Wysocki 	unsigned long long sun;
474c2efefb3SRafael J. Wysocki 
475c2efefb3SRafael J. Wysocki 	status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
476c2efefb3SRafael J. Wysocki 	if (ACPI_FAILURE(status))
4776c024409SBetty Dall 		return -EIO;
478c2efefb3SRafael J. Wysocki 
479c2efefb3SRafael J. Wysocki 	return sprintf(buf, "%llu\n", sun);
480c2efefb3SRafael J. Wysocki }
4810f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(sun);
482c2efefb3SRafael J. Wysocki 
4836283f97dSBetty Dall static ssize_t
hrv_show(struct device * dev,struct device_attribute * attr,char * buf)4840f39ee83SDwaipayan Ray hrv_show(struct device *dev, struct device_attribute *attr,
485d0fb66e9SXiaofei Tan 	 char *buf)
486d0fb66e9SXiaofei Tan {
4876283f97dSBetty Dall 	struct acpi_device *acpi_dev = to_acpi_device(dev);
4886283f97dSBetty Dall 	acpi_status status;
4896283f97dSBetty Dall 	unsigned long long hrv;
4906283f97dSBetty Dall 
4916283f97dSBetty Dall 	status = acpi_evaluate_integer(acpi_dev->handle, "_HRV", NULL, &hrv);
4926283f97dSBetty Dall 	if (ACPI_FAILURE(status))
4936283f97dSBetty Dall 		return -EIO;
4946283f97dSBetty Dall 
4956283f97dSBetty Dall 	return sprintf(buf, "%llu\n", hrv);
4966283f97dSBetty Dall }
4970f39ee83SDwaipayan Ray static DEVICE_ATTR_RO(hrv);
4986283f97dSBetty Dall 
status_show(struct device * dev,struct device_attribute * attr,char * buf)499c2efefb3SRafael J. Wysocki static ssize_t status_show(struct device *dev, struct device_attribute *attr,
500d0fb66e9SXiaofei Tan 				char *buf)
501d0fb66e9SXiaofei Tan {
502c2efefb3SRafael J. Wysocki 	struct acpi_device *acpi_dev = to_acpi_device(dev);
503c2efefb3SRafael J. Wysocki 	acpi_status status;
504c2efefb3SRafael J. Wysocki 	unsigned long long sta;
505c2efefb3SRafael J. Wysocki 
506c2efefb3SRafael J. Wysocki 	status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
507c2efefb3SRafael J. Wysocki 	if (ACPI_FAILURE(status))
5086c024409SBetty Dall 		return -EIO;
509c2efefb3SRafael J. Wysocki 
510c2efefb3SRafael J. Wysocki 	return sprintf(buf, "%llu\n", sta);
511c2efefb3SRafael J. Wysocki }
512c2efefb3SRafael J. Wysocki static DEVICE_ATTR_RO(status);
513c2efefb3SRafael J. Wysocki 
514c2efefb3SRafael J. Wysocki /**
515c2efefb3SRafael J. Wysocki  * acpi_device_setup_files - Create sysfs attributes of an ACPI device.
516c2efefb3SRafael J. Wysocki  * @dev: ACPI device object.
517c2efefb3SRafael J. Wysocki  */
acpi_device_setup_files(struct acpi_device * dev)518c2efefb3SRafael J. Wysocki int acpi_device_setup_files(struct acpi_device *dev)
519c2efefb3SRafael J. Wysocki {
520c2efefb3SRafael J. Wysocki 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
521c2efefb3SRafael J. Wysocki 	acpi_status status;
522c2efefb3SRafael J. Wysocki 	int result = 0;
523c2efefb3SRafael J. Wysocki 
524c2efefb3SRafael J. Wysocki 	/*
525c2efefb3SRafael J. Wysocki 	 * Devices gotten from FADT don't have a "path" attribute
526c2efefb3SRafael J. Wysocki 	 */
527c2efefb3SRafael J. Wysocki 	if (dev->handle) {
528c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_path);
529c2efefb3SRafael J. Wysocki 		if (result)
530c2efefb3SRafael J. Wysocki 			goto end;
531c2efefb3SRafael J. Wysocki 	}
532c2efefb3SRafael J. Wysocki 
533c2efefb3SRafael J. Wysocki 	if (!list_empty(&dev->pnp.ids)) {
534c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_hid);
535c2efefb3SRafael J. Wysocki 		if (result)
536c2efefb3SRafael J. Wysocki 			goto end;
537c2efefb3SRafael J. Wysocki 
538c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_modalias);
539c2efefb3SRafael J. Wysocki 		if (result)
540c2efefb3SRafael J. Wysocki 			goto end;
541c2efefb3SRafael J. Wysocki 	}
542c2efefb3SRafael J. Wysocki 
543c2efefb3SRafael J. Wysocki 	/*
544c2efefb3SRafael J. Wysocki 	 * If device has _STR, 'description' file is created
545c2efefb3SRafael J. Wysocki 	 */
546c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_STR")) {
547c2efefb3SRafael J. Wysocki 		status = acpi_evaluate_object(dev->handle, "_STR",
548c2efefb3SRafael J. Wysocki 					NULL, &buffer);
549c2efefb3SRafael J. Wysocki 		if (ACPI_FAILURE(status))
550c2efefb3SRafael J. Wysocki 			buffer.pointer = NULL;
551c2efefb3SRafael J. Wysocki 		dev->pnp.str_obj = buffer.pointer;
552c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_description);
553c2efefb3SRafael J. Wysocki 		if (result)
554c2efefb3SRafael J. Wysocki 			goto end;
555c2efefb3SRafael J. Wysocki 	}
556c2efefb3SRafael J. Wysocki 
557c2efefb3SRafael J. Wysocki 	if (dev->pnp.type.bus_address)
558c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_adr);
559c2efefb3SRafael J. Wysocki 	if (dev->pnp.unique_id)
560c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_uid);
561c2efefb3SRafael J. Wysocki 
562c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_SUN")) {
563c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_sun);
564c2efefb3SRafael J. Wysocki 		if (result)
565c2efefb3SRafael J. Wysocki 			goto end;
566c2efefb3SRafael J. Wysocki 	}
567c2efefb3SRafael J. Wysocki 
5686283f97dSBetty Dall 	if (acpi_has_method(dev->handle, "_HRV")) {
5696283f97dSBetty Dall 		result = device_create_file(&dev->dev, &dev_attr_hrv);
5706283f97dSBetty Dall 		if (result)
5716283f97dSBetty Dall 			goto end;
5726283f97dSBetty Dall 	}
5736283f97dSBetty Dall 
574c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_STA")) {
575c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_status);
576c2efefb3SRafael J. Wysocki 		if (result)
577c2efefb3SRafael J. Wysocki 			goto end;
578c2efefb3SRafael J. Wysocki 	}
579c2efefb3SRafael J. Wysocki 
580c2efefb3SRafael J. Wysocki 	/*
581c2efefb3SRafael J. Wysocki 	 * If device has _EJ0, 'eject' file is created that is used to trigger
582c2efefb3SRafael J. Wysocki 	 * hot-removal function from userland.
583c2efefb3SRafael J. Wysocki 	 */
584c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_EJ0")) {
585c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_eject);
586c2efefb3SRafael J. Wysocki 		if (result)
587c2efefb3SRafael J. Wysocki 			return result;
588c2efefb3SRafael J. Wysocki 	}
589c2efefb3SRafael J. Wysocki 
590c2efefb3SRafael J. Wysocki 	if (dev->flags.power_manageable) {
591c2efefb3SRafael J. Wysocki 		result = device_create_file(&dev->dev, &dev_attr_power_state);
592c2efefb3SRafael J. Wysocki 		if (result)
593c2efefb3SRafael J. Wysocki 			return result;
594c2efefb3SRafael J. Wysocki 
595c2efefb3SRafael J. Wysocki 		if (dev->power.flags.power_resources)
596c2efefb3SRafael J. Wysocki 			result = device_create_file(&dev->dev,
597c2efefb3SRafael J. Wysocki 						    &dev_attr_real_power_state);
598c2efefb3SRafael J. Wysocki 	}
599c2efefb3SRafael J. Wysocki 
600263b4c1aSRafael J. Wysocki 	acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data);
601263b4c1aSRafael J. Wysocki 
602c2efefb3SRafael J. Wysocki end:
603c2efefb3SRafael J. Wysocki 	return result;
604c2efefb3SRafael J. Wysocki }
605c2efefb3SRafael J. Wysocki 
606c2efefb3SRafael J. Wysocki /**
607c2efefb3SRafael J. Wysocki  * acpi_device_remove_files - Remove sysfs attributes of an ACPI device.
608c2efefb3SRafael J. Wysocki  * @dev: ACPI device object.
609c2efefb3SRafael J. Wysocki  */
acpi_device_remove_files(struct acpi_device * dev)610c2efefb3SRafael J. Wysocki void acpi_device_remove_files(struct acpi_device *dev)
611c2efefb3SRafael J. Wysocki {
612263b4c1aSRafael J. Wysocki 	acpi_hide_nondev_subnodes(&dev->data);
613263b4c1aSRafael J. Wysocki 
614c2efefb3SRafael J. Wysocki 	if (dev->flags.power_manageable) {
615c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_power_state);
616c2efefb3SRafael J. Wysocki 		if (dev->power.flags.power_resources)
617c2efefb3SRafael J. Wysocki 			device_remove_file(&dev->dev,
618c2efefb3SRafael J. Wysocki 					   &dev_attr_real_power_state);
619c2efefb3SRafael J. Wysocki 	}
620c2efefb3SRafael J. Wysocki 
621c2efefb3SRafael J. Wysocki 	/*
622c2efefb3SRafael J. Wysocki 	 * If device has _STR, remove 'description' file
623c2efefb3SRafael J. Wysocki 	 */
624c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_STR")) {
625c2efefb3SRafael J. Wysocki 		kfree(dev->pnp.str_obj);
626c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_description);
627c2efefb3SRafael J. Wysocki 	}
628c2efefb3SRafael J. Wysocki 	/*
629c2efefb3SRafael J. Wysocki 	 * If device has _EJ0, remove 'eject' file.
630c2efefb3SRafael J. Wysocki 	 */
631c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_EJ0"))
632c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_eject);
633c2efefb3SRafael J. Wysocki 
634c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_SUN"))
635c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_sun);
636c2efefb3SRafael J. Wysocki 
6376283f97dSBetty Dall 	if (acpi_has_method(dev->handle, "_HRV"))
6386283f97dSBetty Dall 		device_remove_file(&dev->dev, &dev_attr_hrv);
6396283f97dSBetty Dall 
640c2efefb3SRafael J. Wysocki 	if (dev->pnp.unique_id)
641c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_uid);
642c2efefb3SRafael J. Wysocki 	if (dev->pnp.type.bus_address)
643c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_adr);
644c2efefb3SRafael J. Wysocki 	device_remove_file(&dev->dev, &dev_attr_modalias);
645c2efefb3SRafael J. Wysocki 	device_remove_file(&dev->dev, &dev_attr_hid);
646c2efefb3SRafael J. Wysocki 	if (acpi_has_method(dev->handle, "_STA"))
647c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_status);
648c2efefb3SRafael J. Wysocki 	if (dev->handle)
649c2efefb3SRafael J. Wysocki 		device_remove_file(&dev->dev, &dev_attr_path);
650c2efefb3SRafael J. Wysocki }
651