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