diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-18 17:51:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-18 17:51:52 -0500 |
commit | cdd278db0e3dd714e8076e58f723f3c59547591b (patch) | |
tree | 81d18a709705d8e4d65e31363deb2b270a7fafa5 | |
parent | 794e96e8ecc1eeff56f4ede168fd0b8f4c5a00b9 (diff) | |
parent | 3e45588825c1c9c7b561102dd878d23af1b46bb9 (diff) |
Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac
Pull EDAC driver updates from Mauro Carvalho Chehab:
- sb_edac: add support for Ivy Bridge support
- cell_edac: add a missing of_node_put() call
* 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac:
cell_edac: fix missing of_node_put
sb_edac: add support for Ivy Bridge
sb_edac: avoid decoding the same error multiple times
sb_edac: rename mci_bind_devs()
sb_edac: enable multiple PCI id tables to be used
sb_edac: rework sad_pkg
sb_edac: allow different interleave lists
sb_edac: allow different dram_rule arrays
sb_edac: isolate TOHM retrieval
sb_edac: rename pci_br
sb_edac: isolate TOLM retrieval
sb_edac: make RANK_CFG_A value part of sbridge_info
-rw-r--r-- | drivers/edac/cell_edac.c | 1 | ||||
-rw-r--r-- | drivers/edac/sb_edac.c | 593 |
2 files changed, 465 insertions, 129 deletions
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 9ee1c76da7b9..374b57fc596d 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c | |||
@@ -163,6 +163,7 @@ static void cell_edac_init_csrows(struct mem_ctl_info *mci) | |||
163 | csrow->first_page, nr_pages); | 163 | csrow->first_page, nr_pages); |
164 | break; | 164 | break; |
165 | } | 165 | } |
166 | of_node_put(np); | ||
166 | } | 167 | } |
167 | 168 | ||
168 | static int cell_edac_probe(struct platform_device *pdev) | 169 | static int cell_edac_probe(struct platform_device *pdev) |
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 88f60c5fecbc..8472405c5586 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c | |||
@@ -34,7 +34,7 @@ static int probed; | |||
34 | /* | 34 | /* |
35 | * Alter this version for the module when modifications are made | 35 | * Alter this version for the module when modifications are made |
36 | */ | 36 | */ |
37 | #define SBRIDGE_REVISION " Ver: 1.0.0 " | 37 | #define SBRIDGE_REVISION " Ver: 1.1.0 " |
38 | #define EDAC_MOD_STR "sbridge_edac" | 38 | #define EDAC_MOD_STR "sbridge_edac" |
39 | 39 | ||
40 | /* | 40 | /* |
@@ -83,11 +83,17 @@ static int probed; | |||
83 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3 0x3c77 /* 16.7 */ | 83 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3 0x3c77 /* 16.7 */ |
84 | 84 | ||
85 | /* Devices 12 Function 6, Offsets 0x80 to 0xcc */ | 85 | /* Devices 12 Function 6, Offsets 0x80 to 0xcc */ |
86 | static const u32 dram_rule[] = { | 86 | static const u32 sbridge_dram_rule[] = { |
87 | 0x80, 0x88, 0x90, 0x98, 0xa0, | 87 | 0x80, 0x88, 0x90, 0x98, 0xa0, |
88 | 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, | 88 | 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, |
89 | }; | 89 | }; |
90 | #define MAX_SAD ARRAY_SIZE(dram_rule) | 90 | |
91 | static const u32 ibridge_dram_rule[] = { | ||
92 | 0x60, 0x68, 0x70, 0x78, 0x80, | ||
93 | 0x88, 0x90, 0x98, 0xa0, 0xa8, | ||
94 | 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, | ||
95 | 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, | ||
96 | }; | ||
91 | 97 | ||
92 | #define SAD_LIMIT(reg) ((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff) | 98 | #define SAD_LIMIT(reg) ((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff) |
93 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) | 99 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) |
@@ -108,43 +114,50 @@ static char *get_dram_attr(u32 reg) | |||
108 | } | 114 | } |
109 | } | 115 | } |
110 | 116 | ||
111 | static const u32 interleave_list[] = { | 117 | static const u32 sbridge_interleave_list[] = { |
112 | 0x84, 0x8c, 0x94, 0x9c, 0xa4, | 118 | 0x84, 0x8c, 0x94, 0x9c, 0xa4, |
113 | 0xac, 0xb4, 0xbc, 0xc4, 0xcc, | 119 | 0xac, 0xb4, 0xbc, 0xc4, 0xcc, |
114 | }; | 120 | }; |
115 | #define MAX_INTERLEAVE ARRAY_SIZE(interleave_list) | 121 | |
116 | 122 | static const u32 ibridge_interleave_list[] = { | |
117 | #define SAD_PKG0(reg) GET_BITFIELD(reg, 0, 2) | 123 | 0x64, 0x6c, 0x74, 0x7c, 0x84, |
118 | #define SAD_PKG1(reg) GET_BITFIELD(reg, 3, 5) | 124 | 0x8c, 0x94, 0x9c, 0xa4, 0xac, |
119 | #define SAD_PKG2(reg) GET_BITFIELD(reg, 8, 10) | 125 | 0xb4, 0xbc, 0xc4, 0xcc, 0xd4, |
120 | #define SAD_PKG3(reg) GET_BITFIELD(reg, 11, 13) | 126 | 0xdc, 0xe4, 0xec, 0xf4, 0xfc, |
121 | #define SAD_PKG4(reg) GET_BITFIELD(reg, 16, 18) | 127 | }; |
122 | #define SAD_PKG5(reg) GET_BITFIELD(reg, 19, 21) | 128 | |
123 | #define SAD_PKG6(reg) GET_BITFIELD(reg, 24, 26) | 129 | struct interleave_pkg { |
124 | #define SAD_PKG7(reg) GET_BITFIELD(reg, 27, 29) | 130 | unsigned char start; |
125 | 131 | unsigned char end; | |
126 | static inline int sad_pkg(u32 reg, int interleave) | 132 | }; |
133 | |||
134 | static const struct interleave_pkg sbridge_interleave_pkg[] = { | ||
135 | { 0, 2 }, | ||
136 | { 3, 5 }, | ||
137 | { 8, 10 }, | ||
138 | { 11, 13 }, | ||
139 | { 16, 18 }, | ||
140 | { 19, 21 }, | ||
141 | { 24, 26 }, | ||
142 | { 27, 29 }, | ||
143 | }; | ||
144 | |||
145 | static const struct interleave_pkg ibridge_interleave_pkg[] = { | ||
146 | { 0, 3 }, | ||
147 | { 4, 7 }, | ||
148 | { 8, 11 }, | ||
149 | { 12, 15 }, | ||
150 | { 16, 19 }, | ||
151 | { 20, 23 }, | ||
152 | { 24, 27 }, | ||
153 | { 28, 31 }, | ||
154 | }; | ||
155 | |||
156 | static inline int sad_pkg(const struct interleave_pkg *table, u32 reg, | ||
157 | int interleave) | ||
127 | { | 158 | { |
128 | switch (interleave) { | 159 | return GET_BITFIELD(reg, table[interleave].start, |
129 | case 0: | 160 | table[interleave].end); |
130 | return SAD_PKG0(reg); | ||
131 | case 1: | ||
132 | return SAD_PKG1(reg); | ||
133 | case 2: | ||
134 | return SAD_PKG2(reg); | ||
135 | case 3: | ||
136 | return SAD_PKG3(reg); | ||
137 | case 4: | ||
138 | return SAD_PKG4(reg); | ||
139 | case 5: | ||
140 | return SAD_PKG5(reg); | ||
141 | case 6: | ||
142 | return SAD_PKG6(reg); | ||
143 | case 7: | ||
144 | return SAD_PKG7(reg); | ||
145 | default: | ||
146 | return -EINVAL; | ||
147 | } | ||
148 | } | 161 | } |
149 | 162 | ||
150 | /* Devices 12 Function 7 */ | 163 | /* Devices 12 Function 7 */ |
@@ -262,7 +275,9 @@ static const u32 correrrthrsld[] = { | |||
262 | 275 | ||
263 | /* Device 17, function 0 */ | 276 | /* Device 17, function 0 */ |
264 | 277 | ||
265 | #define RANK_CFG_A 0x0328 | 278 | #define SB_RANK_CFG_A 0x0328 |
279 | |||
280 | #define IB_RANK_CFG_A 0x0320 | ||
266 | 281 | ||
267 | #define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11) | 282 | #define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11) |
268 | 283 | ||
@@ -273,8 +288,23 @@ static const u32 correrrthrsld[] = { | |||
273 | #define NUM_CHANNELS 4 | 288 | #define NUM_CHANNELS 4 |
274 | #define MAX_DIMMS 3 /* Max DIMMS per channel */ | 289 | #define MAX_DIMMS 3 /* Max DIMMS per channel */ |
275 | 290 | ||
291 | enum type { | ||
292 | SANDY_BRIDGE, | ||
293 | IVY_BRIDGE, | ||
294 | }; | ||
295 | |||
296 | struct sbridge_pvt; | ||
276 | struct sbridge_info { | 297 | struct sbridge_info { |
277 | u32 mcmtr; | 298 | enum type type; |
299 | u32 mcmtr; | ||
300 | u32 rankcfgr; | ||
301 | u64 (*get_tolm)(struct sbridge_pvt *pvt); | ||
302 | u64 (*get_tohm)(struct sbridge_pvt *pvt); | ||
303 | const u32 *dram_rule; | ||
304 | const u32 *interleave_list; | ||
305 | const struct interleave_pkg *interleave_pkg; | ||
306 | u8 max_sad; | ||
307 | u8 max_interleave; | ||
278 | }; | 308 | }; |
279 | 309 | ||
280 | struct sbridge_channel { | 310 | struct sbridge_channel { |
@@ -305,8 +335,9 @@ struct sbridge_dev { | |||
305 | 335 | ||
306 | struct sbridge_pvt { | 336 | struct sbridge_pvt { |
307 | struct pci_dev *pci_ta, *pci_ddrio, *pci_ras; | 337 | struct pci_dev *pci_ta, *pci_ddrio, *pci_ras; |
308 | struct pci_dev *pci_sad0, *pci_sad1, *pci_ha0; | 338 | struct pci_dev *pci_sad0, *pci_sad1; |
309 | struct pci_dev *pci_br; | 339 | struct pci_dev *pci_ha0, *pci_ha1; |
340 | struct pci_dev *pci_br0, *pci_br1; | ||
310 | struct pci_dev *pci_tad[NUM_CHANNELS]; | 341 | struct pci_dev *pci_tad[NUM_CHANNELS]; |
311 | 342 | ||
312 | struct sbridge_dev *sbridge_dev; | 343 | struct sbridge_dev *sbridge_dev; |
@@ -364,11 +395,75 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { | |||
364 | {0,} /* 0 terminated list. */ | 395 | {0,} /* 0 terminated list. */ |
365 | }; | 396 | }; |
366 | 397 | ||
398 | /* This changes depending if 1HA or 2HA: | ||
399 | * 1HA: | ||
400 | * 0x0eb8 (17.0) is DDRIO0 | ||
401 | * 2HA: | ||
402 | * 0x0ebc (17.4) is DDRIO0 | ||
403 | */ | ||
404 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0 0x0eb8 | ||
405 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0 0x0ebc | ||
406 | |||
407 | /* pci ids */ | ||
408 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0 0x0ea0 | ||
409 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA 0x0ea8 | ||
410 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS 0x0e71 | ||
411 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0 0x0eaa | ||
412 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1 0x0eab | ||
413 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2 0x0eac | ||
414 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3 0x0ead | ||
415 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_SAD 0x0ec8 | ||
416 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_BR0 0x0ec9 | ||
417 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_BR1 0x0eca | ||
418 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1 0x0e60 | ||
419 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA 0x0e68 | ||
420 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS 0x0e79 | ||
421 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 0x0e6a | ||
422 | #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1 0x0e6b | ||
423 | |||
424 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { | ||
425 | /* Processor Home Agent */ | ||
426 | { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0) }, | ||
427 | |||
428 | /* Memory controller */ | ||
429 | { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0) }, | ||
430 | { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0) }, | ||
431 | { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) }, | ||
432 | { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) }, | ||
433 | { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) }, | ||
434 | { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) }, | ||
435 | |||
436 | /* System Address Decoder */ | ||
437 | { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0) }, | ||
438 | |||
439 | /* Broadcast Registers */ | ||
440 | { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1) }, | ||
441 | { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0) }, | ||
442 | |||
443 | /* Optional, mode 2HA */ | ||
444 | { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1) }, | ||
445 | #if 0 | ||
446 | { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1) }, | ||
447 | { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) }, | ||
448 | #endif | ||
449 | { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) }, | ||
450 | { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) }, | ||
451 | |||
452 | { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) }, | ||
453 | { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) }, | ||
454 | }; | ||
455 | |||
456 | static const struct pci_id_table pci_dev_descr_ibridge_table[] = { | ||
457 | PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge), | ||
458 | {0,} /* 0 terminated list. */ | ||
459 | }; | ||
460 | |||
367 | /* | 461 | /* |
368 | * pci_device_id table for which devices we are looking for | 462 | * pci_device_id table for which devices we are looking for |
369 | */ | 463 | */ |
370 | static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = { | 464 | static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = { |
371 | {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA)}, | 465 | {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)}, | ||
372 | {0,} /* 0 terminated list. */ | 467 | {0,} /* 0 terminated list. */ |
373 | }; | 468 | }; |
374 | 469 | ||
@@ -458,6 +553,52 @@ static void free_sbridge_dev(struct sbridge_dev *sbridge_dev) | |||
458 | kfree(sbridge_dev); | 553 | kfree(sbridge_dev); |
459 | } | 554 | } |
460 | 555 | ||
556 | static u64 sbridge_get_tolm(struct sbridge_pvt *pvt) | ||
557 | { | ||
558 | u32 reg; | ||
559 | |||
560 | /* Address range is 32:28 */ | ||
561 | pci_read_config_dword(pvt->pci_sad1, TOLM, ®); | ||
562 | return GET_TOLM(reg); | ||
563 | } | ||
564 | |||
565 | static u64 sbridge_get_tohm(struct sbridge_pvt *pvt) | ||
566 | { | ||
567 | u32 reg; | ||
568 | |||
569 | pci_read_config_dword(pvt->pci_sad1, TOHM, ®); | ||
570 | return GET_TOHM(reg); | ||
571 | } | ||
572 | |||
573 | static u64 ibridge_get_tolm(struct sbridge_pvt *pvt) | ||
574 | { | ||
575 | u32 reg; | ||
576 | |||
577 | pci_read_config_dword(pvt->pci_br1, TOLM, ®); | ||
578 | |||
579 | return GET_TOLM(reg); | ||
580 | } | ||
581 | |||
582 | static u64 ibridge_get_tohm(struct sbridge_pvt *pvt) | ||
583 | { | ||
584 | u32 reg; | ||
585 | |||
586 | pci_read_config_dword(pvt->pci_br1, TOHM, ®); | ||
587 | |||
588 | return GET_TOHM(reg); | ||
589 | } | ||
590 | |||
591 | static inline u8 sad_pkg_socket(u8 pkg) | ||
592 | { | ||
593 | /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ | ||
594 | return (pkg >> 3) | (pkg & 0x3); | ||
595 | } | ||
596 | |||
597 | static inline u8 sad_pkg_ha(u8 pkg) | ||
598 | { | ||
599 | return (pkg >> 2) & 0x1; | ||
600 | } | ||
601 | |||
461 | /**************************************************************************** | 602 | /**************************************************************************** |
462 | Memory check routines | 603 | Memory check routines |
463 | ****************************************************************************/ | 604 | ****************************************************************************/ |
@@ -520,10 +661,10 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
520 | enum edac_type mode; | 661 | enum edac_type mode; |
521 | enum mem_type mtype; | 662 | enum mem_type mtype; |
522 | 663 | ||
523 | pci_read_config_dword(pvt->pci_br, SAD_TARGET, ®); | 664 | pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); |
524 | pvt->sbridge_dev->source_id = SOURCE_ID(reg); | 665 | pvt->sbridge_dev->source_id = SOURCE_ID(reg); |
525 | 666 | ||
526 | pci_read_config_dword(pvt->pci_br, SAD_CONTROL, ®); | 667 | pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, ®); |
527 | pvt->sbridge_dev->node_id = NODE_ID(reg); | 668 | pvt->sbridge_dev->node_id = NODE_ID(reg); |
528 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", | 669 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", |
529 | pvt->sbridge_dev->mc, | 670 | pvt->sbridge_dev->mc, |
@@ -558,7 +699,8 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
558 | } | 699 | } |
559 | 700 | ||
560 | if (pvt->pci_ddrio) { | 701 | if (pvt->pci_ddrio) { |
561 | pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®); | 702 | pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, |
703 | ®); | ||
562 | if (IS_RDIMM_ENABLED(reg)) { | 704 | if (IS_RDIMM_ENABLED(reg)) { |
563 | /* FIXME: Can also be LRDIMM */ | 705 | /* FIXME: Can also be LRDIMM */ |
564 | edac_dbg(0, "Memory is registered\n"); | 706 | edac_dbg(0, "Memory is registered\n"); |
@@ -629,19 +771,14 @@ static void get_memory_layout(const struct mem_ctl_info *mci) | |||
629 | * Step 1) Get TOLM/TOHM ranges | 771 | * Step 1) Get TOLM/TOHM ranges |
630 | */ | 772 | */ |
631 | 773 | ||
632 | /* Address range is 32:28 */ | 774 | pvt->tolm = pvt->info.get_tolm(pvt); |
633 | pci_read_config_dword(pvt->pci_sad1, TOLM, | ||
634 | ®); | ||
635 | pvt->tolm = GET_TOLM(reg); | ||
636 | tmp_mb = (1 + pvt->tolm) >> 20; | 775 | tmp_mb = (1 + pvt->tolm) >> 20; |
637 | 776 | ||
638 | mb = div_u64_rem(tmp_mb, 1000, &kb); | 777 | mb = div_u64_rem(tmp_mb, 1000, &kb); |
639 | edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); | 778 | edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); |
640 | 779 | ||
641 | /* Address range is already 45:25 */ | 780 | /* Address range is already 45:25 */ |
642 | pci_read_config_dword(pvt->pci_sad1, TOHM, | 781 | pvt->tohm = pvt->info.get_tohm(pvt); |
643 | ®); | ||
644 | pvt->tohm = GET_TOHM(reg); | ||
645 | tmp_mb = (1 + pvt->tohm) >> 20; | 782 | tmp_mb = (1 + pvt->tohm) >> 20; |
646 | 783 | ||
647 | mb = div_u64_rem(tmp_mb, 1000, &kb); | 784 | mb = div_u64_rem(tmp_mb, 1000, &kb); |
@@ -654,9 +791,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci) | |||
654 | * algorithm bellow. | 791 | * algorithm bellow. |
655 | */ | 792 | */ |
656 | prv = 0; | 793 | prv = 0; |
657 | for (n_sads = 0; n_sads < MAX_SAD; n_sads++) { | 794 | for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) { |
658 | /* SAD_LIMIT Address range is 45:26 */ | 795 | /* SAD_LIMIT Address range is 45:26 */ |
659 | pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads], | 796 | pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads], |
660 | ®); | 797 | ®); |
661 | limit = SAD_LIMIT(reg); | 798 | limit = SAD_LIMIT(reg); |
662 | 799 | ||
@@ -677,15 +814,16 @@ static void get_memory_layout(const struct mem_ctl_info *mci) | |||
677 | reg); | 814 | reg); |
678 | prv = limit; | 815 | prv = limit; |
679 | 816 | ||
680 | pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads], | 817 | pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], |
681 | ®); | 818 | ®); |
682 | sad_interl = sad_pkg(reg, 0); | 819 | sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0); |
683 | for (j = 0; j < 8; j++) { | 820 | for (j = 0; j < 8; j++) { |
684 | if (j > 0 && sad_interl == sad_pkg(reg, j)) | 821 | u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, j); |
822 | if (j > 0 && sad_interl == pkg) | ||
685 | break; | 823 | break; |
686 | 824 | ||
687 | edac_dbg(0, "SAD#%d, interleave #%d: %d\n", | 825 | edac_dbg(0, "SAD#%d, interleave #%d: %d\n", |
688 | n_sads, j, sad_pkg(reg, j)); | 826 | n_sads, j, pkg); |
689 | } | 827 | } |
690 | } | 828 | } |
691 | 829 | ||
@@ -797,12 +935,13 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
797 | { | 935 | { |
798 | struct mem_ctl_info *new_mci; | 936 | struct mem_ctl_info *new_mci; |
799 | struct sbridge_pvt *pvt = mci->pvt_info; | 937 | struct sbridge_pvt *pvt = mci->pvt_info; |
938 | struct pci_dev *pci_ha; | ||
800 | int n_rir, n_sads, n_tads, sad_way, sck_xch; | 939 | int n_rir, n_sads, n_tads, sad_way, sck_xch; |
801 | int sad_interl, idx, base_ch; | 940 | int sad_interl, idx, base_ch; |
802 | int interleave_mode; | 941 | int interleave_mode; |
803 | unsigned sad_interleave[MAX_INTERLEAVE]; | 942 | unsigned sad_interleave[pvt->info.max_interleave]; |
804 | u32 reg; | 943 | u32 reg; |
805 | u8 ch_way,sck_way; | 944 | u8 ch_way, sck_way, pkg, sad_ha = 0; |
806 | u32 tad_offset; | 945 | u32 tad_offset; |
807 | u32 rir_way; | 946 | u32 rir_way; |
808 | u32 mb, kb; | 947 | u32 mb, kb; |
@@ -828,8 +967,8 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
828 | /* | 967 | /* |
829 | * Step 1) Get socket | 968 | * Step 1) Get socket |
830 | */ | 969 | */ |
831 | for (n_sads = 0; n_sads < MAX_SAD; n_sads++) { | 970 | for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) { |
832 | pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads], | 971 | pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads], |
833 | ®); | 972 | ®); |
834 | 973 | ||
835 | if (!DRAM_RULE_ENABLE(reg)) | 974 | if (!DRAM_RULE_ENABLE(reg)) |
@@ -844,53 +983,65 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
844 | break; | 983 | break; |
845 | prv = limit; | 984 | prv = limit; |
846 | } | 985 | } |
847 | if (n_sads == MAX_SAD) { | 986 | if (n_sads == pvt->info.max_sad) { |
848 | sprintf(msg, "Can't discover the memory socket"); | 987 | sprintf(msg, "Can't discover the memory socket"); |
849 | return -EINVAL; | 988 | return -EINVAL; |
850 | } | 989 | } |
851 | *area_type = get_dram_attr(reg); | 990 | *area_type = get_dram_attr(reg); |
852 | interleave_mode = INTERLEAVE_MODE(reg); | 991 | interleave_mode = INTERLEAVE_MODE(reg); |
853 | 992 | ||
854 | pci_read_config_dword(pvt->pci_sad0, interleave_list[n_sads], | 993 | pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads], |
855 | ®); | 994 | ®); |
856 | sad_interl = sad_pkg(reg, 0); | 995 | |
857 | for (sad_way = 0; sad_way < 8; sad_way++) { | 996 | if (pvt->info.type == SANDY_BRIDGE) { |
858 | if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way)) | 997 | sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0); |
998 | for (sad_way = 0; sad_way < 8; sad_way++) { | ||
999 | u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, sad_way); | ||
1000 | if (sad_way > 0 && sad_interl == pkg) | ||
1001 | break; | ||
1002 | sad_interleave[sad_way] = pkg; | ||
1003 | edac_dbg(0, "SAD interleave #%d: %d\n", | ||
1004 | sad_way, sad_interleave[sad_way]); | ||
1005 | } | ||
1006 | edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", | ||
1007 | pvt->sbridge_dev->mc, | ||
1008 | n_sads, | ||
1009 | addr, | ||
1010 | limit, | ||
1011 | sad_way + 7, | ||
1012 | !interleave_mode ? "" : "XOR[18:16]"); | ||
1013 | if (interleave_mode) | ||
1014 | idx = ((addr >> 6) ^ (addr >> 16)) & 7; | ||
1015 | else | ||
1016 | idx = (addr >> 6) & 7; | ||
1017 | switch (sad_way) { | ||
1018 | case 1: | ||
1019 | idx = 0; | ||
859 | break; | 1020 | break; |
860 | sad_interleave[sad_way] = sad_pkg(reg, sad_way); | 1021 | case 2: |
861 | edac_dbg(0, "SAD interleave #%d: %d\n", | 1022 | idx = idx & 1; |
862 | sad_way, sad_interleave[sad_way]); | 1023 | break; |
863 | } | 1024 | case 4: |
864 | edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", | 1025 | idx = idx & 3; |
865 | pvt->sbridge_dev->mc, | 1026 | break; |
866 | n_sads, | 1027 | case 8: |
867 | addr, | 1028 | break; |
868 | limit, | 1029 | default: |
869 | sad_way + 7, | 1030 | sprintf(msg, "Can't discover socket interleave"); |
870 | interleave_mode ? "" : "XOR[18:16]"); | 1031 | return -EINVAL; |
871 | if (interleave_mode) | 1032 | } |
872 | idx = ((addr >> 6) ^ (addr >> 16)) & 7; | 1033 | *socket = sad_interleave[idx]; |
873 | else | 1034 | edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", |
1035 | idx, sad_way, *socket); | ||
1036 | } else { | ||
1037 | /* Ivy Bridge's SAD mode doesn't support XOR interleave mode */ | ||
874 | idx = (addr >> 6) & 7; | 1038 | idx = (addr >> 6) & 7; |
875 | switch (sad_way) { | 1039 | pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); |
876 | case 1: | 1040 | *socket = sad_pkg_socket(pkg); |
877 | idx = 0; | 1041 | sad_ha = sad_pkg_ha(pkg); |
878 | break; | 1042 | edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n", |
879 | case 2: | 1043 | idx, *socket, sad_ha); |
880 | idx = idx & 1; | ||
881 | break; | ||
882 | case 4: | ||
883 | idx = idx & 3; | ||
884 | break; | ||
885 | case 8: | ||
886 | break; | ||
887 | default: | ||
888 | sprintf(msg, "Can't discover socket interleave"); | ||
889 | return -EINVAL; | ||
890 | } | 1044 | } |
891 | *socket = sad_interleave[idx]; | ||
892 | edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", | ||
893 | idx, sad_way, *socket); | ||
894 | 1045 | ||
895 | /* | 1046 | /* |
896 | * Move to the proper node structure, in order to access the | 1047 | * Move to the proper node structure, in order to access the |
@@ -909,9 +1060,16 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
909 | * Step 2) Get memory channel | 1060 | * Step 2) Get memory channel |
910 | */ | 1061 | */ |
911 | prv = 0; | 1062 | prv = 0; |
1063 | if (pvt->info.type == SANDY_BRIDGE) | ||
1064 | pci_ha = pvt->pci_ha0; | ||
1065 | else { | ||
1066 | if (sad_ha) | ||
1067 | pci_ha = pvt->pci_ha1; | ||
1068 | else | ||
1069 | pci_ha = pvt->pci_ha0; | ||
1070 | } | ||
912 | for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { | 1071 | for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { |
913 | pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads], | 1072 | pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], ®); |
914 | ®); | ||
915 | limit = TAD_LIMIT(reg); | 1073 | limit = TAD_LIMIT(reg); |
916 | if (limit <= prv) { | 1074 | if (limit <= prv) { |
917 | sprintf(msg, "Can't discover the memory channel"); | 1075 | sprintf(msg, "Can't discover the memory channel"); |
@@ -921,14 +1079,13 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
921 | break; | 1079 | break; |
922 | prv = limit; | 1080 | prv = limit; |
923 | } | 1081 | } |
1082 | if (n_tads == MAX_TAD) { | ||
1083 | sprintf(msg, "Can't discover the memory channel"); | ||
1084 | return -EINVAL; | ||
1085 | } | ||
1086 | |||
924 | ch_way = TAD_CH(reg) + 1; | 1087 | ch_way = TAD_CH(reg) + 1; |
925 | sck_way = TAD_SOCK(reg) + 1; | 1088 | sck_way = TAD_SOCK(reg) + 1; |
926 | /* | ||
927 | * FIXME: Is it right to always use channel 0 for offsets? | ||
928 | */ | ||
929 | pci_read_config_dword(pvt->pci_tad[0], | ||
930 | tad_ch_nilv_offset[n_tads], | ||
931 | &tad_offset); | ||
932 | 1089 | ||
933 | if (ch_way == 3) | 1090 | if (ch_way == 3) |
934 | idx = addr >> 6; | 1091 | idx = addr >> 6; |
@@ -958,6 +1115,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, | |||
958 | } | 1115 | } |
959 | *channel_mask = 1 << base_ch; | 1116 | *channel_mask = 1 << base_ch; |
960 | 1117 | ||
1118 | pci_read_config_dword(pvt->pci_tad[base_ch], | ||
1119 | tad_ch_nilv_offset[n_tads], | ||
1120 | &tad_offset); | ||
1121 | |||
961 | if (pvt->is_mirrored) { | 1122 | if (pvt->is_mirrored) { |
962 | *channel_mask |= 1 << ((base_ch + 2) % 4); | 1123 | *channel_mask |= 1 << ((base_ch + 2) % 4); |
963 | switch(ch_way) { | 1124 | switch(ch_way) { |
@@ -1091,12 +1252,6 @@ static void sbridge_put_all_devices(void) | |||
1091 | } | 1252 | } |
1092 | } | 1253 | } |
1093 | 1254 | ||
1094 | /* | ||
1095 | * sbridge_get_all_devices Find and perform 'get' operation on the MCH's | ||
1096 | * device/functions we want to reference for this driver | ||
1097 | * | ||
1098 | * Need to 'get' device 16 func 1 and func 2 | ||
1099 | */ | ||
1100 | static int sbridge_get_onedevice(struct pci_dev **prev, | 1255 | static int sbridge_get_onedevice(struct pci_dev **prev, |
1101 | u8 *num_mc, | 1256 | u8 *num_mc, |
1102 | const struct pci_id_table *table, | 1257 | const struct pci_id_table *table, |
@@ -1198,11 +1353,21 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
1198 | return 0; | 1353 | return 0; |
1199 | } | 1354 | } |
1200 | 1355 | ||
1201 | static int sbridge_get_all_devices(u8 *num_mc) | 1356 | /* |
1357 | * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's | ||
1358 | * device/functions 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 | ||
1361 | * of success. | ||
1362 | * @table: model specific table | ||
1363 | * | ||
1364 | * returns 0 in case of success or error code | ||
1365 | */ | ||
1366 | static int sbridge_get_all_devices(u8 *num_mc, | ||
1367 | const struct pci_id_table *table) | ||
1202 | { | 1368 | { |
1203 | int i, rc; | 1369 | int i, rc; |
1204 | struct pci_dev *pdev = NULL; | 1370 | struct pci_dev *pdev = NULL; |
1205 | const struct pci_id_table *table = pci_dev_descr_sbridge_table; | ||
1206 | 1371 | ||
1207 | while (table && table->descr) { | 1372 | while (table && table->descr) { |
1208 | for (i = 0; i < table->n_devs; i++) { | 1373 | for (i = 0; i < table->n_devs; i++) { |
@@ -1226,8 +1391,8 @@ static int sbridge_get_all_devices(u8 *num_mc) | |||
1226 | return 0; | 1391 | return 0; |
1227 | } | 1392 | } |
1228 | 1393 | ||
1229 | static int mci_bind_devs(struct mem_ctl_info *mci, | 1394 | static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, |
1230 | struct sbridge_dev *sbridge_dev) | 1395 | struct sbridge_dev *sbridge_dev) |
1231 | { | 1396 | { |
1232 | struct sbridge_pvt *pvt = mci->pvt_info; | 1397 | struct sbridge_pvt *pvt = mci->pvt_info; |
1233 | struct pci_dev *pdev; | 1398 | struct pci_dev *pdev; |
@@ -1255,7 +1420,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci, | |||
1255 | case 13: | 1420 | case 13: |
1256 | switch (func) { | 1421 | switch (func) { |
1257 | case 6: | 1422 | case 6: |
1258 | pvt->pci_br = pdev; | 1423 | pvt->pci_br0 = pdev; |
1259 | break; | 1424 | break; |
1260 | default: | 1425 | default: |
1261 | goto error; | 1426 | goto error; |
@@ -1329,6 +1494,131 @@ error: | |||
1329 | return -EINVAL; | 1494 | return -EINVAL; |
1330 | } | 1495 | } |
1331 | 1496 | ||
1497 | static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, | ||
1498 | struct sbridge_dev *sbridge_dev) | ||
1499 | { | ||
1500 | struct sbridge_pvt *pvt = mci->pvt_info; | ||
1501 | struct pci_dev *pdev, *tmp; | ||
1502 | int i, func, slot; | ||
1503 | bool mode_2ha = false; | ||
1504 | |||
1505 | tmp = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1506 | PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, NULL); | ||
1507 | if (tmp) { | ||
1508 | mode_2ha = true; | ||
1509 | pci_dev_put(tmp); | ||
1510 | } | ||
1511 | |||
1512 | for (i = 0; i < sbridge_dev->n_devs; i++) { | ||
1513 | pdev = sbridge_dev->pdev[i]; | ||
1514 | if (!pdev) | ||
1515 | continue; | ||
1516 | slot = PCI_SLOT(pdev->devfn); | ||
1517 | func = PCI_FUNC(pdev->devfn); | ||
1518 | |||
1519 | switch (slot) { | ||
1520 | case 14: | ||
1521 | if (func == 0) { | ||
1522 | pvt->pci_ha0 = pdev; | ||
1523 | break; | ||
1524 | } | ||
1525 | goto error; | ||
1526 | case 15: | ||
1527 | switch (func) { | ||
1528 | case 0: | ||
1529 | pvt->pci_ta = pdev; | ||
1530 | break; | ||
1531 | case 1: | ||
1532 | pvt->pci_ras = pdev; | ||
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; | ||
1545 | default: | ||
1546 | goto error; | ||
1547 | } | ||
1548 | break; | ||
1549 | case 17: | ||
1550 | if (func == 4) { | ||
1551 | 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; | ||
1574 | case 28: | ||
1575 | if (func == 0) { | ||
1576 | pvt->pci_ha1 = pdev; | ||
1577 | break; | ||
1578 | } | ||
1579 | goto error; | ||
1580 | case 29: | ||
1581 | /* we shouldn't have this device if we have just one | ||
1582 | * HA present */ | ||
1583 | WARN_ON(!mode_2ha); | ||
1584 | if (func == 2 || func == 3) { | ||
1585 | pvt->pci_tad[func] = pdev; | ||
1586 | break; | ||
1587 | } | ||
1588 | goto error; | ||
1589 | default: | ||
1590 | goto error; | ||
1591 | } | ||
1592 | |||
1593 | edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n", | ||
1594 | sbridge_dev->bus, | ||
1595 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | ||
1596 | pdev); | ||
1597 | } | ||
1598 | |||
1599 | /* Check if everything were registered */ | ||
1600 | if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_br0 || | ||
1601 | !pvt->pci_br1 || !pvt->pci_tad || !pvt->pci_ras || | ||
1602 | !pvt->pci_ta) | ||
1603 | goto enodev; | ||
1604 | |||
1605 | for (i = 0; i < NUM_CHANNELS; i++) { | ||
1606 | if (!pvt->pci_tad[i]) | ||
1607 | goto enodev; | ||
1608 | } | ||
1609 | return 0; | ||
1610 | |||
1611 | enodev: | ||
1612 | sbridge_printk(KERN_ERR, "Some needed devices are missing\n"); | ||
1613 | return -ENODEV; | ||
1614 | |||
1615 | error: | ||
1616 | sbridge_printk(KERN_ERR, | ||
1617 | "Device %d, function %d is out of the expected range\n", | ||
1618 | slot, func); | ||
1619 | return -EINVAL; | ||
1620 | } | ||
1621 | |||
1332 | /**************************************************************************** | 1622 | /**************************************************************************** |
1333 | Error check routines | 1623 | Error check routines |
1334 | ****************************************************************************/ | 1624 | ****************************************************************************/ |
@@ -1349,7 +1639,7 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, | |||
1349 | bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); | 1639 | bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); |
1350 | bool overflow = GET_BITFIELD(m->status, 62, 62); | 1640 | bool overflow = GET_BITFIELD(m->status, 62, 62); |
1351 | bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); | 1641 | bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); |
1352 | bool recoverable = GET_BITFIELD(m->status, 56, 56); | 1642 | bool recoverable; |
1353 | u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52); | 1643 | u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52); |
1354 | u32 mscod = GET_BITFIELD(m->status, 16, 31); | 1644 | u32 mscod = GET_BITFIELD(m->status, 16, 31); |
1355 | u32 errcode = GET_BITFIELD(m->status, 0, 15); | 1645 | u32 errcode = GET_BITFIELD(m->status, 0, 15); |
@@ -1360,6 +1650,11 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, | |||
1360 | int rc, dimm; | 1650 | int rc, dimm; |
1361 | char *area_type = NULL; | 1651 | char *area_type = NULL; |
1362 | 1652 | ||
1653 | if (pvt->info.type == IVY_BRIDGE) | ||
1654 | recoverable = true; | ||
1655 | else | ||
1656 | recoverable = GET_BITFIELD(m->status, 56, 56); | ||
1657 | |||
1363 | if (uncorrected_error) { | 1658 | if (uncorrected_error) { |
1364 | if (ripv) { | 1659 | if (ripv) { |
1365 | type = "FATAL"; | 1660 | type = "FATAL"; |
@@ -1409,6 +1704,10 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci, | |||
1409 | } | 1704 | } |
1410 | } | 1705 | } |
1411 | 1706 | ||
1707 | /* Only decode errors with an valid address (ADDRV) */ | ||
1708 | if (!GET_BITFIELD(m->status, 58, 58)) | ||
1709 | return; | ||
1710 | |||
1412 | rc = get_memory_error_data(mci, m->addr, &socket, | 1711 | rc = get_memory_error_data(mci, m->addr, &socket, |
1413 | &channel_mask, &rank, &area_type, msg); | 1712 | &channel_mask, &rank, &area_type, msg); |
1414 | if (rc < 0) | 1713 | if (rc < 0) |
@@ -1614,11 +1913,12 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) | |||
1614 | sbridge_dev->mci = NULL; | 1913 | sbridge_dev->mci = NULL; |
1615 | } | 1914 | } |
1616 | 1915 | ||
1617 | static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) | 1916 | static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) |
1618 | { | 1917 | { |
1619 | struct mem_ctl_info *mci; | 1918 | struct mem_ctl_info *mci; |
1620 | struct edac_mc_layer layers[2]; | 1919 | struct edac_mc_layer layers[2]; |
1621 | struct sbridge_pvt *pvt; | 1920 | struct sbridge_pvt *pvt; |
1921 | struct pci_dev *pdev = sbridge_dev->pdev[0]; | ||
1622 | int rc; | 1922 | int rc; |
1623 | 1923 | ||
1624 | /* Check the number of active and not disabled channels */ | 1924 | /* Check the number of active and not disabled channels */ |
@@ -1640,7 +1940,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) | |||
1640 | return -ENOMEM; | 1940 | return -ENOMEM; |
1641 | 1941 | ||
1642 | edac_dbg(0, "MC: mci = %p, dev = %p\n", | 1942 | edac_dbg(0, "MC: mci = %p, dev = %p\n", |
1643 | mci, &sbridge_dev->pdev[0]->dev); | 1943 | mci, &pdev->dev); |
1644 | 1944 | ||
1645 | pvt = mci->pvt_info; | 1945 | pvt = mci->pvt_info; |
1646 | memset(pvt, 0, sizeof(*pvt)); | 1946 | memset(pvt, 0, sizeof(*pvt)); |
@@ -1654,24 +1954,52 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) | |||
1654 | mci->edac_cap = EDAC_FLAG_NONE; | 1954 | mci->edac_cap = EDAC_FLAG_NONE; |
1655 | mci->mod_name = "sbridge_edac.c"; | 1955 | mci->mod_name = "sbridge_edac.c"; |
1656 | mci->mod_ver = SBRIDGE_REVISION; | 1956 | mci->mod_ver = SBRIDGE_REVISION; |
1657 | mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); | 1957 | mci->dev_name = pci_name(pdev); |
1658 | mci->dev_name = pci_name(sbridge_dev->pdev[0]); | ||
1659 | mci->ctl_page_to_phys = NULL; | 1958 | mci->ctl_page_to_phys = NULL; |
1660 | 1959 | ||
1661 | /* Set the function pointer to an actual operation function */ | 1960 | /* Set the function pointer to an actual operation function */ |
1662 | mci->edac_check = sbridge_check_error; | 1961 | mci->edac_check = sbridge_check_error; |
1663 | 1962 | ||
1664 | /* Store pci devices at mci for faster access */ | 1963 | pvt->info.type = type; |
1665 | rc = mci_bind_devs(mci, sbridge_dev); | 1964 | if (type == IVY_BRIDGE) { |
1666 | if (unlikely(rc < 0)) | 1965 | pvt->info.rankcfgr = IB_RANK_CFG_A; |
1667 | goto fail0; | 1966 | pvt->info.get_tolm = ibridge_get_tolm; |
1967 | pvt->info.get_tohm = ibridge_get_tohm; | ||
1968 | pvt->info.dram_rule = ibridge_dram_rule; | ||
1969 | pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); | ||
1970 | pvt->info.interleave_list = ibridge_interleave_list; | ||
1971 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | ||
1972 | pvt->info.interleave_pkg = ibridge_interleave_pkg; | ||
1973 | mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); | ||
1974 | |||
1975 | /* Store pci devices at mci for faster access */ | ||
1976 | rc = ibridge_mci_bind_devs(mci, sbridge_dev); | ||
1977 | if (unlikely(rc < 0)) | ||
1978 | goto fail0; | ||
1979 | } else { | ||
1980 | pvt->info.rankcfgr = SB_RANK_CFG_A; | ||
1981 | pvt->info.get_tolm = sbridge_get_tolm; | ||
1982 | pvt->info.get_tohm = sbridge_get_tohm; | ||
1983 | pvt->info.dram_rule = sbridge_dram_rule; | ||
1984 | pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); | ||
1985 | pvt->info.interleave_list = sbridge_interleave_list; | ||
1986 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); | ||
1987 | pvt->info.interleave_pkg = sbridge_interleave_pkg; | ||
1988 | mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); | ||
1989 | |||
1990 | /* Store pci devices at mci for faster access */ | ||
1991 | rc = sbridge_mci_bind_devs(mci, sbridge_dev); | ||
1992 | if (unlikely(rc < 0)) | ||
1993 | goto fail0; | ||
1994 | } | ||
1995 | |||
1668 | 1996 | ||
1669 | /* Get dimm basic config and the memory layout */ | 1997 | /* Get dimm basic config and the memory layout */ |
1670 | get_dimm_config(mci); | 1998 | get_dimm_config(mci); |
1671 | get_memory_layout(mci); | 1999 | get_memory_layout(mci); |
1672 | 2000 | ||
1673 | /* record ptr to the generic device */ | 2001 | /* record ptr to the generic device */ |
1674 | mci->pdev = &sbridge_dev->pdev[0]->dev; | 2002 | mci->pdev = &pdev->dev; |
1675 | 2003 | ||
1676 | /* add this new MC control structure to EDAC's list of MCs */ | 2004 | /* add this new MC control structure to EDAC's list of MCs */ |
1677 | if (unlikely(edac_mc_add_mc(mci))) { | 2005 | if (unlikely(edac_mc_add_mc(mci))) { |
@@ -1702,6 +2030,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1702 | int rc; | 2030 | int rc; |
1703 | u8 mc, num_mc = 0; | 2031 | u8 mc, num_mc = 0; |
1704 | struct sbridge_dev *sbridge_dev; | 2032 | struct sbridge_dev *sbridge_dev; |
2033 | enum type type; | ||
1705 | 2034 | ||
1706 | /* get the pci devices we want to reserve for our use */ | 2035 | /* get the pci devices we want to reserve for our use */ |
1707 | mutex_lock(&sbridge_edac_lock); | 2036 | mutex_lock(&sbridge_edac_lock); |
@@ -1715,7 +2044,13 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1715 | } | 2044 | } |
1716 | probed++; | 2045 | probed++; |
1717 | 2046 | ||
1718 | rc = sbridge_get_all_devices(&num_mc); | 2047 | if (pdev->device == PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA) { |
2048 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table); | ||
2049 | type = IVY_BRIDGE; | ||
2050 | } else { | ||
2051 | rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table); | ||
2052 | type = SANDY_BRIDGE; | ||
2053 | } | ||
1719 | if (unlikely(rc < 0)) | 2054 | if (unlikely(rc < 0)) |
1720 | goto fail0; | 2055 | goto fail0; |
1721 | mc = 0; | 2056 | mc = 0; |
@@ -1724,7 +2059,7 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1724 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", | 2059 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", |
1725 | mc, mc + 1, num_mc); | 2060 | mc, mc + 1, num_mc); |
1726 | sbridge_dev->mc = mc++; | 2061 | sbridge_dev->mc = mc++; |
1727 | rc = sbridge_register_mci(sbridge_dev); | 2062 | rc = sbridge_register_mci(sbridge_dev, type); |
1728 | if (unlikely(rc < 0)) | 2063 | if (unlikely(rc < 0)) |
1729 | goto fail1; | 2064 | goto fail1; |
1730 | } | 2065 | } |
@@ -1839,5 +2174,5 @@ MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | |||
1839 | MODULE_LICENSE("GPL"); | 2174 | MODULE_LICENSE("GPL"); |
1840 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | 2175 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); |
1841 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); | 2176 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); |
1842 | MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge memory controllers - " | 2177 | MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - " |
1843 | SBRIDGE_REVISION); | 2178 | SBRIDGE_REVISION); |