aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Thompson <dougthompson@xmission.com>2007-07-19 04:50:27 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:57 -0400
commit8096cfafbb7ad3cb1a286ae7e8086167f4ebb4b6 (patch)
tree27b859beffef019095db810244f93e10473ea06f
parentd45e7823baf655ced91c7987fb4ba9aae990ad6d (diff)
drivers/edac: fix edac_mc sysfs completion code
This patch refactors the 'releasing' of kobjects for the edac_mc type of device. The correct pattern of kobject release is followed. As internal kobjs are allocated they bump a ref count on the top level kobj. It in turn has a module ref count on the edac_core module. When internal kobjects are released, they dec the ref count on the top level kobj. When the top level kobj reaches zero, it decrements the ref count on the edac_core object, allow it to be unloaded, as all resources have all now been released. Cc: Alan Cox alan@lxorguk.ukuu.org.uk Signed-off-by: Doug Thompson <dougthompson@xmission.com> Acked-by: Greg KH <greg@kroah.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/edac/edac_core.h4
-rw-r--r--drivers/edac/edac_mc.c36
-rw-r--r--drivers/edac/edac_mc_sysfs.c568
-rw-r--r--drivers/edac/edac_module.c32
-rw-r--r--drivers/edac/edac_module.h8
5 files changed, 399 insertions, 249 deletions
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h
index 2c399c52193e..bd7f00cf2443 100644
--- a/drivers/edac/edac_core.h
+++ b/drivers/edac/edac_core.h
@@ -317,9 +317,8 @@ struct csrow_info {
317 struct mem_ctl_info *mci; /* the parent */ 317 struct mem_ctl_info *mci; /* the parent */
318 318
319 struct kobject kobj; /* sysfs kobject for this csrow */ 319 struct kobject kobj; /* sysfs kobject for this csrow */
320 struct completion kobj_complete;
321 320
322 /* FIXME the number of CHANNELs might need to become dynamic */ 321 /* channel information for this csrow */
323 u32 nr_channels; 322 u32 nr_channels;
324 struct channel_info *channels; 323 struct channel_info *channels;
325}; 324};
@@ -403,7 +402,6 @@ struct mem_ctl_info {
403 402
404 /* edac sysfs device control */ 403 /* edac sysfs device control */
405 struct kobject edac_mci_kobj; 404 struct kobject edac_mci_kobj;
406 struct completion kobj_complete;
407 405
408 /* Additional top controller level attributes, but specified 406 /* Additional top controller level attributes, but specified
409 * by the low level driver. 407 * by the low level driver.
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 6e4c94e9654a..2d53cb38868a 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -137,6 +137,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
137 void *pvt; 137 void *pvt;
138 unsigned size; 138 unsigned size;
139 int row, chn; 139 int row, chn;
140 int err;
140 141
141 /* Figure out the offsets of the various items from the start of an mc 142 /* Figure out the offsets of the various items from the start of an mc
142 * structure. We want the alignment of each item to be at least as 143 * structure. We want the alignment of each item to be at least as
@@ -149,7 +150,8 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
149 pvt = edac_align_ptr(&chi[nr_chans * nr_csrows], sz_pvt); 150 pvt = edac_align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
150 size = ((unsigned long)pvt) + sz_pvt; 151 size = ((unsigned long)pvt) + sz_pvt;
151 152
152 if ((mci = kmalloc(size, GFP_KERNEL)) == NULL) 153 mci = kzalloc(size, GFP_KERNEL);
154 if (mci == NULL)
153 return NULL; 155 return NULL;
154 156
155 /* Adjust pointers so they point within the memory we just allocated 157 /* Adjust pointers so they point within the memory we just allocated
@@ -182,20 +184,34 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
182 184
183 mci->op_state = OP_ALLOC; 185 mci->op_state = OP_ALLOC;
184 186
187 /*
188 * Initialize the 'root' kobj for the edac_mc controller
189 */
190 err = edac_mc_register_sysfs_main_kobj(mci);
191 if (err) {
192 kfree(mci);
193 return NULL;
194 }
195
196 /* at this point, the root kobj is valid, and in order to
197 * 'free' the object, then the function:
198 * edac_mc_unregister_sysfs_main_kobj() must be called
199 * which will perform kobj unregistration and the actual free
200 * will occur during the kobject callback operation
201 */
185 return mci; 202 return mci;
186} 203}
187
188EXPORT_SYMBOL_GPL(edac_mc_alloc); 204EXPORT_SYMBOL_GPL(edac_mc_alloc);
189 205
190/** 206/**
191 * edac_mc_free: Free a previously allocated 'mci' structure 207 * edac_mc_free
208 * 'Free' a previously allocated 'mci' structure
192 * @mci: pointer to a struct mem_ctl_info structure 209 * @mci: pointer to a struct mem_ctl_info structure
193 */ 210 */
194void edac_mc_free(struct mem_ctl_info *mci) 211void edac_mc_free(struct mem_ctl_info *mci)
195{ 212{
196 kfree(mci); 213 edac_mc_unregister_sysfs_main_kobj(mci);
197} 214}
198
199EXPORT_SYMBOL_GPL(edac_mc_free); 215EXPORT_SYMBOL_GPL(edac_mc_free);
200 216
201static struct mem_ctl_info *find_mci_by_dev(struct device *dev) 217static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
@@ -391,7 +407,6 @@ struct mem_ctl_info *edac_mc_find(int idx)
391 407
392 return NULL; 408 return NULL;
393} 409}
394
395EXPORT_SYMBOL(edac_mc_find); 410EXPORT_SYMBOL(edac_mc_find);
396 411
397/** 412/**
@@ -465,7 +480,6 @@ fail0:
465 mutex_unlock(&mem_ctls_mutex); 480 mutex_unlock(&mem_ctls_mutex);
466 return 1; 481 return 1;
467} 482}
468
469EXPORT_SYMBOL_GPL(edac_mc_add_mc); 483EXPORT_SYMBOL_GPL(edac_mc_add_mc);
470 484
471/** 485/**
@@ -501,7 +515,6 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
501 mci->mod_name, mci->ctl_name, dev_name(mci)); 515 mci->mod_name, mci->ctl_name, dev_name(mci));
502 return mci; 516 return mci;
503} 517}
504
505EXPORT_SYMBOL_GPL(edac_mc_del_mc); 518EXPORT_SYMBOL_GPL(edac_mc_del_mc);
506 519
507static void edac_mc_scrub_block(unsigned long page, unsigned long offset, 520static void edac_mc_scrub_block(unsigned long page, unsigned long offset,
@@ -571,7 +584,6 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
571 584
572 return row; 585 return row;
573} 586}
574
575EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page); 587EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page);
576 588
577/* FIXME - setable log (warning/emerg) levels */ 589/* FIXME - setable log (warning/emerg) levels */
@@ -636,7 +648,6 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
636 mci->csrows[row].grain); 648 mci->csrows[row].grain);
637 } 649 }
638} 650}
639
640EXPORT_SYMBOL_GPL(edac_mc_handle_ce); 651EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
641 652
642void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) 653void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
@@ -648,7 +659,6 @@ void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
648 mci->ce_noinfo_count++; 659 mci->ce_noinfo_count++;
649 mci->ce_count++; 660 mci->ce_count++;
650} 661}
651
652EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info); 662EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info);
653 663
654void edac_mc_handle_ue(struct mem_ctl_info *mci, 664void edac_mc_handle_ue(struct mem_ctl_info *mci,
@@ -702,7 +712,6 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
702 mci->ue_count++; 712 mci->ue_count++;
703 mci->csrows[row].ue_count++; 713 mci->csrows[row].ue_count++;
704} 714}
705
706EXPORT_SYMBOL_GPL(edac_mc_handle_ue); 715EXPORT_SYMBOL_GPL(edac_mc_handle_ue);
707 716
708void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) 717void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
@@ -716,7 +725,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
716 mci->ue_noinfo_count++; 725 mci->ue_noinfo_count++;
717 mci->ue_count++; 726 mci->ue_count++;
718} 727}
719
720EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); 728EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
721 729
722/************************************************************* 730/*************************************************************
@@ -784,7 +792,6 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
784 "labels \"%s\": %s\n", csrow, channela, 792 "labels \"%s\": %s\n", csrow, channela,
785 channelb, labels, msg); 793 channelb, labels, msg);
786} 794}
787
788EXPORT_SYMBOL(edac_mc_handle_fbd_ue); 795EXPORT_SYMBOL(edac_mc_handle_fbd_ue);
789 796
790/************************************************************* 797/*************************************************************
@@ -824,7 +831,6 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
824 mci->csrows[csrow].ce_count++; 831 mci->csrows[csrow].ce_count++;
825 mci->csrows[csrow].channels[channel].ce_count++; 832 mci->csrows[csrow].channels[channel].ce_count++;
826} 833}
827
828EXPORT_SYMBOL(edac_mc_handle_fbd_ce); 834EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
829 835
830/* 836/*
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 0843eaa10ec9..cd090b0677a7 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -10,10 +10,12 @@
10 */ 10 */
11 11
12#include <linux/ctype.h> 12#include <linux/ctype.h>
13#include <linux/bug.h>
13 14
14#include "edac_core.h" 15#include "edac_core.h"
15#include "edac_module.h" 16#include "edac_module.h"
16 17
18
17/* MC EDAC Controls, setable by module parameter, and sysfs */ 19/* MC EDAC Controls, setable by module parameter, and sysfs */
18static int edac_mc_log_ue = 1; 20static int edac_mc_log_ue = 1;
19static int edac_mc_log_ce = 1; 21static int edac_mc_log_ce = 1;
@@ -98,15 +100,7 @@ static const char *edac_caps[] = {
98 [EDAC_S16ECD16ED] = "S16ECD16ED" 100 [EDAC_S16ECD16ED] = "S16ECD16ED"
99}; 101};
100 102
101/* sysfs object:
102 * /sys/devices/system/edac/mc
103 */
104static struct kobject edac_memctrl_kobj;
105 103
106/* We use these to wait for the reference counts on edac_memctrl_kobj and
107 * edac_pci_kobj to reach 0.
108 */
109static struct completion edac_memctrl_kobj_complete;
110 104
111/* 105/*
112 * /sys/devices/system/edac/mc; 106 * /sys/devices/system/edac/mc;
@@ -128,153 +122,6 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
128 return count; 122 return count;
129} 123}
130 124
131struct memctrl_dev_attribute {
132 struct attribute attr;
133 void *value;
134 ssize_t(*show) (void *, char *);
135 ssize_t(*store) (void *, const char *, size_t);
136};
137
138/* Set of show/store abstract level functions for memory control object */
139static ssize_t memctrl_dev_show(struct kobject *kobj,
140 struct attribute *attr, char *buffer)
141{
142 struct memctrl_dev_attribute *memctrl_dev;
143 memctrl_dev = (struct memctrl_dev_attribute *)attr;
144
145 if (memctrl_dev->show)
146 return memctrl_dev->show(memctrl_dev->value, buffer);
147
148 return -EIO;
149}
150
151static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
152 const char *buffer, size_t count)
153{
154 struct memctrl_dev_attribute *memctrl_dev;
155 memctrl_dev = (struct memctrl_dev_attribute *)attr;
156
157 if (memctrl_dev->store)
158 return memctrl_dev->store(memctrl_dev->value, buffer, count);
159
160 return -EIO;
161}
162
163static struct sysfs_ops memctrlfs_ops = {
164 .show = memctrl_dev_show,
165 .store = memctrl_dev_store
166};
167
168#define MEMCTRL_ATTR(_name,_mode,_show,_store) \
169static struct memctrl_dev_attribute attr_##_name = { \
170 .attr = {.name = __stringify(_name), .mode = _mode }, \
171 .value = &_name, \
172 .show = _show, \
173 .store = _store, \
174};
175
176#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store) \
177static struct memctrl_dev_attribute attr_##_name = { \
178 .attr = {.name = __stringify(_name), .mode = _mode }, \
179 .value = _data, \
180 .show = _show, \
181 .store = _store, \
182};
183
184/* csrow<id> control files */
185MEMCTRL_ATTR(edac_mc_panic_on_ue,
186 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
187
188MEMCTRL_ATTR(edac_mc_log_ue,
189 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
190
191MEMCTRL_ATTR(edac_mc_log_ce,
192 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
193
194MEMCTRL_ATTR(edac_mc_poll_msec,
195 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
196
197/* Base Attributes of the memory ECC object */
198static struct memctrl_dev_attribute *memctrl_attr[] = {
199 &attr_edac_mc_panic_on_ue,
200 &attr_edac_mc_log_ue,
201 &attr_edac_mc_log_ce,
202 &attr_edac_mc_poll_msec,
203 NULL,
204};
205
206/* Main MC kobject release() function */
207static void edac_memctrl_master_release(struct kobject *kobj)
208{
209 debugf1("%s()\n", __func__);
210 complete(&edac_memctrl_kobj_complete);
211}
212
213static struct kobj_type ktype_memctrl = {
214 .release = edac_memctrl_master_release,
215 .sysfs_ops = &memctrlfs_ops,
216 .default_attrs = (struct attribute **)memctrl_attr,
217};
218
219/* Initialize the main sysfs entries for edac:
220 * /sys/devices/system/edac
221 *
222 * and children
223 *
224 * Return: 0 SUCCESS
225 * !0 FAILURE
226 */
227int edac_sysfs_memctrl_setup(void)
228{
229 int err = 0;
230 struct sysdev_class *edac_class;
231
232 debugf1("%s()\n", __func__);
233
234 /* get the /sys/devices/system/edac class reference */
235 edac_class = edac_get_edac_class();
236 if (edac_class == NULL) {
237 debugf1("%s() no edac_class error=%d\n", __func__, err);
238 return err;
239 }
240
241 /* Init the MC's kobject */
242 memset(&edac_memctrl_kobj, 0, sizeof(edac_memctrl_kobj));
243 edac_memctrl_kobj.parent = &edac_class->kset.kobj;
244 edac_memctrl_kobj.ktype = &ktype_memctrl;
245
246 /* generate sysfs "..../edac/mc" */
247 err = kobject_set_name(&edac_memctrl_kobj, "mc");
248 if (err) {
249 debugf1("%s() Failed to set name '.../edac/mc'\n", __func__);
250 return err;
251 }
252
253 /* FIXME: maybe new sysdev_create_subdir() */
254 err = kobject_register(&edac_memctrl_kobj);
255 if (err) {
256 debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
257 return err;
258 }
259
260 debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
261 return 0;
262}
263
264/*
265 * MC teardown:
266 * the '..../edac/mc' kobject followed by '..../edac' itself
267 */
268void edac_sysfs_memctrl_teardown(void)
269{
270 debugf0("MC: " __FILE__ ": %s()\n", __func__);
271
272 /* Unregister the MC's kobject and wait for reference count to reach 0.
273 */
274 init_completion(&edac_memctrl_kobj_complete);
275 kobject_unregister(&edac_memctrl_kobj);
276 wait_for_completion(&edac_memctrl_kobj_complete);
277}
278 125
279/* EDAC sysfs CSROW data structures and methods 126/* EDAC sysfs CSROW data structures and methods
280 */ 127 */
@@ -486,10 +333,15 @@ static int edac_create_channel_files(struct kobject *kobj, int chan)
486/* No memory to release for this kobj */ 333/* No memory to release for this kobj */
487static void edac_csrow_instance_release(struct kobject *kobj) 334static void edac_csrow_instance_release(struct kobject *kobj)
488{ 335{
336 struct mem_ctl_info *mci;
489 struct csrow_info *cs; 337 struct csrow_info *cs;
490 338
339 debugf1("%s()\n", __func__);
340
491 cs = container_of(kobj, struct csrow_info, kobj); 341 cs = container_of(kobj, struct csrow_info, kobj);
492 complete(&cs->kobj_complete); 342 mci = cs->mci;
343
344 kobject_put(&mci->edac_mci_kobj);
493} 345}
494 346
495/* the kobj_type instance for a CSROW */ 347/* the kobj_type instance for a CSROW */
@@ -500,38 +352,61 @@ static struct kobj_type ktype_csrow = {
500}; 352};
501 353
502/* Create a CSROW object under specifed edac_mc_device */ 354/* Create a CSROW object under specifed edac_mc_device */
503static int edac_create_csrow_object(struct kobject *edac_mci_kobj, 355static int edac_create_csrow_object(struct mem_ctl_info *mci,
504 struct csrow_info *csrow, int index) 356 struct csrow_info *csrow, int index)
505{ 357{
506 int err = 0; 358 struct kobject *kobj_mci = &mci->edac_mci_kobj;
359 struct kobject *kobj;
507 int chan; 360 int chan;
508 361 int err;
509 memset(&csrow->kobj, 0, sizeof(csrow->kobj));
510 362
511 /* generate ..../edac/mc/mc<id>/csrow<index> */ 363 /* generate ..../edac/mc/mc<id>/csrow<index> */
512 364 memset(&csrow->kobj, 0, sizeof(csrow->kobj));
513 csrow->kobj.parent = edac_mci_kobj; 365 csrow->mci = mci; /* include container up link */
366 csrow->kobj.parent = kobj_mci;
514 csrow->kobj.ktype = &ktype_csrow; 367 csrow->kobj.ktype = &ktype_csrow;
515 368
516 /* name this instance of csrow<id> */ 369 /* name this instance of csrow<id> */
517 err = kobject_set_name(&csrow->kobj, "csrow%d", index); 370 err = kobject_set_name(&csrow->kobj, "csrow%d", index);
518 if (err) 371 if (err)
519 goto error_exit; 372 goto err_out;
373
374 /* bump the mci instance's kobject's ref count */
375 kobj = kobject_get(&mci->edac_mci_kobj);
376 if (!kobj) {
377 err = -ENODEV;
378 goto err_out;
379 }
520 380
521 /* Instanstiate the csrow object */ 381 /* Instanstiate the csrow object */
522 err = kobject_register(&csrow->kobj); 382 err = kobject_register(&csrow->kobj);
523 if (!err) { 383 if (err)
524 /* Create the dyanmic attribute files on this csrow, 384 goto err_release_top_kobj;
525 * namely, the DIMM labels and the channel ce_count 385
526 */ 386 /* At this point, to release a csrow kobj, one must
527 for (chan = 0; chan < csrow->nr_channels; chan++) { 387 * call the kobject_unregister and allow that tear down
528 err = edac_create_channel_files(&csrow->kobj, chan); 388 * to work the releasing
529 if (err) 389 */
530 break; 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_unregister(&csrow->kobj);
399 goto err_out;
531 } 400 }
532 } 401 }
533 402
534error_exit: 403 return 0;
404
405 /* error unwind stack */
406err_release_top_kobj:
407 kobject_put(&mci->edac_mci_kobj);
408
409err_out:
535 return err; 410 return err;
536} 411}
537 412
@@ -688,6 +563,7 @@ static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
688 return -EIO; 563 return -EIO;
689} 564}
690 565
566/* Intermediate show/store table */
691static struct sysfs_ops mci_ops = { 567static struct sysfs_ops mci_ops = {
692 .show = mcidev_show, 568 .show = mcidev_show,
693 .store = mcidev_store 569 .store = mcidev_store
@@ -729,32 +605,213 @@ static struct mcidev_sysfs_attribute *mci_attr[] = {
729 NULL 605 NULL
730}; 606};
731 607
608
732/* 609/*
733 * Release of a MC controlling instance 610 * Release of a MC controlling instance
611 *
612 * each MC control instance has the following resources upon entry:
613 * a) a ref count on the top memctl kobj
614 * b) a ref count on this module
615 *
616 * this function must decrement those ref counts and then
617 * issue a free on the instance's memory
734 */ 618 */
735static void edac_mci_instance_release(struct kobject *kobj) 619static void edac_mci_control_release(struct kobject *kobj)
736{ 620{
737 struct mem_ctl_info *mci; 621 struct mem_ctl_info *mci;
738 622
739 mci = to_mci(kobj); 623 mci = to_mci(kobj);
740 debugf0("%s() idx=%d\n", __func__, mci->mc_idx); 624
741 complete(&mci->kobj_complete); 625 debugf0("%s() mci instance idx=%d releasing\n", __func__, mci->mc_idx);
626
627 /* decrement the module ref count */
628 module_put(mci->owner);
629
630 /* free the mci instance memory here */
631 kfree(mci);
742} 632}
743 633
744static struct kobj_type ktype_mci = { 634static struct kobj_type ktype_mci = {
745 .release = edac_mci_instance_release, 635 .release = edac_mci_control_release,
746 .sysfs_ops = &mci_ops, 636 .sysfs_ops = &mci_ops,
747 .default_attrs = (struct attribute **)mci_attr, 637 .default_attrs = (struct attribute **)mci_attr,
748}; 638};
749 639
640/* show/store, tables, etc for the MC kset */
641
642
643struct memctrl_dev_attribute {
644 struct attribute attr;
645 void *value;
646 ssize_t(*show) (void *, char *);
647 ssize_t(*store) (void *, const char *, size_t);
648};
649
650/* Set of show/store abstract level functions for memory control object */
651static ssize_t memctrl_dev_show(struct kobject *kobj,
652 struct attribute *attr, char *buffer)
653{
654 struct memctrl_dev_attribute *memctrl_dev;
655 memctrl_dev = (struct memctrl_dev_attribute *)attr;
656
657 if (memctrl_dev->show)
658 return memctrl_dev->show(memctrl_dev->value, buffer);
659
660 return -EIO;
661}
662
663static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
664 const char *buffer, size_t count)
665{
666 struct memctrl_dev_attribute *memctrl_dev;
667 memctrl_dev = (struct memctrl_dev_attribute *)attr;
668
669 if (memctrl_dev->store)
670 return memctrl_dev->store(memctrl_dev->value, buffer, count);
671
672 return -EIO;
673}
674
675static struct sysfs_ops memctrlfs_ops = {
676 .show = memctrl_dev_show,
677 .store = memctrl_dev_store
678};
679
680#define MEMCTRL_ATTR(_name, _mode, _show, _store) \
681static struct memctrl_dev_attribute attr_##_name = { \
682 .attr = {.name = __stringify(_name), .mode = _mode }, \
683 .value = &_name, \
684 .show = _show, \
685 .store = _store, \
686};
687
688#define MEMCTRL_STRING_ATTR(_name, _data, _mode, _show, _store) \
689static struct memctrl_dev_attribute attr_##_name = { \
690 .attr = {.name = __stringify(_name), .mode = _mode }, \
691 .value = _data, \
692 .show = _show, \
693 .store = _store, \
694};
695
696/* csrow<id> control files */
697MEMCTRL_ATTR(edac_mc_panic_on_ue,
698 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
699
700MEMCTRL_ATTR(edac_mc_log_ue,
701 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
702
703MEMCTRL_ATTR(edac_mc_log_ce,
704 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
705
706MEMCTRL_ATTR(edac_mc_poll_msec,
707 S_IRUGO | S_IWUSR, memctrl_int_show, memctrl_int_store);
708
709/* Base Attributes of the memory ECC object */
710static struct memctrl_dev_attribute *memctrl_attr[] = {
711 &attr_edac_mc_panic_on_ue,
712 &attr_edac_mc_log_ue,
713 &attr_edac_mc_log_ce,
714 &attr_edac_mc_poll_msec,
715 NULL,
716};
717
718
719/* the ktype for the mc_kset internal kobj */
720static struct kobj_type ktype_mc_set_attribs = {
721 .sysfs_ops = &memctrlfs_ops,
722 .default_attrs = (struct attribute **)memctrl_attr,
723};
724
725/* EDAC memory controller sysfs kset:
726 * /sys/devices/system/edac/mc
727 */
728static struct kset mc_kset = {
729 .kobj = {.name = "mc", .ktype = &ktype_mc_set_attribs },
730 .ktype = &ktype_mci,
731};
732
733
734/*
735 * edac_mc_register_sysfs_main_kobj
736 *
737 * setups and registers the main kobject for each mci
738 */
739int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
740{
741 struct kobject *kobj_mci;
742 int err;
743
744 debugf1("%s()\n", __func__);
745
746 kobj_mci = &mci->edac_mci_kobj;
747
748 /* Init the mci's kobject */
749 memset(kobj_mci, 0, sizeof(*kobj_mci));
750
751 /* this instance become part of the mc_kset */
752 kobj_mci->kset = &mc_kset;
753
754 /* set the name of the mc<id> object */
755 err = kobject_set_name(kobj_mci, "mc%d", mci->mc_idx);
756 if (err)
757 goto fail_out;
758
759 /* Record which module 'owns' this control structure
760 * and bump the ref count of the module
761 */
762 mci->owner = THIS_MODULE;
763
764 /* bump ref count on this module */
765 if (!try_module_get(mci->owner)) {
766 err = -ENODEV;
767 goto fail_out;
768 }
769
770 /* register the mc<id> kobject to the mc_kset */
771 err = kobject_register(kobj_mci);
772 if (err) {
773 debugf1("%s()Failed to register '.../edac/mc%d'\n",
774 __func__, mci->mc_idx);
775 goto kobj_reg_fail;
776 }
777
778 /* At this point, to 'free' the control struct,
779 * edac_mc_unregister_sysfs_main_kobj() must be used
780 */
781
782 debugf1("%s() Registered '.../edac/mc%d' kobject\n",
783 __func__, mci->mc_idx);
784
785 return 0;
786
787 /* Error exit stack */
788
789kobj_reg_fail:
790 module_put(mci->owner);
791
792fail_out:
793 return err;
794}
795
796/*
797 * edac_mc_register_sysfs_main_kobj
798 *
799 * tears down and the main mci kobject from the mc_kset
800 */
801void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
802{
803 /* delete the kobj from the mc_kset */
804 kobject_unregister(&mci->edac_mci_kobj);
805}
806
750#define EDAC_DEVICE_SYMLINK "device" 807#define EDAC_DEVICE_SYMLINK "device"
751 808
752/* 809/*
753 * edac_create_driver_attributes 810 * edac_create_mci_instance_attributes
754 * create MC driver specific attributes at the topmost level 811 * create MC driver specific attributes at the topmost level
755 * directory of this mci instance. 812 * directory of this mci instance.
756 */ 813 */
757static int edac_create_driver_attributes(struct mem_ctl_info *mci) 814static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci)
758{ 815{
759 int err; 816 int err;
760 struct mcidev_sysfs_attribute *sysfs_attrib; 817 struct mcidev_sysfs_attribute *sysfs_attrib;
@@ -764,7 +821,7 @@ static int edac_create_driver_attributes(struct mem_ctl_info *mci)
764 */ 821 */
765 sysfs_attrib = mci->mc_driver_sysfs_attributes; 822 sysfs_attrib = mci->mc_driver_sysfs_attributes;
766 823
767 while (sysfs_attrib->attr.name != NULL) { 824 while (sysfs_attrib && sysfs_attrib->attr.name) {
768 err = sysfs_create_file(&mci->edac_mci_kobj, 825 err = sysfs_create_file(&mci->edac_mci_kobj,
769 (struct attribute*) sysfs_attrib); 826 (struct attribute*) sysfs_attrib);
770 if (err) { 827 if (err) {
@@ -778,6 +835,29 @@ static int edac_create_driver_attributes(struct mem_ctl_info *mci)
778} 835}
779 836
780/* 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{
844 struct mcidev_sysfs_attribute *sysfs_attrib;
845
846 /* point to the start of the array and iterate over it
847 * adding each attribute listed to this mci instance's kobject
848 */
849 sysfs_attrib = mci->mc_driver_sysfs_attributes;
850
851 /* loop if there are attributes and until we hit a NULL entry */
852 while (sysfs_attrib && sysfs_attrib->attr.name) {
853 sysfs_remove_file(&mci->edac_mci_kobj,
854 (struct attribute *) sysfs_attrib);
855 sysfs_attrib++;
856 }
857}
858
859
860/*
781 * Create a new Memory Controller kobject instance, 861 * Create a new Memory Controller kobject instance,
782 * mc<id> under the 'mc' directory 862 * mc<id> under the 'mc' directory
783 * 863 *
@@ -790,51 +870,43 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
790 int i; 870 int i;
791 int err; 871 int err;
792 struct csrow_info *csrow; 872 struct csrow_info *csrow;
793 struct kobject *edac_mci_kobj = &mci->edac_mci_kobj; 873 struct kobject *kobj_mci = &mci->edac_mci_kobj;
794 874
795 debugf0("%s() idx=%d\n", __func__, mci->mc_idx); 875 debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
796 memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
797
798 /* set the name of the mc<id> object */
799 err = kobject_set_name(edac_mci_kobj, "mc%d", mci->mc_idx);
800 if (err)
801 return err;
802
803 /* link to our parent the '..../edac/mc' object */
804 edac_mci_kobj->parent = &edac_memctrl_kobj;
805 edac_mci_kobj->ktype = &ktype_mci;
806
807 /* register the mc<id> kobject */
808 err = kobject_register(edac_mci_kobj);
809 if (err)
810 return err;
811 876
812 /* create a symlink for the device */ 877 /* create a symlink for the device */
813 err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj, 878 err = sysfs_create_link(kobj_mci, &mci->dev->kobj,
814 EDAC_DEVICE_SYMLINK); 879 EDAC_DEVICE_SYMLINK);
815 if (err) 880 if (err) {
881 debugf1("%s() failure to create symlink\n", __func__);
816 goto fail0; 882 goto fail0;
883 }
817 884
818 /* If the low level driver desires some attributes, 885 /* If the low level driver desires some attributes,
819 * then create them now for the driver. 886 * then create them now for the driver.
820 */ 887 */
821 if (mci->mc_driver_sysfs_attributes) { 888 if (mci->mc_driver_sysfs_attributes) {
822 err = edac_create_driver_attributes(mci); 889 err = edac_create_mci_instance_attributes(mci);
823 if (err) 890 if (err) {
891 debugf1("%s() failure to create mci attributes\n",
892 __func__);
824 goto fail0; 893 goto fail0;
894 }
825 } 895 }
826 896
827 /* Make directories for each CSROW object 897 /* Make directories for each CSROW object under the mc<id> kobject
828 * under the mc<id> kobject
829 */ 898 */
830 for (i = 0; i < mci->nr_csrows; i++) { 899 for (i = 0; i < mci->nr_csrows; i++) {
831 csrow = &mci->csrows[i]; 900 csrow = &mci->csrows[i];
832 901
833 /* Only expose populated CSROWs */ 902 /* Only expose populated CSROWs */
834 if (csrow->nr_pages > 0) { 903 if (csrow->nr_pages > 0) {
835 err = edac_create_csrow_object(edac_mci_kobj, csrow, i); 904 err = edac_create_csrow_object(mci, csrow, i);
836 if (err) 905 if (err) {
906 debugf1("%s() failure: create csrow %d obj\n",
907 __func__, i);
837 goto fail1; 908 goto fail1;
909 }
838 } 910 }
839 } 911 }
840 912
@@ -844,16 +916,17 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
844fail1: 916fail1:
845 for (i--; i >= 0; i--) { 917 for (i--; i >= 0; i--) {
846 if (csrow->nr_pages > 0) { 918 if (csrow->nr_pages > 0) {
847 init_completion(&csrow->kobj_complete);
848 kobject_unregister(&mci->csrows[i].kobj); 919 kobject_unregister(&mci->csrows[i].kobj);
849 wait_for_completion(&csrow->kobj_complete);
850 } 920 }
851 } 921 }
852 922
923 /* remove the mci instance's attributes, if any */
924 edac_remove_mci_instance_attributes(mci);
925
926 /* remove the symlink */
927 sysfs_remove_link(kobj_mci, EDAC_DEVICE_SYMLINK);
928
853fail0: 929fail0:
854 init_completion(&mci->kobj_complete);
855 kobject_unregister(edac_mci_kobj);
856 wait_for_completion(&mci->kobj_complete);
857 return err; 930 return err;
858} 931}
859 932
@@ -869,14 +942,83 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
869 /* remove all csrow kobjects */ 942 /* remove all csrow kobjects */
870 for (i = 0; i < mci->nr_csrows; i++) { 943 for (i = 0; i < mci->nr_csrows; i++) {
871 if (mci->csrows[i].nr_pages > 0) { 944 if (mci->csrows[i].nr_pages > 0) {
872 init_completion(&mci->csrows[i].kobj_complete); 945 debugf0("%s() unreg csrow-%d\n", __func__, i);
873 kobject_unregister(&mci->csrows[i].kobj); 946 kobject_unregister(&mci->csrows[i].kobj);
874 wait_for_completion(&mci->csrows[i].kobj_complete);
875 } 947 }
876 } 948 }
877 949
950 debugf0("%s() remove_link\n", __func__);
951
952 /* remove the symlink */
878 sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK); 953 sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
879 init_completion(&mci->kobj_complete); 954
955 debugf0("%s() remove_mci_instance\n", __func__);
956
957 /* remove this mci instance's attribtes */
958 edac_remove_mci_instance_attributes(mci);
959
960 debugf0("%s() unregister this mci kobj\n", __func__);
961
962 /* unregister this instance's kobject */
880 kobject_unregister(&mci->edac_mci_kobj); 963 kobject_unregister(&mci->edac_mci_kobj);
881 wait_for_completion(&mci->kobj_complete);
882} 964}
965
966
967
968
969/*
970 * edac_setup_sysfs_mc_kset(void)
971 *
972 * Initialize the mc_kset for the 'mc' entry
973 * This requires creating the top 'mc' directory with a kset
974 * and its controls/attributes.
975 *
976 * To this 'mc' kset, instance 'mci' will be grouped as children.
977 *
978 * Return: 0 SUCCESS
979 * !0 FAILURE error code
980 */
981int edac_sysfs_setup_mc_kset(void)
982{
983 int err = 0;
984 struct sysdev_class *edac_class;
985
986 debugf1("%s()\n", __func__);
987
988 /* get the /sys/devices/system/edac class reference */
989 edac_class = edac_get_edac_class();
990 if (edac_class == NULL) {
991 debugf1("%s() no edac_class error=%d\n", __func__, err);
992 goto fail_out;
993 }
994
995 /* Init the MC's kobject */
996 mc_kset.kobj.parent = &edac_class->kset.kobj;
997
998 /* register the mc_kset */
999 err = kset_register(&mc_kset);
1000 if (err) {
1001 debugf1("%s() Failed to register '.../edac/mc'\n", __func__);
1002 goto fail_out;
1003 }
1004
1005 debugf1("%s() Registered '.../edac/mc' kobject\n", __func__);
1006
1007 return 0;
1008
1009
1010 /* error unwind stack */
1011fail_out:
1012 return err;
1013}
1014
1015/*
1016 * edac_sysfs_teardown_mc_kset
1017 *
1018 * deconstruct the mc_ket for memory controllers
1019 */
1020void edac_sysfs_teardown_mc_kset(void)
1021{
1022 kset_unregister(&mc_kset);
1023}
1024
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 07bd16564780..fc32bbb9405e 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -14,11 +14,11 @@
14#include "edac_core.h" 14#include "edac_core.h"
15#include "edac_module.h" 15#include "edac_module.h"
16 16
17#define EDAC_MC_VERSION "Ver: 2.0.4 " __DATE__ 17#define EDAC_MC_VERSION "Ver: 2.0.5 " __DATE__
18 18
19#ifdef CONFIG_EDAC_DEBUG 19#ifdef CONFIG_EDAC_DEBUG
20/* Values of 0 to 4 will generate output */ 20/* Values of 0 to 4 will generate output */
21int edac_debug_level = 1; 21int edac_debug_level = 2;
22EXPORT_SYMBOL_GPL(edac_debug_level); 22EXPORT_SYMBOL_GPL(edac_debug_level);
23#endif 23#endif
24 24
@@ -153,7 +153,7 @@ static int __init edac_init(void)
153 edac_pci_clear_parity_errors(); 153 edac_pci_clear_parity_errors();
154 154
155 /* 155 /*
156 * perform the registration of the /sys/devices/system/edac object 156 * perform the registration of the /sys/devices/system/edac class object
157 */ 157 */
158 if (edac_register_sysfs_edac_name()) { 158 if (edac_register_sysfs_edac_name()) {
159 edac_printk(KERN_ERR, EDAC_MC, 159 edac_printk(KERN_ERR, EDAC_MC,
@@ -162,29 +162,29 @@ static int __init edac_init(void)
162 goto error; 162 goto error;
163 } 163 }
164 164
165 /* Create the MC sysfs entries, must be first 165 /*
166 * now set up the mc_kset under the edac class object
166 */ 167 */
167 if (edac_sysfs_memctrl_setup()) { 168 err = edac_sysfs_setup_mc_kset();
168 edac_printk(KERN_ERR, EDAC_MC, 169 if (err)
169 "Error initializing sysfs code\n"); 170 goto sysfs_setup_fail;
170 err = -ENODEV;
171 goto error_sysfs;
172 }
173 171
174 /* Setup/Initialize the edac_device system */ 172 /* Setup/Initialize the workq for this core */
175 err = edac_workqueue_setup(); 173 err = edac_workqueue_setup();
176 if (err) { 174 if (err) {
177 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n"); 175 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
178 goto error_mem; 176 goto workq_fail;
179 } 177 }
180 178
181 return 0; 179 return 0;
182 180
183 /* Error teardown stack */ 181 /* Error teardown stack */
184error_mem: 182workq_fail:
185 edac_sysfs_memctrl_teardown(); 183 edac_sysfs_teardown_mc_kset();
186error_sysfs: 184
185sysfs_setup_fail:
187 edac_unregister_sysfs_edac_name(); 186 edac_unregister_sysfs_edac_name();
187
188error: 188error:
189 return err; 189 return err;
190} 190}
@@ -199,7 +199,7 @@ static void __exit edac_exit(void)
199 199
200 /* tear down the various subsystems */ 200 /* tear down the various subsystems */
201 edac_workqueue_teardown(); 201 edac_workqueue_teardown();
202 edac_sysfs_memctrl_teardown(); 202 edac_sysfs_teardown_mc_kset();
203 edac_unregister_sysfs_edac_name(); 203 edac_unregister_sysfs_edac_name();
204} 204}
205 205
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 37a08aa87d3e..6368cc658fc6 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -18,11 +18,15 @@
18 * INTERNAL EDAC MODULE: 18 * INTERNAL EDAC MODULE:
19 * EDAC memory controller sysfs create/remove functions 19 * EDAC memory controller sysfs create/remove functions
20 * and setup/teardown functions 20 * and setup/teardown functions
21 *
22 * edac_mc objects
21 */ 23 */
24extern int edac_sysfs_setup_mc_kset(void);
25extern void edac_sysfs_teardown_mc_kset(void);
26extern int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci);
27extern void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci);
22extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci); 28extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
23extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci); 29extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
24extern int edac_sysfs_memctrl_setup(void);
25extern void edac_sysfs_memctrl_teardown(void);
26extern void edac_check_mc_devices(void); 30extern void edac_check_mc_devices(void);
27extern int edac_get_log_ue(void); 31extern int edac_get_log_ue(void);
28extern int edac_get_log_ce(void); 32extern int edac_get_log_ce(void);