linux/drivers/edac/cell_edac.c
<<
>>
Prefs
   1/*
   2 * Cell MIC driver for ECC counting
   3 *
   4 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
   5 *                <benh@kernel.crashing.org>
   6 *
   7 * This file may be distributed under the terms of the
   8 * GNU General Public License.
   9 */
  10#undef DEBUG
  11
  12#include <linux/edac.h>
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/platform_device.h>
  16#include <linux/stop_machine.h>
  17#include <linux/io.h>
  18#include <asm/machdep.h>
  19#include <asm/cell-regs.h>
  20
  21#include "edac_core.h"
  22
  23struct cell_edac_priv
  24{
  25        struct cbe_mic_tm_regs __iomem  *regs;
  26        int                             node;
  27        int                             chanmask;
  28#ifdef DEBUG
  29        u64                             prev_fir;
  30#endif
  31};
  32
  33static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
  34{
  35        struct cell_edac_priv           *priv = mci->pvt_info;
  36        struct csrow_info               *csrow = mci->csrows[0];
  37        unsigned long                   address, pfn, offset, syndrome;
  38
  39        dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n",
  40                priv->node, chan, ar);
  41
  42        /* Address decoding is likely a bit bogus, to dbl check */
  43        address = (ar & 0xffffffffe0000000ul) >> 29;
  44        if (priv->chanmask == 0x3)
  45                address = (address << 1) | chan;
  46        pfn = address >> PAGE_SHIFT;
  47        offset = address & ~PAGE_MASK;
  48        syndrome = (ar & 0x000000001fe00000ul) >> 21;
  49
  50        /* TODO: Decoding of the error address */
  51        edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
  52                             csrow->first_page + pfn, offset, syndrome,
  53                             0, chan, -1, "", "");
  54}
  55
  56static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
  57{
  58        struct cell_edac_priv           *priv = mci->pvt_info;
  59        struct csrow_info               *csrow = mci->csrows[0];
  60        unsigned long                   address, pfn, offset;
  61
  62        dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n",
  63                priv->node, chan, ar);
  64
  65        /* Address decoding is likely a bit bogus, to dbl check */
  66        address = (ar & 0xffffffffe0000000ul) >> 29;
  67        if (priv->chanmask == 0x3)
  68                address = (address << 1) | chan;
  69        pfn = address >> PAGE_SHIFT;
  70        offset = address & ~PAGE_MASK;
  71
  72        /* TODO: Decoding of the error address */
  73        edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
  74                             csrow->first_page + pfn, offset, 0,
  75                             0, chan, -1, "", "");
  76}
  77
  78static void cell_edac_check(struct mem_ctl_info *mcilass="sref">ar & 0xffffffffe079" id="L7a>
  57{
  70        struct cell_edac_priv           *priv = mci->pvt_info;
  51        u64                             node, priv<0fo;
  32
  73        priv->reiv->cb=prev_fir" class="">cb=pref">ar);
  14#ifdef DEBUG
  75        if (priv->prev_f) 57{
u64                dev_dbg(mci->pdev, >pr#37;dge :, ar = 0x016llx\n"prev_far);
u64                priv->prev_fiv =   68  76}
  10#endif
  75         if (priv->chanmasr &a1)srr    if (IC_FIR_ECC_SINGLE_0_EVEev_fir" class="CBf">IC_FIR_ECC_SINGLE_0_EVEev_fa) 57{
u64                noiv = priv->reiv->cbdf_ecc_error a_0ev_fir" class="">cbdf_ecc_error a_0ev_far);
  52          , pri|v = IC_FIR_ECC_SINGLE_0_RESEE_SHIFT" class="CBf">IC_FIR_ECC_SINGLE_0_RESEEev_fr);
  63                cell_edac_count_c, mci      0, noar);
  68  76}
  75         if (priv->chanmasr &a2)srr    if (IC_FIR_ECC_SINGLE_1_EVEev_fir" class="CBf">IC_FIR_ECC_SINGLE_1_EVEev_fa) 57{
u64                noiv = priv->reiv->cbdf_ecc_error a_1ev_fir" class="">cbdf_ecc_error a_1">noar);
u64                pri|v = IC_FIR_ECC_SINGLE_1_RESEE_SHIFT" class="CBf">IC_FIR_ECC_SINGLE_1_RESEEev_fr);
  68                cell_edac_count_c, mci1     0, noar);
  68  76}
  75         if (priv->chanmasr &a1)srr    if (IC_FIR_ECC_MULTI_0_EVEev_fir" class="CBf">IC_FIR_ECC_MULTI_0_EVEev_fa) 57{
u64                noiv = priv->reiv->cbdf_ecc_error a_0ev_fir" class="">cbdf_ecc_error a_0ev_far);
  52          , pri|v = IC_FIR_ECC_MULTI_0_RESEE_SHIFT" class="CBf">IC_FIR_ECC_MULTI_0_RESEEev_fr);
  63                cell_edac_count_u, mci      0, noar);
  68  76}
  75         if (priv->chanmasr &a2)srr    if (IC_FIR_ECC_MULTI_1_EVEev_fir" class="CBf">IC_FIR_ECC_MULTI_1_EVEev_fa) 57{
u64                noiv = priv->reiv->cbdf_ecc_error a_1ev_fir" class="">cbdf_ecc_error a_1">noar);
u64                pri|v = IC_FIR_ECC_MULTI_1_RESEE_SHIFT" class="CBf">IC_FIR_ECC_MULTI_1_RESEEev_fr);
  68                cell_edac_count_u, mci1     0, noar);
  68  76}
  20
  51         */
  75            pr) 57{
  63                IC_FIR_ECC_EVEN=PAGE_MASK" class="CBf">IC_FIR_ECC_EVEN=PAG">pri| = IC_FIR_ECC_SETN=PAGE_MASK" class="CBf">IC_FIR_ECC_SETN=PAG">noar);
u64                IC_FIR_ECC_RESEEN=PAGE_MASK" class="CBf">IC_FIR_ECC_RESEEN=PAGev_fr);
  45                prr);
u64                priv->reiv->cb=prev_fir" class="">cb=pref">/       u64          (tati)/a> = priv->reiv->cb=prev_fir" class="">cb=pref">ar);
  38
u64                         */
  14#ifdef DEBUG
u64                priv->reiv->cb=prev_fir" class="">cb=pref">ar);
  52          , dev_dbg(mci->pdev, >pr#3le+c  :, ar = 0x016llx\n"prev_far);
  10#endif
  68  76}
  76}
  6}
  78static void mem_ctl_info *mcilass="sref">ar & 0xffff1ac.c#L28"1 id="L28" class="line" n1ame="128">  57{
  59        struct csrow_info               *csrow = mci->csrows[0];
  70        struct   52                *prr);
  59        struct cell_edac_priv           *priv = mci->pvt_info;
  70        struct   52              *  63        int                               68          52                               55
  36  rivebg(u64       bg(sreory"" =   68                struct   6truct   49
  40                 */
   1sreory"err os. If thati37;dget bo"> *ref= willt"> */
   2   3 */
u64                    ar & 0xffff1ac.c#L45"1 id="L45" class="line" n1ame="145">  45                  "filinue/a>>
u64                    priv->nocilass="sref">ar & 0xffff1ac.c#L17"  id="L47" class="line" n1ame="147f">u64                  "filinue/a>>
  68                csrow->first_pagv = PAGE_SHIFT;
u64                PAGE_SHIFT;
  40                csrow->csrow->first_page +   11
  52          rivebg(csrow->  53                       *prgv = csrow->prr);
u64                  >->priv->prgv = prr);
  45                  >->priv->prgv = prr);
u64                  >->priv->firs=csrows" class="nr>firs=t_ing/ = csrow->u64          76}
  68                dev_dbg(mci->pde6}
u64                   /a>, InitializodUE err on node %d">ch= ar = 0x,""<6}
  40                   /a>,  sref">firs= ar = 0lx, nr>firs== ar = 0x016llx\n",
u64                        priv->node, priv->chanma/span>,
  52                  /a> = csrow->first_pade,   63          breakr);
  68  76}
  76}
  6}
  78s, int cell_eobount_ue" class="sref">cell_eoboev_dbk(struct pdcilass="sref">ar & 0xffff1ac.c#L68"1 id="L68" class="line" n1ame="168">  57{
  59        struct cbe_mic_tm_regs __iomem  *regs;
  70        struct mem_ctl_infffffffffffffo *mgs;
  59        struct edlayeel_inffffffffffff>->  70        struct cell_edac_priv           *pr/a>[0];
  73        u64                             no/a>[0];
  74        int                             chanma/e, no/a>[0];
  55
  66        regv = pdow->  67        if (regvv = ar & 0xffff1ac.c#L78"1 id="L78" class="line" n1ame="178">  68          return -/a> = no/a>[0];
  49
  70        prgv = no/a>[0];
  11
  72         */
  73        noiv = reiv->cbmac_cfdev_dbg" class="">cbmac_cfdt_inar);
  68        dev_dbs  if (pdow->pdev, >IC_MNT_CFG;d, ar = 0x%016llx\n"noar);
  75  , chanmaiv<0fo;
u64        if (noir   if (IC_MNT_CFG_CHAN_0_POPev_dbg" class="CBf">IC_MNT_CFG_CHAN_0_POPt_incilass="sref">ar & 0xffff18c.c#L77"18id="L77" class="line" n18me="187f">u64                chanmai|d, a> 21;
  68        if (noir   if (IC_MNT_CFG_CHAN_1_POPev_dbg" class="CBf">IC_MNT_CFG_CHAN_1_POPt_incilass="sref">ar & 0xffff18c.c#L69"18id="L7a>
u64                chanmai|d, a2gt; 21;
  75      , chanmaivd, ) 57{
u64                pdow->pde7{
  52                    /a>, Yuck ! No#37;d, chpopulated ? Abort Dec!016llx\n");
  63          return -/a> = no/a>[0];
  68  76}
  75  , dev_dbs  if (pdow->pdev, InitialcFIRkd, ar = 0x%016llx\n",
u64                reiv->cb=prev_fir" class="">cb=pref">aar);
  77
  68         */
  69        nogv = chanmaivd,3 ? 2 : > 21;
  20
  51        prgv = no/a>[0];
  52          73        prgv =   68        prgv =   75  , 37;d=csrows" class="num>37;d=">no/a>[0];
  66        prgv = no/a>[0];
u64   *mgv = edalloc_error" class="sref">edallocev_dbg(pdow->  68                      sizoofbk(struct cell_edac_praar);
  68      , mgvv = ar & 0xffff2ac.c#L10"2 id="L10" class="line" n2ame="210">  40          return -/a> = no/a>[0];
  51        priv = mci->pvt_info;
  52        priv->regv = regs;
  73        priv->nogv = pdow->  68        priv->chanmask = chanmags;
  75  , mci->pdsk  if (pdow->pdgs;
  66        mci-> = pdgs;
u64   *miv->mecape=node" class=">cell">mecap">prgv = pdgs;
u64   *miv->prgv = pdgs;
  69        mci->prgv, /edac/cel6llx\n";
  70        mci->prgv, MIC6llx\n";
  51        mci->prgv = prbs  if (pdow->pdar);
  52        miv-> = cell_edac_check" class="sref">cell_edac_cher);
  73        mar);
  );
  75  <      */
  66        edadd">e_error" class="sref">edadd">eev_db      mar);
  67        if (  68                pdow->pdev, failedboguregister with EDAC core016llx\n");
u64                edfrede=node" class=">cellmedfredev_db      mar);
  40          return   if (  59  76}
  32
  63  return 0fo;
  76}
  55
  78s, int cellremovount_ue" class="sref">cellremovoev_dbk(struct pdcilass="sref">ar & 0xffff2ac.c#L17"2 id="L37" class="line" n2ame="237f">u57{
  68  k(struct mem_ctl_info *mgv = eddel">e_error" class="sref">eddel">e">prbs  if (pdow->pdar);
  68      , mcilass="sref">ar & 0xffff2ac.c#L40"2 id="L40" class="line" n2ame="240">  40                edfrede=node" class=">cellmedfredev_db      mar);
  63  return 0fo;
  76}
  6}
u78sk(struct   6, int celldref="e=priv" class="+ref">celldref="f">mgv<57{
  45  ./a> = mgggggggggv<57{
u64          ./a> = prg gv, /be-mic6llx\n",
u64          ./a> = u64v =   68  }/span>,
u64  ./a> = cell_eobount_ue" class="sref">cell_eoboev_d/span>,
  40  ./a> = cellremovount_ue" class="sref">cellremovoev_d/span>,
  }fo;
  32
  78s, int   6, int celllinuunt_ue" class="+ref">celllinuev_dbtati)32
u57{
  75  <      */
  66        cbe_mic_tm_re/span>,
u64                          cbdf_ecc_error a_0ev_fir" class="">cbdf_ecc_error a_0ev_fai!v<0xf8ar);
u64   *cbe_mic_tm_re/span>,
u64                              cbdf_ecc_error a_1ev_fir" class="">cbdf_ecc_error a_1">noai!v<0x1b8ar);
  70        cbe_mic_tm_re/span>,
u64                              cbdf_confidev_dbg" class="">cbdf_confid">noai!v<0x218ar);
  52        cbe_mic_tm_re/span>,
  63                              cb=prev_fir" class="">cb=pref">ai!v<0x230ar);
  68        cbe_mic_tm_re/span>,
  45                              cbmac_cfdev_dbg" class="">cbmac_cfdt_inai!v<0x210ar);
  66        cbe_mic_tm_re/span>,
u64                          cbexe_error" class="">cbexet_inai!v<0x208ar);
  38
  59  return   if (prbs  if (celldref="e=priv" class="+ref">celldref="f">mar);
  76}
  11
  78static void   6, int cellexnuunt_ue" class="+ref">cellexnuev_dbtati)32
  57{
  68        prbs  if (celldref="e=priv" class="+ref">celldref="f">mar);
  76}
  6}
        celllinuunt_ue" class="+ref">celllinuev_dar);
        cellexnuunt_ue" class="+ref">cellexnuev_dar);
  49
        GPL6llx\n");
        Benjamin Herrenschmidtssllx\n");
        ECC count DecriveCeda MIC6llx\n");
  
The original LXR software bying o/a>); LXR lassuinuy">pdevo"> *experis="cal f="dion byi/a>); lxr@lasux.no">pd.
lxr.lasux.no kindly hosted byi/a>); Redpill Laspro AS">pdevprovider of Lasux "fisult Decand operations serorm_s sincel1995.