aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2016-10-03 10:42:57 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-10-03 10:42:57 -0400
commit4dc2db096a9f7c0316bafc18ee00d89e0acf4ebf (patch)
tree99563a111f0f5c0b2d8e90acfe840c7db1d0c603 /drivers/pci/pcie
parent9e18ad98ca71ca0cfcadf633547409829773f36a (diff)
parent6b20f728549030056402d7f68ea670eea1eb8198 (diff)
Merge branch 'pci/aer' into next
* pci/aer: PCI/AER: Fix aer_probe() kernel-doc comment PCI/AER: Cache capability position PCI/AER: Avoid memory allocation in interrupt handling path ACPI / APEI: Send correct severity to calculate AER severity PCI/AER: Remove duplicate AER severity translation PCI/AER: Remove aerdriver.forceload kernel parameter PCI/AER: Remove aerdriver.nosourceid kernel parameter x86/PCI: VMD: Add quirk for AER to ignore source ID PCI/AER: Add bus flag to skip source ID matching Conflicts: drivers/pci/probe.c
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c18
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h9
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c61
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c6
4 files changed, 28 insertions, 66 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 49805a48b81c..139150b2bdfd 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -66,7 +66,7 @@ static int pcie_aer_disable;
66 66
67void pci_no_aer(void) 67void pci_no_aer(void)
68{ 68{
69 pcie_aer_disable = 1; /* has priority over 'forceload' */ 69 pcie_aer_disable = 1;
70} 70}
71 71
72bool pci_aer_available(void) 72bool pci_aer_available(void)
@@ -130,7 +130,7 @@ static void aer_enable_rootport(struct aer_rpc *rpc)
130 pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, 130 pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
131 SYSTEM_ERROR_INTR_ON_MESG_MASK); 131 SYSTEM_ERROR_INTR_ON_MESG_MASK);
132 132
133 aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); 133 aer_pos = pdev->aer_cap;
134 /* Clear error status */ 134 /* Clear error status */
135 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32); 135 pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
136 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); 136 pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
@@ -169,7 +169,7 @@ static void aer_disable_rootport(struct aer_rpc *rpc)
169 */ 169 */
170 set_downstream_devices_error_reporting(pdev, false); 170 set_downstream_devices_error_reporting(pdev, false);
171 171
172 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); 172 pos = pdev->aer_cap;
173 /* Disable Root's interrupt in response to error messages */ 173 /* Disable Root's interrupt in response to error messages */
174 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32); 174 pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
175 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; 175 reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
@@ -196,7 +196,7 @@ irqreturn_t aer_irq(int irq, void *context)
196 unsigned long flags; 196 unsigned long flags;
197 int pos; 197 int pos;
198 198
199 pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR); 199 pos = pdev->port->aer_cap;
200 /* 200 /*
201 * Must lock access to Root Error Status Reg, Root Error ID Reg, 201 * Must lock access to Root Error Status Reg, Root Error ID Reg,
202 * and Root error producer/consumer index 202 * and Root error producer/consumer index
@@ -290,7 +290,6 @@ static void aer_remove(struct pcie_device *dev)
290/** 290/**
291 * aer_probe - initialize resources 291 * aer_probe - initialize resources
292 * @dev: pointer to the pcie_dev data structure 292 * @dev: pointer to the pcie_dev data structure
293 * @id: pointer to the service id data structure
294 * 293 *
295 * Invoked when PCI Express bus loads AER service driver. 294 * Invoked when PCI Express bus loads AER service driver.
296 */ 295 */
@@ -300,11 +299,6 @@ static int aer_probe(struct pcie_device *dev)
300 struct aer_rpc *rpc; 299 struct aer_rpc *rpc;
301 struct device *device = &dev->device; 300 struct device *device = &dev->device;
302 301
303 /* Init */
304 status = aer_init(dev);
305 if (status)
306 return status;
307
308 /* Alloc rpc data structure */ 302 /* Alloc rpc data structure */
309 rpc = aer_alloc_rpc(dev); 303 rpc = aer_alloc_rpc(dev);
310 if (!rpc) { 304 if (!rpc) {
@@ -339,7 +333,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
339 u32 reg32; 333 u32 reg32;
340 int pos; 334 int pos;
341 335
342 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 336 pos = dev->aer_cap;
343 337
344 /* Disable Root's interrupt in response to error messages */ 338 /* Disable Root's interrupt in response to error messages */
345 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32); 339 pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
@@ -392,7 +386,7 @@ static void aer_error_resume(struct pci_dev *dev)
392 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); 386 pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
393 387
394 /* Clean AER Root Error Status */ 388 /* Clean AER Root Error Status */
395 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 389 pos = dev->aer_cap;
396 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); 390 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
397 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); 391 pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
398 if (dev->error_state == pci_channel_io_normal) 392 if (dev->error_state == pci_channel_io_normal)
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 945c939a86c5..d51e4a57b190 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -60,6 +60,7 @@ struct aer_rpc {
60 struct pcie_device *rpd; /* Root Port device */ 60 struct pcie_device *rpd; /* Root Port device */
61 struct work_struct dpc_handler; 61 struct work_struct dpc_handler;
62 struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; 62 struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
63 struct aer_err_info e_info;
63 unsigned short prod_idx; /* Error Producer Index */ 64 unsigned short prod_idx; /* Error Producer Index */
64 unsigned short cons_idx; /* Error Consumer Index */ 65 unsigned short cons_idx; /* Error Consumer Index */
65 int isr; 66 int isr;
@@ -105,7 +106,6 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
105} 106}
106 107
107extern struct bus_type pcie_port_bus_type; 108extern struct bus_type pcie_port_bus_type;
108int aer_init(struct pcie_device *dev);
109void aer_isr(struct work_struct *work); 109void aer_isr(struct work_struct *work);
110void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); 110void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
111void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); 111void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
@@ -121,11 +121,4 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
121 return 0; 121 return 0;
122} 122}
123#endif 123#endif
124
125static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev,
126 int enable)
127{
128 pci_dev->__aer_firmware_first = !!enable;
129 pci_dev->__aer_firmware_first_valid = 1;
130}
131#endif /* _AERDRV_H_ */ 124#endif /* _AERDRV_H_ */
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 521e39c1b66d..b1303b32053f 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -27,11 +27,6 @@
27#include <linux/kfifo.h> 27#include <linux/kfifo.h>
28#include "aerdrv.h" 28#include "aerdrv.h"
29 29
30static bool forceload;
31static bool nosourceid;
32module_param(forceload, bool, 0);
33module_param(nosourceid, bool, 0);
34
35#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ 30#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
36 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) 31 PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
37 32
@@ -40,7 +35,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev)
40 if (pcie_aer_get_firmware_first(dev)) 35 if (pcie_aer_get_firmware_first(dev))
41 return -EIO; 36 return -EIO;
42 37
43 if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) 38 if (!dev->aer_cap)
44 return -EIO; 39 return -EIO;
45 40
46 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);
@@ -62,7 +57,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
62 int pos; 57 int pos;
63 u32 status; 58 u32 status;
64 59
65 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 60 pos = dev->aer_cap;
66 if (!pos) 61 if (!pos)
67 return -EIO; 62 return -EIO;
68 63
@@ -83,7 +78,7 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
83 if (!pci_is_pcie(dev)) 78 if (!pci_is_pcie(dev))
84 return -ENODEV; 79 return -ENODEV;
85 80
86 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 81 pos = dev->aer_cap;
87 if (!pos) 82 if (!pos)
88 return -EIO; 83 return -EIO;
89 84
@@ -102,6 +97,12 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
102 return 0; 97 return 0;
103} 98}
104 99
100int 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
105/** 106/**
106 * add_error_device - list device to be handled 107 * add_error_device - list device to be handled
107 * @e_info: pointer to error info 108 * @e_info: pointer to error info
@@ -132,7 +133,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
132 * When bus id is equal to 0, it might be a bad id 133 * When bus id is equal to 0, it might be a bad id
133 * reported by root port. 134 * reported by root port.
134 */ 135 */
135 if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { 136 if ((PCI_BUS_NUM(e_info->id) != 0) &&
137 !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
136 /* Device ID match? */ 138 /* Device ID match? */
137 if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) 139 if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
138 return true; 140 return true;
@@ -144,10 +146,10 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
144 146
145 /* 147 /*
146 * When either 148 * When either
147 * 1) nosourceid==y; 149 * 1) bus id is equal to 0. Some ports might lose the bus
148 * 2) bus id is equal to 0. Some ports might lose the bus
149 * id of error source id; 150 * id of error source id;
150 * 3) There are multiple errors and prior id comparing fails; 151 * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
152 * 3) There are multiple errors and prior ID comparing fails;
151 * We check AER status registers to find possible reporter. 153 * We check AER status registers to find possible reporter.
152 */ 154 */
153 if (atomic_read(&dev->enable_cnt) == 0) 155 if (atomic_read(&dev->enable_cnt) == 0)
@@ -158,7 +160,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
158 if (!(reg16 & PCI_EXP_AER_FLAGS)) 160 if (!(reg16 & PCI_EXP_AER_FLAGS))
159 return false; 161 return false;
160 162
161 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 163 pos = dev->aer_cap;
162 if (!pos) 164 if (!pos)
163 return false; 165 return false;
164 166
@@ -555,7 +557,7 @@ static void handle_error_source(struct pcie_device *aerdev,
555 * Correctable error does not need software intervention. 557 * Correctable error does not need software intervention.
556 * No need to go through error recovery process. 558 * No need to go through error recovery process.
557 */ 559 */
558 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 560 pos = dev->aer_cap;
559 if (pos) 561 if (pos)
560 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, 562 pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
561 info->status); 563 info->status);
@@ -647,7 +649,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
647 info->status = 0; 649 info->status = 0;
648 info->tlp_header_valid = 0; 650 info->tlp_header_valid = 0;
649 651
650 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); 652 pos = dev->aer_cap;
651 653
652 /* The device might not support AER */ 654 /* The device might not support AER */
653 if (!pos) 655 if (!pos)
@@ -715,15 +717,8 @@ static inline void aer_process_err_devices(struct pcie_device *p_device,
715static void aer_isr_one_error(struct pcie_device *p_device, 717static void aer_isr_one_error(struct pcie_device *p_device,
716 struct aer_err_source *e_src) 718 struct aer_err_source *e_src)
717{ 719{
718 struct aer_err_info *e_info; 720 struct aer_rpc *rpc = get_service_data(p_device);
719 721 struct aer_err_info *e_info = &rpc->e_info;
720 /* struct aer_err_info might be big, so we allocate it with slab */
721 e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL);
722 if (!e_info) {
723 dev_printk(KERN_DEBUG, &p_device->port->dev,
724 "Can't allocate mem when processing AER errors\n");
725 return;
726 }
727 722
728 /* 723 /*
729 * There is a possibility that both correctable error and 724 * There is a possibility that both correctable error and
@@ -762,8 +757,6 @@ static void aer_isr_one_error(struct pcie_device *p_device,
762 if (find_source_device(p_device->port, e_info)) 757 if (find_source_device(p_device->port, e_info))
763 aer_process_err_devices(p_device, e_info); 758 aer_process_err_devices(p_device, e_info);
764 } 759 }
765
766 kfree(e_info);
767} 760}
768 761
769/** 762/**
@@ -812,19 +805,3 @@ void aer_isr(struct work_struct *work)
812 aer_isr_one_error(p_device, &e_src); 805 aer_isr_one_error(p_device, &e_src);
813 mutex_unlock(&rpc->rpc_mutex); 806 mutex_unlock(&rpc->rpc_mutex);
814} 807}
815
816/**
817 * aer_init - provide AER initialization
818 * @dev: pointer to AER pcie device
819 *
820 * Invoked when AER service driver is loaded.
821 */
822int aer_init(struct pcie_device *dev)
823{
824 if (forceload) {
825 dev_printk(KERN_DEBUG, &dev->device,
826 "aerdrv forceload requested.\n");
827 pcie_aer_force_firmware_first(dev->port, 0);
828 }
829 return 0;
830}
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index 167fe411ce2e..54c4b691e51f 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -219,15 +219,13 @@ int cper_severity_to_aer(int cper_severity)
219} 219}
220EXPORT_SYMBOL_GPL(cper_severity_to_aer); 220EXPORT_SYMBOL_GPL(cper_severity_to_aer);
221 221
222void cper_print_aer(struct pci_dev *dev, int cper_severity, 222void cper_print_aer(struct pci_dev *dev, int aer_severity,
223 struct aer_capability_regs *aer) 223 struct aer_capability_regs *aer)
224{ 224{
225 int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; 225 int layer, agent, status_strs_size, tlp_header_valid = 0;
226 u32 status, mask; 226 u32 status, mask;
227 const char **status_strs; 227 const char **status_strs;
228 228
229 aer_severity = cper_severity_to_aer(cper_severity);
230
231 if (aer_severity == AER_CORRECTABLE) { 229 if (aer_severity == AER_CORRECTABLE) {
232 status = aer->cor_status; 230 status = aer->cor_status;
233 mask = aer->cor_mask; 231 mask = aer->cor_mask;