Esempio n. 1
0
/*
 * edac_init
 *      module initialization entry point
 */
static int __init edac_init(void)
{
	int err = 0;

	edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");

	/*
	 * Harvest and clear any boot/initialization PCI parity errors
	 *
	 * FIXME: This only clears errors logged by devices present at time of
	 *      module initialization.  We should also do an initial clear
	 *      of each newly hotplugged device.
	 */
	edac_pci_clear_parity_errors();

	err = edac_mc_sysfs_init();
	if (err)
		goto error;

	edac_debugfs_init();

	/* Setup/Initialize the workq for this core */
	err = edac_workqueue_setup();
	if (err) {
		edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
		goto error;
	}

	return 0;

error:
	return err;
}
Esempio n. 2
0
/**
 * zynqmp_ocm_edac_inject_uebitposition1_store - Set UE second bit postion
 * @dci:	Pointer to the edac device struct
 * @data:	Pointer to user data
 * @count:	read the size bytes from buffer
 *
 * Set the second bit postion for UE Error generation,we need to configure
 * any two bitpositions to inject UE Error
 * Return: Number of bytes copied.
 */
static ssize_t zynqmp_ocm_edac_inject_uebitpos1_store(
		struct edac_device_ctl_info *dci, const char *data,
		size_t count)
{
	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
	u32 mask;

	if (!data)
		return -EFAULT;

	if (kstrtou8(data, 0, &priv->ue_bitpos1))
		return -EINVAL;

	if (priv->ue_bitpos0 == priv->ue_bitpos1) {
		edac_printk(KERN_ERR, EDAC_DEVICE,
				"Bit positions should not be equal\n");
		return -EINVAL;
	}

	/* If both bit postions are referring to 32 bit data, then configure
	 * only FID0 register or if it is 64 bit data, then configure only
	 * FID1 register.
	 */
	if ((priv->ue_bitpos0 >= 0 && priv->ue_bitpos0 <= 31) &&
			(priv->ue_bitpos1 >= 0 && priv->ue_bitpos1 <= 31)) {
		mask = (1 << priv->ue_bitpos0);
		mask |= (1 << priv->ue_bitpos1);
		writel(mask, priv->baseaddr + OCM_FID0_OFST);
		writel(0, priv->baseaddr + OCM_FID1_OFST);
	} else if ((priv->ue_bitpos0 >= 32 && priv->ue_bitpos0 <= 63) &&
			(priv->ue_bitpos1 >= 32 && priv->ue_bitpos1 <= 63)) {
		mask = (1 << (priv->ue_bitpos0 - 32));
		mask |= (1 << (priv->ue_bitpos1 - 32));
		writel(mask, priv->baseaddr + OCM_FID1_OFST);
		writel(0, priv->baseaddr + OCM_FID0_OFST);
	}

	/* If one bit position is referring a bit in 32 bit data and other in
	 * 64 bit data, just configure FID0/FID1 based on uebitpos1.
	 */
	if ((priv->ue_bitpos0 >= 0 && priv->ue_bitpos0 <= 31) &&
			(priv->ue_bitpos1 >= 32 && priv->ue_bitpos1 <= 63)) {
		writel(1 << (priv->ue_bitpos1 - 32),
				priv->baseaddr + OCM_FID1_OFST);
	} else if ((priv->ue_bitpos0 >= 32 && priv->ue_bitpos0 <= 63) &&
			(priv->ue_bitpos1 >= 0 && priv->ue_bitpos1 <= 31)) {
		writel(1 << priv->ue_bitpos1,
				priv->baseaddr + OCM_FID0_OFST);
	} else {
		edac_printk(KERN_ERR, EDAC_DEVICE,
			"Bit position > 64 is not valid, Valid bits:[63:0]\n");
	}

	edac_printk(KERN_INFO, EDAC_DEVICE,
			"UE at Bit Position0: %d Bit Position1: %d\n",
			priv->ue_bitpos0, priv->ue_bitpos1);
	return count;
}
Esempio n. 3
0
/*
 * edac_init
 *      module initialization entry point
 */
static int __init edac_init(void)
{
    int err = 0;

    edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");

    /*
     * Harvest and clear any boot/initialization PCI parity errors
     *
     * FIXME: This only clears errors logged by devices present at time of
     *      module initialization.  We should also do an initial clear
     *      of each newly hotplugged device.
     */
    edac_pci_clear_parity_errors();

    /*
     * perform the registration of the /sys/devices/system/edac class object
     */
    if (edac_register_sysfs_edac_name()) {
        edac_printk(KERN_ERR, EDAC_MC,
                    "Error initializing 'edac' kobject\n");
        err = -ENODEV;
        goto error;
    }

    /*
     * now set up the mc_kset under the edac class object
     */
    err = edac_sysfs_setup_mc_kset();
    if (err)
        goto sysfs_setup_fail;

    /* Setup/Initialize the workq for this core */
    err = edac_workqueue_setup();
    if (err) {
        edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
        goto workq_fail;
    }

    return 0;

    /* Error teardown stack */
workq_fail:
    edac_sysfs_teardown_mc_kset();

sysfs_setup_fail:
    edac_unregister_sysfs_edac_name();

error:
    return err;
}
Esempio n. 4
0
static int
dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
{
	struct llcc_drv_data *drv = edev_ctl->pvt_info;
	int ret;

	ret = dump_syn_reg_values(drv, bank, err_type);
	if (ret)
		return ret;

	switch (err_type) {
	case LLCC_DRAM_CE:
		edac_device_handle_ce(edev_ctl, 0, bank,
				      "LLCC Data RAM correctable Error");
		break;
	case LLCC_DRAM_UE:
		edac_device_handle_ue(edev_ctl, 0, bank,
				      "LLCC Data RAM uncorrectable Error");
		break;
	case LLCC_TRAM_CE:
		edac_device_handle_ce(edev_ctl, 0, bank,
				      "LLCC Tag RAM correctable Error");
		break;
	case LLCC_TRAM_UE:
		edac_device_handle_ue(edev_ctl, 0, bank,
				      "LLCC Tag RAM uncorrectable Error");
		break;
	default:
		ret = -EINVAL;
		edac_printk(KERN_CRIT, EDAC_LLCC, "Unexpected error type: %d\n",
			    err_type);
	}

	return ret;
}
Esempio n. 5
0
/**
 * zynqmp_ocm_edac_inject_cebitpos_store - Set CE bit postion
 * @dci:	Pointer to the edac device struct
 * @data:	Pointer to user data
 * @count:	read the size bytes from buffer
 *
 * Set any one bit to inject CE error
 * Return: Number of bytes copied.
 */
static ssize_t zynqmp_ocm_edac_inject_cebitpos_store(
		struct edac_device_ctl_info *dci, const char *data,
		size_t count)
{
	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;

	if (!data)
		return -EFAULT;

	if (kstrtou8(data, 0, &priv->ce_bitpos))
		return -EINVAL;

	if (priv->ce_bitpos >= 0 && priv->ce_bitpos <= 31) {
		writel(1 << priv->ce_bitpos, priv->baseaddr + OCM_FID0_OFST);
		writel(0, priv->baseaddr + OCM_FID1_OFST);
	} else if (priv->ce_bitpos >= 32 && priv->ce_bitpos <= 63) {
		writel(1 << (priv->ce_bitpos - 32),
				priv->baseaddr + OCM_FID1_OFST);
		writel(0, priv->baseaddr + OCM_FID0_OFST);
	} else {
		edac_printk(KERN_ERR, EDAC_DEVICE,
			"Bit number > 64 is not valid\n");
	}

	return count;
}
Esempio n. 6
0
static irqreturn_t
llcc_ecc_irq_handler(int irq, void *edev_ctl)
{
	struct edac_device_ctl_info *edac_dev_ctl = edev_ctl;
	struct llcc_drv_data *drv = edac_dev_ctl->pvt_info;
	irqreturn_t irq_rc = IRQ_NONE;
	u32 drp_error, trp_error, i;
	int ret;

	/* Iterate over the banks and look for Tag RAM or Data RAM errors */
	for (i = 0; i < drv->num_banks; i++) {
		ret = regmap_read(drv->regmap,
				  drv->offsets[i] + DRP_INTERRUPT_STATUS,
				  &drp_error);

		if (!ret && (drp_error & SB_ECC_ERROR)) {
			edac_printk(KERN_CRIT, EDAC_LLCC,
				    "Single Bit Error detected in Data RAM\n");
			ret = dump_syn_reg(edev_ctl, LLCC_DRAM_CE, i);
		} else if (!ret && (drp_error & DB_ECC_ERROR)) {
			edac_printk(KERN_CRIT, EDAC_LLCC,
				    "Double Bit Error detected in Data RAM\n");
			ret = dump_syn_reg(edev_ctl, LLCC_DRAM_UE, i);
		}
		if (!ret)
			irq_rc = IRQ_HANDLED;

		ret = regmap_read(drv->regmap,
				  drv->offsets[i] + TRP_INTERRUPT_0_STATUS,
				  &trp_error);

		if (!ret && (trp_error & SB_ECC_ERROR)) {
			edac_printk(KERN_CRIT, EDAC_LLCC,
				    "Single Bit Error detected in Tag RAM\n");
			ret = dump_syn_reg(edev_ctl, LLCC_TRAM_CE, i);
		} else if (!ret && (trp_error & DB_ECC_ERROR)) {
			edac_printk(KERN_CRIT, EDAC_LLCC,
				    "Double Bit Error detected in Tag RAM\n");
			ret = dump_syn_reg(edev_ctl, LLCC_TRAM_UE, i);
		}
		if (!ret)
			irq_rc = IRQ_HANDLED;
	}

	return irq_rc;
}
Esempio n. 7
0
/* Dump Syndrome registers data for Tag RAM, Data RAM bit errors*/
static int
dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
{
	struct llcc_edac_reg_data reg_data = edac_reg_data[err_type];
	int err_cnt, err_ways, ret, i;
	u32 synd_reg, synd_val;

	for (i = 0; i < reg_data.reg_cnt; i++) {
		synd_reg = reg_data.synd_reg + (i * 4);
		ret = regmap_read(drv->regmap, drv->offsets[bank] + synd_reg,
				  &synd_val);
		if (ret)
			goto clear;

		edac_printk(KERN_CRIT, EDAC_LLCC, "%s: ECC_SYN%d: 0x%8x\n",
			    reg_data.name, i, synd_val);
	}

	ret = regmap_read(drv->regmap,
			  drv->offsets[bank] + reg_data.count_status_reg,
			  &err_cnt);
	if (ret)
		goto clear;

	err_cnt &= reg_data.count_mask;
	err_cnt >>= reg_data.count_shift;
	edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error count: 0x%4x\n",
		    reg_data.name, err_cnt);

	ret = regmap_read(drv->regmap,
			  drv->offsets[bank] + reg_data.ways_status_reg,
			  &err_ways);
	if (ret)
		goto clear;

	err_ways &= reg_data.ways_mask;
	err_ways >>= reg_data.ways_shift;

	edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error ways: 0x%4x\n",
		    reg_data.name, err_ways);

clear:
	return qcom_llcc_clear_error_status(err_type, drv);
}
Esempio n. 8
0
/*
 * ->get_sdram_scrub_rate() return value semantics same as above.
 */
static ssize_t mci_sdram_scrub_rate_show(struct device *dev,
					 struct device_attribute *mattr,
					 char *data)
{
	struct mem_ctl_info *mci = to_mci(dev);
	int bandwidth = 0;

	bandwidth = mci->get_sdram_scrub_rate(mci);
	if (bandwidth < 0) {
		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
		return bandwidth;
	}

	return sprintf(data, "%d\n", bandwidth);
}
Esempio n. 9
0
/**
 * zynqmp_ocm_edac_inject_uebitpos0_store - set UE bit position0
 * @dci:	Pointer to the edac device struct
 * @data:	Pointer to user data
 * @count:	read the size bytes from buffer
 *
 * Set the first bit postion for UE Error generation,we need to configure
 * any two bitpositions to inject UE Error
 * Return: Number of bytes copied.
 */
static ssize_t zynqmp_ocm_edac_inject_uebitpos0_store(
		struct edac_device_ctl_info *dci,
		const char *data, size_t count)
{
	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;

	if (!data)
		return -EFAULT;

	if (kstrtou8(data, 0, &priv->ue_bitpos0))
		return -EINVAL;

	if (priv->ue_bitpos0 >= 0 && priv->ue_bitpos0 <= 31)
		writel(1 << priv->ue_bitpos0, priv->baseaddr + OCM_FID0_OFST);
	else if (priv->ue_bitpos0 >= 32 && priv->ue_bitpos0 <= 63)
		writel(1 << (priv->ue_bitpos0 - 32),
				priv->baseaddr + OCM_FID1_OFST);
	else
		edac_printk(KERN_ERR, EDAC_DEVICE,
			"Bit position > 64 is not valid\n");
	edac_printk(KERN_INFO, EDAC_DEVICE,
			"Set another bit position for UE\n");
	return count;
}
Esempio n. 10
0
/* Memory scrubbing interface:
 *
 * A MC driver can limit the scrubbing bandwidth based on the CPU type.
 * Therefore, ->set_sdram_scrub_rate should be made to return the actual
 * bandwidth that is accepted or 0 when scrubbing is to be disabled.
 *
 * Negative value still means that an error has occurred while setting
 * the scrub rate.
 */
static ssize_t mci_sdram_scrub_rate_store(struct device *dev,
					  struct device_attribute *mattr,
					  const char *data, size_t count)
{
	struct mem_ctl_info *mci = to_mci(dev);
	unsigned long bandwidth = 0;
	int new_bw = 0;

	if (kstrtoul(data, 10, &bandwidth) < 0)
		return -EINVAL;

	new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
	if (new_bw < 0) {
		edac_printk(KERN_WARNING, EDAC_MC,
			    "Error setting scrub rate to: %lu\n", bandwidth);
		return -EINVAL;
	}

	return count;
}
Esempio n. 11
0
/* Clear the error interrupt and counter registers */
static int
qcom_llcc_clear_error_status(int err_type, struct llcc_drv_data *drv)
{
	int ret = 0;

	switch (err_type) {
	case LLCC_DRAM_CE:
	case LLCC_DRAM_UE:
		ret = regmap_write(drv->bcast_regmap, DRP_INTERRUPT_CLEAR,
				   DRP_TRP_INT_CLEAR);
		if (ret)
			return ret;

		ret = regmap_write(drv->bcast_regmap, DRP_ECC_ERROR_CNTR_CLEAR,
				   DRP_TRP_CNT_CLEAR);
		if (ret)
			return ret;
		break;
	case LLCC_TRAM_CE:
	case LLCC_TRAM_UE:
		ret = regmap_write(drv->bcast_regmap, TRP_INTERRUPT_0_CLEAR,
				   DRP_TRP_INT_CLEAR);
		if (ret)
			return ret;

		ret = regmap_write(drv->bcast_regmap, TRP_ECC_ERROR_CNTR_CLEAR,
				   DRP_TRP_CNT_CLEAR);
		if (ret)
			return ret;
		break;
	default:
		ret = -EINVAL;
		edac_printk(KERN_CRIT, EDAC_LLCC, "Unexpected error type: %d\n",
			    err_type);
	}
	return ret;
}
Esempio n. 12
0
/*
 *  PCI Parity polling
 *
 *	Fucntion to retrieve the current parity status
 *	and decode it
 *
 */
static void edac_pci_dev_parity_test(struct pci_dev *dev)
{
	unsigned long flags;
	u16 status;
	u8 header_type;

	/* stop any interrupts until we can acquire the status */
	local_irq_save(flags);

	/* read the STATUS register on this device */
	status = get_pci_parity_status(dev, 0);

	/* read the device TYPE, looking for bridges */
	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);

	local_irq_restore(flags);

	debugf4("PCI STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));

	/* check the status reg for errors on boards NOT marked as broken
	 * if broken, we cannot trust any of the status bits
	 */
	if (status && !dev->broken_parity_status) {
		if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) {
			edac_printk(KERN_CRIT, EDAC_PCI,
				"Signaled System Error on %s\n",
				pci_name(dev));
			atomic_inc(&pci_nonparity_count);
		}

		if (status & (PCI_STATUS_PARITY)) {
			edac_printk(KERN_CRIT, EDAC_PCI,
				"Master Data Parity Error on %s\n",
				pci_name(dev));

			atomic_inc(&pci_parity_count);
		}

		if (status & (PCI_STATUS_DETECTED_PARITY)) {
			edac_printk(KERN_CRIT, EDAC_PCI,
				"Detected Parity Error on %s\n",
				pci_name(dev));

			atomic_inc(&pci_parity_count);
		}
	}


	debugf4("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev_name(&dev->dev));

	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
		/* On bridges, need to examine secondary status register  */
		status = get_pci_parity_status(dev, 1);

		debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev_name(&dev->dev));

		/* check the secondary status reg for errors,
		 * on NOT broken boards
		 */
		if (status && !dev->broken_parity_status) {
			if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) {
				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
					"Signaled System Error on %s\n",
					pci_name(dev));
				atomic_inc(&pci_nonparity_count);
			}

			if (status & (PCI_STATUS_PARITY)) {
				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
					"Master Data Parity Error on "
					"%s\n", pci_name(dev));

				atomic_inc(&pci_parity_count);
			}

			if (status & (PCI_STATUS_DETECTED_PARITY)) {
				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
					"Detected Parity Error on %s\n",
					pci_name(dev));

				atomic_inc(&pci_parity_count);
			}
		}
	}
}
Esempio n. 13
0
/*
 *  PCI Parity polling
 *
 */
static void edac_pci_dev_parity_test(struct pci_dev *dev)
{
	u16 status;
	u8  header_type;

	/* read the STATUS register on this device
	 */
	status = get_pci_parity_status(dev, 0);

	debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );

	/* check the status reg for errors */
	if (status) {
		if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
			edac_printk(KERN_CRIT, EDAC_PCI,
				"Signaled System Error on %s\n",
				pci_name(dev));

		if (status & (PCI_STATUS_PARITY)) {
			edac_printk(KERN_CRIT, EDAC_PCI,
				"Master Data Parity Error on %s\n",
				pci_name(dev));

			atomic_inc(&pci_parity_count);
		}

		if (status & (PCI_STATUS_DETECTED_PARITY)) {
			edac_printk(KERN_CRIT, EDAC_PCI,
				"Detected Parity Error on %s\n",
				pci_name(dev));

			atomic_inc(&pci_parity_count);
		}
	}

	/* read the device TYPE, looking for bridges */
	pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);

	debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );

	if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
		/* On bridges, need to examine secondary status register  */
		status = get_pci_parity_status(dev, 1);

		debugf2("PCI SEC_STATUS= 0x%04x %s\n",
				status, dev->dev.bus_id );

		/* check the secondary status reg for errors */
		if (status) {
			if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
					"Signaled System Error on %s\n",
					pci_name(dev));

			if (status & (PCI_STATUS_PARITY)) {
				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
					"Master Data Parity Error on "
					"%s\n", pci_name(dev));

				atomic_inc(&pci_parity_count);
			}

			if (status & (PCI_STATUS_DETECTED_PARITY)) {
				edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
					"Detected Parity Error on %s\n",
					pci_name(dev));

				atomic_inc(&pci_parity_count);
			}
		}
	}
}
Esempio n. 14
0
/**
 * zynqmp_ocm_edac_probe - Check controller and bind driver
 * @pdev:	Pointer to the platform_device struct
 *
 * Probes a specific controller instance for binding with the driver.
 *
 * Return: 0 if the controller instance was successfully bound to the
 * driver; otherwise, < 0 on error.
 */
static int zynqmp_ocm_edac_probe(struct platform_device *pdev)
{
	struct edac_device_ctl_info *dci;
	struct zynqmp_ocm_edac_priv *priv;
	int irq, status;
	struct resource *res;
	void __iomem *baseaddr;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	baseaddr = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(baseaddr))
		return PTR_ERR(baseaddr);

	if (!zynqmp_ocm_edac_get_eccstate(baseaddr)) {
		edac_printk(KERN_INFO, EDAC_DEVICE,
				"ECC not enabled - Disabling EDAC driver\n");
		return -ENXIO;
	}

	dci = edac_device_alloc_ctl_info(sizeof(*priv), ZYNQMP_OCM_EDAC_STRING,
			1, ZYNQMP_OCM_EDAC_STRING, 1, 0, NULL, 0, 0);
	if (!dci) {
		edac_printk(KERN_ERR, EDAC_DEVICE,
				"Unable to allocate EDAC device\n");
		return -ENOMEM;
	}

	priv = dci->pvt_info;
	platform_set_drvdata(pdev, dci);
	dci->dev = &pdev->dev;
	priv->baseaddr = baseaddr;
	dci->mod_name = pdev->dev.driver->name;
	dci->ctl_name = ZYNQMP_OCM_EDAC_STRING;
	dci->dev_name = dev_name(&pdev->dev);

	zynqmp_set_ocm_edac_sysfs_attributes(dci);
	if (edac_device_add_device(dci))
		goto free_dev_ctl;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		edac_printk(KERN_ERR, EDAC_DEVICE,
				"No irq %d in DT\n", irq);
		return irq;
	}

	status = devm_request_irq(&pdev->dev, irq,
		zynqmp_ocm_edac_intr_handler,
		0, dev_name(&pdev->dev), dci);
	if (status < 0) {
		edac_printk(KERN_ERR, EDAC_DEVICE, "Failed to request Irq\n");
		goto free_edac_dev;
	}

	writel(OCM_CEUE_MASK, priv->baseaddr + OCM_IEN_OFST);

	return 0;

free_edac_dev:
	edac_device_del_device(&pdev->dev);
free_dev_ctl:
	edac_device_free_ctl_info(dci);

	return -1;
}