aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-09-05 01:35:08 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 10:44:58 -0400
commitf47429494fd50c0b7396fe3f8a26ea638b47c5ba (patch)
treecb951ca0a07f97f19205b9e593b4343662867cbe /drivers/edac
parent66607706cee7b6901aa0509198f075859c93ec6a (diff)
i7core_edac: create one mc per socket/QPI
Instead of creating just one memory controller, create one per socket (e. g. per Quick Link Path Interconnect). This better reflects the Nehalem architecture. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/i7core_edac.c507
1 files changed, 228 insertions, 279 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 7bcb5993b501..5bc316b8e805 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -29,11 +29,21 @@
29#include <linux/mmzone.h> 29#include <linux/mmzone.h>
30#include <linux/edac_mce.h> 30#include <linux/edac_mce.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/smp.h>
32#include <asm/processor.h> 33#include <asm/processor.h>
33 34
34#include "edac_core.h" 35#include "edac_core.h"
35 36
36/* 37/*
38 * This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
39 * registers start at bus 255, and are not reported by BIOS.
40 * We currently find devices with only 2 sockets. In order to support more QPI
41 * Quick Path Interconnect, just increment this number.
42 */
43#define MAX_SOCKET_BUSES 2
44
45
46/*
37 * Alter this version for the module when modifications are made 47 * Alter this version for the module when modifications are made
38 */ 48 */
39#define I7CORE_REVISION " Ver: 1.0.0 " __DATE__ 49#define I7CORE_REVISION " Ver: 1.0.0 " __DATE__
@@ -162,7 +172,6 @@
162 172
163#define NUM_CHANS 3 173#define NUM_CHANS 3
164#define MAX_DIMMS 3 /* Max DIMMS per channel */ 174#define MAX_DIMMS 3 /* Max DIMMS per channel */
165#define NUM_SOCKETS 2 /* Max number of MC sockets */
166#define MAX_MCR_FUNC 4 175#define MAX_MCR_FUNC 4
167#define MAX_CHAN_FUNC 3 176#define MAX_CHAN_FUNC 3
168 177
@@ -177,7 +186,6 @@ struct i7core_info {
177struct i7core_inject { 186struct i7core_inject {
178 int enable; 187 int enable;
179 188
180 u8 socket;
181 u32 section; 189 u32 section;
182 u32 type; 190 u32 type;
183 u32 eccmask; 191 u32 eccmask;
@@ -197,29 +205,37 @@ struct pci_id_descr {
197 int dev_id; 205 int dev_id;
198}; 206};
199 207
208struct i7core_dev {
209 struct list_head list;
210 u8 socket;
211 struct pci_dev **pdev;
212 struct mem_ctl_info *mci;
213};
214
200struct i7core_pvt { 215struct i7core_pvt {
201 struct pci_dev *pci_noncore[NUM_SOCKETS]; 216 struct pci_dev *pci_noncore;
202 struct pci_dev *pci_mcr[NUM_SOCKETS][MAX_MCR_FUNC + 1]; 217 struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1];
203 struct pci_dev *pci_ch[NUM_SOCKETS][NUM_CHANS][MAX_CHAN_FUNC + 1]; 218 struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
219
220 struct i7core_dev *i7core_dev;
204 221
205 struct i7core_info info; 222 struct i7core_info info;
206 struct i7core_inject inject; 223 struct i7core_inject inject;
207 struct i7core_channel channel[NUM_SOCKETS][NUM_CHANS]; 224 struct i7core_channel channel[NUM_CHANS];
208 225
209 int sockets; /* Number of sockets */ 226 int channels; /* Number of active channels */
210 int channels; /* Number of active channels */
211 227
212 int ce_count_available[NUM_SOCKETS]; 228 int ce_count_available;
213 int csrow_map[NUM_SOCKETS][NUM_CHANS][MAX_DIMMS]; 229 int csrow_map[NUM_CHANS][MAX_DIMMS];
214 230
215 /* ECC corrected errors counts per udimm */ 231 /* ECC corrected errors counts per udimm */
216 unsigned long udimm_ce_count[NUM_SOCKETS][MAX_DIMMS]; 232 unsigned long udimm_ce_count[MAX_DIMMS];
217 int udimm_last_ce_count[NUM_SOCKETS][MAX_DIMMS]; 233 int udimm_last_ce_count[MAX_DIMMS];
218 /* ECC corrected errors counts per rdimm */ 234 /* ECC corrected errors counts per rdimm */
219 unsigned long rdimm_ce_count[NUM_SOCKETS][NUM_CHANS][MAX_DIMMS]; 235 unsigned long rdimm_ce_count[NUM_CHANS][MAX_DIMMS];
220 int rdimm_last_ce_count[NUM_SOCKETS][NUM_CHANS][MAX_DIMMS]; 236 int rdimm_last_ce_count[NUM_CHANS][MAX_DIMMS];
221 237
222 unsigned int is_registered[NUM_SOCKETS]; 238 unsigned int is_registered;
223 239
224 /* mcelog glue */ 240 /* mcelog glue */
225 struct edac_mce edac_mce; 241 struct edac_mce edac_mce;
@@ -228,22 +244,10 @@ struct i7core_pvt {
228 spinlock_t mce_lock; 244 spinlock_t mce_lock;
229}; 245};
230 246
231struct i7core_dev {
232 struct list_head list;
233
234 int socket;
235 struct pci_dev **pdev;
236};
237
238/* Static vars */ 247/* Static vars */
239static LIST_HEAD(i7core_edac_list); 248static LIST_HEAD(i7core_edac_list);
240static DEFINE_MUTEX(i7core_edac_lock); 249static DEFINE_MUTEX(i7core_edac_lock);
241 250static u8 max_num_sockets;
242/* Device name and register DID (Device ID) */
243struct i7core_dev_info {
244 const char *ctl_name; /* name for this device */
245 u16 fsb_mapping_errors; /* DID for the branchmap,control */
246};
247 251
248#define PCI_DESCR(device, function, device_id) \ 252#define PCI_DESCR(device, function, device_id) \
249 .dev = (device), \ 253 .dev = (device), \
@@ -295,15 +299,6 @@ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
295 {0,} /* 0 terminated list. */ 299 {0,} /* 0 terminated list. */
296}; 300};
297 301
298
299/* Table of devices attributes supported by this driver */
300static const struct i7core_dev_info i7core_probe_devs[] = {
301 {
302 .ctl_name = "i7 Core",
303 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7_MCR,
304 },
305};
306
307static struct edac_pci_ctl_info *i7core_pci; 302static struct edac_pci_ctl_info *i7core_pci;
308 303
309/**************************************************************************** 304/****************************************************************************
@@ -356,7 +351,7 @@ static inline int numcol(u32 col)
356 return cols[col & 0x3]; 351 return cols[col & 0x3];
357} 352}
358 353
359static struct i7core_dev *get_i7core_dev(int socket) 354static struct i7core_dev *get_i7core_dev(u8 socket)
360{ 355{
361 struct i7core_dev *i7core_dev; 356 struct i7core_dev *i7core_dev;
362 357
@@ -471,18 +466,19 @@ static int i7core_get_active_channels(u8 socket, unsigned *channels,
471 return 0; 466 return 0;
472} 467}
473 468
474static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket) 469static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
475{ 470{
476 struct i7core_pvt *pvt = mci->pvt_info; 471 struct i7core_pvt *pvt = mci->pvt_info;
477 struct csrow_info *csr; 472 struct csrow_info *csr;
478 struct pci_dev *pdev; 473 struct pci_dev *pdev;
479 int i, j; 474 int i, j;
475 u8 socket = pvt->i7core_dev->socket;
480 unsigned long last_page = 0; 476 unsigned long last_page = 0;
481 enum edac_type mode; 477 enum edac_type mode;
482 enum mem_type mtype; 478 enum mem_type mtype;
483 479
484 /* Get data from the MC register, function 0 */ 480 /* Get data from the MC register, function 0 */
485 pdev = pvt->pci_mcr[socket][0]; 481 pdev = pvt->pci_mcr[0];
486 if (!pdev) 482 if (!pdev)
487 return -ENODEV; 483 return -ENODEV;
488 484
@@ -529,10 +525,10 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
529 } 525 }
530 526
531 /* Devices 4-6 function 0 */ 527 /* Devices 4-6 function 0 */
532 pci_read_config_dword(pvt->pci_ch[socket][i][0], 528 pci_read_config_dword(pvt->pci_ch[i][0],
533 MC_CHANNEL_DIMM_INIT_PARAMS, &data); 529 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
534 530
535 pvt->channel[socket][i].ranks = (data & QUAD_RANK_PRESENT) ? 531 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT) ?
536 4 : 2; 532 4 : 2;
537 533
538 if (data & REGISTERED_DIMM) 534 if (data & REGISTERED_DIMM)
@@ -549,11 +545,11 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
549#endif 545#endif
550 546
551 /* Devices 4-6 function 1 */ 547 /* Devices 4-6 function 1 */
552 pci_read_config_dword(pvt->pci_ch[socket][i][1], 548 pci_read_config_dword(pvt->pci_ch[i][1],
553 MC_DOD_CH_DIMM0, &dimm_dod[0]); 549 MC_DOD_CH_DIMM0, &dimm_dod[0]);
554 pci_read_config_dword(pvt->pci_ch[socket][i][1], 550 pci_read_config_dword(pvt->pci_ch[i][1],
555 MC_DOD_CH_DIMM1, &dimm_dod[1]); 551 MC_DOD_CH_DIMM1, &dimm_dod[1]);
556 pci_read_config_dword(pvt->pci_ch[socket][i][1], 552 pci_read_config_dword(pvt->pci_ch[i][1],
557 MC_DOD_CH_DIMM2, &dimm_dod[2]); 553 MC_DOD_CH_DIMM2, &dimm_dod[2]);
558 554
559 debugf0("Ch%d phy rd%d, wr%d (0x%08x): " 555 debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
@@ -561,7 +557,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
561 i, 557 i,
562 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i), 558 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
563 data, 559 data,
564 pvt->channel[socket][i].ranks, 560 pvt->channel[i].ranks,
565 (data & REGISTERED_DIMM) ? 'R' : 'U'); 561 (data & REGISTERED_DIMM) ? 'R' : 'U');
566 562
567 for (j = 0; j < 3; j++) { 563 for (j = 0; j < 3; j++) {
@@ -579,7 +575,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
579 /* DDR3 has 8 I/O banks */ 575 /* DDR3 has 8 I/O banks */
580 size = (rows * cols * banks * ranks) >> (20 - 3); 576 size = (rows * cols * banks * ranks) >> (20 - 3);
581 577
582 pvt->channel[socket][i].dimms++; 578 pvt->channel[i].dimms++;
583 579
584 debugf0("\tdimm %d %d Mb offset: %x, " 580 debugf0("\tdimm %d %d Mb offset: %x, "
585 "bank: %d, rank: %d, row: %#x, col: %#x\n", 581 "bank: %d, rank: %d, row: %#x, col: %#x\n",
@@ -607,7 +603,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
607 csr->channels[0].chan_idx = i; 603 csr->channels[0].chan_idx = i;
608 csr->channels[0].ce_count = 0; 604 csr->channels[0].ce_count = 0;
609 605
610 pvt->csrow_map[socket][i][j] = *csrow; 606 pvt->csrow_map[i][j] = *csrow;
611 607
612 switch (banks) { 608 switch (banks) {
613 case 4: 609 case 4:
@@ -665,43 +661,16 @@ static int disable_inject(struct mem_ctl_info *mci)
665 661
666 pvt->inject.enable = 0; 662 pvt->inject.enable = 0;
667 663
668 if (!pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0]) 664 if (!pvt->pci_ch[pvt->inject.channel][0])
669 return -ENODEV; 665 return -ENODEV;
670 666
671 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], 667 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
672 MC_CHANNEL_ERROR_INJECT, 0); 668 MC_CHANNEL_ERROR_INJECT, 0);
673 669
674 return 0; 670 return 0;
675} 671}
676 672
677/* 673/*
678 * i7core inject inject.socket
679 *
680 * accept and store error injection inject.socket value
681 */
682static ssize_t i7core_inject_socket_store(struct mem_ctl_info *mci,
683 const char *data, size_t count)
684{
685 struct i7core_pvt *pvt = mci->pvt_info;
686 unsigned long value;
687 int rc;
688
689 rc = strict_strtoul(data, 10, &value);
690 if ((rc < 0) || (value >= pvt->sockets))
691 return -EIO;
692
693 pvt->inject.socket = (u32) value;
694 return count;
695}
696
697static ssize_t i7core_inject_socket_show(struct mem_ctl_info *mci,
698 char *data)
699{
700 struct i7core_pvt *pvt = mci->pvt_info;
701 return sprintf(data, "%d\n", pvt->inject.socket);
702}
703
704/*
705 * i7core inject inject.section 674 * i7core inject inject.section
706 * 675 *
707 * accept and store error injection inject.section value 676 * accept and store error injection inject.section value
@@ -965,7 +934,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
965 int rc; 934 int rc;
966 long enable; 935 long enable;
967 936
968 if (!pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0]) 937 if (!pvt->pci_ch[pvt->inject.channel][0])
969 return 0; 938 return 0;
970 939
971 rc = strict_strtoul(data, 10, &enable); 940 rc = strict_strtoul(data, 10, &enable);
@@ -983,7 +952,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
983 if (pvt->inject.dimm < 0) 952 if (pvt->inject.dimm < 0)
984 mask |= 1L << 41; 953 mask |= 1L << 41;
985 else { 954 else {
986 if (pvt->channel[pvt->inject.socket][pvt->inject.channel].dimms > 2) 955 if (pvt->channel[pvt->inject.channel].dimms > 2)
987 mask |= (pvt->inject.dimm & 0x3L) << 35; 956 mask |= (pvt->inject.dimm & 0x3L) << 35;
988 else 957 else
989 mask |= (pvt->inject.dimm & 0x1L) << 36; 958 mask |= (pvt->inject.dimm & 0x1L) << 36;
@@ -993,7 +962,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
993 if (pvt->inject.rank < 0) 962 if (pvt->inject.rank < 0)
994 mask |= 1L << 40; 963 mask |= 1L << 40;
995 else { 964 else {
996 if (pvt->channel[pvt->inject.socket][pvt->inject.channel].dimms > 2) 965 if (pvt->channel[pvt->inject.channel].dimms > 2)
997 mask |= (pvt->inject.rank & 0x1L) << 34; 966 mask |= (pvt->inject.rank & 0x1L) << 34;
998 else 967 else
999 mask |= (pvt->inject.rank & 0x3L) << 34; 968 mask |= (pvt->inject.rank & 0x3L) << 34;
@@ -1029,18 +998,18 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
1029 (pvt->inject.type & 0x6) << (3 - 1); 998 (pvt->inject.type & 0x6) << (3 - 1);
1030 999
1031 /* Unlock writes to registers - this register is write only */ 1000 /* Unlock writes to registers - this register is write only */
1032 pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket], 1001 pci_write_config_dword(pvt->pci_noncore,
1033 MC_CFG_CONTROL, 0x2); 1002 MC_CFG_CONTROL, 0x2);
1034 1003
1035 write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], 1004 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1036 MC_CHANNEL_ADDR_MATCH, mask); 1005 MC_CHANNEL_ADDR_MATCH, mask);
1037 write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], 1006 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1038 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L); 1007 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
1039 1008
1040 write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], 1009 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1041 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask); 1010 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
1042 1011
1043 write_and_test(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], 1012 write_and_test(pvt->pci_ch[pvt->inject.channel][0],
1044 MC_CHANNEL_ERROR_INJECT, injectmask); 1013 MC_CHANNEL_ERROR_INJECT, injectmask);
1045 1014
1046 /* 1015 /*
@@ -1048,7 +1017,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
1048 * Without writing 8 to this register, errors aren't injected. Not sure 1017 * Without writing 8 to this register, errors aren't injected. Not sure
1049 * why. 1018 * why.
1050 */ 1019 */
1051 pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket], 1020 pci_write_config_dword(pvt->pci_noncore,
1052 MC_CFG_CONTROL, 8); 1021 MC_CFG_CONTROL, 8);
1053 1022
1054 debugf0("Error inject addr match 0x%016llx, ecc 0x%08x," 1023 debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
@@ -1065,7 +1034,7 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
1065 struct i7core_pvt *pvt = mci->pvt_info; 1034 struct i7core_pvt *pvt = mci->pvt_info;
1066 u32 injectmask; 1035 u32 injectmask;
1067 1036
1068 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0], 1037 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
1069 MC_CHANNEL_ERROR_INJECT, &injectmask); 1038 MC_CHANNEL_ERROR_INJECT, &injectmask);
1070 1039
1071 debugf0("Inject error read: 0x%018x\n", injectmask); 1040 debugf0("Inject error read: 0x%018x\n", injectmask);
@@ -1078,34 +1047,30 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
1078 1047
1079static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data) 1048static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
1080{ 1049{
1081 unsigned i, j, count, total = 0; 1050 unsigned i, count, total = 0;
1082 struct i7core_pvt *pvt = mci->pvt_info; 1051 struct i7core_pvt *pvt = mci->pvt_info;
1083 1052
1084 for (i = 0; i < pvt->sockets; i++) { 1053 if (!pvt->ce_count_available) {
1085 if (!pvt->ce_count_available[i]) { 1054 count = sprintf(data, "data unavailable\n");
1086 count = sprintf(data, "socket 0 data unavailable\n"); 1055 return 0;
1087 continue;
1088 }
1089 if (!pvt->is_registered[i])
1090 count = sprintf(data, "socket %d, dimm0: %lu\n"
1091 "dimm1: %lu\ndimm2: %lu\n",
1092 i,
1093 pvt->udimm_ce_count[i][0],
1094 pvt->udimm_ce_count[i][1],
1095 pvt->udimm_ce_count[i][2]);
1096 else
1097 for (j = 0; j < NUM_CHANS; j++) {
1098 count = sprintf(data, "socket %d, channel %d "
1099 "RDIMM0: %lu "
1100 "RDIMM1: %lu RDIMM2: %lu\n",
1101 i, j,
1102 pvt->rdimm_ce_count[i][j][0],
1103 pvt->rdimm_ce_count[i][j][1],
1104 pvt->rdimm_ce_count[i][j][2]);
1105 }
1106 data += count;
1107 total += count;
1108 } 1056 }
1057 if (!pvt->is_registered)
1058 count = sprintf(data, "all channels "
1059 "UDIMM0: %lu UDIMM1: %lu UDIMM2: %lu\n",
1060 pvt->udimm_ce_count[0],
1061 pvt->udimm_ce_count[1],
1062 pvt->udimm_ce_count[2]);
1063 else
1064 for (i = 0; i < NUM_CHANS; i++) {
1065 count = sprintf(data, "channel %d RDIMM0: %lu "
1066 "RDIMM1: %lu RDIMM2: %lu\n",
1067 i,
1068 pvt->rdimm_ce_count[i][0],
1069 pvt->rdimm_ce_count[i][1],
1070 pvt->rdimm_ce_count[i][2]);
1071 }
1072 data += count;
1073 total += count;
1109 1074
1110 return total; 1075 return total;
1111} 1076}
@@ -1116,13 +1081,6 @@ static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
1116static struct mcidev_sysfs_attribute i7core_inj_attrs[] = { 1081static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
1117 { 1082 {
1118 .attr = { 1083 .attr = {
1119 .name = "inject_socket",
1120 .mode = (S_IRUGO | S_IWUSR)
1121 },
1122 .show = i7core_inject_socket_show,
1123 .store = i7core_inject_socket_store,
1124 }, {
1125 .attr = {
1126 .name = "inject_section", 1084 .name = "inject_section",
1127 .mode = (S_IRUGO | S_IWUSR) 1085 .mode = (S_IRUGO | S_IWUSR)
1128 }, 1086 },
@@ -1178,7 +1136,7 @@ static void i7core_put_devices(void)
1178{ 1136{
1179 int i, j; 1137 int i, j;
1180 1138
1181 for (i = 0; i < NUM_SOCKETS; i++) { 1139 for (i = 0; i < max_num_sockets; i++) {
1182 struct i7core_dev *i7core_dev = get_i7core_dev(i); 1140 struct i7core_dev *i7core_dev = get_i7core_dev(i);
1183 if (!i7core_dev) 1141 if (!i7core_dev)
1184 continue; 1142 continue;
@@ -1204,7 +1162,7 @@ static void i7core_xeon_pci_fixup(void)
1204 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 1162 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1205 pci_dev_descr[0].dev_id, NULL); 1163 pci_dev_descr[0].dev_id, NULL);
1206 if (unlikely(!pdev)) { 1164 if (unlikely(!pdev)) {
1207 for (i = 0; i < NUM_SOCKETS; i ++) 1165 for (i = 0; i < MAX_SOCKET_BUSES; i++)
1208 pcibios_scan_specific_bus(255-i); 1166 pcibios_scan_specific_bus(255-i);
1209 } 1167 }
1210} 1168}
@@ -1323,13 +1281,11 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
1323 return 0; 1281 return 0;
1324} 1282}
1325 1283
1326static int i7core_get_devices(u8 *sockets) 1284static int i7core_get_devices(void)
1327{ 1285{
1328 int i; 1286 int i;
1329 struct pci_dev *pdev = NULL; 1287 struct pci_dev *pdev = NULL;
1330 struct i7core_dev *i7core_dev = NULL;
1331 1288
1332 *sockets = 0;
1333 for (i = 0; i < N_DEVS; i++) { 1289 for (i = 0; i < N_DEVS; i++) {
1334 pdev = NULL; 1290 pdev = NULL;
1335 do { 1291 do {
@@ -1340,55 +1296,48 @@ static int i7core_get_devices(u8 *sockets)
1340 } while (pdev); 1296 } while (pdev);
1341 } 1297 }
1342 1298
1343 list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
1344 if (i7core_dev->socket + 1 > *sockets)
1345 *sockets = i7core_dev->socket + 1;
1346 }
1347
1348 return 0; 1299 return 0;
1349} 1300}
1350 1301
1351static int mci_bind_devs(struct mem_ctl_info *mci) 1302static int mci_bind_devs(struct mem_ctl_info *mci,
1303 struct i7core_dev *i7core_dev)
1352{ 1304{
1353 struct i7core_pvt *pvt = mci->pvt_info; 1305 struct i7core_pvt *pvt = mci->pvt_info;
1354 struct pci_dev *pdev; 1306 struct pci_dev *pdev;
1355 int i, j, func, slot; 1307 int i, func, slot;
1356 1308
1357 for (i = 0; i < pvt->sockets; i++) { 1309 /* Associates i7core_dev and mci for future usage */
1358 struct i7core_dev *i7core_dev = get_i7core_dev(i); 1310 pvt->i7core_dev = i7core_dev;
1311 i7core_dev->mci = mci;
1359 1312
1360 if (!i7core_dev) 1313 pvt->is_registered = 0;
1314 for (i = 0; i < N_DEVS; i++) {
1315 pdev = i7core_dev->pdev[i];
1316 if (!pdev)
1361 continue; 1317 continue;
1362 1318
1363 pvt->is_registered[i] = 0; 1319 func = PCI_FUNC(pdev->devfn);
1364 for (j = 0; j < N_DEVS; j++) { 1320 slot = PCI_SLOT(pdev->devfn);
1365 pdev = i7core_dev->pdev[j]; 1321 if (slot == 3) {
1366 if (!pdev) 1322 if (unlikely(func > MAX_MCR_FUNC))
1367 continue; 1323 goto error;
1368 1324 pvt->pci_mcr[func] = pdev;
1369 func = PCI_FUNC(pdev->devfn); 1325 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1370 slot = PCI_SLOT(pdev->devfn); 1326 if (unlikely(func > MAX_CHAN_FUNC))
1371 if (slot == 3) {
1372 if (unlikely(func > MAX_MCR_FUNC))
1373 goto error;
1374 pvt->pci_mcr[i][func] = pdev;
1375 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1376 if (unlikely(func > MAX_CHAN_FUNC))
1377 goto error;
1378 pvt->pci_ch[i][slot - 4][func] = pdev;
1379 } else if (!slot && !func)
1380 pvt->pci_noncore[i] = pdev;
1381 else
1382 goto error; 1327 goto error;
1328 pvt->pci_ch[slot - 4][func] = pdev;
1329 } else if (!slot && !func)
1330 pvt->pci_noncore = pdev;
1331 else
1332 goto error;
1383 1333
1384 debugf0("Associated fn %d.%d, dev = %p, socket %d\n", 1334 debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
1385 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), 1335 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
1386 pdev, i); 1336 pdev, i7core_dev->socket);
1387 1337
1388 if (PCI_SLOT(pdev->devfn) == 3 && 1338 if (PCI_SLOT(pdev->devfn) == 3 &&
1389 PCI_FUNC(pdev->devfn) == 2) 1339 PCI_FUNC(pdev->devfn) == 2)
1390 pvt->is_registered[i] = 1; 1340 pvt->is_registered = 1;
1391 }
1392 } 1341 }
1393 1342
1394 return 0; 1343 return 0;
@@ -1403,17 +1352,17 @@ error:
1403/**************************************************************************** 1352/****************************************************************************
1404 Error check routines 1353 Error check routines
1405 ****************************************************************************/ 1354 ****************************************************************************/
1406static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci, int socket, 1355static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
1407 int chan, int dimm, int add) 1356 int chan, int dimm, int add)
1408{ 1357{
1409 char *msg; 1358 char *msg;
1410 struct i7core_pvt *pvt = mci->pvt_info; 1359 struct i7core_pvt *pvt = mci->pvt_info;
1411 int row = pvt->csrow_map[socket][chan][dimm], i; 1360 int row = pvt->csrow_map[chan][dimm], i;
1412 1361
1413 for (i = 0; i < add; i++) { 1362 for (i = 0; i < add; i++) {
1414 msg = kasprintf(GFP_KERNEL, "Corrected error " 1363 msg = kasprintf(GFP_KERNEL, "Corrected error "
1415 "(Socket=%d channel=%d dimm=%d", 1364 "(Socket=%d channel=%d dimm=%d)",
1416 socket, chan, dimm); 1365 pvt->i7core_dev->socket, chan, dimm);
1417 1366
1418 edac_mc_handle_fbd_ce(mci, row, 0, msg); 1367 edac_mc_handle_fbd_ce(mci, row, 0, msg);
1419 kfree (msg); 1368 kfree (msg);
@@ -1421,71 +1370,71 @@ static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci, int socket,
1421} 1370}
1422 1371
1423static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci, 1372static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
1424 int socket, int chan, int new0, int new1, int new2) 1373 int chan, int new0, int new1, int new2)
1425{ 1374{
1426 struct i7core_pvt *pvt = mci->pvt_info; 1375 struct i7core_pvt *pvt = mci->pvt_info;
1427 int add0 = 0, add1 = 0, add2 = 0; 1376 int add0 = 0, add1 = 0, add2 = 0;
1428 /* Updates CE counters if it is not the first time here */ 1377 /* Updates CE counters if it is not the first time here */
1429 if (pvt->ce_count_available[socket]) { 1378 if (pvt->ce_count_available) {
1430 /* Updates CE counters */ 1379 /* Updates CE counters */
1431 1380
1432 add2 = new2 - pvt->rdimm_last_ce_count[socket][chan][2]; 1381 add2 = new2 - pvt->rdimm_last_ce_count[chan][2];
1433 add1 = new1 - pvt->rdimm_last_ce_count[socket][chan][1]; 1382 add1 = new1 - pvt->rdimm_last_ce_count[chan][1];
1434 add0 = new0 - pvt->rdimm_last_ce_count[socket][chan][0]; 1383 add0 = new0 - pvt->rdimm_last_ce_count[chan][0];
1435 1384
1436 if (add2 < 0) 1385 if (add2 < 0)
1437 add2 += 0x7fff; 1386 add2 += 0x7fff;
1438 pvt->rdimm_ce_count[socket][chan][2] += add2; 1387 pvt->rdimm_ce_count[chan][2] += add2;
1439 1388
1440 if (add1 < 0) 1389 if (add1 < 0)
1441 add1 += 0x7fff; 1390 add1 += 0x7fff;
1442 pvt->rdimm_ce_count[socket][chan][1] += add1; 1391 pvt->rdimm_ce_count[chan][1] += add1;
1443 1392
1444 if (add0 < 0) 1393 if (add0 < 0)
1445 add0 += 0x7fff; 1394 add0 += 0x7fff;
1446 pvt->rdimm_ce_count[socket][chan][0] += add0; 1395 pvt->rdimm_ce_count[chan][0] += add0;
1447 } else 1396 } else
1448 pvt->ce_count_available[socket] = 1; 1397 pvt->ce_count_available = 1;
1449 1398
1450 /* Store the new values */ 1399 /* Store the new values */
1451 pvt->rdimm_last_ce_count[socket][chan][2] = new2; 1400 pvt->rdimm_last_ce_count[chan][2] = new2;
1452 pvt->rdimm_last_ce_count[socket][chan][1] = new1; 1401 pvt->rdimm_last_ce_count[chan][1] = new1;
1453 pvt->rdimm_last_ce_count[socket][chan][0] = new0; 1402 pvt->rdimm_last_ce_count[chan][0] = new0;
1454 1403
1455 /*updated the edac core */ 1404 /*updated the edac core */
1456 if (add0 != 0) 1405 if (add0 != 0)
1457 i7core_rdimm_update_csrow(mci, socket, chan, 0, add0); 1406 i7core_rdimm_update_csrow(mci, chan, 0, add0);
1458 if (add1 != 0) 1407 if (add1 != 0)
1459 i7core_rdimm_update_csrow(mci, socket, chan, 1, add1); 1408 i7core_rdimm_update_csrow(mci, chan, 1, add1);
1460 if (add2 != 0) 1409 if (add2 != 0)
1461 i7core_rdimm_update_csrow(mci, socket, chan, 2, add2); 1410 i7core_rdimm_update_csrow(mci, chan, 2, add2);
1462 1411
1463} 1412}
1464 1413
1465static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci, u8 socket) 1414static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci)
1466{ 1415{
1467 struct i7core_pvt *pvt = mci->pvt_info; 1416 struct i7core_pvt *pvt = mci->pvt_info;
1468 u32 rcv[3][2]; 1417 u32 rcv[3][2];
1469 int i, new0, new1, new2; 1418 int i, new0, new1, new2;
1470 1419
1471 /*Read DEV 3: FUN 2: MC_COR_ECC_CNT regs directly*/ 1420 /*Read DEV 3: FUN 2: MC_COR_ECC_CNT regs directly*/
1472 pci_read_config_dword(pvt->pci_mcr[socket][2], MC_COR_ECC_CNT_0, 1421 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_0,
1473 &rcv[0][0]); 1422 &rcv[0][0]);
1474 pci_read_config_dword(pvt->pci_mcr[socket][2], MC_COR_ECC_CNT_1, 1423 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_1,
1475 &rcv[0][1]); 1424 &rcv[0][1]);
1476 pci_read_config_dword(pvt->pci_mcr[socket][2], MC_COR_ECC_CNT_2, 1425 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_2,
1477 &rcv[1][0]); 1426 &rcv[1][0]);
1478 pci_read_config_dword(pvt->pci_mcr[socket][2], MC_COR_ECC_CNT_3, 1427 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_3,
1479 &rcv[1][1]); 1428 &rcv[1][1]);
1480 pci_read_config_dword(pvt->pci_mcr[socket][2], MC_COR_ECC_CNT_4, 1429 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_4,
1481 &rcv[2][0]); 1430 &rcv[2][0]);
1482 pci_read_config_dword(pvt->pci_mcr[socket][2], MC_COR_ECC_CNT_5, 1431 pci_read_config_dword(pvt->pci_mcr[2], MC_COR_ECC_CNT_5,
1483 &rcv[2][1]); 1432 &rcv[2][1]);
1484 for (i = 0 ; i < 3; i++) { 1433 for (i = 0 ; i < 3; i++) {
1485 debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n", 1434 debugf3("MC_COR_ECC_CNT%d = 0x%x; MC_COR_ECC_CNT%d = 0x%x\n",
1486 (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]); 1435 (i * 2), rcv[i][0], (i * 2) + 1, rcv[i][1]);
1487 /*if the channel has 3 dimms*/ 1436 /*if the channel has 3 dimms*/
1488 if (pvt->channel[socket][i].dimms > 2) { 1437 if (pvt->channel[i].dimms > 2) {
1489 new0 = DIMM_BOT_COR_ERR(rcv[i][0]); 1438 new0 = DIMM_BOT_COR_ERR(rcv[i][0]);
1490 new1 = DIMM_TOP_COR_ERR(rcv[i][0]); 1439 new1 = DIMM_TOP_COR_ERR(rcv[i][0]);
1491 new2 = DIMM_BOT_COR_ERR(rcv[i][1]); 1440 new2 = DIMM_BOT_COR_ERR(rcv[i][1]);
@@ -1497,7 +1446,7 @@ static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci, u8 socket)
1497 new2 = 0; 1446 new2 = 0;
1498 } 1447 }
1499 1448
1500 i7core_rdimm_update_ce_count(mci, socket, i, new0, new1, new2); 1449 i7core_rdimm_update_ce_count(mci, i, new0, new1, new2);
1501 } 1450 }
1502} 1451}
1503 1452
@@ -1507,20 +1456,20 @@ static void i7core_rdimm_check_mc_ecc_err(struct mem_ctl_info *mci, u8 socket)
1507 * also available at: 1456 * also available at:
1508 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf 1457 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
1509 */ 1458 */
1510static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci, u8 socket) 1459static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci)
1511{ 1460{
1512 struct i7core_pvt *pvt = mci->pvt_info; 1461 struct i7core_pvt *pvt = mci->pvt_info;
1513 u32 rcv1, rcv0; 1462 u32 rcv1, rcv0;
1514 int new0, new1, new2; 1463 int new0, new1, new2;
1515 1464
1516 if (!pvt->pci_mcr[socket][4]) { 1465 if (!pvt->pci_mcr[4]) {
1517 debugf0("%s MCR registers not found\n", __func__); 1466 debugf0("%s MCR registers not found\n", __func__);
1518 return; 1467 return;
1519 } 1468 }
1520 1469
1521 /* Corrected test errors */ 1470 /* Corrected test errors */
1522 pci_read_config_dword(pvt->pci_mcr[socket][4], MC_TEST_ERR_RCV1, &rcv1); 1471 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1);
1523 pci_read_config_dword(pvt->pci_mcr[socket][4], MC_TEST_ERR_RCV0, &rcv0); 1472 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0);
1524 1473
1525 /* Store the new values */ 1474 /* Store the new values */
1526 new2 = DIMM2_COR_ERR(rcv1); 1475 new2 = DIMM2_COR_ERR(rcv1);
@@ -1528,37 +1477,37 @@ static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci, u8 socket)
1528 new0 = DIMM0_COR_ERR(rcv0); 1477 new0 = DIMM0_COR_ERR(rcv0);
1529 1478
1530 /* Updates CE counters if it is not the first time here */ 1479 /* Updates CE counters if it is not the first time here */
1531 if (pvt->ce_count_available[socket]) { 1480 if (pvt->ce_count_available) {
1532 /* Updates CE counters */ 1481 /* Updates CE counters */
1533 int add0, add1, add2; 1482 int add0, add1, add2;
1534 1483
1535 add2 = new2 - pvt->udimm_last_ce_count[socket][2]; 1484 add2 = new2 - pvt->udimm_last_ce_count[2];
1536 add1 = new1 - pvt->udimm_last_ce_count[socket][1]; 1485 add1 = new1 - pvt->udimm_last_ce_count[1];
1537 add0 = new0 - pvt->udimm_last_ce_count[socket][0]; 1486 add0 = new0 - pvt->udimm_last_ce_count[0];
1538 1487
1539 if (add2 < 0) 1488 if (add2 < 0)
1540 add2 += 0x7fff; 1489 add2 += 0x7fff;
1541 pvt->udimm_ce_count[socket][2] += add2; 1490 pvt->udimm_ce_count[2] += add2;
1542 1491
1543 if (add1 < 0) 1492 if (add1 < 0)
1544 add1 += 0x7fff; 1493 add1 += 0x7fff;
1545 pvt->udimm_ce_count[socket][1] += add1; 1494 pvt->udimm_ce_count[1] += add1;
1546 1495
1547 if (add0 < 0) 1496 if (add0 < 0)
1548 add0 += 0x7fff; 1497 add0 += 0x7fff;
1549 pvt->udimm_ce_count[socket][0] += add0; 1498 pvt->udimm_ce_count[0] += add0;
1550 1499
1551 if (add0 | add1 | add2) 1500 if (add0 | add1 | add2)
1552 i7core_printk(KERN_ERR, "New Corrected error(s): " 1501 i7core_printk(KERN_ERR, "New Corrected error(s): "
1553 "dimm0: +%d, dimm1: +%d, dimm2 +%d\n", 1502 "dimm0: +%d, dimm1: +%d, dimm2 +%d\n",
1554 add0, add1, add2); 1503 add0, add1, add2);
1555 } else 1504 } else
1556 pvt->ce_count_available[socket] = 1; 1505 pvt->ce_count_available = 1;
1557 1506
1558 /* Store the new values */ 1507 /* Store the new values */
1559 pvt->udimm_last_ce_count[socket][2] = new2; 1508 pvt->udimm_last_ce_count[2] = new2;
1560 pvt->udimm_last_ce_count[socket][1] = new1; 1509 pvt->udimm_last_ce_count[1] = new1;
1561 pvt->udimm_last_ce_count[socket][0] = new0; 1510 pvt->udimm_last_ce_count[0] = new0;
1562} 1511}
1563 1512
1564/* 1513/*
@@ -1587,13 +1536,6 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
1587 u32 syndrome = m->misc >> 32; 1536 u32 syndrome = m->misc >> 32;
1588 u32 errnum = find_first_bit(&error, 32); 1537 u32 errnum = find_first_bit(&error, 32);
1589 int csrow; 1538 int csrow;
1590/* FIXME */
1591//#ifdef CONFIG_SMP
1592#if 0
1593 u32 socket_id = per_cpu(cpu_data, cpu).phys_proc_id;
1594#else
1595 u32 socket_id = 0;
1596#endif
1597 1539
1598 if (m->mcgstatus & 1) 1540 if (m->mcgstatus & 1)
1599 type = "FATAL"; 1541 type = "FATAL";
@@ -1655,24 +1597,21 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
1655 1597
1656 /* FIXME: should convert addr into bank and rank information */ 1598 /* FIXME: should convert addr into bank and rank information */
1657 msg = kasprintf(GFP_ATOMIC, 1599 msg = kasprintf(GFP_ATOMIC,
1658 "%s (addr = 0x%08llx, socket=%d, Dimm=%d, Channel=%d, " 1600 "%s (addr = 0x%08llx, cpu=%d, Dimm=%d, Channel=%d, "
1659 "syndrome=0x%08x, count=%d, Err=%08llx:%08llx (%s: %s))\n", 1601 "syndrome=0x%08x, count=%d, Err=%08llx:%08llx (%s: %s))\n",
1660 type, (long long) m->addr, socket_id, dimm, channel, 1602 type, (long long) m->addr, m->cpu, dimm, channel,
1661 syndrome, core_err_cnt, (long long)m->status, 1603 syndrome, core_err_cnt, (long long)m->status,
1662 (long long)m->misc, optype, err); 1604 (long long)m->misc, optype, err);
1663 1605
1664 debugf0("%s", msg); 1606 debugf0("%s", msg);
1665 1607
1666 if (socket_id < NUM_SOCKETS) 1608 csrow = pvt->csrow_map[channel][dimm];
1667 csrow = pvt->csrow_map[socket_id][channel][dimm];
1668 else
1669 csrow = -1;
1670 1609
1671 /* Call the helper to output message */ 1610 /* Call the helper to output message */
1672 if (m->mcgstatus & 1) 1611 if (m->mcgstatus & 1)
1673 edac_mc_handle_fbd_ue(mci, csrow, 0, 1612 edac_mc_handle_fbd_ue(mci, csrow, 0,
1674 0 /* FIXME: should be channel here */, msg); 1613 0 /* FIXME: should be channel here */, msg);
1675 else if (!pvt->is_registered[socket_id]) 1614 else if (!pvt->is_registered)
1676 edac_mc_handle_fbd_ce(mci, csrow, 1615 edac_mc_handle_fbd_ce(mci, csrow,
1677 0 /* FIXME: should be channel here */, msg); 1616 0 /* FIXME: should be channel here */, msg);
1678 1617
@@ -1695,12 +1634,14 @@ static void i7core_check_error(struct mem_ctl_info *mci)
1695 spin_lock_irqsave(&pvt->mce_lock, flags); 1634 spin_lock_irqsave(&pvt->mce_lock, flags);
1696 if (pvt->mce_count) { 1635 if (pvt->mce_count) {
1697 m = kmalloc(sizeof(*m) * pvt->mce_count, GFP_ATOMIC); 1636 m = kmalloc(sizeof(*m) * pvt->mce_count, GFP_ATOMIC);
1637
1698 if (m) { 1638 if (m) {
1699 count = pvt->mce_count; 1639 count = pvt->mce_count;
1700 memcpy(m, &pvt->mce_entry, sizeof(*m) * count); 1640 memcpy(m, &pvt->mce_entry, sizeof(*m) * count);
1701 } 1641 }
1702 pvt->mce_count = 0; 1642 pvt->mce_count = 0;
1703 } 1643 }
1644
1704 spin_unlock_irqrestore(&pvt->mce_lock, flags); 1645 spin_unlock_irqrestore(&pvt->mce_lock, flags);
1705 1646
1706 /* proccess mcelog errors */ 1647 /* proccess mcelog errors */
@@ -1710,11 +1651,10 @@ static void i7core_check_error(struct mem_ctl_info *mci)
1710 kfree(m); 1651 kfree(m);
1711 1652
1712 /* check memory count errors */ 1653 /* check memory count errors */
1713 for (i = 0; i < pvt->sockets; i++) 1654 if (!pvt->is_registered)
1714 if (!pvt->is_registered[i]) 1655 i7core_udimm_check_mc_ecc_err(mci);
1715 i7core_udimm_check_mc_ecc_err(mci, i); 1656 else
1716 else 1657 i7core_rdimm_check_mc_ecc_err(mci);
1717 i7core_rdimm_check_mc_ecc_err(mci, i);
1718} 1658}
1719 1659
1720/* 1660/*
@@ -1740,6 +1680,10 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
1740 if (mce->bank != 8) 1680 if (mce->bank != 8)
1741 return 0; 1681 return 0;
1742 1682
1683 /* Only handle if it is the right mc controller */
1684 if (cpu_data(mce->cpu).phys_proc_id != pvt->i7core_dev->socket)
1685 return 0;
1686
1743 spin_lock_irqsave(&pvt->mce_lock, flags); 1687 spin_lock_irqsave(&pvt->mce_lock, flags);
1744 if (pvt->mce_count < MCE_LOG_LEN) { 1688 if (pvt->mce_count < MCE_LOG_LEN) {
1745 memcpy(&pvt->mce_entry[pvt->mce_count], mce, sizeof(*mce)); 1689 memcpy(&pvt->mce_entry[pvt->mce_count], mce, sizeof(*mce));
@@ -1755,63 +1699,26 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
1755 return 1; 1699 return 1;
1756} 1700}
1757 1701
1758/* 1702static int i7core_register_mci(struct i7core_dev *i7core_dev,
1759 * i7core_probe Probe for ONE instance of device to see if it is 1703 int num_channels, int num_csrows)
1760 * present.
1761 * return:
1762 * 0 for FOUND a device
1763 * < 0 for error code
1764 */
1765static int __devinit i7core_probe(struct pci_dev *pdev,
1766 const struct pci_device_id *id)
1767{ 1704{
1768 struct mem_ctl_info *mci; 1705 struct mem_ctl_info *mci;
1769 struct i7core_pvt *pvt; 1706 struct i7core_pvt *pvt;
1770 int num_channels = 0;
1771 int num_csrows = 0;
1772 int csrow = 0; 1707 int csrow = 0;
1773 int dev_idx = id->driver_data; 1708 int rc;
1774 int rc, i;
1775 u8 sockets;
1776
1777 /*
1778 * FIXME: All memory controllers are allocated at the first pass.
1779 */
1780 if (unlikely(dev_idx >= 1))
1781 return -EINVAL;
1782
1783 /* get the pci devices we want to reserve for our use */
1784 mutex_lock(&i7core_edac_lock);
1785 rc = i7core_get_devices(&sockets);
1786 if (unlikely(rc < 0))
1787 goto fail0;
1788
1789 for (i = 0; i < sockets; i++) {
1790 int channels;
1791 int csrows;
1792
1793 /* Check the number of active and not disabled channels */
1794 rc = i7core_get_active_channels(i, &channels, &csrows);
1795 if (unlikely(rc < 0))
1796 goto fail1;
1797
1798 num_channels += channels;
1799 num_csrows += csrows;
1800 }
1801 1709
1802 /* allocate a new MC control structure */ 1710 /* allocate a new MC control structure */
1803 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0); 1711 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
1804 if (unlikely(!mci)) { 1712 if (unlikely(!mci))
1805 rc = -ENOMEM; 1713 return -ENOMEM;
1806 goto fail1;
1807 }
1808 1714
1809 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); 1715 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1810 1716
1811 mci->dev = &pdev->dev; /* record ptr to the generic device */ 1717 /* record ptr to the generic device */
1718 mci->dev = &i7core_dev->pdev[0]->dev;
1719
1812 pvt = mci->pvt_info; 1720 pvt = mci->pvt_info;
1813 memset(pvt, 0, sizeof(*pvt)); 1721 memset(pvt, 0, sizeof(*pvt));
1814 pvt->sockets = sockets;
1815 mci->mc_idx = 0; 1722 mci->mc_idx = 0;
1816 1723
1817 /* 1724 /*
@@ -1824,21 +1731,21 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1824 mci->edac_cap = EDAC_FLAG_NONE; 1731 mci->edac_cap = EDAC_FLAG_NONE;
1825 mci->mod_name = "i7core_edac.c"; 1732 mci->mod_name = "i7core_edac.c";
1826 mci->mod_ver = I7CORE_REVISION; 1733 mci->mod_ver = I7CORE_REVISION;
1827 mci->ctl_name = i7core_probe_devs[dev_idx].ctl_name; 1734 mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d",
1828 mci->dev_name = pci_name(pdev); 1735 i7core_dev->socket);
1736 mci->dev_name = pci_name(i7core_dev->pdev[0]);
1829 mci->ctl_page_to_phys = NULL; 1737 mci->ctl_page_to_phys = NULL;
1830 mci->mc_driver_sysfs_attributes = i7core_inj_attrs; 1738 mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
1831 /* Set the function pointer to an actual operation function */ 1739 /* Set the function pointer to an actual operation function */
1832 mci->edac_check = i7core_check_error; 1740 mci->edac_check = i7core_check_error;
1833 1741
1834 /* Store pci devices at mci for faster access */ 1742 /* Store pci devices at mci for faster access */
1835 rc = mci_bind_devs(mci); 1743 rc = mci_bind_devs(mci, i7core_dev);
1836 if (unlikely(rc < 0)) 1744 if (unlikely(rc < 0))
1837 goto fail2; 1745 goto fail;
1838 1746
1839 /* Get dimm basic config */ 1747 /* Get dimm basic config */
1840 for (i = 0; i < sockets; i++) 1748 get_dimm_config(mci, &csrow);
1841 get_dimm_config(mci, &csrow, i);
1842 1749
1843 /* add this new MC control structure to EDAC's list of MCs */ 1750 /* add this new MC control structure to EDAC's list of MCs */
1844 if (unlikely(edac_mc_add_mc(mci))) { 1751 if (unlikely(edac_mc_add_mc(mci))) {
@@ -1849,11 +1756,12 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1849 */ 1756 */
1850 1757
1851 rc = -EINVAL; 1758 rc = -EINVAL;
1852 goto fail2; 1759 goto fail;
1853 } 1760 }
1854 1761
1855 /* allocating generic PCI control info */ 1762 /* allocating generic PCI control info */
1856 i7core_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); 1763 i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
1764 EDAC_MOD_STR);
1857 if (unlikely(!i7core_pci)) { 1765 if (unlikely(!i7core_pci)) {
1858 printk(KERN_WARNING 1766 printk(KERN_WARNING
1859 "%s(): Unable to create PCI control\n", 1767 "%s(): Unable to create PCI control\n",
@@ -1880,7 +1788,50 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1880 if (unlikely(rc < 0)) { 1788 if (unlikely(rc < 0)) {
1881 debugf0("MC: " __FILE__ 1789 debugf0("MC: " __FILE__
1882 ": %s(): failed edac_mce_register()\n", __func__); 1790 ": %s(): failed edac_mce_register()\n", __func__);
1883 goto fail2; 1791 }
1792
1793fail:
1794 edac_mc_free(mci);
1795 return rc;
1796}
1797
1798/*
1799 * i7core_probe Probe for ONE instance of device to see if it is
1800 * present.
1801 * return:
1802 * 0 for FOUND a device
1803 * < 0 for error code
1804 */
1805static int __devinit i7core_probe(struct pci_dev *pdev,
1806 const struct pci_device_id *id)
1807{
1808 int dev_idx = id->driver_data;
1809 int rc;
1810 struct i7core_dev *i7core_dev;
1811
1812 /*
1813 * FIXME: All memory controllers are allocated at the first pass.
1814 */
1815 if (unlikely(dev_idx >= 1))
1816 return -EINVAL;
1817
1818 /* get the pci devices we want to reserve for our use */
1819 mutex_lock(&i7core_edac_lock);
1820 rc = i7core_get_devices();
1821 if (unlikely(rc < 0))
1822 goto fail0;
1823
1824 list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
1825 int channels;
1826 int csrows;
1827
1828 /* Check the number of active and not disabled channels */
1829 rc = i7core_get_active_channels(i7core_dev->socket,
1830 &channels, &csrows);
1831 if (unlikely(rc < 0))
1832 goto fail1;
1833
1834 i7core_register_mci(i7core_dev, channels, csrows);
1884 } 1835 }
1885 1836
1886 i7core_printk(KERN_INFO, "Driver loaded.\n"); 1837 i7core_printk(KERN_INFO, "Driver loaded.\n");
@@ -1888,9 +1839,6 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1888 mutex_unlock(&i7core_edac_lock); 1839 mutex_unlock(&i7core_edac_lock);
1889 return 0; 1840 return 0;
1890 1841
1891fail2:
1892 edac_mc_free(mci);
1893
1894fail1: 1842fail1:
1895 i7core_put_devices(); 1843 i7core_put_devices();
1896fail0: 1844fail0:
@@ -1926,6 +1874,7 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
1926 i7core_put_devices(); 1874 i7core_put_devices();
1927 mutex_unlock(&i7core_edac_lock); 1875 mutex_unlock(&i7core_edac_lock);
1928 1876
1877 kfree(mci->ctl_name);
1929 edac_mc_free(mci); 1878 edac_mc_free(mci);
1930} 1879}
1931 1880