aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpi_pcihp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-07-16 20:25:46 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-16 20:25:46 -0400
commitdc7c65db2845a8d17432d89252c4227a9a7cb15f (patch)
tree79030b0aaaafc04bc4303c21495134e744afc058 /drivers/pci/hotplug/acpi_pcihp.c
parent8a0ca91e1db5de5eb5b18cfa919d52ff8be375af (diff)
parent58b6e5538460be358fdf1286d9a2fbcfcc2cfaba (diff)
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (72 commits) Revert "x86/PCI: ACPI based PCI gap calculation" PCI: remove unnecessary volatile in PCIe hotplug struct controller x86/PCI: ACPI based PCI gap calculation PCI: include linux/pm_wakeup.h for device_set_wakeup_capable PCI PM: Fix pci_prepare_to_sleep x86/PCI: Fix PCI config space for domains > 0 Fix acpi_pm_device_sleep_wake() by providing a stub for CONFIG_PM_SLEEP=n PCI: Simplify PCI device PM code PCI PM: Introduce pci_prepare_to_sleep and pci_back_from_sleep PCI ACPI: Rework PCI handling of wake-up ACPI: Introduce new device wakeup flag 'prepared' ACPI: Introduce acpi_device_sleep_wake function PCI: rework pci_set_power_state function to call platform first PCI: Introduce platform_pci_power_manageable function ACPI: Introduce acpi_bus_power_manageable function PCI: make pci_name use dev_name PCI: handle pci_name() being const PCI: add stub for pci_set_consistent_dma_mask() PCI: remove unused arch pcibios_update_resource() functions PCI: fix pci_setup_device()'s sprinting into a const buffer ... Fixed up conflicts in various files (arch/x86/kernel/setup_64.c, arch/x86/pci/irq.c, arch/x86/pci/pci.h, drivers/acpi/sleep/main.c, drivers/pci/pci.c, drivers/pci/pci.h, include/acpi/acpi_bus.h) from x86 and ACPI updates manually.
Diffstat (limited to 'drivers/pci/hotplug/acpi_pcihp.c')
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index f8c187a763bd..93e37f0666ab 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -30,6 +30,7 @@
30#include <linux/types.h> 30#include <linux/types.h>
31#include <linux/pci.h> 31#include <linux/pci.h>
32#include <linux/pci_hotplug.h> 32#include <linux/pci_hotplug.h>
33#include <linux/pci-acpi.h>
33#include <acpi/acpi.h> 34#include <acpi/acpi.h>
34#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
35#include <acpi/actypes.h> 36#include <acpi/actypes.h>
@@ -299,7 +300,7 @@ free_and_return:
299 * 300 *
300 * @handle - the handle of the hotplug controller. 301 * @handle - the handle of the hotplug controller.
301 */ 302 */
302acpi_status acpi_run_oshp(acpi_handle handle) 303static acpi_status acpi_run_oshp(acpi_handle handle)
303{ 304{
304 acpi_status status; 305 acpi_status status;
305 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; 306 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -322,9 +323,6 @@ acpi_status acpi_run_oshp(acpi_handle handle)
322 kfree(string.pointer); 323 kfree(string.pointer);
323 return status; 324 return status;
324} 325}
325EXPORT_SYMBOL_GPL(acpi_run_oshp);
326
327
328 326
329/* acpi_get_hp_params_from_firmware 327/* acpi_get_hp_params_from_firmware
330 * 328 *
@@ -374,6 +372,85 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
374} 372}
375EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); 373EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware);
376 374
375/**
376 * acpi_get_hp_hw_control_from_firmware
377 * @dev: the pci_dev of the bridge that has a hotplug controller
378 * @flags: requested control bits for _OSC
379 *
380 * Attempt to take hotplug control from firmware.
381 */
382int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags)
383{
384 acpi_status status;
385 acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
386 struct pci_dev *pdev = dev;
387 struct pci_bus *parent;
388 struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL };
389
390 flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
391 OSC_SHPC_NATIVE_HP_CONTROL |
392 OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
393 if (!flags) {
394 err("Invalid flags %u specified!\n", flags);
395 return -EINVAL;
396 }
397
398 /*
399 * Per PCI firmware specification, we should run the ACPI _OSC
400 * method to get control of hotplug hardware before using it. If
401 * an _OSC is missing, we look for an OSHP to do the same thing.
402 * To handle different BIOS behavior, we look for _OSC and OSHP
403 * within the scope of the hotplug controller and its parents,
404 * upto the host bridge under which this controller exists.
405 */
406 while (!handle) {
407 /*
408 * This hotplug controller was not listed in the ACPI name
409 * space at all. Try to get acpi handle of parent pci bus.
410 */
411 if (!pdev || !pdev->bus->parent)
412 break;
413 parent = pdev->bus->parent;
414 dbg("Could not find %s in acpi namespace, trying parent\n",
415 pci_name(pdev));
416 if (!parent->self)
417 /* Parent must be a host bridge */
418 handle = acpi_get_pci_rootbridge_handle(
419 pci_domain_nr(parent),
420 parent->number);
421 else
422 handle = DEVICE_ACPI_HANDLE(&(parent->self->dev));
423 pdev = parent->self;
424 }
425
426 while (handle) {
427 acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
428 dbg("Trying to get hotplug control for %s \n",
429 (char *)string.pointer);
430 status = pci_osc_control_set(handle, flags);
431 if (status == AE_NOT_FOUND)
432 status = acpi_run_oshp(handle);
433 if (ACPI_SUCCESS(status)) {
434 dbg("Gained control for hotplug HW for pci %s (%s)\n",
435 pci_name(dev), (char *)string.pointer);
436 kfree(string.pointer);
437 return 0;
438 }
439 if (acpi_root_bridge(handle))
440 break;
441 chandle = handle;
442 status = acpi_get_parent(chandle, &handle);
443 if (ACPI_FAILURE(status))
444 break;
445 }
446
447 dbg("Cannot get control of hotplug hardware for pci %s\n",
448 pci_name(dev));
449
450 kfree(string.pointer);
451 return -ENODEV;
452}
453EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
377 454
378/* acpi_root_bridge - check to see if this acpi object is a root bridge 455/* acpi_root_bridge - check to see if this acpi object is a root bridge
379 * 456 *