diff options
-rw-r--r-- | drivers/pci/pci.c | 70 | ||||
-rw-r--r-- | include/linux/pci_regs.h | 1 |
2 files changed, 57 insertions, 14 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 16fd0d4c3166..34bf0fdf5047 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -681,11 +681,34 @@ EXPORT_SYMBOL(pci_choose_state); | |||
681 | 681 | ||
682 | #define PCI_EXP_SAVE_REGS 7 | 682 | #define PCI_EXP_SAVE_REGS 7 |
683 | 683 | ||
684 | #define pcie_cap_has_devctl(type, flags) 1 | ||
685 | #define pcie_cap_has_lnkctl(type, flags) \ | ||
686 | ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ | ||
687 | (type == PCI_EXP_TYPE_ROOT_PORT || \ | ||
688 | type == PCI_EXP_TYPE_ENDPOINT || \ | ||
689 | type == PCI_EXP_TYPE_LEG_END)) | ||
690 | #define pcie_cap_has_sltctl(type, flags) \ | ||
691 | ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ | ||
692 | ((type == PCI_EXP_TYPE_ROOT_PORT) || \ | ||
693 | (type == PCI_EXP_TYPE_DOWNSTREAM && \ | ||
694 | (flags & PCI_EXP_FLAGS_SLOT)))) | ||
695 | #define pcie_cap_has_rtctl(type, flags) \ | ||
696 | ((flags & PCI_EXP_FLAGS_VERS) > 1 || \ | ||
697 | (type == PCI_EXP_TYPE_ROOT_PORT || \ | ||
698 | type == PCI_EXP_TYPE_RC_EC)) | ||
699 | #define pcie_cap_has_devctl2(type, flags) \ | ||
700 | ((flags & PCI_EXP_FLAGS_VERS) > 1) | ||
701 | #define pcie_cap_has_lnkctl2(type, flags) \ | ||
702 | ((flags & PCI_EXP_FLAGS_VERS) > 1) | ||
703 | #define pcie_cap_has_sltctl2(type, flags) \ | ||
704 | ((flags & PCI_EXP_FLAGS_VERS) > 1) | ||
705 | |||
684 | static int pci_save_pcie_state(struct pci_dev *dev) | 706 | static int pci_save_pcie_state(struct pci_dev *dev) |
685 | { | 707 | { |
686 | int pos, i = 0; | 708 | int pos, i = 0; |
687 | struct pci_cap_saved_state *save_state; | 709 | struct pci_cap_saved_state *save_state; |
688 | u16 *cap; | 710 | u16 *cap; |
711 | u16 flags; | ||
689 | 712 | ||
690 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | 713 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); |
691 | if (pos <= 0) | 714 | if (pos <= 0) |
@@ -698,13 +721,22 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
698 | } | 721 | } |
699 | cap = (u16 *)&save_state->data[0]; | 722 | cap = (u16 *)&save_state->data[0]; |
700 | 723 | ||
701 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); | 724 | pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); |
702 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); | 725 | |
703 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); | 726 | if (pcie_cap_has_devctl(dev->pcie_type, flags)) |
704 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); | 727 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]); |
705 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); | 728 | if (pcie_cap_has_lnkctl(dev->pcie_type, flags)) |
706 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); | 729 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); |
707 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); | 730 | if (pcie_cap_has_sltctl(dev->pcie_type, flags)) |
731 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); | ||
732 | if (pcie_cap_has_rtctl(dev->pcie_type, flags)) | ||
733 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); | ||
734 | if (pcie_cap_has_devctl2(dev->pcie_type, flags)) | ||
735 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); | ||
736 | if (pcie_cap_has_lnkctl2(dev->pcie_type, flags)) | ||
737 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); | ||
738 | if (pcie_cap_has_sltctl2(dev->pcie_type, flags)) | ||
739 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); | ||
708 | 740 | ||
709 | return 0; | 741 | return 0; |
710 | } | 742 | } |
@@ -714,6 +746,7 @@ static void pci_restore_pcie_state(struct pci_dev *dev) | |||
714 | int i = 0, pos; | 746 | int i = 0, pos; |
715 | struct pci_cap_saved_state *save_state; | 747 | struct pci_cap_saved_state *save_state; |
716 | u16 *cap; | 748 | u16 *cap; |
749 | u16 flags; | ||
717 | 750 | ||
718 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); | 751 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); |
719 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | 752 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); |
@@ -721,13 +754,22 @@ static void pci_restore_pcie_state(struct pci_dev *dev) | |||
721 | return; | 754 | return; |
722 | cap = (u16 *)&save_state->data[0]; | 755 | cap = (u16 *)&save_state->data[0]; |
723 | 756 | ||
724 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); | 757 | pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags); |
725 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); | 758 | |
726 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); | 759 | if (pcie_cap_has_devctl(dev->pcie_type, flags)) |
727 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); | 760 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]); |
728 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); | 761 | if (pcie_cap_has_lnkctl(dev->pcie_type, flags)) |
729 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); | 762 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); |
730 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); | 763 | if (pcie_cap_has_sltctl(dev->pcie_type, flags)) |
764 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); | ||
765 | if (pcie_cap_has_rtctl(dev->pcie_type, flags)) | ||
766 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); | ||
767 | if (pcie_cap_has_devctl2(dev->pcie_type, flags)) | ||
768 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); | ||
769 | if (pcie_cap_has_lnkctl2(dev->pcie_type, flags)) | ||
770 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); | ||
771 | if (pcie_cap_has_sltctl2(dev->pcie_type, flags)) | ||
772 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); | ||
731 | } | 773 | } |
732 | 774 | ||
733 | 775 | ||
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index e4d08c1b2e0b..616bf8b3c8b5 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h | |||
@@ -376,6 +376,7 @@ | |||
376 | #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ | 376 | #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ |
377 | #define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ | 377 | #define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ |
378 | #define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */ | 378 | #define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */ |
379 | #define PCI_EXP_TYPE_RC_EC 0x10 /* Root Complex Event Collector */ | ||
379 | #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ | 380 | #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ |
380 | #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ | 381 | #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ |
381 | #define PCI_EXP_DEVCAP 4 /* Device capabilities */ | 382 | #define PCI_EXP_DEVCAP 4 /* Device capabilities */ |