summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-05-03 05:16:31 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-05-03 05:16:31 +0400
commit6c6ca9c2a5b97ab37ffd1b091d15eb5cd3f1bf23 (patch)
tree9507946fff33b9b0ea7acfe0ac26ce497dd88d30
parente981e79585da98397e34809f4773c7fa5e61317a (diff)
parentde3afce5336af3214374de6df360f9eb010a9a36 (diff)
downloadlinux-6c6ca9c2a5b97ab37ffd1b091d15eb5cd3f1bf23.tar.xz
Merge tag 'pm+acpi-3.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki: "A bunch of regression fixes this time. They fix two regressions in the PNP subsystem, one in the ACPI processor driver and one in the ACPI EC driver, four cpufreq driver regressions and an unrelated bug in one of the drivers. The regressions are recent or introduced in 3.14. Specifics: - There are two bugs in the ACPI PNP core that cause errors to be returned if optional ACPI methods are not present. After an ACPI core change made in 3.14 one of those errors leads to serial port suspend failures on some systems. Fix from Rafael J Wysocki. - A recently added PNP quirk related to Intel chipsets intorduced a build error in unusual configurations (PNP without PCI). Fix from Bjorn Helgaas. - An ACPI EC workaround related to system suspend on Samsung machines added in 3.14 introduced a race causing some valid EC events to be discarded. Fix from Kieran Clancy. - The acpi-cpufreq driver fails to load on some systems after a 3.14 commit related to APIC ID parsing that overlooked one corner case. Fix from Lan Tianyu. - Fix for a recently introduced build problem in the ppc-corenet cpufreq driver from Tim Gardner. - A recent cpufreq core change to ensure serialization of frequency transitions for drivers with a ->target_index() callback overlooked the fact that some of those drivers had been doing operations introduced by it into the core already by themselves. That resulted in a mess in which the core and the drivers try to do the same thing and block each other which leads to deadlocks. Fixes for the powernow-k7, powernow-k6, and longhaul cpufreq drivers from Srivatsa S Bhat. - Fix for a computational error in the powernow-k6 cpufreq driver from Srivatsa S Bhat" * tag 'pm+acpi-3.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: ACPI / processor: Fix failure of loading acpi-cpufreq driver PNP / ACPI: Do not return errors if _DIS or _SRS are not present PNP: Fix compile error in quirks.c ACPI / EC: Process rather than discard events in acpi_ec_clear cpufreq: ppc-corenet-cpufreq: Fix __udivdi3 modpost error cpufreq: powernow-k7: Fix double invocation of cpufreq_freq_transition_begin/end cpufreq: powernow-k6: Fix double invocation of cpufreq_freq_transition_begin/end cpufreq: powernow-k6: Fix incorrect comparison with max_multipler cpufreq: longhaul: Fix double invocation of cpufreq_freq_transition_begin/end
-rw-r--r--drivers/acpi/acpi_processor.c7
-rw-r--r--drivers/acpi/ec.c21
-rw-r--r--drivers/cpufreq/longhaul.c36
-rw-r--r--drivers/cpufreq/powernow-k6.c23
-rw-r--r--drivers/cpufreq/powernow-k7.c4
-rw-r--r--drivers/cpufreq/ppc-corenet-cpufreq.c5
-rw-r--r--drivers/pnp/pnpacpi/core.c44
-rw-r--r--drivers/pnp/quirks.c4
8 files changed, 85 insertions, 59 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c
index c29c2c3ec0ad..b06f5f55ada9 100644
--- a/drivers/acpi/acpi_processor.c
+++ b/drivers/acpi/acpi_processor.c
@@ -170,6 +170,9 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
acpi_status status;
int ret;
+ if (pr->apic_id == -1)
+ return -ENODEV;
+
status = acpi_evaluate_integer(pr->handle, "_STA", NULL, &sta);
if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT))
return -ENODEV;
@@ -260,10 +263,8 @@ static int acpi_processor_get_info(struct acpi_device *device)
}
apic_id = acpi_get_apicid(pr->handle, device_declaration, pr->acpi_id);
- if (apic_id < 0) {
+ if (apic_id < 0)
acpi_handle_debug(pr->handle, "failed to get CPU APIC ID.\n");
- return -ENODEV;
- }
pr->apic_id = apic_id;
cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index d7d32c28829b..ad11ba4a412d 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -206,13 +206,13 @@ unlock:
spin_unlock_irqrestore(&ec->lock, flags);
}
-static int acpi_ec_sync_query(struct acpi_ec *ec);
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
static int ec_check_sci_sync(struct acpi_ec *ec, u8 state)
{
if (state & ACPI_EC_FLAG_SCI) {
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
- return acpi_ec_sync_query(ec);
+ return acpi_ec_sync_query(ec, NULL);
}
return 0;
}
@@ -443,10 +443,8 @@ acpi_handle ec_get_handle(void)
EXPORT_SYMBOL(ec_get_handle);
-static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data);
-
/*
- * Clears stale _Q events that might have accumulated in the EC.
+ * Process _Q events that might have accumulated in the EC.
* Run with locked ec mutex.
*/
static void acpi_ec_clear(struct acpi_ec *ec)
@@ -455,7 +453,7 @@ static void acpi_ec_clear(struct acpi_ec *ec)
u8 value = 0;
for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
- status = acpi_ec_query_unlocked(ec, &value);
+ status = acpi_ec_sync_query(ec, &value);
if (status || !value)
break;
}
@@ -582,13 +580,18 @@ static void acpi_ec_run(void *cxt)
kfree(handler);
}
-static int acpi_ec_sync_query(struct acpi_ec *ec)
+static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
{
u8 value = 0;
int status;
struct acpi_ec_query_handler *handler, *copy;
- if ((status = acpi_ec_query_unlocked(ec, &value)))
+
+ status = acpi_ec_query_unlocked(ec, &value);
+ if (data)
+ *data = value;
+ if (status)
return status;
+
list_for_each_entry(handler, &ec->list, node) {
if (value == handler->query_bit) {
/* have custom handler for this bit */
@@ -612,7 +615,7 @@ static void acpi_ec_gpe_query(void *ec_cxt)
if (!ec)
return;
mutex_lock(&ec->mutex);
- acpi_ec_sync_query(ec);
+ acpi_ec_sync_query(ec, NULL);
mutex_unlock(&ec->mutex);
}
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index d00e5d1abd25..5c4369b5d834 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -242,7 +242,7 @@ static void do_powersaver(int cx_address, unsigned int mults_index,
* Sets a new clock ratio.
*/
-static void longhaul_setstate(struct cpufreq_policy *policy,
+static int longhaul_setstate(struct cpufreq_policy *policy,
unsigned int table_index)
{
unsigned int mults_index;
@@ -258,10 +258,12 @@ static void longhaul_setstate(struct cpufreq_policy *policy,
/* Safety precautions */
mult = mults[mults_index & 0x1f];
if (mult == -1)
- return;
+ return -EINVAL;
+
speed = calc_speed(mult);
if ((speed > highest_speed) || (speed < lowest_speed))
- return;
+ return -EINVAL;
+
/* Voltage transition before frequency transition? */
if (can_scale_voltage && longhaul_index < table_index)
dir = 1;
@@ -269,8 +271,6 @@ static void longhaul_setstate(struct cpufreq_policy *policy,
freqs.old = calc_speed(longhaul_get_cpu_mult());
freqs.new = speed;
- cpufreq_freq_transition_begin(policy, &freqs);
-
pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
fsb, mult/10, mult%10, print_speed(speed/1000));
retry_loop:
@@ -385,12 +385,14 @@ retry_loop:
goto retry_loop;
}
}
- /* Report true CPU frequency */
- cpufreq_freq_transition_end(policy, &freqs, 0);
- if (!bm_timeout)
+ if (!bm_timeout) {
printk(KERN_INFO PFX "Warning: Timeout while waiting for "
"idle PCI bus.\n");
+ return -EBUSY;
+ }
+
+ return 0;
}
/*
@@ -631,9 +633,10 @@ static int longhaul_target(struct cpufreq_policy *policy,
unsigned int i;
unsigned int dir = 0;
u8 vid, current_vid;
+ int retval = 0;
if (!can_scale_voltage)
- longhaul_setstate(policy, table_index);
+ retval = longhaul_setstate(policy, table_index);
else {
/* On test system voltage transitions exceeding single
* step up or down were turning motherboard off. Both
@@ -648,7 +651,7 @@ static int longhaul_target(struct cpufreq_policy *policy,
while (i != table_index) {
vid = (longhaul_table[i].driver_data >> 8) & 0x1f;
if (vid != current_vid) {
- longhaul_setstate(policy, i);
+ retval = longhaul_setstate(policy, i);
current_vid = vid;
msleep(200);
}
@@ -657,10 +660,11 @@ static int longhaul_target(struct cpufreq_policy *policy,
else
i--;
}
- longhaul_setstate(policy, table_index);
+ retval = longhaul_setstate(policy, table_index);
}
+
longhaul_index = table_index;
- return 0;
+ return retval;
}
@@ -968,7 +972,15 @@ static void __exit longhaul_exit(void)
for (i = 0; i < numscales; i++) {
if (mults[i] == maxmult) {
+ struct cpufreq_freqs freqs;
+
+ freqs.old = policy->cur;
+ freqs.new = longhaul_table[i].frequency;
+ freqs.flags = 0;
+
+ cpufreq_freq_transition_begin(policy, &freqs);
longhaul_setstate(policy, i);
+ cpufreq_freq_transition_end(policy, &freqs, 0);
break;
}
}
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index 49f120e1bc7b..78904e6ca4a0 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -138,22 +138,14 @@ static void powernow_k6_set_cpu_multiplier(unsigned int best_i)
static int powernow_k6_target(struct cpufreq_policy *policy,
unsigned int best_i)
{
- struct cpufreq_freqs freqs;
if (clock_ratio[best_i].driver_data > max_multiplier) {
printk(KERN_ERR PFX "invalid target frequency\n");
return -EINVAL;
}
- freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
- freqs.new = busfreq * clock_ratio[best_i].driver_data;
-
- cpufreq_freq_transition_begin(policy, &freqs);
-
powernow_k6_set_cpu_multiplier(best_i);
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
return 0;
}
@@ -227,9 +219,20 @@ have_busfreq:
static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
{
unsigned int i;
- for (i = 0; i < 8; i++) {
- if (i == max_multiplier)
+
+ for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+ if (clock_ratio[i].driver_data == max_multiplier) {
+ struct cpufreq_freqs freqs;
+
+ freqs.old = policy->cur;
+ freqs.new = clock_ratio[i].frequency;
+ freqs.flags = 0;
+
+ cpufreq_freq_transition_begin(policy, &freqs);
powernow_k6_target(policy, i);
+ cpufreq_freq_transition_end(policy, &freqs, 0);
+ break;
+ }
}
return 0;
}
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index f911645c3f6d..e61e224475ad 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -269,8 +269,6 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
freqs.new = powernow_table[index].frequency;
- cpufreq_freq_transition_begin(policy, &freqs);
-
/* Now do the magic poking into the MSRs. */
if (have_a0 == 1) /* A0 errata 5 */
@@ -290,8 +288,6 @@ static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
if (have_a0 == 1)
local_irq_enable();
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
return 0;
}
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c
index a1ca3dd04a8e..0af618abebaf 100644
--- a/drivers/cpufreq/ppc-corenet-cpufreq.c
+++ b/drivers/cpufreq/ppc-corenet-cpufreq.c
@@ -138,6 +138,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
struct cpufreq_frequency_table *table;
struct cpu_data *data;
unsigned int cpu = policy->cpu;
+ u64 transition_latency_hz;
np = of_get_cpu_node(cpu, NULL);
if (!np)
@@ -205,8 +206,10 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
for_each_cpu(i, per_cpu(cpu_mask, cpu))
per_cpu(cpu_data, i) = data;
+ transition_latency_hz = 12ULL * NSEC_PER_SEC;
policy->cpuinfo.transition_latency =
- (12ULL * NSEC_PER_SEC) / fsl_get_sys_freq();
+ do_div(transition_latency_hz, fsl_get_sys_freq());
+
of_node_put(np);
return 0;
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 9f611cbbc294..c31aa07b3ba5 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -83,8 +83,7 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
{
struct acpi_device *acpi_dev;
acpi_handle handle;
- struct acpi_buffer buffer;
- int ret;
+ int ret = 0;
pnp_dbg(&dev->dev, "set resources\n");
@@ -97,19 +96,26 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
if (WARN_ON_ONCE(acpi_dev != dev->data))
dev->data = acpi_dev;
- ret = pnpacpi_build_resource_template(dev, &buffer);
- if (ret)
- return ret;
- ret = pnpacpi_encode_resources(dev, &buffer);
- if (ret) {
+ if (acpi_has_method(handle, METHOD_NAME__SRS)) {
+ struct acpi_buffer buffer;
+
+ ret = pnpacpi_build_resource_template(dev, &buffer);
+ if (ret)
+ return ret;
+
+ ret = pnpacpi_encode_resources(dev, &buffer);
+ if (!ret) {
+ acpi_status status;
+
+ status = acpi_set_current_resources(handle, &buffer);
+ if (ACPI_FAILURE(status))
+ ret = -EIO;
+ }
kfree(buffer.pointer);
- return ret;
}
- if (ACPI_FAILURE(acpi_set_current_resources(handle, &buffer)))
- ret = -EINVAL;
- else if (acpi_bus_power_manageable(handle))
+ if (!ret && acpi_bus_power_manageable(handle))
ret = acpi_bus_set_power(handle, ACPI_STATE_D0);
- kfree(buffer.pointer);
+
return ret;
}
@@ -117,7 +123,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
{
struct acpi_device *acpi_dev;
acpi_handle handle;
- int ret;
+ acpi_status status;
dev_dbg(&dev->dev, "disable resources\n");
@@ -128,13 +134,15 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
}
/* acpi_unregister_gsi(pnp_irq(dev, 0)); */
- ret = 0;
if (acpi_bus_power_manageable(handle))
acpi_bus_set_power(handle, ACPI_STATE_D3_COLD);
- /* continue even if acpi_bus_set_power() fails */
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL)))
- ret = -ENODEV;
- return ret;
+
+ /* continue even if acpi_bus_set_power() fails */
+ status = acpi_evaluate_object(handle, "_DIS", NULL, NULL);
+ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
+ return -ENODEV;
+
+ return 0;
}
#ifdef CONFIG_ACPI_SLEEP
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 3736bc408adb..ebf0d6710b5a 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -335,7 +335,7 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
}
#endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_PCI
/* Device IDs of parts that have 32KB MCH space */
static const unsigned int mch_quirk_devices[] = {
0x0154, /* Ivy Bridge */
@@ -440,7 +440,7 @@ static struct pnp_fixup pnp_fixups[] = {
#ifdef CONFIG_AMD_NB
{"PNP0c01", quirk_amd_mmconfig_area},
#endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_PCI
{"PNP0c02", quirk_intel_mch},
#endif
{""}