aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index f5eb69f532e7..ca140580199c 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -208,6 +208,9 @@ static int find_device_iter(struct pci_dev *dev, void *data)
208 * Return true if found. 208 * Return true if found.
209 * 209 *
210 * Invoked by DPC when error is detected at the Root Port. 210 * Invoked by DPC when error is detected at the Root Port.
211 * Caller of this function must set id, severity, and multi_error_valid of
212 * struct aer_err_info pointed by @e_info properly. This function must fill
213 * e_info->error_dev_num and e_info->dev[], based on the given information.
211 */ 214 */
212static bool find_source_device(struct pci_dev *parent, 215static bool find_source_device(struct pci_dev *parent,
213 struct aer_err_info *e_info) 216 struct aer_err_info *e_info)
@@ -215,6 +218,9 @@ static bool find_source_device(struct pci_dev *parent,
215 struct pci_dev *dev = parent; 218 struct pci_dev *dev = parent;
216 int result; 219 int result;
217 220
221 /* Must reset in this function */
222 e_info->error_dev_num = 0;
223
218 /* Is Root Port an agent that sends error message? */ 224 /* Is Root Port an agent that sends error message? */
219 result = find_device_iter(dev, e_info); 225 result = find_device_iter(dev, e_info);
220 if (result) 226 if (result)
@@ -580,11 +586,14 @@ static struct aer_err_source *get_e_source(struct aer_rpc *rpc)
580 * @info: pointer to structure to store the error record 586 * @info: pointer to structure to store the error record
581 * 587 *
582 * Return 1 on success, 0 on error. 588 * Return 1 on success, 0 on error.
589 *
590 * Note that @info is reused among all error devices. Clear fields properly.
583 */ 591 */
584static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) 592static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
585{ 593{
586 int pos, temp; 594 int pos, temp;
587 595
596 /* Must reset in this function */
588 info->status = 0; 597 info->status = 0;
589 info->tlp_header_valid = 0; 598 info->tlp_header_valid = 0;
590 599
@@ -657,11 +666,10 @@ static void aer_isr_one_error(struct pcie_device *p_device,
657 struct aer_err_source *e_src) 666 struct aer_err_source *e_src)
658{ 667{
659 struct aer_err_info *e_info; 668 struct aer_err_info *e_info;
660 int i;
661 669
662 /* struct aer_err_info might be big, so we allocate it with slab */ 670 /* struct aer_err_info might be big, so we allocate it with slab */
663 e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); 671 e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL);
664 if (e_info == NULL) { 672 if (!e_info) {
665 dev_printk(KERN_DEBUG, &p_device->port->dev, 673 dev_printk(KERN_DEBUG, &p_device->port->dev,
666 "Can't allocate mem when processing AER errors\n"); 674 "Can't allocate mem when processing AER errors\n");
667 return; 675 return;
@@ -671,26 +679,33 @@ static void aer_isr_one_error(struct pcie_device *p_device,
671 * There is a possibility that both correctable error and 679 * There is a possibility that both correctable error and
672 * uncorrectable error being logged. Report correctable error first. 680 * uncorrectable error being logged. Report correctable error first.
673 */ 681 */
674 for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) { 682 if (e_src->status & PCI_ERR_ROOT_COR_RCV) {
675 if (i > 4) 683 e_info->id = ERR_COR_ID(e_src->id);
676 break; 684 e_info->severity = AER_CORRECTABLE;
677 if (!(e_src->status & i)) 685
678 continue; 686 if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV)
679 687 e_info->multi_error_valid = 1;
680 memset(e_info, 0, sizeof(struct aer_err_info)); 688 else
681 689 e_info->multi_error_valid = 0;
682 /* Init comprehensive error information */ 690
683 if (i & PCI_ERR_ROOT_COR_RCV) { 691 aer_print_port_info(p_device->port, e_info);
684 e_info->id = ERR_COR_ID(e_src->id); 692
685 e_info->severity = AER_CORRECTABLE; 693 if (find_source_device(p_device->port, e_info))
686 } else { 694 aer_process_err_devices(p_device, e_info);
687 e_info->id = ERR_UNCOR_ID(e_src->id); 695 }
688 e_info->severity = ((e_src->status >> 6) & 1); 696
689 } 697 if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) {
690 if (e_src->status & 698 e_info->id = ERR_UNCOR_ID(e_src->id);
691 (PCI_ERR_ROOT_MULTI_COR_RCV | 699
692 PCI_ERR_ROOT_MULTI_UNCOR_RCV)) 700 if (e_src->status & PCI_ERR_ROOT_FATAL_RCV)
701 e_info->severity = AER_FATAL;
702 else
703 e_info->severity = AER_NONFATAL;
704
705 if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV)
693 e_info->multi_error_valid = 1; 706 e_info->multi_error_valid = 1;
707 else
708 e_info->multi_error_valid = 0;
694 709
695 aer_print_port_info(p_device->port, e_info); 710 aer_print_port_info(p_device->port, e_info);
696 711