Commit cdd278db0e3dd714e8076e58f723f3c59547591b
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
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
Showing 2 changed files Side-by-side Diff
drivers/edac/cell_edac.c
drivers/edac/sb_edac.c
... | ... | @@ -34,7 +34,7 @@ |
34 | 34 | /* |
35 | 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 | 38 | #define EDAC_MOD_STR "sbridge_edac" |
39 | 39 | |
40 | 40 | /* |
41 | 41 | |
42 | 42 | |
... | ... | @@ -83,12 +83,18 @@ |
83 | 83 | #define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_ERR3 0x3c77 /* 16.7 */ |
84 | 84 | |
85 | 85 | /* Devices 12 Function 6, Offsets 0x80 to 0xcc */ |
86 | -static const u32 dram_rule[] = { | |
86 | +static const u32 sbridge_dram_rule[] = { | |
87 | 87 | 0x80, 0x88, 0x90, 0x98, 0xa0, |
88 | 88 | 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, |
89 | 89 | }; |
90 | -#define MAX_SAD ARRAY_SIZE(dram_rule) | |
91 | 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 | +}; | |
97 | + | |
92 | 98 | #define SAD_LIMIT(reg) ((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff) |
93 | 99 | #define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3) |
94 | 100 | #define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1) |
95 | 101 | |
96 | 102 | |
97 | 103 | |
98 | 104 | |
... | ... | @@ -108,43 +114,50 @@ |
108 | 114 | } |
109 | 115 | } |
110 | 116 | |
111 | -static const u32 interleave_list[] = { | |
117 | +static const u32 sbridge_interleave_list[] = { | |
112 | 118 | 0x84, 0x8c, 0x94, 0x9c, 0xa4, |
113 | 119 | 0xac, 0xb4, 0xbc, 0xc4, 0xcc, |
114 | 120 | }; |
115 | -#define MAX_INTERLEAVE ARRAY_SIZE(interleave_list) | |
116 | 121 | |
117 | -#define SAD_PKG0(reg) GET_BITFIELD(reg, 0, 2) | |
118 | -#define SAD_PKG1(reg) GET_BITFIELD(reg, 3, 5) | |
119 | -#define SAD_PKG2(reg) GET_BITFIELD(reg, 8, 10) | |
120 | -#define SAD_PKG3(reg) GET_BITFIELD(reg, 11, 13) | |
121 | -#define SAD_PKG4(reg) GET_BITFIELD(reg, 16, 18) | |
122 | -#define SAD_PKG5(reg) GET_BITFIELD(reg, 19, 21) | |
123 | -#define SAD_PKG6(reg) GET_BITFIELD(reg, 24, 26) | |
124 | -#define SAD_PKG7(reg) GET_BITFIELD(reg, 27, 29) | |
122 | +static const u32 ibridge_interleave_list[] = { | |
123 | + 0x64, 0x6c, 0x74, 0x7c, 0x84, | |
124 | + 0x8c, 0x94, 0x9c, 0xa4, 0xac, | |
125 | + 0xb4, 0xbc, 0xc4, 0xcc, 0xd4, | |
126 | + 0xdc, 0xe4, 0xec, 0xf4, 0xfc, | |
127 | +}; | |
125 | 128 | |
126 | -static inline int sad_pkg(u32 reg, int interleave) | |
129 | +struct interleave_pkg { | |
130 | + unsigned char start; | |
131 | + unsigned char end; | |
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) { | |
129 | - case 0: | |
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 | - } | |
159 | + return GET_BITFIELD(reg, table[interleave].start, | |
160 | + table[interleave].end); | |
148 | 161 | } |
149 | 162 | |
150 | 163 | /* Devices 12 Function 7 */ |
151 | 164 | |
... | ... | @@ -262,8 +275,10 @@ |
262 | 275 | |
263 | 276 | /* Device 17, function 0 */ |
264 | 277 | |
265 | -#define RANK_CFG_A 0x0328 | |
278 | +#define SB_RANK_CFG_A 0x0328 | |
266 | 279 | |
280 | +#define IB_RANK_CFG_A 0x0320 | |
281 | + | |
267 | 282 | #define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11) |
268 | 283 | |
269 | 284 | /* |
270 | 285 | |
... | ... | @@ -273,8 +288,23 @@ |
273 | 288 | #define NUM_CHANNELS 4 |
274 | 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 | 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 | 310 | struct sbridge_channel { |
... | ... | @@ -305,8 +335,9 @@ |
305 | 335 | |
306 | 336 | struct sbridge_pvt { |
307 | 337 | struct pci_dev *pci_ta, *pci_ddrio, *pci_ras; |
308 | - struct pci_dev *pci_sad0, *pci_sad1, *pci_ha0; | |
309 | - struct pci_dev *pci_br; | |
338 | + struct pci_dev *pci_sad0, *pci_sad1; | |
339 | + struct pci_dev *pci_ha0, *pci_ha1; | |
340 | + struct pci_dev *pci_br0, *pci_br1; | |
310 | 341 | struct pci_dev *pci_tad[NUM_CHANNELS]; |
311 | 342 | |
312 | 343 | struct sbridge_dev *sbridge_dev; |
313 | 344 | |
... | ... | @@ -364,11 +395,75 @@ |
364 | 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 | 462 | * pci_device_id table for which devices we are looking for |
369 | 463 | */ |
370 | 464 | static DEFINE_PCI_DEVICE_TABLE(sbridge_pci_tbl) = { |
371 | 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 | 467 | {0,} /* 0 terminated list. */ |
373 | 468 | }; |
374 | 469 | |
... | ... | @@ -458,6 +553,52 @@ |
458 | 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 | 603 | Memory check routines |
463 | 604 | ****************************************************************************/ |
464 | 605 | |
... | ... | @@ -520,10 +661,10 @@ |
520 | 661 | enum edac_type mode; |
521 | 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 | 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 | 668 | pvt->sbridge_dev->node_id = NODE_ID(reg); |
528 | 669 | edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n", |
529 | 670 | pvt->sbridge_dev->mc, |
... | ... | @@ -558,7 +699,8 @@ |
558 | 699 | } |
559 | 700 | |
560 | 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 | 704 | if (IS_RDIMM_ENABLED(reg)) { |
563 | 705 | /* FIXME: Can also be LRDIMM */ |
564 | 706 | edac_dbg(0, "Memory is registered\n"); |
565 | 707 | |
... | ... | @@ -629,19 +771,14 @@ |
629 | 771 | * Step 1) Get TOLM/TOHM ranges |
630 | 772 | */ |
631 | 773 | |
632 | - /* Address range is 32:28 */ | |
633 | - pci_read_config_dword(pvt->pci_sad1, TOLM, | |
634 | - ®); | |
635 | - pvt->tolm = GET_TOLM(reg); | |
774 | + pvt->tolm = pvt->info.get_tolm(pvt); | |
636 | 775 | tmp_mb = (1 + pvt->tolm) >> 20; |
637 | 776 | |
638 | 777 | mb = div_u64_rem(tmp_mb, 1000, &kb); |
639 | 778 | edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); |
640 | 779 | |
641 | 780 | /* Address range is already 45:25 */ |
642 | - pci_read_config_dword(pvt->pci_sad1, TOHM, | |
643 | - ®); | |
644 | - pvt->tohm = GET_TOHM(reg); | |
781 | + pvt->tohm = pvt->info.get_tohm(pvt); | |
645 | 782 | tmp_mb = (1 + pvt->tohm) >> 20; |
646 | 783 | |
647 | 784 | mb = div_u64_rem(tmp_mb, 1000, &kb); |
648 | 785 | |
... | ... | @@ -654,9 +791,9 @@ |
654 | 791 | * algorithm bellow. |
655 | 792 | */ |
656 | 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 | 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 | 798 | limit = SAD_LIMIT(reg); |
662 | 799 | |
663 | 800 | |
664 | 801 | |
665 | 802 | |
... | ... | @@ -677,15 +814,16 @@ |
677 | 814 | reg); |
678 | 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 | 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 | 823 | break; |
686 | 824 | |
687 | 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 | |
692 | 830 | |
693 | 831 | |
... | ... | @@ -797,12 +935,13 @@ |
797 | 935 | { |
798 | 936 | struct mem_ctl_info *new_mci; |
799 | 937 | struct sbridge_pvt *pvt = mci->pvt_info; |
938 | + struct pci_dev *pci_ha; | |
800 | 939 | int n_rir, n_sads, n_tads, sad_way, sck_xch; |
801 | 940 | int sad_interl, idx, base_ch; |
802 | 941 | int interleave_mode; |
803 | - unsigned sad_interleave[MAX_INTERLEAVE]; | |
942 | + unsigned sad_interleave[pvt->info.max_interleave]; | |
804 | 943 | u32 reg; |
805 | - u8 ch_way,sck_way; | |
944 | + u8 ch_way, sck_way, pkg, sad_ha = 0; | |
806 | 945 | u32 tad_offset; |
807 | 946 | u32 rir_way; |
808 | 947 | u32 mb, kb; |
... | ... | @@ -828,8 +967,8 @@ |
828 | 967 | /* |
829 | 968 | * Step 1) Get socket |
830 | 969 | */ |
831 | - for (n_sads = 0; n_sads < MAX_SAD; n_sads++) { | |
832 | - pci_read_config_dword(pvt->pci_sad0, dram_rule[n_sads], | |
970 | + for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) { | |
971 | + pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads], | |
833 | 972 | ®); |
834 | 973 | |
835 | 974 | if (!DRAM_RULE_ENABLE(reg)) |
836 | 975 | |
837 | 976 | |
838 | 977 | |
839 | 978 | |
840 | 979 | |
... | ... | @@ -844,53 +983,65 @@ |
844 | 983 | break; |
845 | 984 | prv = limit; |
846 | 985 | } |
847 | - if (n_sads == MAX_SAD) { | |
986 | + if (n_sads == pvt->info.max_sad) { | |
848 | 987 | sprintf(msg, "Can't discover the memory socket"); |
849 | 988 | return -EINVAL; |
850 | 989 | } |
851 | 990 | *area_type = get_dram_attr(reg); |
852 | 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); | |
857 | - for (sad_way = 0; sad_way < 8; sad_way++) { | |
858 | - if (sad_way > 0 && sad_interl == sad_pkg(reg, sad_way)) | |
995 | + | |
996 | + if (pvt->info.type == SANDY_BRIDGE) { | |
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 | 1020 | break; |
860 | - sad_interleave[sad_way] = sad_pkg(reg, sad_way); | |
861 | - edac_dbg(0, "SAD interleave #%d: %d\n", | |
862 | - sad_way, sad_interleave[sad_way]); | |
863 | - } | |
864 | - edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s\n", | |
865 | - pvt->sbridge_dev->mc, | |
866 | - n_sads, | |
867 | - addr, | |
868 | - limit, | |
869 | - sad_way + 7, | |
870 | - interleave_mode ? "" : "XOR[18:16]"); | |
871 | - if (interleave_mode) | |
872 | - idx = ((addr >> 6) ^ (addr >> 16)) & 7; | |
873 | - else | |
1021 | + case 2: | |
1022 | + idx = idx & 1; | |
1023 | + break; | |
1024 | + case 4: | |
1025 | + idx = idx & 3; | |
1026 | + break; | |
1027 | + case 8: | |
1028 | + break; | |
1029 | + default: | |
1030 | + sprintf(msg, "Can't discover socket interleave"); | |
1031 | + return -EINVAL; | |
1032 | + } | |
1033 | + *socket = sad_interleave[idx]; | |
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 | 1038 | idx = (addr >> 6) & 7; |
875 | - switch (sad_way) { | |
876 | - case 1: | |
877 | - idx = 0; | |
878 | - break; | |
879 | - case 2: | |
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; | |
1039 | + pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx); | |
1040 | + *socket = sad_pkg_socket(pkg); | |
1041 | + sad_ha = sad_pkg_ha(pkg); | |
1042 | + edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d\n", | |
1043 | + idx, *socket, sad_ha); | |
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 | 1047 | * Move to the proper node structure, in order to access the |
897 | 1048 | |
... | ... | @@ -909,9 +1060,16 @@ |
909 | 1060 | * Step 2) Get memory channel |
910 | 1061 | */ |
911 | 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 | 1071 | for (n_tads = 0; n_tads < MAX_TAD; n_tads++) { |
913 | - pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads], | |
914 | - ®); | |
1072 | + pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], ®); | |
915 | 1073 | limit = TAD_LIMIT(reg); |
916 | 1074 | if (limit <= prv) { |
917 | 1075 | sprintf(msg, "Can't discover the memory channel"); |
918 | 1076 | |
... | ... | @@ -921,14 +1079,13 @@ |
921 | 1079 | break; |
922 | 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 | 1087 | ch_way = TAD_CH(reg) + 1; |
925 | 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 | 1090 | if (ch_way == 3) |
934 | 1091 | idx = addr >> 6; |
... | ... | @@ -958,6 +1115,10 @@ |
958 | 1115 | } |
959 | 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 | 1122 | if (pvt->is_mirrored) { |
962 | 1123 | *channel_mask |= 1 << ((base_ch + 2) % 4); |
963 | 1124 | switch(ch_way) { |
... | ... | @@ -1091,12 +1252,6 @@ |
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 | 1255 | static int sbridge_get_onedevice(struct pci_dev **prev, |
1101 | 1256 | u8 *num_mc, |
1102 | 1257 | const struct pci_id_table *table, |
1103 | 1258 | |
... | ... | @@ -1198,11 +1353,21 @@ |
1198 | 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 | 1369 | int i, rc; |
1204 | 1370 | struct pci_dev *pdev = NULL; |
1205 | - const struct pci_id_table *table = pci_dev_descr_sbridge_table; | |
1206 | 1371 | |
1207 | 1372 | while (table && table->descr) { |
1208 | 1373 | for (i = 0; i < table->n_devs; i++) { |
... | ... | @@ -1226,8 +1391,8 @@ |
1226 | 1391 | return 0; |
1227 | 1392 | } |
1228 | 1393 | |
1229 | -static int mci_bind_devs(struct mem_ctl_info *mci, | |
1230 | - struct sbridge_dev *sbridge_dev) | |
1394 | +static int sbridge_mci_bind_devs(struct mem_ctl_info *mci, | |
1395 | + struct sbridge_dev *sbridge_dev) | |
1231 | 1396 | { |
1232 | 1397 | struct sbridge_pvt *pvt = mci->pvt_info; |
1233 | 1398 | struct pci_dev *pdev; |
... | ... | @@ -1255,7 +1420,7 @@ |
1255 | 1420 | case 13: |
1256 | 1421 | switch (func) { |
1257 | 1422 | case 6: |
1258 | - pvt->pci_br = pdev; | |
1423 | + pvt->pci_br0 = pdev; | |
1259 | 1424 | break; |
1260 | 1425 | default: |
1261 | 1426 | goto error; |
... | ... | @@ -1329,6 +1494,131 @@ |
1329 | 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 | 1623 | Error check routines |
1334 | 1624 | ****************************************************************************/ |
... | ... | @@ -1349,7 +1639,7 @@ |
1349 | 1639 | bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); |
1350 | 1640 | bool overflow = GET_BITFIELD(m->status, 62, 62); |
1351 | 1641 | bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); |
1352 | - bool recoverable = GET_BITFIELD(m->status, 56, 56); | |
1642 | + bool recoverable; | |
1353 | 1643 | u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52); |
1354 | 1644 | u32 mscod = GET_BITFIELD(m->status, 16, 31); |
1355 | 1645 | u32 errcode = GET_BITFIELD(m->status, 0, 15); |
... | ... | @@ -1360,6 +1650,11 @@ |
1360 | 1650 | int rc, dimm; |
1361 | 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 | 1658 | if (uncorrected_error) { |
1364 | 1659 | if (ripv) { |
1365 | 1660 | type = "FATAL"; |
... | ... | @@ -1409,6 +1704,10 @@ |
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 | 1711 | rc = get_memory_error_data(mci, m->addr, &socket, |
1413 | 1712 | &channel_mask, &rank, &area_type, msg); |
1414 | 1713 | if (rc < 0) |
1415 | 1714 | |
... | ... | @@ -1614,11 +1913,12 @@ |
1614 | 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 | 1918 | struct mem_ctl_info *mci; |
1620 | 1919 | struct edac_mc_layer layers[2]; |
1621 | 1920 | struct sbridge_pvt *pvt; |
1921 | + struct pci_dev *pdev = sbridge_dev->pdev[0]; | |
1622 | 1922 | int rc; |
1623 | 1923 | |
1624 | 1924 | /* Check the number of active and not disabled channels */ |
... | ... | @@ -1640,7 +1940,7 @@ |
1640 | 1940 | return -ENOMEM; |
1641 | 1941 | |
1642 | 1942 | edac_dbg(0, "MC: mci = %p, dev = %p\n", |
1643 | - mci, &sbridge_dev->pdev[0]->dev); | |
1943 | + mci, &pdev->dev); | |
1644 | 1944 | |
1645 | 1945 | pvt = mci->pvt_info; |
1646 | 1946 | memset(pvt, 0, sizeof(*pvt)); |
1647 | 1947 | |
1648 | 1948 | |
1649 | 1949 | |
... | ... | @@ -1654,24 +1954,52 @@ |
1654 | 1954 | mci->edac_cap = EDAC_FLAG_NONE; |
1655 | 1955 | mci->mod_name = "sbridge_edac.c"; |
1656 | 1956 | mci->mod_ver = SBRIDGE_REVISION; |
1657 | - mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); | |
1658 | - mci->dev_name = pci_name(sbridge_dev->pdev[0]); | |
1957 | + mci->dev_name = pci_name(pdev); | |
1659 | 1958 | mci->ctl_page_to_phys = NULL; |
1660 | 1959 | |
1661 | 1960 | /* Set the function pointer to an actual operation function */ |
1662 | 1961 | mci->edac_check = sbridge_check_error; |
1663 | 1962 | |
1664 | - /* Store pci devices at mci for faster access */ | |
1665 | - rc = mci_bind_devs(mci, sbridge_dev); | |
1666 | - if (unlikely(rc < 0)) | |
1667 | - goto fail0; | |
1963 | + pvt->info.type = type; | |
1964 | + if (type == IVY_BRIDGE) { | |
1965 | + pvt->info.rankcfgr = IB_RANK_CFG_A; | |
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); | |
1668 | 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 | + | |
1996 | + | |
1669 | 1997 | /* Get dimm basic config and the memory layout */ |
1670 | 1998 | get_dimm_config(mci); |
1671 | 1999 | get_memory_layout(mci); |
1672 | 2000 | |
1673 | 2001 | /* record ptr to the generic device */ |
1674 | - mci->pdev = &sbridge_dev->pdev[0]->dev; | |
2002 | + mci->pdev = &pdev->dev; | |
1675 | 2003 | |
1676 | 2004 | /* add this new MC control structure to EDAC's list of MCs */ |
1677 | 2005 | if (unlikely(edac_mc_add_mc(mci))) { |
... | ... | @@ -1702,6 +2030,7 @@ |
1702 | 2030 | int rc; |
1703 | 2031 | u8 mc, num_mc = 0; |
1704 | 2032 | struct sbridge_dev *sbridge_dev; |
2033 | + enum type type; | |
1705 | 2034 | |
1706 | 2035 | /* get the pci devices we want to reserve for our use */ |
1707 | 2036 | mutex_lock(&sbridge_edac_lock); |
... | ... | @@ -1715,7 +2044,13 @@ |
1715 | 2044 | } |
1716 | 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 | 2054 | if (unlikely(rc < 0)) |
1720 | 2055 | goto fail0; |
1721 | 2056 | mc = 0; |
... | ... | @@ -1724,7 +2059,7 @@ |
1724 | 2059 | edac_dbg(0, "Registering MC#%d (%d of %d)\n", |
1725 | 2060 | mc, mc + 1, num_mc); |
1726 | 2061 | sbridge_dev->mc = mc++; |
1727 | - rc = sbridge_register_mci(sbridge_dev); | |
2062 | + rc = sbridge_register_mci(sbridge_dev, type); | |
1728 | 2063 | if (unlikely(rc < 0)) |
1729 | 2064 | goto fail1; |
1730 | 2065 | } |
... | ... | @@ -1839,6 +2174,6 @@ |
1839 | 2174 | MODULE_LICENSE("GPL"); |
1840 | 2175 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); |
1841 | 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 | 2178 | SBRIDGE_REVISION); |