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.c84
1 files changed, 38 insertions, 46 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index ae5ec76dca77..deea8a187eb8 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -13,8 +13,6 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/pci-aspm.h> 14#include <linux/pci-aspm.h>
15#include <acpi/acpi.h> 15#include <acpi/acpi.h>
16#include <acpi/acnamesp.h>
17#include <acpi/acresrc.h>
18#include <acpi/acpi_bus.h> 16#include <acpi/acpi_bus.h>
19 17
20#include <linux/pci-acpi.h> 18#include <linux/pci-acpi.h>
@@ -24,13 +22,14 @@ struct acpi_osc_data {
24 acpi_handle handle; 22 acpi_handle handle;
25 u32 support_set; 23 u32 support_set;
26 u32 control_set; 24 u32 control_set;
25 u32 control_query;
26 int is_queried;
27 struct list_head sibiling; 27 struct list_head sibiling;
28}; 28};
29static LIST_HEAD(acpi_osc_data_list); 29static LIST_HEAD(acpi_osc_data_list);
30 30
31struct acpi_osc_args { 31struct acpi_osc_args {
32 u32 capbuf[3]; 32 u32 capbuf[3];
33 u32 ctrl_result;
34}; 33};
35 34
36static DEFINE_MUTEX(pci_acpi_lock); 35static DEFINE_MUTEX(pci_acpi_lock);
@@ -56,7 +55,7 @@ static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40,
56 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 55 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
57 56
58static acpi_status acpi_run_osc(acpi_handle handle, 57static acpi_status acpi_run_osc(acpi_handle handle,
59 struct acpi_osc_args *osc_args) 58 struct acpi_osc_args *osc_args, u32 *retval)
60{ 59{
61 acpi_status status; 60 acpi_status status;
62 struct acpi_object_list input; 61 struct acpi_object_list input;
@@ -112,8 +111,7 @@ static acpi_status acpi_run_osc(acpi_handle handle,
112 goto out_kfree; 111 goto out_kfree;
113 } 112 }
114out_success: 113out_success:
115 osc_args->ctrl_result = 114 *retval = *((u32 *)(out_obj->buffer.pointer + 8));
116 *((u32 *)(out_obj->buffer.pointer + 8));
117 status = AE_OK; 115 status = AE_OK;
118 116
119out_kfree: 117out_kfree:
@@ -121,11 +119,10 @@ out_kfree:
121 return status; 119 return status;
122} 120}
123 121
124static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data, 122static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data)
125 u32 *result)
126{ 123{
127 acpi_status status; 124 acpi_status status;
128 u32 support_set; 125 u32 support_set, result;
129 struct acpi_osc_args osc_args; 126 struct acpi_osc_args osc_args;
130 127
131 /* do _OSC query for all possible controls */ 128 /* do _OSC query for all possible controls */
@@ -134,56 +131,45 @@ static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data,
134 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; 131 osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set;
135 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 132 osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
136 133
137 status = acpi_run_osc(osc_data->handle, &osc_args); 134 status = acpi_run_osc(osc_data->handle, &osc_args, &result);
138 if (ACPI_SUCCESS(status)) { 135 if (ACPI_SUCCESS(status)) {
139 osc_data->support_set = support_set; 136 osc_data->support_set = support_set;
140 *result = osc_args.ctrl_result; 137 osc_data->control_query = result;
138 osc_data->is_queried = 1;
141 } 139 }
142 140
143 return status; 141 return status;
144} 142}
145 143
146static acpi_status acpi_query_osc(acpi_handle handle, 144/*
147 u32 level, void *context, void **retval) 145 * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature
146 * @flags: Bitmask of flags to support
147 *
148 * See the ACPI spec for the definition of the flags
149 */
150int pci_acpi_osc_support(acpi_handle handle, u32 flags)
148{ 151{
149 acpi_status status; 152 acpi_status status;
150 struct acpi_osc_data *osc_data;
151 u32 flags = (unsigned long)context, dummy;
152 acpi_handle tmp; 153 acpi_handle tmp;
154 struct acpi_osc_data *osc_data;
155 int rc = 0;
153 156
154 status = acpi_get_handle(handle, "_OSC", &tmp); 157 status = acpi_get_handle(handle, "_OSC", &tmp);
155 if (ACPI_FAILURE(status)) 158 if (ACPI_FAILURE(status))
156 return AE_OK; 159 return -ENOTTY;
157 160
158 mutex_lock(&pci_acpi_lock); 161 mutex_lock(&pci_acpi_lock);
159 osc_data = acpi_get_osc_data(handle); 162 osc_data = acpi_get_osc_data(handle);
160 if (!osc_data) { 163 if (!osc_data) {
161 printk(KERN_ERR "acpi osc data array is full\n"); 164 printk(KERN_ERR "acpi osc data array is full\n");
165 rc = -ENOMEM;
162 goto out; 166 goto out;
163 } 167 }
164 168
165 __acpi_query_osc(flags, osc_data, &dummy); 169 __acpi_query_osc(flags, osc_data);
166out: 170out:
167 mutex_unlock(&pci_acpi_lock); 171 mutex_unlock(&pci_acpi_lock);
168 return AE_OK; 172 return rc;
169}
170
171/**
172 * __pci_osc_support_set - register OS support to Firmware
173 * @flags: OS support bits
174 * @hid: hardware ID
175 *
176 * Update OS support fields and doing a _OSC Query to obtain an update
177 * from Firmware on supported control bits.
178 **/
179acpi_status __pci_osc_support_set(u32 flags, const char *hid)
180{
181 if (!(flags & OSC_SUPPORT_MASKS))
182 return AE_TYPE;
183
184 acpi_get_devices(hid, acpi_query_osc,
185 (void *)(unsigned long)flags, NULL);
186 return AE_OK;
187} 173}
188 174
189/** 175/**
@@ -196,7 +182,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid)
196acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) 182acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
197{ 183{
198 acpi_status status; 184 acpi_status status;
199 u32 ctrlset, control_set, result; 185 u32 control_req, control_set, result;
200 acpi_handle tmp; 186 acpi_handle tmp;
201 struct acpi_osc_data *osc_data; 187 struct acpi_osc_data *osc_data;
202 struct acpi_osc_args osc_args; 188 struct acpi_osc_args osc_args;
@@ -213,28 +199,34 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
213 goto out; 199 goto out;
214 } 200 }
215 201
216 ctrlset = (flags & OSC_CONTROL_MASKS); 202 control_req = (flags & OSC_CONTROL_MASKS);
217 if (!ctrlset) { 203 if (!control_req) {
218 status = AE_TYPE; 204 status = AE_TYPE;
219 goto out; 205 goto out;
220 } 206 }
221 207
222 status = __acpi_query_osc(osc_data->support_set, osc_data, &result); 208 /* No need to evaluate _OSC if the control was already granted. */
223 if (ACPI_FAILURE(status)) 209 if ((osc_data->control_set & control_req) == control_req)
224 goto out; 210 goto out;
225 211
226 if ((result & ctrlset) != ctrlset) { 212 if (!osc_data->is_queried) {
213 status = __acpi_query_osc(osc_data->support_set, osc_data);
214 if (ACPI_FAILURE(status))
215 goto out;
216 }
217
218 if ((osc_data->control_query & control_req) != control_req) {
227 status = AE_SUPPORT; 219 status = AE_SUPPORT;
228 goto out; 220 goto out;
229 } 221 }
230 222
231 control_set = osc_data->control_set | ctrlset; 223 control_set = osc_data->control_set | control_req;
232 osc_args.capbuf[OSC_QUERY_TYPE] = 0; 224 osc_args.capbuf[OSC_QUERY_TYPE] = 0;
233 osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; 225 osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set;
234 osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; 226 osc_args.capbuf[OSC_CONTROL_TYPE] = control_set;
235 status = acpi_run_osc(handle, &osc_args); 227 status = acpi_run_osc(handle, &osc_args, &result);
236 if (ACPI_SUCCESS(status)) 228 if (ACPI_SUCCESS(status))
237 osc_data->control_set = control_set; 229 osc_data->control_set = result;
238out: 230out:
239 mutex_unlock(&pci_acpi_lock); 231 mutex_unlock(&pci_acpi_lock);
240 return status; 232 return status;
@@ -375,7 +367,7 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
375 * The string should be the same as root bridge's name 367 * The string should be the same as root bridge's name
376 * Please look at 'pci_scan_bus_parented' 368 * Please look at 'pci_scan_bus_parented'
377 */ 369 */
378 num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus); 370 num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus);
379 if (num != 2) 371 if (num != 2)
380 return -ENODEV; 372 return -ENODEV;
381 *handle = acpi_get_pci_rootbridge_handle(seg, bus); 373 *handle = acpi_get_pci_rootbridge_handle(seg, bus);