diff options
author | Keith Busch <keith.busch@intel.com> | 2016-09-27 16:23:34 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-09-27 17:01:49 -0400 |
commit | 66b808099146166c44157600a166c8372172cd76 (patch) | |
tree | 6dfd3e4ab300a3a3d07a6d546f8a1404c5d0f105 | |
parent | 4b202b716e4e282c26c4a95952ea33e318c363ab (diff) |
PCI/AER: Cache capability position
Save the position of the error reporting capability so it doesn't need to
be rediscovered during error handling.
Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: Lukas Wunner <lukas@wunner.de>
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv.c | 10 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aerdrv_core.c | 18 | ||||
-rw-r--r-- | drivers/pci/probe.c | 3 | ||||
-rw-r--r-- | include/linux/pci.h | 5 |
4 files changed, 24 insertions, 12 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 08ce257077db..e99efaa723d5 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
@@ -134,7 +134,7 @@ static void aer_enable_rootport(struct aer_rpc *rpc) | |||
134 | pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, | 134 | pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, |
135 | SYSTEM_ERROR_INTR_ON_MESG_MASK); | 135 | SYSTEM_ERROR_INTR_ON_MESG_MASK); |
136 | 136 | ||
137 | aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 137 | aer_pos = pdev->aer_cap; |
138 | /* Clear error status */ | 138 | /* Clear error status */ |
139 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); | 139 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); |
140 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); | 140 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); |
@@ -173,7 +173,7 @@ static void aer_disable_rootport(struct aer_rpc *rpc) | |||
173 | */ | 173 | */ |
174 | set_downstream_devices_error_reporting(pdev, false); | 174 | set_downstream_devices_error_reporting(pdev, false); |
175 | 175 | ||
176 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 176 | pos = pdev->aer_cap; |
177 | /* Disable Root's interrupt in response to error messages */ | 177 | /* Disable Root's interrupt in response to error messages */ |
178 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); | 178 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
179 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; | 179 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; |
@@ -200,7 +200,7 @@ irqreturn_t aer_irq(int irq, void *context) | |||
200 | unsigned long flags; | 200 | unsigned long flags; |
201 | int pos; | 201 | int pos; |
202 | 202 | ||
203 | pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR); | 203 | pos = pdev->port->aer_cap; |
204 | /* | 204 | /* |
205 | * Must lock access to Root Error Status Reg, Root Error ID Reg, | 205 | * Must lock access to Root Error Status Reg, Root Error ID Reg, |
206 | * and Root error producer/consumer index | 206 | * and Root error producer/consumer index |
@@ -338,7 +338,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) | |||
338 | u32 reg32; | 338 | u32 reg32; |
339 | int pos; | 339 | int pos; |
340 | 340 | ||
341 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 341 | pos = dev->aer_cap; |
342 | 342 | ||
343 | /* Disable Root's interrupt in response to error messages */ | 343 | /* Disable Root's interrupt in response to error messages */ |
344 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); | 344 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
@@ -391,7 +391,7 @@ static void aer_error_resume(struct pci_dev *dev) | |||
391 | pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); | 391 | pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); |
392 | 392 | ||
393 | /* Clean AER Root Error Status */ | 393 | /* Clean AER Root Error Status */ |
394 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 394 | pos = dev->aer_cap; |
395 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); | 395 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); |
396 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); | 396 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); |
397 | if (dev->error_state == pci_channel_io_normal) | 397 | if (dev->error_state == pci_channel_io_normal) |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 9fd18a08b23e..b1303b32053f 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -35,7 +35,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) | |||
35 | if (pcie_aer_get_firmware_first(dev)) | 35 | if (pcie_aer_get_firmware_first(dev)) |
36 | return -EIO; | 36 | return -EIO; |
37 | 37 | ||
38 | if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) | 38 | if (!dev->aer_cap) |
39 | return -EIO; | 39 | return -EIO; |
40 | 40 | ||
41 | return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); | 41 | return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); |
@@ -57,7 +57,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | |||
57 | int pos; | 57 | int pos; |
58 | u32 status; | 58 | u32 status; |
59 | 59 | ||
60 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 60 | pos = dev->aer_cap; |
61 | if (!pos) | 61 | if (!pos) |
62 | return -EIO; | 62 | return -EIO; |
63 | 63 | ||
@@ -78,7 +78,7 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
78 | if (!pci_is_pcie(dev)) | 78 | if (!pci_is_pcie(dev)) |
79 | return -ENODEV; | 79 | return -ENODEV; |
80 | 80 | ||
81 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 81 | pos = dev->aer_cap; |
82 | if (!pos) | 82 | if (!pos) |
83 | return -EIO; | 83 | return -EIO; |
84 | 84 | ||
@@ -97,6 +97,12 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
100 | int pci_aer_init(struct pci_dev *dev) | ||
101 | { | ||
102 | dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
103 | return pci_cleanup_aer_error_status_regs(dev); | ||
104 | } | ||
105 | |||
100 | /** | 106 | /** |
101 | * add_error_device - list device to be handled | 107 | * add_error_device - list device to be handled |
102 | * @e_info: pointer to error info | 108 | * @e_info: pointer to error info |
@@ -154,7 +160,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
154 | if (!(reg16 & PCI_EXP_AER_FLAGS)) | 160 | if (!(reg16 & PCI_EXP_AER_FLAGS)) |
155 | return false; | 161 | return false; |
156 | 162 | ||
157 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 163 | pos = dev->aer_cap; |
158 | if (!pos) | 164 | if (!pos) |
159 | return false; | 165 | return false; |
160 | 166 | ||
@@ -551,7 +557,7 @@ static void handle_error_source(struct pcie_device *aerdev, | |||
551 | * Correctable error does not need software intervention. | 557 | * Correctable error does not need software intervention. |
552 | * No need to go through error recovery process. | 558 | * No need to go through error recovery process. |
553 | */ | 559 | */ |
554 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 560 | pos = dev->aer_cap; |
555 | if (pos) | 561 | if (pos) |
556 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, | 562 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, |
557 | info->status); | 563 | info->status); |
@@ -643,7 +649,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) | |||
643 | info->status = 0; | 649 | info->status = 0; |
644 | info->tlp_header_valid = 0; | 650 | info->tlp_header_valid = 0; |
645 | 651 | ||
646 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 652 | pos = dev->aer_cap; |
647 | 653 | ||
648 | /* The device might not support AER */ | 654 | /* The device might not support AER */ |
649 | if (!pos) | 655 | if (!pos) |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 93f280df3428..157572420513 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1666,7 +1666,8 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1666 | /* Enable ACS P2P upstream forwarding */ | 1666 | /* Enable ACS P2P upstream forwarding */ |
1667 | pci_enable_acs(dev); | 1667 | pci_enable_acs(dev); |
1668 | 1668 | ||
1669 | pci_cleanup_aer_error_status_regs(dev); | 1669 | /* Advanced Error Reporting */ |
1670 | pci_aer_init(dev); | ||
1670 | } | 1671 | } |
1671 | 1672 | ||
1672 | /* | 1673 | /* |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 57bc838e0666..ab6b02763916 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -269,6 +269,9 @@ struct pci_dev { | |||
269 | unsigned int class; /* 3 bytes: (base,sub,prog-if) */ | 269 | unsigned int class; /* 3 bytes: (base,sub,prog-if) */ |
270 | u8 revision; /* PCI revision, low byte of class word */ | 270 | u8 revision; /* PCI revision, low byte of class word */ |
271 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ | 271 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ |
272 | #ifdef CONFIG_PCIEAER | ||
273 | u16 aer_cap; /* AER capability offset */ | ||
274 | #endif | ||
272 | u8 pcie_cap; /* PCIe capability offset */ | 275 | u8 pcie_cap; /* PCIe capability offset */ |
273 | u8 msi_cap; /* MSI capability offset */ | 276 | u8 msi_cap; /* MSI capability offset */ |
274 | u8 msix_cap; /* MSI-X capability offset */ | 277 | u8 msix_cap; /* MSI-X capability offset */ |
@@ -1369,9 +1372,11 @@ static inline bool pcie_aspm_support_enabled(void) { return false; } | |||
1369 | #ifdef CONFIG_PCIEAER | 1372 | #ifdef CONFIG_PCIEAER |
1370 | void pci_no_aer(void); | 1373 | void pci_no_aer(void); |
1371 | bool pci_aer_available(void); | 1374 | bool pci_aer_available(void); |
1375 | int pci_aer_init(struct pci_dev *dev); | ||
1372 | #else | 1376 | #else |
1373 | static inline void pci_no_aer(void) { } | 1377 | static inline void pci_no_aer(void) { } |
1374 | static inline bool pci_aer_available(void) { return false; } | 1378 | static inline bool pci_aer_available(void) { return false; } |
1379 | static inline int pci_aer_init(struct pci_dev *d) { return -ENODEV; } | ||
1375 | #endif | 1380 | #endif |
1376 | 1381 | ||
1377 | #ifdef CONFIG_PCIE_ECRC | 1382 | #ifdef CONFIG_PCIE_ECRC |