aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorYu Zhao <yu.zhao@intel.com>2009-04-09 02:57:39 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-04-22 18:59:41 -0400
commit1b6b8ce2ac372ea1f2065b89228ede105eb68dc5 (patch)
tree12a67c35d30ee626ca46d497c35f3a7d952034c5 /drivers/pci
parentb10ceb5530df7ee6e81f92910589a34dd3e5690b (diff)
PCI: only save/restore existent registers in the PCIe capability
PCIe 1.1 base neither requires the endpoint to implement the entire PCIe capability structure nor specifies default values of registers that are not implemented by the device. So we only save and restore registers that must be implemented by different device types if the device PCIe capability version is 1. PCIe 1.1 Capability Structure Expansion ECN and PCIe 2.0 requires all registers in the PCIe capability to be either implemented or hardwired to 0. Their PCIe capability version is 2. Signed-off-by: Yu Zhao <yu.zhao@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci.c70
1 files changed, 56 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
684static int pci_save_pcie_state(struct pci_dev *dev) 706static 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