aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2013-12-17 18:43:45 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-12-17 19:38:32 -0500
commitfd0f7f73ca96bb0f8723b5e59759ad43bab88954 (patch)
tree21b10c4ba642085973a5e52b3e970354e6b18ea1
parent157e876ffe0b28821a0d82d8ac944fe7363bbe87 (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.c43
-rw-r--r--include/linux/pci.h9
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
864static struct pci_cap_saved_state *pci_find_saved_cap( 864static 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
876struct 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
881struct 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
876static int pci_save_pcie_state(struct pci_dev *dev) 886static 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 */
2055static int pci_add_cap_save_buffer( 2067static 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
2093int 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
2098int 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
226struct pci_cap_saved_data { 226struct 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);
977int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state); 978int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state);
978int pci_load_and_free_saved_state(struct pci_dev *dev, 979int pci_load_and_free_saved_state(struct pci_dev *dev,
979 struct pci_saved_state **state); 980 struct pci_saved_state **state);
981struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
982struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
983 u16 cap);
984int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
985int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
986 u16 cap, unsigned int size);
980int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); 987int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
981int pci_set_power_state(struct pci_dev *dev, pci_power_t state); 988int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
982pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); 989pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);