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