提交 6c6ca9c2 编写于 作者: L Linus Torvalds

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
......@@ -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);
......
......@@ -206,13 +206,13 @@ static void advance_transaction(struct acpi_ec *ec, u8 status)
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);
}
......
......@@ -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 @@ static void longhaul_setstate(struct cpufreq_policy *policy,
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;
}
}
......
......@@ -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 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
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;
}
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
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) {
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;
status = acpi_evaluate_object(handle, "_DIS", NULL, NULL);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
return -ENODEV;
return 0;
}
#ifdef CONFIG_ACPI_SLEEP
......
......@@ -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
{""}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册