Merge branch 'acpi-cleanup'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 15 Feb 2013 12:58:30 +0000 (13:58 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 15 Feb 2013 12:58:30 +0000 (13:58 +0100)
* acpi-cleanup: (21 commits)
  ACPI / hotplug: Fix concurrency issues and memory leaks
  ACPI: Remove the use of CONFIG_ACPI_CONTAINER_MODULE
  ACPI / scan: Full transition to D3cold in acpi_device_unregister()
  ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock
  ACPI: Drop the container.h header file
  ACPI / Documentation: refer to correct file for acpi_platform_device_ids[] table
  ACPI / scan: Make container driver use struct acpi_scan_handler
  ACPI / scan: Remove useless #ifndef from acpi_eject_store()
  ACPI: Unbind ACPI drv when probe failed
  ACPI: sysfs eject support for ACPI scan handlers
  ACPI / scan: Follow priorities of IDs when matching scan handlers
  ACPI / PCI: pci_slot: replace printk(KERN_xxx) with pr_xxx()
  ACPI / dock: Fix acpi_bus_get_device() check in drivers/acpi/dock.c
  ACPI / scan: Clean up acpi_bus_get_parent()
  ACPI / platform: Use struct acpi_scan_handler for creating devices
  ACPI / PCI: Make PCI IRQ link driver use struct acpi_scan_handler
  ACPI / PCI: Make PCI root driver use struct acpi_scan_handler
  ACPI / scan: Introduce struct acpi_scan_handler
  ACPI / scan: Make scanning of fixed devices follow the general scheme
  ACPI: Drop device start operation that is not used
  ...

55 files changed:
Documentation/acpi/enumeration.txt
Documentation/acpi/scan_handlers.txt [new file with mode: 0644]
arch/ia64/hp/common/aml_nfw.c
arch/x86/platform/olpc/olpc-xo15-sci.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpi_pad.c
drivers/acpi/acpi_platform.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/container.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/fan.c
drivers/acpi/hed.c
drivers/acpi/internal.h
drivers/acpi/pci_link.c
drivers/acpi/pci_root.c
drivers/acpi/pci_slot.c
drivers/acpi/processor_driver.c
drivers/acpi/sbs.c
drivers/acpi/sbshc.c
drivers/acpi/scan.c
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/char/hpet.c
drivers/char/sonypi.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/asus_atk0110.c
drivers/i2c/busses/i2c-scmi.c
drivers/input/misc/atlas_btns.c
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/fujitsu-tablet.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/topstar-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/toshiba_bluetooth.c
drivers/platform/x86/wmi.c
drivers/platform/x86/xo15-ebook.c
drivers/staging/quickstart/quickstart.c
drivers/video/backlight/apple_bl.c
drivers/xen/xen-acpi-pad.c
include/acpi/acpi_bus.h
include/acpi/container.h [deleted file]
include/linux/acpi.h

index 54469bc81b1cbac644e482bd09ebb6c28b77db43..94a656131885f9bd7a2761c9a9b0e6853db54789 100644 (file)
@@ -63,8 +63,8 @@ from ACPI tables.
 Currently the kernel is not able to automatically determine from which ACPI
 device it should make the corresponding platform device so we need to add
 the ACPI device explicitly to acpi_platform_device_ids list defined in
-drivers/acpi/scan.c. This limitation is only for the platform devices, SPI
-and I2C devices are created automatically as described below.
+drivers/acpi/acpi_platform.c. This limitation is only for the platform
+devices, SPI and I2C devices are created automatically as described below.
 
 SPI serial bus support
 ~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/acpi/scan_handlers.txt b/Documentation/acpi/scan_handlers.txt
new file mode 100644 (file)
index 0000000..3246ccf
--- /dev/null
@@ -0,0 +1,77 @@
+ACPI Scan Handlers
+
+Copyright (C) 2012, Intel Corporation
+Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+During system initialization and ACPI-based device hot-add, the ACPI namespace
+is scanned in search of device objects that generally represent various pieces
+of hardware.  This causes a struct acpi_device object to be created and
+registered with the driver core for every device object in the ACPI namespace
+and the hierarchy of those struct acpi_device objects reflects the namespace
+layout (i.e. parent device objects in the namespace are represented by parent
+struct acpi_device objects and analogously for their children).  Those struct
+acpi_device objects are referred to as "device nodes" in what follows, but they
+should not be confused with struct device_node objects used by the Device Trees
+parsing code (although their role is analogous to the role of those objects).
+
+During ACPI-based device hot-remove device nodes representing pieces of hardware
+being removed are unregistered and deleted.
+
+The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
+initialization of device nodes, such as retrieving common configuration
+information from the device objects represented by them and populating them with
+appropriate data, but some of them require additional handling after they have
+been registered.  For example, if the given device node represents a PCI host
+bridge, its registration should cause the PCI bus under that bridge to be
+enumerated and PCI devices on that bus to be registered with the driver core.
+Similarly, if the device node represents a PCI interrupt link, it is necessary
+to configure that link so that the kernel can use it.
+
+Those additional configuration tasks usually depend on the type of the hardware
+component represented by the given device node which can be determined on the
+basis of the device node's hardware ID (HID).  They are performed by objects
+called ACPI scan handlers represented by the following structure:
+
+struct acpi_scan_handler {
+       const struct acpi_device_id *ids;
+       struct list_head list_node;
+       int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
+       void (*detach)(struct acpi_device *dev);
+};
+
+where ids is the list of IDs of device nodes the given handler is supposed to
+take care of, list_node is the hook to the global list of ACPI scan handlers
+maintained by the ACPI core and the .attach() and .detach() callbacks are
+executed, respectively, after registration of new device nodes and before
+unregistration of device nodes the handler attached to previously.
+
+The namespace scanning function, acpi_bus_scan(), first registers all of the
+device nodes in the given namespace scope with the driver core.  Then, it tries
+to match a scan handler against each of them using the ids arrays of the
+available scan handlers.  If a matching scan handler is found, its .attach()
+callback is executed for the given device node.  If that callback returns 1,
+that means that the handler has claimed the device node and is now responsible
+for carrying out any additional configuration tasks related to it.  It also will
+be responsible for preparing the device node for unregistration in that case.
+The device node's handler field is then populated with the address of the scan
+handler that has claimed it.
+
+If the .attach() callback returns 0, it means that the device node is not
+interesting to the given scan handler and may be matched against the next scan
+handler in the list.  If it returns a (negative) error code, that means that
+the namespace scan should be terminated due to a serious error.  The error code
+returned should then reflect the type of the error.
+
+The namespace trimming function, acpi_bus_trim(), first executes .detach()
+callbacks from the scan handlers of all device nodes in the given namespace
+scope (if they have scan handlers).  Next, it unregisters all of the device
+nodes in that scope.
+
+ACPI scan handlers can be added to the list maintained by the ACPI core with the
+help of the acpi_scan_add_handler() function taking a pointer to the new scan
+handler as an argument.  The order in which scan handlers are added to the list
+is the order in which they are matched against device nodes during namespace
+scans.
+
+All scan handles must be added to the list before acpi_bus_scan() is run for the
+first time and they cannot be removed from it.
index 6192f7188654e0549c01d934e7073a68890c7f7a..916ffe770bcf5691c0e2b6744a40f0d45c81d487 100644 (file)
@@ -191,7 +191,7 @@ static int aml_nfw_add(struct acpi_device *device)
        return aml_nfw_add_global_handler();
 }
 
-static int aml_nfw_remove(struct acpi_device *device, int type)
+static int aml_nfw_remove(struct acpi_device *device)
 {
        return aml_nfw_remove_global_handler();
 }
index 2fdca25905ae265c52a2695664da433e57e1b616..fef7d0ba7e3a93d8e44ed09cec92db708759cbcf 100644 (file)
@@ -195,7 +195,7 @@ err_sysfs:
        return r;
 }
 
-static int xo15_sci_remove(struct acpi_device *device, int type)
+static int xo15_sci_remove(struct acpi_device *device)
 {
        acpi_disable_gpe(NULL, xo15_sci_gpe);
        acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
index 38c5078da11d67ea9db98cf936812982b62f313c..78105b3a52623e9b22be90f71dcaa5b1ae33b725 100644 (file)
@@ -337,7 +337,7 @@ config X86_PM_TIMER
          systems require this timer. 
 
 config ACPI_CONTAINER
-       tristate "Container and Module Devices (EXPERIMENTAL)"
+       bool "Container and Module Devices (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
        help
index d5fdd36190cce3f385011b30a1f5c729a5b6a4dd..6d5bf649196dced64c75614fc586f1b16684e7bd 100644 (file)
@@ -60,7 +60,7 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file);
 #endif
 
 static int acpi_ac_add(struct acpi_device *device);
-static int acpi_ac_remove(struct acpi_device *device, int type);
+static int acpi_ac_remove(struct acpi_device *device);
 static void acpi_ac_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id ac_device_ids[] = {
@@ -337,7 +337,7 @@ static int acpi_ac_resume(struct device *dev)
 }
 #endif
 
-static int acpi_ac_remove(struct acpi_device *device, int type)
+static int acpi_ac_remove(struct acpi_device *device)
 {
        struct acpi_ac *ac = NULL;
 
index 03d18f290118b13eea43fbe130f13f1e889eb0f1..034d3e72aa92d6dca344a5da1a756571ad3cc0f8 100644 (file)
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
 #define MEMORY_POWER_OFF_STATE 2
 
 static int acpi_memory_device_add(struct acpi_device *device);
-static int acpi_memory_device_remove(struct acpi_device *device, int type);
+static int acpi_memory_device_remove(struct acpi_device *device);
 
 static const struct acpi_device_id memory_device_ids[] = {
        {ACPI_MEMORY_DEVICE_HID, 0},
@@ -153,14 +153,16 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
        return 0;
 }
 
-static int
-acpi_memory_get_device(acpi_handle handle,
-                      struct acpi_memory_device **mem_device)
+static int acpi_memory_get_device(acpi_handle handle,
+                                 struct acpi_memory_device **mem_device)
 {
        struct acpi_device *device = NULL;
-       int result;
+       int result = 0;
 
-       if (!acpi_bus_get_device(handle, &device) && device)
+       acpi_scan_lock_acquire();
+
+       acpi_bus_get_device(handle, &device);
+       if (device)
                goto end;
 
        /*
@@ -169,23 +171,28 @@ acpi_memory_get_device(acpi_handle handle,
         */
        result = acpi_bus_scan(handle);
        if (result) {
-               acpi_handle_warn(handle, "Cannot add acpi bus\n");
-               return -EINVAL;
+               acpi_handle_warn(handle, "ACPI namespace scan failed\n");
+               result = -EINVAL;
+               goto out;
        }
        result = acpi_bus_get_device(handle, &device);
        if (result) {
                acpi_handle_warn(handle, "Missing device object\n");
-               return -EINVAL;
+               result = -EINVAL;
+               goto out;
        }
 
     end:
+ end:
        *mem_device = acpi_driver_data(device);
        if (!(*mem_device)) {
                dev_err(&device->dev, "driver data not found\n");
-               return -ENODEV;
+               result = -ENODEV;
+               goto out;
        }
 
-       return 0;
+ out:
+       acpi_scan_lock_release();
+       return result;
 }
 
 static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
@@ -305,6 +312,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
        struct acpi_device *device;
        struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
+       acpi_status status;
 
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
@@ -327,29 +335,40 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "\nReceived EJECT REQUEST notification for device\n"));
 
+               status = AE_ERROR;
+               acpi_scan_lock_acquire();
+
                if (acpi_bus_get_device(handle, &device)) {
                        acpi_handle_err(handle, "Device doesn't exist\n");
-                       break;
+                       goto unlock;
                }
                mem_device = acpi_driver_data(device);
                if (!mem_device) {
                        acpi_handle_err(handle, "Driver Data is NULL\n");
-                       break;
+                       goto unlock;
                }
 
                ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
                if (!ej_event) {
                        pr_err(PREFIX "No memory, dropping EJECT\n");
-                       break;
+                       goto unlock;
                }
 
+               get_device(&device->dev);
                ej_event->device = device;
                ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
-               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
-                                       (void *)ej_event);
+               /* The eject is carried out asynchronously. */
+               status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                                ej_event);
+               if (ACPI_FAILURE(status)) {
+                       put_device(&device->dev);
+                       kfree(ej_event);
+               }
 
-               /* eject is performed asynchronously */
-               return;
+ unlock:
+               acpi_scan_lock_release();
+               if (ACPI_SUCCESS(status))
+                       return;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
@@ -360,7 +379,6 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 
        /* Inform firmware that the hotplug operation has completed */
        (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
-       return;
 }
 
 static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
@@ -415,7 +433,7 @@ static int acpi_memory_device_add(struct acpi_device *device)
        return result;
 }
 
-static int acpi_memory_device_remove(struct acpi_device *device, int type)
+static int acpi_memory_device_remove(struct acpi_device *device)
 {
        struct acpi_memory_device *mem_device = NULL;
        int result;
index 16fa979f7180b935a52fbfa03c75ca173359031d..31de1043eea051ca34859193b5ae0afd9d70c2d5 100644 (file)
@@ -482,8 +482,7 @@ static int acpi_pad_add(struct acpi_device *device)
        return 0;
 }
 
-static int acpi_pad_remove(struct acpi_device *device,
-       int type)
+static int acpi_pad_remove(struct acpi_device *device)
 {
        mutex_lock(&isolated_cpus_lock);
        acpi_pad_idle_cpus(0);
index 2d1fb4c21605799d608e504962cacbc0df1bc655..26fce4b8a632a3b8537f4baa16ae36f84d6530d1 100644 (file)
 
 ACPI_MODULE_NAME("platform");
 
+/* Flags for acpi_create_platform_device */
+#define ACPI_PLATFORM_CLK      BIT(0)
+
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+       { "PNP0D40" },
+
+       /* Haswell LPSS devices */
+       { "INT33C0", ACPI_PLATFORM_CLK },
+       { "INT33C1", ACPI_PLATFORM_CLK },
+       { "INT33C2", ACPI_PLATFORM_CLK },
+       { "INT33C3", ACPI_PLATFORM_CLK },
+       { "INT33C4", ACPI_PLATFORM_CLK },
+       { "INT33C5", ACPI_PLATFORM_CLK },
+       { "INT33C6", ACPI_PLATFORM_CLK },
+       { "INT33C7", ACPI_PLATFORM_CLK },
+
+       { }
+};
+
 static int acpi_create_platform_clks(struct acpi_device *adev)
 {
        static struct platform_device *pdev;
@@ -39,8 +63,7 @@ static int acpi_create_platform_clks(struct acpi_device *adev)
 /**
  * acpi_create_platform_device - Create platform device for ACPI device node
  * @adev: ACPI device node to create a platform device for.
- * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
- *        devices.
+ * @id: ACPI device ID used to match @adev.
  *
  * Check if the given @adev can be represented as a platform device and, if
  * that's the case, create and register a platform device, populate its common
@@ -48,9 +71,10 @@ static int acpi_create_platform_clks(struct acpi_device *adev)
  *
  * Name of the platform device will be the same as @adev's.
  */
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
-                                                   unsigned long flags)
+static int acpi_create_platform_device(struct acpi_device *adev,
+                                      const struct acpi_device_id *id)
 {
+       unsigned long flags = id->driver_data;
        struct platform_device *pdev = NULL;
        struct acpi_device *acpi_parent;
        struct platform_device_info pdevinfo;
@@ -59,25 +83,28 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
        struct resource *resources;
        int count;
 
-       if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
-               dev_err(&adev->dev, "failed to create clocks\n");
-               return NULL;
+       if (flags & ACPI_PLATFORM_CLK) {
+               int ret = acpi_create_platform_clks(adev);
+               if (ret) {
+                       dev_err(&adev->dev, "failed to create clocks\n");
+                       return ret;
+               }
        }
 
        /* If the ACPI node already has a physical device attached, skip it. */
        if (adev->physical_node_count)
-               return NULL;
+               return 0;
 
        INIT_LIST_HEAD(&resource_list);
        count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
        if (count <= 0)
-               return NULL;
+               return 0;
 
        resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
        if (!resources) {
                dev_err(&adev->dev, "No memory for resources\n");
                acpi_dev_free_resource_list(&resource_list);
-               return NULL;
+               return -ENOMEM;
        }
        count = 0;
        list_for_each_entry(rentry, &resource_list, node)
@@ -123,5 +150,15 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
        }
 
        kfree(resources);
-       return pdev;
+       return 1;
+}
+
+static struct acpi_scan_handler platform_handler = {
+       .ids = acpi_platform_device_ids,
+       .attach = acpi_create_platform_device,
+};
+
+void __init acpi_platform_init(void)
+{
+       acpi_scan_add_handler(&platform_handler);
 }
index 7efaeaa53b88a5c8db7f9b2f624e65a432b3283a..c5cd5b5513e67a144ac3a7d2b5a76dc9f494bc48 100644 (file)
@@ -1111,7 +1111,7 @@ fail:
        return result;
 }
 
-static int acpi_battery_remove(struct acpi_device *device, int type)
+static int acpi_battery_remove(struct acpi_device *device)
 {
        struct acpi_battery *battery = NULL;
 
index f0d936b65e375c40be1898fbf49b4cb40006ecb9..86c7d5445c38c962614b654a4149eef0ab057869 100644 (file)
@@ -75,7 +75,7 @@ static const struct acpi_device_id button_device_ids[] = {
 MODULE_DEVICE_TABLE(acpi, button_device_ids);
 
 static int acpi_button_add(struct acpi_device *device);
-static int acpi_button_remove(struct acpi_device *device, int type);
+static int acpi_button_remove(struct acpi_device *device);
 static void acpi_button_notify(struct acpi_device *device, u32 event);
 
 #ifdef CONFIG_PM_SLEEP
@@ -433,7 +433,7 @@ static int acpi_button_add(struct acpi_device *device)
        return error;
 }
 
-static int acpi_button_remove(struct acpi_device *device, int type)
+static int acpi_button_remove(struct acpi_device *device)
 {
        struct acpi_button *button = acpi_driver_data(device);
 
index cc79d3e53a3919f9cf84df850ae9fc846549fb45..5523ba7d764dff989c108f5262cbc283c95f329f 100644 (file)
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-#include <acpi/container.h>
 
 #define PREFIX "ACPI: "
 
-#define ACPI_CONTAINER_DEVICE_NAME     "ACPI container device"
-#define ACPI_CONTAINER_CLASS           "container"
-
-#define INSTALL_NOTIFY_HANDLER         1
-#define UNINSTALL_NOTIFY_HANDLER       2
-
 #define _COMPONENT                     ACPI_CONTAINER_COMPONENT
 ACPI_MODULE_NAME("container");
 
-MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION("ACPI container driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_container_add(struct acpi_device *device);
-static int acpi_container_remove(struct acpi_device *device, int type);
-
 static const struct acpi_device_id container_device_ids[] = {
        {"ACPI0004", 0},
        {"PNP0A05", 0},
        {"PNP0A06", 0},
        {"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, container_device_ids);
 
-static struct acpi_driver acpi_container_driver = {
-       .name = "container",
-       .class = ACPI_CONTAINER_CLASS,
+static int container_device_attach(struct acpi_device *device,
+                                  const struct acpi_device_id *not_used)
+{
+       /*
+        * FIXME: This is necessary, so that acpi_eject_store() doesn't return
+        * -ENODEV for containers.
+        */
+       return 1;
+}
+
+static struct acpi_scan_handler container_device_handler = {
        .ids = container_device_ids,
-       .ops = {
-               .add = acpi_container_add,
-               .remove = acpi_container_remove,
-               },
+       .attach = container_device_attach,
 };
 
-/*******************************************************************/
-
 static int is_device_present(acpi_handle handle)
 {
        acpi_handle temp;
@@ -92,49 +80,6 @@ static int is_device_present(acpi_handle handle)
        return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
-static bool is_container_device(const char *hid)
-{
-       const struct acpi_device_id *container_id;
-
-       for (container_id = container_device_ids;
-            container_id->id[0]; container_id++) {
-               if (!strcmp((char *)container_id->id, hid))
-                       return true;
-       }
-
-       return false;
-}
-
-/*******************************************************************/
-static int acpi_container_add(struct acpi_device *device)
-{
-       struct acpi_container *container;
-
-       container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
-       if (!container)
-               return -ENOMEM;
-
-       container->handle = device->handle;
-       strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
-       device->driver_data = container;
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
-                         acpi_device_name(device), acpi_device_bid(device)));
-
-       return 0;
-}
-
-static int acpi_container_remove(struct acpi_device *device, int type)
-{
-       acpi_status status = AE_OK;
-       struct acpi_container *pc = NULL;
-
-       pc = acpi_driver_data(device);
-       kfree(pc);
-       return status;
-}
-
 static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 {
        struct acpi_device *device = NULL;
@@ -143,6 +88,8 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
        acpi_status status;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 
+       acpi_scan_lock_acquire();
+
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* Fall through */
@@ -158,7 +105,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
                                /* device exist and this is a remove request */
                                device->flags.eject_pending = 1;
                                kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
-                               return;
+                               goto out;
                        }
                        break;
                }
@@ -185,98 +132,59 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
                if (!acpi_bus_get_device(handle, &device) && device) {
                        device->flags.eject_pending = 1;
                        kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
-                       return;
+                       goto out;
                }
                break;
 
        default:
                /* non-hotplug event; possibly handled by other handler */
-               return;
+               goto out;
        }
 
        /* Inform firmware that the hotplug operation has completed */
        (void) acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL);
-       return;
+
+ out:
+       acpi_scan_lock_release();
 }
 
-static acpi_status
-container_walk_namespace_cb(acpi_handle handle,
-                           u32 lvl, void *context, void **rv)
+static bool is_container(acpi_handle handle)
 {
-       char *hid = NULL;
        struct acpi_device_info *info;
-       acpi_status status;
-       int *action = context;
+       bool ret = false;
 
-       status = acpi_get_object_info(handle, &info);
-       if (ACPI_FAILURE(status)) {
-               return AE_OK;
-       }
-
-       if (info->valid & ACPI_VALID_HID)
-               hid = info->hardware_id.string;
-
-       if (hid == NULL) {
-               goto end;
-       }
+       if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+               return false;
 
-       if (!is_container_device(hid))
-               goto end;
+       if (info->valid & ACPI_VALID_HID) {
+               const struct acpi_device_id *id;
 
-       switch (*action) {
-       case INSTALL_NOTIFY_HANDLER:
-               acpi_install_notify_handler(handle,
-                                           ACPI_SYSTEM_NOTIFY,
-                                           container_notify_cb, NULL);
-               break;
-       case UNINSTALL_NOTIFY_HANDLER:
-               acpi_remove_notify_handler(handle,
-                                          ACPI_SYSTEM_NOTIFY,
-                                          container_notify_cb);
-               break;
-       default:
-               break;
+               for (id = container_device_ids; id->id[0]; id++) {
+                       ret = !strcmp((char *)id->id, info->hardware_id.string);
+                       if (ret)
+                               break;
+               }
        }
-
-      end:
        kfree(info);
-
-       return AE_OK;
+       return ret;
 }
 
-static int __init acpi_container_init(void)
+static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
+                                                         u32 lvl, void *ctxt,
+                                                         void **retv)
 {
-       int result = 0;
-       int action = INSTALL_NOTIFY_HANDLER;
-
-       result = acpi_bus_register_driver(&acpi_container_driver);
-       if (result < 0) {
-               return (result);
-       }
-
-       /* register notify handler to every container device */
-       acpi_walk_namespace(ACPI_TYPE_DEVICE,
-                           ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX,
-                           container_walk_namespace_cb, NULL, &action, NULL);
+       if (is_container(handle))
+               acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                           container_notify_cb, NULL);
 
-       return (0);
+       return AE_OK;
 }
 
-static void __exit acpi_container_exit(void)
+void __init acpi_container_init(void)
 {
-       int action = UNINSTALL_NOTIFY_HANDLER;
-
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+                           acpi_container_register_notify_handler, NULL,
+                           NULL, NULL);
 
-       acpi_walk_namespace(ACPI_TYPE_DEVICE,
-                           ACPI_ROOT_OBJECT,
-                           ACPI_UINT32_MAX,
-                           container_walk_namespace_cb, NULL, &action, NULL);
-
-       acpi_bus_unregister_driver(&acpi_container_driver);
-
-       return;
+       acpi_scan_add_handler(&container_device_handler);
 }
-
-module_init(acpi_container_init);
-module_exit(acpi_container_exit);
index 78648f8110494cf0262a2d17f0bc77d2de258e67..4fdea381ef21e07017a87b94ae16ce0f8860fb75 100644 (file)
@@ -744,7 +744,9 @@ static void acpi_dock_deferred_cb(void *context)
 {
        struct dock_data *data = context;
 
+       acpi_scan_lock_acquire();
        dock_notify(data->handle, data->event, data->ds);
+       acpi_scan_lock_release();
        kfree(data);
 }
 
@@ -757,20 +759,31 @@ static int acpi_dock_notifier_call(struct notifier_block *this,
        if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
           && event != ACPI_NOTIFY_EJECT_REQUEST)
                return 0;
+
+       acpi_scan_lock_acquire();
+
        list_for_each_entry(dock_station, &dock_stations, sibling) {
                if (dock_station->handle == handle) {
                        struct dock_data *dd;
+                       acpi_status status;
 
                        dd = kmalloc(sizeof(*dd), GFP_KERNEL);
                        if (!dd)
-                               return 0;
+                               break;
+
                        dd->handle = handle;
                        dd->event = event;
                        dd->ds = dock_station;
-                       acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
-                       return 0 ;
+                       status = acpi_os_hotplug_execute(acpi_dock_deferred_cb,
+                                                        dd);
+                       if (ACPI_FAILURE(status))
+                               kfree(dd);
+
+                       break;
                }
        }
+
+       acpi_scan_lock_release();
        return 0;
 }
 
@@ -825,7 +838,7 @@ static ssize_t show_docked(struct device *dev,
 
        struct dock_station *dock_station = dev->platform_data;
 
-       if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
+       if (!acpi_bus_get_device(dock_station->handle, &tmp))
                return snprintf(buf, PAGE_SIZE, "1\n");
        return snprintf(buf, PAGE_SIZE, "0\n");
 }
index 354007d490d1268a6e97cee38ba48fd36c1922f7..d45b2871d33b12fa2453f4f91da1a1d55bf19edc 100644 (file)
@@ -852,7 +852,7 @@ static int acpi_ec_add(struct acpi_device *device)
        return ret;
 }
 
-static int acpi_ec_remove(struct acpi_device *device, int type)
+static int acpi_ec_remove(struct acpi_device *device)
 {
        struct acpi_ec *ec;
        struct acpi_ec_query_handler *handler, *tmp;
index 3bd6a54702d683bbca8bcee056293eb938f7d71b..f815da82c765299a42300ae837fd574bedb8e429 100644 (file)
@@ -45,7 +45,7 @@ MODULE_DESCRIPTION("ACPI Fan Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_fan_add(struct acpi_device *device);
-static int acpi_fan_remove(struct acpi_device *device, int type);
+static int acpi_fan_remove(struct acpi_device *device);
 
 static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
@@ -172,7 +172,7 @@ static int acpi_fan_add(struct acpi_device *device)
        return result;
 }
 
-static int acpi_fan_remove(struct acpi_device *device, int type)
+static int acpi_fan_remove(struct acpi_device *device)
 {
        struct thermal_cooling_device *cdev = acpi_driver_data(device);
 
index a0cc796932f7c6d41eb9fbdf8422031d84f2e210..13b1d39d7cdf57c463534c3a29cfd797e22abfe0 100644 (file)
@@ -70,7 +70,7 @@ static int acpi_hed_add(struct acpi_device *device)
        return 0;
 }
 
-static int acpi_hed_remove(struct acpi_device *device, int type)
+static int acpi_hed_remove(struct acpi_device *device)
 {
        hed_handle = NULL;
        return 0;
index da233477d26022157dd25a1ed1f28e99a261ea10..79092328cf064b237c090690c29b64ec1a733063 100644 (file)
 
 int init_acpi_device_notify(void);
 int acpi_scan_init(void);
+void acpi_pci_root_init(void);
+void acpi_pci_link_init(void);
+void acpi_platform_init(void);
 int acpi_sysfs_init(void);
 void acpi_csrt_init(void);
+#ifdef CONFIG_ACPI_CONTAINER
+void acpi_container_init(void);
+#else
+static inline void acpi_container_init(void) {}
+#endif
 
 #ifdef CONFIG_DEBUG_FS
 extern struct dentry *acpi_debugfs_dir;
@@ -86,7 +94,6 @@ struct acpi_ec {
 
 extern struct acpi_ec *first_ec;
 
-int acpi_pci_root_init(void);
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
 int acpi_boot_ec_enable(void);
@@ -118,10 +125,4 @@ static inline void suspend_nvs_restore(void) {}
   -------------------------------------------------------------------------- */
 struct platform_device;
 
-/* Flags for acpi_create_platform_device */
-#define ACPI_PLATFORM_CLK      BIT(0)
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
-                                                   unsigned long flags);
-
 #endif /* _ACPI_INTERNAL_H_ */
index a12808259dfb9fdf7a1908bbb04fe13b21f422f7..ab764ed34a502aea838f4a70b0478ae73543873d 100644 (file)
@@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link");
 #define ACPI_PCI_LINK_FILE_STATUS      "state"
 #define ACPI_PCI_LINK_MAX_POSSIBLE     16
 
-static int acpi_pci_link_add(struct acpi_device *device);
-static int acpi_pci_link_remove(struct acpi_device *device, int type);
+static int acpi_pci_link_add(struct acpi_device *device,
+                            const struct acpi_device_id *not_used);
+static void acpi_pci_link_remove(struct acpi_device *device);
 
 static const struct acpi_device_id link_device_ids[] = {
        {"PNP0C0F", 0},
        {"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, link_device_ids);
 
-static struct acpi_driver acpi_pci_link_driver = {
-       .name = "pci_link",
-       .class = ACPI_PCI_LINK_CLASS,
+static struct acpi_scan_handler pci_link_handler = {
        .ids = link_device_ids,
-       .ops = {
-               .add = acpi_pci_link_add,
-               .remove = acpi_pci_link_remove,
-       },
+       .attach = acpi_pci_link_add,
+       .detach = acpi_pci_link_remove,
 };
 
 /*
@@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle handle)
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static int acpi_pci_link_add(struct acpi_device *device)
+static int acpi_pci_link_add(struct acpi_device *device,
+                            const struct acpi_device_id *not_used)
 {
        int result;
        struct acpi_pci_link *link;
@@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi_device *device)
        if (result)
                kfree(link);
 
-       return result;
+       return result < 0 ? result : 1;
 }
 
 static int acpi_pci_link_resume(struct acpi_pci_link *link)
@@ -766,7 +763,7 @@ static void irqrouter_resume(void)
        }
 }
 
-static int acpi_pci_link_remove(struct acpi_device *device, int type)
+static void acpi_pci_link_remove(struct acpi_device *device)
 {
        struct acpi_pci_link *link;
 
@@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type)
        mutex_unlock(&acpi_link_lock);
 
        kfree(link);
-       return 0;
 }
 
 /*
@@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_syscore_ops = {
        .resume = irqrouter_resume,
 };
 
-static int __init irqrouter_init_ops(void)
-{
-       if (!acpi_disabled && !acpi_noirq)
-               register_syscore_ops(&irqrouter_syscore_ops);
-
-       return 0;
-}
-
-device_initcall(irqrouter_init_ops);
-
-static int __init acpi_pci_link_init(void)
+void __init acpi_pci_link_init(void)
 {
        if (acpi_noirq)
-               return 0;
+               return;
 
        if (acpi_irq_balance == -1) {
                /* no command line switch: enable balancing in IOAPIC mode */
@@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(void)
                else
                        acpi_irq_balance = 0;
        }
-
-       if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
-               return -ENODEV;
-
-       return 0;
+       register_syscore_ops(&irqrouter_syscore_ops);
+       acpi_scan_add_handler(&pci_link_handler);
 }
-
-subsys_initcall(acpi_pci_link_init);
index 22a8458b4ec90d0c4f0793a04e401b97b4061d5e..b3cc69c5caf1e07bd93aa4111bfcbb0a0d4293b5 100644 (file)
@@ -45,8 +45,9 @@
 ACPI_MODULE_NAME("pci_root");
 #define ACPI_PCI_ROOT_CLASS            "pci_bridge"
 #define ACPI_PCI_ROOT_DEVICE_NAME      "PCI Root Bridge"
-static int acpi_pci_root_add(struct acpi_device *device);
-static int acpi_pci_root_remove(struct acpi_device *device, int type);
+static int acpi_pci_root_add(struct acpi_device *device,
+                            const struct acpi_device_id *not_used);
+static void acpi_pci_root_remove(struct acpi_device *device);
 
 #define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
                                | OSC_ACTIVE_STATE_PWR_SUPPORT \
@@ -57,16 +58,11 @@ static const struct acpi_device_id root_device_ids[] = {
        {"PNP0A03", 0},
        {"", 0},
 };
-MODULE_DEVICE_TABLE(acpi, root_device_ids);
 
-static struct acpi_driver acpi_pci_root_driver = {
-       .name = "pci_root",
-       .class = ACPI_PCI_ROOT_CLASS,
+static struct acpi_scan_handler pci_root_handler = {
        .ids = root_device_ids,
-       .ops = {
-               .add = acpi_pci_root_add,
-               .remove = acpi_pci_root_remove,
-               },
+       .attach = acpi_pci_root_add,
+       .detach = acpi_pci_root_remove,
 };
 
 /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
@@ -428,7 +424,8 @@ out:
 }
 EXPORT_SYMBOL(acpi_pci_osc_control_set);
 
-static int acpi_pci_root_add(struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device,
+                            const struct acpi_device_id *not_used)
 {
        unsigned long long segment, bus;
        acpi_status status;
@@ -614,7 +611,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
                pci_enable_bridges(root->bus);
 
        pci_bus_add_devices(root->bus);
-       return 0;
+       return 1;
 
 out_del_root:
        mutex_lock(&acpi_pci_root_lock);
@@ -627,7 +624,7 @@ end:
        return result;
 }
 
-static int acpi_pci_root_remove(struct acpi_device *device, int type)
+static void acpi_pci_root_remove(struct acpi_device *device)
 {
        acpi_status status;
        acpi_handle handle;
@@ -655,19 +652,14 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
        list_del(&root->node);
        mutex_unlock(&acpi_pci_root_lock);
        kfree(root);
-       return 0;
 }
 
-int __init acpi_pci_root_init(void)
+void __init acpi_pci_root_init(void)
 {
        acpi_hest_init();
 
-       if (acpi_pci_disabled)
-               return 0;
-
-       pci_acpi_crs_quirks();
-       if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
-               return -ENODEV;
-
-       return 0;
+       if (!acpi_pci_disabled) {
+               pci_acpi_crs_quirks();
+               acpi_scan_add_handler(&pci_root_handler);
+       }
 }
index d22585f21aebc0f047e4721e268930bb61c970f9..2c630c006c2ff30a9461b6fb2e0ccb6265c5c224 100644 (file)
@@ -50,13 +50,12 @@ module_param(debug, bool, 0644);
 ACPI_MODULE_NAME("pci_slot");
 
 #define MY_NAME "pci_slot"
-#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
-#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define err(format, arg...) pr_err("%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) pr_info("%s: " format , MY_NAME , ## arg)
 #define dbg(format, arg...)                                    \
        do {                                                    \
                if (debug)                                      \
-                       printk(KERN_DEBUG "%s: " format,        \
-                               MY_NAME , ## arg);              \
+                       pr_debug("%s: " format, MY_NAME , ## arg); \
        } while (0)
 
 #define SLOT_NAME_SIZE 21              /* Inspired by #define in acpiphp.h */
index 9c5929a17d3ae2f8704dd3ce9cdd58a6742686fb..cbf1f122666bfa97dd3bc75ca2fe148918659569 100644 (file)
@@ -81,7 +81,7 @@ MODULE_DESCRIPTION("ACPI Processor Driver");
 MODULE_LICENSE("GPL");
 
 static int acpi_processor_add(struct acpi_device *device);
-static int acpi_processor_remove(struct acpi_device *device, int type);
+static int acpi_processor_remove(struct acpi_device *device);
 static void acpi_processor_notify(struct acpi_device *device, u32 event);
 static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr);
 static int acpi_processor_handle_eject(struct acpi_processor *pr);
@@ -610,7 +610,7 @@ err_free_pr:
        return result;
 }
 
-static int acpi_processor_remove(struct acpi_device *device, int type)
+static int acpi_processor_remove(struct acpi_device *device)
 {
        struct acpi_processor *pr = NULL;
 
@@ -623,7 +623,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
        if (pr->id >= nr_cpu_ids)
                goto free;
 
-       if (type == ACPI_BUS_REMOVAL_EJECT) {
+       if (device->removal_type == ACPI_BUS_REMOVAL_EJECT) {
                if (acpi_processor_handle_eject(pr))
                        return -EINVAL;
        }
@@ -683,8 +683,11 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
        struct acpi_device *device = NULL;
        struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
+       acpi_status status;
        int result;
 
+       acpi_scan_lock_acquire();
+
        switch (event) {
        case ACPI_NOTIFY_BUS_CHECK:
        case ACPI_NOTIFY_DEVICE_CHECK:
@@ -733,25 +736,32 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
                        break;
                }
 
+               get_device(&device->dev);
                ej_event->device = device;
                ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
-               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
-                                       (void *)ej_event);
-
-               /* eject is performed asynchronously */
-               return;
+               /* The eject is carried out asynchronously. */
+               status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                                ej_event);
+               if (ACPI_FAILURE(status)) {
+                       put_device(&device->dev);
+                       kfree(ej_event);
+                       break;
+               }
+               goto out;
 
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
 
                /* non-hotplug event; possibly handled by other handler */
-               return;
+               goto out;
        }
 
        /* Inform firmware that the hotplug operation has completed */
        (void) acpi_evaluate_hotplug_ost(handle, event, ost_code, NULL);
-       return;
+
+ out:
+       acpi_scan_lock_release();
 }
 
 static acpi_status is_processor_device(acpi_handle handle)
index ff0740e0a9c248fc932992e56d23540a59489a55..e523245643acc6c65d68339c64fbf7e00ef09f95 100644 (file)
@@ -130,7 +130,7 @@ struct acpi_sbs {
 
 #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
 
-static int acpi_sbs_remove(struct acpi_device *device, int type);
+static int acpi_sbs_remove(struct acpi_device *device);
 static int acpi_battery_get_state(struct acpi_battery *battery);
 
 static inline int battery_scale(int log)
@@ -949,11 +949,11 @@ static int acpi_sbs_add(struct acpi_device *device)
        acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
       end:
        if (result)
-               acpi_sbs_remove(device, 0);
+               acpi_sbs_remove(device);
        return result;
 }
 
-static int acpi_sbs_remove(struct acpi_device *device, int type)
+static int acpi_sbs_remove(struct acpi_device *device)
 {
        struct acpi_sbs *sbs;
        int id;
index cf6129a8af7c97619809b19e6fc46a5be010dd66..b78bc605837e19a8f7461f48a59cdc90d64f5128 100644 (file)
@@ -33,7 +33,7 @@ struct acpi_smb_hc {
 };
 
 static int acpi_smbus_hc_add(struct acpi_device *device);
-static int acpi_smbus_hc_remove(struct acpi_device *device, int type);
+static int acpi_smbus_hc_remove(struct acpi_device *device);
 
 static const struct acpi_device_id sbs_device_ids[] = {
        {"ACPI0001", 0},
@@ -296,7 +296,7 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
 
 extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
 
-static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
+static int acpi_smbus_hc_remove(struct acpi_device *device)
 {
        struct acpi_smb_hc *hc;
 
index c4358716aadcca510a58ccfb5b0d554d159b917c..daee7497efd30137f2dddef2497f9968555d4e26 100644 (file)
@@ -29,30 +29,10 @@ extern struct acpi_device *acpi_root;
 
 static const char *dummy_hid = "device";
 
-/*
- * The following ACPI IDs are known to be suitable for representing as
- * platform devices.
- */
-static const struct acpi_device_id acpi_platform_device_ids[] = {
-
-       { "PNP0D40" },
-
-       /* Haswell LPSS devices */
-       { "INT33C0", ACPI_PLATFORM_CLK },
-       { "INT33C1", ACPI_PLATFORM_CLK },
-       { "INT33C2", ACPI_PLATFORM_CLK },
-       { "INT33C3", ACPI_PLATFORM_CLK },
-       { "INT33C4", ACPI_PLATFORM_CLK },
-       { "INT33C5", ACPI_PLATFORM_CLK },
-       { "INT33C6", ACPI_PLATFORM_CLK },
-       { "INT33C7", ACPI_PLATFORM_CLK },
-
-       { }
-};
-
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 static DEFINE_MUTEX(acpi_scan_lock);
+static LIST_HEAD(acpi_scan_handlers_list);
 DEFINE_MUTEX(acpi_device_lock);
 LIST_HEAD(acpi_wakeup_device_list);
 
@@ -62,6 +42,27 @@ struct acpi_device_bus_id{
        struct list_head node;
 };
 
+void acpi_scan_lock_acquire(void)
+{
+       mutex_lock(&acpi_scan_lock);
+}
+EXPORT_SYMBOL_GPL(acpi_scan_lock_acquire);
+
+void acpi_scan_lock_release(void)
+{
+       mutex_unlock(&acpi_scan_lock);
+}
+EXPORT_SYMBOL_GPL(acpi_scan_lock_release);
+
+int acpi_scan_add_handler(struct acpi_scan_handler *handler)
+{
+       if (!handler || !handler->attach)
+               return -EINVAL;
+
+       list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
+       return 0;
+}
+
 /*
  * Creates hid/cid(s) string needed for modalias and uevent
  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -116,7 +117,7 @@ static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
  */
 void acpi_bus_hot_remove_device(void *context)
 {
-       struct acpi_eject_event *ej_event = (struct acpi_eject_event *) context;
+       struct acpi_eject_event *ej_event = context;
        struct acpi_device *device = ej_event->device;
        acpi_handle handle = device->handle;
        acpi_handle temp;
@@ -125,19 +126,23 @@ void acpi_bus_hot_remove_device(void *context)
        acpi_status status = AE_OK;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 
+       mutex_lock(&acpi_scan_lock);
+
+       /* If there is no handle, the device node has been unregistered. */
+       if (!device->handle) {
+               dev_dbg(&device->dev, "ACPI handle missing\n");
+               put_device(&device->dev);
+               goto out;
+       }
+
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                "Hot-removing device %s...\n", dev_name(&device->dev)));
 
        acpi_bus_trim(device);
-       /* Device node has been released. */
+       /* Device node has been unregistered. */
+       put_device(&device->dev);
        device = NULL;
 
-       /* power off device */
-       status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
-       if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
-               printk(KERN_WARNING PREFIX
-                               "Power-off device failed\n");
-
        if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
                arg_list.count = 1;
                arg_list.pointer = &arg;
@@ -157,18 +162,15 @@ void acpi_bus_hot_remove_device(void *context)
        status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
        if (ACPI_FAILURE(status)) {
                if (status != AE_NOT_FOUND)
-                       printk(KERN_WARNING PREFIX
-                                       "Eject device failed\n");
-               goto err_out;
-       }
+                       acpi_handle_warn(handle, "Eject failed\n");
 
-       kfree(context);
-       return;
+               /* Tell the firmware the hot-remove operation has failed. */
+               acpi_evaluate_hotplug_ost(handle, ej_event->event,
+                                         ost_code, NULL);
+       }
 
-err_out:
-       /* Inform firmware the hot-remove operation has completed w/ error */
-       (void) acpi_evaluate_hotplug_ost(handle,
-                               ej_event->event, ost_code, NULL);
+ out:
+       mutex_unlock(&acpi_scan_lock);
        kfree(context);
        return;
 }
@@ -213,12 +215,10 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
        if ((!count) || (buf[0] != '1')) {
                return -EINVAL;
        }
-#ifndef FORCE_EJECT
-       if (acpi_device->driver == NULL) {
+       if (!acpi_device->driver && !acpi_device->handler) {
                ret = -ENODEV;
                goto err;
        }
-#endif
        status = acpi_get_type(acpi_device->handle, &type);
        if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
                ret = -ENODEV;
@@ -231,6 +231,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
                goto err;
        }
 
+       get_device(&acpi_device->dev);
        ej_event->device = acpi_device;
        if (acpi_device->flags.eject_pending) {
                /* event originated from ACPI eject notification */
@@ -243,7 +244,11 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
                        ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
        }
 
-       acpi_os_hotplug_execute(acpi_bus_hot_remove_device, (void *)ej_event);
+       status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
+       if (ACPI_FAILURE(status)) {
+               put_device(&acpi_device->dev);
+               kfree(ej_event);
+       }
 err:
        return ret;
 }
@@ -637,8 +642,9 @@ static int acpi_device_probe(struct device * dev)
                        ret = acpi_device_install_notify_handler(acpi_dev);
                        if (ret) {
                                if (acpi_drv->ops.remove)
-                                       acpi_drv->ops.remove(acpi_dev,
-                                                    acpi_dev->removal_type);
+                                       acpi_drv->ops.remove(acpi_dev);
+                               acpi_dev->driver = NULL;
+                               acpi_dev->driver_data = NULL;
                                return ret;
                        }
                }
@@ -660,7 +666,7 @@ static int acpi_device_remove(struct device * dev)
                if (acpi_drv->ops.notify)
                        acpi_device_remove_notify_handler(acpi_dev);
                if (acpi_drv->ops.remove)
-                       acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type);
+                       acpi_drv->ops.remove(acpi_dev);
        }
        acpi_dev->driver = NULL;
        acpi_dev->driver_data = NULL;
@@ -792,10 +798,12 @@ static void acpi_device_unregister(struct acpi_device *device)
 
        device_del(&device->dev);
        /*
-        * Drop the reference counts of all power resources the device depends
-        * on and turn off the ones that have no more references.
+        * Transition the device to D3cold to drop the reference counts of all
+        * power resources the device depends on and turn off the ones that have
+        * no more references.
         */
-       acpi_power_transition(device, ACPI_STATE_D3_COLD);
+       acpi_device_set_power(device, ACPI_STATE_D3_COLD);
+       device->handle = NULL;
        put_device(&device->dev);
 }
 
@@ -883,29 +891,23 @@ EXPORT_SYMBOL(acpi_bus_unregister_driver);
    -------------------------------------------------------------------------- */
 static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
 {
+       struct acpi_device *device = NULL;
        acpi_status status;
-       int ret;
-       struct acpi_device *device;
 
        /*
         * Fixed hardware devices do not appear in the namespace and do not
         * have handles, but we fabricate acpi_devices for them, so we have
         * to deal with them specially.
         */
-       if (handle == NULL)
+       if (!handle)
                return acpi_root;
 
        do {
                status = acpi_get_parent(handle, &handle);
-               if (status == AE_NULL_ENTRY)
-                       return NULL;
                if (ACPI_FAILURE(status))
-                       return acpi_root;
-
-               ret = acpi_bus_get_device(handle, &device);
-               if (ret == 0)
-                       return device;
-       } while (1);
+                       return status == AE_NULL_ENTRY ? NULL : acpi_root;
+       } while (acpi_bus_get_device(handle, &device));
+       return device;
 }
 
 acpi_status
@@ -1441,19 +1443,21 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
        acpi_device_get_busid(device);
        acpi_device_set_id(device);
        acpi_bus_get_flags(device);
+       device->flags.match_driver = false;
        device_initialize(&device->dev);
        dev_set_uevent_suppress(&device->dev, true);
 }
 
 void acpi_device_add_finalize(struct acpi_device *device)
 {
+       device->flags.match_driver = true;
        dev_set_uevent_suppress(&device->dev, false);
        kobject_uevent(&device->dev.kobj, KOBJ_ADD);
 }
 
 static int acpi_add_single_object(struct acpi_device **child,
                                  acpi_handle handle, int type,
-                                 unsigned long long sta, bool match_driver)
+                                 unsigned long long sta)
 {
        int result;
        struct acpi_device *device;
@@ -1469,7 +1473,6 @@ static int acpi_add_single_object(struct acpi_device **child,
        acpi_bus_get_power_flags(device);
        acpi_bus_get_wakeup_device_flags(device);
 
-       device->flags.match_driver = match_driver;
        result = acpi_device_add(device, acpi_device_release);
        if (result) {
                acpi_device_release(&device->dev);
@@ -1562,12 +1565,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
                return AE_CTRL_DEPTH;
        }
 
-       acpi_add_single_object(&device, handle, type, sta, false);
+       acpi_add_single_object(&device, handle, type, sta);
        if (!device)
                return AE_CTRL_DEPTH;
 
-       device->flags.match_driver = true;
-
  out:
        if (!*return_value)
                *return_value = device;
@@ -1575,33 +1576,68 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
        return AE_OK;
 }
 
+static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
+{
+       struct acpi_scan_handler *handler;
+
+       list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
+               const struct acpi_device_id *devid;
+
+               for (devid = handler->ids; devid->id[0]; devid++) {
+                       int ret;
+
+                       if (strcmp((char *)devid->id, id))
+                               continue;
+
+                       ret = handler->attach(device, devid);
+                       if (ret > 0) {
+                               device->handler = handler;
+                               return ret;
+                       } else if (ret < 0) {
+                               return ret;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int acpi_scan_attach_handler(struct acpi_device *device)
+{
+       struct acpi_hardware_id *hwid;
+       int ret = 0;
+
+       list_for_each_entry(hwid, &device->pnp.ids, list) {
+               ret = acpi_scan_do_attach_handler(device, hwid->id);
+               if (ret)
+                       break;
+
+       }
+       return ret;
+}
+
 static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
                                          void *not_used, void **ret_not_used)
 {
-       const struct acpi_device_id *id;
-       acpi_status status = AE_OK;
        struct acpi_device *device;
        unsigned long long sta_not_used;
-       int type_not_used;
+       int ret;
 
        /*
         * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
         * namespace walks prematurely.
         */
-       if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+       if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
                return AE_OK;
 
        if (acpi_bus_get_device(handle, &device))
                return AE_CTRL_DEPTH;
 
-       id = __acpi_match_device(device, acpi_platform_device_ids);
-       if (id) {
-               /* This is a known good platform device. */
-               acpi_create_platform_device(device, id->driver_data);
-       } else if (device_attach(&device->dev) < 0) {
-               status = AE_CTRL_DEPTH;
-       }
-       return status;
+       ret = acpi_scan_attach_handler(device);
+       if (ret)
+               return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
+
+       ret = device_attach(&device->dev);
+       return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
 }
 
 /**
@@ -1615,14 +1651,14 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
  * there has been a real error.  There just have been no suitable ACPI objects
  * in the table trunk from which the kernel could create a device and add an
  * appropriate driver.
+ *
+ * Must be called under acpi_scan_lock.
  */
 int acpi_bus_scan(acpi_handle handle)
 {
        void *device = NULL;
        int error = 0;
 
-       mutex_lock(&acpi_scan_lock);
-
        if (ACPI_SUCCESS(acpi_bus_check_add(handle, 0, NULL, &device)))
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
                                    acpi_bus_check_add, NULL, NULL, &device);
@@ -1633,7 +1669,6 @@ int acpi_bus_scan(acpi_handle handle)
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
                                    acpi_bus_device_attach, NULL, NULL, NULL);
 
-       mutex_unlock(&acpi_scan_lock);
        return error;
 }
 EXPORT_SYMBOL(acpi_bus_scan);
@@ -1644,8 +1679,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
        struct acpi_device *device = NULL;
 
        if (!acpi_bus_get_device(handle, &device)) {
+               struct acpi_scan_handler *dev_handler = device->handler;
+
                device->removal_type = ACPI_BUS_REMOVAL_EJECT;
-               device_release_driver(&device->dev);
+               if (dev_handler) {
+                       if (dev_handler->detach)
+                               dev_handler->detach(device);
+
+                       device->handler = NULL;
+               } else {
+                       device_release_driver(&device->dev);
+               }
        }
        return AE_OK;
 }
@@ -1661,10 +1705,14 @@ static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
        return AE_OK;
 }
 
+/**
+ * acpi_bus_trim - Remove ACPI device node and all of its descendants
+ * @start: Root of the ACPI device nodes subtree to remove.
+ *
+ * Must be called under acpi_scan_lock.
+ */
 void acpi_bus_trim(struct acpi_device *start)
 {
-       mutex_lock(&acpi_scan_lock);
-
        /*
         * Execute acpi_bus_device_detach() as a post-order callback to detach
         * all ACPI drivers from the device nodes being removed.
@@ -1679,33 +1727,45 @@ void acpi_bus_trim(struct acpi_device *start)
        acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
                            acpi_bus_remove, NULL, NULL);
        acpi_bus_remove(start->handle, 0, NULL, NULL);
-
-       mutex_unlock(&acpi_scan_lock);
 }
 EXPORT_SYMBOL_GPL(acpi_bus_trim);
 
 static int acpi_bus_scan_fixed(void)
 {
        int result = 0;
-       struct acpi_device *device = NULL;
 
        /*
         * Enumerate all fixed-feature devices.
         */
-       if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
+       if (!(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) {
+               struct acpi_device *device = NULL;
+
                result = acpi_add_single_object(&device, NULL,
                                                ACPI_BUS_TYPE_POWER_BUTTON,
-                                               ACPI_STA_DEFAULT, true);
+                                               ACPI_STA_DEFAULT);
+               if (result)
+                       return result;
+
+               result = device_attach(&device->dev);
+               if (result < 0)
+                       return result;
+
                device_init_wakeup(&device->dev, true);
        }
 
-       if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
+       if (!(acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON)) {
+               struct acpi_device *device = NULL;
+
                result = acpi_add_single_object(&device, NULL,
                                                ACPI_BUS_TYPE_SLEEP_BUTTON,
-                                               ACPI_STA_DEFAULT, true);
+                                               ACPI_STA_DEFAULT);
+               if (result)
+                       return result;
+
+               result = device_attach(&device->dev);
        }
 
-       return result;
+       return result < 0 ? result : 0;
 }
 
 int __init acpi_scan_init(void)
@@ -1719,25 +1779,32 @@ int __init acpi_scan_init(void)
        }
 
        acpi_pci_root_init();
+       acpi_pci_link_init();
+       acpi_platform_init();
        acpi_csrt_init();
+       acpi_container_init();
 
+       mutex_lock(&acpi_scan_lock);
        /*
         * Enumerate devices in the ACPI namespace.
         */
        result = acpi_bus_scan(ACPI_ROOT_OBJECT);
        if (result)
-               return result;
+               goto out;
 
        result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
        if (result)
-               return result;
+               goto out;
 
        result = acpi_bus_scan_fixed();
        if (result) {
                acpi_device_unregister(acpi_root);
-               return result;
+               goto out;
        }
 
        acpi_update_all_gpes();
-       return 0;
+
+ out:
+       mutex_unlock(&acpi_scan_lock);
+       return result;
 }
index 506fbd4b5733b5f1751d8c23521aaa398447e33d..da079d4e0baa12d7e4bfe05410ccfd4f28b383d0 100644 (file)
@@ -97,7 +97,7 @@ module_param(psv, int, 0644);
 MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 
 static int acpi_thermal_add(struct acpi_device *device);
-static int acpi_thermal_remove(struct acpi_device *device, int type);
+static int acpi_thermal_remove(struct acpi_device *device);
 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id  thermal_device_ids[] = {
@@ -1111,7 +1111,7 @@ end:
        return result;
 }
 
-static int acpi_thermal_remove(struct acpi_device *device, int type)
+static int acpi_thermal_remove(struct acpi_device *device)
 {
        struct acpi_thermal *tz = NULL;
 
index ac9a69cd45f5a4082a05c743de6dd58aad369c60..5be60ad8381f26694ac29cbfe069e47b6b435299 100644 (file)
@@ -88,7 +88,7 @@ module_param(use_bios_initial_backlight, bool, 0644);
 
 static int register_count = 0;
 static int acpi_video_bus_add(struct acpi_device *device);
-static int acpi_video_bus_remove(struct acpi_device *device, int type);
+static int acpi_video_bus_remove(struct acpi_device *device);
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id video_device_ids[] = {
@@ -1740,7 +1740,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
        return error;
 }
 
-static int acpi_video_bus_remove(struct acpi_device *device, int type)
+static int acpi_video_bus_remove(struct acpi_device *device)
 {
        struct acpi_video_bus *video = NULL;
 
index fe6d4be4829600d9c6e44078f95ddb65b84ba957..e3f9a99b8522e41dd2a4005142ea396838f26bbf 100644 (file)
@@ -1041,7 +1041,7 @@ static int hpet_acpi_add(struct acpi_device *device)
        return hpet_alloc(&data);
 }
 
-static int hpet_acpi_remove(struct acpi_device *device, int type)
+static int hpet_acpi_remove(struct acpi_device *device)
 {
        /* XXX need to unregister clocksource, dealloc mem, etc */
        return -EINVAL;
index d780295a147371533e5ad936d8c10e86a85fac57..6386a98e43c1b153242254a8c1f4a125daf7a2ad 100644 (file)
@@ -1142,7 +1142,7 @@ static int sonypi_acpi_add(struct acpi_device *device)
        return 0;
 }
 
-static int sonypi_acpi_remove(struct acpi_device *device, int type)
+static int sonypi_acpi_remove(struct acpi_device *device)
 {
        sonypi_acpi_device = NULL;
        return 0;
index 1672e2a5db46865cd2849927517c528f287c3314..6351aba8819ceec4ff33a2d9c9a8a43ce8114713 100644 (file)
@@ -911,7 +911,7 @@ exit:
        return res;
 }
 
-static int acpi_power_meter_remove(struct acpi_device *device, int type)
+static int acpi_power_meter_remove(struct acpi_device *device)
 {
        struct acpi_power_meter_resource *resource;
 
index 56dbcfb3e30170346f16826a37cff51b641e8ef2..b25c64302cbc1911f5d272e50dc05f8477b326c9 100644 (file)
@@ -190,7 +190,7 @@ struct atk_acpi_input_buf {
 };
 
 static int atk_add(struct acpi_device *device);
-static int atk_remove(struct acpi_device *device, int type);
+static int atk_remove(struct acpi_device *device);
 static void atk_print_sensor(struct atk_data *data, union acpi_object *obj);
 static int atk_read_value(struct atk_sensor_data *sensor, u64 *value);
 static void atk_free_sensors(struct atk_data *data);
@@ -1416,7 +1416,7 @@ out:
        return err;
 }
 
-static int atk_remove(struct acpi_device *device, int type)
+static int atk_remove(struct acpi_device *device)
 {
        struct atk_data *data = device->driver_data;
        dev_dbg(&device->dev, "removing...\n");
index 6aafa3d88ff0438f6585d0a315998bd8bfba5f9f..c447e8d40b78fb5cc3d58b0fb7b48ffff066c28a 100644 (file)
@@ -406,7 +406,7 @@ err:
        return -EIO;
 }
 
-static int acpi_smbus_cmi_remove(struct acpi_device *device, int type)
+static int acpi_smbus_cmi_remove(struct acpi_device *device)
 {
        struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device);
 
index 26f13131639aa8e5432f499efa155403a972607a..5d4402365a5207258dbd9b4b7d68f18489fa1598 100644 (file)
@@ -121,7 +121,7 @@ static int atlas_acpi_button_add(struct acpi_device *device)
        return err;
 }
 
-static int atlas_acpi_button_remove(struct acpi_device *device, int type)
+static int atlas_acpi_button_remove(struct acpi_device *device)
 {
        acpi_status status;
 
index d1a6f4a25da8bb0bb4ab0482b5e165ba527c6e97..a951c22921d165bb1553de35cb68ffc95ddc3abf 100644 (file)
@@ -1218,6 +1218,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
        handle = hp_work->handle;
        type = hp_work->type;
 
+       acpi_scan_lock_acquire();
+
        if (acpi_bus_get_device(handle, &device)) {
                /* This bridge must have just been physically inserted */
                handle_bridge_insertion(handle, type);
@@ -1295,6 +1297,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
        }
 
 out:
+       acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
 }
 
@@ -1341,6 +1344,8 @@ static void _handle_hotplug_event_func(struct work_struct *work)
 
        func = (struct acpiphp_func *)context;
 
+       acpi_scan_lock_acquire();
+
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
                /* bus re-enumerate */
@@ -1371,6 +1376,7 @@ static void _handle_hotplug_event_func(struct work_struct *work)
                break;
        }
 
+       acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_func */
 }
 
index ae606b3e991e90694728ae3d1f8c380c5762774d..574421bc2fa63bd4e407cafbe2ecd8ca1d22d780 100644 (file)
@@ -425,6 +425,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
                        pdevice = NULL;
                }
 
+               acpi_scan_lock_acquire();
                /*
                 * Walk the rootbus node's immediate children looking for
                 * the slot's device node(s). There can be more than
@@ -458,6 +459,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
                                }
                        }
                }
+               acpi_scan_lock_release();
        }
 
        /* Call the driver for the new device */
@@ -508,6 +510,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
                /* Get the rootbus node pointer */
                phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
 
+               acpi_scan_lock_acquire();
                /*
                 * Walk the rootbus node's immediate children looking for
                 * the slot's device node(s). There can be more than
@@ -538,7 +541,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
                                        acpi_bus_trim(device);
                        }
                }
-
+               acpi_scan_lock_release();
        }
 
        /* Free the SN resources assigned to the Linux device.*/
index fcde4e528819c04daf4b919ba00d70a20f7456c3..d9f9a0dbc6f3502333ea4441777afbd3227805ad 100644 (file)
@@ -1910,7 +1910,7 @@ fail_platform:
        return result;
 }
 
-static int asus_acpi_remove(struct acpi_device *device, int type)
+static int asus_acpi_remove(struct acpi_device *device)
 {
        struct asus_laptop *asus = acpi_driver_data(device);
 
index c87ff16873f9753ef589111763d743bc09ed1409..36e5e6c13db4edbdd0aaae00e405eff248619290 100644 (file)
@@ -432,7 +432,7 @@ failed_sensitivity:
        return error;
 }
 
-static int cmpc_accel_remove_v4(struct acpi_device *acpi, int type)
+static int cmpc_accel_remove_v4(struct acpi_device *acpi)
 {
        struct input_dev *inputdev;
        struct cmpc_accel *accel;
@@ -668,7 +668,7 @@ failed_file:
        return error;
 }
 
-static int cmpc_accel_remove(struct acpi_device *acpi, int type)
+static int cmpc_accel_remove(struct acpi_device *acpi)
 {
        struct input_dev *inputdev;
        struct cmpc_accel *accel;
@@ -753,7 +753,7 @@ static int cmpc_tablet_add(struct acpi_device *acpi)
                                           cmpc_tablet_idev_init);
 }
 
-static int cmpc_tablet_remove(struct acpi_device *acpi, int type)
+static int cmpc_tablet_remove(struct acpi_device *acpi)
 {
        return cmpc_remove_acpi_notify_device(acpi);
 }
@@ -1000,7 +1000,7 @@ out_bd:
        return retval;
 }
 
-static int cmpc_ipml_remove(struct acpi_device *acpi, int type)
+static int cmpc_ipml_remove(struct acpi_device *acpi)
 {
        struct ipml200_dev *ipml;
 
@@ -1079,7 +1079,7 @@ static int cmpc_keys_add(struct acpi_device *acpi)
                                           cmpc_keys_idev_init);
 }
 
-static int cmpc_keys_remove(struct acpi_device *acpi, int type)
+static int cmpc_keys_remove(struct acpi_device *acpi)
 {
        return cmpc_remove_acpi_notify_device(acpi);
 }
index 528e9495458d35f3396efeb6a3ce6e78e201bcd9..98935f945f53fad536be68bee242ef5c88029357 100644 (file)
@@ -1501,7 +1501,7 @@ fail_platform:
        return result;
 }
 
-static int eeepc_acpi_remove(struct acpi_device *device, int type)
+static int eeepc_acpi_remove(struct acpi_device *device)
 {
        struct eeepc_laptop *eeepc = acpi_driver_data(device);
 
index c4c1a5444b38e3486d0617f0a843e3cc8f9cfd9c..1c9386e7c58ce723ca583714b862604cbcfd25e5 100644 (file)
@@ -733,7 +733,7 @@ err_stop:
        return result;
 }
 
-static int acpi_fujitsu_remove(struct acpi_device *device, int type)
+static int acpi_fujitsu_remove(struct acpi_device *device)
 {
        struct fujitsu_t *fujitsu = acpi_driver_data(device);
        struct input_dev *input = fujitsu->input;
@@ -938,7 +938,7 @@ err_stop:
        return result;
 }
 
-static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type)
+static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)
 {
        struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device);
        struct input_dev *input = fujitsu_hotkey->input;
index 174ca01c4aa71fda16dac075bc3171860c70c06e..570926c10014d53ef3c1a2afc4de6aa87eb71a96 100644 (file)
@@ -431,7 +431,7 @@ static int acpi_fujitsu_add(struct acpi_device *adev)
        return 0;
 }
 
-static int acpi_fujitsu_remove(struct acpi_device *adev, int type)
+static int acpi_fujitsu_remove(struct acpi_device *adev)
 {
        free_irq(fujitsu.irq, fujitsu_interrupt);
        release_region(fujitsu.io_base, fujitsu.io_length);
index 18d74f29dcb21784c6f83814f46e58d67366ae3c..e64a7a870d42146c910ffb39b955c29a11a88080 100644 (file)
@@ -337,7 +337,7 @@ static int lis3lv02d_add(struct acpi_device *device)
        return ret;
 }
 
-static int lis3lv02d_remove(struct acpi_device *device, int type)
+static int lis3lv02d_remove(struct acpi_device *device)
 {
        if (!device)
                return -EINVAL;
index 64bfb30a52e9a022c3a1c08be8f4f59c0a8a5ee6..17f00b8dc5cbcb841540f07c7330775bcb5393df 100644 (file)
@@ -834,7 +834,7 @@ platform_failed:
        return ret;
 }
 
-static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
+static int ideapad_acpi_remove(struct acpi_device *adevice)
 {
        struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int i;
index 3271ac85115e4914237c902575e0f694ea0dd6f9..d6cfc1558c2f1e067d8fd72edb1dc7ce3ecd00e3 100644 (file)
@@ -200,7 +200,7 @@ static int intel_menlow_memory_add(struct acpi_device *device)
 
 }
 
-static int intel_menlow_memory_remove(struct acpi_device *device, int type)
+static int intel_menlow_memory_remove(struct acpi_device *device)
 {
        struct thermal_cooling_device *cdev = acpi_driver_data(device);
 
index 8e8caa767d6aec521e65cd42475e3b2950c32907..4add9a31bf601cf151c5f0b6ce938de73ba0aa96 100644 (file)
@@ -176,7 +176,7 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
 /* R1 handles SINF_AC_CUR_BRIGHT as SINF_CUR_BRIGHT, doesn't know AC state */
 
 static int acpi_pcc_hotkey_add(struct acpi_device *device);
-static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
+static int acpi_pcc_hotkey_remove(struct acpi_device *device);
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id pcc_device_ids[] = {
@@ -663,7 +663,7 @@ static int __init acpi_pcc_init(void)
        return 0;
 }
 
-static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
+static int acpi_pcc_hotkey_remove(struct acpi_device *device)
 {
        struct pcc_acpi *pcc = acpi_driver_data(device);
 
index b8ad71f7863fa2b0fa9c741e9605ffdfe5a92fcf..ceb41eff4230ecc0f21d765b376a42b6fbbe2eac 100644 (file)
@@ -2740,7 +2740,7 @@ outwalk:
        return result;
 }
 
-static int sony_nc_remove(struct acpi_device *device, int type)
+static int sony_nc_remove(struct acpi_device *device)
 {
        struct sony_nc_value *item;
 
@@ -4111,7 +4111,7 @@ found:
  *  ACPI driver
  *
  *****************/
-static int sony_pic_remove(struct acpi_device *device, int type)
+static int sony_pic_remove(struct acpi_device *device)
 {
        struct sony_pic_ioport *io, *tmp_io;
        struct sony_pic_irq *irq, *tmp_irq;
index d727bfee89a6eef656aef88df13b78e4d082ad49..4ab618c63b457e0bbf5a613274ab10a3e76f26cc 100644 (file)
@@ -157,7 +157,7 @@ add_err:
        return -ENODEV;
 }
 
-static int acpi_topstar_remove(struct acpi_device *device, int type)
+static int acpi_topstar_remove(struct acpi_device *device)
 {
        struct topstar_hkey *tps_hkey = acpi_driver_data(device);
 
index c2727895794ca51d7623bc820c6aeadd422fa4c5..904476b2fa8f3e1de0bcc003f440a35c058befd9 100644 (file)
@@ -1118,7 +1118,7 @@ static int toshiba_acpi_setup_backlight(struct toshiba_acpi_dev *dev)
        return 0;
 }
 
-static int toshiba_acpi_remove(struct acpi_device *acpi_dev, int type)
+static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
 {
        struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
 
@@ -1250,7 +1250,7 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
        return 0;
 
 error:
-       toshiba_acpi_remove(acpi_dev, 0);
+       toshiba_acpi_remove(acpi_dev);
        return ret;
 }
 
index e95be0b74859b286c92979a1de1e766abaf4e65e..74dd01ae343b01f5f5a9827c5ec02f11ceee61b5 100644 (file)
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
 
 
 static int toshiba_bt_rfkill_add(struct acpi_device *device);
-static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
+static int toshiba_bt_rfkill_remove(struct acpi_device *device);
 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id bt_device_ids[] = {
@@ -122,7 +122,7 @@ static int toshiba_bt_rfkill_add(struct acpi_device *device)
        return result;
 }
 
-static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type)
+static int toshiba_bt_rfkill_remove(struct acpi_device *device)
 {
        /* clean up */
        return 0;
index 42a4dcc25f92ae0cfacc127b6310594bda477e25..e4ac38aca5802ef995ad84fc9d191749075771ff 100644 (file)
@@ -92,7 +92,7 @@ module_param(debug_dump_wdg, bool, 0444);
 MODULE_PARM_DESC(debug_dump_wdg,
                 "Dump available WMI interfaces [0/1]");
 
-static int acpi_wmi_remove(struct acpi_device *device, int type);
+static int acpi_wmi_remove(struct acpi_device *device);
 static int acpi_wmi_add(struct acpi_device *device);
 static void acpi_wmi_notify(struct acpi_device *device, u32 event);
 
@@ -917,7 +917,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
        }
 }
 
-static int acpi_wmi_remove(struct acpi_device *device, int type)
+static int acpi_wmi_remove(struct acpi_device *device)
 {
        acpi_remove_address_space_handler(device->handle,
                                ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
index 16d340c3b85256fad50fe57c4ca620d49f8fdcc1..4b1377bd59446a50405e00414418adf9ac8f8381 100644 (file)
@@ -150,7 +150,7 @@ static int ebook_switch_add(struct acpi_device *device)
        return error;
 }
 
-static int ebook_switch_remove(struct acpi_device *device, int type)
+static int ebook_switch_remove(struct acpi_device *device)
 {
        struct ebook_switch *button = acpi_driver_data(device);
 
index cac320738142f1caeb0479705f920f8d47180e08..adb8da564cf6356a8fcdabe35a17256f8e766f4d 100644 (file)
@@ -296,7 +296,7 @@ fail_config:
        return ret;
 }
 
-static int quickstart_acpi_remove(struct acpi_device *device, int type)
+static int quickstart_acpi_remove(struct acpi_device *device)
 {
        acpi_status status;
        struct quickstart_acpi *quickstart;
index f088d4c07381cec00155a4818a14cb8bc1f96357..d843296766896d3abe8e2e2b10c34cbd23aed40a 100644 (file)
@@ -196,7 +196,7 @@ static int apple_bl_add(struct acpi_device *dev)
        return 0;
 }
 
-static int apple_bl_remove(struct acpi_device *dev, int type)
+static int apple_bl_remove(struct acpi_device *dev)
 {
        backlight_device_unregister(apple_backlight_device);
 
index da39191e7278aa0aa26a242ca5c4542551e200c2..c763479ed85ebcfc47eaa76014d3bcc765a2f68e 100644 (file)
@@ -140,8 +140,7 @@ static int acpi_pad_add(struct acpi_device *device)
        return 0;
 }
 
-static int acpi_pad_remove(struct acpi_device *device,
-       int type)
+static int acpi_pad_remove(struct acpi_device *device)
 {
        mutex_lock(&xen_cpu_lock);
        xen_acpi_pad_idle_cpus(0);
index 36ed7e025bfccf2052657013a7996e2e7b229507..227ba7dc293d0f334e4d56de92189022200badd2 100644 (file)
@@ -83,20 +83,30 @@ enum acpi_bus_device_type {
 struct acpi_driver;
 struct acpi_device;
 
+/*
+ * ACPI Scan Handler
+ * -----------------
+ */
+
+struct acpi_scan_handler {
+       const struct acpi_device_id *ids;
+       struct list_head list_node;
+       int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
+       void (*detach)(struct acpi_device *dev);
+};
+
 /*
  * ACPI Driver
  * -----------
  */
 
 typedef int (*acpi_op_add) (struct acpi_device * device);
-typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
-typedef int (*acpi_op_start) (struct acpi_device * device);
+typedef int (*acpi_op_remove) (struct acpi_device * device);
 typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
 
 struct acpi_device_ops {
        acpi_op_add add;
        acpi_op_remove remove;
-       acpi_op_start start;
        acpi_op_notify notify;
 };
 
@@ -271,6 +281,7 @@ struct acpi_device {
        struct acpi_device_wakeup wakeup;
        struct acpi_device_perf performance;
        struct acpi_device_dir dir;
+       struct acpi_scan_handler *handler;
        struct acpi_driver *driver;
        void *driver_data;
        struct device dev;
@@ -384,6 +395,10 @@ int acpi_bus_receive_event(struct acpi_bus_event *event);
 static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
        { return 0; }
 #endif
+
+void acpi_scan_lock_acquire(void);
+void acpi_scan_lock_release(void);
+int acpi_scan_add_handler(struct acpi_scan_handler *handler);
 int acpi_bus_register_driver(struct acpi_driver *driver);
 void acpi_bus_unregister_driver(struct acpi_driver *driver);
 int acpi_bus_scan(acpi_handle handle);
diff --git a/include/acpi/container.h b/include/acpi/container.h
deleted file mode 100644 (file)
index a703f14..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __ACPI_CONTAINER_H
-#define __ACPI_CONTAINER_H
-
-#include <linux/kernel.h>
-
-struct acpi_container {
-       acpi_handle handle;
-       unsigned long sun;
-       int state;
-};
-
-#endif                         /* __ACPI_CONTAINER_H */
index c6ccd9fa8f086d6279ba7ad57a8d9b7b4de437bd..bcbdd7484e581404d54be807c034fced32ba45c2 100644 (file)
@@ -363,8 +363,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
 #if defined(CONFIG_ACPI_HOTPLUG_CPU) &&                        \
        (defined(CONFIG_ACPI_HOTPLUG_MEMORY) ||         \
         defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) && \
-       (defined(CONFIG_ACPI_CONTAINER) ||              \
-        defined(CONFIG_ACPI_CONTAINER_MODULE))
+       defined(CONFIG_ACPI_CONTAINER)
 #define ACPI_HOTPLUG_OST
 #endif