aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-08 06:31:23 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-04-08 06:31:23 -0400
commit408fb7f37bf8e76a22d6058cde7c1f0fc7fa7da9 (patch)
tree1352c0be04d06620d7ecfe8b027ee84c2397206f /drivers/acpi
parent31880c37c11e28cb81c70757e38392b42e695dc6 (diff)
parentfd4655c259fa91b3b207345eb7b4d9faa1b6bc8d (diff)
Merge branch 'acpi-hotplug' into linux-next
* acpi-hotplug: ACPI / memhotplug: Remove info->failed bit ACPI / memhotplug: set info->enabled for memory present at boot time ACPI: Verify device status after eject acpi: remove reference to ACPI_HOTPLUG_IO ACPI: Update _OST handling for notify ACPI: Update PNPID match handling for notify ACPI: Update PNPID set/free interfaces ACPI: Remove acpi_device dependency in acpi_device_set_id() ACPI / hotplug: Make acpi_hotplug_profile_ktype static ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler ACPI / container: Use hotplug profile user space interface ACPI / hotplug: Introduce user space interface for hotplug profiles ACPI / scan: Introduce acpi_scan_handler_matching() ACPI / container: Use common hotplug code ACPI / scan: Introduce common code for ACPI-based device hotplug ACPI / scan: Introduce acpi_scan_match_handler()
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig5
-rw-r--r--drivers/acpi/acpi_memhotplug.c328
-rw-r--r--drivers/acpi/container.c150
-rw-r--r--drivers/acpi/internal.h13
-rw-r--r--drivers/acpi/power.c2
-rw-r--r--drivers/acpi/scan.c530
-rw-r--r--drivers/acpi/sysfs.c66
-rw-r--r--drivers/acpi/video_detect.c25
8 files changed, 538 insertions, 581 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 4bf68c8d4797..8fcae6df0a42 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -334,7 +334,7 @@ config X86_PM_TIMER
334 334
335config ACPI_CONTAINER 335config ACPI_CONTAINER
336 bool "Container and Module Devices" 336 bool "Container and Module Devices"
337 default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) 337 default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU)
338 help 338 help
339 This driver supports ACPI Container and Module devices (IDs 339 This driver supports ACPI Container and Module devices (IDs
340 ACPI0004, PNP0A05, and PNP0A06). 340 ACPI0004, PNP0A05, and PNP0A06).
@@ -345,9 +345,8 @@ config ACPI_CONTAINER
345 the module will be called container. 345 the module will be called container.
346 346
347config ACPI_HOTPLUG_MEMORY 347config ACPI_HOTPLUG_MEMORY
348 tristate "Memory Hotplug" 348 bool "Memory Hotplug"
349 depends on MEMORY_HOTPLUG 349 depends on MEMORY_HOTPLUG
350 default n
351 help 350 help
352 This driver supports ACPI memory hotplug. The driver 351 This driver supports ACPI memory hotplug. The driver
353 fields notifications on ACPI memory devices (PNP0C80), 352 fields notifications on ACPI memory devices (PNP0C80),
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index da1f82b445e0..5e6301e94920 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -1,5 +1,7 @@
1/* 1/*
2 * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com> 2 * Copyright (C) 2004, 2013 Intel Corporation
3 * Author: Naveen B S <naveen.b.s@intel.com>
4 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
3 * 5 *
4 * All rights reserved. 6 * All rights reserved.
5 * 7 *
@@ -25,14 +27,10 @@
25 * ranges. 27 * ranges.
26 */ 28 */
27 29
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/types.h>
32#include <linux/memory_hotplug.h>
33#include <linux/slab.h>
34#include <linux/acpi.h> 30#include <linux/acpi.h>
35#include <acpi/acpi_drivers.h> 31#include <linux/memory_hotplug.h>
32
33#include "internal.h"
36 34
37#define ACPI_MEMORY_DEVICE_CLASS "memory" 35#define ACPI_MEMORY_DEVICE_CLASS "memory"
38#define ACPI_MEMORY_DEVICE_HID "PNP0C80" 36#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
@@ -44,32 +42,28 @@
44#define PREFIX "ACPI:memory_hp:" 42#define PREFIX "ACPI:memory_hp:"
45 43
46ACPI_MODULE_NAME("acpi_memhotplug"); 44ACPI_MODULE_NAME("acpi_memhotplug");
47MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
48MODULE_DESCRIPTION("Hotplug Mem Driver");
49MODULE_LICENSE("GPL");
50 45
51/* Memory Device States */ 46/* Memory Device States */
52#define MEMORY_INVALID_STATE 0 47#define MEMORY_INVALID_STATE 0
53#define MEMORY_POWER_ON_STATE 1 48#define MEMORY_POWER_ON_STATE 1
54#define MEMORY_POWER_OFF_STATE 2 49#define MEMORY_POWER_OFF_STATE 2
55 50
56static int acpi_memory_device_add(struct acpi_device *device); 51static int acpi_memory_device_add(struct acpi_device *device,
57static int acpi_memory_device_remove(struct acpi_device *device); 52 const struct acpi_device_id *not_used);
53static void acpi_memory_device_remove(struct acpi_device *device);
58 54
59static const struct acpi_device_id memory_device_ids[] = { 55static const struct acpi_device_id memory_device_ids[] = {
60 {ACPI_MEMORY_DEVICE_HID, 0}, 56 {ACPI_MEMORY_DEVICE_HID, 0},
61 {"", 0}, 57 {"", 0},
62}; 58};
63MODULE_DEVICE_TABLE(acpi, memory_device_ids);
64 59
65static struct acpi_driver acpi_memory_device_driver = { 60static struct acpi_scan_handler memory_device_handler = {
66 .name = "acpi_memhotplug",
67 .class = ACPI_MEMORY_DEVICE_CLASS,
68 .ids = memory_device_ids, 61 .ids = memory_device_ids,
69 .ops = { 62 .attach = acpi_memory_device_add,
70 .add = acpi_memory_device_add, 63 .detach = acpi_memory_device_remove,
71 .remove = acpi_memory_device_remove, 64 .hotplug = {
72 }, 65 .enabled = true,
66 },
73}; 67};
74 68
75struct acpi_memory_info { 69struct acpi_memory_info {
@@ -79,7 +73,6 @@ struct acpi_memory_info {
79 unsigned short caching; /* memory cache attribute */ 73 unsigned short caching; /* memory cache attribute */
80 unsigned short write_protect; /* memory read/write attribute */ 74 unsigned short write_protect; /* memory read/write attribute */
81 unsigned int enabled:1; 75 unsigned int enabled:1;
82 unsigned int failed:1;
83}; 76};
84 77
85struct acpi_memory_device { 78struct acpi_memory_device {
@@ -153,48 +146,6 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
153 return 0; 146 return 0;
154} 147}
155 148
156static int acpi_memory_get_device(acpi_handle handle,
157 struct acpi_memory_device **mem_device)
158{
159 struct acpi_device *device = NULL;
160 int result = 0;
161
162 acpi_scan_lock_acquire();
163
164 acpi_bus_get_device(handle, &device);
165 if (device)
166 goto end;
167
168 /*
169 * Now add the notified device. This creates the acpi_device
170 * and invokes .add function
171 */
172 result = acpi_bus_scan(handle);
173 if (result) {
174 acpi_handle_warn(handle, "ACPI namespace scan failed\n");
175 result = -EINVAL;
176 goto out;
177 }
178 result = acpi_bus_get_device(handle, &device);
179 if (result) {
180 acpi_handle_warn(handle, "Missing device object\n");
181 result = -EINVAL;
182 goto out;
183 }
184
185 end:
186 *mem_device = acpi_driver_data(device);
187 if (!(*mem_device)) {
188 dev_err(&device->dev, "driver data not found\n");
189 result = -ENODEV;
190 goto out;
191 }
192
193 out:
194 acpi_scan_lock_release();
195 return result;
196}
197
198static int acpi_memory_check_device(struct acpi_memory_device *mem_device) 149static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
199{ 150{
200 unsigned long long current_status; 151 unsigned long long current_status;
@@ -249,13 +200,11 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
249 * returns -EEXIST. If add_memory() returns the other error, it 200 * returns -EEXIST. If add_memory() returns the other error, it
250 * means that this memory block is not used by the kernel. 201 * means that this memory block is not used by the kernel.
251 */ 202 */
252 if (result && result != -EEXIST) { 203 if (result && result != -EEXIST)
253 info->failed = 1;
254 continue; 204 continue;
255 }
256 205
257 if (!result) 206 info->enabled = 1;
258 info->enabled = 1; 207
259 /* 208 /*
260 * Add num_enable even if add_memory() returns -EEXIST, so the 209 * Add num_enable even if add_memory() returns -EEXIST, so the
261 * device is bound to this driver. 210 * device is bound to this driver.
@@ -286,16 +235,8 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
286 nid = acpi_get_node(mem_device->device->handle); 235 nid = acpi_get_node(mem_device->device->handle);
287 236
288 list_for_each_entry_safe(info, n, &mem_device->res_list, list) { 237 list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
289 if (info->failed)
290 /* The kernel does not use this memory block */
291 continue;
292
293 if (!info->enabled) 238 if (!info->enabled)
294 /* 239 continue;
295 * The kernel uses this memory block, but it may be not
296 * managed by us.
297 */
298 return -EBUSY;
299 240
300 if (nid < 0) 241 if (nid < 0)
301 nid = memory_add_physaddr_to_nid(info->start_addr); 242 nid = memory_add_physaddr_to_nid(info->start_addr);
@@ -310,95 +251,21 @@ static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
310 return result; 251 return result;
311} 252}
312 253
313static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
314{
315 struct acpi_memory_device *mem_device;
316 struct acpi_device *device;
317 struct acpi_eject_event *ej_event = NULL;
318 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
319 acpi_status status;
320
321 switch (event) {
322 case ACPI_NOTIFY_BUS_CHECK:
323 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
324 "\nReceived BUS CHECK notification for device\n"));
325 /* Fall Through */
326 case ACPI_NOTIFY_DEVICE_CHECK:
327 if (event == ACPI_NOTIFY_DEVICE_CHECK)
328 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
329 "\nReceived DEVICE CHECK notification for device\n"));
330 if (acpi_memory_get_device(handle, &mem_device)) {
331 acpi_handle_err(handle, "Cannot find driver data\n");
332 break;
333 }
334
335 ost_code = ACPI_OST_SC_SUCCESS;
336 break;
337
338 case ACPI_NOTIFY_EJECT_REQUEST:
339 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
340 "\nReceived EJECT REQUEST notification for device\n"));
341
342 status = AE_ERROR;
343 acpi_scan_lock_acquire();
344
345 if (acpi_bus_get_device(handle, &device)) {
346 acpi_handle_err(handle, "Device doesn't exist\n");
347 goto unlock;
348 }
349 mem_device = acpi_driver_data(device);
350 if (!mem_device) {
351 acpi_handle_err(handle, "Driver Data is NULL\n");
352 goto unlock;
353 }
354
355 ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
356 if (!ej_event) {
357 pr_err(PREFIX "No memory, dropping EJECT\n");
358 goto unlock;
359 }
360
361 get_device(&device->dev);
362 ej_event->device = device;
363 ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
364 /* The eject is carried out asynchronously. */
365 status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
366 ej_event);
367 if (ACPI_FAILURE(status)) {
368 put_device(&device->dev);
369 kfree(ej_event);
370 }
371
372 unlock:
373 acpi_scan_lock_release();
374 if (ACPI_SUCCESS(status))
375 return;
376 default:
377 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
378 "Unsupported event [0x%x]\n", event));
379
380 /* non-hotplug event; possibly handled by other handler */
381 return;
382 }
383
384 /* Inform firmware that the hotplug operation has completed */
385 (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
386}
387
388static void acpi_memory_device_free(struct acpi_memory_device *mem_device) 254static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
389{ 255{
390 if (!mem_device) 256 if (!mem_device)
391 return; 257 return;
392 258
393 acpi_memory_free_device_resources(mem_device); 259 acpi_memory_free_device_resources(mem_device);
260 mem_device->device->driver_data = NULL;
394 kfree(mem_device); 261 kfree(mem_device);
395} 262}
396 263
397static int acpi_memory_device_add(struct acpi_device *device) 264static int acpi_memory_device_add(struct acpi_device *device,
265 const struct acpi_device_id *not_used)
398{ 266{
267 struct acpi_memory_device *mem_device;
399 int result; 268 int result;
400 struct acpi_memory_device *mem_device = NULL;
401
402 269
403 if (!device) 270 if (!device)
404 return -EINVAL; 271 return -EINVAL;
@@ -423,147 +290,36 @@ static int acpi_memory_device_add(struct acpi_device *device)
423 /* Set the device state */ 290 /* Set the device state */
424 mem_device->state = MEMORY_POWER_ON_STATE; 291 mem_device->state = MEMORY_POWER_ON_STATE;
425 292
426 pr_debug("%s\n", acpi_device_name(device)); 293 result = acpi_memory_check_device(mem_device);
294 if (result) {
295 acpi_memory_device_free(mem_device);
296 return 0;
297 }
427 298
428 if (!acpi_memory_check_device(mem_device)) { 299 result = acpi_memory_enable_device(mem_device);
429 /* call add_memory func */ 300 if (result) {
430 result = acpi_memory_enable_device(mem_device); 301 dev_err(&device->dev, "acpi_memory_enable_device() error\n");
431 if (result) { 302 acpi_memory_device_free(mem_device);
432 dev_err(&device->dev, 303 return -ENODEV;
433 "Error in acpi_memory_enable_device\n");
434 acpi_memory_device_free(mem_device);
435 }
436 } 304 }
437 return result; 305
306 dev_dbg(&device->dev, "Memory device configured by ACPI\n");
307 return 1;
438} 308}
439 309
440static int acpi_memory_device_remove(struct acpi_device *device) 310static void acpi_memory_device_remove(struct acpi_device *device)
441{ 311{
442 struct acpi_memory_device *mem_device = NULL; 312 struct acpi_memory_device *mem_device;
443 int result;
444 313
445 if (!device || !acpi_driver_data(device)) 314 if (!device || !acpi_driver_data(device))
446 return -EINVAL; 315 return;
447 316
448 mem_device = acpi_driver_data(device); 317 mem_device = acpi_driver_data(device);
449 318 acpi_memory_remove_memory(mem_device);
450 result = acpi_memory_remove_memory(mem_device);
451 if (result)
452 return result;
453
454 acpi_memory_device_free(mem_device); 319 acpi_memory_device_free(mem_device);
455
456 return 0;
457}
458
459/*
460 * Helper function to check for memory device
461 */
462static acpi_status is_memory_device(acpi_handle handle)
463{
464 char *hardware_id;
465 acpi_status status;
466 struct acpi_device_info *info;
467
468 status = acpi_get_object_info(handle, &info);
469 if (ACPI_FAILURE(status))
470 return status;
471
472 if (!(info->valid & ACPI_VALID_HID)) {
473 kfree(info);
474 return AE_ERROR;
475 }
476
477 hardware_id = info->hardware_id.string;
478 if ((hardware_id == NULL) ||
479 (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
480 status = AE_ERROR;
481
482 kfree(info);
483 return status;
484}
485
486static acpi_status
487acpi_memory_register_notify_handler(acpi_handle handle,
488 u32 level, void *ctxt, void **retv)
489{
490 acpi_status status;
491
492
493 status = is_memory_device(handle);
494 if (ACPI_FAILURE(status))
495 return AE_OK; /* continue */
496
497 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
498 acpi_memory_device_notify, NULL);
499 /* continue */
500 return AE_OK;
501}
502
503static acpi_status
504acpi_memory_deregister_notify_handler(acpi_handle handle,
505 u32 level, void *ctxt, void **retv)
506{
507 acpi_status status;
508
509
510 status = is_memory_device(handle);
511 if (ACPI_FAILURE(status))
512 return AE_OK; /* continue */
513
514 status = acpi_remove_notify_handler(handle,
515 ACPI_SYSTEM_NOTIFY,
516 acpi_memory_device_notify);
517
518 return AE_OK; /* continue */
519}
520
521static int __init acpi_memory_device_init(void)
522{
523 int result;
524 acpi_status status;
525
526
527 result = acpi_bus_register_driver(&acpi_memory_device_driver);
528
529 if (result < 0)
530 return -ENODEV;
531
532 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
533 ACPI_UINT32_MAX,
534 acpi_memory_register_notify_handler, NULL,
535 NULL, NULL);
536
537 if (ACPI_FAILURE(status)) {
538 ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
539 acpi_bus_unregister_driver(&acpi_memory_device_driver);
540 return -ENODEV;
541 }
542
543 return 0;
544} 320}
545 321
546static void __exit acpi_memory_device_exit(void) 322void __init acpi_memory_hotplug_init(void)
547{ 323{
548 acpi_status status; 324 acpi_scan_add_handler_with_hotplug(&memory_device_handler, "memory");
549
550
551 /*
552 * Adding this to un-install notification handlers for all the device
553 * handles.
554 */
555 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
556 ACPI_UINT32_MAX,
557 acpi_memory_deregister_notify_handler, NULL,
558 NULL, NULL);
559
560 if (ACPI_FAILURE(status))
561 ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
562
563 acpi_bus_unregister_driver(&acpi_memory_device_driver);
564
565 return;
566} 325}
567
568module_init(acpi_memory_device_init);
569module_exit(acpi_memory_device_exit);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 5523ba7d764d..f9f8a08827fa 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * acpi_container.c - ACPI Generic Container Driver 2 * container.c - ACPI Generic Container Driver
3 * ($Revision: )
4 * 3 *
5 * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com) 4 * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
6 * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com) 5 * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
7 * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com) 6 * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
8 * Copyright (C) 2004 Intel Corp.
9 * Copyright (C) 2004 FUJITSU LIMITED 7 * Copyright (C) 2004 FUJITSU LIMITED
8 * Copyright (C) 2004, 2013 Intel Corp.
9 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
10 * 10 *
11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12 * 12 *
@@ -26,14 +26,9 @@
26 * 26 *
27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 */ 28 */
29#include <linux/kernel.h>
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/slab.h>
33#include <linux/types.h>
34#include <linux/acpi.h> 29#include <linux/acpi.h>
35#include <acpi/acpi_bus.h> 30
36#include <acpi/acpi_drivers.h> 31#include "internal.h"
37 32
38#define PREFIX "ACPI: " 33#define PREFIX "ACPI: "
39 34
@@ -50,141 +45,20 @@ static const struct acpi_device_id container_device_ids[] = {
50static int container_device_attach(struct acpi_device *device, 45static int container_device_attach(struct acpi_device *device,
51 const struct acpi_device_id *not_used) 46 const struct acpi_device_id *not_used)
52{ 47{
53 /* 48 /* This is necessary for container hotplug to work. */
54 * FIXME: This is necessary, so that acpi_eject_store() doesn't return
55 * -ENODEV for containers.
56 */
57 return 1; 49 return 1;
58} 50}
59 51
60static struct acpi_scan_handler container_device_handler = { 52static struct acpi_scan_handler container_handler = {
61 .ids = container_device_ids, 53 .ids = container_device_ids,
62 .attach = container_device_attach, 54 .attach = container_device_attach,
55 .hotplug = {
56 .enabled = true,
57 .mode = AHM_CONTAINER,
58 },
63}; 59};
64 60
65static int is_device_present(acpi_handle handle)
66{
67 acpi_handle temp;
68 acpi_status status;
69 unsigned long long sta;
70
71
72 status = acpi_get_handle(handle, "_STA", &temp);
73 if (ACPI_FAILURE(status))
74 return 1; /* _STA not found, assume device present */
75
76 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
77 if (ACPI_FAILURE(status))
78 return 0; /* Firmware error */
79
80 return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
81}
82
83static void container_notify_cb(acpi_handle handle, u32 type, void *context)
84{
85 struct acpi_device *device = NULL;
86 int result;
87 int present;
88 acpi_status status;
89 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
90
91 acpi_scan_lock_acquire();
92
93 switch (type) {
94 case ACPI_NOTIFY_BUS_CHECK:
95 /* Fall through */
96 case ACPI_NOTIFY_DEVICE_CHECK:
97 pr_debug("Container driver received %s event\n",
98 (type == ACPI_NOTIFY_BUS_CHECK) ?
99 "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
100
101 present = is_device_present(handle);
102 status = acpi_bus_get_device(handle, &device);
103 if (!present) {
104 if (ACPI_SUCCESS(status)) {
105 /* device exist and this is a remove request */
106 device->flags.eject_pending = 1;
107 kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
108 goto out;
109 }
110 break;
111 }
112
113 if (!ACPI_FAILURE(status) || device)
114 break;
115
116 result = acpi_bus_scan(handle);
117 if (result) {
118 acpi_handle_warn(handle, "Failed to add container\n");
119 break;
120 }
121 result = acpi_bus_get_device(handle, &device);
122 if (result) {
123 acpi_handle_warn(handle, "Missing device object\n");
124 break;
125 }
126
127 kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
128 ost_code = ACPI_OST_SC_SUCCESS;
129 break;
130
131 case ACPI_NOTIFY_EJECT_REQUEST:
132 if (!acpi_bus_get_device(handle, &device) && device) {
133 device->flags.eject_pending = 1;
134 kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
135 goto out;
136 }
137 break;
138
139 default:
140 /* non-hotplug event; possibly handled by other handler */
141 goto out;
142 }
143
144 /* Inform firmware that the hotplug operation has completed */
145 (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
146
147 out:
148 acpi_scan_lock_release();
149}
150
151static bool is_container(acpi_handle handle)
152{
153 struct acpi_device_info *info;
154 bool ret = false;
155
156 if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
157 return false;
158
159 if (info->valid & ACPI_VALID_HID) {
160 const struct acpi_device_id *id;
161
162 for (id = container_device_ids; id->id[0]; id++) {
163 ret = !strcmp((char *)id->id, info->hardware_id.string);
164 if (ret)
165 break;
166 }
167 }
168 kfree(info);
169 return ret;
170}
171
172static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
173 u32 lvl, void *ctxt,
174 void **retv)
175{
176 if (is_container(handle))
177 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
178 container_notify_cb, NULL);
179
180 return AE_OK;
181}
182
183void __init acpi_container_init(void) 61void __init acpi_container_init(void)
184{ 62{
185 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 63 acpi_scan_add_handler_with_hotplug(&container_handler, "container");
186 acpi_container_register_notify_handler, NULL,
187 NULL, NULL);
188
189 acpi_scan_add_handler(&container_device_handler);
190} 64}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 3c94a732b4b3..7f094adfe05a 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -41,6 +41,17 @@ void acpi_container_init(void);
41#else 41#else
42static inline void acpi_container_init(void) {} 42static inline void acpi_container_init(void) {}
43#endif 43#endif
44#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
45void acpi_memory_hotplug_init(void);
46#else
47static inline void acpi_memory_hotplug_init(void) {}
48#endif
49
50void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
51 const char *name);
52int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
53 const char *hotplug_profile_name);
54void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);
44 55
45#ifdef CONFIG_DEBUG_FS 56#ifdef CONFIG_DEBUG_FS
46extern struct dentry *acpi_debugfs_dir; 57extern struct dentry *acpi_debugfs_dir;
@@ -60,7 +71,7 @@ int acpi_device_add(struct acpi_device *device,
60void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, 71void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
61 int type, unsigned long long sta); 72 int type, unsigned long long sta);
62void acpi_device_add_finalize(struct acpi_device *device); 73void acpi_device_add_finalize(struct acpi_device *device);
63void acpi_free_ids(struct acpi_device *device); 74void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
64 75
65/* -------------------------------------------------------------------------- 76/* --------------------------------------------------------------------------
66 Power Resource 77 Power Resource
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 34f5ef11d427..0481b1b1d2aa 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -824,7 +824,7 @@ static void acpi_release_power_resource(struct device *dev)
824 list_del(&resource->list_node); 824 list_del(&resource->list_node);
825 mutex_unlock(&power_resource_list_lock); 825 mutex_unlock(&power_resource_list_lock);
826 826
827 acpi_free_ids(device); 827 acpi_free_pnp_ids(&device->pnp);
828 kfree(resource); 828 kfree(resource);
829} 829}
830 830
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5e7e991717d7..8cacc16af6e7 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -63,6 +63,19 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler)
63 return 0; 63 return 0;
64} 64}
65 65
66int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
67 const char *hotplug_profile_name)
68{
69 int error;
70
71 error = acpi_scan_add_handler(handler);
72 if (error)
73 return error;
74
75 acpi_sysfs_add_hotplug_profile(&handler->hotplug, hotplug_profile_name);
76 return 0;
77}
78
66/* 79/*
67 * Creates hid/cid(s) string needed for modalias and uevent 80 * Creates hid/cid(s) string needed for modalias and uevent
68 * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: 81 * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -107,32 +120,20 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha
107} 120}
108static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); 121static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
109 122
110/** 123static int acpi_scan_hot_remove(struct acpi_device *device)
111 * acpi_bus_hot_remove_device: hot-remove a device and its children
112 * @context: struct acpi_eject_event pointer (freed in this func)
113 *
114 * Hot-remove a device and its children. This function frees up the
115 * memory space passed by arg context, so that the caller may call
116 * this function asynchronously through acpi_os_hotplug_execute().
117 */
118void acpi_bus_hot_remove_device(void *context)
119{ 124{
120 struct acpi_eject_event *ej_event = context;
121 struct acpi_device *device = ej_event->device;
122 acpi_handle handle = device->handle; 125 acpi_handle handle = device->handle;
123 acpi_handle temp; 126 acpi_handle not_used;
124 struct acpi_object_list arg_list; 127 struct acpi_object_list arg_list;
125 union acpi_object arg; 128 union acpi_object arg;
126 acpi_status status = AE_OK; 129 acpi_status status;
127 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ 130 unsigned long long sta;
128
129 mutex_lock(&acpi_scan_lock);
130 131
131 /* If there is no handle, the device node has been unregistered. */ 132 /* If there is no handle, the device node has been unregistered. */
132 if (!device->handle) { 133 if (!handle) {
133 dev_dbg(&device->dev, "ACPI handle missing\n"); 134 dev_dbg(&device->dev, "ACPI handle missing\n");
134 put_device(&device->dev); 135 put_device(&device->dev);
135 goto out; 136 return -EINVAL;
136 } 137 }
137 138
138 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 139 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -143,7 +144,7 @@ void acpi_bus_hot_remove_device(void *context)
143 put_device(&device->dev); 144 put_device(&device->dev);
144 device = NULL; 145 device = NULL;
145 146
146 if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { 147 if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &not_used))) {
147 arg_list.count = 1; 148 arg_list.count = 1;
148 arg_list.pointer = &arg; 149 arg_list.pointer = &arg;
149 arg.type = ACPI_TYPE_INTEGER; 150 arg.type = ACPI_TYPE_INTEGER;
@@ -161,18 +162,205 @@ void acpi_bus_hot_remove_device(void *context)
161 */ 162 */
162 status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); 163 status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
163 if (ACPI_FAILURE(status)) { 164 if (ACPI_FAILURE(status)) {
164 if (status != AE_NOT_FOUND) 165 if (status == AE_NOT_FOUND) {
165 acpi_handle_warn(handle, "Eject failed\n"); 166 return -ENODEV;
167 } else {
168 acpi_handle_warn(handle, "Eject failed (0x%x)\n",
169 status);
170 return -EIO;
171 }
172 }
166 173
167 /* Tell the firmware the hot-remove operation has failed. */ 174 /*
168 acpi_evaluate_hotplug_ost(handle, ej_event->event, 175 * Verify if eject was indeed successful. If not, log an error
169 ost_code, NULL); 176 * message. No need to call _OST since _EJ0 call was made OK.
177 */
178 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
179 if (ACPI_FAILURE(status)) {
180 acpi_handle_warn(handle,
181 "Status check after eject failed (0x%x)\n", status);
182 } else if (sta & ACPI_STA_DEVICE_ENABLED) {
183 acpi_handle_warn(handle,
184 "Eject incomplete - status 0x%llx\n", sta);
185 }
186
187 return 0;
188}
189
190static void acpi_bus_device_eject(void *context)
191{
192 acpi_handle handle = context;
193 struct acpi_device *device = NULL;
194 struct acpi_scan_handler *handler;
195 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
196
197 mutex_lock(&acpi_scan_lock);
198
199 acpi_bus_get_device(handle, &device);
200 if (!device)
201 goto err_out;
202
203 handler = device->handler;
204 if (!handler || !handler->hotplug.enabled) {
205 ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
206 goto err_out;
207 }
208 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST,
209 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
210 if (handler->hotplug.mode == AHM_CONTAINER) {
211 device->flags.eject_pending = true;
212 kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
213 } else {
214 int error;
215
216 get_device(&device->dev);
217 error = acpi_scan_hot_remove(device);
218 if (error)
219 goto err_out;
170 } 220 }
171 221
172 out: 222 out:
173 mutex_unlock(&acpi_scan_lock); 223 mutex_unlock(&acpi_scan_lock);
174 kfree(context);
175 return; 224 return;
225
226 err_out:
227 acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code,
228 NULL);
229 goto out;
230}
231
232static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source)
233{
234 struct acpi_device *device = NULL;
235 u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
236 int error;
237
238 mutex_lock(&acpi_scan_lock);
239
240 acpi_bus_get_device(handle, &device);
241 if (device) {
242 dev_warn(&device->dev, "Attempt to re-insert\n");
243 goto out;
244 }
245 acpi_evaluate_hotplug_ost(handle, ost_source,
246 ACPI_OST_SC_INSERT_IN_PROGRESS, NULL);
247 error = acpi_bus_scan(handle);
248 if (error) {
249 acpi_handle_warn(handle, "Namespace scan failure\n");
250 goto out;
251 }
252 error = acpi_bus_get_device(handle, &device);
253 if (error) {
254 acpi_handle_warn(handle, "Missing device node object\n");
255 goto out;
256 }
257 ost_code = ACPI_OST_SC_SUCCESS;
258 if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER)
259 kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
260
261 out:
262 acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL);
263 mutex_unlock(&acpi_scan_lock);
264}
265
266static void acpi_scan_bus_check(void *context)
267{
268 acpi_scan_bus_device_check((acpi_handle)context,
269 ACPI_NOTIFY_BUS_CHECK);
270}
271
272static void acpi_scan_device_check(void *context)
273{
274 acpi_scan_bus_device_check((acpi_handle)context,
275 ACPI_NOTIFY_DEVICE_CHECK);
276}
277
278static void acpi_hotplug_unsupported(acpi_handle handle, u32 type)
279{
280 u32 ost_status;
281
282 switch (type) {
283 case ACPI_NOTIFY_BUS_CHECK:
284 acpi_handle_debug(handle,
285 "ACPI_NOTIFY_BUS_CHECK event: unsupported\n");
286 ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
287 break;
288 case ACPI_NOTIFY_DEVICE_CHECK:
289 acpi_handle_debug(handle,
290 "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n");
291 ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED;
292 break;
293 case ACPI_NOTIFY_EJECT_REQUEST:
294 acpi_handle_debug(handle,
295 "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n");
296 ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
297 break;
298 default:
299 /* non-hotplug event; possibly handled by other handler */
300 return;
301 }
302
303 acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL);
304}
305
306static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
307{
308 acpi_osd_exec_callback callback;
309 struct acpi_scan_handler *handler = data;
310 acpi_status status;
311
312 if (!handler->hotplug.enabled)
313 return acpi_hotplug_unsupported(handle, type);
314
315 switch (type) {
316 case ACPI_NOTIFY_BUS_CHECK:
317 acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n");
318 callback = acpi_scan_bus_check;
319 break;
320 case ACPI_NOTIFY_DEVICE_CHECK:
321 acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n");
322 callback = acpi_scan_device_check;
323 break;
324 case ACPI_NOTIFY_EJECT_REQUEST:
325 acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
326 callback = acpi_bus_device_eject;
327 break;
328 default:
329 /* non-hotplug event; possibly handled by other handler */
330 return;
331 }
332 status = acpi_os_hotplug_execute(callback, handle);
333 if (ACPI_FAILURE(status))
334 acpi_evaluate_hotplug_ost(handle, type,
335 ACPI_OST_SC_NON_SPECIFIC_FAILURE,
336 NULL);
337}
338
339/**
340 * acpi_bus_hot_remove_device: hot-remove a device and its children
341 * @context: struct acpi_eject_event pointer (freed in this func)
342 *
343 * Hot-remove a device and its children. This function frees up the
344 * memory space passed by arg context, so that the caller may call
345 * this function asynchronously through acpi_os_hotplug_execute().
346 */
347void acpi_bus_hot_remove_device(void *context)
348{
349 struct acpi_eject_event *ej_event = context;
350 struct acpi_device *device = ej_event->device;
351 acpi_handle handle = device->handle;
352 int error;
353
354 mutex_lock(&acpi_scan_lock);
355
356 error = acpi_scan_hot_remove(device);
357 if (error && handle)
358 acpi_evaluate_hotplug_ost(handle, ej_event->event,
359 ACPI_OST_SC_NON_SPECIFIC_FAILURE,
360 NULL);
361
362 mutex_unlock(&acpi_scan_lock);
363 kfree(context);
176} 364}
177EXPORT_SYMBOL(acpi_bus_hot_remove_device); 365EXPORT_SYMBOL(acpi_bus_hot_remove_device);
178 366
@@ -206,51 +394,61 @@ static ssize_t
206acpi_eject_store(struct device *d, struct device_attribute *attr, 394acpi_eject_store(struct device *d, struct device_attribute *attr,
207 const char *buf, size_t count) 395 const char *buf, size_t count)
208{ 396{
209 int ret = count;
210 acpi_status status;
211 acpi_object_type type = 0;
212 struct acpi_device *acpi_device = to_acpi_device(d); 397 struct acpi_device *acpi_device = to_acpi_device(d);
213 struct acpi_eject_event *ej_event; 398 struct acpi_eject_event *ej_event;
399 acpi_object_type not_used;
400 acpi_status status;
401 u32 ost_source;
402 int ret;
214 403
215 if ((!count) || (buf[0] != '1')) { 404 if (!count || buf[0] != '1')
216 return -EINVAL; 405 return -EINVAL;
217 }
218 if (!acpi_device->driver && !acpi_device->handler) {
219 ret = -ENODEV;
220 goto err;
221 }
222 status = acpi_get_type(acpi_device->handle, &type);
223 if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
224 ret = -ENODEV;
225 goto err;
226 }
227 406
228 ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); 407 if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled)
229 if (!ej_event) { 408 && !acpi_device->driver)
230 ret = -ENOMEM; 409 return -ENODEV;
231 goto err; 410
232 } 411 status = acpi_get_type(acpi_device->handle, &not_used);
412 if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable)
413 return -ENODEV;
414
415 mutex_lock(&acpi_scan_lock);
233 416
234 get_device(&acpi_device->dev);
235 ej_event->device = acpi_device;
236 if (acpi_device->flags.eject_pending) { 417 if (acpi_device->flags.eject_pending) {
237 /* event originated from ACPI eject notification */ 418 /* ACPI eject notification event. */
238 ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; 419 ost_source = ACPI_NOTIFY_EJECT_REQUEST;
239 acpi_device->flags.eject_pending = 0; 420 acpi_device->flags.eject_pending = 0;
240 } else { 421 } else {
241 /* event originated from user */ 422 /* Eject initiated by user space. */
242 ej_event->event = ACPI_OST_EC_OSPM_EJECT; 423 ost_source = ACPI_OST_EC_OSPM_EJECT;
243 (void) acpi_evaluate_hotplug_ost(acpi_device->handle,
244 ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
245 } 424 }
246 425 ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
426 if (!ej_event) {
427 ret = -ENOMEM;
428 goto err_out;
429 }
430 acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
431 ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
432 ej_event->device = acpi_device;
433 ej_event->event = ost_source;
434 get_device(&acpi_device->dev);
247 status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); 435 status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
248 if (ACPI_FAILURE(status)) { 436 if (ACPI_FAILURE(status)) {
249 put_device(&acpi_device->dev); 437 put_device(&acpi_device->dev);
250 kfree(ej_event); 438 kfree(ej_event);
439 ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
440 goto err_out;
251 } 441 }
252err: 442 ret = count;
443
444 out:
445 mutex_unlock(&acpi_scan_lock);
253 return ret; 446 return ret;
447
448 err_out:
449 acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source,
450 ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL);
451 goto out;
254} 452}
255 453
256static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); 454static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
@@ -376,7 +574,7 @@ static int acpi_device_setup_files(struct acpi_device *dev)
376 goto end; 574 goto end;
377 } 575 }
378 576
379 if (dev->flags.bus_address) 577 if (dev->pnp.type.bus_address)
380 result = device_create_file(&dev->dev, &dev_attr_adr); 578 result = device_create_file(&dev->dev, &dev_attr_adr);
381 if (dev->pnp.unique_id) 579 if (dev->pnp.unique_id)
382 result = device_create_file(&dev->dev, &dev_attr_uid); 580 result = device_create_file(&dev->dev, &dev_attr_uid);
@@ -449,7 +647,7 @@ static void acpi_device_remove_files(struct acpi_device *dev)
449 647
450 if (dev->pnp.unique_id) 648 if (dev->pnp.unique_id)
451 device_remove_file(&dev->dev, &dev_attr_uid); 649 device_remove_file(&dev->dev, &dev_attr_uid);
452 if (dev->flags.bus_address) 650 if (dev->pnp.type.bus_address)
453 device_remove_file(&dev->dev, &dev_attr_adr); 651 device_remove_file(&dev->dev, &dev_attr_adr);
454 device_remove_file(&dev->dev, &dev_attr_modalias); 652 device_remove_file(&dev->dev, &dev_attr_modalias);
455 device_remove_file(&dev->dev, &dev_attr_hid); 653 device_remove_file(&dev->dev, &dev_attr_hid);
@@ -512,17 +710,6 @@ int acpi_match_device_ids(struct acpi_device *device,
512} 710}
513EXPORT_SYMBOL(acpi_match_device_ids); 711EXPORT_SYMBOL(acpi_match_device_ids);
514 712
515void acpi_free_ids(struct acpi_device *device)
516{
517 struct acpi_hardware_id *id, *tmp;
518
519 list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) {
520 kfree(id->id);
521 kfree(id);
522 }
523 kfree(device->pnp.unique_id);
524}
525
526static void acpi_free_power_resources_lists(struct acpi_device *device) 713static void acpi_free_power_resources_lists(struct acpi_device *device)
527{ 714{
528 int i; 715 int i;
@@ -543,7 +730,7 @@ static void acpi_device_release(struct device *dev)
543{ 730{
544 struct acpi_device *acpi_dev = to_acpi_device(dev); 731 struct acpi_device *acpi_dev = to_acpi_device(dev);
545 732
546 acpi_free_ids(acpi_dev); 733 acpi_free_pnp_ids(&acpi_dev->pnp);
547 acpi_free_power_resources_lists(acpi_dev); 734 acpi_free_power_resources_lists(acpi_dev);
548 kfree(acpi_dev); 735 kfree(acpi_dev);
549} 736}
@@ -1256,19 +1443,17 @@ static void acpi_device_get_busid(struct acpi_device *device)
1256} 1443}
1257 1444
1258/* 1445/*
1259 * acpi_bay_match - see if a device is an ejectable driver bay 1446 * acpi_bay_match - see if an acpi object is an ejectable driver bay
1260 * 1447 *
1261 * If an acpi object is ejectable and has one of the ACPI ATA methods defined, 1448 * If an acpi object is ejectable and has one of the ACPI ATA methods defined,
1262 * then we can safely call it an ejectable drive bay 1449 * then we can safely call it an ejectable drive bay
1263 */ 1450 */
1264static int acpi_bay_match(struct acpi_device *device){ 1451static int acpi_bay_match(acpi_handle handle)
1452{
1265 acpi_status status; 1453 acpi_status status;
1266 acpi_handle handle;
1267 acpi_handle tmp; 1454 acpi_handle tmp;
1268 acpi_handle phandle; 1455 acpi_handle phandle;
1269 1456
1270 handle = device->handle;
1271
1272 status = acpi_get_handle(handle, "_EJ0", &tmp); 1457 status = acpi_get_handle(handle, "_EJ0", &tmp);
1273 if (ACPI_FAILURE(status)) 1458 if (ACPI_FAILURE(status))
1274 return -ENODEV; 1459 return -ENODEV;
@@ -1292,12 +1477,12 @@ static int acpi_bay_match(struct acpi_device *device){
1292} 1477}
1293 1478
1294/* 1479/*
1295 * acpi_dock_match - see if a device has a _DCK method 1480 * acpi_dock_match - see if an acpi object has a _DCK method
1296 */ 1481 */
1297static int acpi_dock_match(struct acpi_device *device) 1482static int acpi_dock_match(acpi_handle handle)
1298{ 1483{
1299 acpi_handle tmp; 1484 acpi_handle tmp;
1300 return acpi_get_handle(device->handle, "_DCK", &tmp); 1485 return acpi_get_handle(handle, "_DCK", &tmp);
1301} 1486}
1302 1487
1303const char *acpi_device_hid(struct acpi_device *device) 1488const char *acpi_device_hid(struct acpi_device *device)
@@ -1312,7 +1497,7 @@ const char *acpi_device_hid(struct acpi_device *device)
1312} 1497}
1313EXPORT_SYMBOL(acpi_device_hid); 1498EXPORT_SYMBOL(acpi_device_hid);
1314 1499
1315static void acpi_add_id(struct acpi_device *device, const char *dev_id) 1500static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id)
1316{ 1501{
1317 struct acpi_hardware_id *id; 1502 struct acpi_hardware_id *id;
1318 1503
@@ -1326,7 +1511,8 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
1326 return; 1511 return;
1327 } 1512 }
1328 1513
1329 list_add_tail(&id->list, &device->pnp.ids); 1514 list_add_tail(&id->list, &pnp->ids);
1515 pnp->type.hardware_id = 1;
1330} 1516}
1331 1517
1332/* 1518/*
@@ -1334,7 +1520,7 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id)
1334 * lacks the SMBUS01 HID and the methods do not have the necessary "_" 1520 * lacks the SMBUS01 HID and the methods do not have the necessary "_"
1335 * prefix. Work around this. 1521 * prefix. Work around this.
1336 */ 1522 */
1337static int acpi_ibm_smbus_match(struct acpi_device *device) 1523static int acpi_ibm_smbus_match(acpi_handle handle)
1338{ 1524{
1339 acpi_handle h_dummy; 1525 acpi_handle h_dummy;
1340 struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; 1526 struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -1344,7 +1530,7 @@ static int acpi_ibm_smbus_match(struct acpi_device *device)
1344 return -ENODEV; 1530 return -ENODEV;
1345 1531
1346 /* Look for SMBS object */ 1532 /* Look for SMBS object */
1347 result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path); 1533 result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path);
1348 if (result) 1534 if (result)
1349 return result; 1535 return result;
1350 1536
@@ -1355,48 +1541,50 @@ static int acpi_ibm_smbus_match(struct acpi_device *device)
1355 1541
1356 /* Does it have the necessary (but misnamed) methods? */ 1542 /* Does it have the necessary (but misnamed) methods? */
1357 result = -ENODEV; 1543 result = -ENODEV;
1358 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) && 1544 if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) &&
1359 ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) && 1545 ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) &&
1360 ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy))) 1546 ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy)))
1361 result = 0; 1547 result = 0;
1362out: 1548out:
1363 kfree(path.pointer); 1549 kfree(path.pointer);
1364 return result; 1550 return result;
1365} 1551}
1366 1552
1367static void acpi_device_set_id(struct acpi_device *device) 1553static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
1554 int device_type)
1368{ 1555{
1369 acpi_status status; 1556 acpi_status status;
1370 struct acpi_device_info *info; 1557 struct acpi_device_info *info;
1371 struct acpi_pnp_device_id_list *cid_list; 1558 struct acpi_pnp_device_id_list *cid_list;
1372 int i; 1559 int i;
1373 1560
1374 switch (device->device_type) { 1561 switch (device_type) {
1375 case ACPI_BUS_TYPE_DEVICE: 1562 case ACPI_BUS_TYPE_DEVICE:
1376 if (ACPI_IS_ROOT_DEVICE(device)) { 1563 if (handle == ACPI_ROOT_OBJECT) {
1377 acpi_add_id(device, ACPI_SYSTEM_HID); 1564 acpi_add_id(pnp, ACPI_SYSTEM_HID);
1378 break; 1565 break;
1379 } 1566 }
1380 1567
1381 status = acpi_get_object_info(device->handle, &info); 1568 status = acpi_get_object_info(handle, &info);
1382 if (ACPI_FAILURE(status)) { 1569 if (ACPI_FAILURE(status)) {
1383 printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); 1570 pr_err(PREFIX "%s: Error reading device info\n",
1571 __func__);
1384 return; 1572 return;
1385 } 1573 }
1386 1574
1387 if (info->valid & ACPI_VALID_HID) 1575 if (info->valid & ACPI_VALID_HID)
1388 acpi_add_id(device, info->hardware_id.string); 1576 acpi_add_id(pnp, info->hardware_id.string);
1389 if (info->valid & ACPI_VALID_CID) { 1577 if (info->valid & ACPI_VALID_CID) {
1390 cid_list = &info->compatible_id_list; 1578 cid_list = &info->compatible_id_list;
1391 for (i = 0; i < cid_list->count; i++) 1579 for (i = 0; i < cid_list->count; i++)
1392 acpi_add_id(device, cid_list->ids[i].string); 1580 acpi_add_id(pnp, cid_list->ids[i].string);
1393 } 1581 }
1394 if (info->valid & ACPI_VALID_ADR) { 1582 if (info->valid & ACPI_VALID_ADR) {
1395 device->pnp.bus_address = info->address; 1583 pnp->bus_address = info->address;
1396 device->flags.bus_address = 1; 1584 pnp->type.bus_address = 1;
1397 } 1585 }
1398 if (info->valid & ACPI_VALID_UID) 1586 if (info->valid & ACPI_VALID_UID)
1399 device->pnp.unique_id = kstrdup(info->unique_id.string, 1587 pnp->unique_id = kstrdup(info->unique_id.string,
1400 GFP_KERNEL); 1588 GFP_KERNEL);
1401 1589
1402 kfree(info); 1590 kfree(info);
@@ -1405,40 +1593,50 @@ static void acpi_device_set_id(struct acpi_device *device)
1405 * Some devices don't reliably have _HIDs & _CIDs, so add 1593 * Some devices don't reliably have _HIDs & _CIDs, so add
1406 * synthetic HIDs to make sure drivers can find them. 1594 * synthetic HIDs to make sure drivers can find them.
1407 */ 1595 */
1408 if (acpi_is_video_device(device)) 1596 if (acpi_is_video_device(handle))
1409 acpi_add_id(device, ACPI_VIDEO_HID); 1597 acpi_add_id(pnp, ACPI_VIDEO_HID);
1410 else if (ACPI_SUCCESS(acpi_bay_match(device))) 1598 else if (ACPI_SUCCESS(acpi_bay_match(handle)))
1411 acpi_add_id(device, ACPI_BAY_HID); 1599 acpi_add_id(pnp, ACPI_BAY_HID);
1412 else if (ACPI_SUCCESS(acpi_dock_match(device))) 1600 else if (ACPI_SUCCESS(acpi_dock_match(handle)))
1413 acpi_add_id(device, ACPI_DOCK_HID); 1601 acpi_add_id(pnp, ACPI_DOCK_HID);
1414 else if (!acpi_ibm_smbus_match(device)) 1602 else if (!acpi_ibm_smbus_match(handle))
1415 acpi_add_id(device, ACPI_SMBUS_IBM_HID); 1603 acpi_add_id(pnp, ACPI_SMBUS_IBM_HID);
1416 else if (list_empty(&device->pnp.ids) && 1604 else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) {
1417 ACPI_IS_ROOT_DEVICE(device->parent)) { 1605 acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
1418 acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ 1606 strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME);
1419 strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); 1607 strcpy(pnp->device_class, ACPI_BUS_CLASS);
1420 strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
1421 } 1608 }
1422 1609
1423 break; 1610 break;
1424 case ACPI_BUS_TYPE_POWER: 1611 case ACPI_BUS_TYPE_POWER:
1425 acpi_add_id(device, ACPI_POWER_HID); 1612 acpi_add_id(pnp, ACPI_POWER_HID);
1426 break; 1613 break;
1427 case ACPI_BUS_TYPE_PROCESSOR: 1614 case ACPI_BUS_TYPE_PROCESSOR:
1428 acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID); 1615 acpi_add_id(pnp, ACPI_PROCESSOR_OBJECT_HID);
1429 break; 1616 break;
1430 case ACPI_BUS_TYPE_THERMAL: 1617 case ACPI_BUS_TYPE_THERMAL:
1431 acpi_add_id(device, ACPI_THERMAL_HID); 1618 acpi_add_id(pnp, ACPI_THERMAL_HID);
1432 break; 1619 break;
1433 case ACPI_BUS_TYPE_POWER_BUTTON: 1620 case ACPI_BUS_TYPE_POWER_BUTTON:
1434 acpi_add_id(device, ACPI_BUTTON_HID_POWERF); 1621 acpi_add_id(pnp, ACPI_BUTTON_HID_POWERF);
1435 break; 1622 break;
1436 case ACPI_BUS_TYPE_SLEEP_BUTTON: 1623 case ACPI_BUS_TYPE_SLEEP_BUTTON:
1437 acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); 1624 acpi_add_id(pnp, ACPI_BUTTON_HID_SLEEPF);
1438 break; 1625 break;
1439 } 1626 }
1440} 1627}
1441 1628
1629void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
1630{
1631 struct acpi_hardware_id *id, *tmp;
1632
1633 list_for_each_entry_safe(id, tmp, &pnp->ids, list) {
1634 kfree(id->id);
1635 kfree(id);
1636 }
1637 kfree(pnp->unique_id);
1638}
1639
1442void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, 1640void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
1443 int type, unsigned long long sta) 1641 int type, unsigned long long sta)
1444{ 1642{
@@ -1448,7 +1646,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
1448 device->parent = acpi_bus_get_parent(handle); 1646 device->parent = acpi_bus_get_parent(handle);
1449 STRUCT_TO_INT(device->status) = sta; 1647 STRUCT_TO_INT(device->status) = sta;
1450 acpi_device_get_busid(device); 1648 acpi_device_get_busid(device);
1451 acpi_device_set_id(device); 1649 acpi_set_pnp_ids(handle, &device->pnp, type);
1452 acpi_bus_get_flags(device); 1650 acpi_bus_get_flags(device);
1453 device->flags.match_driver = false; 1651 device->flags.match_driver = false;
1454 device_initialize(&device->dev); 1652 device_initialize(&device->dev);
@@ -1536,6 +1734,75 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
1536 return 0; 1734 return 0;
1537} 1735}
1538 1736
1737static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
1738 char *idstr,
1739 const struct acpi_device_id **matchid)
1740{
1741 const struct acpi_device_id *devid;
1742
1743 for (devid = handler->ids; devid->id[0]; devid++)
1744 if (!strcmp((char *)devid->id, idstr)) {
1745 if (matchid)
1746 *matchid = devid;
1747
1748 return true;
1749 }
1750
1751 return false;
1752}
1753
1754static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
1755 const struct acpi_device_id **matchid)
1756{
1757 struct acpi_scan_handler *handler;
1758
1759 list_for_each_entry(handler, &acpi_scan_handlers_list, list_node)
1760 if (acpi_scan_handler_matching(handler, idstr, matchid))
1761 return handler;
1762
1763 return NULL;
1764}
1765
1766void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
1767{
1768 if (!!hotplug->enabled == !!val)
1769 return;
1770
1771 mutex_lock(&acpi_scan_lock);
1772
1773 hotplug->enabled = val;
1774
1775 mutex_unlock(&acpi_scan_lock);
1776}
1777
1778static void acpi_scan_init_hotplug(acpi_handle handle, int type)
1779{
1780 struct acpi_device_pnp pnp = {};
1781 struct acpi_hardware_id *hwid;
1782 struct acpi_scan_handler *handler;
1783
1784 INIT_LIST_HEAD(&pnp.ids);
1785 acpi_set_pnp_ids(handle, &pnp, type);
1786
1787 if (!pnp.type.hardware_id)
1788 return;
1789
1790 /*
1791 * This relies on the fact that acpi_install_notify_handler() will not
1792 * install the same notify handler routine twice for the same handle.
1793 */
1794 list_for_each_entry(hwid, &pnp.ids, list) {
1795 handler = acpi_scan_match_handler(hwid->id, NULL);
1796 if (handler) {
1797 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
1798 acpi_hotplug_notify_cb, handler);
1799 break;
1800 }
1801 }
1802
1803 acpi_free_pnp_ids(&pnp);
1804}
1805
1539static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, 1806static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1540 void *not_used, void **return_value) 1807 void *not_used, void **return_value)
1541{ 1808{
@@ -1558,6 +1825,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1558 return AE_OK; 1825 return AE_OK;
1559 } 1826 }
1560 1827
1828 acpi_scan_init_hotplug(handle, type);
1829
1561 if (!(sta & ACPI_STA_DEVICE_PRESENT) && 1830 if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
1562 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { 1831 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
1563 struct acpi_device_wakeup wakeup; 1832 struct acpi_device_wakeup wakeup;
@@ -1583,42 +1852,26 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1583 return AE_OK; 1852 return AE_OK;
1584} 1853}
1585 1854
1586static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id) 1855static int acpi_scan_attach_handler(struct acpi_device *device)
1587{ 1856{
1588 struct acpi_scan_handler *handler; 1857 struct acpi_hardware_id *hwid;
1858 int ret = 0;
1589 1859
1590 list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { 1860 list_for_each_entry(hwid, &device->pnp.ids, list) {
1591 const struct acpi_device_id *devid; 1861 const struct acpi_device_id *devid;
1862 struct acpi_scan_handler *handler;
1592 1863
1593 for (devid = handler->ids; devid->id[0]; devid++) { 1864 handler = acpi_scan_match_handler(hwid->id, &devid);
1594 int ret; 1865 if (handler) {
1595
1596 if (strcmp((char *)devid->id, id))
1597 continue;
1598
1599 ret = handler->attach(device, devid); 1866 ret = handler->attach(device, devid);
1600 if (ret > 0) { 1867 if (ret > 0) {
1601 device->handler = handler; 1868 device->handler = handler;
1602 return ret; 1869 break;
1603 } else if (ret < 0) { 1870 } else if (ret < 0) {
1604 return ret; 1871 break;
1605 } 1872 }
1606 } 1873 }
1607 } 1874 }
1608 return 0;
1609}
1610
1611static int acpi_scan_attach_handler(struct acpi_device *device)
1612{
1613 struct acpi_hardware_id *hwid;
1614 int ret = 0;
1615
1616 list_for_each_entry(hwid, &device->pnp.ids, list) {
1617 ret = acpi_scan_do_attach_handler(device, hwid->id);
1618 if (ret)
1619 break;
1620
1621 }
1622 return ret; 1875 return ret;
1623} 1876}
1624 1877
@@ -1791,6 +2044,7 @@ int __init acpi_scan_init(void)
1791 acpi_csrt_init(); 2044 acpi_csrt_init();
1792 acpi_container_init(); 2045 acpi_container_init();
1793 acpi_pci_slot_init(); 2046 acpi_pci_slot_init();
2047 acpi_memory_hotplug_init();
1794 2048
1795 mutex_lock(&acpi_scan_lock); 2049 mutex_lock(&acpi_scan_lock);
1796 /* 2050 /*
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 41c0504470db..fcae5fa2e1b3 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -7,6 +7,8 @@
7#include <linux/moduleparam.h> 7#include <linux/moduleparam.h>
8#include <acpi/acpi_drivers.h> 8#include <acpi/acpi_drivers.h>
9 9
10#include "internal.h"
11
10#define _COMPONENT ACPI_SYSTEM_COMPONENT 12#define _COMPONENT ACPI_SYSTEM_COMPONENT
11ACPI_MODULE_NAME("sysfs"); 13ACPI_MODULE_NAME("sysfs");
12 14
@@ -249,6 +251,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
249static LIST_HEAD(acpi_table_attr_list); 251static LIST_HEAD(acpi_table_attr_list);
250static struct kobject *tables_kobj; 252static struct kobject *tables_kobj;
251static struct kobject *dynamic_tables_kobj; 253static struct kobject *dynamic_tables_kobj;
254static struct kobject *hotplug_kobj;
252 255
253struct acpi_table_attr { 256struct acpi_table_attr {
254 struct bin_attribute attr; 257 struct bin_attribute attr;
@@ -716,6 +719,67 @@ acpi_show_profile(struct device *dev, struct device_attribute *attr,
716static const struct device_attribute pm_profile_attr = 719static const struct device_attribute pm_profile_attr =
717 __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL); 720 __ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
718 721
722static ssize_t hotplug_enabled_show(struct kobject *kobj,
723 struct kobj_attribute *attr, char *buf)
724{
725 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
726
727 return sprintf(buf, "%d\n", hotplug->enabled);
728}
729
730static ssize_t hotplug_enabled_store(struct kobject *kobj,
731 struct kobj_attribute *attr,
732 const char *buf, size_t size)
733{
734 struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
735 unsigned int val;
736
737 if (kstrtouint(buf, 10, &val) || val > 1)
738 return -EINVAL;
739
740 acpi_scan_hotplug_enabled(hotplug, val);
741 return size;
742}
743
744static struct kobj_attribute hotplug_enabled_attr =
745 __ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show,
746 hotplug_enabled_store);
747
748static struct attribute *hotplug_profile_attrs[] = {
749 &hotplug_enabled_attr.attr,
750 NULL
751};
752
753static struct kobj_type acpi_hotplug_profile_ktype = {
754 .sysfs_ops = &kobj_sysfs_ops,
755 .default_attrs = hotplug_profile_attrs,
756};
757
758void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
759 const char *name)
760{
761 int error;
762
763 if (!hotplug_kobj)
764 goto err_out;
765
766 kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype);
767 error = kobject_set_name(&hotplug->kobj, "%s", name);
768 if (error)
769 goto err_out;
770
771 hotplug->kobj.parent = hotplug_kobj;
772 error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL);
773 if (error)
774 goto err_out;
775
776 kobject_uevent(&hotplug->kobj, KOBJ_ADD);
777 return;
778
779 err_out:
780 pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name);
781}
782
719int __init acpi_sysfs_init(void) 783int __init acpi_sysfs_init(void)
720{ 784{
721 int result; 785 int result;
@@ -723,6 +787,8 @@ int __init acpi_sysfs_init(void)
723 result = acpi_tables_sysfs_init(); 787 result = acpi_tables_sysfs_init();
724 if (result) 788 if (result)
725 return result; 789 return result;
790
791 hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
726 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr); 792 result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
727 return result; 793 return result;
728} 794}
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 4ac2593234e7..66f67626f02e 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -67,40 +67,37 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context,
67 return 0; 67 return 0;
68} 68}
69 69
70/* Returns true if the device is a video device which can be handled by 70/* Returns true if the ACPI object is a video device which can be
71 * video.ko. 71 * handled by video.ko.
72 * The device will get a Linux specific CID added in scan.c to 72 * The device will get a Linux specific CID added in scan.c to
73 * identify the device as an ACPI graphics device 73 * identify the device as an ACPI graphics device
74 * Be aware that the graphics device may not be physically present 74 * Be aware that the graphics device may not be physically present
75 * Use acpi_video_get_capabilities() to detect general ACPI video 75 * Use acpi_video_get_capabilities() to detect general ACPI video
76 * capabilities of present cards 76 * capabilities of present cards
77 */ 77 */
78long acpi_is_video_device(struct acpi_device *device) 78long acpi_is_video_device(acpi_handle handle)
79{ 79{
80 acpi_handle h_dummy; 80 acpi_handle h_dummy;
81 long video_caps = 0; 81 long video_caps = 0;
82 82
83 if (!device)
84 return 0;
85
86 /* Is this device able to support video switching ? */ 83 /* Is this device able to support video switching ? */
87 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) || 84 if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) ||
88 ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) 85 ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy)))
89 video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; 86 video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
90 87
91 /* Is this device able to retrieve a video ROM ? */ 88 /* Is this device able to retrieve a video ROM ? */
92 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) 89 if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy)))
93 video_caps |= ACPI_VIDEO_ROM_AVAILABLE; 90 video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
94 91
95 /* Is this device able to configure which video head to be POSTed ? */ 92 /* Is this device able to configure which video head to be POSTed ? */
96 if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && 93 if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) &&
97 ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && 94 ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) &&
98 ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) 95 ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy)))
99 video_caps |= ACPI_VIDEO_DEVICE_POSTING; 96 video_caps |= ACPI_VIDEO_DEVICE_POSTING;
100 97
101 /* Only check for backlight functionality if one of the above hit. */ 98 /* Only check for backlight functionality if one of the above hit. */
102 if (video_caps) 99 if (video_caps)
103 acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle, 100 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
104 ACPI_UINT32_MAX, acpi_backlight_cap_match, NULL, 101 ACPI_UINT32_MAX, acpi_backlight_cap_match, NULL,
105 &video_caps, NULL); 102 &video_caps, NULL);
106 103
@@ -127,7 +124,7 @@ find_video(acpi_handle handle, u32 lvl, void *context, void **rv)
127 if (!dev) 124 if (!dev)
128 return AE_OK; 125 return AE_OK;
129 pci_dev_put(dev); 126 pci_dev_put(dev);
130 *cap |= acpi_is_video_device(acpi_dev); 127 *cap |= acpi_is_video_device(handle);
131 } 128 }
132 return AE_OK; 129 return AE_OK;
133} 130}