Enable C2/C3 on SMP systems
Subsystems (2)
PATCH 1/1 Enable C2/C3 on SMP systems
Attached patch enables C2/C3 on SMP systems. Please review and let me know your comments.
Thanks,
Venki
Currently, C2/C3 is supported on UP systems only. This patch adds support for C2/C3 on SMP systems.
http://bugme.osdl.org/show_bug.cgi?id=4401
has some history on this.
Signed-off-by Venkatesh Pallipadi <[email protected]>
arch/i386/kernel/acpi/cstate.c +71 -0
@@ -0,0 +1,71 @@ +/* +* arch/i386/kernel/acpi/cstate.c +* +* Copyright (C) 2005 Intel Corporation +* Venkatesh Pallipadi <[email protected]> +* - Added _PDC for SMP C-states on Intel CPUs +*/ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/acpi.h> + +#include <acpi/processor.h> +#include <asm/acpi.h> + +static void acpi_processor_power_init_intel_pdc ( +struct acpi_processor_power *pow) +{ +struct acpi_object_list *obj_list; +union acpi_object *obj; +u32 *buf; + +/* allocate and initialize pdc. It will be used later. */ + obj_list =kmalloc (sizeof (struct acpi_object_list ),GFP_KERNEL ); +if (!obj_list) { +printk (KERN_ERR "Memory allocation error\n" ); +return ; + } + + obj =kmalloc (sizeof (union acpi_object ),GFP_KERNEL ); +if (!obj) { +printk (KERN_ERR "Memory allocation error\n" ); +kfree (obj_list); +return ; + } + + buf =kmalloc (12 ,GFP_KERNEL ); +if (!buf) { +printk (KERN_ERR "Memory allocation error\n" ); +kfree (obj); +kfree (obj_list); +return ; + } + + buf[0 ] =ACPI_PDC_REVISION_ID ; + buf[1 ] =1 ; + buf[2 ] =ACPI_PDC_C_CAPABILITY_SMP ; + + obj->type =ACPI_TYPE_BUFFER ; + obj->buffer.length =12 ; + obj->buffer.pointer = (u8 *)buf; + obj_list->count =1 ; + obj_list->pointer = obj; + pow->pdc = obj_list; + +return ; +} + +void acpi_processor_power_init_pdc (struct acpi_processor_power *pow, +unsigned int cpu) +{ +struct cpuinfo_x86 *c = cpu_data + cpu; + + pow->pdc =NULL ; +if (c->x86_vendor ==X86_VENDOR_INTEL ) +acpi_processor_power_init_intel_pdc (pow); + +return ; +} +EXPORT_SYMBOL (acpi_processor_power_init_pdc);
arch/i386/kernel/acpi/Makefile +4 -0
@@ -2,3 +2,7 @@ obj-$(CONFIG_ACPI_BOOT) := boot.o obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o +ifneq ($(CONFIG_ACPI_PROCESSOR),) +obj-y += cstate.o +endif +
arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +1 -1
@@ -369,7 +369,7 @@ static int centrino_cpu_init_acpi(struct arg0.buffer.pointer = (u8 *) arg0_buf; arg0_buf[0 ] =ACPI_PDC_REVISION_ID ; arg0_buf[1 ] =1 ; - arg0_buf[2 ] =ACPI_PDC_EST_CAPABILITY_SMP |ACPI_PDC_EST_CAPABILITY_MSR ; + arg0_buf[2 ] =ACPI_PDC_EST_CAPABILITY_SMP_MSR ; p.pdc = &arg_list;
drivers/acpi/processor_core.c +37 -0
@@ -256,6 +256,43 @@ acpi_processor_errata (/* -------------------------------------------------------------------------- +Common ACPI processor fucntions +-------------------------------------------------------------------------- */ + +/* +* _PDC is required for a BIOS-OS handshake for most of the newer +* ACPI processor features. +*/ + +int acpi_processor_set_pdc (struct acpi_processor *pr, +struct acpi_object_list *pdc_in) +{ +acpi_status status =AE_OK ; +u32 arg0_buf[3 ]; +union acpi_object arg0 = {ACPI_TYPE_BUFFER }; +struct acpi_object_list no_object = {1 , &arg0}; +struct acpi_object_list *pdc; + +ACPI_FUNCTION_TRACE ("acpi_processor_set_pdc" ); + + arg0.buffer.length =12 ; + arg0.buffer.pointer = (u8 *) arg0_buf; + arg0_buf[0 ] =ACPI_PDC_REVISION_ID ; + arg0_buf[1 ] =0 ; + arg0_buf[2 ] =0 ; + + pdc = (pdc_in) ? pdc_in : &no_object; + + status =acpi_evaluate_object (pr->handle,"_PDC" , pdc,NULL ); + +if ((ACPI_FAILURE (status)) && (pdc_in)) +ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Error evaluating _PDC, using legacy perf. control...\n" )); + +return_VALUE (status); +} + + +/* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */
drivers/acpi/processor_idle.c +49 -28
166 lines not on this page · raw message
drivers/acpi/processor_perflib.c +1 -32
@@ -165,37 +165,6 @@ void acpi_processor_ppc_exit(void) { acpi_processor_ppc_status &= ~PPC_REGISTERED ; } -/* -* when registering a cpufreq driver with this ACPI processor driver, the -* _PCT and _PSS structures are read out and written into struct -* acpi_processor_performance. -*/ -static int acpi_processor_set_pdc (struct acpi_processor *pr) -{ -acpi_status status =AE_OK ; -u32 arg0_buf[3 ]; -union acpi_object arg0 = {ACPI_TYPE_BUFFER }; -struct acpi_object_list no_object = {1 , &arg0}; -struct acpi_object_list *pdc; - -ACPI_FUNCTION_TRACE ("acpi_processor_set_pdc" ); - - arg0.buffer.length =12 ; - arg0.buffer.pointer = (u8 *) arg0_buf; - arg0_buf[0 ] =ACPI_PDC_REVISION_ID ; - arg0_buf[1 ] =0 ; - arg0_buf[2 ] =0 ; - - pdc = (pr->performance->pdc) ? pr->performance->pdc : &no_object; - - status =acpi_evaluate_object (pr->handle,"_PDC" , pdc,NULL ); - -if ((ACPI_FAILURE (status)) && (pr->performance->pdc)) -ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Error evaluating _PDC, using legacy perf. control...\n" )); - -return_VALUE (status); -} -static int acpi_processor_get_performance_control (
@@ -357,7 +326,7 @@ acpi_processor_get_performance_info (if (!pr || !pr->performance || !pr->handle)return_VALUE (-EINVAL ); -acpi_processor_set_pdc (pr); +acpi_processor_set_pdc (pr, pr->performance->pdc); status =acpi_get_handle (pr->handle,"_PCT" , &handle);if (ACPI_FAILURE (status)) {
include/acpi/pdc_intel.h +29 -0
@@ -0,0 +1,29 @@ + +/* _PDC bit definition for Intel processors */ + +#ifndef __PDC_INTEL_H__ +#define __PDC_INTEL_H__ + +#define ACPI_PDC_P_FFH (0x0001) +#define ACPI_PDC_C_C1_HALT (0x0002) +#define ACPI_PDC_T_FFH (0x0004) +#define ACPI_PDC_SMP_C1PT (0x0008) +#define ACPI_PDC_SMP_C2C3 (0x0010) +#define ACPI_PDC_SMP_P_SWCOORD (0x0020) +#define ACPI_PDC_SMP_C_SWCOORD (0x0040) +#define ACPI_PDC_SMP_T_SWCOORD (0x0080) +#define ACPI_PDC_C_C1_FFH (0x0100) + + +#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ + ACPI_PDC_C_C1_HALT) + +#define ACPI_PDC_EST_CAPABILITY_SMP_MSR (ACPI_PDC_EST_CAPABILITY_SMP | \ + ACPI_PDC_P_FFH) + +#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ + ACPI_PDC_SMP_C1PT | \ + ACPI_PDC_C_C1_HALT) + +#endif /* __PDC_INTEL_H__ */ +
include/acpi/processor.h +23 -2
@@ -4,6 +4,8 @@#include <linux/kernel.h> #include <linux/config.h> +#include <asm/acpi.h> +#define ACPI_PROCESSOR_BUSY_METRIC 10#define ACPI_PROCESSOR_MAX_POWER 8
@@ -14,6 +16,8 @@#define ACPI_PROCESSOR_MAX_THROTTLE 250/* 25% */ #define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 +#define ACPI_PDC_REVISION_ID 0x1 +/* Power Management */ struct acpi_processor_cx ;
@@ -59,6 +63,9 @@ struct acpi_processor_power {u32 bm_activity;int count;struct acpi_processor_cx states[ACPI_PROCESSOR_MAX_POWER ]; + +/* the _PDC objects passed by the driver, if any */ +struct acpi_object_list *pdc; };/* Performance Management */
@@ -82,8 +89,6 @@ struct acpi_processor_px {acpi_integer status;/* success indicator */ }; -#define ACPI_PDC_REVISION_ID 0x1 -struct acpi_processor_performance {unsigned int state;unsigned int platform_limit;
@@ -179,7 +184,23 @@ int acpi_processor_notify_smm(struct modextern struct acpi_processor *processors[NR_CPUS ];extern struct acpi_processor_errata errata; +int acpi_processor_set_pdc (struct acpi_processor *pr, +struct acpi_object_list *pdc_in); + +#ifdef ARCH_HAS_POWER_PDC_INIT +void acpi_processor_power_init_pdc (struct acpi_processor_power *pow, +unsigned int cpu); +#else +static inline void acpi_processor_power_init_pdc ( +struct acpi_processor_power *pow,unsigned int cpu) +{ + pow->pdc =NULL ; +return ; +} +#endif +/* in processor_perflib.c */ +#ifdef CONFIG_CPU_FREQ void acpi_processor_ppc_init (void );void acpi_processor_ppc_exit (void );
include/asm-i386/acpi.h +4 -6
@@ -28,6 +28,8 @@#ifdef __KERNEL__ +#include <acpi/pdc_intel.h> +#include <asm/system.h> /* defines cmpxchg */ #define COMPILER_DEPENDENT_INT64 long long
@@ -101,12 +103,6 @@ __acpi_release_global_lock (unsigned int :"=r"(n_hi), "=r"(n_lo) \ :"0"(n_hi), "1"(n_lo)) -/* -* Refer Intel ACPI _PDC support document for bit definitions -*/ -#define ACPI_PDC_EST_CAPABILITY_SMP 0xa -#define ACPI_PDC_EST_CAPABILITY_MSR 0x1 -#ifdef CONFIG_ACPI_BOOT extern int acpi_lapic;extern int acpi_ioapic;
@@ -185,6 +181,8 @@ extern void acpi_reserve_bootmem(void);extern u8 x86_acpiid_to_apicid[]; +#define ARCH_HAS_POWER_PDC_INIT 1 +#endif /*__KERNEL__*/ #endif /*_ASM_ACPI_H*/
include/asm-x86_64/acpi.h +2 -6
@@ -28,6 +28,8 @@#ifdef __KERNEL__ +#include <acpi/pdc_intel.h> +#define COMPILER_DEPENDENT_INT64 long long#define COMPILER_DEPENDENT_UINT64 unsigned long long
@@ -99,12 +101,6 @@ __acpi_release_global_lock (unsigned int :"=r"(n_hi), "=r"(n_lo) \ :"0"(n_hi), "1"(n_lo)) -/* -* Refer Intel ACPI _PDC support document for bit definitions -*/ -#define ACPI_PDC_EST_CAPABILITY_SMP 0xa -#define ACPI_PDC_EST_CAPABILITY_MSR 0x1 -#ifdef CONFIG_ACPI_BOOT extern int acpi_lapic;extern int acpi_ioapic;
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click