1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/ctype.h>
14#include <linux/module.h>
15
16#include "edac_core.h"
17#include "edac_module.h"
18
19#define EDAC_DEVICE_SYMLINK "device"
20
21#define to_edacdev(k) container_of(k, struct edac_device_ctl_info, kobj)
22#define to_edacdev_attr(a) container_of(a, struct edacdev_attribute, attr)
23
24
25
26
27
28
29
30static ssize_t edac_device_ctl_log_ue_show(struct edac_device_ctl_info
31 *ctl_info, char *data)
32{
33 return sprintf(data, "%u\n", ctl_info->log_ue);
34}
35
36static ssize_t edac_device_ctl_log_ue_store(struct edac_device_ctl_info
37 *ctl_info, const char *data,
38 size_t count)
39{
40
41 ctl_info->log_ue = (simple_strtoul(data, NULL, 0) != 0);
42
43 return count;
44}
45
46
47static ssize_t edac_device_ctl_log_ce_show(struct edac_device_ctl_info
48 *ctl_info, char *data)
49{
50 return sprintf(data, "%u\n", ctl_info->log_ce);
51}
52
53static ssize_t edac_device_ctl_log_ce_store(struct edac_device_ctl_info
54 *ctl_info, const char *data,
55 size_t count)
56{
57
58 ctl_info->log_ce = (simple_strtoul(data, NULL, 0) != 0);
59
60 return count;
61}
62
63
64static ssize_t edac_device_ctl_panic_on_ue_show(struct edac_device_ctl_info
65 *ctl_info, char *data)
66{
67 return sprintf(data, "%u\n", ctl_info->panic_on_ue);
68}
69
70static ssize_t edac_device_ctl_panic_on_ue_store(struct edac_device_ctl_info
71 *ctl_info, const char *data,
72 size_t count)
73{
74
75 ctl_info->panic_on_ue = (simple_strtoul(data, NULL, 0) != 0);
76
77 return count;
78}
79
80
81static ssize_t edac_device_ctl_poll_msec_show(struct edac_device_ctl_info
82 *ctl_info, char *data)
83{
84 return sprintf(data, "%u\n", ctl_info->poll_msec);
85}
86
87static ssize_t edac_device_ctl_poll_msec_store(struct edac_device_ctl_info
88 *ctl_info, const char *data,
89 size_t count)
90{
91 unsigned long value;
92
93
94
95
96
97
98 value = simple_strtoul(data, NULL, 0);
99 edac_device_reset_delay_period(ctl_info, value);
100
101 return count;
102}
103
104
105struct ctl_info_attribute {
106 struct attribute attr;
107 ssize_t(*show) (struct edac_device_ctl_info *, char *);
108 ssize_t(*store) (struct edac_device_ctl_info *, const char *, size_t);
109};
110
111#define to_ctl_info(k) container_of(k, struct edac_device_ctl_info, kobj)
112#define to_ctl_info_attr(a) container_of(a,struct ctl_info_attribute,attr)
113
114
115static ssize_t edac_dev_ctl_info_show(struct kobject *kobj,
116 struct attribute *attr, char *buffer)
117{
118 struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
119 struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
120
121 if (ctl_info_attr->show)
122 return ctl_info_attr->show(edac_dev, buffer);
123 return -EIO;
124}
125
126
127static ssize_t edac_dev_ctl_info_store(struct kobject *kobj,
128 struct attribute *attr,
129 const char *buffer, size_t count)
130{
131 struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
132 struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
133
134 if (ctl_info_attr->store)
135 return ctl_info_attr->store(edac_dev, buffer, count);
136 return -EIO;
137}
138
139
140static struct sysfs_ops device_ctl_info_ops = {
141 .show = edac_dev_ctl_info_show,
142 .store = edac_dev_ctl_info_store
143};
144
145#define CTL_INFO_ATTR(_name,_mode,_show,_store) \
146static struct ctl_info_attribute attr_ctl_info_##_name = { \
147 .attr = {.name = __stringify(_name), .mode = _mode }, \
148 .show = _show, \
149 .store = _store, \
150};
151
152
153CTL_INFO_ATTR(log_ue, S_IRUGO | S_IWUSR,
154 edac_device_ctl_log_ue_show, edac_device_ctl_log_ue_store);
155CTL_INFO_ATTR(log_ce, S_IRUGO | S_IWUSR,
156 edac_device_ctl_log_ce_show, edac_device_ctl_log_ce_store);
157CTL_INFO_ATTR(panic_on_ue, S_IRUGO | S_IWUSR,
158 edac_device_ctl_panic_on_ue_show,
159 edac_device_ctl_panic_on_ue_store);
160CTL_INFO_ATTR(poll_msec, S_IRUGO | S_IWUSR,
161 edac_device_ctl_poll_msec_show, edac_device_ctl_poll_msec_store);
162
163
164static struct ctl_info_attribute *device_ctrl_attr[] = {
165 &attr_ctl_info_panic_on_ue,
166 &attr_ctl_info_log_ue,
167 &attr_ctl_info_log_ce,
168 &attr_ctl_info_poll_msec,
169 NULL,
170};
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199static void edac_device_ctrl_master_release(struct kobject *kobj)
200{
201 struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
202
203 debugf4("%s() control index=%d\n", __func__, edac_dev->dev_idx);
204
205
206 module_put(edac_dev->owner);
207
208
209
210
211 kfree(edac_dev);
212}
213
214
215static struct kobj_type ktype_device_ctrl = {
216 .release = edac_device_ctrl_master_release,
217 .sysfs_ops = &device_ctl_info_ops,
218 .default_attrs = (struct attribute **)device_ctrl_attr,
219};
220
221
222
223
224
225
226
227
228
229int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
230{
231 struct sysdev_class *edac_class;
232 int err;
233
234 debugf1("%s()\n", __func__);
235
236
237 edac_class = edac_get_edac_class();
238 if (edac_class == NULL) {
239 debugf1("%s() no edac_class error\n", __func__);
240 err = -ENODEV;
241 goto err_out;
242 }
243
244
245 edac_dev->edac_class = edac_class;
246
247
248 memset(&edac_dev->kobj, 0, sizeof(struct kobject));
249
250
251
252
253 edac_dev->owner = THIS_MODULE;
254
255 if (!try_module_get(edac_dev->owner)) {
256 err = -ENODEV;
257 goto err_out;
258 }
259
260
261 err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
262 &edac_class->kset.kobj,
263 "%s", edac_dev->name);
264 if (err) {
265 debugf1("%s()Failed to register '.../edac/%s'\n",
266 __func__, edac_dev->name);
267 goto err_kobj_reg;
268 }
269 kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
270
271
272
273
274
275 debugf4("%s() Registered '.../edac/%s' kobject\n",
276 __func__, edac_dev->name);
277
278 return 0;
279
280
281err_kobj_reg:
282 module_put(edac_dev->owner);
283
284err_out:
285 return err;
286}
287
288
289
290
291
292void edac_device_unregister_sysfs_main_kobj(
293 struct edac_device_ctl_info *edac_dev)
294{
295 debugf0("%s()\n", __func__);
296 debugf4("%s() name of kobject is: %s\n",
297 __func__, kobject_name(&edac_dev->kobj));
298
299
300
301
302
303
304
305
306 kobject_put(&edac_dev->kobj);
307}
308
309
310
311
312
313
314static ssize_t instance_ue_count_show(struct edac_device_instance *instance,
315 char *data)
316{
317 return sprintf(data, "%u\n", instance->counters.ue_count);
318}
319
320static ssize_t instance_ce_count_show(struct edac_device_instance *instance,
321 char *data)
322{
323 return sprintf(data, "%u\n", instance->counters.ce_count);
324}
325
326#define to_instance(k) container_of(k, struct edac_device_instance, kobj)
327#define to_instance_attr(a) container_of(a,struct instance_attribute,attr)
328
329
330static void edac_device_ctrl_instance_release(struct kobject *kobj)
331{
332 struct edac_device_instance *instance;
333
334 debugf1("%s()\n", __func__);
335
336
337
338
339 instance = to_instance(kobj);
340 kobject_put(&instance->ctl->kobj);
341}
342
343
344struct instance_attribute {
345 struct attribute attr;
346 ssize_t(*show) (struct edac_device_instance *, char *);
347 ssize_t(*store) (struct edac_device_instance *, const char *, size_t);
348};
349
350
351static ssize_t edac_dev_instance_show(struct kobject *kobj,
352 struct attribute *attr, char *buffer)
353{
354 struct edac_device_instance *instance = to_instance(kobj);
355 struct instance_attribute *instance_attr = to_instance_attr(attr);
356
357 if (instance_attr->show)
358 return instance_attr->show(instance, buffer);
359 return -EIO;
360}
361
362
363static ssize_t edac_dev_instance_store(struct kobject *kobj,
364 struct attribute *attr,
365 const char *buffer, size_t count)
366{
367 struct edac_device_instance *instance = to_instance(kobj);
368 struct instance_attribute *instance_attr = to_instance_attr(attr);
369
370 if (instance_attr->store)
371 return instance_attr->store(instance, buffer, count);
372 return -EIO;
373}
374
375
376static struct sysfs_ops device_instance_ops = {
377 .show = edac_dev_instance_show,
378 .store = edac_dev_instance_store
379};
380
381#define INSTANCE_ATTR(_name,_mode,_show,_store) \
382static struct instance_attribute attr_instance_##_name = { \
383 .attr = {.name = __stringify(_name), .mode = _mode }, \
384 .show = _show, \
385 .store = _store, \
386};
387
388
389
390
391
392
393INSTANCE_ATTR(ce_count, S_IRUGO, instance_ce_count_show, NULL);
394INSTANCE_ATTR(ue_count, S_IRUGO, instance_ue_count_show, NULL);
395
396
397static struct instance_attribute *device_instance_attr[] = {
398 &attr_instance_ce_count,
399 &attr_instance_ue_count,
400 NULL,
401};
402
403
404static struct kobj_type ktype_instance_ctrl = {
405 .release = edac_device_ctrl_instance_release,
406 .sysfs_ops = &device_instance_ops,
407 .default_attrs = (struct attribute **)device_instance_attr,
408};
409
410
411
412#define to_block(k) container_of(k, struct edac_device_block, kobj)
413#define to_block_attr(a) \
414 container_of(a, struct edac_dev_sysfs_block_attribute, attr)
415
416
417
418
419static ssize_t block_ue_count_show(struct kobject *kobj,
420 struct attribute *attr, char *data)
421{
422 struct edac_device_block *block = to_block(kobj);
423
424 return sprintf(data, "%u\n", block->counters.ue_count);
425}
426
427static ssize_t block_ce_count_show(struct kobject *kobj,
428 struct attribute *attr, char *data)
429{
430 struct edac_device_block *block = to_block(kobj);
431
432 return sprintf(data, "%u\n", block->counters.ce_count);
433}
434
435
436static void edac_device_ctrl_block_release(struct kobject *kobj)
437{
438 struct edac_device_block *block;
439
440 debugf1("%s()\n", __func__);
441
442
443 block = to_block(kobj);
444
445
446
447
448 kobject_put(&block->instance->ctl->kobj);
449}
450
451
452
453static ssize_t edac_dev_block_show(struct kobject *kobj,
454 struct attribute *attr, char *buffer)
455{
456 struct edac_dev_sysfs_block_attribute *block_attr =
457 to_block_attr(attr);
458
459 if (block_attr->show)
460 return block_attr->show(kobj, attr, buffer);
461 return -EIO;
462}
463
464
465static ssize_t edac_dev_block_store(struct kobject *kobj,
466 struct attribute *attr,
467 const char *buffer, size_t count)
468{
469 struct edac_dev_sysfs_block_attribute *block_attr;
470
471 block_attr = to_block_attr(attr);
472
473 if (block_attr->store)
474 return block_attr->store(kobj, attr, buffer, count);
475 return -EIO;
476}
477
478
479static struct sysfs_ops device_block_ops = {
480 .show = edac_dev_block_show,
481 .store = edac_dev_block_store
482};
483
484#define BLOCK_ATTR(_name,_mode,_show,_store) \
485static struct edac_dev_sysfs_block_attribute attr_block_##_name = { \
486 .attr = {.name = __stringify(_name), .mode = _mode }, \
487 .show = _show, \
488 .store = _store, \
489};
490
491BLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);
492BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);
493
494
495static struct edac_dev_sysfs_block_attribute *device_block_attr[] = {
496 &attr_block_ce_count,
497 &attr_block_ue_count,
498 NULL,
499};
500
501
502static struct kobj_type ktype_block_ctrl = {
503 .release = edac_device_ctrl_block_release,
504 .sysfs_ops = &device_block_ops,
505 .default_attrs = (struct attribute **)device_block_attr,
506};
507
508
509
510
511
512
513static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
514 struct edac_device_instance *instance,
515 struct edac_device_block *block)
516{
517 int i;
518 int err;
519 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
520 struct kobject *main_kobj;
521
522 debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n",
523 __func__, instance->name, instance, block->name, block);
524 debugf4("%s() block kobj=%p block kobj->parent=%p\n",
525 __func__, &block->kobj, &block->kobj.parent);
526
527
528 memset(&block->kobj, 0, sizeof(struct kobject));
529
530
531
532
533 main_kobj = kobject_get(&edac_dev->kobj);
534 if (!main_kobj) {
535 err = -ENODEV;
536 goto err_out;
537 }
538
539
540 err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
541 &instance->kobj,
542 "%s", block->name);
543 if (err) {
544 debugf1("%s() Failed to register instance '%s'\n",
545 __func__, block->name);
546 kobject_put(main_kobj);
547 err = -ENODEV;
548 goto err_out;
549 }
550
551
552
553
554 sysfs_attrib = block->block_attributes;
555 if (sysfs_attrib && block->nr_attribs) {
556 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
557
558 debugf4("%s() creating block attrib='%s' "
559 "attrib->%p to kobj=%p\n",
560 __func__,
561 sysfs_attrib->attr.name,
562 sysfs_attrib, &block->kobj);
563
564
565 err = sysfs_create_file(&block->kobj,
566 &sysfs_attrib->attr);
567 if (err)
568 goto err_on_attrib;
569 }
570 }
571 kobject_uevent(&block->kobj, KOBJ_ADD);
572
573 return 0;
574
575
576err_on_attrib:
577 kobject_put(&block->kobj);
578
579err_out:
580 return err;
581}
582
583
584
585
586static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
587 struct edac_device_block *block)
588{
589 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
590 int i;
591
592
593
594
595 sysfs_attrib = block->block_attributes;
596 if (sysfs_attrib && block->nr_attribs) {
597 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
598
599
600 sysfs_remove_file(&block->kobj,
601 (struct attribute *) sysfs_attrib);
602 }
603 }
604
605
606
607
608 kobject_put(&block->kobj);
609}
610
611
612
613
614
615
616
617static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
618 int idx)
619{
620 int i, j;
621 int err;
622 struct edac_device_instance *instance;
623 struct kobject *main_kobj;
624
625 instance = &edac_dev->instances[idx];
626
627
628 memset(&instance->kobj, 0, sizeof(struct kobject));
629
630 instance->ctl = edac_dev;
631
632
633
634
635 main_kobj = kobject_get(&edac_dev->kobj);
636 if (!main_kobj) {
637 err = -ENODEV;
638 goto err_out;
639 }
640
641
642 err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
643 &edac_dev->kobj, "%s", instance->name);
644 if (err != 0) {
645 debugf2("%s() Failed to register instance '%s'\n",
646 __func__, instance->name);
647 kobject_put(main_kobj);
648 goto err_out;
649 }
650
651 debugf4("%s() now register '%d' blocks for instance %d\n",
652 __func__, instance->nr_blocks, idx);
653
654
655 for (i = 0; i < instance->nr_blocks; i++) {
656 err = edac_device_create_block(edac_dev, instance,
657 &instance->blocks[i]);
658 if (err) {
659
660 for (j = 0; j < i; j++)
661 edac_device_delete_block(edac_dev,
662 &instance->blocks[j]);
663 goto err_release_instance_kobj;
664 }
665 }
666 kobject_uevent(&instance->kobj, KOBJ_ADD);
667
668 debugf4("%s() Registered instance %d '%s' kobject\n",
669 __func__, idx, instance->name);
670
671 return 0;
672
673
674err_release_instance_kobj:
675 kobject_put(&instance->kobj);
676
677err_out:
678 return err;
679}
680
681
682
683
684
685static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
686 int idx)
687{
688 struct edac_device_instance *instance;
689 int i;
690
691 instance = &edac_dev->instances[idx];
692
693
694 for (i = 0; i < instance->nr_blocks; i++)
695 edac_device_delete_block(edac_dev, &instance->blocks[i]);
696
697
698
699
700 kobject_put(&instance->kobj);
701}
702
703
704
705
706
707
708static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
709{
710 int i, j;
711 int err;
712
713 debugf0("%s()\n", __func__);
714
715
716 for (i = 0; i < edac_dev->nr_instances; i++) {
717 err = edac_device_create_instance(edac_dev, i);
718 if (err) {
719
720 for (j = 0; j < i; j++)
721 edac_device_delete_instance(edac_dev, j);
722 return err;
723 }
724 }
725
726 return 0;
727}
728
729
730
731
732
733static void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev)
734{
735 int i;
736
737
738 for (i = 0; i < edac_dev->nr_instances; i++)
739 edac_device_delete_instance(edac_dev, i);
740}
741
742
743
744
745
746
747
748static int edac_device_add_main_sysfs_attributes(
749 struct edac_device_ctl_info *edac_dev)
750{
751 struct edac_dev_sysfs_attribute *sysfs_attrib;
752 int err = 0;
753
754 sysfs_attrib = edac_dev->sysfs_attributes;
755 if (sysfs_attrib) {
756
757
758
759 while (sysfs_attrib->attr.name != NULL) {
760 err = sysfs_create_file(&edac_dev->kobj,
761 (struct attribute*) sysfs_attrib);
762 if (err)
763 goto err_out;
764
765 sysfs_attrib++;
766 }
767 }
768
769err_out:
770 return err;
771}
772
773
774
775
776
777static void edac_device_remove_main_sysfs_attributes(
778 struct edac_device_ctl_info *edac_dev)
779{
780 struct edac_dev_sysfs_attribute *sysfs_attrib;
781
782
783
784
785
786 sysfs_attrib = edac_dev->sysfs_attributes;
787 if (sysfs_attrib) {
788 while (sysfs_attrib->attr.name != NULL) {
789 sysfs_remove_file(&edac_dev->kobj,
790 (struct attribute *) sysfs_attrib);
791 sysfs_attrib++;
792 }
793 }
794}
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
811{
812 int err;
813 struct kobject *edac_kobj = &edac_dev->kobj;
814
815 debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx);
816
817
818 err = edac_device_add_main_sysfs_attributes(edac_dev);
819 if (err) {
820 debugf0("%s() failed to add sysfs attribs\n", __func__);
821 goto err_out;
822 }
823
824
825
826
827 err = sysfs_create_link(edac_kobj,
828 &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK);
829 if (err) {
830 debugf0("%s() sysfs_create_link() returned err= %d\n",
831 __func__, err);
832 goto err_remove_main_attribs;
833 }
834
835
836
837
838
839 err = edac_device_create_instances(edac_dev);
840 if (err) {
841 debugf0("%s() edac_device_create_instances() "
842 "returned err= %d\n", __func__, err);
843 goto err_remove_link;
844 }
845
846
847 debugf4("%s() create-instances done, idx=%d\n",
848 __func__, edac_dev->dev_idx);
849
850 return 0;
851
852
853err_remove_link:
854
855 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
856
857err_remove_main_attribs:
858 edac_device_remove_main_sysfs_attributes(edac_dev);
859
860err_out:
861 return err;
862}
863
864
865
866
867
868
869void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
870{
871 debugf0("%s()\n", __func__);
872
873
874 edac_device_remove_main_sysfs_attributes(edac_dev);
875
876
877 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
878
879
880 edac_device_delete_instances(edac_dev);
881}
882