diff --git a/headers/os/drivers/cpufreq.h b/headers/os/drivers/cpufreq.h new file mode 100644 index 0000000000..7a4301feeb --- /dev/null +++ b/headers/os/drivers/cpufreq.h @@ -0,0 +1,26 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _CPUFREQ_H +#define _CPUFREQ_H + + +#include + + +#define CPUFREQ_MODULES_PREFIX "power/cpufreq" + + +const int kCPUPerformanceScaleMax = 1000; + +typedef struct cpufreq_module_info { + module_info info; + + status_t (*increase_performance)(int delta, bool allowBoost); + status_t (*decrease_performance)(int delta); +} cpufreq_module_info; + + +#endif // _CPUFREQ_H + diff --git a/headers/private/kernel/cpu.h b/headers/private/kernel/cpu.h index e833a944cd..bcd06aa59b 100644 --- a/headers/private/kernel/cpu.h +++ b/headers/private/kernel/cpu.h @@ -104,6 +104,9 @@ extern inline cpu_ent *get_cpu_struct(void) { return &gCPU[smp_get_current_cpu() status_t cpu_build_topology_tree(void); cpu_topology_node* get_cpu_topology(void); +status_t increase_cpu_performance(int delta, bool allowBoost); +status_t decrease_cpu_performance(int delta); + void _user_clear_caches(void *address, size_t length, uint32 flags); bool _user_cpu_enabled(int32 cpu); status_t _user_set_cpu_enabled(int32 cpu, bool enabled); diff --git a/src/system/kernel/cpu.cpp b/src/system/kernel/cpu.cpp index bacc8a3ec7..b98ad77bdd 100644 --- a/src/system/kernel/cpu.cpp +++ b/src/system/kernel/cpu.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org. * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * @@ -14,6 +15,8 @@ #include +#include + #include #include #include @@ -25,6 +28,8 @@ cpu_ent gCPU[MAX_BOOT_CPUS]; uint32 gCPUCacheLevelCount; static cpu_topology_node sCPUTopology; +static cpufreq_module_info* sCPUPerformanceModule; + static spinlock sSetCpuLock; @@ -49,10 +54,40 @@ cpu_init_post_vm(kernel_args *args) } +static void +load_cpufreq_module() +{ + void* cookie = open_module_list(CPUFREQ_MODULES_PREFIX); + + while (true) { + char name[B_FILE_NAME_LENGTH]; + size_t nameLength = sizeof(name); + + if (read_next_module_name(cookie, name, &nameLength) != B_OK) + break; + + if (get_module(name, (module_info**)&sCPUPerformanceModule) == B_OK) { + dprintf("found cpufreq module: %s\n", name); + break; + } + } + + close_module_list(cookie); + + if (sCPUPerformanceModule == NULL) + dprintf("no valid cpufreq module found\n"); +} + + status_t cpu_init_post_modules(kernel_args *args) { - return arch_cpu_init_post_modules(args); + status_t result = arch_cpu_init_post_modules(args); + if (result != B_OK) + return result; + + load_cpufreq_module(); + return B_OK; } @@ -194,6 +229,24 @@ get_cpu_topology(void) } +status_t +increase_cpu_performance(int delta, bool allowBoost) +{ + if (sCPUPerformanceModule != NULL) + return sCPUPerformanceModule->increase_performance(delta, allowBoost); + return B_NOT_SUPPORTED; +} + + +status_t +decrease_cpu_performance(int delta) +{ + if (sCPUPerformanceModule != NULL) + return sCPUPerformanceModule->decrease_performance(delta); + return B_NOT_SUPPORTED; +} + + // #pragma mark -