Commit fd0f7f73 authored by Alex Williamson's avatar Alex Williamson Committed by Bjorn Helgaas

PCI: Add support for save/restore of extended capabilities

Current save/restore is specific to standard capabilities.
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent 157e876f
...@@ -861,18 +861,28 @@ EXPORT_SYMBOL(pci_choose_state); ...@@ -861,18 +861,28 @@ EXPORT_SYMBOL(pci_choose_state);
#define PCI_EXP_SAVE_REGS 7 #define PCI_EXP_SAVE_REGS 7
static struct pci_cap_saved_state *pci_find_saved_cap( static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev,
struct pci_dev *pci_dev, char cap) u16 cap, bool extended)
{ {
struct pci_cap_saved_state *tmp; struct pci_cap_saved_state *tmp;
hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) { hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) {
if (tmp->cap.cap_nr == cap) if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap)
return tmp; return tmp;
} }
return NULL; return NULL;
} }
struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap)
{
return _pci_find_saved_cap(dev, cap, false);
}
struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap)
{
return _pci_find_saved_cap(dev, cap, true);
}
static int pci_save_pcie_state(struct pci_dev *dev) static int pci_save_pcie_state(struct pci_dev *dev)
{ {
int i = 0; int i = 0;
...@@ -1113,7 +1123,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state) ...@@ -1113,7 +1123,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)
while (cap->size) { while (cap->size) {
struct pci_cap_saved_state *tmp; struct pci_cap_saved_state *tmp;
tmp = pci_find_saved_cap(dev, cap->cap_nr); tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended);
if (!tmp || tmp->cap.size != cap->size) if (!tmp || tmp->cap.size != cap->size)
return -EINVAL; return -EINVAL;
...@@ -2047,18 +2057,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev, ...@@ -2047,18 +2057,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,
} }
/** /**
* pci_add_cap_save_buffer - allocate buffer for saving given capability registers * _pci_add_cap_save_buffer - allocate buffer for saving given
* capability registers
* @dev: the PCI device * @dev: the PCI device
* @cap: the capability to allocate the buffer for * @cap: the capability to allocate the buffer for
* @extended: Standard or Extended capability ID
* @size: requested size of the buffer * @size: requested size of the buffer
*/ */
static int pci_add_cap_save_buffer( static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap,
struct pci_dev *dev, char cap, unsigned int size) bool extended, unsigned int size)
{ {
int pos; int pos;
struct pci_cap_saved_state *save_state; struct pci_cap_saved_state *save_state;
if (extended)
pos = pci_find_ext_capability(dev, cap);
else
pos = pci_find_capability(dev, cap); pos = pci_find_capability(dev, cap);
if (pos <= 0) if (pos <= 0)
return 0; return 0;
...@@ -2067,12 +2083,23 @@ static int pci_add_cap_save_buffer( ...@@ -2067,12 +2083,23 @@ static int pci_add_cap_save_buffer(
return -ENOMEM; return -ENOMEM;
save_state->cap.cap_nr = cap; save_state->cap.cap_nr = cap;
save_state->cap.cap_extended = extended;
save_state->cap.size = size; save_state->cap.size = size;
pci_add_saved_cap(dev, save_state); pci_add_saved_cap(dev, save_state);
return 0; return 0;
} }
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size)
{
return _pci_add_cap_save_buffer(dev, cap, false, size);
}
int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size)
{
return _pci_add_cap_save_buffer(dev, cap, true, size);
}
/** /**
* pci_allocate_cap_save_buffers - allocate buffers for saving capabilities * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities
* @dev: the PCI device * @dev: the PCI device
......
...@@ -224,7 +224,8 @@ enum pci_bus_speed { ...@@ -224,7 +224,8 @@ enum pci_bus_speed {
}; };
struct pci_cap_saved_data { struct pci_cap_saved_data {
char cap_nr; u16 cap_nr;
bool cap_extended;
unsigned int size; unsigned int size;
u32 data[0]; u32 data[0];
}; };
...@@ -977,6 +978,12 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev); ...@@ -977,6 +978,12 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev);
int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state); int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state);
int pci_load_and_free_saved_state(struct pci_dev *dev, int pci_load_and_free_saved_state(struct pci_dev *dev,
struct pci_saved_state **state); struct pci_saved_state **state);
struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap);
struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev,
u16 cap);
int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size);
int pci_add_ext_cap_save_buffer(struct pci_dev *dev,
u16 cap, unsigned int size);
int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state); int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state);
int pci_set_power_state(struct pci_dev *dev, pci_power_t state); int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state); pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment