diff options
| author | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-28 08:29:59 -0400 |
|---|---|---|
| committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-09-28 08:29:59 -0400 |
| commit | 185a257f2f73bcd89050ad02da5bedbc28fc43fa (patch) | |
| tree | 5e32586114534ed3f2165614cba3d578f5d87307 /drivers/pci/pci.c | |
| parent | 3f1a9aaeffd8d1cbc5ab9776c45cbd66af1c9699 (diff) | |
| parent | a77c64c1a641950626181b4857abb701d8f38ccc (diff) | |
Merge branch 'master' into gfs2
Diffstat (limited to 'drivers/pci/pci.c')
| -rw-r--r-- | drivers/pci/pci.c | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9f79dd6d51ab..a544997399b3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -432,10 +432,12 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) | |||
| 432 | case PM_EVENT_ON: | 432 | case PM_EVENT_ON: |
| 433 | return PCI_D0; | 433 | return PCI_D0; |
| 434 | case PM_EVENT_FREEZE: | 434 | case PM_EVENT_FREEZE: |
| 435 | case PM_EVENT_PRETHAW: | ||
| 436 | /* REVISIT both freeze and pre-thaw "should" use D0 */ | ||
| 435 | case PM_EVENT_SUSPEND: | 437 | case PM_EVENT_SUSPEND: |
| 436 | return PCI_D3hot; | 438 | return PCI_D3hot; |
| 437 | default: | 439 | default: |
| 438 | printk("They asked me for state %d\n", state.event); | 440 | printk("Unrecognized suspend event %d\n", state.event); |
| 439 | BUG(); | 441 | BUG(); |
| 440 | } | 442 | } |
| 441 | return PCI_D0; | 443 | return PCI_D0; |
| @@ -443,6 +445,51 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) | |||
| 443 | 445 | ||
| 444 | EXPORT_SYMBOL(pci_choose_state); | 446 | EXPORT_SYMBOL(pci_choose_state); |
| 445 | 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 | |||
| 446 | /** | 493 | /** |
| 447 | * 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 |
| 448 | * @dev: - PCI device that we're dealing with | 495 | * @dev: - PCI device that we're dealing with |
| @@ -458,6 +505,8 @@ pci_save_state(struct pci_dev *dev) | |||
| 458 | return i; | 505 | return i; |
| 459 | if ((i = pci_save_msix_state(dev)) != 0) | 506 | if ((i = pci_save_msix_state(dev)) != 0) |
| 460 | return i; | 507 | return i; |
| 508 | if ((i = pci_save_pcie_state(dev)) != 0) | ||
| 509 | return i; | ||
| 461 | return 0; | 510 | return 0; |
| 462 | } | 511 | } |
| 463 | 512 | ||
| @@ -471,6 +520,9 @@ pci_restore_state(struct pci_dev *dev) | |||
| 471 | int i; | 520 | int i; |
| 472 | int val; | 521 | int val; |
| 473 | 522 | ||
| 523 | /* PCI Express register must be restored first */ | ||
| 524 | pci_restore_pcie_state(dev); | ||
| 525 | |||
| 474 | /* | 526 | /* |
| 475 | * The Base Address register should be programmed before the command | 527 | * The Base Address register should be programmed before the command |
| 476 | * register(s) | 528 | * register(s) |
| @@ -953,13 +1005,12 @@ static int __devinit pci_setup(char *str) | |||
| 953 | } | 1005 | } |
| 954 | str = k; | 1006 | str = k; |
| 955 | } | 1007 | } |
| 956 | return 1; | 1008 | return 0; |
| 957 | } | 1009 | } |
| 1010 | early_param("pci", pci_setup); | ||
| 958 | 1011 | ||
| 959 | device_initcall(pci_init); | 1012 | device_initcall(pci_init); |
| 960 | 1013 | ||
| 961 | __setup("pci=", pci_setup); | ||
| 962 | |||
| 963 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) | 1014 | #if defined(CONFIG_ISA) || defined(CONFIG_EISA) |
| 964 | /* FIXME: Some boxes have multiple ISA bridges! */ | 1015 | /* FIXME: Some boxes have multiple ISA bridges! */ |
| 965 | struct pci_dev *isa_bridge; | 1016 | struct pci_dev *isa_bridge; |
