* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
* Opteron Processors" available for download from www.amd.com
*
- * Tables for specific CPUs can be infrerred from
+ * Tables for specific CPUs can be inferred from
* http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
*/
#ifdef CONFIG_X86_POWERNOW_K8_ACPI
#include <linux/acpi.h>
+#include <linux/mutex.h>
#include <acpi/processor.h>
#endif
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.0"
+#define VERSION "version 1.60.2"
#include "powernow-k8.h"
/* serialize freq changes */
-static DECLARE_MUTEX(fidvid_sem);
+static DEFINE_MUTEX(fidvid_mutex);
static struct powernow_k8_data *powernow_data[NR_CPUS];
*/
static u32 convert_fid_to_vco_fid(u32 fid)
{
- if (fid < HI_FID_TABLE_BOTTOM) {
+ if (fid < HI_FID_TABLE_BOTTOM)
return 8 + (2 * fid);
- } else {
+ else
return fid;
- }
}
/*
if (i++ > 100) {
printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
return 1;
- }
+ }
} while (query_current_values_with_pending_wait(data));
count_off_irt(data);
/* verify only 1 entry from the lo frequency table */
if (fid < HI_FID_TABLE_BOTTOM) {
if (cntlofreq) {
- /* if both entries are the same, ignore this
- * one...
- */
+ /* if both entries are the same, ignore this one ... */
if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
(powernow_table[i].index != powernow_table[cntlofreq].index)) {
printk(KERN_ERR PFX "Too many lo freq table entries\n");
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
/* fid are the lower 8 bits of the index we stored into
- * the cpufreq frequency table in find_psb_table, vid are
+ * the cpufreq frequency table in find_psb_table, vid are
* the upper 8 bits.
*/
for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
freqs.cpu = i;
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- }
+ }
return res;
}
{
cpumask_t oldmask = CPU_MASK_ALL;
struct powernow_k8_data *data = powernow_data[pol->cpu];
- u32 checkfid = data->currfid;
- u32 checkvid = data->currvid;
+ u32 checkfid;
+ u32 checkvid;
unsigned int newstate;
int ret = -EIO;
- int i;
+
+ if (!data)
+ return -EINVAL;
+
+ checkfid = data->currfid;
+ checkvid = data->currvid;
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
pol->cpu, targfreq, pol->min, pol->max, relation);
- if (query_current_values_with_pending_wait(data)) {
- ret = -EIO;
+ if (query_current_values_with_pending_wait(data))
goto err_out;
- }
dprintk("targ: curr fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
goto err_out;
- down(&fidvid_sem);
+ mutex_lock(&fidvid_mutex);
powernow_k8_acpi_pst_values(data, newstate);
if (transition_frequency(data, newstate)) {
printk(KERN_ERR PFX "transition frequency failed\n");
ret = 1;
- up(&fidvid_sem);
+ mutex_unlock(&fidvid_mutex);
goto err_out;
}
-
- /* Update all the fid/vids of our siblings */
- for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
- powernow_data[i]->currvid = data->currvid;
- powernow_data[i]->currfid = data->currfid;
- }
- up(&fidvid_sem);
+ mutex_unlock(&fidvid_mutex);
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
{
struct powernow_k8_data *data = powernow_data[pol->cpu];
+ if (!data)
+ return -EINVAL;
+
return cpufreq_frequency_table_verify(pol, data->powernow_table);
}
{
struct powernow_k8_data *data;
cpumask_t oldmask = CPU_MASK_ALL;
- int rc, i;
+ int rc;
if (!cpu_online(pol->cpu))
return -ENODEV;
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
pol->cpus = cpu_core_map[pol->cpu];
- /* Take a crude guess here.
+ /* Take a crude guess here.
* That guess was in microseconds, so multiply with 1000 */
pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
+ (3 * (1 << data->irt) * 10)) * 1000;
printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
- for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
- powernow_data[i] = data;
- }
+ powernow_data[pol->cpu] = data;
return 0;
static unsigned int powernowk8_get (unsigned int cpu)
{
- struct powernow_k8_data *data = powernow_data[cpu];
+ struct powernow_k8_data *data;
cpumask_t oldmask = current->cpus_allowed;
unsigned int khz = 0;
+ data = powernow_data[first_cpu(cpu_core_map[cpu])];
+
+ if (!data)
+ return -EINVAL;
+
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
{
unsigned int i, supported_cpus = 0;
- for (i=0; i<NR_CPUS; i++) {
- if (!cpu_online(i))
- continue;
+ for_each_online_cpu(i) {
if (check_supported_cpu(i))
supported_cpus++;
}
if (supported_cpus == num_online_cpus()) {
- printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron processors (" VERSION ")\n",
- supported_cpus);
+ printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron "
+ "processors (" VERSION ")\n", supported_cpus);
return cpufreq_register_driver(&cpufreq_amd64_driver);
}