Commit c8d9c367 authored by Hans de Goede's avatar Hans de Goede
Browse files

Merge remote-tracking branch 'linux-pm/acpi-scan' into review-hans

parents 6c8f2df3 23db673d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1627,7 +1627,7 @@ static int acpi_ec_add(struct acpi_device *device)
	WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);

	/* Reprobe devices depending on the EC */
	acpi_walk_dep_device_list(ec->handle);
	acpi_dev_clear_dependencies(device);

	acpi_handle_debug(ec->handle, "enumerated.\n");
	return 0;
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ static int chtdc_ti_pmic_opregion_probe(struct platform_device *pdev)
		return err;

	/* Re-enumerate devices depending on PMIC */
	acpi_walk_dep_device_list(ACPI_HANDLE(pdev->dev.parent));
	acpi_dev_clear_dependencies(ACPI_COMPANION(pdev->dev.parent));
	return 0;
}

+114 −50
Original line number Diff line number Diff line
@@ -47,12 +47,6 @@ static DEFINE_MUTEX(acpi_hp_context_lock);
 */
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);
@@ -1671,8 +1665,20 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
	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;

	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);
}

void acpi_device_add_finalize(struct acpi_device *device)
@@ -1688,7 +1694,7 @@ static void acpi_scan_init_status(struct acpi_device *adev)
}

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;
	int result;
@@ -1703,8 +1709,12 @@ static int acpi_add_single_object(struct acpi_device **child,
	 * 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)
			acpi_scan_dep_init(device);

		acpi_scan_init_status(device);
	}

	acpi_bus_get_power_flags(device);
	acpi_bus_get_wakeup_device_flags(device);
@@ -1886,22 +1896,6 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
	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,
@@ -1949,19 +1943,15 @@ 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)
@@ -2111,14 +2101,24 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
		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_device *adev;

	adev = acpi_bus_get_acpi_device(dep->consumer);
	if (!adev)
		/* If we don't find an adev then we want to continue parsing */
		return 0;

	*(struct acpi_device **)data = adev;

	return 1;
}

static int acpi_scan_clear_dep(struct acpi_dep_data *dep, void *data)
{
	struct acpi_dep_data *dep, *tmp;
	struct acpi_device *adev;

	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) {
@@ -2129,12 +2129,76 @@ void acpi_walk_dep_device_list(acpi_handle handle)

	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.
 */
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) {
			ret = callback(dep, data);
			if (ret)
				break;
		}
	}
	mutex_unlock(&acpi_dep_list_lock);

	return ret > 0 ? 0 : ret;
}
EXPORT_SYMBOL_GPL(acpi_walk_dep_device_list);

/**
 * 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_dev_get_first_consumer_dev);

/**
 * acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
 * @handle: Root of the namespace scope to scan.
@@ -2223,7 +2287,7 @@ int acpi_bus_register_early_device(int type)
	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;

@@ -2243,7 +2307,7 @@ static int acpi_bus_scan_fixed(void)
		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;

@@ -2259,7 +2323,7 @@ static int acpi_bus_scan_fixed(void)
		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;

+5 −5
Original line number Diff line number Diff line
@@ -1284,14 +1284,14 @@ static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
void acpi_gpiochip_add(struct gpio_chip *chip)
{
	struct acpi_gpio_chip *acpi_gpio;
	acpi_handle handle;
	struct acpi_device *adev;
	acpi_status status;

	if (!chip || !chip->parent)
		return;

	handle = ACPI_HANDLE(chip->parent);
	if (!handle)
	adev = ACPI_COMPANION(chip->parent);
	if (!adev)
		return;

	acpi_gpio = kzalloc(sizeof(*acpi_gpio), GFP_KERNEL);
@@ -1305,7 +1305,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
	INIT_LIST_HEAD(&acpi_gpio->events);
	INIT_LIST_HEAD(&acpi_gpio->deferred_req_irqs_list_entry);

	status = acpi_attach_data(handle, acpi_gpio_chip_dh, acpi_gpio);
	status = acpi_attach_data(adev->handle, acpi_gpio_chip_dh, acpi_gpio);
	if (ACPI_FAILURE(status)) {
		dev_err(chip->parent, "Failed to attach ACPI GPIO chip\n");
		kfree(acpi_gpio);
@@ -1314,7 +1314,7 @@ void acpi_gpiochip_add(struct gpio_chip *chip)

	acpi_gpiochip_request_regions(acpi_gpio);
	acpi_gpiochip_scan_gpios(acpi_gpio);
	acpi_walk_dep_device_list(handle);
	acpi_dev_clear_dependencies(adev);
}

void acpi_gpiochip_remove(struct gpio_chip *chip)
+4 −4
Original line number Diff line number Diff line
@@ -259,8 +259,8 @@ static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
 */
void i2c_acpi_register_devices(struct i2c_adapter *adap)
{
	struct acpi_device *adev;
	acpi_status status;
	acpi_handle handle;

	if (!has_acpi_companion(&adap->dev))
		return;
@@ -275,11 +275,11 @@ void i2c_acpi_register_devices(struct i2c_adapter *adap)
	if (!adap->dev.parent)
		return;

	handle = ACPI_HANDLE(adap->dev.parent);
	if (!handle)
	adev = ACPI_COMPANION(adap->dev.parent);
	if (!adev)
		return;

	acpi_walk_dep_device_list(handle);
	acpi_dev_clear_dependencies(adev);
}

static const struct acpi_device_id i2c_acpi_force_400khz_device_ids[] = {
Loading