diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 645 |
1 files changed, 316 insertions, 329 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 698a1540e303..e0255cbd5e19 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -111,233 +111,6 @@ static struct kset acpi_namespace_kset = { | |||
111 | .uevent_ops = &namespace_uevent_ops, | 111 | .uevent_ops = &namespace_uevent_ops, |
112 | }; | 112 | }; |
113 | 113 | ||
114 | static void acpi_device_register(struct acpi_device *device, | ||
115 | struct acpi_device *parent) | ||
116 | { | ||
117 | int err; | ||
118 | |||
119 | /* | ||
120 | * Linkage | ||
121 | * ------- | ||
122 | * Link this device to its parent and siblings. | ||
123 | */ | ||
124 | INIT_LIST_HEAD(&device->children); | ||
125 | INIT_LIST_HEAD(&device->node); | ||
126 | INIT_LIST_HEAD(&device->g_list); | ||
127 | INIT_LIST_HEAD(&device->wakeup_list); | ||
128 | |||
129 | spin_lock(&acpi_device_lock); | ||
130 | if (device->parent) { | ||
131 | list_add_tail(&device->node, &device->parent->children); | ||
132 | list_add_tail(&device->g_list, &device->parent->g_list); | ||
133 | } else | ||
134 | list_add_tail(&device->g_list, &acpi_device_list); | ||
135 | if (device->wakeup.flags.valid) | ||
136 | list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); | ||
137 | spin_unlock(&acpi_device_lock); | ||
138 | |||
139 | strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN); | ||
140 | if (parent) | ||
141 | device->kobj.parent = &parent->kobj; | ||
142 | device->kobj.ktype = &ktype_acpi_ns; | ||
143 | device->kobj.kset = &acpi_namespace_kset; | ||
144 | err = kobject_register(&device->kobj); | ||
145 | if (err < 0) | ||
146 | printk(KERN_WARNING "%s: kobject_register error: %d\n", | ||
147 | __FUNCTION__, err); | ||
148 | create_sysfs_device_files(device); | ||
149 | } | ||
150 | |||
151 | static void acpi_device_unregister(struct acpi_device *device, int type) | ||
152 | { | ||
153 | spin_lock(&acpi_device_lock); | ||
154 | if (device->parent) { | ||
155 | list_del(&device->node); | ||
156 | list_del(&device->g_list); | ||
157 | } else | ||
158 | list_del(&device->g_list); | ||
159 | |||
160 | list_del(&device->wakeup_list); | ||
161 | |||
162 | spin_unlock(&acpi_device_lock); | ||
163 | |||
164 | acpi_detach_data(device->handle, acpi_bus_data_handler); | ||
165 | remove_sysfs_device_files(device); | ||
166 | kobject_unregister(&device->kobj); | ||
167 | } | ||
168 | |||
169 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) | ||
170 | { | ||
171 | |||
172 | /* TBD */ | ||
173 | |||
174 | return; | ||
175 | } | ||
176 | |||
177 | static int acpi_bus_get_power_flags(struct acpi_device *device) | ||
178 | { | ||
179 | acpi_status status = 0; | ||
180 | acpi_handle handle = NULL; | ||
181 | u32 i = 0; | ||
182 | |||
183 | |||
184 | /* | ||
185 | * Power Management Flags | ||
186 | */ | ||
187 | status = acpi_get_handle(device->handle, "_PSC", &handle); | ||
188 | if (ACPI_SUCCESS(status)) | ||
189 | device->power.flags.explicit_get = 1; | ||
190 | status = acpi_get_handle(device->handle, "_IRC", &handle); | ||
191 | if (ACPI_SUCCESS(status)) | ||
192 | device->power.flags.inrush_current = 1; | ||
193 | |||
194 | /* | ||
195 | * Enumerate supported power management states | ||
196 | */ | ||
197 | for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { | ||
198 | struct acpi_device_power_state *ps = &device->power.states[i]; | ||
199 | char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; | ||
200 | |||
201 | /* Evaluate "_PRx" to se if power resources are referenced */ | ||
202 | acpi_evaluate_reference(device->handle, object_name, NULL, | ||
203 | &ps->resources); | ||
204 | if (ps->resources.count) { | ||
205 | device->power.flags.power_resources = 1; | ||
206 | ps->flags.valid = 1; | ||
207 | } | ||
208 | |||
209 | /* Evaluate "_PSx" to see if we can do explicit sets */ | ||
210 | object_name[2] = 'S'; | ||
211 | status = acpi_get_handle(device->handle, object_name, &handle); | ||
212 | if (ACPI_SUCCESS(status)) { | ||
213 | ps->flags.explicit_set = 1; | ||
214 | ps->flags.valid = 1; | ||
215 | } | ||
216 | |||
217 | /* State is valid if we have some power control */ | ||
218 | if (ps->resources.count || ps->flags.explicit_set) | ||
219 | ps->flags.valid = 1; | ||
220 | |||
221 | ps->power = -1; /* Unknown - driver assigned */ | ||
222 | ps->latency = -1; /* Unknown - driver assigned */ | ||
223 | } | ||
224 | |||
225 | /* Set defaults for D0 and D3 states (always valid) */ | ||
226 | device->power.states[ACPI_STATE_D0].flags.valid = 1; | ||
227 | device->power.states[ACPI_STATE_D0].power = 100; | ||
228 | device->power.states[ACPI_STATE_D3].flags.valid = 1; | ||
229 | device->power.states[ACPI_STATE_D3].power = 0; | ||
230 | |||
231 | /* TBD: System wake support and resource requirements. */ | ||
232 | |||
233 | device->power.state = ACPI_STATE_UNKNOWN; | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | int acpi_match_ids(struct acpi_device *device, char *ids) | ||
239 | { | ||
240 | if (device->flags.hardware_id) | ||
241 | if (strstr(ids, device->pnp.hardware_id)) | ||
242 | return 0; | ||
243 | |||
244 | if (device->flags.compatible_ids) { | ||
245 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; | ||
246 | int i; | ||
247 | |||
248 | /* compare multiple _CID entries against driver ids */ | ||
249 | for (i = 0; i < cid_list->count; i++) { | ||
250 | if (strstr(ids, cid_list->id[i].value)) | ||
251 | return 0; | ||
252 | } | ||
253 | } | ||
254 | return -ENOENT; | ||
255 | } | ||
256 | |||
257 | static acpi_status | ||
258 | acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, | ||
259 | union acpi_object *package) | ||
260 | { | ||
261 | int i = 0; | ||
262 | union acpi_object *element = NULL; | ||
263 | |||
264 | if (!device || !package || (package->package.count < 2)) | ||
265 | return AE_BAD_PARAMETER; | ||
266 | |||
267 | element = &(package->package.elements[0]); | ||
268 | if (!element) | ||
269 | return AE_BAD_PARAMETER; | ||
270 | if (element->type == ACPI_TYPE_PACKAGE) { | ||
271 | if ((element->package.count < 2) || | ||
272 | (element->package.elements[0].type != | ||
273 | ACPI_TYPE_LOCAL_REFERENCE) | ||
274 | || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) | ||
275 | return AE_BAD_DATA; | ||
276 | device->wakeup.gpe_device = | ||
277 | element->package.elements[0].reference.handle; | ||
278 | device->wakeup.gpe_number = | ||
279 | (u32) element->package.elements[1].integer.value; | ||
280 | } else if (element->type == ACPI_TYPE_INTEGER) { | ||
281 | device->wakeup.gpe_number = element->integer.value; | ||
282 | } else | ||
283 | return AE_BAD_DATA; | ||
284 | |||
285 | element = &(package->package.elements[1]); | ||
286 | if (element->type != ACPI_TYPE_INTEGER) { | ||
287 | return AE_BAD_DATA; | ||
288 | } | ||
289 | device->wakeup.sleep_state = element->integer.value; | ||
290 | |||
291 | if ((package->package.count - 2) > ACPI_MAX_HANDLES) { | ||
292 | return AE_NO_MEMORY; | ||
293 | } | ||
294 | device->wakeup.resources.count = package->package.count - 2; | ||
295 | for (i = 0; i < device->wakeup.resources.count; i++) { | ||
296 | element = &(package->package.elements[i + 2]); | ||
297 | if (element->type != ACPI_TYPE_ANY) { | ||
298 | return AE_BAD_DATA; | ||
299 | } | ||
300 | |||
301 | device->wakeup.resources.handles[i] = element->reference.handle; | ||
302 | } | ||
303 | |||
304 | return AE_OK; | ||
305 | } | ||
306 | |||
307 | static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | ||
308 | { | ||
309 | acpi_status status = 0; | ||
310 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
311 | union acpi_object *package = NULL; | ||
312 | |||
313 | |||
314 | /* _PRW */ | ||
315 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); | ||
316 | if (ACPI_FAILURE(status)) { | ||
317 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); | ||
318 | goto end; | ||
319 | } | ||
320 | |||
321 | package = (union acpi_object *)buffer.pointer; | ||
322 | status = acpi_bus_extract_wakeup_device_power_package(device, package); | ||
323 | if (ACPI_FAILURE(status)) { | ||
324 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); | ||
325 | goto end; | ||
326 | } | ||
327 | |||
328 | kfree(buffer.pointer); | ||
329 | |||
330 | device->wakeup.flags.valid = 1; | ||
331 | /* Power button, Lid switch always enable wakeup */ | ||
332 | if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E")) | ||
333 | device->wakeup.flags.run_wake = 1; | ||
334 | |||
335 | end: | ||
336 | if (ACPI_FAILURE(status)) | ||
337 | device->flags.wake_capable = 0; | ||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | /* -------------------------------------------------------------------------- | 114 | /* -------------------------------------------------------------------------- |
342 | ACPI sysfs device file support | 115 | ACPI sysfs device file support |
343 | -------------------------------------------------------------------------- */ | 116 | -------------------------------------------------------------------------- */ |
@@ -447,20 +220,86 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count) | |||
447 | } | 220 | } |
448 | 221 | ||
449 | /* -------------------------------------------------------------------------- | 222 | /* -------------------------------------------------------------------------- |
450 | Performance Management | 223 | ACPI Bus operations |
451 | -------------------------------------------------------------------------- */ | 224 | -------------------------------------------------------------------------- */ |
225 | static inline struct acpi_device * to_acpi_dev(struct device * dev) | ||
226 | { | ||
227 | return container_of(dev, struct acpi_device, dev); | ||
228 | } | ||
452 | 229 | ||
453 | static int acpi_bus_get_perf_flags(struct acpi_device *device) | 230 | static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) |
454 | { | 231 | { |
455 | device->performance.state = ACPI_STATE_UNKNOWN; | 232 | struct acpi_device * dev, * next; |
233 | int result; | ||
234 | |||
235 | spin_lock(&acpi_device_lock); | ||
236 | list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { | ||
237 | if (dev->driver && dev->driver->ops.suspend) { | ||
238 | spin_unlock(&acpi_device_lock); | ||
239 | result = dev->driver->ops.suspend(dev, 0); | ||
240 | if (result) { | ||
241 | printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", | ||
242 | acpi_device_name(dev), | ||
243 | acpi_device_bid(dev), result); | ||
244 | } | ||
245 | spin_lock(&acpi_device_lock); | ||
246 | } | ||
247 | } | ||
248 | spin_unlock(&acpi_device_lock); | ||
456 | return 0; | 249 | return 0; |
457 | } | 250 | } |
458 | 251 | ||
459 | /* -------------------------------------------------------------------------- | 252 | static int acpi_device_suspend(struct device * dev, pm_message_t state) |
460 | Driver Management | 253 | { |
461 | -------------------------------------------------------------------------- */ | 254 | struct acpi_device * acpi_dev = to_acpi_dev(dev); |
462 | 255 | ||
463 | static LIST_HEAD(acpi_bus_drivers); | 256 | /* |
257 | * For now, we should only register 1 generic device - | ||
258 | * the ACPI root device - and from there, we walk the | ||
259 | * tree of ACPI devices to suspend each one using the | ||
260 | * ACPI driver methods. | ||
261 | */ | ||
262 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
263 | root_suspend(acpi_dev, state); | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int root_resume(struct acpi_device * acpi_dev) | ||
268 | { | ||
269 | struct acpi_device * dev, * next; | ||
270 | int result; | ||
271 | |||
272 | spin_lock(&acpi_device_lock); | ||
273 | list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { | ||
274 | if (dev->driver && dev->driver->ops.resume) { | ||
275 | spin_unlock(&acpi_device_lock); | ||
276 | result = dev->driver->ops.resume(dev, 0); | ||
277 | if (result) { | ||
278 | printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", | ||
279 | acpi_device_name(dev), | ||
280 | acpi_device_bid(dev), result); | ||
281 | } | ||
282 | spin_lock(&acpi_device_lock); | ||
283 | } | ||
284 | } | ||
285 | spin_unlock(&acpi_device_lock); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int acpi_device_resume(struct device * dev) | ||
290 | { | ||
291 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
292 | |||
293 | /* | ||
294 | * For now, we should only register 1 generic device - | ||
295 | * the ACPI root device - and from there, we walk the | ||
296 | * tree of ACPI devices to resume each one using the | ||
297 | * ACPI driver methods. | ||
298 | */ | ||
299 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
300 | root_resume(acpi_dev); | ||
301 | return 0; | ||
302 | } | ||
464 | 303 | ||
465 | /** | 304 | /** |
466 | * acpi_bus_match - match device IDs to driver's supported IDs | 305 | * acpi_bus_match - match device IDs to driver's supported IDs |
@@ -478,6 +317,72 @@ acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver) | |||
478 | return acpi_match_ids(device, driver->ids); | 317 | return acpi_match_ids(device, driver->ids); |
479 | } | 318 | } |
480 | 319 | ||
320 | static struct bus_type acpi_bus_type = { | ||
321 | .name = "acpi", | ||
322 | .suspend = acpi_device_suspend, | ||
323 | .resume = acpi_device_resume, | ||
324 | }; | ||
325 | |||
326 | static void acpi_device_register(struct acpi_device *device, | ||
327 | struct acpi_device *parent) | ||
328 | { | ||
329 | int err; | ||
330 | |||
331 | /* | ||
332 | * Linkage | ||
333 | * ------- | ||
334 | * Link this device to its parent and siblings. | ||
335 | */ | ||
336 | INIT_LIST_HEAD(&device->children); | ||
337 | INIT_LIST_HEAD(&device->node); | ||
338 | INIT_LIST_HEAD(&device->g_list); | ||
339 | INIT_LIST_HEAD(&device->wakeup_list); | ||
340 | |||
341 | spin_lock(&acpi_device_lock); | ||
342 | if (device->parent) { | ||
343 | list_add_tail(&device->node, &device->parent->children); | ||
344 | list_add_tail(&device->g_list, &device->parent->g_list); | ||
345 | } else | ||
346 | list_add_tail(&device->g_list, &acpi_device_list); | ||
347 | if (device->wakeup.flags.valid) | ||
348 | list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list); | ||
349 | spin_unlock(&acpi_device_lock); | ||
350 | |||
351 | strlcpy(device->kobj.name, device->pnp.bus_id, KOBJ_NAME_LEN); | ||
352 | if (parent) | ||
353 | device->kobj.parent = &parent->kobj; | ||
354 | device->kobj.ktype = &ktype_acpi_ns; | ||
355 | device->kobj.kset = &acpi_namespace_kset; | ||
356 | err = kobject_register(&device->kobj); | ||
357 | if (err < 0) | ||
358 | printk(KERN_WARNING "%s: kobject_register error: %d\n", | ||
359 | __FUNCTION__, err); | ||
360 | create_sysfs_device_files(device); | ||
361 | } | ||
362 | |||
363 | static void acpi_device_unregister(struct acpi_device *device, int type) | ||
364 | { | ||
365 | spin_lock(&acpi_device_lock); | ||
366 | if (device->parent) { | ||
367 | list_del(&device->node); | ||
368 | list_del(&device->g_list); | ||
369 | } else | ||
370 | list_del(&device->g_list); | ||
371 | |||
372 | list_del(&device->wakeup_list); | ||
373 | |||
374 | spin_unlock(&acpi_device_lock); | ||
375 | |||
376 | acpi_detach_data(device->handle, acpi_bus_data_handler); | ||
377 | remove_sysfs_device_files(device); | ||
378 | kobject_unregister(&device->kobj); | ||
379 | } | ||
380 | |||
381 | /* -------------------------------------------------------------------------- | ||
382 | Driver Management | ||
383 | -------------------------------------------------------------------------- */ | ||
384 | static LIST_HEAD(acpi_bus_drivers); | ||
385 | |||
481 | /** | 386 | /** |
482 | * acpi_bus_driver_init - add a device to a driver | 387 | * acpi_bus_driver_init - add a device to a driver |
483 | * @device: the device to add and initialize | 388 | * @device: the device to add and initialize |
@@ -668,7 +573,6 @@ static int acpi_bus_find_driver(struct acpi_device *device) | |||
668 | /* -------------------------------------------------------------------------- | 573 | /* -------------------------------------------------------------------------- |
669 | Device Enumeration | 574 | Device Enumeration |
670 | -------------------------------------------------------------------------- */ | 575 | -------------------------------------------------------------------------- */ |
671 | |||
672 | acpi_status | 576 | acpi_status |
673 | acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) | 577 | acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) |
674 | { | 578 | { |
@@ -691,6 +595,183 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) | |||
691 | } | 595 | } |
692 | EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); | 596 | EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); |
693 | 597 | ||
598 | void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) | ||
599 | { | ||
600 | |||
601 | /* TBD */ | ||
602 | |||
603 | return; | ||
604 | } | ||
605 | |||
606 | int acpi_match_ids(struct acpi_device *device, char *ids) | ||
607 | { | ||
608 | if (device->flags.hardware_id) | ||
609 | if (strstr(ids, device->pnp.hardware_id)) | ||
610 | return 0; | ||
611 | |||
612 | if (device->flags.compatible_ids) { | ||
613 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; | ||
614 | int i; | ||
615 | |||
616 | /* compare multiple _CID entries against driver ids */ | ||
617 | for (i = 0; i < cid_list->count; i++) { | ||
618 | if (strstr(ids, cid_list->id[i].value)) | ||
619 | return 0; | ||
620 | } | ||
621 | } | ||
622 | return -ENOENT; | ||
623 | } | ||
624 | |||
625 | static int acpi_bus_get_perf_flags(struct acpi_device *device) | ||
626 | { | ||
627 | device->performance.state = ACPI_STATE_UNKNOWN; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static acpi_status | ||
632 | acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, | ||
633 | union acpi_object *package) | ||
634 | { | ||
635 | int i = 0; | ||
636 | union acpi_object *element = NULL; | ||
637 | |||
638 | if (!device || !package || (package->package.count < 2)) | ||
639 | return AE_BAD_PARAMETER; | ||
640 | |||
641 | element = &(package->package.elements[0]); | ||
642 | if (!element) | ||
643 | return AE_BAD_PARAMETER; | ||
644 | if (element->type == ACPI_TYPE_PACKAGE) { | ||
645 | if ((element->package.count < 2) || | ||
646 | (element->package.elements[0].type != | ||
647 | ACPI_TYPE_LOCAL_REFERENCE) | ||
648 | || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) | ||
649 | return AE_BAD_DATA; | ||
650 | device->wakeup.gpe_device = | ||
651 | element->package.elements[0].reference.handle; | ||
652 | device->wakeup.gpe_number = | ||
653 | (u32) element->package.elements[1].integer.value; | ||
654 | } else if (element->type == ACPI_TYPE_INTEGER) { | ||
655 | device->wakeup.gpe_number = element->integer.value; | ||
656 | } else | ||
657 | return AE_BAD_DATA; | ||
658 | |||
659 | element = &(package->package.elements[1]); | ||
660 | if (element->type != ACPI_TYPE_INTEGER) { | ||
661 | return AE_BAD_DATA; | ||
662 | } | ||
663 | device->wakeup.sleep_state = element->integer.value; | ||
664 | |||
665 | if ((package->package.count - 2) > ACPI_MAX_HANDLES) { | ||
666 | return AE_NO_MEMORY; | ||
667 | } | ||
668 | device->wakeup.resources.count = package->package.count - 2; | ||
669 | for (i = 0; i < device->wakeup.resources.count; i++) { | ||
670 | element = &(package->package.elements[i + 2]); | ||
671 | if (element->type != ACPI_TYPE_ANY) { | ||
672 | return AE_BAD_DATA; | ||
673 | } | ||
674 | |||
675 | device->wakeup.resources.handles[i] = element->reference.handle; | ||
676 | } | ||
677 | |||
678 | return AE_OK; | ||
679 | } | ||
680 | |||
681 | static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | ||
682 | { | ||
683 | acpi_status status = 0; | ||
684 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
685 | union acpi_object *package = NULL; | ||
686 | |||
687 | |||
688 | /* _PRW */ | ||
689 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); | ||
690 | if (ACPI_FAILURE(status)) { | ||
691 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW")); | ||
692 | goto end; | ||
693 | } | ||
694 | |||
695 | package = (union acpi_object *)buffer.pointer; | ||
696 | status = acpi_bus_extract_wakeup_device_power_package(device, package); | ||
697 | if (ACPI_FAILURE(status)) { | ||
698 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); | ||
699 | goto end; | ||
700 | } | ||
701 | |||
702 | kfree(buffer.pointer); | ||
703 | |||
704 | device->wakeup.flags.valid = 1; | ||
705 | /* Power button, Lid switch always enable wakeup */ | ||
706 | if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E")) | ||
707 | device->wakeup.flags.run_wake = 1; | ||
708 | |||
709 | end: | ||
710 | if (ACPI_FAILURE(status)) | ||
711 | device->flags.wake_capable = 0; | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static int acpi_bus_get_power_flags(struct acpi_device *device) | ||
716 | { | ||
717 | acpi_status status = 0; | ||
718 | acpi_handle handle = NULL; | ||
719 | u32 i = 0; | ||
720 | |||
721 | |||
722 | /* | ||
723 | * Power Management Flags | ||
724 | */ | ||
725 | status = acpi_get_handle(device->handle, "_PSC", &handle); | ||
726 | if (ACPI_SUCCESS(status)) | ||
727 | device->power.flags.explicit_get = 1; | ||
728 | status = acpi_get_handle(device->handle, "_IRC", &handle); | ||
729 | if (ACPI_SUCCESS(status)) | ||
730 | device->power.flags.inrush_current = 1; | ||
731 | |||
732 | /* | ||
733 | * Enumerate supported power management states | ||
734 | */ | ||
735 | for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) { | ||
736 | struct acpi_device_power_state *ps = &device->power.states[i]; | ||
737 | char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' }; | ||
738 | |||
739 | /* Evaluate "_PRx" to se if power resources are referenced */ | ||
740 | acpi_evaluate_reference(device->handle, object_name, NULL, | ||
741 | &ps->resources); | ||
742 | if (ps->resources.count) { | ||
743 | device->power.flags.power_resources = 1; | ||
744 | ps->flags.valid = 1; | ||
745 | } | ||
746 | |||
747 | /* Evaluate "_PSx" to see if we can do explicit sets */ | ||
748 | object_name[2] = 'S'; | ||
749 | status = acpi_get_handle(device->handle, object_name, &handle); | ||
750 | if (ACPI_SUCCESS(status)) { | ||
751 | ps->flags.explicit_set = 1; | ||
752 | ps->flags.valid = 1; | ||
753 | } | ||
754 | |||
755 | /* State is valid if we have some power control */ | ||
756 | if (ps->resources.count || ps->flags.explicit_set) | ||
757 | ps->flags.valid = 1; | ||
758 | |||
759 | ps->power = -1; /* Unknown - driver assigned */ | ||
760 | ps->latency = -1; /* Unknown - driver assigned */ | ||
761 | } | ||
762 | |||
763 | /* Set defaults for D0 and D3 states (always valid) */ | ||
764 | device->power.states[ACPI_STATE_D0].flags.valid = 1; | ||
765 | device->power.states[ACPI_STATE_D0].power = 100; | ||
766 | device->power.states[ACPI_STATE_D3].flags.valid = 1; | ||
767 | device->power.states[ACPI_STATE_D3].power = 0; | ||
768 | |||
769 | /* TBD: System wake support and resource requirements. */ | ||
770 | |||
771 | device->power.state = ACPI_STATE_UNKNOWN; | ||
772 | |||
773 | return 0; | ||
774 | } | ||
694 | 775 | ||
695 | static int acpi_bus_get_flags(struct acpi_device *device) | 776 | static int acpi_bus_get_flags(struct acpi_device *device) |
696 | { | 777 | { |
@@ -1353,100 +1434,6 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) | |||
1353 | return result; | 1434 | return result; |
1354 | } | 1435 | } |
1355 | 1436 | ||
1356 | |||
1357 | static inline struct acpi_device * to_acpi_dev(struct device * dev) | ||
1358 | { | ||
1359 | return container_of(dev, struct acpi_device, dev); | ||
1360 | } | ||
1361 | |||
1362 | |||
1363 | static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) | ||
1364 | { | ||
1365 | struct acpi_device * dev, * next; | ||
1366 | int result; | ||
1367 | |||
1368 | spin_lock(&acpi_device_lock); | ||
1369 | list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { | ||
1370 | if (dev->driver && dev->driver->ops.suspend) { | ||
1371 | spin_unlock(&acpi_device_lock); | ||
1372 | result = dev->driver->ops.suspend(dev, 0); | ||
1373 | if (result) { | ||
1374 | printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n", | ||
1375 | acpi_device_name(dev), | ||
1376 | acpi_device_bid(dev), result); | ||
1377 | } | ||
1378 | spin_lock(&acpi_device_lock); | ||
1379 | } | ||
1380 | } | ||
1381 | spin_unlock(&acpi_device_lock); | ||
1382 | return 0; | ||
1383 | } | ||
1384 | |||
1385 | |||
1386 | static int acpi_device_suspend(struct device * dev, pm_message_t state) | ||
1387 | { | ||
1388 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
1389 | |||
1390 | /* | ||
1391 | * For now, we should only register 1 generic device - | ||
1392 | * the ACPI root device - and from there, we walk the | ||
1393 | * tree of ACPI devices to suspend each one using the | ||
1394 | * ACPI driver methods. | ||
1395 | */ | ||
1396 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
1397 | root_suspend(acpi_dev, state); | ||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | |||
1402 | |||
1403 | static int root_resume(struct acpi_device * acpi_dev) | ||
1404 | { | ||
1405 | struct acpi_device * dev, * next; | ||
1406 | int result; | ||
1407 | |||
1408 | spin_lock(&acpi_device_lock); | ||
1409 | list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { | ||
1410 | if (dev->driver && dev->driver->ops.resume) { | ||
1411 | spin_unlock(&acpi_device_lock); | ||
1412 | result = dev->driver->ops.resume(dev, 0); | ||
1413 | if (result) { | ||
1414 | printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", | ||
1415 | acpi_device_name(dev), | ||
1416 | acpi_device_bid(dev), result); | ||
1417 | } | ||
1418 | spin_lock(&acpi_device_lock); | ||
1419 | } | ||
1420 | } | ||
1421 | spin_unlock(&acpi_device_lock); | ||
1422 | return 0; | ||
1423 | } | ||
1424 | |||
1425 | |||
1426 | static int acpi_device_resume(struct device * dev) | ||
1427 | { | ||
1428 | struct acpi_device * acpi_dev = to_acpi_dev(dev); | ||
1429 | |||
1430 | /* | ||
1431 | * For now, we should only register 1 generic device - | ||
1432 | * the ACPI root device - and from there, we walk the | ||
1433 | * tree of ACPI devices to resume each one using the | ||
1434 | * ACPI driver methods. | ||
1435 | */ | ||
1436 | if (acpi_dev->handle == ACPI_ROOT_OBJECT) | ||
1437 | root_resume(acpi_dev); | ||
1438 | return 0; | ||
1439 | } | ||
1440 | |||
1441 | |||
1442 | static struct bus_type acpi_bus_type = { | ||
1443 | .name = "acpi", | ||
1444 | .suspend = acpi_device_suspend, | ||
1445 | .resume = acpi_device_resume, | ||
1446 | }; | ||
1447 | |||
1448 | |||
1449 | |||
1450 | static int __init acpi_scan_init(void) | 1437 | static int __init acpi_scan_init(void) |
1451 | { | 1438 | { |
1452 | int result; | 1439 | int result; |