aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-07-15 05:56:23 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 10:44:51 -0400
commit67166af4abc11d9c0deb497ebe0b562f69c71942 (patch)
tree261aeff4c9277e5c93d01c13548e5c04bbbb2ddf /drivers/edac
parentd1fd4fb69eeeb7db0693df58b9116db498d5bfe1 (diff)
i7core_edac: add support for more than one MC socket
Some Nehalem architectures have more than one MC socket. Socket 0 is located at bus 255. Currently, it is using up to 2 sockets, but increasing it to a larger number is just a matter of increasing MAX_SOCKETS definition. This seems to be required for properly support of Xeon 55xx. Still needs testing with Xeon 55xx. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/i7core_edac.c326
1 files changed, 213 insertions, 113 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index eec0c13c0205..69eacc1b50d7 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -155,6 +155,7 @@
155 155
156#define NUM_CHANS 3 156#define NUM_CHANS 3
157#define MAX_DIMMS 3 /* Max DIMMS per channel */ 157#define MAX_DIMMS 3 /* Max DIMMS per channel */
158#define NUM_SOCKETS 2 /* Max number of MC sockets */
158#define MAX_MCR_FUNC 4 159#define MAX_MCR_FUNC 4
159#define MAX_CHAN_FUNC 3 160#define MAX_CHAN_FUNC 3
160 161
@@ -169,6 +170,7 @@ struct i7core_info {
169struct i7core_inject { 170struct i7core_inject {
170 int enable; 171 int enable;
171 172
173 u8 socket;
172 u32 section; 174 u32 section;
173 u32 type; 175 u32 type;
174 u32 eccmask; 176 u32 eccmask;
@@ -186,21 +188,25 @@ struct pci_id_descr {
186 int dev; 188 int dev;
187 int func; 189 int func;
188 int dev_id; 190 int dev_id;
189 struct pci_dev *pdev; 191 struct pci_dev *pdev[NUM_SOCKETS];
190}; 192};
191 193
192struct i7core_pvt { 194struct i7core_pvt {
193 struct pci_dev *pci_noncore; 195 struct pci_dev *pci_noncore[NUM_SOCKETS];
194 struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; 196 struct pci_dev *pci_mcr[NUM_SOCKETS][MAX_MCR_FUNC + 1];
195 struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1]; 197 struct pci_dev *pci_ch[NUM_SOCKETS][NUM_CHANS][MAX_CHAN_FUNC + 1];
198
196 struct i7core_info info; 199 struct i7core_info info;
197 struct i7core_inject inject; 200 struct i7core_inject inject;
198 struct i7core_channel channel[NUM_CHANS]; 201 struct i7core_channel channel[NUM_SOCKETS][NUM_CHANS];
202
203 int sockets; /* Number of sockets */
199 int channels; /* Number of active channels */ 204 int channels; /* Number of active channels */
200 205
201 int ce_count_available; 206 int ce_count_available[NUM_SOCKETS];
202 unsigned long ce_count[MAX_DIMMS]; /* ECC corrected errors counts per dimm */ 207 /* ECC corrected errors counts per dimm */
203 int last_ce_count[MAX_DIMMS]; 208 unsigned long ce_count[NUM_SOCKETS][MAX_DIMMS];
209 int last_ce_count[NUM_SOCKETS][MAX_DIMMS];
204 210
205 /* mcelog glue */ 211 /* mcelog glue */
206 struct edac_mce edac_mce; 212 struct edac_mce edac_mce;
@@ -324,24 +330,26 @@ static inline int numcol(u32 col)
324/**************************************************************************** 330/****************************************************************************
325 Memory check routines 331 Memory check routines
326 ****************************************************************************/ 332 ****************************************************************************/
327static struct pci_dev *get_pdev_slot_func(int slot, int func) 333static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
334 unsigned func)
328{ 335{
329 int i; 336 int i;
330 337
331 for (i = 0; i < N_DEVS; i++) { 338 for (i = 0; i < N_DEVS; i++) {
332 if (!pci_devs[i].pdev) 339 if (!pci_devs[i].pdev[socket])
333 continue; 340 continue;
334 341
335 if (PCI_SLOT(pci_devs[i].pdev->devfn) == slot && 342 if (PCI_SLOT(pci_devs[i].pdev[socket]->devfn) == slot &&
336 PCI_FUNC(pci_devs[i].pdev->devfn) == func) { 343 PCI_FUNC(pci_devs[i].pdev[socket]->devfn) == func) {
337 return pci_devs[i].pdev; 344 return pci_devs[i].pdev[socket];
338 } 345 }
339 } 346 }
340 347
341 return NULL; 348 return NULL;
342} 349}
343 350
344static int i7core_get_active_channels(int *channels, int *csrows) 351static int i7core_get_active_channels(u8 socket, unsigned *channels,
352 unsigned *csrows)
345{ 353{
346 struct pci_dev *pdev = NULL; 354 struct pci_dev *pdev = NULL;
347 int i, j; 355 int i, j;
@@ -350,9 +358,10 @@ static int i7core_get_active_channels(int *channels, int *csrows)
350 *channels = 0; 358 *channels = 0;
351 *csrows = 0; 359 *csrows = 0;
352 360
353 pdev = get_pdev_slot_func(3, 0); 361 pdev = get_pdev_slot_func(socket, 3, 0);
354 if (!pdev) { 362 if (!pdev) {
355 i7core_printk(KERN_ERR, "Couldn't find fn 3.0!!!\n"); 363 i7core_printk(KERN_ERR, "Couldn't find socket %d fn 3.0!!!\n",
364 socket);
356 return -ENODEV; 365 return -ENODEV;
357 } 366 }
358 367
@@ -370,10 +379,11 @@ static int i7core_get_active_channels(int *channels, int *csrows)
370 if (status & (1 << i)) 379 if (status & (1 << i))
371 continue; 380 continue;
372 381
373 pdev = get_pdev_slot_func(i + 4, 1); 382 pdev = get_pdev_slot_func(socket, i + 4, 1);
374 if (!pdev) { 383 if (!pdev) {
375 i7core_printk(KERN_ERR, "Couldn't find fn %d.%d!!!\n", 384 i7core_printk(KERN_ERR, "Couldn't find socket %d "
376 i + 4, 1); 385 "fn %d.%d!!!\n",
386 socket, i + 4, 1);
377 return -ENODEV; 387 return -ENODEV;
378 } 388 }
379 /* Devices 4-6 function 1 */ 389 /* Devices 4-6 function 1 */
@@ -393,12 +403,13 @@ static int i7core_get_active_channels(int *channels, int *csrows)
393 } 403 }
394 } 404 }
395 405
396 debugf0("Number of active channels: %d\n", *channels); 406 debugf0("Number of active channels on socked %d: %d\n",
407 socket, *channels);
397 408
398 return 0; 409 return 0;
399} 410}
400 411
401static int get_dimm_config(struct mem_ctl_info *mci) 412static int get_dimm_config(struct mem_ctl_info *mci, u8 socket)
402{ 413{
403 struct i7core_pvt *pvt = mci->pvt_info; 414 struct i7core_pvt *pvt = mci->pvt_info;
404 struct csrow_info *csr; 415 struct csrow_info *csr;
@@ -409,7 +420,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
409 enum mem_type mtype; 420 enum mem_type mtype;
410 421
411 /* Get data from the MC register, function 0 */ 422 /* Get data from the MC register, function 0 */
412 pdev = pvt->pci_mcr[0]; 423 pdev = pvt->pci_mcr[socket][0];
413 if (!pdev) 424 if (!pdev)
414 return -ENODEV; 425 return -ENODEV;
415 426
@@ -458,10 +469,11 @@ static int get_dimm_config(struct mem_ctl_info *mci)
458 } 469 }
459 470
460 /* Devices 4-6 function 0 */ 471 /* Devices 4-6 function 0 */
461 pci_read_config_dword(pvt->pci_ch[i][0], 472 pci_read_config_dword(pvt->pci_ch[socket][i][0],
462 MC_CHANNEL_DIMM_INIT_PARAMS, &data); 473 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
463 474
464 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT) ? 4 : 2; 475 pvt->channel[socket][i].ranks = (data & QUAD_RANK_PRESENT) ?
476 4 : 2;
465 477
466 if (data & REGISTERED_DIMM) 478 if (data & REGISTERED_DIMM)
467 mtype = MEM_RDDR3; 479 mtype = MEM_RDDR3;
@@ -477,11 +489,11 @@ static int get_dimm_config(struct mem_ctl_info *mci)
477#endif 489#endif
478 490
479 /* Devices 4-6 function 1 */ 491 /* Devices 4-6 function 1 */
480 pci_read_config_dword(pvt->pci_ch[i][1], 492 pci_read_config_dword(pvt->pci_ch[socket][i][1],
481 MC_DOD_CH_DIMM0, &dimm_dod[0]); 493 MC_DOD_CH_DIMM0, &dimm_dod[0]);
482 pci_read_config_dword(pvt->pci_ch[i][1], 494 pci_read_config_dword(pvt->pci_ch[socket][i][1],
483 MC_DOD_CH_DIMM1, &dimm_dod[1]); 495 MC_DOD_CH_DIMM1, &dimm_dod[1]);
484 pci_read_config_dword(pvt->pci_ch[i][1], 496 pci_read_config_dword(pvt->pci_ch[socket][i][1],
485 MC_DOD_CH_DIMM2, &dimm_dod[2]); 497 MC_DOD_CH_DIMM2, &dimm_dod[2]);
486 498
487 debugf0("Ch%d phy rd%d, wr%d (0x%08x): " 499 debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
@@ -489,7 +501,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
489 i, 501 i,
490 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i), 502 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
491 data, 503 data,
492 pvt->channel[i].ranks, 504 pvt->channel[socket][i].ranks,
493 (data & REGISTERED_DIMM) ? 'R' : 'U'); 505 (data & REGISTERED_DIMM) ? 'R' : 'U');
494 506
495 for (j = 0; j < 3; j++) { 507 for (j = 0; j < 3; j++) {
@@ -507,7 +519,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
507 /* DDR3 has 8 I/O banks */ 519 /* DDR3 has 8 I/O banks */
508 size = (rows * cols * banks * ranks) >> (20 - 3); 520 size = (rows * cols * banks * ranks) >> (20 - 3);
509 521
510 pvt->channel[i].dimms++; 522 pvt->channel[socket][i].dimms++;
511 523
512 debugf0("\tdimm %d (0x%08x) %d Mb offset: %x, " 524 debugf0("\tdimm %d (0x%08x) %d Mb offset: %x, "
513 "numbank: %d,\n\t\t" 525 "numbank: %d,\n\t\t"
@@ -592,16 +604,43 @@ static int disable_inject(struct mem_ctl_info *mci)
592 604
593 pvt->inject.enable = 0; 605 pvt->inject.enable = 0;
594 606
595 if (!pvt->pci_ch[pvt->inject.channel][0]) 607 if (!pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0])
596 return -ENODEV; 608 return -ENODEV;
597 609
598 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], 610 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
599 MC_CHANNEL_ERROR_MASK, 0); 611 MC_CHANNEL_ERROR_MASK, 0);
600 612
601 return 0; 613 return 0;
602} 614}
603 615
604/* 616/*
617 * i7core inject inject.socket
618 *
619 * accept and store error injection inject.socket value
620 */
621static ssize_t i7core_inject_socket_store(struct mem_ctl_info *mci,
622 const char *data, size_t count)
623{
624 struct i7core_pvt *pvt = mci->pvt_info;
625 unsigned long value;
626 int rc;
627
628 rc = strict_strtoul(data, 10, &value);
629 if ((rc < 0) || (value > pvt->sockets))
630 return 0;
631
632 pvt->inject.section = (u32) value;
633 return count;
634}
635
636static ssize_t i7core_inject_socket_show(struct mem_ctl_info *mci,
637 char *data)
638{
639 struct i7core_pvt *pvt = mci->pvt_info;
640 return sprintf(data, "%d\n", pvt->inject.socket);
641}
642
643/*
605 * i7core inject inject.section 644 * i7core inject inject.section
606 * 645 *
607 * accept and store error injection inject.section value 646 * accept and store error injection inject.section value
@@ -838,7 +877,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
838 int rc; 877 int rc;
839 long enable; 878 long enable;
840 879
841 if (!pvt->pci_ch[pvt->inject.channel][0]) 880 if (!pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0])
842 return 0; 881 return 0;
843 882
844 rc = strict_strtoul(data, 10, &enable); 883 rc = strict_strtoul(data, 10, &enable);
@@ -856,7 +895,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
856 if (pvt->inject.dimm < 0) 895 if (pvt->inject.dimm < 0)
857 mask |= 1L << 41; 896 mask |= 1L << 41;
858 else { 897 else {
859 if (pvt->channel[pvt->inject.channel].dimms > 2) 898 if (pvt->channel[pvt->inject.socket][pvt->inject.channel].dimms > 2)
860 mask |= (pvt->inject.dimm & 0x3L) << 35; 899 mask |= (pvt->inject.dimm & 0x3L) << 35;
861 else 900 else
862 mask |= (pvt->inject.dimm & 0x1L) << 36; 901 mask |= (pvt->inject.dimm & 0x1L) << 36;
@@ -866,7 +905,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
866 if (pvt->inject.rank < 0) 905 if (pvt->inject.rank < 0)
867 mask |= 1L << 40; 906 mask |= 1L << 40;
868 else { 907 else {
869 if (pvt->channel[pvt->inject.channel].dimms > 2) 908 if (pvt->channel[pvt->inject.socket][pvt->inject.channel].dimms > 2)
870 mask |= (pvt->inject.rank & 0x1L) << 34; 909 mask |= (pvt->inject.rank & 0x1L) << 34;
871 else 910 else
872 mask |= (pvt->inject.rank & 0x3L) << 34; 911 mask |= (pvt->inject.rank & 0x3L) << 34;
@@ -891,38 +930,41 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
891 mask |= (pvt->inject.col & 0x3fffL); 930 mask |= (pvt->inject.col & 0x3fffL);
892 931
893 /* Unlock writes to registers */ 932 /* Unlock writes to registers */
894 pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0x2); 933 pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket],
934 MC_CFG_CONTROL, 0x2);
895 msleep(100); 935 msleep(100);
896 936
897 /* Zeroes error count registers */ 937 /* Zeroes error count registers */
898 pci_write_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, 0); 938 pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4],
899 pci_write_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, 0); 939 MC_TEST_ERR_RCV1, 0);
900 pvt->ce_count_available = 0; 940 pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4],
941 MC_TEST_ERR_RCV0, 0);
942 pvt->ce_count_available[pvt->inject.socket] = 0;
901 943
902 944
903#if USE_QWORD 945#if USE_QWORD
904 pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0], 946 pci_write_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
905 MC_CHANNEL_ADDR_MATCH, mask); 947 MC_CHANNEL_ADDR_MATCH, mask);
906#else 948#else
907 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], 949 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
908 MC_CHANNEL_ADDR_MATCH, mask); 950 MC_CHANNEL_ADDR_MATCH, mask);
909 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], 951 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
910 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L); 952 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
911#endif 953#endif
912 954
913#if 1 955#if 1
914#if USE_QWORD 956#if USE_QWORD
915 u64 rdmask; 957 u64 rdmask;
916 pci_read_config_qword(pvt->pci_ch[pvt->inject.channel][0], 958 pci_read_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
917 MC_CHANNEL_ADDR_MATCH, &rdmask); 959 MC_CHANNEL_ADDR_MATCH, &rdmask);
918 debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n", 960 debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n",
919 mask, rdmask); 961 mask, rdmask);
920#else 962#else
921 u32 rdmask1, rdmask2; 963 u32 rdmask1, rdmask2;
922 964
923 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0], 965 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
924 MC_CHANNEL_ADDR_MATCH, &rdmask1); 966 MC_CHANNEL_ADDR_MATCH, &rdmask1);
925 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0], 967 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
926 MC_CHANNEL_ADDR_MATCH + 4, &rdmask2); 968 MC_CHANNEL_ADDR_MATCH + 4, &rdmask2);
927 969
928 debugf0("Inject addr match write 0x%016llx, read: 0x%08x 0x%08x\n", 970 debugf0("Inject addr match write 0x%016llx, read: 0x%08x 0x%08x\n",
@@ -930,7 +972,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
930#endif 972#endif
931#endif 973#endif
932 974
933 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], 975 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
934 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask); 976 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
935 977
936 /* 978 /*
@@ -944,7 +986,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
944 (pvt->inject.section & 0x3) << 1 | 986 (pvt->inject.section & 0x3) << 1 |
945 (pvt->inject.type & 0x6) << (3 - 1); 987 (pvt->inject.type & 0x6) << (3 - 1);
946 988
947 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], 989 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
948 MC_CHANNEL_ERROR_MASK, injectmask); 990 MC_CHANNEL_ERROR_MASK, injectmask);
949 991
950#if 0 992#if 0
@@ -965,7 +1007,7 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
965 struct i7core_pvt *pvt = mci->pvt_info; 1007 struct i7core_pvt *pvt = mci->pvt_info;
966 u32 injectmask; 1008 u32 injectmask;
967 1009
968 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0], 1010 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
969 MC_CHANNEL_ERROR_MASK, &injectmask); 1011 MC_CHANNEL_ERROR_MASK, &injectmask);
970 1012
971 debugf0("Inject error read: 0x%018x\n", injectmask); 1013 debugf0("Inject error read: 0x%018x\n", injectmask);
@@ -978,24 +1020,39 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
978 1020
979static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data) 1021static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
980{ 1022{
1023 unsigned i, count, total = 0;
981 struct i7core_pvt *pvt = mci->pvt_info; 1024 struct i7core_pvt *pvt = mci->pvt_info;
982 1025
983 if (!pvt->ce_count_available) 1026 for (i = 0; i < pvt->sockets; i++) {
984 return sprintf(data, "unavailable\n"); 1027 if (!pvt->ce_count_available[i])
1028 count = sprintf(data, "socket 0 data unavailable\n");
1029 else
1030 count = sprintf(data, "socket %d, dimm0: %lu\n"
1031 "dimm1: %lu\ndimm2: %lu\n",
1032 i,
1033 pvt->ce_count[i][0],
1034 pvt->ce_count[i][1],
1035 pvt->ce_count[i][2]);
1036 data += count;
1037 total += count;
1038 }
985 1039
986 return sprintf(data, "dimm0: %lu\ndimm1: %lu\ndimm2: %lu\n", 1040 return total;
987 pvt->ce_count[0],
988 pvt->ce_count[1],
989 pvt->ce_count[2]);
990} 1041}
991 1042
992/* 1043/*
993 * Sysfs struct 1044 * Sysfs struct
994 */ 1045 */
995static struct mcidev_sysfs_attribute i7core_inj_attrs[] = { 1046static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
996
997 { 1047 {
998 .attr = { 1048 .attr = {
1049 .name = "inject_socket",
1050 .mode = (S_IRUGO | S_IWUSR)
1051 },
1052 .show = i7core_inject_socket_show,
1053 .store = i7core_inject_socket_store,
1054 }, {
1055 .attr = {
999 .name = "inject_section", 1056 .name = "inject_section",
1000 .mode = (S_IRUGO | S_IWUSR) 1057 .mode = (S_IRUGO | S_IWUSR)
1001 }, 1058 },
@@ -1049,10 +1106,11 @@ static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
1049 */ 1106 */
1050static void i7core_put_devices(void) 1107static void i7core_put_devices(void)
1051{ 1108{
1052 int i; 1109 int i, j;
1053 1110
1054 for (i = 0; i < N_DEVS; i++) 1111 for (i = 0; i < NUM_SOCKETS; i++)
1055 pci_dev_put(pci_devs[i].pdev); 1112 for (j = 0; j < N_DEVS; j++)
1113 pci_dev_put(pci_devs[j].pdev[i]);
1056} 1114}
1057 1115
1058/* 1116/*
@@ -1065,6 +1123,8 @@ static int i7core_get_devices(void)
1065{ 1123{
1066 int rc, i; 1124 int rc, i;
1067 struct pci_dev *pdev = NULL; 1125 struct pci_dev *pdev = NULL;
1126 u8 bus = 0;
1127 u8 socket = 0;
1068 1128
1069 for (i = 0; i < N_DEVS; i++) { 1129 for (i = 0; i < N_DEVS; i++) {
1070 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 1130 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1078,14 +1138,32 @@ static int i7core_get_devices(void)
1078 pci_devs[i].dev_id, NULL); 1138 pci_devs[i].dev_id, NULL);
1079 } 1139 }
1080 1140
1081 if (likely(pdev)) 1141 if (likely(pdev)) {
1082 pci_devs[i].pdev = pdev; 1142 bus = pdev->bus->number;
1083 else { 1143
1144 if (bus == 0x3f)
1145 socket = 0;
1146 else
1147 socket = 255 - bus;
1148
1149 if (socket >= NUM_SOCKETS) {
1150 i7core_printk(KERN_ERR,
1151 "Found unexpected socket for "
1152 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1153 bus, pci_devs[i].dev, pci_devs[i].func,
1154 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
1155
1156 rc = -ENODEV;
1157 goto error;
1158 }
1159
1160 pci_devs[i].pdev[socket] = pdev;
1161 } else {
1084 i7core_printk(KERN_ERR, 1162 i7core_printk(KERN_ERR,
1085 "Device not found: PCI ID %04x:%04x " 1163 "Device not found: "
1086 "(dev %d, func %d)\n", 1164 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1087 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id, 1165 bus, pci_devs[i].dev, pci_devs[i].func,
1088 pci_devs[i].dev, pci_devs[i].func); 1166 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
1089 1167
1090 /* Dev 3 function 2 only exists on chips with RDIMMs */ 1168 /* Dev 3 function 2 only exists on chips with RDIMMs */
1091 if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2)) 1169 if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
@@ -1121,9 +1199,10 @@ static int i7core_get_devices(void)
1121 } 1199 }
1122 1200
1123 i7core_printk(KERN_INFO, 1201 i7core_printk(KERN_INFO,
1124 "Registered device %0x:%0x fn %d.%d\n", 1202 "Registered socket %d "
1125 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id, 1203 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1126 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); 1204 socket, bus, pci_devs[i].dev, pci_devs[i].func,
1205 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
1127 } 1206 }
1128 1207
1129 return 0; 1208 return 0;
@@ -1137,30 +1216,33 @@ static int mci_bind_devs(struct mem_ctl_info *mci)
1137{ 1216{
1138 struct i7core_pvt *pvt = mci->pvt_info; 1217 struct i7core_pvt *pvt = mci->pvt_info;
1139 struct pci_dev *pdev; 1218 struct pci_dev *pdev;
1140 int i, func, slot; 1219 int i, j, func, slot;
1141 1220
1142 for (i = 0; i < N_DEVS; i++) { 1221 for (i = 0; i < pvt->sockets; i++) {
1143 pdev = pci_devs[i].pdev; 1222 for (j = 0; j < N_DEVS; j++) {
1144 if (!pdev) 1223 pdev = pci_devs[j].pdev[i];
1145 continue; 1224 if (!pdev)
1225 continue;
1146 1226
1147 func = PCI_FUNC(pdev->devfn); 1227 func = PCI_FUNC(pdev->devfn);
1148 slot = PCI_SLOT(pdev->devfn); 1228 slot = PCI_SLOT(pdev->devfn);
1149 if (slot == 3) { 1229 if (slot == 3) {
1150 if (unlikely(func > MAX_MCR_FUNC)) 1230 if (unlikely(func > MAX_MCR_FUNC))
1151 goto error; 1231 goto error;
1152 pvt->pci_mcr[func] = pdev; 1232 pvt->pci_mcr[i][func] = pdev;
1153 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) { 1233 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1154 if (unlikely(func > MAX_CHAN_FUNC)) 1234 if (unlikely(func > MAX_CHAN_FUNC))
1235 goto error;
1236 pvt->pci_ch[i][slot - 4][func] = pdev;
1237 } else if (!slot && !func)
1238 pvt->pci_noncore[i] = pdev;
1239 else
1155 goto error; 1240 goto error;
1156 pvt->pci_ch[slot - 4][func] = pdev;
1157 } else if (!slot && !func)
1158 pvt->pci_noncore = pdev;
1159 else
1160 goto error;
1161 1241
1162 debugf0("Associated fn %d.%d, dev = %p\n", 1242 debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
1163 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev); 1243 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
1244 pdev, i);
1245 }
1164 } 1246 }
1165 1247
1166 return 0; 1248 return 0;
@@ -1182,20 +1264,20 @@ error:
1182 * also available at: 1264 * also available at:
1183 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf 1265 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
1184 */ 1266 */
1185static void check_mc_test_err(struct mem_ctl_info *mci) 1267static void check_mc_test_err(struct mem_ctl_info *mci, u8 socket)
1186{ 1268{
1187 struct i7core_pvt *pvt = mci->pvt_info; 1269 struct i7core_pvt *pvt = mci->pvt_info;
1188 u32 rcv1, rcv0; 1270 u32 rcv1, rcv0;
1189 int new0, new1, new2; 1271 int new0, new1, new2;
1190 1272
1191 if (!pvt->pci_mcr[4]) { 1273 if (!pvt->pci_mcr[socket][4]) {
1192 debugf0("%s MCR registers not found\n",__func__); 1274 debugf0("%s MCR registers not found\n",__func__);
1193 return; 1275 return;
1194 } 1276 }
1195 1277
1196 /* Corrected error reads */ 1278 /* Corrected error reads */
1197 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1); 1279 pci_read_config_dword(pvt->pci_mcr[socket][4], MC_TEST_ERR_RCV1, &rcv1);
1198 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0); 1280 pci_read_config_dword(pvt->pci_mcr[socket][4], MC_TEST_ERR_RCV0, &rcv0);
1199 1281
1200 /* Store the new values */ 1282 /* Store the new values */
1201 new2 = DIMM2_COR_ERR(rcv1); 1283 new2 = DIMM2_COR_ERR(rcv1);
@@ -1209,32 +1291,32 @@ static void check_mc_test_err(struct mem_ctl_info *mci)
1209#endif 1291#endif
1210 1292
1211 /* Updates CE counters if it is not the first time here */ 1293 /* Updates CE counters if it is not the first time here */
1212 if (pvt->ce_count_available) { 1294 if (pvt->ce_count_available[socket]) {
1213 /* Updates CE counters */ 1295 /* Updates CE counters */
1214 int add0, add1, add2; 1296 int add0, add1, add2;
1215 1297
1216 add2 = new2 - pvt->last_ce_count[2]; 1298 add2 = new2 - pvt->last_ce_count[socket][2];
1217 add1 = new1 - pvt->last_ce_count[1]; 1299 add1 = new1 - pvt->last_ce_count[socket][1];
1218 add0 = new0 - pvt->last_ce_count[0]; 1300 add0 = new0 - pvt->last_ce_count[socket][0];
1219 1301
1220 if (add2 < 0) 1302 if (add2 < 0)
1221 add2 += 0x7fff; 1303 add2 += 0x7fff;
1222 pvt->ce_count[2] += add2; 1304 pvt->ce_count[socket][2] += add2;
1223 1305
1224 if (add1 < 0) 1306 if (add1 < 0)
1225 add1 += 0x7fff; 1307 add1 += 0x7fff;
1226 pvt->ce_count[1] += add1; 1308 pvt->ce_count[socket][1] += add1;
1227 1309
1228 if (add0 < 0) 1310 if (add0 < 0)
1229 add0 += 0x7fff; 1311 add0 += 0x7fff;
1230 pvt->ce_count[0] += add0; 1312 pvt->ce_count[socket][0] += add0;
1231 } else 1313 } else
1232 pvt->ce_count_available = 1; 1314 pvt->ce_count_available[socket] = 1;
1233 1315
1234 /* Store the new values */ 1316 /* Store the new values */
1235 pvt->last_ce_count[2] = new2; 1317 pvt->last_ce_count[socket][2] = new2;
1236 pvt->last_ce_count[1] = new1; 1318 pvt->last_ce_count[socket][1] = new1;
1237 pvt->last_ce_count[0] = new0; 1319 pvt->last_ce_count[socket][0] = new0;
1238} 1320}
1239 1321
1240static void i7core_mce_output_error(struct mem_ctl_info *mci, 1322static void i7core_mce_output_error(struct mem_ctl_info *mci,
@@ -1299,7 +1381,8 @@ static void i7core_check_error(struct mem_ctl_info *mci)
1299 kfree(m); 1381 kfree(m);
1300 1382
1301 /* check memory count errors */ 1383 /* check memory count errors */
1302 check_mc_test_err(mci); 1384 for (i = 0; i < pvt->sockets; i++)
1385 check_mc_test_err(mci, i);
1303} 1386}
1304 1387
1305/* 1388/*
@@ -1339,10 +1422,11 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1339{ 1422{
1340 struct mem_ctl_info *mci; 1423 struct mem_ctl_info *mci;
1341 struct i7core_pvt *pvt; 1424 struct i7core_pvt *pvt;
1342 int num_channels; 1425 int num_channels = 0;
1343 int num_csrows; 1426 int num_csrows = 0;
1344 int dev_idx = id->driver_data; 1427 int dev_idx = id->driver_data;
1345 int rc; 1428 int rc, i;
1429 u8 sockets;
1346 1430
1347 if (unlikely(dev_idx >= ARRAY_SIZE(i7core_devs))) 1431 if (unlikely(dev_idx >= ARRAY_SIZE(i7core_devs)))
1348 return -EINVAL; 1432 return -EINVAL;
@@ -1352,10 +1436,25 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1352 if (unlikely(rc < 0)) 1436 if (unlikely(rc < 0))
1353 return rc; 1437 return rc;
1354 1438
1355 /* Check the number of active and not disabled channels */ 1439 sockets = 1;
1356 rc = i7core_get_active_channels(&num_channels, &num_csrows); 1440 for (i = NUM_SOCKETS - 1; i > 0; i--)
1357 if (unlikely(rc < 0)) 1441 if (pci_devs[0].pdev[i]) {
1358 goto fail0; 1442 sockets = i + 1;
1443 break;
1444 }
1445
1446 for (i = 0; i < sockets; i++) {
1447 int channels;
1448 int csrows;
1449
1450 /* Check the number of active and not disabled channels */
1451 rc = i7core_get_active_channels(i, &channels, &csrows);
1452 if (unlikely(rc < 0))
1453 goto fail0;
1454
1455 num_channels += channels;
1456 num_csrows += csrows;
1457 }
1359 1458
1360 /* allocate a new MC control structure */ 1459 /* allocate a new MC control structure */
1361 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0); 1460 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
@@ -1367,11 +1466,11 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1367 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); 1466 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1368 1467
1369 mci->dev = &pdev->dev; /* record ptr to the generic device */ 1468 mci->dev = &pdev->dev; /* record ptr to the generic device */
1370
1371 pvt = mci->pvt_info; 1469 pvt = mci->pvt_info;
1372 memset(pvt, 0, sizeof(*pvt)); 1470 memset(pvt, 0, sizeof(*pvt));
1373 1471 pvt->sockets = sockets;
1374 mci->mc_idx = 0; 1472 mci->mc_idx = 0;
1473
1375 /* 1474 /*
1376 * FIXME: how to handle RDDR3 at MCI level? It is possible to have 1475 * FIXME: how to handle RDDR3 at MCI level? It is possible to have
1377 * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different 1476 * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
@@ -1395,7 +1494,8 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
1395 goto fail1; 1494 goto fail1;
1396 1495
1397 /* Get dimm basic config */ 1496 /* Get dimm basic config */
1398 get_dimm_config(mci); 1497 for (i = 0; i < sockets; i++)
1498 get_dimm_config(mci, i);
1399 1499
1400 /* add this new MC control structure to EDAC's list of MCs */ 1500 /* add this new MC control structure to EDAC's list of MCs */
1401 if (unlikely(edac_mc_add_mc(mci))) { 1501 if (unlikely(edac_mc_add_mc(mci))) {