aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/container.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/container.c')
-rw-r--r--drivers/acpi/container.c167
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
48ACPI_MODULE_NAME("container"); 42ACPI_MODULE_NAME("container");
49 43
50MODULE_AUTHOR("Anil S Keshavamurthy");
51MODULE_DESCRIPTION("ACPI container driver");
52MODULE_LICENSE("GPL");
53
54static int acpi_container_add(struct acpi_device *device);
55static int acpi_container_remove(struct acpi_device *device);
56
57static const struct acpi_device_id container_device_ids[] = { 44static 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};
63MODULE_DEVICE_TABLE(acpi, container_device_ids);
64 50
65static struct acpi_driver acpi_container_driver = { 51static 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
61static 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
77static int is_device_present(acpi_handle handle) 66static 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
95static 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/*******************************************************************/
109static 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
128static 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
138static void container_notify_cb(acpi_handle handle, u32 type, void *context) 84static 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
202static acpi_status 148static bool is_container(acpi_handle handle)
203container_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
247static int __init acpi_container_init(void) 169static 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
266static void __exit acpi_container_exit(void) 180void __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
281module_init(acpi_container_init);
282module_exit(acpi_container_exit);