* [gentoo-commits] gentoo-x86 commit in sys-power/phc-intel/files: phc-intel-0.3.2.12.1-2.6.39.patch
@ 2011-05-20 13:13 Michael Weber (xmw)
0 siblings, 0 replies; only message in thread
From: Michael Weber (xmw) @ 2011-05-20 13:13 UTC (permalink / raw
To: gentoo-commits
xmw 11/05/20 13:13:40
Added: phc-intel-0.3.2.12.1-2.6.39.patch
Log:
New patch set for kernel 2.6.39
(Portage version: 2.1.9.42/cvs/Linux x86_64)
Revision Changes Path
1.1 sys-power/phc-intel/files/phc-intel-0.3.2.12.1-2.6.39.patch
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-2.6.39.patch?rev=1.1&view=markup
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-power/phc-intel/files/phc-intel-0.3.2.12.1-2.6.39.patch?rev=1.1&content-type=text/plain
Index: phc-intel-0.3.2.12.1-2.6.39.patch
===================================================================
--- linux-2.6.37-gentoo/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ phc-intel-0.3.2-12-1/inc/2.6.37/acpi-cpufreq.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,470 @@
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);
+ 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_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,
};
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-05-20 13:13 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-20 13:13 [gentoo-commits] gentoo-x86 commit in sys-power/phc-intel/files: phc-intel-0.3.2.12.1-2.6.39.patch Michael Weber (xmw)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox