WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] Backport of powernow-k8 cpufreq chang

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] Backport of powernow-k8 cpufreq changes, required for power management
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 26 Sep 2007 15:50:23 -0700
Delivery-date: Wed, 26 Sep 2007 15:52:22 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1190294190 -3600
# Node ID 8a407c41dfb0cc03b66366b45eacd48c3e7bda4c
# Parent  08e2785d344f66abe3e84b875c3cb7b26497459f
Backport of powernow-k8 cpufreq changes, required for power management
on Xen.
Signed-off-by: Mark Langsdorf <mark.langsdorf@xxxxxxx>
---
 arch/i386/kernel/cpu/cpufreq/powernow-k8.c |  122 +++++++++++++++++++----------
 arch/i386/kernel/cpu/cpufreq/powernow-k8.h |    3 
 2 files changed, 85 insertions(+), 40 deletions(-)

diff -r 08e2785d344f -r 8a407c41dfb0 arch/i386/kernel/cpu/cpufreq/powernow-k8.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c        Wed Sep 19 16:26:49 
2007 +0100
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c        Thu Sep 20 14:16:30 
2007 +0100
@@ -738,6 +738,7 @@ static int find_psb_table(struct powerno
 
                data->numps = psb->numps;
                dprintk("numpstates: 0x%x\n", data->numps);
+               data->starting_core_affinity = cpumask_of_cpu(0);
                return fill_powernow_table(data, (struct pst_s *)(psb+1), 
maxvid);
        }
        /*
@@ -758,15 +759,43 @@ static int find_psb_table(struct powerno
 #ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, 
unsigned int index)
 {
-       if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE))
+       if (!data->acpi_data->state_count || (cpu_family == CPU_HW_PSTATE))
                return;
 
-       data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & 
IRT_MASK;
-       data->rvo = (data->acpi_data.states[index].control >> RVO_SHIFT) & 
RVO_MASK;
-       data->exttype = (data->acpi_data.states[index].control >> 
EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
-       data->plllock = (data->acpi_data.states[index].control >> PLL_L_SHIFT) 
& PLL_L_MASK;
-       data->vidmvs = 1 << ((data->acpi_data.states[index].control >> 
MVS_SHIFT) & MVS_MASK);
-       data->vstable = (data->acpi_data.states[index].control >> VST_SHIFT) & 
VST_MASK;
+       data->irt = (data->acpi_data->states[index].control >> IRT_SHIFT) & 
IRT_MASK;
+       data->rvo = (data->acpi_data->states[index].control >> RVO_SHIFT) & 
RVO_MASK;
+       data->exttype = (data->acpi_data->states[index].control >> 
EXT_TYPE_SHIFT) & EXT_TYPE_MASK;
+       data->plllock = (data->acpi_data->states[index].control >> PLL_L_SHIFT) 
& PLL_L_MASK;
+       data->vidmvs = 1 << ((data->acpi_data->states[index].control >> 
MVS_SHIFT) & MVS_MASK);
+       data->vstable = (data->acpi_data->states[index].control >> VST_SHIFT) & 
VST_MASK;
+}
+
+static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
+static int preregister_valid = 0;
+
+static int powernow_k8_cpu_preinit_acpi()
+{
+       int i; 
+       struct acpi_processor_performance *data;
+       for_each_possible_cpu(i) {
+               data = kzalloc(sizeof(struct acpi_processor_performance),
+                               GFP_KERNEL);
+               if (!data) {
+                       int j;
+                       for_each_possible_cpu(j) {
+                               kfree(acpi_perf_data[j]);
+                               acpi_perf_data[j] = NULL;
+                       }
+                       return -ENODEV;
+               }
+               acpi_perf_data[i] = data;
+       }
+
+       if (acpi_processor_preregister_performance(acpi_perf_data))
+               return -ENODEV;
+       else 
+               preregister_valid = 1;
+       return 0;
 }
 
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
@@ -774,28 +803,29 @@ static int powernow_k8_cpu_init_acpi(str
        struct cpufreq_frequency_table *powernow_table;
        int ret_val;
 
-       if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
+       data->acpi_data = acpi_perf_data[data->cpu];
+       if (acpi_processor_register_performance(data->acpi_data, data->cpu)) {
                dprintk("register performance failed: bad ACPI data\n");
                return -EIO;
        }
 
        /* verify the data contained in the ACPI structures */
-       if (data->acpi_data.state_count <= 1) {
+       if (data->acpi_data->state_count <= 1) {
                dprintk("No ACPI P-States\n");
                goto err_out;
        }
 
-       if ((data->acpi_data.control_register.space_id != 
ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-               (data->acpi_data.status_register.space_id != 
ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+       if ((data->acpi_data->control_register.space_id != 
ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+               (data->acpi_data->status_register.space_id != 
ACPI_ADR_SPACE_FIXED_HARDWARE)) {
                dprintk("Invalid control/status registers (%x - %x)\n",
-                       data->acpi_data.control_register.space_id,
-                       data->acpi_data.status_register.space_id);
+                       data->acpi_data->control_register.space_id,
+                       data->acpi_data->status_register.space_id);
                goto err_out;
        }
 
        /* fill in data->powernow_table */
        powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table)
-               * (data->acpi_data.state_count + 1)), GFP_KERNEL);
+               * (data->acpi_data->state_count + 1)), GFP_KERNEL);
        if (!powernow_table) {
                dprintk("powernow_table memory alloc failure\n");
                goto err_out;
@@ -808,28 +838,43 @@ static int powernow_k8_cpu_init_acpi(str
        if (ret_val)
                goto err_out_mem;
 
-       powernow_table[data->acpi_data.state_count].frequency = 
CPUFREQ_TABLE_END;
-       powernow_table[data->acpi_data.state_count].index = 0;
+       powernow_table[data->acpi_data->state_count].frequency = 
CPUFREQ_TABLE_END;
+       powernow_table[data->acpi_data->state_count].index = 0;
        data->powernow_table = powernow_table;
 
        /* fill in data */
-       data->numps = data->acpi_data.state_count;
+       data->numps = data->acpi_data->state_count;
        print_basics(data);
        powernow_k8_acpi_pst_values(data, 0);
 
        /* notify BIOS that we exist */
        acpi_processor_notify_smm(THIS_MODULE);
 
+       /* determine affinity, from ACPI if available */
+       if (preregister_valid) {
+               if ((data->acpi_data->shared_type == CPUFREQ_SHARED_TYPE_ALL) ||
+                   (data->acpi_data->shared_type == CPUFREQ_SHARED_TYPE_ANY))
+                       data->starting_core_affinity = 
data->acpi_data->shared_cpu_map;
+               else
+                       data->starting_core_affinity = 
cpumask_of_cpu(data->cpu);
+       } else {
+               /* best guess from family if not */
+               if (cpu_family == CPU_HW_PSTATE)
+                       data->starting_core_affinity = 
cpumask_of_cpu(data->cpu);
+               else
+                       data->starting_core_affinity = cpu_core_map[data->cpu];
+       }
+
        return 0;
 
 err_out_mem:
        kfree(powernow_table);
 
 err_out:
-       acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
-
-       /* data->acpi_data.state_count informs us at ->exit() whether ACPI was 
used */
-       data->acpi_data.state_count = 0;
+       acpi_processor_unregister_performance(data->acpi_data, data->cpu);
+
+       /* data->acpi_data->state_count informs us at ->exit() whether ACPI was 
used */
+       data->acpi_data->state_count = 0;
 
        return -ENODEV;
 }
@@ -838,13 +883,13 @@ static int fill_powernow_table_pstate(st
 {
        int i;
 
-       for (i = 0; i < data->acpi_data.state_count; i++) {
+       for (i = 0; i < data->acpi_data->state_count; i++) {
                u32 index;
                u32 hi = 0, lo = 0;
                u32 fid;
                u32 did;
 
-               index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
+               index = data->acpi_data->states[i].control & HW_PSTATE_MASK;
                if (index > MAX_HW_PSTATE) {
                        printk(KERN_ERR PFX "invalid pstate %d - bad value 
%d.\n", i, index);
                        printk(KERN_ERR PFX "Please report to BIOS 
manufacturer\n");
@@ -865,10 +910,10 @@ static int fill_powernow_table_pstate(st
 
                powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, 
did);
 
-               if (powernow_table[i].frequency != 
(data->acpi_data.states[i].core_frequency * 1000)) {
+               if (powernow_table[i].frequency != 
(data->acpi_data->states[i].core_frequency * 1000)) {
                        printk(KERN_INFO PFX "invalid freq entries %u kHz vs. 
%u kHz\n",
                                powernow_table[i].frequency,
-                               (unsigned int) 
(data->acpi_data.states[i].core_frequency * 1000));
+                               (unsigned int) 
(data->acpi_data->states[i].core_frequency * 1000));
                        powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
                        continue;
                }
@@ -880,16 +925,16 @@ static int fill_powernow_table_fidvid(st
 {
        int i;
        int cntlofreq = 0;
-       for (i = 0; i < data->acpi_data.state_count; i++) {
+       for (i = 0; i < data->acpi_data->state_count; i++) {
                u32 fid;
                u32 vid;
 
                if (data->exttype) {
-                       fid = data->acpi_data.states[i].status & EXT_FID_MASK;
-                       vid = (data->acpi_data.states[i].status >> VID_SHIFT) & 
EXT_VID_MASK;
+                       fid = data->acpi_data->states[i].status & EXT_FID_MASK;
+                       vid = (data->acpi_data->states[i].status >> VID_SHIFT) 
& EXT_VID_MASK;
                } else {
-                       fid = data->acpi_data.states[i].control & FID_MASK;
-                       vid = (data->acpi_data.states[i].control >> VID_SHIFT) 
& VID_MASK;
+                       fid = data->acpi_data->states[i].control & FID_MASK;
+                       vid = (data->acpi_data->states[i].control >> VID_SHIFT) 
& VID_MASK;
                }
 
                dprintk("   %d : fid 0x%x, vid 0x%x\n", i, fid, vid);
@@ -930,10 +975,10 @@ static int fill_powernow_table_fidvid(st
                                cntlofreq = i;
                }
 
-               if (powernow_table[i].frequency != 
(data->acpi_data.states[i].core_frequency * 1000)) {
+               if (powernow_table[i].frequency != 
(data->acpi_data->states[i].core_frequency * 1000)) {
                        printk(KERN_INFO PFX "invalid freq entries %u kHz vs. 
%u kHz\n",
                                powernow_table[i].frequency,
-                               (unsigned int) 
(data->acpi_data.states[i].core_frequency * 1000));
+                               (unsigned int) 
(data->acpi_data->states[i].core_frequency * 1000));
                        powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
                        continue;
                }
@@ -943,14 +988,15 @@ static int fill_powernow_table_fidvid(st
 
 static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
 {
-       if (data->acpi_data.state_count)
-               acpi_processor_unregister_performance(&data->acpi_data, 
data->cpu);
+       if (data->acpi_data->state_count)
+               acpi_processor_unregister_performance(data->acpi_data, 
data->cpu);
 }
 
 #else
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) { return 
-ENODEV; }
 static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) { return; 
}
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, 
unsigned int index) { return; }
+static int powernow_k8_cpu_preinit_acpi() { return -ENODEV; }
 #endif /* CONFIG_X86_POWERNOW_K8_ACPI */
 
 /* Take a frequency, and issue the fid/vid transition command */
@@ -1164,7 +1210,7 @@ static int __cpuinit powernowk8_cpu_init
                 * an UP version, and is deprecated by AMD.
                 */
                if (num_online_cpus() != 1) {
-                       printk(KERN_ERR PFX "MP systems not supported by PSB 
BIOS structure\n");
+                       printk(KERN_ERR PFX "Your BIOS does not provide _PSS 
objects.  PowerNow! does not work on SMP systems without _PSS objects.  
Complain to your BIOS vendor.\n");
                        kfree(data);
                        return -ENODEV;
                }
@@ -1204,10 +1250,7 @@ static int __cpuinit powernowk8_cpu_init
        set_cpus_allowed(current, oldmask);
 
        pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
-       if (cpu_family == CPU_HW_PSTATE)
-               pol->cpus = cpumask_of_cpu(pol->cpu);
-       else
-               pol->cpus = cpu_core_map[pol->cpu];
+       pol->cpus = data->starting_core_affinity;
        data->available_cores = &(pol->cpus);
 
        /* Take a crude guess here.
@@ -1323,6 +1366,7 @@ static int __cpuinit powernowk8_init(voi
        }
 
        if (supported_cpus == num_online_cpus()) {
+               powernow_k8_cpu_preinit_acpi();
                printk(KERN_INFO PFX "Found %d %s "
                        "processors (" VERSION ")\n", supported_cpus,
                        boot_cpu_data.x86_model_id);
diff -r 08e2785d344f -r 8a407c41dfb0 arch/i386/kernel/cpu/cpufreq/powernow-k8.h
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h        Wed Sep 19 16:26:49 
2007 +0100
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h        Thu Sep 20 14:16:30 
2007 +0100
@@ -32,12 +32,13 @@ struct powernow_k8_data {
 #ifdef CONFIG_X86_POWERNOW_K8_ACPI
        /* the acpi table needs to be kept. it's only available if ACPI was
         * used to determine valid frequency/vid/fid states */
-       struct acpi_processor_performance acpi_data;
+       struct acpi_processor_performance *acpi_data;
 #endif
        /* we need to keep track of associated cores, but let cpufreq
         * handle hotplug events - so just point at cpufreq pol->cpus
         * structure */
        cpumask_t *available_cores;
+       cpumask_t starting_core_affinity;
 };
 
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] Backport of powernow-k8 cpufreq changes, required for power management, Xen patchbot-linux-2.6.18-xen <=