]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
68a67f6c | 2 | * container.c - ACPI Generic Container Driver |
1da177e4 LT |
3 | * |
4 | * Copyright (C) 2004 Anil S Keshavamurthy ([email protected]) | |
5 | * Copyright (C) 2004 Keiichiro Tokunaga ([email protected]) | |
6 | * Copyright (C) 2004 Motoyuki Ito ([email protected]) | |
1da177e4 | 7 | * Copyright (C) 2004 FUJITSU LIMITED |
68a67f6c RW |
8 | * Copyright (C) 2004, 2013 Intel Corp. |
9 | * Author: Rafael J. Wysocki <[email protected]> | |
1da177e4 LT |
10 | * |
11 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or modify | |
14 | * it under the terms of the GNU General Public License as published by | |
15 | * the Free Software Foundation; either version 2 of the License, or (at | |
16 | * your option) any later version. | |
17 | * | |
18 | * This program is distributed in the hope that it will be useful, but | |
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
21 | * General Public License for more details. | |
22 | * | |
23 | * You should have received a copy of the GNU General Public License along | |
24 | * with this program; if not, write to the Free Software Foundation, Inc., | |
25 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
26 | * | |
27 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
28 | */ | |
1da177e4 | 29 | #include <linux/acpi.h> |
caa73ea1 | 30 | #include <linux/container.h> |
1da177e4 | 31 | |
2f9b06fc AS |
32 | #include "internal.h" |
33 | ||
1da177e4 | 34 | #define _COMPONENT ACPI_CONTAINER_COMPONENT |
f52fd66d | 35 | ACPI_MODULE_NAME("container"); |
1da177e4 | 36 | |
1ba90e3a TR |
37 | static const struct acpi_device_id container_device_ids[] = { |
38 | {"ACPI0004", 0}, | |
39 | {"PNP0A05", 0}, | |
40 | {"PNP0A06", 0}, | |
41 | {"", 0}, | |
42 | }; | |
1ba90e3a | 43 | |
a1ec6572 RW |
44 | #ifdef CONFIG_ACPI_CONTAINER |
45 | ||
caa73ea1 RW |
46 | static int acpi_container_offline(struct container_dev *cdev) |
47 | { | |
48 | struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); | |
49 | struct acpi_device *child; | |
50 | ||
51 | /* Check all of the dependent devices' physical companions. */ | |
52 | list_for_each_entry(child, &adev->children, node) | |
53 | if (!acpi_scan_is_offline(child, false)) | |
54 | return -EBUSY; | |
55 | ||
56 | return 0; | |
57 | } | |
58 | ||
59 | static void acpi_container_release(struct device *dev) | |
60 | { | |
61 | kfree(to_container_dev(dev)); | |
62 | } | |
63 | ||
46394fd0 | 64 | static int container_device_attach(struct acpi_device *adev, |
737f1a9f RW |
65 | const struct acpi_device_id *not_used) |
66 | { | |
caa73ea1 RW |
67 | struct container_dev *cdev; |
68 | struct device *dev; | |
69 | int ret; | |
70 | ||
1e2380cd RW |
71 | if (adev->flags.is_dock_station) |
72 | return 0; | |
73 | ||
caa73ea1 RW |
74 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); |
75 | if (!cdev) | |
76 | return -ENOMEM; | |
77 | ||
78 | cdev->offline = acpi_container_offline; | |
79 | dev = &cdev->dev; | |
80 | dev->bus = &container_subsys; | |
81 | dev_set_name(dev, "%s", dev_name(&adev->dev)); | |
82 | ACPI_COMPANION_SET(dev, adev); | |
83 | dev->release = acpi_container_release; | |
84 | ret = device_register(dev); | |
0f6aa09e RW |
85 | if (ret) { |
86 | put_device(dev); | |
caa73ea1 | 87 | return ret; |
0f6aa09e | 88 | } |
caa73ea1 | 89 | adev->driver_data = dev; |
737f1a9f RW |
90 | return 1; |
91 | } | |
92 | ||
46394fd0 RW |
93 | static void container_device_detach(struct acpi_device *adev) |
94 | { | |
caa73ea1 RW |
95 | struct device *dev = acpi_driver_data(adev); |
96 | ||
97 | adev->driver_data = NULL; | |
98 | if (dev) | |
99 | device_unregister(dev); | |
46394fd0 RW |
100 | } |
101 | ||
8ab17fc9 RW |
102 | static void container_device_online(struct acpi_device *adev) |
103 | { | |
104 | struct device *dev = acpi_driver_data(adev); | |
105 | ||
106 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); | |
107 | } | |
108 | ||
79917f34 | 109 | static struct acpi_scan_handler container_handler = { |
1ba90e3a | 110 | .ids = container_device_ids, |
737f1a9f | 111 | .attach = container_device_attach, |
46394fd0 | 112 | .detach = container_device_detach, |
68a67f6c RW |
113 | .hotplug = { |
114 | .enabled = true, | |
caa73ea1 | 115 | .demand_offline = true, |
8ab17fc9 | 116 | .notify_online = container_device_online, |
68a67f6c | 117 | }, |
1da177e4 LT |
118 | }; |
119 | ||
a1ec6572 RW |
120 | void __init acpi_container_init(void) |
121 | { | |
122 | acpi_scan_add_handler(&container_handler); | |
123 | } | |
124 | ||
125 | #else | |
126 | ||
127 | static struct acpi_scan_handler container_handler = { | |
128 | .ids = container_device_ids, | |
129 | }; | |
130 | ||
737f1a9f | 131 | void __init acpi_container_init(void) |
1da177e4 | 132 | { |
79917f34 | 133 | acpi_scan_add_handler_with_hotplug(&container_handler, "container"); |
1da177e4 | 134 | } |
a1ec6572 RW |
135 | |
136 | #endif /* CONFIG_ACPI_CONTAINER */ |