aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@linux.intel.com>2006-12-07 07:56:38 -0500
committerLen Brown <len.brown@intel.com>2006-12-15 23:38:34 -0500
commitf883d9db008deb20d4969c26475100cec2b7f6f8 (patch)
tree4d66f2bf9f0a6142685870177e26837fc510f9e1 /drivers/acpi/scan.c
parenta7178df5e7e5730e5daa6cf6d8b8bf73adbe75c0 (diff)
ACPI: convert to sysfs framework
Setup new sysfs framework 1. Remove /sys/firmware/acpi 2. Add ACPI device in device tree. File "eject" for every device that has _EJ0 method is moved from /sys/firmware to /sys/devices. Operation on this file is exactly the same as before. i.e. echo 1 to "eject" will cause hot removal of this device. Corresponding changes should be made in userspace for hot removal. Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Zhang Rui<rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c187
1 files changed, 41 insertions, 146 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b616e17de522..97f6bbd6ef3c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -24,126 +24,6 @@ static LIST_HEAD(acpi_device_list);
24DEFINE_SPINLOCK(acpi_device_lock); 24DEFINE_SPINLOCK(acpi_device_lock);
25LIST_HEAD(acpi_wakeup_device_list); 25LIST_HEAD(acpi_wakeup_device_list);
26 26
27
28static void acpi_device_release_legacy(struct kobject *kobj)
29{
30 struct acpi_device *dev = container_of(kobj, struct acpi_device, kobj);
31 kfree(dev->pnp.cid_list);
32 kfree(dev);
33}
34
35struct acpi_device_attribute {
36 struct attribute attr;
37 ssize_t(*show) (struct acpi_device *, char *);
38 ssize_t(*store) (struct acpi_device *, const char *, size_t);
39};
40
41typedef void acpi_device_sysfs_files(struct kobject *,
42 const struct attribute *);
43
44static void setup_sys_fs_device_files(struct acpi_device *dev,
45 acpi_device_sysfs_files * func);
46
47#define create_sysfs_device_files(dev) \
48 setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_create_file)
49#define remove_sysfs_device_files(dev) \
50 setup_sys_fs_device_files(dev, (acpi_device_sysfs_files *)&sysfs_remove_file)
51
52#define to_acpi_dev(n) container_of(n, struct acpi_device, kobj)
53#define to_handle_attr(n) container_of(n, struct acpi_device_attribute, attr);
54
55static ssize_t acpi_device_attr_show(struct kobject *kobj,
56 struct attribute *attr, char *buf)
57{
58 struct acpi_device *device = to_acpi_dev(kobj);
59 struct acpi_device_attribute *attribute = to_handle_attr(attr);
60 return attribute->show ? attribute->show(device, buf) : -EIO;
61}
62static ssize_t acpi_device_attr_store(struct kobject *kobj,
63 struct attribute *attr, const char *buf,
64 size_t len)
65{
66 struct acpi_device *device = to_acpi_dev(kobj);
67 struct acpi_device_attribute *attribute = to_handle_attr(attr);
68 return attribute->store ? attribute->store(device, buf, len) : -EIO;
69}
70
71static struct sysfs_ops acpi_device_sysfs_ops = {
72 .show = acpi_device_attr_show,
73 .store = acpi_device_attr_store,
74};
75
76static struct kobj_type ktype_acpi_ns = {
77 .sysfs_ops = &acpi_device_sysfs_ops,
78 .release = acpi_device_release_legacy,
79};
80
81static int namespace_uevent(struct kset *kset, struct kobject *kobj,
82 char **envp, int num_envp, char *buffer,
83 int buffer_size)
84{
85 struct acpi_device *dev = to_acpi_dev(kobj);
86 int i = 0;
87 int len = 0;
88
89 if (!dev->driver)
90 return 0;
91
92 if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
93 "PHYSDEVDRIVER=%s", dev->driver->name))
94 return -ENOMEM;
95
96 envp[i] = NULL;
97
98 return 0;
99}
100
101static struct kset_uevent_ops namespace_uevent_ops = {
102 .uevent = &namespace_uevent,
103};
104
105static struct kset acpi_namespace_kset = {
106 .kobj = {
107 .name = "namespace",
108 },
109 .subsys = &acpi_subsys,
110 .ktype = &ktype_acpi_ns,
111 .uevent_ops = &namespace_uevent_ops,
112};
113
114/* --------------------------------------------------------------------------
115 ACPI sysfs device file support
116 -------------------------------------------------------------------------- */
117static ssize_t acpi_eject_store(struct acpi_device *device,
118 const char *buf, size_t count);
119
120#define ACPI_DEVICE_ATTR(_name,_mode,_show,_store) \
121static struct acpi_device_attribute acpi_device_attr_##_name = \
122 __ATTR(_name, _mode, _show, _store)
123
124ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
125
126/**
127 * setup_sys_fs_device_files - sets up the device files under device namespace
128 * @dev: acpi_device object
129 * @func: function pointer to create or destroy the device file
130 */
131static void
132setup_sys_fs_device_files(struct acpi_device *dev,
133 acpi_device_sysfs_files * func)
134{
135 acpi_status status;
136 acpi_handle temp = NULL;
137
138 /*
139 * If device has _EJ0, 'eject' file is created that is used to trigger
140 * hot-removal function from userland.
141 */
142 status = acpi_get_handle(dev->handle, "_EJ0", &temp);
143 if (ACPI_SUCCESS(status))
144 (*(func)) (&dev->kobj, &acpi_device_attr_eject.attr);
145}
146
147static int acpi_eject_operation(acpi_handle handle, int lockable) 27static int acpi_eject_operation(acpi_handle handle, int lockable)
148{ 28{
149 struct acpi_object_list arg_list; 29 struct acpi_object_list arg_list;
@@ -180,7 +60,8 @@ static int acpi_eject_operation(acpi_handle handle, int lockable)
180} 60}
181 61
182static ssize_t 62static ssize_t
183acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) 63acpi_eject_store(struct device *d, struct device_attribute *attr,
64 const char *buf, size_t count)
184{ 65{
185 int result; 66 int result;
186 int ret = count; 67 int ret = count;
@@ -188,26 +69,27 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
188 acpi_status status; 69 acpi_status status;
189 acpi_handle handle; 70 acpi_handle handle;
190 acpi_object_type type = 0; 71 acpi_object_type type = 0;
72 struct acpi_device *acpi_device = to_acpi_device(d);
191 73
192 if ((!count) || (buf[0] != '1')) { 74 if ((!count) || (buf[0] != '1')) {
193 return -EINVAL; 75 return -EINVAL;
194 } 76 }
195#ifndef FORCE_EJECT 77#ifndef FORCE_EJECT
196 if (device->driver == NULL) { 78 if (acpi_device->driver == NULL) {
197 ret = -ENODEV; 79 ret = -ENODEV;
198 goto err; 80 goto err;
199 } 81 }
200#endif 82#endif
201 status = acpi_get_type(device->handle, &type); 83 status = acpi_get_type(acpi_device->handle, &type);
202 if (ACPI_FAILURE(status) || (!device->flags.ejectable)) { 84 if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
203 ret = -ENODEV; 85 ret = -ENODEV;
204 goto err; 86 goto err;
205 } 87 }
206 88
207 islockable = device->flags.lockable; 89 islockable = acpi_device->flags.lockable;
208 handle = device->handle; 90 handle = acpi_device->handle;
209 91
210 result = acpi_bus_trim(device, 1); 92 result = acpi_bus_trim(acpi_device, 1);
211 93
212 if (!result) 94 if (!result)
213 result = acpi_eject_operation(handle, islockable); 95 result = acpi_eject_operation(handle, islockable);
@@ -219,6 +101,35 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
219 return ret; 101 return ret;
220} 102}
221 103
104static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
105
106static void acpi_device_setup_files(struct acpi_device *dev)
107{
108 acpi_status status;
109 acpi_handle temp;
110
111 /*
112 * If device has _EJ0, 'eject' file is created that is used to trigger
113 * hot-removal function from userland.
114 */
115 status = acpi_get_handle(dev->handle, "_EJ0", &temp);
116 if (ACPI_SUCCESS(status))
117 device_create_file(&dev->dev, &dev_attr_eject);
118}
119
120static void acpi_device_remove_files(struct acpi_device *dev)
121{
122 acpi_status status;
123 acpi_handle temp;
124
125 /*
126 * If device has _EJ0, 'eject' file is created that is used to trigger
127 * hot-removal function from userland.
128 */
129 status = acpi_get_handle(dev->handle, "_EJ0", &temp);
130 if (ACPI_SUCCESS(status))
131 device_remove_file(&dev->dev, &dev_attr_eject);
132}
222/* -------------------------------------------------------------------------- 133/* --------------------------------------------------------------------------
223 ACPI Bus operations 134 ACPI Bus operations
224 -------------------------------------------------------------------------- */ 135 -------------------------------------------------------------------------- */
@@ -353,8 +264,6 @@ static struct bus_type acpi_bus_type = {
353static void acpi_device_register(struct acpi_device *device, 264static void acpi_device_register(struct acpi_device *device,
354 struct acpi_device *parent) 265 struct acpi_device *parent)
355{ 266{
356 int err;
357
358 /* 267 /*
359 * Linkage 268 * Linkage
360 * ------- 269 * -------
@@ -375,17 +284,6 @@ static void acpi_device_register(struct acpi_device *device,
375 list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); 284 list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
376 spin_unlock(&acpi_device_lock); 285 spin_unlock(&acpi_device_lock);
377 286
378 strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN);
379 if (parent)
380 device->kobj.parent = &parent->kobj;
381 device->kobj.ktype = &ktype_acpi_ns;
382 device->kobj.kset = &acpi_namespace_kset;
383 err = kobject_register(&device->kobj);
384 if (err < 0)
385 printk(KERN_WARNING "%s: kobject_register error: %d\n",
386 __FUNCTION__, err);
387 create_sysfs_device_files(device);
388
389 if (device->parent) 287 if (device->parent)
390 device->dev.parent = &parent->dev; 288 device->dev.parent = &parent->dev;
391 device->dev.bus = &acpi_bus_type; 289 device->dev.bus = &acpi_bus_type;
@@ -393,6 +291,8 @@ static void acpi_device_register(struct acpi_device *device,
393 sprintf(device->dev.bus_id, "%s", device->pnp.bus_id); 291 sprintf(device->dev.bus_id, "%s", device->pnp.bus_id);
394 device->dev.release = &acpi_device_release; 292 device->dev.release = &acpi_device_release;
395 device_add(&device->dev); 293 device_add(&device->dev);
294
295 acpi_device_setup_files(device);
396} 296}
397 297
398static void acpi_device_unregister(struct acpi_device *device, int type) 298static void acpi_device_unregister(struct acpi_device *device, int type)
@@ -409,9 +309,8 @@ static void acpi_device_unregister(struct acpi_device *device, int type)
409 spin_unlock(&acpi_device_lock); 309 spin_unlock(&acpi_device_lock);
410 310
411 acpi_detach_data(device->handle, acpi_bus_data_handler); 311 acpi_detach_data(device->handle, acpi_bus_data_handler);
412 remove_sysfs_device_files(device);
413 kobject_unregister(&device->kobj);
414 312
313 acpi_device_remove_files(device);
415 device_unregister(&device->dev); 314 device_unregister(&device->dev);
416} 315}
417 316
@@ -1353,10 +1252,6 @@ static int __init acpi_scan_init(void)
1353 if (acpi_disabled) 1252 if (acpi_disabled)
1354 return 0; 1253 return 0;
1355 1254
1356 result = kset_register(&acpi_namespace_kset);
1357 if (result < 0)
1358 printk(KERN_ERR PREFIX "kset_register error: %d\n", result);
1359
1360 result = bus_register(&acpi_bus_type); 1255 result = bus_register(&acpi_bus_type);
1361 if (result) { 1256 if (result) {
1362 /* We don't want to quit even if we failed to add suspend/resume */ 1257 /* We don't want to quit even if we failed to add suspend/resume */