EDAC: Expose node link in sysfs if CONFIG_NUMA

Message ID 20230516080748.3155788-1-yajun.deng@linux.dev
State New
Headers
Series EDAC: Expose node link in sysfs if CONFIG_NUMA |

Commit Message

Yajun Deng May 16, 2023, 8:07 a.m. UTC
  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

Borislav Petkov May 16, 2023, 10:34 a.m. UTC | #1
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.
  
Yajun Deng May 16, 2023, 11:07 a.m. UTC | #2
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
  
Borislav Petkov May 16, 2023, 11:19 a.m. UTC | #3
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?
  
Yajun Deng May 16, 2023, 11:59 a.m. UTC | #4
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
  
Borislav Petkov May 16, 2023, 12:10 p.m. UTC | #5
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.
  
Luck, Tony May 16, 2023, 5:25 p.m. UTC | #6
>> 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
  
Yajun Deng May 17, 2023, 2:49 a.m. UTC | #7
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
  
Bagas Sanjaya May 17, 2023, 7:43 a.m. UTC | #8
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.
  
Liu, Yujie May 22, 2023, 7:04 a.m. UTC | #9
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>
  

Patch

diff --git a/Documentation/ABI/testing/sysfs-devices-edac b/Documentation/ABI/testing/sysfs-devices-edac
index 256a9e990c0b..726f97170b9f 100644
--- a/Documentation/ABI/testing/sysfs-devices-edac
+++ b/Documentation/ABI/testing/sysfs-devices-edac
@@ -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
diff --git a/Documentation/admin-guide/ras.rst b/Documentation/admin-guide/ras.rst
index 8e03751d126d..ef7cc9867fc8 100644
--- a/Documentation/admin-guide/ras.rst
+++ b/Documentation/admin-guide/ras.rst
@@ -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
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 68f576700911..e61a29e0eb28 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -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
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 15f63452a9be..7b81d898f4f2 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -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;