diff options
Diffstat (limited to 'drivers/pci/hotplug/acpi_pcihp.c')
-rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 117 |
1 files changed, 38 insertions, 79 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index eb159587d0bf..a73028ec52e5 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) | 41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) |
42 | 42 | ||
43 | #define METHOD_NAME__SUN "_SUN" | 43 | #define METHOD_NAME__SUN "_SUN" |
44 | #define METHOD_NAME__HPP "_HPP" | ||
45 | #define METHOD_NAME_OSHP "OSHP" | 44 | #define METHOD_NAME_OSHP "OSHP" |
46 | 45 | ||
47 | static int debug_acpi; | 46 | static int debug_acpi; |
@@ -215,80 +214,41 @@ acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) | |||
215 | static acpi_status | 214 | static acpi_status |
216 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | 215 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
217 | { | 216 | { |
218 | acpi_status status; | 217 | acpi_status status; |
219 | u8 nui[4]; | 218 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
220 | struct acpi_buffer ret_buf = { 0, NULL}; | 219 | union acpi_object *package, *fields; |
221 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 220 | int i; |
222 | union acpi_object *ext_obj, *package; | ||
223 | int i, len = 0; | ||
224 | |||
225 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
226 | 221 | ||
227 | /* Clear the return buffer with zeros */ | ||
228 | memset(hpp, 0, sizeof(struct hotplug_params)); | 222 | memset(hpp, 0, sizeof(struct hotplug_params)); |
229 | 223 | ||
230 | /* get _hpp */ | 224 | status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer); |
231 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); | 225 | if (ACPI_FAILURE(status)) |
232 | switch (status) { | 226 | return status; |
233 | case AE_BUFFER_OVERFLOW: | ||
234 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | ||
235 | if (!ret_buf.pointer) { | ||
236 | printk(KERN_ERR "%s:%s alloc for _HPP fail\n", | ||
237 | __func__, (char *)string.pointer); | ||
238 | kfree(string.pointer); | ||
239 | return AE_NO_MEMORY; | ||
240 | } | ||
241 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, | ||
242 | NULL, &ret_buf); | ||
243 | if (ACPI_SUCCESS(status)) | ||
244 | break; | ||
245 | default: | ||
246 | if (ACPI_FAILURE(status)) { | ||
247 | pr_debug("%s:%s _HPP fail=0x%x\n", __func__, | ||
248 | (char *)string.pointer, status); | ||
249 | kfree(string.pointer); | ||
250 | return status; | ||
251 | } | ||
252 | } | ||
253 | 227 | ||
254 | ext_obj = (union acpi_object *) ret_buf.pointer; | 228 | package = (union acpi_object *) buffer.pointer; |
255 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 229 | if (package->type != ACPI_TYPE_PACKAGE || |
256 | printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__, | 230 | package->package.count != 4) { |
257 | (char *)string.pointer); | ||
258 | status = AE_ERROR; | 231 | status = AE_ERROR; |
259 | goto free_and_return; | 232 | goto exit; |
260 | } | 233 | } |
261 | 234 | ||
262 | len = ext_obj->package.count; | 235 | fields = package->package.elements; |
263 | package = (union acpi_object *) ret_buf.pointer; | 236 | for (i = 0; i < 4; i++) { |
264 | for ( i = 0; (i < len) || (i < 4); i++) { | 237 | if (fields[i].type != ACPI_TYPE_INTEGER) { |
265 | ext_obj = (union acpi_object *) &package->package.elements[i]; | ||
266 | switch (ext_obj->type) { | ||
267 | case ACPI_TYPE_INTEGER: | ||
268 | nui[i] = (u8)ext_obj->integer.value; | ||
269 | break; | ||
270 | default: | ||
271 | printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", | ||
272 | __func__, (char *)string.pointer); | ||
273 | status = AE_ERROR; | 238 | status = AE_ERROR; |
274 | goto free_and_return; | 239 | goto exit; |
275 | } | 240 | } |
276 | } | 241 | } |
277 | 242 | ||
278 | hpp->t0 = &hpp->type0_data; | 243 | hpp->t0 = &hpp->type0_data; |
279 | hpp->t0->cache_line_size = nui[0]; | 244 | hpp->t0->revision = 1; |
280 | hpp->t0->latency_timer = nui[1]; | 245 | hpp->t0->cache_line_size = fields[0].integer.value; |
281 | hpp->t0->enable_serr = nui[2]; | 246 | hpp->t0->latency_timer = fields[1].integer.value; |
282 | hpp->t0->enable_perr = nui[3]; | 247 | hpp->t0->enable_serr = fields[2].integer.value; |
283 | 248 | hpp->t0->enable_perr = fields[3].integer.value; | |
284 | pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); | ||
285 | pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); | ||
286 | pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); | ||
287 | pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); | ||
288 | 249 | ||
289 | free_and_return: | 250 | exit: |
290 | kfree(string.pointer); | 251 | kfree(buffer.pointer); |
291 | kfree(ret_buf.pointer); | ||
292 | return status; | 252 | return status; |
293 | } | 253 | } |
294 | 254 | ||
@@ -322,20 +282,19 @@ static acpi_status acpi_run_oshp(acpi_handle handle) | |||
322 | return status; | 282 | return status; |
323 | } | 283 | } |
324 | 284 | ||
325 | /* acpi_get_hp_params_from_firmware | 285 | /* pci_get_hp_params |
326 | * | 286 | * |
327 | * @bus - the pci_bus of the bus on which the device is newly added | 287 | * @dev - the pci_dev for which we want parameters |
328 | * @hpp - allocated by the caller | 288 | * @hpp - allocated by the caller |
329 | */ | 289 | */ |
330 | acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | 290 | int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp) |
331 | struct hotplug_params *hpp) | ||
332 | { | 291 | { |
333 | acpi_status status = AE_NOT_FOUND; | 292 | acpi_status status; |
334 | acpi_handle handle, phandle; | 293 | acpi_handle handle, phandle; |
335 | struct pci_bus *pbus; | 294 | struct pci_bus *pbus; |
336 | 295 | ||
337 | handle = NULL; | 296 | handle = NULL; |
338 | for (pbus = bus; pbus; pbus = pbus->parent) { | 297 | for (pbus = dev->bus; pbus; pbus = pbus->parent) { |
339 | handle = acpi_pci_get_bridge_handle(pbus); | 298 | handle = acpi_pci_get_bridge_handle(pbus); |
340 | if (handle) | 299 | if (handle) |
341 | break; | 300 | break; |
@@ -345,15 +304,15 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
345 | * _HPP settings apply to all child buses, until another _HPP is | 304 | * _HPP settings apply to all child buses, until another _HPP is |
346 | * encountered. If we don't find an _HPP for the input pci dev, | 305 | * encountered. If we don't find an _HPP for the input pci dev, |
347 | * look for it in the parent device scope since that would apply to | 306 | * look for it in the parent device scope since that would apply to |
348 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | 307 | * this pci dev. |
349 | */ | 308 | */ |
350 | while (handle) { | 309 | while (handle) { |
351 | status = acpi_run_hpx(handle, hpp); | 310 | status = acpi_run_hpx(handle, hpp); |
352 | if (ACPI_SUCCESS(status)) | 311 | if (ACPI_SUCCESS(status)) |
353 | break; | 312 | return 0; |
354 | status = acpi_run_hpp(handle, hpp); | 313 | status = acpi_run_hpp(handle, hpp); |
355 | if (ACPI_SUCCESS(status)) | 314 | if (ACPI_SUCCESS(status)) |
356 | break; | 315 | return 0; |
357 | if (acpi_is_root_bridge(handle)) | 316 | if (acpi_is_root_bridge(handle)) |
358 | break; | 317 | break; |
359 | status = acpi_get_parent(handle, &phandle); | 318 | status = acpi_get_parent(handle, &phandle); |
@@ -361,9 +320,9 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
361 | break; | 320 | break; |
362 | handle = phandle; | 321 | handle = phandle; |
363 | } | 322 | } |
364 | return status; | 323 | return -ENODEV; |
365 | } | 324 | } |
366 | EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | 325 | EXPORT_SYMBOL_GPL(pci_get_hp_params); |
367 | 326 | ||
368 | /** | 327 | /** |
369 | * acpi_get_hp_hw_control_from_firmware | 328 | * acpi_get_hp_hw_control_from_firmware |
@@ -500,18 +459,18 @@ check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
500 | 459 | ||
501 | /** | 460 | /** |
502 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots | 461 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots |
503 | * @pbus - PCI bus to scan | 462 | * @handle - handle of the PCI bus to scan |
504 | * | 463 | * |
505 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. | 464 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. |
506 | */ | 465 | */ |
507 | int acpi_pci_detect_ejectable(struct pci_bus *pbus) | 466 | int acpi_pci_detect_ejectable(acpi_handle handle) |
508 | { | 467 | { |
509 | acpi_handle handle; | ||
510 | int found = 0; | 468 | int found = 0; |
511 | 469 | ||
512 | if (!(handle = acpi_pci_get_bridge_handle(pbus))) | 470 | if (!handle) |
513 | return 0; | 471 | return found; |
514 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 472 | |
473 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
515 | check_hotplug, (void *)&found, NULL); | 474 | check_hotplug, (void *)&found, NULL); |
516 | return found; | 475 | return found; |
517 | } | 476 | } |