Merge branch 'for-3.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[firefly-linux-kernel-4.4.55.git] / drivers / edac / cell_edac.c
index 9a6a274e6925f2c03edf2a92fda72b28f1d65aa6..69ee6aab5c716fefd0b919a5da4b46ef5c7c4a64 100644 (file)
@@ -48,8 +48,9 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
        syndrome = (ar & 0x000000001fe00000ul) >> 21;
 
        /* TODO: Decoding of the error address */
-       edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
-                         syndrome, 0, chan, "");
+       edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
+                            csrow->first_page + pfn, offset, syndrome,
+                            0, chan, -1, "", "", NULL);
 }
 
 static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
@@ -69,7 +70,9 @@ static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
        offset = address & ~PAGE_MASK;
 
        /* TODO: Decoding of the error address */
-       edac_mc_handle_ue(mci, csrow->first_page + pfn, offset, 0, "");
+       edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
+                            csrow->first_page + pfn, offset, 0,
+                            0, chan, -1, "", "", NULL);
 }
 
 static void cell_edac_check(struct mem_ctl_info *mci)
@@ -124,8 +127,11 @@ static void cell_edac_check(struct mem_ctl_info *mci)
 static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
 {
        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,15 +146,20 @@ 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 = resource_size(&r) >> PAGE_SHIFT;
-               csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
-               csrow->mtype = MEM_XDR;
-               csrow->edac_mode = EDAC_SECDED;
+               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->dev,
                        "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;
        }
 }
@@ -157,9 +168,10 @@ static int __devinit 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,8 +196,16 @@ static int __devinit cell_edac_probe(struct platform_device *pdev)
                in_be64(&regs->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;