Linux Audio

Check our new training course

Loading...
v6.8
   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 * (c) 2012-2013 - Mauro Carvalho Chehab
  11 *	The entire API were re-written, and ported to use struct device
  12 *
  13 */
  14
  15#include <linux/ctype.h>
  16#include <linux/slab.h>
  17#include <linux/edac.h>
  18#include <linux/bug.h>
  19#include <linux/pm_runtime.h>
  20#include <linux/uaccess.h>
  21
  22#include "edac_mc.h"
  23#include "edac_module.h"
  24
 
  25/* MC EDAC Controls, setable by module parameter, and sysfs */
  26static int edac_mc_log_ue = 1;
  27static int edac_mc_log_ce = 1;
  28static int edac_mc_panic_on_ue;
  29static unsigned int edac_mc_poll_msec = 1000;
  30
  31/* Getter functions for above */
  32int edac_mc_get_log_ue(void)
  33{
  34	return edac_mc_log_ue;
  35}
  36
  37int edac_mc_get_log_ce(void)
  38{
  39	return edac_mc_log_ce;
  40}
  41
  42int edac_mc_get_panic_on_ue(void)
  43{
  44	return edac_mc_panic_on_ue;
  45}
  46
  47/* this is temporary */
  48unsigned int edac_mc_get_poll_msec(void)
  49{
  50	return edac_mc_poll_msec;
  51}
  52
  53static int edac_set_poll_msec(const char *val, const struct kernel_param *kp)
  54{
  55	unsigned int i;
  56	int ret;
  57
  58	if (!val)
  59		return -EINVAL;
  60
  61	ret = kstrtouint(val, 0, &i);
  62	if (ret)
  63		return ret;
  64
  65	if (i < 1000)
  66		return -EINVAL;
  67
  68	*((unsigned int *)kp->arg) = i;
  69
  70	/* notify edac_mc engine to reset the poll period */
  71	edac_mc_reset_delay_period(i);
  72
  73	return 0;
  74}
  75
  76/* Parameter declarations for above */
  77module_param(edac_mc_panic_on_ue, int, 0644);
  78MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
  79module_param(edac_mc_log_ue, int, 0644);
  80MODULE_PARM_DESC(edac_mc_log_ue,
  81		 "Log uncorrectable error to console: 0=off 1=on");
  82module_param(edac_mc_log_ce, int, 0644);
  83MODULE_PARM_DESC(edac_mc_log_ce,
  84		 "Log correctable error to console: 0=off 1=on");
  85module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_uint,
  86		  &edac_mc_poll_msec, 0644);
  87MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
  88
  89static struct device *mci_pdev;
  90
  91/*
  92 * various constants for Memory Controllers
  93 */
  94static const char * const dev_types[] = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  95	[DEV_UNKNOWN] = "Unknown",
  96	[DEV_X1] = "x1",
  97	[DEV_X2] = "x2",
  98	[DEV_X4] = "x4",
  99	[DEV_X8] = "x8",
 100	[DEV_X16] = "x16",
 101	[DEV_X32] = "x32",
 102	[DEV_X64] = "x64"
 103};
 104
 105static const char * const edac_caps[] = {
 106	[EDAC_UNKNOWN] = "Unknown",
 107	[EDAC_NONE] = "None",
 108	[EDAC_RESERVED] = "Reserved",
 109	[EDAC_PARITY] = "PARITY",
 110	[EDAC_EC] = "EC",
 111	[EDAC_SECDED] = "SECDED",
 112	[EDAC_S2ECD2ED] = "S2ECD2ED",
 113	[EDAC_S4ECD4ED] = "S4ECD4ED",
 114	[EDAC_S8ECD8ED] = "S8ECD8ED",
 115	[EDAC_S16ECD16ED] = "S16ECD16ED"
 116};
 117
 118#ifdef CONFIG_EDAC_LEGACY_SYSFS
 119/*
 120 * EDAC sysfs CSROW data structures and methods
 121 */
 122
 123#define to_csrow(k) container_of(k, struct csrow_info, dev)
 124
 125/*
 126 * We need it to avoid namespace conflicts between the legacy API
 127 * and the per-dimm/per-rank one
 128 */
 129#define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \
 130	static struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store)
 131
 132struct dev_ch_attribute {
 133	struct device_attribute attr;
 134	unsigned int channel;
 135};
 136
 137#define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \
 138	static struct dev_ch_attribute dev_attr_legacy_##_name = \
 139		{ __ATTR(_name, _mode, _show, _store), (_var) }
 140
 141#define to_channel(k) (container_of(k, struct dev_ch_attribute, attr)->channel)
 142
 143/* Set of more default csrow<id> attribute show/store functions */
 144static ssize_t csrow_ue_count_show(struct device *dev,
 145				   struct device_attribute *mattr, char *data)
 146{
 147	struct csrow_info *csrow = to_csrow(dev);
 148
 149	return sprintf(data, "%u\n", csrow->ue_count);
 150}
 151
 152static ssize_t csrow_ce_count_show(struct device *dev,
 153				   struct device_attribute *mattr, char *data)
 154{
 155	struct csrow_info *csrow = to_csrow(dev);
 156
 157	return sprintf(data, "%u\n", csrow->ce_count);
 158}
 159
 160static ssize_t csrow_size_show(struct device *dev,
 161			       struct device_attribute *mattr, char *data)
 162{
 163	struct csrow_info *csrow = to_csrow(dev);
 164	int i;
 165	u32 nr_pages = 0;
 166
 167	for (i = 0; i < csrow->nr_channels; i++)
 168		nr_pages += csrow->channels[i]->dimm->nr_pages;
 169	return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
 170}
 171
 172static ssize_t csrow_mem_type_show(struct device *dev,
 173				   struct device_attribute *mattr, char *data)
 174{
 175	struct csrow_info *csrow = to_csrow(dev);
 176
 177	return sprintf(data, "%s\n", edac_mem_types[csrow->channels[0]->dimm->mtype]);
 178}
 179
 180static ssize_t csrow_dev_type_show(struct device *dev,
 181				   struct device_attribute *mattr, char *data)
 182{
 183	struct csrow_info *csrow = to_csrow(dev);
 184
 185	return sprintf(data, "%s\n", dev_types[csrow->channels[0]->dimm->dtype]);
 186}
 187
 188static ssize_t csrow_edac_mode_show(struct device *dev,
 189				    struct device_attribute *mattr,
 190				    char *data)
 191{
 192	struct csrow_info *csrow = to_csrow(dev);
 193
 194	return sprintf(data, "%s\n", edac_caps[csrow->channels[0]->dimm->edac_mode]);
 195}
 196
 197/* show/store functions for DIMM Label attributes */
 198static ssize_t channel_dimm_label_show(struct device *dev,
 199				       struct device_attribute *mattr,
 200				       char *data)
 201{
 202	struct csrow_info *csrow = to_csrow(dev);
 203	unsigned int chan = to_channel(mattr);
 204	struct rank_info *rank = csrow->channels[chan];
 205
 206	/* if field has not been initialized, there is nothing to send */
 207	if (!rank->dimm->label[0])
 208		return 0;
 209
 210	return snprintf(data, sizeof(rank->dimm->label) + 1, "%s\n",
 211			rank->dimm->label);
 212}
 213
 214static ssize_t channel_dimm_label_store(struct device *dev,
 215					struct device_attribute *mattr,
 216					const char *data, size_t count)
 217{
 218	struct csrow_info *csrow = to_csrow(dev);
 219	unsigned int chan = to_channel(mattr);
 220	struct rank_info *rank = csrow->channels[chan];
 221	size_t copy_count = count;
 222
 223	if (count == 0)
 224		return -EINVAL;
 
 225
 226	if (data[count - 1] == '\0' || data[count - 1] == '\n')
 227		copy_count -= 1;
 228
 229	if (copy_count == 0 || copy_count >= sizeof(rank->dimm->label))
 230		return -EINVAL;
 
 
 
 
 231
 232	memcpy(rank->dimm->label, data, copy_count);
 233	rank->dimm->label[copy_count] = '\0';
 
 
 
 
 
 234
 235	return count;
 
 
 
 
 
 
 
 
 
 
 
 
 
 236}
 237
 238/* show function for dynamic chX_ce_count attribute */
 239static ssize_t channel_ce_count_show(struct device *dev,
 240				     struct device_attribute *mattr, char *data)
 241{
 242	struct csrow_info *csrow = to_csrow(dev);
 243	unsigned int chan = to_channel(mattr);
 244	struct rank_info *rank = csrow->channels[chan];
 245
 246	return sprintf(data, "%u\n", rank->ce_count);
 247}
 248
 249/* cwrow<id>/attribute files */
 250DEVICE_ATTR_LEGACY(size_mb, S_IRUGO, csrow_size_show, NULL);
 251DEVICE_ATTR_LEGACY(dev_type, S_IRUGO, csrow_dev_type_show, NULL);
 252DEVICE_ATTR_LEGACY(mem_type, S_IRUGO, csrow_mem_type_show, NULL);
 253DEVICE_ATTR_LEGACY(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL);
 254DEVICE_ATTR_LEGACY(ue_count, S_IRUGO, csrow_ue_count_show, NULL);
 255DEVICE_ATTR_LEGACY(ce_count, S_IRUGO, csrow_ce_count_show, NULL);
 256
 257/* default attributes of the CSROW<id> object */
 258static struct attribute *csrow_attrs[] = {
 259	&dev_attr_legacy_dev_type.attr,
 260	&dev_attr_legacy_mem_type.attr,
 261	&dev_attr_legacy_edac_mode.attr,
 262	&dev_attr_legacy_size_mb.attr,
 263	&dev_attr_legacy_ue_count.attr,
 264	&dev_attr_legacy_ce_count.attr,
 265	NULL,
 266};
 267
 268static const struct attribute_group csrow_attr_grp = {
 269	.attrs	= csrow_attrs,
 
 270};
 271
 272static const struct attribute_group *csrow_attr_groups[] = {
 273	&csrow_attr_grp,
 274	NULL
 
 
 
 275};
 276
 277static const struct device_type csrow_attr_type = {
 278	.groups		= csrow_attr_groups,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 279};
 280
 281/*
 282 * possible dynamic channel DIMM Label attribute files
 283 *
 284 */
 285DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR,
 286	channel_dimm_label_show, channel_dimm_label_store, 0);
 287DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR,
 288	channel_dimm_label_show, channel_dimm_label_store, 1);
 289DEVICE_CHANNEL(ch2_dimm_label, S_IRUGO | S_IWUSR,
 290	channel_dimm_label_show, channel_dimm_label_store, 2);
 291DEVICE_CHANNEL(ch3_dimm_label, S_IRUGO | S_IWUSR,
 292	channel_dimm_label_show, channel_dimm_label_store, 3);
 293DEVICE_CHANNEL(ch4_dimm_label, S_IRUGO | S_IWUSR,
 294	channel_dimm_label_show, channel_dimm_label_store, 4);
 295DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR,
 296	channel_dimm_label_show, channel_dimm_label_store, 5);
 297DEVICE_CHANNEL(ch6_dimm_label, S_IRUGO | S_IWUSR,
 298	channel_dimm_label_show, channel_dimm_label_store, 6);
 299DEVICE_CHANNEL(ch7_dimm_label, S_IRUGO | S_IWUSR,
 300	channel_dimm_label_show, channel_dimm_label_store, 7);
 301DEVICE_CHANNEL(ch8_dimm_label, S_IRUGO | S_IWUSR,
 302	channel_dimm_label_show, channel_dimm_label_store, 8);
 303DEVICE_CHANNEL(ch9_dimm_label, S_IRUGO | S_IWUSR,
 304	channel_dimm_label_show, channel_dimm_label_store, 9);
 305DEVICE_CHANNEL(ch10_dimm_label, S_IRUGO | S_IWUSR,
 306	channel_dimm_label_show, channel_dimm_label_store, 10);
 307DEVICE_CHANNEL(ch11_dimm_label, S_IRUGO | S_IWUSR,
 308	channel_dimm_label_show, channel_dimm_label_store, 11);
 309
 310/* Total possible dynamic DIMM Label attribute file table */
 311static struct attribute *dynamic_csrow_dimm_attr[] = {
 312	&dev_attr_legacy_ch0_dimm_label.attr.attr,
 313	&dev_attr_legacy_ch1_dimm_label.attr.attr,
 314	&dev_attr_legacy_ch2_dimm_label.attr.attr,
 315	&dev_attr_legacy_ch3_dimm_label.attr.attr,
 316	&dev_attr_legacy_ch4_dimm_label.attr.attr,
 317	&dev_attr_legacy_ch5_dimm_label.attr.attr,
 318	&dev_attr_legacy_ch6_dimm_label.attr.attr,
 319	&dev_attr_legacy_ch7_dimm_label.attr.attr,
 320	&dev_attr_legacy_ch8_dimm_label.attr.attr,
 321	&dev_attr_legacy_ch9_dimm_label.attr.attr,
 322	&dev_attr_legacy_ch10_dimm_label.attr.attr,
 323	&dev_attr_legacy_ch11_dimm_label.attr.attr,
 324	NULL
 325};
 326
 327/* possible dynamic channel ce_count attribute files */
 328DEVICE_CHANNEL(ch0_ce_count, S_IRUGO,
 329		   channel_ce_count_show, NULL, 0);
 330DEVICE_CHANNEL(ch1_ce_count, S_IRUGO,
 331		   channel_ce_count_show, NULL, 1);
 332DEVICE_CHANNEL(ch2_ce_count, S_IRUGO,
 333		   channel_ce_count_show, NULL, 2);
 334DEVICE_CHANNEL(ch3_ce_count, S_IRUGO,
 335		   channel_ce_count_show, NULL, 3);
 336DEVICE_CHANNEL(ch4_ce_count, S_IRUGO,
 337		   channel_ce_count_show, NULL, 4);
 338DEVICE_CHANNEL(ch5_ce_count, S_IRUGO,
 339		   channel_ce_count_show, NULL, 5);
 340DEVICE_CHANNEL(ch6_ce_count, S_IRUGO,
 341		   channel_ce_count_show, NULL, 6);
 342DEVICE_CHANNEL(ch7_ce_count, S_IRUGO,
 343		   channel_ce_count_show, NULL, 7);
 344DEVICE_CHANNEL(ch8_ce_count, S_IRUGO,
 345		   channel_ce_count_show, NULL, 8);
 346DEVICE_CHANNEL(ch9_ce_count, S_IRUGO,
 347		   channel_ce_count_show, NULL, 9);
 348DEVICE_CHANNEL(ch10_ce_count, S_IRUGO,
 349		   channel_ce_count_show, NULL, 10);
 350DEVICE_CHANNEL(ch11_ce_count, S_IRUGO,
 351		   channel_ce_count_show, NULL, 11);
 352
 353/* Total possible dynamic ce_count attribute file table */
 354static struct attribute *dynamic_csrow_ce_count_attr[] = {
 355	&dev_attr_legacy_ch0_ce_count.attr.attr,
 356	&dev_attr_legacy_ch1_ce_count.attr.attr,
 357	&dev_attr_legacy_ch2_ce_count.attr.attr,
 358	&dev_attr_legacy_ch3_ce_count.attr.attr,
 359	&dev_attr_legacy_ch4_ce_count.attr.attr,
 360	&dev_attr_legacy_ch5_ce_count.attr.attr,
 361	&dev_attr_legacy_ch6_ce_count.attr.attr,
 362	&dev_attr_legacy_ch7_ce_count.attr.attr,
 363	&dev_attr_legacy_ch8_ce_count.attr.attr,
 364	&dev_attr_legacy_ch9_ce_count.attr.attr,
 365	&dev_attr_legacy_ch10_ce_count.attr.attr,
 366	&dev_attr_legacy_ch11_ce_count.attr.attr,
 367	NULL
 368};
 369
 370static umode_t csrow_dev_is_visible(struct kobject *kobj,
 371				    struct attribute *attr, int idx)
 
 
 372{
 373	struct device *dev = kobj_to_dev(kobj);
 374	struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);
 375
 376	if (idx >= csrow->nr_channels)
 377		return 0;
 378
 379	if (idx >= ARRAY_SIZE(dynamic_csrow_ce_count_attr) - 1) {
 380		WARN_ONCE(1, "idx: %d\n", idx);
 381		return 0;
 
 
 
 
 
 
 
 
 
 
 382	}
 383
 384	/* Only expose populated DIMMs */
 385	if (!csrow->channels[idx]->dimm->nr_pages)
 386		return 0;
 387
 388	return attr->mode;
 389}
 390
 391
 392static const struct attribute_group csrow_dev_dimm_group = {
 393	.attrs = dynamic_csrow_dimm_attr,
 394	.is_visible = csrow_dev_is_visible,
 395};
 396
 397static const struct attribute_group csrow_dev_ce_count_group = {
 398	.attrs = dynamic_csrow_ce_count_attr,
 399	.is_visible = csrow_dev_is_visible,
 400};
 401
 402static const struct attribute_group *csrow_dev_groups[] = {
 403	&csrow_dev_dimm_group,
 404	&csrow_dev_ce_count_group,
 405	NULL
 406};
 407
 408static void csrow_release(struct device *dev)
 409{
 410	/*
 411	 * Nothing to do, just unregister sysfs here. The mci
 412	 * device owns the data and will also release it.
 413	 */
 414}
 415
 416static inline int nr_pages_per_csrow(struct csrow_info *csrow)
 417{
 418	int chan, nr_pages = 0;
 419
 420	for (chan = 0; chan < csrow->nr_channels; chan++)
 421		nr_pages += csrow->channels[chan]->dimm->nr_pages;
 422
 423	return nr_pages;
 424}
 425
 
 
 
 
 
 
 
 426/* Create a CSROW object under specifed edac_mc_device */
 427static int edac_create_csrow_object(struct mem_ctl_info *mci,
 428				    struct csrow_info *csrow, int index)
 429{
 
 
 
 430	int err;
 431
 432	csrow->dev.type = &csrow_attr_type;
 433	csrow->dev.groups = csrow_dev_groups;
 434	csrow->dev.release = csrow_release;
 435	device_initialize(&csrow->dev);
 436	csrow->dev.parent = &mci->dev;
 437	csrow->mci = mci;
 438	dev_set_name(&csrow->dev, "csrow%d", index);
 439	dev_set_drvdata(&csrow->dev, csrow);
 440
 441	err = device_add(&csrow->dev);
 442	if (err) {
 443		edac_dbg(1, "failure: create device %s\n", dev_name(&csrow->dev));
 444		put_device(&csrow->dev);
 445		return err;
 446	}
 447
 448	edac_dbg(0, "device %s created\n", dev_name(&csrow->dev));
 449
 450	return 0;
 451}
 452
 453/* Create a CSROW object under specifed edac_mc_device */
 454static int edac_create_csrow_objects(struct mem_ctl_info *mci)
 455{
 456	int err, i;
 457	struct csrow_info *csrow;
 458
 459	for (i = 0; i < mci->nr_csrows; i++) {
 460		csrow = mci->csrows[i];
 461		if (!nr_pages_per_csrow(csrow))
 462			continue;
 463		err = edac_create_csrow_object(mci, mci->csrows[i], i);
 464		if (err < 0)
 465			goto error;
 
 
 
 466	}
 
 467	return 0;
 468
 469error:
 470	for (--i; i >= 0; i--) {
 471		if (device_is_registered(&mci->csrows[i]->dev))
 472			device_unregister(&mci->csrows[i]->dev);
 473	}
 474
 
 475	return err;
 476}
 477
 478static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
 479{
 480	int i;
 481
 482	for (i = 0; i < mci->nr_csrows; i++) {
 483		if (device_is_registered(&mci->csrows[i]->dev))
 484			device_unregister(&mci->csrows[i]->dev);
 485	}
 486}
 487
 488#endif
 489
 490/*
 491 * Per-dimm (or per-rank) devices
 492 */
 
 493
 494#define to_dimm(k) container_of(k, struct dimm_info, dev)
 
 495
 496/* show/store functions for DIMM Label attributes */
 497static ssize_t dimmdev_location_show(struct device *dev,
 498				     struct device_attribute *mattr, char *data)
 499{
 500	struct dimm_info *dimm = to_dimm(dev);
 501	ssize_t count;
 502
 503	count = edac_dimm_info_location(dimm, data, PAGE_SIZE);
 504	count += scnprintf(data + count, PAGE_SIZE - count, "\n");
 
 505
 
 506	return count;
 507}
 508
 509static ssize_t dimmdev_label_show(struct device *dev,
 510				  struct device_attribute *mattr, char *data)
 
 
 
 
 
 
 
 
 
 511{
 512	struct dimm_info *dimm = to_dimm(dev);
 513
 514	/* if field has not been initialized, there is nothing to send */
 515	if (!dimm->label[0])
 516		return 0;
 517
 518	return snprintf(data, sizeof(dimm->label) + 1, "%s\n", dimm->label);
 519}
 520
 521static ssize_t dimmdev_label_store(struct device *dev,
 522				   struct device_attribute *mattr,
 523				   const char *data,
 524				   size_t count)
 525{
 526	struct dimm_info *dimm = to_dimm(dev);
 527	size_t copy_count = count;
 528
 529	if (count == 0)
 
 
 
 530		return -EINVAL;
 
 531
 532	if (data[count - 1] == '\0' || data[count - 1] == '\n')
 533		copy_count -= 1;
 534
 535	if (copy_count == 0 || copy_count >= sizeof(dimm->label))
 
 
 
 
 
 
 
 536		return -EINVAL;
 537
 538	memcpy(dimm->label, data, copy_count);
 539	dimm->label[copy_count] = '\0';
 
 
 
 540
 541	return count;
 542}
 543
 544static ssize_t dimmdev_size_show(struct device *dev,
 545				 struct device_attribute *mattr, char *data)
 546{
 547	struct dimm_info *dimm = to_dimm(dev);
 
 548
 549	return sprintf(data, "%u\n", PAGES_TO_MiB(dimm->nr_pages));
 
 
 550}
 551
 552static ssize_t dimmdev_mem_type_show(struct device *dev,
 553				     struct device_attribute *mattr, char *data)
 554{
 555	struct dimm_info *dimm = to_dimm(dev);
 
 556
 557	return sprintf(data, "%s\n", edac_mem_types[dimm->mtype]);
 
 
 558}
 559
 560static ssize_t dimmdev_dev_type_show(struct device *dev,
 561				     struct device_attribute *mattr, char *data)
 562{
 563	struct dimm_info *dimm = to_dimm(dev);
 
 564
 565	return sprintf(data, "%s\n", dev_types[dimm->dtype]);
 
 
 566}
 567
 568static ssize_t dimmdev_edac_mode_show(struct device *dev,
 569				      struct device_attribute *mattr,
 570				      char *data)
 571{
 572	struct dimm_info *dimm = to_dimm(dev);
 
 
 
 
 
 
 
 573
 574	return sprintf(data, "%s\n", edac_caps[dimm->edac_mode]);
 
 
 
 575}
 576
 577static ssize_t dimmdev_ce_count_show(struct device *dev,
 578				      struct device_attribute *mattr,
 579				      char *data)
 
 
 
 580{
 581	struct dimm_info *dimm = to_dimm(dev);
 
 
 
 582
 583	return sprintf(data, "%u\n", dimm->ce_count);
 
 
 
 584}
 585
 586static ssize_t dimmdev_ue_count_show(struct device *dev,
 587				      struct device_attribute *mattr,
 588				      char *data)
 589{
 590	struct dimm_info *dimm = to_dimm(dev);
 
 591
 592	return sprintf(data, "%u\n", dimm->ue_count);
 593}
 594
 595/* dimm/rank attribute files */
 596static DEVICE_ATTR(dimm_label, S_IRUGO | S_IWUSR,
 597		   dimmdev_label_show, dimmdev_label_store);
 598static DEVICE_ATTR(dimm_location, S_IRUGO, dimmdev_location_show, NULL);
 599static DEVICE_ATTR(size, S_IRUGO, dimmdev_size_show, NULL);
 600static DEVICE_ATTR(dimm_mem_type, S_IRUGO, dimmdev_mem_type_show, NULL);
 601static DEVICE_ATTR(dimm_dev_type, S_IRUGO, dimmdev_dev_type_show, NULL);
 602static DEVICE_ATTR(dimm_edac_mode, S_IRUGO, dimmdev_edac_mode_show, NULL);
 603static DEVICE_ATTR(dimm_ce_count, S_IRUGO, dimmdev_ce_count_show, NULL);
 604static DEVICE_ATTR(dimm_ue_count, S_IRUGO, dimmdev_ue_count_show, NULL);
 605
 606/* attributes of the dimm<id>/rank<id> object */
 607static struct attribute *dimm_attrs[] = {
 608	&dev_attr_dimm_label.attr,
 609	&dev_attr_dimm_location.attr,
 610	&dev_attr_size.attr,
 611	&dev_attr_dimm_mem_type.attr,
 612	&dev_attr_dimm_dev_type.attr,
 613	&dev_attr_dimm_edac_mode.attr,
 614	&dev_attr_dimm_ce_count.attr,
 615	&dev_attr_dimm_ue_count.attr,
 616	NULL,
 617};
 618
 619static const struct attribute_group dimm_attr_grp = {
 620	.attrs	= dimm_attrs,
 
 
 621};
 622
 623static const struct attribute_group *dimm_attr_groups[] = {
 624	&dimm_attr_grp,
 625	NULL
 
 
 626};
 627
 628static const struct device_type dimm_attr_type = {
 629	.groups		= dimm_attr_groups,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 630};
 631
 632static void dimm_release(struct device *dev)
 633{
 634	/*
 635	 * Nothing to do, just unregister sysfs here. The mci
 636	 * device owns the data and will also release it.
 637	 */
 638}
 639
 640/* Create a DIMM object under specifed memory controller device */
 641static int edac_create_dimm_object(struct mem_ctl_info *mci,
 642				   struct dimm_info *dimm)
 
 
 
 
 
 
 
 
 643{
 644	int err;
 645	dimm->mci = mci;
 646
 647	dimm->dev.type = &dimm_attr_type;
 648	dimm->dev.release = dimm_release;
 649	device_initialize(&dimm->dev);
 650
 651	dimm->dev.parent = &mci->dev;
 652	if (mci->csbased)
 653		dev_set_name(&dimm->dev, "rank%d", dimm->idx);
 654	else
 655		dev_set_name(&dimm->dev, "dimm%d", dimm->idx);
 656	dev_set_drvdata(&dimm->dev, dimm);
 657	pm_runtime_forbid(&mci->dev);
 658
 659	err = device_add(&dimm->dev);
 660	if (err) {
 661		edac_dbg(1, "failure: create device %s\n", dev_name(&dimm->dev));
 662		put_device(&dimm->dev);
 663		return err;
 664	}
 665
 666	if (IS_ENABLED(CONFIG_EDAC_DEBUG)) {
 667		char location[80];
 
 668
 669		edac_dimm_info_location(dimm, location, sizeof(location));
 670		edac_dbg(0, "device %s created at location %s\n",
 671			dev_name(&dimm->dev), location);
 672	}
 
 673
 674	return 0;
 675}
 
 
 676
 677/*
 678 * Memory controller device
 
 
 679 */
 680
 681#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
 682
 683static ssize_t mci_reset_counters_store(struct device *dev,
 684					struct device_attribute *mattr,
 685					const char *data, size_t count)
 686{
 687	struct mem_ctl_info *mci = to_mci(dev);
 688	struct dimm_info *dimm;
 689	int row, chan;
 690
 691	mci->ue_mc = 0;
 692	mci->ce_mc = 0;
 693	mci->ue_noinfo_count = 0;
 694	mci->ce_noinfo_count = 0;
 695
 696	for (row = 0; row < mci->nr_csrows; row++) {
 697		struct csrow_info *ri = mci->csrows[row];
 698
 699		ri->ue_count = 0;
 700		ri->ce_count = 0;
 701
 702		for (chan = 0; chan < ri->nr_channels; chan++)
 703			ri->channels[chan]->ce_count = 0;
 
 
 
 
 
 
 
 704	}
 705
 706	mci_for_each_dimm(mci, dimm) {
 707		dimm->ue_count = 0;
 708		dimm->ce_count = 0;
 
 
 
 
 
 
 
 709	}
 
 710
 711	mci->start_time = jiffies;
 712	return count;
 713}
 714
 715/* Memory scrubbing interface:
 716 *
 717 * A MC driver can limit the scrubbing bandwidth based on the CPU type.
 718 * Therefore, ->set_sdram_scrub_rate should be made to return the actual
 719 * bandwidth that is accepted or 0 when scrubbing is to be disabled.
 720 *
 721 * Negative value still means that an error has occurred while setting
 722 * the scrub rate.
 723 */
 724static ssize_t mci_sdram_scrub_rate_store(struct device *dev,
 725					  struct device_attribute *mattr,
 726					  const char *data, size_t count)
 727{
 728	struct mem_ctl_info *mci = to_mci(dev);
 729	unsigned long bandwidth = 0;
 730	int new_bw = 0;
 731
 732	if (kstrtoul(data, 10, &bandwidth) < 0)
 733		return -EINVAL;
 734
 735	new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
 736	if (new_bw < 0) {
 737		edac_printk(KERN_WARNING, EDAC_MC,
 738			    "Error setting scrub rate to: %lu\n", bandwidth);
 739		return -EINVAL;
 740	}
 741
 742	return count;
 
 
 
 
 743}
 744
 745/*
 746 * ->get_sdram_scrub_rate() return value semantics same as above.
 
 
 747 */
 748static ssize_t mci_sdram_scrub_rate_show(struct device *dev,
 749					 struct device_attribute *mattr,
 750					 char *data)
 751{
 752	struct mem_ctl_info *mci = to_mci(dev);
 753	int bandwidth = 0;
 754
 755	bandwidth = mci->get_sdram_scrub_rate(mci);
 756	if (bandwidth < 0) {
 757		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
 758		return bandwidth;
 759	}
 760
 761	return sprintf(data, "%d\n", bandwidth);
 762}
 763
 764/* default attribute files for the MCI object */
 765static ssize_t mci_ue_count_show(struct device *dev,
 766				 struct device_attribute *mattr,
 767				 char *data)
 768{
 769	struct mem_ctl_info *mci = to_mci(dev);
 770
 771	return sprintf(data, "%u\n", mci->ue_mc);
 772}
 773
 774static ssize_t mci_ce_count_show(struct device *dev,
 775				 struct device_attribute *mattr,
 776				 char *data)
 777{
 778	struct mem_ctl_info *mci = to_mci(dev);
 
 779
 780	return sprintf(data, "%u\n", mci->ce_mc);
 781}
 782
 783static ssize_t mci_ce_noinfo_show(struct device *dev,
 784				  struct device_attribute *mattr,
 785				  char *data)
 786{
 787	struct mem_ctl_info *mci = to_mci(dev);
 788
 789	return sprintf(data, "%u\n", mci->ce_noinfo_count);
 790}
 791
 792static ssize_t mci_ue_noinfo_show(struct device *dev,
 793				  struct device_attribute *mattr,
 794				  char *data)
 795{
 796	struct mem_ctl_info *mci = to_mci(dev);
 
 797
 798	return sprintf(data, "%u\n", mci->ue_noinfo_count);
 799}
 800
 801static ssize_t mci_seconds_show(struct device *dev,
 802				struct device_attribute *mattr,
 803				char *data)
 804{
 805	struct mem_ctl_info *mci = to_mci(dev);
 806
 807	return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ);
 808}
 809
 810static ssize_t mci_ctl_name_show(struct device *dev,
 811				 struct device_attribute *mattr,
 812				 char *data)
 813{
 814	struct mem_ctl_info *mci = to_mci(dev);
 
 815
 816	return sprintf(data, "%s\n", mci->ctl_name);
 
 
 
 817}
 818
 819static ssize_t mci_size_mb_show(struct device *dev,
 820				struct device_attribute *mattr,
 821				char *data)
 822{
 823	struct mem_ctl_info *mci = to_mci(dev);
 824	int total_pages = 0, csrow_idx, j;
 825
 826	for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
 827		struct csrow_info *csrow = mci->csrows[csrow_idx];
 
 
 
 828
 829		for (j = 0; j < csrow->nr_channels; j++) {
 830			struct dimm_info *dimm = csrow->channels[j]->dimm;
 831
 832			total_pages += dimm->nr_pages;
 833		}
 834	}
 
 
 
 
 
 
 
 
 835
 836	return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages));
 837}
 838
 839static ssize_t mci_max_location_show(struct device *dev,
 840				     struct device_attribute *mattr,
 841				     char *data)
 842{
 843	struct mem_ctl_info *mci = to_mci(dev);
 844	int len = PAGE_SIZE;
 845	char *p = data;
 846	int i, n;
 847
 848	for (i = 0; i < mci->n_layers; i++) {
 849		n = scnprintf(p, len, "%s %d ",
 850			      edac_layer_name[mci->layers[i].type],
 851			      mci->layers[i].size - 1);
 852		len -= n;
 853		if (len <= 0)
 854			goto out;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 855
 856		p += n;
 857	}
 858
 859	p += scnprintf(p, len, "\n");
 860out:
 861	return p - data;
 862}
 863
 864/* default Control file */
 865static DEVICE_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store);
 866
 867/* default Attribute files */
 868static DEVICE_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL);
 869static DEVICE_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL);
 870static DEVICE_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL);
 871static DEVICE_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL);
 872static DEVICE_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL);
 873static DEVICE_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL);
 874static DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);
 875static DEVICE_ATTR(max_location, S_IRUGO, mci_max_location_show, NULL);
 876
 877/* memory scrubber attribute file */
 878static DEVICE_ATTR(sdram_scrub_rate, 0, mci_sdram_scrub_rate_show,
 879	    mci_sdram_scrub_rate_store); /* umode set later in is_visible */
 880
 881static struct attribute *mci_attrs[] = {
 882	&dev_attr_reset_counters.attr,
 883	&dev_attr_mc_name.attr,
 884	&dev_attr_size_mb.attr,
 885	&dev_attr_seconds_since_reset.attr,
 886	&dev_attr_ue_noinfo_count.attr,
 887	&dev_attr_ce_noinfo_count.attr,
 888	&dev_attr_ue_count.attr,
 889	&dev_attr_ce_count.attr,
 890	&dev_attr_max_location.attr,
 891	&dev_attr_sdram_scrub_rate.attr,
 892	NULL
 893};
 894
 895static umode_t mci_attr_is_visible(struct kobject *kobj,
 896				   struct attribute *attr, int idx)
 897{
 898	struct device *dev = kobj_to_dev(kobj);
 899	struct mem_ctl_info *mci = to_mci(dev);
 900	umode_t mode = 0;
 901
 902	if (attr != &dev_attr_sdram_scrub_rate.attr)
 903		return attr->mode;
 904	if (mci->get_sdram_scrub_rate)
 905		mode |= S_IRUGO;
 906	if (mci->set_sdram_scrub_rate)
 907		mode |= S_IWUSR;
 908	return mode;
 909}
 910
 911static const struct attribute_group mci_attr_grp = {
 912	.attrs	= mci_attrs,
 913	.is_visible = mci_attr_is_visible,
 914};
 
 
 
 
 
 
 
 
 
 
 
 915
 916static const struct attribute_group *mci_attr_groups[] = {
 917	&mci_attr_grp,
 918	NULL
 919};
 
 
 
 
 
 920
 921static const struct device_type mci_attr_type = {
 922	.groups		= mci_attr_groups,
 923};
 924
 925/*
 926 * Create a new Memory Controller kobject instance,
 927 *	mc<id> under the 'mc' directory
 928 *
 929 * Return:
 930 *	0	Success
 931 *	!0	Failure
 932 */
 933int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
 934				 const struct attribute_group **groups)
 935{
 936	struct dimm_info *dimm;
 937	int err;
 
 
 938
 939	/* get the /sys/devices/system/edac subsys reference */
 940	mci->dev.type = &mci_attr_type;
 941	mci->dev.parent = mci_pdev;
 942	mci->dev.groups = groups;
 943	dev_set_name(&mci->dev, "mc%d", mci->mc_idx);
 944	dev_set_drvdata(&mci->dev, mci);
 945	pm_runtime_forbid(&mci->dev);
 946
 947	err = device_add(&mci->dev);
 948	if (err < 0) {
 949		edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
 950		/* no put_device() here, free mci with _edac_mc_free() */
 951		return err;
 952	}
 953
 954	edac_dbg(0, "device %s created\n", dev_name(&mci->dev));
 
 
 
 
 
 
 
 
 
 
 
 
 955
 956	/*
 957	 * Create the dimm/rank devices
 958	 */
 959	mci_for_each_dimm(mci, dimm) {
 960		/* Only expose populated DIMMs */
 961		if (!dimm->nr_pages)
 962			continue;
 963
 964		err = edac_create_dimm_object(mci, dimm);
 965		if (err)
 966			goto fail;
 
 
 
 
 
 
 967	}
 968
 969#ifdef CONFIG_EDAC_LEGACY_SYSFS
 970	err = edac_create_csrow_objects(mci);
 971	if (err < 0)
 972		goto fail;
 973#endif
 974
 975	edac_create_debugfs_nodes(mci);
 976	return 0;
 977
 978fail:
 979	edac_remove_sysfs_mci_device(mci);
 
 
 
 
 
 
 
 
 
 
 
 
 980
 
 981	return err;
 982}
 983
 984/*
 985 * remove a Memory Controller instance
 986 */
 987void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
 988{
 989	struct dimm_info *dimm;
 990
 991	if (!device_is_registered(&mci->dev))
 992		return;
 993
 994	edac_dbg(0, "\n");
 995
 996#ifdef CONFIG_EDAC_DEBUG
 997	edac_debugfs_remove_recursive(mci->debugfs);
 998#endif
 999#ifdef CONFIG_EDAC_LEGACY_SYSFS
1000	edac_delete_csrow_objects(mci);
1001#endif
 
 
1002
1003	mci_for_each_dimm(mci, dimm) {
1004		if (!device_is_registered(&dimm->dev))
1005			continue;
1006		edac_dbg(1, "unregistering device %s\n", dev_name(&dimm->dev));
1007		device_unregister(&dimm->dev);
 
1008	}
1009
1010	/* only remove the device, but keep mci */
1011	device_del(&mci->dev);
 
 
 
 
 
1012}
1013
1014static void mc_attr_release(struct device *dev)
1015{
1016	/*
1017	 * There's no container structure here, as this is just the mci
1018	 * parent device, used to create the /sys/devices/mc sysfs node.
1019	 * So, there are no attributes on it.
1020	 */
1021	edac_dbg(1, "device %s released\n", dev_name(dev));
1022	kfree(dev);
1023}
1024
1025/*
1026 * Init/exit code for the module. Basically, creates/removes /sys/class/rc
 
 
 
 
 
 
 
 
 
1027 */
1028int __init edac_mc_sysfs_init(void)
1029{
1030	int err;
 
1031
1032	mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
1033	if (!mci_pdev)
1034		return -ENOMEM;
1035
1036	mci_pdev->bus = edac_get_sysfs_subsys();
1037	mci_pdev->release = mc_attr_release;
1038	mci_pdev->init_name = "mc";
1039
1040	err = device_register(mci_pdev);
1041	if (err < 0) {
1042		edac_dbg(1, "failure: create device %s\n", dev_name(mci_pdev));
1043		put_device(mci_pdev);
1044		return err;
 
 
1045	}
1046
1047	edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
1048
1049	return 0;
 
 
 
 
 
 
1050}
1051
1052void edac_mc_sysfs_exit(void)
 
 
 
 
 
1053{
1054	device_unregister(mci_pdev);
 
1055}
v3.1
   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/slab.h>
  14#include <linux/edac.h>
  15#include <linux/bug.h>
 
 
  16
  17#include "edac_core.h"
  18#include "edac_module.h"
  19
  20
  21/* MC EDAC Controls, setable by module parameter, and sysfs */
  22static int edac_mc_log_ue = 1;
  23static int edac_mc_log_ce = 1;
  24static int edac_mc_panic_on_ue;
  25static int edac_mc_poll_msec = 1000;
  26
  27/* Getter functions for above */
  28int edac_mc_get_log_ue(void)
  29{
  30	return edac_mc_log_ue;
  31}
  32
  33int edac_mc_get_log_ce(void)
  34{
  35	return edac_mc_log_ce;
  36}
  37
  38int edac_mc_get_panic_on_ue(void)
  39{
  40	return edac_mc_panic_on_ue;
  41}
  42
  43/* this is temporary */
  44int edac_mc_get_poll_msec(void)
  45{
  46	return edac_mc_poll_msec;
  47}
  48
  49static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
  50{
  51	long l;
  52	int ret;
  53
  54	if (!val)
  55		return -EINVAL;
  56
  57	ret = strict_strtol(val, 0, &l);
  58	if (ret == -EINVAL || ((int)l != l))
 
 
 
  59		return -EINVAL;
  60	*((int *)kp->arg) = l;
 
  61
  62	/* notify edac_mc engine to reset the poll period */
  63	edac_mc_reset_delay_period(l);
  64
  65	return 0;
  66}
  67
  68/* Parameter declarations for above */
  69module_param(edac_mc_panic_on_ue, int, 0644);
  70MODULE_PARM_DESC(edac_mc_panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
  71module_param(edac_mc_log_ue, int, 0644);
  72MODULE_PARM_DESC(edac_mc_log_ue,
  73		 "Log uncorrectable error to console: 0=off 1=on");
  74module_param(edac_mc_log_ce, int, 0644);
  75MODULE_PARM_DESC(edac_mc_log_ce,
  76		 "Log correctable error to console: 0=off 1=on");
  77module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int,
  78		  &edac_mc_poll_msec, 0644);
  79MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
  80
 
 
  81/*
  82 * various constants for Memory Controllers
  83 */
  84static const char *mem_types[] = {
  85	[MEM_EMPTY] = "Empty",
  86	[MEM_RESERVED] = "Reserved",
  87	[MEM_UNKNOWN] = "Unknown",
  88	[MEM_FPM] = "FPM",
  89	[MEM_EDO] = "EDO",
  90	[MEM_BEDO] = "BEDO",
  91	[MEM_SDR] = "Unbuffered-SDR",
  92	[MEM_RDR] = "Registered-SDR",
  93	[MEM_DDR] = "Unbuffered-DDR",
  94	[MEM_RDDR] = "Registered-DDR",
  95	[MEM_RMBS] = "RMBS",
  96	[MEM_DDR2] = "Unbuffered-DDR2",
  97	[MEM_FB_DDR2] = "FullyBuffered-DDR2",
  98	[MEM_RDDR2] = "Registered-DDR2",
  99	[MEM_XDR] = "XDR",
 100	[MEM_DDR3] = "Unbuffered-DDR3",
 101	[MEM_RDDR3] = "Registered-DDR3"
 102};
 103
 104static const char *dev_types[] = {
 105	[DEV_UNKNOWN] = "Unknown",
 106	[DEV_X1] = "x1",
 107	[DEV_X2] = "x2",
 108	[DEV_X4] = "x4",
 109	[DEV_X8] = "x8",
 110	[DEV_X16] = "x16",
 111	[DEV_X32] = "x32",
 112	[DEV_X64] = "x64"
 113};
 114
 115static const char *edac_caps[] = {
 116	[EDAC_UNKNOWN] = "Unknown",
 117	[EDAC_NONE] = "None",
 118	[EDAC_RESERVED] = "Reserved",
 119	[EDAC_PARITY] = "PARITY",
 120	[EDAC_EC] = "EC",
 121	[EDAC_SECDED] = "SECDED",
 122	[EDAC_S2ECD2ED] = "S2ECD2ED",
 123	[EDAC_S4ECD4ED] = "S4ECD4ED",
 124	[EDAC_S8ECD8ED] = "S8ECD8ED",
 125	[EDAC_S16ECD16ED] = "S16ECD16ED"
 126};
 127
 128/* EDAC sysfs CSROW data structures and methods
 
 
 
 
 
 
 
 
 
 129 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 130
 131/* Set of more default csrow<id> attribute show/store functions */
 132static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data,
 133				int private)
 134{
 
 
 135	return sprintf(data, "%u\n", csrow->ue_count);
 136}
 137
 138static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data,
 139				int private)
 140{
 
 
 141	return sprintf(data, "%u\n", csrow->ce_count);
 142}
 143
 144static ssize_t csrow_size_show(struct csrow_info *csrow, char *data,
 145				int private)
 146{
 147	return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
 
 
 
 
 
 
 148}
 149
 150static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data,
 151				int private)
 152{
 153	return sprintf(data, "%s\n", mem_types[csrow->mtype]);
 
 
 154}
 155
 156static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data,
 157				int private)
 158{
 159	return sprintf(data, "%s\n", dev_types[csrow->dtype]);
 
 
 160}
 161
 162static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data,
 163				int private)
 
 164{
 165	return sprintf(data, "%s\n", edac_caps[csrow->edac_mode]);
 
 
 166}
 167
 168/* show/store functions for DIMM Label attributes */
 169static ssize_t channel_dimm_label_show(struct csrow_info *csrow,
 170				char *data, int channel)
 171{
 
 
 
 
 
 172	/* if field has not been initialized, there is nothing to send */
 173	if (!csrow->channels[channel].label[0])
 174		return 0;
 175
 176	return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
 177			csrow->channels[channel].label);
 178}
 179
 180static ssize_t channel_dimm_label_store(struct csrow_info *csrow,
 181					const char *data,
 182					size_t count, int channel)
 183{
 184	ssize_t max_size = 0;
 
 
 
 185
 186	max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
 187	strncpy(csrow->channels[channel].label, data, max_size);
 188	csrow->channels[channel].label[max_size] = '\0';
 189
 190	return max_size;
 191}
 192
 193/* show function for dynamic chX_ce_count attribute */
 194static ssize_t channel_ce_count_show(struct csrow_info *csrow,
 195				char *data, int channel)
 196{
 197	return sprintf(data, "%u\n", csrow->channels[channel].ce_count);
 198}
 199
 200/* csrow specific attribute structure */
 201struct csrowdev_attribute {
 202	struct attribute attr;
 203	 ssize_t(*show) (struct csrow_info *, char *, int);
 204	 ssize_t(*store) (struct csrow_info *, const char *, size_t, int);
 205	int private;
 206};
 207
 208#define to_csrow(k) container_of(k, struct csrow_info, kobj)
 209#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
 210
 211/* Set of show/store higher level functions for default csrow attributes */
 212static ssize_t csrowdev_show(struct kobject *kobj,
 213			struct attribute *attr, char *buffer)
 214{
 215	struct csrow_info *csrow = to_csrow(kobj);
 216	struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
 217
 218	if (csrowdev_attr->show)
 219		return csrowdev_attr->show(csrow,
 220					buffer, csrowdev_attr->private);
 221	return -EIO;
 222}
 223
 224static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
 225			const char *buffer, size_t count)
 
 226{
 227	struct csrow_info *csrow = to_csrow(kobj);
 228	struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
 
 
 
 
 
 
 
 
 
 
 
 
 229
 230	if (csrowdev_attr->store)
 231		return csrowdev_attr->store(csrow,
 232					buffer,
 233					count, csrowdev_attr->private);
 234	return -EIO;
 235}
 
 
 
 
 236
 237static const struct sysfs_ops csrowfs_ops = {
 238	.show = csrowdev_show,
 239	.store = csrowdev_store
 240};
 241
 242#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private)	\
 243static struct csrowdev_attribute attr_##_name = {			\
 244	.attr = {.name = __stringify(_name), .mode = _mode },	\
 245	.show   = _show,					\
 246	.store  = _store,					\
 247	.private = _private,					\
 248};
 249
 250/* default cwrow<id>/attribute files */
 251CSROWDEV_ATTR(size_mb, S_IRUGO, csrow_size_show, NULL, 0);
 252CSROWDEV_ATTR(dev_type, S_IRUGO, csrow_dev_type_show, NULL, 0);
 253CSROWDEV_ATTR(mem_type, S_IRUGO, csrow_mem_type_show, NULL, 0);
 254CSROWDEV_ATTR(edac_mode, S_IRUGO, csrow_edac_mode_show, NULL, 0);
 255CSROWDEV_ATTR(ue_count, S_IRUGO, csrow_ue_count_show, NULL, 0);
 256CSROWDEV_ATTR(ce_count, S_IRUGO, csrow_ce_count_show, NULL, 0);
 257
 258/* default attributes of the CSROW<id> object */
 259static struct csrowdev_attribute *default_csrow_attr[] = {
 260	&attr_dev_type,
 261	&attr_mem_type,
 262	&attr_edac_mode,
 263	&attr_size_mb,
 264	&attr_ue_count,
 265	&attr_ce_count,
 266	NULL,
 267};
 268
 269/* possible dynamic channel DIMM Label attribute files */
 270CSROWDEV_ATTR(ch0_dimm_label, S_IRUGO | S_IWUSR,
 
 
 
 271	channel_dimm_label_show, channel_dimm_label_store, 0);
 272CSROWDEV_ATTR(ch1_dimm_label, S_IRUGO | S_IWUSR,
 273	channel_dimm_label_show, channel_dimm_label_store, 1);
 274CSROWDEV_ATTR(ch2_dimm_label, S_IRUGO | S_IWUSR,
 275	channel_dimm_label_show, channel_dimm_label_store, 2);
 276CSROWDEV_ATTR(ch3_dimm_label, S_IRUGO | S_IWUSR,
 277	channel_dimm_label_show, channel_dimm_label_store, 3);
 278CSROWDEV_ATTR(ch4_dimm_label, S_IRUGO | S_IWUSR,
 279	channel_dimm_label_show, channel_dimm_label_store, 4);
 280CSROWDEV_ATTR(ch5_dimm_label, S_IRUGO | S_IWUSR,
 281	channel_dimm_label_show, channel_dimm_label_store, 5);
 
 
 
 
 
 
 
 
 
 
 
 
 282
 283/* Total possible dynamic DIMM Label attribute file table */
 284static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = {
 285	&attr_ch0_dimm_label,
 286	&attr_ch1_dimm_label,
 287	&attr_ch2_dimm_label,
 288	&attr_ch3_dimm_label,
 289	&attr_ch4_dimm_label,
 290	&attr_ch5_dimm_label
 
 
 
 
 
 
 
 291};
 292
 293/* possible dynamic channel ce_count attribute files */
 294CSROWDEV_ATTR(ch0_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 0);
 295CSROWDEV_ATTR(ch1_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 1);
 296CSROWDEV_ATTR(ch2_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 2);
 297CSROWDEV_ATTR(ch3_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 3);
 298CSROWDEV_ATTR(ch4_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 4);
 299CSROWDEV_ATTR(ch5_ce_count, S_IRUGO | S_IWUSR, channel_ce_count_show, NULL, 5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 300
 301/* Total possible dynamic ce_count attribute file table */
 302static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = {
 303	&attr_ch0_ce_count,
 304	&attr_ch1_ce_count,
 305	&attr_ch2_ce_count,
 306	&attr_ch3_ce_count,
 307	&attr_ch4_ce_count,
 308	&attr_ch5_ce_count
 
 
 
 
 
 
 
 309};
 310
 311#define EDAC_NR_CHANNELS	6
 312
 313/* Create dynamic CHANNEL files, indexed by 'chan',  under specifed CSROW */
 314static int edac_create_channel_files(struct kobject *kobj, int chan)
 315{
 316	int err = -ENODEV;
 
 317
 318	if (chan >= EDAC_NR_CHANNELS)
 319		return err;
 320
 321	/* create the DIMM label attribute file */
 322	err = sysfs_create_file(kobj,
 323				(struct attribute *)
 324				dynamic_csrow_dimm_attr[chan]);
 325
 326	if (!err) {
 327		/* create the CE Count attribute file */
 328		err = sysfs_create_file(kobj,
 329					(struct attribute *)
 330					dynamic_csrow_ce_count_attr[chan]);
 331	} else {
 332		debugf1("%s()  dimm labels and ce_count files created",
 333			__func__);
 334	}
 335
 336	return err;
 
 
 
 
 337}
 338
 339/* No memory to release for this kobj */
 340static void edac_csrow_instance_release(struct kobject *kobj)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 341{
 342	struct mem_ctl_info *mci;
 343	struct csrow_info *cs;
 
 
 
 344
 345	debugf1("%s()\n", __func__);
 
 
 346
 347	cs = container_of(kobj, struct csrow_info, kobj);
 348	mci = cs->mci;
 349
 350	kobject_put(&mci->edac_mci_kobj);
 351}
 352
 353/* the kobj_type instance for a CSROW */
 354static struct kobj_type ktype_csrow = {
 355	.release = edac_csrow_instance_release,
 356	.sysfs_ops = &csrowfs_ops,
 357	.default_attrs = (struct attribute **)default_csrow_attr,
 358};
 359
 360/* Create a CSROW object under specifed edac_mc_device */
 361static int edac_create_csrow_object(struct mem_ctl_info *mci,
 362					struct csrow_info *csrow, int index)
 363{
 364	struct kobject *kobj_mci = &mci->edac_mci_kobj;
 365	struct kobject *kobj;
 366	int chan;
 367	int err;
 368
 369	/* generate ..../edac/mc/mc<id>/csrow<index>   */
 370	memset(&csrow->kobj, 0, sizeof(csrow->kobj));
 371	csrow->mci = mci;	/* include container up link */
 372
 373	/* bump the mci instance's kobject's ref count */
 374	kobj = kobject_get(&mci->edac_mci_kobj);
 375	if (!kobj) {
 376		err = -ENODEV;
 377		goto err_out;
 
 
 
 
 
 378	}
 379
 380	/* Instanstiate the csrow object */
 381	err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci,
 382				   "csrow%d", index);
 383	if (err)
 384		goto err_release_top_kobj;
 385
 386	/* At this point, to release a csrow kobj, one must
 387	 * call the kobject_put and allow that tear down
 388	 * to work the releasing
 389	 */
 390
 391	/* Create the dyanmic attribute files on this csrow,
 392	 * namely, the DIMM labels and the channel ce_count
 393	 */
 394	for (chan = 0; chan < csrow->nr_channels; chan++) {
 395		err = edac_create_channel_files(&csrow->kobj, chan);
 396		if (err) {
 397			/* special case the unregister here */
 398			kobject_put(&csrow->kobj);
 399			goto err_out;
 400		}
 401	}
 402	kobject_uevent(&csrow->kobj, KOBJ_ADD);
 403	return 0;
 404
 405	/* error unwind stack */
 406err_release_top_kobj:
 407	kobject_put(&mci->edac_mci_kobj);
 
 
 408
 409err_out:
 410	return err;
 411}
 412
 413/* default sysfs methods and data structures for the main MCI kobject */
 
 
 414
 415static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
 416					const char *data, size_t count)
 417{
 418	int row, chan;
 
 
 
 419
 420	mci->ue_noinfo_count = 0;
 421	mci->ce_noinfo_count = 0;
 422	mci->ue_count = 0;
 423	mci->ce_count = 0;
 424
 425	for (row = 0; row < mci->nr_csrows; row++) {
 426		struct csrow_info *ri = &mci->csrows[row];
 427
 428		ri->ue_count = 0;
 429		ri->ce_count = 0;
 
 
 
 
 430
 431		for (chan = 0; chan < ri->nr_channels; chan++)
 432			ri->channels[chan].ce_count = 0;
 433	}
 434
 435	mci->start_time = jiffies;
 436	return count;
 437}
 438
 439/* Memory scrubbing interface:
 440 *
 441 * A MC driver can limit the scrubbing bandwidth based on the CPU type.
 442 * Therefore, ->set_sdram_scrub_rate should be made to return the actual
 443 * bandwidth that is accepted or 0 when scrubbing is to be disabled.
 444 *
 445 * Negative value still means that an error has occurred while setting
 446 * the scrub rate.
 447 */
 448static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
 449					  const char *data, size_t count)
 450{
 451	unsigned long bandwidth = 0;
 452	int new_bw = 0;
 
 
 
 453
 454	if (!mci->set_sdram_scrub_rate)
 455		return -EINVAL;
 456
 457	if (strict_strtoul(data, 10, &bandwidth) < 0)
 458		return -EINVAL;
 
 
 
 
 
 459
 460	new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
 461	if (new_bw < 0) {
 462		edac_printk(KERN_WARNING, EDAC_MC,
 463			    "Error setting scrub rate to: %lu\n", bandwidth);
 464		return -EINVAL;
 465	}
 466
 467	return count;
 468}
 469
 470/*
 471 * ->get_sdram_scrub_rate() return value semantics same as above.
 472 */
 473static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
 474{
 475	int bandwidth = 0;
 476
 477	if (!mci->get_sdram_scrub_rate)
 478		return -EINVAL;
 479
 480	bandwidth = mci->get_sdram_scrub_rate(mci);
 481	if (bandwidth < 0) {
 482		edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n");
 483		return bandwidth;
 484	}
 485
 486	return sprintf(data, "%d\n", bandwidth);
 487}
 488
 489/* default attribute files for the MCI object */
 490static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
 491{
 492	return sprintf(data, "%d\n", mci->ue_count);
 493}
 494
 495static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
 496{
 497	return sprintf(data, "%d\n", mci->ce_count);
 498}
 499
 500static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
 
 501{
 502	return sprintf(data, "%d\n", mci->ce_noinfo_count);
 503}
 504
 505static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
 506{
 507	return sprintf(data, "%d\n", mci->ue_noinfo_count);
 508}
 509
 510static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
 
 511{
 512	return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ);
 513}
 514
 515static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
 516{
 517	return sprintf(data, "%s\n", mci->ctl_name);
 518}
 519
 520static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
 
 
 521{
 522	int total_pages, csrow_idx;
 523
 524	for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
 525		csrow_idx++) {
 526		struct csrow_info *csrow = &mci->csrows[csrow_idx];
 527
 528		if (!csrow->nr_pages)
 529			continue;
 530
 531		total_pages += csrow->nr_pages;
 532	}
 533
 534	return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages));
 535}
 536
 537#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
 538#define to_mcidev_attr(a) container_of(a,struct mcidev_sysfs_attribute,attr)
 539
 540/* MCI show/store functions for top most object */
 541static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
 542			char *buffer)
 543{
 544	struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
 545	struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 546
 547	debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
 548
 549	if (mcidev_attr->show)
 550		return mcidev_attr->show(mem_ctl_info, buffer);
 551
 552	return -EIO;
 553}
 554
 555static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
 556			const char *buffer, size_t count)
 
 557{
 558	struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
 559	struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 560
 561	debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
 
 562
 563	if (mcidev_attr->store)
 564		return mcidev_attr->store(mem_ctl_info, buffer, count);
 
 
 
 
 
 
 
 
 565
 566	return -EIO;
 567}
 
 
 
 
 
 
 
 
 
 
 568
 569/* Intermediate show/store table */
 570static const struct sysfs_ops mci_ops = {
 571	.show = mcidev_show,
 572	.store = mcidev_store
 573};
 574
 575#define MCIDEV_ATTR(_name,_mode,_show,_store)			\
 576static struct mcidev_sysfs_attribute mci_attr_##_name = {			\
 577	.attr = {.name = __stringify(_name), .mode = _mode },	\
 578	.show   = _show,					\
 579	.store  = _store,					\
 580};
 581
 582/* default Control file */
 583MCIDEV_ATTR(reset_counters, S_IWUSR, NULL, mci_reset_counters_store);
 584
 585/* default Attribute files */
 586MCIDEV_ATTR(mc_name, S_IRUGO, mci_ctl_name_show, NULL);
 587MCIDEV_ATTR(size_mb, S_IRUGO, mci_size_mb_show, NULL);
 588MCIDEV_ATTR(seconds_since_reset, S_IRUGO, mci_seconds_show, NULL);
 589MCIDEV_ATTR(ue_noinfo_count, S_IRUGO, mci_ue_noinfo_show, NULL);
 590MCIDEV_ATTR(ce_noinfo_count, S_IRUGO, mci_ce_noinfo_show, NULL);
 591MCIDEV_ATTR(ue_count, S_IRUGO, mci_ue_count_show, NULL);
 592MCIDEV_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);
 593
 594/* memory scrubber attribute file */
 595MCIDEV_ATTR(sdram_scrub_rate, S_IRUGO | S_IWUSR, mci_sdram_scrub_rate_show,
 596	mci_sdram_scrub_rate_store);
 597
 598static struct mcidev_sysfs_attribute *mci_attr[] = {
 599	&mci_attr_reset_counters,
 600	&mci_attr_mc_name,
 601	&mci_attr_size_mb,
 602	&mci_attr_seconds_since_reset,
 603	&mci_attr_ue_noinfo_count,
 604	&mci_attr_ce_noinfo_count,
 605	&mci_attr_ue_count,
 606	&mci_attr_ce_count,
 607	&mci_attr_sdram_scrub_rate,
 608	NULL
 609};
 610
 
 
 
 
 
 
 
 611
 612/*
 613 * Release of a MC controlling instance
 614 *
 615 *	each MC control instance has the following resources upon entry:
 616 *		a) a ref count on the top memctl kobj
 617 *		b) a ref count on this module
 618 *
 619 *	this function must decrement those ref counts and then
 620 *	issue a free on the instance's memory
 621 */
 622static void edac_mci_control_release(struct kobject *kobj)
 623{
 624	struct mem_ctl_info *mci;
 
 625
 626	mci = to_mci(kobj);
 
 
 
 
 
 
 
 
 
 
 627
 628	debugf0("%s() mci instance idx=%d releasing\n", __func__, mci->mc_idx);
 
 
 
 
 
 629
 630	/* decrement the module ref count */
 631	module_put(mci->owner);
 632}
 633
 634static struct kobj_type ktype_mci = {
 635	.release = edac_mci_control_release,
 636	.sysfs_ops = &mci_ops,
 637	.default_attrs = (struct attribute **)mci_attr,
 638};
 639
 640/* EDAC memory controller sysfs kset:
 641 *	/sys/devices/system/edac/mc
 642 */
 643static struct kset *mc_kset;
 644
 645/*
 646 * edac_mc_register_sysfs_main_kobj
 647 *
 648 *	setups and registers the main kobject for each mci
 649 */
 650int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
 
 
 
 
 
 651{
 652	struct kobject *kobj_mci;
 653	int err;
 
 654
 655	debugf1("%s()\n", __func__);
 
 
 
 656
 657	kobj_mci = &mci->edac_mci_kobj;
 
 658
 659	/* Init the mci's kobject */
 660	memset(kobj_mci, 0, sizeof(*kobj_mci));
 661
 662	/* Record which module 'owns' this control structure
 663	 * and bump the ref count of the module
 664	 */
 665	mci->owner = THIS_MODULE;
 666
 667	/* bump ref count on this module */
 668	if (!try_module_get(mci->owner)) {
 669		err = -ENODEV;
 670		goto fail_out;
 671	}
 672
 673	/* this instance become part of the mc_kset */
 674	kobj_mci->kset = mc_kset;
 675
 676	/* register the mc<id> kobject to the mc_kset */
 677	err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
 678				   "mc%d", mci->mc_idx);
 679	if (err) {
 680		debugf1("%s()Failed to register '.../edac/mc%d'\n",
 681			__func__, mci->mc_idx);
 682		goto kobj_reg_fail;
 683	}
 684	kobject_uevent(kobj_mci, KOBJ_ADD);
 685
 686	/* At this point, to 'free' the control struct,
 687	 * edac_mc_unregister_sysfs_main_kobj() must be used
 688	 */
 689
 690	debugf1("%s() Registered '.../edac/mc%d' kobject\n",
 691		__func__, mci->mc_idx);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 692
 693	return 0;
 
 694
 695	/* Error exit stack */
 
 
 
 
 
 696
 697kobj_reg_fail:
 698	module_put(mci->owner);
 699
 700fail_out:
 701	return err;
 702}
 703
 704/*
 705 * edac_mc_register_sysfs_main_kobj
 706 *
 707 *	tears down and the main mci kobject from the mc_kset
 708 */
 709void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
 
 
 710{
 711	debugf1("%s()\n", __func__);
 
 712
 713	/* delete the kobj from the mc_kset */
 714	kobject_put(&mci->edac_mci_kobj);
 
 
 
 
 
 715}
 716
 717#define EDAC_DEVICE_SYMLINK	"device"
 
 
 
 
 
 718
 719#define grp_to_mci(k) (container_of(k, struct mcidev_sysfs_group_kobj, kobj)->mci)
 
 720
 721/* MCI show/store functions for top most object */
 722static ssize_t inst_grp_show(struct kobject *kobj, struct attribute *attr,
 723			char *buffer)
 724{
 725	struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
 726	struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 727
 728	debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
 
 729
 730	if (mcidev_attr->show)
 731		return mcidev_attr->show(mem_ctl_info, buffer);
 
 
 
 732
 733	return -EIO;
 734}
 735
 736static ssize_t inst_grp_store(struct kobject *kobj, struct attribute *attr,
 737			const char *buffer, size_t count)
 
 738{
 739	struct mem_ctl_info *mem_ctl_info = grp_to_mci(kobj);
 740	struct mcidev_sysfs_attribute *mcidev_attr = to_mcidev_attr(attr);
 741
 742	debugf1("%s() mem_ctl_info %p\n", __func__, mem_ctl_info);
 
 743
 744	if (mcidev_attr->store)
 745		return mcidev_attr->store(mem_ctl_info, buffer, count);
 
 
 
 746
 747	return -EIO;
 748}
 749
 750/* No memory to release for this kobj */
 751static void edac_inst_grp_release(struct kobject *kobj)
 
 752{
 753	struct mcidev_sysfs_group_kobj *grp;
 754	struct mem_ctl_info *mci;
 755
 756	debugf1("%s()\n", __func__);
 757
 758	grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
 759	mci = grp->mci;
 760}
 761
 762/* Intermediate show/store table */
 763static struct sysfs_ops inst_grp_ops = {
 764	.show = inst_grp_show,
 765	.store = inst_grp_store
 766};
 
 767
 768/* the kobj_type instance for a instance group */
 769static struct kobj_type ktype_inst_grp = {
 770	.release = edac_inst_grp_release,
 771	.sysfs_ops = &inst_grp_ops,
 772};
 773
 
 
 774
 775/*
 776 * edac_create_mci_instance_attributes
 777 *	create MC driver specific attributes bellow an specified kobj
 778 * This routine calls itself recursively, in order to create an entire
 779 * object tree.
 780 */
 781static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
 782				const struct mcidev_sysfs_attribute *sysfs_attrib,
 783				struct kobject *kobj)
 784{
 785	int err;
 786
 787	debugf4("%s()\n", __func__);
 
 788
 789	while (sysfs_attrib) {
 790		debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 791		if (sysfs_attrib->grp) {
 792			struct mcidev_sysfs_group_kobj *grp_kobj;
 793
 794			grp_kobj = kzalloc(sizeof(*grp_kobj), GFP_KERNEL);
 795			if (!grp_kobj)
 796				return -ENOMEM;
 797
 798			grp_kobj->grp = sysfs_attrib->grp;
 799			grp_kobj->mci = mci;
 800			list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
 801
 802			debugf0("%s() grp %s, mci %p\n", __func__,
 803				sysfs_attrib->grp->name, mci);
 804
 805			err = kobject_init_and_add(&grp_kobj->kobj,
 806						&ktype_inst_grp,
 807						&mci->edac_mci_kobj,
 808						sysfs_attrib->grp->name);
 809			if (err < 0) {
 810				printk(KERN_ERR "kobject_init_and_add failed: %d\n", err);
 811				return err;
 812			}
 813			err = edac_create_mci_instance_attributes(mci,
 814					grp_kobj->grp->mcidev_attr,
 815					&grp_kobj->kobj);
 816
 817			if (err < 0)
 818				return err;
 819		} else if (sysfs_attrib->attr.name) {
 820			debugf4("%s() file %s\n", __func__,
 821				sysfs_attrib->attr.name);
 822
 823			err = sysfs_create_file(kobj, &sysfs_attrib->attr);
 824			if (err < 0) {
 825				printk(KERN_ERR "sysfs_create_file failed: %d\n", err);
 826				return err;
 827			}
 828		} else
 829			break;
 830
 831		sysfs_attrib++;
 832	}
 833
 834	return 0;
 
 
 835}
 836
 837/*
 838 * edac_remove_mci_instance_attributes
 839 *	remove MC driver specific attributes at the topmost level
 840 *	directory of this mci instance.
 841 */
 842static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
 843				const struct mcidev_sysfs_attribute *sysfs_attrib,
 844				struct kobject *kobj, int count)
 845{
 846	struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
 
 
 
 
 
 
 847
 848	debugf1("%s()\n", __func__);
 
 
 
 
 
 
 
 
 
 
 
 
 849
 850	/*
 851	 * loop if there are attributes and until we hit a NULL entry
 852	 * Remove first all the attributes
 853	 */
 854	while (sysfs_attrib) {
 855		debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 856		if (sysfs_attrib->grp) {
 857			debugf4("%s() seeking for group %s\n",
 858				__func__, sysfs_attrib->grp->name);
 859			list_for_each_entry(grp_kobj,
 860					    &mci->grp_kobj_list, list) {
 861				debugf4("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
 862				if (grp_kobj->grp == sysfs_attrib->grp) {
 863					edac_remove_mci_instance_attributes(mci,
 864						    grp_kobj->grp->mcidev_attr,
 865						    &grp_kobj->kobj, count + 1);
 866					debugf4("%s() group %s\n", __func__,
 867						sysfs_attrib->grp->name);
 868					kobject_put(&grp_kobj->kobj);
 869				}
 870			}
 871			debugf4("%s() end of seeking for group %s\n",
 872				__func__, sysfs_attrib->grp->name);
 873		} else if (sysfs_attrib->attr.name) {
 874			debugf4("%s() file %s\n", __func__,
 875				sysfs_attrib->attr.name);
 876			sysfs_remove_file(kobj, &sysfs_attrib->attr);
 877		} else
 878			break;
 879		sysfs_attrib++;
 880	}
 881
 882	/* Remove the group objects */
 883	if (count)
 884		return;
 885	list_for_each_entry_safe(grp_kobj, tmp,
 886				 &mci->grp_kobj_list, list) {
 887		list_del(&grp_kobj->list);
 888		kfree(grp_kobj);
 889	}
 890}
 891
 
 
 
 892
 893/*
 894 * Create a new Memory Controller kobject instance,
 895 *	mc<id> under the 'mc' directory
 896 *
 897 * Return:
 898 *	0	Success
 899 *	!0	Failure
 900 */
 901int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
 
 902{
 903	int i;
 904	int err;
 905	struct csrow_info *csrow;
 906	struct kobject *kobj_mci = &mci->edac_mci_kobj;
 907
 908	debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
 909
 910	INIT_LIST_HEAD(&mci->grp_kobj_list);
 911
 912	/* create a symlink for the device */
 913	err = sysfs_create_link(kobj_mci, &mci->dev->kobj,
 914				EDAC_DEVICE_SYMLINK);
 915	if (err) {
 916		debugf1("%s() failure to create symlink\n", __func__);
 917		goto fail0;
 
 
 
 918	}
 919
 920	/* If the low level driver desires some attributes,
 921	 * then create them now for the driver.
 922	 */
 923	if (mci->mc_driver_sysfs_attributes) {
 924		err = edac_create_mci_instance_attributes(mci,
 925					mci->mc_driver_sysfs_attributes,
 926					&mci->edac_mci_kobj);
 927		if (err) {
 928			debugf1("%s() failure to create mci attributes\n",
 929				__func__);
 930			goto fail0;
 931		}
 932	}
 933
 934	/* Make directories for each CSROW object under the mc<id> kobject
 
 935	 */
 936	for (i = 0; i < mci->nr_csrows; i++) {
 937		csrow = &mci->csrows[i];
 
 
 938
 939		/* Only expose populated CSROWs */
 940		if (csrow->nr_pages > 0) {
 941			err = edac_create_csrow_object(mci, csrow, i);
 942			if (err) {
 943				debugf1("%s() failure: create csrow %d obj\n",
 944					__func__, i);
 945				goto fail1;
 946			}
 947		}
 948	}
 949
 
 
 
 
 
 
 
 950	return 0;
 951
 952	/* CSROW error: backout what has already been registered,  */
 953fail1:
 954	for (i--; i >= 0; i--) {
 955		if (csrow->nr_pages > 0) {
 956			kobject_put(&mci->csrows[i].kobj);
 957		}
 958	}
 959
 960	/* remove the mci instance's attributes, if any */
 961	edac_remove_mci_instance_attributes(mci,
 962		mci->mc_driver_sysfs_attributes, &mci->edac_mci_kobj, 0);
 963
 964	/* remove the symlink */
 965	sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
 966
 967fail0:
 968	return err;
 969}
 970
 971/*
 972 * remove a Memory Controller instance
 973 */
 974void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
 975{
 976	int i;
 
 
 
 977
 978	debugf0("%s()\n", __func__);
 979
 980	/* remove all csrow kobjects */
 981	debugf4("%s()  unregister this mci kobj\n", __func__);
 982	for (i = 0; i < mci->nr_csrows; i++) {
 983		if (mci->csrows[i].nr_pages > 0) {
 984			debugf0("%s()  unreg csrow-%d\n", __func__, i);
 985			kobject_put(&mci->csrows[i].kobj);
 986		}
 987	}
 988
 989	/* remove this mci instance's attribtes */
 990	if (mci->mc_driver_sysfs_attributes) {
 991		debugf4("%s()  unregister mci private attributes\n", __func__);
 992		edac_remove_mci_instance_attributes(mci,
 993						mci->mc_driver_sysfs_attributes,
 994						&mci->edac_mci_kobj, 0);
 995	}
 996
 997	/* remove the symlink */
 998	debugf4("%s()  remove_link\n", __func__);
 999	sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
1000
1001	/* unregister this instance's kobject */
1002	debugf4("%s()  remove_mci_instance\n", __func__);
1003	kobject_put(&mci->edac_mci_kobj);
1004}
1005
1006
1007
 
 
 
 
 
 
 
 
1008
1009/*
1010 * edac_setup_sysfs_mc_kset(void)
1011 *
1012 * Initialize the mc_kset for the 'mc' entry
1013 *	This requires creating the top 'mc' directory with a kset
1014 *	and its controls/attributes.
1015 *
1016 *	To this 'mc' kset, instance 'mci' will be grouped as children.
1017 *
1018 * Return:  0 SUCCESS
1019 *         !0 FAILURE error code
1020 */
1021int edac_sysfs_setup_mc_kset(void)
1022{
1023	int err = -EINVAL;
1024	struct sysdev_class *edac_class;
1025
1026	debugf1("%s()\n", __func__);
1027
1028	/* get the /sys/devices/system/edac class reference */
1029	edac_class = edac_get_sysfs_class();
1030	if (edac_class == NULL) {
1031		debugf1("%s() no edac_class error=%d\n", __func__, err);
1032		goto fail_out;
1033	}
1034
1035	/* Init the MC's kobject */
1036	mc_kset = kset_create_and_add("mc", NULL, &edac_class->kset.kobj);
1037	if (!mc_kset) {
1038		err = -ENOMEM;
1039		debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
1040		goto fail_kset;
1041	}
1042
1043	debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
1044
1045	return 0;
1046
1047fail_kset:
1048	edac_put_sysfs_class();
1049
1050fail_out:
1051	return err;
1052}
1053
1054/*
1055 * edac_sysfs_teardown_mc_kset
1056 *
1057 *	deconstruct the mc_ket for memory controllers
1058 */
1059void edac_sysfs_teardown_mc_kset(void)
1060{
1061	kset_unregister(mc_kset);
1062	edac_put_sysfs_class();
1063}
1064