Teach EDAC driver about NVDIMMs
Subsystems (6)
Tony Luck
maintainercover Teach EDAC driver about NVDIMMs
A Skylake server may have some DIMM slots filled with NVDIMMs instead of normal DDR4 DIMMs. These are enumerated differently by the memory controller.
Sadly there isn't an easy way to just peek at some memory controller register to find the size of these DIMMs, so we have to rely on the NFIT and SMBIOS tables to get that information.
This series only tackles the topology function of the EDAC driver. A later series of patches will fix the address translation parts so that errors in NVDIMMs will be reported correctly.
It's marked "RFC" because it depends on the new ACPCIA version 20171110 which has only just made it to Rafael's tree.
Some of you may only care about some of the parts that touch code you maintain, but I copied you on all four because you might like to see the bigger picture.
Tony Luck (4):
acpi, nfit: Add function to look up nvdimm device and provide SMBIOS
handle
firmware: dmi: Add function to look up a handle and return DIMM size
edac: Add new memory type for non-volatile DIMMs
EDAC, skx_edac: Detect non-volatile DIMMs
drivers/acpi/nfit/core.c | 27 +++++++++++++++++++++ drivers/edac/Kconfig | 2 ++ drivers/edac/edac_mc.c | 1 + drivers/edac/edac_mc_sysfs.c | 3 ++- drivers/edac/skx_edac.c | 56 ++++++++++++++++++++++++++++++++++++++++---- drivers/firmware/dmi_scan.c | 29 +++++++++++++++++++++++ include/acpi/nfit.h | 19 +++++++++++++++ include/linux/dmi.h | 2 ++ include/linux/edac.h | 3 +++ 9 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 include/acpi/nfit.h
base-commit: 3fc70f8be59950ee2deecefdddb68be19b8cddd1
Signature · 6 lines
2.14.1 _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
Tony Luck
maintainerRFC PATCH 1/4 acpi, nfit: Add function to look up nvdimm device and provide SMBIOS handle
EDAC driver needs to look up attributes of NVDIMMs provided in SMBIOS.
Provide a function that looks up an acpi_nfit_memory_map from a device handle (node/socket/mc/channel/dimm) and returns the SMBIOS handle. Also pass back the "flags" so we can see if the NVDIMM is OK.
--- drivers/acpi/nfit/core.c | 27 +++++++++++++++++++++++++++ include/acpi/nfit.h | 19 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 include/acpi/nfit.h
drivers/acpi/nfit/core.c +27 -0
@@ -23,6 +23,7 @@#include <linux/io.h> #include <linux/nd.h> #include <asm/cacheflush.h> +#include <acpi/nfit.h> #include "nfit.h" /*
@@ -478,6 +479,32 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,return true; } +int nfit_get_smbios_id (u32 device_handle,u16 *flags) +{ +struct acpi_nfit_memory_map *memdev; +struct acpi_nfit_desc *acpi_desc; +struct nfit_mem *nfit_mem; + +mutex_lock (&acpi_desc_lock); +list_for_each_entry (acpi_desc, &acpi_descs, list) { +mutex_lock (&acpi_desc->init_mutex); +list_for_each_entry (nfit_mem, &acpi_desc->dimms, list) { + memdev =__to_nfit_memdev (nfit_mem); +if (memdev->device_handle == device_handle) { +mutex_unlock (&acpi_desc->init_mutex); +mutex_unlock (&acpi_desc_lock); + *flags = memdev->flags; +return memdev->physical_id; + } + } +mutex_unlock (&acpi_desc->init_mutex); + } +mutex_unlock (&acpi_desc_lock); + +return -ENODEV ; +} +EXPORT_SYMBOL_GPL (nfit_get_smbios_id); +/* * An implementation may provide a truncated control region if no block windows * are defined.
include/acpi/nfit.h new file +19 -0
@@ -0,0 +1,19 @@ +/* +* Copyright(c) 2017 Intel Corporation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +*/ + +#ifndef __ACPI_NFIT_H +#define __ACPI_NFIT_H + +int nfit_get_smbios_id (u32 device_handle,u16 *flags); + +#endif /* __ACPI_NFIT_H */
Signature · 6 lines
2.14.1 _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
Tony Luck
maintainerRFC PATCH 2/4 firmware: dmi: Add function to look up a handle and return DIMM size
In reply to Tony LuckWhen we first scan the SMBIOS table, save the size of the DIMM.
Provide a function for other code (EDAC driver) to look up the size of a DIMM from its SMBIOS handle.
--- drivers/firmware/dmi_scan.c | 29 +++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 31 insertions(+)
drivers/firmware/dmi_scan.c +29 -0
@@ -37,6 +37,7 @@ static char dmi_ids_string[128] __initdata;static struct dmi_memdev_info {const char *device;const char *bank; +u64 size;u16 handle; } *dmi_memdev;static int dmi_memdev_nr;
@@ -395,6 +396,8 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v) {const char *d = (const char *)dm;static int nr; +u64 bytes; +u16 size;if (dm->type !=DMI_ENTRY_MEM_DEVICE || dm->length <0x12 )return ;
@@ -405,6 +408,18 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v) dmi_memdev[nr].handle =get_unaligned (&dm->handle); dmi_memdev[nr].device =dmi_string (dm, d[0x10 ]); dmi_memdev[nr].bank =dmi_string (dm, d[0x11 ]); + size =get_unaligned ((u16 *)&d[0xC ]); +if (size ==0 ) + bytes =0 ; +else if (size ==0xffff ) + bytes = ~0ul ; +else if (size &0x8000 ) + bytes = (u64)(size &0x7fff ) <<10 ; +else if (size !=0x7fff ) + bytes = (u64 )size <<20 ; +else + bytes = (u64 )get_unaligned ((u32 *)&d[0x1C ]) <<20 ; + dmi_memdev[nr].size = bytes; nr++; }
@@ -1073,3 +1088,17 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } }EXPORT_SYMBOL_GPL (dmi_memdev_name); + +u64 dmi_memdev_size (u16 handle) +{ +int n; + +if (dmi_memdev) { +for (n =0 ; n < dmi_memdev_nr; n++) { +if (handle == dmi_memdev[n].handle) +return dmi_memdev[n].size; + } + } +return ~0ul ; +} +EXPORT_SYMBOL_GPL (dmi_memdev_size);
include/linux/dmi.h +2 -0
@@ -113,6 +113,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *), void *private_data);extern bool dmi_match (enum dmi_field f,const char *str);extern void dmi_memdev_name (u16 handle,const char **bank,const char **device); +extern u64 dmi_memdev_size (u16 handle);#else
@@ -142,6 +143,7 @@ static inline bool dmi_match(enum dmi_field f, const char *str) {return false; }static inline void dmi_memdev_name (u16 handle,const char **bank,const char **device) { } +static inline u64 dmi_memdev_size (u16 handle) {return ~0ul ; }static inline const struct dmi_system_id *dmi_first_match (const struct dmi_system_id *list) {return NULL ; }
Signature · 6 lines
2.14.1 _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
Borislav Petkov
maintainerRe: [RFC PATCH 2/4] firmware: dmi: Add function to look up a handle and return DIMM size
Quoted 33 lines · Tony Luck
When we first scan the SMBIOS table, save the size of the DIMM.
Provide a function for other code (EDAC driver) to look up the size of a DIMM from its SMBIOS handle.
Signed-off-by Tony Luck <[email protected]>--- drivers/firmware/dmi_scan.c | 29 +++++++++++++++++++++++++++++ include/linux/dmi.h | 2 ++ 2 files changed, 31 insertions(+)drivers/firmware/dmi_scan.c +3
-0@@ -37,6 +37,7 @@ static char dmi_ids_string[128] __initdata;static struct dmi_memdev_info {const char *device;const char *bank; +u64 size;u16 handle; } *dmi_memdev;static int dmi_memdev_nr;@@ -395,6 +396,8 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v) {const char *d = (const char *)dm;static int nr; +u64 bytes; +u16 size;if (dm->type !=DMI_ENTRY_MEM_DEVICE || dm->length <0x12 )return ;
drivers/firmware/dmi_scan.c static void __init save_mem_devices(const struct dmi_header *dm, void *v) · line 410
Quoted 3 lines
drivers/firmware/dmi_scan.c +0
-0@@ -405,6 +408,18 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v) dmi_memdev[nr].handle =get_unaligned (&dm->handle); dmi_memdev[nr].device =dmi_string (dm, d[0x10 ]); dmi_memdev[nr].bank =dmi_string (dm, d[0x11 ]);
<---- newline here.
drivers/firmware/dmi_scan.c static void __init save_mem_devices(const struct dmi_header *dm, void *v) · line 421
Quoted 11 lines
drivers/firmware/dmi_scan.c +11
-0+ size =get_unaligned ((u16 *)&d[0xC ]); +if (size ==0 ) + bytes =0 ; +else if (size ==0xffff ) + bytes = ~0ul ; +else if (size &0x8000 ) + bytes = (u64)(size &0x7fff ) <<10 ; +else if (size !=0x7fff ) + bytes = (u64 )size <<20 ; +else + bytes = (u64 )get_unaligned ((u32 *)&d[0x1C ]) <<20 ;
<---- newline here.
Quoted 11 lines
drivers/firmware/dmi_scan.c +4
-0+ dmi_memdev[nr].size = bytes; nr++; }@@ -1073,3 +1088,17 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device) } }EXPORT_SYMBOL_GPL (dmi_memdev_name); + +u64 dmi_memdev_size (u16 handle) +{
drivers/firmware/dmi_scan.c void dmi_memdev_name(u16 handle, const char **bank, const char **device) · line 1103
Quoted 10 lines
drivers/firmware/dmi_scan.c +10
-0+int n; + +if (dmi_memdev) { +for (n =0 ; n < dmi_memdev_nr; n++) { +if (handle == dmi_memdev[n].handle) +return dmi_memdev[n].size; + } + } +return ~0ul ; +}
So dmi_memdev_name() also loops over dmi_memdev and returns bank and device. This new function returns size.
If code is going to be calling those one after the other, you could do a
dmi_memdev_desc(u16 handle, struct memdev_desc *desc)
which fills up a descriptor with all fields a caller would need in one go so that you don't have to iterate multiple times. Looking at struct dmi_memdev_info, there are no more fields so maybe this is probably silly though or you can simply return struct dmi_memdev_info directly...
Meh.
Signature · 8 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimmLuck, Tony
maintainerRe: [RFC PATCH 2/4] firmware: dmi: Add function to look up a handle and return DIMM size
Quoted 5 lines · Borislav Petkov
Quoted 1 line · Tony Luck
dmi_memdev[nr].bank =
dmi_string(dm, d[0x11]);<---- newline here.
Quoted 13 lines
drivers/firmware/dmi_scan.c static void __init save_mem_devices(const struct dmi_header *dm, void *v) · line 421
Quoted 11 lines
drivers/firmware/dmi_scan.c +11
-0+ size =get_unaligned ((u16 *)&d[0xC ]); +if (size ==0 ) + bytes =0 ; +else if (size ==0xffff ) + bytes = ~0ul ; +else if (size &0x8000 ) + bytes = (u64)(size &0x7fff ) <<10 ; +else if (size !=0x7fff ) + bytes = (u64 )size <<20 ; +else + bytes = (u64 )get_unaligned ((u32 *)&d[0x1C ]) <<20 ;<---- newline here.
Ok ... it does read better with those breaks. Will add.
Quoted 6 lines
So
dmi_memdev_name()also loops overdmi_memdevand returns bank and device. This new function returns size.If code is going to be calling those one after the other, you could do a
dmi_memdev_desc(u16 handle, struct memdev_desc *desc)
Current callers are from different code paths (dmi_memdev_name() from ghes and EFI, dmi_memdev_size() just from the Skylake EDAC driver). If we later find a place that calls both this would be a good cleanup.
Quoted 6 lines
which fills up a descriptor with all fields a caller would need in one go so that you don't have to iterate multiple times. Looking at struct
dmi_memdev_info, there are no more fields so maybe this is probably silly though or you can simply return structdmi_memdev_infodirectly...Meh.
I take it that you talked yourself out of asking for the cleanup now?
-Tony
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
Borislav Petkov
maintainerRe: [RFC PATCH 2/4] firmware: dmi: Add function to look up a handle and return DIMM size
Quoted 1 line · Tony
I take it that you talked yourself out of asking for the cleanup now?
:-)
Nah, it was just a thinking-out-loud thing. Doesn't make sense to do the cleanup, it seems.
Signature · 8 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimmTony Luck
maintainerRFC PATCH 3/4 edac: Add new memory type for non-volatile DIMMs
In reply to Tony LuckThere are now non-volatile versions of DIMMs. Add a new entry to "enum mem_type" and update places that use it with new strings.
--- drivers/edac/edac_mc.c | 1 + drivers/edac/edac_mc_sysfs.c | 3 ++- include/linux/edac.h | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-)
drivers/edac/edac_mc.c +1 -0
@@ -215,6 +215,7 @@ const char * const edac_mem_types[] = { [MEM_LRDDR3] = "Load-Reduced DDR3 RAM", [MEM_DDR4] = "Unbuffered DDR4 RAM", [MEM_RDDR4] = "Registered DDR4 RAM", + [MEM_NVDIMM ] ="Non-volatile RAM" , };EXPORT_SYMBOL_GPL (edac_mem_types);
drivers/edac/edac_mc_sysfs.c +2 -1
@@ -110,7 +110,8 @@ static const char * const mem_types[] = { [MEM_DDR3] = "Unbuffered-DDR3", [MEM_RDDR3] = "Registered-DDR3", [MEM_DDR4] = "Unbuffered-DDR4", - [MEM_RDDR4 ] ="Registered-DDR4" + [MEM_RDDR4] = "Registered-DDR4", + [MEM_NVDIMM] = "Non-volatile RAM", };static const char *const dev_types[] = {
include/linux/edac.h +3 -0
@@ -186,6 +186,7 @@ static inline char *mc_event_error_type(const unsigned int err_type)* @MEM_RDDR4: Registered DDR4 RAM * This is a variant of the DDR4 memories. * @MEM_LRDDR4: Load-Reduced DDR4 memory. +* @MEM_NVDIMM: Non-volatile RAM */ enum mem_type {MEM_EMPTY =0 ,
@@ -209,6 +210,7 @@ enum mem_type {MEM_DDR4 ,MEM_RDDR4 ,MEM_LRDDR4 , + MEM_NVDIMM, };#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
@@ -231,6 +233,7 @@ enum mem_type {#define MEM_FLAG_DDR4 BIT(MEM_DDR4)#define MEM_FLAG_RDDR4 BIT(MEM_RDDR4)#define MEM_FLAG_LRDDR4 BIT(MEM_LRDDR4) +#define MEM_FLAG_NVDIMM BIT(MEM_NVDIMM)/** * enum edac-type - Error Detection and Correction capabilities and mode
Signature · 6 lines
2.14.1 _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
Borislav Petkov
maintainerRe: [RFC PATCH 3/4] edac: Add new memory type for non-volatile DIMMs
Quoted 27 lines · Tony Luck
There are now non-volatile versions of DIMMs. Add a new entry to "enum
mem_type" and update places that use it with new strings.Signed-off-by Tony Luck <[email protected]>--- drivers/edac/edac_mc.c | 1 + drivers/edac/edac_mc_sysfs.c | 3 ++- include/linux/edac.h | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-)drivers/edac/edac_mc.c +1
-0@@ -215,6 +215,7 @@ const char * const edac_mem_types[] = { [MEM_LRDDR3] = "Load-Reduced DDR3 RAM", [MEM_DDR4] = "Unbuffered DDR4 RAM", [MEM_RDDR4] = "Registered DDR4 RAM", + [MEM_NVDIMM ] ="Non-volatile RAM" , };EXPORT_SYMBOL_GPL (edac_mem_types);drivers/edac/edac_mc_sysfs.c +0
-0
drivers/edac/edac_mc_sysfs.c static const char * const mem_types[] = { · line 115
Quoted 7 lines
drivers/edac/edac_mc_sysfs.c +2
-1@@ -110,7 +110,8 @@ static const char * const mem_types[] = { [MEM_DDR3] = "Unbuffered-DDR3", [MEM_RDDR3] = "Registered-DDR3", [MEM_DDR4] = "Unbuffered-DDR4", - [MEM_RDDR4] = "Registered-DDR4" + [MEM_RDDR4] = "Registered-DDR4", + [MEM_NVDIMM] = "Non-volatile RAM", };
WTF, there are *two* string arrays with memory types?! How did that happen?
Can you please remove that above in a prepatch and switch to edac_mem_types? Or should we switch to this mem_types array instead and kill edac_mem_types since former is visible in sysfs?
:-( Grrr.
Signature · 8 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimmLuck, Tony
maintainerRe: [RFC PATCH 3/4] edac: Add new memory type for non-volatile DIMMs
Quoted 9 lines · Borislav Petkov
On Thu, Nov 30, 2017 at 12:40:41PM -0800, Tony Luck wrote:
WTF, there are *two* string arrays with memory types?! How did that happen?Can you please remove that above in a prepatch and switch to
edac_mem_types? Or should we switch to thismem_typesarray instead and killedac_mem_typessince former is visible in sysfs?:-( Grrr.
Oops. I didn't stare hard enough as I walked the "grep" output to just blindly add a new case everywhere for the new type.
Need to resolve the differences:
1) MEM_LRDDR3 only appears in one of the tables
2) edac_mem_types[] is exported from edac_mc.c and used by two drivers
3) mem_types[] is static in edac_mc_sysfs.c, but values are visible to user via sysfs
4) Strings are different between the two :-(
Since the drivers that use edac_mem_types[] only do so in edac_dbg() output, I think it's safe to declare those strings as the non-canon ones.
So the plan: copy the strings from mem_types[] to edac_mem_types[] and then make edac_mc_sysfs.c pick up the exported list from edac_mc.c instead of having its own static version.
Both files have the same build scope:
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o
so there shouldn't be any weird dependency problems.
-Tony
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
Tony Luck
maintainerRFC PATCH 4/4 EDAC, skx_edac: Detect non-volatile DIMMs
In reply to Tony LuckThis just covers the topology function of the EDAC driver. We locate which DIMM slots are populated with NVDIMMs and query the NFIT and SMBIOS tables to get the size.
--- drivers/edac/Kconfig | 2 ++ drivers/edac/skx_edac.c | 56 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-)
drivers/edac/Kconfig +2 -0
@@ -232,6 +232,8 @@ config EDAC_SBRIDGE config EDAC_SKX tristate "Intel Skylake server Integrated MC" depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG + select DMI + select ACPI_NFIT help Support for error detection and correction the Intel Skylake server Integrated Memory Controllers.
drivers/edac/skx_edac.c +51 -5
110 lines not on this page · raw message
Signature · 6 lines
2.14.1 _______________________________________________ Linux-nvdimm mailing list [email protected] https://lists.01.org/mailman/listinfo/linux-nvdimm
A message that is not in the archive (sent off-list or not yet received): da4c989314e82ec29195804ba5349ac3136f74c0.1512070562.git.tony.luck-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Re: [RFC PATCH 4/4] EDAC, skx_edac: Detect non-volatile DIMMs
Quoted 15 lines · Tony Luck
This just covers the topology function of the EDAC driver. We locate which DIMM slots are populated with NVDIMMs and query the NFIT and SMBIOS tables to get the size.
Signed-off-by Tony Luck <[email protected]>--- drivers/edac/Kconfig | 2 ++ drivers/edac/skx_edac.c | 56 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 5 deletions(-)drivers/edac/Kconfig +0
-0
drivers/edac/Kconfig config EDAC_SBRIDGE · line 236
Quoted 5 lines
drivers/edac/Kconfig +2
-0@@ -232,6 +232,8 @@ config EDAC_SBRIDGE config EDAC_SKX tristate "Intel Skylake server Integrated MC" depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG + select DMI + select ACPI_NFIT
Hmm, that ACPI_NFIT depends on a bunch of stuff and enabling EDAC_SKX would pull in all that. Should we make this a user choice instead?
I mean, there could be boxes which don't have nvdimms so all that code would be dead weight there...
Quoted 51 lines
drivers/edac/Kconfig +0
-0help Support for error detection and correction the Intel Skylake server Integrated Memory Controllers.drivers/edac/skx_edac.c +10
-2@@ -14,6 +14,8 @@#include <linux/module.h> #include <linux/init.h> +#include <linux/acpi.h> +#include <linux/dmi.h> #include <linux/pci.h> #include <linux/pci_ids.h> #include <linux/slab.h> @@ -24,6 +26,7 @@#include <linux/bitmap.h> #include <linux/math64.h> #include <linux/mod_devicetable.h> +#include <acpi/nfit.h> #include <asm/cpu_device_id.h> #include <asm/intel-family.h> #include <asm/processor.h> @@ -298,6 +301,7 @@ static int get_dimm_attr(u32 reg, int lobit, int hibit, int add, int minval, }#define IS_DIMM_PRESENT (mtr) GET_BITFIELD((mtr), 15, 15) +#define IS_NVDIMM_PRESENT (mcddrtcfg, i) GET_BITFIELD((mcddrtcfg), (i), (i))#define numrank (reg) get_dimm_attr((reg), 12, 13, 0, 1, 2, "ranks")#define numrow (reg) get_dimm_attr((reg), 2, 4, 12, 1, 6, "rows")@@ -346,8 +350,6 @@ static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,int banks =16 , ranks, rows, cols, npages;u64 size; -if (!IS_DIMM_PRESENT (mtr)) -return 0 ; ranks =numrank (mtr); rows =numrow (mtr); cols =numcol (mtr);@@ -379,6 +381,46 @@ static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,return 1 ; } +static int get_nvdimm_info (struct dimm_info *dimm,struct skx_imc *imc, +int chan,int dimmno) +{ +int smbios_handle; +u32 dev_handle; +u16 flags;
drivers/edac/skx_edac.c static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, · line 399
Quoted 10 lines
drivers/edac/skx_edac.c +10
-0+u64 size; + + dev_handle =ACPI_NFIT_BUILD_DEVICE_HANDLE (dimmno, chan, imc->lmc, + imc->src_id,0 ); + + smbios_handle =nfit_get_smbios_id (dev_handle, &flags); +if (smbios_handle <0 ) { +skx_printk (KERN_ERR ,"Can't find handle for NVDIMM ADR=%x\n" , dev_handle); +return 0 ; + }
<---- newline here.
drivers/edac/skx_edac.c static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, · line 403
Quoted 4 lines
drivers/edac/skx_edac.c +4
-0+if (flags &ACPI_NFIT_MEM_MAP_FAILED ) { +skx_printk (KERN_ERR ,"NVDIMM ADR=%x is not mapped\n" , dev_handle); +return 0 ; + }
<---- newline here.
drivers/edac/skx_edac.c static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, · line 409
Quoted 6 lines
drivers/edac/skx_edac.c +6
-0+ size =dmi_memdev_size (smbios_handle); +if (size == ~0ul ) { +skx_printk (KERN_ERR ,"Can't find size for NVDIMM ADR=%x/SMBIOS=%x\n" , + dev_handle, smbios_handle); +return 0 ; + }
Ditto.
drivers/edac/skx_edac.c static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, · line 417
Quoted 8 lines
drivers/edac/skx_edac.c +8
-0+edac_dbg (0 ,"mc#%d: channel %d, dimm %d, %lld Mb (%lld pages)\n" , + imc->mc, chan, dimmno, size >>20 , size >>PAGE_SHIFT ); + + dimm->nr_pages = size >>PAGE_SHIFT ; + dimm->grain =32 ; + dimm->dtype =DEV_UNKNOWN ; + dimm->mtype =MEM_NVDIMM ; + dimm->edac_mode =EDAC_SECDED ;/* likely better than this */
Ditto.
/me hands aegl a bunch of newlines - seems he's all out of \n's
Quoted 8 lines
drivers/edac/skx_edac.c +6
-0+snprintf (dimm->label,sizeof (dimm->label),"CPU_SrcID#%u_MC#%u_Chan#%u_DIMM#%u" , + imc->src_id, imc->lmc, chan, dimmno); + +return 1 ; +} +#define SKX_GET_MTMTR (dev, reg) \ pci_read_config_dword((dev), 0x87c, ®)
Signature · 8 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimmA message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [RFC PATCH 4/4] EDAC, skx_edac: Detect non-volatile DIMMs
Quoted 10 lines · Borislav Petkov
drivers/edac/Kconfig config EDAC_SBRIDGE · line 236
Quoted 5 lines · Tony Luck
config
EDAC_SKXdrivers/edac/Kconfig +2
-0tristate "Intel Skylake server Integrated MC" depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG + select DMI + select ACPI_NFITHmm, that
ACPI_NFITdepends on a bunch of stuff and enablingEDAC_SKXwould pull in all that. Should we make this a user choice instead?
Quoted 2 lines
I mean, there could be boxes which don't have nvdimms so all that code would be dead weight there...
I could. But what happens when someone ends up on a system with an edac driver configured without ACPI_NFIT that does have NVDIMMs?
I can make a stub version of nfit_get_smbios_id() that returns some error code ... and have the EDAC driver report size==0.
Would that be OK?
Quoted 22 lines
<---- newline here.
drivers/edac/skx_edac.c static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, · line 409
Quoted 6 lines
drivers/edac/skx_edac.c +6
-0+ size =dmi_memdev_size (smbios_handle); +if (size == ~0ul ) { +skx_printk (KERN_ERR ,"Can't find size for NVDIMM ADR=%x/SMBIOS=%x\n" , + dev_handle, smbios_handle); +return 0 ; + }Ditto.
drivers/edac/skx_edac.c static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, · line 417
Quoted 8 lines
drivers/edac/skx_edac.c +8
-0+edac_dbg (0 ,"mc#%d: channel %d, dimm %d, %lld Mb (%lld pages)\n" , + imc->mc, chan, dimmno, size >>20 , size >>PAGE_SHIFT ); + + dimm->nr_pages = size >>PAGE_SHIFT ; + dimm->grain =32 ; + dimm->dtype =DEV_UNKNOWN ; + dimm->mtype =MEM_NVDIMM ; + dimm->edac_mode =EDAC_SECDED ;/* likely better than this */ Ditto.
Quoted 1 line
/me hands aegl a bunch of newlines - seems he's all out of \n's
/me finds that the "Enter" key on his keyboard will put in a newline. Hurrah! now I don't have to copy/paste them from Boris.
-Tony
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
Borislav Petkov
maintainerRe: [RFC PATCH 4/4] EDAC, skx_edac: Detect non-volatile DIMMs
Quoted 2 lines · Tony
I could. But what happens when someone ends up on a system with an edac driver configured without
ACPI_NFITthat does have NVDIMMs?
Same thing when you land on a system with a kernel where the driver for a piece of hw is not enabled. I mean, this won't be an issue on distros as there *everything* is enabled but for tailored configs, where people want skx_edac but don't need the nvdimm part.
Quoted 4 lines
I can make a stub version of
nfit_get_smbios_id()that returns some error code ... and have the EDAC driver report size==0.Would that be OK?
Sure, thanks!
Quoted 2 lines
/me finds that the "Enter" key on his keyboard will put in a newline. Hurrah! now I don't have to copy/paste them from Boris.
Cheers! :-)))
Signature · 8 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimmA message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [RFC PATCH 4/4] EDAC, skx_edac: Detect non-volatile DIMMs
Quoted 9 lines · Borislav Petkov
Quoted 2 lines · Tony
I could. But what happens when someone ends up on a system with an edac driver configured without
ACPI_NFITthat does have NVDIMMs?Same thing when you land on a system with a kernel where the driver for a piece of hw is not enabled. I mean, this won't be an issue on distros as there *everything* is enabled but for tailored configs, where people want
skx_edacbut don't need the nvdimm part.
Quoted 6 lines
Quoted 4 lines
I can make a stub version of
nfit_get_smbios_id()that returns some error code ... and have the EDAC driver report size==0.Would that be OK?
Sure, thanks!
So this is what that would look like (on top of existing patches, but would be folded into them for next version):
drivers/edac/Kconfig +3 -2
@@ -233,10 +233,11 @@ config EDAC_SKX tristate "Intel Skylake server Integrated MC" depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG select DMI - select ACPI_NFIT help Support for error detection and correction the Intel - Skylake server Integrated Memory Controllers. + Skylake server Integrated Memory Controllers. If your + has non-volatile DIMMs you should also manually select + CONFIG_ACPI_NFIT config EDAC_PND2 tristate "Intel Pondicherry2"
drivers/edac/skx_edac.c +6 -1
@@ -387,12 +387,16 @@ static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,int smbios_handle;u32 dev_handle;u16 flags; -u64 size; +u64 size =0 ; dev_handle =ACPI_NFIT_BUILD_DEVICE_HANDLE (dimmno, chan, imc->lmc, imc->src_id,0 ); smbios_handle =nfit_get_smbios_id (dev_handle, &flags); +if (smbios_handle == -EOPNOTSUPP ) { +pr_warn_once ("skx_edac: can't find size of NVDIMM\n" ); + goto unknown_size; + }if (smbios_handle <0 ) {skx_printk (KERN_ERR ,"Can't find handle for NVDIMM ADR=%x\n" , dev_handle);return 0 ;
@@ -410,6 +414,7 @@ static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,return 0 ; } +unknown_size:edac_dbg (0 ,"mc#%d: channel %d, dimm %d, %lld Mb (%lld pages)\n" , imc->mc, chan, dimmno, size >>20 , size >>PAGE_SHIFT );
include/acpi/nfit.h +7 -0
@@ -14,6 +14,13 @@#ifndef __ACPI_NFIT_H#define __ACPI_NFIT_H +#if defined(CONFIG_ACPI_NFIT ) || defined(CONFIG_ACPI_NFIT_MODULE )int nfit_get_smbios_id (u32 device_handle,u16 *flags); +#else +static inline int nfit_get_smbios_id (u32 device_handle,u16 *flags) +{ +return -EOPNOTSUPP ; +} +#endif #endif /* __ACPI_NFIT_H */
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm
Borislav Petkov
maintainerRe: [RFC PATCH 4/4] EDAC, skx_edac: Detect non-volatile DIMMs
Quoted 28 lines · Tony
So this is what that would look like (on top of existing patches, but would be folded into them for next version):
drivers/edac/Kconfig +3
-2@@ -233,10 +233,11 @@ config EDAC_SKX tristate "Intel Skylake server Integrated MC" depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG select DMI - select ACPI_NFIT help Support for error detection and correction the Intel - Skylake server Integrated Memory Controllers. + Skylake server Integrated Memory Controllers. If your + has non-volatile DIMMs you should also manually select + CONFIG_ACPI_NFIT config EDAC_PND2 tristate "Intel Pondicherry2"drivers/edac/skx_edac.c +0
-0@@ -387,12 +387,16 @@ static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,int smbios_handle;u32 dev_handle;
drivers/edac/skx_edac.c static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc, · line 397
Quoted 10 lines
drivers/edac/skx_edac.c +3
-1u16 flags; -u64 size; +u64 size =0 ; dev_handle =ACPI_NFIT_BUILD_DEVICE_HANDLE (dimmno, chan, imc->lmc, imc->src_id,0 ); smbios_handle =nfit_get_smbios_id (dev_handle, &flags); +if (smbios_handle == -EOPNOTSUPP ) { +pr_warn_once ("skx_edac: can't find size of NVDIMM\n" );
" ... find size of NVDIMM. Try enabling CONFIG_ACPI_NFIT.\n"
to make it a bit more user-friendly.
Looks ok, otherwise.
Thx.
Signature · 8 lines
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm