.. | .. |
---|
131 | 131 | |
---|
132 | 132 | struct dev_ch_attribute { |
---|
133 | 133 | struct device_attribute attr; |
---|
134 | | - int channel; |
---|
| 134 | + unsigned int channel; |
---|
135 | 135 | }; |
---|
136 | 136 | |
---|
137 | 137 | #define DEVICE_CHANNEL(_name, _mode, _show, _store, _var) \ |
---|
.. | .. |
---|
200 | 200 | char *data) |
---|
201 | 201 | { |
---|
202 | 202 | struct csrow_info *csrow = to_csrow(dev); |
---|
203 | | - unsigned chan = to_channel(mattr); |
---|
| 203 | + unsigned int chan = to_channel(mattr); |
---|
204 | 204 | struct rank_info *rank = csrow->channels[chan]; |
---|
205 | 205 | |
---|
206 | 206 | /* if field has not been initialized, there is nothing to send */ |
---|
.. | .. |
---|
216 | 216 | const char *data, size_t count) |
---|
217 | 217 | { |
---|
218 | 218 | struct csrow_info *csrow = to_csrow(dev); |
---|
219 | | - unsigned chan = to_channel(mattr); |
---|
| 219 | + unsigned int chan = to_channel(mattr); |
---|
220 | 220 | struct rank_info *rank = csrow->channels[chan]; |
---|
221 | 221 | size_t copy_count = count; |
---|
222 | 222 | |
---|
.. | .. |
---|
240 | 240 | struct device_attribute *mattr, char *data) |
---|
241 | 241 | { |
---|
242 | 242 | struct csrow_info *csrow = to_csrow(dev); |
---|
243 | | - unsigned chan = to_channel(mattr); |
---|
| 243 | + unsigned int chan = to_channel(mattr); |
---|
244 | 244 | struct rank_info *rank = csrow->channels[chan]; |
---|
245 | 245 | |
---|
246 | 246 | return sprintf(data, "%u\n", rank->ce_count); |
---|
.. | .. |
---|
274 | 274 | NULL |
---|
275 | 275 | }; |
---|
276 | 276 | |
---|
277 | | -static void csrow_attr_release(struct device *dev) |
---|
278 | | -{ |
---|
279 | | - struct csrow_info *csrow = container_of(dev, struct csrow_info, dev); |
---|
280 | | - |
---|
281 | | - edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); |
---|
282 | | - kfree(csrow); |
---|
283 | | -} |
---|
284 | | - |
---|
285 | 277 | static const struct device_type csrow_attr_type = { |
---|
286 | 278 | .groups = csrow_attr_groups, |
---|
287 | | - .release = csrow_attr_release, |
---|
288 | 279 | }; |
---|
289 | 280 | |
---|
290 | 281 | /* |
---|
.. | .. |
---|
390 | 381 | NULL |
---|
391 | 382 | }; |
---|
392 | 383 | |
---|
| 384 | +static void csrow_release(struct device *dev) |
---|
| 385 | +{ |
---|
| 386 | + /* |
---|
| 387 | + * Nothing to do, just unregister sysfs here. The mci |
---|
| 388 | + * device owns the data and will also release it. |
---|
| 389 | + */ |
---|
| 390 | +} |
---|
| 391 | + |
---|
393 | 392 | static inline int nr_pages_per_csrow(struct csrow_info *csrow) |
---|
394 | 393 | { |
---|
395 | 394 | int chan, nr_pages = 0; |
---|
.. | .. |
---|
407 | 406 | int err; |
---|
408 | 407 | |
---|
409 | 408 | csrow->dev.type = &csrow_attr_type; |
---|
410 | | - csrow->dev.bus = mci->bus; |
---|
411 | 409 | csrow->dev.groups = csrow_dev_groups; |
---|
| 410 | + csrow->dev.release = csrow_release; |
---|
412 | 411 | device_initialize(&csrow->dev); |
---|
413 | 412 | csrow->dev.parent = &mci->dev; |
---|
414 | 413 | csrow->mci = mci; |
---|
415 | 414 | dev_set_name(&csrow->dev, "csrow%d", index); |
---|
416 | 415 | dev_set_drvdata(&csrow->dev, csrow); |
---|
417 | 416 | |
---|
418 | | - edac_dbg(0, "creating (virtual) csrow node %s\n", |
---|
419 | | - dev_name(&csrow->dev)); |
---|
420 | | - |
---|
421 | 417 | err = device_add(&csrow->dev); |
---|
422 | | - if (err) |
---|
| 418 | + if (err) { |
---|
| 419 | + edac_dbg(1, "failure: create device %s\n", dev_name(&csrow->dev)); |
---|
423 | 420 | put_device(&csrow->dev); |
---|
| 421 | + return err; |
---|
| 422 | + } |
---|
424 | 423 | |
---|
425 | | - return err; |
---|
| 424 | + edac_dbg(0, "device %s created\n", dev_name(&csrow->dev)); |
---|
| 425 | + |
---|
| 426 | + return 0; |
---|
426 | 427 | } |
---|
427 | 428 | |
---|
428 | 429 | /* Create a CSROW object under specifed edac_mc_device */ |
---|
.. | .. |
---|
436 | 437 | if (!nr_pages_per_csrow(csrow)) |
---|
437 | 438 | continue; |
---|
438 | 439 | err = edac_create_csrow_object(mci, mci->csrows[i], i); |
---|
439 | | - if (err < 0) { |
---|
440 | | - edac_dbg(1, |
---|
441 | | - "failure: create csrow objects for csrow %d\n", |
---|
442 | | - i); |
---|
| 440 | + if (err < 0) |
---|
443 | 441 | goto error; |
---|
444 | | - } |
---|
445 | 442 | } |
---|
446 | 443 | return 0; |
---|
447 | 444 | |
---|
448 | 445 | error: |
---|
449 | 446 | for (--i; i >= 0; i--) { |
---|
450 | | - csrow = mci->csrows[i]; |
---|
451 | | - if (!nr_pages_per_csrow(csrow)) |
---|
452 | | - continue; |
---|
453 | | - put_device(&mci->csrows[i]->dev); |
---|
| 447 | + if (device_is_registered(&mci->csrows[i]->dev)) |
---|
| 448 | + device_unregister(&mci->csrows[i]->dev); |
---|
454 | 449 | } |
---|
455 | 450 | |
---|
456 | 451 | return err; |
---|
.. | .. |
---|
459 | 454 | static void edac_delete_csrow_objects(struct mem_ctl_info *mci) |
---|
460 | 455 | { |
---|
461 | 456 | int i; |
---|
462 | | - struct csrow_info *csrow; |
---|
463 | 457 | |
---|
464 | | - for (i = mci->nr_csrows - 1; i >= 0; i--) { |
---|
465 | | - csrow = mci->csrows[i]; |
---|
466 | | - if (!nr_pages_per_csrow(csrow)) |
---|
467 | | - continue; |
---|
468 | | - device_unregister(&mci->csrows[i]->dev); |
---|
| 458 | + for (i = 0; i < mci->nr_csrows; i++) { |
---|
| 459 | + if (device_is_registered(&mci->csrows[i]->dev)) |
---|
| 460 | + device_unregister(&mci->csrows[i]->dev); |
---|
469 | 461 | } |
---|
470 | 462 | } |
---|
| 463 | + |
---|
471 | 464 | #endif |
---|
472 | 465 | |
---|
473 | 466 | /* |
---|
.. | .. |
---|
481 | 474 | struct device_attribute *mattr, char *data) |
---|
482 | 475 | { |
---|
483 | 476 | struct dimm_info *dimm = to_dimm(dev); |
---|
| 477 | + ssize_t count; |
---|
484 | 478 | |
---|
485 | | - return edac_dimm_info_location(dimm, data, PAGE_SIZE); |
---|
| 479 | + count = edac_dimm_info_location(dimm, data, PAGE_SIZE); |
---|
| 480 | + count += scnprintf(data + count, PAGE_SIZE - count, "\n"); |
---|
| 481 | + |
---|
| 482 | + return count; |
---|
486 | 483 | } |
---|
487 | 484 | |
---|
488 | 485 | static ssize_t dimmdev_label_show(struct device *dev, |
---|
.. | .. |
---|
558 | 555 | char *data) |
---|
559 | 556 | { |
---|
560 | 557 | struct dimm_info *dimm = to_dimm(dev); |
---|
561 | | - u32 count; |
---|
562 | | - int off; |
---|
563 | 558 | |
---|
564 | | - off = EDAC_DIMM_OFF(dimm->mci->layers, |
---|
565 | | - dimm->mci->n_layers, |
---|
566 | | - dimm->location[0], |
---|
567 | | - dimm->location[1], |
---|
568 | | - dimm->location[2]); |
---|
569 | | - count = dimm->mci->ce_per_layer[dimm->mci->n_layers-1][off]; |
---|
570 | | - return sprintf(data, "%u\n", count); |
---|
| 559 | + return sprintf(data, "%u\n", dimm->ce_count); |
---|
571 | 560 | } |
---|
572 | 561 | |
---|
573 | 562 | static ssize_t dimmdev_ue_count_show(struct device *dev, |
---|
.. | .. |
---|
575 | 564 | char *data) |
---|
576 | 565 | { |
---|
577 | 566 | struct dimm_info *dimm = to_dimm(dev); |
---|
578 | | - u32 count; |
---|
579 | | - int off; |
---|
580 | 567 | |
---|
581 | | - off = EDAC_DIMM_OFF(dimm->mci->layers, |
---|
582 | | - dimm->mci->n_layers, |
---|
583 | | - dimm->location[0], |
---|
584 | | - dimm->location[1], |
---|
585 | | - dimm->location[2]); |
---|
586 | | - count = dimm->mci->ue_per_layer[dimm->mci->n_layers-1][off]; |
---|
587 | | - return sprintf(data, "%u\n", count); |
---|
| 568 | + return sprintf(data, "%u\n", dimm->ue_count); |
---|
588 | 569 | } |
---|
589 | 570 | |
---|
590 | 571 | /* dimm/rank attribute files */ |
---|
.. | .. |
---|
620 | 601 | NULL |
---|
621 | 602 | }; |
---|
622 | 603 | |
---|
623 | | -static void dimm_attr_release(struct device *dev) |
---|
624 | | -{ |
---|
625 | | - struct dimm_info *dimm = container_of(dev, struct dimm_info, dev); |
---|
626 | | - |
---|
627 | | - edac_dbg(1, "Releasing dimm device %s\n", dev_name(dev)); |
---|
628 | | - kfree(dimm); |
---|
629 | | -} |
---|
630 | | - |
---|
631 | 604 | static const struct device_type dimm_attr_type = { |
---|
632 | 605 | .groups = dimm_attr_groups, |
---|
633 | | - .release = dimm_attr_release, |
---|
634 | 606 | }; |
---|
| 607 | + |
---|
| 608 | +static void dimm_release(struct device *dev) |
---|
| 609 | +{ |
---|
| 610 | + /* |
---|
| 611 | + * Nothing to do, just unregister sysfs here. The mci |
---|
| 612 | + * device owns the data and will also release it. |
---|
| 613 | + */ |
---|
| 614 | +} |
---|
635 | 615 | |
---|
636 | 616 | /* Create a DIMM object under specifed memory controller device */ |
---|
637 | 617 | static int edac_create_dimm_object(struct mem_ctl_info *mci, |
---|
638 | | - struct dimm_info *dimm, |
---|
639 | | - int index) |
---|
| 618 | + struct dimm_info *dimm) |
---|
640 | 619 | { |
---|
641 | 620 | int err; |
---|
642 | 621 | dimm->mci = mci; |
---|
643 | 622 | |
---|
644 | 623 | dimm->dev.type = &dimm_attr_type; |
---|
645 | | - dimm->dev.bus = mci->bus; |
---|
| 624 | + dimm->dev.release = dimm_release; |
---|
646 | 625 | device_initialize(&dimm->dev); |
---|
647 | 626 | |
---|
648 | 627 | dimm->dev.parent = &mci->dev; |
---|
649 | 628 | if (mci->csbased) |
---|
650 | | - dev_set_name(&dimm->dev, "rank%d", index); |
---|
| 629 | + dev_set_name(&dimm->dev, "rank%d", dimm->idx); |
---|
651 | 630 | else |
---|
652 | | - dev_set_name(&dimm->dev, "dimm%d", index); |
---|
| 631 | + dev_set_name(&dimm->dev, "dimm%d", dimm->idx); |
---|
653 | 632 | dev_set_drvdata(&dimm->dev, dimm); |
---|
654 | 633 | pm_runtime_forbid(&mci->dev); |
---|
655 | 634 | |
---|
656 | | - err = device_add(&dimm->dev); |
---|
| 635 | + err = device_add(&dimm->dev); |
---|
| 636 | + if (err) { |
---|
| 637 | + edac_dbg(1, "failure: create device %s\n", dev_name(&dimm->dev)); |
---|
| 638 | + put_device(&dimm->dev); |
---|
| 639 | + return err; |
---|
| 640 | + } |
---|
657 | 641 | |
---|
658 | | - edac_dbg(0, "creating rank/dimm device %s\n", dev_name(&dimm->dev)); |
---|
| 642 | + if (IS_ENABLED(CONFIG_EDAC_DEBUG)) { |
---|
| 643 | + char location[80]; |
---|
659 | 644 | |
---|
660 | | - return err; |
---|
| 645 | + edac_dimm_info_location(dimm, location, sizeof(location)); |
---|
| 646 | + edac_dbg(0, "device %s created at location %s\n", |
---|
| 647 | + dev_name(&dimm->dev), location); |
---|
| 648 | + } |
---|
| 649 | + |
---|
| 650 | + return 0; |
---|
661 | 651 | } |
---|
662 | 652 | |
---|
663 | 653 | /* |
---|
.. | .. |
---|
671 | 661 | const char *data, size_t count) |
---|
672 | 662 | { |
---|
673 | 663 | struct mem_ctl_info *mci = to_mci(dev); |
---|
674 | | - int cnt, row, chan, i; |
---|
| 664 | + struct dimm_info *dimm; |
---|
| 665 | + int row, chan; |
---|
| 666 | + |
---|
675 | 667 | mci->ue_mc = 0; |
---|
676 | 668 | mci->ce_mc = 0; |
---|
677 | 669 | mci->ue_noinfo_count = 0; |
---|
.. | .. |
---|
687 | 679 | ri->channels[chan]->ce_count = 0; |
---|
688 | 680 | } |
---|
689 | 681 | |
---|
690 | | - cnt = 1; |
---|
691 | | - for (i = 0; i < mci->n_layers; i++) { |
---|
692 | | - cnt *= mci->layers[i].size; |
---|
693 | | - memset(mci->ce_per_layer[i], 0, cnt * sizeof(u32)); |
---|
694 | | - memset(mci->ue_per_layer[i], 0, cnt * sizeof(u32)); |
---|
| 682 | + mci_for_each_dimm(mci, dimm) { |
---|
| 683 | + dimm->ue_count = 0; |
---|
| 684 | + dimm->ce_count = 0; |
---|
695 | 685 | } |
---|
696 | 686 | |
---|
697 | 687 | mci->start_time = jiffies; |
---|
.. | .. |
---|
827 | 817 | char *data) |
---|
828 | 818 | { |
---|
829 | 819 | struct mem_ctl_info *mci = to_mci(dev); |
---|
830 | | - int i; |
---|
| 820 | + int len = PAGE_SIZE; |
---|
831 | 821 | char *p = data; |
---|
| 822 | + int i, n; |
---|
832 | 823 | |
---|
833 | 824 | for (i = 0; i < mci->n_layers; i++) { |
---|
834 | | - p += sprintf(p, "%s %d ", |
---|
835 | | - edac_layer_name[mci->layers[i].type], |
---|
836 | | - mci->layers[i].size - 1); |
---|
| 825 | + n = scnprintf(p, len, "%s %d ", |
---|
| 826 | + edac_layer_name[mci->layers[i].type], |
---|
| 827 | + mci->layers[i].size - 1); |
---|
| 828 | + len -= n; |
---|
| 829 | + if (len <= 0) |
---|
| 830 | + goto out; |
---|
| 831 | + |
---|
| 832 | + p += n; |
---|
837 | 833 | } |
---|
838 | 834 | |
---|
| 835 | + p += scnprintf(p, len, "\n"); |
---|
| 836 | +out: |
---|
839 | 837 | return p - data; |
---|
840 | 838 | } |
---|
841 | 839 | |
---|
.. | .. |
---|
896 | 894 | NULL |
---|
897 | 895 | }; |
---|
898 | 896 | |
---|
899 | | -static void mci_attr_release(struct device *dev) |
---|
900 | | -{ |
---|
901 | | - struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); |
---|
902 | | - |
---|
903 | | - edac_dbg(1, "Releasing csrow device %s\n", dev_name(dev)); |
---|
904 | | - kfree(mci); |
---|
905 | | -} |
---|
906 | | - |
---|
907 | 897 | static const struct device_type mci_attr_type = { |
---|
908 | 898 | .groups = mci_attr_groups, |
---|
909 | | - .release = mci_attr_release, |
---|
910 | 899 | }; |
---|
911 | 900 | |
---|
912 | 901 | /* |
---|
.. | .. |
---|
920 | 909 | int edac_create_sysfs_mci_device(struct mem_ctl_info *mci, |
---|
921 | 910 | const struct attribute_group **groups) |
---|
922 | 911 | { |
---|
923 | | - char *name; |
---|
924 | | - int i, err; |
---|
925 | | - |
---|
926 | | - /* |
---|
927 | | - * The memory controller needs its own bus, in order to avoid |
---|
928 | | - * namespace conflicts at /sys/bus/edac. |
---|
929 | | - */ |
---|
930 | | - name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); |
---|
931 | | - if (!name) |
---|
932 | | - return -ENOMEM; |
---|
933 | | - |
---|
934 | | - mci->bus->name = name; |
---|
935 | | - |
---|
936 | | - edac_dbg(0, "creating bus %s\n", mci->bus->name); |
---|
937 | | - |
---|
938 | | - err = bus_register(mci->bus); |
---|
939 | | - if (err < 0) { |
---|
940 | | - kfree(name); |
---|
941 | | - return err; |
---|
942 | | - } |
---|
| 912 | + struct dimm_info *dimm; |
---|
| 913 | + int err; |
---|
943 | 914 | |
---|
944 | 915 | /* get the /sys/devices/system/edac subsys reference */ |
---|
945 | 916 | mci->dev.type = &mci_attr_type; |
---|
946 | | - device_initialize(&mci->dev); |
---|
947 | | - |
---|
948 | 917 | mci->dev.parent = mci_pdev; |
---|
949 | | - mci->dev.bus = mci->bus; |
---|
950 | 918 | mci->dev.groups = groups; |
---|
951 | 919 | dev_set_name(&mci->dev, "mc%d", mci->mc_idx); |
---|
952 | 920 | dev_set_drvdata(&mci->dev, mci); |
---|
953 | 921 | pm_runtime_forbid(&mci->dev); |
---|
954 | 922 | |
---|
955 | | - edac_dbg(0, "creating device %s\n", dev_name(&mci->dev)); |
---|
956 | 923 | err = device_add(&mci->dev); |
---|
957 | 924 | if (err < 0) { |
---|
958 | 925 | edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev)); |
---|
959 | | - goto fail_unregister_bus; |
---|
| 926 | + /* no put_device() here, free mci with _edac_mc_free() */ |
---|
| 927 | + return err; |
---|
960 | 928 | } |
---|
| 929 | + |
---|
| 930 | + edac_dbg(0, "device %s created\n", dev_name(&mci->dev)); |
---|
961 | 931 | |
---|
962 | 932 | /* |
---|
963 | 933 | * Create the dimm/rank devices |
---|
964 | 934 | */ |
---|
965 | | - for (i = 0; i < mci->tot_dimms; i++) { |
---|
966 | | - struct dimm_info *dimm = mci->dimms[i]; |
---|
| 935 | + mci_for_each_dimm(mci, dimm) { |
---|
967 | 936 | /* Only expose populated DIMMs */ |
---|
968 | 937 | if (!dimm->nr_pages) |
---|
969 | 938 | continue; |
---|
970 | 939 | |
---|
971 | | -#ifdef CONFIG_EDAC_DEBUG |
---|
972 | | - edac_dbg(1, "creating dimm%d, located at ", i); |
---|
973 | | - if (edac_debug_level >= 1) { |
---|
974 | | - int lay; |
---|
975 | | - for (lay = 0; lay < mci->n_layers; lay++) |
---|
976 | | - printk(KERN_CONT "%s %d ", |
---|
977 | | - edac_layer_name[mci->layers[lay].type], |
---|
978 | | - dimm->location[lay]); |
---|
979 | | - printk(KERN_CONT "\n"); |
---|
980 | | - } |
---|
981 | | -#endif |
---|
982 | | - err = edac_create_dimm_object(mci, dimm, i); |
---|
983 | | - if (err) { |
---|
984 | | - edac_dbg(1, "failure: create dimm %d obj\n", i); |
---|
985 | | - goto fail_unregister_dimm; |
---|
986 | | - } |
---|
| 940 | + err = edac_create_dimm_object(mci, dimm); |
---|
| 941 | + if (err) |
---|
| 942 | + goto fail; |
---|
987 | 943 | } |
---|
988 | 944 | |
---|
989 | 945 | #ifdef CONFIG_EDAC_LEGACY_SYSFS |
---|
990 | 946 | err = edac_create_csrow_objects(mci); |
---|
991 | 947 | if (err < 0) |
---|
992 | | - goto fail_unregister_dimm; |
---|
| 948 | + goto fail; |
---|
993 | 949 | #endif |
---|
994 | 950 | |
---|
995 | 951 | edac_create_debugfs_nodes(mci); |
---|
996 | 952 | return 0; |
---|
997 | 953 | |
---|
998 | | -fail_unregister_dimm: |
---|
999 | | - for (i--; i >= 0; i--) { |
---|
1000 | | - struct dimm_info *dimm = mci->dimms[i]; |
---|
1001 | | - if (!dimm->nr_pages) |
---|
1002 | | - continue; |
---|
1003 | | - |
---|
1004 | | - device_unregister(&dimm->dev); |
---|
1005 | | - } |
---|
1006 | | - device_unregister(&mci->dev); |
---|
1007 | | -fail_unregister_bus: |
---|
1008 | | - bus_unregister(mci->bus); |
---|
1009 | | - kfree(name); |
---|
| 954 | +fail: |
---|
| 955 | + edac_remove_sysfs_mci_device(mci); |
---|
1010 | 956 | |
---|
1011 | 957 | return err; |
---|
1012 | 958 | } |
---|
.. | .. |
---|
1016 | 962 | */ |
---|
1017 | 963 | void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) |
---|
1018 | 964 | { |
---|
1019 | | - int i; |
---|
| 965 | + struct dimm_info *dimm; |
---|
| 966 | + |
---|
| 967 | + if (!device_is_registered(&mci->dev)) |
---|
| 968 | + return; |
---|
1020 | 969 | |
---|
1021 | 970 | edac_dbg(0, "\n"); |
---|
1022 | 971 | |
---|
.. | .. |
---|
1027 | 976 | edac_delete_csrow_objects(mci); |
---|
1028 | 977 | #endif |
---|
1029 | 978 | |
---|
1030 | | - for (i = 0; i < mci->tot_dimms; i++) { |
---|
1031 | | - struct dimm_info *dimm = mci->dimms[i]; |
---|
1032 | | - if (dimm->nr_pages == 0) |
---|
| 979 | + mci_for_each_dimm(mci, dimm) { |
---|
| 980 | + if (!device_is_registered(&dimm->dev)) |
---|
1033 | 981 | continue; |
---|
1034 | | - edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev)); |
---|
| 982 | + edac_dbg(1, "unregistering device %s\n", dev_name(&dimm->dev)); |
---|
1035 | 983 | device_unregister(&dimm->dev); |
---|
1036 | 984 | } |
---|
1037 | | -} |
---|
1038 | 985 | |
---|
1039 | | -void edac_unregister_sysfs(struct mem_ctl_info *mci) |
---|
1040 | | -{ |
---|
1041 | | - struct bus_type *bus = mci->bus; |
---|
1042 | | - const char *name = mci->bus->name; |
---|
1043 | | - |
---|
1044 | | - edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); |
---|
1045 | | - device_unregister(&mci->dev); |
---|
1046 | | - bus_unregister(bus); |
---|
1047 | | - kfree(name); |
---|
| 986 | + /* only remove the device, but keep mci */ |
---|
| 987 | + device_del(&mci->dev); |
---|
1048 | 988 | } |
---|
1049 | 989 | |
---|
1050 | 990 | static void mc_attr_release(struct device *dev) |
---|
.. | .. |
---|
1054 | 994 | * parent device, used to create the /sys/devices/mc sysfs node. |
---|
1055 | 995 | * So, there are no attributes on it. |
---|
1056 | 996 | */ |
---|
1057 | | - edac_dbg(1, "Releasing device %s\n", dev_name(dev)); |
---|
| 997 | + edac_dbg(1, "device %s released\n", dev_name(dev)); |
---|
1058 | 998 | kfree(dev); |
---|
1059 | 999 | } |
---|
1060 | 1000 | |
---|
1061 | | -static const struct device_type mc_attr_type = { |
---|
1062 | | - .release = mc_attr_release, |
---|
1063 | | -}; |
---|
1064 | 1001 | /* |
---|
1065 | 1002 | * Init/exit code for the module. Basically, creates/removes /sys/class/rc |
---|
1066 | 1003 | */ |
---|
.. | .. |
---|
1069 | 1006 | int err; |
---|
1070 | 1007 | |
---|
1071 | 1008 | mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL); |
---|
1072 | | - if (!mci_pdev) { |
---|
1073 | | - err = -ENOMEM; |
---|
1074 | | - goto out; |
---|
1075 | | - } |
---|
| 1009 | + if (!mci_pdev) |
---|
| 1010 | + return -ENOMEM; |
---|
1076 | 1011 | |
---|
1077 | 1012 | mci_pdev->bus = edac_get_sysfs_subsys(); |
---|
1078 | | - mci_pdev->type = &mc_attr_type; |
---|
1079 | | - device_initialize(mci_pdev); |
---|
1080 | | - dev_set_name(mci_pdev, "mc"); |
---|
| 1013 | + mci_pdev->release = mc_attr_release; |
---|
| 1014 | + mci_pdev->init_name = "mc"; |
---|
1081 | 1015 | |
---|
1082 | | - err = device_add(mci_pdev); |
---|
1083 | | - if (err < 0) |
---|
1084 | | - goto out_put_device; |
---|
| 1016 | + err = device_register(mci_pdev); |
---|
| 1017 | + if (err < 0) { |
---|
| 1018 | + edac_dbg(1, "failure: create device %s\n", dev_name(mci_pdev)); |
---|
| 1019 | + put_device(mci_pdev); |
---|
| 1020 | + return err; |
---|
| 1021 | + } |
---|
1085 | 1022 | |
---|
1086 | 1023 | edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); |
---|
1087 | 1024 | |
---|
1088 | 1025 | return 0; |
---|
1089 | | - |
---|
1090 | | - out_put_device: |
---|
1091 | | - put_device(mci_pdev); |
---|
1092 | | - out: |
---|
1093 | | - return err; |
---|
1094 | 1026 | } |
---|
1095 | 1027 | |
---|
1096 | 1028 | void edac_mc_sysfs_exit(void) |
---|