aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c109
1 files changed, 79 insertions, 30 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 72f7476930c8..9d6fc8e6285d 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -19,8 +19,31 @@
19#include <linux/pci-acpi.h> 19#include <linux/pci-acpi.h>
20#include "pci.h" 20#include "pci.h"
21 21
22static u32 ctrlset_buf[3] = {0, 0, 0}; 22struct acpi_osc_data {
23static u32 global_ctrlsets = 0; 23 acpi_handle handle;
24 u32 ctrlset_buf[3];
25 u32 global_ctrlsets;
26 struct list_head sibiling;
27};
28static LIST_HEAD(acpi_osc_data_list);
29
30static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
31{
32 struct acpi_osc_data *data;
33
34 list_for_each_entry(data, &acpi_osc_data_list, sibiling) {
35 if (data->handle == handle)
36 return data;
37 }
38 data = kzalloc(sizeof(*data), GFP_KERNEL);
39 if (!data)
40 return NULL;
41 INIT_LIST_HEAD(&data->sibiling);
42 data->handle = handle;
43 list_add_tail(&data->sibiling, &acpi_osc_data_list);
44 return data;
45}
46
24static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 47static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
25 48
26static acpi_status 49static acpi_status
@@ -37,8 +60,27 @@ acpi_query_osc (
37 union acpi_object *out_obj; 60 union acpi_object *out_obj;
38 u32 osc_dw0; 61 u32 osc_dw0;
39 acpi_status *ret_status = (acpi_status *)retval; 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;
40 83
41
42 /* Setting up input parameters */ 84 /* Setting up input parameters */
43 input.count = 4; 85 input.count = 4;
44 input.pointer = in_params; 86 input.pointer = in_params;
@@ -51,13 +93,11 @@ acpi_query_osc (
51 in_params[2].integer.value = 3; 93 in_params[2].integer.value = 3;
52 in_params[3].type = ACPI_TYPE_BUFFER; 94 in_params[3].type = ACPI_TYPE_BUFFER;
53 in_params[3].buffer.length = 12; 95 in_params[3].buffer.length = 12;
54 in_params[3].buffer.pointer = (u8 *)context; 96 in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf;
55 97
56 status = acpi_evaluate_object(handle, "_OSC", &input, &output); 98 status = acpi_evaluate_object(handle, "_OSC", &input, &output);
57 if (ACPI_FAILURE (status)) { 99 if (ACPI_FAILURE(status))
58 *ret_status = status; 100 goto out_nofree;
59 return status;
60 }
61 out_obj = output.pointer; 101 out_obj = output.pointer;
62 102
63 if (out_obj->type != ACPI_TYPE_BUFFER) { 103 if (out_obj->type != ACPI_TYPE_BUFFER) {
@@ -76,7 +116,8 @@ acpi_query_osc (
76 printk(KERN_DEBUG "_OSC invalid revision\n"); 116 printk(KERN_DEBUG "_OSC invalid revision\n");
77 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { 117 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
78 /* Update Global Control Set */ 118 /* Update Global Control Set */
79 global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); 119 osc_data->global_ctrlsets =
120 *((u32 *)(out_obj->buffer.pointer + 8));
80 status = AE_OK; 121 status = AE_OK;
81 goto query_osc_out; 122 goto query_osc_out;
82 } 123 }
@@ -85,12 +126,21 @@ acpi_query_osc (
85 } 126 }
86 127
87 /* Update Global Control Set */ 128 /* Update Global Control Set */
88 global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); 129 osc_data->global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8));
89 status = AE_OK; 130 status = AE_OK;
90 131
91query_osc_out: 132query_osc_out:
92 kfree(output.pointer); 133 kfree(output.pointer);
134out_nofree:
93 *ret_status = status; 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
94 return status; 144 return status;
95} 145}
96 146
@@ -165,28 +215,15 @@ run_osc_out:
165 **/ 215 **/
166acpi_status __pci_osc_support_set(u32 flags, const char *hid) 216acpi_status __pci_osc_support_set(u32 flags, const char *hid)
167{ 217{
168 u32 temp; 218 acpi_status retval = AE_NOT_FOUND;
169 acpi_status retval;
170 219
171 if (!(flags & OSC_SUPPORT_MASKS)) { 220 if (!(flags & OSC_SUPPORT_MASKS)) {
172 return AE_TYPE; 221 return AE_TYPE;
173 } 222 }
174 ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
175
176 /* do _OSC query for all possible controls */
177 temp = ctrlset_buf[OSC_CONTROL_TYPE];
178 ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
179 ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
180 acpi_get_devices(hid, 223 acpi_get_devices(hid,
181 acpi_query_osc, 224 acpi_query_osc,
182 ctrlset_buf, 225 (void *)(unsigned long)flags,
183 (void **) &retval ); 226 (void **) &retval );
184 ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
185 ctrlset_buf[OSC_CONTROL_TYPE] = temp;
186 if (ACPI_FAILURE(retval)) {
187 /* no osc support at all */
188 ctrlset_buf[OSC_SUPPORT_TYPE] = 0;
189 }
190 return AE_OK; 227 return AE_OK;
191} 228}
192 229
@@ -201,19 +238,31 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
201{ 238{
202 acpi_status status; 239 acpi_status status;
203 u32 ctrlset; 240 u32 ctrlset;
241 acpi_handle tmp;
242 struct acpi_osc_data *osc_data;
243
244 status = acpi_get_handle(handle, "_OSC", &tmp);
245 if (ACPI_FAILURE(status))
246 return status;
247
248 osc_data = acpi_get_osc_data(handle);
249 if (!osc_data) {
250 printk(KERN_ERR "acpi osc data array is full\n");
251 return AE_ERROR;
252 }
204 253
205 ctrlset = (flags & OSC_CONTROL_MASKS); 254 ctrlset = (flags & OSC_CONTROL_MASKS);
206 if (!ctrlset) { 255 if (!ctrlset) {
207 return AE_TYPE; 256 return AE_TYPE;
208 } 257 }
209 if (ctrlset_buf[OSC_SUPPORT_TYPE] && 258 if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] &&
210 ((global_ctrlsets & ctrlset) != ctrlset)) { 259 ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) {
211 return AE_SUPPORT; 260 return AE_SUPPORT;
212 } 261 }
213 ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; 262 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
214 status = acpi_run_osc(handle, ctrlset_buf); 263 status = acpi_run_osc(handle, osc_data->ctrlset_buf);
215 if (ACPI_FAILURE (status)) { 264 if (ACPI_FAILURE (status)) {
216 ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; 265 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
217 } 266 }
218 267
219 return status; 268 return status;