Commit ee13cbde authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq:
  [CPUFREQ] powernow-k8: Limit Pstate transition latency check
  [CPUFREQ] Fix PCC driver error path
  [CPUFREQ] fix double freeing in error path of pcc-cpufreq
  [CPUFREQ] pcc driver should check for pcch method before calling _OSC
  [CPUFREQ] fix memory leak in cpufreq_add_dev
  [CPUFREQ] revert "[CPUFREQ] remove rwsem lock from CPUFREQ_GOV_STOP call (second call site)"
parents 863da955 3581ced3
...@@ -368,22 +368,16 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle) ...@@ -368,22 +368,16 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
return -ENODEV; return -ENODEV;
out_obj = output.pointer; out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) { if (out_obj->type != ACPI_TYPE_BUFFER)
ret = -ENODEV; return -ENODEV;
goto out_free;
}
errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
if (errors) { if (errors)
ret = -ENODEV; return -ENODEV;
goto out_free;
}
supported = *((u32 *)(out_obj->buffer.pointer + 4)); supported = *((u32 *)(out_obj->buffer.pointer + 4));
if (!(supported & 0x1)) { if (!(supported & 0x1))
ret = -ENODEV; return -ENODEV;
goto out_free;
}
out_free: out_free:
kfree(output.pointer); kfree(output.pointer);
...@@ -397,13 +391,17 @@ static int __init pcc_cpufreq_probe(void) ...@@ -397,13 +391,17 @@ static int __init pcc_cpufreq_probe(void)
struct pcc_memory_resource *mem_resource; struct pcc_memory_resource *mem_resource;
struct pcc_register_resource *reg_resource; struct pcc_register_resource *reg_resource;
union acpi_object *out_obj, *member; union acpi_object *out_obj, *member;
acpi_handle handle, osc_handle; acpi_handle handle, osc_handle, pcch_handle;
int ret = 0; int ret = 0;
status = acpi_get_handle(NULL, "\\_SB", &handle); status = acpi_get_handle(NULL, "\\_SB", &handle);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return -ENODEV; return -ENODEV;
status = acpi_get_handle(handle, "PCCH", &pcch_handle);
if (ACPI_FAILURE(status))
return -ENODEV;
status = acpi_get_handle(handle, "_OSC", &osc_handle); status = acpi_get_handle(handle, "_OSC", &osc_handle);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
ret = pcc_cpufreq_do_osc(&osc_handle); ret = pcc_cpufreq_do_osc(&osc_handle);
...@@ -543,13 +541,13 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -543,13 +541,13 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (!pcch_virt_addr) { if (!pcch_virt_addr) {
result = -1; result = -1;
goto pcch_null; goto out;
} }
result = pcc_get_offset(cpu); result = pcc_get_offset(cpu);
if (result) { if (result) {
dprintk("init: PCCP evaluation failed\n"); dprintk("init: PCCP evaluation failed\n");
goto free; goto out;
} }
policy->max = policy->cpuinfo.max_freq = policy->max = policy->cpuinfo.max_freq =
...@@ -558,14 +556,15 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -558,14 +556,15 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
ioread32(&pcch_hdr->minimum_frequency) * 1000; ioread32(&pcch_hdr->minimum_frequency) * 1000;
policy->cur = pcc_get_freq(cpu); policy->cur = pcc_get_freq(cpu);
if (!policy->cur) {
dprintk("init: Unable to get current CPU frequency\n");
result = -EINVAL;
goto out;
}
dprintk("init: policy->max is %d, policy->min is %d\n", dprintk("init: policy->max is %d, policy->min is %d\n",
policy->max, policy->min); policy->max, policy->min);
out:
return 0;
free:
pcc_clear_mapping();
free_percpu(pcc_cpu_info);
pcch_null:
return result; return result;
} }
......
...@@ -1023,13 +1023,12 @@ static int get_transition_latency(struct powernow_k8_data *data) ...@@ -1023,13 +1023,12 @@ static int get_transition_latency(struct powernow_k8_data *data)
} }
if (max_latency == 0) { if (max_latency == 0) {
/* /*
* Fam 11h always returns 0 as transition latency. * Fam 11h and later may return 0 as transition latency. This
* This is intended and means "very fast". While cpufreq core * is intended and means "very fast". While cpufreq core and
* and governors currently can handle that gracefully, better * governors currently can handle that gracefully, better set it
* set it to 1 to avoid problems in the future. * to 1 to avoid problems in the future.
* For all others it's a BIOS bug.
*/ */
if (boot_cpu_data.x86 != 0x11) if (boot_cpu_data.x86 < 0x11)
printk(KERN_ERR FW_WARN PFX "Invalid zero transition " printk(KERN_ERR FW_WARN PFX "Invalid zero transition "
"latency\n"); "latency\n");
max_latency = 1; max_latency = 1;
......
...@@ -1077,6 +1077,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) ...@@ -1077,6 +1077,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
err_unlock_policy: err_unlock_policy:
unlock_policy_rwsem_write(cpu); unlock_policy_rwsem_write(cpu);
free_cpumask_var(policy->related_cpus);
err_free_cpumask: err_free_cpumask:
free_cpumask_var(policy->cpus); free_cpumask_var(policy->cpus);
err_free_policy: err_free_policy:
...@@ -1762,17 +1763,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, ...@@ -1762,17 +1763,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
dprintk("governor switch\n"); dprintk("governor switch\n");
/* end old governor */ /* end old governor */
if (data->governor) { if (data->governor)
/*
* Need to release the rwsem around governor
* stop due to lock dependency between
* cancel_delayed_work_sync and the read lock
* taken in the delayed work handler.
*/
unlock_policy_rwsem_write(data->cpu);
__cpufreq_governor(data, CPUFREQ_GOV_STOP); __cpufreq_governor(data, CPUFREQ_GOV_STOP);
lock_policy_rwsem_write(data->cpu);
}
/* start new governor */ /* start new governor */
data->governor = policy->governor; data->governor = policy->governor;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment