0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/ctype.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/edac.h>
0017
0018 #include "edac_device.h"
0019 #include "edac_module.h"
0020
0021 #define EDAC_DEVICE_SYMLINK "device"
0022
0023 #define to_edacdev(k) container_of(k, struct edac_device_ctl_info, kobj)
0024 #define to_edacdev_attr(a) container_of(a, struct edacdev_attribute, attr)
0025
0026
0027
0028
0029
0030
0031
0032 static ssize_t edac_device_ctl_log_ue_show(struct edac_device_ctl_info
0033 *ctl_info, char *data)
0034 {
0035 return sprintf(data, "%u\n", ctl_info->log_ue);
0036 }
0037
0038 static ssize_t edac_device_ctl_log_ue_store(struct edac_device_ctl_info
0039 *ctl_info, const char *data,
0040 size_t count)
0041 {
0042
0043 ctl_info->log_ue = (simple_strtoul(data, NULL, 0) != 0);
0044
0045 return count;
0046 }
0047
0048
0049 static ssize_t edac_device_ctl_log_ce_show(struct edac_device_ctl_info
0050 *ctl_info, char *data)
0051 {
0052 return sprintf(data, "%u\n", ctl_info->log_ce);
0053 }
0054
0055 static ssize_t edac_device_ctl_log_ce_store(struct edac_device_ctl_info
0056 *ctl_info, const char *data,
0057 size_t count)
0058 {
0059
0060 ctl_info->log_ce = (simple_strtoul(data, NULL, 0) != 0);
0061
0062 return count;
0063 }
0064
0065
0066 static ssize_t edac_device_ctl_panic_on_ue_show(struct edac_device_ctl_info
0067 *ctl_info, char *data)
0068 {
0069 return sprintf(data, "%u\n", ctl_info->panic_on_ue);
0070 }
0071
0072 static ssize_t edac_device_ctl_panic_on_ue_store(struct edac_device_ctl_info
0073 *ctl_info, const char *data,
0074 size_t count)
0075 {
0076
0077 ctl_info->panic_on_ue = (simple_strtoul(data, NULL, 0) != 0);
0078
0079 return count;
0080 }
0081
0082
0083 static ssize_t edac_device_ctl_poll_msec_show(struct edac_device_ctl_info
0084 *ctl_info, char *data)
0085 {
0086 return sprintf(data, "%u\n", ctl_info->poll_msec);
0087 }
0088
0089 static ssize_t edac_device_ctl_poll_msec_store(struct edac_device_ctl_info
0090 *ctl_info, const char *data,
0091 size_t count)
0092 {
0093 unsigned long value;
0094
0095
0096
0097
0098
0099
0100 value = simple_strtoul(data, NULL, 0);
0101 edac_device_reset_delay_period(ctl_info, value);
0102
0103 return count;
0104 }
0105
0106
0107 struct ctl_info_attribute {
0108 struct attribute attr;
0109 ssize_t(*show) (struct edac_device_ctl_info *, char *);
0110 ssize_t(*store) (struct edac_device_ctl_info *, const char *, size_t);
0111 };
0112
0113 #define to_ctl_info(k) container_of(k, struct edac_device_ctl_info, kobj)
0114 #define to_ctl_info_attr(a) container_of(a,struct ctl_info_attribute,attr)
0115
0116
0117 static ssize_t edac_dev_ctl_info_show(struct kobject *kobj,
0118 struct attribute *attr, char *buffer)
0119 {
0120 struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
0121 struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
0122
0123 if (ctl_info_attr->show)
0124 return ctl_info_attr->show(edac_dev, buffer);
0125 return -EIO;
0126 }
0127
0128
0129 static ssize_t edac_dev_ctl_info_store(struct kobject *kobj,
0130 struct attribute *attr,
0131 const char *buffer, size_t count)
0132 {
0133 struct edac_device_ctl_info *edac_dev = to_ctl_info(kobj);
0134 struct ctl_info_attribute *ctl_info_attr = to_ctl_info_attr(attr);
0135
0136 if (ctl_info_attr->store)
0137 return ctl_info_attr->store(edac_dev, buffer, count);
0138 return -EIO;
0139 }
0140
0141
0142 static const struct sysfs_ops device_ctl_info_ops = {
0143 .show = edac_dev_ctl_info_show,
0144 .store = edac_dev_ctl_info_store
0145 };
0146
0147 #define CTL_INFO_ATTR(_name,_mode,_show,_store) \
0148 static struct ctl_info_attribute attr_ctl_info_##_name = { \
0149 .attr = {.name = __stringify(_name), .mode = _mode }, \
0150 .show = _show, \
0151 .store = _store, \
0152 };
0153
0154
0155 CTL_INFO_ATTR(log_ue, S_IRUGO | S_IWUSR,
0156 edac_device_ctl_log_ue_show, edac_device_ctl_log_ue_store);
0157 CTL_INFO_ATTR(log_ce, S_IRUGO | S_IWUSR,
0158 edac_device_ctl_log_ce_show, edac_device_ctl_log_ce_store);
0159 CTL_INFO_ATTR(panic_on_ue, S_IRUGO | S_IWUSR,
0160 edac_device_ctl_panic_on_ue_show,
0161 edac_device_ctl_panic_on_ue_store);
0162 CTL_INFO_ATTR(poll_msec, S_IRUGO | S_IWUSR,
0163 edac_device_ctl_poll_msec_show, edac_device_ctl_poll_msec_store);
0164
0165
0166 static struct attribute *device_ctrl_attrs[] = {
0167 &attr_ctl_info_panic_on_ue.attr,
0168 &attr_ctl_info_log_ue.attr,
0169 &attr_ctl_info_log_ce.attr,
0170 &attr_ctl_info_poll_msec.attr,
0171 NULL,
0172 };
0173 ATTRIBUTE_GROUPS(device_ctrl);
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 static void edac_device_ctrl_master_release(struct kobject *kobj)
0203 {
0204 struct edac_device_ctl_info *edac_dev = to_edacdev(kobj);
0205
0206 edac_dbg(4, "control index=%d\n", edac_dev->dev_idx);
0207
0208
0209 module_put(edac_dev->owner);
0210
0211 __edac_device_free_ctl_info(edac_dev);
0212 }
0213
0214
0215 static struct kobj_type ktype_device_ctrl = {
0216 .release = edac_device_ctrl_master_release,
0217 .sysfs_ops = &device_ctl_info_ops,
0218 .default_groups = device_ctrl_groups,
0219 };
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
0230 {
0231 struct bus_type *edac_subsys;
0232 int err;
0233
0234 edac_dbg(1, "\n");
0235
0236
0237 edac_subsys = edac_get_sysfs_subsys();
0238
0239
0240 edac_dev->edac_subsys = edac_subsys;
0241
0242
0243 memset(&edac_dev->kobj, 0, sizeof(struct kobject));
0244
0245
0246
0247
0248 edac_dev->owner = THIS_MODULE;
0249
0250 if (!try_module_get(edac_dev->owner)) {
0251 err = -ENODEV;
0252 goto err_out;
0253 }
0254
0255
0256 err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
0257 &edac_subsys->dev_root->kobj,
0258 "%s", edac_dev->name);
0259 if (err) {
0260 edac_dbg(1, "Failed to register '.../edac/%s'\n",
0261 edac_dev->name);
0262 goto err_kobj_reg;
0263 }
0264 kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
0265
0266
0267
0268
0269
0270 edac_dbg(4, "Registered '.../edac/%s' kobject\n", edac_dev->name);
0271
0272 return 0;
0273
0274
0275 err_kobj_reg:
0276 kobject_put(&edac_dev->kobj);
0277 module_put(edac_dev->owner);
0278
0279 err_out:
0280 return err;
0281 }
0282
0283
0284
0285
0286
0287 void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
0288 {
0289 edac_dbg(0, "\n");
0290 edac_dbg(4, "name of kobject is: %s\n", kobject_name(&dev->kobj));
0291
0292
0293
0294
0295
0296
0297
0298
0299 kobject_put(&dev->kobj);
0300 }
0301
0302
0303
0304
0305
0306
0307 static ssize_t instance_ue_count_show(struct edac_device_instance *instance,
0308 char *data)
0309 {
0310 return sprintf(data, "%u\n", instance->counters.ue_count);
0311 }
0312
0313 static ssize_t instance_ce_count_show(struct edac_device_instance *instance,
0314 char *data)
0315 {
0316 return sprintf(data, "%u\n", instance->counters.ce_count);
0317 }
0318
0319 #define to_instance(k) container_of(k, struct edac_device_instance, kobj)
0320 #define to_instance_attr(a) container_of(a,struct instance_attribute,attr)
0321
0322
0323 static void edac_device_ctrl_instance_release(struct kobject *kobj)
0324 {
0325 struct edac_device_instance *instance;
0326
0327 edac_dbg(1, "\n");
0328
0329
0330
0331
0332 instance = to_instance(kobj);
0333 kobject_put(&instance->ctl->kobj);
0334 }
0335
0336
0337 struct instance_attribute {
0338 struct attribute attr;
0339 ssize_t(*show) (struct edac_device_instance *, char *);
0340 ssize_t(*store) (struct edac_device_instance *, const char *, size_t);
0341 };
0342
0343
0344 static ssize_t edac_dev_instance_show(struct kobject *kobj,
0345 struct attribute *attr, char *buffer)
0346 {
0347 struct edac_device_instance *instance = to_instance(kobj);
0348 struct instance_attribute *instance_attr = to_instance_attr(attr);
0349
0350 if (instance_attr->show)
0351 return instance_attr->show(instance, buffer);
0352 return -EIO;
0353 }
0354
0355
0356 static ssize_t edac_dev_instance_store(struct kobject *kobj,
0357 struct attribute *attr,
0358 const char *buffer, size_t count)
0359 {
0360 struct edac_device_instance *instance = to_instance(kobj);
0361 struct instance_attribute *instance_attr = to_instance_attr(attr);
0362
0363 if (instance_attr->store)
0364 return instance_attr->store(instance, buffer, count);
0365 return -EIO;
0366 }
0367
0368
0369 static const struct sysfs_ops device_instance_ops = {
0370 .show = edac_dev_instance_show,
0371 .store = edac_dev_instance_store
0372 };
0373
0374 #define INSTANCE_ATTR(_name,_mode,_show,_store) \
0375 static struct instance_attribute attr_instance_##_name = { \
0376 .attr = {.name = __stringify(_name), .mode = _mode }, \
0377 .show = _show, \
0378 .store = _store, \
0379 };
0380
0381
0382
0383
0384
0385
0386 INSTANCE_ATTR(ce_count, S_IRUGO, instance_ce_count_show, NULL);
0387 INSTANCE_ATTR(ue_count, S_IRUGO, instance_ue_count_show, NULL);
0388
0389
0390 static struct attribute *device_instance_attrs[] = {
0391 &attr_instance_ce_count.attr,
0392 &attr_instance_ue_count.attr,
0393 NULL,
0394 };
0395 ATTRIBUTE_GROUPS(device_instance);
0396
0397
0398 static struct kobj_type ktype_instance_ctrl = {
0399 .release = edac_device_ctrl_instance_release,
0400 .sysfs_ops = &device_instance_ops,
0401 .default_groups = device_instance_groups,
0402 };
0403
0404
0405
0406 #define to_block(k) container_of(k, struct edac_device_block, kobj)
0407 #define to_block_attr(a) \
0408 container_of(a, struct edac_dev_sysfs_block_attribute, attr)
0409
0410
0411
0412
0413 static ssize_t block_ue_count_show(struct kobject *kobj,
0414 struct attribute *attr, char *data)
0415 {
0416 struct edac_device_block *block = to_block(kobj);
0417
0418 return sprintf(data, "%u\n", block->counters.ue_count);
0419 }
0420
0421 static ssize_t block_ce_count_show(struct kobject *kobj,
0422 struct attribute *attr, char *data)
0423 {
0424 struct edac_device_block *block = to_block(kobj);
0425
0426 return sprintf(data, "%u\n", block->counters.ce_count);
0427 }
0428
0429
0430 static void edac_device_ctrl_block_release(struct kobject *kobj)
0431 {
0432 struct edac_device_block *block;
0433
0434 edac_dbg(1, "\n");
0435
0436
0437 block = to_block(kobj);
0438
0439
0440
0441
0442 kobject_put(&block->instance->ctl->kobj);
0443 }
0444
0445
0446
0447 static ssize_t edac_dev_block_show(struct kobject *kobj,
0448 struct attribute *attr, char *buffer)
0449 {
0450 struct edac_dev_sysfs_block_attribute *block_attr =
0451 to_block_attr(attr);
0452
0453 if (block_attr->show)
0454 return block_attr->show(kobj, attr, buffer);
0455 return -EIO;
0456 }
0457
0458
0459 static ssize_t edac_dev_block_store(struct kobject *kobj,
0460 struct attribute *attr,
0461 const char *buffer, size_t count)
0462 {
0463 struct edac_dev_sysfs_block_attribute *block_attr;
0464
0465 block_attr = to_block_attr(attr);
0466
0467 if (block_attr->store)
0468 return block_attr->store(kobj, attr, buffer, count);
0469 return -EIO;
0470 }
0471
0472
0473 static const struct sysfs_ops device_block_ops = {
0474 .show = edac_dev_block_show,
0475 .store = edac_dev_block_store
0476 };
0477
0478 #define BLOCK_ATTR(_name,_mode,_show,_store) \
0479 static struct edac_dev_sysfs_block_attribute attr_block_##_name = { \
0480 .attr = {.name = __stringify(_name), .mode = _mode }, \
0481 .show = _show, \
0482 .store = _store, \
0483 };
0484
0485 BLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);
0486 BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);
0487
0488
0489 static struct attribute *device_block_attrs[] = {
0490 &attr_block_ce_count.attr,
0491 &attr_block_ue_count.attr,
0492 NULL,
0493 };
0494 ATTRIBUTE_GROUPS(device_block);
0495
0496
0497 static struct kobj_type ktype_block_ctrl = {
0498 .release = edac_device_ctrl_block_release,
0499 .sysfs_ops = &device_block_ops,
0500 .default_groups = device_block_groups,
0501 };
0502
0503
0504
0505
0506
0507
0508 static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
0509 struct edac_device_instance *instance,
0510 struct edac_device_block *block)
0511 {
0512 int i;
0513 int err;
0514 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
0515 struct kobject *main_kobj;
0516
0517 edac_dbg(4, "Instance '%s' inst_p=%p block '%s' block_p=%p\n",
0518 instance->name, instance, block->name, block);
0519 edac_dbg(4, "block kobj=%p block kobj->parent=%p\n",
0520 &block->kobj, &block->kobj.parent);
0521
0522
0523 memset(&block->kobj, 0, sizeof(struct kobject));
0524
0525
0526
0527
0528 main_kobj = kobject_get(&edac_dev->kobj);
0529 if (!main_kobj) {
0530 err = -ENODEV;
0531 goto err_out;
0532 }
0533
0534
0535 err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
0536 &instance->kobj,
0537 "%s", block->name);
0538 if (err) {
0539 edac_dbg(1, "Failed to register instance '%s'\n", block->name);
0540 kobject_put(main_kobj);
0541 err = -ENODEV;
0542 goto err_out;
0543 }
0544
0545
0546
0547
0548 sysfs_attrib = block->block_attributes;
0549 if (sysfs_attrib && block->nr_attribs) {
0550 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
0551
0552 edac_dbg(4, "creating block attrib='%s' attrib->%p to kobj=%p\n",
0553 sysfs_attrib->attr.name,
0554 sysfs_attrib, &block->kobj);
0555
0556
0557 err = sysfs_create_file(&block->kobj,
0558 &sysfs_attrib->attr);
0559 if (err)
0560 goto err_on_attrib;
0561 }
0562 }
0563 kobject_uevent(&block->kobj, KOBJ_ADD);
0564
0565 return 0;
0566
0567
0568 err_on_attrib:
0569 kobject_put(&block->kobj);
0570
0571 err_out:
0572 return err;
0573 }
0574
0575
0576
0577
0578 static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
0579 struct edac_device_block *block)
0580 {
0581 struct edac_dev_sysfs_block_attribute *sysfs_attrib;
0582 int i;
0583
0584
0585
0586
0587 sysfs_attrib = block->block_attributes;
0588 if (sysfs_attrib && block->nr_attribs) {
0589 for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) {
0590
0591
0592 sysfs_remove_file(&block->kobj,
0593 (struct attribute *) sysfs_attrib);
0594 }
0595 }
0596
0597
0598
0599
0600 kobject_put(&block->kobj);
0601 }
0602
0603
0604
0605
0606
0607
0608
0609 static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
0610 int idx)
0611 {
0612 int i, j;
0613 int err;
0614 struct edac_device_instance *instance;
0615 struct kobject *main_kobj;
0616
0617 instance = &edac_dev->instances[idx];
0618
0619
0620 memset(&instance->kobj, 0, sizeof(struct kobject));
0621
0622 instance->ctl = edac_dev;
0623
0624
0625
0626
0627 main_kobj = kobject_get(&edac_dev->kobj);
0628 if (!main_kobj) {
0629 err = -ENODEV;
0630 goto err_out;
0631 }
0632
0633
0634 err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
0635 &edac_dev->kobj, "%s", instance->name);
0636 if (err != 0) {
0637 edac_dbg(2, "Failed to register instance '%s'\n",
0638 instance->name);
0639 kobject_put(main_kobj);
0640 goto err_out;
0641 }
0642
0643 edac_dbg(4, "now register '%d' blocks for instance %d\n",
0644 instance->nr_blocks, idx);
0645
0646
0647 for (i = 0; i < instance->nr_blocks; i++) {
0648 err = edac_device_create_block(edac_dev, instance,
0649 &instance->blocks[i]);
0650 if (err) {
0651
0652 for (j = 0; j < i; j++)
0653 edac_device_delete_block(edac_dev,
0654 &instance->blocks[j]);
0655 goto err_release_instance_kobj;
0656 }
0657 }
0658 kobject_uevent(&instance->kobj, KOBJ_ADD);
0659
0660 edac_dbg(4, "Registered instance %d '%s' kobject\n",
0661 idx, instance->name);
0662
0663 return 0;
0664
0665
0666 err_release_instance_kobj:
0667 kobject_put(&instance->kobj);
0668
0669 err_out:
0670 return err;
0671 }
0672
0673
0674
0675
0676
0677 static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
0678 int idx)
0679 {
0680 struct edac_device_instance *instance;
0681 int i;
0682
0683 instance = &edac_dev->instances[idx];
0684
0685
0686 for (i = 0; i < instance->nr_blocks; i++)
0687 edac_device_delete_block(edac_dev, &instance->blocks[i]);
0688
0689
0690
0691
0692 kobject_put(&instance->kobj);
0693 }
0694
0695
0696
0697
0698
0699
0700 static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev)
0701 {
0702 int i, j;
0703 int err;
0704
0705 edac_dbg(0, "\n");
0706
0707
0708 for (i = 0; i < edac_dev->nr_instances; i++) {
0709 err = edac_device_create_instance(edac_dev, i);
0710 if (err) {
0711
0712 for (j = 0; j < i; j++)
0713 edac_device_delete_instance(edac_dev, j);
0714 return err;
0715 }
0716 }
0717
0718 return 0;
0719 }
0720
0721
0722
0723
0724
0725 static void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev)
0726 {
0727 int i;
0728
0729
0730 for (i = 0; i < edac_dev->nr_instances; i++)
0731 edac_device_delete_instance(edac_dev, i);
0732 }
0733
0734
0735
0736
0737
0738
0739
0740 static int edac_device_add_main_sysfs_attributes(
0741 struct edac_device_ctl_info *edac_dev)
0742 {
0743 struct edac_dev_sysfs_attribute *sysfs_attrib;
0744 int err = 0;
0745
0746 sysfs_attrib = edac_dev->sysfs_attributes;
0747 if (sysfs_attrib) {
0748
0749
0750
0751 while (sysfs_attrib->attr.name != NULL) {
0752 err = sysfs_create_file(&edac_dev->kobj,
0753 (struct attribute*) sysfs_attrib);
0754 if (err)
0755 goto err_out;
0756
0757 sysfs_attrib++;
0758 }
0759 }
0760
0761 err_out:
0762 return err;
0763 }
0764
0765
0766
0767
0768
0769 static void edac_device_remove_main_sysfs_attributes(
0770 struct edac_device_ctl_info *edac_dev)
0771 {
0772 struct edac_dev_sysfs_attribute *sysfs_attrib;
0773
0774
0775
0776
0777
0778 sysfs_attrib = edac_dev->sysfs_attributes;
0779 if (sysfs_attrib) {
0780 while (sysfs_attrib->attr.name != NULL) {
0781 sysfs_remove_file(&edac_dev->kobj,
0782 (struct attribute *) sysfs_attrib);
0783 sysfs_attrib++;
0784 }
0785 }
0786 }
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802 int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev)
0803 {
0804 int err;
0805 struct kobject *edac_kobj = &edac_dev->kobj;
0806
0807 edac_dbg(0, "idx=%d\n", edac_dev->dev_idx);
0808
0809
0810 err = edac_device_add_main_sysfs_attributes(edac_dev);
0811 if (err) {
0812 edac_dbg(0, "failed to add sysfs attribs\n");
0813 goto err_out;
0814 }
0815
0816
0817
0818
0819 err = sysfs_create_link(edac_kobj,
0820 &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK);
0821 if (err) {
0822 edac_dbg(0, "sysfs_create_link() returned err= %d\n", err);
0823 goto err_remove_main_attribs;
0824 }
0825
0826
0827
0828
0829
0830 err = edac_device_create_instances(edac_dev);
0831 if (err) {
0832 edac_dbg(0, "edac_device_create_instances() returned err= %d\n",
0833 err);
0834 goto err_remove_link;
0835 }
0836
0837
0838 edac_dbg(4, "create-instances done, idx=%d\n", edac_dev->dev_idx);
0839
0840 return 0;
0841
0842
0843 err_remove_link:
0844
0845 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
0846
0847 err_remove_main_attribs:
0848 edac_device_remove_main_sysfs_attributes(edac_dev);
0849
0850 err_out:
0851 return err;
0852 }
0853
0854
0855
0856
0857
0858
0859 void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev)
0860 {
0861 edac_dbg(0, "\n");
0862
0863
0864 edac_device_remove_main_sysfs_attributes(edac_dev);
0865
0866
0867 sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);
0868
0869
0870 edac_device_delete_instances(edac_dev);
0871 }