aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-30 17:48:49 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-14 19:33:11 -0400
commit59401ccce8729e5c43f9781cc5570da5ca470e27 (patch)
tree89df37b34421898ea83163c942af31318039f99e
parent4ec24065a65b4debfdeb591cc01a4aa092651f53 (diff)
ACPI / dock: Rework the handling of notifications
The ACPI dock driver uses register_acpi_bus_notifier() which installs a notifier triggered globally for all system notifications. That first of all is inefficient, because the dock driver is only interested in notifications associated with the devices it handles, but it has to handle all system notifies for all devices. Moreover, it does that even if no docking stations are present in the system (CONFIG_ACPI_DOCK set is sufficient for that to happen). Besides, that is inconvenient, because it requires the driver to do extra work for each notification to find the target dock station object. For these reasons, rework the dock driver to install a notify handler individually for each dock station in the system using acpi_install_notify_handler(). This allows the dock station object to be passed directly to the notify handler and makes it possible to simplify the dock driver quite a bit. It also reduces the overhead related to the handling of all system notifies when CONFIG_ACPI_DOCK is set. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org>
-rw-r--r--drivers/acpi/dock.c67
1 files changed, 24 insertions, 43 deletions
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index b1170d60a836..a326c7993f4f 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -607,18 +607,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
607 607
608/** 608/**
609 * dock_notify - act upon an acpi dock notification 609 * dock_notify - act upon an acpi dock notification
610 * @handle: the dock station handle 610 * @ds: dock station
611 * @event: the acpi event 611 * @event: the acpi event
612 * @data: our driver data struct
613 * 612 *
614 * If we are notified to dock, then check to see if the dock is 613 * If we are notified to dock, then check to see if the dock is
615 * present and then dock. Notify all drivers of the dock event, 614 * present and then dock. Notify all drivers of the dock event,
616 * and then hotplug and devices that may need hotplugging. 615 * and then hotplug and devices that may need hotplugging.
617 */ 616 */
618static void dock_notify(acpi_handle handle, u32 event, void *data) 617static void dock_notify(struct dock_station *ds, u32 event)
619{ 618{
620 struct dock_station *ds = data; 619 acpi_handle handle = ds->handle;
621 struct acpi_device *tmp; 620 struct acpi_device *ad;
622 int surprise_removal = 0; 621 int surprise_removal = 0;
623 622
624 /* 623 /*
@@ -641,8 +640,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
641 switch (event) { 640 switch (event) {
642 case ACPI_NOTIFY_BUS_CHECK: 641 case ACPI_NOTIFY_BUS_CHECK:
643 case ACPI_NOTIFY_DEVICE_CHECK: 642 case ACPI_NOTIFY_DEVICE_CHECK:
644 if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, 643 if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) {
645 &tmp)) {
646 begin_dock(ds); 644 begin_dock(ds);
647 dock(ds); 645 dock(ds);
648 if (!dock_present(ds)) { 646 if (!dock_present(ds)) {
@@ -679,9 +677,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
679} 677}
680 678
681struct dock_data { 679struct dock_data {
682 acpi_handle handle;
683 unsigned long event;
684 struct dock_station *ds; 680 struct dock_station *ds;
681 u32 event;
685}; 682};
686 683
687static void acpi_dock_deferred_cb(void *context) 684static void acpi_dock_deferred_cb(void *context)
@@ -689,52 +686,31 @@ static void acpi_dock_deferred_cb(void *context)
689 struct dock_data *data = context; 686 struct dock_data *data = context;
690 687
691 acpi_scan_lock_acquire(); 688 acpi_scan_lock_acquire();
692 dock_notify(data->handle, data->event, data->ds); 689 dock_notify(data->ds, data->event);
693 acpi_scan_lock_release(); 690 acpi_scan_lock_release();
694 kfree(data); 691 kfree(data);
695} 692}
696 693
697static int acpi_dock_notifier_call(struct notifier_block *this, 694static void dock_notify_handler(acpi_handle handle, u32 event, void *data)
698 unsigned long event, void *data)
699{ 695{
700 struct dock_station *dock_station; 696 struct dock_data *dd;
701 acpi_handle handle = data;
702 697
703 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK 698 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
704 && event != ACPI_NOTIFY_EJECT_REQUEST) 699 && event != ACPI_NOTIFY_EJECT_REQUEST)
705 return 0; 700 return;
706
707 acpi_scan_lock_acquire();
708
709 list_for_each_entry(dock_station, &dock_stations, sibling) {
710 if (dock_station->handle == handle) {
711 struct dock_data *dd;
712 acpi_status status;
713
714 dd = kmalloc(sizeof(*dd), GFP_KERNEL);
715 if (!dd)
716 break;
717 701
718 dd->handle = handle; 702 dd = kmalloc(sizeof(*dd), GFP_KERNEL);
719 dd->event = event; 703 if (dd) {
720 dd->ds = dock_station; 704 acpi_status status;
721 status = acpi_os_hotplug_execute(acpi_dock_deferred_cb,
722 dd);
723 if (ACPI_FAILURE(status))
724 kfree(dd);
725 705
726 break; 706 dd->ds = data;
727 } 707 dd->event = event;
708 status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
709 if (ACPI_FAILURE(status))
710 kfree(dd);
728 } 711 }
729
730 acpi_scan_lock_release();
731 return 0;
732} 712}
733 713
734static struct notifier_block dock_acpi_notifier = {
735 .notifier_call = acpi_dock_notifier_call,
736};
737
738/** 714/**
739 * find_dock_devices - find devices on the dock station 715 * find_dock_devices - find devices on the dock station
740 * @handle: the handle of the device we are examining 716 * @handle: the handle of the device we are examining
@@ -868,6 +844,7 @@ static int __init dock_add(acpi_handle handle)
868 int ret, id; 844 int ret, id;
869 struct dock_station ds, *dock_station; 845 struct dock_station ds, *dock_station;
870 struct platform_device *dd; 846 struct platform_device *dd;
847 acpi_status status;
871 848
872 id = dock_station_count; 849 id = dock_station_count;
873 memset(&ds, 0, sizeof(ds)); 850 memset(&ds, 0, sizeof(ds));
@@ -908,6 +885,11 @@ static int __init dock_add(acpi_handle handle)
908 if (ret) 885 if (ret)
909 goto err_rmgroup; 886 goto err_rmgroup;
910 887
888 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
889 dock_notify_handler, dock_station);
890 if (ACPI_FAILURE(status))
891 goto err_rmgroup;
892
911 dock_station_count++; 893 dock_station_count++;
912 list_add(&dock_station->sibling, &dock_stations); 894 list_add(&dock_station->sibling, &dock_stations);
913 return 0; 895 return 0;
@@ -953,7 +935,6 @@ void __init acpi_dock_init(void)
953 } 935 }
954 936
955 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 937 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
956 register_acpi_bus_notifier(&dock_acpi_notifier);
957 pr_info(PREFIX "%s: %d docks/bays found\n", 938 pr_info(PREFIX "%s: %d docks/bays found\n",
958 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); 939 ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
959} 940}