aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c457
1 files changed, 253 insertions, 204 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 2c80765670bc..b47e93a24a9a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -19,6 +19,8 @@
#include <linux/dma-map-ops.h>
#include <linux/platform_data/x86/apple.h>
#include <linux/pgtable.h>
+#include <linux/crc32.h>
+#include <linux/dma-direct.h>
#include "internal.h"
@@ -28,8 +30,6 @@ extern struct acpi_device *acpi_root;
#define ACPI_BUS_HID "LNXSYBUS"
#define ACPI_BUS_DEVICE_NAME "System Bus"
-#define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent)
-
#define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page)
static const char *dummy_hid = "device";
@@ -135,12 +135,12 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
void **ret_p)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_device_physical_node *pn;
bool second_pass = (bool)data;
acpi_status status = AE_OK;
- if (acpi_bus_get_device(handle, &device))
+ if (!device)
return AE_OK;
if (device->handler && !device->handler->hotplug.enabled) {
@@ -180,10 +180,10 @@ static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data,
static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data,
void **ret_p)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = acpi_fetch_acpi_dev(handle);
struct acpi_device_physical_node *pn;
- if (acpi_bus_get_device(handle, &device))
+ if (!device)
return AE_OK;
mutex_lock(&device->physical_node_lock);
@@ -333,10 +333,9 @@ static int acpi_scan_device_check(struct acpi_device *adev)
return error;
}
-static int acpi_scan_bus_check(struct acpi_device *adev)
+static int acpi_scan_bus_check(struct acpi_device *adev, void *not_used)
{
struct acpi_scan_handler *handler = adev->handler;
- struct acpi_device *child;
int error;
acpi_bus_get_status(adev);
@@ -352,19 +351,14 @@ static int acpi_scan_bus_check(struct acpi_device *adev)
dev_warn(&adev->dev, "Namespace scan failure\n");
return error;
}
- list_for_each_entry(child, &adev->children, node) {
- error = acpi_scan_bus_check(child);
- if (error)
- return error;
- }
- return 0;
+ return acpi_dev_for_each_child(adev, acpi_scan_bus_check, NULL);
}
static int acpi_generic_hotplug_event(struct acpi_device *adev, u32 type)
{
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
- return acpi_scan_bus_check(adev);
+ return acpi_scan_bus_check(adev, NULL);
case ACPI_NOTIFY_DEVICE_CHECK:
return acpi_scan_device_check(adev);
case ACPI_NOTIFY_EJECT_REQUEST:
@@ -434,7 +428,7 @@ void acpi_device_hotplug(struct acpi_device *adev, u32 src)
acpi_evaluate_ost(adev->handle, src, ost_code, NULL);
out:
- acpi_bus_put_acpi_device(adev);
+ acpi_put_acpi_dev(adev);
mutex_unlock(&acpi_scan_lock);
unlock_device_hotplug();
}
@@ -470,13 +464,12 @@ static void acpi_device_del(struct acpi_device *device)
struct acpi_device_bus_id *acpi_device_bus_id;
mutex_lock(&acpi_device_lock);
- if (device->parent)
- list_del(&device->node);
list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
if (!strcmp(acpi_device_bus_id->bus_id,
acpi_device_hid(device))) {
- ida_simple_remove(&acpi_device_bus_id->instance_ida, device->pnp.instance_no);
+ ida_free(&acpi_device_bus_id->instance_ida,
+ device->pnp.instance_no);
if (ida_is_empty(&acpi_device_bus_id->instance_ida)) {
list_del(&acpi_device_bus_id->node);
kfree_const(acpi_device_bus_id->bus_id);
@@ -486,6 +479,7 @@ static void acpi_device_del(struct acpi_device *device)
}
list_del(&device->wakeup_list);
+
mutex_unlock(&acpi_device_lock);
acpi_power_add_remove_device(device, false);
@@ -586,29 +580,40 @@ static struct acpi_device *handle_to_device(acpi_handle handle,
return adev;
}
-int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
+/**
+ * acpi_fetch_acpi_dev - Retrieve ACPI device object.
+ * @handle: ACPI handle associated with the requested ACPI device object.
+ *
+ * Return a pointer to the ACPI device object associated with @handle, if
+ * present, or NULL otherwise.
+ */
+struct acpi_device *acpi_fetch_acpi_dev(acpi_handle handle)
{
- if (!device)
- return -EINVAL;
-
- *device = handle_to_device(handle, NULL);
- if (!*device)
- return -ENODEV;
-
- return 0;
+ return handle_to_device(handle, NULL);
}
-EXPORT_SYMBOL(acpi_bus_get_device);
+EXPORT_SYMBOL_GPL(acpi_fetch_acpi_dev);
static void get_acpi_device(void *dev)
{
acpi_dev_get(dev);
}
-struct acpi_device *acpi_bus_get_acpi_device(acpi_handle handle)
+/**
+ * acpi_get_acpi_dev - Retrieve ACPI device object and reference count it.
+ * @handle: ACPI handle associated with the requested ACPI device object.
+ *
+ * Return a pointer to the ACPI device object associated with @handle and bump
+ * up that object's reference counter (under the ACPI Namespace lock), if
+ * present, or return NULL otherwise.
+ *
+ * The ACPI device object reference acquired by this function needs to be
+ * dropped via acpi_dev_put().
+ */
+struct acpi_device *acpi_get_acpi_dev(acpi_handle handle)
{
return handle_to_device(handle, get_acpi_device);
}
-EXPORT_SYMBOL_GPL(acpi_bus_get_acpi_device);
+EXPORT_SYMBOL_GPL(acpi_get_acpi_dev);
static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id)
{
@@ -628,7 +633,7 @@ static int acpi_device_set_name(struct acpi_device *device,
struct ida *instance_ida = &acpi_device_bus_id->instance_ida;
int result;
- result = ida_simple_get(instance_ida, 0, ACPI_MAX_DEVICE_INSTANCES, GFP_KERNEL);
+ result = ida_alloc(instance_ida, GFP_KERNEL);
if (result < 0)
return result;
@@ -637,7 +642,7 @@ static int acpi_device_set_name(struct acpi_device *device,
return 0;
}
-static int acpi_tie_acpi_dev(struct acpi_device *adev)
+int acpi_tie_acpi_dev(struct acpi_device *adev)
{
acpi_handle handle = adev->handle;
acpi_status status;
@@ -654,8 +659,20 @@ static int acpi_tie_acpi_dev(struct acpi_device *adev)
return 0;
}
-static int __acpi_device_add(struct acpi_device *device,
- void (*release)(struct device *))
+static void acpi_store_pld_crc(struct acpi_device *adev)
+{
+ struct acpi_pld_info *pld;
+ acpi_status status;
+
+ status = acpi_get_physical_device_location(adev->handle, &pld);
+ if (ACPI_FAILURE(status))
+ return;
+
+ adev->pld_crc = crc32(~0, pld, sizeof(*pld));
+ ACPI_FREE(pld);
+}
+
+int acpi_device_add(struct acpi_device *device)
{
struct acpi_device_bus_id *acpi_device_bus_id;
int result;
@@ -665,8 +682,6 @@ static int __acpi_device_add(struct acpi_device *device,
* -------
* Link this device to its parent and siblings.
*/
- INIT_LIST_HEAD(&device->children);
- INIT_LIST_HEAD(&device->node);
INIT_LIST_HEAD(&device->wakeup_list);
INIT_LIST_HEAD(&device->physical_node_list);
INIT_LIST_HEAD(&device->del_list);
@@ -706,19 +721,13 @@ static int __acpi_device_add(struct acpi_device *device,
list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
}
- if (device->parent)
- list_add_tail(&device->node, &device->parent->children);
-
if (device->wakeup.flags.valid)
list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
- mutex_unlock(&acpi_device_lock);
+ acpi_store_pld_crc(device);
- if (device->parent)
- device->dev.parent = &device->parent->dev;
+ mutex_unlock(&acpi_device_lock);
- device->dev.bus = &acpi_bus_type;
- device->dev.release = release;
result = device_add(&device->dev);
if (result) {
dev_err(&device->dev, "Error registering device\n");
@@ -735,9 +744,6 @@ static int __acpi_device_add(struct acpi_device *device,
err:
mutex_lock(&acpi_device_lock);
- if (device->parent)
- list_del(&device->node);
-
list_del(&device->wakeup_list);
err_unlock:
@@ -748,17 +754,6 @@ err_unlock:
return result;
}
-int acpi_device_add(struct acpi_device *adev, void (*release)(struct device *))
-{
- int ret;
-
- ret = acpi_tie_acpi_dev(adev);
- if (ret)
- return ret;
-
- return __acpi_device_add(adev, release);
-}
-
/* --------------------------------------------------------------------------
Device Enumeration
-------------------------------------------------------------------------- */
@@ -794,13 +789,19 @@ static bool acpi_info_matches_ids(struct acpi_device_info *info,
static const char * const acpi_ignore_dep_ids[] = {
"PNP0D80", /* Windows-compatible System Power Management Controller */
"INT33BD", /* Intel Baytrail Mailbox Device */
+ "LATT2021", /* Lattice FW Update Client Driver */
NULL
};
-static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
+/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
+static const char * const acpi_honor_dep_ids[] = {
+ "INT3472", /* Camera sensor PMIC / clk and regulator info */
+ NULL
+};
+
+static struct acpi_device *acpi_find_parent_acpi_dev(acpi_handle handle)
{
- struct acpi_device *device = NULL;
- acpi_status status;
+ struct acpi_device *adev;
/*
* Fixed hardware devices do not appear in the namespace and do not
@@ -811,11 +812,18 @@ static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
return acpi_root;
do {
+ acpi_status status;
+
status = acpi_get_parent(handle, &handle);
- if (ACPI_FAILURE(status))
- return status == AE_NULL_ENTRY ? NULL : acpi_root;
- } while (acpi_bus_get_device(handle, &device));
- return device;
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NULL_ENTRY)
+ return acpi_root;
+
+ return NULL;
+ }
+ adev = acpi_fetch_acpi_dev(handle);
+ } while (!adev);
+ return adev;
}
acpi_status
@@ -1102,7 +1110,7 @@ static void acpi_device_get_busid(struct acpi_device *device)
* The device's Bus ID is simply the object name.
* TBD: Shouldn't this value be unique (within the ACPI namespace)?
*/
- if (ACPI_IS_ROOT_DEVICE(device)) {
+ if (!acpi_dev_parent(device)) {
strcpy(device->pnp.bus_id, "ACPI");
return;
}
@@ -1457,25 +1465,21 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
* acpi_dma_get_range() - Get device DMA parameters.
*
* @dev: device to configure
- * @dma_addr: pointer device DMA address result
- * @offset: pointer to the DMA offset result
- * @size: pointer to DMA range size result
+ * @map: pointer to DMA ranges result
*
- * Evaluate DMA regions and return respectively DMA region start, offset
- * and size in dma_addr, offset and size on parsing success; it does not
- * update the passed in values on failure.
+ * Evaluate DMA regions and return pointer to DMA regions on
+ * parsing success; it does not update the passed in values on failure.
*
* Return 0 on success, < 0 on failure.
*/
-int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
- u64 *size)
+int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)
{
struct acpi_device *adev;
LIST_HEAD(list);
struct resource_entry *rentry;
int ret;
struct device *dma_dev = dev;
- u64 len, dma_start = U64_MAX, dma_end = 0, dma_offset = 0;
+ struct bus_dma_region *r;
/*
* Walk the device tree chasing an ACPI companion with a _DMA
@@ -1500,31 +1504,29 @@ int acpi_dma_get_range(struct device *dev, u64 *dma_addr, u64 *offset,
ret = acpi_dev_get_dma_resources(adev, &list);
if (ret > 0) {
+ r = kcalloc(ret + 1, sizeof(*r), GFP_KERNEL);
+ if (!r) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ *map = r;
+
list_for_each_entry(rentry, &list, node) {
- if (dma_offset && rentry->offset != dma_offset) {
+ if (rentry->res->start >= rentry->res->end) {
+ kfree(*map);
+ *map = NULL;
ret = -EINVAL;
- dev_warn(dma_dev, "Can't handle multiple windows with different offsets\n");
+ dev_dbg(dma_dev, "Invalid DMA regions configuration\n");
goto out;
}
- dma_offset = rentry->offset;
- /* Take lower and upper limits */
- if (rentry->res->start < dma_start)
- dma_start = rentry->res->start;
- if (rentry->res->end > dma_end)
- dma_end = rentry->res->end;
- }
-
- if (dma_start >= dma_end) {
- ret = -EINVAL;
- dev_dbg(dma_dev, "Invalid DMA regions configuration\n");
- goto out;
+ r->cpu_start = rentry->res->start;
+ r->dma_start = rentry->res->start - rentry->offset;
+ r->size = resource_size(rentry->res);
+ r->offset = rentry->offset;
+ r++;
}
-
- *dma_addr = dma_start - dma_offset;
- len = dma_end - dma_start;
- *size = max(len, len + 1);
- *offset = dma_offset;
}
out:
acpi_dev_free_resource_list(&list);
@@ -1614,20 +1616,19 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr,
const u32 *input_id)
{
const struct iommu_ops *iommu;
- u64 dma_addr = 0, size = 0;
if (attr == DEV_DMA_NOT_SUPPORTED) {
set_dma_ops(dev, &dma_dummy_ops);
return 0;
}
- acpi_arch_dma_setup(dev, &dma_addr, &size);
+ acpi_arch_dma_setup(dev);
iommu = acpi_iommu_configure_id(dev, input_id);
if (PTR_ERR(iommu) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- arch_setup_dma_ops(dev, dma_addr, size,
+ arch_setup_dma_ops(dev, 0, U64_MAX,
iommu, attr == DEV_DMA_COHERENT);
return 0;
@@ -1638,7 +1639,7 @@ static void acpi_init_coherency(struct acpi_device *adev)
{
unsigned long long cca = 0;
acpi_status status;
- struct acpi_device *parent = adev->parent;
+ struct acpi_device *parent = acpi_dev_parent(adev);
if (parent && parent->flags.cca_seen) {
/*
@@ -1682,7 +1683,7 @@ static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data)
static bool acpi_is_indirect_io_slave(struct acpi_device *device)
{
- struct acpi_device *parent = device->parent;
+ struct acpi_device *parent = acpi_dev_parent(device);
static const struct acpi_device_id indirect_io_hosts[] = {
{"HISI0191", 0},
{}
@@ -1695,19 +1696,37 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
{
struct list_head resource_list;
bool is_serial_bus_slave = false;
+ static const struct acpi_device_id ignore_serial_bus_ids[] = {
/*
- * These devices have multiple I2cSerialBus resources and an i2c-client
- * must be instantiated for each, each with its own i2c_device_id.
- * Normally we only instantiate an i2c-client for the first resource,
- * using the ACPI HID as id. These special cases are handled by the
- * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows
- * which i2c_device_id to use for each resource.
+ * These devices have multiple SerialBus resources and a client
+ * device must be instantiated for each of them, each with
+ * its own device id.
+ * Normally we only instantiate one client device for the first
+ * resource, using the ACPI HID as id. These special cases are handled
+ * by the drivers/platform/x86/serial-multi-instantiate.c driver, which
+ * knows which client device id to use for each resource.
*/
- static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
{"BSG1160", },
{"BSG2150", },
+ {"CSC3551", },
{"INT33FE", },
{"INT3515", },
+ /* Non-conforming _HID for Cirrus Logic already released */
+ {"CLSA0100", },
+ {"CLSA0101", },
+ /*
+ * Some ACPI devs contain SerialBus resources even though they are not
+ * attached to a serial bus at all.
+ */
+ {"MSHW0028", },
+ /*
+ * HIDs of device with an UartSerialBusV2 resource for which userspace
+ * expects a regular tty cdev to be created (instead of the in kernel
+ * serdev) and which have a kernel driver which expects a platform_dev
+ * such as the rfkill-gpio driver.
+ */
+ {"BCM4752", },
+ {"LNV4752", },
{}
};
@@ -1721,8 +1740,7 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
fwnode_property_present(&device->fwnode, "baud")))
return true;
- /* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */
- if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids))
+ if (!acpi_match_device_ids(device, ignore_serial_bus_ids))
return false;
INIT_LIST_HEAD(&resource_list);
@@ -1735,12 +1753,16 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
}
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
- int type)
+ int type, void (*release)(struct device *))
{
+ struct acpi_device *parent = acpi_find_parent_acpi_dev(handle);
+
INIT_LIST_HEAD(&device->pnp.ids);
device->device_type = type;
device->handle = handle;
- device->parent = acpi_bus_get_parent(handle);
+ device->dev.parent = parent ? &parent->dev : NULL;
+ device->dev.release = release;
+ device->dev.bus = &acpi_bus_type;
fwnode_init(&device->fwnode, &acpi_device_fwnode_ops);
acpi_set_device_status(device, ACPI_STA_DEFAULT);
acpi_device_get_busid(device);
@@ -1762,8 +1784,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
struct acpi_dep_data *dep;
list_for_each_entry(dep, &acpi_dep_list, node) {
- if (dep->consumer == adev->handle)
+ if (dep->consumer == adev->handle) {
+ if (dep->honor_dep)
+ adev->flags.honor_deps = 1;
+
adev->dep_unmet++;
+ }
}
}
@@ -1790,7 +1816,7 @@ static int acpi_add_single_object(struct acpi_device **child,
if (!device)
return -ENOMEM;
- acpi_init_device_object(device, handle, type);
+ acpi_init_device_object(device, handle, type, acpi_device_release);
/*
* Getting the status is delayed till here so that we can call
* acpi_bus_get_status() and use its quirk handling. Note that
@@ -1820,7 +1846,7 @@ static int acpi_add_single_object(struct acpi_device **child,
mutex_unlock(&acpi_dep_list_lock);
if (!result)
- result = __acpi_device_add(device, acpi_device_release);
+ result = acpi_device_add(device);
if (result) {
acpi_device_release(&device->dev);
@@ -1831,8 +1857,8 @@ static int acpi_add_single_object(struct acpi_device **child,
acpi_device_add_finalize(device);
acpi_handle_debug(handle, "Added as %s, parent %s\n",
- dev_name(&device->dev), device->parent ?
- dev_name(&device->parent->dev) : "(null)");
+ dev_name(&device->dev), device->dev.parent ?
+ dev_name(device->dev.parent) : "(null)");
*child = device;
return 0;
@@ -1967,7 +1993,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
for (count = 0, i = 0; i < dep_devices.count; i++) {
struct acpi_device_info *info;
struct acpi_dep_data *dep;
- bool skip;
+ bool skip, honor_dep;
status = acpi_get_object_info(dep_devices.handles[i], &info);
if (ACPI_FAILURE(status)) {
@@ -1976,6 +2002,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
}
skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
+ honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
kfree(info);
if (skip)
@@ -1989,6 +2016,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
dep->supplier = dep_devices.handles[i];
dep->consumer = handle;
+ dep->honor_dep = honor_dep;
mutex_lock(&acpi_dep_list_lock);
list_add_tail(&dep->node , &acpi_dep_list);
@@ -2003,11 +2031,10 @@ static bool acpi_bus_scan_second_pass;
static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
struct acpi_device **adev_p)
{
- struct acpi_device *device = NULL;
+ struct acpi_device *device = acpi_fetch_acpi_dev(handle);
acpi_object_type acpi_type;
int type;
- acpi_bus_get_device(handle, &device);
if (device)
goto out;
@@ -2141,9 +2168,8 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
return ret;
}
-static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
+static int acpi_bus_attach(struct acpi_device *device, void *first_pass)
{
- struct acpi_device *child;
bool skip = !first_pass && device->flags.visited;
acpi_handle ejd;
int ret;
@@ -2155,12 +2181,12 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
register_dock_dependent_device(device, ejd);
acpi_bus_get_status(device);
- /* Skip devices that are not present. */
- if (!acpi_device_is_present(device)) {
+ /* Skip devices that are not ready for enumeration (e.g. not present) */
+ if (!acpi_dev_ready_for_enumeration(device)) {
device->flags.initialized = false;
acpi_device_clear_enumerated(device);
device->flags.power_manageable = 0;
- return;
+ return 0;
}
if (device->handler)
goto ok;
@@ -2178,7 +2204,7 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
ret = acpi_scan_attach_handler(device);
if (ret < 0)
- return;
+ return 0;
device->flags.match_driver = true;
if (ret > 0 && !device->flags.enumeration_by_parent) {
@@ -2188,26 +2214,40 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
ret = device_attach(&device->dev);
if (ret < 0)
- return;
+ return 0;
if (device->pnp.type.platform_id || device->flags.enumeration_by_parent)
acpi_default_enumeration(device);
else
acpi_device_set_enumerated(device);
- ok:
- list_for_each_entry(child, &device->children, node)
- acpi_bus_attach(child, first_pass);
+ok:
+ acpi_dev_for_each_child(device, acpi_bus_attach, first_pass);
if (!skip && device->handler && device->handler->hotplug.notify_online)
device->handler->hotplug.notify_online(device);
+
+ return 0;
}
-static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
+static int acpi_dev_get_next_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
{
- struct acpi_device *adev;
+ struct acpi_device **adev_p = data;
+ struct acpi_device *adev = *adev_p;
- adev = acpi_bus_get_acpi_device(dep->consumer);
+ /*
+ * If we're passed a 'previous' consumer device then we need to skip
+ * any consumers until we meet the previous one, and then NULL @data
+ * so the next one can be returned.
+ */
+ if (adev) {
+ if (dep->consumer == adev->handle)
+ *adev_p = NULL;
+
+ return 0;
+ }
+
+ adev = acpi_get_acpi_dev(dep->consumer);
if (adev) {
*(struct acpi_device **)data = adev;
return 1;
@@ -2228,7 +2268,7 @@ static void acpi_scan_clear_dep_fn(struct work_struct *work)
cdw = container_of(work, struct acpi_scan_clear_dep_work, work);
acpi_scan_lock_acquire();
- acpi_bus_attach(cdw->adev, true);
+ acpi_bus_attach(cdw->adev, (void *)true);
acpi_scan_lock_release();
acpi_dev_put(cdw->adev);
@@ -2260,7 +2300,7 @@ static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
{
- struct acpi_device *adev = acpi_bus_get_acpi_device(dep->consumer);
+ struct acpi_device *adev = acpi_get_acpi_dev(dep->consumer);
if (adev) {
adev->dep_unmet--;
@@ -2319,25 +2359,49 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)
EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
/**
- * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
+ * acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration
+ * @device: Pointer to the &struct acpi_device to check
+ *
+ * Check if the device is present and has no unmet dependencies.
+ *
+ * Return true if the device is ready for enumeratino. Otherwise, return false.
+ */
+bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
+{
+ if (device->flags.honor_deps && device->dep_unmet)
+ return false;
+
+ return acpi_device_is_present(device);
+}
+EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
+
+/**
+ * acpi_dev_get_next_consumer_dev - Return the next adev dependent on @supplier
* @supplier: Pointer to the dependee device
+ * @start: Pointer to the current dependent device
*
- * Returns the first &struct acpi_device which declares itself dependent on
+ * Returns the next &struct acpi_device which declares itself dependent on
* @supplier via the _DEP buffer, parsed from the acpi_dep_list.
*
- * The caller is responsible for putting the reference to adev when it is no
- * longer needed.
+ * If the returned adev is not passed as @start to this function, the caller is
+ * responsible for putting the reference to adev when it is no longer needed.
*/
-struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier)
+struct acpi_device *acpi_dev_get_next_consumer_dev(struct acpi_device *supplier,
+ struct acpi_device *start)
{
- struct acpi_device *adev = NULL;
+ struct acpi_device *adev = start;
acpi_walk_dep_device_list(supplier->handle,
- acpi_dev_get_first_consumer_dev_cb, &adev);
+ acpi_dev_get_next_consumer_dev_cb, &adev);
+
+ acpi_dev_put(start);
+
+ if (adev == start)
+ return NULL;
return adev;
}
-EXPORT_SYMBOL_GPL(acpi_dev_get_first_consumer_dev);
+EXPORT_SYMBOL_GPL(acpi_dev_get_next_consumer_dev);
/**
* acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
@@ -2369,7 +2433,7 @@ int acpi_bus_scan(acpi_handle handle)
if (!device)
return -ENODEV;
- acpi_bus_attach(device, true);
+ acpi_bus_attach(device, (void *)true);
if (!acpi_bus_scan_second_pass)
return 0;
@@ -2383,25 +2447,17 @@ int acpi_bus_scan(acpi_handle handle)
acpi_bus_check_add_2, NULL, NULL,
(void **)&device);
- acpi_bus_attach(device, false);
+ acpi_bus_attach(device, NULL);
return 0;
}
EXPORT_SYMBOL(acpi_bus_scan);
-/**
- * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
- * @adev: Root of the ACPI namespace scope to walk.
- *
- * Must be called under acpi_scan_lock.
- */
-void acpi_bus_trim(struct acpi_device *adev)
+static int acpi_bus_trim_one(struct acpi_device *adev, void *not_used)
{
struct acpi_scan_handler *handler = adev->handler;
- struct acpi_device *child;
- list_for_each_entry_reverse(child, &adev->children, node)
- acpi_bus_trim(child);
+ acpi_dev_for_each_child_reverse(adev, acpi_bus_trim_one, NULL);
adev->flags.match_driver = false;
if (handler) {
@@ -2419,6 +2475,19 @@ void acpi_bus_trim(struct acpi_device *adev)
acpi_device_set_power(adev, ACPI_STATE_D3_COLD);
adev->flags.initialized = false;
acpi_device_clear_enumerated(adev);
+
+ return 0;
+}
+
+/**
+ * acpi_bus_trim - Detach scan handlers and drivers from ACPI device objects.
+ * @adev: Root of the ACPI namespace scope to walk.
+ *
+ * Must be called under acpi_scan_lock.
+ */
+void acpi_bus_trim(struct acpi_device *adev)
+{
+ acpi_bus_trim_one(adev, NULL);
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
@@ -2436,42 +2505,33 @@ int acpi_bus_register_early_device(int type)
}
EXPORT_SYMBOL_GPL(acpi_bus_register_early_device);
-static int acpi_bus_scan_fixed(void)
+static void acpi_bus_scan_fixed(void)
{
- int result = 0;
-
- /*
- * Enumerate all fixed-feature devices.
- */
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, false);
- if (result)
- return result;
-
- device->flags.match_driver = true;
- result = device_attach(&device->dev);
- if (result < 0)
- return result;
-
- device_init_wakeup(&device->dev, true);
+ struct acpi_device *adev = NULL;
+
+ acpi_add_single_object(&adev, NULL, ACPI_BUS_TYPE_POWER_BUTTON,
+ false);
+ if (adev) {
+ adev->flags.match_driver = true;
+ if (device_attach(&adev->dev) >= 0)
+ device_init_wakeup(&adev->dev, true);
+ else
+ dev_dbg(&adev->dev, "No driver\n");
+ }
}
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, false);
- if (result)
- return result;
-
- device->flags.match_driver = true;
- result = device_attach(&device->dev);
+ struct acpi_device *adev = NULL;
+
+ acpi_add_single_object(&adev, NULL, ACPI_BUS_TYPE_SLEEP_BUTTON,
+ false);
+ if (adev) {
+ adev->flags.match_driver = true;
+ if (device_attach(&adev->dev) < 0)
+ dev_dbg(&adev->dev, "No driver\n");
+ }
}
-
- return result < 0 ? result : 0;
}
static void __init acpi_get_spcr_uart_addr(void)
@@ -2492,9 +2552,8 @@ static void __init acpi_get_spcr_uart_addr(void)
static bool acpi_scan_initialized;
-int __init acpi_scan_init(void)
+void __init acpi_scan_init(void)
{
- int result;
acpi_status status;
struct acpi_table_stao *stao_ptr;
@@ -2544,33 +2603,23 @@ int __init acpi_scan_init(void)
/*
* Enumerate devices in the ACPI namespace.
*/
- result = acpi_bus_scan(ACPI_ROOT_OBJECT);
- if (result)
- goto out;
+ if (acpi_bus_scan(ACPI_ROOT_OBJECT))
+ goto unlock;
- result = acpi_bus_get_device(ACPI_ROOT_OBJECT, &acpi_root);
- if (result)
- goto out;
+ acpi_root = acpi_fetch_acpi_dev(ACPI_ROOT_OBJECT);
+ if (!acpi_root)
+ goto unlock;
/* Fixed feature devices do not exist on HW-reduced platform */
- if (!acpi_gbl_reduced_hardware) {
- result = acpi_bus_scan_fixed();
- if (result) {
- acpi_detach_data(acpi_root->handle,
- acpi_scan_drop_device);
- acpi_device_del(acpi_root);
- acpi_bus_put_acpi_device(acpi_root);
- goto out;
- }
- }
+ if (!acpi_gbl_reduced_hardware)
+ acpi_bus_scan_fixed();
acpi_turn_off_unused_power_resources();
acpi_scan_initialized = true;
- out:
+unlock:
mutex_unlock(&acpi_scan_lock);
- return result;
}
static struct acpi_probe_entry *ape;