Re: [PATCH v3 4/4] edac: xilinx: Add EDAC support for Versal XilSem

"Pandey, Radhey Shyam" <[email protected]>
Newsgroups org.kernel.vger.linux-edac,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
> Xilinx Versal Soft Error Mitigation (XilSEM) is responsible for reporting
> and optionally correcting soft errors in Configuration Memory of Versal.
> The Configuration Memory includes Configuration RAM and
> Network on Chip (NoC) peripheral interconnect (NPI) Registers.
> 
> The Configuration RAM (CRAM) memory is used for storing configuration
> data for the programmable logic (PL) fabric. The NPI registers are used
> for configuring the memory controllers, miscellaneous integrated hardware,
> NoC interface units in the Veral device.
> 
> Add support to handle correctable and uncorrectable error events
> from XilSEM.
> 
> Add sysfs interface for XilSEM scan operations
> initialize, start, stop scan, error inject, read ECC, scan status and
> configuration values.
> 
> Signed-off-by: Rama devi Veggalam <[email protected]>
> ---
<snip>

>   static int mc_probe(struct platform_device *pdev)
>   {
> -	void __iomem *ddrmc_baseaddr, *ddrmc_noc_baseaddr;
> +	void __iomem *ddrmc_baseaddr, *ddrmc_noc_baseaddr, *sem_baseaddr;
>   	struct edac_mc_layer layers[2];
>   	struct mem_ctl_info *mci;
>   	u8 num_chans, num_csrows;
>   	struct edac_priv *priv;
>   	u32 edac_mc_id, regval;
> +	u32 family_code;
>   	int rc;
>   
>   	ddrmc_baseaddr = devm_platform_ioremap_resource_byname(pdev, "base");
> @@ -1094,6 +2365,10 @@ static int mc_probe(struct platform_device *pdev)
>   	if (!get_ecc_state(ddrmc_baseaddr))
>   		return -ENXIO;
>   
> +	sem_baseaddr = devm_platform_ioremap_resource_byname(pdev, "semrtca");
> +	if (IS_ERR(sem_baseaddr))
> +		return PTR_ERR(sem_baseaddr);
> +

As mentioned by Krzysztof in DT review this change breaks existing
system. Please ioremap this semrtca resource only for xilSEM support.
We can make use of compatible based match data.

>   	/* Allocate ID number for the EMIF controller */
>   	edac_mc_id = emif_get_id(pdev->dev.of_node);
>   
> @@ -1124,9 +2399,29 @@ static int mc_probe(struct platform_device *pdev)
>   	priv = mci->pvt_info;
>   	priv->ddrmc_baseaddr = ddrmc_baseaddr;
>   	priv->ddrmc_noc_baseaddr = ddrmc_noc_baseaddr;
> +	priv->sem_baseaddr = sem_baseaddr;
>   	priv->ce_cnt = 0;
>   	priv->ue_cnt = 0;
>   	priv->mc_id = edac_mc_id;
> +	priv->xsem_rtca = NULL;
> +
> +	/* Allocate and initialize XilSem RTCA structure */
> +	priv->xsem_rtca = devm_kzalloc(&pdev->dev,
> +				       sizeof(struct xsem_rtca_priv),
> +				       GFP_KERNEL);
> +	if (!priv->xsem_rtca) {
> +		edac_printk(KERN_ERR, EDAC_MC,
> +			    "Failed to allocate xsem_rtca\n");
> +		rc = -ENOMEM;
> +		goto free_edac_mc;
> +	}
> +
> +	priv->xsem_rtca->slr_info = devm_kzalloc(&pdev->dev, sizeof(struct xsem_ssit_status),
> +						 GFP_KERNEL);
> +	if (!priv->xsem_rtca->slr_info) {
> +		rc = -ENOMEM;
> +		goto free_edac_mc;
> +	}
>   
>   	mc_init(mci, pdev);
>   
> @@ -1147,6 +2442,41 @@ static int mc_probe(struct platform_device *pdev)
>   		goto del_mc;
>   	}
>   
> +	/* Create XilSem sysfs attributes only if XilSem is available */
> +	rc = xsem_edac_create_sysfs_attributes(mci);
> +	if (rc) {
> +		edac_printk(KERN_ERR, EDAC_MC,
> +			    "Failed to create sysfs entries\n");
> +		goto remove_sysfs;
> +	}
> +
> +	/*
> +	 * Firmware driver returns -ENODEV if it is not probed. In this case
> +	 * defer XilSEM error event registration.
> +	 */
> +	rc = zynqmp_pm_get_family_info(&family_code);
> +	if (rc) {
> +		if (rc == -ENODEV)
> +			rc = -EPROBE_DEFER;
> +
> +		goto del_mc;
> +	}
> +	if (family_code == PM_VERSAL_FAMILY_CODE) {
> +		priv->xsem_rtca->sw_event_node_id = VERSAL_EVENT_ERROR_SW_ERR;
> +		priv->xsem_rtca->cram_ce_mask = XPM_VERSAL_EVENT_ERROR_MASK_XSEM_CRAM_CE_5;
> +		priv->xsem_rtca->cram_ue_mask = XPM_VERSAL_EVENT_ERROR_MASK_XSEM_CRAM_UE_6;
> +		priv->xsem_rtca->npi_ue_mask = XPM_VERSAL_EVENT_ERROR_MASK_XSEM_NPI_UE_7;
> +	} else {
> +		edac_printk(KERN_ERR, EDAC_MC, "Invalid Device family code %d\n", family_code);
> +	}
> +
> +	rc = xlnx_register_event(PM_NOTIFY_CB, priv->xsem_rtca->sw_event_node_id,
> +				 priv->xsem_rtca->cram_ce_mask | priv->xsem_rtca->cram_ue_mask |
> +				 priv->xsem_rtca->npi_ue_mask,
> +				 false, xsem_err_callback, mci);
> +	if (rc)
> +		goto del_mc;
> +
>   #ifdef CONFIG_EDAC_DEBUG
>   	create_debugfs_attributes(mci);
>   	setup_address_map(priv);
> @@ -1154,6 +2484,8 @@ static int mc_probe(struct platform_device *pdev)
>   	enable_intr(priv);
>   	return rc;
>   
> +remove_sysfs:
> +	xsem_edac_remove_sysfs_attributes(mci);
>   del_mc:
>   	edac_mc_del_mc(&pdev->dev);
>   free_edac_mc:
> @@ -1173,9 +2505,21 @@ static void mc_remove(struct platform_device *pdev)
>   	debugfs_remove_recursive(priv->debugfs);
>   #endif
>   
> +	/* Unregister XilSem events if they were registered */
> +	if (priv->xsem_rtca) {
> +		xlnx_unregister_event(PM_NOTIFY_CB, priv->xsem_rtca->sw_event_node_id,
> +				      priv->xsem_rtca->cram_ce_mask |
> +					  priv->xsem_rtca->cram_ue_mask |
> +					  priv->xsem_rtca->npi_ue_mask,
> +				      xsem_err_callback, mci);
> +	}
>   	xlnx_unregister_event(PM_NOTIFY_CB, VERSAL_EVENT_ERROR_PMC_ERR1,
>   			      XPM_EVENT_ERROR_MASK_DDRMC_CR |
>   			      XPM_EVENT_ERROR_MASK_DDRMC_NCR, err_callback, mci);
> +	/* Remove XilSem sysfs attributes if they were created */
> +	if (priv->xsem_rtca)
> +		xsem_edac_remove_sysfs_attributes(mci);
> +
>   	edac_mc_del_mc(&pdev->dev);
>   	edac_mc_free(mci);
>   }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.