Re: [PATCH net] net: stmmac: xgmac: fix safety error descriptions

From: Serge Semin
Date: Thu Jan 25 2024 - 08:50:21 EST


On Thu, Jan 25, 2024 at 04:48:27PM +0300, Serge Semin wrote:
> On Thu, Jan 25, 2024 at 10:34:54AM +0800, Furong Xu wrote:
> > On Wed, 24 Jan 2024 17:25:27 +0300
> > Serge Semin <fancer.lancer@xxxxxxxxx> wrote:
> >
> > > On Tue, Jan 23, 2024 at 04:50:37PM +0800, Furong Xu wrote:
> > > > Commit 56e58d6c8a56 ("net: stmmac: Implement Safety Features in
> > > > XGMAC core") prints safety error descriptions when safety error assert,
> > > > but missed some special errors, and mixed correctable errors and
> > > > uncorrectable errors together.
> > > > This patch complete the error code list and print the type of errors.
> > >
> > > The XGMAC ECC Safety code has likely been just copied from the DW GMAC
> > > v5 (DW QoS Eth) part. So this change is partly relevant to that code too. I
> > > can't confirm that the special errors support is relevant to the DW
> > > QoS Eth too (it likely is though), so what about splitting this patch
> > > up into two:
> > > 1. Elaborate the errors description for DW GMAC v5 and DW XGMAC.
> > > 2. Add new ECC safety errors support.
> > > ?
> > >
> > > On the other hand if we were sure that both DW QoS Eth and XGMAC
> > > safety features implementation match the ideal solution would be to
> > > refactor out the common code into a dedicated module.
> > >
> > > -Serge(y)
> > >
> >
>
> > Checked XGMAC Version 3.20a and DW QoS Eth Version 5.20a, the safety error
> > code definitions are not identical at all, they do have some differences,
> > about more than 20 bits of status register are different.
> > I think we should just leave them in individual implementations.
>
> For some reason you answered to the last part of my comment and
> completely ignored the first part which was the main point of my
> message.
>
> Regarding the Safety Feature support implemented in QoS Eth and XGMAC
> STMMAC modules. You were wrong in using the statement "at all". Except
> the optional events enable/disable procedure introduced in the commit
> 5ac712dcdfef ("net: stmmac: enable platform specific safety
> features"), there aren't many differences: at least the errors
> handling and report are identical, MTL and DMA error flags match, even
> MTL and DMA ECC/Safety IRQ flags match. The only difference is in the
> MTL/MAC DPP (Data Parity Protection) part which can be easily factored
> out based on the device ID should we attempt to refactor the safety
> feature code. See the attached html-diff for more details of what
> match and what is different.

Grrr, forgot to attach the html-file...

-Serge(y)

>
> Anyway I am not insisting on the refactoring. That was just a
> proposal, a more preferred alternative to simultaneously patching two
> parts of the drivers looking very much alike. Such refactoring would
> improve the code maintainability. The main point of my comment was to
> extend your patch for DW QoS Eth safety feature implementation too
> since some of the changes you introduced were useful for it too, and
> in splitting the patch up since your patch added new flags support
> which was unrelated change. Thus your patch would turned into the
> two-patches patchset like this:
> [Patch 1] would provide an elaborated errors description for both DW
> QOS Eth (GMAC v5.x) and DW XGMAC.
> [Patch 2] would introduce the new ECC safety errors support.
>
> See my further comments about the respective changes.
>
> >
> > > >
> > > > Fixes: 56e58d6c8a56 ("net: stmmac: Implement Safety Features in XGMAC core")
> > > > Signed-off-by: Furong Xu <0x1207@xxxxxxxxx>
> > > > ---
> > > > .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 36 +++++++++----------
> > > > 1 file changed, 18 insertions(+), 18 deletions(-)
> > > >
> > > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> > > > index eb48211d9b0e..ad812484059e 100644
> > > > --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> > > > +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
> > > > @@ -748,29 +748,29 @@ static void dwxgmac3_handle_mac_err(struct net_device *ndev,
> > > > }
> > > >
> > > > static const struct dwxgmac3_error_desc dwxgmac3_mtl_errors[32]= {
>
> > > > - { true, "TXCES", "MTL TX Memory Error" },
> > > > + { true, "TXCES", "MTL TX Memory Correctable Error" },
>
> Applicable for both IP-cores
> [Patch 1] +QoS, +XGMAC
> please apply this change to dwmac5.c too.
>
> > > > { true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
>
> > > > - { true, "TXUES", "MTL TX Memory Error" },
> > > > + { true, "TXUES", "MTL TX Memory Uncorrectable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 3 */
>
> > > > - { true, "RXCES", "MTL RX Memory Error" },
> > > > + { true, "RXCES", "MTL RX Memory Correctable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
>
> > > > - { true, "RXUES", "MTL RX Memory Error" },
> > > > + { true, "RXUES", "MTL RX Memory Uncorrectable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 7 */
>
> > > > - { true, "ECES", "MTL EST Memory Error" },
> > > > + { true, "ECES", "MTL EST Memory Correctable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { true, "EAMS", "MTL EST Memory Address Mismatch Error" },
>
> > > > - { true, "EUES", "MTL EST Memory Error" },
> > > > + { true, "EUES", "MTL EST Memory Uncorrectable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 11 */
>
> > > > - { true, "RPCES", "MTL RX Parser Memory Error" },
> > > > + { true, "RPCES", "MTL RX Parser Memory Correctable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { true, "RPAMS", "MTL RX Parser Memory Address Mismatch Error" },
>
> > > > - { true, "RPUES", "MTL RX Parser Memory Error" },
> > > > + { true, "RPUES", "MTL RX Parser Memory Uncorrectable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 15 */
>
> > > > - { false, "UNKNOWN", "Unknown Error" }, /* 16 */
> > > > - { false, "UNKNOWN", "Unknown Error" }, /* 17 */
> > > > - { false, "UNKNOWN", "Unknown Error" }, /* 18 */
> > > > + { true, "SCES", "MTL SGF GCL Memory Correctable Error" },
> > > > + { true, "SAMS", "MTL SGF GCL Memory Address Mismatch Error" },
> > > > + { true, "SUES", "MTL SGF GCL Memory Uncorrectable Error" },
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 19 */
> > > > - { false, "UNKNOWN", "Unknown Error" }, /* 20 */
> > > > - { false, "UNKNOWN", "Unknown Error" }, /* 21 */
> > > > - { false, "UNKNOWN", "Unknown Error" }, /* 22 */
> > > > + { true, "RXFCES", "MTL RXF Memory Correctable Error" },
> > > > + { true, "RXFAMS", "MTL RXF Memory Address Mismatch Error" },
> > > > + { true, "RXFUES", "MTL RXF Memory Uncorrectable Error" },
>
> This introduces the new flags support. Please move this change into a
> separate patch (Patch 2):
> [Patch 2] +XGMAC only.
>
> My DW QoS Eth v5.10a databook doesn't have these flags defined. If
> your 5.20a HW-manual have them described then please add them for DW
> QoS Eth too.
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 23 */
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 24 */
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 25 */
> > > > @@ -796,13 +796,13 @@ static void dwxgmac3_handle_mtl_err(struct net_device *ndev,
> > > > }
> > > >
> > > > static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= {
>
> > > > - { true, "TCES", "DMA TSO Memory Error" },
> > > > + { true, "TCES", "DMA TSO Memory Correctable Error" },
>
> Applicable for both IP-cores
> [Patch 1] +QoS, +XGMAC
> please apply this change to dwmac5.c too.
>
> > > > { true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
>
> > > > - { true, "TUES", "DMA TSO Memory Error" },
> > > > + { true, "TUES", "DMA TSO Memory Uncorrectable Error" },
>
> [Patch 1] +QoS, +XGMAC
> ditto
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 3 */
>
> > > > - { true, "DCES", "DMA DCACHE Memory Error" },
> > > > + { true, "DCES", "DMA DCACHE Memory Correctable Error" },
> > > > { true, "DAMS", "DMA DCACHE Address Mismatch Error" },
> > > > - { true, "DUES", "DMA DCACHE Memory Error" },
> > > > + { true, "DUES", "DMA DCACHE Memory Uncorrectable Error" },
>
> AFAICS applicable for XGMAC only
> [Patch 1] +XGMAC only.
> Once again, My DW QoS Eth v5.10a databook doesn't have these flags
> defined. So if your DW QoS Eth 5.20a HW-manual do have them described
> please add them for DW QoS Eth with the elaborated description in the
> framework of the Patch 2.
>
> -Serge(y)
>
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 7 */
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 8 */
> > > > { false, "UNKNOWN", "Unknown Error" }, /* 9 */
> > > > --
> > > > 2.34.1
> > > >
> > > >
> >
Title: diff
drivers/net/ethernet/stmicro/stmmac/dwmac5_sfty.c drivers/net/ethernet/stmicro/stmmac/dwxgmac2_sfty.c
#define MAC_DPP_FSM_INT_STATUS		0x00000140                                                                                                                         
#define MAC_FSM_CONTROL			0x00000148                                                                                                                         
                                                                                                                                                                           
#define MTL_ECC_CONTROL			0x00000cc0                                                                                                                         
#define MEEAO				BIT(8)                                                                                                                             
#define TSOEE				BIT(4)                                                                                                                             
#define MRXPEE				BIT(3)                                                                                                                             
#define MESTEE				BIT(2)                                                                                                                             
#define MRXEE				BIT(1)                                                                                                                             
#define MTXEE				BIT(0)                                                                                                                             
                                                                                                                                                                           
#define MTL_SAFETY_INT_STATUS		0x00000cc4                                                                                                                         
#define MCSIS				BIT(31)                                                                                                                            
#define MEUIS				BIT(1)                                                                                                                             
#define MECIS				BIT(0)                                                                                                                             
                                                                                                                                                                           
#define MTL_ECC_INT_ENABLE		0x00000cc8                                                                                                                         
#define RPCEIE				BIT(12)                                                                                                                            
#define ECEIE				BIT(8)                                                                                                                             
#define RXCEIE				BIT(4)                                                                                                                             
#define TXCEIE				BIT(0)                                                                                                                             
#define MTL_ECC_INT_STATUS		0x00000ccc                                                                                                                         
                                                                                                                                                                           
#define MTL_DPP_CONTROL			0x00000ce0                                                                                                                         
#define EPSI				BIT(2)                                                                                                                             
#define OPE				BIT(1)                                                                                                                             
#define EDPP				BIT(0)                                                                                                                             
                                                                                                                                                                           
#define DMA_SAFETY_INT_STATUS		0x00001080                                                                                                                         
                                                                                                                                                                           
#define MSUIS				BIT(29)                                                                                                                            
#define MSCIS				BIT(28)                                                                                                                            
#define DEUIS				BIT(1)                                                                                                                             
#define DECIS				BIT(0)                                                                                                                             
#define DMA_ECC_INT_ENABLE		0x00001084                                                                                                                         
                                                                                                                                                                           
#define TCEIE				BIT(0)                                                                                                                             
#define DMA_ECC_INT_STATUS		0x00001088                                                                                                                         
                                                                                                                                                                           
struct dwmac5_error_desc {                                                                                                                                                 
	bool valid;
	const char *desc;
	const char *detailed_desc;
};

#define STAT_OFF(field)		offsetof(struct stmmac_safety_stats, field)

static void dwmac5_log_error(struct net_device *ndev, u32 value, bool corr,                                                                                                
			       const char *module_name,
			       const struct dwmac5_error_desc *desc,                                                                                                       
			       unsigned long field_offset,
			       struct stmmac_safety_stats *stats)
{
	unsigned long loc, mask;
	u8 *bptr = (u8 *)stats;
	unsigned long *ptr;
+--  8 lines: ptr = (unsigned long *)(bptr + field_offset);----------------------------------------------------------------------------------------------------------------

		/* Update counters */
		ptr[loc]++;
	}
}

static const struct dwmac5_error_desc dwmac5_mac_errors[32]= {                                                                                                             
	{ true, "ATPES", "Application Transmit Interface Parity Check Error" },
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	{ true, "TPES", "TSO Data Path Parity Check Error" },
	{ true, "RDPES", "Read Descriptor Parity Check Error" },                                                                                                           
	{ true, "MPES", "MTL Data Path Parity Check Error" },                                                                                                              
	{ true, "MTSPES", "MTL TX Status Data Path Parity Check Error" },
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	{ true, "ARPES", "Application Receive Interface Data Path Parity Check Error" },
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	{ true, "CWPES", "CSR Write Data Path Parity Check Error" },
	{ true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" },
	{ true, "TTES", "TX FSM Timeout Error" },
	{ true, "RTES", "RX FSM Timeout Error" },
	{ true, "CTES", "CSR FSM Timeout Error" },
	{ true, "ATES", "APP FSM Timeout Error" },
	{ true, "PTES", "PTP FSM Timeout Error" },
	{ true, "T125ES", "TX125 FSM Timeout Error" },                                                                                                                     
	{ true, "R125ES", "RX125 FSM Timeout Error" },                                                                                                                     
	{ true, "RVCTES", "REV MDC FSM Timeout Error" },                                                                                                                   
	{ true, "MSTTES", "Master Read/Write Timeout Error" },
	{ true, "SLVTES", "Slave Read/Write Timeout Error" },
	{ true, "ATITES", "Application Timeout on ATI Interface Error" },
	{ true, "ARITES", "Application Timeout on ARI Interface Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 20 */                                                                                                                    
	{ false, "UNKNOWN", "Unknown Error" }, /* 21 */                                                                                                                    
	{ false, "UNKNOWN", "Unknown Error" }, /* 22 */                                                                                                                    
	{ false, "UNKNOWN", "Unknown Error" }, /* 23 */                                                                                                                    
	{ true, "FSMPES", "FSM State Parity Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 25 */                                                                                                                    
	{ false, "UNKNOWN", "Unknown Error" }, /* 26 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 27 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 28 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 29 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 30 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 31 */                                                                                                                    
};

static void dwmac5_handle_mac_err(struct net_device *ndev,                                                                                                                 
				    void __iomem *ioaddr, bool correctable,
				    struct stmmac_safety_stats *stats)
{
	u32 value;

	value = readl(ioaddr + MAC_DPP_FSM_INT_STATUS);                                                                                                                    
	writel(value, ioaddr + MAC_DPP_FSM_INT_STATUS);                                                                                                                    

	dwmac5_log_error(ndev, value, correctable, "MAC", dwmac5_mac_errors,                                                                                               
			STAT_OFF(mac_errors), stats);                                                                                                                      
}

static const struct dwmac5_error_desc dwmac5_mtl_errors[32]= {                                                                                                             
	{ true, "TXCES", "MTL TX Memory Error" },
	{ true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
	{ true, "TXUES", "MTL TX Memory Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 3 */
	{ true, "RXCES", "MTL RX Memory Error" },
	{ true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
+-- 22 lines: { true, "RXUES", "MTL RX Memory Error" },--------------------------------------------------------------------------------------------------------------------
	{ false, "UNKNOWN", "Unknown Error" }, /* 28 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 29 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 30 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 31 */
};

static void dwmac5_handle_mtl_err(struct net_device *ndev,                                                                                                                 
				    void __iomem *ioaddr, bool correctable,
				    struct stmmac_safety_stats *stats)
{
	u32 value;

	value = readl(ioaddr + MTL_ECC_INT_STATUS);                                                                                                                        
	writel(value, ioaddr + MTL_ECC_INT_STATUS);                                                                                                                        

	dwmac5_log_error(ndev, value, correctable, "MTL", dwmac5_mtl_errors,                                                                                               
			STAT_OFF(mtl_errors), stats);                                                                                                                      
}

static const struct dwmac5_error_desc dwmac5_dma_errors[32]= {                                                                                                             
	{ true, "TCES", "DMA TSO Memory Error" },
	{ true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
	{ true, "TUES", "DMA TSO Memory Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 3 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 4 */                                                                                                                     
	{ false, "UNKNOWN", "Unknown Error" }, /* 5 */                                                                                                                     
	{ false, "UNKNOWN", "Unknown Error" }, /* 6 */                                                                                                                     
	{ false, "UNKNOWN", "Unknown Error" }, /* 7 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 8 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 9 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 10 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 11 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 12 */
+-- 15 lines: { false, "UNKNOWN", "Unknown Error" }, 13 -------------------------------------------------------------------------------------------------------------------
	{ false, "UNKNOWN", "Unknown Error" }, /* 28 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 29 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 30 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 31 */
};

static void dwmac5_handle_dma_err(struct net_device *ndev,                                                                                                                 
				  void __iomem *ioaddr, bool correctable,                                                                                                  
				  struct stmmac_safety_stats *stats)                                                                                                       
{
	u32 value;

	value = readl(ioaddr + DMA_ECC_INT_STATUS);                                                                                                                        
	writel(value, ioaddr + DMA_ECC_INT_STATUS);                                                                                                                        

	dwmac5_log_error(ndev, value, correctable, "DMA", dwmac5_dma_errors,                                                                                               
			STAT_OFF(dma_errors), stats);                                                                                                                      
}

int dwmac5_safety_feat_irq_status(struct net_device *ndev,                                                                                                                 
				  void __iomem *ioaddr,                                                                                                                    
				  unsigned int asp,                                                                                                                        
				  struct stmmac_safety_stats *stats)                                                                                                       
{
	bool err, corr;
	u32 mtl, dma;
	int ret = 0;

	if (!asp)
		return -EINVAL;

	mtl = readl(ioaddr + MTL_SAFETY_INT_STATUS);                                                                                                                       
	dma = readl(ioaddr + DMA_SAFETY_INT_STATUS);                                                                                                                       

	err = (mtl & MCSIS) || (dma & MCSIS);                                                                                                                              
	corr = false;
	if (err) {
		dwmac5_handle_mac_err(ndev, ioaddr, corr, stats);                                                                                                          
		ret |= !corr;
	}

	err = (mtl & (MEUIS | MECIS)) || (dma & (MSUIS | MSCIS));                                                                                                          
	corr = (mtl & MECIS) || (dma & MSCIS);                                                                                                                             
	if (err) {
		dwmac5_handle_mtl_err(ndev, ioaddr, corr, stats);                                                                                                          
		ret |= !corr;
	}

	err = dma & (DEUIS | DECIS);                                                                                                                                       
	corr = dma & DECIS;                                                                                                                                                
	if (err) {
		dwmac5_handle_dma_err(ndev, ioaddr, corr, stats);                                                                                                          
		ret |= !corr;
	}

	return ret;
}

static const struct dwmac5_error {                                                                                                                                         
	const struct dwmac5_error_desc *desc;                                                                                                                              
} dwmac5_all_errors[] = {                                                                                                                                                  
	{ dwmac5_mac_errors },                                                                                                                                             
	{ dwmac5_mtl_errors },                                                                                                                                             
	{ dwmac5_dma_errors },                                                                                                                                             
};

int dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats,                                                                                                             
			    int index, unsigned long *count,                                                                                                               
			    const char **desc)                                                                                                                             
{
	int module = index / 32, offset = index % 32;
	unsigned long *ptr = (unsigned long *)stats;

	if (module >= ARRAY_SIZE(dwmac5_all_errors))                                                                                                                       
		return -EINVAL;
	if (!dwmac5_all_errors[module].desc[offset].valid)                                                                                                                 
		return -EINVAL;
	if (count)
		*count = *(ptr + index);
	if (desc)
		*desc = dwmac5_all_errors[module].desc[offset].desc;                                                                                                       
	return 0;
}

int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp,                                                                                                      
			      struct stmmac_safety_feature_cfg *safety_feat_cfg)                                                                                           
{
	struct stmmac_safety_feature_cfg all_safety_feats = {                                                                                                              
		.tsoee = 1,                                                                                                                                                
		.mrxpee = 1,                                                                                                                                               
		.mestee = 1,                                                                                                                                               
		.mrxee = 1,                                                                                                                                                
		.mtxee = 1,                                                                                                                                                
		.epsi = 1,                                                                                                                                                 
		.edpp = 1,                                                                                                                                                 
		.prtyen = 1,                                                                                                                                               
		.tmouten = 1,                                                                                                                                              
	};                                                                                                                                                                 
	u32 value;

	if (!asp)
		return -EINVAL;

	if (!safety_feat_cfg)                                                                                                                                              
		safety_feat_cfg = &all_safety_feats;                                                                                                                       
                                                                                                                                                                           
	/* 1. Enable Safety Features */
	value = readl(ioaddr + MTL_ECC_CONTROL);                                                                                                                           
	value |= MEEAO; /* MTL ECC Error Addr Status Override */                                                                                                           
	if (safety_feat_cfg->tsoee)                                                                                                                                        
		value |= TSOEE; /* TSO ECC */                                                                                                                              
	if (safety_feat_cfg->mrxpee)                                                                                                                                       
		value |= MRXPEE; /* MTL RX Parser ECC */                                                                                                                   
	if (safety_feat_cfg->mestee)                                                                                                                                       
		value |= MESTEE; /* MTL EST ECC */                                                                                                                         
	if (safety_feat_cfg->mrxee)                                                                                                                                        
		value |= MRXEE; /* MTL RX FIFO ECC */                                                                                                                      
	if (safety_feat_cfg->mtxee)                                                                                                                                        
		value |= MTXEE; /* MTL TX FIFO ECC */                                                                                                                      
	writel(value, ioaddr + MTL_ECC_CONTROL);                                                                                                                           

	/* 2. Enable MTL Safety Interrupts */
	value = readl(ioaddr + MTL_ECC_INT_ENABLE);                                                                                                                        
	value |= RPCEIE; /* RX Parser Memory Correctable Error */                                                                                                          
	value |= ECEIE; /* EST Memory Correctable Error */                                                                                                                 
	value |= RXCEIE; /* RX Memory Correctable Error */                                                                                                                 
	value |= TXCEIE; /* TX Memory Correctable Error */                                                                                                                 
	writel(value, ioaddr + MTL_ECC_INT_ENABLE);                                                                                                                        

	/* 3. Enable DMA Safety Interrupts */
	value = readl(ioaddr + DMA_ECC_INT_ENABLE);                                                                                                                        
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	value |= TCEIE; /* TSO Memory Correctable Error */                                                                                                                 
	writel(value, ioaddr + DMA_ECC_INT_ENABLE);                                                                                                                        


	/* Only ECC Protection for External Memory feature is selected                                                                                                     
	 *                                                                                                                                                                 
	 */
	if (asp <= 0x1)                                                                                                                                                    
		return 0;

	/* 5. Enable Parity and Timeout for FSM */                                                                                                                         
	value = readl(ioaddr + MAC_FSM_CONTROL);                                                                                                                           
	if (safety_feat_cfg->prtyen)                                                                                                                                       
		value |= PRTYEN; /* FSM Parity Feature */                                                                                                                  
	if (safety_feat_cfg->tmouten)                                                                                                                                      
		value |= TMOUTEN; /* FSM Timeout Feature */                                                                                                                
	writel(value, ioaddr + MAC_FSM_CONTROL);                                                                                                                           
                                                                                                                                                                           
	/* 4. Enable Data Parity Protection */                                                                                                                             
	value = readl(ioaddr + MTL_DPP_CONTROL);                                                                                                                           
	if (safety_feat_cfg->edpp)                                                                                                                                         
		value |= EDPP;                                                                                                                                             
	writel(value, ioaddr + MTL_DPP_CONTROL);                                                                                                                           
                                                                                                                                                                           
	/*                                                                                                                                                                 
	 * All the Automotive Safety features are selected without the "Parity                                                                                             
	 * Port Enable for external interface" feature.                                                                                                                    
	 */                                                                                                                                                                
	if (asp <= 0x2)                                                                                                                                                    
		return 0;                                                                                                                                                  

	if (safety_feat_cfg->epsi)                                                                                                                                         
		value |= EPSI;                                                                                                                                             
	writel(value, ioaddr + MTL_DPP_CONTROL);                                                                                                                           
	return 0;
}
#define XGMAC_MAC_DPP_FSM_INT_STATUS	0x00000150                                                                                                                         
#define XGMAC_MAC_FSM_CONTROL		0x00000158                                                                                                                         
                                                                                                                                                                           
#define XGMAC_MTL_ECC_CONTROL		0x000010c0                                                                                                                         
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
#define XGMAC_MTL_SAFETY_INT_STATUS	0x000010c4                                                                                                                         
                                                                                                                                                                           
#define XGMAC_MEUIS			BIT(1)                                                                                                                             
#define XGMAC_MECIS			BIT(0)                                                                                                                             
                                                                                                                                                                           
#define XGMAC_MTL_ECC_INT_ENABLE	0x000010c8                                                                                                                         
#define XGMAC_RPCEIE			BIT(12)                                                                                                                            
#define XGMAC_ECEIE			BIT(8)                                                                                                                             
#define XGMAC_RXCEIE			BIT(4)                                                                                                                             
#define XGMAC_TXCEIE			BIT(0)                                                                                                                             
#define XGMAC_MTL_ECC_INT_STATUS	0x000010cc                                                                                                                         
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
                                                                                                                                                                           
#define XGMAC_DMA_SAFETY_INT_STATUS	0x00003064                                                                                                                         
#define XGMAC_MCSIS			BIT(31)                                                                                                                            
#define XGMAC_MSUIS			BIT(29)                                                                                                                            
#define XGMAC_MSCIS			BIT(28)                                                                                                                            
#define XGMAC_DEUIS			BIT(1)                                                                                                                             
#define XGMAC_DECIS			BIT(0)                                                                                                                             
#define XGMAC_DMA_ECC_INT_ENABLE	0x00003068                                                                                                                         
#define XGMAC_DCEIE			BIT(1)                                                                                                                             
#define XGMAC_TCEIE			BIT(0)                                                                                                                             
#define XGMAC_DMA_ECC_INT_STATUS	0x0000306c                                                                                                                         
                                                                                                                                                                           
struct dwxgmac3_error_desc {                                                                                                                                               
	bool valid;
	const char *desc;
	const char *detailed_desc;
};

#define STAT_OFF(field)		offsetof(struct stmmac_safety_stats, field)

static void dwxgmac3_log_error(struct net_device *ndev, u32 value, bool corr,                                                                                              
			       const char *module_name,
			       const struct dwxgmac3_error_desc *desc,                                                                                                     
			       unsigned long field_offset,
			       struct stmmac_safety_stats *stats)
{
	unsigned long loc, mask;
	u8 *bptr = (u8 *)stats;
	unsigned long *ptr;
+--  8 lines: ptr = (unsigned long *)(bptr + field_offset);----------------------------------------------------------------------------------------------------------------

		/* Update counters */
		ptr[loc]++;
	}
}

static const struct dwxgmac3_error_desc dwxgmac3_mac_errors[32]= {                                                                                                         
	{ true, "ATPES", "Application Transmit Interface Parity Check Error" },
	{ true, "DPES", "Descriptor Cache Data Path Parity Check Error" },                                                                                                 
	{ true, "TPES", "TSO Data Path Parity Check Error" },
	{ true, "TSOPES", "TSO Header Data Path Parity Check Error" },                                                                                                     
	{ true, "MTPES", "MTL Data Path Parity Check Error" },                                                                                                             
	{ true, "MTSPES", "MTL TX Status Data Path Parity Check Error" },
	{ true, "MTBUPES", "MAC TBU Data Path Parity Check Error" },                                                                                                       
	{ true, "MTFCPES", "MAC TFC Data Path Parity Check Error" },                                                                                                       
	{ true, "ARPES", "Application Receive Interface Data Path Parity Check Error" },
	{ true, "MRWCPES", "MTL RWC Data Path Parity Check Error" },                                                                                                       
	{ true, "MRRCPES", "MTL RCC Data Path Parity Check Error" },                                                                                                       
	{ true, "CWPES", "CSR Write Data Path Parity Check Error" },
	{ true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" },
	{ true, "TTES", "TX FSM Timeout Error" },
	{ true, "RTES", "RX FSM Timeout Error" },
	{ true, "CTES", "CSR FSM Timeout Error" },
	{ true, "ATES", "APP FSM Timeout Error" },
	{ true, "PTES", "PTP FSM Timeout Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 18 */                                                                                                                    
	{ false, "UNKNOWN", "Unknown Error" }, /* 19 */                                                                                                                    
	{ false, "UNKNOWN", "Unknown Error" }, /* 20 */                                                                                                                    
	{ true, "MSTTES", "Master Read/Write Timeout Error" },
	{ true, "SLVTES", "Slave Read/Write Timeout Error" },
	{ true, "ATITES", "Application Timeout on ATI Interface Error" },
	{ true, "ARITES", "Application Timeout on ARI Interface Error" },
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	{ true, "FSMPES", "FSM State Parity Error" },
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	{ false, "UNKNOWN", "Unknown Error" }, /* 26 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 27 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 28 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 29 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 30 */
	{ true, "CPI", "Control Register Parity Check Error" },                                                                                                            
};

static void dwxgmac3_handle_mac_err(struct net_device *ndev,                                                                                                               
				    void __iomem *ioaddr, bool correctable,
				    struct stmmac_safety_stats *stats)
{
	u32 value;

	value = readl(ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS);                                                                                                              
	writel(value, ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS);                                                                                                              

	dwxgmac3_log_error(ndev, value, correctable, "MAC", dwxgmac3_mac_errors,                                                                                           
			   STAT_OFF(mac_errors), stats);                                                                                                                   
}

static const struct dwxgmac3_error_desc dwxgmac3_mtl_errors[32]= {                                                                                                         
	{ true, "TXCES", "MTL TX Memory Error" },
	{ true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
	{ true, "TXUES", "MTL TX Memory Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 3 */
	{ true, "RXCES", "MTL RX Memory Error" },
	{ true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
+-- 22 lines: { true, "RXUES", "MTL RX Memory Error" },--------------------------------------------------------------------------------------------------------------------
	{ false, "UNKNOWN", "Unknown Error" }, /* 28 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 29 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 30 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 31 */
};

static void dwxgmac3_handle_mtl_err(struct net_device *ndev,                                                                                                               
				    void __iomem *ioaddr, bool correctable,
				    struct stmmac_safety_stats *stats)
{
	u32 value;

	value = readl(ioaddr + XGMAC_MTL_ECC_INT_STATUS);                                                                                                                  
	writel(value, ioaddr + XGMAC_MTL_ECC_INT_STATUS);                                                                                                                  

	dwxgmac3_log_error(ndev, value, correctable, "MTL",                                                                                                                
			   dwxgmac3_mtl_errors, STAT_OFF(mtl_errors), stats);                                                                                              
}

static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= {                                                                                                         
	{ true, "TCES", "DMA TSO Memory Error" },
	{ true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
	{ true, "TUES", "DMA TSO Memory Error" },
	{ false, "UNKNOWN", "Unknown Error" }, /* 3 */
	{ true, "DCES", "DMA DCACHE Memory Error" },                                                                                                                       
	{ true, "DAMS", "DMA DCACHE Address Mismatch Error" },                                                                                                             
	{ true, "DUES", "DMA DCACHE Memory Error" },                                                                                                                       
	{ false, "UNKNOWN", "Unknown Error" }, /* 7 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 8 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 9 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 10 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 11 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 12 */
+-- 15 lines: { false, "UNKNOWN", "Unknown Error" }, 13 -------------------------------------------------------------------------------------------------------------------
	{ false, "UNKNOWN", "Unknown Error" }, /* 28 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 29 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 30 */
	{ false, "UNKNOWN", "Unknown Error" }, /* 31 */
};

static void dwxgmac3_handle_dma_err(struct net_device *ndev,                                                                                                               
				    void __iomem *ioaddr, bool correctable,                                                                                                
				    struct stmmac_safety_stats *stats)                                                                                                     
{
	u32 value;

	value = readl(ioaddr + XGMAC_DMA_ECC_INT_STATUS);                                                                                                                  
	writel(value, ioaddr + XGMAC_DMA_ECC_INT_STATUS);                                                                                                                  

	dwxgmac3_log_error(ndev, value, correctable, "DMA", dwxgmac3_dma_errors,                                                                                           
			   STAT_OFF(dma_errors), stats);                                                                                                                   
}

static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev,                                                                                                        
					   void __iomem *ioaddr,                                                                                                           
					   unsigned int asp,                                                                                                               
					   struct stmmac_safety_stats *stats)                                                                                              
{
	bool err, corr;
	u32 mtl, dma;
	int ret = 0;

	if (!asp)
		return -EINVAL;

	mtl = readl(ioaddr + XGMAC_MTL_SAFETY_INT_STATUS);                                                                                                                 
	dma = readl(ioaddr + XGMAC_DMA_SAFETY_INT_STATUS);                                                                                                                 

	err = (mtl & XGMAC_MCSIS) || (dma & XGMAC_MCSIS);                                                                                                                  
	corr = false;
	if (err) {
		dwxgmac3_handle_mac_err(ndev, ioaddr, corr, stats);                                                                                                        
		ret |= !corr;
	}

	err = (mtl & (XGMAC_MEUIS | XGMAC_MECIS)) || (dma & (XGMAC_MSUIS | XGMAC_MSCIS));                                                                                  
	corr = (mtl & XGMAC_MECIS) || (dma & XGMAC_MSCIS);                                                                                                                 
	if (err) {
		dwxgmac3_handle_mtl_err(ndev, ioaddr, corr, stats);                                                                                                        
		ret |= !corr;
	}

	err = dma & (XGMAC_DEUIS | XGMAC_DECIS);                                                                                                                           
	corr = dma & XGMAC_DECIS;                                                                                                                                          
	if (err) {
		dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats);                                                                                                        
		ret |= !corr;
	}

	return ret;
}

static const struct dwxgmac3_error {                                                                                                                                       
	const struct dwxgmac3_error_desc *desc;                                                                                                                            
} dwxgmac3_all_errors[] = {                                                                                                                                                
	{ dwxgmac3_mac_errors },                                                                                                                                           
	{ dwxgmac3_mtl_errors },                                                                                                                                           
	{ dwxgmac3_dma_errors },                                                                                                                                           
};

static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats,                                                                                                    
				     int index, unsigned long *count,                                                                                                      
				     const char **desc)                                                                                                                    
{
	int module = index / 32, offset = index % 32;
	unsigned long *ptr = (unsigned long *)stats;

	if (module >= ARRAY_SIZE(dwxgmac3_all_errors))                                                                                                                     
		return -EINVAL;
	if (!dwxgmac3_all_errors[module].desc[offset].valid)                                                                                                               
		return -EINVAL;
	if (count)
		*count = *(ptr + index);
	if (desc)
		*desc = dwxgmac3_all_errors[module].desc[offset].desc;                                                                                                     
	return 0;
}

static int dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp,                                                                                             
				       struct stmmac_safety_feature_cfg *safety_cfg)                                                                                       
{
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	u32 value;

	if (!asp)
		return -EINVAL;

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	/* 1. Enable Safety Features */
	writel(0x0, ioaddr + XGMAC_MTL_ECC_CONTROL);                                                                                                                       
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

	/* 2. Enable MTL Safety Interrupts */
	value = readl(ioaddr + XGMAC_MTL_ECC_INT_ENABLE);                                                                                                                  
	value |= XGMAC_RPCEIE; /* RX Parser Memory Correctable Error */                                                                                                    
	value |= XGMAC_ECEIE; /* EST Memory Correctable Error */                                                                                                           
	value |= XGMAC_RXCEIE; /* RX Memory Correctable Error */                                                                                                           
	value |= XGMAC_TXCEIE; /* TX Memory Correctable Error */                                                                                                           
	writel(value, ioaddr + XGMAC_MTL_ECC_INT_ENABLE);                                                                                                                  

	/* 3. Enable DMA Safety Interrupts */
	value = readl(ioaddr + XGMAC_DMA_ECC_INT_ENABLE);                                                                                                                  
	value |= XGMAC_DCEIE; /* Descriptor Cache Memory Correctable Error */                                                                                              

	value |= XGMAC_TCEIE; /* TSO Memory Correctable Error */                                                                                                           
	writel(value, ioaddr + XGMAC_DMA_ECC_INT_ENABLE);                                                                                                                  


	/* 0x2: Without ECC or Parity Ports on External Application Interface                                                                                              
	 * 0x4: Only ECC Protection for External Memory feature is selected                                                                                                
	 */
	if (asp == 0x2 || asp == 0x4)                                                                                                                                      
		return 0;

	/* 4. Enable Parity and Timeout for FSM */                                                                                                                         
	value = readl(ioaddr + XGMAC_MAC_FSM_CONTROL);                                                                                                                     
                                                                                                                                                                           
	value |= XGMAC_PRTYEN; /* FSM Parity Feature */                                                                                                                    
                                                                                                                                                                           
	value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */                                                                                                                  
	writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL);                                                                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	return 0;
}