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