*/
static u64 spcr_uart_addr;
---struct acpi_dep_data {
--- struct list_head node;
--- acpi_handle supplier;
--- acpi_handle consumer;
---};
---
void acpi_scan_lock_acquire(void)
{
mutex_lock(&acpi_scan_lock);
return handle_to_device(handle, get_acpi_device);
}
---void acpi_bus_put_acpi_device(struct acpi_device *adev)
---{
--- acpi_dev_put(adev);
---}
---
static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id)
{
struct acpi_device_bus_id *acpi_device_bus_id;
return 0;
}
---int acpi_device_add(struct acpi_device *device,
--- void (*release)(struct device *))
+++static int acpi_tie_acpi_dev(struct acpi_device *adev)
{
--- struct acpi_device_bus_id *acpi_device_bus_id;
--- int result;
+++ acpi_handle handle = adev->handle;
+++ acpi_status status;
--- if (device->handle) {
--- acpi_status status;
+++ if (!handle)
+++ return 0;
--- status = acpi_attach_data(device->handle, acpi_scan_drop_device,
--- device);
--- if (ACPI_FAILURE(status)) {
--- acpi_handle_err(device->handle,
--- "Unable to attach device data\n");
--- return -ENODEV;
--- }
+++ status = acpi_attach_data(handle, acpi_scan_drop_device, adev);
+++ if (ACPI_FAILURE(status)) {
+++ acpi_handle_err(handle, "Unable to attach device data\n");
+++ return -ENODEV;
}
+++ return 0;
+++}
+++
+++static int __acpi_device_add(struct acpi_device *device,
+++ void (*release)(struct device *))
+++{
+++ struct acpi_device_bus_id *acpi_device_bus_id;
+++ int result;
+++
/*
* Linkage
* -------
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
-------------------------------------------------------------------------- */
device_initialize(&device->dev);
dev_set_uevent_suppress(&device->dev, true);
acpi_init_coherency(device);
--- /* Assume there are unmet deps to start with. */
--- device->dep_unmet = 1;
+++}
+++
+++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)
+++ adev->dep_unmet++;
+++ }
}
void acpi_device_add_finalize(struct acpi_device *device)
}
static int acpi_add_single_object(struct acpi_device **child,
--- acpi_handle handle, int type)
+++ acpi_handle handle, int type, bool dep_init)
{
struct acpi_device *device;
+++ bool release_dep_lock = false;
int result;
device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
* acpi_bus_get_status() and use its quirk handling. Note that
* this must be done before the get power-/wakeup_dev-flags calls.
*/
--- if (type == ACPI_BUS_TYPE_DEVICE || type == ACPI_BUS_TYPE_PROCESSOR)
+++ if (type == ACPI_BUS_TYPE_DEVICE || type == ACPI_BUS_TYPE_PROCESSOR) {
+++ if (dep_init) {
+++ mutex_lock(&acpi_dep_list_lock);
+++ /*
+++ * Hold the lock until the acpi_tie_acpi_dev() call
+++ * below to prevent concurrent acpi_scan_clear_dep()
+++ * from deleting a dependency list entry without
+++ * updating dep_unmet for the device.
+++ */
+++ release_dep_lock = true;
+++ acpi_scan_dep_init(device);
+++ }
acpi_scan_init_status(device);
+++ }
acpi_bus_get_power_flags(device);
acpi_bus_get_wakeup_device_flags(device);
--- result = acpi_device_add(device, acpi_device_release);
+++ result = acpi_tie_acpi_dev(device);
+++
+++ if (release_dep_lock)
+++ mutex_unlock(&acpi_dep_list_lock);
+++
+++ if (!result)
+++ result = __acpi_device_add(device, acpi_device_release);
+++
if (result) {
acpi_device_release(&device->dev);
return result;
return count;
}
---static void acpi_scan_dep_init(struct acpi_device *adev)
---{
--- struct acpi_dep_data *dep;
---
--- adev->dep_unmet = 0;
---
--- mutex_lock(&acpi_dep_list_lock);
---
--- list_for_each_entry(dep, &acpi_dep_list, node) {
--- if (dep->consumer == adev->handle)
--- adev->dep_unmet++;
--- }
---
--- mutex_unlock(&acpi_dep_list_lock);
---}
---
static bool acpi_bus_scan_second_pass;
static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep,
return AE_OK;
}
--- acpi_add_single_object(&device, handle, type);
--- if (!device)
--- return AE_CTRL_DEPTH;
---
--- acpi_scan_init_hotplug(device);
/*
* If check_dep is true at this point, the device has no dependencies,
* or the creation of the device object would have been postponed above.
*/
--- if (check_dep)
--- device->dep_unmet = 0;
--- else
--- acpi_scan_dep_init(device);
+++ acpi_add_single_object(&device, handle, type, !check_dep);
+++ if (!device)
+++ return AE_CTRL_DEPTH;
+++
+++ acpi_scan_init_hotplug(device);
out:
if (!*adev_p)
device->handler->hotplug.notify_online(device);
}
---void acpi_walk_dep_device_list(acpi_handle handle)
+++static int acpi_dev_get_first_consumer_dev_cb(struct acpi_dep_data *dep, void *data)
{
--- struct acpi_dep_data *dep, *tmp;
struct acpi_device *adev;
+++ adev = acpi_bus_get_acpi_device(dep->consumer);
+++ if (adev) {
+++ *(struct acpi_device **)data = adev;
+++ return 1;
+++ }
+++ /* Continue parsing if the device object is not present. */
+++ return 0;
+++}
+++
+++struct acpi_scan_clear_dep_work {
+++ struct work_struct work;
+++ struct acpi_device *adev;
+++};
+++
+++static void acpi_scan_clear_dep_fn(struct work_struct *work)
+++{
+++ struct acpi_scan_clear_dep_work *cdw;
+++
+++ cdw = container_of(work, struct acpi_scan_clear_dep_work, work);
+++
+++ acpi_scan_lock_acquire();
+++ acpi_bus_attach(cdw->adev, true);
+++ acpi_scan_lock_release();
+++
+++ acpi_dev_put(cdw->adev);
+++ kfree(cdw);
+++}
+++
+++static bool acpi_scan_clear_dep_queue(struct acpi_device *adev)
+++{
+++ struct acpi_scan_clear_dep_work *cdw;
+++
+++ if (adev->dep_unmet)
+++ return false;
+++
+++ cdw = kmalloc(sizeof(*cdw), GFP_KERNEL);
+++ if (!cdw)
+++ return false;
+++
+++ cdw->adev = adev;
+++ INIT_WORK(&cdw->work, acpi_scan_clear_dep_fn);
+++ /*
+++ * Since the work function may block on the lock until the entire
+++ * initial enumeration of devices is complete, put it into the unbound
+++ * workqueue.
+++ */
+++ queue_work(system_unbound_wq, &cdw->work);
+++
+++ return true;
+++}
+++
+++static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
+++{
+++ struct acpi_device *adev = acpi_bus_get_acpi_device(dep->consumer);
+++
+++ if (adev) {
+++ adev->dep_unmet--;
+++ if (!acpi_scan_clear_dep_queue(adev))
+++ acpi_dev_put(adev);
+++ }
+++
+++ list_del(&dep->node);
+++ kfree(dep);
+++
+++ return 0;
+++}
+++
+++/**
+++ * acpi_walk_dep_device_list - Apply a callback to every entry in acpi_dep_list
+++ * @handle: The ACPI handle of the supplier device
+++ * @callback: Pointer to the callback function to apply
+++ * @data: Pointer to some data to pass to the callback
+++ *
+++ * The return value of the callback determines this function's behaviour. If 0
+++ * is returned we continue to iterate over acpi_dep_list. If a positive value
+++ * is returned then the loop is broken but this function returns 0. If a
+++ * negative value is returned by the callback then the loop is broken and that
+++ * value is returned as the final error.
+++ */
+++static int acpi_walk_dep_device_list(acpi_handle handle,
+++ int (*callback)(struct acpi_dep_data *, void *),
+++ void *data)
+++{
+++ struct acpi_dep_data *dep, *tmp;
+++ int ret = 0;
+++
mutex_lock(&acpi_dep_list_lock);
list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) {
if (dep->supplier == handle) {
--- acpi_bus_get_device(dep->consumer, &adev);
---
--- if (adev) {
--- adev->dep_unmet--;
--- if (!adev->dep_unmet)
--- acpi_bus_attach(adev, true);
--- }
---
--- list_del(&dep->node);
--- kfree(dep);
+++ ret = callback(dep, data);
+++ if (ret)
+++ break;
}
}
mutex_unlock(&acpi_dep_list_lock);
+++
+++ return ret > 0 ? 0 : ret;
+++}
+++
+++/**
+++ * acpi_dev_clear_dependencies - Inform consumers that the device is now active
+++ * @supplier: Pointer to the supplier &struct acpi_device
+++ *
+++ * Clear dependencies on the given device.
+++ */
+++void acpi_dev_clear_dependencies(struct acpi_device *supplier)
+++{
+++ acpi_walk_dep_device_list(supplier->handle, acpi_scan_clear_dep, NULL);
+++}
+++EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
+++
+++/**
+++ * acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
+++ * @supplier: Pointer to the dependee device
+++ *
+++ * Returns the first &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.
+++ */
+++struct acpi_device *acpi_dev_get_first_consumer_dev(struct acpi_device *supplier)
+++{
+++ struct acpi_device *adev = NULL;
+++
+++ acpi_walk_dep_device_list(supplier->handle,
+++ acpi_dev_get_first_consumer_dev_cb, &adev);
+++
+++ return adev;
}
---EXPORT_SYMBOL_GPL(acpi_walk_dep_device_list);
+++EXPORT_SYMBOL_GPL(acpi_dev_get_first_consumer_dev);
/**
* acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
struct acpi_device *device = NULL;
int result;
--- result = acpi_add_single_object(&device, NULL, type);
+++ result = acpi_add_single_object(&device, NULL, type, false);
if (result)
return result;
struct acpi_device *device = NULL;
result = acpi_add_single_object(&device, NULL,
--- ACPI_BUS_TYPE_POWER_BUTTON);
+++ ACPI_BUS_TYPE_POWER_BUTTON, false);
if (result)
return result;
struct acpi_device *device = NULL;
result = acpi_add_single_object(&device, NULL,
--- ACPI_BUS_TYPE_SLEEP_BUTTON);
+++ ACPI_BUS_TYPE_SLEEP_BUTTON, false);
if (result)
return result;
}
}
- - acpi_turn_off_unused_power_resources(true);
+ + acpi_turn_off_unused_power_resources();
acpi_scan_initialized = true;
return count;
}
---struct acpi_table_events_work {
--- struct work_struct work;
--- void *table;
--- u32 event;
---};
---
static void acpi_table_events_fn(struct work_struct *work)
{
--- struct acpi_table_events_work *tew;
+++ acpi_scan_lock_acquire();
+++ acpi_bus_scan(ACPI_ROOT_OBJECT);
+++ acpi_scan_lock_release();
--- tew = container_of(work, struct acpi_table_events_work, work);
---
--- if (tew->event == ACPI_TABLE_EVENT_LOAD) {
--- acpi_scan_lock_acquire();
--- acpi_bus_scan(ACPI_ROOT_OBJECT);
--- acpi_scan_lock_release();
--- }
---
--- kfree(tew);
+++ kfree(work);
}
---void acpi_scan_table_handler(u32 event, void *table, void *context)
+++void acpi_scan_table_notify(void)
{
--- struct acpi_table_events_work *tew;
+++ struct work_struct *work;
if (!acpi_scan_initialized)
return;
--- if (event != ACPI_TABLE_EVENT_LOAD)
--- return;
---
--- tew = kmalloc(sizeof(*tew), GFP_KERNEL);
--- if (!tew)
+++ work = kmalloc(sizeof(*work), GFP_KERNEL);
+++ if (!work)
return;
--- INIT_WORK(&tew->work, acpi_table_events_fn);
--- tew->table = table;
--- tew->event = event;
---
--- schedule_work(&tew->work);
+++ INIT_WORK(work, acpi_table_events_fn);
+++ schedule_work(work);
}
int acpi_reconfig_notifier_register(struct notifier_block *nb)