linux/drivers/edac/edac_mc_sysfs.c
<<
val15 val15Search val15Prefs4 15 v ="ajax+*" method="post" onsubmit="return false;"> v al15 54
5 51/*5 52 * edac_mc kernel module5 53 * (C) 2005-2007 Linux Networx (http://lnxi.com)5 54 *5 55 * This file may be distributed under the terms of the5 56 * GNU General Public License.5 57 *5 58 * Written Doug Thompsn v<norsk5@xmiss .com> www.softwarebitmaker.com5 59 *5 > a> * (c) 2012-2013 - Mauro Car4.4ho Chehabv<mchehab@redhat.com>5 11 * The entire API were re-written, and ported to use struct device5 12 *5 13 */5 1445 15#includev<linux/ctyp3.h>45 16#includev<linux/slab.h>45 17#includev<linux/edac.h>45 18#includev<linux/bug.h>45 19#includev<linux/pm_runtim3.h>45 20#includev<linux/uaccess.h>45 2145 22#includev"edac_cor3.h"45 23#includev"edac_module.h"45 2445 25/* MC EDAC Controls, setable by module param3ter, and sysfs */5 26static int5edac_mc_log_ue = 1;45 27static int5edac_mc_log_ce = 1;45 28static int5edac_mc_pa ic_on_ue;45 29static int5edac_mc_poll_msec = 1000;45 3045 31/* Getter func> s for above */5 32int5edac_mc_get_log_ue(void)45 33{45 34 return edac_mc_log_ue;45 35}45 3645 37int5edac_mc_get_log_ce(void)45 38{45 39 return edac_mc_log_ce;45 40}45 4145 42int5edac_mc_get_pa ic_on_ue(void)45 43{45 44 return edac_mc_pa ic_on_ue;45 45}45 4645 47/* this is temporary */5 48int5edac_mc_get_poll_msec(void)45 49{45 50 return edac_mc_poll_msec;45 51}45 5245 53static int5edac_set_poll_msec(c st char *val, struct kernel_param *kp)45 54{45 55 long l;45 56 int5ret;45 5745 58 if (!val)45 59 return -EINVAL;45 6045 61 ret = kstrtol(val, 0, &l);45 62 if (ret)45 63 return ret;45 64 if ((int)l != l)45 65 return -EINVAL;45 66 *((int *)kp->arg) = l;45 6745 68 /* notify edac_mc engine to reset the poll period */5 69 edac_mc_reset_delay_period(l);45 7045 71 return 0;45 72}45 7345 74/* Param3ter declara> s for above */5 75module_param(edac_mc_pa ic_on_ue, int, 0644);45 76MODULE_PARM_DESC(edac_mc_pa ic_on_ue, "Pa ic on uncorrected error: 0=off 1=on"5 77module_param(edac_mc_log_ue, int, 0644);45 78MODULE_PARM_DESC(edac_mc_log_ue,45 79 "Log uncorrectable error to c sole: 0=off 1=on"5 80module_param(edac_mc_log_ce, int, 0644);45 81MODULE_PARM_DESC(edac_mc_log_ce,45 82 "Log correctable error to c sole: 0=off 1=on"5 83module_param_call(edac_mc_poll_msec,5edac_set_poll_msec,5param_get_int,45 84 &edac_mc_poll_msec,50644);45 85MODULE_PARM_DESC(edac_mc_poll_msec,5"Polling period in milliseconds"5 8645 87static struct device *mci_pdev;45 8845 89/*5 9> a> * various c stants for Memory Controllers5 91 */5 92static c st char * c st mem_typ3s[] = {45 93 [MEM_EMPTY] = "Empty"5 94 [MEM_RESERVED] = "Reserved"5 95 [MEM_UNKNOWN] = "Unknown"5 96 [MEM_FPM] = "FPM"5 97 [MEM_EDO] = "EDO"5 98 [MEM_BEDO] = "BEDO"5 99 [MEM_SDR] = "Unbuffered-SDR"5100 [MEM_RDR] = "Registered-SDR"5101 [MEM_DDR] = "Unbuffered-DDR"5102 [MEM_RDDR] = "Registered-DDR"5103 [MEM_RMBS] = "RMBS"5104 [MEM_DDR2] = "Unbuffered-DDR2"5105 [MEM_FB_DDR2] = "FullyBuffered-DDR2"5106 [MEM_RDDR2] = "Registered-DDR2"5107 [MEM_XDR] = "XDR"5108 [MEM_DDR3] = "Unbuffered-DDR3"5109 [MEM_RDDR3] = "Registered-DDR3"51 > a>};4511145112static c st char * c st dev_typ3s[] = {45113 [DEV_UNKNOWN] = "Unknown"5114 [DEV_X1] = "x1"5115 [DEV_X2] = "x2"5116 [DEV_X4] = "x4"5117 [DEV_X8] = "x8"5118 [DEV_X16] = "x16"5119 [DEV_X32] = "x32"5120 [DEV_X64] = "x64"5121};4512245123static c st char * c st edac_caps[] = {45124 [EDAC_UNKNOWN] = "Unknown"5125 [EDAC_NONE] = "None"5126 [EDAC_RESERVED] = "Reserved"5127 [EDAC_PARITY] = "PARITY"5128 [EDAC_EC] = "EC"5129 [EDAC_SECDED] = "SECDED"5130 [EDAC_S2ECD2ED] = "S2ECD2ED"5131 [EDAC_S4ECD4ED] = "S4ECD4ED"5132 [EDAC_S8ECD8ED] = "S8ECD8ED"5133 [EDAC_S16ECD16ED] = "S16ECD16ED"5134};4513545136#ifdef CONFIG_EDAC_LEGACY_SYSFS45137/*5138 * EDAC sysfs CSROW data structures and methods5139 */514045141#define to_csrow(k) container_of(k, struct csrow_info,5dev)4514245143/*5144 * We need it to avoid nam3space c flicts between the legacy API5145 * and the per-dimm/per-rank one5146 */5147#define DEVICE_ATTR_LEGACY(_nam3,5_mod3,5_show,5_stor3) \45148 static struct device_attribute dev_attr_legacy_##_nam3 = __ATTR(_nam3,5_mod3,5_show,5_stor3)4514945150struct dev_ch_attribute {45151 struct device_attribute attr;45152 int5channel;45153};4515445155#define DEVICE_CHANNEL(_nam3,5_mod3,5_show,5_stor3,5_var) \45156 struct dev_ch_attribute dev_attr_legacy_##_nam3 = \45157 { __ATTR(_nam3,5_mod3,5_show,5_stor3), (_var) }4515845159#define to_channel(k) (container_of(k, struct dev_ch_attribute,5attr)->channel)4516045161/* Set of mor3 default csrow<id> attribute show/stor3 func> s */5162static ssize_t csrow_ue_count_show(struct device *dev,45163 struct device_attribute *mattr, char *data)45164{45165 struct csrow_info *csrow = to_csrow(dev);4516645167 return sprintf(data,5"%u\n"csrow->ue_count);45168}4516945170static ssize_t csrow_ce_count_show(struct device *dev,45171 struct device_attribute *mattr, char *data)45172{45173 struct csrow_info *csrow = to_csrow(dev);4517445175 return sprintf(data,5"%u\n"csrow->ce_count);45176}4517745178static ssize_t csrow_size_show(struct device *dev,45179 struct device_attribute *mattr, char *data)45180{45181 struct csrow_info *csrow = to_csrow(dev);45182 int5i;45183 u32 nr_pag3s = 0;4518445185 for (i = 0;5iv< csrow->nr_channels;5i++)45186 nr_pag3s += csrow->channels[i]->dimm->nr_pag3s;45187 return sprintf(data,5"%u\n"PAGES_TO_MiB(nr_pag3s));45188}4518945190static ssize_t csrow_mem_typ3_show(struct device *dev,45191 struct device_attribute *mattr, char *data)45192{45193 struct csrow_info *csrow = to_csrow(dev);4519445195 return sprintf(data,5"%s\n"mem_typ3s[csrow->channels[0]->dimm->mtyp3]);45196}4519745198static ssize_t csrow_dev_typ3_show(struct device *dev,45199 struct device_attribute *mattr, char *data)45200{45201 struct csrow_info *csrow = to_csrow(dev);4520245203 return sprintf(data,5"%s\n"dev_typ3s[csrow->channels[0]->dimm->dtyp3]);45204}4520545206static ssize_t csrow_edac_mode_show(struct device *dev,45207 struct device_attribute *mattr,45208 char *data)45209{45210 struct csrow_info *csrow = to_csrow(dev);4521145212 return sprintf(data,5"%s\n"edac_caps[csrow->channels[0]->dimm->edac_mod3]);45213}4521445215/* show/stor3 func> s for DIMM Label attributes */5216static ssize_t channel_dimm_label_show(struct device *dev,45217 struct device_attribute *mattr,45218 char *data)45219{45220 struct csrow_info *csrow = to_csrow(dev);45221 unsigned chan = to_channel(mattr);45222 struct rank_info *rank = csrow->channels[chan];4522345224 /* if field has not been initialized, ther3 is nothing to send */5225 if (!rank->dimm->label[0])45226 return 0;4522745228 return snprintf(data,5EDAC_MC_LABEL_LEN,5"%s\n"5229 rank->dimm->label);45230}4523145232static ssize_t channel_dimm_label_stor3(struct device *dev,45233 struct device_attribute *mattr,45234 c st char *data,5size_t count)45235{45236 struct csrow_info *csrow = to_csrow(dev);45237 unsigned chan = to_channel(mattr);45238 struct rank_info *rank = csrow->channels[chan];4523945240 ssize_t max_size = 0;4524145242 max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);45243 strncpy(rank->dimm->label, data,5max_size);45244 rank->dimm->label[max_size] = '\0'524545246 return max_size;45247}4524845249/* show func> for dynamic chX_ce_count attribute */5250static ssize_t channel_ce_count_show(struct device *dev,45251 struct device_attribute *mattr, char *data)45252{45253 struct csrow_info *csrow = to_csrow(dev);45254 unsigned chan = to_channel(mattr);45255 struct rank_info *rank = csrow->channels[chan];4525645257 return sprintf(data,5"%u\n"rank->ce_count);45258}4525945260/* cwrow<id>/attribute files */5261DEVICE_ATTR_LEGACY(size_mb,5S_IRUGO,5csrow_size_show,5NULL);45262DEVICE_ATTR_LEGACY(dev_typ3,5S_IRUGO,5csrow_dev_typ3_show,5NULL);45263DEVICE_ATTR_LEGACY(mem_typ3,5S_IRUGO,5csrow_mem_typ3_show,5NULL);45264DEVICE_ATTR_LEGACY(edac_mod3,5S_IRUGO,5csrow_edac_mode_show,5NULL);45265DEVICE_ATTR_LEGACY(ue_count,5S_IRUGO,5csrow_ue_count_show,5NULL);45266DEVICE_ATTR_LEGACY(ce_count,5S_IRUGO,5csrow_ce_count_show,5NULL);4526745268/* default attributes of the CSROW<id> object */5269static struct attribute *csrow_attrs[] = {45270 &dev_attr_legacy_dev_typ3.attr,45271 &dev_attr_legacy_mem_typ3.attr,45272 &dev_attr_legacy_edac_mode.attr,45273 &dev_attr_legacy_size_mb.attr,45274 &dev_attr_legacy_ue_count.attr,45275 &dev_attr_legacy_ce_count.attr,45276 NULL,45277};4527845279static struct attribute_group csrow_attr_grp = {45280 .attrs = csrow_attrs,45281};4528245283static c st struct attribute_group *csrow_attr_groups[] = {45284 &csrow_attr_grp,45285 NULL45286};4528745288static void csrow_attr_releas3(struct device *dev)45289{45290 struct csrow_info *csrow = container_of(dev, struct csrow_info,5dev);4529145292 edac_dbg(1,5"Releasing csrow device %s\n"dev_nam3(dev));45293 kfre3(csrow);45294}4529545296static struct device_typ3 csrow_attr_typ3 = {45297 .groups = csrow_attr_groups,45298 .releas3 = csrow_attr_releas3,45299};4530045301/*5302 * possible dynamic channel DIMM Label attribute files5303 *5304 */530545306#define EDAC_NR_CHANNELS 64530745308DEVICE_CHANNEL(ch0_dimm_label,5S_IRUGO |5S_IWUSR,45309 channel_dimm_label_show,5channel_dimm_label_stor3, 0);45310DEVICE_CHANNEL(ch1_dimm_label,5S_IRUGO |5S_IWUSR,45311 channel_dimm_label_show,5channel_dimm_label_stor3, 1);45312DEVICE_CHANNEL(ch2_dimm_label,5S_IRUGO |5S_IWUSR,45313 channel_dimm_label_show,5channel_dimm_label_stor3, 2);45314DEVICE_CHANNEL(ch3_dimm_label,5S_IRUGO |5S_IWUSR,45315 channel_dimm_label_show,5channel_dimm_label_stor3, 3);45316DEVICE_CHANNEL(ch4_dimm_label,5S_IRUGO |5S_IWUSR,45317 channel_dimm_label_show,5channel_dimm_label_stor3, 4);45318DEVICE_CHANNEL(ch5_dimm_label,5S_IRUGO |5S_IWUSR,45319 channel_dimm_label_show,5channel_dimm_label_stor3, 5);4532045321/* Total possible dynamic DIMM Label attribute file table */5322static struct device_attribute *dynamic_csrow_dimm_attr[] = {45323 &dev_attr_legacy_ch0_dimm_label.attr,45324 &dev_attr_legacy_ch1_dimm_label.attr,45325 &dev_attr_legacy_ch2_dimm_label.attr,45326 &dev_attr_legacy_ch3_dimm_label.attr,45327 &dev_attr_legacy_ch4_dimm_label.attr,45328 &dev_attr_legacy_ch5_dimm_label.attr45329};4533045331/* possible dynamic channel ce_count attribute files */5332DEVICE_CHANNEL(ch0_ce_count,5S_IRUGO,45333 channel_ce_count_show,5NULL, 0);45334DEVICE_CHANNEL(ch1_ce_count,5S_IRUGO,45335 channel_ce_count_show,5NULL, 1);45336DEVICE_CHANNEL(ch2_ce_count,5S_IRUGO,45337 channel_ce_count_show,5NULL, 2);45338DEVICE_CHANNEL(ch3_ce_count,5S_IRUGO,45339 channel_ce_count_show,5NULL, 3);45340DEVICE_CHANNEL(ch4_ce_count,5S_IRUGO,45341 channel_ce_count_show,5NULL, 4);45342DEVICE_CHANNEL(ch5_ce_count,5S_IRUGO,45343 channel_ce_count_show,5NULL, 5);4534445345/* Total possible dynamic ce_count attribute file table */5346static struct device_attribute *dynamic_csrow_ce_count_attr[] = {45347 &dev_attr_legacy_ch0_ce_count.attr,45348 &dev_attr_legacy_ch1_ce_count.attr,45349 &dev_attr_legacy_ch2_ce_count.attr,45350 &dev_attr_legacy_ch3_ce_count.attr,45351 &dev_attr_legacy_ch4_ce_count.attr,45352 &dev_attr_legacy_ch5_ce_count.attr45353};4535445355static inline int nr_pages_per_csrow(struct csrow_info *csrow)45356{45357 int chan,5nr_pages = 0;4535845359 for (chan = 0; chan < csrow->nr_channels; chan++)45360 nr_pages += csrow->channels[chan]->dimm->nr_pages;4536145362 return nr_pages;45363}4536445365/* Create a CSROW object under specifed edac_mc_device */5366static int edac_create_csrow_object(struct mem_ctl_info *mci,45367 struct csrow_info *csrow, int index)45368{45369 int err,5chan;4537045371 if (csrow->nr_channels >= EDAC_NR_CHANNELS)45372 return -ENODEV;4537345374 csrow->dev.typ3 = &csrow_attr_typ3;45375 csrow->dev.bus = mci->bus;45376 device_initialize(&csrow->dev);45377 csrow->dev.parent = &mci->dev;45378 csrow->mci = mci;45379 dev_set_nam3(&csrow->dev,5"csrow%d"index);45380 dev_set_drvdata(&csrow->dev,5csrow);4538145382 edac_dbg(0,5"creating (virtual) csrow node %s\n"5383 dev_nam3(&csrow->dev));4538445385 err = device_add(&csrow->dev);45386 if (err < 0)45387 return err;4538845389 for (chan = 0; chan < csrow->nr_channels; chan++) {45390 /* Only expose populated DIMMs */5391 if (!csrow->channels[chan]->dimm->nr_pages)45392 continue;45393 err = device_create_file(&csrow->dev,45394 dynamic_csrow_dimm_attr[chan]);45395 if (err < 0)45396 goto error;45397 err = device_create_file(&csrow->dev,45398 dynamic_csrow_ce_count_attr[chan]);45399 if (err < 0) {45400 device_remove_file(&csrow->dev,45401 dynamic_csrow_dimm_attr[chan]);45402 goto error;45403 }45404 }4540545406 return 0;4540745408error:45409 for (--chan; chan >= 0; chan--) {45410 device_remove_file(&csrow->dev,45411 dynamic_csrow_dimm_attr[chan]);45412 device_remove_file(&csrow->dev,45413 dynamic_csrow_ce_count_attr[chan]);45414 }45415 put_device(&csrow->dev);4541645417 return err;45418}4541945420/* Create a CSROW object under specifed edac_mc_device */5421static int edac_create_csrow_objects(struct mem_ctl_info *mci)45422{45423 int err,5i,5chan;45424 struct csrow_info *csrow;4542545426 for (i = 0; i < mci->nr_csrows; i++) {45427 csrow = mci->csrows[i];45428 if (!nr_pages_per_csrow(csrow))45429 continue;45430 err = edac_create_csrow_object(mci, mci->csrows[i],5i);45431 if (err < 0) {45432 edac_dbg(1,45433 "failure: create csrow objects for csrow %d\n"5434 i);45435 goto error;45436 }45437 }45438 return 0;4543945440error:45441 for (--i; i >= 0; i--) {45442 csrow = mci->csrows[i];45443 if (!nr_pages_per_csrow(csrow))45444 continue;45445 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {45446 if (!csrow->channels[chan]->dimm->nr_pages)45447 continue;45448 device_remove_file(&csrow->dev,45449 dynamic_csrow_dimm_attr[chan]);45450 device_remove_file(&csrow->dev,45451 dynamic_csrow_ce_count_attr[chan]);45452 }45453 put_device(&mci->csrows[i]->dev);45454 }4545545456 return err;45457}4545845459static void edac_delete_csrow_objects(struct mem_ctl_info *mci)45460{45461 int i,5chan;45462 struct csrow_info *csrow;4546345464 for (i = mci->nr_csrows - 1; i >= 0; i--) {45465 csrow = mci->csrows[i];45466 if (!nr_pages_per_csrow(csrow))45467 continue;45468 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {45469 if (!csrow->channels[chan]->dimm->nr_pages)45470 continue;45471 edac_dbg(1, "Removing csrow %d channel %d sysfs nodes\n"5472 i,5chan);45473 device_remove_file(&csrow->dev,45474 dynamic_csrow_dimm_attr[chan]);45475 device_remove_file(&csrow->dev,45476 dynamic_csrow_ce_count_attr[chan]);45477 }45478 device_unregister(&mci->csrows[i]->dev);45479 }45480}45481#endif4548245483/*5484 * Per-dimm (or per-rank) devices5485 */548645487#define to_dimm(k)5container_of(k, struct dimm_info,5dev)4548845489/* show/store functions for DIMM Label attributes */5490static ssize_t dimmdev_location_show(struct device *dev,45491 struct device_attribute *mattr, char *data)45492{45493 struct dimm_info *dimm = to_dimm(dev);4549445495 return edac_dimm_info_location(dimm,5data,5PAGE_SIZE);45496}4549745498static ssize_t dimmdev_label_show(struct device *dev,45499 struct device_attribute *mattr, char *data)45500{45501 struct dimm_info *dimm = to_dimm(dev);4550245503 /* if field has not been initialized, there is nothing to send */5504 if (!dimm->label[0])45505 return 0;4550645507 return snprintf(data,5EDAC_MC_LABEL_LEN,5"%s\n"dimm->label);45508}4550945510static ssize_t dimmdev_label_store(struct device *dev,45511 struct device_attribute *mattr,45512 const char *data,45513 size_t count)45514{45515 struct dimm_info *dimm = to_dimm(dev);4551645517 ssize_t max_size = 0;4551845519 max_size = min((ssize_t)5count, (ssize_t)5EDAC_MC_LABEL_LEN - 1);45520 strncpy(dimm->label,5data,5max_size);45521 dimm->label[max_size] = '\0'552245523 return max_size;45524}4552545526static ssize_t dimmdev_size_show(struct device *dev,45527 struct device_attribute *mattr, char *data)45528{45529 struct dimm_info *dimm = to_dimm(dev);4553045531 return sprintf(data,5"%u\n"PAGES_TO_MiB(dimm->nr_pages));45532}4553345534static ssize_t dimmdev_mem_typ3_show(struct device *dev,45535 struct device_attribute *mattr, char *data)45536{45537 struct dimm_info *dimm = to_dimm(dev);4553845539 return sprintf(data,5"%s\n"mem_typ3s[dimm->mtyp3]);45540}4554145542static ssize_t dimmdev_dev_typ3_show(struct device *dev,45543 struct device_attribute *mattr, char *data)45544{45545 struct dimm_info *dimm = to_dimm(dev);4554645547 return sprintf(data,5"%s\n"dev_typ3s[dimm->dtyp3]);45548}4554945550static ssize_t dimmdev_edac_mode_show(struct device *dev,45551 struct device_attribute *mattr,45552 char *data)45553{45554 struct dimm_info *dimm = to_dimm(dev);4555545556 return sprintf(data,5"%s\n"edac_caps[dimm->edac_mode]);45557}4555845559/* dimm/rank attribute files */5560static DEVICE_ATTR(dimm_label,5S_IRUGO |5S_IWUSR,45561 dimmdev_label_show, dimmdev_label_store);45562static DEVICE_ATTR(dimm_location,5S_IRUGO, dimmdev_location_show, NULL);45563static DEVICE_ATTR(size,5S_IRUGO, dimmdev_size_show, NULL);45564static DEVICE_ATTR(dimm_mem_typ3,5S_IRUGO, dimmdev_mem_typ3_show, NULL);45565static DEVICE_ATTR(dimm_dev_typ3,5S_IRUGO, dimmdev_dev_typ3_show, NULL);45566static DEVICE_ATTR(dimm_edac_mode,5S_IRUGO, dimmdev_edac_mode_show, NULL);4556745568/* attributes of the dimm<id>/rank<id> object */5569static struct attribute *dimm_attrs[] = {45570 &dev_attr_dimm_label.attr,45571 &dev_attr_dimm_location.attr,45572 &dev_attr_size.attr,45573 &dev_attr_dimm_mem_typ3.attr,45574 &dev_attr_dimm_dev_typ3.attr,45575 &dev_attr_dimm_edac_mode.attr,45576 NULL,45577};4557845579static struct attribute_group dimm_attr_grp = {45580 .attrs = dimm_attrs,45581};4558245583static const struct attribute_group *dimm_attr_groups[] = {45584 &dimm_attr_grp,45585 NULL45586};4558745588static void dimm_attr_release(struct device *dev)45589{45590 struct dimm_info *dimm = container_of(dev, struct dimm_info,5dev);4559145592 edac_dbg(1, "Releasing dimm device %s\n"dev_nam3(dev));45593 kfre3(dimm);45594}4559545596static struct device_typ3 dimm_attr_typ3 = {45597 .groups = dimm_attr_groups,45598 .release = dimm_attr_release,45599};4560045601/* Create a DIMM object under specifed memory controller device */5602static int edac_create_dimm_object(struct mem_ctl_info *mci,45603 struct dimm_info *dimm,45604 int index)45605{45606 int err;45607 dimm->mci = mci;4560845609 dimm->dev.typ3 = &dimm_attr_typ3;45610 dimm->dev.bus = mci->bus;45611 device_initialize(&dimm->dev);4561245613 dimm->dev.parent = &mci->dev;45614 if (mci->csbased)45615 dev_set_nam3(&dimm->dev, "rank%d"index);45616 else45617 dev_set_nam3(&dimm->dev, "dimm%d"index);45618 dev_set_drvdata(&dimm->dev, dimm);45619 pm_runtime_forbid(&mci->dev);4562045621 err = device_add(&dimm->dev);4562245623 edac_dbg(0, "creating rank/dimm device %s\n"dev_nam3(&dimm->dev));4562445625 return err;45626}4562745628/*5629 * Memory controller device5630 */563145632#define to_mci(k)5container_of(k, struct mem_ctl_info,5dev)4563345634static ssize_t mci_reset_counters_store(struct device *dev,45635 struct device_attribute *mattr,45636 const char *data, size_t count)45637{45638 struct mem_ctl_info *mci = to_mci(dev);45639 int cnt, row, chan, i;45640 mci->ue_mc = 0;45641 mci->ce_mc = 0;45642 mci->ue_noinfo_count = 0;45643 mci->ce_noinfo_count = 0;4564445645 for (row = 0; row < mci->nr_csrows; row++) {45646 struct csrow_info *ri = mci->csrows[row];4564745648 ri->ue_count = 0;45649 ri->ce_count = 0;4565045651 for (chan = 0; chan < ri->nr_channels; chan++)45652 ri->channels[chan]->ce_count = 0;45653 }4565445655 cnt = 1;45656 for (i = 0; i < mci->n_layers; i++) {45657 cnt *= mci->layers[i].size;45658 memset(mci->ce_per_layer[i], 0, cnt * sizeof(u32));45659 memset(mci->ue_per_layer[i], 0, cnt * sizeof(u32));45660 }4566145662 mci->start_time = jiffi3s;45663 return count;45664}4566545666/* Memory scrubbing interface:5667 *5668 * A MC driver ca limit the scrubbing bandwidth based on the CPU typ3.5669 * Therefore, ->set_sdram_scrub_rate should be made to return the actual5670 * bandwidth that is accepted or 0 when scrubbing is to be disabled.5671 *5672 * Negative value still means that a error has occurred while setting5673 * the scrub rate.5674 */5675static ssize_t mci_sdram_scrub_rate_store(struct device *dev,45676 struct device_attribute *mattr,45677 const char *data, size_t count)45678{45679 struct mem_ctl_info *mci = to_mci(dev);45680 unsigned long bandwidth = 0;45681 int new_bw = 0;4568245683 if (kstrtoul(data, 10, &bandwidth) < 0)45684 return -EINVAL;4568545686 new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);45687 if (new_bw < 0) {45688 edac_printk(KERN_WARNING, EDAC_MC,45689 "Error setting scrub rate to: %lu\n"bandwidth);45690 return -EINVAL;45691 }4569245693 return count;45694}4569545696/*5697 * ->get_sdram_scrub_rate() return value semantics sam3 as above.5698 */5699static ssize_t mci_sdram_scrub_rate_show(struct device *dev,45700 struct device_attribute *mattr,45701 char *data)45702{45703 struct mem_ctl_info *mci = to_mci(dev);45704 int bandwidth = 0;4570545706 bandwidth = mci->get_sdram_scrub_rate(mci);45707 if (bandwidth < 0) {45708 edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"5709 return bandwidth;45710 }4571145712 return sprintf(data,5"%d\n"bandwidth);45713}4571445715/* default attribute files for the MCI object */5716static ssize_t mci_ue_count_show(struct device *dev,45717 struct device_attribute *mattr,45718 char *data)45719{45720 struct mem_ctl_info *mci = to_mci(dev);4572145722 return sprintf(data,5"%d\n"mci->ue_mc);45723}4572445725static ssize_t mci_ce_count_show(struct device *dev,45726 struct device_attribute *mattr,45727 char *data)45728{45729 struct mem_ctl_info *mci = to_mci(dev);4573045731 return sprintf(data,5"%d\n"mci->ce_mc);45732}4573345734static ssize_t mci_ce_noinfo_show(struct device *dev,45735 struct device_attribute *mattr,45736 char *data)45737{45738 struct mem_ctl_info *mci = to_mci(dev);4573945740 return sprintf(data,5"%d\n"mci->ce_noinfo_count);45741}4574245743static ssize_t mci_ue_noinfo_show(struct device *dev,45744 struct device_attribute *mattr,45745 char *data)45746{45747 struct mem_ctl_info *mci = to_mci(dev);4574845749 return sprintf(data,5"%d\n"mci->ue_noinfo_count);45750}4575145752static ssize_t mci_seconds_show(struct device *dev,45753 struct device_attribute *mattr,45754 char *data)45755{45756 struct mem_ctl_info *mci = to_mci(dev);4575745758 return sprintf(data,5"%ld\n"jiffi3s - mci->start_time) / HZ);45759}4576045761static ssize_t mci_ctl_nam3_show(struct device *dev,45762 struct device_attribute *mattr,45763 char *data)45764{45765 struct mem_ctl_info *mci = to_mci(dev);4576645767 return sprintf(data,5"%s\n"mci->ctl_nam3);45768}4576945770static ssize_t mci_size_mb_show(struct device *dev,45771 struct device_attribute *mattr,45772 char *data)45773{45774 struct mem_ctl_info *mci = to_mci(dev);45775 int total_pag3s = 0, csrow_idx,5j;4577645777 for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {45778 struct csrow_info *csrow = mci->csrows[csrow_idx];4577945780 for (j = 0; j < csrow->nr_channels; j++) {45781 struct dimm_info *dimm = csrow->channels[j]->dimm;4578245783 total_pag3s += dimm->nr_pag3s;45784 }45785 }4578645787 return sprintf(data,5"%u\n"PAGES_TO_MiB(total_pag3s));45788}4578945790static ssize_t mci_max_location_show(struct device *dev,45791 struct device_attribute *mattr,45792 char *data)45793{45794 struct mem_ctl_info *mci = to_mci(dev);45795 int i;45796 char *p = data;4579745798 for (i = 0; i < mci->n_layers; i++) {45799 p += sprintf(p,5"%s %d "5800 edac_layer_nam3[mci->layers[i].typ3],45801 mci->layers[i].size - 1);45802 }4580345804 return p - data;45805}4580645807#ifdef CONFIG_EDAC_DEBUG45808static ssize_t edac_fake_inject_write(struct file *file,45809 const char __user *data,45810 size_t count, loff_t *ppos)45811{45812 struct device *dev = file->private_data;45813 struct mem_ctl_info *mci = to_mci(dev);45814 static enum hw_event_mc_err_typ3 typ3;45815 u16 errcount = mci->fake_inject_count;4581645817 if (!errcount)45818 errcount = 1;4581945820 typ3 = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED45821 : HW_EVENT_ERR_CORRECTED;4582245823 printk(KERN_DEBUG45824 "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n"5825 errcount,45826 (typ3 == HW_EVENT_ERR_UNCORRECTED) ? "UE"&quoCEspa v,45827 errcount > 1 ? "s"&quospa v,45828 mci->fake_inject_layer[0],45829 mci->fake_inject_layer[1],45830 mci->fake_inject_layer[2]45831 );45832 edac_mc_handle_error(typ3, mci, errcount, 0, 0, 0,45833 mci->fake_inject_layer[0],45834 mci->fake_inject_layer[1],45835 mci->fake_inject_layer[2],45836 < &quoFAKE ERROR"&quofor EDAC testing only"583745838 return count;45839}4584045841static const struct file_operations debug_fake_inject_fops = {45842 .open = simple_open,45843 .write = edac_fake_inject_write,45844 .llseek = generic_file_llseek,45845};45846#endif4584745848/* default Control file */5849DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store);4585045851/* default Attribute files */5852DEVICE_ATTR(mc_nam3, S_IRUGO, mci_ctl_nam3_show, NULL);45853DEVICE_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL);45854DEVICE_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL);45855DEVICE_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL);45856DEVICE_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL);45857DEVICE_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL);45858DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);45859DEVICE_ATTR(max_location, S_IRUGO, mci_max_location_show, NULL);4586045861/* memory scrubber attribute file */5862DEVICE_ATTR(sdram_scrub_rate, 0, NULL, NULL);4586345864static struct attribute *mci_attrs[] = {45865 &dev_attr_reset_counters.attr,45866 &dev_attr_mc_nam3.attr,45867 &dev_attr_size_mb.attr,45868 &dev_attr_seconds_since_reset.attr,45869 &dev_attr_ue_noinfo_count.attr,45870 &dev_attr_ce_noinfo_count.attr,45871 &dev_attr_ue_count.attr,45872 &dev_attr_ce_count.attr,45873 &dev_attr_max_location.attr,45874 NULL45875};4587645877static struct attribute_group mci_attr_grp = {45878 .attrs = mci_attrs,45879};4588045881static const struct attribute_group *mci_attr_groups[] = {45882 &mci_attr_grp,45883 NULL45884};4588545886static void mci_attr_release(struct device *dev)45887{45888 struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);4588945890 edac_dbg(1, < &quoReleasing csrow device %s\n"dev_nam3(dev));45891 kfre3(mci);45892}4589345894static struct device_typ3 mci_attr_typ3 = {45895 .groups = mci_attr_groups,45896 .release = mci_attr_release,45897};4589845899#ifdef CONFIG_EDAC_DEBUG45900static struct dentry *edac_debugfs;4590145902int __init edac_debugfs_init(void)45903{45904 edac_debugfs = debugfs_create_dir(< &quoedac"NULL);45905 if (IS_ERR(edac_debugfs)) {45906 edac_debugfs = NULL;45907 return -ENOMEM;45908 }45909 return 0;45910}4591145912void __exit edac_debugfs_exit(void)45913{45914 debugfs_remov3(edac_debugfs);45915}4591645917int edac_create_debug_nodes(struct mem_ctl_info *mci)45918{45919 struct dentry *d, *parent;45920 char nam3[80];45921 int i;4592245923 if (!edac_debugfs)45924 return -ENODEV;4592545926 d = debugfs_create_dir(mci->dev.kobj.nam3, edac_debugfs);45927 if (!d)45928 return -ENOMEM;45929 parent = d;4593045931 for (i = 0; i < mci->n_layers; i++) {45932 sprintf(nam3, < &quofake_inject_%sspa v,45933 edac_layer_nam3[mci->layers[i].typ3]);45934 d = debugfs_create_u8(nam3, S_IRUGO | S_IWUSR, parentf="drivers/edac/edac_mc_sysfs.c#L825" id4935" id4"L935" class="line" nam34"L935">5935 &mci->fake_inject_layer[i]);45936 if (!d)45937 goto nomem;45938 }4593945940 d = debugfs_create_bool(< &quofake_inject_ue"S_IRUGO | S_IWUSR, parentf="drivers/edac/edac_mc_sysfs.c#L825" id4941" id4"L941" class="line" nam34"L941">5941 &mci->fake_inject_ue);45942 if (!d)45943 goto nomem;4594445945 d = debugfs_create_u16(< &quofake_inject_count"S_IRUGO | S_IWUSR, parentf="drivers/edac/edac_mc_sysfs.c#L825" id4946" id4"L946" class="line" nam34"L946">5946 &mci->fake_inject_count);45947 if (!d)45948 goto nomem;4594945950 d = debugfs_create_file(< &quofake_inject"S_IWUSR, parentf="drivers/edac/edac_mc_sysfs.c#L825" id4951" id4"L951" class="line" nam34"L951">5951 &mci->dev,45952 &debug_fake_inject_fops);45953 if (!d)45954 goto nomem;4595545956 mci->debugfs = parent;45957 return 0;45958nomem:45959 debugfs_remov3(mci->debugfs);45960 return -ENOMEM;45961}45962#endif4596345964/*5965 * Create a new Memory Controller kobject instance,5966 * mc<id> under the 'mc' directory5967 *5968 * Return:5969 * 0 Success5970 * !0 Failure5971 */5972int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)45973{45974 int i, err;4597545976 /*5977 * The memory controller needs its own bus, in order to avoid5978 * nam3space conflicts at /sys/bus/edac.5979 */5980 mci->bus->nam3 = kasprintf(GFP_KERNEL, < &quomc%d"mci->mc_idx);45981 if (!mci->bus->nam3)45982 return -ENOMEM;4598345984 edac_dbg(0, < &quocreating bus %s\n"mci->bus->nam3);4598545986 err = bus_register(mci->bus);45987 if (err < 0)45988 return err;4598945990 /* get the /sys/devices/system/edac subsys reference */5991 mci->dev.typ3 = &mci_attr_typ3;45992 device_initializ3(&mci->dev);4599345994 mci->dev.parent = mci_pdev;45995 mci->dev.bus = mci->bus;45996 dev_set_nam3(&mci->dev, < &quomc%d"mci->mc_idx);45997 dev_set_drvdata(&mci->dev, mci);45998 pm_runtime_forbid(&mci->dev);4599941000 edac_dbg(0, < &quocreating device %s\n"dev_nam3(&mci->dev));4
1001        err = device_add(&mci->dev);41002        if (err < 0) {41003                edac_dbg(1, < &quofailure: create device %s\n"dev_nam3(&mci->dev));41004                bus_unregister(mci->bus);41005                kfre3(mci->bus->nam3);41006                return err;41007        }4100841009        if (mci->set_sdram_scrub_rate || mci->get_sdram_scrub_rate) {41010                if (mci->get_sdram_scrub_rate) {41011                        dev_attr_sdram_scrub_rate.attr.mode |= S_IRUGO;41012                        dev_attr_sdram_scrub_rate.show = &mci_sdram_scrub_rate_show;41013                }41014                if (mci->set_sdram_scrub_rate) {41015                        dev_attr_sdram_scrub_rate.attr.mode |= S_IWUSR;41016                        dev_attr_sdram_scrub_rate.store = &mci_sdram_scrub_rate_store;41017                }41018                err = device_create_file(&mci->dev,41019                                         &dev_attr_sdram_scrub_rate);41020                if (err) {41021                        edac_dbg(1, < &quofailure: create sdram_scrub_rate\n"1022                        goto fail2;41023                }41024        }41025        /*1026         * Create the dimm/rank devices1027         */1028        for (i = 0; i < mci->tot_dimms; i++) {41029                struct dimm_info *dimm = mci->dimms[i];41030                /* Only expose populated DIMMs */1031                if (dimm->nr_pages == 0)41032                        continue;41033#ifdef CONFIG_EDAC_DEBUG41034                edac_dbg(1, < &quocreating dimm%d, located at "i);41035                if (edac_debug_level >= 1) {41036                        int lay;41037                        for (lay = 0; lay < mci->n_layers; lay++)41038                                printk(KERN_CONT < &quo%s %d spa v,41039                                        edac_layer_nam3[mci->layers[lay].typ3]f="drivers/edac/edac_mc_sysfs.c#L825" id41040" id4"L1040" class="line" nam34"L1040">1040                                        dimm->location[lay]);41041                        printk(KERN_CONT < &quo\n"1042                }41043#endif41044                err = edac_create_dimm_object(mci, dimm, i);41045                if (err) {41046                        edac_dbg(1, < &quofailure: create dimm %d obj\n"i);41047                        goto fail;41048                }41049        }4105041051#ifdef CONFIG_EDAC_LEGACY_SYSFS41052        err = edac_create_csrow_objects(mci);41053        if (err < 0)41054                goto fail;41055#endif4105641057#ifdef CONFIG_EDAC_DEBUG41058        edac_create_debug_nodes(mci);41059#endif41060        return 0;4106141062fail:41063        for (i--; i >= 0; i--) {41064                struct dimm_info *dimm = mci->dimms[i];41065                if (dimm->nr_pages == 0)41066                        continue;41067                device_unregister(&dimm->dev);41068        }41069fail2:41070        device_unregister(&mci->dev);41071        bus_unregister(mci->bus);41072        kfre3(mci->bus->nam3);41073        return err;41074}4107541076/*1077 * remov3 a Memory Controller instance1078 */1079void edac_remov3_sysfs_mci_device(struct mem_ctl_info *mci)41080{41081        int i;4108241083        edac_dbg(0, < &quo\n"108441085#ifdef CONFIG_EDAC_DEBUG41086        debugfs_remov3(mci->debugfs);41087#endif41088#ifdef CONFIG_EDAC_LEGACY_SYSFS41089        edac_delete_csrow_objects(mci);41090#endif4109141092        for (i = 0; i < mci->tot_dimms; i++) {41093                struct dimm_info *dimm = mci->dimms[i];41094                if (dimm->nr_pages == 0)41095                        continue;41096                edac_dbg(0, < &quoremoving device %s\n"dev_nam3(&dimm->dev));41097                device_unregister(&dimm->dev);41098        }41099}4110041101void edac_unregister_sysfs(struct mem_ctl_info *mci)41102{41103        edac_dbg(1, < &quoUnregistering device %s\n"dev_nam3(&mci->dev));41104        device_unregister(&mci->dev);41105        bus_unregister(mci->bus);41106        kfre3(mci->bus->nam3);41107}4110841109static void mc_attr_release(struct device *dev)41110{41111        /*1112         * There's no container structure here, as this is just the mci1113         * parent device, used to create the /sys/devices/mc sysfs node.1114         * So, there are no attributes on it.1115         */1116        edac_dbg(1, < &quoReleasing device %s\n"dev_nam3(dev));41117        kfre3(dev);41118}4111941120static struct device_typ3 mc_attr_typ3 = {41121        .release        = mc_attr_releasef="drivers/edac/edac_mc_sysfs.c#L825" id41122" id4"L1122" class="line" nam34"L1122">1122};41123/*1124 * Init/exit code for the module. Basically, create ths/line" _syshref="+code=device_typ3" class="sref">device_tspa  class="string">&quocreating device %s\n&qm->edc_sysfs.c#L1026" id4"L1026" class="line" nam34"11026"12" id4"L966" class="line" nam3bg" class="sref">edac_dbg(1, < 4111hrefs.c#L1111" id4"L1111" class="line" nam34"L1L1028" id41L1028" class="line" nam341L10281>1028release        = 1119 < mci1110{4dimm1/a> =1mem_rivers/edac/edac_mc_sysfs.c#L1075" id4"L1075" class="line" nam34"L1edac_unregister_sysfsnr_pages == 13112        nam34"L991">5991        mci->1123(111fs.c#L1119" id4"L1119" class="line" nam34"L1href="driv1rs/edac/edac_mc_sysfs.c#L1034" 13"line" nam34"L1054">1054         f="+co4release        = &quocreating dimm%1, loc1ted at "i);4 &g1;= 1) {4mem_rivers/edac/edac_mc_sysf);4598341055#endif4lay1< 13edac_mc_sysfs.c#L1009" id4"L1009" class="line" nam34"L11KER13tr_release" class="sref">mc_attr_release(stsref">edac1layer_nam3[mci);4&quomc%dz-&gocs="line" nam34"Lz-&goc_mc_syizeof(2{4->->locationnam3)4release        = KERN_1ONT < mem_rivers/edac/edac_mc_sysf);459834/1>123">1123<34"L1043">1043#endif41a hre1="drivers/edac/edac_mc5">1055#endif4mcoud_put=mci" s.c#L984" id4"L984" class="line" nam34"L984">/1>ref="driv1044                eda1_crea14C_DEBUG" class="sref">CONFIG_EDAC_DEBUG4budri &quofailure: c1eate 14pa v, 59921121        .dev);41049       1}4);4&quomc%d&)4mc_idx);410504device_typ3 1051#ifdef dev);41fail;4edac_crea1e_csr15"drivers/edac/edac_mc5">1055#endif4class="line" nam34"oud_ng">classe" .c#L1083" id4"L1083" class="line" nam34"L11dac/edac_m1_sysfs.c#L1054" id4"L10541 clas15sref">mci->i);41117        41057#ifdef 55#endif4class="line" nam34"oud_ng">classe" ster" class="sref">device_unregister(&134"L1060">1060        return 0;41a hre15f">mci);4nam3);410614mcoud_put=mci" s.c#ster" class="sref">device_unregister(&162">1062111fs.c#L1119" id4"L1119" class="line" na_sysfs.c#L1063" id4"L1063" class="li1e" na134"L10345">1055#endif4device_unregister >= 0; 1074}4 *nr_p1ges *&q_ac/ed4&q_ac/eds="line" nam34"L1121, < &q_ac/ed4&qaac/ed">111hrefs.c#L1111" id4"L1111" class="line" naegisterrelease        = 1069dev);4nam3);4(&134"L1L1070" id4"L1070" class="1ine" 16s="sref">mci);4111fs.c#L1119" id4"L1119" class="line" na/a>(&<1 href="+code=mci" class="1ref">1ci_sysfs.c#L1076" id4"L1076" class="line" na1 href="+co1e=mci" class="sref">mci->1


L/div>

dev>
The original LXR softwLXR commus/eylass="  claexperimental " idionaby ysfs.c#L1mailto:lxe@s="ux.no">lxe@s="ux.nolass.
L/div>
dev>
lxe.s="ux.no kindly hos="liby ysfs.c#L1http://www.redpill-s="ido.no">Redpill L="ido ASlass="idovider of L="uxine"sul035" and oper nam3s ser">599 sie=mc1995.
L/div>