Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alex Williamson and committed by
Bjorn Helgaas
fd0f7f73 157e876f

+43 -9
+35 -8
drivers/pci/pci.c
··· 861 861 #define PCI_EXP_SAVE_REGS 7 862 862 863 863 864 - static struct pci_cap_saved_state *pci_find_saved_cap( 865 - struct pci_dev *pci_dev, char cap) 864 + static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev, 865 + u16 cap, bool extended) 866 866 { 867 867 struct pci_cap_saved_state *tmp; 868 868 869 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 871 return tmp; 872 872 } 873 873 return NULL; 874 + } 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); 874 884 } 875 885 876 886 static int pci_save_pcie_state(struct pci_dev *dev) ··· 1123 1113 while (cap->size) { 1124 1114 struct pci_cap_saved_state *tmp; 1125 1115 1126 - tmp = pci_find_saved_cap(dev, cap->cap_nr); 1116 + tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended); 1127 1117 if (!tmp || tmp->cap.size != cap->size) 1128 1118 return -EINVAL; 1129 1119 ··· 2057 2047 } 2058 2048 2059 2049 /** 2060 - * pci_add_cap_save_buffer - allocate buffer for saving given capability registers 2050 + * _pci_add_cap_save_buffer - allocate buffer for saving given 2051 + * capability registers 2061 2052 * @dev: the PCI device 2062 2053 * @cap: the capability to allocate the buffer for 2054 + * @extended: Standard or Extended capability ID 2063 2055 * @size: requested size of the buffer 2064 2056 */ 2065 - static int pci_add_cap_save_buffer( 2066 - struct pci_dev *dev, char cap, unsigned int size) 2057 + static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap, 2058 + bool extended, unsigned int size) 2067 2059 { 2068 2060 int pos; 2069 2061 struct pci_cap_saved_state *save_state; 2070 2062 2071 - pos = pci_find_capability(dev, cap); 2063 + if (extended) 2064 + pos = pci_find_ext_capability(dev, cap); 2065 + else 2066 + pos = pci_find_capability(dev, cap); 2067 + 2072 2068 if (pos <= 0) 2073 2069 return 0; 2074 2070 ··· 2083 2067 return -ENOMEM; 2084 2068 2085 2069 save_state->cap.cap_nr = cap; 2070 + save_state->cap.cap_extended = extended; 2086 2071 save_state->cap.size = size; 2087 2072 pci_add_saved_cap(dev, save_state); 2088 2073 2089 2074 return 0; 2075 + } 2076 + 2077 + int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size) 2078 + { 2079 + return _pci_add_cap_save_buffer(dev, cap, false, size); 2080 + } 2081 + 2082 + int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size) 2083 + { 2084 + return _pci_add_cap_save_buffer(dev, cap, true, size); 2090 2085 } 2091 2086 2092 2087 /**
+8 -1
include/linux/pci.h
··· 224 224 }; 225 225 226 226 struct pci_cap_saved_data { 227 - char cap_nr; 227 + u16 cap_nr; 228 + bool cap_extended; 228 229 unsigned int size; 229 230 u32 data[0]; 230 231 }; ··· 978 977 int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state); 979 978 int pci_load_and_free_saved_state(struct pci_dev *dev, 980 979 struct pci_saved_state **state); 980 + struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap); 981 + struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, 982 + u16 cap); 983 + int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size); 984 + int pci_add_ext_cap_save_buffer(struct pci_dev *dev, 985 + u16 cap, unsigned int size); 981 986 int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); 982 987 int pci_set_power_state(struct pci_dev *dev, pci_power_t state); 983 988 pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);