aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2008-10-22 23:25:26 -0400
committerLen Brown <len.brown@intel.com>2008-10-22 23:25:26 -0400
commit47bf31adc541bef0c20de15e800e0011f1ae70c7 (patch)
tree28903879a8570eaefa57942ec3d475d365f5a465 /drivers/acpi
parent4538fad56ee1c16bce0294b5647d2551f0e03164 (diff)
parent0a918a9432cc30aede10f904253b66ea6ab485ac (diff)
Merge branch 'dock' into test
Conflicts: drivers/acpi/osl.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Kconfig11
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/bay.c411
-rw-r--r--drivers/acpi/bus.c15
-rw-r--r--drivers/acpi/dock.c382
-rw-r--r--drivers/acpi/osl.c46
6 files changed, 355 insertions, 511 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 735f5ea17473..3919d6dbe06f 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -160,15 +160,8 @@ config ACPI_DOCK
160 tristate "Dock" 160 tristate "Dock"
161 depends on EXPERIMENTAL 161 depends on EXPERIMENTAL
162 help 162 help
163 This driver adds support for ACPI controlled docking stations 163 This driver adds support for ACPI controlled docking stations and removable
164 164 drive bays such as the IBM ultrabay or the Dell Module Bay.
165config ACPI_BAY
166 tristate "Removable Drive Bay (EXPERIMENTAL)"
167 depends on EXPERIMENTAL
168 depends on ACPI_DOCK
169 help
170 This driver adds support for ACPI controlled removable drive
171 bays such as the IBM ultrabay or the Dell Module Bay.
172 165
173config ACPI_PROCESSOR 166config ACPI_PROCESSOR
174 tristate "Processor" 167 tristate "Processor"
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 52a4cd4b81d0..ad4bfd558ff3 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -45,7 +45,6 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o
45obj-$(CONFIG_ACPI_BUTTON) += button.o 45obj-$(CONFIG_ACPI_BUTTON) += button.o
46obj-$(CONFIG_ACPI_FAN) += fan.o 46obj-$(CONFIG_ACPI_FAN) += fan.o
47obj-$(CONFIG_ACPI_DOCK) += dock.o 47obj-$(CONFIG_ACPI_DOCK) += dock.o
48obj-$(CONFIG_ACPI_BAY) += bay.o
49obj-$(CONFIG_ACPI_VIDEO) += video.o 48obj-$(CONFIG_ACPI_VIDEO) += video.o
50obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o 49obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
51obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o 50obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
deleted file mode 100644
index 61b6c5beb2d3..000000000000
--- a/drivers/acpi/bay.c
+++ /dev/null
@@ -1,411 +0,0 @@
1/*
2 * bay.c - ACPI removable drive bay driver
3 *
4 * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/types.h>
28#include <linux/notifier.h>
29#include <acpi/acpi_bus.h>
30#include <acpi/acpi_drivers.h>
31#include <linux/seq_file.h>
32#include <asm/uaccess.h>
33#include <linux/platform_device.h>
34
35ACPI_MODULE_NAME("bay");
36MODULE_AUTHOR("Kristen Carlson Accardi");
37MODULE_DESCRIPTION("ACPI Removable Drive Bay Driver");
38MODULE_LICENSE("GPL");
39#define ACPI_BAY_CLASS "bay"
40#define ACPI_BAY_COMPONENT 0x10000000
41#define _COMPONENT ACPI_BAY_COMPONENT
42#define bay_dprintk(h,s) {\
43 char prefix[80] = {'\0'};\
44 struct acpi_buffer buffer = {sizeof(prefix), prefix};\
45 acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
46 printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); }
47static void bay_notify(acpi_handle handle, u32 event, void *data);
48
49static const struct acpi_device_id bay_device_ids[] = {
50 {"LNXIOBAY", 0},
51 {"", 0},
52};
53MODULE_DEVICE_TABLE(acpi, bay_device_ids);
54
55struct bay {
56 acpi_handle handle;
57 char *name;
58 struct list_head list;
59 struct platform_device *pdev;
60};
61
62static LIST_HEAD(drive_bays);
63
64
65/*****************************************************************************
66 * Drive Bay functions *
67 *****************************************************************************/
68/**
69 * is_ejectable - see if a device is ejectable
70 * @handle: acpi handle of the device
71 *
72 * If an acpi object has a _EJ0 method, then it is ejectable
73 */
74static int is_ejectable(acpi_handle handle)
75{
76 acpi_status status;
77 acpi_handle tmp;
78
79 status = acpi_get_handle(handle, "_EJ0", &tmp);
80 if (ACPI_FAILURE(status))
81 return 0;
82 return 1;
83}
84
85/**
86 * bay_present - see if the bay device is present
87 * @bay: the drive bay
88 *
89 * execute the _STA method.
90 */
91static int bay_present(struct bay *bay)
92{
93 unsigned long sta;
94 acpi_status status;
95
96 if (bay) {
97 status = acpi_evaluate_integer(bay->handle, "_STA", NULL, &sta);
98 if (ACPI_SUCCESS(status) && sta)
99 return 1;
100 }
101 return 0;
102}
103
104/**
105 * eject_device - respond to an eject request
106 * @handle - the device to eject
107 *
108 * Call this devices _EJ0 method.
109 */
110static void eject_device(acpi_handle handle)
111{
112 struct acpi_object_list arg_list;
113 union acpi_object arg;
114
115 bay_dprintk(handle, "Ejecting device");
116
117 arg_list.count = 1;
118 arg_list.pointer = &arg;
119 arg.type = ACPI_TYPE_INTEGER;
120 arg.integer.value = 1;
121
122 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_EJ0",
123 &arg_list, NULL)))
124 pr_debug("Failed to evaluate _EJ0!\n");
125}
126
127/*
128 * show_present - read method for "present" file in sysfs
129 */
130static ssize_t show_present(struct device *dev,
131 struct device_attribute *attr, char *buf)
132{
133 struct bay *bay = dev_get_drvdata(dev);
134 return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay));
135
136}
137static DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
138
139/*
140 * write_eject - write method for "eject" file in sysfs
141 */
142static ssize_t write_eject(struct device *dev, struct device_attribute *attr,
143 const char *buf, size_t count)
144{
145 struct bay *bay = dev_get_drvdata(dev);
146
147 if (!count)
148 return -EINVAL;
149
150 eject_device(bay->handle);
151 return count;
152}
153static DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject);
154
155/**
156 * is_ata - see if a device is an ata device
157 * @handle: acpi handle of the device
158 *
159 * If an acpi object has one of 4 ATA ACPI methods defined,
160 * then it is an ATA device
161 */
162static int is_ata(acpi_handle handle)
163{
164 acpi_handle tmp;
165
166 if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
167 (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
168 (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
169 (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
170 return 1;
171
172 return 0;
173}
174
175/**
176 * parent_is_ata(acpi_handle handle)
177 *
178 */
179static int parent_is_ata(acpi_handle handle)
180{
181 acpi_handle phandle;
182
183 if (acpi_get_parent(handle, &phandle))
184 return 0;
185
186 return is_ata(phandle);
187}
188
189/**
190 * is_ejectable_bay - see if a device is an ejectable drive bay
191 * @handle: acpi handle of the device
192 *
193 * If an acpi object is ejectable and has one of the ACPI ATA
194 * methods defined, then we can safely call it an ejectable
195 * drive bay
196 */
197static int is_ejectable_bay(acpi_handle handle)
198{
199 if ((is_ata(handle) || parent_is_ata(handle)) && is_ejectable(handle))
200 return 1;
201 return 0;
202}
203
204#if 0
205/**
206 * eject_removable_drive - try to eject this drive
207 * @dev : the device structure of the drive
208 *
209 * If a device is a removable drive that requires an _EJ0 method
210 * to be executed in order to safely remove from the system, do
211 * it. ATM - always returns success
212 */
213int eject_removable_drive(struct device *dev)
214{
215 acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
216
217 if (handle) {
218 bay_dprintk(handle, "Got device handle");
219 if (is_ejectable_bay(handle))
220 eject_device(handle);
221 } else {
222 printk("No acpi handle for device\n");
223 }
224
225 /* should I return an error code? */
226 return 0;
227}
228EXPORT_SYMBOL_GPL(eject_removable_drive);
229#endif /* 0 */
230
231static int acpi_bay_add_fs(struct bay *bay)
232{
233 int ret;
234 struct device *dev = &bay->pdev->dev;
235
236 ret = device_create_file(dev, &dev_attr_present);
237 if (ret)
238 goto add_fs_err;
239 ret = device_create_file(dev, &dev_attr_eject);
240 if (ret) {
241 device_remove_file(dev, &dev_attr_present);
242 goto add_fs_err;
243 }
244 return 0;
245
246 add_fs_err:
247 bay_dprintk(bay->handle, "Error adding sysfs files\n");
248 return ret;
249}
250
251static void acpi_bay_remove_fs(struct bay *bay)
252{
253 struct device *dev = &bay->pdev->dev;
254
255 /* cleanup sysfs */
256 device_remove_file(dev, &dev_attr_present);
257 device_remove_file(dev, &dev_attr_eject);
258}
259
260static int bay_is_dock_device(acpi_handle handle)
261{
262 acpi_handle parent;
263
264 acpi_get_parent(handle, &parent);
265
266 /* if the device or it's parent is dependent on the
267 * dock, then we are a dock device
268 */
269 return (is_dock_device(handle) || is_dock_device(parent));
270}
271
272static int bay_add(acpi_handle handle, int id)
273{
274 acpi_status status;
275 struct bay *new_bay;
276 struct platform_device *pdev;
277 struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL};
278 acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer);
279
280 bay_dprintk(handle, "Adding notify handler");
281
282 /*
283 * Initialize bay device structure
284 */
285 new_bay = kzalloc(sizeof(*new_bay), GFP_ATOMIC);
286 INIT_LIST_HEAD(&new_bay->list);
287 new_bay->handle = handle;
288 new_bay->name = (char *)nbuffer.pointer;
289
290 /* initialize platform device stuff */
291 pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0);
292 if (IS_ERR(pdev)) {
293 printk(KERN_ERR PREFIX "Error registering bay device\n");
294 goto bay_add_err;
295 }
296 new_bay->pdev = pdev;
297 platform_set_drvdata(pdev, new_bay);
298
299 /*
300 * we want the bay driver to be able to send uevents
301 */
302 pdev->dev.uevent_suppress = 0;
303
304 /* register for events on this device */
305 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
306 bay_notify, new_bay);
307 if (ACPI_FAILURE(status)) {
308 printk(KERN_INFO PREFIX "Error installing bay notify handler\n");
309 platform_device_unregister(new_bay->pdev);
310 goto bay_add_err;
311 }
312
313 if (acpi_bay_add_fs(new_bay)) {
314 acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
315 bay_notify);
316 platform_device_unregister(new_bay->pdev);
317 goto bay_add_err;
318 }
319
320 /* if we are on a dock station, we should register for dock
321 * notifications.
322 */
323 if (bay_is_dock_device(handle)) {
324 bay_dprintk(handle, "Is dependent on dock\n");
325 register_hotplug_dock_device(handle, bay_notify, new_bay);
326 }
327 list_add(&new_bay->list, &drive_bays);
328 printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name);
329 return 0;
330
331bay_add_err:
332 kfree(new_bay->name);
333 kfree(new_bay);
334 return -ENODEV;
335}
336
337/**
338 * bay_notify - act upon an acpi bay notification
339 * @handle: the bay handle
340 * @event: the acpi event
341 * @data: our driver data struct
342 *
343 */
344static void bay_notify(acpi_handle handle, u32 event, void *data)
345{
346 struct bay *bay_dev = (struct bay *)data;
347 struct device *dev = &bay_dev->pdev->dev;
348 char event_string[12];
349 char *envp[] = { event_string, NULL };
350
351 bay_dprintk(handle, "Bay event");
352 sprintf(event_string, "BAY_EVENT=%d", event);
353 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
354}
355
356static acpi_status
357find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
358{
359 int *count = (int *)context;
360
361 /*
362 * there could be more than one ejectable bay.
363 * so, just return AE_OK always so that every object
364 * will be checked.
365 */
366 if (is_ejectable_bay(handle)) {
367 bay_dprintk(handle, "found ejectable bay");
368 if (!bay_add(handle, *count))
369 (*count)++;
370 }
371 return AE_OK;
372}
373
374static int __init bay_init(void)
375{
376 int bays = 0;
377
378 INIT_LIST_HEAD(&drive_bays);
379
380 if (acpi_disabled)
381 return -ENODEV;
382
383 /* look for dockable drive bays */
384 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
385 ACPI_UINT32_MAX, find_bay, &bays, NULL);
386
387 if (!bays)
388 return -ENODEV;
389
390 return 0;
391}
392
393static void __exit bay_exit(void)
394{
395 struct bay *bay, *tmp;
396
397 list_for_each_entry_safe(bay, tmp, &drive_bays, list) {
398 if (is_dock_device(bay->handle))
399 unregister_hotplug_dock_device(bay->handle);
400 acpi_bay_remove_fs(bay);
401 acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY,
402 bay_notify);
403 platform_device_unregister(bay->pdev);
404 kfree(bay->name);
405 kfree(bay);
406 }
407}
408
409postcore_initcall(bay_init);
410module_exit(bay_exit);
411
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e9b116d2b56d..e6311f432edf 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -525,6 +525,19 @@ static int acpi_bus_check_scope(struct acpi_device *device)
525 return 0; 525 return 0;
526} 526}
527 527
528static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
529int register_acpi_bus_notifier(struct notifier_block *nb)
530{
531 return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
532}
533EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
534
535void unregister_acpi_bus_notifier(struct notifier_block *nb)
536{
537 blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
538}
539EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
540
528/** 541/**
529 * acpi_bus_notify 542 * acpi_bus_notify
530 * --------------- 543 * ---------------
@@ -535,6 +548,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
535 int result = 0; 548 int result = 0;
536 struct acpi_device *device = NULL; 549 struct acpi_device *device = NULL;
537 550
551 blocking_notifier_call_chain(&acpi_bus_notify_list,
552 type, (void *)handle);
538 553
539 if (acpi_bus_get_device(handle, &device)) 554 if (acpi_bus_get_device(handle, &device))
540 return; 555 return;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 7d2edf143f16..913bb1e89dd6 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -48,7 +48,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
48 " before undocking"); 48 " before undocking");
49 49
50static struct atomic_notifier_head dock_notifier_list; 50static struct atomic_notifier_head dock_notifier_list;
51static struct platform_device *dock_device;
52static char dock_device_name[] = "dock"; 51static char dock_device_name[] = "dock";
53 52
54static const struct acpi_device_id dock_device_ids[] = { 53static const struct acpi_device_id dock_device_ids[] = {
@@ -65,23 +64,29 @@ struct dock_station {
65 struct mutex hp_lock; 64 struct mutex hp_lock;
66 struct list_head dependent_devices; 65 struct list_head dependent_devices;
67 struct list_head hotplug_devices; 66 struct list_head hotplug_devices;
67
68 struct list_head sibiling;
69 struct platform_device *dock_device;
68}; 70};
71static LIST_HEAD(dock_stations);
72static int dock_station_count;
69 73
70struct dock_dependent_device { 74struct dock_dependent_device {
71 struct list_head list; 75 struct list_head list;
72 struct list_head hotplug_list; 76 struct list_head hotplug_list;
73 acpi_handle handle; 77 acpi_handle handle;
74 acpi_notify_handler handler; 78 struct acpi_dock_ops *ops;
75 void *context; 79 void *context;
76}; 80};
77 81
78#define DOCK_DOCKING 0x00000001 82#define DOCK_DOCKING 0x00000001
79#define DOCK_UNDOCKING 0x00000002 83#define DOCK_UNDOCKING 0x00000002
84#define DOCK_IS_DOCK 0x00000010
85#define DOCK_IS_ATA 0x00000020
86#define DOCK_IS_BAT 0x00000040
80#define DOCK_EVENT 3 87#define DOCK_EVENT 3
81#define UNDOCK_EVENT 2 88#define UNDOCK_EVENT 2
82 89
83static struct dock_station *dock_station;
84
85/***************************************************************************** 90/*****************************************************************************
86 * Dock Dependent device functions * 91 * Dock Dependent device functions *
87 *****************************************************************************/ 92 *****************************************************************************/
@@ -199,6 +204,60 @@ static int is_dock(acpi_handle handle)
199 return 1; 204 return 1;
200} 205}
201 206
207static int is_ejectable(acpi_handle handle)
208{
209 acpi_status status;
210 acpi_handle tmp;
211
212 status = acpi_get_handle(handle, "_EJ0", &tmp);
213 if (ACPI_FAILURE(status))
214 return 0;
215 return 1;
216}
217
218static int is_ata(acpi_handle handle)
219{
220 acpi_handle tmp;
221
222 if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) ||
223 (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) ||
224 (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) ||
225 (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp))))
226 return 1;
227
228 return 0;
229}
230
231static int is_battery(acpi_handle handle)
232{
233 struct acpi_device_info *info;
234 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
235 int ret = 1;
236
237 if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer)))
238 return 0;
239 info = buffer.pointer;
240 if (!(info->valid & ACPI_VALID_HID))
241 ret = 0;
242 else
243 ret = !strcmp("PNP0C0A", info->hardware_id.value);
244
245 kfree(buffer.pointer);
246 return ret;
247}
248
249static int is_ejectable_bay(acpi_handle handle)
250{
251 acpi_handle phandle;
252 if (!is_ejectable(handle))
253 return 0;
254 if (is_battery(handle) || is_ata(handle))
255 return 1;
256 if (!acpi_get_parent(handle, &phandle) && is_ata(phandle))
257 return 1;
258 return 0;
259}
260
202/** 261/**
203 * is_dock_device - see if a device is on a dock station 262 * is_dock_device - see if a device is on a dock station
204 * @handle: acpi handle of the device 263 * @handle: acpi handle of the device
@@ -209,11 +268,17 @@ static int is_dock(acpi_handle handle)
209 */ 268 */
210int is_dock_device(acpi_handle handle) 269int is_dock_device(acpi_handle handle)
211{ 270{
212 if (!dock_station) 271 struct dock_station *dock_station;
272
273 if (!dock_station_count)
213 return 0; 274 return 0;
214 275
215 if (is_dock(handle) || find_dock_dependent_device(dock_station, handle)) 276 if (is_dock(handle))
216 return 1; 277 return 1;
278 list_for_each_entry(dock_station, &dock_stations, sibiling) {
279 if (find_dock_dependent_device(dock_station, handle))
280 return 1;
281 }
217 282
218 return 0; 283 return 0;
219} 284}
@@ -320,8 +385,8 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
320 * First call driver specific hotplug functions 385 * First call driver specific hotplug functions
321 */ 386 */
322 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { 387 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) {
323 if (dd->handler) 388 if (dd->ops && dd->ops->handler)
324 dd->handler(dd->handle, event, dd->context); 389 dd->ops->handler(dd->handle, event, dd->context);
325 } 390 }
326 391
327 /* 392 /*
@@ -341,9 +406,10 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
341 406
342static void dock_event(struct dock_station *ds, u32 event, int num) 407static void dock_event(struct dock_station *ds, u32 event, int num)
343{ 408{
344 struct device *dev = &dock_device->dev; 409 struct device *dev = &ds->dock_device->dev;
345 char event_string[13]; 410 char event_string[13];
346 char *envp[] = { event_string, NULL }; 411 char *envp[] = { event_string, NULL };
412 struct dock_dependent_device *dd;
347 413
348 if (num == UNDOCK_EVENT) 414 if (num == UNDOCK_EVENT)
349 sprintf(event_string, "EVENT=undock"); 415 sprintf(event_string, "EVENT=undock");
@@ -354,7 +420,14 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
354 * Indicate that the status of the dock station has 420 * Indicate that the status of the dock station has
355 * changed. 421 * changed.
356 */ 422 */
357 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 423 if (num == DOCK_EVENT)
424 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
425
426 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
427 if (dd->ops && dd->ops->uevent)
428 dd->ops->uevent(dd->handle, event, dd->context);
429 if (num != DOCK_EVENT)
430 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
358} 431}
359 432
360/** 433/**
@@ -414,9 +487,10 @@ static void handle_dock(struct dock_station *ds, int dock)
414 arg.type = ACPI_TYPE_INTEGER; 487 arg.type = ACPI_TYPE_INTEGER;
415 arg.integer.value = dock; 488 arg.integer.value = dock;
416 status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); 489 status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
417 if (ACPI_FAILURE(status)) 490 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
418 printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", 491 ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
419 (char *)name_buffer.pointer); 492 " _DCK\n", (char *)name_buffer.pointer));
493
420 kfree(buffer.pointer); 494 kfree(buffer.pointer);
421 kfree(name_buffer.pointer); 495 kfree(name_buffer.pointer);
422} 496}
@@ -452,6 +526,25 @@ static inline void complete_undock(struct dock_station *ds)
452 ds->flags &= ~(DOCK_UNDOCKING); 526 ds->flags &= ~(DOCK_UNDOCKING);
453} 527}
454 528
529static void dock_lock(struct dock_station *ds, int lock)
530{
531 struct acpi_object_list arg_list;
532 union acpi_object arg;
533 acpi_status status;
534
535 arg_list.count = 1;
536 arg_list.pointer = &arg;
537 arg.type = ACPI_TYPE_INTEGER;
538 arg.integer.value = !!lock;
539 status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
540 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
541 if (lock)
542 printk(KERN_WARNING PREFIX "Locking device failed\n");
543 else
544 printk(KERN_WARNING PREFIX "Unlocking device failed\n");
545 }
546}
547
455/** 548/**
456 * dock_in_progress - see if we are in the middle of handling a dock event 549 * dock_in_progress - see if we are in the middle of handling a dock event
457 * @ds: the dock station 550 * @ds: the dock station
@@ -479,7 +572,7 @@ static int dock_in_progress(struct dock_station *ds)
479 */ 572 */
480int register_dock_notifier(struct notifier_block *nb) 573int register_dock_notifier(struct notifier_block *nb)
481{ 574{
482 if (!dock_station) 575 if (!dock_station_count)
483 return -ENODEV; 576 return -ENODEV;
484 577
485 return atomic_notifier_chain_register(&dock_notifier_list, nb); 578 return atomic_notifier_chain_register(&dock_notifier_list, nb);
@@ -493,7 +586,7 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
493 */ 586 */
494void unregister_dock_notifier(struct notifier_block *nb) 587void unregister_dock_notifier(struct notifier_block *nb)
495{ 588{
496 if (!dock_station) 589 if (!dock_station_count)
497 return; 590 return;
498 591
499 atomic_notifier_chain_unregister(&dock_notifier_list, nb); 592 atomic_notifier_chain_unregister(&dock_notifier_list, nb);
@@ -504,7 +597,7 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
504/** 597/**
505 * register_hotplug_dock_device - register a hotplug function 598 * register_hotplug_dock_device - register a hotplug function
506 * @handle: the handle of the device 599 * @handle: the handle of the device
507 * @handler: the acpi_notifier_handler to call after docking 600 * @ops: handlers to call after docking
508 * @context: device specific data 601 * @context: device specific data
509 * 602 *
510 * If a driver would like to perform a hotplug operation after a dock 603 * If a driver would like to perform a hotplug operation after a dock
@@ -512,27 +605,36 @@ EXPORT_SYMBOL_GPL(unregister_dock_notifier);
512 * the dock driver after _DCK is executed. 605 * the dock driver after _DCK is executed.
513 */ 606 */
514int 607int
515register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, 608register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
516 void *context) 609 void *context)
517{ 610{
518 struct dock_dependent_device *dd; 611 struct dock_dependent_device *dd;
612 struct dock_station *dock_station;
613 int ret = -EINVAL;
519 614
520 if (!dock_station) 615 if (!dock_station_count)
521 return -ENODEV; 616 return -ENODEV;
522 617
523 /* 618 /*
524 * make sure this handle is for a device dependent on the dock, 619 * make sure this handle is for a device dependent on the dock,
525 * this would include the dock station itself 620 * this would include the dock station itself
526 */ 621 */
527 dd = find_dock_dependent_device(dock_station, handle); 622 list_for_each_entry(dock_station, &dock_stations, sibiling) {
528 if (dd) { 623 /*
529 dd->handler = handler; 624 * An ATA bay can be in a dock and itself can be ejected
530 dd->context = context; 625 * seperately, so there are two 'dock stations' which need the
531 dock_add_hotplug_device(dock_station, dd); 626 * ops
532 return 0; 627 */
628 dd = find_dock_dependent_device(dock_station, handle);
629 if (dd) {
630 dd->ops = ops;
631 dd->context = context;
632 dock_add_hotplug_device(dock_station, dd);
633 ret = 0;
634 }
533 } 635 }
534 636
535 return -EINVAL; 637 return ret;
536} 638}
537 639
538EXPORT_SYMBOL_GPL(register_hotplug_dock_device); 640EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
@@ -544,13 +646,16 @@ EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
544void unregister_hotplug_dock_device(acpi_handle handle) 646void unregister_hotplug_dock_device(acpi_handle handle)
545{ 647{
546 struct dock_dependent_device *dd; 648 struct dock_dependent_device *dd;
649 struct dock_station *dock_station;
547 650
548 if (!dock_station) 651 if (!dock_station_count)
549 return; 652 return;
550 653
551 dd = find_dock_dependent_device(dock_station, handle); 654 list_for_each_entry(dock_station, &dock_stations, sibiling) {
552 if (dd) 655 dd = find_dock_dependent_device(dock_station, handle);
553 dock_del_hotplug_device(dock_station, dd); 656 if (dd)
657 dock_del_hotplug_device(dock_station, dd);
658 }
554} 659}
555 660
556EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 661EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
@@ -575,13 +680,9 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
575 */ 680 */
576 dock_event(ds, event, UNDOCK_EVENT); 681 dock_event(ds, event, UNDOCK_EVENT);
577 682
578 if (!dock_present(ds)) {
579 complete_undock(ds);
580 return -ENODEV;
581 }
582
583 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); 683 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
584 undock(ds); 684 undock(ds);
685 dock_lock(ds, 0);
585 eject_dock(ds); 686 eject_dock(ds);
586 if (dock_present(ds)) { 687 if (dock_present(ds)) {
587 printk(KERN_ERR PREFIX "Unable to undock!\n"); 688 printk(KERN_ERR PREFIX "Unable to undock!\n");
@@ -604,14 +705,36 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
604static void dock_notify(acpi_handle handle, u32 event, void *data) 705static void dock_notify(acpi_handle handle, u32 event, void *data)
605{ 706{
606 struct dock_station *ds = data; 707 struct dock_station *ds = data;
708 struct acpi_device *tmp;
709 int surprise_removal = 0;
710
711 /*
712 * According to acpi spec 3.0a, if a DEVICE_CHECK notification
713 * is sent and _DCK is present, it is assumed to mean an undock
714 * request.
715 */
716 if ((ds->flags & DOCK_IS_DOCK) && event == ACPI_NOTIFY_DEVICE_CHECK)
717 event = ACPI_NOTIFY_EJECT_REQUEST;
607 718
719 /*
720 * dock station: BUS_CHECK - docked or surprise removal
721 * DEVICE_CHECK - undocked
722 * other device: BUS_CHECK/DEVICE_CHECK - added or surprise removal
723 *
724 * To simplify event handling, dock dependent device handler always
725 * get ACPI_NOTIFY_BUS_CHECK/ACPI_NOTIFY_DEVICE_CHECK for add and
726 * ACPI_NOTIFY_EJECT_REQUEST for removal
727 */
608 switch (event) { 728 switch (event) {
609 case ACPI_NOTIFY_BUS_CHECK: 729 case ACPI_NOTIFY_BUS_CHECK:
610 if (!dock_in_progress(ds) && dock_present(ds)) { 730 case ACPI_NOTIFY_DEVICE_CHECK:
731 if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle,
732 &tmp)) {
611 begin_dock(ds); 733 begin_dock(ds);
612 dock(ds); 734 dock(ds);
613 if (!dock_present(ds)) { 735 if (!dock_present(ds)) {
614 printk(KERN_ERR PREFIX "Unable to dock!\n"); 736 printk(KERN_ERR PREFIX "Unable to dock!\n");
737 complete_dock(ds);
615 break; 738 break;
616 } 739 }
617 atomic_notifier_call_chain(&dock_notifier_list, 740 atomic_notifier_call_chain(&dock_notifier_list,
@@ -619,20 +742,19 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
619 hotplug_dock_devices(ds, event); 742 hotplug_dock_devices(ds, event);
620 complete_dock(ds); 743 complete_dock(ds);
621 dock_event(ds, event, DOCK_EVENT); 744 dock_event(ds, event, DOCK_EVENT);
745 dock_lock(ds, 1);
746 break;
622 } 747 }
623 break; 748 if (dock_present(ds) || dock_in_progress(ds))
624 case ACPI_NOTIFY_DEVICE_CHECK: 749 break;
625 /* 750 /* This is a surprise removal */
626 * According to acpi spec 3.0a, if a DEVICE_CHECK notification 751 surprise_removal = 1;
627 * is sent and _DCK is present, it is assumed to mean an 752 event = ACPI_NOTIFY_EJECT_REQUEST;
628 * undock request. This notify routine will only be called 753 /* Fall back */
629 * for objects defining _DCK, so we will fall through to eject
630 * request here. However, we will pass an eject request through
631 * to the driver who wish to hotplug.
632 */
633 case ACPI_NOTIFY_EJECT_REQUEST: 754 case ACPI_NOTIFY_EJECT_REQUEST:
634 begin_undock(ds); 755 begin_undock(ds);
635 if (immediate_undock) 756 if ((immediate_undock && !(ds->flags & DOCK_IS_ATA))
757 || surprise_removal)
636 handle_eject_request(ds, event); 758 handle_eject_request(ds, event);
637 else 759 else
638 dock_event(ds, event, UNDOCK_EVENT); 760 dock_event(ds, event, UNDOCK_EVENT);
@@ -642,6 +764,51 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
642 } 764 }
643} 765}
644 766
767struct dock_data {
768 acpi_handle handle;
769 unsigned long event;
770 struct dock_station *ds;
771};
772
773static void acpi_dock_deferred_cb(void *context)
774{
775 struct dock_data *data = (struct dock_data *)context;
776
777 dock_notify(data->handle, data->event, data->ds);
778 kfree(data);
779}
780
781static int acpi_dock_notifier_call(struct notifier_block *this,
782 unsigned long event, void *data)
783{
784 struct dock_station *dock_station;
785 acpi_handle handle = (acpi_handle)data;
786
787 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
788 && event != ACPI_NOTIFY_EJECT_REQUEST)
789 return 0;
790 list_for_each_entry(dock_station, &dock_stations, sibiling) {
791 if (dock_station->handle == handle) {
792 struct dock_data *dock_data;
793
794 dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL);
795 if (!dock_data)
796 return 0;
797 dock_data->handle = handle;
798 dock_data->event = event;
799 dock_data->ds = dock_station;
800 acpi_os_hotplug_execute(acpi_dock_deferred_cb,
801 dock_data);
802 return 0 ;
803 }
804 }
805 return 0;
806}
807
808static struct notifier_block dock_acpi_notifier = {
809 .notifier_call = acpi_dock_notifier_call,
810};
811
645/** 812/**
646 * find_dock_devices - find devices on the dock station 813 * find_dock_devices - find devices on the dock station
647 * @handle: the handle of the device we are examining 814 * @handle: the handle of the device we are examining
@@ -688,6 +855,8 @@ fdd_out:
688static ssize_t show_docked(struct device *dev, 855static ssize_t show_docked(struct device *dev,
689 struct device_attribute *attr, char *buf) 856 struct device_attribute *attr, char *buf)
690{ 857{
858 struct dock_station *dock_station = *((struct dock_station **)
859 dev->platform_data);
691 return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station)); 860 return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
692 861
693} 862}
@@ -699,6 +868,8 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
699static ssize_t show_flags(struct device *dev, 868static ssize_t show_flags(struct device *dev,
700 struct device_attribute *attr, char *buf) 869 struct device_attribute *attr, char *buf)
701{ 870{
871 struct dock_station *dock_station = *((struct dock_station **)
872 dev->platform_data);
702 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); 873 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
703 874
704} 875}
@@ -711,6 +882,8 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
711 const char *buf, size_t count) 882 const char *buf, size_t count)
712{ 883{
713 int ret; 884 int ret;
885 struct dock_station *dock_station = *((struct dock_station **)
886 dev->platform_data);
714 887
715 if (!count) 888 if (!count)
716 return -EINVAL; 889 return -EINVAL;
@@ -728,6 +901,8 @@ static ssize_t show_dock_uid(struct device *dev,
728 struct device_attribute *attr, char *buf) 901 struct device_attribute *attr, char *buf)
729{ 902{
730 unsigned long lbuf; 903 unsigned long lbuf;
904 struct dock_station *dock_station = *((struct dock_station **)
905 dev->platform_data);
731 acpi_status status = acpi_evaluate_integer(dock_station->handle, 906 acpi_status status = acpi_evaluate_integer(dock_station->handle,
732 "_UID", NULL, &lbuf); 907 "_UID", NULL, &lbuf);
733 if (ACPI_FAILURE(status)) 908 if (ACPI_FAILURE(status))
@@ -737,6 +912,26 @@ static ssize_t show_dock_uid(struct device *dev,
737} 912}
738static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); 913static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
739 914
915static ssize_t show_dock_type(struct device *dev,
916 struct device_attribute *attr, char *buf)
917{
918 struct dock_station *dock_station = *((struct dock_station **)
919 dev->platform_data);
920 char *type;
921
922 if (dock_station->flags & DOCK_IS_DOCK)
923 type = "dock_station";
924 else if (dock_station->flags & DOCK_IS_ATA)
925 type = "ata_bay";
926 else if (dock_station->flags & DOCK_IS_BAT)
927 type = "battery_bay";
928 else
929 type = "unknown";
930
931 return snprintf(buf, PAGE_SIZE, "%s\n", type);
932}
933static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
934
740/** 935/**
741 * dock_add - add a new dock station 936 * dock_add - add a new dock station
742 * @handle: the dock station handle 937 * @handle: the dock station handle
@@ -747,8 +942,9 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
747static int dock_add(acpi_handle handle) 942static int dock_add(acpi_handle handle)
748{ 943{
749 int ret; 944 int ret;
750 acpi_status status;
751 struct dock_dependent_device *dd; 945 struct dock_dependent_device *dd;
946 struct dock_station *dock_station;
947 struct platform_device *dock_device;
752 948
753 /* allocate & initialize the dock_station private data */ 949 /* allocate & initialize the dock_station private data */
754 dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); 950 dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
@@ -758,22 +954,34 @@ static int dock_add(acpi_handle handle)
758 dock_station->last_dock_time = jiffies - HZ; 954 dock_station->last_dock_time = jiffies - HZ;
759 INIT_LIST_HEAD(&dock_station->dependent_devices); 955 INIT_LIST_HEAD(&dock_station->dependent_devices);
760 INIT_LIST_HEAD(&dock_station->hotplug_devices); 956 INIT_LIST_HEAD(&dock_station->hotplug_devices);
957 INIT_LIST_HEAD(&dock_station->sibiling);
761 spin_lock_init(&dock_station->dd_lock); 958 spin_lock_init(&dock_station->dd_lock);
762 mutex_init(&dock_station->hp_lock); 959 mutex_init(&dock_station->hp_lock);
763 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 960 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
764 961
765 /* initialize platform device stuff */ 962 /* initialize platform device stuff */
766 dock_device = 963 dock_station->dock_device =
767 platform_device_register_simple(dock_device_name, 0, NULL, 0); 964 platform_device_register_simple(dock_device_name,
965 dock_station_count, NULL, 0);
966 dock_device = dock_station->dock_device;
768 if (IS_ERR(dock_device)) { 967 if (IS_ERR(dock_device)) {
769 kfree(dock_station); 968 kfree(dock_station);
770 dock_station = NULL; 969 dock_station = NULL;
771 return PTR_ERR(dock_device); 970 return PTR_ERR(dock_device);
772 } 971 }
972 platform_device_add_data(dock_device, &dock_station,
973 sizeof(struct dock_station *));
773 974
774 /* we want the dock device to send uevents */ 975 /* we want the dock device to send uevents */
775 dock_device->dev.uevent_suppress = 0; 976 dock_device->dev.uevent_suppress = 0;
776 977
978 if (is_dock(handle))
979 dock_station->flags |= DOCK_IS_DOCK;
980 if (is_ata(handle))
981 dock_station->flags |= DOCK_IS_ATA;
982 if (is_battery(handle))
983 dock_station->flags |= DOCK_IS_BAT;
984
777 ret = device_create_file(&dock_device->dev, &dev_attr_docked); 985 ret = device_create_file(&dock_device->dev, &dev_attr_docked);
778 if (ret) { 986 if (ret) {
779 printk("Error %d adding sysfs file\n", ret); 987 printk("Error %d adding sysfs file\n", ret);
@@ -812,6 +1020,9 @@ static int dock_add(acpi_handle handle)
812 dock_station = NULL; 1020 dock_station = NULL;
813 return ret; 1021 return ret;
814 } 1022 }
1023 ret = device_create_file(&dock_device->dev, &dev_attr_type);
1024 if (ret)
1025 printk(KERN_ERR"Error %d adding sysfs file\n", ret);
815 1026
816 /* Find dependent devices */ 1027 /* Find dependent devices */
817 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 1028 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -828,24 +1039,12 @@ static int dock_add(acpi_handle handle)
828 } 1039 }
829 add_dock_dependent_device(dock_station, dd); 1040 add_dock_dependent_device(dock_station, dd);
830 1041
831 /* register for dock events */ 1042 dock_station_count++;
832 status = acpi_install_notify_handler(dock_station->handle, 1043 list_add(&dock_station->sibiling, &dock_stations);
833 ACPI_SYSTEM_NOTIFY,
834 dock_notify, dock_station);
835
836 if (ACPI_FAILURE(status)) {
837 printk(KERN_ERR PREFIX "Error installing notify handler\n");
838 ret = -ENODEV;
839 goto dock_add_err;
840 }
841
842 printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION);
843
844 return 0; 1044 return 0;
845 1045
846dock_add_err:
847 kfree(dd);
848dock_add_err_unregister: 1046dock_add_err_unregister:
1047 device_remove_file(&dock_device->dev, &dev_attr_type);
849 device_remove_file(&dock_device->dev, &dev_attr_docked); 1048 device_remove_file(&dock_device->dev, &dev_attr_docked);
850 device_remove_file(&dock_device->dev, &dev_attr_undock); 1049 device_remove_file(&dock_device->dev, &dev_attr_undock);
851 device_remove_file(&dock_device->dev, &dev_attr_uid); 1050 device_remove_file(&dock_device->dev, &dev_attr_uid);
@@ -859,12 +1058,12 @@ dock_add_err_unregister:
859/** 1058/**
860 * dock_remove - free up resources related to the dock station 1059 * dock_remove - free up resources related to the dock station
861 */ 1060 */
862static int dock_remove(void) 1061static int dock_remove(struct dock_station *dock_station)
863{ 1062{
864 struct dock_dependent_device *dd, *tmp; 1063 struct dock_dependent_device *dd, *tmp;
865 acpi_status status; 1064 struct platform_device *dock_device = dock_station->dock_device;
866 1065
867 if (!dock_station) 1066 if (!dock_station_count)
868 return 0; 1067 return 0;
869 1068
870 /* remove dependent devices */ 1069 /* remove dependent devices */
@@ -872,14 +1071,8 @@ static int dock_remove(void)
872 list) 1071 list)
873 kfree(dd); 1072 kfree(dd);
874 1073
875 /* remove dock notify handler */
876 status = acpi_remove_notify_handler(dock_station->handle,
877 ACPI_SYSTEM_NOTIFY,
878 dock_notify);
879 if (ACPI_FAILURE(status))
880 printk(KERN_ERR "Error removing notify handler\n");
881
882 /* cleanup sysfs */ 1074 /* cleanup sysfs */
1075 device_remove_file(&dock_device->dev, &dev_attr_type);
883 device_remove_file(&dock_device->dev, &dev_attr_docked); 1076 device_remove_file(&dock_device->dev, &dev_attr_docked);
884 device_remove_file(&dock_device->dev, &dev_attr_undock); 1077 device_remove_file(&dock_device->dev, &dev_attr_undock);
885 device_remove_file(&dock_device->dev, &dev_attr_uid); 1078 device_remove_file(&dock_device->dev, &dev_attr_uid);
@@ -904,41 +1097,60 @@ static int dock_remove(void)
904static acpi_status 1097static acpi_status
905find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) 1098find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
906{ 1099{
907 int *count = context;
908 acpi_status status = AE_OK; 1100 acpi_status status = AE_OK;
909 1101
910 if (is_dock(handle)) { 1102 if (is_dock(handle)) {
911 if (dock_add(handle) >= 0) { 1103 if (dock_add(handle) >= 0) {
912 (*count)++;
913 status = AE_CTRL_TERMINATE; 1104 status = AE_CTRL_TERMINATE;
914 } 1105 }
915 } 1106 }
916 return status; 1107 return status;
917} 1108}
918 1109
919static int __init dock_init(void) 1110static acpi_status
1111find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
920{ 1112{
921 int num = 0; 1113 /* If bay is a dock, it's already handled */
922 1114 if (is_ejectable_bay(handle) && !is_dock(handle))
923 dock_station = NULL; 1115 dock_add(handle);
1116 return AE_OK;
1117}
924 1118
1119static int __init dock_init(void)
1120{
925 if (acpi_disabled) 1121 if (acpi_disabled)
926 return 0; 1122 return 0;
927 1123
928 /* look for a dock station */ 1124 /* look for a dock station */
929 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 1125 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
930 ACPI_UINT32_MAX, find_dock, &num, NULL); 1126 ACPI_UINT32_MAX, find_dock, NULL, NULL);
931 1127
932 if (!num) 1128 /* look for bay */
933 printk(KERN_INFO "No dock devices found.\n"); 1129 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1130 ACPI_UINT32_MAX, find_bay, NULL, NULL);
1131 if (!dock_station_count) {
1132 printk(KERN_INFO PREFIX "No dock devices found.\n");
1133 return 0;
1134 }
934 1135
1136 register_acpi_bus_notifier(&dock_acpi_notifier);
1137 printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
1138 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
935 return 0; 1139 return 0;
936} 1140}
937 1141
938static void __exit dock_exit(void) 1142static void __exit dock_exit(void)
939{ 1143{
940 dock_remove(); 1144 struct dock_station *dock_station;
1145
1146 unregister_acpi_bus_notifier(&dock_acpi_notifier);
1147 list_for_each_entry(dock_station, &dock_stations, sibiling)
1148 dock_remove(dock_station);
941} 1149}
942 1150
943postcore_initcall(dock_init); 1151/*
1152 * Must be called before drivers of devices in dock, otherwise we can't know
1153 * which devices are in a dock
1154 */
1155subsys_initcall(dock_init);
944module_exit(dock_exit); 1156module_exit(dock_exit);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 1420a9f69e5d..6234d3e7acd3 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -682,6 +682,22 @@ static void acpi_os_execute_deferred(struct work_struct *work)
682 return; 682 return;
683} 683}
684 684
685static void acpi_os_execute_hp_deferred(struct work_struct *work)
686{
687 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
688 if (!dpc) {
689 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
690 return;
691 }
692
693 acpi_os_wait_events_complete(NULL);
694
695 dpc->function(dpc->context);
696 kfree(dpc);
697
698 return;
699}
700
685/******************************************************************************* 701/*******************************************************************************
686 * 702 *
687 * FUNCTION: acpi_os_execute 703 * FUNCTION: acpi_os_execute
@@ -697,12 +713,13 @@ static void acpi_os_execute_deferred(struct work_struct *work)
697 * 713 *
698 ******************************************************************************/ 714 ******************************************************************************/
699 715
700acpi_status acpi_os_execute(acpi_execute_type type, 716static acpi_status __acpi_os_execute(acpi_execute_type type,
701 acpi_osd_exec_callback function, void *context) 717 acpi_osd_exec_callback function, void *context, int hp)
702{ 718{
703 acpi_status status = AE_OK; 719 acpi_status status = AE_OK;
704 struct acpi_os_dpc *dpc; 720 struct acpi_os_dpc *dpc;
705 struct workqueue_struct *queue; 721 struct workqueue_struct *queue;
722 int ret;
706 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 723 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
707 "Scheduling function [%p(%p)] for deferred execution.\n", 724 "Scheduling function [%p(%p)] for deferred execution.\n",
708 function, context)); 725 function, context));
@@ -726,9 +743,17 @@ acpi_status acpi_os_execute(acpi_execute_type type,
726 dpc->function = function; 743 dpc->function = function;
727 dpc->context = context; 744 dpc->context = context;
728 745
729 INIT_WORK(&dpc->work, acpi_os_execute_deferred); 746 if (!hp) {
730 queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; 747 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
731 if (!queue_work(queue, &dpc->work)) { 748 queue = (type == OSL_NOTIFY_HANDLER) ?
749 kacpi_notify_wq : kacpid_wq;
750 ret = queue_work(queue, &dpc->work);
751 } else {
752 INIT_WORK(&dpc->work, acpi_os_execute_hp_deferred);
753 ret = schedule_work(&dpc->work);
754 }
755
756 if (!ret) {
732 printk(KERN_ERR PREFIX 757 printk(KERN_ERR PREFIX
733 "Call to queue_work() failed.\n"); 758 "Call to queue_work() failed.\n");
734 status = AE_ERROR; 759 status = AE_ERROR;
@@ -737,8 +762,19 @@ acpi_status acpi_os_execute(acpi_execute_type type,
737 return_ACPI_STATUS(status); 762 return_ACPI_STATUS(status);
738} 763}
739 764
765acpi_status acpi_os_execute(acpi_execute_type type,
766 acpi_osd_exec_callback function, void *context)
767{
768 return __acpi_os_execute(type, function, context, 0);
769}
740EXPORT_SYMBOL(acpi_os_execute); 770EXPORT_SYMBOL(acpi_os_execute);
741 771
772acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
773 void *context)
774{
775 return __acpi_os_execute(0, function, context, 1);
776}
777
742void acpi_os_wait_events_complete(void *context) 778void acpi_os_wait_events_complete(void *context)
743{ 779{
744 flush_workqueue(kacpid_wq); 780 flush_workqueue(kacpid_wq);