EDAC: Expose node link in sysfs if CONFIG_NUMA
Commit Message
The node in sysfs already has cpu link and memory link, the memory
control also under a node.
Expose node link to memory control directory and expose memory control
link to node directory if CONFIG_NUMA.
At the same time, change the type of EDAC from tristate to boolean
because it needs node_devices.
Signed-off-by: Yajun Deng <yajun.deng@linux.dev>
---
Documentation/ABI/testing/sysfs-devices-edac | 26 ++++++++++
Documentation/admin-guide/ras.rst | 2 +
drivers/edac/Kconfig | 2 +-
drivers/edac/edac_mc_sysfs.c | 54 ++++++++++++++++++++
4 files changed, 83 insertions(+), 1 deletion(-)
Comments
On Tue, May 16, 2023 at 04:07:48PM +0800, Yajun Deng wrote:
> The node in sysfs already has cpu link and memory link, the memory
> control also under a node.
>
> Expose node link to memory control directory and expose memory control
> link to node directory if CONFIG_NUMA.
Why?
> At the same time, change the type of EDAC from tristate to boolean
> because it needs node_devices.
Nope.
May 16, 2023 6:34 PM, "Borislav Petkov" <bp@alien8.de> wrote:
> On Tue, May 16, 2023 at 04:07:48PM +0800, Yajun Deng wrote:
>
>> The node in sysfs already has cpu link and memory link, the memory
>> control also under a node.
>>
>> Expose node link to memory control directory and expose memory control
>> link to node directory if CONFIG_NUMA.
>
> Why?
>
It will help users to confirm which MC belongs to which node if there are multiple
MCs. Therefore, we can also know how many dimm on each node.
>> At the same time, change the type of EDAC from tristate to boolean
>> because it needs node_devices.
>
> Nope.
>
> --
> Regards/Gruss,
> Boris.
>
> https://people.kernel.org/tglx/notes-about-netiquette
On Tue, May 16, 2023 at 11:07:11AM +0000, Yajun Deng wrote:
> It will help users to confirm which MC belongs to which node if there
> are multiple MCs. Therefore, we can also know how many dimm on each
> node.
There are physical nodes, logical nodes, NUMA nodes, interleaving
between nodes...
Is there any practical use case and need behind this?
May 16, 2023 7:19 PM, "Borislav Petkov" <bp@alien8.de> wrote:
> On Tue, May 16, 2023 at 11:07:11AM +0000, Yajun Deng wrote:
>
>> It will help users to confirm which MC belongs to which node if there
>> are multiple MCs. Therefore, we can also know how many dimm on each
>> node.
>
> There are physical nodes, logical nodes, NUMA nodes, interleaving
> between nodes...
>
Node is the NUMA node, We get the numa id by calling dev_to_node().
> Is there any practical use case and need behind this?
>
Some dimm may not be recognized when boot, we want to find it.
The '/sys/devices/system/node/node0/meminfo' would show the memory on
node0.
If we have '/sys/devices/system/node/node0/mc0', by comparing the number
of dimm and MemTotal in meminfo. It is easy to know that the dimm didn't
recognized whether it belonged to this NUMA node or not.
> --
> Regards/Gruss,
> Boris.
>
> https://people.kernel.org/tglx/notes-about-netiquette
On Tue, May 16, 2023 at 11:59:07AM +0000, Yajun Deng wrote:
> If we have '/sys/devices/system/node/node0/mc0', by comparing the number
> of dimm and MemTotal in meminfo. It is easy to know that the dimm didn't
> recognized whether it belonged to this NUMA node or not.
mc != NUMA node.
In any case, EDAC's purpose is not for finding lost memory. Fix your
system's configuration so that no DIMMs remain unrecognized at boot.
>> If we have '/sys/devices/system/node/node0/mc0', by comparing the number
>> of dimm and MemTotal in meminfo. It is easy to know that the dimm didn't
>> recognized whether it belonged to this NUMA node or not.
>
> mc != NUMA node.
Modern systems have multiple memory controllers per socket.
On an Icelake server I see:
$ cd /sys/devices/system/edac/mc
$ ls -l
total 0
drwxr-xr-x. 5 root root 0 May 16 10:13 mc0
drwxr-xr-x. 3 root root 0 May 16 10:13 mc1
drwxr-xr-x. 5 root root 0 May 16 10:13 mc2
drwxr-xr-x. 3 root root 0 May 16 10:13 mc3
drwxr-xr-x. 5 root root 0 May 16 10:13 mc4
drwxr-xr-x. 3 root root 0 May 16 10:13 mc5
drwxr-xr-x. 5 root root 0 May 16 10:13 mc6
drwxr-xr-x. 3 root root 0 May 16 10:13 mc7
drwxr-xr-x. 2 root root 0 May 16 10:13 power
lrwxrwxrwx. 1 root root 0 May 16 03:11 subsystem -> ../../../../bus/edac
-rw-r--r--. 1 root root 4096 May 16 03:11 uevent
But I can figure out the socket topology with:
$ grep . mc*/mc_name
mc0/mc_name:Intel_10nm Socket#0 IMC#0
mc1/mc_name:Intel_10nm Socket#0 IMC#1
mc2/mc_name:Intel_10nm Socket#0 IMC#2
mc3/mc_name:Intel_10nm Socket#0 IMC#3
mc4/mc_name:Intel_10nm Socket#1 IMC#0
mc5/mc_name:Intel_10nm Socket#1 IMC#1
mc6/mc_name:Intel_10nm Socket#1 IMC#2
mc7/mc_name:Intel_10nm Socket#1 IMC#3
I think this should help connect "mc*" to which node
they belong to.
-Tony
May 17, 2023 1:25 AM, "Luck, Tony" <tony.luck@intel.com> wrote:
>>> If we have '/sys/devices/system/node/node0/mc0', by comparing the number
>>> of dimm and MemTotal in meminfo. It is easy to know that the dimm didn't
>>> recognized whether it belonged to this NUMA node or not.
>>
>> mc != NUMA node.
>
> Modern systems have multiple memory controllers per socket.
> On an Icelake server I see:
>
> $ cd /sys/devices/system/edac/mc
> $ ls -l
> total 0
> drwxr-xr-x. 5 root root 0 May 16 10:13 mc0
> drwxr-xr-x. 3 root root 0 May 16 10:13 mc1
> drwxr-xr-x. 5 root root 0 May 16 10:13 mc2
> drwxr-xr-x. 3 root root 0 May 16 10:13 mc3
> drwxr-xr-x. 5 root root 0 May 16 10:13 mc4
> drwxr-xr-x. 3 root root 0 May 16 10:13 mc5
> drwxr-xr-x. 5 root root 0 May 16 10:13 mc6
> drwxr-xr-x. 3 root root 0 May 16 10:13 mc7
> drwxr-xr-x. 2 root root 0 May 16 10:13 power
> lrwxrwxrwx. 1 root root 0 May 16 03:11 subsystem -> ../../../../bus/edac
> -rw-r--r--. 1 root root 4096 May 16 03:11 uevent
>
> But I can figure out the socket topology with:
>
> $ grep . mc*/mc_name
> mc0/mc_name:Intel_10nm Socket#0 IMC#0
> mc1/mc_name:Intel_10nm Socket#0 IMC#1
> mc2/mc_name:Intel_10nm Socket#0 IMC#2
> mc3/mc_name:Intel_10nm Socket#0 IMC#3
> mc4/mc_name:Intel_10nm Socket#1 IMC#0
> mc5/mc_name:Intel_10nm Socket#1 IMC#1
> mc6/mc_name:Intel_10nm Socket#1 IMC#2
> mc7/mc_name:Intel_10nm Socket#1 IMC#3
>
> I think this should help connect "mc*" to which node
> they belong to.
>
Thanks!
Yes, mc_name may show the NUMA id, it depends on the vendor edac modules.
On the other hand, this directory '/sys/devices/system/node/node0/' should
show all resources that belong to it. It already has cpu and memory symbolic
link. Memory controller also belongs to one NUMA. The memory controller
symbolic link should appear under node* directory.
> -Tony
On 5/16/23 15:07, Yajun Deng wrote:
> +
> +What: /sys/devices/system/edac/mc/mc*/node*
> +Date: May 2023
> +Contact: Yajun Deng <yajun.deng@linux.dev>
> + linux-edac@vger.kernel.org
> +Description: When CONFIG_NUMA is enabled, a symbolic link that points to the
> + corresponding NUMA node directory.
> +
> + For example, the following symbolic link is created for node0 on mc0
> + and mc1:
> +
"For example, on node0 with two memory control directories mc0 and mc1
the symlinks are::" (I prefer using literal code block here).
> + /sys/devices/system/edac/mc/mc0/node0 -> ../../../node/node0
> + /sys/devices/system/edac/mc/mc1/node0 -> ../../../node/node0
Or bullet lists should better fit listing above?
> +
> +What: /sys/devices/system/node/node*/mc*
> +Date: May 2023
> +Contact: Yajun Deng <yajun.deng@linux.dev>
> + linux-edac@vger.kernel.org
> +Description: When CONFIG_NUMA is enabled, a symbolic link that points to the
> + corresponding memory control directory.
> +
> + For example, the following symbolic link is created for mc0 and mc1
> + on node0:
> +
> + /sys/devices/system/node/node0/mc0 -> ../../edac/mc/mc0
> + /sys/devices/system/node/node0/mc1 -> ../../edac/mc/mc1
Similar as my review above.
Thanks.
Hello,
kernel test robot noticed "BUG:KASAN:wild-memory-access_in_edac_create_sysfs_mci_device" on:
commit: 725ca92fab0b553466d32b1fecd4e8b4adb4ed03 ("[PATCH] EDAC: Expose node link in sysfs if CONFIG_NUMA")
url: https://github.com/intel-lab-lkp/linux/commits/Yajun-Deng/EDAC-Expose-node-link-in-sysfs-if-CONFIG_NUMA/20230516-160858
base: https://git.kernel.org/cgit/linux/kernel/git/ras/ras.git edac-for-next
patch subject: [PATCH] EDAC: Expose node link in sysfs if CONFIG_NUMA
patch link: https://lore.kernel.org/all/20230516080748.3155788-1-yajun.deng@linux.dev/
in testcase: kernel-selftests
version: kernel-selftests-x86_64-60acb023-1_20230329
with following parameters:
group: sgx
test-description: The kernel contains a set of "self tests" under the tools/testing/selftests/ directory. These are intended to be small unit tests to exercise individual code paths in the kernel.
test-url: https://www.kernel.org/doc/Documentation/kselftest.txt
compiler: gcc-11
test machine: 16 threads 1 sockets Intel(R) Xeon(R) E-2278G CPU @ 3.40GHz (Coffee Lake) with 32G memory
(please refer to attached dmesg/kmsg for entire log/backtrace)
If you fix the issue, kindly add following tag
| Reported-by: kernel test robot <yujie.liu@intel.com>
| Closes: https://lore.kernel.org/oe-lkp/202305221451.b48d9b55-yujie.liu@intel.com
[ 61.987277][ T311] BUG: KASAN: wild-memory-access in edac_create_sysfs_mci_device (arch/x86/include/asm/bitops.h:228 arch/x86/include/asm/bitops.h:240 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:423 drivers/edac/edac_mc_sysfs.c:934 drivers/edac/edac_mc_sysfs.c:1019)
[ 61.987284][ T311] Read of size 8 at addr 1fffffff854eddd8 by task systemd-udevd/311
0m] Reached targ[ 61.987289][ T311] CPU: 9 PID: 311 Comm: systemd-udevd Not tainted 6.4.0-rc1-00003-g725ca92fab0b #1
[ 61.987295][ T311] Call Trace:
[ 61.987297][ T311] <TASK>
[ 61.987299][ T311] dump_stack_lvl (lib/dump_stack.c:108)
[ 61.987305][ T311] kasan_report (mm/kasan/report.c:574)
[ 61.987311][ T311] ? edac_create_sysfs_mci_device (arch/x86/include/asm/bitops.h:228 arch/x86/include/asm/bitops.h:240 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:423 drivers/edac/edac_mc_sysfs.c:934 drivers/edac/edac_mc_sysfs.c:1019)
[ 61.987317][ T311] kasan_check_range (mm/kasan/generic.c:188)
[ 61.987320][ T311] edac_create_sysfs_mci_device (arch/x86/include/asm/bitops.h:228 arch/x86/include/asm/bitops.h:240 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:423 drivers/edac/edac_mc_sysfs.c:934 drivers/edac/edac_mc_sysfs.c:1019)
[ 62.067405][ T311] edac_mc_add_mc_with_groups (drivers/edac/edac_mc.c:648)
[ 62.073291][ T311] ? _raw_spin_unlock_irqrestore (arch/x86/include/asm/irqflags.h:42 arch/x86/include/asm/irqflags.h:77 arch/x86/include/asm/irqflags.h:135 include/linux/spinlock_api_smp.h:151 kernel/locking/spinlock.c:194)
[ 62.079279][ T311] ie31200_probe1 (drivers/edac/ie31200_edac.c:528) ie31200_edac
1;39mRegular bac[ 62.093328][ T311] ? ie31200_check (drivers/edac/ie31200_edac.c:405) ie31200_edac
kground program [ 62.100696][ T311] ? do_pci_enable_device (drivers/pci/pci.c:1931 drivers/pci/pci.c:1907)
processing daemo[ 62.107379][ T311] ? rpm_callback (drivers/base/power/runtime.c:763)
[ 62.113329][ T311] ? spin_bug (kernel/locking/spinlock_debug.c:113)
[ 62.118112][ T311] ? pci_enable_device_flags (drivers/pci/pci.c:2007)
[ 62.123916][ T311] ? ie31200_probe1 (drivers/edac/ie31200_edac.c:549) ie31200_edac
[ 62.126911][ T321] calling mei_init+0x0/0xc0 [mei] @ 321
[ 62.130145][ T311] ie31200_init_one (drivers/edac/ie31200_edac.c:555) ie31200_edac
[ 62.130151][ T311] ? ie31200_probe1 (drivers/edac/ie31200_edac.c:549) ie31200_edac
[ 62.137671][ T321] initcall mei_init+0x0/0xc0 [mei] returned 0 after 2001 usecs
[ 62.141510][ T311] local_pci_probe (drivers/pci/pci-driver.c:324)
[ 62.141518][ T311] pci_call_probe (drivers/pci/pci-driver.c:392)
[ 62.166212][ T311] ? spin_bug (kernel/locking/spinlock_debug.c:113)
[ 62.166220][ T311] ? pci_pm_suspend_late (drivers/pci/pci-driver.c:352)
Startin[ 62.166225][ T311] ? pci_match_device (drivers/pci/pci-driver.c:159)
System Message [ 62.188729][ T311] ? kernfs_put (arch/x86/include/asm/atomic.h:123 (discriminator 1) include/linux/atomic/atomic-instrumented.h:576 (discriminator 1) fs/kernfs/dir.c:539 (discriminator 1))
[ 62.194359][ T311] pci_device_probe (drivers/pci/pci-driver.c:461)
[ 62.199890][ T311] really_probe (drivers/base/dd.c:579 drivers/base/dd.c:658)
[ 62.204551][ T311] ? ktime_get (arch/x86/include/asm/irqflags.h:42 arch/x86/include/asm/irqflags.h:77 arch/x86/include/asm/irqflags.h:135 include/linux/seqlock.h:104 kernel/time/timekeeping.c:846)
[ 62.209137][ T311] __driver_probe_device (drivers/base/dd.c:736 drivers/base/dd.c:798)
[ 62.214589][ T311] driver_probe_device (drivers/base/dd.c:830)
[ 62.219781][ T311] __driver_attach (drivers/base/dd.c:1217)
[ 62.224707][ T311] ? __device_attach_driver (drivers/base/dd.c:1157)
[ 62.230405][ T311] bus_for_each_dev (drivers/base/bus.c:367)
[ 62.235339][ T311] ? lockdep_init_map_type (kernel/locking/lockdep.c:4856)
[ 62.235346][ T311] ? bus_remove_file (drivers/base/bus.c:356)
[ 62.235351][ T311] ? bus_add_driver (drivers/base/bus.c:672)
Startin[ 62.235357][ T311] bus_add_driver (drivers/base/bus.c:674)
4 Metadata Check[ 62.235368][ T311] ie31200_init (drivers/edac/ie31200_edac.c:574) ie31200_edac
.
[ 62.235378][ T311] ? 0xffffffffa0538000
[ 62.235381][ T311] do_one_initcall (init/main.c:1246)
[ 62.235385][ T311] ? trace_event_raw_event_initcall_level (init/main.c:1237)
[ 62.235390][ T311] ? __kmem_cache_alloc_node (mm/slub.c:3453 mm/slub.c:3490)
[ 62.235394][ T311] ? do_init_module (include/linux/slab.h:559 kernel/module/main.c:2517)
[ 62.235398][ T311] ? kasan_unpoison (mm/kasan/shadow.c:160 mm/kasan/shadow.c:194)
[ 62.235402][ T311] do_init_module (kernel/module/main.c:2529)
[ 62.235406][ T311] load_module (kernel/module/main.c:2980)
[ 62.235409][ T311] ? ima_read_file (security/integrity/ima/ima_main.c:788)
[ 62.235415][ T311] ? post_relocation (kernel/module/main.c:2829)
[ 62.235419][ T311] ? __x64_sys_fspick (fs/kernel_read_file.c:38)
[ 62.235424][ T311] ? __do_sys_finit_module (kernel/module/main.c:3099)
[ 62.235427][ T311] __do_sys_finit_module (kernel/module/main.c:3099)
[ 62.235430][ T311] ? __ia32_sys_init_module (kernel/module/main.c:3061)
[ 62.235433][ T311] ? seccomp_notify_ioctl (kernel/seccomp.c:1193)
[ 62.235440][ T311] do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80)
[ 62.235445][ T311] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120)
[ 62.235448][ T311] RIP: 0033:0x7f92a8c3f5a9
[ 62.235451][ T311] Code: 08 89 e8 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 27 08 0d 00 f7 d8 64 89 01 48
All code
========
0: 08 89 e8 5b 5d c3 or %cl,-0x3ca2a418(%rcx)
6: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
d: 00 00 00
10: 90 nop
11: 48 89 f8 mov %rdi,%rax
14: 48 89 f7 mov %rsi,%rdi
17: 48 89 d6 mov %rdx,%rsi
1a: 48 89 ca mov %rcx,%rdx
1d: 4d 89 c2 mov %r8,%r10
20: 4d 89 c8 mov %r9,%r8
23: 4c 8b 4c 24 08 mov 0x8(%rsp),%r9
28: 0f 05 syscall
2a:* 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax <-- trapping instruction
30: 73 01 jae 0x33
32: c3 ret
33: 48 8b 0d 27 08 0d 00 mov 0xd0827(%rip),%rcx # 0xd0861
3a: f7 d8 neg %eax
3c: 64 89 01 mov %eax,%fs:(%rcx)
3f: 48 rex.W
Code starting with the faulting instruction
===========================================
0: 48 3d 01 f0 ff ff cmp $0xfffffffffffff001,%rax
6: 73 01 jae 0x9
8: c3 ret
9: 48 8b 0d 27 08 0d 00 mov 0xd0827(%rip),%rcx # 0xd0837
10: f7 d8 neg %eax
12: 64 89 01 mov %eax,%fs:(%rcx)
15: 48 rex.W
[ 62.235453][ T311] RSP: 002b:00007fff2a61dc58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[ 62.235456][ T311] RAX: ffffffffffffffda RBX: 000055a843568f40 RCX: 00007f92a8c3f5a9
[ 62.235458][ T311] RDX: 0000000000000000 RSI: 00007f92a8dd2efd RDI: 0000000000000006
[ 62.235459][ T311] RBP: 00007f92a8dd2efd R08: 0000000000000000 R09: 000055a84353a4c0
[ 62.235461][ T311] R10: 0000000000000006 R11: 0000000000000246 R12: 0000000000020000
[ 62.235462][ T311] R13: 0000000000000000 R14: 000055a84357c480 R15: 000055a8417d0e50
[ 62.235466][ T311] </TASK>
@@ -155,3 +155,29 @@ Description: This attribute file displays the total count of uncorrectable
errors that have occurred on this DIMM. If panic_on_ue is set, this
counter will not have a chance to increment, since EDAC will panic the
system
+
+What: /sys/devices/system/edac/mc/mc*/node*
+Date: May 2023
+Contact: Yajun Deng <yajun.deng@linux.dev>
+ linux-edac@vger.kernel.org
+Description: When CONFIG_NUMA is enabled, a symbolic link that points to the
+ corresponding NUMA node directory.
+
+ For example, the following symbolic link is created for node0 on mc0
+ and mc1:
+
+ /sys/devices/system/edac/mc/mc0/node0 -> ../../../node/node0
+ /sys/devices/system/edac/mc/mc1/node0 -> ../../../node/node0
+
+What: /sys/devices/system/node/node*/mc*
+Date: May 2023
+Contact: Yajun Deng <yajun.deng@linux.dev>
+ linux-edac@vger.kernel.org
+Description: When CONFIG_NUMA is enabled, a symbolic link that points to the
+ corresponding memory control directory.
+
+ For example, the following symbolic link is created for mc0 and mc1
+ on node0:
+
+ /sys/devices/system/node/node0/mc0 -> ../../edac/mc/mc0
+ /sys/devices/system/node/node0/mc1 -> ../../edac/mc/mc1
@@ -458,6 +458,7 @@ A typical EDAC system has the following structure under
│ │ │ └── uevent
│ │ ├── max_location
│ │ ├── mc_name
+ │ │ ├── node0 -> ../../../node/node0 #if CONFIG_NUMA
│ │ ├── reset_counters
│ │ ├── seconds_since_reset
│ │ ├── size_mb
@@ -479,6 +480,7 @@ A typical EDAC system has the following structure under
│ │ │ └── uevent
│ │ ├── max_location
│ │ ├── mc_name
+ │ │ ├── node0 -> ../../../node/node0 #if CONFIG_NUMA
│ │ ├── reset_counters
│ │ ├── seconds_since_reset
│ │ ├── size_mb
@@ -10,7 +10,7 @@ config EDAC_SUPPORT
bool
menuconfig EDAC
- tristate "EDAC (Error Detection And Correction) reporting"
+ bool "EDAC (Error Detection And Correction) reporting"
depends on HAS_IOMEM && EDAC_SUPPORT && RAS
help
EDAC is a subsystem along with hardware-specific drivers designed to
@@ -18,6 +18,7 @@
#include <linux/bug.h>
#include <linux/pm_runtime.h>
#include <linux/uaccess.h>
+#include <linux/node.h>
#include "edac_mc.h"
#include "edac_module.h"
@@ -922,6 +923,55 @@ static const struct device_type mci_attr_type = {
.groups = mci_attr_groups,
};
+#ifdef CONFIG_NUMA
+static int edac_create_node_link(struct mem_ctl_info *mci)
+{
+ int nid = dev_to_node(mci->pdev);
+ struct node *node;
+ struct device *dev;
+ int ret;
+
+ if (!node_online(nid))
+ return 0;
+
+ node = node_devices[nid];
+ dev = &mci->dev;
+
+ ret = sysfs_create_link(&node->dev.kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+ if (ret)
+ return ret;
+
+ return sysfs_create_link(&dev->kobj, &node->dev.kobj,
+ kobject_name(&node->dev.kobj));
+}
+
+static void edac_remove_node_link(struct mem_ctl_info *mci)
+{
+ int nid = dev_to_node(mci->pdev);
+ struct node *node;
+ struct device *dev;
+
+ if (!node_online(nid))
+ return;
+
+ node = node_devices[nid];
+ dev = &mci->dev;
+
+ sysfs_remove_link(&node->dev.kobj, kobject_name(&dev->kobj));
+
+ sysfs_remove_link(&dev->kobj, kobject_name(&node->dev.kobj));
+}
+#else
+static inline int edac_create_node_link(struct mem_ctl_info *mci)
+{
+ return 0;
+}
+static inline void edac_remove_node_link(struct mem_ctl_info *mci)
+{
+}
+#endif
+
/*
* Create a new Memory Controller kobject instance,
* mc<id> under the 'mc' directory
@@ -966,6 +1016,8 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
goto fail;
}
+ edac_create_node_link(mci);
+
#ifdef CONFIG_EDAC_LEGACY_SYSFS
err = edac_create_csrow_objects(mci);
if (err < 0)
@@ -1000,6 +1052,8 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
edac_delete_csrow_objects(mci);
#endif
+ edac_remove_node_link(mci);
+
mci_for_each_dimm(mci, dimm) {
if (!device_is_registered(&dimm->dev))
continue;