diff options
author | Michael Weber <xmw@gentoo.org> | 2012-12-17 07:20:10 +0000 |
---|---|---|
committer | Michael Weber <xmw@gentoo.org> | 2012-12-17 07:20:10 +0000 |
commit | a8f6a1c4f717ccf2997a9700cf9a74c046a30a34 (patch) | |
tree | 44bea46a2481e11bd0f16c6c10c19dcf54e47eb9 /sys-power | |
parent | Version bump wrt #447522 by Marcin Mirosław (diff) | |
download | gentoo-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/ChangeLog | 11 | ||||
-rw-r--r-- | sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.35.patch | 531 | ||||
-rw-r--r-- | sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.36.patch | 531 | ||||
-rw-r--r-- | sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-2.6.37.patch | 530 | ||||
-rw-r--r-- | sys-power/phc-intel/files/phc-intel-0.3.2.12.1-r5-3.7.patch | 536 | ||||
-rw-r--r-- | sys-power/phc-intel/phc-intel-0.3.2.12.1-r5.ebuild | 60 |
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 +} |