Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq: [CPUFREQ] Fix BUG: using smp_processor_id() in preemptible code [CPUFREQ] Don't export governors for default governor [CPUFREQ][6/6] cpufreq: Add idle microaccounting in ondemand governor [CPUFREQ][5/6] cpufreq: Changes to get_cpu_idle_time_us(), used by ondemand governor [CPUFREQ][4/6] cpufreq_ondemand: Parameterize down differential [CPUFREQ][3/6] cpufreq: get_cpu_idle_time() changes in ondemand for idle-microaccounting [CPUFREQ][2/6] cpufreq: Change load calculation in ondemand for software coordination [CPUFREQ][1/6] cpufreq: Add cpu number parameter to __cpufreq_driver_getavg() [CPUFREQ] use deferrable delayed work init in conservative governor [CPUFREQ] drivers/cpufreq/cpufreq.c: Adjust error handling code involving cpufreq_cpu_put [CPUFREQ] add error handling for cpufreq_register_governor() error [CPUFREQ] acpi-cpufreq: add error handling for cpufreq_register_driver() error [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/powernow-k6.c [CPUFREQ] Coding style fixes to arch/x86/kernel/cpu/cpufreq/elanfreq.c
This commit is contained in:
commit
098ef215b1
12 changed files with 205 additions and 107 deletions
|
@ -256,7 +256,8 @@ static u32 get_cur_val(const cpumask_t *mask)
|
||||||
* Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
|
* Only IA32_APERF/IA32_MPERF ratio is architecturally defined and
|
||||||
* no meaning should be associated with absolute values of these MSRs.
|
* no meaning should be associated with absolute values of these MSRs.
|
||||||
*/
|
*/
|
||||||
static unsigned int get_measured_perf(unsigned int cpu)
|
static unsigned int get_measured_perf(struct cpufreq_policy *policy,
|
||||||
|
unsigned int cpu)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -326,7 +327,7 @@ static unsigned int get_measured_perf(unsigned int cpu)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
retval = per_cpu(drv_data, cpu)->max_freq * perf_percent / 100;
|
retval = per_cpu(drv_data, policy->cpu)->max_freq * perf_percent / 100;
|
||||||
|
|
||||||
put_cpu();
|
put_cpu();
|
||||||
set_cpus_allowed_ptr(current, &saved_mask);
|
set_cpus_allowed_ptr(current, &saved_mask);
|
||||||
|
@ -785,7 +786,11 @@ static int __init acpi_cpufreq_init(void)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return cpufreq_register_driver(&acpi_cpufreq_driver);
|
ret = cpufreq_register_driver(&acpi_cpufreq_driver);
|
||||||
|
if (ret)
|
||||||
|
free_percpu(acpi_perf_data);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit acpi_cpufreq_exit(void)
|
static void __exit acpi_cpufreq_exit(void)
|
||||||
|
@ -795,8 +800,6 @@ static void __exit acpi_cpufreq_exit(void)
|
||||||
cpufreq_unregister_driver(&acpi_cpufreq_driver);
|
cpufreq_unregister_driver(&acpi_cpufreq_driver);
|
||||||
|
|
||||||
free_percpu(acpi_perf_data);
|
free_percpu(acpi_perf_data);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_param(acpi_pstate_strict, uint, 0644);
|
module_param(acpi_pstate_strict, uint, 0644);
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/timex.h>
|
#include <linux/timex.h>
|
||||||
#include <asm/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
|
#define REG_CSCIR 0x22 /* Chip Setup and Control Index Register */
|
||||||
#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */
|
#define REG_CSCDR 0x23 /* Chip Setup and Control Data Register */
|
||||||
|
@ -82,7 +82,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
|
||||||
u8 clockspeed_reg; /* Clock Speed Register */
|
u8 clockspeed_reg; /* Clock Speed Register */
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
outb_p(0x80,REG_CSCIR);
|
outb_p(0x80, REG_CSCIR);
|
||||||
clockspeed_reg = inb_p(REG_CSCDR);
|
clockspeed_reg = inb_p(REG_CSCDR);
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
|
@ -98,10 +98,10 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 33 MHz is not 32 MHz... */
|
/* 33 MHz is not 32 MHz... */
|
||||||
if ((clockspeed_reg & 0xE0)==0xA0)
|
if ((clockspeed_reg & 0xE0) == 0xA0)
|
||||||
return 33000;
|
return 33000;
|
||||||
|
|
||||||
return ((1<<((clockspeed_reg & 0xE0) >> 5)) * 1000);
|
return (1<<((clockspeed_reg & 0xE0) >> 5)) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ static unsigned int elanfreq_get_cpu_frequency(unsigned int cpu)
|
||||||
* There is no return value.
|
* There is no return value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void elanfreq_set_cpu_state (unsigned int state)
|
static void elanfreq_set_cpu_state(unsigned int state)
|
||||||
{
|
{
|
||||||
struct cpufreq_freqs freqs;
|
struct cpufreq_freqs freqs;
|
||||||
|
|
||||||
|
@ -144,20 +144,20 @@ static void elanfreq_set_cpu_state (unsigned int state)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
outb_p(0x40,REG_CSCIR); /* Disable hyperspeed mode */
|
outb_p(0x40, REG_CSCIR); /* Disable hyperspeed mode */
|
||||||
outb_p(0x00,REG_CSCDR);
|
outb_p(0x00, REG_CSCDR);
|
||||||
local_irq_enable(); /* wait till internal pipelines and */
|
local_irq_enable(); /* wait till internal pipelines and */
|
||||||
udelay(1000); /* buffers have cleaned up */
|
udelay(1000); /* buffers have cleaned up */
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
||||||
/* now, set the CPU clock speed register (0x80) */
|
/* now, set the CPU clock speed register (0x80) */
|
||||||
outb_p(0x80,REG_CSCIR);
|
outb_p(0x80, REG_CSCIR);
|
||||||
outb_p(elan_multiplier[state].val80h,REG_CSCDR);
|
outb_p(elan_multiplier[state].val80h, REG_CSCDR);
|
||||||
|
|
||||||
/* now, the hyperspeed bit in PMU Force Mode Register (0x40) */
|
/* now, the hyperspeed bit in PMU Force Mode Register (0x40) */
|
||||||
outb_p(0x40,REG_CSCIR);
|
outb_p(0x40, REG_CSCIR);
|
||||||
outb_p(elan_multiplier[state].val40h,REG_CSCDR);
|
outb_p(elan_multiplier[state].val40h, REG_CSCDR);
|
||||||
udelay(10000);
|
udelay(10000);
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
|
@ -173,12 +173,12 @@ static void elanfreq_set_cpu_state (unsigned int state)
|
||||||
* for the hardware supported by the driver.
|
* for the hardware supported by the driver.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int elanfreq_verify (struct cpufreq_policy *policy)
|
static int elanfreq_verify(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
|
return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elanfreq_target (struct cpufreq_policy *policy,
|
static int elanfreq_target(struct cpufreq_policy *policy,
|
||||||
unsigned int target_freq,
|
unsigned int target_freq,
|
||||||
unsigned int relation)
|
unsigned int relation)
|
||||||
{
|
{
|
||||||
|
@ -205,7 +205,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
/* capability check */
|
/* capability check */
|
||||||
if ((c->x86_vendor != X86_VENDOR_AMD) ||
|
if ((c->x86_vendor != X86_VENDOR_AMD) ||
|
||||||
(c->x86 != 4) || (c->x86_model!=10))
|
(c->x86 != 4) || (c->x86_model != 10))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* max freq */
|
/* max freq */
|
||||||
|
@ -213,7 +213,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
max_freq = elanfreq_get_cpu_frequency(0);
|
max_freq = elanfreq_get_cpu_frequency(0);
|
||||||
|
|
||||||
/* table init */
|
/* table init */
|
||||||
for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
|
for (i = 0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
|
||||||
if (elanfreq_table[i].frequency > max_freq)
|
if (elanfreq_table[i].frequency > max_freq)
|
||||||
elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
|
result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
|
||||||
if (result)
|
if (result)
|
||||||
return (result);
|
return result;
|
||||||
|
|
||||||
cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
|
cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -260,7 +260,7 @@ __setup("elanfreq=", elanfreq_setup);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static struct freq_attr* elanfreq_attr[] = {
|
static struct freq_attr *elanfreq_attr[] = {
|
||||||
&cpufreq_freq_attr_scaling_available_freqs,
|
&cpufreq_freq_attr_scaling_available_freqs,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
@ -284,9 +284,9 @@ static int __init elanfreq_init(void)
|
||||||
|
|
||||||
/* Test if we have the right hardware */
|
/* Test if we have the right hardware */
|
||||||
if ((c->x86_vendor != X86_VENDOR_AMD) ||
|
if ((c->x86_vendor != X86_VENDOR_AMD) ||
|
||||||
(c->x86 != 4) || (c->x86_model!=10)) {
|
(c->x86 != 4) || (c->x86_model != 10)) {
|
||||||
printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
|
printk(KERN_INFO "elanfreq: error: no Elan processor found!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
return cpufreq_register_driver(&elanfreq_driver);
|
return cpufreq_register_driver(&elanfreq_driver);
|
||||||
}
|
}
|
||||||
|
@ -298,7 +298,7 @@ static void __exit elanfreq_exit(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module_param (max_freq, int, 0444);
|
module_param(max_freq, int, 0444);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
|
MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
|
||||||
|
|
|
@ -15,12 +15,11 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
#include <asm/msr.h>
|
#include <asm/msr.h>
|
||||||
#include <asm/timex.h>
|
#include <linux/timex.h>
|
||||||
#include <asm/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long
|
||||||
#define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long
|
as it is unused */
|
||||||
as it is unused */
|
|
||||||
|
|
||||||
static unsigned int busfreq; /* FSB, in 10 kHz */
|
static unsigned int busfreq; /* FSB, in 10 kHz */
|
||||||
static unsigned int max_multiplier;
|
static unsigned int max_multiplier;
|
||||||
|
@ -53,7 +52,7 @@ static int powernow_k6_get_cpu_multiplier(void)
|
||||||
|
|
||||||
msrval = POWERNOW_IOPORT + 0x1;
|
msrval = POWERNOW_IOPORT + 0x1;
|
||||||
wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
|
wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
|
||||||
invalue=inl(POWERNOW_IOPORT + 0x8);
|
invalue = inl(POWERNOW_IOPORT + 0x8);
|
||||||
msrval = POWERNOW_IOPORT + 0x0;
|
msrval = POWERNOW_IOPORT + 0x0;
|
||||||
wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
|
wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
|
||||||
|
|
||||||
|
@ -67,9 +66,9 @@ static int powernow_k6_get_cpu_multiplier(void)
|
||||||
*
|
*
|
||||||
* Tries to change the PowerNow! multiplier
|
* Tries to change the PowerNow! multiplier
|
||||||
*/
|
*/
|
||||||
static void powernow_k6_set_state (unsigned int best_i)
|
static void powernow_k6_set_state(unsigned int best_i)
|
||||||
{
|
{
|
||||||
unsigned long outvalue=0, invalue=0;
|
unsigned long outvalue = 0, invalue = 0;
|
||||||
unsigned long msrval;
|
unsigned long msrval;
|
||||||
struct cpufreq_freqs freqs;
|
struct cpufreq_freqs freqs;
|
||||||
|
|
||||||
|
@ -90,10 +89,10 @@ static void powernow_k6_set_state (unsigned int best_i)
|
||||||
|
|
||||||
msrval = POWERNOW_IOPORT + 0x1;
|
msrval = POWERNOW_IOPORT + 0x1;
|
||||||
wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
|
wrmsr(MSR_K6_EPMR, msrval, 0); /* enable the PowerNow port */
|
||||||
invalue=inl(POWERNOW_IOPORT + 0x8);
|
invalue = inl(POWERNOW_IOPORT + 0x8);
|
||||||
invalue = invalue & 0xf;
|
invalue = invalue & 0xf;
|
||||||
outvalue = outvalue | invalue;
|
outvalue = outvalue | invalue;
|
||||||
outl(outvalue ,(POWERNOW_IOPORT + 0x8));
|
outl(outvalue , (POWERNOW_IOPORT + 0x8));
|
||||||
msrval = POWERNOW_IOPORT + 0x0;
|
msrval = POWERNOW_IOPORT + 0x0;
|
||||||
wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
|
wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
|
||||||
|
|
||||||
|
@ -124,7 +123,7 @@ static int powernow_k6_verify(struct cpufreq_policy *policy)
|
||||||
*
|
*
|
||||||
* sets a new CPUFreq policy
|
* sets a new CPUFreq policy
|
||||||
*/
|
*/
|
||||||
static int powernow_k6_target (struct cpufreq_policy *policy,
|
static int powernow_k6_target(struct cpufreq_policy *policy,
|
||||||
unsigned int target_freq,
|
unsigned int target_freq,
|
||||||
unsigned int relation)
|
unsigned int relation)
|
||||||
{
|
{
|
||||||
|
@ -152,7 +151,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
|
||||||
busfreq = cpu_khz / max_multiplier;
|
busfreq = cpu_khz / max_multiplier;
|
||||||
|
|
||||||
/* table init */
|
/* table init */
|
||||||
for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
|
for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
|
||||||
if (clock_ratio[i].index > max_multiplier)
|
if (clock_ratio[i].index > max_multiplier)
|
||||||
clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
|
clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
|
||||||
else
|
else
|
||||||
|
@ -165,7 +164,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
|
||||||
|
|
||||||
result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
|
result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
|
||||||
if (result)
|
if (result)
|
||||||
return (result);
|
return result;
|
||||||
|
|
||||||
cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu);
|
cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu);
|
||||||
|
|
||||||
|
@ -176,8 +175,8 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
|
||||||
static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
|
static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i=0; i<8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (i==max_multiplier)
|
if (i == max_multiplier)
|
||||||
powernow_k6_set_state(i);
|
powernow_k6_set_state(i);
|
||||||
}
|
}
|
||||||
cpufreq_frequency_table_put_attr(policy->cpu);
|
cpufreq_frequency_table_put_attr(policy->cpu);
|
||||||
|
@ -189,7 +188,7 @@ static unsigned int powernow_k6_get(unsigned int cpu)
|
||||||
return busfreq * powernow_k6_get_cpu_multiplier();
|
return busfreq * powernow_k6_get_cpu_multiplier();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct freq_attr* powernow_k6_attr[] = {
|
static struct freq_attr *powernow_k6_attr[] = {
|
||||||
&cpufreq_freq_attr_scaling_available_freqs,
|
&cpufreq_freq_attr_scaling_available_freqs,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
@ -227,7 +226,7 @@ static int __init powernow_k6_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpufreq_register_driver(&powernow_k6_driver)) {
|
if (cpufreq_register_driver(&powernow_k6_driver)) {
|
||||||
release_region (POWERNOW_IOPORT, 16);
|
release_region(POWERNOW_IOPORT, 16);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,13 +242,13 @@ static int __init powernow_k6_init(void)
|
||||||
static void __exit powernow_k6_exit(void)
|
static void __exit powernow_k6_exit(void)
|
||||||
{
|
{
|
||||||
cpufreq_unregister_driver(&powernow_k6_driver);
|
cpufreq_unregister_driver(&powernow_k6_driver);
|
||||||
release_region (POWERNOW_IOPORT, 16);
|
release_region(POWERNOW_IOPORT, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MODULE_AUTHOR ("Arjan van de Ven <arjanv@redhat.com>, Dave Jones <davej@codemonkey.org.uk>, Dominik Brodowski <linux@brodo.de>");
|
MODULE_AUTHOR("Arjan van de Ven <arjanv@redhat.com>, Dave Jones <davej@codemonkey.org.uk>, Dominik Brodowski <linux@brodo.de>");
|
||||||
MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
|
MODULE_DESCRIPTION("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
|
||||||
MODULE_LICENSE ("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
module_init(powernow_k6_init);
|
module_init(powernow_k6_init);
|
||||||
module_exit(powernow_k6_exit);
|
module_exit(powernow_k6_exit);
|
||||||
|
|
|
@ -1467,25 +1467,27 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||||
unsigned int target_freq,
|
unsigned int target_freq,
|
||||||
unsigned int relation)
|
unsigned int relation)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
policy = cpufreq_cpu_get(policy->cpu);
|
policy = cpufreq_cpu_get(policy->cpu);
|
||||||
if (!policy)
|
if (!policy)
|
||||||
return -EINVAL;
|
goto no_policy;
|
||||||
|
|
||||||
if (unlikely(lock_policy_rwsem_write(policy->cpu)))
|
if (unlikely(lock_policy_rwsem_write(policy->cpu)))
|
||||||
return -EINVAL;
|
goto fail;
|
||||||
|
|
||||||
ret = __cpufreq_driver_target(policy, target_freq, relation);
|
ret = __cpufreq_driver_target(policy, target_freq, relation);
|
||||||
|
|
||||||
unlock_policy_rwsem_write(policy->cpu);
|
unlock_policy_rwsem_write(policy->cpu);
|
||||||
|
|
||||||
|
fail:
|
||||||
cpufreq_cpu_put(policy);
|
cpufreq_cpu_put(policy);
|
||||||
|
no_policy:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
|
EXPORT_SYMBOL_GPL(cpufreq_driver_target);
|
||||||
|
|
||||||
int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
|
int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -1493,8 +1495,8 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy)
|
||||||
if (!policy)
|
if (!policy)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (cpu_online(policy->cpu) && cpufreq_driver->getavg)
|
if (cpu_online(cpu) && cpufreq_driver->getavg)
|
||||||
ret = cpufreq_driver->getavg(policy->cpu);
|
ret = cpufreq_driver->getavg(policy, cpu);
|
||||||
|
|
||||||
cpufreq_cpu_put(policy);
|
cpufreq_cpu_put(policy);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1717,13 +1719,17 @@ int cpufreq_update_policy(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
|
struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
|
||||||
struct cpufreq_policy policy;
|
struct cpufreq_policy policy;
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
if (!data)
|
if (!data) {
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto no_policy;
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(lock_policy_rwsem_write(cpu)))
|
if (unlikely(lock_policy_rwsem_write(cpu))) {
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
dprintk("updating policy for CPU %u\n", cpu);
|
dprintk("updating policy for CPU %u\n", cpu);
|
||||||
memcpy(&policy, data, sizeof(struct cpufreq_policy));
|
memcpy(&policy, data, sizeof(struct cpufreq_policy));
|
||||||
|
@ -1750,7 +1756,9 @@ int cpufreq_update_policy(unsigned int cpu)
|
||||||
|
|
||||||
unlock_policy_rwsem_write(cpu);
|
unlock_policy_rwsem_write(cpu);
|
||||||
|
|
||||||
|
fail:
|
||||||
cpufreq_cpu_put(data);
|
cpufreq_cpu_put(data);
|
||||||
|
no_policy:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cpufreq_update_policy);
|
EXPORT_SYMBOL(cpufreq_update_policy);
|
||||||
|
|
|
@ -460,6 +460,7 @@ static void do_dbs_timer(struct work_struct *work)
|
||||||
|
|
||||||
static inline void dbs_timer_init(void)
|
static inline void dbs_timer_init(void)
|
||||||
{
|
{
|
||||||
|
init_timer_deferrable(&dbs_work.timer);
|
||||||
schedule_delayed_work(&dbs_work,
|
schedule_delayed_work(&dbs_work,
|
||||||
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
|
usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
|
||||||
return;
|
return;
|
||||||
|
@ -575,13 +576,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
|
||||||
|
static
|
||||||
|
#endif
|
||||||
struct cpufreq_governor cpufreq_gov_conservative = {
|
struct cpufreq_governor cpufreq_gov_conservative = {
|
||||||
.name = "conservative",
|
.name = "conservative",
|
||||||
.governor = cpufreq_governor_dbs,
|
.governor = cpufreq_governor_dbs,
|
||||||
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
|
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(cpufreq_gov_conservative);
|
|
||||||
|
|
||||||
static int __init cpufreq_gov_dbs_init(void)
|
static int __init cpufreq_gov_dbs_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,13 +18,19 @@
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/kernel_stat.h>
|
#include <linux/kernel_stat.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/hrtimer.h>
|
||||||
|
#include <linux/tick.h>
|
||||||
|
#include <linux/ktime.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dbs is used in this file as a shortform for demandbased switching
|
* dbs is used in this file as a shortform for demandbased switching
|
||||||
* It helps to keep variable names smaller, simpler
|
* It helps to keep variable names smaller, simpler
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10)
|
||||||
#define DEF_FREQUENCY_UP_THRESHOLD (80)
|
#define DEF_FREQUENCY_UP_THRESHOLD (80)
|
||||||
|
#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3)
|
||||||
|
#define MICRO_FREQUENCY_UP_THRESHOLD (95)
|
||||||
#define MIN_FREQUENCY_UP_THRESHOLD (11)
|
#define MIN_FREQUENCY_UP_THRESHOLD (11)
|
||||||
#define MAX_FREQUENCY_UP_THRESHOLD (100)
|
#define MAX_FREQUENCY_UP_THRESHOLD (100)
|
||||||
|
|
||||||
|
@ -57,6 +63,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
|
||||||
struct cpu_dbs_info_s {
|
struct cpu_dbs_info_s {
|
||||||
cputime64_t prev_cpu_idle;
|
cputime64_t prev_cpu_idle;
|
||||||
cputime64_t prev_cpu_wall;
|
cputime64_t prev_cpu_wall;
|
||||||
|
cputime64_t prev_cpu_nice;
|
||||||
struct cpufreq_policy *cur_policy;
|
struct cpufreq_policy *cur_policy;
|
||||||
struct delayed_work work;
|
struct delayed_work work;
|
||||||
struct cpufreq_frequency_table *freq_table;
|
struct cpufreq_frequency_table *freq_table;
|
||||||
|
@ -86,21 +93,24 @@ static struct workqueue_struct *kondemand_wq;
|
||||||
static struct dbs_tuners {
|
static struct dbs_tuners {
|
||||||
unsigned int sampling_rate;
|
unsigned int sampling_rate;
|
||||||
unsigned int up_threshold;
|
unsigned int up_threshold;
|
||||||
|
unsigned int down_differential;
|
||||||
unsigned int ignore_nice;
|
unsigned int ignore_nice;
|
||||||
unsigned int powersave_bias;
|
unsigned int powersave_bias;
|
||||||
} dbs_tuners_ins = {
|
} dbs_tuners_ins = {
|
||||||
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
|
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
|
||||||
|
.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
|
||||||
.ignore_nice = 0,
|
.ignore_nice = 0,
|
||||||
.powersave_bias = 0,
|
.powersave_bias = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
|
static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
|
||||||
|
cputime64_t *wall)
|
||||||
{
|
{
|
||||||
cputime64_t idle_time;
|
cputime64_t idle_time;
|
||||||
cputime64_t cur_jiffies;
|
cputime64_t cur_wall_time;
|
||||||
cputime64_t busy_time;
|
cputime64_t busy_time;
|
||||||
|
|
||||||
cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
|
cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
|
||||||
busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
|
busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
|
||||||
kstat_cpu(cpu).cpustat.system);
|
kstat_cpu(cpu).cpustat.system);
|
||||||
|
|
||||||
|
@ -113,7 +123,37 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
|
||||||
kstat_cpu(cpu).cpustat.nice);
|
kstat_cpu(cpu).cpustat.nice);
|
||||||
}
|
}
|
||||||
|
|
||||||
idle_time = cputime64_sub(cur_jiffies, busy_time);
|
idle_time = cputime64_sub(cur_wall_time, busy_time);
|
||||||
|
if (wall)
|
||||||
|
*wall = cur_wall_time;
|
||||||
|
|
||||||
|
return idle_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
|
||||||
|
{
|
||||||
|
u64 idle_time = get_cpu_idle_time_us(cpu, wall);
|
||||||
|
|
||||||
|
if (idle_time == -1ULL)
|
||||||
|
return get_cpu_idle_time_jiffy(cpu, wall);
|
||||||
|
|
||||||
|
if (dbs_tuners_ins.ignore_nice) {
|
||||||
|
cputime64_t cur_nice;
|
||||||
|
unsigned long cur_nice_jiffies;
|
||||||
|
struct cpu_dbs_info_s *dbs_info;
|
||||||
|
|
||||||
|
dbs_info = &per_cpu(cpu_dbs_info, cpu);
|
||||||
|
cur_nice = cputime64_sub(kstat_cpu(cpu).cpustat.nice,
|
||||||
|
dbs_info->prev_cpu_nice);
|
||||||
|
/*
|
||||||
|
* Assumption: nice time between sampling periods will be
|
||||||
|
* less than 2^32 jiffies for 32 bit sys
|
||||||
|
*/
|
||||||
|
cur_nice_jiffies = (unsigned long)
|
||||||
|
cputime64_to_jiffies64(cur_nice);
|
||||||
|
dbs_info->prev_cpu_nice = kstat_cpu(cpu).cpustat.nice;
|
||||||
|
return idle_time + jiffies_to_usecs(cur_nice_jiffies);
|
||||||
|
}
|
||||||
return idle_time;
|
return idle_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,8 +317,8 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy,
|
||||||
for_each_online_cpu(j) {
|
for_each_online_cpu(j) {
|
||||||
struct cpu_dbs_info_s *dbs_info;
|
struct cpu_dbs_info_s *dbs_info;
|
||||||
dbs_info = &per_cpu(cpu_dbs_info, j);
|
dbs_info = &per_cpu(cpu_dbs_info, j);
|
||||||
dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
|
dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
|
||||||
dbs_info->prev_cpu_wall = get_jiffies_64();
|
&dbs_info->prev_cpu_wall);
|
||||||
}
|
}
|
||||||
mutex_unlock(&dbs_mutex);
|
mutex_unlock(&dbs_mutex);
|
||||||
|
|
||||||
|
@ -334,9 +374,7 @@ static struct attribute_group dbs_attr_group = {
|
||||||
|
|
||||||
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
||||||
{
|
{
|
||||||
unsigned int idle_ticks, total_ticks;
|
unsigned int max_load_freq;
|
||||||
unsigned int load = 0;
|
|
||||||
cputime64_t cur_jiffies;
|
|
||||||
|
|
||||||
struct cpufreq_policy *policy;
|
struct cpufreq_policy *policy;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
@ -346,13 +384,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
||||||
|
|
||||||
this_dbs_info->freq_lo = 0;
|
this_dbs_info->freq_lo = 0;
|
||||||
policy = this_dbs_info->cur_policy;
|
policy = this_dbs_info->cur_policy;
|
||||||
cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
|
|
||||||
total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
|
|
||||||
this_dbs_info->prev_cpu_wall);
|
|
||||||
this_dbs_info->prev_cpu_wall = get_jiffies_64();
|
|
||||||
|
|
||||||
if (!total_ticks)
|
|
||||||
return;
|
|
||||||
/*
|
/*
|
||||||
* Every sampling_rate, we check, if current idle time is less
|
* Every sampling_rate, we check, if current idle time is less
|
||||||
* than 20% (default), then we try to increase frequency
|
* than 20% (default), then we try to increase frequency
|
||||||
|
@ -365,27 +397,44 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
||||||
* 5% (default) of current frequency
|
* 5% (default) of current frequency
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Get Idle Time */
|
/* Get Absolute Load - in terms of freq */
|
||||||
idle_ticks = UINT_MAX;
|
max_load_freq = 0;
|
||||||
|
|
||||||
for_each_cpu_mask_nr(j, policy->cpus) {
|
for_each_cpu_mask_nr(j, policy->cpus) {
|
||||||
cputime64_t total_idle_ticks;
|
|
||||||
unsigned int tmp_idle_ticks;
|
|
||||||
struct cpu_dbs_info_s *j_dbs_info;
|
struct cpu_dbs_info_s *j_dbs_info;
|
||||||
|
cputime64_t cur_wall_time, cur_idle_time;
|
||||||
|
unsigned int idle_time, wall_time;
|
||||||
|
unsigned int load, load_freq;
|
||||||
|
int freq_avg;
|
||||||
|
|
||||||
j_dbs_info = &per_cpu(cpu_dbs_info, j);
|
j_dbs_info = &per_cpu(cpu_dbs_info, j);
|
||||||
total_idle_ticks = get_cpu_idle_time(j);
|
|
||||||
tmp_idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks,
|
|
||||||
j_dbs_info->prev_cpu_idle);
|
|
||||||
j_dbs_info->prev_cpu_idle = total_idle_ticks;
|
|
||||||
|
|
||||||
if (tmp_idle_ticks < idle_ticks)
|
cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
|
||||||
idle_ticks = tmp_idle_ticks;
|
|
||||||
|
wall_time = (unsigned int) cputime64_sub(cur_wall_time,
|
||||||
|
j_dbs_info->prev_cpu_wall);
|
||||||
|
j_dbs_info->prev_cpu_wall = cur_wall_time;
|
||||||
|
|
||||||
|
idle_time = (unsigned int) cputime64_sub(cur_idle_time,
|
||||||
|
j_dbs_info->prev_cpu_idle);
|
||||||
|
j_dbs_info->prev_cpu_idle = cur_idle_time;
|
||||||
|
|
||||||
|
if (unlikely(!wall_time || wall_time < idle_time))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
load = 100 * (wall_time - idle_time) / wall_time;
|
||||||
|
|
||||||
|
freq_avg = __cpufreq_driver_getavg(policy, j);
|
||||||
|
if (freq_avg <= 0)
|
||||||
|
freq_avg = policy->cur;
|
||||||
|
|
||||||
|
load_freq = load * freq_avg;
|
||||||
|
if (load_freq > max_load_freq)
|
||||||
|
max_load_freq = load_freq;
|
||||||
}
|
}
|
||||||
if (likely(total_ticks > idle_ticks))
|
|
||||||
load = (100 * (total_ticks - idle_ticks)) / total_ticks;
|
|
||||||
|
|
||||||
/* Check for frequency increase */
|
/* Check for frequency increase */
|
||||||
if (load > dbs_tuners_ins.up_threshold) {
|
if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
|
||||||
/* if we are already at full speed then break out early */
|
/* if we are already at full speed then break out early */
|
||||||
if (!dbs_tuners_ins.powersave_bias) {
|
if (!dbs_tuners_ins.powersave_bias) {
|
||||||
if (policy->cur == policy->max)
|
if (policy->cur == policy->max)
|
||||||
|
@ -412,15 +461,13 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
||||||
* can support the current CPU usage without triggering the up
|
* can support the current CPU usage without triggering the up
|
||||||
* policy. To be safe, we focus 10 points under the threshold.
|
* policy. To be safe, we focus 10 points under the threshold.
|
||||||
*/
|
*/
|
||||||
if (load < (dbs_tuners_ins.up_threshold - 10)) {
|
if (max_load_freq <
|
||||||
unsigned int freq_next, freq_cur;
|
(dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
|
||||||
|
policy->cur) {
|
||||||
freq_cur = __cpufreq_driver_getavg(policy);
|
unsigned int freq_next;
|
||||||
if (!freq_cur)
|
freq_next = max_load_freq /
|
||||||
freq_cur = policy->cur;
|
(dbs_tuners_ins.up_threshold -
|
||||||
|
dbs_tuners_ins.down_differential);
|
||||||
freq_next = (freq_cur * load) /
|
|
||||||
(dbs_tuners_ins.up_threshold - 10);
|
|
||||||
|
|
||||||
if (!dbs_tuners_ins.powersave_bias) {
|
if (!dbs_tuners_ins.powersave_bias) {
|
||||||
__cpufreq_driver_target(policy, freq_next,
|
__cpufreq_driver_target(policy, freq_next,
|
||||||
|
@ -526,8 +573,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
j_dbs_info = &per_cpu(cpu_dbs_info, j);
|
j_dbs_info = &per_cpu(cpu_dbs_info, j);
|
||||||
j_dbs_info->cur_policy = policy;
|
j_dbs_info->cur_policy = policy;
|
||||||
|
|
||||||
j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);
|
j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
|
||||||
j_dbs_info->prev_cpu_wall = get_jiffies_64();
|
&j_dbs_info->prev_cpu_wall);
|
||||||
}
|
}
|
||||||
this_dbs_info->cpu = cpu;
|
this_dbs_info->cpu = cpu;
|
||||||
/*
|
/*
|
||||||
|
@ -579,22 +626,42 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
|
||||||
|
static
|
||||||
|
#endif
|
||||||
struct cpufreq_governor cpufreq_gov_ondemand = {
|
struct cpufreq_governor cpufreq_gov_ondemand = {
|
||||||
.name = "ondemand",
|
.name = "ondemand",
|
||||||
.governor = cpufreq_governor_dbs,
|
.governor = cpufreq_governor_dbs,
|
||||||
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
|
.max_transition_latency = TRANSITION_LATENCY_LIMIT,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(cpufreq_gov_ondemand);
|
|
||||||
|
|
||||||
static int __init cpufreq_gov_dbs_init(void)
|
static int __init cpufreq_gov_dbs_init(void)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
cputime64_t wall;
|
||||||
|
u64 idle_time;
|
||||||
|
int cpu = get_cpu();
|
||||||
|
|
||||||
|
idle_time = get_cpu_idle_time_us(cpu, &wall);
|
||||||
|
put_cpu();
|
||||||
|
if (idle_time != -1ULL) {
|
||||||
|
/* Idle micro accounting is supported. Use finer thresholds */
|
||||||
|
dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
|
||||||
|
dbs_tuners_ins.down_differential =
|
||||||
|
MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
|
||||||
|
}
|
||||||
|
|
||||||
kondemand_wq = create_workqueue("kondemand");
|
kondemand_wq = create_workqueue("kondemand");
|
||||||
if (!kondemand_wq) {
|
if (!kondemand_wq) {
|
||||||
printk(KERN_ERR "Creation of kondemand failed\n");
|
printk(KERN_ERR "Creation of kondemand failed\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
return cpufreq_register_governor(&cpufreq_gov_ondemand);
|
err = cpufreq_register_governor(&cpufreq_gov_ondemand);
|
||||||
|
if (err)
|
||||||
|
destroy_workqueue(kondemand_wq);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit cpufreq_gov_dbs_exit(void)
|
static void __exit cpufreq_gov_dbs_exit(void)
|
||||||
|
|
|
@ -36,12 +36,14 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE
|
||||||
|
static
|
||||||
|
#endif
|
||||||
struct cpufreq_governor cpufreq_gov_performance = {
|
struct cpufreq_governor cpufreq_gov_performance = {
|
||||||
.name = "performance",
|
.name = "performance",
|
||||||
.governor = cpufreq_governor_performance,
|
.governor = cpufreq_governor_performance,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(cpufreq_gov_performance);
|
|
||||||
|
|
||||||
|
|
||||||
static int __init cpufreq_gov_performance_init(void)
|
static int __init cpufreq_gov_performance_init(void)
|
||||||
|
|
|
@ -35,12 +35,14 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
|
||||||
|
static
|
||||||
|
#endif
|
||||||
struct cpufreq_governor cpufreq_gov_powersave = {
|
struct cpufreq_governor cpufreq_gov_powersave = {
|
||||||
.name = "powersave",
|
.name = "powersave",
|
||||||
.governor = cpufreq_governor_powersave,
|
.governor = cpufreq_governor_powersave,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(cpufreq_gov_powersave);
|
|
||||||
|
|
||||||
static int __init cpufreq_gov_powersave_init(void)
|
static int __init cpufreq_gov_powersave_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,6 +187,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
|
||||||
|
static
|
||||||
|
#endif
|
||||||
struct cpufreq_governor cpufreq_gov_userspace = {
|
struct cpufreq_governor cpufreq_gov_userspace = {
|
||||||
.name = "userspace",
|
.name = "userspace",
|
||||||
.governor = cpufreq_governor_userspace,
|
.governor = cpufreq_governor_userspace,
|
||||||
|
@ -194,7 +197,6 @@ struct cpufreq_governor cpufreq_gov_userspace = {
|
||||||
.show_setspeed = show_speed,
|
.show_setspeed = show_speed,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(cpufreq_gov_userspace);
|
|
||||||
|
|
||||||
static int __init cpufreq_gov_userspace_init(void)
|
static int __init cpufreq_gov_userspace_init(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,7 +187,8 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||||
unsigned int relation);
|
unsigned int relation);
|
||||||
|
|
||||||
|
|
||||||
extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy);
|
extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy,
|
||||||
|
unsigned int cpu);
|
||||||
|
|
||||||
int cpufreq_register_governor(struct cpufreq_governor *governor);
|
int cpufreq_register_governor(struct cpufreq_governor *governor);
|
||||||
void cpufreq_unregister_governor(struct cpufreq_governor *governor);
|
void cpufreq_unregister_governor(struct cpufreq_governor *governor);
|
||||||
|
@ -226,7 +227,9 @@ struct cpufreq_driver {
|
||||||
unsigned int (*get) (unsigned int cpu);
|
unsigned int (*get) (unsigned int cpu);
|
||||||
|
|
||||||
/* optional */
|
/* optional */
|
||||||
unsigned int (*getavg) (unsigned int cpu);
|
unsigned int (*getavg) (struct cpufreq_policy *policy,
|
||||||
|
unsigned int cpu);
|
||||||
|
|
||||||
int (*exit) (struct cpufreq_policy *policy);
|
int (*exit) (struct cpufreq_policy *policy);
|
||||||
int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg);
|
int (*suspend) (struct cpufreq_policy *policy, pm_message_t pmsg);
|
||||||
int (*resume) (struct cpufreq_policy *policy);
|
int (*resume) (struct cpufreq_policy *policy);
|
||||||
|
|
|
@ -126,7 +126,7 @@ static inline ktime_t tick_nohz_get_sleep_length(void)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
static inline void tick_nohz_stop_idle(int cpu) { }
|
static inline void tick_nohz_stop_idle(int cpu) { }
|
||||||
static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return 0; }
|
static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; }
|
||||||
# endif /* !NO_HZ */
|
# endif /* !NO_HZ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <linux/profile.h>
|
#include <linux/profile.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/tick.h>
|
#include <linux/tick.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include <asm/irq_regs.h>
|
#include <asm/irq_regs.h>
|
||||||
|
|
||||||
|
@ -190,9 +191,17 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time)
|
||||||
{
|
{
|
||||||
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
|
struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
|
||||||
|
|
||||||
*last_update_time = ktime_to_us(ts->idle_lastupdate);
|
if (!tick_nohz_enabled)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (ts->idle_active)
|
||||||
|
*last_update_time = ktime_to_us(ts->idle_lastupdate);
|
||||||
|
else
|
||||||
|
*last_update_time = ktime_to_us(ktime_get());
|
||||||
|
|
||||||
return ktime_to_us(ts->idle_sleeptime);
|
return ktime_to_us(ts->idle_sleeptime);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(get_cpu_idle_time_us);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tick_nohz_stop_sched_tick - stop the idle tick from the idle task
|
* tick_nohz_stop_sched_tick - stop the idle tick from the idle task
|
||||||
|
|
Loading…
Reference in a new issue