diff options
-rw-r--r-- | drivers/acpi/dock.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index b5addd411b55..98ec717b14cf 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -40,6 +40,13 @@ MODULE_AUTHOR("Kristen Carlson Accardi"); | |||
40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); | 40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); |
41 | MODULE_LICENSE("GPL"); | 41 | MODULE_LICENSE("GPL"); |
42 | 42 | ||
43 | static int immediate_undock = 1; | ||
44 | module_param(immediate_undock, bool, 0644); | ||
45 | MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " | ||
46 | "undock immediately when the undock button is pressed, 0 will cause" | ||
47 | " the driver to wait for userspace to write the undock sysfs file " | ||
48 | " before undocking"); | ||
49 | |||
43 | static struct atomic_notifier_head dock_notifier_list; | 50 | static struct atomic_notifier_head dock_notifier_list; |
44 | static struct platform_device *dock_device; | 51 | static struct platform_device *dock_device; |
45 | static char dock_device_name[] = "dock"; | 52 | static char dock_device_name[] = "dock"; |
@@ -63,6 +70,7 @@ struct dock_dependent_device { | |||
63 | }; | 70 | }; |
64 | 71 | ||
65 | #define DOCK_DOCKING 0x00000001 | 72 | #define DOCK_DOCKING 0x00000001 |
73 | #define DOCK_UNDOCKING 0x00000002 | ||
66 | #define DOCK_EVENT 3 | 74 | #define DOCK_EVENT 3 |
67 | #define UNDOCK_EVENT 2 | 75 | #define UNDOCK_EVENT 2 |
68 | 76 | ||
@@ -420,6 +428,16 @@ static inline void complete_dock(struct dock_station *ds) | |||
420 | ds->last_dock_time = jiffies; | 428 | ds->last_dock_time = jiffies; |
421 | } | 429 | } |
422 | 430 | ||
431 | static inline void begin_undock(struct dock_station *ds) | ||
432 | { | ||
433 | ds->flags |= DOCK_UNDOCKING; | ||
434 | } | ||
435 | |||
436 | static inline void complete_undock(struct dock_station *ds) | ||
437 | { | ||
438 | ds->flags &= ~(DOCK_UNDOCKING); | ||
439 | } | ||
440 | |||
423 | /** | 441 | /** |
424 | * dock_in_progress - see if we are in the middle of handling a dock event | 442 | * dock_in_progress - see if we are in the middle of handling a dock event |
425 | * @ds: the dock station | 443 | * @ds: the dock station |
@@ -550,7 +568,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) | |||
550 | printk(KERN_ERR PREFIX "Unable to undock!\n"); | 568 | printk(KERN_ERR PREFIX "Unable to undock!\n"); |
551 | return -EBUSY; | 569 | return -EBUSY; |
552 | } | 570 | } |
553 | 571 | complete_undock(ds); | |
554 | return 0; | 572 | return 0; |
555 | } | 573 | } |
556 | 574 | ||
@@ -594,7 +612,11 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
594 | * to the driver who wish to hotplug. | 612 | * to the driver who wish to hotplug. |
595 | */ | 613 | */ |
596 | case ACPI_NOTIFY_EJECT_REQUEST: | 614 | case ACPI_NOTIFY_EJECT_REQUEST: |
597 | handle_eject_request(ds, event); | 615 | begin_undock(ds); |
616 | if (immediate_undock) | ||
617 | handle_eject_request(ds, event); | ||
618 | else | ||
619 | dock_event(ds, event, UNDOCK_EVENT); | ||
598 | break; | 620 | break; |
599 | default: | 621 | default: |
600 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); | 622 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); |
@@ -653,6 +675,17 @@ static ssize_t show_docked(struct device *dev, | |||
653 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); | 675 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); |
654 | 676 | ||
655 | /* | 677 | /* |
678 | * show_flags - read method for flags file in sysfs | ||
679 | */ | ||
680 | static ssize_t show_flags(struct device *dev, | ||
681 | struct device_attribute *attr, char *buf) | ||
682 | { | ||
683 | return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); | ||
684 | |||
685 | } | ||
686 | DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); | ||
687 | |||
688 | /* | ||
656 | * write_undock - write method for "undock" file in sysfs | 689 | * write_undock - write method for "undock" file in sysfs |
657 | */ | 690 | */ |
658 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, | 691 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, |
@@ -717,6 +750,7 @@ static int dock_add(acpi_handle handle) | |||
717 | dock_station = NULL; | 750 | dock_station = NULL; |
718 | return PTR_ERR(dock_device); | 751 | return PTR_ERR(dock_device); |
719 | } | 752 | } |
753 | |||
720 | ret = device_create_file(&dock_device->dev, &dev_attr_docked); | 754 | ret = device_create_file(&dock_device->dev, &dev_attr_docked); |
721 | if (ret) { | 755 | if (ret) { |
722 | printk("Error %d adding sysfs file\n", ret); | 756 | printk("Error %d adding sysfs file\n", ret); |
@@ -744,6 +778,17 @@ static int dock_add(acpi_handle handle) | |||
744 | dock_station = NULL; | 778 | dock_station = NULL; |
745 | return ret; | 779 | return ret; |
746 | } | 780 | } |
781 | ret = device_create_file(&dock_device->dev, &dev_attr_flags); | ||
782 | if (ret) { | ||
783 | printk("Error %d adding sysfs file\n", ret); | ||
784 | device_remove_file(&dock_device->dev, &dev_attr_docked); | ||
785 | device_remove_file(&dock_device->dev, &dev_attr_undock); | ||
786 | device_remove_file(&dock_device->dev, &dev_attr_uid); | ||
787 | platform_device_unregister(dock_device); | ||
788 | kfree(dock_station); | ||
789 | dock_station = NULL; | ||
790 | return ret; | ||
791 | } | ||
747 | 792 | ||
748 | /* Find dependent devices */ | 793 | /* Find dependent devices */ |
749 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 794 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
@@ -781,6 +826,7 @@ dock_add_err_unregister: | |||
781 | device_remove_file(&dock_device->dev, &dev_attr_docked); | 826 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
782 | device_remove_file(&dock_device->dev, &dev_attr_undock); | 827 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
783 | device_remove_file(&dock_device->dev, &dev_attr_uid); | 828 | device_remove_file(&dock_device->dev, &dev_attr_uid); |
829 | device_remove_file(&dock_device->dev, &dev_attr_flags); | ||
784 | platform_device_unregister(dock_device); | 830 | platform_device_unregister(dock_device); |
785 | kfree(dock_station); | 831 | kfree(dock_station); |
786 | dock_station = NULL; | 832 | dock_station = NULL; |
@@ -814,6 +860,7 @@ static int dock_remove(void) | |||
814 | device_remove_file(&dock_device->dev, &dev_attr_docked); | 860 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
815 | device_remove_file(&dock_device->dev, &dev_attr_undock); | 861 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
816 | device_remove_file(&dock_device->dev, &dev_attr_uid); | 862 | device_remove_file(&dock_device->dev, &dev_attr_uid); |
863 | device_remove_file(&dock_device->dev, &dev_attr_flags); | ||
817 | platform_device_unregister(dock_device); | 864 | platform_device_unregister(dock_device); |
818 | 865 | ||
819 | /* free dock station memory */ | 866 | /* free dock station memory */ |