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.c73
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 032b3268018b..b1bd6e6155a3 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -21,12 +21,18 @@
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 u32 query_result;
26 struct list_head sibiling; 27 struct list_head sibiling;
27}; 28};
28static LIST_HEAD(acpi_osc_data_list); 29static LIST_HEAD(acpi_osc_data_list);
29 30
31struct acpi_osc_args {
32 u32 capbuf[3];
33 u32 query_result;
34};
35
30static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) 36static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
31{ 37{
32 struct acpi_osc_data *data; 38 struct acpi_osc_data *data;
@@ -47,14 +53,14 @@ static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle)
47static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 53static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
48 54
49static acpi_status acpi_run_osc(acpi_handle handle, 55static acpi_status acpi_run_osc(acpi_handle handle,
50 struct acpi_osc_data *osc_data) 56 struct acpi_osc_args *osc_args)
51{ 57{
52 acpi_status status; 58 acpi_status status;
53 struct acpi_object_list input; 59 struct acpi_object_list input;
54 union acpi_object in_params[4]; 60 union acpi_object in_params[4];
55 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; 61 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
56 union acpi_object *out_obj; 62 union acpi_object *out_obj;
57 u32 osc_dw0, flags = osc_data->ctrlset_buf[OSC_QUERY_TYPE]; 63 u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE];
58 64
59 /* Setting up input parameters */ 65 /* Setting up input parameters */
60 input.count = 4; 66 input.count = 4;
@@ -68,7 +74,7 @@ static acpi_status acpi_run_osc(acpi_handle handle,
68 in_params[2].integer.value = 3; 74 in_params[2].integer.value = 3;
69 in_params[3].type = ACPI_TYPE_BUFFER; 75 in_params[3].type = ACPI_TYPE_BUFFER;
70 in_params[3].buffer.length = 12; 76 in_params[3].buffer.length = 12;
71 in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf; 77 in_params[3].buffer.pointer = (u8 *)osc_args->capbuf;
72 78
73 status = acpi_evaluate_object(handle, "_OSC", &input, &output); 79 status = acpi_evaluate_object(handle, "_OSC", &input, &output);
74 if (ACPI_FAILURE(status)) 80 if (ACPI_FAILURE(status))
@@ -99,11 +105,9 @@ static acpi_status acpi_run_osc(acpi_handle handle,
99 goto out_kfree; 105 goto out_kfree;
100 } 106 }
101out_success: 107out_success:
102 if (flags & OSC_QUERY_ENABLE) { 108 if (flags & OSC_QUERY_ENABLE)
103 /* Update Global Control Set */ 109 osc_args->query_result =
104 osc_data->global_ctrlsets =
105 *((u32 *)(out_obj->buffer.pointer + 8)); 110 *((u32 *)(out_obj->buffer.pointer + 8));
106 }
107 status = AE_OK; 111 status = AE_OK;
108 112
109out_kfree: 113out_kfree:
@@ -117,8 +121,9 @@ static acpi_status acpi_query_osc(acpi_handle handle,
117 acpi_status status; 121 acpi_status status;
118 acpi_status *ret_status = (acpi_status *)retval; 122 acpi_status *ret_status = (acpi_status *)retval;
119 struct acpi_osc_data *osc_data; 123 struct acpi_osc_data *osc_data;
120 u32 flags = (unsigned long)context, temp; 124 u32 flags = (unsigned long)context, support_set;
121 acpi_handle tmp; 125 acpi_handle tmp;
126 struct acpi_osc_args osc_args;
122 127
123 status = acpi_get_handle(handle, "_OSC", &tmp); 128 status = acpi_get_handle(handle, "_OSC", &tmp);
124 if (ACPI_FAILURE(status)) 129 if (ACPI_FAILURE(status))
@@ -130,21 +135,18 @@ static acpi_status acpi_query_osc(acpi_handle handle,
130 return AE_ERROR; 135 return AE_ERROR;
131 } 136 }
132 137
133 osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
134
135 /* do _OSC query for all possible controls */ 138 /* do _OSC query for all possible controls */
136 temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; 139 support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS);
137 osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 140 osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
138 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 141 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
142 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
139 143
140 status = acpi_run_osc(handle, osc_data); 144 status = acpi_run_osc(handle, &osc_args);
141 *ret_status = status; 145 *ret_status = status;
142 146
143 osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; 147 if (ACPI_SUCCESS(status)) {
144 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; 148 osc_data->support_set = support_set;
145 if (ACPI_FAILURE(status)) { 149 osc_data->query_result = osc_args.query_result;
146 /* no osc support at all */
147 osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0;
148 } 150 }
149 151
150 return status; 152 return status;
@@ -181,10 +183,11 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
181 **/ 183 **/
182acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) 184acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
183{ 185{
184 acpi_status status; 186 acpi_status status;
185 u32 ctrlset; 187 u32 ctrlset, control_set;
186 acpi_handle tmp; 188 acpi_handle tmp;
187 struct acpi_osc_data *osc_data; 189 struct acpi_osc_data *osc_data;
190 struct acpi_osc_args osc_args;
188 191
189 status = acpi_get_handle(handle, "_OSC", &tmp); 192 status = acpi_get_handle(handle, "_OSC", &tmp);
190 if (ACPI_FAILURE(status)) 193 if (ACPI_FAILURE(status))
@@ -197,19 +200,21 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
197 } 200 }
198 201
199 ctrlset = (flags & OSC_CONTROL_MASKS); 202 ctrlset = (flags & OSC_CONTROL_MASKS);
200 if (!ctrlset) { 203 if (!ctrlset)
201 return AE_TYPE; 204 return AE_TYPE;
202 } 205
203 if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] && 206 if (osc_data->support_set &&
204 ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) { 207 ((osc_data->query_result & ctrlset) != ctrlset))
205 return AE_SUPPORT; 208 return AE_SUPPORT;
206 } 209
207 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; 210 control_set = osc_data->control_set | ctrlset;
208 status = acpi_run_osc(handle, osc_data); 211 osc_args.capbuf[OSC_QUERY_TYPE] = 0;
209 if (ACPI_FAILURE (status)) { 212 osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
210 osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; 213 osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
211 } 214 status = acpi_run_osc(handle, &osc_args);
212 215 if (ACPI_SUCCESS(status))
216 osc_data->control_set = control_set;
217
213 return status; 218 return status;
214} 219}
215EXPORT_SYMBOL(pci_osc_control_set); 220EXPORT_SYMBOL(pci_osc_control_set);