Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c41b3810 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ACPI and power management fixes from Rafael Wysocki:

 - Fixes for blackfin and microblaze build problems introduced by the
   removal of global pm_idle.  From Lars-Peter Clausen.

 - OPP core build fix from Shawn Guo.

 - Error condition check fix for the new imx6q-cpufreq driver from Wei
   Yongjun.

 - Fix for an AER driver crash related to the lack of APEI
   initialization for acpi=off.  From Rafael J Wysocki.

 - Fix for a USB breakage on Thinkpad T430 related to ACPI power
   resources and PCI wakeup from Rafael J.  Wysocki.

* tag 'pm+acpi-fixes-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / PM: Take unusual configurations of power resources into account
  imx6q-cpufreq: fix return value check in imx6q_cpufreq_probe()
  PM / OPP: fix condition for empty of_init_opp_table()
  ACPI / APEI: Fix crash in apei_hest_parse() for acpi=off
  microblaze idle: Fix compile error
  blackfin idle: Fix compile error
parents 556f12f6 43838220
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -80,12 +80,10 @@ void cpu_idle(void)
		if (cpu_is_offline(smp_processor_id()))
			cpu_die();
#endif
		if (!idle)
			idle = default_idle;
		tick_nohz_idle_enter();
		rcu_idle_enter();
		while (!need_resched())
			idle();
			default_idle();
		rcu_idle_exit();
		tick_nohz_idle_exit();
		preempt_enable_no_resched();
+1 −4
Original line number Diff line number Diff line
@@ -97,13 +97,10 @@ void cpu_idle(void)

	/* endless idle loop with no priority at all */
	while (1) {
		if (!idle)
			idle = default_idle;

		tick_nohz_idle_enter();
		rcu_idle_enter();
		while (!need_resched())
			idle();
			default_idle();
		rcu_idle_exit();
		tick_nohz_idle_exit();

+1 −4
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ int apei_hest_parse(apei_hest_func_t func, void *data)
	struct acpi_hest_header *hest_hdr;
	int i, rc, len;

	if (hest_disable)
	if (hest_disable || !hest_tab)
		return -EINVAL;

	hest_hdr = (struct acpi_hest_header *)(hest_tab + 1);
@@ -216,9 +216,6 @@ void __init acpi_hest_init(void)
		return;
	}

	if (acpi_disabled)
		goto err;

	status = acpi_get_table(ACPI_SIG_HEST, 0,
				(struct acpi_table_header **)&hest_tab);
	if (status == AE_NOT_FOUND)
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
				 struct list_head *list);
int acpi_add_power_resource(acpi_handle handle);
void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
int acpi_power_min_system_level(struct list_head *list);
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level);
int acpi_device_sleep_wake(struct acpi_device *dev,
                           int enable, int sleep_state, int dev_state);
int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
+85 −27
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ struct acpi_power_resource {
	u32 system_level;
	u32 order;
	unsigned int ref_count;
	bool wakeup_enabled;
	struct mutex resource_lock;
};

@@ -272,11 +273,9 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
	return 0;
}

static int acpi_power_on(struct acpi_power_resource *resource)
static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
{
	int result = 0;;

	mutex_lock(&resource->resource_lock);
	int result = 0;

	if (resource->ref_count++) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -293,9 +292,16 @@ static int acpi_power_on(struct acpi_power_resource *resource)
				schedule_work(&dep->work);
		}
	}
	return result;
}

	mutex_unlock(&resource->resource_lock);
static int acpi_power_on(struct acpi_power_resource *resource)
{
	int result;

	mutex_lock(&resource->resource_lock);
	result = acpi_power_on_unlocked(resource);
	mutex_unlock(&resource->resource_lock);
	return result;
}

@@ -313,17 +319,15 @@ static int __acpi_power_off(struct acpi_power_resource *resource)
	return 0;
}

static int acpi_power_off(struct acpi_power_resource *resource)
static int acpi_power_off_unlocked(struct acpi_power_resource *resource)
{
	int result = 0;

	mutex_lock(&resource->resource_lock);

	if (!resource->ref_count) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Power resource [%s] already off",
				  resource->name));
		goto unlock;
		return 0;
	}

	if (--resource->ref_count) {
@@ -335,10 +339,16 @@ static int acpi_power_off(struct acpi_power_resource *resource)
		if (result)
			resource->ref_count++;
	}
	return result;
}

 unlock:
	mutex_unlock(&resource->resource_lock);
static int acpi_power_off(struct acpi_power_resource *resource)
{
	int result;

	mutex_lock(&resource->resource_lock);
	result = acpi_power_off_unlocked(resource);
	mutex_unlock(&resource->resource_lock);
	return result;
}

@@ -521,18 +531,35 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
	}
}

int acpi_power_min_system_level(struct list_head *list)
int acpi_power_wakeup_list_init(struct list_head *list, int *system_level_p)
{
	struct acpi_power_resource_entry *entry;
	int system_level = 5;

	list_for_each_entry(entry, list, node) {
		struct acpi_power_resource *resource = entry->resource;
		acpi_handle handle = resource->device.handle;
		int result;
		int state;

		mutex_lock(&resource->resource_lock);

		result = acpi_power_get_state(handle, &state);
		if (result) {
			mutex_unlock(&resource->resource_lock);
			return result;
		}
		if (state == ACPI_POWER_RESOURCE_STATE_ON) {
			resource->ref_count++;
			resource->wakeup_enabled = true;
		}
		if (system_level > resource->system_level)
			system_level = resource->system_level;

		mutex_unlock(&resource->resource_lock);
	}
	return system_level;
	*system_level_p = system_level;
	return 0;
}

/* --------------------------------------------------------------------------
@@ -610,6 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
 */
int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
{
	struct acpi_power_resource_entry *entry;
	int err = 0;

	if (!dev || !dev->wakeup.flags.valid)
@@ -620,17 +648,31 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
	if (dev->wakeup.prepare_count++)
		goto out;

	err = acpi_power_on_list(&dev->wakeup.resources);
	list_for_each_entry(entry, &dev->wakeup.resources, node) {
		struct acpi_power_resource *resource = entry->resource;

		mutex_lock(&resource->resource_lock);

		if (!resource->wakeup_enabled) {
			err = acpi_power_on_unlocked(resource);
			if (!err)
				resource->wakeup_enabled = true;
		}

		mutex_unlock(&resource->resource_lock);

		if (err) {
		dev_err(&dev->dev, "Cannot turn wakeup power resources on\n");
			dev_err(&dev->dev,
				"Cannot turn wakeup power resources on\n");
			dev->wakeup.flags.valid = 0;
	} else {
			goto out;
		}
	}
	/*
	 * Passing 3 as the third argument below means the device may be
	 * put into arbitrary power state afterward.
	 */
	err = acpi_device_sleep_wake(dev, 1, sleep_state, 3);
	}
	if (err)
		dev->wakeup.prepare_count = 0;

@@ -647,6 +689,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
 */
int acpi_disable_wakeup_device_power(struct acpi_device *dev)
{
	struct acpi_power_resource_entry *entry;
	int err = 0;

	if (!dev || !dev->wakeup.flags.valid)
@@ -668,10 +711,25 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
	if (err)
		goto out;

	err = acpi_power_off_list(&dev->wakeup.resources);
	list_for_each_entry(entry, &dev->wakeup.resources, node) {
		struct acpi_power_resource *resource = entry->resource;

		mutex_lock(&resource->resource_lock);

		if (resource->wakeup_enabled) {
			err = acpi_power_off_unlocked(resource);
			if (!err)
				resource->wakeup_enabled = false;
		}

		mutex_unlock(&resource->resource_lock);

		if (err) {
		dev_err(&dev->dev, "Cannot turn wakeup power resources off\n");
			dev_err(&dev->dev,
				"Cannot turn wakeup power resources off\n");
			dev->wakeup.flags.valid = 0;
			break;
		}
	}

 out:
Loading