diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d408a3c30426..a544997399b3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | 19 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
20 | #include "pci.h" | 20 | #include "pci.h" |
21 | 21 | ||
22 | unsigned int pci_pm_d3_delay = 10; | ||
22 | 23 | ||
23 | /** | 24 | /** |
24 | * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children | 25 | * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children |
@@ -313,6 +314,14 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
313 | } else if (dev->current_state == state) | 314 | } else if (dev->current_state == state) |
314 | return 0; /* we're already there */ | 315 | return 0; /* we're already there */ |
315 | 316 | ||
317 | /* | ||
318 | * If the device or the parent bridge can't support PCI PM, ignore | ||
319 | * the request if we're doing anything besides putting it into D0 | ||
320 | * (which would only happen on boot). | ||
321 | */ | ||
322 | if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev)) | ||
323 | return 0; | ||
324 | |||
316 | /* find PCI PM capability in list */ | 325 | /* find PCI PM capability in list */ |
317 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); | 326 | pm = pci_find_capability(dev, PCI_CAP_ID_PM); |
318 | 327 | ||
@@ -363,13 +372,13 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
363 | /* Mandatory power management transition delays */ | 372 | /* Mandatory power management transition delays */ |
364 | /* see PCI PM 1.1 5.6.1 table 18 */ | 373 | /* see PCI PM 1.1 5.6.1 table 18 */ |
365 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) | 374 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) |
366 | msleep(10); | 375 | msleep(pci_pm_d3_delay); |
367 | else if (state == PCI_D2 || dev->current_state == PCI_D2) | 376 | else if (state == PCI_D2 || dev->current_state == PCI_D2) |
368 | udelay(200); | 377 | udelay(200); |
369 | 378 | ||
370 | /* | 379 | /* |
371 | * Give firmware a chance to be called, such as ACPI _PRx, _PSx | 380 | * Give firmware a chance to be called, such as ACPI _PRx, _PSx |
372 | * Firmware method after natice method ? | 381 | * Firmware method after native method ? |
373 | */ | 382 | */ |
374 | if (platform_pci_set_power_state) | 383 | if (platform_pci_set_power_state) |
375 | platform_pci_set_power_state(dev, state); | 384 | platform_pci_set_power_state(dev, state); |
@@ -423,10 +432,12 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) | |||
423 | case PM_EVENT_ON: | 432 | case PM_EVENT_ON: |
424 | return PCI_D0; | 433 | return PCI_D0; |
425 | case PM_EVENT_FREEZE: | 434 | case PM_EVENT_FREEZE: |
435 | case PM_EVENT_PRETHAW: | ||
436 | /* REVISIT both freeze and pre-thaw "should" use D0 */ | ||
426 | case PM_EVENT_SUSPEND: | 437 | case PM_EVENT_SUSPEND: |
427 | return PCI_D3hot; | 438 | return PCI_D3hot; |
428 | default: | 439 | default: |
429 | printk("They asked me for state %d\n", state.event); | 440 | printk("Unrecognized suspend event %d\n", state.event); |
430 | BUG(); | 441 | BUG(); |
431 | } | 442 | } |
432 | return PCI_D0; | 443 | return PCI_D0; |
@@ -434,6 +445,51 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) | |||
434 | 445 | ||
435 | EXPORT_SYMBOL(pci_choose_state); | 446 | EXPORT_SYMBOL(pci_choose_state); |
436 | 447 | ||
448 | static int pci_save_pcie_state(struct pci_dev *dev) | ||
449 | { | ||
450 | int pos, i = 0; | ||
451 | struct pci_cap_saved_state *save_state; | ||
452 | u16 *cap; | ||
453 | |||
454 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
455 | if (pos <= 0) | ||
456 | return 0; | ||
457 | |||
458 | save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL); | ||
459 | if (!save_state) { | ||
460 | dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); | ||
461 | return -ENOMEM; | ||
462 | } | ||
463 | cap = (u16 *)&save_state->data[0]; | ||
464 | |||
465 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); | ||
466 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); | ||
467 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); | ||
468 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); | ||
469 | pci_add_saved_cap(dev, save_state); | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static void pci_restore_pcie_state(struct pci_dev *dev) | ||
474 | { | ||
475 | int i = 0, pos; | ||
476 | struct pci_cap_saved_state *save_state; | ||
477 | u16 *cap; | ||
478 | |||
479 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); | ||
480 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
481 | if (!save_state || pos <= 0) | ||
482 | return; | ||
483 | cap = (u16 *)&save_state->data[0]; | ||
484 | |||
485 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); | ||
486 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); | ||
487 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); | ||
488 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); | ||
489 | pci_remove_saved_cap(save_state); | ||
490 | kfree(save_state); | ||
491 | } | ||
492 | |||
437 | /** | 493 | /** |
438 | * pci_save_state - save the PCI configuration space of a device before suspending | 494 | * pci_save_state - save the PCI configuration space of a device before suspending |
439 | * @dev: - PCI device that we're dealing with | 495 | * @dev: - PCI device that we're dealing with |
@@ -449,6 +505,8 @@ pci_save_state(struct pci_dev *dev) | |||
449 | return i; | 505 | return i; |
450 | if ((i = pci_save_msix_state(dev)) != 0) | 506 | if ((i = pci_save_msix_state(dev)) != 0) |
451 | return i; | 507 | return i; |
508 | if ((i = pci_save_pcie_state(dev)) != 0) | ||
509 | return i; | ||
452 | return 0; | 510 | return 0; |
453 | } | 511 | } |
454 | 512 | ||
@@ -462,6 +520,9 @@ pci_restore_state(struct pci_dev *dev) | |||
462 | int i; | 520 | int i; |
463 | int val; | 521 | int val; |
464 | 522 | ||
523 | /* PCI Express register must be restored first */ | ||
524 | pci_restore_pcie_state(dev); | ||
525 | |||
465 | /* | 526 | /* |
466 | * The Base Address register should be programmed before the command | 527 | * The Base Address register should be programmed before the command |
467 | * register(s) | 528 | * register(s) |
@@ -691,10 +752,12 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name) | |||
691 | return 0; | 752 | return 0; |
692 | 753 | ||
693 | err_out: | 754 | err_out: |
694 | printk (KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n", | 755 | printk (KERN_WARNING "PCI: Unable to reserve %s region #%d:%llx@%llx " |
756 | "for device %s\n", | ||
695 | pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem", | 757 | pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem", |
696 | bar + 1, /* PCI BAR # */ | 758 | bar + 1, /* PCI BAR # */ |
697 | pci_resource_len(pdev, bar), pci_resource_start(pdev, bar), | 759 | (unsigned long long)pci_resource_len(pdev, bar), |
760 | (unsigned long long)pci_resource_start(pdev, bar), | ||
698 | pci_name(pdev)); | 761 | pci_name(pdev)); |
699 | return -EBUSY; | 762 | return -EBUSY; |
700 | } | 763 | } |
@@ -942,13 +1005,12 @@ static int __devinit pci_setup(char *str) | |||
942 | } | 1005 | } |
943 | str = k; | 1006 | str = k; |
944 | } | 1007 | } |
945 | return 1; | 1008 | return 0; |
946 | } | 1009 | } |
1010 | early_param("pci", pci_setup); | ||
947 | 1011 | ||
948 | device_initcall(pci_init); | 1012 | device_initcall(pci_init); |
949 | 1013 | ||
950 | __setup("pci=", pci_setup); | ||
951 | |||
952 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | 1014 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
953 | /* FIXME: Some boxes have multiple ISA bridges! */ | 1015 | /* FIXME: Some boxes have multiple ISA bridges! */ |
954 | struct pci_dev *isa_bridge; | 1016 | struct pci_dev *isa_bridge; |