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:
Linus Torvalds 2013-10-18 14:26:51 -07:00
commit 797afdf708
10 changed files with 15 additions and 196 deletions

View File

@ -123,9 +123,9 @@ config ACPI_BUTTON
default y default y
help help
This driver handles events on the power, sleep, and lid buttons. This driver handles events on the power, sleep, and lid buttons.
A daemon reads /proc/acpi/event and perform user-defined actions A daemon reads events from input devices or via netlink and
such as shutting down the system. This is necessary for performs user-defined actions such as shutting down the system.
software-controlled poweroff. This is necessary for software-controlled poweroff.
To compile this driver as a module, choose M here: To compile this driver as a module, choose M here:
the module will be called button. the module will be called button.

View File

@ -1025,60 +1025,4 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
} }
} }
EXPORT_SYMBOL_GPL(acpi_dev_pm_detach); 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 */ #endif /* CONFIG_PM */

View File

@ -59,16 +59,9 @@ ACPI_MODULE_NAME("power");
#define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF #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_power_resource {
struct acpi_device device; struct acpi_device device;
struct list_head list_node; struct list_head list_node;
struct list_head dependent;
char *name; char *name;
u32 system_level; u32 system_level;
u32 order; u32 order;
@ -233,32 +226,6 @@ static int acpi_power_get_list_state(struct list_head *list, int *state)
return 0; 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) static int __acpi_power_on(struct acpi_power_resource *resource)
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
@ -283,14 +250,8 @@ static int acpi_power_on_unlocked(struct acpi_power_resource *resource)
resource->name)); resource->name));
} else { } else {
result = __acpi_power_on(resource); result = __acpi_power_on(resource);
if (result) { if (result)
resource->ref_count--; resource->ref_count--;
} else {
struct acpi_power_dependent_device *dep;
list_for_each_entry(dep, &resource->dependent, node)
schedule_work(&dep->work);
}
} }
return result; return result;
} }
@ -390,52 +351,6 @@ static int acpi_power_on_list(struct list_head *list)
return result; 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[] = { static struct attribute *attrs[] = {
NULL, 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) 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; int state;
if (adev->wakeup.flags.valid) 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) if (!adev->power.flags.power_resources)
return; 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++) for (state = ACPI_STATE_D0; state <= ACPI_STATE_D3_HOT; state++)
acpi_power_expose_hide(adev, acpi_power_expose_hide(adev,
&adev->power.states[state].resources, &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_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
ACPI_STA_DEFAULT); ACPI_STA_DEFAULT);
mutex_init(&resource->resource_lock); mutex_init(&resource->resource_lock);
INIT_LIST_HEAD(&resource->dependent);
INIT_LIST_HEAD(&resource->list_node); INIT_LIST_HEAD(&resource->list_node);
resource->name = device->pnp.bus_id; resource->name = device->pnp.bus_id;
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
@ -936,8 +838,10 @@ void acpi_resume_power_resources(void)
mutex_lock(&resource->resource_lock); mutex_lock(&resource->resource_lock);
result = acpi_power_get_state(resource->device.handle, &state); result = acpi_power_get_state(resource->device.handle, &state);
if (result) if (result) {
mutex_unlock(&resource->resource_lock);
continue; continue;
}
if (state == ACPI_POWER_RESOURCE_STATE_OFF if (state == ACPI_POWER_RESOURCE_STATE_OFF
&& resource->ref_count) { && resource->ref_count) {

View File

@ -999,7 +999,6 @@ int acpi_device_add(struct acpi_device *device,
INIT_LIST_HEAD(&device->wakeup_list); INIT_LIST_HEAD(&device->wakeup_list);
INIT_LIST_HEAD(&device->physical_node_list); INIT_LIST_HEAD(&device->physical_node_list);
mutex_init(&device->physical_node_lock); mutex_init(&device->physical_node_lock);
INIT_LIST_HEAD(&device->power_dependent);
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
if (!new_bus_id) { if (!new_bus_id) {

View File

@ -1035,17 +1035,3 @@ void ata_acpi_on_disable(struct ata_device *dev)
{ {
ata_acpi_clear_gtf(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);
}

View File

@ -3679,7 +3679,6 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
if (!IS_ERR(sdev)) { if (!IS_ERR(sdev)) {
dev->sdev = sdev; dev->sdev = sdev;
scsi_device_put(sdev); scsi_device_put(sdev);
ata_scsi_acpi_bind(dev);
} else { } else {
dev->sdev = NULL; dev->sdev = NULL;
} }
@ -3767,8 +3766,6 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
struct scsi_device *sdev; struct scsi_device *sdev;
unsigned long flags; unsigned long flags;
ata_scsi_acpi_unbind(dev);
/* Alas, we need to grab scan_mutex to ensure SCSI device /* Alas, we need to grab scan_mutex to ensure SCSI device
* state doesn't change underneath us and thus * state doesn't change underneath us and thus
* scsi_device_get() always succeeds. The mutex locking can * scsi_device_get() always succeeds. The mutex locking can

View File

@ -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_port(struct ata_port *ap);
extern void ata_acpi_bind_dev(struct ata_device *dev); extern void ata_acpi_bind_dev(struct ata_device *dev);
extern acpi_handle ata_dev_acpi_handle(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 #else
static inline void ata_acpi_dissociate(struct ata_host *host) { } static inline void ata_acpi_dissociate(struct ata_host *host) { }
static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } 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) { } pm_message_t state) { }
static inline void ata_acpi_bind_port(struct ata_port *ap) {} 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_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 #endif
/* libata-scsi.c */ /* libata-scsi.c */

View File

@ -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) static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate)
{ {
int max_perf, min_perf; int max_perf, min_perf;
u64 val;
intel_pstate_get_min_max(cpu, &min_perf, &max_perf); 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); trace_cpu_frequency(pstate * 100000, cpu->cpu);
cpu->pstate.current_pstate = pstate; cpu->pstate.current_pstate = pstate;
val = pstate << 8;
if (limits.no_turbo) if (limits.no_turbo)
wrmsrl(MSR_IA32_PERF_CTL, BIT(32) | (pstate << 8)); val |= (u64)1 << 32;
else
wrmsrl(MSR_IA32_PERF_CTL, pstate << 8);
wrmsrl(MSR_IA32_PERF_CTL, val);
} }
static inline void intel_pstate_pstate_increase(struct cpudata *cpu, int steps) 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) static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
{ {
int rc, min_pstate, max_pstate;
struct cpudata *cpu; struct cpudata *cpu;
int rc;
rc = intel_pstate_init_cpu(policy->cpu); rc = intel_pstate_init_cpu(policy->cpu);
if (rc) if (rc)
@ -652,9 +653,8 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
else else
policy->policy = CPUFREQ_POLICY_POWERSAVE; policy->policy = CPUFREQ_POLICY_POWERSAVE;
intel_pstate_get_min_max(cpu, &min_pstate, &max_pstate); policy->min = cpu->pstate.min_pstate * 100000;
policy->min = min_pstate * 100000; policy->max = cpu->pstate.turbo_pstate * 100000;
policy->max = max_pstate * 100000;
/* cpuinfo and default policy values */ /* cpuinfo and default policy values */
policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000; policy->cpuinfo.min_freq = cpu->pstate.min_pstate * 100000;

View File

@ -166,7 +166,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
if (freq->frequency == CPUFREQ_ENTRY_INVALID) if (freq->frequency == CPUFREQ_ENTRY_INVALID)
continue; continue;
dvfs = &s3c64xx_dvfs_table[freq->index]; dvfs = &s3c64xx_dvfs_table[freq->driver_data];
found = 0; found = 0;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {

View File

@ -311,7 +311,6 @@ struct acpi_device {
unsigned int physical_node_count; unsigned int physical_node_count;
struct list_head physical_node_list; struct list_head physical_node_list;
struct mutex physical_node_lock; struct mutex physical_node_lock;
struct list_head power_dependent;
void (*remove)(struct acpi_device *); 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_status acpi_remove_pm_notifier(struct acpi_device *adev,
acpi_notify_handler handler); acpi_notify_handler handler);
int acpi_pm_device_sleep_state(struct device *, int *, int); 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 #else
static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
acpi_notify_handler handler, 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) ? return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ?
m : ACPI_STATE_D0; 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 #endif
#ifdef CONFIG_PM_RUNTIME #ifdef CONFIG_PM_RUNTIME