aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-05 17:21:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-05 17:21:13 -0400
commitdd972f924df6bdbc0ab185a38d5d2361dbc26311 (patch)
tree181c24478ae55284f7baee88c3cf794794467aa2
parent3c8ba0d61d04ced9f8d9ff93977995a9e4e96e91 (diff)
parent6fd052665274b4e7570491ba272f2dbb09cbbcd5 (diff)
Merge tag 'edac_for_4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
Pull EDAC updates from Borislav Petkov: "Noteworthy is the NVDIMM support: - NVDIMM support to EDAC (Tony Luck) - misc fixes" * tag 'edac_for_4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp: EDAC, sb_edac: Remove variable length array usage EDAC, skx_edac: Detect non-volatile DIMMs firmware, DMI: Add function to look up a handle and return DIMM size acpi, nfit: Add function to look up nvdimm device and provide SMBIOS handle EDAC: Add new memory type for non-volatile DIMMs EDAC: Drop duplicated array of strings for memory type names EDAC, layerscape: Allow building for LS1021A
-rw-r--r--drivers/acpi/nfit/core.c27
-rw-r--r--drivers/edac/Kconfig7
-rw-r--r--drivers/edac/edac_mc.c41
-rw-r--r--drivers/edac/edac_mc_sysfs.c26
-rw-r--r--drivers/edac/sb_edac.c12
-rw-r--r--drivers/edac/skx_edac.c67
-rw-r--r--drivers/firmware/dmi_scan.c31
-rw-r--r--include/acpi/nfit.h18
-rw-r--r--include/linux/dmi.h2
-rw-r--r--include/linux/edac.h3
10 files changed, 175 insertions, 59 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index eb09ef55c38a..22a112b4f4d8 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -23,6 +23,7 @@
23#include <linux/io.h> 23#include <linux/io.h>
24#include <linux/nd.h> 24#include <linux/nd.h>
25#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
26#include <acpi/nfit.h>
26#include "nfit.h" 27#include "nfit.h"
27 28
28/* 29/*
@@ -690,6 +691,32 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
690 return true; 691 return true;
691} 692}
692 693
694int nfit_get_smbios_id(u32 device_handle, u16 *flags)
695{
696 struct acpi_nfit_memory_map *memdev;
697 struct acpi_nfit_desc *acpi_desc;
698 struct nfit_mem *nfit_mem;
699
700 mutex_lock(&acpi_desc_lock);
701 list_for_each_entry(acpi_desc, &acpi_descs, list) {
702 mutex_lock(&acpi_desc->init_mutex);
703 list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
704 memdev = __to_nfit_memdev(nfit_mem);
705 if (memdev->device_handle == device_handle) {
706 mutex_unlock(&acpi_desc->init_mutex);
707 mutex_unlock(&acpi_desc_lock);
708 *flags = memdev->flags;
709 return memdev->physical_id;
710 }
711 }
712 mutex_unlock(&acpi_desc->init_mutex);
713 }
714 mutex_unlock(&acpi_desc_lock);
715
716 return -ENODEV;
717}
718EXPORT_SYMBOL_GPL(nfit_get_smbios_id);
719
693/* 720/*
694 * An implementation may provide a truncated control region if no block windows 721 * An implementation may provide a truncated control region if no block windows
695 * are defined. 722 * are defined.
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index cfcb91056f23..da2da53bca6d 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -232,9 +232,12 @@ config EDAC_SBRIDGE
232config EDAC_SKX 232config EDAC_SKX
233 tristate "Intel Skylake server Integrated MC" 233 tristate "Intel Skylake server Integrated MC"
234 depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG 234 depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG
235 select DMI
235 help 236 help
236 Support for error detection and correction the Intel 237 Support for error detection and correction the Intel
237 Skylake server Integrated Memory Controllers. 238 Skylake server Integrated Memory Controllers. If your
239 system has non-volatile DIMMs you should also manually
240 select CONFIG_ACPI_NFIT.
238 241
239config EDAC_PND2 242config EDAC_PND2
240 tristate "Intel Pondicherry2" 243 tristate "Intel Pondicherry2"
@@ -254,7 +257,7 @@ config EDAC_MPC85XX
254 257
255config EDAC_LAYERSCAPE 258config EDAC_LAYERSCAPE
256 tristate "Freescale Layerscape DDR" 259 tristate "Freescale Layerscape DDR"
257 depends on ARCH_LAYERSCAPE 260 depends on ARCH_LAYERSCAPE || SOC_LS1021A
258 help 261 help
259 Support for error detection and correction on Freescale memory 262 Support for error detection and correction on Freescale memory
260 controllers on Layerscape SoCs. 263 controllers on Layerscape SoCs.
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 48193f5f3b56..3bb82e511eca 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -195,26 +195,27 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci)
195#endif /* CONFIG_EDAC_DEBUG */ 195#endif /* CONFIG_EDAC_DEBUG */
196 196
197const char * const edac_mem_types[] = { 197const char * const edac_mem_types[] = {
198 [MEM_EMPTY] = "Empty csrow", 198 [MEM_EMPTY] = "Empty",
199 [MEM_RESERVED] = "Reserved csrow type", 199 [MEM_RESERVED] = "Reserved",
200 [MEM_UNKNOWN] = "Unknown csrow type", 200 [MEM_UNKNOWN] = "Unknown",
201 [MEM_FPM] = "Fast page mode RAM", 201 [MEM_FPM] = "FPM",
202 [MEM_EDO] = "Extended data out RAM", 202 [MEM_EDO] = "EDO",
203 [MEM_BEDO] = "Burst Extended data out RAM", 203 [MEM_BEDO] = "BEDO",
204 [MEM_SDR] = "Single data rate SDRAM", 204 [MEM_SDR] = "Unbuffered-SDR",
205 [MEM_RDR] = "Registered single data rate SDRAM", 205 [MEM_RDR] = "Registered-SDR",
206 [MEM_DDR] = "Double data rate SDRAM", 206 [MEM_DDR] = "Unbuffered-DDR",
207 [MEM_RDDR] = "Registered Double data rate SDRAM", 207 [MEM_RDDR] = "Registered-DDR",
208 [MEM_RMBS] = "Rambus DRAM", 208 [MEM_RMBS] = "RMBS",
209 [MEM_DDR2] = "Unbuffered DDR2 RAM", 209 [MEM_DDR2] = "Unbuffered-DDR2",
210 [MEM_FB_DDR2] = "Fully buffered DDR2", 210 [MEM_FB_DDR2] = "FullyBuffered-DDR2",
211 [MEM_RDDR2] = "Registered DDR2 RAM", 211 [MEM_RDDR2] = "Registered-DDR2",
212 [MEM_XDR] = "Rambus XDR", 212 [MEM_XDR] = "XDR",
213 [MEM_DDR3] = "Unbuffered DDR3 RAM", 213 [MEM_DDR3] = "Unbuffered-DDR3",
214 [MEM_RDDR3] = "Registered DDR3 RAM", 214 [MEM_RDDR3] = "Registered-DDR3",
215 [MEM_LRDDR3] = "Load-Reduced DDR3 RAM", 215 [MEM_LRDDR3] = "Load-Reduced-DDR3-RAM",
216 [MEM_DDR4] = "Unbuffered DDR4 RAM", 216 [MEM_DDR4] = "Unbuffered-DDR4",
217 [MEM_RDDR4] = "Registered DDR4 RAM", 217 [MEM_RDDR4] = "Registered-DDR4",
218 [MEM_NVDIMM] = "Non-volatile-RAM",
218}; 219};
219EXPORT_SYMBOL_GPL(edac_mem_types); 220EXPORT_SYMBOL_GPL(edac_mem_types);
220 221
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index c70ea82c815c..7481955160a4 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -91,28 +91,6 @@ static struct device *mci_pdev;
91/* 91/*
92 * various constants for Memory Controllers 92 * various constants for Memory Controllers
93 */ 93 */
94static const char * const mem_types[] = {
95 [MEM_EMPTY] = "Empty",
96 [MEM_RESERVED] = "Reserved",
97 [MEM_UNKNOWN] = "Unknown",
98 [MEM_FPM] = "FPM",
99 [MEM_EDO] = "EDO",
100 [MEM_BEDO] = "BEDO",
101 [MEM_SDR] = "Unbuffered-SDR",
102 [MEM_RDR] = "Registered-SDR",
103 [MEM_DDR] = "Unbuffered-DDR",
104 [MEM_RDDR] = "Registered-DDR",
105 [MEM_RMBS] = "RMBS",
106 [MEM_DDR2] = "Unbuffered-DDR2",
107 [MEM_FB_DDR2] = "FullyBuffered-DDR2",
108 [MEM_RDDR2] = "Registered-DDR2",
109 [MEM_XDR] = "XDR",
110 [MEM_DDR3] = "Unbuffered-DDR3",
111 [MEM_RDDR3] = "Registered-DDR3",
112 [MEM_DDR4] = "Unbuffered-DDR4",
113 [MEM_RDDR4] = "Registered-DDR4"
114};
115
116static const char * const dev_types[] = { 94static const char * const dev_types[] = {
117 [DEV_UNKNOWN] = "Unknown", 95 [DEV_UNKNOWN] = "Unknown",
118 [DEV_X1] = "x1", 96 [DEV_X1] = "x1",
@@ -196,7 +174,7 @@ static ssize_t csrow_mem_type_show(struct device *dev,
196{ 174{
197 struct csrow_info *csrow = to_csrow(dev); 175 struct csrow_info *csrow = to_csrow(dev);
198 176
199 return sprintf(data, "%s\n", mem_types[csrow->channels[0]->dimm->mtype]); 177 return sprintf(data, "%s\n", edac_mem_types[csrow->channels[0]->dimm->mtype]);
200} 178}
201 179
202static ssize_t csrow_dev_type_show(struct device *dev, 180static ssize_t csrow_dev_type_show(struct device *dev,
@@ -549,7 +527,7 @@ static ssize_t dimmdev_mem_type_show(struct device *dev,
549{ 527{
550 struct dimm_info *dimm = to_dimm(dev); 528 struct dimm_info *dimm = to_dimm(dev);
551 529
552 return sprintf(data, "%s\n", mem_types[dimm->mtype]); 530 return sprintf(data, "%s\n", edac_mem_types[dimm->mtype]);
553} 531}
554 532
555static ssize_t dimmdev_dev_type_show(struct device *dev, 533static ssize_t dimmdev_dev_type_show(struct device *dev,
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 872100215ca0..4a89c8093307 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -110,6 +110,10 @@ static const u32 knl_interleave_list[] = {
110 0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */ 110 0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */
111 0x104, 0x10c, 0x114, 0x11c, /* 20-23 */ 111 0x104, 0x10c, 0x114, 0x11c, /* 20-23 */
112}; 112};
113#define MAX_INTERLEAVE \
114 (max_t(unsigned int, ARRAY_SIZE(sbridge_interleave_list), \
115 max_t(unsigned int, ARRAY_SIZE(ibridge_interleave_list), \
116 ARRAY_SIZE(knl_interleave_list))))
113 117
114struct interleave_pkg { 118struct interleave_pkg {
115 unsigned char start; 119 unsigned char start;
@@ -321,7 +325,6 @@ struct sbridge_info {
321 const u32 *interleave_list; 325 const u32 *interleave_list;
322 const struct interleave_pkg *interleave_pkg; 326 const struct interleave_pkg *interleave_pkg;
323 u8 max_sad; 327 u8 max_sad;
324 u8 max_interleave;
325 u8 (*get_node_id)(struct sbridge_pvt *pvt); 328 u8 (*get_node_id)(struct sbridge_pvt *pvt);
326 enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); 329 enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt);
327 enum dev_type (*get_width)(struct sbridge_pvt *pvt, u32 mtr); 330 enum dev_type (*get_width)(struct sbridge_pvt *pvt, u32 mtr);
@@ -1899,7 +1902,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
1899 int n_rir, n_sads, n_tads, sad_way, sck_xch; 1902 int n_rir, n_sads, n_tads, sad_way, sck_xch;
1900 int sad_interl, idx, base_ch; 1903 int sad_interl, idx, base_ch;
1901 int interleave_mode, shiftup = 0; 1904 int interleave_mode, shiftup = 0;
1902 unsigned sad_interleave[pvt->info.max_interleave]; 1905 unsigned int sad_interleave[MAX_INTERLEAVE];
1903 u32 reg, dram_rule; 1906 u32 reg, dram_rule;
1904 u8 ch_way, sck_way, pkg, sad_ha = 0; 1907 u8 ch_way, sck_way, pkg, sad_ha = 0;
1905 u32 tad_offset; 1908 u32 tad_offset;
@@ -3169,7 +3172,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
3169 pvt->info.dram_attr = dram_attr; 3172 pvt->info.dram_attr = dram_attr;
3170 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); 3173 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
3171 pvt->info.interleave_list = ibridge_interleave_list; 3174 pvt->info.interleave_list = ibridge_interleave_list;
3172 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
3173 pvt->info.interleave_pkg = ibridge_interleave_pkg; 3175 pvt->info.interleave_pkg = ibridge_interleave_pkg;
3174 pvt->info.get_width = ibridge_get_width; 3176 pvt->info.get_width = ibridge_get_width;
3175 3177
@@ -3194,7 +3196,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
3194 pvt->info.dram_attr = dram_attr; 3196 pvt->info.dram_attr = dram_attr;
3195 pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); 3197 pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
3196 pvt->info.interleave_list = sbridge_interleave_list; 3198 pvt->info.interleave_list = sbridge_interleave_list;
3197 pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
3198 pvt->info.interleave_pkg = sbridge_interleave_pkg; 3199 pvt->info.interleave_pkg = sbridge_interleave_pkg;
3199 pvt->info.get_width = sbridge_get_width; 3200 pvt->info.get_width = sbridge_get_width;
3200 3201
@@ -3219,7 +3220,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
3219 pvt->info.dram_attr = dram_attr; 3220 pvt->info.dram_attr = dram_attr;
3220 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); 3221 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
3221 pvt->info.interleave_list = ibridge_interleave_list; 3222 pvt->info.interleave_list = ibridge_interleave_list;
3222 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
3223 pvt->info.interleave_pkg = ibridge_interleave_pkg; 3223 pvt->info.interleave_pkg = ibridge_interleave_pkg;
3224 pvt->info.get_width = ibridge_get_width; 3224 pvt->info.get_width = ibridge_get_width;
3225 3225
@@ -3244,7 +3244,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
3244 pvt->info.dram_attr = dram_attr; 3244 pvt->info.dram_attr = dram_attr;
3245 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); 3245 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
3246 pvt->info.interleave_list = ibridge_interleave_list; 3246 pvt->info.interleave_list = ibridge_interleave_list;
3247 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
3248 pvt->info.interleave_pkg = ibridge_interleave_pkg; 3247 pvt->info.interleave_pkg = ibridge_interleave_pkg;
3249 pvt->info.get_width = broadwell_get_width; 3248 pvt->info.get_width = broadwell_get_width;
3250 3249
@@ -3269,7 +3268,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
3269 pvt->info.dram_attr = dram_attr_knl; 3268 pvt->info.dram_attr = dram_attr_knl;
3270 pvt->info.max_sad = ARRAY_SIZE(knl_dram_rule); 3269 pvt->info.max_sad = ARRAY_SIZE(knl_dram_rule);
3271 pvt->info.interleave_list = knl_interleave_list; 3270 pvt->info.interleave_list = knl_interleave_list;
3272 pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list);
3273 pvt->info.interleave_pkg = ibridge_interleave_pkg; 3271 pvt->info.interleave_pkg = ibridge_interleave_pkg;
3274 pvt->info.get_width = knl_get_width; 3272 pvt->info.get_width = knl_get_width;
3275 3273
diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c
index 912c4930c9ef..fae095162c01 100644
--- a/drivers/edac/skx_edac.c
+++ b/drivers/edac/skx_edac.c
@@ -14,6 +14,8 @@
14 14
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/acpi.h>
18#include <linux/dmi.h>
17#include <linux/pci.h> 19#include <linux/pci.h>
18#include <linux/pci_ids.h> 20#include <linux/pci_ids.h>
19#include <linux/slab.h> 21#include <linux/slab.h>
@@ -24,6 +26,7 @@
24#include <linux/bitmap.h> 26#include <linux/bitmap.h>
25#include <linux/math64.h> 27#include <linux/math64.h>
26#include <linux/mod_devicetable.h> 28#include <linux/mod_devicetable.h>
29#include <acpi/nfit.h>
27#include <asm/cpu_device_id.h> 30#include <asm/cpu_device_id.h>
28#include <asm/intel-family.h> 31#include <asm/intel-family.h>
29#include <asm/processor.h> 32#include <asm/processor.h>
@@ -302,6 +305,7 @@ static int get_dimm_attr(u32 reg, int lobit, int hibit, int add, int minval,
302} 305}
303 306
304#define IS_DIMM_PRESENT(mtr) GET_BITFIELD((mtr), 15, 15) 307#define IS_DIMM_PRESENT(mtr) GET_BITFIELD((mtr), 15, 15)
308#define IS_NVDIMM_PRESENT(mcddrtcfg, i) GET_BITFIELD((mcddrtcfg), (i), (i))
305 309
306#define numrank(reg) get_dimm_attr((reg), 12, 13, 0, 0, 2, "ranks") 310#define numrank(reg) get_dimm_attr((reg), 12, 13, 0, 0, 2, "ranks")
307#define numrow(reg) get_dimm_attr((reg), 2, 4, 12, 1, 6, "rows") 311#define numrow(reg) get_dimm_attr((reg), 2, 4, 12, 1, 6, "rows")
@@ -350,8 +354,6 @@ static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
350 int banks = 16, ranks, rows, cols, npages; 354 int banks = 16, ranks, rows, cols, npages;
351 u64 size; 355 u64 size;
352 356
353 if (!IS_DIMM_PRESENT(mtr))
354 return 0;
355 ranks = numrank(mtr); 357 ranks = numrank(mtr);
356 rows = numrow(mtr); 358 rows = numrow(mtr);
357 cols = numcol(mtr); 359 cols = numcol(mtr);
@@ -383,6 +385,54 @@ static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
383 return 1; 385 return 1;
384} 386}
385 387
388static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
389 int chan, int dimmno)
390{
391 int smbios_handle;
392 u32 dev_handle;
393 u16 flags;
394 u64 size = 0;
395
396 dev_handle = ACPI_NFIT_BUILD_DEVICE_HANDLE(dimmno, chan, imc->lmc,
397 imc->src_id, 0);
398
399 smbios_handle = nfit_get_smbios_id(dev_handle, &flags);
400 if (smbios_handle == -EOPNOTSUPP) {
401 pr_warn_once(EDAC_MOD_STR ": Can't find size of NVDIMM. Try enabling CONFIG_ACPI_NFIT\n");
402 goto unknown_size;
403 }
404
405 if (smbios_handle < 0) {
406 skx_printk(KERN_ERR, "Can't find handle for NVDIMM ADR=%x\n", dev_handle);
407 goto unknown_size;
408 }
409
410 if (flags & ACPI_NFIT_MEM_MAP_FAILED) {
411 skx_printk(KERN_ERR, "NVDIMM ADR=%x is not mapped\n", dev_handle);
412 goto unknown_size;
413 }
414
415 size = dmi_memdev_size(smbios_handle);
416 if (size == ~0ull)
417 skx_printk(KERN_ERR, "Can't find size for NVDIMM ADR=%x/SMBIOS=%x\n",
418 dev_handle, smbios_handle);
419
420unknown_size:
421 dimm->nr_pages = size >> PAGE_SHIFT;
422 dimm->grain = 32;
423 dimm->dtype = DEV_UNKNOWN;
424 dimm->mtype = MEM_NVDIMM;
425 dimm->edac_mode = EDAC_SECDED; /* likely better than this */
426
427 edac_dbg(0, "mc#%d: channel %d, dimm %d, %llu Mb (%u pages)\n",
428 imc->mc, chan, dimmno, size >> 20, dimm->nr_pages);
429
430 snprintf(dimm->label, sizeof(dimm->label), "CPU_SrcID#%u_MC#%u_Chan#%u_DIMM#%u",
431 imc->src_id, imc->lmc, chan, dimmno);
432
433 return (size == 0 || size == ~0ull) ? 0 : 1;
434}
435
386#define SKX_GET_MTMTR(dev, reg) \ 436#define SKX_GET_MTMTR(dev, reg) \
387 pci_read_config_dword((dev), 0x87c, &reg) 437 pci_read_config_dword((dev), 0x87c, &reg)
388 438
@@ -399,20 +449,24 @@ static int skx_get_dimm_config(struct mem_ctl_info *mci)
399{ 449{
400 struct skx_pvt *pvt = mci->pvt_info; 450 struct skx_pvt *pvt = mci->pvt_info;
401 struct skx_imc *imc = pvt->imc; 451 struct skx_imc *imc = pvt->imc;
452 u32 mtr, amap, mcddrtcfg;
402 struct dimm_info *dimm; 453 struct dimm_info *dimm;
403 int i, j; 454 int i, j;
404 u32 mtr, amap;
405 int ndimms; 455 int ndimms;
406 456
407 for (i = 0; i < NUM_CHANNELS; i++) { 457 for (i = 0; i < NUM_CHANNELS; i++) {
408 ndimms = 0; 458 ndimms = 0;
409 pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap); 459 pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap);
460 pci_read_config_dword(imc->chan[i].cdev, 0x400, &mcddrtcfg);
410 for (j = 0; j < NUM_DIMMS; j++) { 461 for (j = 0; j < NUM_DIMMS; j++) {
411 dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, 462 dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
412 mci->n_layers, i, j, 0); 463 mci->n_layers, i, j, 0);
413 pci_read_config_dword(imc->chan[i].cdev, 464 pci_read_config_dword(imc->chan[i].cdev,
414 0x80 + 4*j, &mtr); 465 0x80 + 4*j, &mtr);
415 ndimms += get_dimm_info(mtr, amap, dimm, imc, i, j); 466 if (IS_DIMM_PRESENT(mtr))
467 ndimms += get_dimm_info(mtr, amap, dimm, imc, i, j);
468 else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
469 ndimms += get_nvdimm_info(dimm, imc, i, j);
416 } 470 }
417 if (ndimms && !skx_check_ecc(imc->chan[0].cdev)) { 471 if (ndimms && !skx_check_ecc(imc->chan[0].cdev)) {
418 skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc); 472 skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc);
@@ -468,13 +522,14 @@ static int skx_register_mci(struct skx_imc *imc)
468 pvt = mci->pvt_info; 522 pvt = mci->pvt_info;
469 pvt->imc = imc; 523 pvt->imc = imc;
470 524
471 mci->ctl_name = kasprintf(GFP_KERNEL, "Skylake Socket#%d IMC#%d", imc->node_id, imc->lmc); 525 mci->ctl_name = kasprintf(GFP_KERNEL, "Skylake Socket#%d IMC#%d",
526 imc->node_id, imc->lmc);
472 if (!mci->ctl_name) { 527 if (!mci->ctl_name) {
473 rc = -ENOMEM; 528 rc = -ENOMEM;
474 goto fail0; 529 goto fail0;
475 } 530 }
476 531
477 mci->mtype_cap = MEM_FLAG_DDR4; 532 mci->mtype_cap = MEM_FLAG_DDR4 | MEM_FLAG_NVDIMM;
478 mci->edac_ctl_cap = EDAC_FLAG_NONE; 533 mci->edac_ctl_cap = EDAC_FLAG_NONE;
479 mci->edac_cap = EDAC_FLAG_NONE; 534 mci->edac_cap = EDAC_FLAG_NONE;
480 mci->mod_name = EDAC_MOD_STR; 535 mci->mod_name = EDAC_MOD_STR;
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index e35c5e04c46a..6feeacbe4d97 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -32,6 +32,7 @@ static char dmi_ids_string[128] __initdata;
32static struct dmi_memdev_info { 32static struct dmi_memdev_info {
33 const char *device; 33 const char *device;
34 const char *bank; 34 const char *bank;
35 u64 size; /* bytes */
35 u16 handle; 36 u16 handle;
36} *dmi_memdev; 37} *dmi_memdev;
37static int dmi_memdev_nr; 38static int dmi_memdev_nr;
@@ -386,6 +387,8 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
386{ 387{
387 const char *d = (const char *)dm; 388 const char *d = (const char *)dm;
388 static int nr; 389 static int nr;
390 u64 bytes;
391 u16 size;
389 392
390 if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12) 393 if (dm->type != DMI_ENTRY_MEM_DEVICE || dm->length < 0x12)
391 return; 394 return;
@@ -396,6 +399,20 @@ static void __init save_mem_devices(const struct dmi_header *dm, void *v)
396 dmi_memdev[nr].handle = get_unaligned(&dm->handle); 399 dmi_memdev[nr].handle = get_unaligned(&dm->handle);
397 dmi_memdev[nr].device = dmi_string(dm, d[0x10]); 400 dmi_memdev[nr].device = dmi_string(dm, d[0x10]);
398 dmi_memdev[nr].bank = dmi_string(dm, d[0x11]); 401 dmi_memdev[nr].bank = dmi_string(dm, d[0x11]);
402
403 size = get_unaligned((u16 *)&d[0xC]);
404 if (size == 0)
405 bytes = 0;
406 else if (size == 0xffff)
407 bytes = ~0ull;
408 else if (size & 0x8000)
409 bytes = (u64)(size & 0x7fff) << 10;
410 else if (size != 0x7fff)
411 bytes = (u64)size << 20;
412 else
413 bytes = (u64)get_unaligned((u32 *)&d[0x1C]) << 20;
414
415 dmi_memdev[nr].size = bytes;
399 nr++; 416 nr++;
400} 417}
401 418
@@ -1085,3 +1102,17 @@ void dmi_memdev_name(u16 handle, const char **bank, const char **device)
1085 } 1102 }
1086} 1103}
1087EXPORT_SYMBOL_GPL(dmi_memdev_name); 1104EXPORT_SYMBOL_GPL(dmi_memdev_name);
1105
1106u64 dmi_memdev_size(u16 handle)
1107{
1108 int n;
1109
1110 if (dmi_memdev) {
1111 for (n = 0; n < dmi_memdev_nr; n++) {
1112 if (handle == dmi_memdev[n].handle)
1113 return dmi_memdev[n].size;
1114 }
1115 }
1116 return ~0ull;
1117}
1118EXPORT_SYMBOL_GPL(dmi_memdev_size);
diff --git a/include/acpi/nfit.h b/include/acpi/nfit.h
new file mode 100644
index 000000000000..86ed07c1200d
--- /dev/null
+++ b/include/acpi/nfit.h
@@ -0,0 +1,18 @@
1/*
2 * SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Intel Corporation
4 */
5
6#ifndef __ACPI_NFIT_H
7#define __ACPI_NFIT_H
8
9#if IS_ENABLED(CONFIG_ACPI_NFIT)
10int nfit_get_smbios_id(u32 device_handle, u16 *flags);
11#else
12static inline int nfit_get_smbios_id(u32 device_handle, u16 *flags)
13{
14 return -EOPNOTSUPP;
15}
16#endif
17
18#endif /* __ACPI_NFIT_H */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 6a86d8db16d9..c46fdb36700b 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -114,6 +114,7 @@ extern int dmi_walk(void (*decode)(const struct dmi_header *, void *),
114 void *private_data); 114 void *private_data);
115extern bool dmi_match(enum dmi_field f, const char *str); 115extern bool dmi_match(enum dmi_field f, const char *str);
116extern void dmi_memdev_name(u16 handle, const char **bank, const char **device); 116extern void dmi_memdev_name(u16 handle, const char **bank, const char **device);
117extern u64 dmi_memdev_size(u16 handle);
117 118
118#else 119#else
119 120
@@ -144,6 +145,7 @@ static inline bool dmi_match(enum dmi_field f, const char *str)
144 { return false; } 145 { return false; }
145static inline void dmi_memdev_name(u16 handle, const char **bank, 146static inline void dmi_memdev_name(u16 handle, const char **bank,
146 const char **device) { } 147 const char **device) { }
148static inline u64 dmi_memdev_size(u16 handle) { return ~0ul; }
147static inline const struct dmi_system_id * 149static inline const struct dmi_system_id *
148 dmi_first_match(const struct dmi_system_id *list) { return NULL; } 150 dmi_first_match(const struct dmi_system_id *list) { return NULL; }
149 151
diff --git a/include/linux/edac.h b/include/linux/edac.h
index cd75c173fd00..bffb97828ed6 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -186,6 +186,7 @@ static inline char *mc_event_error_type(const unsigned int err_type)
186 * @MEM_RDDR4: Registered DDR4 RAM 186 * @MEM_RDDR4: Registered DDR4 RAM
187 * This is a variant of the DDR4 memories. 187 * This is a variant of the DDR4 memories.
188 * @MEM_LRDDR4: Load-Reduced DDR4 memory. 188 * @MEM_LRDDR4: Load-Reduced DDR4 memory.
189 * @MEM_NVDIMM: Non-volatile RAM
189 */ 190 */
190enum mem_type { 191enum mem_type {
191 MEM_EMPTY = 0, 192 MEM_EMPTY = 0,
@@ -209,6 +210,7 @@ enum mem_type {
209 MEM_DDR4, 210 MEM_DDR4,
210 MEM_RDDR4, 211 MEM_RDDR4,
211 MEM_LRDDR4, 212 MEM_LRDDR4,
213 MEM_NVDIMM,
212}; 214};
213 215
214#define MEM_FLAG_EMPTY BIT(MEM_EMPTY) 216#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
@@ -231,6 +233,7 @@ enum mem_type {
231#define MEM_FLAG_DDR4 BIT(MEM_DDR4) 233#define MEM_FLAG_DDR4 BIT(MEM_DDR4)
232#define MEM_FLAG_RDDR4 BIT(MEM_RDDR4) 234#define MEM_FLAG_RDDR4 BIT(MEM_RDDR4)
233#define MEM_FLAG_LRDDR4 BIT(MEM_LRDDR4) 235#define MEM_FLAG_LRDDR4 BIT(MEM_LRDDR4)
236#define MEM_FLAG_NVDIMM BIT(MEM_NVDIMM)
234 237
235/** 238/**
236 * enum edac-type - Error Detection and Correction capabilities and mode 239 * enum edac-type - Error Detection and Correction capabilities and mode