processor_core.c revision d18960494f65ca4fa0d67c865aaca99452070d15
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
2278f1699659963fff97975df44db6d5dbe7218e55Alex Chiangstatic int 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
3078f1699659963fff97975df44db6d5dbe7218e55Alex Chiangstatic struct dmi_system_id __cpuinitdata 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 Chiang#ifdef CONFIG_SMP
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{
16878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int i;
16978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
17078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
17178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	apic_id = map_mat_entry(handle, type, acpi_id);
17278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
17378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		apic_id = map_madt_entry(type, acpi_id);
17478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
17578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
17678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
17778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	for_each_possible_cpu(i) {
17878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (cpu_physical_id(i) == apic_id)
17978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			return i;
18078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
18178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return -1;
18278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
18378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex ChiangEXPORT_SYMBOL_GPL(acpi_get_cpuid);
18478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang#endif
18578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
1865d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiangstatic bool processor_physically_present(acpi_handle handle)
1875d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang{
1885d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	int cpuid, type;
1895d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	u32 acpi_id;
1905d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_status status;
1915d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_object_type acpi_type;
1925d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	unsigned long long tmp;
1935d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	union acpi_object object = { 0 };
1945d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
1955d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
1965d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	status = acpi_get_type(handle, &acpi_type);
1975d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (ACPI_FAILURE(status))
1985d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
1995d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2005d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	switch (acpi_type) {
2015d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_PROCESSOR:
2025d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
2035d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2045d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2055d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = object.processor.proc_id;
2065d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2075d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_DEVICE:
2085d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
2095d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2105d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2115d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = tmp;
2125d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2135d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	default:
2145d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2155d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	}
2165d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2175d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
2185d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	cpuid = acpi_get_cpuid(handle, type, acpi_id);
2195d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
220856b185dd23da39e562983fbf28860f54e661b41Alex Chiang	if ((cpuid == -1) && (num_possible_cpus() > 1))
2215d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2225d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2235d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	return true;
2245d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang}
22578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
22608ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiangstatic void acpi_set_pdc_bits(u32 *buf)
22708ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang{
22808ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[0] = ACPI_PDC_REVISION_ID;
22908ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[1] = 1;
23008ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
23108ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	/* Enable coordination with firmware's _TSD info */
23208ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
2336c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang
2346c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	/* Twiddle arch-specific bits needed for _PDC */
2356c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	arch_acpi_set_pdc_bits(buf);
23608ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang}
23708ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
2383b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiangstatic struct acpi_object_list *acpi_processor_alloc_pdc(void)
239407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang{
240407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	struct acpi_object_list *obj_list;
241407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	union acpi_object *obj;
242407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	u32 *buf;
243407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
244407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	/* allocate and initialize pdc. It will be used later. */
245407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
246407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj_list) {
247407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
2483b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
249407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
250407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
251407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
252407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj) {
253407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
254407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2553b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
256407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
257407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
258407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	buf = kmalloc(12, GFP_KERNEL);
259407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!buf) {
260407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
261407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj);
262407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2633b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
264407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
265407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
26608ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	acpi_set_pdc_bits(buf);
26708ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
268407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->type = ACPI_TYPE_BUFFER;
269407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.length = 12;
270407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.pointer = (u8 *) buf;
271407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->count = 1;
272407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->pointer = obj;
273407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
2743b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	return obj_list;
275407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang}
276407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
27778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang/*
27878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * _PDC is required for a BIOS-OS handshake for most of the newer
27978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * ACPI processor features.
28078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang */
281fa118564ed66f785f957d8230745b62e9244700dAlex Chiangstatic int
282fa118564ed66f785f957d8230745b62e9244700dAlex Chiangacpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
28378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
28478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_status status = AE_OK;
28578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
286d18960494f65ca4fa0d67c865aaca99452070d15Thomas Renninger	if (boot_option_idle_override == IDLE_NOMWAIT) {
28778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		/*
28878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
28978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * mode will be disabled in the parameter of _PDC object.
29078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * Of course C1_FFH access mode will also be disabled.
29178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 */
29278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		union acpi_object *obj;
29378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		u32 *buffer = NULL;
29478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
29578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		obj = pdc_in->pointer;
29678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer = (u32 *)(obj->buffer.pointer);
29778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
29878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
29978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	}
300fa118564ed66f785f957d8230745b62e9244700dAlex Chiang	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
30178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	if (ACPI_FAILURE(status))
30378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
30478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		    "Could not evaluate _PDC, using legacy perf. control.\n"));
30578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return status;
30778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
30878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30943bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiangvoid acpi_processor_set_pdc(acpi_handle handle)
31078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3113b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	struct acpi_object_list *obj_list;
3123b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
3131d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang	if (arch_has_acpi_pdc() == false)
3141d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang		return;
3151d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang
3163b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	obj_list = acpi_processor_alloc_pdc();
3173b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	if (!obj_list)
3183b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return;
3193b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
32043bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_eval_pdc(handle, obj_list);
321b9c2db783456bcbce31e2482214cd337528db295Alex Chiang
322b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer->buffer.pointer);
323b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer);
324b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list);
32578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
32678f1699659963fff97975df44db6d5dbe7218e55Alex ChiangEXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
32778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
32878f1699659963fff97975df44db6d5dbe7218e55Alex Chiangstatic acpi_status
32978f1699659963fff97975df44db6d5dbe7218e55Alex Chiangearly_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
33078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3315d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (processor_physically_present(handle) == false)
3325d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return AE_OK;
3335d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
33443bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_set_pdc(handle);
33578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return AE_OK;
33678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
33778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
3387a0b73a49ab56fb1e836675c00d6d0d2ba39a714Tony Luckvoid __init acpi_early_processor_set_pdc(void)
33978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
34078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	/*
34178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * Check whether the system is DMI table. If yes, OSPM
34278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * should not use mwait for CPU-states.
34378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 */
34478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	dmi_check_system(processor_idle_dmi_table);
34578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
34678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
34778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    ACPI_UINT32_MAX,
34878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    early_init_pdc, NULL, NULL, NULL);
349c1e0ddbf0a97e1704d7f13b4934f9acca002402dYinghai Lu	acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL);
35078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
351