linux/drivers/edac/i82860_edac.c
<<
>>
Prefs
   1/*
   2 * Intel 82860 Memory Controller kernel module
   3 * (C) 2005 Red Hat (http://www.redhat.com)
   4 * This file may be distributed under the terms of the
   5 * GNU General Public License.
   6 *
   7 * Written by Ben Woodard <woodard@redhat.com>
   8 * shamelessly copied from and based upon the edac_i82875 driver
   9 * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/init.h>
  14#include <linux/pci.h>
  15#include <linux/pci_ids.h>
  16#include <linux/edac.h>
  17#include "edac_core.h"
  18
  19#define  I82860_REVISION " Ver: 2.0.2 " __DATE__
  20#define EDAC_MOD_STR    "i82860_edac"
  21
  22#define i82860_printk(level, fmt, arg...) \
  23        edac_printk(level, "i82860", fmt, ##arg)
  24
  25#define i82860_mc_printk(mci, level, fmt, arg...) \
  26        edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
  27
  28#ifndef PCI_DEVICE_ID_INTEL_82860_0
  29#define PCI_DEVICE_ID_INTEL_82860_0     0x2531
  30#endif                          /* PCI_DEVICE_ID_INTEL_82860_0 */
  31
  32#define I82860_MCHCFG 0x50
  33#define I82860_GBA 0x60
  34#define I82860_GBA_MASK 0x7FF
  35#define I82860_GBA_SHIFT 24
  36#define I82860_ERRSTS 0xC8
  37#define I82860_EAP 0xE4
  38#define I82860_DERRCTL_STS 0xE2
  39
  40enum i82860_chips {
  41        I82860 = 0,
  42};
  43
  44struct i82860_dev_info {
  45        const char *ctl_name;
  46};
  47
  48struct i82860_error_info {
  49        u16 errsts;
  50        u32 eap;
  51        u16 derrsyn;
  52        u16 errsts2;
  53};
  54
  55static const struct i82860_dev_info i82860_devs[] = {
  56        [I82860] = {
  57                .ctl_name = "i82860"},
  58};
  59
  60static struct pci_dev *mci_pdev;        /* init dev: in case that AGP code
  61                                         * has already registered driver
  62                                         */
  63static struct edac_pci_ctl_info *i82860_pci;
  64
  65static void i82860_get_error_info(struct mem_ctl_info *mci,
  66                                struct i82860_error_info *info)
  67{
  68        struct pci_dev *pdev;
  69
  70        pdev = to_pci_dev(mci->dev);
  71
  72        /*
  73         * This is a mess because there is no atomic way to read all the
  74         * registers at once and the registers can transition from CE being
  75         * overwritten by UE.
  76         */
  77        pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts);
  78        pci_read_config_dword(pdev, I82860_EAP, &info->eap);
  79        pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
  80        pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts2);
  81
  82        pci_write_bits16(pdev, I82860_ERRSTS, 0x0003, 0x0003);
  83
  84        /*
  85         * If the error is the same for both reads then the first set of reads
  86         * is valid.  If there is a change then there is a CE no info and the
  87         * second set of reads is valid and should be UE info.
  88         */
  89        if (!(info->errsts2 & 0x0003))
  90                return;
  91
  92        if ((info->errsts ^ info->errsts2) & 0x0003) {
  93                pci_read_config_dword(pdev, I82860_EAP, &info->eap);
  94                pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
  95        }
  96}
  97
  98static int i82860_process_error_info(struct mem_ctl_info *mci,
  99                                struct i82860_error_info *info,
 100                                int handle_errors)
 101{
 102        int row;
 103
 104        if (!(info->errsts2 & 0x0003))
 105                return 0;
 106
 107        if (!handle_errors)
 108                return 1;
 109
 110        if ((info->errsts ^ info->errsts2) & 0x0003) {
 111                edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
 112                info->errsts = info->errsts2;
 113        }
 114
 115        info->eap >>= PAGE_SHIFT;
 116        row = edac_mc_find_csrow_by_page(mci, info->eap);
 117
 118        if (info->errsts & 0x0002)
 119                edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
 120        else
 121                edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0,
 122                                "i82860 UE");
 123
 124        return 1;
 125}
 126
 127static void i82860_check(struct mem_ctl_info *mci)
 128{
 129        struct i82860_error_info info;
 130
 131        debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
 132        i82860_get_error_info(mci, &info);
 133        i82860_process_error_info(mci, &info, 1);
 134}
 135
 136static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
 137{
 138        unsigned long last_cumul_size;
 139        u16 mchcfg_ddim;        /* DRAM Data Integrity Mode 0=none, 2=edac */
 140        u16 value;
 141        u32 cumul_size;
 142        struct csrow_info *csrow;
 143        int index;
 144
 145        pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim);
 146        mchcfg_ddim = mchcfg_ddim & 0x180;
 147        last_cumul_size = 0;
 148
 149        /* The group row boundary (GRA) reg values are boundary address
 150         * for each DRAM row with a granularity of 16MB.  GRA regs are
 151         * cumulative; therefore GRA15 will contain the total memory contained
 152         * in all eight rows.
 153         */
 154        for (index = 0; index < mci->nr_csrows; index++) {
 155                csrow = &mci->csrows[index];
 156                pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
 157                cumul_size = (value & I82860_GBA_MASK) <<
 158                        (I82860_GBA_SHIFT - PAGE_SHIFT);
 159                debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
 160                        cumul_size);
 161
 162                if (cumul_size == last_cumul_size)
 163                        continue;       /* not populated */
 164
 165                csrow->first_page = last_cumul_size;
 166                csrow->last_page = cumul_size - 1;
 167                csrow->nr_pages = cumul_size - last_cumul_size;
 168                last_cumul_size = cumul_size;
 169                csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
 170                csrow->mtype = MEM_RMBS;
 171                csrow->dtype = DEV_UNKNOWN;
 172                csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
 173        }
 174}
 175
 176static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
 177{
 178        struct mem_ctl_info *mci;
 179        struct i82860_error_info discard;
 180
 181        /* RDRAM has channels but these don't map onto the abstractions that
 182           edac uses.
 183           The device groups from the GRA registers seem to map reasonably
 184           well onto the notion of a chip select row.
 185           There are 16 GRA registers and since the name is associated with
 186           the channel and the GRA registers map to physical devices so we are
 187           going to make 1 channel for group.
 188         */
 189        mci = edac_mc_alloc(0, 16, 1, 0);
 190
 191        if (!mci)
 192                return -ENOMEM;
 193
 194        debugf3("%s(): init mci\n", __func__);
 195        mci->dev = &pdev->dev;
 196        mci->mtype_cap = MEM_FLAG_DDR;
 197        mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
 198        /* I"m not sure about this but I think that all RDRAM is SECDED */
 199        mci->edac_cap = EDAC_FLAG_SECDED;
 200        mci->mod_name = EDAC_MOD_STR;
 201        mci->mod_ver = I82860_REVISION;
 202        mci->ctl_name = i82860_devs[dev_idx].ctl_name;
 203        mci->dev_name = pci_name(pdev);
 204        mci->edac_check = i82860_check;
 205        mci->ctl_page_to_phys = NULL;
 206        i82860_init_csrows(mci, pdev);
 207        i82860_get_error_info(mci, &discard);   /* clear counters */
 208
 209        /* Here we assume that we will never see multiple instances of this
 210         * type of memory controller.  The ID is therefore hardcoded to 0.
 211         */
 212        if (edac_mc_add_mc(mci)) {
 213                debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
 214                goto fail;
 215        }
 216
 217        /* allocating generic PCI control info */
 218        i82860_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
 219        if (!i82860_pci) {
 220                printk(KERN_WARNING
 221                        "%s(): Unable to create PCI control\n",
 222                        __func__);
 223                printk(KERN_WARNING
 224                        "%s(): PCI error report via EDAC not setup\n",
 225                        __func__);
 226        }
 227
 228        /* get this far and it's successful */
 229        debugf3("%s(): success\n", __func__);
 230
 231        return 0;
 232
 233fail:
 234        edac_mc_free(mci);
 235        return -ENODEV;
 236}
 237
 238/* returns count (>= 0), or negative on error */
 239static int __devinit i82860_init_one(struct pci_dev *pdev,
 240                                const struct pci_device_id *ent)
 241{
 242        int rc;
 243
 244        debugf0("%s()\n", __func__);
 245        i82860_printk(KERN_INFO, "i82860 init one\n");
 246
 247        if (pci_enable_device(pdev) < 0)
 248                return -EIO;
 249
 250        rc = i82860_probe1(pdev, ent->driver_data);
 251
 252        if (rc == 0)
 253                mci_pdev = pci_dev_get(pdev);
 254
 255        return rc;
 256}
 257
 258static void __devexit i82860_remove_one(struct pci_dev *pdev)
 259{
 260        struct mem_ctl_info *mci;
 261
 262        debugf0("%s()\n", __func__);
 263
 264        if (i82860_pci)
 265                edac_pci_release_generic_ctl(i82860_pci);
 266
 267        if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
 268                return;
 269
 270        edac_mc_free(mci);
 271}
 272
 273static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
 274        {
 275         PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 276         I82860},
 277        {
 278         0,
 279         }                      /* 0 terminated list. */
 280};
 281
 282MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
 283
 284static struct pci_driver i82860_driver = {
 285        .name = EDAC_MOD_STR,
 286        .probe = i82860_init_one,
 287        .remove = __devexit_p(i82860_remove_one),
 288        .id_table = i82860_pci_tbl,
 289};
 290
 291static int __init i82860_init(void)
 292{
 293        int pci_rc;
 294
 295        debugf3("%s()\n", __func__);
 296
 297       /* Ensure that the OPSTATE is set correctly for POLL or NMI */
 298       opstate_init();
 299
 300        if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
 301                goto fail0;
 302
 303        if (!mci_pdev) {
 304                mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
 305                                        PCI_DEVICE_ID_INTEL_82860_0, NULL);
 306
 307                if (mci_pdev == NULL) {
 308                        debugf0("860 pci_get_device fail\n");
 309                        pci_rc = -ENODEV;
 310                        goto fail1;
 311                }
 312
 313                pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
 314
 315                if (pci_rc < 0) {
 316                        debugf0("860 init fail\n");
 317                        pci_rc = -ENODEV;
 318                        goto fail1;
 319                }
 320        }
 321
 322        return 0;
 323
 324fail1:
 325        pci_unregister_driver(&i82860_driver);
 326
 327fail0:
 328        if (mci_pdev != NULL)
 329                pci_dev_put(mci_pdev);
 330
 331        return pci_rc;
 332}
 333
 334static void __exit i82860_exit(void)
 335{
 336        debugf3("%s()\n", __func__);
 337
 338        pci_unregister_driver(&i82860_driver);
 339
 340        if (mci_pdev != NULL)
 341                pci_dev_put(mci_pdev);
 342}
 343
 344module_init(i82860_init);
 345module_exit(i82860_exit);
 346
 347MODULE_LICENSE("GPL");
 348MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
 349                "Ben Woodard <woodard@redhat.com>");
 350MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
 351
 352module_param(edac_op_state, int, 0444);
 353MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
 354