static inline void aer_process_err_devices(struct pcie_device *p_device, struct aer_err_info *e_info) { int i; /* Report all before handle them, not to lost records by reset etc. */ for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { if (get_device_error_info(e_info->dev[i], e_info)) aer_print_error(e_info->dev[i], e_info); } for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { if (get_device_error_info(e_info->dev[i], e_info)) handle_error_source(p_device, e_info->dev[i], e_info); } }
/** * aer_isr_one_error - consume an error detected by root port * @p_device: pointer to error root port service device * @e_src: pointer to an error source **/ static void aer_isr_one_error(struct pcie_device *p_device, struct aer_err_source *e_src) { struct device *s_device; struct aer_err_info e_info = {0, 0, 0,}; int i; u16 id; /* * There is a possibility that both correctable error and * uncorrectable error being logged. Report correctable error first. */ for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) { if (i > 4) break; if (!(e_src->status & i)) continue; /* Init comprehensive error information */ if (i & PCI_ERR_ROOT_COR_RCV) { id = ERR_COR_ID(e_src->id); e_info.severity = AER_CORRECTABLE; } else { id = ERR_UNCOR_ID(e_src->id); e_info.severity = ((e_src->status >> 6) & 1); } if (e_src->status & (PCI_ERR_ROOT_MULTI_COR_RCV | PCI_ERR_ROOT_MULTI_UNCOR_RCV)) e_info.flags |= AER_MULTI_ERROR_VALID_FLAG; if (!(s_device = find_source_device(p_device->port, id))) { printk(KERN_DEBUG "%s->can't find device of ID%04x\n", __FUNCTION__, id); continue; } if (get_device_error_info(to_pci_dev(s_device), &e_info) == AER_SUCCESS) { aer_print_error(to_pci_dev(s_device), &e_info); handle_error_source(p_device, to_pci_dev(s_device), e_info); } } }
static inline void aer_process_err_devices(struct pcie_device *p_device, struct aer_err_info *e_info) { int i; if (!e_info->dev[0]) { dev_printk(KERN_DEBUG, &p_device->port->dev, "can't find device of ID%04x\n", e_info->id); } /* Report all before handle them, not to lost records by reset etc. */ for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { if (get_device_error_info(e_info->dev[i], e_info)) aer_print_error(e_info->dev[i], e_info); } for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) { if (get_device_error_info(e_info->dev[i], e_info)) handle_error_source(p_device, e_info->dev[i], e_info); } }
static irqreturn_t dpc_handler(int irq, void *context) { struct aer_err_info info; struct dpc_dev *dpc = context; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; u16 cap = dpc->cap_pos, status, source, reason, ext_reason; pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &status); pci_read_config_word(pdev, cap + PCI_EXP_DPC_SOURCE_ID, &source); dev_info(dev, "DPC containment event, status:%#06x source:%#06x\n", status, source); reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN) >> 1; ext_reason = (status & PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT) >> 5; dev_warn(dev, "DPC %s detected\n", (reason == 0) ? "unmasked uncorrectable error" : (reason == 1) ? "ERR_NONFATAL" : (reason == 2) ? "ERR_FATAL" : (ext_reason == 0) ? "RP PIO error" : (ext_reason == 1) ? "software trigger" : "reserved error"); /* show RP PIO error detail information */ if (dpc->rp_extensions && reason == 3 && ext_reason == 0) dpc_process_rp_pio_error(dpc); else if (reason == 0 && dpc_get_aer_uncorrect_severity(pdev, &info) && aer_get_device_error_info(pdev, &info)) { aer_print_error(pdev, &info); pci_cleanup_aer_uncorrect_error_status(pdev); pci_aer_clear_fatal_status(pdev); } /* We configure DPC so it only triggers on ERR_FATAL */ pcie_do_recovery(pdev, pci_channel_io_frozen, PCIE_PORT_SERVICE_DPC); return IRQ_HANDLED; }