ACPI and power management fixes for 3.12-rc6
- 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. / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABCAAGBQJSYZQiAAoJEILEb/54YlRxed8QAJxDNJ4sHEzahsEFREZWwUy6 KN6yLRFs80aplbiCdNyYQnp5RZ0QqEVq0Vwkur/pxk5j00XJWTMknKvJhiAlIaHd l1T1X0Oh3w4Z8h+0l49QaU0z5tHt+dAxzl4ArMlcQ3BQuKf5/8c+dIfNutkWpOWP xHIDjEV+Y+8JCQoP92we7BbJpBRqzC3AOr05iH0wUN/i4dZzfqEca6KxTBPSXAcX CbEBOXauG4BR4LyEQ2rlEt53FTp7XjZ9my1kKVH6LmtA+HiHeQmZMHTUf9dlaYAH 1n38ebeIHpskRYhu7nknto1S/mTVKxkzuSQ8TyKM+QOZz9x+WT/uiZjwbxINmxKk fLi8TdMdv+WwALAqI36AjgfxdTtQ8Fhs/jSOoCY3KqoE4LMUInq2izWy8ALTQCPm 8PhM2WiYPFt6qSCqaKLfbbYH3ou6t2PQZihRfqpGEaTatNvwL2AYgl5QhOhs90EV kYwZpfxodTNLnk4UfLGASjVEDRxgN7DUSrUvn0z7HmhbH/0YK3OVdLU0UQalAvfR eUKYO+aWXzGsJO/ym3qfHkehumReCM62ykf295ApYnt134oqGDe3+Ajgx53WPj/P ruIrfkmqDHCXjlVJ8f+UaZ/HXlDLcLrjlIVF1Dp0MKnl49pe+va4OmAxyImvTtFC gciZiW+n5uowNojt8yye =MV4Q -----END PGP SIGNATURE----- Merge tag 'pm+acpi-3.12-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm 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
This commit is contained in:
Коммит
797afdf708
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -3679,7 +3679,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
|
|||
if (!IS_ERR(sdev)) {
|
||||
dev->sdev = sdev;
|
||||
scsi_device_put(sdev);
|
||||
ata_scsi_acpi_bind(dev);
|
||||
} else {
|
||||
dev->sdev = NULL;
|
||||
}
|
||||
|
@ -3767,8 +3766,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
|
|||
struct scsi_device *sdev;
|
||||
unsigned long flags;
|
||||
|
||||
ata_scsi_acpi_unbind(dev);
|
||||
|
||||
/* Alas, we need to grab scan_mutex to ensure SCSI device
|
||||
* state doesn't change underneath us and thus
|
||||
* scsi_device_get() always succeeds. The mutex locking can
|
||||
|
|
|
@ -121,8 +121,6 @@ extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
|
|||
extern void ata_acpi_bind_port(struct ata_port *ap);
|
||||
extern void ata_acpi_bind_dev(struct ata_device *dev);
|
||||
extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev);
|
||||
extern void ata_scsi_acpi_bind(struct ata_device *dev);
|
||||
extern void ata_scsi_acpi_unbind(struct ata_device *dev);
|
||||
#else
|
||||
static inline void ata_acpi_dissociate(struct ata_host *host) { }
|
||||
static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
|
||||
|
@ -133,8 +131,6 @@ static inline void ata_acpi_set_state(struct ata_port *ap,
|
|||
pm_message_t state) { }
|
||||
static inline void ata_acpi_bind_port(struct ata_port *ap) {}
|
||||
static inline void ata_acpi_bind_dev(struct ata_device *dev) {}
|
||||
static inline void ata_scsi_acpi_bind(struct ata_device *dev) {}
|
||||
static inline void ata_scsi_acpi_unbind(struct ata_device *dev) {}
|
||||
#endif
|
||||
|
||||
/* libata-scsi.c */
|
||||
|
|
|
@ -383,6 +383,7 @@ static void intel_pstate_get_min_max(struct cpudata *cpu, int *min, int *max)
|
|||
static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
||||
{
|
||||
int max_perf, min_perf;
|
||||
u64 val;
|
||||
|
||||
intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
|
||||
|
||||
|
@ -394,11 +395,11 @@ static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
|
|||
trace_cpu_frequency(pstate * 100000, cpu->cpu);
|
||||
|
||||
cpu->pstate.current_pstate = pstate;
|
||||
val = pstate << 8;
|
||||
if (limits.no_turbo)
|
||||
wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8));
|
||||
else
|
||||
wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
|
||||
val |= (u64)1 << 32;
|
||||
|
||||
wrmsrl(MSR_IA32_PERF_CTL, val);
|
||||
}
|
||||
|
||||
static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps)
|
||||
|
@ -637,8 +638,8 @@ static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
|
|||
|
||||
static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int rc, min_pstate, max_pstate;
|
||||
struct cpudata *cpu;
|
||||
int rc;
|
||||
|
||||
rc = intel_pstate_init_cpu(policy->cpu);
|
||||
if (rc)
|
||||
|
@ -652,9 +653,8 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
|
|||
else
|
||||
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
||||
|
||||
intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate);
|
||||
policy->min = min_pstate * 100000;
|
||||
policy->max = max_pstate * 100000;
|
||||
policy->min = cpu->pstate.min_pstate * 100000;
|
||||
policy->max = cpu->pstate.turbo_pstate * 100000;
|
||||
|
||||
/* cpuinfo and default policy values */
|
||||
policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000;
|
||||
|
|
|
@ -166,7 +166,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
|
|||
if (freq->frequency == CPUFREQ_ENTRY_INVALID)
|
||||
continue;
|
||||
|
||||
dvfs = &s3c64xx_dvfs_table[freq->index];
|
||||
dvfs = &s3c64xx_dvfs_table[freq->driver_data];
|
||||
found = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
|
|
@ -311,7 +311,6 @@ struct acpi_device {
|
|||
unsigned int physical_node_count;
|
||||
struct list_head physical_node_list;
|
||||
struct mutex physical_node_lock;
|
||||
struct list_head power_dependent;
|
||||
void (*remove)(struct acpi_device *);
|
||||
};
|
||||
|
||||
|
@ -456,8 +455,6 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
|
|||
acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
|
||||
acpi_notify_handler handler);
|
||||
int acpi_pm_device_sleep_state(struct device *, int *, int);
|
||||
void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev);
|
||||
void acpi_dev_pm_remove_dependent(acpi_handle handle, struct device *depdev);
|
||||
#else
|
||||
static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
|
||||
acpi_notify_handler handler,
|
||||
|
@ -478,10 +475,6 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
|
|||
return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
|
||||
m : ACPI_STATE_D0;
|
||||
}
|
||||
static inline void acpi_dev_pm_add_dependent(acpi_handle handle,
|
||||
struct device *depdev) {}
|
||||
static inline void acpi_dev_pm_remove_dependent(acpi_handle handle,
|
||||
struct device *depdev) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
|
|
Загрузка…
Ссылка в новой задаче