summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_pdc.c
blob: b416c32dda04917b501446dde0bf6873115f86f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <linux/dmi.h>

#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>

#include "internal.h"

#define PREFIX			"ACPI: "
#define _COMPONENT		ACPI_PROCESSOR_COMPONENT
ACPI_MODULE_NAME("processor_pdc");

static int set_no_mwait(const struct dmi_system_id *id)
{
	printk(KERN_NOTICE PREFIX "%s detected - "
		"disabling mwait for CPU C-states\n", id->ident);
	idle_nomwait = 1;
	return 0;
}

static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
	{
	set_no_mwait, "IFL91 board", {
	DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
	DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"),
	DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"),
	DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL},
	{
	set_no_mwait, "Extensa 5220", {
	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
	DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
	DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
	DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL},
	{},
};

/*
 * _PDC is required for a BIOS-OS handshake for most of the newer
 * ACPI processor features.
 */
static int acpi_processor_eval_pdc(struct acpi_processor *pr)
{
	struct acpi_object_list *pdc_in = pr->pdc;
	acpi_status status = AE_OK;

	if (!pdc_in)
		return status;
	if (idle_nomwait) {
		/*
		 * If mwait is disabled for CPU C-states, the C2C3_FFH access
		 * mode will be disabled in the parameter of _PDC object.
		 * Of course C1_FFH access mode will also be disabled.
		 */
		union acpi_object *obj;
		u32 *buffer = NULL;

		obj = pdc_in->pointer;
		buffer = (u32 *)(obj->buffer.pointer);
		buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);

	}
	status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL);

	if (ACPI_FAILURE(status))
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
		    "Could not evaluate _PDC, using legacy perf. control.\n"));

	return status;
}

void acpi_processor_set_pdc(struct acpi_processor *pr)
{
	arch_acpi_processor_init_pdc(pr);
	acpi_processor_eval_pdc(pr);
	arch_acpi_processor_cleanup_pdc(pr);
}
EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);

static acpi_status
early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
{
	struct acpi_processor pr;

	pr.handle = handle;

	/* x86 implementation looks at pr.id to determine some
	 * CPU capabilites. We can just hard code to 0 since we're
	 * assuming the CPUs in the system are homogenous and all
	 * have the same capabilities.
	 */
	pr.id = 0;

	acpi_processor_set_pdc(&pr);

	return AE_OK;
}

void acpi_early_processor_set_pdc(void)
{
	/*
	 * Check whether the system is DMI table. If yes, OSPM
	 * should not use mwait for CPU-states.
	 */
	dmi_check_system(processor_idle_dmi_table);

	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
			    ACPI_UINT32_MAX,
			    early_init_pdc, NULL, NULL, NULL);
}