PCI/AER: Save AER Capability for suspend/resume
Previously we did not save and restore the AER configuration on suspend/resume, so the configuration may be lost after resume. Save the AER configuration during suspend and restore it during resume. [bhelgaas: commit log] Link: https://lore.kernel.org/r/92EBB4272BF81E4089A7126EC1E7B28492C3B007@IRSMSX101.ger.corp.intel.com Signed-off-by: Mayurkumar Patel <mayurkumar.patel@intel.com> Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
This commit is contained in:
parent
54ecb8f702
commit
af65d1ad41
|
@ -355,7 +355,7 @@ static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
|
||||||
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
|
pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
|
bool pcie_cap_has_rtctl(const struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int type = pci_pcie_type(dev);
|
int type = pci_pcie_type(dev);
|
||||||
|
|
||||||
|
|
|
@ -1361,6 +1361,7 @@ int pci_save_state(struct pci_dev *dev)
|
||||||
|
|
||||||
pci_save_ltr_state(dev);
|
pci_save_ltr_state(dev);
|
||||||
pci_save_dpc_state(dev);
|
pci_save_dpc_state(dev);
|
||||||
|
pci_save_aer_state(dev);
|
||||||
return pci_save_vc_state(dev);
|
return pci_save_vc_state(dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_save_state);
|
EXPORT_SYMBOL(pci_save_state);
|
||||||
|
@ -1474,6 +1475,7 @@ void pci_restore_state(struct pci_dev *dev)
|
||||||
pci_restore_dpc_state(dev);
|
pci_restore_dpc_state(dev);
|
||||||
|
|
||||||
pci_cleanup_aer_error_status_regs(dev);
|
pci_cleanup_aer_error_status_regs(dev);
|
||||||
|
pci_restore_aer_state(dev);
|
||||||
|
|
||||||
pci_restore_config_space(dev);
|
pci_restore_config_space(dev);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ extern const unsigned char pcie_link_speed[];
|
||||||
extern bool pci_early_dump;
|
extern bool pci_early_dump;
|
||||||
|
|
||||||
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
|
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
|
||||||
|
bool pcie_cap_has_rtctl(const struct pci_dev *dev);
|
||||||
|
|
||||||
/* Functions internal to the PCI core code */
|
/* Functions internal to the PCI core code */
|
||||||
|
|
||||||
|
|
|
@ -448,12 +448,70 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pci_save_aer_state(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
struct pci_cap_saved_state *save_state;
|
||||||
|
u32 *cap;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = dev->aer_cap;
|
||||||
|
if (!pos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_ERR);
|
||||||
|
if (!save_state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cap = &save_state->cap.data[0];
|
||||||
|
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, cap++);
|
||||||
|
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, cap++);
|
||||||
|
pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, cap++);
|
||||||
|
pci_read_config_dword(dev, pos + PCI_ERR_CAP, cap++);
|
||||||
|
if (pcie_cap_has_rtctl(dev))
|
||||||
|
pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, cap++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pci_restore_aer_state(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
struct pci_cap_saved_state *save_state;
|
||||||
|
u32 *cap;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = dev->aer_cap;
|
||||||
|
if (!pos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_ERR);
|
||||||
|
if (!save_state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cap = &save_state->cap.data[0];
|
||||||
|
pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, *cap++);
|
||||||
|
pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, *cap++);
|
||||||
|
pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, *cap++);
|
||||||
|
pci_write_config_dword(dev, pos + PCI_ERR_CAP, *cap++);
|
||||||
|
if (pcie_cap_has_rtctl(dev))
|
||||||
|
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, *cap++);
|
||||||
|
}
|
||||||
|
|
||||||
void pci_aer_init(struct pci_dev *dev)
|
void pci_aer_init(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
int n;
|
||||||
|
|
||||||
if (dev->aer_cap)
|
dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
|
||||||
dev->aer_stats = kzalloc(sizeof(struct aer_stats), GFP_KERNEL);
|
if (!dev->aer_cap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dev->aer_stats = kzalloc(sizeof(struct aer_stats), GFP_KERNEL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We save/restore PCI_ERR_UNCOR_MASK, PCI_ERR_UNCOR_SEVER,
|
||||||
|
* PCI_ERR_COR_MASK, and PCI_ERR_CAP. Root and Root Complex Event
|
||||||
|
* Collectors also implement PCI_ERR_ROOT_COMMAND (PCIe r5.0, sec
|
||||||
|
* 7.8.4).
|
||||||
|
*/
|
||||||
|
n = pcie_cap_has_rtctl(dev) ? 5 : 4;
|
||||||
|
pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_ERR, sizeof(u32) * n);
|
||||||
|
|
||||||
pci_cleanup_aer_error_status_regs(dev);
|
pci_cleanup_aer_error_status_regs(dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev);
|
||||||
int pci_disable_pcie_error_reporting(struct pci_dev *dev);
|
int pci_disable_pcie_error_reporting(struct pci_dev *dev);
|
||||||
int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
|
int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
|
||||||
int pci_cleanup_aer_error_status_regs(struct pci_dev *dev);
|
int pci_cleanup_aer_error_status_regs(struct pci_dev *dev);
|
||||||
|
void pci_save_aer_state(struct pci_dev *dev);
|
||||||
|
void pci_restore_aer_state(struct pci_dev *dev);
|
||||||
#else
|
#else
|
||||||
static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
|
static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
|
@ -63,6 +65,8 @@ static inline int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
static inline void pci_save_aer_state(struct pci_dev *dev) {}
|
||||||
|
static inline void pci_restore_aer_state(struct pci_dev *dev) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void cper_print_aer(struct pci_dev *dev, int aer_severity,
|
void cper_print_aer(struct pci_dev *dev, int aer_severity,
|
||||||
|
|
Loading…
Reference in New Issue