processor_core.c revision 11130736c99c37e253f45b2d3fd30b07313f83c6
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>
1178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <acpi/acpi_drivers.h>
1378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include <acpi/processor.h>
1478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#include "internal.h"
1678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
1778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#define PREFIX			"ACPI: "
1878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
194d5d4cd88c542ff56cf7feacd29cc907f2abbfbbAlex ChiangACPI_MODULE_NAME("processor_core");
2078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
2178f1699659963fff97975df44db6d5dbe7218e55Alex Chiangstatic int set_no_mwait(const struct dmi_system_id *id)
2278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
2378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	printk(KERN_NOTICE PREFIX "%s detected - "
2478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		"disabling mwait for CPU C-states\n", id->ident);
2578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	idle_nomwait = 1;
2678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return 0;
2778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
2878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
2978f1699659963fff97975df44db6d5dbe7218e55Alex Chiangstatic struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
3078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{
3178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	set_no_mwait, "IFL91 board", {
3278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
3378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
3478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
3578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
3678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{
3778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	set_no_mwait, "Extensa 5220", {
3878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
3978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
4078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
4178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
4278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	{},
4378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang};
4478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
4578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang#ifdef CONFIG_SMP
4678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic struct acpi_table_madt *madt;
4778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
4878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_lapic_id(struct acpi_subtable_header *entry,
4978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		 u32 acpi_id, int *apic_id)
5078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
5178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_apic *lapic =
5278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_apic *)entry;
5311130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
5411130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	if (!(lapic->lapic_flags & ACPI_MADT_ENABLED))
5511130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang		return 0;
5611130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
5711130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	if (lapic->processor_id != acpi_id)
5811130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang		return 0;
5911130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang
6011130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	*apic_id = lapic->id;
6111130736c99c37e253f45b2d3fd30b07313f83c6Alex Chiang	return 1;
6278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
6378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
6478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_x2apic_id(struct acpi_subtable_header *entry,
6578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			 int device_declaration, u32 acpi_id, int *apic_id)
6678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
6778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_x2apic *apic =
6878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_x2apic *)entry;
6978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	u32 tmp = apic->local_apic_id;
7078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Only check enabled APICs*/
7278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!(apic->lapic_flags & ACPI_MADT_ENABLED))
7378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return 0;
7478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
7578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Device statement declaration type */
7678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (device_declaration) {
7778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (apic->uid == acpi_id)
7878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			goto found;
7978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
8078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
8178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 0;
8278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangfound:
8378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	*apic_id = tmp;
8478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 1;
8578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
8678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
8778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_lsapic_id(struct acpi_subtable_header *entry,
8878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		int device_declaration, u32 acpi_id, int *apic_id)
8978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
9078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_madt_local_sapic *lsapic =
9178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		(struct acpi_madt_local_sapic *)entry;
9278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	u32 tmp = (lsapic->id << 8) | lsapic->eid;
9378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
9478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Only check enabled APICs*/
9578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))
9678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return 0;
9778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
9878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Device statement declaration type */
9978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (device_declaration) {
10078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (entry->length < 16)
10178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			printk(KERN_ERR PREFIX
10278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			    "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n",
10378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			    tmp);
10478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		else if (lsapic->uid == acpi_id)
10578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			goto found;
10678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Processor statement declaration type */
10778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	} else if (lsapic->processor_id == acpi_id)
10878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto found;
10978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 0;
11178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangfound:
11278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	*apic_id = tmp;
11378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return 1;
11478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
11578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
11678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_madt_entry(int type, u32 acpi_id)
11778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
11878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	unsigned long madt_end, entry;
11978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
12078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
12178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!madt)
12278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
12378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
12478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	entry = (unsigned long)madt;
12578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	madt_end = entry + madt->header.length;
12678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
12778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	/* Parse all entries looking for a match. */
12878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
12978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	entry += sizeof(struct acpi_table_madt);
13078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	while (entry + sizeof(struct acpi_subtable_header) < madt_end) {
13178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		struct acpi_subtable_header *header =
13278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			(struct acpi_subtable_header *)entry;
13378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
13478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_lapic_id(header, acpi_id, &apic_id))
13578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
13678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		} else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) {
13778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_x2apic_id(header, type, acpi_id, &apic_id))
13878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
13978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
14078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			if (map_lsapic_id(header, type, acpi_id, &apic_id))
14178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				break;
14278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		}
14378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		entry += header->length;
14478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
14578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return apic_id;
14678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
14778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
14878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangstatic int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
14978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
15078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
15178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	union acpi_object *obj;
15278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	struct acpi_subtable_header *header;
15378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
15478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
15578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
15678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
15778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
15878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (!buffer.length || !buffer.pointer)
15978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
16078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
16178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	obj = buffer.pointer;
16278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (obj->type != ACPI_TYPE_BUFFER ||
16378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	    obj->buffer.length < sizeof(struct acpi_subtable_header)) {
16478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		goto exit;
16578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
16678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
16778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	header = (struct acpi_subtable_header *)obj->buffer.pointer;
16878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) {
16978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		map_lapic_id(header, acpi_id, &apic_id);
17078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	} else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) {
17178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		map_lsapic_id(header, type, acpi_id, &apic_id);
17278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
17378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
17478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangexit:
17578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (buffer.pointer)
17678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		kfree(buffer.pointer);
17778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return apic_id;
17878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
17978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
18078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiangint acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
18178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang{
18278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int i;
18378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	int apic_id = -1;
18478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
18578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	apic_id = map_mat_entry(handle, type, acpi_id);
18678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
18778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		apic_id = map_madt_entry(type, acpi_id);
18878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (apic_id == -1)
18978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		return apic_id;
19078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
19178ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	for_each_possible_cpu(i) {
19278ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		if (cpu_physical_id(i) == apic_id)
19378ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang			return i;
19478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	}
19578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	return -1;
19678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang}
19778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex ChiangEXPORT_SYMBOL_GPL(acpi_get_cpuid);
19878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang#endif
19978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
2005d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiangstatic bool processor_physically_present(acpi_handle handle)
2015d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang{
2025d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	int cpuid, type;
2035d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	u32 acpi_id;
2045d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_status status;
2055d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	acpi_object_type acpi_type;
2065d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	unsigned long long tmp;
2075d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	union acpi_object object = { 0 };
2085d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
2095d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2105d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	status = acpi_get_type(handle, &acpi_type);
2115d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (ACPI_FAILURE(status))
2125d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2135d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2145d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	switch (acpi_type) {
2155d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_PROCESSOR:
2165d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_object(handle, NULL, NULL, &buffer);
2175d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2185d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2195d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = object.processor.proc_id;
2205d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2215d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	case ACPI_TYPE_DEVICE:
2225d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp);
2235d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		if (ACPI_FAILURE(status))
2245d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang			return false;
2255d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		acpi_id = tmp;
2265d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		break;
2275d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	default:
2285d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2295d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	}
2305d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2315d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0;
2325d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	cpuid = acpi_get_cpuid(handle, type, acpi_id);
2335d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2345d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (cpuid == -1)
2355d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return false;
2365d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
2375d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	return true;
2385d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang}
23978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
24008ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiangstatic void acpi_set_pdc_bits(u32 *buf)
24108ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang{
24208ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[0] = ACPI_PDC_REVISION_ID;
24308ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[1] = 1;
24408ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
24508ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	/* Enable coordination with firmware's _TSD info */
24608ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
2476c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang
2486c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	/* Twiddle arch-specific bits needed for _PDC */
2496c5807d7bc7d051fce00863ffb98d36325501eb2Alex Chiang	arch_acpi_set_pdc_bits(buf);
25008ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang}
25108ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
2523b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiangstatic struct acpi_object_list *acpi_processor_alloc_pdc(void)
253407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang{
254407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	struct acpi_object_list *obj_list;
255407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	union acpi_object *obj;
256407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	u32 *buf;
257407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
258407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	/* allocate and initialize pdc. It will be used later. */
259407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
260407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj_list) {
261407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
2623b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
263407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
264407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
265407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
266407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!obj) {
267407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
268407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2693b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
270407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
271407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
272407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	buf = kmalloc(12, GFP_KERNEL);
273407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	if (!buf) {
274407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		printk(KERN_ERR "Memory allocation error\n");
275407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj);
276407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang		kfree(obj_list);
2773b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return NULL;
278407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	}
279407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
28008ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang	acpi_set_pdc_bits(buf);
28108ea48a326d8030ef5b7fb02292faf5a53c95e0aAlex Chiang
282407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->type = ACPI_TYPE_BUFFER;
283407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.length = 12;
284407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj->buffer.pointer = (u8 *) buf;
285407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->count = 1;
286407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang	obj_list->pointer = obj;
287407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
2883b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	return obj_list;
289407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang}
290407cd87c54e76c266245e8faef8dd4a84b7254feAlex Chiang
29178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang/*
29278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * _PDC is required for a BIOS-OS handshake for most of the newer
29378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang * ACPI processor features.
29478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang */
295fa118564ed66f785f957d8230745b62e9244700dAlex Chiangstatic int
296fa118564ed66f785f957d8230745b62e9244700dAlex Chiangacpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
29778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
29878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_status status = AE_OK;
29978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	if (idle_nomwait) {
30178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		/*
30278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
30378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * mode will be disabled in the parameter of _PDC object.
30478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 * Of course C1_FFH access mode will also be disabled.
30578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		 */
30678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		union acpi_object *obj;
30778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		u32 *buffer = NULL;
30878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
30978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		obj = pdc_in->pointer;
31078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer = (u32 *)(obj->buffer.pointer);
31178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
31278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
31378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	}
314fa118564ed66f785f957d8230745b62e9244700dAlex Chiang	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
31578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
31678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	if (ACPI_FAILURE(status))
31778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
31878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang		    "Could not evaluate _PDC, using legacy perf. control.\n"));
31978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
32078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return status;
32178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
32278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
32343bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiangvoid acpi_processor_set_pdc(acpi_handle handle)
32478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3253b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	struct acpi_object_list *obj_list;
3263b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
3271d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang	if (arch_has_acpi_pdc() == false)
3281d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang		return;
3291d9cb470a755409ce97c3376174b1e234bd20371Alex Chiang
3303b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	obj_list = acpi_processor_alloc_pdc();
3313b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang	if (!obj_list)
3323b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang		return;
3333b407aef573b82139c3bc4dcaad2731fad56c054Alex Chiang
33443bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_eval_pdc(handle, obj_list);
335b9c2db783456bcbce31e2482214cd337528db295Alex Chiang
336b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer->buffer.pointer);
337b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list->pointer);
338b9c2db783456bcbce31e2482214cd337528db295Alex Chiang	kfree(obj_list);
33978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
34078f1699659963fff97975df44db6d5dbe7218e55Alex ChiangEXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
34178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
34278f1699659963fff97975df44db6d5dbe7218e55Alex Chiangstatic acpi_status
34378f1699659963fff97975df44db6d5dbe7218e55Alex Chiangearly_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
34478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
3455d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang	if (processor_physically_present(handle) == false)
3465d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang		return AE_OK;
3475d554a7bb0643a6151a84319bfeba8270bf5269eAlex Chiang
34843bab25ced218385f7e6a076c2459ea008cfd2e1Alex Chiang	acpi_processor_set_pdc(handle);
34978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	return AE_OK;
35078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
35178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
3527a0b73a49ab56fb1e836675c00d6d0d2ba39a714Tony Luckvoid __init acpi_early_processor_set_pdc(void)
35378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang{
35478ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
35578ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang#ifdef CONFIG_SMP
35678ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang	if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0,
35778ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang				(struct acpi_table_header **)&madt)))
35878ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang		madt = NULL;
35978ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang#endif
36078ed8bd2944b6400f742306e5fe9d1b9b6bf18baAlex Chiang
36178f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	/*
36278f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * Check whether the system is DMI table. If yes, OSPM
36378f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 * should not use mwait for CPU-states.
36478f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	 */
36578f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	dmi_check_system(processor_idle_dmi_table);
36678f1699659963fff97975df44db6d5dbe7218e55Alex Chiang
36778f1699659963fff97975df44db6d5dbe7218e55Alex Chiang	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
36878f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    ACPI_UINT32_MAX,
36978f1699659963fff97975df44db6d5dbe7218e55Alex Chiang			    early_init_pdc, NULL, NULL, NULL);
37078f1699659963fff97975df44db6d5dbe7218e55Alex Chiang}
371