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 /drivers | |
| 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
Diffstat (limited to 'drivers')
| -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 |
3 files changed, 546 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)) |
