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.c127
1 files changed, 97 insertions, 30 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 4546bf873aea..6192c8be66df 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -40,8 +40,15 @@ MODULE_AUTHOR("Kristen Carlson Accardi");
40MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); 40MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION);
41MODULE_LICENSE("GPL"); 41MODULE_LICENSE("GPL");
42 42
43static int immediate_undock = 1;
44module_param(immediate_undock, bool, 0644);
45MODULE_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
43static struct atomic_notifier_head dock_notifier_list; 50static struct atomic_notifier_head dock_notifier_list;
44static struct platform_device dock_device; 51static struct platform_device *dock_device;
45static char dock_device_name[] = "dock"; 52static char dock_device_name[] = "dock";
46 53
47struct dock_station { 54struct dock_station {
@@ -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
@@ -327,12 +335,20 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
327 335
328static void dock_event(struct dock_station *ds, u32 event, int num) 336static void dock_event(struct dock_station *ds, u32 event, int num)
329{ 337{
330 struct device *dev = &dock_device.dev; 338 struct device *dev = &dock_device->dev;
339 char event_string[7];
340 char *envp[] = { event_string, NULL };
341
342 if (num == UNDOCK_EVENT)
343 sprintf(event_string, "UNDOCK");
344 else
345 sprintf(event_string, "DOCK");
346
331 /* 347 /*
332 * Indicate that the status of the dock station has 348 * Indicate that the status of the dock station has
333 * changed. 349 * changed.
334 */ 350 */
335 kobject_uevent(&dev->kobj, KOBJ_CHANGE); 351 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
336} 352}
337 353
338/** 354/**
@@ -380,12 +396,11 @@ static void handle_dock(struct dock_station *ds, int dock)
380 union acpi_object arg; 396 union acpi_object arg;
381 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 397 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
382 struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 398 struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
383 union acpi_object *obj;
384 399
385 acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); 400 acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
386 obj = name_buffer.pointer;
387 401
388 printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking"); 402 printk(KERN_INFO PREFIX "%s - %s\n",
403 (char *)name_buffer.pointer, dock ? "docking" : "undocking");
389 404
390 /* _DCK method has one argument */ 405 /* _DCK method has one argument */
391 arg_list.count = 1; 406 arg_list.count = 1;
@@ -394,7 +409,8 @@ static void handle_dock(struct dock_station *ds, int dock)
394 arg.integer.value = dock; 409 arg.integer.value = dock;
395 status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); 410 status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
396 if (ACPI_FAILURE(status)) 411 if (ACPI_FAILURE(status))
397 pr_debug("%s: failed to execute _DCK\n", obj->string.pointer); 412 printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n",
413 (char *)name_buffer.pointer);
398 kfree(buffer.pointer); 414 kfree(buffer.pointer);
399 kfree(name_buffer.pointer); 415 kfree(name_buffer.pointer);
400} 416}
@@ -420,6 +436,16 @@ static inline void complete_dock(struct dock_station *ds)
420 ds->last_dock_time = jiffies; 436 ds->last_dock_time = jiffies;
421} 437}
422 438
439static inline void begin_undock(struct dock_station *ds)
440{
441 ds->flags |= DOCK_UNDOCKING;
442}
443
444static inline void complete_undock(struct dock_station *ds)
445{
446 ds->flags &= ~(DOCK_UNDOCKING);
447}
448
423/** 449/**
424 * dock_in_progress - see if we are in the middle of handling a dock event 450 * dock_in_progress - see if we are in the middle of handling a dock event
425 * @ds: the dock station 451 * @ds: the dock station
@@ -550,7 +576,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
550 printk(KERN_ERR PREFIX "Unable to undock!\n"); 576 printk(KERN_ERR PREFIX "Unable to undock!\n");
551 return -EBUSY; 577 return -EBUSY;
552 } 578 }
553 579 complete_undock(ds);
554 return 0; 580 return 0;
555} 581}
556 582
@@ -594,7 +620,11 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
594 * to the driver who wish to hotplug. 620 * to the driver who wish to hotplug.
595 */ 621 */
596 case ACPI_NOTIFY_EJECT_REQUEST: 622 case ACPI_NOTIFY_EJECT_REQUEST:
597 handle_eject_request(ds, event); 623 begin_undock(ds);
624 if (immediate_undock)
625 handle_eject_request(ds, event);
626 else
627 dock_event(ds, event, UNDOCK_EVENT);
598 break; 628 break;
599 default: 629 default:
600 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); 630 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
@@ -653,6 +683,17 @@ static ssize_t show_docked(struct device *dev,
653DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); 683DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
654 684
655/* 685/*
686 * show_flags - read method for flags file in sysfs
687 */
688static ssize_t show_flags(struct device *dev,
689 struct device_attribute *attr, char *buf)
690{
691 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
692
693}
694DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
695
696/*
656 * write_undock - write method for "undock" file in sysfs 697 * write_undock - write method for "undock" file in sysfs
657 */ 698 */
658static ssize_t write_undock(struct device *dev, struct device_attribute *attr, 699static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
@@ -675,16 +716,15 @@ static ssize_t show_dock_uid(struct device *dev,
675 struct device_attribute *attr, char *buf) 716 struct device_attribute *attr, char *buf)
676{ 717{
677 unsigned long lbuf; 718 unsigned long lbuf;
678 acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); 719 acpi_status status = acpi_evaluate_integer(dock_station->handle,
679 if(ACPI_FAILURE(status)) { 720 "_UID", NULL, &lbuf);
721 if (ACPI_FAILURE(status))
680 return 0; 722 return 0;
681 } 723
682 return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); 724 return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf);
683} 725}
684DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); 726DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
685 727
686
687
688/** 728/**
689 * dock_add - add a new dock station 729 * dock_add - add a new dock station
690 * @handle: the dock station handle 730 * @handle: the dock station handle
@@ -711,33 +751,53 @@ static int dock_add(acpi_handle handle)
711 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 751 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
712 752
713 /* initialize platform device stuff */ 753 /* initialize platform device stuff */
714 dock_device.name = dock_device_name; 754 dock_device =
715 ret = platform_device_register(&dock_device); 755 platform_device_register_simple(dock_device_name, 0, NULL, 0);
756 if (IS_ERR(dock_device)) {
757 kfree(dock_station);
758 dock_station = NULL;
759 return PTR_ERR(dock_device);
760 }
761
762 /* we want the dock device to send uevents */
763 dock_device->dev.uevent_suppress = 0;
764
765 ret = device_create_file(&dock_device->dev, &dev_attr_docked);
716 if (ret) { 766 if (ret) {
717 printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret); 767 printk("Error %d adding sysfs file\n", ret);
768 platform_device_unregister(dock_device);
718 kfree(dock_station); 769 kfree(dock_station);
770 dock_station = NULL;
719 return ret; 771 return ret;
720 } 772 }
721 ret = device_create_file(&dock_device.dev, &dev_attr_docked); 773 ret = device_create_file(&dock_device->dev, &dev_attr_undock);
722 if (ret) { 774 if (ret) {
723 printk("Error %d adding sysfs file\n", ret); 775 printk("Error %d adding sysfs file\n", ret);
724 platform_device_unregister(&dock_device); 776 device_remove_file(&dock_device->dev, &dev_attr_docked);
777 platform_device_unregister(dock_device);
725 kfree(dock_station); 778 kfree(dock_station);
779 dock_station = NULL;
726 return ret; 780 return ret;
727 } 781 }
728 ret = device_create_file(&dock_device.dev, &dev_attr_undock); 782 ret = device_create_file(&dock_device->dev, &dev_attr_uid);
729 if (ret) { 783 if (ret) {
730 printk("Error %d adding sysfs file\n", ret); 784 printk("Error %d adding sysfs file\n", ret);
731 device_remove_file(&dock_device.dev, &dev_attr_docked); 785 device_remove_file(&dock_device->dev, &dev_attr_docked);
732 platform_device_unregister(&dock_device); 786 device_remove_file(&dock_device->dev, &dev_attr_undock);
787 platform_device_unregister(dock_device);
733 kfree(dock_station); 788 kfree(dock_station);
789 dock_station = NULL;
734 return ret; 790 return ret;
735 } 791 }
736 ret = device_create_file(&dock_device.dev, &dev_attr_uid); 792 ret = device_create_file(&dock_device->dev, &dev_attr_flags);
737 if (ret) { 793 if (ret) {
738 printk("Error %d adding sysfs file\n", ret); 794 printk("Error %d adding sysfs file\n", ret);
739 platform_device_unregister(&dock_device); 795 device_remove_file(&dock_device->dev, &dev_attr_docked);
796 device_remove_file(&dock_device->dev, &dev_attr_undock);
797 device_remove_file(&dock_device->dev, &dev_attr_uid);
798 platform_device_unregister(dock_device);
740 kfree(dock_station); 799 kfree(dock_station);
800 dock_station = NULL;
741 return ret; 801 return ret;
742 } 802 }
743 803
@@ -750,6 +810,7 @@ static int dock_add(acpi_handle handle)
750 dd = alloc_dock_dependent_device(handle); 810 dd = alloc_dock_dependent_device(handle);
751 if (!dd) { 811 if (!dd) {
752 kfree(dock_station); 812 kfree(dock_station);
813 dock_station = NULL;
753 ret = -ENOMEM; 814 ret = -ENOMEM;
754 goto dock_add_err_unregister; 815 goto dock_add_err_unregister;
755 } 816 }
@@ -773,10 +834,13 @@ static int dock_add(acpi_handle handle)
773dock_add_err: 834dock_add_err:
774 kfree(dd); 835 kfree(dd);
775dock_add_err_unregister: 836dock_add_err_unregister:
776 device_remove_file(&dock_device.dev, &dev_attr_docked); 837 device_remove_file(&dock_device->dev, &dev_attr_docked);
777 device_remove_file(&dock_device.dev, &dev_attr_undock); 838 device_remove_file(&dock_device->dev, &dev_attr_undock);
778 platform_device_unregister(&dock_device); 839 device_remove_file(&dock_device->dev, &dev_attr_uid);
840 device_remove_file(&dock_device->dev, &dev_attr_flags);
841 platform_device_unregister(dock_device);
779 kfree(dock_station); 842 kfree(dock_station);
843 dock_station = NULL;
780 return ret; 844 return ret;
781} 845}
782 846
@@ -804,12 +868,15 @@ static int dock_remove(void)
804 printk(KERN_ERR "Error removing notify handler\n"); 868 printk(KERN_ERR "Error removing notify handler\n");
805 869
806 /* cleanup sysfs */ 870 /* cleanup sysfs */
807 device_remove_file(&dock_device.dev, &dev_attr_docked); 871 device_remove_file(&dock_device->dev, &dev_attr_docked);
808 device_remove_file(&dock_device.dev, &dev_attr_undock); 872 device_remove_file(&dock_device->dev, &dev_attr_undock);
809 platform_device_unregister(&dock_device); 873 device_remove_file(&dock_device->dev, &dev_attr_uid);
874 device_remove_file(&dock_device->dev, &dev_attr_flags);
875 platform_device_unregister(dock_device);
810 876
811 /* free dock station memory */ 877 /* free dock station memory */
812 kfree(dock_station); 878 kfree(dock_station);
879 dock_station = NULL;
813 return 0; 880 return 0;
814} 881}
815 882