aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/dock.c95
1 files changed, 79 insertions, 16 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 2c2f28db9fb2..e4c1a4ff4e31 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -515,6 +515,37 @@ void unregister_hotplug_dock_device(acpi_handle handle)
515EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 515EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
516 516
517/** 517/**
518 * handle_eject_request - handle an undock request checking for error conditions
519 *
520 * Check to make sure the dock device is still present, then undock and
521 * hotremove all the devices that may need removing.
522 */
523static int handle_eject_request(struct dock_station *ds, u32 event)
524{
525 if (!dock_present(ds))
526 return -ENODEV;
527
528 if (dock_in_progress(ds))
529 return -EBUSY;
530
531 /*
532 * here we need to generate the undock
533 * event prior to actually doing the undock
534 * so that the device struct still exists.
535 */
536 dock_event(ds, event, UNDOCK_EVENT);
537 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
538 undock(ds);
539 eject_dock(ds);
540 if (dock_present(ds)) {
541 printk(KERN_ERR PREFIX "Unable to undock!\n");
542 return -EBUSY;
543 }
544
545 return 0;
546}
547
548/**
518 * dock_notify - act upon an acpi dock notification 549 * dock_notify - act upon an acpi dock notification
519 * @handle: the dock station handle 550 * @handle: the dock station handle
520 * @event: the acpi event 551 * @event: the acpi event
@@ -522,9 +553,7 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
522 * 553 *
523 * If we are notified to dock, then check to see if the dock is 554 * If we are notified to dock, then check to see if the dock is
524 * present and then dock. Notify all drivers of the dock event, 555 * present and then dock. Notify all drivers of the dock event,
525 * and then hotplug and devices that may need hotplugging. For undock 556 * and then hotplug and devices that may need hotplugging.
526 * check to make sure the dock device is still present, then undock
527 * and hotremove all the devices that may need removing.
528 */ 557 */
529static void dock_notify(acpi_handle handle, u32 event, void *data) 558static void dock_notify(acpi_handle handle, u32 event, void *data)
530{ 559{
@@ -556,19 +585,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
556 * to the driver who wish to hotplug. 585 * to the driver who wish to hotplug.
557 */ 586 */
558 case ACPI_NOTIFY_EJECT_REQUEST: 587 case ACPI_NOTIFY_EJECT_REQUEST:
559 if (!dock_in_progress(ds) && dock_present(ds)) { 588 handle_eject_request(ds, event);
560 /*
561 * here we need to generate the undock
562 * event prior to actually doing the undock
563 * so that the device struct still exists.
564 */
565 dock_event(ds, event, UNDOCK_EVENT);
566 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
567 undock(ds);
568 eject_dock(ds);
569 if (dock_present(ds))
570 printk(KERN_ERR PREFIX "Unable to undock!\n");
571 }
572 break; 589 break;
573 default: 590 default:
574 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); 591 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
@@ -607,6 +624,33 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
607 return AE_OK; 624 return AE_OK;
608} 625}
609 626
627/*
628 * show_docked - read method for "docked" file in sysfs
629 */
630static ssize_t show_docked(struct device *dev,
631 struct device_attribute *attr, char *buf)
632{
633 return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
634
635}
636DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
637
638/*
639 * write_undock - write method for "undock" file in sysfs
640 */
641static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
642 const char *buf, size_t count)
643{
644 int ret;
645
646 if (!count)
647 return -EINVAL;
648
649 ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
650 return ret ? ret: count;
651}
652DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
653
610/** 654/**
611 * dock_add - add a new dock station 655 * dock_add - add a new dock station
612 * @handle: the dock station handle 656 * @handle: the dock station handle
@@ -640,6 +684,21 @@ static int dock_add(acpi_handle handle)
640 kfree(dock_station); 684 kfree(dock_station);
641 return ret; 685 return ret;
642 } 686 }
687 ret = device_create_file(&dock_device.dev, &dev_attr_docked);
688 if (ret) {
689 printk("Error %d adding sysfs file\n", ret);
690 platform_device_unregister(&dock_device);
691 kfree(dock_station);
692 return ret;
693 }
694 ret = device_create_file(&dock_device.dev, &dev_attr_undock);
695 if (ret) {
696 printk("Error %d adding sysfs file\n", ret);
697 device_remove_file(&dock_device.dev, &dev_attr_docked);
698 platform_device_unregister(&dock_device);
699 kfree(dock_station);
700 return ret;
701 }
643 702
644 /* Find dependent devices */ 703 /* Find dependent devices */
645 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 704 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -673,6 +732,8 @@ static int dock_add(acpi_handle handle)
673dock_add_err: 732dock_add_err:
674 kfree(dd); 733 kfree(dd);
675dock_add_err_unregister: 734dock_add_err_unregister:
735 device_remove_file(&dock_device.dev, &dev_attr_docked);
736 device_remove_file(&dock_device.dev, &dev_attr_undock);
676 platform_device_unregister(&dock_device); 737 platform_device_unregister(&dock_device);
677 kfree(dock_station); 738 kfree(dock_station);
678 return ret; 739 return ret;
@@ -702,6 +763,8 @@ static int dock_remove(void)
702 printk(KERN_ERR "Error removing notify handler\n"); 763 printk(KERN_ERR "Error removing notify handler\n");
703 764
704 /* cleanup sysfs */ 765 /* cleanup sysfs */
766 device_remove_file(&dock_device.dev, &dev_attr_docked);
767 device_remove_file(&dock_device.dev, &dev_attr_undock);
705 platform_device_unregister(&dock_device); 768 platform_device_unregister(&dock_device);
706 769
707 /* free dock station memory */ 770 /* free dock station memory */