aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-17 17:57:20 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-17 17:57:20 -0400
commit393d81aa026e19b6ede6f5f11955c97ee62e5df5 (patch)
treea1d9511e488e19d41089ff0a736f6ce52a81c6e5 /drivers/pci/pci-acpi.c
parent93a0886e2368eafb9df5e2021fb185195cee88b2 (diff)
parent5b664cb235e97afbf34db9c4d77f08ebd725335e (diff)
Merge branch 'linus' into xen-64bit
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c277
1 files changed, 126 insertions, 151 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 9d6fc8e6285d..7764768b6a0e 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -21,12 +21,19 @@
21 21
22struct acpi_osc_data { 22struct acpi_osc_data {
23 acpi_handle handle; 23 acpi_handle handle;
24 u32 ctrlset_buf[3]; 24 u32 support_set;
25 u32 global_ctrlsets; 25 u32 control_set;
26 int is_queried;
27 u32 query_result;
26 struct list_head sibiling; 28 struct list_head sibiling;
27}; 29};
28static LIST_HEAD(acpi_osc_data_list); 30static LIST_HEAD(acpi_osc_data_list);
29 31
32struct acpi_osc_args {
33 u32 capbuf[3];
34 u32 query_result;
35};
36
30static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) 37static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
31{ 38{
32 struct acpi_osc_data *data; 39 struct acpi_osc_data *data;
@@ -44,42 +51,18 @@ static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
44 return data; 51 return data;
45} 52}
46 53
47static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 54static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
55 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
48 56
49static acpi_status 57static acpi_status acpi_run_osc(acpi_handle handle,
50acpi_query_osc ( 58 struct acpi_osc_args *osc_args)
51 acpi_handle handle,
52 u32 level,
53 void *context,
54 void **retval )
55{ 59{
56 acpi_status status; 60 acpi_status status;
57 struct acpi_object_list input; 61 struct acpi_object_list input;
58 union acpi_object in_params[4]; 62 union acpi_object in_params[4];
59 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; 63 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
60 union acpi_object *out_obj; 64 union acpi_object *out_obj;
61 u32 osc_dw0; 65 u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE];
62 acpi_status *ret_status = (acpi_status *)retval;
63 struct acpi_osc_data *osc_data;
64 u32 flags = (unsigned long)context, temp;
65 acpi_handle tmp;
66
67 status = acpi_get_handle(handle, "_OSC", &tmp);
68 if (ACPI_FAILURE(status))
69 return status;
70
71 osc_data = acpi_get_osc_data(handle);
72 if (!osc_data) {
73 printk(KERN_ERR "acpi osc data array is full\n");
74 return AE_ERROR;
75 }
76
77 osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
78
79 /* do _OSC query for all possible controls */
80 temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE];
81 osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
82 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
83 66
84 /* Setting up input parameters */ 67 /* Setting up input parameters */
85 input.count = 4; 68 input.count = 4;
@@ -93,20 +76,19 @@ acpi_query_osc (
93 in_params[2].integer.value = 3; 76 in_params[2].integer.value = 3;
94 in_params[3].type = ACPI_TYPE_BUFFER; 77 in_params[3].type = ACPI_TYPE_BUFFER;
95 in_params[3].buffer.length = 12; 78 in_params[3].buffer.length = 12;
96 in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf; 79 in_params[3].buffer.pointer = (u8 *)osc_args->capbuf;
97 80
98 status = acpi_evaluate_object(handle, "_OSC", &input, &output); 81 status = acpi_evaluate_object(handle, "_OSC", &input, &output);
99 if (ACPI_FAILURE(status)) 82 if (ACPI_FAILURE(status))
100 goto out_nofree; 83 return status;
101 out_obj = output.pointer;
102 84
85 out_obj = output.pointer;
103 if (out_obj->type != ACPI_TYPE_BUFFER) { 86 if (out_obj->type != ACPI_TYPE_BUFFER) {
104 printk(KERN_DEBUG 87 printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n");
105 "Evaluate _OSC returns wrong type\n");
106 status = AE_TYPE; 88 status = AE_TYPE;
107 goto query_osc_out; 89 goto out_kfree;
108 } 90 }
109 osc_dw0 = *((u32 *) out_obj->buffer.pointer); 91 osc_dw0 = *((u32 *)out_obj->buffer.pointer);
110 if (osc_dw0) { 92 if (osc_dw0) {
111 if (osc_dw0 & OSC_REQUEST_ERROR) 93 if (osc_dw0 & OSC_REQUEST_ERROR)
112 printk(KERN_DEBUG "_OSC request fails\n"); 94 printk(KERN_DEBUG "_OSC request fails\n");
@@ -115,93 +97,58 @@ acpi_query_osc (
115 if (osc_dw0 & OSC_INVALID_REVISION_ERROR) 97 if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
116 printk(KERN_DEBUG "_OSC invalid revision\n"); 98 printk(KERN_DEBUG "_OSC invalid revision\n");
117 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { 99 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
118 /* Update Global Control Set */ 100 if (flags & OSC_QUERY_ENABLE)
119 osc_data->global_ctrlsets = 101 goto out_success;
120 *((u32 *)(out_obj->buffer.pointer + 8)); 102 printk(KERN_DEBUG "_OSC FW not grant req. control\n");
121 status = AE_OK; 103 status = AE_SUPPORT;
122 goto query_osc_out; 104 goto out_kfree;
123 } 105 }
124 status = AE_ERROR; 106 status = AE_ERROR;
125 goto query_osc_out; 107 goto out_kfree;
126 } 108 }
127 109out_success:
128 /* Update Global Control Set */ 110 if (flags & OSC_QUERY_ENABLE)
129 osc_data->global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); 111 osc_args->query_result =
112 *((u32 *)(out_obj->buffer.pointer + 8));
130 status = AE_OK; 113 status = AE_OK;
131 114
132query_osc_out: 115out_kfree:
133 kfree(output.pointer); 116 kfree(output.pointer);
134out_nofree:
135 *ret_status = status;
136
137 osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
138 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp;
139 if (ACPI_FAILURE(status)) {
140 /* no osc support at all */
141 osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0;
142 }
143
144 return status; 117 return status;
145} 118}
146 119
147 120static acpi_status acpi_query_osc(acpi_handle handle,
148static acpi_status 121 u32 level, void *context, void **retval)
149acpi_run_osc (
150 acpi_handle handle,
151 void *context)
152{ 122{
153 acpi_status status; 123 acpi_status status;
154 struct acpi_object_list input; 124 struct acpi_osc_data *osc_data;
155 union acpi_object in_params[4]; 125 u32 flags = (unsigned long)context, support_set;
156 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; 126 acpi_handle tmp;
157 union acpi_object *out_obj; 127 struct acpi_osc_args osc_args;
158 u32 osc_dw0;
159
160 /* Setting up input parameters */
161 input.count = 4;
162 input.pointer = in_params;
163 in_params[0].type = ACPI_TYPE_BUFFER;
164 in_params[0].buffer.length = 16;
165 in_params[0].buffer.pointer = OSC_UUID;
166 in_params[1].type = ACPI_TYPE_INTEGER;
167 in_params[1].integer.value = 1;
168 in_params[2].type = ACPI_TYPE_INTEGER;
169 in_params[2].integer.value = 3;
170 in_params[3].type = ACPI_TYPE_BUFFER;
171 in_params[3].buffer.length = 12;
172 in_params[3].buffer.pointer = (u8 *)context;
173 128
174 status = acpi_evaluate_object(handle, "_OSC", &input, &output); 129 status = acpi_get_handle(handle, "_OSC", &tmp);
175 if (ACPI_FAILURE (status)) 130 if (ACPI_FAILURE(status))
176 return status; 131 return status;
177 132
178 out_obj = output.pointer; 133 osc_data = acpi_get_osc_data(handle);
179 if (out_obj->type != ACPI_TYPE_BUFFER) { 134 if (!osc_data) {
180 printk(KERN_DEBUG 135 printk(KERN_ERR "acpi osc data array is full\n");
181 "Evaluate _OSC returns wrong type\n"); 136 return AE_ERROR;
182 status = AE_TYPE;
183 goto run_osc_out;
184 } 137 }
185 osc_dw0 = *((u32 *) out_obj->buffer.pointer); 138
186 if (osc_dw0) { 139 /* do _OSC query for all possible controls */
187 if (osc_dw0 & OSC_REQUEST_ERROR) 140 support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
188 printk(KERN_DEBUG "_OSC request fails\n"); 141 osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
189 if (osc_dw0 & OSC_INVALID_UUID_ERROR) 142 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
190 printk(KERN_DEBUG "_OSC invalid UUID\n"); 143 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
191 if (osc_dw0 & OSC_INVALID_REVISION_ERROR) 144
192 printk(KERN_DEBUG "_OSC invalid revision\n"); 145 status = acpi_run_osc(handle, &osc_args);
193 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { 146 if (ACPI_SUCCESS(status)) {
194 printk(KERN_DEBUG "_OSC FW not grant req. control\n"); 147 osc_data->support_set = support_set;
195 status = AE_SUPPORT; 148 osc_data->query_result = osc_args.query_result;
196 goto run_osc_out; 149 osc_data->is_queried = 1;
197 }
198 status = AE_ERROR;
199 goto run_osc_out;
200 } 150 }
201 status = AE_OK;
202 151
203run_osc_out:
204 kfree(output.pointer);
205 return status; 152 return status;
206} 153}
207 154
@@ -215,15 +162,11 @@ run_osc_out:
215 **/ 162 **/
216acpi_status __pci_osc_support_set(u32 flags, const char *hid) 163acpi_status __pci_osc_support_set(u32 flags, const char *hid)
217{ 164{
218 acpi_status retval = AE_NOT_FOUND; 165 if (!(flags & OSC_SUPPORT_MASKS))
219
220 if (!(flags & OSC_SUPPORT_MASKS)) {
221 return AE_TYPE; 166 return AE_TYPE;
222 } 167
223 acpi_get_devices(hid, 168 acpi_get_devices(hid, acpi_query_osc,
224 acpi_query_osc, 169 (void *)(unsigned long)flags, NULL);
225 (void *)(unsigned long)flags,
226 (void **) &retval );
227 return AE_OK; 170 return AE_OK;
228} 171}
229 172
@@ -236,10 +179,11 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
236 **/ 179 **/
237acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) 180acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
238{ 181{
239 acpi_status status; 182 acpi_status status;
240 u32 ctrlset; 183 u32 ctrlset, control_set;
241 acpi_handle tmp; 184 acpi_handle tmp;
242 struct acpi_osc_data *osc_data; 185 struct acpi_osc_data *osc_data;
186 struct acpi_osc_args osc_args;
243 187
244 status = acpi_get_handle(handle, "_OSC", &tmp); 188 status = acpi_get_handle(handle, "_OSC", &tmp);
245 if (ACPI_FAILURE(status)) 189 if (ACPI_FAILURE(status))
@@ -252,24 +196,25 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
252 } 196 }
253 197
254 ctrlset = (flags & OSC_CONTROL_MASKS); 198 ctrlset = (flags & OSC_CONTROL_MASKS);
255 if (!ctrlset) { 199 if (!ctrlset)
256 return AE_TYPE; 200 return AE_TYPE;
257 } 201
258 if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] && 202 if (osc_data->is_queried &&
259 ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) { 203 ((osc_data->query_result & ctrlset) != ctrlset))
260 return AE_SUPPORT; 204 return AE_SUPPORT;
261 } 205
262 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; 206 control_set = osc_data->control_set | ctrlset;
263 status = acpi_run_osc(handle, osc_data->ctrlset_buf); 207 osc_args.capbuf[OSC_QUERY_TYPE] = 0;
264 if (ACPI_FAILURE (status)) { 208 osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
265 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; 209 osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
266 } 210 status = acpi_run_osc(handle, &osc_args);
267 211 if (ACPI_SUCCESS(status))
212 osc_data->control_set = control_set;
213
268 return status; 214 return status;
269} 215}
270EXPORT_SYMBOL(pci_osc_control_set); 216EXPORT_SYMBOL(pci_osc_control_set);
271 217
272#ifdef CONFIG_ACPI_SLEEP
273/* 218/*
274 * _SxD returns the D-state with the highest power 219 * _SxD returns the D-state with the highest power
275 * (lowest D-state number) supported in the S-state "x". 220 * (lowest D-state number) supported in the S-state "x".
@@ -293,13 +238,11 @@ EXPORT_SYMBOL(pci_osc_control_set);
293 * choose highest power _SxD or any lower power 238 * choose highest power _SxD or any lower power
294 */ 239 */
295 240
296static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev, 241static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
297 pm_message_t state)
298{ 242{
299 int acpi_state; 243 int acpi_state;
300 244
301 acpi_state = acpi_pm_device_sleep_state(&pdev->dev, 245 acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
302 device_may_wakeup(&pdev->dev), NULL);
303 if (acpi_state < 0) 246 if (acpi_state < 0)
304 return PCI_POWER_ERROR; 247 return PCI_POWER_ERROR;
305 248
@@ -315,7 +258,13 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev,
315 } 258 }
316 return PCI_POWER_ERROR; 259 return PCI_POWER_ERROR;
317} 260}
318#endif 261
262static bool acpi_pci_power_manageable(struct pci_dev *dev)
263{
264 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
265
266 return handle ? acpi_bus_power_manageable(handle) : false;
267}
319 268
320static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) 269static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
321{ 270{
@@ -328,12 +277,11 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
328 [PCI_D3hot] = ACPI_STATE_D3, 277 [PCI_D3hot] = ACPI_STATE_D3,
329 [PCI_D3cold] = ACPI_STATE_D3 278 [PCI_D3cold] = ACPI_STATE_D3
330 }; 279 };
280 int error = -EINVAL;
331 281
332 if (!handle)
333 return -ENODEV;
334 /* If the ACPI device has _EJ0, ignore the device */ 282 /* If the ACPI device has _EJ0, ignore the device */
335 if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) 283 if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
336 return 0; 284 return -ENODEV;
337 285
338 switch (state) { 286 switch (state) {
339 case PCI_D0: 287 case PCI_D0:
@@ -341,11 +289,41 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
341 case PCI_D2: 289 case PCI_D2:
342 case PCI_D3hot: 290 case PCI_D3hot:
343 case PCI_D3cold: 291 case PCI_D3cold:
344 return acpi_bus_set_power(handle, state_conv[state]); 292 error = acpi_bus_set_power(handle, state_conv[state]);
345 } 293 }
346 return -EINVAL; 294
295 if (!error)
296 dev_printk(KERN_INFO, &dev->dev,
297 "power state changed by ACPI to D%d\n", state);
298
299 return error;
300}
301
302static bool acpi_pci_can_wakeup(struct pci_dev *dev)
303{
304 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
305
306 return handle ? acpi_bus_can_wakeup(handle) : false;
307}
308
309static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
310{
311 int error = acpi_pm_device_sleep_wake(&dev->dev, enable);
312
313 if (!error)
314 dev_printk(KERN_INFO, &dev->dev,
315 "wake-up capability %s by ACPI\n",
316 enable ? "enabled" : "disabled");
317 return error;
347} 318}
348 319
320static struct pci_platform_pm_ops acpi_pci_platform_pm = {
321 .is_manageable = acpi_pci_power_manageable,
322 .set_state = acpi_pci_set_power_state,
323 .choose_state = acpi_pci_choose_state,
324 .can_wakeup = acpi_pci_can_wakeup,
325 .sleep_wake = acpi_pci_sleep_wake,
326};
349 327
350/* ACPI bus type */ 328/* ACPI bus type */
351static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) 329static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
@@ -397,10 +375,7 @@ static int __init acpi_pci_init(void)
397 ret = register_acpi_bus_type(&acpi_pci_bus); 375 ret = register_acpi_bus_type(&acpi_pci_bus);
398 if (ret) 376 if (ret)
399 return 0; 377 return 0;
400#ifdef CONFIG_ACPI_SLEEP 378 pci_set_platform_pm(&acpi_pci_platform_pm);
401 platform_pci_choose_state = acpi_pci_choose_state;
402#endif
403 platform_pci_set_power_state = acpi_pci_set_power_state;
404 return 0; 379 return 0;
405} 380}
406arch_initcall(acpi_pci_init); 381arch_initcall(acpi_pci_init);