Blame view

drivers/acpi/processor_pdc.c 4.84 KB
47817254b   Alex Chiang   ACPI: processor: ...
1
2
3
4
5
6
7
8
9
  /*
   * Copyright (C) 2005 Intel Corporation
   * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
   *
   *	Alex Chiang <achiang@hp.com>
   *	- Unified x86/ia64 implementations
   *	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
   *	- Added _PDC for platforms with Intel CPUs
   */
78f169965   Alex Chiang   ACPI: processor: ...
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
  #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
  ", 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},
  	{},
  };
08ea48a32   Alex Chiang   ACPI: processor: ...
45
46
47
48
49
50
51
  static void acpi_set_pdc_bits(u32 *buf)
  {
  	buf[0] = ACPI_PDC_REVISION_ID;
  	buf[1] = 1;
  
  	/* Enable coordination with firmware's _TSD info */
  	buf[2] = ACPI_PDC_SMP_T_SWCOORD;
6c5807d7b   Alex Chiang   ACPI: processor: ...
52
53
54
  
  	/* Twiddle arch-specific bits needed for _PDC */
  	arch_acpi_set_pdc_bits(buf);
08ea48a32   Alex Chiang   ACPI: processor: ...
55
  }
3b407aef5   Alex Chiang   ACPI: processor: ...
56
  static struct acpi_object_list *acpi_processor_alloc_pdc(void)
407cd87c5   Alex Chiang   ACPI: processor: ...
57
58
59
60
  {
  	struct acpi_object_list *obj_list;
  	union acpi_object *obj;
  	u32 *buf;
407cd87c5   Alex Chiang   ACPI: processor: ...
61
62
63
64
65
  	/* allocate and initialize pdc. It will be used later. */
  	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
  	if (!obj_list) {
  		printk(KERN_ERR "Memory allocation error
  ");
3b407aef5   Alex Chiang   ACPI: processor: ...
66
  		return NULL;
407cd87c5   Alex Chiang   ACPI: processor: ...
67
68
69
70
71
72
73
  	}
  
  	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
  	if (!obj) {
  		printk(KERN_ERR "Memory allocation error
  ");
  		kfree(obj_list);
3b407aef5   Alex Chiang   ACPI: processor: ...
74
  		return NULL;
407cd87c5   Alex Chiang   ACPI: processor: ...
75
76
77
78
79
80
81
82
  	}
  
  	buf = kmalloc(12, GFP_KERNEL);
  	if (!buf) {
  		printk(KERN_ERR "Memory allocation error
  ");
  		kfree(obj);
  		kfree(obj_list);
3b407aef5   Alex Chiang   ACPI: processor: ...
83
  		return NULL;
407cd87c5   Alex Chiang   ACPI: processor: ...
84
  	}
08ea48a32   Alex Chiang   ACPI: processor: ...
85
  	acpi_set_pdc_bits(buf);
407cd87c5   Alex Chiang   ACPI: processor: ...
86
87
88
89
90
  	obj->type = ACPI_TYPE_BUFFER;
  	obj->buffer.length = 12;
  	obj->buffer.pointer = (u8 *) buf;
  	obj_list->count = 1;
  	obj_list->pointer = obj;
407cd87c5   Alex Chiang   ACPI: processor: ...
91

3b407aef5   Alex Chiang   ACPI: processor: ...
92
  	return obj_list;
407cd87c5   Alex Chiang   ACPI: processor: ...
93
  }
78f169965   Alex Chiang   ACPI: processor: ...
94
95
96
97
  /*
   * _PDC is required for a BIOS-OS handshake for most of the newer
   * ACPI processor features.
   */
fa118564e   Alex Chiang   ACPI: processor: ...
98
99
  static int
  acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
78f169965   Alex Chiang   ACPI: processor: ...
100
  {
78f169965   Alex Chiang   ACPI: processor: ...
101
  	acpi_status status = AE_OK;
78f169965   Alex Chiang   ACPI: processor: ...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  	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);
  
  	}
fa118564e   Alex Chiang   ACPI: processor: ...
116
  	status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
78f169965   Alex Chiang   ACPI: processor: ...
117
118
119
120
121
122
123
124
  
  	if (ACPI_FAILURE(status))
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  		    "Could not evaluate _PDC, using legacy perf. control.
  "));
  
  	return status;
  }
a4932299d   Alex Chiang   ACPI: processor: ...
125
  static int early_pdc_done;
43bab25ce   Alex Chiang   ACPI: processor: ...
126
  void acpi_processor_set_pdc(acpi_handle handle)
78f169965   Alex Chiang   ACPI: processor: ...
127
  {
3b407aef5   Alex Chiang   ACPI: processor: ...
128
  	struct acpi_object_list *obj_list;
1d9cb470a   Alex Chiang   ACPI: processor: ...
129
130
  	if (arch_has_acpi_pdc() == false)
  		return;
a4932299d   Alex Chiang   ACPI: processor: ...
131
132
  	if (early_pdc_done)
  		return;
3b407aef5   Alex Chiang   ACPI: processor: ...
133
134
135
  	obj_list = acpi_processor_alloc_pdc();
  	if (!obj_list)
  		return;
43bab25ce   Alex Chiang   ACPI: processor: ...
136
  	acpi_processor_eval_pdc(handle, obj_list);
b9c2db783   Alex Chiang   ACPI: processor: ...
137
138
139
140
  
  	kfree(obj_list->pointer->buffer.pointer);
  	kfree(obj_list->pointer);
  	kfree(obj_list);
78f169965   Alex Chiang   ACPI: processor: ...
141
142
  }
  EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
2205cbe8e   Alex Chiang   ACPI: processor: ...
143
144
145
146
147
148
  static int early_pdc_optin;
  static int set_early_pdc_optin(const struct dmi_system_id *id)
  {
  	early_pdc_optin = 1;
  	return 0;
  }
0406ad336   Alex Chiang   ACPI: processor: ...
149
150
151
152
153
154
  static int param_early_pdc_optin(char *s)
  {
  	early_pdc_optin = 1;
  	return 1;
  }
  __setup("acpi_early_pdc_eval", param_early_pdc_optin);
2205cbe8e   Alex Chiang   ACPI: processor: ...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = {
  	{
  	set_early_pdc_optin, "HP Envy", {
  	DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
  	DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL},
  	{
  	set_early_pdc_optin, "HP Pavilion dv6", {
  	DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
  	DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL},
  	{
  	set_early_pdc_optin, "HP Pavilion dv7", {
  	DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"),
  	DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL},
  	{},
  };
78f169965   Alex Chiang   ACPI: processor: ...
170
171
172
  static acpi_status
  early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
  {
43bab25ce   Alex Chiang   ACPI: processor: ...
173
  	acpi_processor_set_pdc(handle);
78f169965   Alex Chiang   ACPI: processor: ...
174
175
  	return AE_OK;
  }
7a0b73a49   Tony Luck   ACPI: Fix section...
176
  void __init acpi_early_processor_set_pdc(void)
78f169965   Alex Chiang   ACPI: processor: ...
177
178
179
180
181
182
  {
  	/*
  	 * Check whether the system is DMI table. If yes, OSPM
  	 * should not use mwait for CPU-states.
  	 */
  	dmi_check_system(processor_idle_dmi_table);
2205cbe8e   Alex Chiang   ACPI: processor: ...
183
184
185
186
187
188
  	/*
  	 * Allow systems to opt-in to early _PDC evaluation.
  	 */
  	dmi_check_system(early_pdc_optin_table);
  	if (!early_pdc_optin)
  		return;
78f169965   Alex Chiang   ACPI: processor: ...
189
190
191
  	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
  			    ACPI_UINT32_MAX,
  			    early_init_pdc, NULL, NULL, NULL);
a4932299d   Alex Chiang   ACPI: processor: ...
192
193
  
  	early_pdc_done = 1;
78f169965   Alex Chiang   ACPI: processor: ...
194
  }