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.c171
1 files changed, 42 insertions, 129 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 5bfd769fc91f..44c6e6c0d545 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -103,8 +103,7 @@ enum dock_callback_type {
103 * 103 *
104 * Add the dependent device to the dock's dependent device list. 104 * Add the dependent device to the dock's dependent device list.
105 */ 105 */
106static int __init 106static int add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
107add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
108{ 107{
109 struct dock_dependent_device *dd; 108 struct dock_dependent_device *dd;
110 109
@@ -218,6 +217,17 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event,
218 dock_release_hotplug(dd); 217 dock_release_hotplug(dd);
219} 218}
220 219
220static struct dock_station *find_dock_station(acpi_handle handle)
221{
222 struct dock_station *ds;
223
224 list_for_each_entry(ds, &dock_stations, sibling)
225 if (ds->handle == handle)
226 return ds;
227
228 return NULL;
229}
230
221/** 231/**
222 * find_dock_dependent_device - get a device dependent on this dock 232 * find_dock_dependent_device - get a device dependent on this dock
223 * @ds: the dock station 233 * @ds: the dock station
@@ -238,33 +248,19 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
238 return NULL; 248 return NULL;
239} 249}
240 250
241/***************************************************************************** 251void register_dock_dependent_device(struct acpi_device *adev,
242 * Dock functions * 252 acpi_handle dshandle)
243 *****************************************************************************/
244static int __init is_battery(acpi_handle handle)
245{ 253{
246 struct acpi_device_info *info; 254 struct dock_station *ds = find_dock_station(dshandle);
247 int ret = 1; 255 acpi_handle handle = adev->handle;
248 256
249 if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) 257 if (ds && !find_dock_dependent_device(ds, handle))
250 return 0; 258 add_dock_dependent_device(ds, handle);
251 if (!(info->valid & ACPI_VALID_HID))
252 ret = 0;
253 else
254 ret = !strcmp("PNP0C0A", info->hardware_id.string);
255
256 kfree(info);
257 return ret;
258} 259}
259 260
260/* Check whether ACPI object is an ejectable battery or disk bay */ 261/*****************************************************************************
261static bool __init is_ejectable_bay(acpi_handle handle) 262 * Dock functions *
262{ 263 *****************************************************************************/
263 if (acpi_has_method(handle, "_EJ0") && is_battery(handle))
264 return true;
265
266 return acpi_bay_match(handle);
267}
268 264
269/** 265/**
270 * is_dock_device - see if a device is on a dock station 266 * is_dock_device - see if a device is on a dock station
@@ -598,20 +594,23 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
598} 594}
599 595
600/** 596/**
601 * dock_notify - act upon an acpi dock notification 597 * dock_notify - Handle ACPI dock notification.
602 * @ds: dock station 598 * @adev: Dock station's ACPI device object.
603 * @event: the acpi event 599 * @event: Event code.
604 * 600 *
605 * If we are notified to dock, then check to see if the dock is 601 * If we are notified to dock, then check to see if the dock is
606 * present and then dock. Notify all drivers of the dock event, 602 * present and then dock. Notify all drivers of the dock event,
607 * and then hotplug and devices that may need hotplugging. 603 * and then hotplug and devices that may need hotplugging.
608 */ 604 */
609static void dock_notify(struct dock_station *ds, u32 event) 605int dock_notify(struct acpi_device *adev, u32 event)
610{ 606{
611 acpi_handle handle = ds->handle; 607 acpi_handle handle = adev->handle;
612 struct acpi_device *adev = NULL; 608 struct dock_station *ds = find_dock_station(handle);
613 int surprise_removal = 0; 609 int surprise_removal = 0;
614 610
611 if (!ds)
612 return -ENODEV;
613
615 /* 614 /*
616 * According to acpi spec 3.0a, if a DEVICE_CHECK notification 615 * According to acpi spec 3.0a, if a DEVICE_CHECK notification
617 * is sent and _DCK is present, it is assumed to mean an undock 616 * is sent and _DCK is present, it is assumed to mean an undock
@@ -632,7 +631,6 @@ static void dock_notify(struct dock_station *ds, u32 event)
632 switch (event) { 631 switch (event) {
633 case ACPI_NOTIFY_BUS_CHECK: 632 case ACPI_NOTIFY_BUS_CHECK:
634 case ACPI_NOTIFY_DEVICE_CHECK: 633 case ACPI_NOTIFY_DEVICE_CHECK:
635 acpi_bus_get_device(handle, &adev);
636 if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) { 634 if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
637 begin_dock(ds); 635 begin_dock(ds);
638 dock(ds); 636 dock(ds);
@@ -662,49 +660,8 @@ static void dock_notify(struct dock_station *ds, u32 event)
662 else 660 else
663 dock_event(ds, event, UNDOCK_EVENT); 661 dock_event(ds, event, UNDOCK_EVENT);
664 break; 662 break;
665 default:
666 acpi_handle_err(handle, "Unknown dock event %d\n", event);
667 } 663 }
668} 664 return 0;
669
670static void acpi_dock_deferred_cb(void *data, u32 event)
671{
672 acpi_scan_lock_acquire();
673 dock_notify(data, event);
674 acpi_scan_lock_release();
675}
676
677static void dock_notify_handler(acpi_handle handle, u32 event, void *data)
678{
679 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
680 && event != ACPI_NOTIFY_EJECT_REQUEST)
681 return;
682
683 acpi_hotplug_execute(acpi_dock_deferred_cb, data, event);
684}
685
686/**
687 * find_dock_devices - find devices on the dock station
688 * @handle: the handle of the device we are examining
689 * @lvl: unused
690 * @context: the dock station private data
691 * @rv: unused
692 *
693 * This function is called by acpi_walk_namespace. It will
694 * check to see if an object has an _EJD method. If it does, then it
695 * will see if it is dependent on the dock station.
696 */
697static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl,
698 void *context, void **rv)
699{
700 struct dock_station *ds = context;
701 acpi_handle ejd = NULL;
702
703 acpi_bus_get_ejd(handle, &ejd);
704 if (ejd == ds->handle)
705 add_dock_dependent_device(ds, handle);
706
707 return AE_OK;
708} 665}
709 666
710/* 667/*
@@ -803,23 +760,22 @@ static struct attribute_group dock_attribute_group = {
803}; 760};
804 761
805/** 762/**
806 * dock_add - add a new dock station 763 * acpi_dock_add - Add a new dock station
807 * @handle: the dock station handle 764 * @adev: Dock station ACPI device object.
808 * 765 *
809 * allocated and initialize a new dock station device. Find all devices 766 * allocated and initialize a new dock station device.
810 * that are on the dock station, and register for dock event notifications.
811 */ 767 */
812static int __init dock_add(acpi_handle handle) 768void acpi_dock_add(struct acpi_device *adev)
813{ 769{
814 struct dock_station *dock_station, ds = { NULL, }; 770 struct dock_station *dock_station, ds = { NULL, };
771 acpi_handle handle = adev->handle;
815 struct platform_device *dd; 772 struct platform_device *dd;
816 acpi_status status;
817 int ret; 773 int ret;
818 774
819 dd = platform_device_register_data(NULL, "dock", dock_station_count, 775 dd = platform_device_register_data(NULL, "dock", dock_station_count,
820 &ds, sizeof(ds)); 776 &ds, sizeof(ds));
821 if (IS_ERR(dd)) 777 if (IS_ERR(dd))
822 return PTR_ERR(dd); 778 return;
823 779
824 dock_station = dd->dev.platform_data; 780 dock_station = dd->dev.platform_data;
825 781
@@ -837,33 +793,24 @@ static int __init dock_add(acpi_handle handle)
837 dock_station->flags |= DOCK_IS_DOCK; 793 dock_station->flags |= DOCK_IS_DOCK;
838 if (acpi_ata_match(handle)) 794 if (acpi_ata_match(handle))
839 dock_station->flags |= DOCK_IS_ATA; 795 dock_station->flags |= DOCK_IS_ATA;
840 if (is_battery(handle)) 796 if (acpi_device_is_battery(handle))
841 dock_station->flags |= DOCK_IS_BAT; 797 dock_station->flags |= DOCK_IS_BAT;
842 798
843 ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group); 799 ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
844 if (ret) 800 if (ret)
845 goto err_unregister; 801 goto err_unregister;
846 802
847 /* Find dependent devices */
848 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
849 ACPI_UINT32_MAX, find_dock_devices, NULL,
850 dock_station, NULL);
851
852 /* add the dock station as a device dependent on itself */ 803 /* add the dock station as a device dependent on itself */
853 ret = add_dock_dependent_device(dock_station, handle); 804 ret = add_dock_dependent_device(dock_station, handle);
854 if (ret) 805 if (ret)
855 goto err_rmgroup; 806 goto err_rmgroup;
856 807
857 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
858 dock_notify_handler, dock_station);
859 if (ACPI_FAILURE(status)) {
860 ret = -ENODEV;
861 goto err_rmgroup;
862 }
863
864 dock_station_count++; 808 dock_station_count++;
865 list_add(&dock_station->sibling, &dock_stations); 809 list_add(&dock_station->sibling, &dock_stations);
866 return 0; 810 adev->flags.is_dock_station = true;
811 dev_info(&adev->dev, "ACPI dock station (docks/bays count: %d)\n",
812 dock_station_count);
813 return;
867 814
868err_rmgroup: 815err_rmgroup:
869 remove_dock_dependent_devices(dock_station); 816 remove_dock_dependent_devices(dock_station);
@@ -871,38 +818,4 @@ err_rmgroup:
871err_unregister: 818err_unregister:
872 platform_device_unregister(dd); 819 platform_device_unregister(dd);
873 acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret); 820 acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
874 return ret;
875}
876
877/**
878 * find_dock_and_bay - look for dock stations and bays
879 * @handle: acpi handle of a device
880 * @lvl: unused
881 * @context: unused
882 * @rv: unused
883 *
884 * This is called by acpi_walk_namespace to look for dock stations and bays.
885 */
886static acpi_status __init
887find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
888{
889 if (acpi_dock_match(handle) || is_ejectable_bay(handle))
890 dock_add(handle);
891
892 return AE_OK;
893}
894
895void __init acpi_dock_init(void)
896{
897 /* look for dock stations and bays */
898 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
899 ACPI_UINT32_MAX, find_dock_and_bay, NULL, NULL, NULL);
900
901 if (!dock_station_count) {
902 pr_info(PREFIX "No dock devices found.\n");
903 return;
904 }
905
906 pr_info(PREFIX "%s: %d docks/bays found\n",
907 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
908} 821}