aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dock.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/dock.c')
-rw-r--r--drivers/acpi/dock.c382
1 files changed, 297 insertions, 85 deletions
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);