aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_device_sysfs.c
diff options
context:
space:
mode:
authorDouglas Thompson <dougthompson@xmission.com>2007-07-19 04:49:36 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:53 -0400
commite27e3dac651771fe3250f6305dee277bce29fc5d (patch)
tree9c0ac81a0948d8e52a72865ff9fbae4a12031a32 /drivers/edac/edac_device_sysfs.c
parent7c9281d76c1c0b130f79d5fc021084e9749959d4 (diff)
drivers/edac: add edac_device class
This patch adds the new 'class' of object to be managed, named: 'edac_device'. As a peer of the 'edac_mc' class of object, it provides a non-memory centric view of an ERROR DETECTING device in hardware. It provides a sysfs interface and an abstraction for varioius EDAC type devices. Multiple 'instances' within the class are possible, with each 'instance' able to have multiple 'blocks', and each 'block' having 'attributes'. At the 'block' level there are the 'ce_count' and 'ue_count' fields which the device driver can update and/or call edac_device_handle_XX() functions. At each higher level are additional 'total' count fields, which are a summation of counts below that level. This 'edac_device' has been used to capture and present ECC errors which are found in a a L1 and L2 system on a per CORE/CPU basis. Signed-off-by: Douglas Thompson <dougthompson@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac/edac_device_sysfs.c')
-rw-r--r--drivers/edac/edac_device_sysfs.c837
1 files changed, 837 insertions, 0 deletions
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
new file mode 100644
index 00000000000..afb19050264
--- /dev/null
+++ b/drivers/edac/edac_device_sysfs.c
@@ -0,0 +1,837 @@
1/*
2 * file for managing the edac_device class of devices for EDAC
3 *
4 * (C) 2007 SoftwareBitMaker(http://www.softwarebitmaker.com)
5 * This file may be distributed under the terms of the
6 * GNU General Public License.
7 *
8 * Written Doug Thompson <norsk5@xmission.com>
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/sysdev.h>
14#include <linux/ctype.h>
15
16#include "edac_core.h"
17#include "edac_module.h"
18
19
20#define EDAC_DEVICE_SYMLINK "device"
21
22#define to_edacdev(k) container_of(k, struct edac_device_ctl_info, kobj)
23#define to_edacdev_attr(a) container_of(a, struct edacdev_attribute, attr)
24
25#ifdef DKT
26
27static ssize_t edac_dev_ue_count_show(struct edac_device_ctl_info *edac_dev,
28 char *data)
29{
30 return sprintf(data,"%d\n", edac_dev->ue_count);
31}
32
33static ssize_t edac_dev_ce_count_show(struct edac_device_ctl_info *edac_dev,
34 char *data)
35{
36 return sprintf(data,"%d\n", edac_dev->ce_count);
37}
38
39static ssize_t edac_dev_seconds_show(struct edac_device_ctl_info *edac_dev,
40 char *data)
41{
42 return sprintf(data,"%ld\n", (jiffies - edac_dev->start_time) / HZ);
43}
44
45static ssize_t edac_dev_ctl_name_show(struct edac_device_ctl_info *edac_dev,
46 char *data)
47{
48 return sprintf(data,"%s\n", edac_dev->ctl_name);
49}
50
51
52struct edacdev_attribute {
53 struct attribute attr;
54 ssize_t (*show)(struct edac_device_ctl_info *,char *);
55 ssize_t (*store)(struct edac_device_ctl_info *, const char *,size_t);
56};
57
58
59/* EDAC DEVICE show/store functions for top most object */
60static ssize_t edacdev_show(struct kobject *kobj, struct attribute *attr,
61 char *buffer)
62{
63 struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
64 struct edacdev_attribute * edacdev_attr = to_edacdev_attr(attr);
65
66 if (edacdev_attr->show)
67 return edacdev_attr->show(edac_dev, buffer);
68
69 return -EIO;
70}
71
72static ssize_t edacdev_store(struct kobject *kobj, struct attribute *attr,
73 const char *buffer, size_t count)
74{
75 struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
76 struct edacdev_attribute * edacdev_attr = to_edacdev_attr(attr);
77
78 if (edacdev_attr->store)
79 return edacdev_attr->store(edac_dev, buffer, count);
80
81 return -EIO;
82}
83
84static struct sysfs_ops edac_dev_ops = {
85 .show = edacdev_show,
86 .store = edacdev_store
87};
88
89#define EDACDEV_ATTR(_name,_mode,_show,_store) \
90static struct edacdev_attribute edac_dev_attr_##_name = { \
91 .attr = {.name = __stringify(_name), .mode = _mode }, \
92 .show = _show, \
93 .store = _store, \
94};
95
96/* default Control file */
97EDACDEV_ATTR(reset_counters,S_IWUSR,NULL,edac_dev_reset_counters_store);
98
99/* default Attribute files */
100EDACDEV_ATTR(mc_name,S_IRUGO,edac_dev_ctl_name_show,NULL);
101EDACDEV_ATTR(seconds_since_reset,S_IRUGO,edac_dev_seconds_show,NULL);
102EDACDEV_ATTR(ue_count,S_IRUGO,edac_dev_ue_count_show,NULL);
103EDACDEV_ATTR(ce_count,S_IRUGO,edac_dev_ce_count_show,NULL);
104
105
106static struct edacdev_attribute *edacdev_attr[] = {
107 &edacdev_attr_reset_counters,
108 &edacdev_attr_mc_name,
109 &edacdev_attr_seconds_since_reset,
110 &edacdev_attr_ue_count,
111 &edacdev_attr_ce_count,
112 NULL
113};
114
115/*
116 * Release of a Edac Device controlling instance
117 */
118static void edac_dev_instance_release(struct kobject *kobj)
119{
120 struct edac_device_ctl_info *edac_dev;
121
122 edac_dev = to_edacdev(kobj);
123 debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx);
124 complete(&edac_dev->kobj_complete);
125}
126
127static struct kobj_type ktype_device = {
128 .release = edac_dev_instance_release,
129 .sysfs_ops = &edacdev_ops,
130 .default_attrs = (struct attribute **) edacdev_attr,
131};
132
133#endif
134
135/************************** edac_device sysfs code and data **************/
136
137/*
138 * Set of edac_device_ctl_info attribute store/show functions
139 */
140
141/* 'log_ue' */
142static ssize_t edac_device_ctl_log_ue_show(
143 struct edac_device_ctl_info *ctl_info, char *data)
144{
145 return sprintf(data,"%u\n", ctl_info->log_ue);
146}
147
148static ssize_t edac_device_ctl_log_ue_store(
149 struct edac_device_ctl_info *ctl_info,
150 const char *data,size_t count)
151{
152 /* if parameter is zero, turn off flag, if non-zero turn on flag */
153 ctl_info->log_ue = (simple_strtoul(data,NULL,0) != 0);
154
155 return count;
156}
157
158/* 'log_ce' */
159static ssize_t edac_device_ctl_log_ce_show(
160 struct edac_device_ctl_info *ctl_info,char *data)
161{
162 return sprintf(data,"%u\n", ctl_info->log_ce);
163}
164
165static ssize_t edac_device_ctl_log_ce_store(
166 struct edac_device_ctl_info *ctl_info,
167 const char *data,size_t count)
168{
169 /* if parameter is zero, turn off flag, if non-zero turn on flag */
170 ctl_info->log_ce = (simple_strtoul(data,NULL,0) != 0);
171
172 return count;
173}
174
175
176/* 'panic_on_ue' */
177static ssize_t edac_device_ctl_panic_on_ue_show(
178 struct edac_device_ctl_info *ctl_info, char *data)
179{
180 return sprintf(data,"%u\n", ctl_info->panic_on_ue);
181}
182
183static ssize_t edac_device_ctl_panic_on_ue_store(
184 struct edac_device_ctl_info *ctl_info,
185 const char *data,size_t count)
186{
187 /* if parameter is zero, turn off flag, if non-zero turn on flag */
188 ctl_info->panic_on_ue = (simple_strtoul(data,NULL,0) != 0);
189
190 return count;
191}
192
193/* 'poll_msec' show and store functions*/
194static ssize_t edac_device_ctl_poll_msec_show(
195 struct edac_device_ctl_info *ctl_info, char *data)
196{
197 return sprintf(data,"%u\n", ctl_info->poll_msec);
198}
199
200static ssize_t edac_device_ctl_poll_msec_store(
201 struct edac_device_ctl_info *ctl_info,
202 const char *data,size_t count)
203{
204 unsigned long value;
205
206 /* get the value and enforce that it is non-zero, must be at least
207 * one millisecond for the delay period, between scans
208 * Then cancel last outstanding delay for the work request
209 * and set a new one.
210 */
211 value = simple_strtoul(data,NULL,0);
212 edac_device_reset_delay_period(ctl_info,value);
213
214 return count;
215}
216
217
218/* edac_device_ctl_info specific attribute structure */
219struct ctl_info_attribute {
220 struct attribute attr;
221 ssize_t (*show)(struct edac_device_ctl_info *,char *);
222 ssize_t (*store)(struct edac_device_ctl_info *,const char *,size_t);
223};
224
225#define to_ctl_info(k) container_of(k, struct edac_device_ctl_info, kobj)
226#define to_ctl_info_attr(a) container_of(a,struct ctl_info_attribute,attr)
227
228/* Function to 'show' fields from the edac_dev 'ctl_info' structure */
229static ssize_t edac_dev_ctl_info_show(struct kobject *kobj,
230 struct attribute *attr,
231 char *buffer)
232{
233 struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
234 struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
235
236 if (ctl_info_attr->show)
237 return ctl_info_attr->show(edac_dev,buffer);
238 return -EIO;
239}
240
241/* Function to 'store' fields into the edac_dev 'ctl_info' structure */
242static ssize_t edac_dev_ctl_info_store(struct kobject *kobj,
243 struct attribute *attr,
244 const char *buffer, size_t count)
245{
246 struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
247 struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
248
249 if (ctl_info_attr->store)
250 return ctl_info_attr->store(edac_dev, buffer, count);
251 return -EIO;
252}
253
254/* edac_dev file operations for an 'ctl_info' */
255static struct sysfs_ops device_ctl_info_ops = {
256 .show = edac_dev_ctl_info_show,
257 .store = edac_dev_ctl_info_store
258};
259
260#define CTL_INFO_ATTR(_name,_mode,_show,_store) \
261static struct ctl_info_attribute attr_ctl_info_##_name = { \
262 .attr = {.name = __stringify(_name), .mode = _mode }, \
263 .show = _show, \
264 .store = _store, \
265};
266
267
268/* Declare the various ctl_info attributes here and their respective ops */
269CTL_INFO_ATTR(log_ue,S_IRUGO|S_IWUSR,
270 edac_device_ctl_log_ue_show,
271 edac_device_ctl_log_ue_store);
272CTL_INFO_ATTR(log_ce,S_IRUGO|S_IWUSR,
273 edac_device_ctl_log_ce_show,
274 edac_device_ctl_log_ce_store);
275CTL_INFO_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,
276 edac_device_ctl_panic_on_ue_show,
277 edac_device_ctl_panic_on_ue_store);
278CTL_INFO_ATTR(poll_msec,S_IRUGO|S_IWUSR,
279 edac_device_ctl_poll_msec_show,
280 edac_device_ctl_poll_msec_store);
281
282
283/* Base Attributes of the EDAC_DEVICE ECC object */
284static struct ctl_info_attribute *device_ctrl_attr[] = {
285 &attr_ctl_info_panic_on_ue,
286 &attr_ctl_info_log_ue,
287 &attr_ctl_info_log_ce,
288 &attr_ctl_info_poll_msec,
289 NULL,
290};
291
292/* Main DEVICE kobject release() function */
293static void edac_device_ctrl_master_release(struct kobject *kobj)
294{
295 struct edac_device_ctl_info *edac_dev;
296
297 edac_dev = to_edacdev(kobj);
298
299 debugf1("%s()\n", __func__);
300 complete(&edac_dev->kobj_complete);
301}
302
303static struct kobj_type ktype_device_ctrl = {
304 .release = edac_device_ctrl_master_release,
305 .sysfs_ops = &device_ctl_info_ops,
306 .default_attrs = (struct attribute **) device_ctrl_attr,
307};
308
309
310/**************** edac_device main kobj ctor/dtor code *********************/
311
312/*
313 * edac_device_register_main_kobj
314 *
315 * perform the high level setup for the new edac_device instance
316 *
317 * Return: 0 SUCCESS
318 * !0 FAILURE
319 */
320static int edac_device_register_main_kobj(
321 struct edac_device_ctl_info *edac_dev)
322{
323 int err = 0;
324 struct sysdev_class *edac_class;
325
326 debugf1("%s()\n", __func__);
327
328 /* get the /sys/devices/system/edac reference */
329 edac_class = edac_get_edac_class();
330 if (edac_class == NULL) {
331 debugf1("%s() no edac_class error=%d\n", __func__, err);
332 return err;
333 }
334
335 /* Point to the 'edac_class' this instance 'reports' to */
336 edac_dev->edac_class = edac_class;
337
338 /* Init the devices's kobject */
339 memset(&edac_dev->kobj, 0, sizeof (struct kobject));
340 edac_dev->kobj.ktype = &ktype_device_ctrl;
341
342 /* set this new device under the edac_class kobject */
343 edac_dev->kobj.parent = &edac_class->kset.kobj;
344
345 /* generate sysfs "..../edac/<name>" */
346 debugf1("%s() set name of kobject to: %s\n",
347 __func__, edac_dev->name);
348 err = kobject_set_name(&edac_dev->kobj,"%s",edac_dev->name);
349 if (err)
350 return err;
351 err = kobject_register(&edac_dev->kobj);
352 if (err) {
353 debugf1("%s()Failed to register '.../edac/%s'\n",
354 __func__,edac_dev->name);
355 return err;
356 }
357
358 debugf1("%s() Registered '.../edac/%s' kobject\n",
359 __func__, edac_dev->name);
360
361 return 0;
362}
363
364/*
365 * edac_device_unregister_main_kobj:
366 * the '..../edac/<name>' kobject
367 */
368static void edac_device_unregister_main_kobj(
369 struct edac_device_ctl_info *edac_dev)
370{
371 debugf0("%s()\n", __func__);
372 debugf1("%s() name of kobject is: %s\n",
373 __func__, kobject_name(&edac_dev->kobj));
374
375 init_completion(&edac_dev->kobj_complete);
376
377 /*
378 * Unregister the edac device's kobject and
379 * wait for reference count to reach 0.
380 */
381 kobject_unregister(&edac_dev->kobj);
382 wait_for_completion(&edac_dev->kobj_complete);
383}
384
385
386/*************** edac_dev -> instance information ***********/
387
388/*
389 * Set of low-level instance attribute show functions
390 */
391static ssize_t instance_ue_count_show(
392 struct edac_device_instance *instance, char *data)
393{
394 return sprintf(data,"%u\n", instance->counters.ue_count);
395}
396
397static ssize_t instance_ce_count_show(
398 struct edac_device_instance *instance, char *data)
399{
400 return sprintf(data,"%u\n", instance->counters.ce_count);
401}
402
403
404
405#define to_instance(k) container_of(k, struct edac_device_instance, kobj)
406#define to_instance_attr(a) container_of(a,struct instance_attribute,attr)
407
408/* DEVICE instance kobject release() function */
409static void edac_device_ctrl_instance_release(struct kobject *kobj)
410{
411 struct edac_device_instance *instance;
412
413 debugf1("%s()\n", __func__);
414
415 instance = to_instance(kobj);
416 complete(&instance->kobj_complete);
417}
418
419
420/* instance specific attribute structure */
421struct instance_attribute {
422 struct attribute attr;
423 ssize_t (*show)(struct edac_device_instance *,char *);
424 ssize_t (*store)(struct edac_device_instance *,const char *,size_t);
425};
426
427
428/* Function to 'show' fields from the edac_dev 'instance' structure */
429static ssize_t edac_dev_instance_show(struct kobject *kobj,
430 struct attribute *attr,
431 char *buffer)
432{
433 struct edac_device_instance *instance = to_instance(kobj);
434 struct instance_attribute *instance_attr = to_instance_attr(attr);
435
436 if (instance_attr->show)
437 return instance_attr->show(instance,buffer);
438 return -EIO;
439}
440
441
442/* Function to 'store' fields into the edac_dev 'instance' structure */
443static ssize_t edac_dev_instance_store(struct kobject *kobj,
444 struct attribute *attr,
445 const char *buffer, size_t count)
446{
447 struct edac_device_instance *instance = to_instance(kobj);
448 struct instance_attribute *instance_attr = to_instance_attr(attr);
449
450 if (instance_attr->store)
451 return instance_attr->store(instance, buffer, count);
452 return -EIO;
453}
454
455
456
457/* edac_dev file operations for an 'instance' */
458static struct sysfs_ops device_instance_ops = {
459 .show = edac_dev_instance_show,
460 .store = edac_dev_instance_store
461};
462
463#define INSTANCE_ATTR(_name,_mode,_show,_store) \
464static struct instance_attribute attr_instance_##_name = { \
465 .attr = {.name = __stringify(_name), .mode = _mode }, \
466 .show = _show, \
467 .store = _store, \
468};
469
470/*
471 * Define attributes visible for the edac_device instance object
472 * Each contains a pointer to a show and an optional set
473 * function pointer that does the low level output/input
474 */
475INSTANCE_ATTR(ce_count,S_IRUGO,instance_ce_count_show,NULL);
476INSTANCE_ATTR(ue_count,S_IRUGO,instance_ue_count_show,NULL);
477
478/* list of edac_dev 'instance' attributes */
479static struct instance_attribute *device_instance_attr[] = {
480 &attr_instance_ce_count,
481 &attr_instance_ue_count,
482 NULL,
483};
484
485/* The 'ktype' for each edac_dev 'instance' */
486static struct kobj_type ktype_instance_ctrl = {
487 .release = edac_device_ctrl_instance_release,
488 .sysfs_ops = &device_instance_ops,
489 .default_attrs = (struct attribute **) device_instance_attr,
490};
491
492
493/*************** edac_dev -> instance -> block information *********/
494
495/*
496 * Set of low-level block attribute show functions
497 */
498static ssize_t block_ue_count_show(
499 struct edac_device_block *block, char *data)
500{
501 return sprintf(data,"%u\n", block->counters.ue_count);
502}
503
504static ssize_t block_ce_count_show(
505 struct edac_device_block *block, char *data)
506{
507 return sprintf(data,"%u\n", block->counters.ce_count);
508}
509
510
511
512#define to_block(k) container_of(k, struct edac_device_block, kobj)
513#define to_block_attr(a) container_of(a,struct block_attribute,attr)
514
515/* DEVICE block kobject release() function */
516static void edac_device_ctrl_block_release(struct kobject *kobj)
517{
518 struct edac_device_block *block;
519
520 debugf1("%s()\n", __func__);
521
522 block = to_block(kobj);
523 complete(&block->kobj_complete);
524}
525
526/* block specific attribute structure */
527struct block_attribute {
528 struct attribute attr;
529 ssize_t (*show)(struct edac_device_block *,char *);
530 ssize_t (*store)(struct edac_device_block *,const char *,size_t);
531};
532
533/* Function to 'show' fields from the edac_dev 'block' structure */
534static ssize_t edac_dev_block_show(struct kobject *kobj,
535 struct attribute *attr,
536 char *buffer)
537{
538 struct edac_device_block *block = to_block(kobj);
539 struct block_attribute *block_attr = to_block_attr(attr);
540
541 if (block_attr->show)
542 return block_attr->show(block,buffer);
543 return -EIO;
544}
545
546
547/* Function to 'store' fields into the edac_dev 'block' structure */
548static ssize_t edac_dev_block_store(struct kobject *kobj,
549 struct attribute *attr,
550 const char *buffer, size_t count)
551{
552 struct edac_device_block *block = to_block(kobj);
553 struct block_attribute *block_attr = to_block_attr(attr);
554
555 if (block_attr->store)
556 return block_attr->store(block, buffer, count);
557 return -EIO;
558}
559
560
561/* edac_dev file operations for a 'block' */
562static struct sysfs_ops device_block_ops = {
563 .show = edac_dev_block_show,
564 .store = edac_dev_block_store
565};
566
567
568#define BLOCK_ATTR(_name,_mode,_show,_store) \
569static struct block_attribute attr_block_##_name = { \
570 .attr = {.name = __stringify(_name), .mode = _mode }, \
571 .show = _show, \
572 .store = _store, \
573};
574
575BLOCK_ATTR(ce_count,S_IRUGO,block_ce_count_show,NULL);
576BLOCK_ATTR(ue_count,S_IRUGO,block_ue_count_show,NULL);
577
578
579/* list of edac_dev 'block' attributes */
580static struct block_attribute *device_block_attr[] = {
581 &attr_block_ce_count,
582 &attr_block_ue_count,
583 NULL,
584};
585
586/* The 'ktype' for each edac_dev 'block' */
587static struct kobj_type ktype_block_ctrl = {
588 .release = edac_device_ctrl_block_release,
589 .sysfs_ops = &device_block_ops,
590 .default_attrs = (struct attribute **) device_block_attr,
591};
592
593
594/************** block ctor/dtor code ************/
595
596/*
597 * edac_device_create_block
598 */
599static int edac_device_create_block(
600 struct edac_device_ctl_info *edac_dev,
601 struct edac_device_instance *instance,
602 int idx)
603{
604 int err;
605 struct edac_device_block *block;
606
607 block = &instance->blocks[idx];
608
609 debugf1("%s() Instance '%s' block[%d] '%s'\n",
610 __func__,instance->name, idx, block->name);
611
612 /* init this block's kobject */
613 memset(&block->kobj, 0, sizeof (struct kobject));
614 block->kobj.parent = &instance->kobj;
615 block->kobj.ktype = &ktype_block_ctrl;
616
617 err = kobject_set_name(&block->kobj,"%s",block->name);
618 if (err)
619 return err;
620
621 err = kobject_register(&block->kobj);
622 if (err) {
623 debugf1("%s()Failed to register instance '%s'\n",
624 __func__,block->name);
625 return err;
626 }
627
628 return 0;
629}
630
631/*
632 * edac_device_delete_block(edac_dev,j);
633 */
634static void edac_device_delete_block(
635 struct edac_device_ctl_info *edac_dev,
636 struct edac_device_instance *instance,
637 int idx)
638{
639 struct edac_device_block *block;
640
641 block = &instance->blocks[idx];
642
643 /* unregister this block's kobject */
644 init_completion(&block->kobj_complete);
645 kobject_unregister(&block->kobj);
646 wait_for_completion(&block->kobj_complete);
647}
648
649/************** instance ctor/dtor code ************/
650
651/*
652 * edac_device_create_instance
653 * create just one instance of an edac_device 'instance'
654 */
655static int edac_device_create_instance(
656 struct edac_device_ctl_info *edac_dev, int idx)
657{
658 int i, j;
659 int err;
660 struct edac_device_instance *instance;
661
662 instance = &edac_dev->instances[idx];
663
664 /* Init the instance's kobject */
665 memset(&instance->kobj, 0, sizeof (struct kobject));
666
667 /* set this new device under the edac_device main kobject */
668 instance->kobj.parent = &edac_dev->kobj;
669 instance->kobj.ktype = &ktype_instance_ctrl;
670
671 err = kobject_set_name(&instance->kobj,"%s",instance->name);
672 if (err)
673 return err;
674
675 err = kobject_register(&instance->kobj);
676 if (err != 0) {
677 debugf2("%s() Failed to register instance '%s'\n",
678 __func__,instance->name);
679 return err;
680 }
681
682 debugf1("%s() now register '%d' blocks for instance %d\n",
683 __func__,instance->nr_blocks,idx);
684
685 /* register all blocks of this instance */
686 for (i = 0; i < instance->nr_blocks; i++ ) {
687 err = edac_device_create_block(edac_dev,instance,i);
688 if (err) {
689 for (j = 0; j < i; j++) {
690 edac_device_delete_block(edac_dev,instance,j);
691 }
692 return err;
693 }
694 }
695
696 debugf1("%s() Registered instance %d '%s' kobject\n",
697 __func__, idx, instance->name);
698
699 return 0;
700}
701
702/*
703 * edac_device_remove_instance
704 * remove an edac_device instance
705 */
706static void edac_device_delete_instance(
707 struct edac_device_ctl_info *edac_dev, int idx)
708{
709 int i;
710 struct edac_device_instance *instance;
711
712 instance = &edac_dev->instances[idx];
713
714 /* unregister all blocks in this instance */
715 for (i = 0; i < instance->nr_blocks; i++) {
716 edac_device_delete_block(edac_dev,instance,i);
717 }
718
719 /* unregister this instance's kobject */
720 init_completion(&instance->kobj_complete);
721 kobject_unregister(&instance->kobj);
722 wait_for_completion(&instance->kobj_complete);
723}
724
725/*
726 * edac_device_create_instances
727 * create the first level of 'instances' for this device
728 * (ie 'cache' might have 'cache0', 'cache1', 'cache2', etc
729 */
730static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
731{
732 int i, j;
733 int err;
734
735 debugf0("%s()\n", __func__);
736
737 /* iterate over creation of the instances */
738 for (i = 0; i < edac_dev->nr_instances; i++ ) {
739 err = edac_device_create_instance(edac_dev,i);
740 if (err) {
741 /* unwind previous instances on error */
742 for (j = 0; j < i; j++) {
743 edac_device_delete_instance(edac_dev,j);
744 }
745 return err;
746 }
747 }
748
749 return 0;
750}
751
752/*
753 * edac_device_delete_instances(edac_dev);
754 * unregister all the kobjects of the instances
755 */
756static void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev)
757{
758 int i;
759
760 /* iterate over creation of the instances */
761 for (i = 0; i < edac_dev->nr_instances; i++ ) {
762 edac_device_delete_instance(edac_dev,i);
763 }
764}
765
766/******************* edac_dev sysfs ctor/dtor code *************/
767
768/*
769 * edac_device_create_sysfs() Constructor
770 *
771 * Create a new edac_device kobject instance,
772 *
773 * Return:
774 * 0 Success
775 * !0 Failure
776 */
777int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
778{
779 int err;
780 struct kobject *edac_kobj=&edac_dev->kobj;
781
782 /* register this instance's main kobj with the edac class kobj */
783 err = edac_device_register_main_kobj(edac_dev);
784 if (err)
785 return err;
786
787 debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx);
788
789 /* create a symlink from the edac device
790 * to the platform 'device' being used for this
791 */
792 err = sysfs_create_link(edac_kobj,
793 &edac_dev->dev->kobj,
794 EDAC_DEVICE_SYMLINK);
795 if (err) {
796 debugf0("%s() sysfs_create_link() returned err= %d\n",
797 __func__, err);
798 return err;
799 }
800
801 debugf0("%s() calling create-instances, idx=%d\n",
802 __func__, edac_dev->dev_idx);
803
804 /* Create the first level instance directories */
805 err = edac_device_create_instances(edac_dev);
806 if (err) {
807 goto error0;
808 }
809
810 return 0;
811
812 /* Error unwind stack */
813
814error0:
815 edac_device_unregister_main_kobj(edac_dev);
816
817 return err;
818}
819
820/*
821 * edac_device_remove_sysfs() destructor
822 *
823 * remove a edac_device instance
824 */
825void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
826{
827 debugf0("%s()\n", __func__);
828
829 edac_device_delete_instances(edac_dev);
830
831 /* remove the sym link */
832 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
833
834 /* unregister the instance's main kobj */
835 edac_device_unregister_main_kobj(edac_dev);
836}
837