ACPI: introduce notifier change to avoid duplicates
authorShaohua Li <shaohua.li@intel.com>
Thu, 28 Aug 2008 02:04:29 +0000 (10:04 +0800)
committerLen Brown <len.brown@intel.com>
Wed, 24 Sep 2008 03:04:43 +0000 (23:04 -0400)
The battery driver already registers notification handler.
To avoid registering notification handler again,
introduce a notifier chain in global system notifier handler
and use it in dock driver.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/bus.c
drivers/acpi/dock.c
include/acpi/acpi_bus.h

index ccae305..0dc4494 100644 (file)
@@ -496,6 +496,19 @@ static int acpi_bus_check_scope(struct acpi_device *device)
        return 0;
 }
 
+static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
+int register_acpi_bus_notifier(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);
+
+void unregister_acpi_bus_notifier(struct notifier_block *nb)
+{
+       blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);
+
 /**
  * acpi_bus_notify
  * ---------------
@@ -506,6 +519,8 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
        int result = 0;
        struct acpi_device *device = NULL;
 
+       blocking_notifier_call_chain(&acpi_bus_notify_list,
+               type, (void *)handle);
 
        if (acpi_bus_get_device(handle, &device))
                return;
index 799a0fd..2563bc6 100644 (file)
@@ -748,6 +748,28 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
        }
 }
 
+static int acpi_dock_notifier_call(struct notifier_block *this,
+       unsigned long event, void *data)
+{
+       struct dock_station *dock_station;
+       acpi_handle handle = (acpi_handle)data;
+
+       if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
+          && event != ACPI_NOTIFY_EJECT_REQUEST)
+               return 0;
+       list_for_each_entry(dock_station, &dock_stations, sibiling) {
+               if (dock_station->handle == handle) {
+                       dock_notify(handle, event, dock_station);
+                       return 0 ;
+               }
+       }
+       return 0;
+}
+
+static struct notifier_block dock_acpi_notifier = {
+       .notifier_call = acpi_dock_notifier_call,
+};
+
 /**
  * find_dock_devices - find devices on the dock station
  * @handle: the handle of the device we are examining
@@ -861,7 +883,6 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
 static int dock_add(acpi_handle handle)
 {
        int ret;
-       acpi_status status;
        struct dock_dependent_device *dd;
        struct dock_station *dock_station;
        struct platform_device *dock_device;
@@ -956,23 +977,10 @@ static int dock_add(acpi_handle handle)
        }
        add_dock_dependent_device(dock_station, dd);
 
-       /* register for dock events */
-       status = acpi_install_notify_handler(dock_station->handle,
-                                            ACPI_SYSTEM_NOTIFY,
-                                            dock_notify, dock_station);
-
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR PREFIX "Error installing notify handler\n");
-               ret = -ENODEV;
-               goto dock_add_err;
-       }
-
        dock_station_count++;
        list_add(&dock_station->sibiling, &dock_stations);
        return 0;
 
-dock_add_err:
-       kfree(dd);
 dock_add_err_unregister:
        device_remove_file(&dock_device->dev, &dev_attr_docked);
        device_remove_file(&dock_device->dev, &dev_attr_undock);
@@ -990,7 +998,6 @@ dock_add_err_unregister:
 static int dock_remove(struct dock_station *dock_station)
 {
        struct dock_dependent_device *dd, *tmp;
-       acpi_status status;
        struct platform_device *dock_device = dock_station->dock_device;
 
        if (!dock_station_count)
@@ -1001,13 +1008,6 @@ static int dock_remove(struct dock_station *dock_station)
                                 list)
            kfree(dd);
 
-       /* remove dock notify handler */
-       status = acpi_remove_notify_handler(dock_station->handle,
-                                           ACPI_SYSTEM_NOTIFY,
-                                           dock_notify);
-       if (ACPI_FAILURE(status))
-               printk(KERN_ERR "Error removing notify handler\n");
-
        /* cleanup sysfs */
        device_remove_file(&dock_device->dev, &dev_attr_docked);
        device_remove_file(&dock_device->dev, &dev_attr_undock);
@@ -1069,6 +1069,7 @@ static int __init dock_init(void)
                return 0;
        }
 
+       register_acpi_bus_notifier(&dock_acpi_notifier);
        printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
                ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
        return 0;
@@ -1078,6 +1079,7 @@ static void __exit dock_exit(void)
 {
        struct dock_station *dock_station;
 
+       unregister_acpi_bus_notifier(&dock_acpi_notifier);
        list_for_each_entry(dock_station, &dock_stations, sibiling)
                dock_remove(dock_station);
 }
index a5ac0bc..f74f882 100644 (file)
@@ -327,6 +327,9 @@ int acpi_bus_get_private_data(acpi_handle, void **);
 extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32);
 extern int register_acpi_notifier(struct notifier_block *);
 extern int unregister_acpi_notifier(struct notifier_block *);
+
+extern int register_acpi_bus_notifier(struct notifier_block *nb);
+extern void unregister_acpi_bus_notifier(struct notifier_block *nb);
 /*
  * External Functions
  */