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_device.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 edac_dbg(4, "control index=%d\n", 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 edac_dbg(1, "\n");
237
238
239 edac_subsys = edac_get_sysfs_subsys();
240
241
242 edac_dev->edac_subsys = edac_subsys;
243
244
245 memset(&edac_dev->kobj, 0, sizeof(struct kobject));
246
247
248
249
250 edac_dev->owner = THIS_MODULE;
251
252 if (!try_module_get(edac_dev->owner)) {
253 err = -ENODEV;
254 goto err_out;
255 }
256
257
258 err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
259 &edac_subsys->dev_root->kobj,
260 "%s", edac_dev->name);
261 if (err) {
262 edac_dbg(1, "Failed to register '.../edac/%s'\n",
263 edac_dev->name);
264 goto err_kobj_reg;
265 }
266 kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
267
268
269
270
271
272 edac_dbg(4, "Registered '.../edac/%s' kobject\n", edac_dev->name);
273
274 return 0;
275
276
277err_kobj_reg:
278 kobject_put(&edac_dev->kobj);
279 module_put(edac_dev->owner);
280
281err_out:
282 return err;
283}
284
285
286
287
288
289void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
290{
291 edac_dbg(0, "\n");
292 edac_dbg(4, "name of kobject is: %s\n", kobject_name(&dev->kobj));
293
294
295
296
297
298
299
300
301 kobject_put(&dev->kobj);
302}
303
304
305
306
307
308
309static ssize_t instance_ue_count_show(struct edac_device_instance *instance,
310 char *data)
311{
312 return sprintf(data, "%u\n", instance->counters.ue_count);
313}
314
315static ssize_t instance_ce_count_show(struct edac_device_instance *instance,
316 char *data)
317{
318 return sprintf(data, "%u\n", instance->counters.ce_count);
319}
320
321#define to_instance(k) container_of(k, struct edac_device_instance, kobj)
322#define to_instance_attr(a) container_of(a,struct instance_attribute,attr)
323
324
325static void edac_device_ctrl_instance_release(struct kobject *kobj)
326{
327 struct edac_device_instance *instance;
328
329 edac_dbg(1, "\n");
330
331
332
333
334 instance = to_instance(kobj);
335 kobject_put(&instance->ctl->kobj);
336}
337
338
339struct instance_attribute {
340 struct attribute attr;
341 ssize_t(*show) (struct edac_device_instance *, char *);
342 ssize_t(*store) (struct edac_device_instance *, const char *, size_t);
343};
344
345
346static ssize_t edac_dev_instance_show(struct kobject *kobj,
347 struct attribute *attr, char *buffer)
348{
349 struct edac_device_instance *instance = to_instance(kobj);
350 struct instance_attribute *instance_attr = to_instance_attr(attr);
351
352 if (instance_attr->show)
353 return instance_attr->show(instance, buffer);
354 return -EIO;
355}
356
357
358static ssize_t edac_dev_instance_store(struct kobject *kobj,
359 struct attribute *attr,
360 const char *buffer, size_t count)
361{
362 struct edac_device_instance *instance = to_instance(kobj);
363 struct instance_attribute *instance_attr = to_instance_attr(attr);
364
365 if (instance_attr->store)
366 return instance_attr->store(instance, buffer, count);
367 return -EIO;
368}
369
370
371static const struct sysfs_ops device_instance_ops = {
372 .show = edac_dev_instance_show,
373 .store = edac_dev_instance_store
374};
375
376#define INSTANCE_ATTR(_name,_mode,_show,_store) \
377static struct instance_attribute attr_instance_##_name = { \
378 .attr = {.name = __stringify(_name), .mode = _mode }, \
379 .show = _show, \
380 .store = _store, \
381};
382
383
384
385
386
387
388INSTANCE_ATTR(ce_count, S_IRUGO, instance_ce_count_show, NULL);
389INSTANCE_ATTR(ue_count, S_IRUGO, instance_ue_count_show, NULL);
390
391
392static struct instance_attribute *device_instance_attr[] = {
393 &attr_instance_ce_count,
394 &attr_instance_ue_count,
395 NULL,
396};
397
398
399static struct kobj_type ktype_instance_ctrl = {
400 .release = edac_device_ctrl_instance_release,
401 .sysfs_ops = &device_instance_ops,
402 .default_attrs = (struct attribute **)device_instance_attr,
403};
404
405
406
407#define to_block(k) container_of(k, struct edac_device_block, kobj)
408#define to_block_attr(a) \
409 container_of(a, struct edac_dev_sysfs_block_attribute, attr)
410
411
412
413
414static ssize_t block_ue_count_show(struct kobject *kobj,
415 struct attribute *attr, char *data)
416{
417 struct edac_device_block *block = to_block(kobj);
418
419 return sprintf(data, "%u\n", block->counters.ue_count);
420}
421
422static ssize_t block_ce_count_show(struct kobject *kobj,
423 struct attribute *attr, char *data)
424{
425 struct edac_device_block *block = to_block(kobj);
426
427 return sprintf(data, "%u\n", block->counters.ce_count);
428}
429
430
431static void edac_device_ctrl_block_release(struct kobject *kobj)
432{
433 struct edac_device_block *block;
434
435 edac_dbg(1, "\n");
436
437
438 block = to_block(kobj);
439
440
441
442
443 kobject_put(&block->instance->ctl->kobj);
444}
445
446
447
448static ssize_t edac_dev_block_show(struct kobject *kobj,
449 struct attribute *attr, char *buffer)
450{
451 struct edac_dev_sysfs_block_attribute *block_attr =
452 to_block_attr(attr);
453
454 if (block_attr->show)
455 return block_attr->show(kobj, attr, buffer);
456 return -EIO;
457}
458
459
460static ssize_t edac_dev_block_store(struct kobject *kobj,
461 struct attribute *attr,
462 const char *buffer, size_t count)
463{
464 struct edac_dev_sysfs_block_attribute *block_attr;
465
466 block_attr = to_block_attr(attr);
467
468 if (block_attr->store)
469 return block_attr->store(kobj, attr, buffer, count);
470 return -EIO;
471}
472
473
474static const struct sysfs_ops device_block_ops = {
475 .show = edac_dev_block_show,
476 .store = edac_dev_block_store
477};
478
479#define BLOCK_ATTR(_name,_mode,_show,_store) \
480static struct edac_dev_sysfs_block_attribute attr_block_##_name = { \
481 .attr = {.name = __stringify(_name), .mode = _mode }, \
482 .show = _show, \
483 .store = _store, \
484};
485
486BLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);
487BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);
488
489
490static struct edac_dev_sysfs_block_attribute *device_block_attr[] = {
491 &attr_block_ce_count,
492 &attr_block_ue_count,
493 NULL,
494};
495
496
497static struct kobj_type ktype_block_ctrl = {
498 .release = edac_device_ctrl_block_release,
499 .sysfs_ops = &device_block_ops,
500 .default_attrs = (struct attribute **)device_block_attr,
501};
502
503
504
505
506
507
508static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
509 struct edac_device_instance *instance,
510 struct edac_device_block *block)
511{
512 int i;
513 int err;
514 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
515 struct kobject *main_kobj;
516
517 edac_dbg(4, "Instance '%s' inst_p=%p block '%s' block_p=%p\n",
518 instance->name, instance, block->name, block);
519 edac_dbg(4, "block kobj=%p block kobj->parent=%p\n",
520 &block->kobj, &block->kobj.parent);
521
522
523 memset(&block->kobj, 0, sizeof(struct kobject));
524
525
526
527
528 main_kobj = kobject_get(&edac_dev->kobj);
529 if (!main_kobj) {
530 err = -ENODEV;
531 goto err_out;
532 }
533
534
535 err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
536 &instance->kobj,
537 "%s", block->name);
538 if (err) {
539 edac_dbg(1, "Failed to register instance '%s'\n", block->name);
540 kobject_put(main_kobj);
541 err = -ENODEV;
542 goto err_out;
543 }
544
545
546
547
548 sysfs_attrib = block->block_attributes;
549 if (sysfs_attrib && block->nr_attribs) {
550 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
551
552 edac_dbg(4, "creating block attrib='%s' attrib->%p to kobj=%p\n",
553 sysfs_attrib->attr.name,
554 sysfs_attrib, &block->kobj);
555
556
557 err = sysfs_create_file(&block->kobj,
558 &sysfs_attrib->attr);
559 if (err)
560 goto err_on_attrib;
561 }
562 }
563 kobject_uevent(&block->kobj, KOBJ_ADD);
564
565 return 0;
566
567
568err_on_attrib:
569 kobject_put(&block->kobj);
570
571err_out:
572 return err;
573}
574
575
576
577
578static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
579 struct edac_device_block *block)
580{
581 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
582 int i;
583
584
585
586
587 sysfs_attrib = block->block_attributes;
588 if (sysfs_attrib && block->nr_attribs) {
589 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
590
591
592 sysfs_remove_file(&block->kobj,
593 (struct attribute *) sysfs_attrib);
594 }
595 }
596
597
598
599
600 kobject_put(&block->kobj);
601}
602
603
604
605
606
607
608
609static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
610 int idx)
611{
612 int i, j;
613 int err;
614 struct edac_device_instance *instance;
615 struct kobject *main_kobj;
616
617 instance = &edac_dev->instances[idx];
618
619
620 memset(&instance->kobj, 0, sizeof(struct kobject));
621
622 instance->ctl = edac_dev;
623
624
625
626
627 main_kobj = kobject_get(&edac_dev->kobj);
628 if (!main_kobj) {
629 err = -ENODEV;
630 goto err_out;
631 }
632
633
634 err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
635 &edac_dev->kobj, "%s", instance->name);
636 if (err != 0) {
637 edac_dbg(2, "Failed to register instance '%s'\n",
638 instance->name);
639 kobject_put(main_kobj);
640 goto err_out;
641 }
642
643 edac_dbg(4, "now register '%d' blocks for instance %d\n",
644 instance->nr_blocks, idx);
645
646
647 for (i = 0; i < instance->nr_blocks; i++) {
648 err = edac_device_create_block(edac_dev, instance,
649 &instance->blocks[i]);
650 if (err) {
651
652 for (j = 0; j < i; j++)
653 edac_device_delete_block(edac_dev,
654 &instance->blocks[j]);
655 goto err_release_instance_kobj;
656 }
657 }
658 kobject_uevent(&instance->kobj, KOBJ_ADD);
659
660 edac_dbg(4, "Registered instance %d '%s' kobject\n",
661 idx, instance->name);
662
663 return 0;
664
665
666err_release_instance_kobj:
667 kobject_put(&instance->kobj);
668
669err_out:
670 return err;
671}
672
673
674
675
676
677static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
678 int idx)
679{
680 struct edac_device_instance *instance;
681 int i;
682
683 instance = &edac_dev->instances[idx];
684
685
686 for (i = 0; i < instance->nr_blocks; i++)
687 edac_device_delete_block(edac_dev, &instance->blocks[i]);
688
689
690
691
692 kobject_put(&instance->kobj);
693}
694
695
696
697
698
699
700static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
701{
702 int i, j;
703 int err;
704
705 edac_dbg(0, "\n");
706
707
708 for (i = 0; i < edac_dev->nr_instances; i++) {
709 err = edac_device_create_instance(edac_dev, i);
710 if (err) {
711
712 for (j = 0; j < i; j++)
713 edac_device_delete_instance(edac_dev, j);
714 return err;
715 }
716 }
717
718 return 0;
719}
720
721
722
723
724
725static void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev)
726{
727 int i;
728
729
730 for (i = 0; i < edac_dev->nr_instances; i++)
731 edac_device_delete_instance(edac_dev, i);
732}
733
734
735
736
737
738
739
740static int edac_device_add_main_sysfs_attributes(
741 struct edac_device_ctl_info *edac_dev)
742{
743 struct edac_dev_sysfs_attribute *sysfs_attrib;
744 int err = 0;
745
746 sysfs_attrib = edac_dev->sysfs_attributes;
747 if (sysfs_attrib) {
748
749
750
751 while (sysfs_attrib->attr.name != NULL) {
752 err = sysfs_create_file(&edac_dev->kobj,
753 (struct attribute*) sysfs_attrib);
754 if (err)
755 goto err_out;
756
757 sysfs_attrib++;
758 }
759 }
760
761err_out:
762 return err;
763}
764
765
766
767
768
769static void edac_device_remove_main_sysfs_attributes(
770 struct edac_device_ctl_info *edac_dev)
771{
772 struct edac_dev_sysfs_attribute *sysfs_attrib;
773
774
775
776
777
778 sysfs_attrib = edac_dev->sysfs_attributes;
779 if (sysfs_attrib) {
780 while (sysfs_attrib->attr.name != NULL) {
781 sysfs_remove_file(&edac_dev->kobj,
782 (struct attribute *) sysfs_attrib);
783 sysfs_attrib++;
784 }
785 }
786}
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
803{
804 int err;
805 struct kobject *edac_kobj = &edac_dev->kobj;
806
807 edac_dbg(0, "idx=%d\n", edac_dev->dev_idx);
808
809
810 err = edac_device_add_main_sysfs_attributes(edac_dev);
811 if (err) {
812 edac_dbg(0, "failed to add sysfs attribs\n");
813 goto err_out;
814 }
815
816
817
818
819 err = sysfs_create_link(edac_kobj,
820 &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK);
821 if (err) {
822 edac_dbg(0, "sysfs_create_link() returned err= %d\n", err);
823 goto err_remove_main_attribs;
824 }
825
826
827
828
829
830 err = edac_device_create_instances(edac_dev);
831 if (err) {
832 edac_dbg(0, "edac_device_create_instances() returned err= %d\n",
833 err);
834 goto err_remove_link;
835 }
836
837
838 edac_dbg(4, "create-instances done, idx=%d\n", edac_dev->dev_idx);
839
840 return 0;
841
842
843err_remove_link:
844
845 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
846
847err_remove_main_attribs:
848 edac_device_remove_main_sysfs_attributes(edac_dev);
849
850err_out:
851 return err;
852}
853
854
855
856
857
858
859void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
860{
861 edac_dbg(0, "\n");
862
863
864 edac_device_remove_main_sysfs_attributes(edac_dev);
865
866
867 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
868
869
870 edac_device_delete_instances(edac_dev);
871}
872