linux/drivers/edac/edac_mc_sysfs.c
<<
>>
Prefs
   1/*
   2 * edac_mc kernel module
   3 * (C) 2005-2007 Linux Networx (http://lnxi.com)
   4 *
   5 * This file may be distributed under the terms of the
   6 * GNU General Public License.
   7 *
   8 * Written Doug Thompson <norsk5@xmission.com> www.softwarebitmaker.com
   9 *
  10 */
  11
  12#include <linux/ctype.h>
  13#include <linux/bug.h>
  14
  15#include "edac_core.h"
  16#include "edac_module.h"
  17
  18
  19/* MC EDAC Controls, setable by module parameter, and sysfs */
  20static int edac_mc_log_ue = 1;
  21static int edac_mc_log_ce = 1;
  22static int edac_mc_panic_on_ue;
  23static int edac_mc_poll_msec = 1000;
  24
  25/* Getter functions for above */
  26int edac_mc_get_log_ue(void)
  27{
  28        return edac_mc_log_ue;
  29}
  30
  31int edac_mc_get_log_ce(void)
  32{
  33        return edac_mc_log_ce;
  34}
  35
  36int edac_mc_get_panic_on_ue(void)
  37{
  38        return edac_mc_panic_on_ue;
  39}
  40
  41/* this is temporary */
  42int edac_mc_get_poll_msec(void)
  43{
  44        return edac_mc_poll_msec;
  45}
  46
  47static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
  48{
  49        long l;
  50        int ret;
  51
  52        if (!val)
  53                return -EINVAL;
  54
  55        ret = strict_strtol(val, 0, &l);
  56        if (ret == -EINVAL || ((int)l != l))
  57                return -EINVAL;
  58        *((int *)kp->arg) = l;
  59
  60        /* notify edac_mc engine to reset the poll period */
  61        edac_mc_reset_delay_period(l);
  62
  63        return 0;
  64}
  65
  66/* Parameter declarations for above */
  67module_param(edac_mc_panic_on_ue, int, 0644);
  68MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
  69module_param(edac_mc_log_ue, int, 0644);
  70MODULE_PARM_DESC(edac_mc_log_ue,
  71                 "Log uncorrectable error to console: 0=off 1=on");
  72module_param(edac_mc_log_ce, int, 0644);
  73MODULE_PARM_DESC(edac_mc_log_ce,
  74                 "Log correctable error to console: 0=off 1=on");
  75module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int,
  76                  &edac_mc_poll_msec, 0644);
  77MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
  78
  79/*
  80 * various constants for Memory Controllers
  81 */
  82static const char *mem_types[] = {
  83        [MEM_EMPTY] = "Empty",
  84        [MEM_RESERVED] = "Reserved",
  85        [MEM_UNKNOWN] = "Unknown",
  86        [MEM_FPM] = "FPM",
  87        [MEM_EDO] = "EDO",
  88        [MEM_BEDO] = "BEDO",
  89        [MEM_SDR] = "Unbuffered-SDR",
  90        [MEM_RDR] = "Registered-SDR",
  91        [MEM_DDR] = "Unbuffered-DDR",
  92        [MEM_RDDR] = "Registered-DDR",
  93        [MEM_RMBS] = "RMBS",
  94        [MEM_DDR2] = "Unbuffered-DDR2",
  95        [MEM_FB_DDR2] = "FullyBuffered-DDR2",
  96        [MEM_RDDR2] = "Registered-DDR2",
  97        [MEM_XDR] = "XDR"
  98};
  99
 100static const char *dev_types[] = {
 101        [DEV_UNKNOWN] = "Unknown",
 102        [DEV_X1] = "x1",
 103        [DEV_X2] = "x2",
 104        [DEV_X4] = "x4",
 105        [DEV_X8] = "x8",
 106        [DEV_X16] = "x16",
 107        [DEV_X32] = "x32",
 108        [DEV_X64] = "x64"
 109};
 110
 111static const char *edac_caps[] = {
 112        [EDAC_UNKNOWN] = "Unknown",
 113        [EDAC_NONE] = "None",
 114        [EDAC_RESERVED] = "Reserved",
 115        [EDAC_PARITY] = "PARITY",
 116        [EDAC_EC] = "EC",
 117        [EDAC_SECDED] = "SECDED",
 118        [EDAC_S2ECD2ED] = "S2ECD2ED",
 119        [EDAC_S4ECD4ED] = "S4ECD4ED",
 120        [EDAC_S8ECD8ED] = "S8ECD8ED",
 121        [EDAC_S16ECD16ED] = "S16ECD16ED"
 122};
 123
 124
 125
 126static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
 127{
 128        int *value = (int *)ptr;
 129
 130        if (isdigit(*buffer))
 131                *value = simple_strtoul(buffer, NULL, 0);
 132
 133        return count;
 134}
 135
 136
 137/* EDAC sysfs CSROW data structures and methods
 138 */
 139
 140/* Set of more default csrow<id> attribute show/store functions */
 141static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data,
 142                                int private)
 143{
 144        return sprintf(data, "%u\n", csrow->ue_count);
 145}
 146
 147static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data,
 148                                int private)
 149{
 150        return sprintf(data, "%u\n", csrow->ce_count);
 151}
 152
 153static ssize_t csrow_size_show(struct csrow_info *csrow, char *data,
 154                                int private)
 155{
 156        return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
 157}
 158
 159static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
 160                                int private)
 161{
 162        return sprintf(data, "%s\n", mem_types[csrow->mtype]);
 163}
 164
 165static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data,
 166                                int private)
 167{
 168        return sprintf(data, "%s\n", dev_types[csrow->dtype]);
 169}
 170
 171static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
 172                                int private)
 173{
 174        return sprintf(data, "%s\n", edac_caps[csrow->edac_mode]);
 175}
 176
 177/* show/store functions for DIMM Label attributes */
 178static ssize_t channel_dimm_label_show(struct csrow_info *csrow,
 179                                char *data, int channel)
 180{
 181        /* if field has not been initialized, there is nothing to send */
 182        if (!csrow->channels[channel].label[0])
 183                return 0;
 184
 185        return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
 186                        csrow->channels[channel].label);
 187}
 188
 189static ssize_t channel_dimm_label_store(struct csrow_info *csrow,
 190                                        const char *data,
 191                                        size_t count, int channel)
 192{
 193        ssize_t max_size = 0;
 194
 195        max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
 196        strncpy(csrow->channels[channel].label, data, max_size);
 197        csrow->channels[channel].label[max_size] = '\0';
 198
 199        return max_size;
 200}
 201
 202/* show function for dynamic chX_ce_count attribute */
 203static ssize_t channel_ce_count_show(struct csrow_info *csrow,
 204                                char *data, int channel)
 205{
 206        return sprintf(data, "%u\n", csrow->channels[channel].ce_count);
 207}
 208
 209/* csrow specific attribute structure */
 210struct csrowdev_attribute {
 211        struct attribute attr;
 212         ssize_t(*show) (struct csrow_info *, char *, int);
 213         ssize_t(*store) (struct csrow_info *, const char *, size_t, int);
 214        int private;
 215};
 216
 217#define to_csrow(k) container_of(k, struct csrow_info, kobj)
 218#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
 219
 220/* Set of show/store higher level functions for default csrow attributes */
 221static ssize_t csrowdev_show(struct kobject *kobj,
 222                        struct attribute *attr, char *buffer)
 223{
 224        struct csrow_info *csrow = to_csrow(kobj);
 225        struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
 226
 227        if (csrowdev_attr->show)
 228                return csrowdev_attr->show(csrow,
 229                                        buffer, csrowdev_attr->private);
 230        return -EIO;
 231}
 232
 233static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
 234                        const char *buffer, size_t count)
 235{
 236        struct csrow_info *csrow = to_csrow(kobj);
 237        struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
 238
 239        if (csrowdev_attr->store)
 240                return csrowdev_attr->store(csrow,
 241                                        buffer,
 242                                        count, csrowdev_attr->private);
 243        return -EIO;
 244}
 245
 246static struct sysfs_ops csrowfs_ops = {
 247        .show = csrowdev_show,
 248        .store = csrowdev_store
 249};
 250
 251#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private)        \
 252static struct csrowdev_attribute attr_##_name = {                       \
 253        .attr = {.name = __stringify(_name), .mode = _mode },   \
 254        .show   = _show,                                        \
 255        .store  = _store,                                       \
 256        .private = _private,                                    \
 257};
 258
 259/* default cwrow<id>/attribute files */
 260CSROWDEV_ATTR(size_mb, S_IRUGO, csrow_size_show, NULL, 0);
 261CSROWDEV_ATTR(dev_type, S_IRUGO, csrow_dev_type_show, NULL, 0);
 262CSROWDEV_ATTR(mem_type, S_IRUGO, csrow_mem_type_show, NULL, 0);
 263CSROWDEV_ATTR(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL, 0);
 264CSROWDEV_ATTR(ue_count, S_IRUGO, csrow_ue_count_show, NULL, 0);
 265CSROWDEV_ATTR(ce_count, S_IRUGO, csrow_ce_count_show, NULL, 0);
 266
 267/* default attributes of the CSROW<id> object */
 268static struct csrowdev_attribute *default_csrow_attr[] = {
 269        &attr_dev_type,
 270        &attr_mem_type,
 271        &attr_edac_mode,
 272        &attr_size_mb,
 273        &attr_ue_count,
 274        &attr_ce_count,
 275        NULL,
 276};
 277
 278/* possible dynamic channel DIMM Label attribute files */
 279CSROWDEV_ATTR(ch0_dimm_label, S_IRUGO | S_IWUSR,
 280        channel_dimm_label_show, channel_dimm_label_store, 0);
 281CSROWDEV_ATTR(ch1_dimm_label, S_IRUGO | S_IWUSR,
 282        channel_dimm_label_show, channel_dimm_label_store, 1);
 283CSROWDEV_ATTR(ch2_dimm_label, S_IRUGO | S_IWUSR,
 284        channel_dimm_label_show, channel_dimm_label_store, 2);
 285CSROWDEV_ATTR(ch3_dimm_label, S_IRUGO | S_IWUSR,
 286        channel_dimm_label_show, channel_dimm_label_store, 3);
 287CSROWDEV_ATTR(ch4_dimm_label, S_IRUGO | S_IWUSR,
 288        channel_dimm_label_show, channel_dimm_label_store, 4);
 289CSROWDEV_ATTR(ch5_dimm_label, S_IRUGO | S_IWUSR,
 290        channel_dimm_label_show, channel_dimm_label_store, 5);
 291
 292/* Total possible dynamic DIMM Label attribute file table */
 293static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = {
 294        &attr_ch0_dimm_label,
 295        &attr_ch1_dimm_label,
 296        &attr_ch2_dimm_label,
 297        &attr_ch3_dimm_label,
 298        &attr_ch4_dimm_label,
 299        &attr_ch5_dimm_label
 300};
 301
 302/* possible dynamic channel ce_count attribute files */
 303CSROWDEV_ATTR(ch0_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 0);
 304CSROWDEV_ATTR(ch1_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 1);
 305CSROWDEV_ATTR(ch2_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 2);
 306CSROWDEV_ATTR(ch3_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 3);
 307CSROWDEV_ATTR(ch4_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 4);
 308CSROWDEV_ATTR(ch5_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 5);
 309
 310/* Total possible dynamic ce_count attribute file table */
 311static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = {
 312        &attr_ch0_ce_count,
 313        &attr_ch1_ce_count,
 314        &attr_ch2_ce_count,
 315        &attr_ch3_ce_count,
 316        &attr_ch4_ce_count,
 317        &attr_ch5_ce_count
 318};
 319
 320#define EDAC_NR_CHANNELS        6
 321
 322/* Create dynamic CHANNEL files, indexed by 'chan',  under specifed CSROW */
 323static int edac_create_channel_files(struct kobject *kobj, int chan)
 324{
 325        int err = -ENODEV;
 326
 327        if (chan >= EDAC_NR_CHANNELS)
 328                return err;
 329
 330        /* create the DIMM label attribute file */
 331        err = sysfs_create_file(kobj,
 332                                (struct attribute *)
 333                                dynamic_csrow_dimm_attr[chan]);
 334
 335        if (!err) {
 336                /* create the CE Count attribute file */
 337                err = sysfs_create_file(kobj,
 338                                        (struct attribute *)
 339                                        dynamic_csrow_ce_count_attr[chan]);
 340        } else {
 341                debugf1("%s()  dimm labels and ce_count files created",
 342                        __func__);
 343        }
 344
 345        return err;
 346}
 347
 348/* No memory to release for this kobj */
 349static void edac_csrow_instance_release(struct kobject *kobj)
 350{
 351        struct mem_ctl_info *mci;
 352        struct csrow_info *cs;
 353
 354        debugf1("%s()\n", __func__);
 355
 356        cs = container_of(kobj, struct csrow_info, kobj);
 357        mci = cs->mci;
 358
 359        kobject_put(&mci->edac_mci_kobj);
 360}
 361
 362/* the kobj_type instance for a CSROW */
 363static struct kobj_type ktype_csrow = {
 364        .release = edac_csrow_instance_release,
 365        .sysfs_ops = &csrowfs_ops,
 366        .default_attrs = (struct attribute **)default_csrow_attr,
 367};
 368
 369/* Create a CSROW object under specifed edac_mc_device */
 370static int edac_create_csrow_object(struct mem_ctl_info *mci,
 371                                        struct csrow_info *csrow, int index)
 372{
 373        struct kobject *kobj_mci = &mci->edac_mci_kobj;
 374        struct kobject *kobj;
 375        int chan;
 376        int err;
 377
 378        /* generate ..../edac/mc/mc<id>/csrow<index>   */
 379        memset(&csrow->kobj, 0, sizeof(csrow->kobj));
 380        csrow->mci = mci;       /* include container up link */
 381
 382        /* bump the mci instance's kobject's ref count */
 383        kobj = kobject_get(&mci->edac_mci_kobj);
 384        if (!kobj) {
 385                err = -ENODEV;
 386                goto err_out;
 387        }
 388
 389        /* Instanstiate the csrow object */
 390        err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci,
 391                                   "csrow%d", index);
 392        if (err)
 393                goto err_release_top_kobj;
 394
 395        /* At this point, to release a csrow kobj, one must
 396         * call the kobject_put and allow that tear down
 397         * to work the releasing
 398         */
 399
 400        /* Create the dyanmic attribute files on this csrow,
 401         * namely, the DIMM labels and the channel ce_count
 402         */
 403        for (chan = 0; chan < csrow->nr_channels; chan++) {
 404                err = edac_create_channel_files(&csrow->kobj, chan);
 405                if (err) {
 406                        /* special case the unregister here */
 407                        kobject_put(&csrow->kobj);
 408                        goto err_out;
 409                }
 410        }
 411        kobject_uevent(&csrow->kobj, KOBJ_ADD);
 412        return 0;
 413
 414        /* error unwind stack */
 415err_release_top_kobj:
 416        kobject_put(&mci->edac_mci_kobj);
 417
 418err_out:
 419        return err;
 420}
 421
 422/* default sysfs methods and data structures for the main MCI kobject */
 423
 424static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
 425                                        const char *data, size_t count)
 426{
 427        int row, chan;
 428
 429        mci->ue_noinfo_count = 0;
 430        mci->ce_noinfo_count = 0;
 431        mci->ue_count = 0;
 432        mci->ce_count = 0;
 433
 434        for (row = 0; row < mci->nr_csrows; row++) {
 435                struct csrow_info *ri = &mci->csrows[row];
 436
 437                ri->ue_count = 0;
 438                ri->ce_count = 0;
 439
 440                for (chan = 0; chan < ri->nr_channels; chan++)
 441                        ri->channels[chan].ce_count = 0;
 442        }
 443
 444        mci->start_time = jiffies;
 445        return count;
 446}
 447
 448/* memory scrubbing */
 449static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
 450                                        const char *data, size_t count)
 451{
 452        u32 bandwidth = -1;
 453
 454        if (mci->set_sdram_scrub_rate) {
 455
 456                memctrl_int_store(&bandwidth, data, count);
 457
 458                if (!(*mci->set_sdram_scrub_rate) (mci, &bandwidth)) {
 459                        edac_printk(KERN_DEBUG, EDAC_MC,
 460                                "Scrub rate set successfully, applied: %d\n",
 461                                bandwidth);
 462                } else {
 463                        /* FIXME: error codes maybe? */
 464                        edac_printk(KERN_DEBUG, EDAC_MC,
 465                                "Scrub rate set FAILED, could not apply: %d\n",
 466                                bandwidth);
 467                }
 468        } else {
 469                /* FIXME: produce "not implemented" ERROR for user-side. */
 470                edac_printk(KERN_WARNING, EDAC_MC,
 471                        "Memory scrubbing 'set'control is not implemented!\n");
 472        }
 473        return count;
 474}
 475
 476static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
 477{
 478        u32 bandwidth = -1;
 479
 480        if (mci->get_sdram_scrub_rate) {
 481                if (!(*mci->get_sdram_scrub_rate) (mci, &bandwidth)) {
 482                        edac_printk(KERN_DEBUG, EDAC_MC,
 483                                "Scrub rate successfully, fetched: %d\n",
 484                                bandwidth);
 485                } else {
 486                        /* FIXME: error codes maybe? */
 487                        edac_printk(KERN_DEBUG, EDAC_MC,
 488                                "Scrub rate fetch FAILED, got: %d\n",
 489                                bandwidth);
 490                }
 491        } else {
 492                /* FIXME: produce "not implemented" ERROR for user-side.  */
 493                edac_printk(KERN_WARNING, EDAC_MC,
 494                        "Memory scrubbing 'get' control is not implemented\n");
 495        }
 496        return sprintf(data, "%d\n", bandwidth);
 497}
 498
 499/* default attribute files for the MCI object */
 500static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
 501{
 502        return sprintf(data, "%d\n", mci->ue_count);
 503}
 504
 505static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
 506{
 507        return sprintf(data, "%d\n", mci->ce_count);
 508}
 509
 510static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
 511{
 512        return sprintf(data, "%d\n", mci->ce_noinfo_count);
 513}
 514
 515static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
 516{
 517        return sprintf(data, "%d\n", mci->ue_noinfo_count);
 518}
 519
 520static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
 521{
 522        return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ);
 523}
 524
 525static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
 526{
 527        return sprintf(data, "%s\n", mci->ctl_name);
 528}
 529
 530static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
 531{
 532        int total_pages, csrow_idx;
 533
 534        for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
 535                csrow_idx++) {
 536                struct csrow_info *csrow = &mci->csrows[csrow_idx];
 537
 538                if (!csrow->nr_pages)
 539                        continue;
 540
 541                total_pages += csrow->nr_pages;
 542        }
 543
 544        return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages));
 545}
 546
 547#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
 548#define to_mcidev_attr(a) container_of(a,struct mcidev_sysfs_attribute,attr)
 549
 550/* MCI show/store functions for top most object */
 551static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
 552                        char *buffer)
 553{
 554        struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
 555        struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 556
 557        if (mcidev_attr->show)
 558                return mcidev_attr->show(mem_ctl_info, buffer);
 559
 560        return -EIO;
 561}
 562
 563static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
 564                        const char *buffer, size_t count)
 565{
 566        struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
 567        struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 568
 569        if (mcidev_attr->store)
 570                return mcidev_attr->store(mem_ctl_info, buffer, count);
 571
 572        return -EIO;
 573}
 574
 575/* Intermediate show/store table */
 576static struct sysfs_ops mci_ops = {
 577        .show = mcidev_show,
 578        .store = mcidev_store
 579};
 580
 581#define MCIDEV_ATTR(_name,_mode,_show,_store)                   \
 582static struct mcidev_sysfs_attribute mci_attr_##_name = {                       \
 583        .attr = {.name = __stringify(_name), .mode = _mode },   \
 584        .show   = _show,                                        \
 585        .store  = _store,                                       \
 586};
 587
 588/* default Control file */
 589MCIDEV_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store);
 590
 591/* default Attribute files */
 592MCIDEV_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL);
 593MCIDEV_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL);
 594MCIDEV_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL);
 595MCIDEV_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL);
 596MCIDEV_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL);
 597MCIDEV_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL);
 598MCIDEV_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);
 599
 600/* memory scrubber attribute file */
 601MCIDEV_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show,
 602        mci_sdram_scrub_rate_store);
 603
 604static struct mcidev_sysfs_attribute *mci_attr[] = {
 605        &mci_attr_reset_counters,
 606        &mci_attr_mc_name,
 607        &mci_attr_size_mb,
 608        &mci_attr_seconds_since_reset,
 609        &mci_attr_ue_noinfo_count,
 610        &mci_attr_ce_noinfo_count,
 611        &mci_attr_ue_count,
 612        &mci_attr_ce_count,
 613        &mci_attr_sdram_scrub_rate,
 614        NULL
 615};
 616
 617
 618/*
 619 * Release of a MC controlling instance
 620 *
 621 *      each MC control instance has the following resources upon entry:
 622 *              a) a ref count on the top memctl kobj
 623 *              b) a ref count on this module
 624 *
 625 *      this function must decrement those ref counts and then
 626 *      issue a free on the instance's memory
 627 */
 628static void edac_mci_control_release(struct kobject *kobj)
 629{
 630        struct mem_ctl_info *mci;
 631
 632        mci = to_mci(kobj);
 633
 634        debugf0("%s() mci instance idx=%d releasing\n", __func__, mci->mc_idx);
 635
 636        /* decrement the module ref count */
 637        module_put(mci->owner);
 638
 639        /* free the mci instance memory here */
 640        kfree(mci);
 641}
 642
 643static struct kobj_type ktype_mci = {
 644        .release = edac_mci_control_release,
 645        .sysfs_ops = &mci_ops,
 646        .default_attrs = (struct attribute **)mci_attr,
 647};
 648
 649/* EDAC memory controller sysfs kset:
 650 *      /sys/devices/system/edac/mc
 651 */
 652static struct kset *mc_kset;
 653
 654/*
 655 * edac_mc_register_sysfs_main_kobj
 656 *
 657 *      setups and registers the main kobject for each mci
 658 */
 659int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
 660{
 661        struct kobject *kobj_mci;
 662        int err;
 663
 664        debugf1("%s()\n", __func__);
 665
 666        kobj_mci = &mci->edac_mci_kobj;
 667
 668        /* Init the mci's kobject */
 669        memset(kobj_mci, 0, sizeof(*kobj_mci));
 670
 671        /* Record which module 'owns' this control structure
 672         * and bump the ref count of the module
 673         */
 674        mci->owner = THIS_MODULE;
 675
 676        /* bump ref count on this module */
 677        if (!try_module_get(mci->owner)) {
 678                err = -ENODEV;
 679                goto fail_out;
 680        }
 681
 682        /* this instance become part of the mc_kset */
 683        kobj_mci->kset = mc_kset;
 684
 685        /* register the mc<id> kobject to the mc_kset */
 686        err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
 687                                   "mc%d", mci->mc_idx);
 688        if (err) {
 689                debugf1("%s()Failed to register '.../edac/mc%d'\n",
 690                        __func__, mci->mc_idx);
 691                goto kobj_reg_fail;
 692        }
 693        kobject_uevent(kobj_mci, KOBJ_ADD);
 694
 695        /* At this point, to 'free' the control struct,
 696         * edac_mc_unregister_sysfs_main_kobj() must be used
 697         */
 698
 699        debugf1("%s() Registered '.../edac/mc%d' kobject\n",
 700                __func__, mci->mc_idx);
 701
 702        return 0;
 703
 704        /* Error exit stack */
 705
 706kobj_reg_fail:
 707        module_put(mci->owner);
 708
 709fail_out:
 710        return err;
 711}
 712
 713/*
 714 * edac_mc_register_sysfs_main_kobj
 715 *
 716 *      tears down and the main mci kobject from the mc_kset
 717 */
 718void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
 719{
 720        /* delete the kobj from the mc_kset */
 721        kobject_put(&mci->edac_mci_kobj);
 722}
 723
 724#define EDAC_DEVICE_SYMLINK     "device"
 725
 726/*
 727 * edac_create_mci_instance_attributes
 728 *      create MC driver specific attributes at the topmost level
 729 *      directory of this mci instance.
 730 */
 731static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
 732{
 733        int err;
 734        struct mcidev_sysfs_attribute *sysfs_attrib;
 735
 736        /* point to the start of the array and iterate over it
 737         * adding each attribute listed to this mci instance's kobject
 738         */
 739        sysfs_attrib = mci->mc_driver_sysfs_attributes;
 740
 741        while (sysfs_attrib && sysfs_attrib->attr.name) {
 742                err = sysfs_create_file(&mci->edac_mci_kobj,
 743                                        (struct attribute*) sysfs_attrib);
 744                if (err) {
 745                        return err;
 746                }
 747
 748                sysfs_attrib++;
 749        }
 750
 751        return 0;
 752}
 753
 754/*
 755 * edac_remove_mci_instance_attributes
 756 *      remove MC driver specific attributes at the topmost level
 757 *      directory of this mci instance.
 758 */
 759static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci)
 760{
 761        struct mcidev_sysfs_attribute *sysfs_attrib;
 762
 763        /* point to the start of the array and iterate over it
 764         * adding each attribute listed to this mci instance's kobject
 765         */
 766        sysfs_attrib = mci->mc_driver_sysfs_attributes;
 767
 768        /* loop if there are attributes and until we hit a NULL entry */
 769        while (sysfs_attrib && sysfs_attrib->attr.name) {
 770                sysfs_remove_file(&mci->edac_mci_kobj,
 771                                        (struct attribute *) sysfs_attrib);
 772                sysfs_attrib++;
 773        }
 774}
 775
 776
 777/*
 778 * Create a new Memory Controller kobject instance,
 779 *      mc<id> under the 'mc' directory
 780 *
 781 * Return:
 782 *      0       Success
 783 *      !0      Failure
 784 */
 785int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
 786{
 787        int i;
 788        int err;
 789        struct csrow_info *csrow;
 790        struct kobject *kobj_mci = &mci->edac_mci_kobj;
 791
 792        debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
 793
 794        /* create a symlink for the device */
 795        err = sysfs_create_link(kobj_mci, &mci->dev->kobj,
 796                                EDAC_DEVICE_SYMLINK);
 797        if (err) {
 798                debugf1("%s() failure to create symlink\n", __func__);
 799                goto fail0;
 800        }
 801
 802        /* If the low level driver desires some attributes,
 803         * then create them now for the driver.
 804         */
 805        if (mci->mc_driver_sysfs_attributes) {
 806                err = edac_create_mci_instance_attributes(mci);
 807                if (err) {
 808                        debugf1("%s() failure to create mci attributes\n",
 809                                __func__);
 810                        goto fail0;
 811                }
 812        }
 813
 814        /* Make directories for each CSROW object under the mc<id> kobject
 815         */
 816        for (i = 0; i < mci->nr_csrows; i++) {
 817                csrow = &mci->csrows[i];
 818
 819                /* Only expose populated CSROWs */
 820                if (csrow->nr_pages > 0) {
 821                        err = edac_create_csrow_object(mci, csrow, i);
 822                        if (err) {
 823                                debugf1("%s() failure: create csrow %d obj\n",
 824                                        __func__, i);
 825                                goto fail1;
 826                        }
 827                }
 828        }
 829
 830        return 0;
 831
 832        /* CSROW error: backout what has already been registered,  */
 833fail1:
 834        for (i--; i >= 0; i--) {
 835                if (csrow->nr_pages > 0) {
 836                        kobject_put(&mci->csrows[i].kobj);
 837                }
 838        }
 839
 840        /* remove the mci instance's attributes, if any */
 841        edac_remove_mci_instance_attributes(mci);
 842
 843        /* remove the symlink */
 844        sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
 845
 846fail0:
 847        return err;
 848}
 849
 850/*
 851 * remove a Memory Controller instance
 852 */
 853void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
 854{
 855        int i;
 856
 857        debugf0("%s()\n", __func__);
 858
 859        /* remove all csrow kobjects */
 860        for (i = 0; i < mci->nr_csrows; i++) {
 861                if (mci->csrows[i].nr_pages > 0) {
 862                        debugf0("%s()  unreg csrow-%d\n", __func__, i);
 863                        kobject_put(&mci->csrows[i].kobj);
 864                }
 865        }
 866
 867        debugf0("%s()  remove_link\n", __func__);
 868
 869        /* remove the symlink */
 870        sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
 871
 872        debugf0("%s()  remove_mci_instance\n", __func__);
 873
 874        /* remove this mci instance's attribtes */
 875        edac_remove_mci_instance_attributes(mci);
 876
 877        debugf0("%s()  unregister this mci kobj\n", __func__);
 878
 879        /* unregister this instance's kobject */
 880        kobject_put(&mci->edac_mci_kobj);
 881}
 882
 883
 884
 885
 886/*
 887 * edac_setup_sysfs_mc_kset(void)
 888 *
 889 * Initialize the mc_kset for the 'mc' entry
 890 *      This requires creating the top 'mc' directory with a kset
 891 *      and its controls/attributes.
 892 *
 893 *      To this 'mc' kset, instance 'mci' will be grouped as children.
 894 *
 895 * Return:  0 SUCCESS
 896 *         !0 FAILURE error code
 897 */
 898int edac_sysfs_setup_mc_kset(void)
 899{
 900        int err = 0;
 901        struct sysdev_class *edac_class;
 902
 903        debugf1("%s()\n", __func__);
 904
 905        /* get the /sys/devices/system/edac class reference */
 906        edac_class = edac_get_edac_class();
 907        if (edac_class == NULL) {
 908                debugf1("%s() no edac_class error=%d\n", __func__, err);
 909                goto fail_out;
 910        }
 911
 912        /* Init the MC's kobject */
 913        mc_kset = kset_create_and_add("mc", NULL, &edac_class->kset.kobj);
 914        if (!mc_kset) {
 915                err = -ENOMEM;
 916                debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
 917                goto fail_out;
 918        }
 919
 920        debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
 921
 922        return 0;
 923
 924
 925        /* error unwind stack */
 926fail_out:
 927        return err;
 928}
 929
 930/*
 931 * edac_sysfs_teardown_mc_kset
 932 *
 933 *      deconstruct the mc_ket for memory controllers
 934 */
 935void edac_sysfs_teardown_mc_kset(void)
 936{
 937        kset_unregister(mc_kset);
 938}
 939
 940