예제 #1
0
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);
	}
}
예제 #2
0
파일: aerdrv_core.c 프로젝트: cilynx/dd-wrt
/**
 * 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);
		}
	}
}
예제 #3
0
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);
    }
}
예제 #4
0
파일: dpc.c 프로젝트: Anjali05/linux
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;
}