aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2006-12-16 00:33:45 -0500
committerLen Brown <len.brown@intel.com>2006-12-16 00:33:45 -0500
commitfb7665544dd60e016494cd5531f5b65ddae22ddc (patch)
treea28c785088202533100fcea292215e223fb87a89 /drivers/acpi
parent678f2b7df24c34f90fee264fa3a8069bca9c99ad (diff)
parent8ea86e0ba7c9d16ae0f35cb0c4165194fa573f7a (diff)
Pull dock into test branch
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/dock.c131
1 files changed, 110 insertions, 21 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index bf5b79ed3613..215f5b30a1f1 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -27,6 +27,7 @@
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/types.h> 28#include <linux/types.h>
29#include <linux/notifier.h> 29#include <linux/notifier.h>
30#include <linux/platform_device.h>
30#include <linux/jiffies.h> 31#include <linux/jiffies.h>
31#include <acpi/acpi_bus.h> 32#include <acpi/acpi_bus.h>
32#include <acpi/acpi_drivers.h> 33#include <acpi/acpi_drivers.h>
@@ -39,6 +40,8 @@ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
39MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
40 41
41static struct atomic_notifier_head dock_notifier_list; 42static struct atomic_notifier_head dock_notifier_list;
43static struct platform_device dock_device;
44static char dock_device_name[] = "dock";
42 45
43struct dock_station { 46struct dock_station {
44 acpi_handle handle; 47 acpi_handle handle;
@@ -323,10 +326,12 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
323 326
324static void dock_event(struct dock_station *ds, u32 event, int num) 327static void dock_event(struct dock_station *ds, u32 event, int num)
325{ 328{
329 struct device *dev = &dock_device.dev;
326 /* 330 /*
327 * we don't do events until someone tells me that 331 * Indicate that the status of the dock station has
328 * they would like to have them. 332 * changed.
329 */ 333 */
334 kobject_uevent(&dev->kobj, KOBJ_CHANGE);
330} 335}
331 336
332/** 337/**
@@ -441,6 +446,9 @@ static int dock_in_progress(struct dock_station *ds)
441 */ 446 */
442int register_dock_notifier(struct notifier_block *nb) 447int register_dock_notifier(struct notifier_block *nb)
443{ 448{
449 if (!dock_station)
450 return -ENODEV;
451
444 return atomic_notifier_chain_register(&dock_notifier_list, nb); 452 return atomic_notifier_chain_register(&dock_notifier_list, nb);
445} 453}
446 454
@@ -452,6 +460,9 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
452 */ 460 */
453void unregister_dock_notifier(struct notifier_block *nb) 461void unregister_dock_notifier(struct notifier_block *nb)
454{ 462{
463 if (!dock_station)
464 return;
465
455 atomic_notifier_chain_unregister(&dock_notifier_list, nb); 466 atomic_notifier_chain_unregister(&dock_notifier_list, nb);
456} 467}
457 468
@@ -512,6 +523,37 @@ void unregister_hotplug_dock_device(acpi_handle handle)
512EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 523EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
513 524
514/** 525/**
526 * handle_eject_request - handle an undock request checking for error conditions
527 *
528 * Check to make sure the dock device is still present, then undock and
529 * hotremove all the devices that may need removing.
530 */
531static int handle_eject_request(struct dock_station *ds, u32 event)
532{
533 if (!dock_present(ds))
534 return -ENODEV;
535
536 if (dock_in_progress(ds))
537 return -EBUSY;
538
539 /*
540 * here we need to generate the undock
541 * event prior to actually doing the undock
542 * so that the device struct still exists.
543 */
544 dock_event(ds, event, UNDOCK_EVENT);
545 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
546 undock(ds);
547 eject_dock(ds);
548 if (dock_present(ds)) {
549 printk(KERN_ERR PREFIX "Unable to undock!\n");
550 return -EBUSY;
551 }
552
553 return 0;
554}
555
556/**
515 * dock_notify - act upon an acpi dock notification 557 * dock_notify - act upon an acpi dock notification
516 * @handle: the dock station handle 558 * @handle: the dock station handle
517 * @event: the acpi event 559 * @event: the acpi event
@@ -519,9 +561,7 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
519 * 561 *
520 * If we are notified to dock, then check to see if the dock is 562 * If we are notified to dock, then check to see if the dock is
521 * present and then dock. Notify all drivers of the dock event, 563 * present and then dock. Notify all drivers of the dock event,
522 * and then hotplug and devices that may need hotplugging. For undock 564 * and then hotplug and devices that may need hotplugging.
523 * check to make sure the dock device is still present, then undock
524 * and hotremove all the devices that may need removing.
525 */ 565 */
526static void dock_notify(acpi_handle handle, u32 event, void *data) 566static void dock_notify(acpi_handle handle, u32 event, void *data)
527{ 567{
@@ -553,19 +593,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
553 * to the driver who wish to hotplug. 593 * to the driver who wish to hotplug.
554 */ 594 */
555 case ACPI_NOTIFY_EJECT_REQUEST: 595 case ACPI_NOTIFY_EJECT_REQUEST:
556 if (!dock_in_progress(ds) && dock_present(ds)) { 596 handle_eject_request(ds, event);
557 /*
558 * here we need to generate the undock
559 * event prior to actually doing the undock
560 * so that the device struct still exists.
561 */
562 dock_event(ds, event, UNDOCK_EVENT);
563 hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
564 undock(ds);
565 eject_dock(ds);
566 if (dock_present(ds))
567 printk(KERN_ERR PREFIX "Unable to undock!\n");
568 }
569 break; 597 break;
570 default: 598 default:
571 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); 599 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
@@ -604,6 +632,33 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
604 return AE_OK; 632 return AE_OK;
605} 633}
606 634
635/*
636 * show_docked - read method for "docked" file in sysfs
637 */
638static ssize_t show_docked(struct device *dev,
639 struct device_attribute *attr, char *buf)
640{
641 return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
642
643}
644DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
645
646/*
647 * write_undock - write method for "undock" file in sysfs
648 */
649static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
650 const char *buf, size_t count)
651{
652 int ret;
653
654 if (!count)
655 return -EINVAL;
656
657 ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
658 return ret ? ret: count;
659}
660DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
661
607/** 662/**
608 * dock_add - add a new dock station 663 * dock_add - add a new dock station
609 * @handle: the dock station handle 664 * @handle: the dock station handle
@@ -629,6 +684,30 @@ static int dock_add(acpi_handle handle)
629 spin_lock_init(&dock_station->hp_lock); 684 spin_lock_init(&dock_station->hp_lock);
630 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 685 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
631 686
687 /* initialize platform device stuff */
688 dock_device.name = dock_device_name;
689 ret = platform_device_register(&dock_device);
690 if (ret) {
691 printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);
692 kfree(dock_station);
693 return ret;
694 }
695 ret = device_create_file(&dock_device.dev, &dev_attr_docked);
696 if (ret) {
697 printk("Error %d adding sysfs file\n", ret);
698 platform_device_unregister(&dock_device);
699 kfree(dock_station);
700 return ret;
701 }
702 ret = device_create_file(&dock_device.dev, &dev_attr_undock);
703 if (ret) {
704 printk("Error %d adding sysfs file\n", ret);
705 device_remove_file(&dock_device.dev, &dev_attr_docked);
706 platform_device_unregister(&dock_device);
707 kfree(dock_station);
708 return ret;
709 }
710
632 /* Find dependent devices */ 711 /* Find dependent devices */
633 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 712 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
634 ACPI_UINT32_MAX, find_dock_devices, dock_station, 713 ACPI_UINT32_MAX, find_dock_devices, dock_station,
@@ -638,7 +717,8 @@ static int dock_add(acpi_handle handle)
638 dd = alloc_dock_dependent_device(handle); 717 dd = alloc_dock_dependent_device(handle);
639 if (!dd) { 718 if (!dd) {
640 kfree(dock_station); 719 kfree(dock_station);
641 return -ENOMEM; 720 ret = -ENOMEM;
721 goto dock_add_err_unregister;
642 } 722 }
643 add_dock_dependent_device(dock_station, dd); 723 add_dock_dependent_device(dock_station, dd);
644 724
@@ -658,8 +738,12 @@ static int dock_add(acpi_handle handle)
658 return 0; 738 return 0;
659 739
660dock_add_err: 740dock_add_err:
661 kfree(dock_station);
662 kfree(dd); 741 kfree(dd);
742dock_add_err_unregister:
743 device_remove_file(&dock_device.dev, &dev_attr_docked);
744 device_remove_file(&dock_device.dev, &dev_attr_undock);
745 platform_device_unregister(&dock_device);
746 kfree(dock_station);
663 return ret; 747 return ret;
664} 748}
665 749
@@ -686,6 +770,11 @@ static int dock_remove(void)
686 if (ACPI_FAILURE(status)) 770 if (ACPI_FAILURE(status))
687 printk(KERN_ERR "Error removing notify handler\n"); 771 printk(KERN_ERR "Error removing notify handler\n");
688 772
773 /* cleanup sysfs */
774 device_remove_file(&dock_device.dev, &dev_attr_docked);
775 device_remove_file(&dock_device.dev, &dev_attr_undock);
776 platform_device_unregister(&dock_device);
777
689 /* free dock station memory */ 778 /* free dock station memory */
690 kfree(dock_station); 779 kfree(dock_station);
691 return 0; 780 return 0;
@@ -726,7 +815,7 @@ static int __init dock_init(void)
726 ACPI_UINT32_MAX, find_dock, &num, NULL); 815 ACPI_UINT32_MAX, find_dock, &num, NULL);
727 816
728 if (!num) 817 if (!num)
729 return -ENODEV; 818 printk(KERN_INFO "No dock devices found.\n");
730 819
731 return 0; 820 return 0;
732} 821}