From: Greg Kroah-Hartman Date: Thu, 10 Apr 2014 03:16:14 +0000 (-0700) Subject: 3.13-stable patches X-Git-Tag: v3.10.37~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=712a81e180e551cb7c1e88390b4d04f2b9a23cd8;p=thirdparty%2Fkernel%2Fstable-queue.git 3.13-stable patches added patches: powernow-k6-correctly-initialize-default-parameters.patch powernow-k6-disable-cache-when-changing-frequency.patch powernow-k6-reorder-frequencies.patch --- diff --git a/queue-3.13/powernow-k6-correctly-initialize-default-parameters.patch b/queue-3.13/powernow-k6-correctly-initialize-default-parameters.patch new file mode 100644 index 00000000000..88f6afff58e --- /dev/null +++ b/queue-3.13/powernow-k6-correctly-initialize-default-parameters.patch @@ -0,0 +1,151 @@ +From d82b922a4acc1781d368aceac2f9da43b038cab2 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 11 Dec 2013 19:38:53 -0500 +Subject: powernow-k6: correctly initialize default parameters + +From: Mikulas Patocka + +commit d82b922a4acc1781d368aceac2f9da43b038cab2 upstream. + +The powernow-k6 driver used to read the initial multiplier from the +powernow register. However, there is a problem with this: + +* If there was a frequency transition before, the multiplier read from the + register corresponds to the current multiplier. +* If there was no frequency transition since reset, the field in the + register always reads as zero, regardless of the current multiplier that + is set using switches on the mainboard and that the CPU is running at. + +The zero value corresponds to multiplier 4.5, so as a consequence, the +powernow-k6 driver always assumes multiplier 4.5. + +For example, if we have 550MHz CPU with bus frequency 100MHz and +multiplier 5.5, the powernow-k6 driver thinks that the multiplier is 4.5 +and bus frequency is 122MHz. The powernow-k6 driver then sets the +multiplier to 4.5, underclocking the CPU to 450MHz, but reports the +current frequency as 550MHz. + +There is no reliable way how to read the initial multiplier. I modified +the driver so that it contains a table of known frequencies (based on +parameters of existing CPUs and some common overclocking schemes) and sets +the multiplier according to the frequency. If the frequency is unknown +(because of unusual overclocking or underclocking), the user must supply +the bus speed and maximum multiplier as module parameters. + +This patch should be backported to all stable kernels. If it doesn't +apply cleanly, change it, or ask me to change it. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpufreq/powernow-k6.c | 76 +++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 72 insertions(+), 4 deletions(-) + +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -26,6 +26,14 @@ + static unsigned int busfreq; /* FSB, in 10 kHz */ + static unsigned int max_multiplier; + ++static unsigned int param_busfreq = 0; ++static unsigned int param_max_multiplier = 0; ++ ++module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO); ++MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)"); ++ ++module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO); ++MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz"); + + /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ + static struct cpufreq_frequency_table clock_ratio[] = { +@@ -40,6 +48,27 @@ static struct cpufreq_frequency_table cl + {0, CPUFREQ_TABLE_END} + }; + ++static const struct { ++ unsigned freq; ++ unsigned mult; ++} usual_frequency_table[] = { ++ { 400000, 40 }, // 100 * 4 ++ { 450000, 45 }, // 100 * 4.5 ++ { 475000, 50 }, // 95 * 5 ++ { 500000, 50 }, // 100 * 5 ++ { 506250, 45 }, // 112.5 * 4.5 ++ { 533500, 55 }, // 97 * 5.5 ++ { 550000, 55 }, // 100 * 5.5 ++ { 562500, 50 }, // 112.5 * 5 ++ { 570000, 60 }, // 95 * 6 ++ { 600000, 60 }, // 100 * 6 ++ { 618750, 55 }, // 112.5 * 5.5 ++ { 660000, 55 }, // 120 * 5.5 ++ { 675000, 60 }, // 112.5 * 6 ++ { 720000, 60 }, // 120 * 6 ++}; ++ ++#define FREQ_RANGE 3000 + + /** + * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier +@@ -125,17 +154,56 @@ static int powernow_k6_target(struct cpu + return 0; + } + +- + static int powernow_k6_cpu_init(struct cpufreq_policy *policy) + { + unsigned int i, f; ++ unsigned khz; + + if (policy->cpu != 0) + return -ENODEV; + +- /* get frequencies */ +- max_multiplier = powernow_k6_get_cpu_multiplier(); +- busfreq = cpu_khz / max_multiplier; ++ max_multiplier = 0; ++ khz = cpu_khz; ++ for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) { ++ if (khz >= usual_frequency_table[i].freq - FREQ_RANGE && ++ khz <= usual_frequency_table[i].freq + FREQ_RANGE) { ++ khz = usual_frequency_table[i].freq; ++ max_multiplier = usual_frequency_table[i].mult; ++ break; ++ } ++ } ++ if (param_max_multiplier) { ++ for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { ++ if (clock_ratio[i].driver_data == param_max_multiplier) { ++ max_multiplier = param_max_multiplier; ++ goto have_max_multiplier; ++ } ++ } ++ printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n"); ++ return -EINVAL; ++ } ++ ++ if (!max_multiplier) { ++ printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz); ++ printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n"); ++ return -EOPNOTSUPP; ++ } ++ ++have_max_multiplier: ++ param_max_multiplier = max_multiplier; ++ ++ if (param_busfreq) { ++ if (param_busfreq >= 50000 && param_busfreq <= 150000) { ++ busfreq = param_busfreq / 10; ++ goto have_busfreq; ++ } ++ printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n"); ++ return -EINVAL; ++ } ++ ++ busfreq = khz / max_multiplier; ++have_busfreq: ++ param_busfreq = busfreq * 10; + + /* table init */ + for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { diff --git a/queue-3.13/powernow-k6-disable-cache-when-changing-frequency.patch b/queue-3.13/powernow-k6-disable-cache-when-changing-frequency.patch new file mode 100644 index 00000000000..efd9f7d093c --- /dev/null +++ b/queue-3.13/powernow-k6-disable-cache-when-changing-frequency.patch @@ -0,0 +1,144 @@ +From e20e1d0ac02308e2211306fc67abcd0b2668fb8b Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 11 Dec 2013 19:38:32 -0500 +Subject: powernow-k6: disable cache when changing frequency + +From: Mikulas Patocka + +commit e20e1d0ac02308e2211306fc67abcd0b2668fb8b upstream. + +I found out that a system with k6-3+ processor is unstable during network +server load. The system locks up or the network card stops receiving. The +reason for the instability is the CPU frequency scaling. + +During frequency transition the processor is in "EPM Stop Grant" state. +The documentation says that the processor doesn't respond to inquiry +requests in this state. Consequently, coherency of processor caches and +bus master devices is not maintained, causing the system instability. + +This patch flushes the cache during frequency transition. It fixes the +instability. + +Other minor changes: +* u64 invalue changed to unsigned long because the variable is 32-bit +* move the logic to set the multiplier to a separate function + powernow_k6_set_cpu_multiplier +* preserve lower 5 bits of the powernow port instead of 4 (the voltage + field has 5 bits) +* mask interrupts when reading the multiplier, so that the port is not + open during other activity (running other kernel code with the port open + shouldn't cause any misbehavior, but we should better be safe and keep + the port closed) + +This patch should be backported to all stable kernels. If it doesn't +apply cleanly, change it, or ask me to change it. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpufreq/powernow-k6.c | 56 +++++++++++++++++++++++++++++------------- + 1 file changed, 39 insertions(+), 17 deletions(-) + +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -44,23 +44,58 @@ static struct cpufreq_frequency_table cl + /** + * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier + * +- * Returns the current setting of the frequency multiplier. Core clock ++ * Returns the current setting of the frequency multiplier. Core clock + * speed is frequency of the Front-Side Bus multiplied with this value. + */ + static int powernow_k6_get_cpu_multiplier(void) + { +- u64 invalue = 0; ++ unsigned long invalue = 0; + u32 msrval; + ++ local_irq_disable(); ++ + msrval = POWERNOW_IOPORT + 0x1; + wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ + invalue = inl(POWERNOW_IOPORT + 0x8); + msrval = POWERNOW_IOPORT + 0x0; + wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ + ++ local_irq_enable(); ++ + return clock_ratio[(invalue >> 5)&7].driver_data; + } + ++static void powernow_k6_set_cpu_multiplier(unsigned int best_i) ++{ ++ unsigned long outvalue, invalue; ++ unsigned long msrval; ++ unsigned long cr0; ++ ++ /* we now need to transform best_i to the BVC format, see AMD#23446 */ ++ ++ /* ++ * The processor doesn't respond to inquiry cycles while changing the ++ * frequency, so we must disable cache. ++ */ ++ local_irq_disable(); ++ cr0 = read_cr0(); ++ write_cr0(cr0 | X86_CR0_CD); ++ wbinvd(); ++ ++ outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); ++ ++ msrval = POWERNOW_IOPORT + 0x1; ++ wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ ++ invalue = inl(POWERNOW_IOPORT + 0x8); ++ invalue = invalue & 0x1f; ++ outvalue = outvalue | invalue; ++ outl(outvalue, (POWERNOW_IOPORT + 0x8)); ++ msrval = POWERNOW_IOPORT + 0x0; ++ wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ ++ ++ write_cr0(cr0); ++ local_irq_enable(); ++} + + /** + * powernow_k6_target - set the PowerNow! multiplier +@@ -71,8 +106,6 @@ static int powernow_k6_get_cpu_multiplie + static int powernow_k6_target(struct cpufreq_policy *policy, + unsigned int best_i) + { +- unsigned long outvalue = 0, invalue = 0; +- unsigned long msrval; + struct cpufreq_freqs freqs; + + if (clock_ratio[best_i].driver_data > max_multiplier) { +@@ -85,18 +118,7 @@ static int powernow_k6_target(struct cpu + + cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); + +- /* we now need to transform best_i to the BVC format, see AMD#23446 */ +- +- outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); +- +- msrval = POWERNOW_IOPORT + 0x1; +- wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ +- invalue = inl(POWERNOW_IOPORT + 0x8); +- invalue = invalue & 0xf; +- outvalue = outvalue | invalue; +- outl(outvalue , (POWERNOW_IOPORT + 0x8)); +- msrval = POWERNOW_IOPORT + 0x0; +- wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */ ++ powernow_k6_set_cpu_multiplier(best_i); + + cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); + +@@ -125,7 +147,7 @@ static int powernow_k6_cpu_init(struct c + } + + /* cpuinfo and default policy values */ +- policy->cpuinfo.transition_latency = 200000; ++ policy->cpuinfo.transition_latency = 500000; + + return cpufreq_table_validate_and_show(policy, clock_ratio); + } diff --git a/queue-3.13/powernow-k6-reorder-frequencies.patch b/queue-3.13/powernow-k6-reorder-frequencies.patch new file mode 100644 index 00000000000..0b59c75788c --- /dev/null +++ b/queue-3.13/powernow-k6-reorder-frequencies.patch @@ -0,0 +1,67 @@ +From 22c73795b101597051924556dce019385a1e2fa0 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Wed, 11 Dec 2013 19:39:19 -0500 +Subject: powernow-k6: reorder frequencies + +From: Mikulas Patocka + +commit 22c73795b101597051924556dce019385a1e2fa0 upstream. + +This patch reorders reported frequencies from the highest to the lowest, +just like in other frequency drivers. + +Signed-off-by: Mikulas Patocka +Acked-by: Viresh Kumar +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpufreq/powernow-k6.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/cpufreq/powernow-k6.c ++++ b/drivers/cpufreq/powernow-k6.c +@@ -37,17 +37,20 @@ MODULE_PARM_DESC(bus_frequency, "Bus fre + + /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ + static struct cpufreq_frequency_table clock_ratio[] = { +- {45, /* 000 -> 4.5x */ 0}, ++ {60, /* 110 -> 6.0x */ 0}, ++ {55, /* 011 -> 5.5x */ 0}, + {50, /* 001 -> 5.0x */ 0}, ++ {45, /* 000 -> 4.5x */ 0}, + {40, /* 010 -> 4.0x */ 0}, +- {55, /* 011 -> 5.5x */ 0}, +- {20, /* 100 -> 2.0x */ 0}, +- {30, /* 101 -> 3.0x */ 0}, +- {60, /* 110 -> 6.0x */ 0}, + {35, /* 111 -> 3.5x */ 0}, ++ {30, /* 101 -> 3.0x */ 0}, ++ {20, /* 100 -> 2.0x */ 0}, + {0, CPUFREQ_TABLE_END} + }; + ++static const u8 index_to_register[8] = { 6, 3, 1, 0, 2, 7, 5, 4 }; ++static const u8 register_to_index[8] = { 3, 2, 4, 1, 7, 6, 0, 5 }; ++ + static const struct { + unsigned freq; + unsigned mult; +@@ -91,7 +94,7 @@ static int powernow_k6_get_cpu_multiplie + + local_irq_enable(); + +- return clock_ratio[(invalue >> 5)&7].driver_data; ++ return clock_ratio[register_to_index[(invalue >> 5)&7]].driver_data; + } + + static void powernow_k6_set_cpu_multiplier(unsigned int best_i) +@@ -111,7 +114,7 @@ static void powernow_k6_set_cpu_multipli + write_cr0(cr0 | X86_CR0_CD); + wbinvd(); + +- outvalue = (1<<12) | (1<<10) | (1<<9) | (best_i<<5); ++ outvalue = (1<<12) | (1<<10) | (1<<9) | (index_to_register[best_i]<<5); + + msrval = POWERNOW_IOPORT + 0x1; + wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */ diff --git a/queue-3.13/series b/queue-3.13/series index d6cfdf54fe8..0dc05c05abc 100644 --- a/queue-3.13/series +++ b/queue-3.13/series @@ -1 +1,4 @@ selinux-correctly-label-proc-inodes-in-use-before-the-policy-is-loaded.patch +powernow-k6-disable-cache-when-changing-frequency.patch +powernow-k6-correctly-initialize-default-parameters.patch +powernow-k6-reorder-frequencies.patch