summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Weber <xmw@gentoo.org>2012-12-17 07:20:10 +0000
committerMichael Weber <xmw@gentoo.org>2012-12-17 07:20:10 +0000
commita8f6a1c4f717ccf2997a9700cf9a74c046a30a34 (patch)
tree44bea46a2481e11bd0f16c6c10c19dcf54e47eb9 /sys-power
parentVersion bump wrt #447522 by Marcin Mirosław (diff)
downloadgentoo-2-a8f6a1c4f717ccf2997a9700cf9a74c046a30a34.tar.gz
gentoo-2-a8f6a1c4f717ccf2997a9700cf9a74c046a30a34.tar.bz2
gentoo-2-a8f6a1c4f717ccf2997a9700cf9a74c046a30a34.zip
Remove trailing space from cpufreq/phc_controls output
(Portage version: 2.2.0_alpha147/cvs/Linux x86_64, signed Manifest commit with key 62EEF090)
Diffstat (limited to 'sys-power')
-rw-r--r--sys-power/phc-intel/ChangeLog11
-rw-r--r--sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.35.patch531
-rw-r--r--sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.36.patch531
-rw-r--r--sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.37.patch530
-rw-r--r--sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-3.7.patch536
-rw-r--r--sys-power/phc-intel/phc-intel-0.3.2.12.1-r5.ebuild60
6 files changed, 2198 insertions, 1 deletions
diff --git a/sys-power/phc-intel/ChangeLog b/sys-power/phc-intel/ChangeLog
index 7d84189e49aa..e60038c055cb 100644
--- a/sys-power/phc-intel/ChangeLog
+++ b/sys-power/phc-intel/ChangeLog
@@ -1,6 +1,15 @@
# ChangeLog for sys-power/phc-intel
# Copyright 1999-2012 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/sys-power/phc-intel/ChangeLog,v 1.10 2012/11/15 01:08:43 xmw Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-power/phc-intel/ChangeLog,v 1.11 2012/12/17 07:20:10 xmw Exp $
+
+*phc-intel-0.3.2.12.1-r5 (17 Dec 2012)
+
+ 17 Dec 2012; Michael Weber <xmw@gentoo.org> +phc-intel-0.3.2.12.1-r5.ebuild,
+ +files/phc-intel-0.3.2.12.1-r5-2.6.35.patch,
+ +files/phc-intel-0.3.2.12.1-r5-2.6.36.patch,
+ +files/phc-intel-0.3.2.12.1-r5-2.6.37.patch,
+ +files/phc-intel-0.3.2.12.1-r5-3.7.patch:
+ Remove trailing space from cpufreq/phc_controls output
*phc-intel-0.3.2.12.1-r4 (15 Nov 2012)
diff --git a/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.35.patch b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.35.patch
new file mode 100644
index 000000000000..3a80b057955d
--- /dev/null
+++ b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.35.patch
@@ -0,0 +1,531 @@
+--- /tmp/acpi-cpufreq.c.orig 2010-08-07 09:25:45.510440771 +0200
++++ phc-intel-0.3.2-12-1/phc-intel.c
+@@ -25,6 +25,10 @@
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
++/* This file has been patched with Linux PHC: www.linux-phc.org
++* Patch version: linux-phc-0.3.2
++*/
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -62,12 +66,17 @@
+ };
+
+ #define INTEL_MSR_RANGE (0xffff)
++#define INTEL_MSR_VID_MASK (0x00ff)
++#define INTEL_MSR_FID_MASK (0xff00)
++#define INTEL_MSR_FID_SHIFT (0x8)
++#define PHC_VERSION_STRING "0.3.2:2"
+
+ struct acpi_cpufreq_data {
+ struct acpi_processor_performance *acpi_data;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int resume;
+ unsigned int cpu_feature;
++ acpi_integer *original_controls;
+ };
+
+ static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
+@@ -103,13 +112,14 @@
+ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
+ {
+ int i;
++ u32 fid;
+ struct acpi_processor_performance *perf;
+
+- msr &= INTEL_MSR_RANGE;
++ fid = msr & INTEL_MSR_FID_MASK;
+ perf = data->acpi_data;
+
+ for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+- if (msr == perf->states[data->freq_table[i].index].status)
++ if (fid == (perf->states[data->freq_table[i].index].status & INTEL_MSR_FID_MASK))
+ return data->freq_table[i].frequency;
+ }
+ return data->freq_table[0].frequency;
+@@ -704,6 +714,8 @@
+ per_cpu(acfreq_data, policy->cpu) = NULL;
+ acpi_processor_unregister_performance(data->acpi_data,
+ policy->cpu);
++ if (data->original_controls)
++ kfree(data->original_controls);
+ kfree(data);
+ }
+
+@@ -721,8 +733,472 @@
+ return 0;
+ }
+
++
++/* sysfs interface to change operating points voltages */
++
++static unsigned int extract_fid_from_control(unsigned int control)
++{
++ return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT);
++}
++
++static unsigned int extract_vid_from_control(unsigned int control)
++{
++ return (control & INTEL_MSR_VID_MASK);
++}
++
++
++static bool check_cpu_control_capability(struct acpi_cpufreq_data *data) {
++ /* check if the cpu we are running on is capable of setting new control data
++ *
++ */
++ if (unlikely(data == NULL ||
++ data->acpi_data == NULL ||
++ data->freq_table == NULL ||
++ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
++ return false;
++ } else {
++ return true;
++ };
++}
++
++
++static ssize_t check_origial_table (struct acpi_cpufreq_data *data)
++{
++
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int state_index;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ if (data->original_controls == NULL) {
++ // Backup original control values
++ data->original_controls = kcalloc(acpi_data->state_count,
++ sizeof(acpi_integer), GFP_KERNEL);
++ if (data->original_controls == NULL) {
++ printk("failed to allocate memory for original control values\n");
++ return -ENOMEM;
++ }
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ data->original_controls[state_index] = acpi_data->states[state_index].control;
++ }
++ }
++ return 0;
++}
++
++static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's frequeny id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", fid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf)
++ /* display phc's controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ if (count)
++ count += sprintf(&buf[count], " ");
++ count += sprintf(&buf[count], "%u:%u ", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(data->original_controls[freq_table[i].index]);
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u:%u ", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++
++static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the voltage id's for the related frequency
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int freq_index;
++ unsigned int state_index;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_control;
++ unsigned int original_control;
++ const char *curr_buf = buf;
++ char *next_buf;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ /* for each value taken from the sysfs interfalce (phc_vids) get entrys and convert them to unsigned long integers*/
++ for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) {
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if (next_buf == curr_buf) {
++ if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) { //end of line?
++ curr_buf++;
++ break;
++ }
++ //if we didn't got end of line but there is nothing more to read something went wrong...
++ printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf);
++ return -EINVAL;
++ }
++
++ state_index = freq_table[freq_index].index;
++ original_control = data->original_controls[state_index];
++ original_vid = original_control & INTEL_MSR_VID_MASK;
++
++ /* before we store the values we do some checks to prevent
++ * users to set up values higher than the default one
++ */
++ if (new_vid <= original_vid) {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ dprintk("setting control at %i to %x (default is %x)\n",
++ freq_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ printk("skipping vid at %i, %u is greater than default %u\n",
++ freq_index, new_vid, original_vid);
++ }
++
++ curr_buf = next_buf;
++ /* jump over value seperators (space or comma).
++ * There could be more than one space or comma character
++ * to separate two values so we better do it using a loop.
++ */
++ while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) {
++ curr_buf++;
++ }
++ }
++
++ /* set new voltage for current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++
++ return curr_buf - buf;
++}
++
++static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the controls (frequency id's and related voltage id's)
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ const char *curr_buf;
++ unsigned int op_count;
++ unsigned int state_index;
++ int isok;
++ char *next_buf;
++ ssize_t retval;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_fid;
++ unsigned int old_fid;
++ unsigned int original_control;
++ unsigned int old_control;
++ unsigned int new_control;
++ int found;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV;
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ op_count = 0;
++ curr_buf = buf;
++ next_buf = NULL;
++ isok = 1;
++
++ while ( (isok) && (curr_buf != NULL) )
++ {
++ op_count++;
++ // Parse fid
++ new_fid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ // Parse separator between frequency and voltage
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if (*curr_buf==':')
++ {
++ curr_buf++;
++ // Parse vid
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ found = 0;
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ old_control = acpi_data->states[state_index].control;
++ old_fid = extract_fid_from_control(old_control);
++ if (new_fid == old_fid)
++ {
++ found = 1;
++ original_control = data->original_controls[state_index];
++ original_vid = extract_vid_from_control(original_control);
++ if (new_vid <= original_vid)
++ {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ dprintk("setting control at %i to %x (default is %x)\n",
++ state_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ printk("skipping vid at %i, %u is greater than default %u\n",
++ state_index, new_vid, original_vid);
++ }
++ }
++ }
++
++ if (found == 0)
++ {
++ printk("operating point # %u not found (FID = %u)\n", op_count, new_fid);
++ isok = 0;
++ }
++
++ // Parse seprator before next operating point, if any
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if ((*curr_buf == ',') || (*curr_buf == ' '))
++ curr_buf++;
++ else
++ curr_buf = NULL;
++ }
++ else
++ {
++ printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++
++ if (isok)
++ {
++ retval = count;
++ /* set new voltage at current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++ }
++ else
++ {
++ retval = -EINVAL;
++ }
++
++ return retval;
++}
++
++static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf)
++ /* print out the phc version string set at the beginning of that file
++ */
++{
++ ssize_t count = 0;
++ count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING);
++ return count;
++}
++
++
++
++static struct freq_attr cpufreq_freq_attr_phc_version =
++{
++ /*display phc's version string*/
++ .attr = { .name = "phc_version", .mode = 0444, .owner = THIS_MODULE },
++ .show = show_freq_attr_phc_version,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_vids =
++{
++ /*display phc's voltage id's for the cpu*/
++ .attr = { .name = "phc_vids", .mode = 0644, .owner = THIS_MODULE },
++ .show = show_freq_attr_vids,
++ .store = store_freq_attr_vids,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_vids =
++{
++ /*display acpi's default frequency id's for the cpu*/
++ .attr = { .name = "phc_default_vids", .mode = 0444, .owner = THIS_MODULE },
++ .show = show_freq_attr_default_vids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_fids =
++{
++ /*display phc's default frequency id's for the cpu*/
++ .attr = { .name = "phc_fids", .mode = 0444, .owner = THIS_MODULE },
++ .show = show_freq_attr_fids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_controls =
++{
++ /*display phc's current voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_controls", .mode = 0644, .owner = THIS_MODULE },
++ .show = show_freq_attr_controls,
++ .store = store_freq_attr_controls,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_controls =
++{
++ /*display acpi's default voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_default_controls", .mode = 0444, .owner = THIS_MODULE },
++ .show = show_freq_attr_default_controls,
++ .store = NULL,
++};
++
+ static struct freq_attr *acpi_cpufreq_attr[] = {
+- &cpufreq_freq_attr_scaling_available_freqs,
++ &cpufreq_freq_attr_scaling_available_freqs,
++ &cpufreq_freq_attr_phc_version,
++ &cpufreq_freq_attr_vids,
++ &cpufreq_freq_attr_default_vids,
++ &cpufreq_freq_attr_fids,
++ &cpufreq_freq_attr_controls,
++ &cpufreq_freq_attr_default_controls,
+ NULL,
+ };
+
diff --git a/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.36.patch b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.36.patch
new file mode 100644
index 000000000000..f952cbc0d540
--- /dev/null
+++ b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.36.patch
@@ -0,0 +1,531 @@
+--- /tmp/acpi-cpufreq.c.orig 2010-08-07 09:25:45.510440771 +0200
++++ phc-intel-0.3.2-12-1/phc-intel.c
+@@ -25,6 +25,10 @@
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
++/* This file has been patched with Linux PHC: www.linux-phc.org
++* Patch version: linux-phc-0.3.2
++*/
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -62,12 +66,17 @@
+ };
+
+ #define INTEL_MSR_RANGE (0xffff)
++#define INTEL_MSR_VID_MASK (0x00ff)
++#define INTEL_MSR_FID_MASK (0xff00)
++#define INTEL_MSR_FID_SHIFT (0x8)
++#define PHC_VERSION_STRING "0.3.2:2"
+
+ struct acpi_cpufreq_data {
+ struct acpi_processor_performance *acpi_data;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int resume;
+ unsigned int cpu_feature;
++ acpi_integer *original_controls;
+ };
+
+ static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
+@@ -103,13 +112,14 @@
+ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
+ {
+ int i;
++ u32 fid;
+ struct acpi_processor_performance *perf;
+
+- msr &= INTEL_MSR_RANGE;
++ fid = msr & INTEL_MSR_FID_MASK;
+ perf = data->acpi_data;
+
+ for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+- if (msr == perf->states[data->freq_table[i].index].status)
++ if (fid == (perf->states[data->freq_table[i].index].status & INTEL_MSR_FID_MASK))
+ return data->freq_table[i].frequency;
+ }
+ return data->freq_table[0].frequency;
+@@ -704,6 +714,8 @@
+ per_cpu(acfreq_data, policy->cpu) = NULL;
+ acpi_processor_unregister_performance(data->acpi_data,
+ policy->cpu);
++ if (data->original_controls)
++ kfree(data->original_controls);
+ kfree(data);
+ }
+
+@@ -721,8 +733,472 @@
+ return 0;
+ }
+
++
++/* sysfs interface to change operating points voltages */
++
++static unsigned int extract_fid_from_control(unsigned int control)
++{
++ return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT);
++}
++
++static unsigned int extract_vid_from_control(unsigned int control)
++{
++ return (control & INTEL_MSR_VID_MASK);
++}
++
++
++static bool check_cpu_control_capability(struct acpi_cpufreq_data *data) {
++ /* check if the cpu we are running on is capable of setting new control data
++ *
++ */
++ if (unlikely(data == NULL ||
++ data->acpi_data == NULL ||
++ data->freq_table == NULL ||
++ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
++ return false;
++ } else {
++ return true;
++ };
++}
++
++
++static ssize_t check_origial_table (struct acpi_cpufreq_data *data)
++{
++
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int state_index;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ if (data->original_controls == NULL) {
++ // Backup original control values
++ data->original_controls = kcalloc(acpi_data->state_count,
++ sizeof(acpi_integer), GFP_KERNEL);
++ if (data->original_controls == NULL) {
++ printk("failed to allocate memory for original control values\n");
++ return -ENOMEM;
++ }
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ data->original_controls[state_index] = acpi_data->states[state_index].control;
++ }
++ }
++ return 0;
++}
++
++static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's frequeny id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", fid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf)
++ /* display phc's controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ if (count)
++ count += sprintf(&buf[count], " ");
++ count += sprintf(&buf[count], "%u:%u", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(data->original_controls[freq_table[i].index]);
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u:%u ", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++
++static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the voltage id's for the related frequency
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int freq_index;
++ unsigned int state_index;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_control;
++ unsigned int original_control;
++ const char *curr_buf = buf;
++ char *next_buf;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ /* for each value taken from the sysfs interfalce (phc_vids) get entrys and convert them to unsigned long integers*/
++ for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) {
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if (next_buf == curr_buf) {
++ if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) { //end of line?
++ curr_buf++;
++ break;
++ }
++ //if we didn't got end of line but there is nothing more to read something went wrong...
++ printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf);
++ return -EINVAL;
++ }
++
++ state_index = freq_table[freq_index].index;
++ original_control = data->original_controls[state_index];
++ original_vid = original_control & INTEL_MSR_VID_MASK;
++
++ /* before we store the values we do some checks to prevent
++ * users to set up values higher than the default one
++ */
++ if (new_vid <= original_vid) {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ dprintk("setting control at %i to %x (default is %x)\n",
++ freq_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ printk("skipping vid at %i, %u is greater than default %u\n",
++ freq_index, new_vid, original_vid);
++ }
++
++ curr_buf = next_buf;
++ /* jump over value seperators (space or comma).
++ * There could be more than one space or comma character
++ * to separate two values so we better do it using a loop.
++ */
++ while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) {
++ curr_buf++;
++ }
++ }
++
++ /* set new voltage for current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++
++ return curr_buf - buf;
++}
++
++static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the controls (frequency id's and related voltage id's)
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ const char *curr_buf;
++ unsigned int op_count;
++ unsigned int state_index;
++ int isok;
++ char *next_buf;
++ ssize_t retval;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_fid;
++ unsigned int old_fid;
++ unsigned int original_control;
++ unsigned int old_control;
++ unsigned int new_control;
++ int found;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV;
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ op_count = 0;
++ curr_buf = buf;
++ next_buf = NULL;
++ isok = 1;
++
++ while ( (isok) && (curr_buf != NULL) )
++ {
++ op_count++;
++ // Parse fid
++ new_fid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ // Parse separator between frequency and voltage
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if (*curr_buf==':')
++ {
++ curr_buf++;
++ // Parse vid
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ found = 0;
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ old_control = acpi_data->states[state_index].control;
++ old_fid = extract_fid_from_control(old_control);
++ if (new_fid == old_fid)
++ {
++ found = 1;
++ original_control = data->original_controls[state_index];
++ original_vid = extract_vid_from_control(original_control);
++ if (new_vid <= original_vid)
++ {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ dprintk("setting control at %i to %x (default is %x)\n",
++ state_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ printk("skipping vid at %i, %u is greater than default %u\n",
++ state_index, new_vid, original_vid);
++ }
++ }
++ }
++
++ if (found == 0)
++ {
++ printk("operating point # %u not found (FID = %u)\n", op_count, new_fid);
++ isok = 0;
++ }
++
++ // Parse seprator before next operating point, if any
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if ((*curr_buf == ',') || (*curr_buf == ' '))
++ curr_buf++;
++ else
++ curr_buf = NULL;
++ }
++ else
++ {
++ printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++
++ if (isok)
++ {
++ retval = count;
++ /* set new voltage at current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++ }
++ else
++ {
++ retval = -EINVAL;
++ }
++
++ return retval;
++}
++
++static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf)
++ /* print out the phc version string set at the beginning of that file
++ */
++{
++ ssize_t count = 0;
++ count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING);
++ return count;
++}
++
++
++
++static struct freq_attr cpufreq_freq_attr_phc_version =
++{
++ /*display phc's version string*/
++ .attr = { .name = "phc_version", .mode = 0444 },
++ .show = show_freq_attr_phc_version,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_vids =
++{
++ /*display phc's voltage id's for the cpu*/
++ .attr = { .name = "phc_vids", .mode = 0644 },
++ .show = show_freq_attr_vids,
++ .store = store_freq_attr_vids,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_vids =
++{
++ /*display acpi's default frequency id's for the cpu*/
++ .attr = { .name = "phc_default_vids", .mode = 0444 },
++ .show = show_freq_attr_default_vids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_fids =
++{
++ /*display phc's default frequency id's for the cpu*/
++ .attr = { .name = "phc_fids", .mode = 0444 },
++ .show = show_freq_attr_fids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_controls =
++{
++ /*display phc's current voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_controls", .mode = 0644 },
++ .show = show_freq_attr_controls,
++ .store = store_freq_attr_controls,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_controls =
++{
++ /*display acpi's default voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_default_controls", .mode = 0444 },
++ .show = show_freq_attr_default_controls,
++ .store = NULL,
++};
++
+ static struct freq_attr *acpi_cpufreq_attr[] = {
+- &cpufreq_freq_attr_scaling_available_freqs,
++ &cpufreq_freq_attr_scaling_available_freqs,
++ &cpufreq_freq_attr_phc_version,
++ &cpufreq_freq_attr_vids,
++ &cpufreq_freq_attr_default_vids,
++ &cpufreq_freq_attr_fids,
++ &cpufreq_freq_attr_controls,
++ &cpufreq_freq_attr_default_controls,
+ NULL,
+ };
+
diff --git a/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.37.patch b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.37.patch
new file mode 100644
index 000000000000..233c322be5a8
--- /dev/null
+++ b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.37.patch
@@ -0,0 +1,530 @@
+--- linux-2.6.37-gentoo/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
++++ phc-intel-0.3.2-12-1/phc-intel.c
+@@ -25,6 +25,10 @@
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
++/* This file has been patched with Linux PHC: www.linux-phc.org
++* Patch version: linux-phc-0.3.2
++*/
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -61,12 +65,17 @@
+ };
+
+ #define INTEL_MSR_RANGE (0xffff)
++#define INTEL_MSR_VID_MASK (0x00ff)
++#define INTEL_MSR_FID_MASK (0xff00)
++#define INTEL_MSR_FID_SHIFT (0x8)
++#define PHC_VERSION_STRING "0.3.2:2"
+
+ struct acpi_cpufreq_data {
+ struct acpi_processor_performance *acpi_data;
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int resume;
+ unsigned int cpu_feature;
++ acpi_integer *original_controls;
+ };
+
+ static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
+@@ -102,13 +111,14 @@
+ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
+ {
+ int i;
++ u32 fid;
+ struct acpi_processor_performance *perf;
+
+- msr &= INTEL_MSR_RANGE;
++ fid = msr & INTEL_MSR_FID_MASK;
+ perf = data->acpi_data;
+
+ for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+- if (msr == perf->states[data->freq_table[i].index].status)
++ if (fid == (perf->states[data->freq_table[i].index].status & INTEL_MSR_FID_MASK))
+ return data->freq_table[i].frequency;
+ }
+ return data->freq_table[0].frequency;
+@@ -701,6 +711,8 @@
+ per_cpu(acfreq_data, policy->cpu) = NULL;
+ acpi_processor_unregister_performance(data->acpi_data,
+ policy->cpu);
++ if (data->original_controls)
++ kfree(data->original_controls);
+ kfree(data->freq_table);
+ kfree(data);
+ }
+@@ -719,8 +731,472 @@
+ return 0;
+ }
+
++/* sysfs interface to change operating points voltages */
++
++static unsigned int extract_fid_from_control(unsigned int control)
++{
++ return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT);
++}
++
++static unsigned int extract_vid_from_control(unsigned int control)
++{
++ return (control & INTEL_MSR_VID_MASK);
++}
++
++
++static bool check_cpu_control_capability(struct acpi_cpufreq_data *data) {
++ /* check if the cpu we are running on is capable of setting new control data
++ *
++ */
++ if (unlikely(data == NULL ||
++ data->acpi_data == NULL ||
++ data->freq_table == NULL ||
++ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
++ return false;
++ } else {
++ return true;
++ };
++}
++
++
++static ssize_t check_origial_table (struct acpi_cpufreq_data *data)
++{
++
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int state_index;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ if (data->original_controls == NULL) {
++ // Backup original control values
++ data->original_controls = kcalloc(acpi_data->state_count,
++ sizeof(acpi_integer), GFP_KERNEL);
++ if (data->original_controls == NULL) {
++ printk("failed to allocate memory for original control values\n");
++ return -ENOMEM;
++ }
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ data->original_controls[state_index] = acpi_data->states[state_index].control;
++ }
++ }
++ return 0;
++}
++
++static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's frequeny id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", fid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf)
++ /* display phc's controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ if (count)
++ count += sprintf(&buf[count], " ");
++ count += sprintf(&buf[count], "%u:%u", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(data->original_controls[freq_table[i].index]);
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u:%u ", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++
++static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the voltage id's for the related frequency
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int freq_index;
++ unsigned int state_index;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_control;
++ unsigned int original_control;
++ const char *curr_buf = buf;
++ char *next_buf;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ /* for each value taken from the sysfs interfalce (phc_vids) get entrys and convert them to unsigned long integers*/
++ for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) {
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if (next_buf == curr_buf) {
++ if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) { //end of line?
++ curr_buf++;
++ break;
++ }
++ //if we didn't got end of line but there is nothing more to read something went wrong...
++ printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf);
++ return -EINVAL;
++ }
++
++ state_index = freq_table[freq_index].index;
++ original_control = data->original_controls[state_index];
++ original_vid = original_control & INTEL_MSR_VID_MASK;
++
++ /* before we store the values we do some checks to prevent
++ * users to set up values higher than the default one
++ */
++ if (new_vid <= original_vid) {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ pr_debug("setting control at %i to %x (default is %x)\n",
++ freq_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ pr_debug("skipping vid at %i, %u is greater than default %u\n",
++ freq_index, new_vid, original_vid);
++ }
++
++ curr_buf = next_buf;
++ /* jump over value seperators (space or comma).
++ * There could be more than one space or comma character
++ * to separate two values so we better do it using a loop.
++ */
++ while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) {
++ curr_buf++;
++ }
++ }
++
++ /* set new voltage for current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++
++ return curr_buf - buf;
++}
++
++static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the controls (frequency id's and related voltage id's)
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ const char *curr_buf;
++ unsigned int op_count;
++ unsigned int state_index;
++ int isok;
++ char *next_buf;
++ ssize_t retval;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_fid;
++ unsigned int old_fid;
++ unsigned int original_control;
++ unsigned int old_control;
++ unsigned int new_control;
++ int found;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV;
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ op_count = 0;
++ curr_buf = buf;
++ next_buf = NULL;
++ isok = 1;
++
++ while ( (isok) && (curr_buf != NULL) )
++ {
++ op_count++;
++ // Parse fid
++ new_fid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ // Parse separator between frequency and voltage
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if (*curr_buf==':')
++ {
++ curr_buf++;
++ // Parse vid
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ found = 0;
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ old_control = acpi_data->states[state_index].control;
++ old_fid = extract_fid_from_control(old_control);
++ if (new_fid == old_fid)
++ {
++ found = 1;
++ original_control = data->original_controls[state_index];
++ original_vid = extract_vid_from_control(original_control);
++ if (new_vid <= original_vid)
++ {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ pr_debug("setting control at %i to %x (default is %x)\n",
++ state_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ printk("skipping vid at %i, %u is greater than default %u\n",
++ state_index, new_vid, original_vid);
++ }
++ }
++ }
++
++ if (found == 0)
++ {
++ printk("operating point # %u not found (FID = %u)\n", op_count, new_fid);
++ isok = 0;
++ }
++
++ // Parse seprator before next operating point, if any
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if ((*curr_buf == ',') || (*curr_buf == ' '))
++ curr_buf++;
++ else
++ curr_buf = NULL;
++ }
++ else
++ {
++ printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++
++ if (isok)
++ {
++ retval = count;
++ /* set new voltage at current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++ }
++ else
++ {
++ retval = -EINVAL;
++ }
++
++ return retval;
++}
++
++static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf)
++ /* print out the phc version string set at the beginning of that file
++ */
++{
++ ssize_t count = 0;
++ count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING);
++ return count;
++}
++
++
++
++static struct freq_attr cpufreq_freq_attr_phc_version =
++{
++ /*display phc's version string*/
++ .attr = { .name = "phc_version", .mode = 0444 },
++ .show = show_freq_attr_phc_version,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_vids =
++{
++ /*display phc's voltage id's for the cpu*/
++ .attr = { .name = "phc_vids", .mode = 0644 },
++ .show = show_freq_attr_vids,
++ .store = store_freq_attr_vids,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_vids =
++{
++ /*display acpi's default frequency id's for the cpu*/
++ .attr = { .name = "phc_default_vids", .mode = 0444 },
++ .show = show_freq_attr_default_vids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_fids =
++{
++ /*display phc's default frequency id's for the cpu*/
++ .attr = { .name = "phc_fids", .mode = 0444 },
++ .show = show_freq_attr_fids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_controls =
++{
++ /*display phc's current voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_controls", .mode = 0644 },
++ .show = show_freq_attr_controls,
++ .store = store_freq_attr_controls,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_controls =
++{
++ /*display acpi's default voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_default_controls", .mode = 0444 },
++ .show = show_freq_attr_default_controls,
++ .store = NULL,
++};
++
++
+ static struct freq_attr *acpi_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
++ &cpufreq_freq_attr_phc_version,
++ &cpufreq_freq_attr_vids,
++ &cpufreq_freq_attr_default_vids,
++ &cpufreq_freq_attr_fids,
++ &cpufreq_freq_attr_controls,
++ &cpufreq_freq_attr_default_controls,
+ NULL,
+ };
+
diff --git a/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-3.7.patch b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-3.7.patch
new file mode 100644
index 000000000000..5f06f54136ba
--- /dev/null
+++ b/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-3.7.patch
@@ -0,0 +1,536 @@
+--- hc-intel-0.3.2-12-1/phc-intel.c
++++ hc-intel-0.3.2-12-1/phc-intel.c
+@@ -25,6 +25,10 @@
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
++/* This file has been patched with Linux PHC: www.linux-phc.org
++* Patch version: linux-phc-0.3.2
++*/
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -61,6 +65,10 @@ enum {
+ };
+
+ #define INTEL_MSR_RANGE (0xffff)
++#define INTEL_MSR_VID_MASK (0x00ff)
++#define INTEL_MSR_FID_MASK (0xff00)
++#define INTEL_MSR_FID_SHIFT (0x8)
++#define PHC_VERSION_STRING "0.3.2:2"
+ #define AMD_MSR_RANGE (0x7)
+
+ #define MSR_K7_HWCR_CPB_DIS (1ULL << 25)
+@@ -70,6 +78,7 @@ struct acpi_cpufreq_data {
+ struct cpufreq_frequency_table *freq_table;
+ unsigned int resume;
+ unsigned int cpu_feature;
++ acpi_integer *original_controls;
+ };
+
+ static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data);
+@@ -222,17 +231,18 @@ static unsigned extract_io(u32 value, st
+ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
+ {
+ int i;
++ u32 fid;
+ struct acpi_processor_performance *perf;
+
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ msr &= AMD_MSR_RANGE;
+ else
+- msr &= INTEL_MSR_RANGE;
++ fid = msr & INTEL_MSR_FID_MASK;
+
+ perf = data->acpi_data;
+
+ for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+- if (msr == perf->states[data->freq_table[i].index].status)
++ if (fid == (perf->states[data->freq_table[i].index].status & INTEL_MSR_FID_MASK))
+ return data->freq_table[i].frequency;
+ }
+ return data->freq_table[0].frequency;
+@@ -868,6 +878,8 @@ static int acpi_cpufreq_cpu_init(struct
+ return result;
+
+ err_freqfree:
++ if (data->original_controls)
++ kfree(data->original_controls);
+ kfree(data->freq_table);
+ err_unreg:
+ acpi_processor_unregister_performance(perf, cpu);
+@@ -907,8 +919,473 @@ static int acpi_cpufreq_resume(struct cp
+ return 0;
+ }
+
++/* sysfs interface to change operating points voltages */
++
++static unsigned int extract_fid_from_control(unsigned int control)
++{
++ return ((control & INTEL_MSR_FID_MASK) >> INTEL_MSR_FID_SHIFT);
++}
++
++static unsigned int extract_vid_from_control(unsigned int control)
++{
++ return (control & INTEL_MSR_VID_MASK);
++}
++
++
++static bool check_cpu_control_capability(struct acpi_cpufreq_data *data) {
++ /* check if the cpu we are running on is capable of setting new control data
++ *
++ */
++ if (unlikely(data == NULL ||
++ data->acpi_data == NULL ||
++ data->freq_table == NULL ||
++ data->cpu_feature != SYSTEM_INTEL_MSR_CAPABLE)) {
++ return false;
++ } else {
++ return true;
++ };
++}
++
++
++static ssize_t check_origial_table (struct acpi_cpufreq_data *data)
++{
++
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int state_index;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ if (data->original_controls == NULL) {
++ // Backup original control values
++ data->original_controls = kcalloc(acpi_data->state_count,
++ sizeof(acpi_integer), GFP_KERNEL);
++ if (data->original_controls == NULL) {
++ printk("failed to allocate memory for original control values\n");
++ return -ENOMEM;
++ }
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ data->original_controls[state_index] = acpi_data->states[state_index].control;
++ }
++ }
++ return 0;
++}
++
++static ssize_t show_freq_attr_vids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_vids(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default voltage id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u ", vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_fids(struct cpufreq_policy *policy, char *buf)
++ /* display phc's frequeny id's
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ count += sprintf(&buf[count], "%u ", fid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_controls(struct cpufreq_policy *policy, char *buf)
++ /* display phc's controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(acpi_data->states[freq_table[i].index].control);
++ vid = extract_vid_from_control(acpi_data->states[freq_table[i].index].control);
++ if (count)
++ count += sprintf(&buf[count], " ");
++ count += sprintf(&buf[count], "%u:%u", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++static ssize_t show_freq_attr_default_controls(struct cpufreq_policy *policy, char *buf)
++ /* display acpi's default controls for the cpu (frequency id's and related voltage id's)
++ *
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int i;
++ unsigned int fid;
++ unsigned int vid;
++ ssize_t count = 0;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ freq_table = data->freq_table;
++
++ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
++ fid = extract_fid_from_control(data->original_controls[freq_table[i].index]);
++ vid = extract_vid_from_control(data->original_controls[freq_table[i].index]);
++ count += sprintf(&buf[count], "%u:%u ", fid, vid);
++ }
++ count += sprintf(&buf[count], "\n");
++
++ return count;
++}
++
++
++static ssize_t store_freq_attr_vids(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the voltage id's for the related frequency
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ unsigned int freq_index;
++ unsigned int state_index;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_control;
++ unsigned int original_control;
++ const char *curr_buf = buf;
++ char *next_buf;
++ ssize_t retval;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV; //check if CPU is capable of changing controls
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ /* for each value taken from the sysfs interfalce (phc_vids) get entrys and convert them to unsigned long integers*/
++ for (freq_index = 0; freq_table[freq_index].frequency != CPUFREQ_TABLE_END; freq_index++) {
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if (next_buf == curr_buf) {
++ if ((curr_buf - buf == count - 1) && (*curr_buf == '\n')) { //end of line?
++ curr_buf++;
++ break;
++ }
++ //if we didn't got end of line but there is nothing more to read something went wrong...
++ printk("failed to parse vid value at %i (%s)\n", freq_index, curr_buf);
++ return -EINVAL;
++ }
++
++ state_index = freq_table[freq_index].index;
++ original_control = data->original_controls[state_index];
++ original_vid = original_control & INTEL_MSR_VID_MASK;
++
++ /* before we store the values we do some checks to prevent
++ * users to set up values higher than the default one
++ */
++ if (new_vid <= original_vid) {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ pr_debug("setting control at %i to %x (default is %x)\n",
++ freq_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ pr_debug("skipping vid at %i, %u is greater than default %u\n",
++ freq_index, new_vid, original_vid);
++ }
++
++ curr_buf = next_buf;
++ /* jump over value seperators (space or comma).
++ * There could be more than one space or comma character
++ * to separate two values so we better do it using a loop.
++ */
++ while ((curr_buf - buf < count) && ((*curr_buf == ' ') || (*curr_buf == ','))) {
++ curr_buf++;
++ }
++ }
++
++ /* set new voltage for current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++
++ return curr_buf - buf;
++}
++
++static ssize_t store_freq_attr_controls(struct cpufreq_policy *policy, const char *buf, size_t count)
++ /* store the controls (frequency id's and related voltage id's)
++ * We are going to do some sanity checks here to prevent users
++ * from setting higher voltages than the default one.
++ */
++{
++ struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
++ struct acpi_processor_performance *acpi_data;
++ struct cpufreq_frequency_table *freq_table;
++ const char *curr_buf;
++ unsigned int op_count;
++ unsigned int state_index;
++ int isok;
++ char *next_buf;
++ ssize_t retval;
++ unsigned int new_vid;
++ unsigned int original_vid;
++ unsigned int new_fid;
++ unsigned int old_fid;
++ unsigned int original_control;
++ unsigned int old_control;
++ unsigned int new_control;
++ int found;
++
++ if (!check_cpu_control_capability(data)) return -ENODEV;
++
++ retval = check_origial_table(data);
++ if (0 != retval)
++ return retval;
++
++ acpi_data = data->acpi_data;
++ freq_table = data->freq_table;
++
++ op_count = 0;
++ curr_buf = buf;
++ next_buf = NULL;
++ isok = 1;
++
++ while ( (isok) && (curr_buf != NULL) )
++ {
++ op_count++;
++ // Parse fid
++ new_fid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ // Parse separator between frequency and voltage
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if (*curr_buf==':')
++ {
++ curr_buf++;
++ // Parse vid
++ new_vid = simple_strtoul(curr_buf, &next_buf, 10);
++ if ((next_buf != curr_buf) && (next_buf != NULL))
++ {
++ found = 0;
++ for (state_index = 0; state_index < acpi_data->state_count; state_index++) {
++ old_control = acpi_data->states[state_index].control;
++ old_fid = extract_fid_from_control(old_control);
++ if (new_fid == old_fid)
++ {
++ found = 1;
++ original_control = data->original_controls[state_index];
++ original_vid = extract_vid_from_control(original_control);
++ if (new_vid <= original_vid)
++ {
++ new_control = (original_control & ~INTEL_MSR_VID_MASK) | new_vid;
++ pr_debug("setting control at %i to %x (default is %x)\n",
++ state_index, new_control, original_control);
++ acpi_data->states[state_index].control = new_control;
++
++ } else {
++ printk("skipping vid at %i, %u is greater than default %u\n",
++ state_index, new_vid, original_vid);
++ }
++ }
++ }
++
++ if (found == 0)
++ {
++ printk("operating point # %u not found (FID = %u)\n", op_count, new_fid);
++ isok = 0;
++ }
++
++ // Parse seprator before next operating point, if any
++ curr_buf = next_buf;
++ next_buf = NULL;
++ if ((*curr_buf == ',') || (*curr_buf == ' '))
++ curr_buf++;
++ else
++ curr_buf = NULL;
++ }
++ else
++ {
++ printk("failed to parse VID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++ else
++ {
++ printk("failed to parse FID of operating point # %u (%s)\n", op_count, curr_buf);
++ isok = 0;
++ }
++ }
++
++ if (isok)
++ {
++ retval = count;
++ /* set new voltage at current frequency */
++ data->resume = 1;
++ acpi_cpufreq_target(policy, get_cur_freq_on_cpu(policy->cpu), CPUFREQ_RELATION_L);
++ }
++ else
++ {
++ retval = -EINVAL;
++ }
++
++ return retval;
++}
++
++static ssize_t show_freq_attr_phc_version(struct cpufreq_policy *policy, char *buf)
++ /* print out the phc version string set at the beginning of that file
++ */
++{
++ ssize_t count = 0;
++ count += sprintf(&buf[count], "%s\n", PHC_VERSION_STRING);
++ return count;
++}
++
++
++
++static struct freq_attr cpufreq_freq_attr_phc_version =
++{
++ /*display phc's version string*/
++ .attr = { .name = "phc_version", .mode = 0444 },
++ .show = show_freq_attr_phc_version,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_vids =
++{
++ /*display phc's voltage id's for the cpu*/
++ .attr = { .name = "phc_vids", .mode = 0644 },
++ .show = show_freq_attr_vids,
++ .store = store_freq_attr_vids,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_vids =
++{
++ /*display acpi's default frequency id's for the cpu*/
++ .attr = { .name = "phc_default_vids", .mode = 0444 },
++ .show = show_freq_attr_default_vids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_fids =
++{
++ /*display phc's default frequency id's for the cpu*/
++ .attr = { .name = "phc_fids", .mode = 0444 },
++ .show = show_freq_attr_fids,
++ .store = NULL,
++};
++
++static struct freq_attr cpufreq_freq_attr_controls =
++{
++ /*display phc's current voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_controls", .mode = 0644 },
++ .show = show_freq_attr_controls,
++ .store = store_freq_attr_controls,
++};
++
++static struct freq_attr cpufreq_freq_attr_default_controls =
++{
++ /*display acpi's default voltage/frequency controls for the cpu*/
++ .attr = { .name = "phc_default_controls", .mode = 0444 },
++ .show = show_freq_attr_default_controls,
++ .store = NULL,
++};
++
++
++
+ static struct freq_attr *acpi_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
++ &cpufreq_freq_attr_phc_version,
++ &cpufreq_freq_attr_vids,
++ &cpufreq_freq_attr_default_vids,
++ &cpufreq_freq_attr_fids,
++ &cpufreq_freq_attr_controls,
++ &cpufreq_freq_attr_default_controls,
+ NULL, /* this is a placeholder for cpb, do not remove */
+ NULL,
+ };
diff --git a/sys-power/phc-intel/phc-intel-0.3.2.12.1-r5.ebuild b/sys-power/phc-intel/phc-intel-0.3.2.12.1-r5.ebuild
new file mode 100644
index 000000000000..6acb5784c820
--- /dev/null
+++ b/sys-power/phc-intel/phc-intel-0.3.2.12.1-r5.ebuild
@@ -0,0 +1,60 @@
+# Copyright 1999-2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-power/phc-intel/phc-intel-0.3.2.12.1-r5.ebuild,v 1.1 2012/12/17 07:20:10 xmw Exp $
+
+EAPI=2
+
+inherit linux-info linux-mod versionator eutils
+
+DESCRIPTION="Processor Hardware Control for Intel CPUs"
+HOMEPAGE="http://www.linux-phc.org/"
+SRC_URI="http://www.linux-phc.org/forum/download/file.php?id=94 -> ${P}.tar.bz2"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+
+S=${WORKDIR}/${PN}-$(replace_version_separator 3 '-' $(replace_version_separator 4 '-'))
+
+CONFIG_CHECK="~!X86_ACPI_CPUFREQ"
+ERROR_X86_ACPI_CPUFREQ="CONFIG_X86_ACPI_CPUFREQ has to be configured to Module to enable the replacement of acpi-cpufreq with phc-intel."
+
+MODULE_NAMES="phc-intel(misc:)"
+BUILD_PARAMS="KERNELSRC=\"${KERNEL_DIR}\" -j1"
+BUILD_TARGETS="all"
+
+pkg_setup() {
+ if kernel_is lt 2 6 33 ; then
+ eerror "Your kernel version is no longer supported by this version of ${PN}."
+ eerror "Please use a previous version of ${PN} or a newer kernel."
+ die
+ fi
+ linux-mod_pkg_setup
+}
+
+src_prepare() {
+ sed -e '/^all:/s:prepare::' \
+ -e '/error Only support for 2.6 series kernels/d' \
+ -i Makefile || die
+
+ local my_sub=arch/x86/kernel/cpu
+ if kernel_is gt 2 6 39 ; then
+ my_sub=drivers
+ fi
+ cp -v "${KERNEL_DIR}"/${my_sub}/cpufreq/acpi-cpufreq.c phc-intel.c || die
+ cp -v "${KERNEL_DIR}"/${my_sub}/cpufreq/mperf.h . || die
+
+ if kernel_is eq 2 6 35 || kernel_is eq 2 6 36 ; then
+ epatch "${FILESDIR}"/${PF}-${KV_MAJOR}.${KV_MINOR}.${KV_PATCH}.patch
+ elif kernel_is lt 3 7 ; then
+ epatch "${FILESDIR}"/${PF}-2.6.37.patch
+ else
+ epatch "${FILESDIR}"/${PF}-3.7.patch
+ fi
+}
+
+src_install() {
+ linux-mod_src_install
+ dodoc README || die
+}