diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-15 19:56:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-15 19:56:45 -0400 |
commit | 68ffeca4f40dcdfc04e7134b4667e268af6c0683 (patch) | |
tree | e7e9cebac321cbb7074ce665a2de0aa0cd724c0a | |
parent | c9d26423e56ce1ab4d786f92aebecf859d419293 (diff) | |
parent | 50d1bb93672fa2f42cec6e06ce799fbe864f57e9 (diff) |
Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac
Pull EDAC updates from Mauro Carvalho Chehab.
* 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac:
sb_edac: add support for Haswell based systems
sb_edac: Fix mix tab/spaces alignments
edac: add DDR4 and RDDR4
sb_edac: remove bogus assumption on mc ordering
sb_edac: make minimal use of channel_mask
sb_edac: fix socket detection on Ivy Bridge controllers
sb_edac: update Kconfig description
sb_edac: search devices using product id
sb_edac: make RIR limit retrieval per model
sb_edac: make node id retrieval per model
sb_edac: make memory type detection per memory controller
-rw-r--r-- | drivers/edac/Kconfig | 4 | ||||
-rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 4 | ||||
-rw-r--r-- | drivers/edac/sb_edac.c | 810 | ||||
-rw-r--r-- | include/linux/edac.h | 5 |
4 files changed, 551 insertions, 272 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index f8665f9c3e03..fd89ca982748 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -253,12 +253,12 @@ config EDAC_I7300 | |||
253 | Clarksboro MCH (Intel 7300 chipset). | 253 | Clarksboro MCH (Intel 7300 chipset). |
254 | 254 | ||
255 | config EDAC_SBRIDGE | 255 | config EDAC_SBRIDGE |
256 | tristate "Intel Sandy-Bridge Integrated MC" | 256 | tristate "Intel Sandy-Bridge/Ivy-Bridge/Haswell Integrated MC" |
257 | depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL | 257 | depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL |
258 | depends on PCI_MMCONFIG | 258 | depends on PCI_MMCONFIG |
259 | help | 259 | help |
260 | Support for error detection and correction the Intel | 260 | Support for error detection and correction the Intel |
261 | Sandy Bridge Integrated Memory Controller. | 261 | Sandy Bridge, Ivy Bridge and Haswell Integrated Memory Controllers. |
262 | 262 | ||
263 | config EDAC_MPC85XX | 263 | config EDAC_MPC85XX |
264 | tristate "Freescale MPC83xx / MPC85xx" | 264 | tristate "Freescale MPC83xx / MPC85xx" |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 01fae8289cf0..a6cd36100663 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -108,7 +108,9 @@ static const char * const mem_types[] = { | |||
108 | [MEM_RDDR2] = "Registered-DDR2", | 108 | [MEM_RDDR2] = "Registered-DDR2", |
109 | [MEM_XDR] = "XDR", | 109 | [MEM_XDR] = "XDR", |
110 | [MEM_DDR3] = "Unbuffered-DDR3", | 110 | [MEM_DDR3] = "Unbuffered-DDR3", |
111 | [MEM_RDDR3] = "Registered-DDR3" | 111 | [MEM_RDDR3] = "Registered-DDR3", |
112 | [MEM_DDR4] = "Unbuffered-DDR4", | ||
113 | [MEM_RDDR4] = "Registered-DDR4" | ||
112 | }; | 114 | }; |
113 | 115 | ||
114 | static const char * const dev_types[] = { | 116 | static const char * const dev_types[] = { |
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index deea0dc9999b..0034c4844428 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c | |||
@@ -99,6 +99,7 @@ static const u32 ibridge_dram_rule[] = { | |||
99 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) | 99 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) |
100 | #define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1) | 100 | #define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1) |
101 | #define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0) | 101 | #define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0) |
102 | #define A7MODE(reg) GET_BITFIELD(reg, 26, 26) | ||
102 | 103 | ||
103 | static char *get_dram_attr(u32 reg) | 104 | static char *get_dram_attr(u32 reg) |
104 | { | 105 | { |
@@ -164,6 +165,8 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, | |||
164 | 165 | ||
165 | #define TOLM 0x80 | 166 | #define TOLM 0x80 |
166 | #define TOHM 0x84 | 167 | #define TOHM 0x84 |
168 | #define HASWELL_TOHM_0 0xd4 | ||
169 | #define HASWELL_TOHM_1 0xd8 | ||
167 | 170 | ||
168 | #define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff) | 171 | #define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff) |
169 | #define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff) | 172 | #define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff) |
@@ -176,8 +179,6 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, | |||
176 | 179 | ||
177 | #define SAD_CONTROL 0xf4 | 180 | #define SAD_CONTROL 0xf4 |
178 | 181 | ||
179 | #define NODE_ID(reg) GET_BITFIELD(reg, 0, 2) | ||
180 | |||
181 | /* Device 14 function 0 */ | 182 | /* Device 14 function 0 */ |
182 | 183 | ||
183 | static const u32 tad_dram_rule[] = { | 184 | static const u32 tad_dram_rule[] = { |
@@ -235,7 +236,6 @@ static const u32 rir_way_limit[] = { | |||
235 | 236 | ||
236 | #define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31) | 237 | #define IS_RIR_VALID(reg) GET_BITFIELD(reg, 31, 31) |
237 | #define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29) | 238 | #define RIR_WAY(reg) GET_BITFIELD(reg, 28, 29) |
238 | #define RIR_LIMIT(reg) ((GET_BITFIELD(reg, 1, 10) << 29)| 0x1fffffff) | ||
239 | 239 | ||
240 | #define MAX_RIR_WAY 8 | 240 | #define MAX_RIR_WAY 8 |
241 | 241 | ||
@@ -279,8 +279,6 @@ static const u32 correrrthrsld[] = { | |||
279 | 279 | ||
280 | #define IB_RANK_CFG_A 0x0320 | 280 | #define IB_RANK_CFG_A 0x0320 |
281 | 281 | ||
282 | #define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11) | ||
283 | |||
284 | /* | 282 | /* |
285 | * sbridge structs | 283 | * sbridge structs |
286 | */ | 284 | */ |
@@ -291,6 +289,7 @@ static const u32 correrrthrsld[] = { | |||
291 | enum type { | 289 | enum type { |
292 | SANDY_BRIDGE, | 290 | SANDY_BRIDGE, |
293 | IVY_BRIDGE, | 291 | IVY_BRIDGE, |
292 | HASWELL, | ||
294 | }; | 293 | }; |
295 | 294 | ||
296 | struct sbridge_pvt; | 295 | struct sbridge_pvt; |
@@ -300,11 +299,15 @@ struct sbridge_info { | |||
300 | u32 rankcfgr; | 299 | u32 rankcfgr; |
301 | u64 (*get_tolm)(struct sbridge_pvt *pvt); | 300 | u64 (*get_tolm)(struct sbridge_pvt *pvt); |
302 | u64 (*get_tohm)(struct sbridge_pvt *pvt); | 301 | u64 (*get_tohm)(struct sbridge_pvt *pvt); |
302 | u64 (*rir_limit)(u32 reg); | ||
303 | const u32 *dram_rule; | 303 | const u32 *dram_rule; |
304 | const u32 *interleave_list; | 304 | const u32 *interleave_list; |
305 | const struct interleave_pkg *interleave_pkg; | 305 | const struct interleave_pkg *interleave_pkg; |
306 | u8 max_sad; | 306 | u8 max_sad; |
307 | u8 max_interleave; | 307 | u8 max_interleave; |
308 | u8 (*get_node_id)(struct sbridge_pvt *pvt); | ||
309 | enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); | ||
310 | struct pci_dev *pci_vtd; | ||
308 | }; | 311 | }; |
309 | 312 | ||
310 | struct sbridge_channel { | 313 | struct sbridge_channel { |
@@ -313,9 +316,7 @@ struct sbridge_channel { | |||
313 | }; | 316 | }; |
314 | 317 | ||
315 | struct pci_id_descr { | 318 | struct pci_id_descr { |
316 | int dev; | 319 | int dev_id; |
317 | int func; | ||
318 | int dev_id; | ||
319 | int optional; | 320 | int optional; |
320 | }; | 321 | }; |
321 | 322 | ||
@@ -338,6 +339,7 @@ struct sbridge_pvt { | |||
338 | struct pci_dev *pci_sad0, *pci_sad1; | 339 | struct pci_dev *pci_sad0, *pci_sad1; |
339 | struct pci_dev *pci_ha0, *pci_ha1; | 340 | struct pci_dev *pci_ha0, *pci_ha1; |
340 | struct pci_dev *pci_br0, *pci_br1; | 341 | struct pci_dev *pci_br0, *pci_br1; |
342 | struct pci_dev *pci_ha1_ta; | ||
341 | struct pci_dev *pci_tad[NUM_CHANNELS]; | 343 | struct pci_dev *pci_tad[NUM_CHANNELS]; |
342 | 344 | ||
343 | struct sbridge_dev *sbridge_dev; | 345 | struct sbridge_dev *sbridge_dev; |
@@ -362,31 +364,29 @@ struct sbridge_pvt { | |||
362 | u64 tolm, tohm; | 364 | u64 tolm, tohm; |
363 | }; | 365 | }; |
364 | 366 | ||
365 | #define PCI_DESCR(device, function, device_id, opt) \ | 367 | #define PCI_DESCR(device_id, opt) \ |
366 | .dev = (device), \ | 368 | .dev_id = (device_id), \ |
367 | .func = (function), \ | ||
368 | .dev_id = (device_id), \ | ||
369 | .optional = opt | 369 | .optional = opt |
370 | 370 | ||
371 | static const struct pci_id_descr pci_dev_descr_sbridge[] = { | 371 | static const struct pci_id_descr pci_dev_descr_sbridge[] = { |
372 | /* Processor Home Agent */ | 372 | /* Processor Home Agent */ |
373 | { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, | 373 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, |
374 | 374 | ||
375 | /* Memory controller */ | 375 | /* Memory controller */ |
376 | { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, | 376 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, |
377 | { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, | 377 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, |
378 | { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, | 378 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, |
379 | { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, | 379 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, |
380 | { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, | 380 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, |
381 | { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, | 381 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, |
382 | { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, | 382 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, |
383 | 383 | ||
384 | /* System Address Decoder */ | 384 | /* System Address Decoder */ |
385 | { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, | 385 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, |
386 | { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, | 386 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, |
387 | 387 | ||
388 | /* Broadcast Registers */ | 388 | /* Broadcast Registers */ |
389 | { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, | 389 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, |
390 | }; | 390 | }; |
391 | 391 | ||
392 | #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) } | 392 | #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) } |
@@ -423,34 +423,34 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { | |||
423 | 423 | ||
424 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { | 424 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { |
425 | /* Processor Home Agent */ | 425 | /* Processor Home Agent */ |
426 | { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, | 426 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, |
427 | 427 | ||
428 | /* Memory controller */ | 428 | /* Memory controller */ |
429 | { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, | 429 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, |
430 | { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, | 430 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, |
431 | { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, | 431 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, |
432 | { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, | 432 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, |
433 | { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, | 433 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, |
434 | { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, | 434 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, |
435 | 435 | ||
436 | /* System Address Decoder */ | 436 | /* System Address Decoder */ |
437 | { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, | 437 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, |
438 | 438 | ||
439 | /* Broadcast Registers */ | 439 | /* Broadcast Registers */ |
440 | { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, | 440 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, |
441 | { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, | 441 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, |
442 | 442 | ||
443 | /* Optional, mode 2HA */ | 443 | /* Optional, mode 2HA */ |
444 | { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, | 444 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, |
445 | #if 0 | 445 | #if 0 |
446 | { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, | 446 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, |
447 | { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, | 447 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, |
448 | #endif | 448 | #endif |
449 | { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, | 449 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, |
450 | { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, | 450 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, |
451 | 451 | ||
452 | { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, | 452 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, |
453 | { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, | 453 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, |
454 | }; | 454 | }; |
455 | 455 | ||
456 | static const struct pci_id_table pci_dev_descr_ibridge_table[] = { | 456 | static const struct pci_id_table pci_dev_descr_ibridge_table[] = { |
@@ -458,12 +458,80 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { | |||
458 | {0,} /* 0 terminated list. */ | 458 | {0,} /* 0 terminated list. */ |
459 | }; | 459 | }; |
460 | 460 | ||
461 | /* Haswell support */ | ||
462 | /* EN processor: | ||
463 | * - 1 IMC | ||
464 | * - 3 DDR3 channels, 2 DPC per channel | ||
465 | * EP processor: | ||
466 | * - 1 or 2 IMC | ||
467 | * - 4 DDR4 channels, 3 DPC per channel | ||
468 | * EP 4S processor: | ||
469 | * - 2 IMC | ||
470 | * - 4 DDR4 channels, 3 DPC per channel | ||
471 | * EX processor: | ||
472 | * - 2 IMC | ||
473 | * - each IMC interfaces with a SMI 2 channel | ||
474 | * - each SMI channel interfaces with a scalable memory buffer | ||
475 | * - each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC | ||
476 | */ | ||
477 | #define HASWELL_DDRCRCLKCONTROLS 0xa10 | ||
478 | #define HASWELL_HASYSDEFEATURE2 0x84 | ||
479 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28 | ||
480 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0 | ||
481 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1 0x2f60 | ||
482 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA 0x2fa8 | ||
483 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71 | ||
484 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA 0x2f68 | ||
485 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79 | ||
486 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc | ||
487 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd | ||
488 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa | ||
489 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 0x2fab | ||
490 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 0x2fac | ||
491 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 0x2fad | ||
492 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 0x2f6a | ||
493 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 0x2f6b | ||
494 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c | ||
495 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d | ||
496 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd | ||
497 | static const struct pci_id_descr pci_dev_descr_haswell[] = { | ||
498 | /* first item must be the HA */ | ||
499 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, | ||
500 | |||
501 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0) }, | ||
502 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0) }, | ||
503 | |||
504 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1) }, | ||
505 | |||
506 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0) }, | ||
507 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0) }, | ||
508 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0) }, | ||
509 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0) }, | ||
510 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1) }, | ||
511 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, | ||
512 | |||
513 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, | ||
514 | |||
515 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, | ||
516 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, | ||
517 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1) }, | ||
518 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1) }, | ||
519 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1) }, | ||
520 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1) }, | ||
521 | }; | ||
522 | |||
523 | static const struct pci_id_table pci_dev_descr_haswell_table[] = { | ||
524 | PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell), | ||
525 | {0,} /* 0 terminated list. */ | ||
526 | }; | ||
527 | |||
461 | /* | 528 | /* |
462 | * pci_device_id table for which devices we are looking for | 529 | * pci_device_id table for which devices we are looking for |
463 | */ | 530 | */ |
464 | static const struct pci_device_id sbridge_pci_tbl[] = { | 531 | static const struct pci_device_id sbridge_pci_tbl[] = { |
465 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, | 532 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, |
466 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, | 533 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, |
534 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)}, | ||
467 | {0,} /* 0 terminated list. */ | 535 | {0,} /* 0 terminated list. */ |
468 | }; | 536 | }; |
469 | 537 | ||
@@ -472,13 +540,17 @@ static const struct pci_device_id sbridge_pci_tbl[] = { | |||
472 | Ancillary status routines | 540 | Ancillary status routines |
473 | ****************************************************************************/ | 541 | ****************************************************************************/ |
474 | 542 | ||
475 | static inline int numrank(u32 mtr) | 543 | static inline int numrank(enum type type, u32 mtr) |
476 | { | 544 | { |
477 | int ranks = (1 << RANK_CNT_BITS(mtr)); | 545 | int ranks = (1 << RANK_CNT_BITS(mtr)); |
546 | int max = 4; | ||
478 | 547 | ||
479 | if (ranks > 4) { | 548 | if (type == HASWELL) |
480 | edac_dbg(0, "Invalid number of ranks: %d (max = 4) raw value = %x (%04x)\n", | 549 | max = 8; |
481 | ranks, (unsigned int)RANK_CNT_BITS(mtr), mtr); | 550 | |
551 | if (ranks > max) { | ||
552 | edac_dbg(0, "Invalid number of ranks: %d (max = %i) raw value = %x (%04x)\n", | ||
553 | ranks, max, (unsigned int)RANK_CNT_BITS(mtr), mtr); | ||
482 | return -EINVAL; | 554 | return -EINVAL; |
483 | } | 555 | } |
484 | 556 | ||
@@ -588,10 +660,107 @@ static u64 ibridge_get_tohm(struct sbridge_pvt *pvt) | |||
588 | return GET_TOHM(reg); | 660 | return GET_TOHM(reg); |
589 | } | 661 | } |
590 | 662 | ||
663 | static u64 rir_limit(u32 reg) | ||
664 | { | ||
665 | return ((u64)GET_BITFIELD(reg, 1, 10) << 29) | 0x1fffffff; | ||
666 | } | ||
667 | |||
668 | static enum mem_type get_memory_type(struct sbridge_pvt *pvt) | ||
669 | { | ||
670 | u32 reg; | ||
671 | enum mem_type mtype; | ||
672 | |||
673 | if (pvt->pci_ddrio) { | ||
674 | pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, | ||
675 | ®); | ||
676 | if (GET_BITFIELD(reg, 11, 11)) | ||
677 | /* FIXME: Can also be LRDIMM */ | ||
678 | mtype = MEM_RDDR3; | ||
679 | else | ||
680 | mtype = MEM_DDR3; | ||
681 | } else | ||
682 | mtype = MEM_UNKNOWN; | ||
683 | |||
684 | return mtype; | ||
685 | } | ||
686 | |||
687 | static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt) | ||
688 | { | ||
689 | u32 reg; | ||
690 | bool registered = false; | ||
691 | enum mem_type mtype = MEM_UNKNOWN; | ||
692 | |||
693 | if (!pvt->pci_ddrio) | ||
694 | goto out; | ||
695 | |||
696 | pci_read_config_dword(pvt->pci_ddrio, | ||
697 | HASWELL_DDRCRCLKCONTROLS, ®); | ||
698 | /* Is_Rdimm */ | ||
699 | if (GET_BITFIELD(reg, 16, 16)) | ||
700 | registered = true; | ||
701 | |||
702 | pci_read_config_dword(pvt->pci_ta, MCMTR, ®); | ||
703 | if (GET_BITFIELD(reg, 14, 14)) { | ||
704 | if (registered) | ||
705 | mtype = MEM_RDDR4; | ||
706 | else | ||
707 | mtype = MEM_DDR4; | ||
708 | } else { | ||
709 | if (registered) | ||
710 | mtype = MEM_RDDR3; | ||
711 | else | ||
712 | mtype = MEM_DDR3; | ||
713 | } | ||
714 | |||
715 | out: | ||
716 | return mtype; | ||
717 | } | ||
718 | |||
719 | static u8 get_node_id(struct sbridge_pvt *pvt) | ||
720 | { | ||
721 | u32 reg; | ||
722 | pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); | ||
723 | return GET_BITFIELD(reg, 0, 2); | ||
724 | } | ||
725 | |||
726 | static u8 haswell_get_node_id(struct sbridge_pvt *pvt) | ||
727 | { | ||
728 | u32 reg; | ||
729 | |||
730 | pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, ®); | ||
731 | return GET_BITFIELD(reg, 0, 3); | ||
732 | } | ||
733 | |||
734 | static u64 haswell_get_tolm(struct sbridge_pvt *pvt) | ||
735 | { | ||
736 | u32 reg; | ||
737 | |||
738 | pci_read_config_dword(pvt->info.pci_vtd, TOLM, ®); | ||
739 | return (GET_BITFIELD(reg, 26, 31) << 26) | 0x1ffffff; | ||
740 | } | ||
741 | |||
742 | static u64 haswell_get_tohm(struct sbridge_pvt *pvt) | ||
743 | { | ||
744 | u64 rc; | ||
745 | u32 reg; | ||
746 | |||
747 | pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_0, ®); | ||
748 | rc = GET_BITFIELD(reg, 26, 31); | ||
749 | pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, ®); | ||
750 | rc = ((reg << 6) | rc) << 26; | ||
751 | |||
752 | return rc | 0x1ffffff; | ||
753 | } | ||
754 | |||
755 | static u64 haswell_rir_limit(u32 reg) | ||
756 | { | ||
757 | return (((u64)GET_BITFIELD(reg, 1, 11) + 1) << 29) - 1; | ||
758 | } | ||
759 | |||
591 | static inline u8 sad_pkg_socket(u8 pkg) | 760 | static inline u8 sad_pkg_socket(u8 pkg) |
592 | { | 761 | { |
593 | /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ | 762 | /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ |
594 | return (pkg >> 3) | (pkg & 0x3); | 763 | return ((pkg >> 3) << 2) | (pkg & 0x3); |
595 | } | 764 | } |
596 | 765 | ||
597 | static inline u8 sad_pkg_ha(u8 pkg) | 766 | static inline u8 sad_pkg_ha(u8 pkg) |
@@ -602,44 +771,43 @@ static inline u8 sad_pkg_ha(u8 pkg) | |||
602 | /**************************************************************************** | 771 | /**************************************************************************** |
603 | Memory check routines | 772 | Memory check routines |
604 | ****************************************************************************/ | 773 | ****************************************************************************/ |
605 | static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot, | 774 | static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id) |
606 | unsigned func) | ||
607 | { | 775 | { |
608 | struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus); | 776 | struct pci_dev *pdev = NULL; |
609 | int i; | ||
610 | |||
611 | if (!sbridge_dev) | ||
612 | return NULL; | ||
613 | |||
614 | for (i = 0; i < sbridge_dev->n_devs; i++) { | ||
615 | if (!sbridge_dev->pdev[i]) | ||
616 | continue; | ||
617 | 777 | ||
618 | if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot && | 778 | do { |
619 | PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) { | 779 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev); |
620 | edac_dbg(1, "Associated %02x.%02x.%d with %p\n", | 780 | if (pdev && pdev->bus->number == bus) |
621 | bus, slot, func, sbridge_dev->pdev[i]); | 781 | break; |
622 | return sbridge_dev->pdev[i]; | 782 | } while (pdev); |
623 | } | ||
624 | } | ||
625 | 783 | ||
626 | return NULL; | 784 | return pdev; |
627 | } | 785 | } |
628 | 786 | ||
629 | /** | 787 | /** |
630 | * check_if_ecc_is_active() - Checks if ECC is active | 788 | * check_if_ecc_is_active() - Checks if ECC is active |
631 | * bus: Device bus | 789 | * @bus: Device bus |
790 | * @type: Memory controller type | ||
791 | * returns: 0 in case ECC is active, -ENODEV if it can't be determined or | ||
792 | * disabled | ||
632 | */ | 793 | */ |
633 | static int check_if_ecc_is_active(const u8 bus) | 794 | static int check_if_ecc_is_active(const u8 bus, enum type type) |
634 | { | 795 | { |
635 | struct pci_dev *pdev = NULL; | 796 | struct pci_dev *pdev = NULL; |
636 | u32 mcmtr; | 797 | u32 mcmtr, id; |
798 | |||
799 | if (type == IVY_BRIDGE) | ||
800 | id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA; | ||
801 | else if (type == HASWELL) | ||
802 | id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA; | ||
803 | else | ||
804 | id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA; | ||
637 | 805 | ||
638 | pdev = get_pdev_slot_func(bus, 15, 0); | 806 | pdev = get_pdev_same_bus(bus, id); |
639 | if (!pdev) { | 807 | if (!pdev) { |
640 | sbridge_printk(KERN_ERR, "Couldn't find PCI device " | 808 | sbridge_printk(KERN_ERR, "Couldn't find PCI device " |
641 | "%2x.%02d.%d!!!\n", | 809 | "%04x:%04x! on bus %02d\n", |
642 | bus, 15, 0); | 810 | PCI_VENDOR_ID_INTEL, id, bus); |
643 | return -ENODEV; | 811 | return -ENODEV; |
644 | } | 812 | } |
645 | 813 | ||
@@ -661,11 +829,14 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
661 | enum edac_type mode; | 829 | enum edac_type mode; |
662 | enum mem_type mtype; | 830 | enum mem_type mtype; |
663 | 831 | ||
664 | pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); | 832 | if (pvt->info.type == HASWELL) |
833 | pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®); | ||
834 | else | ||
835 | pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); | ||
836 | |||
665 | pvt->sbridge_dev->source_id = SOURCE_ID(reg); | 837 | pvt->sbridge_dev->source_id = SOURCE_ID(reg); |
666 | 838 | ||
667 | pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); | 839 | pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt); |
668 | pvt->sbridge_dev->node_id = NODE_ID(reg); | ||
669 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", | 840 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", |
670 | pvt->sbridge_dev->mc, | 841 | pvt->sbridge_dev->mc, |
671 | pvt->sbridge_dev->node_id, | 842 | pvt->sbridge_dev->node_id, |
@@ -698,24 +869,18 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
698 | pvt->is_close_pg = false; | 869 | pvt->is_close_pg = false; |
699 | } | 870 | } |
700 | 871 | ||
701 | if (pvt->pci_ddrio) { | 872 | mtype = pvt->info.get_memory_type(pvt); |
702 | pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, | 873 | if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4) |
703 | ®); | 874 | edac_dbg(0, "Memory is registered\n"); |
704 | if (IS_RDIMM_ENABLED(reg)) { | 875 | else if (mtype == MEM_UNKNOWN) |
705 | /* FIXME: Can also be LRDIMM */ | ||
706 | edac_dbg(0, "Memory is registered\n"); | ||
707 | mtype = MEM_RDDR3; | ||
708 | } else { | ||
709 | edac_dbg(0, "Memory is unregistered\n"); | ||
710 | mtype = MEM_DDR3; | ||
711 | } | ||
712 | } else { | ||
713 | edac_dbg(0, "Cannot determine memory type\n"); | 876 | edac_dbg(0, "Cannot determine memory type\n"); |
714 | mtype = MEM_UNKNOWN; | 877 | else |
715 | } | 878 | edac_dbg(0, "Memory is unregistered\n"); |
716 | 879 | ||
717 | /* On all supported DDR3 DIMM types, there are 8 banks available */ | 880 | if (mtype == MEM_DDR4 || MEM_RDDR4) |
718 | banks = 8; | 881 | banks = 16; |
882 | else | ||
883 | banks = 8; | ||
719 | 884 | ||
720 | for (i = 0; i < NUM_CHANNELS; i++) { | 885 | for (i = 0; i < NUM_CHANNELS; i++) { |
721 | u32 mtr; | 886 | u32 mtr; |
@@ -729,11 +894,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
729 | if (IS_DIMM_PRESENT(mtr)) { | 894 | if (IS_DIMM_PRESENT(mtr)) { |
730 | pvt->channel[i].dimms++; | 895 | pvt->channel[i].dimms++; |
731 | 896 | ||
732 | ranks = numrank(mtr); | 897 | ranks = numrank(pvt->info.type, mtr); |
733 | rows = numrow(mtr); | 898 | rows = numrow(mtr); |
734 | cols = numcol(mtr); | 899 | cols = numcol(mtr); |
735 | 900 | ||
736 | /* DDR3 has 8 I/O banks */ | ||
737 | size = ((u64)rows * cols * banks * ranks) >> (20 - 3); | 901 | size = ((u64)rows * cols * banks * ranks) >> (20 - 3); |
738 | npages = MiB_TO_PAGES(size); | 902 | npages = MiB_TO_PAGES(size); |
739 | 903 | ||
@@ -744,7 +908,17 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
744 | 908 | ||
745 | dimm->nr_pages = npages; | 909 | dimm->nr_pages = npages; |
746 | dimm->grain = 32; | 910 | dimm->grain = 32; |
747 | dimm->dtype = (banks == 8) ? DEV_X8 : DEV_X4; | 911 | switch (banks) { |
912 | case 16: | ||
913 | dimm->dtype = DEV_X16; | ||
914 | break; | ||
915 | case 8: | ||
916 | dimm->dtype = DEV_X8; | ||
917 | break; | ||
918 | case 4: | ||
919 | dimm->dtype = DEV_X4; | ||
920 | break; | ||
921 | } | ||
748 | dimm->mtype = mtype; | 922 | dimm->mtype = mtype; |
749 | dimm->edac_mode = mode; | 923 | dimm->edac_mode = mode; |
750 | snprintf(dimm->label, sizeof(dimm->label), | 924 | snprintf(dimm->label, sizeof(dimm->label), |
@@ -887,7 +1061,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) | |||
887 | if (!IS_RIR_VALID(reg)) | 1061 | if (!IS_RIR_VALID(reg)) |
888 | continue; | 1062 | continue; |
889 | 1063 | ||
890 | tmp_mb = RIR_LIMIT(reg) >> 20; | 1064 | tmp_mb = pvt->info.rir_limit(reg) >> 20; |
891 | rir_way = 1 << RIR_WAY(reg); | 1065 | rir_way = 1 << RIR_WAY(reg); |
892 | mb = div_u64_rem(tmp_mb, 1000, &kb); | 1066 | mb = div_u64_rem(tmp_mb, 1000, &kb); |
893 | edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", | 1067 | edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", |
@@ -936,11 +1110,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
936 | struct mem_ctl_info *new_mci; | 1110 | struct mem_ctl_info *new_mci; |
937 | struct sbridge_pvt *pvt = mci->pvt_info; | 1111 | struct sbridge_pvt *pvt = mci->pvt_info; |
938 | struct pci_dev *pci_ha; | 1112 | struct pci_dev *pci_ha; |
939 | int n_rir, n_sads, n_tads, sad_way, sck_xch; | 1113 | int n_rir, n_sads, n_tads, sad_way, sck_xch; |
940 | int sad_interl, idx, base_ch; | 1114 | int sad_interl, idx, base_ch; |
941 | int interleave_mode; | 1115 | int interleave_mode, shiftup = 0; |
942 | unsigned sad_interleave[pvt->info.max_interleave]; | 1116 | unsigned sad_interleave[pvt->info.max_interleave]; |
943 | u32 reg; | 1117 | u32 reg, dram_rule; |
944 | u8 ch_way, sck_way, pkg, sad_ha = 0; | 1118 | u8 ch_way, sck_way, pkg, sad_ha = 0; |
945 | u32 tad_offset; | 1119 | u32 tad_offset; |
946 | u32 rir_way; | 1120 | u32 rir_way; |
@@ -987,8 +1161,9 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
987 | sprintf(msg, "Can't discover the memory socket"); | 1161 | sprintf(msg, "Can't discover the memory socket"); |
988 | return -EINVAL; | 1162 | return -EINVAL; |
989 | } | 1163 | } |
990 | *area_type = get_dram_attr(reg); | 1164 | dram_rule = reg; |
991 | interleave_mode = INTERLEAVE_MODE(reg); | 1165 | *area_type = get_dram_attr(dram_rule); |
1166 | interleave_mode = INTERLEAVE_MODE(dram_rule); | ||
992 | 1167 | ||
993 | pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], | 1168 | pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], |
994 | ®); | 1169 | ®); |
@@ -1033,6 +1208,36 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
1033 | *socket = sad_interleave[idx]; | 1208 | *socket = sad_interleave[idx]; |
1034 | edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", | 1209 | edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", |
1035 | idx, sad_way, *socket); | 1210 | idx, sad_way, *socket); |
1211 | } else if (pvt->info.type == HASWELL) { | ||
1212 | int bits, a7mode = A7MODE(dram_rule); | ||
1213 | |||
1214 | if (a7mode) { | ||
1215 | /* A7 mode swaps P9 with P6 */ | ||
1216 | bits = GET_BITFIELD(addr, 7, 8) << 1; | ||
1217 | bits |= GET_BITFIELD(addr, 9, 9); | ||
1218 | } else | ||
1219 | bits = GET_BITFIELD(addr, 7, 9); | ||
1220 | |||
1221 | if (interleave_mode) { | ||
1222 | /* interleave mode will XOR {8,7,6} with {18,17,16} */ | ||
1223 | idx = GET_BITFIELD(addr, 16, 18); | ||
1224 | idx ^= bits; | ||
1225 | } else | ||
1226 | idx = bits; | ||
1227 | |||
1228 | pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); | ||
1229 | *socket = sad_pkg_socket(pkg); | ||
1230 | sad_ha = sad_pkg_ha(pkg); | ||
1231 | |||
1232 | if (a7mode) { | ||
1233 | /* MCChanShiftUpEnable */ | ||
1234 | pci_read_config_dword(pvt->pci_ha0, | ||
1235 | HASWELL_HASYSDEFEATURE2, ®); | ||
1236 | shiftup = GET_BITFIELD(reg, 22, 22); | ||
1237 | } | ||
1238 | |||
1239 | edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %i, shiftup: %i\n", | ||
1240 | idx, *socket, sad_ha, shiftup); | ||
1036 | } else { | 1241 | } else { |
1037 | /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */ | 1242 | /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */ |
1038 | idx = (addr >> 6) & 7; | 1243 | idx = (addr >> 6) & 7; |
@@ -1090,7 +1295,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
1090 | if (ch_way == 3) | 1295 | if (ch_way == 3) |
1091 | idx = addr >> 6; | 1296 | idx = addr >> 6; |
1092 | else | 1297 | else |
1093 | idx = addr >> (6 + sck_way); | 1298 | idx = (addr >> (6 + sck_way + shiftup)) & 0x3; |
1094 | idx = idx % ch_way; | 1299 | idx = idx % ch_way; |
1095 | 1300 | ||
1096 | /* | 1301 | /* |
@@ -1181,7 +1386,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
1181 | if (!IS_RIR_VALID(reg)) | 1386 | if (!IS_RIR_VALID(reg)) |
1182 | continue; | 1387 | continue; |
1183 | 1388 | ||
1184 | limit = RIR_LIMIT(reg); | 1389 | limit = pvt->info.rir_limit(reg); |
1185 | mb = div_u64_rem(limit >> 20, 1000, &kb); | 1390 | mb = div_u64_rem(limit >> 20, 1000, &kb); |
1186 | edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", | 1391 | edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", |
1187 | n_rir, | 1392 | n_rir, |
@@ -1197,6 +1402,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
1197 | return -EINVAL; | 1402 | return -EINVAL; |
1198 | } | 1403 | } |
1199 | rir_way = RIR_WAY(reg); | 1404 | rir_way = RIR_WAY(reg); |
1405 | |||
1200 | if (pvt->is_close_pg) | 1406 | if (pvt->is_close_pg) |
1201 | idx = (ch_addr >> 6); | 1407 | idx = (ch_addr >> 6); |
1202 | else | 1408 | else |
@@ -1259,13 +1465,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
1259 | { | 1465 | { |
1260 | struct sbridge_dev *sbridge_dev; | 1466 | struct sbridge_dev *sbridge_dev; |
1261 | const struct pci_id_descr *dev_descr = &table->descr[devno]; | 1467 | const struct pci_id_descr *dev_descr = &table->descr[devno]; |
1262 | |||
1263 | struct pci_dev *pdev = NULL; | 1468 | struct pci_dev *pdev = NULL; |
1264 | u8 bus = 0; | 1469 | u8 bus = 0; |
1265 | 1470 | ||
1266 | sbridge_printk(KERN_DEBUG, | 1471 | sbridge_printk(KERN_DEBUG, |
1267 | "Seeking for: dev %02x.%d PCI ID %04x:%04x\n", | 1472 | "Seeking for: PCI ID %04x:%04x\n", |
1268 | dev_descr->dev, dev_descr->func, | ||
1269 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1473 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1270 | 1474 | ||
1271 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1475 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
@@ -1280,12 +1484,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
1280 | if (dev_descr->optional) | 1484 | if (dev_descr->optional) |
1281 | return 0; | 1485 | return 0; |
1282 | 1486 | ||
1487 | /* if the HA wasn't found */ | ||
1283 | if (devno == 0) | 1488 | if (devno == 0) |
1284 | return -ENODEV; | 1489 | return -ENODEV; |
1285 | 1490 | ||
1286 | sbridge_printk(KERN_INFO, | 1491 | sbridge_printk(KERN_INFO, |
1287 | "Device not found: dev %02x.%d PCI ID %04x:%04x\n", | 1492 | "Device not found: %04x:%04x\n", |
1288 | dev_descr->dev, dev_descr->func, | ||
1289 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1493 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1290 | 1494 | ||
1291 | /* End of list, leave */ | 1495 | /* End of list, leave */ |
@@ -1305,9 +1509,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
1305 | 1509 | ||
1306 | if (sbridge_dev->pdev[devno]) { | 1510 | if (sbridge_dev->pdev[devno]) { |
1307 | sbridge_printk(KERN_ERR, | 1511 | sbridge_printk(KERN_ERR, |
1308 | "Duplicated device for " | 1512 | "Duplicated device for %04x:%04x\n", |
1309 | "dev %02x:%d.%d PCI ID %04x:%04x\n", | ||
1310 | bus, dev_descr->dev, dev_descr->func, | ||
1311 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1513 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1312 | pci_dev_put(pdev); | 1514 | pci_dev_put(pdev); |
1313 | return -ENODEV; | 1515 | return -ENODEV; |
@@ -1315,30 +1517,15 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
1315 | 1517 | ||
1316 | sbridge_dev->pdev[devno] = pdev; | 1518 | sbridge_dev->pdev[devno] = pdev; |
1317 | 1519 | ||
1318 | /* Sanity check */ | ||
1319 | if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev || | ||
1320 | PCI_FUNC(pdev->devfn) != dev_descr->func)) { | ||
1321 | sbridge_printk(KERN_ERR, | ||
1322 | "Device PCI ID %04x:%04x " | ||
1323 | "has dev %02x:%d.%d instead of dev %02x:%02x.%d\n", | ||
1324 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id, | ||
1325 | bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
1326 | bus, dev_descr->dev, dev_descr->func); | ||
1327 | return -ENODEV; | ||
1328 | } | ||
1329 | |||
1330 | /* Be sure that the device is enabled */ | 1520 | /* Be sure that the device is enabled */ |
1331 | if (unlikely(pci_enable_device(pdev) < 0)) { | 1521 | if (unlikely(pci_enable_device(pdev) < 0)) { |
1332 | sbridge_printk(KERN_ERR, | 1522 | sbridge_printk(KERN_ERR, |
1333 | "Couldn't enable " | 1523 | "Couldn't enable %04x:%04x\n", |
1334 | "dev %02x:%d.%d PCI ID %04x:%04x\n", | ||
1335 | bus, dev_descr->dev, dev_descr->func, | ||
1336 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1524 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1337 | return -ENODEV; | 1525 | return -ENODEV; |
1338 | } | 1526 | } |
1339 | 1527 | ||
1340 | edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n", | 1528 | edac_dbg(0, "Detected %04x:%04x\n", |
1341 | bus, dev_descr->dev, dev_descr->func, | ||
1342 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | 1529 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1343 | 1530 | ||
1344 | /* | 1531 | /* |
@@ -1355,10 +1542,9 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
1355 | 1542 | ||
1356 | /* | 1543 | /* |
1357 | * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's | 1544 | * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's |
1358 | * device/functions we want to reference for this driver. | 1545 | * devices we want to reference for this driver. |
1359 | * Need to 'get' device 16 func 1 and func 2. | ||
1360 | * @num_mc: pointer to the memory controllers count, to be incremented in case | 1546 | * @num_mc: pointer to the memory controllers count, to be incremented in case |
1361 | * of success. | 1547 | * of success. |
1362 | * @table: model specific table | 1548 | * @table: model specific table |
1363 | * | 1549 | * |
1364 | * returns 0 in case of success or error code | 1550 | * returns 0 in case of success or error code |
@@ -1396,79 +1582,51 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
1396 | { | 1582 | { |
1397 | struct sbridge_pvt *pvt = mci->pvt_info; | 1583 | struct sbridge_pvt *pvt = mci->pvt_info; |
1398 | struct pci_dev *pdev; | 1584 | struct pci_dev *pdev; |
1399 | int i, func, slot; | 1585 | int i; |
1400 | 1586 | ||
1401 | for (i = 0; i < sbridge_dev->n_devs; i++) { | 1587 | for (i = 0; i < sbridge_dev->n_devs; i++) { |
1402 | pdev = sbridge_dev->pdev[i]; | 1588 | pdev = sbridge_dev->pdev[i]; |
1403 | if (!pdev) | 1589 | if (!pdev) |
1404 | continue; | 1590 | continue; |
1405 | slot = PCI_SLOT(pdev->devfn); | 1591 | |
1406 | func = PCI_FUNC(pdev->devfn); | 1592 | switch (pdev->device) { |
1407 | switch (slot) { | 1593 | case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0: |
1408 | case 12: | 1594 | pvt->pci_sad0 = pdev; |
1409 | switch (func) { | ||
1410 | case 6: | ||
1411 | pvt->pci_sad0 = pdev; | ||
1412 | break; | ||
1413 | case 7: | ||
1414 | pvt->pci_sad1 = pdev; | ||
1415 | break; | ||
1416 | default: | ||
1417 | goto error; | ||
1418 | } | ||
1419 | break; | 1595 | break; |
1420 | case 13: | 1596 | case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1: |
1421 | switch (func) { | 1597 | pvt->pci_sad1 = pdev; |
1422 | case 6: | ||
1423 | pvt->pci_br0 = pdev; | ||
1424 | break; | ||
1425 | default: | ||
1426 | goto error; | ||
1427 | } | ||
1428 | break; | 1598 | break; |
1429 | case 14: | 1599 | case PCI_DEVICE_ID_INTEL_SBRIDGE_BR: |
1430 | switch (func) { | 1600 | pvt->pci_br0 = pdev; |
1431 | case 0: | ||
1432 | pvt->pci_ha0 = pdev; | ||
1433 | break; | ||
1434 | default: | ||
1435 | goto error; | ||
1436 | } | ||
1437 | break; | 1601 | break; |
1438 | case 15: | 1602 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0: |
1439 | switch (func) { | 1603 | pvt->pci_ha0 = pdev; |
1440 | case 0: | ||
1441 | pvt->pci_ta = pdev; | ||
1442 | break; | ||
1443 | case 1: | ||
1444 | pvt->pci_ras = pdev; | ||
1445 | break; | ||
1446 | case 2: | ||
1447 | case 3: | ||
1448 | case 4: | ||
1449 | case 5: | ||
1450 | pvt->pci_tad[func - 2] = pdev; | ||
1451 | break; | ||
1452 | default: | ||
1453 | goto error; | ||
1454 | } | ||
1455 | break; | 1604 | break; |
1456 | case 17: | 1605 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: |
1457 | switch (func) { | 1606 | pvt->pci_ta = pdev; |
1458 | case 0: | 1607 | break; |
1459 | pvt->pci_ddrio = pdev; | 1608 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS: |
1460 | break; | 1609 | pvt->pci_ras = pdev; |
1461 | default: | 1610 | break; |
1462 | goto error; | 1611 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0: |
1463 | } | 1612 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1: |
1613 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2: | ||
1614 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3: | ||
1615 | { | ||
1616 | int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0; | ||
1617 | pvt->pci_tad[id] = pdev; | ||
1618 | } | ||
1619 | break; | ||
1620 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO: | ||
1621 | pvt->pci_ddrio = pdev; | ||
1464 | break; | 1622 | break; |
1465 | default: | 1623 | default: |
1466 | goto error; | 1624 | goto error; |
1467 | } | 1625 | } |
1468 | 1626 | ||
1469 | edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", | 1627 | edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n", |
1628 | pdev->vendor, pdev->device, | ||
1470 | sbridge_dev->bus, | 1629 | sbridge_dev->bus, |
1471 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
1472 | pdev); | 1630 | pdev); |
1473 | } | 1631 | } |
1474 | 1632 | ||
@@ -1488,9 +1646,8 @@ enodev: | |||
1488 | return -ENODEV; | 1646 | return -ENODEV; |
1489 | 1647 | ||
1490 | error: | 1648 | error: |
1491 | sbridge_printk(KERN_ERR, "Device %d, function %d " | 1649 | sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n", |
1492 | "is out of the expected range\n", | 1650 | PCI_VENDOR_ID_INTEL, pdev->device); |
1493 | slot, func); | ||
1494 | return -EINVAL; | 1651 | return -EINVAL; |
1495 | } | 1652 | } |
1496 | 1653 | ||
@@ -1499,7 +1656,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
1499 | { | 1656 | { |
1500 | struct sbridge_pvt *pvt = mci->pvt_info; | 1657 | struct sbridge_pvt *pvt = mci->pvt_info; |
1501 | struct pci_dev *pdev, *tmp; | 1658 | struct pci_dev *pdev, *tmp; |
1502 | int i, func, slot; | 1659 | int i; |
1503 | bool mode_2ha = false; | 1660 | bool mode_2ha = false; |
1504 | 1661 | ||
1505 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, | 1662 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, |
@@ -1513,79 +1670,60 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
1513 | pdev = sbridge_dev->pdev[i]; | 1670 | pdev = sbridge_dev->pdev[i]; |
1514 | if (!pdev) | 1671 | if (!pdev) |
1515 | continue; | 1672 | continue; |
1516 | slot = PCI_SLOT(pdev->devfn); | ||
1517 | func = PCI_FUNC(pdev->devfn); | ||
1518 | 1673 | ||
1519 | switch (slot) { | 1674 | switch (pdev->device) { |
1520 | case 14: | 1675 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0: |
1521 | if (func == 0) { | 1676 | pvt->pci_ha0 = pdev; |
1522 | pvt->pci_ha0 = pdev; | 1677 | break; |
1523 | break; | 1678 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: |
1524 | } | 1679 | pvt->pci_ta = pdev; |
1525 | goto error; | 1680 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: |
1526 | case 15: | 1681 | pvt->pci_ras = pdev; |
1527 | switch (func) { | 1682 | break; |
1528 | case 0: | 1683 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2: |
1529 | pvt->pci_ta = pdev; | 1684 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3: |
1530 | break; | 1685 | /* if we have 2 HAs active, channels 2 and 3 |
1531 | case 1: | 1686 | * are in other device */ |
1532 | pvt->pci_ras = pdev; | 1687 | if (mode_2ha) |
1533 | break; | ||
1534 | case 4: | ||
1535 | case 5: | ||
1536 | /* if we have 2 HAs active, channels 2 and 3 | ||
1537 | * are in other device */ | ||
1538 | if (mode_2ha) | ||
1539 | break; | ||
1540 | /* fall through */ | ||
1541 | case 2: | ||
1542 | case 3: | ||
1543 | pvt->pci_tad[func - 2] = pdev; | ||
1544 | break; | 1688 | break; |
1545 | default: | 1689 | /* fall through */ |
1546 | goto error; | 1690 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0: |
1547 | } | 1691 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1: |
1692 | { | ||
1693 | int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0; | ||
1694 | pvt->pci_tad[id] = pdev; | ||
1695 | } | ||
1548 | break; | 1696 | break; |
1549 | case 17: | 1697 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0: |
1550 | if (func == 4) { | 1698 | pvt->pci_ddrio = pdev; |
1699 | break; | ||
1700 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0: | ||
1701 | if (!mode_2ha) | ||
1551 | pvt->pci_ddrio = pdev; | 1702 | pvt->pci_ddrio = pdev; |
1552 | break; | ||
1553 | } else if (func == 0) { | ||
1554 | if (!mode_2ha) | ||
1555 | pvt->pci_ddrio = pdev; | ||
1556 | break; | ||
1557 | } | ||
1558 | goto error; | ||
1559 | case 22: | ||
1560 | switch (func) { | ||
1561 | case 0: | ||
1562 | pvt->pci_sad0 = pdev; | ||
1563 | break; | ||
1564 | case 1: | ||
1565 | pvt->pci_br0 = pdev; | ||
1566 | break; | ||
1567 | case 2: | ||
1568 | pvt->pci_br1 = pdev; | ||
1569 | break; | ||
1570 | default: | ||
1571 | goto error; | ||
1572 | } | ||
1573 | break; | 1703 | break; |
1574 | case 28: | 1704 | case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD: |
1575 | if (func == 0) { | 1705 | pvt->pci_sad0 = pdev; |
1576 | pvt->pci_ha1 = pdev; | 1706 | break; |
1577 | break; | 1707 | case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0: |
1578 | } | 1708 | pvt->pci_br0 = pdev; |
1579 | goto error; | 1709 | break; |
1580 | case 29: | 1710 | case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1: |
1711 | pvt->pci_br1 = pdev; | ||
1712 | break; | ||
1713 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1: | ||
1714 | pvt->pci_ha1 = pdev; | ||
1715 | break; | ||
1716 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0: | ||
1717 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1: | ||
1718 | { | ||
1719 | int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2; | ||
1720 | |||
1581 | /* we shouldn't have this device if we have just one | 1721 | /* we shouldn't have this device if we have just one |
1582 | * HA present */ | 1722 | * HA present */ |
1583 | WARN_ON(!mode_2ha); | 1723 | WARN_ON(!mode_2ha); |
1584 | if (func == 2 || func == 3) { | 1724 | pvt->pci_tad[id] = pdev; |
1585 | pvt->pci_tad[func] = pdev; | 1725 | } |
1586 | break; | 1726 | break; |
1587 | } | ||
1588 | goto error; | ||
1589 | default: | 1727 | default: |
1590 | goto error; | 1728 | goto error; |
1591 | } | 1729 | } |
@@ -1614,11 +1752,111 @@ enodev: | |||
1614 | 1752 | ||
1615 | error: | 1753 | error: |
1616 | sbridge_printk(KERN_ERR, | 1754 | sbridge_printk(KERN_ERR, |
1617 | "Device %d, function %d is out of the expected range\n", | 1755 | "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL, |
1618 | slot, func); | 1756 | pdev->device); |
1619 | return -EINVAL; | 1757 | return -EINVAL; |
1620 | } | 1758 | } |
1621 | 1759 | ||
1760 | static int haswell_mci_bind_devs(struct mem_ctl_info *mci, | ||
1761 | struct sbridge_dev *sbridge_dev) | ||
1762 | { | ||
1763 | struct sbridge_pvt *pvt = mci->pvt_info; | ||
1764 | struct pci_dev *pdev, *tmp; | ||
1765 | int i; | ||
1766 | bool mode_2ha = false; | ||
1767 | |||
1768 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1769 | PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, NULL); | ||
1770 | if (tmp) { | ||
1771 | mode_2ha = true; | ||
1772 | pci_dev_put(tmp); | ||
1773 | } | ||
1774 | |||
1775 | /* there's only one device per system; not tied to any bus */ | ||
1776 | if (pvt->info.pci_vtd == NULL) | ||
1777 | /* result will be checked later */ | ||
1778 | pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1779 | PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC, | ||
1780 | NULL); | ||
1781 | |||
1782 | for (i = 0; i < sbridge_dev->n_devs; i++) { | ||
1783 | pdev = sbridge_dev->pdev[i]; | ||
1784 | if (!pdev) | ||
1785 | continue; | ||
1786 | |||
1787 | switch (pdev->device) { | ||
1788 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0: | ||
1789 | pvt->pci_sad0 = pdev; | ||
1790 | break; | ||
1791 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1: | ||
1792 | pvt->pci_sad1 = pdev; | ||
1793 | break; | ||
1794 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: | ||
1795 | pvt->pci_ha0 = pdev; | ||
1796 | break; | ||
1797 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA: | ||
1798 | pvt->pci_ta = pdev; | ||
1799 | break; | ||
1800 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL: | ||
1801 | pvt->pci_ras = pdev; | ||
1802 | break; | ||
1803 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0: | ||
1804 | pvt->pci_tad[0] = pdev; | ||
1805 | break; | ||
1806 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1: | ||
1807 | pvt->pci_tad[1] = pdev; | ||
1808 | break; | ||
1809 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2: | ||
1810 | if (!mode_2ha) | ||
1811 | pvt->pci_tad[2] = pdev; | ||
1812 | break; | ||
1813 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3: | ||
1814 | if (!mode_2ha) | ||
1815 | pvt->pci_tad[3] = pdev; | ||
1816 | break; | ||
1817 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0: | ||
1818 | pvt->pci_ddrio = pdev; | ||
1819 | break; | ||
1820 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: | ||
1821 | pvt->pci_ha1 = pdev; | ||
1822 | break; | ||
1823 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA: | ||
1824 | pvt->pci_ha1_ta = pdev; | ||
1825 | break; | ||
1826 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0: | ||
1827 | if (mode_2ha) | ||
1828 | pvt->pci_tad[2] = pdev; | ||
1829 | break; | ||
1830 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1: | ||
1831 | if (mode_2ha) | ||
1832 | pvt->pci_tad[3] = pdev; | ||
1833 | break; | ||
1834 | default: | ||
1835 | break; | ||
1836 | } | ||
1837 | |||
1838 | edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", | ||
1839 | sbridge_dev->bus, | ||
1840 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
1841 | pdev); | ||
1842 | } | ||
1843 | |||
1844 | /* Check if everything were registered */ | ||
1845 | if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 || | ||
1846 | !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd) | ||
1847 | goto enodev; | ||
1848 | |||
1849 | for (i = 0; i < NUM_CHANNELS; i++) { | ||
1850 | if (!pvt->pci_tad[i]) | ||
1851 | goto enodev; | ||
1852 | } | ||
1853 | return 0; | ||
1854 | |||
1855 | enodev: | ||
1856 | sbridge_printk(KERN_ERR, "Some needed devices are missing\n"); | ||
1857 | return -ENODEV; | ||
1858 | } | ||
1859 | |||
1622 | /**************************************************************************** | 1860 | /**************************************************************************** |
1623 | Error check routines | 1861 | Error check routines |
1624 | ****************************************************************************/ | 1862 | ****************************************************************************/ |
@@ -1736,6 +1974,9 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, | |||
1736 | * EDAC core should be handling the channel mask, in order to point | 1974 | * EDAC core should be handling the channel mask, in order to point |
1737 | * to the group of dimm's where the error may be happening. | 1975 | * to the group of dimm's where the error may be happening. |
1738 | */ | 1976 | */ |
1977 | if (!pvt->is_lockstep && !pvt->is_mirrored && !pvt->is_close_pg) | ||
1978 | channel = first_channel; | ||
1979 | |||
1739 | snprintf(msg, sizeof(msg), | 1980 | snprintf(msg, sizeof(msg), |
1740 | "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", | 1981 | "%s%s area:%s err_code:%04x:%04x socket:%d channel_mask:%ld rank:%d", |
1741 | overflow ? " OVERFLOW" : "", | 1982 | overflow ? " OVERFLOW" : "", |
@@ -1865,10 +2106,6 @@ static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val, | |||
1865 | "%u APIC %x\n", mce->cpuvendor, mce->cpuid, | 2106 | "%u APIC %x\n", mce->cpuvendor, mce->cpuid, |
1866 | mce->time, mce->socketid, mce->apicid); | 2107 | mce->time, mce->socketid, mce->apicid); |
1867 | 2108 | ||
1868 | /* Only handle if it is the right mc controller */ | ||
1869 | if (cpu_data(mce->cpu).phys_proc_id != pvt->sbridge_dev->mc) | ||
1870 | return NOTIFY_DONE; | ||
1871 | |||
1872 | smp_rmb(); | 2109 | smp_rmb(); |
1873 | if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { | 2110 | if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { |
1874 | smp_wmb(); | 2111 | smp_wmb(); |
@@ -1932,7 +2169,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
1932 | int rc; | 2169 | int rc; |
1933 | 2170 | ||
1934 | /* Check the number of active and not disabled channels */ | 2171 | /* Check the number of active and not disabled channels */ |
1935 | rc = check_if_ecc_is_active(sbridge_dev->bus); | 2172 | rc = check_if_ecc_is_active(sbridge_dev->bus, type); |
1936 | if (unlikely(rc < 0)) | 2173 | if (unlikely(rc < 0)) |
1937 | return rc; | 2174 | return rc; |
1938 | 2175 | ||
@@ -1971,11 +2208,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
1971 | mci->edac_check = sbridge_check_error; | 2208 | mci->edac_check = sbridge_check_error; |
1972 | 2209 | ||
1973 | pvt->info.type = type; | 2210 | pvt->info.type = type; |
1974 | if (type == IVY_BRIDGE) { | 2211 | switch (type) { |
2212 | case IVY_BRIDGE: | ||
1975 | pvt->info.rankcfgr = IB_RANK_CFG_A; | 2213 | pvt->info.rankcfgr = IB_RANK_CFG_A; |
1976 | pvt->info.get_tolm = ibridge_get_tolm; | 2214 | pvt->info.get_tolm = ibridge_get_tolm; |
1977 | pvt->info.get_tohm = ibridge_get_tohm; | 2215 | pvt->info.get_tohm = ibridge_get_tohm; |
1978 | pvt->info.dram_rule = ibridge_dram_rule; | 2216 | pvt->info.dram_rule = ibridge_dram_rule; |
2217 | pvt->info.get_memory_type = get_memory_type; | ||
2218 | pvt->info.get_node_id = get_node_id; | ||
2219 | pvt->info.rir_limit = rir_limit; | ||
1979 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); | 2220 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); |
1980 | pvt->info.interleave_list = ibridge_interleave_list; | 2221 | pvt->info.interleave_list = ibridge_interleave_list; |
1981 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | 2222 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
@@ -1986,11 +2227,15 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
1986 | rc = ibridge_mci_bind_devs(mci, sbridge_dev); | 2227 | rc = ibridge_mci_bind_devs(mci, sbridge_dev); |
1987 | if (unlikely(rc < 0)) | 2228 | if (unlikely(rc < 0)) |
1988 | goto fail0; | 2229 | goto fail0; |
1989 | } else { | 2230 | break; |
2231 | case SANDY_BRIDGE: | ||
1990 | pvt->info.rankcfgr = SB_RANK_CFG_A; | 2232 | pvt->info.rankcfgr = SB_RANK_CFG_A; |
1991 | pvt->info.get_tolm = sbridge_get_tolm; | 2233 | pvt->info.get_tolm = sbridge_get_tolm; |
1992 | pvt->info.get_tohm = sbridge_get_tohm; | 2234 | pvt->info.get_tohm = sbridge_get_tohm; |
1993 | pvt->info.dram_rule = sbridge_dram_rule; | 2235 | pvt->info.dram_rule = sbridge_dram_rule; |
2236 | pvt->info.get_memory_type = get_memory_type; | ||
2237 | pvt->info.get_node_id = get_node_id; | ||
2238 | pvt->info.rir_limit = rir_limit; | ||
1994 | pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); | 2239 | pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); |
1995 | pvt->info.interleave_list = sbridge_interleave_list; | 2240 | pvt->info.interleave_list = sbridge_interleave_list; |
1996 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); | 2241 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); |
@@ -2001,8 +2246,27 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
2001 | rc = sbridge_mci_bind_devs(mci, sbridge_dev); | 2246 | rc = sbridge_mci_bind_devs(mci, sbridge_dev); |
2002 | if (unlikely(rc < 0)) | 2247 | if (unlikely(rc < 0)) |
2003 | goto fail0; | 2248 | goto fail0; |
2004 | } | 2249 | break; |
2250 | case HASWELL: | ||
2251 | /* rankcfgr isn't used */ | ||
2252 | pvt->info.get_tolm = haswell_get_tolm; | ||
2253 | pvt->info.get_tohm = haswell_get_tohm; | ||
2254 | pvt->info.dram_rule = ibridge_dram_rule; | ||
2255 | pvt->info.get_memory_type = haswell_get_memory_type; | ||
2256 | pvt->info.get_node_id = haswell_get_node_id; | ||
2257 | pvt->info.rir_limit = haswell_rir_limit; | ||
2258 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); | ||
2259 | pvt->info.interleave_list = ibridge_interleave_list; | ||
2260 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | ||
2261 | pvt->info.interleave_pkg = ibridge_interleave_pkg; | ||
2262 | mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); | ||
2005 | 2263 | ||
2264 | /* Store pci devices at mci for faster access */ | ||
2265 | rc = haswell_mci_bind_devs(mci, sbridge_dev); | ||
2266 | if (unlikely(rc < 0)) | ||
2267 | goto fail0; | ||
2268 | break; | ||
2269 | } | ||
2006 | 2270 | ||
2007 | /* Get dimm basic config and the memory layout */ | 2271 | /* Get dimm basic config and the memory layout */ |
2008 | get_dimm_config(mci); | 2272 | get_dimm_config(mci); |
@@ -2037,10 +2301,10 @@ fail0: | |||
2037 | 2301 | ||
2038 | static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 2302 | static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
2039 | { | 2303 | { |
2040 | int rc; | 2304 | int rc = -ENODEV; |
2041 | u8 mc, num_mc = 0; | 2305 | u8 mc, num_mc = 0; |
2042 | struct sbridge_dev *sbridge_dev; | 2306 | struct sbridge_dev *sbridge_dev; |
2043 | enum type type; | 2307 | enum type type = SANDY_BRIDGE; |
2044 | 2308 | ||
2045 | /* get the pci devices we want to reserve for our use */ | 2309 | /* get the pci devices we want to reserve for our use */ |
2046 | mutex_lock(&sbridge_edac_lock); | 2310 | mutex_lock(&sbridge_edac_lock); |
@@ -2054,12 +2318,19 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2054 | } | 2318 | } |
2055 | probed++; | 2319 | probed++; |
2056 | 2320 | ||
2057 | if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) { | 2321 | switch (pdev->device) { |
2322 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: | ||
2058 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table); | 2323 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table); |
2059 | type = IVY_BRIDGE; | 2324 | type = IVY_BRIDGE; |
2060 | } else { | 2325 | break; |
2326 | case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA: | ||
2061 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table); | 2327 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table); |
2062 | type = SANDY_BRIDGE; | 2328 | type = SANDY_BRIDGE; |
2329 | break; | ||
2330 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0: | ||
2331 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table); | ||
2332 | type = HASWELL; | ||
2333 | break; | ||
2063 | } | 2334 | } |
2064 | if (unlikely(rc < 0)) | 2335 | if (unlikely(rc < 0)) |
2065 | goto fail0; | 2336 | goto fail0; |
@@ -2068,6 +2339,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2068 | list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { | 2339 | list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) { |
2069 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", | 2340 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", |
2070 | mc, mc + 1, num_mc); | 2341 | mc, mc + 1, num_mc); |
2342 | |||
2071 | sbridge_dev->mc = mc++; | 2343 | sbridge_dev->mc = mc++; |
2072 | rc = sbridge_register_mci(sbridge_dev, type); | 2344 | rc = sbridge_register_mci(sbridge_dev, type); |
2073 | if (unlikely(rc < 0)) | 2345 | if (unlikely(rc < 0)) |
diff --git a/include/linux/edac.h b/include/linux/edac.h index 8e6c20af11a2..e1e68da6f35c 100644 --- a/include/linux/edac.h +++ b/include/linux/edac.h | |||
@@ -194,6 +194,9 @@ static inline char *mc_event_error_type(const unsigned int err_type) | |||
194 | * @MEM_DDR3: DDR3 RAM | 194 | * @MEM_DDR3: DDR3 RAM |
195 | * @MEM_RDDR3: Registered DDR3 RAM | 195 | * @MEM_RDDR3: Registered DDR3 RAM |
196 | * This is a variant of the DDR3 memories. | 196 | * This is a variant of the DDR3 memories. |
197 | * @MEM_DDR4: DDR4 RAM | ||
198 | * @MEM_RDDR4: Registered DDR4 RAM | ||
199 | * This is a variant of the DDR4 memories. | ||
197 | */ | 200 | */ |
198 | enum mem_type { | 201 | enum mem_type { |
199 | MEM_EMPTY = 0, | 202 | MEM_EMPTY = 0, |
@@ -213,6 +216,8 @@ enum mem_type { | |||
213 | MEM_XDR, | 216 | MEM_XDR, |
214 | MEM_DDR3, | 217 | MEM_DDR3, |
215 | MEM_RDDR3, | 218 | MEM_RDDR3, |
219 | MEM_DDR4, | ||
220 | MEM_RDDR4, | ||
216 | }; | 221 | }; |
217 | 222 | ||
218 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) | 223 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) |