summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-02-11 16:20:02 +0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-02-11 16:20:02 +0400
commit59893298947e0ca28cbaba6d02b9973181f14eea (patch)
tree98d4a2461381458662e5fed813c1d6bc1bfb9f26 /drivers/acpi
parent836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 (diff)
parent0613e1f7fd98a0cef2a7add1368a87cdd86a1106 (diff)
downloadlinux-59893298947e0ca28cbaba6d02b9973181f14eea.tar.xz
Merge branch 'acpi-scan'
* acpi-scan: (30 commits) ACPI / scan: Fix acpi_bus_get_device() check in acpi_match_device() ACPI / scan: Make namespace scanning and trimming mutually exclusive ACPI / scan: Make it clear that acpi_bus_trim() cannot fail ACPI / scan: Drop acpi_bus_add() and use acpi_bus_scan() instead ACPI: update ej_event interface to take acpi_device ACPI / scan: Add second pass to acpi_bus_trim() ACPI / scan: Change the implementation of acpi_bus_trim() ACPI / scan: Drop the second argument of acpi_bus_trim() ACPI / scan: Drop the second argument of acpi_device_unregister() ACPI: Remove the ops field from struct acpi_device ACPI: remove unused acpi_op_bind and acpi_op_unbind ACPI / scan: Fix check of device_attach() return value. ACPI / scan: Treat power resources in a special way ACPI: Remove unused struct acpi_pci_root.id member ACPI: Drop ACPI device .bind() and .unbind() callbacks ACPI / PCI: Move the _PRT setup and cleanup code to pci-acpi.c ACPI / PCI: Rework the setup and cleanup of device wakeup ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type ACPI: Make acpi_bus_scan() and acpi_bus_add() take only one argument ACPI: Replace ACPI device add_type field with a match_driver flag ...
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/acpi_memhotplug.c26
-rw-r--r--drivers/acpi/container.c31
-rw-r--r--drivers/acpi/device_pm.c2
-rw-r--r--drivers/acpi/dock.c23
-rw-r--r--drivers/acpi/glue.c50
-rw-r--r--drivers/acpi/internal.h1
-rw-r--r--drivers/acpi/pci_bind.c122
-rw-r--r--drivers/acpi/pci_root.c67
-rw-r--r--drivers/acpi/processor_driver.c32
-rw-r--r--drivers/acpi/scan.c340
11 files changed, 198 insertions, 498 deletions
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 2a4502becd13..4ee2e753306a 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -37,7 +37,7 @@ acpi-y += resource.o
acpi-y += processor_core.o
acpi-y += ec.o
acpi-$(CONFIG_ACPI_DOCK) += dock.o
-acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o
+acpi-y += pci_root.o pci_link.o pci_irq.o
acpi-y += acpi_platform.o
acpi-y += power.o
acpi-y += event.o
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index b679bf8478f7..03d18f290118 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -157,38 +157,26 @@ static int
acpi_memory_get_device(acpi_handle handle,
struct acpi_memory_device **mem_device)
{
- acpi_status status;
- acpi_handle phandle;
struct acpi_device *device = NULL;
- struct acpi_device *pdevice = NULL;
int result;
-
if (!acpi_bus_get_device(handle, &device) && device)
goto end;
- status = acpi_get_parent(handle, &phandle);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Cannot find acpi parent"));
- return -EINVAL;
- }
-
- /* Get the parent device */
- result = acpi_bus_get_device(phandle, &pdevice);
- if (result) {
- acpi_handle_warn(phandle, "Cannot get acpi bus device\n");
- return -EINVAL;
- }
-
/*
* Now add the notified device. This creates the acpi_device
* and invokes .add function
*/
- result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
+ result = acpi_bus_scan(handle);
if (result) {
acpi_handle_warn(handle, "Cannot add acpi bus\n");
return -EINVAL;
}
+ result = acpi_bus_get_device(handle, &device);
+ if (result) {
+ acpi_handle_warn(handle, "Missing device object\n");
+ return -EINVAL;
+ }
end:
*mem_device = acpi_driver_data(device);
@@ -355,7 +343,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
break;
}
- ej_event->handle = handle;
+ ej_event->device = device;
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
(void *)ej_event);
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 811910b50b75..cc79d3e53a39 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -135,30 +135,6 @@ static int acpi_container_remove(struct acpi_device *device, int type)
return status;
}
-static int container_device_add(struct acpi_device **device, acpi_handle handle)
-{
- acpi_handle phandle;
- struct acpi_device *pdev;
- int result;
-
-
- if (acpi_get_parent(handle, &phandle)) {
- return -ENODEV;
- }
-
- if (acpi_bus_get_device(phandle, &pdev)) {
- return -ENODEV;
- }
-
- if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) {
- return -ENODEV;
- }
-
- result = acpi_bus_start(*device);
-
- return result;
-}
-
static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
struct acpi_device *device = NULL;
@@ -190,11 +166,16 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
if (!ACPI_FAILURE(status) || device)
break;
- result = container_device_add(&device, handle);
+ result = acpi_bus_scan(handle);
if (result) {
acpi_handle_warn(handle, "Failed to add container\n");
break;
}
+ result = acpi_bus_get_device(handle, &device);
+ if (result) {
+ acpi_handle_warn(handle, "Missing device object\n");
+ break;
+ }
kobject_uevent(&device->dev.kobj, KOBJ_ONLINE);
ost_code = ACPI_OST_SC_SUCCESS;
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index c6ff606c6d5b..995019063f64 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -353,7 +353,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
* acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
* @dev: Device to get the ACPI node for.
*/
-static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
{
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
struct acpi_device *adev;
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index f32bd47b35e0..78648f811049 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -310,8 +310,6 @@ static int dock_present(struct dock_station *ds)
static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
{
struct acpi_device *device;
- struct acpi_device *parent_device;
- acpi_handle parent;
int ret;
if (acpi_bus_get_device(handle, &device)) {
@@ -319,16 +317,11 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
* no device created for this object,
* so we should create one.
*/
- acpi_get_parent(handle, &parent);
- if (acpi_bus_get_device(parent, &parent_device))
- parent_device = NULL;
-
- ret = acpi_bus_add(&device, parent_device, handle,
- ACPI_BUS_TYPE_DEVICE);
- if (ret) {
+ ret = acpi_bus_scan(handle);
+ if (ret)
pr_debug("error adding bus, %x\n", -ret);
- return NULL;
- }
+
+ acpi_bus_get_device(handle, &device);
}
return device;
}
@@ -343,13 +336,9 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
static void dock_remove_acpi_device(acpi_handle handle)
{
struct acpi_device *device;
- int ret;
- if (!acpi_bus_get_device(handle, &device)) {
- ret = acpi_bus_trim(device, 1);
- if (ret)
- pr_debug("error removing bus, %x\n", -ret);
- }
+ if (!acpi_bus_get_device(handle, &device))
+ acpi_bus_trim(device);
}
/**
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 35da18113216..9aee4fc2b218 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -68,6 +68,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
{
struct acpi_bus_type *tmp, *ret = NULL;
+ if (!type)
+ return NULL;
+
down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) {
if (tmp->bus == type) {
@@ -269,28 +272,39 @@ static int acpi_platform_notify(struct device *dev)
{
struct acpi_bus_type *type;
acpi_handle handle;
- int ret = -EINVAL;
+ int ret;
ret = acpi_bind_one(dev, NULL);
- if (!ret)
- goto out;
-
- if (!dev->bus || !dev->parent) {
+ if (ret && (!dev->bus || !dev->parent)) {
/* bridge devices genernally haven't bus or parent */
ret = acpi_find_bridge_device(dev, &handle);
- goto end;
+ if (!ret) {
+ ret = acpi_bind_one(dev, handle);
+ if (ret)
+ goto out;
+ }
}
+
type = acpi_get_bus_type(dev->bus);
- if (!type) {
- DBG("No ACPI bus support for %s\n", dev_name(dev));
- ret = -EINVAL;
- goto end;
+ if (ret) {
+ if (!type || !type->find_device) {
+ DBG("No ACPI bus support for %s\n", dev_name(dev));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = type->find_device(dev, &handle);
+ if (ret) {
+ DBG("Unable to get handle for %s\n", dev_name(dev));
+ goto out;
+ }
+ ret = acpi_bind_one(dev, handle);
+ if (ret)
+ goto out;
}
- if ((ret = type->find_device(dev, &handle)) != 0)
- DBG("Can't get handler for %s\n", dev_name(dev));
- end:
- if (!ret)
- acpi_bind_one(dev, handle);
+
+ if (type && type->setup)
+ type->setup(dev);
out:
#if ACPI_GLUE_DEBUG
@@ -309,6 +323,12 @@ static int acpi_platform_notify(struct device *dev)
static int acpi_platform_notify_remove(struct device *dev)
{
+ struct acpi_bus_type *type;
+
+ type = acpi_get_bus_type(dev->bus);
+ if (type && type->cleanup)
+ type->cleanup(dev);
+
acpi_unbind_one(dev);
return 0;
}
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 3c407cdc1ec1..e050254ae143 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -67,6 +67,7 @@ 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);
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
deleted file mode 100644
index a1dee29beed3..000000000000
--- a/drivers/acpi/pci_bind.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * pci_bind.c - ACPI PCI Device Binding ($Revision: 2 $)
- *
- * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
- * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/pci-acpi.h>
-#include <linux/acpi.h>
-#include <linux/pm_runtime.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
-#define _COMPONENT ACPI_PCI_COMPONENT
-ACPI_MODULE_NAME("pci_bind");
-
-static int acpi_pci_unbind(struct acpi_device *device)
-{
- struct pci_dev *dev;
-
- dev = acpi_get_pci_dev(device->handle);
- if (!dev)
- goto out;
-
- device_set_run_wake(&dev->dev, false);
- pci_acpi_remove_pm_notifier(device);
- acpi_power_resource_unregister_device(&dev->dev, device->handle);
-
- if (!dev->subordinate)
- goto out;
-
- acpi_pci_irq_del_prt(pci_domain_nr(dev->bus), dev->subordinate->number);
-
- device->ops.bind = NULL;
- device->ops.unbind = NULL;
-
-out:
- pci_dev_put(dev);
- return 0;
-}
-
-static int acpi_pci_bind(struct acpi_device *device)
-{
- acpi_status status;
- acpi_handle handle;
- unsigned char bus;
- struct pci_dev *dev;
-
- dev = acpi_get_pci_dev(device->handle);
- if (!dev)
- return 0;
-
- pci_acpi_add_pm_notifier(device, dev);
- acpi_power_resource_register_device(&dev->dev, device->handle);
- if (device->wakeup.flags.run_wake)
- device_set_run_wake(&dev->dev, true);
-
- /*
- * Install the 'bind' function to facilitate callbacks for
- * children of the P2P bridge.
- */
- if (dev->subordinate) {
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Device %04x:%02x:%02x.%d is a PCI bridge\n",
- pci_domain_nr(dev->bus), dev->bus->number,
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)));
- device->ops.bind = acpi_pci_bind;
- device->ops.unbind = acpi_pci_unbind;
- }
-
- /*
- * Evaluate and parse _PRT, if exists. This code allows parsing of
- * _PRT objects within the scope of non-bridge devices. Note that
- * _PRTs within the scope of a PCI bridge assume the bridge's
- * subordinate bus number.
- *
- * TBD: Can _PRTs exist within the scope of non-bridge PCI devices?
- */
- status = acpi_get_handle(device->handle, METHOD_NAME__PRT, &handle);
- if (ACPI_FAILURE(status))
- goto out;
-
- if (dev->subordinate)
- bus = dev->subordinate->number;
- else
- bus = dev->bus->number;
-
- acpi_pci_irq_add_prt(device->handle, pci_domain_nr(dev->bus), bus);
-
-out:
- pci_dev_put(dev);
- return 0;
-}
-
-int acpi_pci_bind_root(struct acpi_device *device)
-{
- device->ops.bind = acpi_pci_bind;
- device->ops.unbind = acpi_pci_unbind;
-
- return 0;
-}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 7928d4dc7056..22a8458b4ec9 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -47,7 +47,6 @@ ACPI_MODULE_NAME("pci_root");
#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_start(struct acpi_device *device);
#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
| OSC_ACTIVE_STATE_PWR_SUPPORT \
@@ -67,7 +66,6 @@ static struct acpi_driver acpi_pci_root_driver = {
.ops = {
.add = acpi_pci_root_add,
.remove = acpi_pci_root_remove,
- .start = acpi_pci_root_start,
},
};
@@ -188,21 +186,6 @@ static acpi_status try_get_root_bridge_busnr(acpi_handle handle,
return AE_OK;
}
-static void acpi_pci_bridge_scan(struct acpi_device *device)
-{
- int status;
- struct acpi_device *child = NULL;
-
- if (device->flags.bus_address)
- if (device->parent && device->parent->ops.bind) {
- status = device->parent->ops.bind(device);
- if (!status) {
- list_for_each_entry(child, &device->children, node)
- acpi_pci_bridge_scan(child);
- }
- }
-}
-
static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
static acpi_status acpi_pci_run_osc(acpi_handle handle,
@@ -452,7 +435,7 @@ static int acpi_pci_root_add(struct acpi_device *device)
int result;
struct acpi_pci_root *root;
acpi_handle handle;
- struct acpi_device *child;
+ struct acpi_pci_driver *driver;
u32 flags, base_flags;
bool is_osc_granted = false;
@@ -603,21 +586,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
goto out_del_root;
}
- /*
- * Attach ACPI-PCI Context
- * -----------------------
- * Thus binding the ACPI and PCI devices.
- */
- result = acpi_pci_bind_root(device);
- if (result)
- goto out_del_root;
-
- /*
- * Scan and bind all _ADR-Based Devices
- */
- list_for_each_entry(child, &device->children, node)
- acpi_pci_bridge_scan(child);
-
/* ASPM setting */
if (is_osc_granted) {
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
@@ -632,24 +600,6 @@ static int acpi_pci_root_add(struct acpi_device *device)
if (device->wakeup.flags.run_wake)
device_set_run_wake(root->bus->bridge, true);
- return 0;
-
-out_del_root:
- mutex_lock(&acpi_pci_root_lock);
- list_del(&root->node);
- mutex_unlock(&acpi_pci_root_lock);
-
- acpi_pci_irq_del_prt(root->segment, root->secondary.start);
-end:
- kfree(root);
- return result;
-}
-
-static int acpi_pci_root_start(struct acpi_device *device)
-{
- struct acpi_pci_root *root = acpi_driver_data(device);
- struct acpi_pci_driver *driver;
-
if (system_state != SYSTEM_BOOTING)
pci_assign_unassigned_bus_resources(root->bus);
@@ -664,8 +614,17 @@ static int acpi_pci_root_start(struct acpi_device *device)
pci_enable_bridges(root->bus);
pci_bus_add_devices(root->bus);
-
return 0;
+
+out_del_root:
+ mutex_lock(&acpi_pci_root_lock);
+ list_del(&root->node);
+ mutex_unlock(&acpi_pci_root_lock);
+
+ acpi_pci_irq_del_prt(root->segment, root->secondary.start);
+end:
+ kfree(root);
+ return result;
}
static int acpi_pci_root_remove(struct acpi_device *device, int type)
@@ -699,7 +658,7 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type)
return 0;
}
-static int __init acpi_pci_root_init(void)
+int __init acpi_pci_root_init(void)
{
acpi_hest_init();
@@ -712,5 +671,3 @@ static int __init acpi_pci_root_init(void)
return 0;
}
-
-subsys_initcall(acpi_pci_root_init);
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index e83311bf1ebd..9c5929a17d3a 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -677,28 +677,6 @@ static int is_processor_present(acpi_handle handle)
return 0;
}
-static
-int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
-{
- acpi_handle phandle;
- struct acpi_device *pdev;
-
-
- if (acpi_get_parent(handle, &phandle)) {
- return -ENODEV;
- }
-
- if (acpi_bus_get_device(phandle, &pdev)) {
- return -ENODEV;
- }
-
- if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
- return -ENODEV;
- }
-
- return 0;
-}
-
static void acpi_processor_hotplug_notify(acpi_handle handle,
u32 event, void *data)
{
@@ -721,12 +699,16 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
if (!acpi_bus_get_device(handle, &device))
break;
- result = acpi_processor_device_add(handle, &device);
+ result = acpi_bus_scan(handle);
if (result) {
acpi_handle_err(handle, "Unable to add the device\n");
break;
}
-
+ result = acpi_bus_get_device(handle, &device);
+ if (result) {
+ acpi_handle_err(handle, "Missing device object\n");
+ break;
+ }
ost_code = ACPI_OST_SC_SUCCESS;
break;
@@ -751,7 +733,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
break;
}
- ej_event->handle = handle;
+ ej_event->device = device;
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
(void *)ej_event);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index c88be6c37c30..83fe3bf4cdc8 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -52,6 +52,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = {
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
+static DEFINE_MUTEX(acpi_scan_lock);
DEFINE_MUTEX(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
@@ -116,30 +117,19 @@ 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_device *device;
- acpi_handle handle = ej_event->handle;
+ struct acpi_device *device = ej_event->device;
+ acpi_handle handle = device->handle;
acpi_handle temp;
struct acpi_object_list arg_list;
union acpi_object arg;
acpi_status status = AE_OK;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
- if (acpi_bus_get_device(handle, &device))
- goto err_out;
-
- if (!device)
- goto err_out;
-
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Hot-removing device %s...\n", dev_name(&device->dev)));
- if (acpi_bus_trim(device, 1)) {
- printk(KERN_ERR PREFIX
- "Removing device failed\n");
- goto err_out;
- }
-
- /* device has been freed */
+ acpi_bus_trim(device);
+ /* Device node has been released. */
device = NULL;
/* power off device */
@@ -215,7 +205,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
goto err;
}
- ej_event->handle = acpi_device->handle;
+ ej_event->device = acpi_device;
if (acpi_device->flags.eject_pending) {
/* event originated from ACPI eject notification */
ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
@@ -223,7 +213,7 @@ acpi_eject_store(struct device *d, struct device_attribute *attr,
} else {
/* event originated from user */
ej_event->event = ACPI_OST_EC_OSPM_EJECT;
- (void) acpi_evaluate_hotplug_ost(ej_event->handle,
+ (void) acpi_evaluate_hotplug_ost(acpi_device->handle,
ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL);
}
@@ -454,9 +444,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
const struct device *dev)
{
struct acpi_device *adev;
+ acpi_handle handle = ACPI_HANDLE(dev);
- if (!ids || !ACPI_HANDLE(dev)
- || ACPI_FAILURE(acpi_bus_get_device(ACPI_HANDLE(dev), &adev)))
+ if (!ids || !handle || acpi_bus_get_device(handle, &adev))
return NULL;
return __acpi_match_device(adev, ids);
@@ -494,7 +484,8 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv)
struct acpi_device *acpi_dev = to_acpi_device(dev);
struct acpi_driver *acpi_drv = to_acpi_driver(drv);
- return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+ return acpi_dev->flags.match_driver
+ && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
}
static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -570,7 +561,6 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
}
static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *);
-static int acpi_start_single_object(struct acpi_device *);
static int acpi_device_probe(struct device * dev)
{
struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -579,9 +569,6 @@ static int acpi_device_probe(struct device * dev)
ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
if (!ret) {
- if (acpi_dev->bus_ops.acpi_op_start)
- acpi_start_single_object(acpi_dev);
-
if (acpi_drv->ops.notify) {
ret = acpi_device_install_notify_handler(acpi_dev);
if (ret) {
@@ -704,7 +691,7 @@ end:
return result;
}
-static void acpi_device_unregister(struct acpi_device *device, int type)
+static void acpi_device_unregister(struct acpi_device *device)
{
mutex_lock(&acpi_device_lock);
if (device->parent)
@@ -760,24 +747,6 @@ acpi_bus_driver_init(struct acpi_device *device, struct acpi_driver *driver)
return 0;
}
-static int acpi_start_single_object(struct acpi_device *device)
-{
- int result = 0;
- struct acpi_driver *driver;
-
-
- if (!(driver = device->driver))
- return 0;
-
- if (driver->ops.start) {
- result = driver->ops.start(device);
- if (result && driver->ops.remove)
- driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
- }
-
- return result;
-}
-
/**
* acpi_bus_register_driver - register a driver with the ACPI bus
* @driver: driver being registered
@@ -1395,33 +1364,9 @@ static int acpi_device_set_context(struct acpi_device *device)
return -ENODEV;
}
-static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
-{
- if (!dev)
- return -EINVAL;
-
- dev->removal_type = ACPI_BUS_REMOVAL_EJECT;
- device_release_driver(&dev->dev);
-
- if (!rmdevice)
- return 0;
-
- /*
- * unbind _ADR-Based Devices when hot removal
- */
- if (dev->flags.bus_address) {
- if ((dev->parent) && (dev->parent->ops.unbind))
- dev->parent->ops.unbind(dev);
- }
- acpi_device_unregister(dev, ACPI_BUS_REMOVAL_EJECT);
-
- return 0;
-}
-
static int acpi_add_single_object(struct acpi_device **child,
acpi_handle handle, int type,
- unsigned long long sta,
- struct acpi_bus_ops *ops)
+ unsigned long long sta, bool match_driver)
{
int result;
struct acpi_device *device;
@@ -1437,7 +1382,6 @@ static int acpi_add_single_object(struct acpi_device **child,
device->device_type = type;
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
- device->bus_ops = *ops; /* workround for not call .start */
STRUCT_TO_INT(device->status) = sta;
acpi_device_get_busid(device);
@@ -1488,16 +1432,9 @@ static int acpi_add_single_object(struct acpi_device **child,
if ((result = acpi_device_set_context(device)))
goto end;
+ device->flags.match_driver = match_driver;
result = acpi_device_register(device);
- /*
- * Bind _ADR-Based Devices when hot add
- */
- if (device->flags.bus_address) {
- if (device->parent && device->parent->ops.bind)
- device->parent->ops.bind(device);
- }
-
end:
if (!result) {
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1519,16 +1456,12 @@ end:
static void acpi_bus_add_power_resource(acpi_handle handle)
{
- struct acpi_bus_ops ops = {
- .acpi_op_add = 1,
- .acpi_op_start = 1,
- };
struct acpi_device *device = NULL;
acpi_bus_get_device(handle, &device);
if (!device)
acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
- ACPI_STA_DEFAULT, &ops);
+ ACPI_STA_DEFAULT, true);
}
static int acpi_bus_type_and_status(acpi_handle handle, int *type,
@@ -1570,16 +1503,19 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
return 0;
}
-static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
- void *context, void **return_value)
+static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
+ void *not_used, void **return_value)
{
- struct acpi_bus_ops *ops = context;
+ struct acpi_device *device = NULL;
int type;
unsigned long long sta;
- struct acpi_device *device;
acpi_status status;
int result;
+ acpi_bus_get_device(handle, &device);
+ if (device)
+ goto out;
+
result = acpi_bus_type_and_status(handle, &type, &sta);
if (result)
return AE_OK;
@@ -1596,150 +1532,124 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
return AE_CTRL_DEPTH;
}
- /*
- * We may already have an acpi_device from a previous enumeration. If
- * so, we needn't add it again, but we may still have to start it.
- */
- device = NULL;
- acpi_bus_get_device(handle, &device);
- if (ops->acpi_op_add && !device) {
- acpi_add_single_object(&device, handle, type, sta, ops);
- /* Is the device a known good platform device? */
- if (device
- && !acpi_match_device_ids(device, acpi_platform_device_ids))
- acpi_create_platform_device(device);
- }
-
+ acpi_add_single_object(&device, handle, type, sta,
+ type == ACPI_BUS_TYPE_POWER);
if (!device)
return AE_CTRL_DEPTH;
- if (ops->acpi_op_start && !(ops->acpi_op_add)) {
- status = acpi_start_single_object(device);
- if (ACPI_FAILURE(status))
- return AE_CTRL_DEPTH;
- }
+ device->flags.match_driver = true;
+ out:
if (!*return_value)
*return_value = device;
+
return AE_OK;
}
-static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
- struct acpi_device **child)
+static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
+ void *not_used, void **ret_not_used)
{
- acpi_status status;
- void *device = NULL;
+ acpi_status status = AE_OK;
+ struct acpi_device *device;
+ unsigned long long sta_not_used;
+ int type_not_used;
- status = acpi_bus_check_add(handle, 0, ops, &device);
- if (ACPI_SUCCESS(status))
- acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
- acpi_bus_check_add, NULL, ops, &device);
+ /*
+ * 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))
+ return AE_OK;
- if (child)
- *child = device;
+ if (acpi_bus_get_device(handle, &device))
+ return AE_CTRL_DEPTH;
- if (device)
- return 0;
- else
- return -ENODEV;
+ if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+ /* This is a known good platform device. */
+ acpi_create_platform_device(device);
+ } else if (device_attach(&device->dev) < 0) {
+ status = AE_CTRL_DEPTH;
+ }
+ return status;
}
-/*
- * acpi_bus_add and acpi_bus_start
+/**
+ * acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
+ * @handle: Root of the namespace scope to scan.
*
- * scan a given ACPI tree and (probably recently hot-plugged)
- * create and add or starts found devices.
+ * Scan a given ACPI tree (probably recently hot-plugged) and create and add
+ * found devices.
*
- * If no devices were found -ENODEV is returned which does not
- * mean that this is 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/start an appropriate driver.
+ * If no devices were found, -ENODEV is returned, but it does not mean that
+ * 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.
*/
-
-int
-acpi_bus_add(struct acpi_device **child,
- struct acpi_device *parent, acpi_handle handle, int type)
+int acpi_bus_scan(acpi_handle handle)
{
- struct acpi_bus_ops ops;
-
- memset(&ops, 0, sizeof(ops));
- ops.acpi_op_add = 1;
+ void *device = NULL;
+ int error = 0;
- return acpi_bus_scan(handle, &ops, child);
-}
-EXPORT_SYMBOL(acpi_bus_add);
+ mutex_lock(&acpi_scan_lock);
-int acpi_bus_start(struct acpi_device *device)
-{
- struct acpi_bus_ops ops;
- int result;
+ 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);
if (!device)
- return -EINVAL;
-
- memset(&ops, 0, sizeof(ops));
- ops.acpi_op_start = 1;
+ error = -ENODEV;
+ else if (ACPI_SUCCESS(acpi_bus_device_attach(handle, 0, NULL, NULL)))
+ acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+ acpi_bus_device_attach, NULL, NULL, NULL);
- result = acpi_bus_scan(device->handle, &ops, NULL);
+ mutex_unlock(&acpi_scan_lock);
+ return error;
+}
+EXPORT_SYMBOL(acpi_bus_scan);
- acpi_update_all_gpes();
+static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
+ void *not_used, void **ret_not_used)
+{
+ struct acpi_device *device = NULL;
- return result;
+ if (!acpi_bus_get_device(handle, &device)) {
+ device->removal_type = ACPI_BUS_REMOVAL_EJECT;
+ device_release_driver(&device->dev);
+ }
+ return AE_OK;
}
-EXPORT_SYMBOL(acpi_bus_start);
-int acpi_bus_trim(struct acpi_device *start, int rmdevice)
+static acpi_status acpi_bus_remove(acpi_handle handle, u32 lvl_not_used,
+ void *not_used, void **ret_not_used)
{
- acpi_status status;
- struct acpi_device *parent, *child;
- acpi_handle phandle, chandle;
- acpi_object_type type;
- u32 level = 1;
- int err = 0;
+ struct acpi_device *device = NULL;
- parent = start;
- phandle = start->handle;
- child = chandle = NULL;
+ if (!acpi_bus_get_device(handle, &device))
+ acpi_device_unregister(device);
- while ((level > 0) && parent && (!err)) {
- status = acpi_get_next_object(ACPI_TYPE_ANY, phandle,
- chandle, &chandle);
+ return AE_OK;
+}
- /*
- * If this scope is exhausted then move our way back up.
- */
- if (ACPI_FAILURE(status)) {
- level--;
- chandle = phandle;
- acpi_get_parent(phandle, &phandle);
- child = parent;
- parent = parent->parent;
-
- if (level == 0)
- err = acpi_bus_remove(child, rmdevice);
- else
- err = acpi_bus_remove(child, 1);
+void acpi_bus_trim(struct acpi_device *start)
+{
+ mutex_lock(&acpi_scan_lock);
- continue;
- }
+ /*
+ * Execute acpi_bus_device_detach() as a post-order callback to detach
+ * all ACPI drivers from the device nodes being removed.
+ */
+ acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
+ acpi_bus_device_detach, NULL, NULL);
+ acpi_bus_device_detach(start->handle, 0, NULL, NULL);
+ /*
+ * Execute acpi_bus_remove() as a post-order callback to remove device
+ * nodes in the given namespace scope.
+ */
+ 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);
- status = acpi_get_type(chandle, &type);
- if (ACPI_FAILURE(status)) {
- continue;
- }
- /*
- * If there is a device corresponding to chandle then
- * parse it (depth-first).
- */
- if (acpi_bus_get_device(chandle, &child) == 0) {
- level++;
- phandle = chandle;
- chandle = NULL;
- parent = child;
- }
- continue;
- }
- return err;
+ mutex_unlock(&acpi_scan_lock);
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
@@ -1747,11 +1657,6 @@ static int acpi_bus_scan_fixed(void)
{
int result = 0;
struct acpi_device *device = NULL;
- struct acpi_bus_ops ops;
-
- memset(&ops, 0, sizeof(ops));
- ops.acpi_op_add = 1;
- ops.acpi_op_start = 1;
/*
* Enumerate all fixed-feature devices.
@@ -1759,16 +1664,14 @@ static int acpi_bus_scan_fixed(void)
if ((acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON) == 0) {
result = acpi_add_single_object(&device, NULL,
ACPI_BUS_TYPE_POWER_BUTTON,
- ACPI_STA_DEFAULT,
- &ops);
+ ACPI_STA_DEFAULT, true);
device_init_wakeup(&device->dev, true);
}
if ((acpi_gbl_FADT.flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
result = acpi_add_single_object(&device, NULL,
ACPI_BUS_TYPE_SLEEP_BUTTON,
- ACPI_STA_DEFAULT,
- &ops);
+ ACPI_STA_DEFAULT, true);
}
return result;
@@ -1777,11 +1680,6 @@ static int acpi_bus_scan_fixed(void)
int __init acpi_scan_init(void)
{
int result;
- struct acpi_bus_ops ops;
-
- memset(&ops, 0, sizeof(ops));
- ops.acpi_op_add = 1;
- ops.acpi_op_start = 1;
result = bus_register(&acpi_bus_type);
if (result) {
@@ -1790,19 +1688,25 @@ int __init acpi_scan_init(void)
}
acpi_power_init();
+ acpi_pci_root_init();
/*
* Enumerate devices in the ACPI namespace.
*/
- result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
-
- if (!result)
- result = acpi_bus_scan_fixed();
+ result = acpi_bus_scan(ACPI_ROOT_OBJECT);
+ if (result)
+ return result;
+ result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
if (result)
- acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
- else
- acpi_update_all_gpes();
+ return result;
- return result;
+ result = acpi_bus_scan_fixed();
+ if (result) {
+ acpi_device_unregister(acpi_root);
+ return result;
+ }
+
+ acpi_update_all_gpes();
+ return 0;
}