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

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

 - intel_pstate fix for misbehavior after system resume if sysfs
   attributes are set in a specific way before the corresponding suspend
   from Dirk Brandewie.

 - A recent intel_pstate fix has no effect if unsigned long is 32-bit,
   so fix it up to cover that case as well.

 - The s3c64xx cpufreq driver was not updated when the index field of
   struct cpufreq_frequency_table was replaced with driver_data, so
   update it now.  From Charles Keepax.

 - The Kconfig help text for ACPI_BUTTON still refers to
   /proc/acpi/event that has been dropped recently, so modify it to
   remove that reference.  From Krzysztof Mazur.

 - A Lan Tianyu's change adds a missing mutex unlock to an error code
   path in acpi_resume_power_resources().

 - Some code related to ACPI power resources, whose very purpose is
   questionable to put it lightly, turns out to cause problems to happen
   during testing on real systems, so remove it completely (we may
   revisit that in the future if there's a compelling enough reason).
   From Rafael J Wysocki and Aaron Lu.

* tag 'pm+acpi-3.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / PM: Drop two functions that are not used any more
  ATA / ACPI: remove power dependent device handling
  cpufreq: s3c64xx: Rename index to driver_data
  ACPI / power: Drop automaitc resume of power resource dependent devices
  intel_pstate: Fix type mismatch warning
  cpufreq / intel_pstate: Fix max_perf_pct on resume
  ACPI: remove /proc/acpi/event from ACPI_BUTTON help
  ACPI / power: Release resource_lock after acpi_power_get_state() return error
parents 9219cec5 981984cb
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -123,9 +123,9 @@ config ACPI_BUTTON
	default y
	help
	  This driver handles events on the power, sleep, and lid buttons.
	  A daemon reads /proc/acpi/event and perform user-defined actions
	  such as shutting down the system.  This is necessary for
	  software-controlled poweroff.
	  A daemon reads events from input devices or via netlink and
	  performs user-defined actions such as shutting down the system.
	  This is necessary for software-controlled poweroff.

	  To compile this driver as a module, choose M here:
	  the module will be called button.
+0 −56
Original line number Diff line number Diff line
@@ -1025,60 +1025,4 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
	}
}
EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);

/**
 * acpi_dev_pm_add_dependent - Add physical device depending for PM.
 * @handle: Handle of ACPI device node.
 * @depdev: Device depending on that node for PM.
 */
void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev)
{
	struct acpi_device_physical_node *dep;
	struct acpi_device *adev;

	if (!depdev || acpi_bus_get_device(handle, &adev))
		return;

	mutex_lock(&adev->physical_node_lock);

	list_for_each_entry(dep, &adev->power_dependent, node)
		if (dep->dev == depdev)
			goto out;

	dep = kzalloc(sizeof(*dep), GFP_KERNEL);
	if (dep) {
		dep->dev = depdev;
		list_add_tail(&dep->node, &adev->power_dependent);
	}

 out:
	mutex_unlock(&adev->physical_node_lock);
}
EXPORT_SYMBOL_GPL(acpi_dev_pm_add_dependent);

/**
 * acpi_dev_pm_remove_dependent - Remove physical device depending for PM.
 * @handle: Handle of ACPI device node.
 * @depdev: Device depending on that node for PM.
 */
void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev)
{
	struct acpi_device_physical_node *dep;
	struct acpi_device *adev;

	if (!depdev || acpi_bus_get_device(handle, &adev))
		return;

	mutex_lock(&adev->physical_node_lock);

	list_for_each_entry(dep, &adev->power_dependent, node)
		if (dep->dev == depdev) {
			list_del(&dep->node);
			kfree(dep);
			break;
		}

	mutex_unlock(&adev->physical_node_lock);
}
EXPORT_SYMBOL_GPL(acpi_dev_pm_remove_dependent);
#endif /* CONFIG_PM */
+4 −100
Original line number Diff line number Diff line
@@ -59,16 +59,9 @@ ACPI_MODULE_NAME("power");
#define ACPI_POWER_RESOURCE_STATE_ON	0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF

struct acpi_power_dependent_device {
	struct list_head node;
	struct acpi_device *adev;
	struct work_struct work;
};

struct acpi_power_resource {
	struct acpi_device device;
	struct list_head list_node;
	struct list_head dependent;
	char *name;
	u32 system_level;
	u32 order;
@@ -233,32 +226,6 @@ static int acpi_power_get_list_state(struct list_head *list, int *state)
	return 0;
}

static void acpi_power_resume_dependent(struct work_struct *work)
{
	struct acpi_power_dependent_device *dep;
	struct acpi_device_physical_node *pn;
	struct acpi_device *adev;
	int state;

	dep = container_of(work, struct acpi_power_dependent_device, work);
	adev = dep->adev;
	if (acpi_power_get_inferred_state(adev, &state))
		return;

	if (state > ACPI_STATE_D0)
		return;

	mutex_lock(&adev->physical_node_lock);

	list_for_each_entry(pn, &adev->physical_node_list, node)
		pm_request_resume(pn->dev);

	list_for_each_entry(pn, &adev->power_dependent, node)
		pm_request_resume(pn->dev);

	mutex_unlock(&adev->physical_node_lock);
}

static int __acpi_power_on(struct acpi_power_resource *resource)
{
	acpi_status status = AE_OK;
@@ -283,14 +250,8 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
				  resource->name));
	} else {
		result = __acpi_power_on(resource);
		if (result) {
		if (result)
			resource->ref_count--;
		} else {
			struct acpi_power_dependent_device *dep;

			list_for_each_entry(dep, &resource->dependent, node)
				schedule_work(&dep->work);
		}
	}
	return result;
}
@@ -390,52 +351,6 @@ static int acpi_power_on_list(struct list_head *list)
	return result;
}

static void acpi_power_add_dependent(struct acpi_power_resource *resource,
				     struct acpi_device *adev)
{
	struct acpi_power_dependent_device *dep;

	mutex_lock(&resource->resource_lock);

	list_for_each_entry(dep, &resource->dependent, node)
		if (dep->adev == adev)
			goto out;

	dep = kzalloc(sizeof(*dep), GFP_KERNEL);
	if (!dep)
		goto out;

	dep->adev = adev;
	INIT_WORK(&dep->work, acpi_power_resume_dependent);
	list_add_tail(&dep->node, &resource->dependent);

 out:
	mutex_unlock(&resource->resource_lock);
}

static void acpi_power_remove_dependent(struct acpi_power_resource *resource,
					struct acpi_device *adev)
{
	struct acpi_power_dependent_device *dep;
	struct work_struct *work = NULL;

	mutex_lock(&resource->resource_lock);

	list_for_each_entry(dep, &resource->dependent, node)
		if (dep->adev == adev) {
			list_del(&dep->node);
			work = &dep->work;
			break;
		}

	mutex_unlock(&resource->resource_lock);

	if (work) {
		cancel_work_sync(work);
		kfree(dep);
	}
}

static struct attribute *attrs[] = {
	NULL,
};
@@ -524,8 +439,6 @@ static void acpi_power_expose_hide(struct acpi_device *adev,

void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
{
	struct acpi_device_power_state *ps;
	struct acpi_power_resource_entry *entry;
	int state;

	if (adev->wakeup.flags.valid)
@@ -535,16 +448,6 @@ void acpi_power_add_remove_device(struct acpi_device *adev, bool add)
	if (!adev->power.flags.power_resources)
		return;

	ps = &adev->power.states[ACPI_STATE_D0];
	list_for_each_entry(entry, &ps->resources, node) {
		struct acpi_power_resource *resource = entry->resource;

		if (add)
			acpi_power_add_dependent(resource, adev);
		else
			acpi_power_remove_dependent(resource, adev);
	}

	for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
		acpi_power_expose_hide(adev,
				       &adev->power.states[state].resources,
@@ -882,7 +785,6 @@ int acpi_add_power_resource(acpi_handle handle)
	acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
				ACPI_STA_DEFAULT);
	mutex_init(&resource->resource_lock);
	INIT_LIST_HEAD(&resource->dependent);
	INIT_LIST_HEAD(&resource->list_node);
	resource->name = device->pnp.bus_id;
	strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
@@ -936,8 +838,10 @@ void acpi_resume_power_resources(void)
		mutex_lock(&resource->resource_lock);

		result = acpi_power_get_state(resource->device.handle, &state);
		if (result)
		if (result) {
			mutex_unlock(&resource->resource_lock);
			continue;
		}

		if (state == ACPI_POWER_RESOURCE_STATE_OFF
		    && resource->ref_count) {
+0 −1
Original line number Diff line number Diff line
@@ -999,7 +999,6 @@ int acpi_device_add(struct acpi_device *device,
	INIT_LIST_HEAD(&device->wakeup_list);
	INIT_LIST_HEAD(&device->physical_node_list);
	mutex_init(&device->physical_node_lock);
	INIT_LIST_HEAD(&device->power_dependent);

	new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
	if (!new_bus_id) {
+0 −14
Original line number Diff line number Diff line
@@ -1035,17 +1035,3 @@ void ata_acpi_on_disable(struct ata_device *dev)
{
	ata_acpi_clear_gtf(dev);
}

void ata_scsi_acpi_bind(struct ata_device *dev)
{
	acpi_handle handle = ata_dev_acpi_handle(dev);
	if (handle)
		acpi_dev_pm_add_dependent(handle, &dev->sdev->sdev_gendev);
}

void ata_scsi_acpi_unbind(struct ata_device *dev)
{
	acpi_handle handle = ata_dev_acpi_handle(dev);
	if (handle)
		acpi_dev_pm_remove_dependent(handle, &dev->sdev->sdev_gendev);
}
Loading