aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/bus.c8
-rw-r--r--drivers/acpi/button.c13
-rw-r--r--drivers/acpi/fan.c22
-rw-r--r--drivers/acpi/glue.c135
-rw-r--r--drivers/acpi/hed.c20
-rw-r--r--drivers/acpi/proc.c57
-rw-r--r--drivers/acpi/sbshc.c18
-rw-r--r--drivers/acpi/scan.c56
-rw-r--r--drivers/acpi/tables.c18
9 files changed, 201 insertions, 146 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e0596954290b..d59175efc428 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -994,8 +994,6 @@ static int __init acpi_bus_init(void)
994 status = acpi_ec_ecdt_probe(); 994 status = acpi_ec_ecdt_probe();
995 /* Ignore result. Not having an ECDT is not fatal. */ 995 /* Ignore result. Not having an ECDT is not fatal. */
996 996
997 acpi_bus_osc_support();
998
999 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); 997 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
1000 if (ACPI_FAILURE(status)) { 998 if (ACPI_FAILURE(status)) {
1001 printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); 999 printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
@@ -1003,6 +1001,12 @@ static int __init acpi_bus_init(void)
1003 } 1001 }
1004 1002
1005 /* 1003 /*
1004 * _OSC method may exist in module level code,
1005 * so it must be run after ACPI_FULL_INITIALIZATION
1006 */
1007 acpi_bus_osc_support();
1008
1009 /*
1006 * _PDC control method may load dynamic SSDT tables, 1010 * _PDC control method may load dynamic SSDT tables,
1007 * and we need to install the table handler before that. 1011 * and we need to install the table handler before that.
1008 */ 1012 */
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 314a3b84bbc7..f0d936b65e37 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -450,15 +450,4 @@ static int acpi_button_remove(struct acpi_device *device, int type)
450 return 0; 450 return 0;
451} 451}
452 452
453static int __init acpi_button_init(void) 453module_acpi_driver(acpi_button_driver);
454{
455 return acpi_bus_register_driver(&acpi_button_driver);
456}
457
458static void __exit acpi_button_exit(void)
459{
460 acpi_bus_unregister_driver(&acpi_button_driver);
461}
462
463module_init(acpi_button_init);
464module_exit(acpi_button_exit);
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index bc36a476f1ab..3bd6a54702d6 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -212,24 +212,4 @@ static int acpi_fan_resume(struct device *dev)
212} 212}
213#endif 213#endif
214 214
215static int __init acpi_fan_init(void) 215module_acpi_driver(acpi_fan_driver);
216{
217 int result = 0;
218
219 result = acpi_bus_register_driver(&acpi_fan_driver);
220 if (result < 0)
221 return -ENODEV;
222
223 return 0;
224}
225
226static void __exit acpi_fan_exit(void)
227{
228
229 acpi_bus_unregister_driver(&acpi_fan_driver);
230
231 return;
232}
233
234module_init(acpi_fan_init);
235module_exit(acpi_fan_exit);
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 243ee85e4d2e..d1a2d74033e9 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -25,6 +25,8 @@
25static LIST_HEAD(bus_type_list); 25static LIST_HEAD(bus_type_list);
26static DECLARE_RWSEM(bus_type_sem); 26static DECLARE_RWSEM(bus_type_sem);
27 27
28#define PHYSICAL_NODE_STRING "physical_node"
29
28int register_acpi_bus_type(struct acpi_bus_type *type) 30int register_acpi_bus_type(struct acpi_bus_type *type)
29{ 31{
30 if (acpi_disabled) 32 if (acpi_disabled)
@@ -124,84 +126,119 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address)
124 126
125EXPORT_SYMBOL(acpi_get_child); 127EXPORT_SYMBOL(acpi_get_child);
126 128
127/* Link ACPI devices with physical devices */
128static void acpi_glue_data_handler(acpi_handle handle,
129 void *context)
130{
131 /* we provide an empty handler */
132}
133
134/* Note: a success call will increase reference count by one */
135struct device *acpi_get_physical_device(acpi_handle handle)
136{
137 acpi_status status;
138 struct device *dev;
139
140 status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev);
141 if (ACPI_SUCCESS(status))
142 return get_device(dev);
143 return NULL;
144}
145
146EXPORT_SYMBOL(acpi_get_physical_device);
147
148static int acpi_bind_one(struct device *dev, acpi_handle handle) 129static int acpi_bind_one(struct device *dev, acpi_handle handle)
149{ 130{
150 struct acpi_device *acpi_dev; 131 struct acpi_device *acpi_dev;
151 acpi_status status; 132 acpi_status status;
133 struct acpi_device_physical_node *physical_node;
134 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
135 int retval = -EINVAL;
152 136
153 if (dev->archdata.acpi_handle) { 137 if (dev->archdata.acpi_handle) {
154 dev_warn(dev, "Drivers changed 'acpi_handle'\n"); 138 dev_warn(dev, "Drivers changed 'acpi_handle'\n");
155 return -EINVAL; 139 return -EINVAL;
156 } 140 }
141
157 get_device(dev); 142 get_device(dev);
158 status = acpi_attach_data(handle, acpi_glue_data_handler, dev); 143 status = acpi_bus_get_device(handle, &acpi_dev);
159 if (ACPI_FAILURE(status)) { 144 if (ACPI_FAILURE(status))
160 put_device(dev); 145 goto err;
161 return -EINVAL; 146
147 physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
148 GFP_KERNEL);
149 if (!physical_node) {
150 retval = -ENOMEM;
151 goto err;
162 } 152 }
163 dev->archdata.acpi_handle = handle;
164 153
165 status = acpi_bus_get_device(handle, &acpi_dev); 154 mutex_lock(&acpi_dev->physical_node_lock);
166 if (!ACPI_FAILURE(status)) { 155 /* allocate physical node id according to physical_node_id_bitmap */
167 int ret; 156 physical_node->node_id =
168 157 find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
169 ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, 158 ACPI_MAX_PHYSICAL_NODE);
170 "firmware_node"); 159 if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
171 ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, 160 retval = -ENOSPC;
172 "physical_node"); 161 mutex_unlock(&acpi_dev->physical_node_lock);
173 if (acpi_dev->wakeup.flags.valid) 162 goto err;
174 device_set_wakeup_capable(dev, true);
175 } 163 }
176 164
165 set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
166 physical_node->dev = dev;
167 list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
168 acpi_dev->physical_node_count++;
169 mutex_unlock(&acpi_dev->physical_node_lock);
170
171 dev->archdata.acpi_handle = handle;
172
173 if (!physical_node->node_id)
174 strcpy(physical_node_name, PHYSICAL_NODE_STRING);
175 else
176 sprintf(physical_node_name,
177 "physical_node%d", physical_node->node_id);
178 retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
179 physical_node_name);
180 retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
181 "firmware_node");
182
183 if (acpi_dev->wakeup.flags.valid)
184 device_set_wakeup_capable(dev, true);
185
177 return 0; 186 return 0;
187
188 err:
189 put_device(dev);
190 return retval;
178} 191}
179 192
180static int acpi_unbind_one(struct device *dev) 193static int acpi_unbind_one(struct device *dev)
181{ 194{
195 struct acpi_device_physical_node *entry;
196 struct acpi_device *acpi_dev;
197 acpi_status status;
198 struct list_head *node, *next;
199
182 if (!dev->archdata.acpi_handle) 200 if (!dev->archdata.acpi_handle)
183 return 0; 201 return 0;
184 if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
185 struct acpi_device *acpi_dev;
186 202
187 /* acpi_get_physical_device increase refcnt by one */ 203 status = acpi_bus_get_device(dev->archdata.acpi_handle,
188 put_device(dev); 204 &acpi_dev);
205 if (ACPI_FAILURE(status))
206 goto err;
189 207
190 if (!acpi_bus_get_device(dev->archdata.acpi_handle, 208 mutex_lock(&acpi_dev->physical_node_lock);
191 &acpi_dev)) { 209 list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
192 sysfs_remove_link(&dev->kobj, "firmware_node"); 210 char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
193 sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); 211
194 } 212 entry = list_entry(node, struct acpi_device_physical_node,
213 node);
214 if (entry->dev != dev)
215 continue;
216
217 list_del(node);
218 clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
195 219
196 acpi_detach_data(dev->archdata.acpi_handle, 220 acpi_dev->physical_node_count--;
197 acpi_glue_data_handler); 221
222 if (!entry->node_id)
223 strcpy(physical_node_name, PHYSICAL_NODE_STRING);
224 else
225 sprintf(physical_node_name,
226 "physical_node%d", entry->node_id);
227
228 sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
229 sysfs_remove_link(&dev->kobj, "firmware_node");
198 dev->archdata.acpi_handle = NULL; 230 dev->archdata.acpi_handle = NULL;
199 /* acpi_bind_one increase refcnt by one */ 231 /* acpi_bind_one increase refcnt by one */
200 put_device(dev); 232 put_device(dev);
201 } else { 233 kfree(entry);
202 dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
203 } 234 }
235 mutex_unlock(&acpi_dev->physical_node_lock);
236
204 return 0; 237 return 0;
238
239err:
240 dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
241 return -EINVAL;
205} 242}
206 243
207static int acpi_platform_notify(struct device *dev) 244static int acpi_platform_notify(struct device *dev)
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index d0c1967f7597..20a0f2c3ca3b 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -86,25 +86,7 @@ static struct acpi_driver acpi_hed_driver = {
86 .notify = acpi_hed_notify, 86 .notify = acpi_hed_notify,
87 }, 87 },
88}; 88};
89 89module_acpi_driver(acpi_hed_driver);
90static int __init acpi_hed_init(void)
91{
92 if (acpi_disabled)
93 return -ENODEV;
94
95 if (acpi_bus_register_driver(&acpi_hed_driver) < 0)
96 return -ENODEV;
97
98 return 0;
99}
100
101static void __exit acpi_hed_exit(void)
102{
103 acpi_bus_unregister_driver(&acpi_hed_driver);
104}
105
106module_init(acpi_hed_init);
107module_exit(acpi_hed_exit);
108 90
109ACPI_MODULE_NAME("hed"); 91ACPI_MODULE_NAME("hed");
110MODULE_AUTHOR("Huang Ying"); 92MODULE_AUTHOR("Huang Ying");
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 251c7b6273a9..27adb090bb30 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -302,26 +302,41 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
302 list_for_each_safe(node, next, &acpi_wakeup_device_list) { 302 list_for_each_safe(node, next, &acpi_wakeup_device_list) {
303 struct acpi_device *dev = 303 struct acpi_device *dev =
304 container_of(node, struct acpi_device, wakeup_list); 304 container_of(node, struct acpi_device, wakeup_list);
305 struct device *ldev; 305 struct acpi_device_physical_node *entry;
306 306
307 if (!dev->wakeup.flags.valid) 307 if (!dev->wakeup.flags.valid)
308 continue; 308 continue;
309 309
310 ldev = acpi_get_physical_device(dev->handle); 310 seq_printf(seq, "%s\t S%d\t",
311 seq_printf(seq, "%s\t S%d\t%c%-8s ",
312 dev->pnp.bus_id, 311 dev->pnp.bus_id,
313 (u32) dev->wakeup.sleep_state, 312 (u32) dev->wakeup.sleep_state);
314 dev->wakeup.flags.run_wake ? '*' : ' ', 313
315 (device_may_wakeup(&dev->dev) 314 if (!dev->physical_node_count)
316 || (ldev && device_may_wakeup(ldev))) ? 315 seq_printf(seq, "%c%-8s\n",
317 "enabled" : "disabled"); 316 dev->wakeup.flags.run_wake ?
318 if (ldev) 317 '*' : ' ', "disabled");
319 seq_printf(seq, "%s:%s", 318 else {
320 ldev->bus ? ldev->bus->name : "no-bus", 319 struct device *ldev;
321 dev_name(ldev)); 320 list_for_each_entry(entry, &dev->physical_node_list,
322 seq_printf(seq, "\n"); 321 node) {
323 put_device(ldev); 322 ldev = get_device(entry->dev);
324 323 if (!ldev)
324 continue;
325
326 if (&entry->node !=
327 dev->physical_node_list.next)
328 seq_printf(seq, "\t\t");
329
330 seq_printf(seq, "%c%-8s %s:%s\n",
331 dev->wakeup.flags.run_wake ? '*' : ' ',
332 (device_may_wakeup(&dev->dev) ||
333 (ldev && device_may_wakeup(ldev))) ?
334 "enabled" : "disabled",
335 ldev->bus ? ldev->bus->name :
336 "no-bus", dev_name(ldev));
337 put_device(ldev);
338 }
339 }
325 } 340 }
326 mutex_unlock(&acpi_device_lock); 341 mutex_unlock(&acpi_device_lock);
327 return 0; 342 return 0;
@@ -329,12 +344,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
329 344
330static void physical_device_enable_wakeup(struct acpi_device *adev) 345static void physical_device_enable_wakeup(struct acpi_device *adev)
331{ 346{
332 struct device *dev = acpi_get_physical_device(adev->handle); 347 struct acpi_device_physical_node *entry;
333 348
334 if (dev && device_can_wakeup(dev)) { 349 list_for_each_entry(entry,
335 bool enable = !device_may_wakeup(dev); 350 &adev->physical_node_list, node)
336 device_set_wakeup_enable(dev, enable); 351 if (entry->dev && device_can_wakeup(entry->dev)) {
337 } 352 bool enable = !device_may_wakeup(entry->dev);
353 device_set_wakeup_enable(entry->dev, enable);
354 }
338} 355}
339 356
340static ssize_t 357static ssize_t
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index f8d2a472795c..cf6129a8af7c 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -310,23 +310,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
310 return 0; 310 return 0;
311} 311}
312 312
313static int __init acpi_smb_hc_init(void) 313module_acpi_driver(acpi_smb_hc_driver);
314{
315 int result;
316
317 result = acpi_bus_register_driver(&acpi_smb_hc_driver);
318 if (result < 0)
319 return -ENODEV;
320 return 0;
321}
322
323static void __exit acpi_smb_hc_exit(void)
324{
325 acpi_bus_unregister_driver(&acpi_smb_hc_driver);
326}
327
328module_init(acpi_smb_hc_init);
329module_exit(acpi_smb_hc_exit);
330 314
331MODULE_LICENSE("GPL"); 315MODULE_LICENSE("GPL");
332MODULE_AUTHOR("Alexey Starikovskiy"); 316MODULE_AUTHOR("Alexey Starikovskiy");
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d1ecca2b641a..1fcb8678665c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -10,6 +10,7 @@
10#include <linux/signal.h> 10#include <linux/signal.h>
11#include <linux/kthread.h> 11#include <linux/kthread.h>
12#include <linux/dmi.h> 12#include <linux/dmi.h>
13#include <linux/nls.h>
13 14
14#include <acpi/acpi_drivers.h> 15#include <acpi/acpi_drivers.h>
15 16
@@ -232,8 +233,35 @@ end:
232} 233}
233static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); 234static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
234 235
236/* sysfs file that shows description text from the ACPI _STR method */
237static ssize_t description_show(struct device *dev,
238 struct device_attribute *attr,
239 char *buf) {
240 struct acpi_device *acpi_dev = to_acpi_device(dev);
241 int result;
242
243 if (acpi_dev->pnp.str_obj == NULL)
244 return 0;
245
246 /*
247 * The _STR object contains a Unicode identifier for a device.
248 * We need to convert to utf-8 so it can be displayed.
249 */
250 result = utf16s_to_utf8s(
251 (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
252 acpi_dev->pnp.str_obj->buffer.length,
253 UTF16_LITTLE_ENDIAN, buf,
254 PAGE_SIZE);
255
256 buf[result++] = '\n';
257
258 return result;
259}
260static DEVICE_ATTR(description, 0444, description_show, NULL);
261
235static int acpi_device_setup_files(struct acpi_device *dev) 262static int acpi_device_setup_files(struct acpi_device *dev)
236{ 263{
264 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
237 acpi_status status; 265 acpi_status status;
238 acpi_handle temp; 266 acpi_handle temp;
239 int result = 0; 267 int result = 0;
@@ -257,6 +285,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
257 goto end; 285 goto end;
258 } 286 }
259 287
288 /*
289 * If device has _STR, 'description' file is created
290 */
291 status = acpi_get_handle(dev->handle, "_STR", &temp);
292 if (ACPI_SUCCESS(status)) {
293 status = acpi_evaluate_object(dev->handle, "_STR",
294 NULL, &buffer);
295 if (ACPI_FAILURE(status))
296 buffer.pointer = NULL;
297 dev->pnp.str_obj = buffer.pointer;
298 result = device_create_file(&dev->dev, &dev_attr_description);
299 if (result)
300 goto end;
301 }
302
260 /* 303 /*
261 * If device has _EJ0, 'eject' file is created that is used to trigger 304 * If device has _EJ0, 'eject' file is created that is used to trigger
262 * hot-removal function from userland. 305 * hot-removal function from userland.
@@ -274,8 +317,15 @@ static void acpi_device_remove_files(struct acpi_device *dev)
274 acpi_handle temp; 317 acpi_handle temp;
275 318
276 /* 319 /*
277 * If device has _EJ0, 'eject' file is created that is used to trigger 320 * If device has _STR, remove 'description' file
278 * hot-removal function from userland. 321 */
322 status = acpi_get_handle(dev->handle, "_STR", &temp);
323 if (ACPI_SUCCESS(status)) {
324 kfree(dev->pnp.str_obj);
325 device_remove_file(&dev->dev, &dev_attr_description);
326 }
327 /*
328 * If device has _EJ0, remove 'eject' file.
279 */ 329 */
280 status = acpi_get_handle(dev->handle, "_EJ0", &temp); 330 status = acpi_get_handle(dev->handle, "_EJ0", &temp);
281 if (ACPI_SUCCESS(status)) 331 if (ACPI_SUCCESS(status))
@@ -481,6 +531,8 @@ static int acpi_device_register(struct acpi_device *device)
481 INIT_LIST_HEAD(&device->children); 531 INIT_LIST_HEAD(&device->children);
482 INIT_LIST_HEAD(&device->node); 532 INIT_LIST_HEAD(&device->node);
483 INIT_LIST_HEAD(&device->wakeup_list); 533 INIT_LIST_HEAD(&device->wakeup_list);
534 INIT_LIST_HEAD(&device->physical_node_list);
535 mutex_init(&device->physical_node_lock);
484 536
485 new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); 537 new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
486 if (!new_bus_id) { 538 if (!new_bus_id) {
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index f336bca7c450..2572d9715bda 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -240,10 +240,17 @@ acpi_table_parse_entries(char *id,
240 table_end) { 240 table_end) {
241 if (entry->type == entry_id 241 if (entry->type == entry_id
242 && (!max_entries || count++ < max_entries)) 242 && (!max_entries || count++ < max_entries))
243 if (handler(entry, table_end)) { 243 if (handler(entry, table_end))
244 early_acpi_os_unmap_memory((char *)table_header, tbl_size); 244 goto err;
245 return -EINVAL; 245
246 } 246 /*
247 * If entry->length is 0, break from this loop to avoid
248 * infinite loop.
249 */
250 if (entry->length == 0) {
251 pr_err(PREFIX "[%4.4s:0x%02x] Invalid zero length\n", id, entry_id);
252 goto err;
253 }
247 254
248 entry = (struct acpi_subtable_header *) 255 entry = (struct acpi_subtable_header *)
249 ((unsigned long)entry + entry->length); 256 ((unsigned long)entry + entry->length);
@@ -255,6 +262,9 @@ acpi_table_parse_entries(char *id,
255 262
256 early_acpi_os_unmap_memory((char *)table_header, tbl_size); 263 early_acpi_os_unmap_memory((char *)table_header, tbl_size);
257 return count; 264 return count;
265err:
266 early_acpi_os_unmap_memory((char *)table_header, tbl_size);
267 return -EINVAL;
258} 268}
259 269
260int __init 270int __init