Skip to contentSkip to conversation

Enable C2/C3 on SMP systems

PATCH New Venkatesh Pallipadi 1 participant 1 message Apr 2, 2005

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

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.

arch/i386/kernel/acpi/cstate.c +71 -0
diff -purN linux-2.6.12-rc1-org/arch/i386/kernel/acpi/cstate.c linux-2.6.12-rc1-org-patch/arch/i386/kernel/acpi/cstate.c
@@ -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
diff -purN linux-2.6.12-rc1-org/arch/i386/kernel/acpi/Makefile linux-2.6.12-rc1-org-patch/arch/i386/kernel/acpi/Makefile
@@ -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
diff -purN linux-2.6.12-rc1-org/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.6.12-rc1-org-patch/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -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
diff -purN linux-2.6.12-rc1-org/drivers/acpi/processor_core.c linux-2.6.12-rc1-org-patch/drivers/acpi/processor_core.c
@@ -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
diff -purN linux-2.6.12-rc1-org/drivers/acpi/processor_perflib.c linux-2.6.12-rc1-org-patch/drivers/acpi/processor_perflib.c
@@ -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
diff -purN linux-2.6.12-rc1-org/include/acpi/pdc_intel.h linux-2.6.12-rc1-org-patch/include/acpi/pdc_intel.h
@@ -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
diff -purN linux-2.6.12-rc1-org/include/acpi/processor.h linux-2.6.12-rc1-org-patch/include/acpi/processor.h
@@ -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 mod
 extern 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
diff -purN linux-2.6.12-rc1-org/include/asm-i386/acpi.h linux-2.6.12-rc1-org-patch/include/asm-i386/acpi.h
@@ -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
diff -purN linux-2.6.12-rc1-org/include/asm-x86_64/acpi.h linux-2.6.12-rc1-org-patch/include/asm-x86_64/acpi.h
@@ -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