diff options
Diffstat (limited to 'drivers/acpi/container.c')
-rw-r--r-- | drivers/acpi/container.c | 167 |
1 files changed, 36 insertions, 131 deletions
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index cc0bf4613e0d..9053e86e9904 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c | |||
@@ -38,42 +38,31 @@ | |||
38 | 38 | ||
39 | #define PREFIX "ACPI: " | 39 | #define PREFIX "ACPI: " |
40 | 40 | ||
41 | #define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" | ||
42 | #define ACPI_CONTAINER_CLASS "container" | ||
43 | |||
44 | #define INSTALL_NOTIFY_HANDLER 1 | ||
45 | #define UNINSTALL_NOTIFY_HANDLER 2 | ||
46 | |||
47 | #define _COMPONENT ACPI_CONTAINER_COMPONENT | 41 | #define _COMPONENT ACPI_CONTAINER_COMPONENT |
48 | ACPI_MODULE_NAME("container"); | 42 | ACPI_MODULE_NAME("container"); |
49 | 43 | ||
50 | MODULE_AUTHOR("Anil S Keshavamurthy"); | ||
51 | MODULE_DESCRIPTION("ACPI container driver"); | ||
52 | MODULE_LICENSE("GPL"); | ||
53 | |||
54 | static int acpi_container_add(struct acpi_device *device); | ||
55 | static int acpi_container_remove(struct acpi_device *device); | ||
56 | |||
57 | static const struct acpi_device_id container_device_ids[] = { | 44 | static const struct acpi_device_id container_device_ids[] = { |
58 | {"ACPI0004", 0}, | 45 | {"ACPI0004", 0}, |
59 | {"PNP0A05", 0}, | 46 | {"PNP0A05", 0}, |
60 | {"PNP0A06", 0}, | 47 | {"PNP0A06", 0}, |
61 | {"", 0}, | 48 | {"", 0}, |
62 | }; | 49 | }; |
63 | MODULE_DEVICE_TABLE(acpi, container_device_ids); | ||
64 | 50 | ||
65 | static struct acpi_driver acpi_container_driver = { | 51 | static int container_device_attach(struct acpi_device *device, |
66 | .name = "container", | 52 | const struct acpi_device_id *not_used) |
67 | .class = ACPI_CONTAINER_CLASS, | 53 | { |
54 | /* | ||
55 | * FIXME: This is necessary, so that acpi_eject_store() doesn't return | ||
56 | * -ENODEV for containers. | ||
57 | */ | ||
58 | return 1; | ||
59 | } | ||
60 | |||
61 | static struct acpi_scan_handler container_device_handler = { | ||
68 | .ids = container_device_ids, | 62 | .ids = container_device_ids, |
69 | .ops = { | 63 | .attach = container_device_attach, |
70 | .add = acpi_container_add, | ||
71 | .remove = acpi_container_remove, | ||
72 | }, | ||
73 | }; | 64 | }; |
74 | 65 | ||
75 | /*******************************************************************/ | ||
76 | |||
77 | static int is_device_present(acpi_handle handle) | 66 | static int is_device_present(acpi_handle handle) |
78 | { | 67 | { |
79 | acpi_handle temp; | 68 | acpi_handle temp; |
@@ -92,49 +81,6 @@ static int is_device_present(acpi_handle handle) | |||
92 | return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); | 81 | return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT); |
93 | } | 82 | } |
94 | 83 | ||
95 | static bool is_container_device(const char *hid) | ||
96 | { | ||
97 | const struct acpi_device_id *container_id; | ||
98 | |||
99 | for (container_id = container_device_ids; | ||
100 | container_id->id[0]; container_id++) { | ||
101 | if (!strcmp((char *)container_id->id, hid)) | ||
102 | return true; | ||
103 | } | ||
104 | |||
105 | return false; | ||
106 | } | ||
107 | |||
108 | /*******************************************************************/ | ||
109 | static int acpi_container_add(struct acpi_device *device) | ||
110 | { | ||
111 | struct acpi_container *container; | ||
112 | |||
113 | container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL); | ||
114 | if (!container) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | container->handle = device->handle; | ||
118 | strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME); | ||
119 | strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS); | ||
120 | device->driver_data = container; | ||
121 | |||
122 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n", | ||
123 | acpi_device_name(device), acpi_device_bid(device))); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int acpi_container_remove(struct acpi_device *device) | ||
129 | { | ||
130 | acpi_status status = AE_OK; | ||
131 | struct acpi_container *pc = NULL; | ||
132 | |||
133 | pc = acpi_driver_data(device); | ||
134 | kfree(pc); | ||
135 | return status; | ||
136 | } | ||
137 | |||
138 | static void container_notify_cb(acpi_handle handle, u32 type, void *context) | 84 | static void container_notify_cb(acpi_handle handle, u32 type, void *context) |
139 | { | 85 | { |
140 | struct acpi_device *device = NULL; | 86 | struct acpi_device *device = NULL; |
@@ -199,84 +145,43 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context) | |||
199 | return; | 145 | return; |
200 | } | 146 | } |
201 | 147 | ||
202 | static acpi_status | 148 | static bool is_container(acpi_handle handle) |
203 | container_walk_namespace_cb(acpi_handle handle, | ||
204 | u32 lvl, void *context, void **rv) | ||
205 | { | 149 | { |
206 | char *hid = NULL; | ||
207 | struct acpi_device_info *info; | 150 | struct acpi_device_info *info; |
208 | acpi_status status; | 151 | bool ret = false; |
209 | int *action = context; | ||
210 | |||
211 | status = acpi_get_object_info(handle, &info); | ||
212 | if (ACPI_FAILURE(status)) { | ||
213 | return AE_OK; | ||
214 | } | ||
215 | 152 | ||
216 | if (info->valid & ACPI_VALID_HID) | 153 | if (ACPI_FAILURE(acpi_get_object_info(handle, &info))) |
217 | hid = info->hardware_id.string; | 154 | return false; |
218 | 155 | ||
219 | if (hid == NULL) { | 156 | if (info->valid & ACPI_VALID_HID) { |
220 | goto end; | 157 | const struct acpi_device_id *id; |
221 | } | ||
222 | |||
223 | if (!is_container_device(hid)) | ||
224 | goto end; | ||
225 | 158 | ||
226 | switch (*action) { | 159 | for (id = container_device_ids; id->id[0]; id++) { |
227 | case INSTALL_NOTIFY_HANDLER: | 160 | ret = !strcmp((char *)id->id, info->hardware_id.string); |
228 | acpi_install_notify_handler(handle, | 161 | if (ret) |
229 | ACPI_SYSTEM_NOTIFY, | 162 | break; |
230 | container_notify_cb, NULL); | 163 | } |
231 | break; | ||
232 | case UNINSTALL_NOTIFY_HANDLER: | ||
233 | acpi_remove_notify_handler(handle, | ||
234 | ACPI_SYSTEM_NOTIFY, | ||
235 | container_notify_cb); | ||
236 | break; | ||
237 | default: | ||
238 | break; | ||
239 | } | 164 | } |
240 | |||
241 | end: | ||
242 | kfree(info); | 165 | kfree(info); |
243 | 166 | return ret; | |
244 | return AE_OK; | ||
245 | } | 167 | } |
246 | 168 | ||
247 | static int __init acpi_container_init(void) | 169 | static acpi_status acpi_container_register_notify_handler(acpi_handle handle, |
170 | u32 lvl, void *ctxt, | ||
171 | void **retv) | ||
248 | { | 172 | { |
249 | int result = 0; | 173 | if (is_container(handle)) |
250 | int action = INSTALL_NOTIFY_HANDLER; | 174 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
251 | 175 | container_notify_cb, NULL); | |
252 | result = acpi_bus_register_driver(&acpi_container_driver); | ||
253 | if (result < 0) { | ||
254 | return (result); | ||
255 | } | ||
256 | |||
257 | /* register notify handler to every container device */ | ||
258 | acpi_walk_namespace(ACPI_TYPE_DEVICE, | ||
259 | ACPI_ROOT_OBJECT, | ||
260 | ACPI_UINT32_MAX, | ||
261 | container_walk_namespace_cb, NULL, &action, NULL); | ||
262 | 176 | ||
263 | return (0); | 177 | return AE_OK; |
264 | } | 178 | } |
265 | 179 | ||
266 | static void __exit acpi_container_exit(void) | 180 | void __init acpi_container_init(void) |
267 | { | 181 | { |
268 | int action = UNINSTALL_NOTIFY_HANDLER; | 182 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, |
269 | 183 | acpi_container_register_notify_handler, NULL, | |
270 | 184 | NULL, NULL); | |
271 | acpi_walk_namespace(ACPI_TYPE_DEVICE, | ||
272 | ACPI_ROOT_OBJECT, | ||
273 | ACPI_UINT32_MAX, | ||
274 | container_walk_namespace_cb, NULL, &action, NULL); | ||
275 | 185 | ||
276 | acpi_bus_unregister_driver(&acpi_container_driver); | 186 | acpi_scan_add_handler(&container_device_handler); |
277 | |||
278 | return; | ||
279 | } | 187 | } |
280 | |||
281 | module_init(acpi_container_init); | ||
282 | module_exit(acpi_container_exit); | ||