diff options
Diffstat (limited to 'drivers/edac/cell_edac.c')
| -rw-r--r-- | drivers/edac/cell_edac.c | 74 | 
1 files changed, 48 insertions, 26 deletions
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index c973004c002..374b57fc596 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -15,6 +15,7 @@  #include <linux/platform_device.h>  #include <linux/stop_machine.h>  #include <linux/io.h> +#include <linux/of_address.h>  #include <asm/machdep.h>  #include <asm/cell-regs.h> @@ -33,10 +34,10 @@ struct cell_edac_priv  static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)  {  	struct cell_edac_priv		*priv = mci->pvt_info; -	struct csrow_info		*csrow = &mci->csrows[0]; +	struct csrow_info		*csrow = mci->csrows[0];  	unsigned long			address, pfn, offset, syndrome; -	dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", +	dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n",  		priv->node, chan, ar);  	/* Address decoding is likely a bit bogus, to dbl check */ @@ -47,18 +48,19 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)  	offset = address & ~PAGE_MASK;  	syndrome = (ar & 0x000000001fe00000ul) >> 21; -	/* TODO: Decoding of the error addresss */ -	edac_mc_handle_ce(mci, csrow->first_page + pfn, offset, -			  syndrome, 0, chan, ""); +	/* TODO: Decoding of the error address */ +	edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, +			     csrow->first_page + pfn, offset, syndrome, +			     0, chan, -1, "", "");  }  static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)  {  	struct cell_edac_priv		*priv = mci->pvt_info; -	struct csrow_info		*csrow = &mci->csrows[0]; +	struct csrow_info		*csrow = mci->csrows[0];  	unsigned long			address, pfn, offset; -	dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", +	dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n",  		priv->node, chan, ar);  	/* Address decoding is likely a bit bogus, to dbl check */ @@ -68,8 +70,10 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)  	pfn = address >> PAGE_SHIFT;  	offset = address & ~PAGE_MASK; -	/* TODO: Decoding of the error addresss */ -	edac_mc_handle_ue(mci, csrow->first_page + pfn, offset, 0, ""); +	/* TODO: Decoding of the error address */ +	edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, +			     csrow->first_page + pfn, offset, 0, +			     0, chan, -1, "", "");  }  static void cell_edac_check(struct mem_ctl_info *mci) @@ -80,7 +84,7 @@ static void cell_edac_check(struct mem_ctl_info *mci)  	fir = in_be64(&priv->regs->mic_fir);  #ifdef DEBUG  	if (fir != priv->prev_fir) { -		dev_dbg(mci->dev, "fir change : 0x%016lx\n", fir); +		dev_dbg(mci->pdev, "fir change : 0x%016lx\n", fir);  		priv->prev_fir = fir;  	}  #endif @@ -116,16 +120,19 @@ static void cell_edac_check(struct mem_ctl_info *mci)  		mb();	/* sync up */  #ifdef DEBUG  		fir = in_be64(&priv->regs->mic_fir); -		dev_dbg(mci->dev, "fir clear  : 0x%016lx\n", fir); +		dev_dbg(mci->pdev, "fir clear  : 0x%016lx\n", fir);  #endif  	}  } -static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) +static void cell_edac_init_csrows(struct mem_ctl_info *mci)  { -	struct csrow_info		*csrow = &mci->csrows[0]; +	struct csrow_info		*csrow = mci->csrows[0]; +	struct dimm_info		*dimm;  	struct cell_edac_priv		*priv = mci->pvt_info;  	struct device_node		*np; +	int				j; +	u32				nr_pages;  	for (np = NULL;  	     (np = of_find_node_by_name(np, "memory")) != NULL;) { @@ -140,26 +147,33 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)  		if (of_node_to_nid(np) != priv->node)  			continue;  		csrow->first_page = r.start >> PAGE_SHIFT; -		csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT; -		csrow->last_page = csrow->first_page + csrow->nr_pages - 1; -		csrow->mtype = MEM_XDR; -		csrow->edac_mode = EDAC_SECDED; -		dev_dbg(mci->dev, +		nr_pages = resource_size(&r) >> PAGE_SHIFT; +		csrow->last_page = csrow->first_page + nr_pages - 1; + +		for (j = 0; j < csrow->nr_channels; j++) { +			dimm = csrow->channels[j]->dimm; +			dimm->mtype = MEM_XDR; +			dimm->edac_mode = EDAC_SECDED; +			dimm->nr_pages = nr_pages / csrow->nr_channels; +		} +		dev_dbg(mci->pdev,  			"Initialized on node %d, chanmask=0x%x,"  			" first_page=0x%lx, nr_pages=0x%x\n",  			priv->node, priv->chanmask, -			csrow->first_page, csrow->nr_pages); +			csrow->first_page, nr_pages);  		break;  	} +	of_node_put(np);  } -static int __devinit cell_edac_probe(struct platform_device *pdev) +static int cell_edac_probe(struct platform_device *pdev)  {  	struct cbe_mic_tm_regs __iomem	*regs;  	struct mem_ctl_info		*mci; +	struct edac_mc_layer		layers[2];  	struct cell_edac_priv		*priv;  	u64				reg; -	int				rc, chanmask; +	int				rc, chanmask, num_chans;  	regs = cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(pdev->id));  	if (regs == NULL) @@ -184,15 +198,23 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)  		in_be64(®s->mic_fir));  	/* Allocate & init EDAC MC data structure */ -	mci = edac_mc_alloc(sizeof(struct cell_edac_priv), 1, -			    chanmask == 3 ? 2 : 1, pdev->id); +	num_chans = chanmask == 3 ? 2 : 1; + +	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; +	layers[0].size = 1; +	layers[0].is_virt_csrow = true; +	layers[1].type = EDAC_MC_LAYER_CHANNEL; +	layers[1].size = num_chans; +	layers[1].is_virt_csrow = false; +	mci = edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, +			    sizeof(struct cell_edac_priv));  	if (mci == NULL)  		return -ENOMEM;  	priv = mci->pvt_info;  	priv->regs = regs;  	priv->node = pdev->id;  	priv->chanmask = chanmask; -	mci->dev = &pdev->dev; +	mci->pdev = &pdev->dev;  	mci->mtype_cap = MEM_FLAG_XDR;  	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;  	mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED; @@ -213,7 +235,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)  	return 0;  } -static int __devexit cell_edac_remove(struct platform_device *pdev) +static int cell_edac_remove(struct platform_device *pdev)  {  	struct mem_ctl_info *mci = edac_mc_del_mc(&pdev->dev);  	if (mci) @@ -227,7 +249,7 @@ static struct platform_driver cell_edac_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= cell_edac_probe, -	.remove		= __devexit_p(cell_edac_remove), +	.remove		= cell_edac_remove,  };  static int __init cell_edac_init(void)  | 
