From 1d9cb470a755409ce97c3376174b1e234bd20371 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:14 -0700 Subject: ACPI: processor: introduce arch_has_acpi_pdc arch dependent helper function that tells us if we should attempt to evaluate _PDC on this machine or not. The x86 implementation assumes that the CPUs in the machine must be homogeneous, and that you cannot mix CPUs of different vendors. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index b416c32dda0..931e735e9e3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -69,6 +69,9 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + if (arch_has_acpi_pdc() == false) + return; + arch_acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); -- cgit v1.2.3 From 407cd87c54e76c266245e8faef8dd4a84b7254fe Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:19 -0700 Subject: ACPI: processor: unify arch_acpi_processor_init_pdc The x86 and ia64 implementations of arch_acpi_processor_init_pdc() are almost exactly the same. The only difference is in what bits they set in obj_list buffer. Combine the boilerplate memory management code, and leave the arch-specific bit twiddling in separate implementations. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 931e735e9e3..87946b6da76 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,49 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_processor_init_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + pr->pdc = NULL; + + /* 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; + } + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + /* Now let the arch do the bit-twiddling to buf[] */ + arch_acpi_processor_init_pdc(pr); + + return; +} + /* * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. @@ -72,7 +115,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (arch_has_acpi_pdc() == false) return; - arch_acpi_processor_init_pdc(pr); + acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3 From 08ea48a326d8030ef5b7fb02292faf5a53c95e0a Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:24 -0700 Subject: ACPI: processor: factor out common _PDC settings Both x86 and ia64 initialize _PDC with mostly common bit settings. Factor out the common settings and leave the arch-specific ones alone. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 87946b6da76..ccda7c95d07 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,15 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_set_pdc_bits(u32 *buf) +{ + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + + /* Enable coordination with firmware's _TSD info */ + buf[2] = ACPI_PDC_SMP_T_SWCOORD; +} + static void acpi_processor_init_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -63,6 +72,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) return; } + acpi_set_pdc_bits(buf); + obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; obj->buffer.pointer = (u8 *) buf; -- cgit v1.2.3 From 6c5807d7bc7d051fce00863ffb98d36325501eb2 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:29 -0700 Subject: ACPI: processor: finish unifying arch_acpi_processor_init_pdc() The only thing arch-specific about calling _PDC is what bits get set in the input obj_list buffer. There's no need for several levels of indirection to twiddle those bits. Additionally, since we're just messing around with a buffer, we can simplify the interface; no need to pass around the entire struct acpi_processor * just to get at the buffer. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index ccda7c95d07..48df08ebcec 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -40,6 +40,9 @@ static void acpi_set_pdc_bits(u32 *buf) /* Enable coordination with firmware's _TSD info */ buf[2] = ACPI_PDC_SMP_T_SWCOORD; + + /* Twiddle arch-specific bits needed for _PDC */ + arch_acpi_set_pdc_bits(buf); } static void acpi_processor_init_pdc(struct acpi_processor *pr) @@ -81,9 +84,6 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj_list->pointer = obj; pr->pdc = obj_list; - /* Now let the arch do the bit-twiddling to buf[] */ - arch_acpi_processor_init_pdc(pr); - return; } -- cgit v1.2.3 From 47817254b8637b56730aec26eed2c337d3938bb5 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:34 -0700 Subject: ACPI: processor: unify arch_acpi_processor_cleanup_pdc The x86 and ia64 implementations of the function in $subject are exactly the same. Also, since the arch-specific implementations of setting _PDC have been completely hollowed out, remove the empty shells. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 48df08ebcec..e786e2ce188 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -1,3 +1,12 @@ +/* + * Copyright (C) 2005 Intel Corporation + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * + * Alex Chiang + * - Unified x86/ia64 implementations + * Venkatesh Pallipadi + * - Added _PDC for platforms with Intel CPUs + */ #include #include @@ -121,6 +130,16 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) return status; } +static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) +{ + if (pr->pdc) { + kfree(pr->pdc->pointer->buffer.pointer); + kfree(pr->pdc->pointer); + kfree(pr->pdc); + pr->pdc = NULL; + } +} + void acpi_processor_set_pdc(struct acpi_processor *pr) { if (arch_has_acpi_pdc() == false) @@ -128,7 +147,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); + acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From 3b407aef573b82139c3bc4dcaad2731fad56c054 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:39 -0700 Subject: ACPI: processor: introduce acpi_processor_alloc_pdc() acpi_processor_init_pdc() isn't really doing anything interesting with the struct acpi_processor * parameter. Its real job is to allocate the buffer for the _PDC bits. So rename the function to acpi_processor_alloc_pdc(), and just return the struct acpi_object_list * it's supposed to allocate. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index e786e2ce188..23d2828157e 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -54,26 +54,24 @@ static void acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static void acpi_processor_init_pdc(struct acpi_processor *pr) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; u32 *buf; - pr->pdc = NULL; - /* 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; + return NULL; } obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!obj) { printk(KERN_ERR "Memory allocation error\n"); kfree(obj_list); - return; + return NULL; } buf = kmalloc(12, GFP_KERNEL); @@ -81,7 +79,7 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) printk(KERN_ERR "Memory allocation error\n"); kfree(obj); kfree(obj_list); - return; + return NULL; } acpi_set_pdc_bits(buf); @@ -91,9 +89,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj->buffer.pointer = (u8 *) buf; obj_list->count = 1; obj_list->pointer = obj; - pr->pdc = obj_list; - return; + return obj_list; } /* @@ -142,10 +139,17 @@ static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + struct acpi_object_list *obj_list; + if (arch_has_acpi_pdc() == false) return; - acpi_processor_init_pdc(pr); + obj_list = acpi_processor_alloc_pdc(); + if (!obj_list) + return; + + pr->pdc = obj_list; + acpi_processor_eval_pdc(pr); acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3 From fa118564ed66f785f957d8230745b62e9244700d Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:45 -0700 Subject: ACPI: processor: change acpi_processor_eval_pdc interface acpi_processor_eval_pdc() really only needs a handle and an acpi_object_list * to do its work. No need to pass in a struct acpi_processor *, so let's be more specific about what we want. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 23d2828157e..974de4eb298 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -97,13 +97,11 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int acpi_processor_eval_pdc(struct acpi_processor *pr) +static int +acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { - struct acpi_object_list *pdc_in = pr->pdc; acpi_status status = AE_OK; - if (!pdc_in) - return status; if (idle_nomwait) { /* * If mwait is disabled for CPU C-states, the C2C3_FFH access @@ -118,7 +116,7 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -148,9 +146,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - pr->pdc = obj_list; - - acpi_processor_eval_pdc(pr); + acpi_processor_eval_pdc(pr->handle, obj_list); acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From b9c2db783456bcbce31e2482214cd337528db295 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:11 -0700 Subject: ACPI: processor: open code acpi_processor_cleanup_pdc We have the acpi_object_list * right there in acpi_processor_set_pdc() so it doesn't seem necessary for an entire helper function just to free it. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 974de4eb298..deeba22c932 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,16 +125,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - void acpi_processor_set_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -147,7 +137,10 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) return; acpi_processor_eval_pdc(pr->handle, obj_list); - acpi_processor_cleanup_pdc(pr); + + kfree(obj_list->pointer->buffer.pointer); + kfree(obj_list->pointer); + kfree(obj_list); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From 43bab25ced218385f7e6a076c2459ea008cfd2e1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:16 -0700 Subject: ACPI: processor: change acpi_processor_set_pdc() interface When calling _PDC, we really only need the handle to the processor to call the method; we don't look at any other parts of the struct acpi_processor * given to us. In the early path, when we walk the namespace, we are given the handle directly, so just pass it through to acpi_processor_set_pdc() without stuffing it into a wasteful struct acpi_processor allocated on the stack each time This saves 2834 bytes of stack. Update the interface accordingly. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 2 +- drivers/acpi/processor_pdc.c | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a19a4ff962e..9863c98c81b 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -763,7 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - acpi_processor_set_pdc(pr); + acpi_processor_set_pdc(pr->handle); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index deeba22c932..30e4dc0cdf3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,7 +125,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void acpi_processor_set_pdc(struct acpi_processor *pr) +void acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; @@ -136,7 +136,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - acpi_processor_eval_pdc(pr->handle, obj_list); + acpi_processor_eval_pdc(handle, obj_list); kfree(obj_list->pointer->buffer.pointer); kfree(obj_list->pointer); @@ -147,19 +147,7 @@ EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { - struct acpi_processor pr; - - pr.handle = handle; - - /* x86 implementation looks at pr.id to determine some - * CPU capabilites. We can just hard code to 0 since we're - * assuming the CPUs in the system are homogenous and all - * have the same capabilities. - */ - pr.id = 0; - - acpi_processor_set_pdc(&pr); - + acpi_processor_set_pdc(handle); return AE_OK; } -- cgit v1.2.3