processor_core.c revision 932df7414336a00f45e5aec62724cf736b0bcfd4
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 */
1078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <linux/dmi.h>
115a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
1278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <acpi/acpi_drivers.h>
1478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <acpi/processor.h>
1578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include "internal.h"
1778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#define PREFIX			"ACPI: "
1978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
204d5d4cd88c542ff56cf7feacd29cc907f2abbfbbAlex ChiangACPI_MODULE_NAME("processor_core");
2178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
226430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic int __init set_no_mwait(const struct dmi_system_id *id)
2378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
2478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	printk(KERN_NOTICE PREFIX "%s detected - "
2578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		"disabling mwait for CPU C-states\n", id->ident);
26d18960494f65ca4fa0d67c865aaca99452070d15Thomas Renninger	boot_option_idle_override = IDLE_NOMWAIT;
2778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return 0;
2878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
2978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
306430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic struct dmi_system_id __initdata processor_idle_dmi_table[] = {
3178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{
3278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	set_no_mwait, "Extensa 5220", {
3378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
3478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
3578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
3678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
3778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{},
3878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang};
3978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
4078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_lapic_id(struct acpi_subtable_header *entry,
4178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		 u32 acpi_id, int *apic_id)
4278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
4378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_apic *lapic =
4478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_apic *)entry;
4511130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
4611130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
4711130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang		return 0;
4811130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
4911130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	if (lapic->processor_id != acpi_id)
5011130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang		return 0;
5111130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
5211130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	*apic_id = lapic->id;
5311130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	return 1;
5478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
5578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
5678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_x2apic_id(struct acpi_subtable_header *entry,
5778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			 int device_declaration, u32 acpi_id, int *apic_id)
5878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
5978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_x2apic *apic =
6078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_x2apic *)entry;
6178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
6278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
6378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return 0;
6478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
65d67420956b7b1dcffb894b2f1f81b9408fca1b4cAlex Chiang	if (device_declaration && (apic->uid == acpi_id)) {
66d67420956b7b1dcffb894b2f1f81b9408fca1b4cAlex Chiang		*apic_id = apic->local_apic_id;
67d67420956b7b1dcffb894b2f1f81b9408fca1b4cAlex Chiang		return 1;
6878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
6978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 0;
7178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
7278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_lsapic_id(struct acpi_subtable_header *entry,
7478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		int device_declaration, u32 acpi_id, int *apic_id)
7578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
7678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_sapic *lsapic =
7778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_sapic *)entry;
7878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
8078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return 0;
8178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
8278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (device_declaration) {
83eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang		if ((entry->length < 16) || (lsapic->uid != acpi_id))
84eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang			return 0;
85eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang	} else if (lsapic->processor_id != acpi_id)
86eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang		return 0;
8778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
88eae701ceadf5aa3fc3b334029ef71f6885ef1cdeAlex Chiang	*apic_id = (lsapic->id << 8) | lsapic->eid;
8978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 1;
9078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
9178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
9278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_madt_entry(int type, u32 acpi_id)
9378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
9478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	unsigned long madt_end, entry;
95149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	static struct acpi_table_madt *madt;
96149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	static int read_madt;
9778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
9878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
99149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	if (!read_madt) {
100149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang		if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
101149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang					(struct acpi_table_header **)&madt)))
102149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang			madt = NULL;
103149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang		read_madt++;
104149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang	}
105149fe9c293f76803206648270ca24fc2604d5f01Alex Chiang
10678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!madt)
10778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
10878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
10978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	entry = (unsigned long)madt;
11078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	madt_end = entry + madt->header.length;
11178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Parse all entries looking for a match. */
11378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	entry += sizeof(struct acpi_table_madt);
11578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
11678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		struct acpi_subtable_header *header =
11778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			(struct acpi_subtable_header *)entry;
11878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
11978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_lapic_id(header, acpi_id, &apic_id))
12078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
12178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
12278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_x2apic_id(header, type, acpi_id, &apic_id))
12378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
12478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
12578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_lsapic_id(header, type, acpi_id, &apic_id))
12678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
12778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		}
12878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		entry += header->length;
12978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
13078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return apic_id;
13178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
13278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
13378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
13478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
13578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
13678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	union acpi_object *obj;
13778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_subtable_header *header;
13878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
13978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
14178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
14278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!buffer.length || !buffer.pointer)
14478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
14578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	obj = buffer.pointer;
14778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (obj->type != ACPI_TYPE_BUFFER ||
14878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
14978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
15078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
15178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
15278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	header = (struct acpi_subtable_header *)obj->buffer.pointer;
15378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
15478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		map_lapic_id(header, acpi_id, &apic_id);
15578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
15678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		map_lsapic_id(header, type, acpi_id, &apic_id);
15778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
15878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
15978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangexit:
16078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (buffer.pointer)
16178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		kfree(buffer.pointer);
16278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return apic_id;
16378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
16478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
16578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangint acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
16678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
167932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#ifdef CONFIG_SMP
16878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int i;
169932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#endif
17078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
17178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
17278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	apic_id = map_mat_entry(handle, type, acpi_id);
17378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
17478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		apic_id = map_madt_entry(type, acpi_id);
17578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
17678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
17778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
178932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#ifdef CONFIG_SMP
17978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	for_each_possible_cpu(i) {
18078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (cpu_physical_id(i) == apic_id)
18178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			return i;
18278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
183932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#else
184932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming	/* In UP kernel, only processor 0 is valid */
185932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming	if (apic_id == 0)
186932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming		return apic_id;
187932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming#endif
18878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return -1;
18978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
19078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex ChiangEXPORT_SYMBOL_GPL(acpi_get_cpuid);
19178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
1926430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic bool __init processor_physically_present(acpi_handle handle)
1935d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang{
1945d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	int cpuid, type;
1955d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	u32 acpi_id;
1965d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_status status;
1975d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_object_type acpi_type;
1985d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	unsigned long long tmp;
1995d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	union acpi_object object = { 0 };
2005d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
2015d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2025d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	status = acpi_get_type(handle, &acpi_type);
2035d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (ACPI_FAILURE(status))
2045d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2055d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2065d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	switch (acpi_type) {
2075d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_PROCESSOR:
2085d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
2095d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2105d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2115d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = object.processor.proc_id;
2125d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2135d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_DEVICE:
2145d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
2155d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2165d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2175d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = tmp;
2185d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2195d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	default:
2205d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2215d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	}
2225d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2235d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
2245d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	cpuid = acpi_get_cpuid(handle, type, acpi_id);
2255d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
226932df7414336a00f45e5aec62724cf736b0bcfd4Lin Ming	if (cpuid == -1)
2275d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2285d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2295d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	return true;
2305d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang}
23178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
232af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichstatic void __cpuinit acpi_set_pdc_bits(u32 *buf)
23308ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang{
23408ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[0] = ACPI_PDC_REVISION_ID;
23508ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[1] = 1;
23608ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
23708ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	/* Enable coordination with firmware's _TSD info */
23808ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
2396c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang
2406c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	/* Twiddle arch-specific bits needed for _PDC */
2416c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	arch_acpi_set_pdc_bits(buf);
24208ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang}
24308ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
244af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichstatic struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void)
245407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang{
246407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	struct acpi_object_list *obj_list;
247407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	union acpi_object *obj;
248407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	u32 *buf;
249407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
250407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	/* allocate and initialize pdc. It will be used later. */
251407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
252407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj_list) {
253407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
2543b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
255407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
256407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
257407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
258407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj) {
259407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
260407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2613b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
262407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
263407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
264407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	buf = kmalloc(12, GFP_KERNEL);
265407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!buf) {
266407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
267407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj);
268407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2693b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
270407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
271407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
27208ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	acpi_set_pdc_bits(buf);
27308ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
274407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->type = ACPI_TYPE_BUFFER;
275407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.length = 12;
276407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.pointer = (u8 *) buf;
277407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->count = 1;
278407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->pointer = obj;
279407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
2803b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	return obj_list;
281407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang}
282407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
28378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang/*
28478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * _PDC is required for a BIOS-OS handshake for most of the newer
28578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * ACPI processor features.
28678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang */
287af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichstatic int __cpuinit
288fa118564ed66f785f957d8230745b62e9244700dAlex Chiangacpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
28978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
29078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_status status = AE_OK;
29178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
292d18960494f65ca4fa0d67c865aaca99452070d15Thomas Renninger	if (boot_option_idle_override == IDLE_NOMWAIT) {
29378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		/*
29478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
29578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * mode will be disabled in the parameter of _PDC object.
29678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * Of course C1_FFH access mode will also be disabled.
29778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 */
29878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		union acpi_object *obj;
29978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		u32 *buffer = NULL;
30078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		obj = pdc_in->pointer;
30278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer = (u32 *)(obj->buffer.pointer);
30378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
30478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	}
306fa118564ed66f785f957d8230745b62e9244700dAlex Chiang	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
30778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	if (ACPI_FAILURE(status))
30978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
31078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		    "Could not evaluate _PDC, using legacy perf. control.\n"));
31178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
31278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return status;
31378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
31478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
315af10f941ab7807d8b0bb3c66e679d8a6bbbe7485Jan Beulichvoid __cpuinit acpi_processor_set_pdc(acpi_handle handle)
31678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3173b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	struct acpi_object_list *obj_list;
3183b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
3191d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang	if (arch_has_acpi_pdc() == false)
3201d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang		return;
3211d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang
3223b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	obj_list = acpi_processor_alloc_pdc();
3233b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	if (!obj_list)
3243b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return;
3253b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
32643bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_eval_pdc(handle, obj_list);
327b9c2db783456bcbce31e2482214cd337528db295Alex Chiang
328b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer->buffer.pointer);
329b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer);
330b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list);
33178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
33278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
3336430c9c12a7dbb8f60f0d8294b73b3c0bb03f64fJan Beulichstatic acpi_status __init
33478f1699659963fff97975df44db6d5dbe7218e55Alex Chiangearly_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
33578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3365d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (processor_physically_present(handle) == false)
3375d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return AE_OK;
3385d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
33943bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_set_pdc(handle);
34078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return AE_OK;
34178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
34278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
3437a0b73a49ab56fb1e836675c00d6d0d2ba39a714Tony Luckvoid __init acpi_early_processor_set_pdc(void)
34478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
34578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	/*
34678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * Check whether the system is DMI table. If yes, OSPM
34778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * should not use mwait for CPU-states.
34878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 */
34978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	dmi_check_system(processor_idle_dmi_table);
35078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
35178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
35278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    ACPI_UINT32_MAX,
35378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    early_init_pdc, NULL, NULL, NULL);
354c1e0ddbf0a97e1704d7f13b4934f9acca002402dYinghai Lu	acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
35578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
356