processor_core.c revision 214f2c90b970e098e75cf719c0c5b0f1fe69b716
147817254b8637b56730aec26eed2c337d3938bb5Alex Chiang/*
247817254b8637b56730aec26eed2c337d3938bb5Alex Chiang * Copyright (C) 2005 Intel Corporation
347817254b8637b56730aec26eed2c337d3938bb5Alex Chiang * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
447817254b8637b56730aec26eed2c337d3938bb5Alex Chiang *
547817254b8637b56730aec26eed2c337d3938bb5Alex Chiang *	Alex Chiang <achiang@hp.com>
647817254b8637b56730aec26eed2c337d3938bb5Alex Chiang *	- Unified x86/ia64 implementations
747817254b8637b56730aec26eed2c337d3938bb5Alex Chiang *	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
847817254b8637b56730aec26eed2c337d3938bb5Alex Chiang *	- Added _PDC for platforms with Intel CPUs
947817254b8637b56730aec26eed2c337d3938bb5Alex Chiang */
10214f2c90b970e098e75cf719c0c5b0f1fe69b716Paul Gortmaker#include <linux/export.h>
1178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <linux/dmi.h>
125a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
1378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <acpi/acpi_drivers.h>
1578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <acpi/processor.h>
1678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include "internal.h"
1878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#define PREFIX			"ACPI: "
2078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
214d5d4cd88c542ff56cf7feacd29cc907f2abbfbbAlex ChiangACPI_MODULE_NAME("processor_core");
2278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
236430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic int __init set_no_mwait(const struct dmi_system_id *id)
2478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
2578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	printk(KERN_NOTICE PREFIX "%s detected - "
2678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		"disabling mwait for CPU C-states\n", id->ident);
27d18960494f65ca4fa0d67c865aaca99452070d15Thomas Renninger	boot_option_idle_override = IDLE_NOMWAIT;
2878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return 0;
2978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
3078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
316430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic struct dmi_system_id __initdata processor_idle_dmi_table[] = {
3278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{
3378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	set_no_mwait, "Extensa 5220", {
3478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
3578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
3678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
3778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
3878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{},
3978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang};
4078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
4178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_lapic_id(struct acpi_subtable_header *entry,
4278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		 u32 acpi_id, int *apic_id)
4378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
4478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_apic *lapic =
4578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_apic *)entry;
4611130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
4711130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
4811130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang		return 0;
4911130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
5011130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	if (lapic->processor_id != acpi_id)
5111130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang		return 0;
5211130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
5311130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	*apic_id = lapic->id;
5411130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	return 1;
5578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
5678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
5778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_x2apic_id(struct acpi_subtable_header *entry,
5878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			 int device_declaration, u32 acpi_id, int *apic_id)
5978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
6078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_x2apic *apic =
6178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_x2apic *)entry;
6278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
6378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
6478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return 0;
6578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
66d67420956b7b1dcffb894b2f1f81b9408fca1b4cAlex Chiang	if (device_declaration && (apic->uid == acpi_id)) {
67d67420956b7b1dcffb894b2f1f81b9408fca1b4cAlex Chiang		*apic_id = apic->local_apic_id;
68d67420956b7b1dcffb894b2f1f81b9408fca1b4cAlex Chiang		return 1;
6978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
7078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 0;
7278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
7378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_lsapic_id(struct acpi_subtable_header *entry,
7578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		int device_declaration, u32 acpi_id, int *apic_id)
7678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
7778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_sapic *lsapic =
7878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_sapic *)entry;
7978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
8078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
8178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return 0;
8278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
8378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (device_declaration) {
84eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang		if ((entry->length < 16) || (lsapic->uid != acpi_id))
85eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang			return 0;
86eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang	} else if (lsapic->processor_id != acpi_id)
87eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang		return 0;
8878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
89eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang	*apic_id = (lsapic->id << 8) | lsapic->eid;
9078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 1;
9178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
9278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
9378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_madt_entry(int type, u32 acpi_id)
9478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
9578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	unsigned long madt_end, entry;
96149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	static struct acpi_table_madt *madt;
97149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	static int read_madt;
9878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
9978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
100149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	if (!read_madt) {
101149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
102149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang					(struct acpi_table_header **)&madt)))
103149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang			madt = NULL;
104149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang		read_madt++;
105149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	}
106149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang
10778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!madt)
10878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
10978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	entry = (unsigned long)madt;
11178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	madt_end = entry + madt->header.length;
11278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Parse all entries looking for a match. */
11478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	entry += sizeof(struct acpi_table_madt);
11678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
11778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		struct acpi_subtable_header *header =
11878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			(struct acpi_subtable_header *)entry;
11978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
12078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_lapic_id(header, acpi_id, &apic_id))
12178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
12278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
12378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_x2apic_id(header, type, acpi_id, &apic_id))
12478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
12578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
12678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_lsapic_id(header, type, acpi_id, &apic_id))
12778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
12878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		}
12978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		entry += header->length;
13078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
13178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return apic_id;
13278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
13378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
13478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
13578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
13678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
13778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	union acpi_object *obj;
13878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_subtable_header *header;
13978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
14078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
14278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
14378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!buffer.length || !buffer.pointer)
14578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
14678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	obj = buffer.pointer;
14878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (obj->type != ACPI_TYPE_BUFFER ||
14978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
15078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
15178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
15278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
15378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	header = (struct acpi_subtable_header *)obj->buffer.pointer;
15478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
15578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		map_lapic_id(header, acpi_id, &apic_id);
15678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
15778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		map_lsapic_id(header, type, acpi_id, &apic_id);
15878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
15978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
16078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangexit:
16178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (buffer.pointer)
16278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		kfree(buffer.pointer);
16378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return apic_id;
16478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
16578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
16678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangint acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
16778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
168932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#ifdef CONFIG_SMP
16978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int i;
170932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#endif
17178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
17278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
17378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	apic_id = map_mat_entry(handle, type, acpi_id);
17478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
17578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		apic_id = map_madt_entry(type, acpi_id);
17678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
17778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
17878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
179932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#ifdef CONFIG_SMP
18078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	for_each_possible_cpu(i) {
18178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (cpu_physical_id(i) == apic_id)
18278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			return i;
18378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
184932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#else
185932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming	/* In UP kernel, only processor 0 is valid */
186932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming	if (apic_id == 0)
187932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming		return apic_id;
188932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#endif
18978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return -1;
19078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
19178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex ChiangEXPORT_SYMBOL_GPL(acpi_get_cpuid);
19278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
1936430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic bool __init processor_physically_present(acpi_handle handle)
1945d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang{
1955d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	int cpuid, type;
1965d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	u32 acpi_id;
1975d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_status status;
1985d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_object_type acpi_type;
1995d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	unsigned long long tmp;
2005d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	union acpi_object object = { 0 };
2015d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
2025d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2035d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	status = acpi_get_type(handle, &acpi_type);
2045d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (ACPI_FAILURE(status))
2055d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2065d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2075d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	switch (acpi_type) {
2085d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_PROCESSOR:
2095d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
2105d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2115d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2125d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = object.processor.proc_id;
2135d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2145d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_DEVICE:
2155d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
2165d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2175d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2185d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = tmp;
2195d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2205d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	default:
2215d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2225d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	}
2235d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2245d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
2255d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	cpuid = acpi_get_cpuid(handle, type, acpi_id);
2265d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
227932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming	if (cpuid == -1)
2285d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2295d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2305d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	return true;
2315d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang}
23278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
233af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichstatic void __cpuinit acpi_set_pdc_bits(u32 *buf)
23408ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang{
23508ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[0] = ACPI_PDC_REVISION_ID;
23608ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[1] = 1;
23708ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
23808ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	/* Enable coordination with firmware's _TSD info */
23908ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
2406c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang
2416c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	/* Twiddle arch-specific bits needed for _PDC */
2426c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	arch_acpi_set_pdc_bits(buf);
24308ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang}
24408ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
245af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichstatic struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void)
246407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang{
247407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	struct acpi_object_list *obj_list;
248407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	union acpi_object *obj;
249407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	u32 *buf;
250407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
251407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	/* allocate and initialize pdc. It will be used later. */
252407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
253407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj_list) {
254407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
2553b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
256407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
257407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
258407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
259407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj) {
260407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
261407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2623b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
263407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
264407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
265407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	buf = kmalloc(12, GFP_KERNEL);
266407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!buf) {
267407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
268407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj);
269407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2703b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
271407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
272407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
27308ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	acpi_set_pdc_bits(buf);
27408ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
275407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->type = ACPI_TYPE_BUFFER;
276407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.length = 12;
277407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.pointer = (u8 *) buf;
278407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->count = 1;
279407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->pointer = obj;
280407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
2813b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	return obj_list;
282407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang}
283407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
28478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang/*
28578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * _PDC is required for a BIOS-OS handshake for most of the newer
28678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * ACPI processor features.
28778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang */
288af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichstatic int __cpuinit
289fa118564ed66f785f957d8230745b62e9244700dAlex Chiangacpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
29078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
29178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_status status = AE_OK;
29278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
293d18960494f65ca4fa0d67c865aaca99452070d15Thomas Renninger	if (boot_option_idle_override == IDLE_NOMWAIT) {
29478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		/*
29578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
29678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * mode will be disabled in the parameter of _PDC object.
29778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * Of course C1_FFH access mode will also be disabled.
29878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 */
29978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		union acpi_object *obj;
30078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		u32 *buffer = NULL;
30178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		obj = pdc_in->pointer;
30378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer = (u32 *)(obj->buffer.pointer);
30478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
30578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	}
307fa118564ed66f785f957d8230745b62e9244700dAlex Chiang	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
30878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	if (ACPI_FAILURE(status))
31078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
31178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		    "Could not evaluate _PDC, using legacy perf. control.\n"));
31278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
31378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return status;
31478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
31578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
316af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichvoid __cpuinit acpi_processor_set_pdc(acpi_handle handle)
31778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3183b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	struct acpi_object_list *obj_list;
3193b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
3201d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang	if (arch_has_acpi_pdc() == false)
3211d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang		return;
3221d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang
3233b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	obj_list = acpi_processor_alloc_pdc();
3243b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	if (!obj_list)
3253b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return;
3263b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
32743bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_eval_pdc(handle, obj_list);
328b9c2db783456bcbce31e2482214cd337528db295Alex Chiang
329b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer->buffer.pointer);
330b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer);
331b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list);
33278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
33378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
3346430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic acpi_status __init
33578f1699659963fff97975df44db6d5dbe7218e55Alex Chiangearly_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
33678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3375d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (processor_physically_present(handle) == false)
3385d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return AE_OK;
3395d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
34043bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_set_pdc(handle);
34178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return AE_OK;
34278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
34378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
3447a0b73a49ab56fb1e836675c00d6d0d2ba39a714Tony Luckvoid __init acpi_early_processor_set_pdc(void)
34578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
34678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	/*
34778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * Check whether the system is DMI table. If yes, OSPM
34878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * should not use mwait for CPU-states.
34978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 */
35078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	dmi_check_system(processor_idle_dmi_table);
35178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
35278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
35378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    ACPI_UINT32_MAX,
35478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    early_init_pdc, NULL, NULL, NULL);
355c1e0ddbf0a97e1704d7f13b4934f9acca002402dYinghai Lu	acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
35678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
357