diff options
author | Alex Williamson <alex.williamson@redhat.com> | 2013-12-17 18:43:45 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-17 19:38:32 -0500 |
commit | fd0f7f73ca96bb0f8723b5e59759ad43bab88954 (patch) | |
tree | 21b10c4ba642085973a5e52b3e970354e6b18ea1 | |
parent | 157e876ffe0b28821a0d82d8ac944fe7363bbe87 (diff) |
PCI: Add support for save/restore of extended capabilities
Current save/restore is specific to standard capabilities.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/pci.c | 43 | ||||
-rw-r--r-- | include/linux/pci.h | 9 |
2 files changed, 43 insertions, 9 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bb257b975a8f..8f2be7ec705c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -861,18 +861,28 @@ EXPORT_SYMBOL(pci_choose_state); | |||
861 | #define PCI_EXP_SAVE_REGS 7 | 861 | #define PCI_EXP_SAVE_REGS 7 |
862 | 862 | ||
863 | 863 | ||
864 | static struct pci_cap_saved_state *pci_find_saved_cap( | 864 | static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev, |
865 | struct pci_dev *pci_dev, char cap) | 865 | u16 cap, bool extended) |
866 | { | 866 | { |
867 | struct pci_cap_saved_state *tmp; | 867 | struct pci_cap_saved_state *tmp; |
868 | 868 | ||
869 | hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) { | 869 | hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) { |
870 | if (tmp->cap.cap_nr == cap) | 870 | if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap) |
871 | return tmp; | 871 | return tmp; |
872 | } | 872 | } |
873 | return NULL; | 873 | return NULL; |
874 | } | 874 | } |
875 | 875 | ||
876 | struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap) | ||
877 | { | ||
878 | return _pci_find_saved_cap(dev, cap, false); | ||
879 | } | ||
880 | |||
881 | struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap) | ||
882 | { | ||
883 | return _pci_find_saved_cap(dev, cap, true); | ||
884 | } | ||
885 | |||
876 | static int pci_save_pcie_state(struct pci_dev *dev) | 886 | static int pci_save_pcie_state(struct pci_dev *dev) |
877 | { | 887 | { |
878 | int i = 0; | 888 | int i = 0; |
@@ -1113,7 +1123,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state) | |||
1113 | while (cap->size) { | 1123 | while (cap->size) { |
1114 | struct pci_cap_saved_state *tmp; | 1124 | struct pci_cap_saved_state *tmp; |
1115 | 1125 | ||
1116 | tmp = pci_find_saved_cap(dev, cap->cap_nr); | 1126 | tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended); |
1117 | if (!tmp || tmp->cap.size != cap->size) | 1127 | if (!tmp || tmp->cap.size != cap->size) |
1118 | return -EINVAL; | 1128 | return -EINVAL; |
1119 | 1129 | ||
@@ -2047,18 +2057,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev, | |||
2047 | } | 2057 | } |
2048 | 2058 | ||
2049 | /** | 2059 | /** |
2050 | * pci_add_cap_save_buffer - allocate buffer for saving given capability registers | 2060 | * _pci_add_cap_save_buffer - allocate buffer for saving given |
2061 | * capability registers | ||
2051 | * @dev: the PCI device | 2062 | * @dev: the PCI device |
2052 | * @cap: the capability to allocate the buffer for | 2063 | * @cap: the capability to allocate the buffer for |
2064 | * @extended: Standard or Extended capability ID | ||
2053 | * @size: requested size of the buffer | 2065 | * @size: requested size of the buffer |
2054 | */ | 2066 | */ |
2055 | static int pci_add_cap_save_buffer( | 2067 | static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap, |
2056 | struct pci_dev *dev, char cap, unsigned int size) | 2068 | bool extended, unsigned int size) |
2057 | { | 2069 | { |
2058 | int pos; | 2070 | int pos; |
2059 | struct pci_cap_saved_state *save_state; | 2071 | struct pci_cap_saved_state *save_state; |
2060 | 2072 | ||
2061 | pos = pci_find_capability(dev, cap); | 2073 | if (extended) |
2074 | pos = pci_find_ext_capability(dev, cap); | ||
2075 | else | ||
2076 | pos = pci_find_capability(dev, cap); | ||
2077 | |||
2062 | if (pos <= 0) | 2078 | if (pos <= 0) |
2063 | return 0; | 2079 | return 0; |
2064 | 2080 | ||
@@ -2067,12 +2083,23 @@ static int pci_add_cap_save_buffer( | |||
2067 | return -ENOMEM; | 2083 | return -ENOMEM; |
2068 | 2084 | ||
2069 | save_state->cap.cap_nr = cap; | 2085 | save_state->cap.cap_nr = cap; |
2086 | save_state->cap.cap_extended = extended; | ||
2070 | save_state->cap.size = size; | 2087 | save_state->cap.size = size; |
2071 | pci_add_saved_cap(dev, save_state); | 2088 | pci_add_saved_cap(dev, save_state); |
2072 | 2089 | ||
2073 | return 0; | 2090 | return 0; |
2074 | } | 2091 | } |
2075 | 2092 | ||
2093 | int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size) | ||
2094 | { | ||
2095 | return _pci_add_cap_save_buffer(dev, cap, false, size); | ||
2096 | } | ||
2097 | |||
2098 | int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size) | ||
2099 | { | ||
2100 | return _pci_add_cap_save_buffer(dev, cap, true, size); | ||
2101 | } | ||
2102 | |||
2076 | /** | 2103 | /** |
2077 | * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities | 2104 | * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities |
2078 | * @dev: the PCI device | 2105 | * @dev: the PCI device |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 211ce43ba483..1bb75b0c4c6f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -224,7 +224,8 @@ enum pci_bus_speed { | |||
224 | }; | 224 | }; |
225 | 225 | ||
226 | struct pci_cap_saved_data { | 226 | struct pci_cap_saved_data { |
227 | char cap_nr; | 227 | u16 cap_nr; |
228 | bool cap_extended; | ||
228 | unsigned int size; | 229 | unsigned int size; |
229 | u32 data[0]; | 230 | u32 data[0]; |
230 | }; | 231 | }; |
@@ -977,6 +978,12 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev); | |||
977 | int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state); | 978 | int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state); |
978 | int pci_load_and_free_saved_state(struct pci_dev *dev, | 979 | int pci_load_and_free_saved_state(struct pci_dev *dev, |
979 | struct pci_saved_state **state); | 980 | struct pci_saved_state **state); |
981 | struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap); | ||
982 | struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, | ||
983 | u16 cap); | ||
984 | int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size); | ||
985 | int pci_add_ext_cap_save_buffer(struct pci_dev *dev, | ||
986 | u16 cap, unsigned int size); | ||
980 | int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); | 987 | int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); |
981 | int pci_set_power_state(struct pci_dev *dev, pci_power_t state); | 988 | int pci_set_power_state(struct pci_dev *dev, pci_power_t state); |
982 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); | 989 | pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); |