1 /* Intel 7 core Memory Controller kernel module (Nehalem)
3 * This file may be distributed under the terms of the
4 * GNU General Public License version 2 only.
6 * Copyright (c) 2009 by:
7 * Mauro Carvalho Chehab <mchehab@redhat.com>
9 * Red Hat Inc. http://www.redhat.com
11 * Forked and adapted from the i5400_edac driver
13 * Based on the following public Intel datasheets:
14 * Intel Core i7 Processor Extreme Edition and Intel Core i7 Processor
15 * Datasheet, Volume 2:
16 * http://download.intel.com/design/processor/datashts/320835.pdf
17 * Intel Xeon Processor 5500 Series Datasheet Volume 2
18 * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
20 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/pci.h>
26 #include <linux/pci_ids.h>
27 #include <linux/slab.h>
28 #include <linux/edac.h>
29 #include <linux/mmzone.h>
31 #include "edac_core.h"
33 /* To use the new pci_[read/write]_config_qword instead of two dword */
37 * Alter this version for the module when modifications are made
39 #define I7CORE_REVISION " Ver: 1.0.0 " __DATE__
40 #define EDAC_MOD_STR "i7core_edac"
42 /* HACK: temporary, just to enable all logs, for now */
44 #define debugf0(fmt, arg...) edac_printk(KERN_INFO, "i7core", fmt, ##arg)
49 #define i7core_printk(level, fmt, arg...) \
50 edac_printk(level, "i7core", fmt, ##arg)
52 #define i7core_mc_printk(mci, level, fmt, arg...) \
53 edac_mc_chipset_printk(mci, level, "i7core", fmt, ##arg)
56 * i7core Memory Controller Registers
59 /* OFFSETS for Device 3 Function 0 */
61 #define MC_CONTROL 0x48
62 #define MC_STATUS 0x4c
63 #define MC_MAX_DOD 0x64
66 * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
67 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
70 #define MC_TEST_ERR_RCV1 0x60
71 #define DIMM2_COR_ERR(r) ((r) & 0x7fff)
73 #define MC_TEST_ERR_RCV0 0x64
74 #define DIMM1_COR_ERR(r) (((r) >> 16) & 0x7fff)
75 #define DIMM0_COR_ERR(r) ((r) & 0x7fff)
77 /* OFFSETS for Devices 4,5 and 6 Function 0 */
79 #define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
80 #define THREE_DIMMS_PRESENT (1 << 24)
81 #define SINGLE_QUAD_RANK_PRESENT (1 << 23)
82 #define QUAD_RANK_PRESENT (1 << 22)
83 #define REGISTERED_DIMM (1 << 15)
85 #define MC_CHANNEL_MAPPER 0x60
86 #define RDLCH(r, ch) ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
87 #define WRLCH(r, ch) ((((r) >> (ch * 6)) & 0x07) - 1)
89 #define MC_CHANNEL_RANK_PRESENT 0x7c
90 #define RANK_PRESENT_MASK 0xffff
92 #define MC_CHANNEL_ADDR_MATCH 0xf0
93 #define MC_CHANNEL_ERROR_MASK 0xf8
94 #define MC_CHANNEL_ERROR_INJECT 0xfc
95 #define INJECT_ADDR_PARITY 0x10
96 #define INJECT_ECC 0x08
97 #define MASK_CACHELINE 0x06
98 #define MASK_FULL_CACHELINE 0x06
99 #define MASK_MSB32_CACHELINE 0x04
100 #define MASK_LSB32_CACHELINE 0x02
101 #define NO_MASK_CACHELINE 0x00
102 #define REPEAT_EN 0x01
104 /* OFFSETS for Devices 4,5 and 6 Function 1 */
105 #define MC_DOD_CH_DIMM0 0x48
106 #define MC_DOD_CH_DIMM1 0x4c
107 #define MC_DOD_CH_DIMM2 0x50
108 #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10))
109 #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10)
110 #define DIMM_PRESENT_MASK (1 << 9)
111 #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9)
112 #define NUMBANK_MASK ((1 << 8) | (1 << 7))
113 #define NUMBANK(x) (((x) & NUMBANK_MASK) >> 7)
114 #define NUMRANK_MASK ((1 << 6) | (1 << 5))
115 #define NUMRANK(x) (((x) & NUMRANK_MASK) >> 5)
116 #define NUMROW_MASK ((1 << 4) | (1 << 3))
117 #define NUMROW(x) (((x) & NUMROW_MASK) >> 3)
118 #define NUMCOL_MASK 3
119 #define NUMCOL(x) ((x) & NUMCOL_MASK)
121 #define MC_RANK_PRESENT 0x7c
123 #define MC_SAG_CH_0 0x80
124 #define MC_SAG_CH_1 0x84
125 #define MC_SAG_CH_2 0x88
126 #define MC_SAG_CH_3 0x8c
127 #define MC_SAG_CH_4 0x90
128 #define MC_SAG_CH_5 0x94
129 #define MC_SAG_CH_6 0x98
130 #define MC_SAG_CH_7 0x9c
132 #define MC_RIR_LIMIT_CH_0 0x40
133 #define MC_RIR_LIMIT_CH_1 0x44
134 #define MC_RIR_LIMIT_CH_2 0x48
135 #define MC_RIR_LIMIT_CH_3 0x4C
136 #define MC_RIR_LIMIT_CH_4 0x50
137 #define MC_RIR_LIMIT_CH_5 0x54
138 #define MC_RIR_LIMIT_CH_6 0x58
139 #define MC_RIR_LIMIT_CH_7 0x5C
140 #define MC_RIR_LIMIT_MASK ((1 << 10) - 1)
142 #define MC_RIR_WAY_CH 0x80
143 #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7)
144 #define MC_RIR_WAY_RANK_MASK 0x7
151 #define MAX_DIMMS 3 /* Max DIMMS per channel */
152 #define MAX_MCR_FUNC 4
153 #define MAX_CHAN_FUNC 3
163 struct i7core_inject {
170 /* Error address mask */
171 int channel, dimm, rank, bank, page, col;
174 struct i7core_channel {
179 struct pci_id_descr {
183 struct pci_dev *pdev;
187 struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1];
188 struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
189 struct i7core_info info;
190 struct i7core_inject inject;
191 struct i7core_channel channel[NUM_CHANS];
192 int channels; /* Number of active channels */
194 int ce_count_available;
195 unsigned long ce_count[MAX_DIMMS]; /* ECC corrected errors counts per dimm */
196 int last_ce_count[MAX_DIMMS];
200 /* Device name and register DID (Device ID) */
201 struct i7core_dev_info {
202 const char *ctl_name; /* name for this device */
203 u16 fsb_mapping_errors; /* DID for the branchmap,control */
206 #define PCI_DESCR(device, function, device_id) \
208 .func = (function), \
209 .dev_id = (device_id)
211 struct pci_id_descr pci_devs[] = {
212 /* Memory controller */
213 { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
214 { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
215 { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM is supported */
216 { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
219 { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
220 { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
221 { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
222 { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC) },
225 { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
226 { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
227 { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
228 { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC) },
231 { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
232 { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
233 { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
234 { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
236 #define N_DEVS ARRAY_SIZE(pci_devs)
239 * pci_device_id table for which devices we are looking for
240 * This should match the first device at pci_devs table
242 static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
243 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR)},
244 {0,} /* 0 terminated list. */
248 /* Table of devices attributes supported by this driver */
249 static const struct i7core_dev_info i7core_devs[] = {
251 .ctl_name = "i7 Core",
252 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7_MCR,
256 static struct edac_pci_ctl_info *i7core_pci;
258 /****************************************************************************
259 Anciliary status routines
260 ****************************************************************************/
262 /* MC_CONTROL bits */
263 #define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & (1 << (8 + ch)))
264 #define ECCx8(pvt) ((pvt)->info.mc_control & (1 << 1))
267 #define ECC_ENABLED(pvt) ((pvt)->info.mc_status & (1 << 3))
268 #define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & (1 << ch))
270 /* MC_MAX_DOD read functions */
271 static inline int maxnumdimms(struct i7core_pvt *pvt)
273 return (pvt->info.max_dod & 0x3) + 1;
276 static inline int maxnumrank(struct i7core_pvt *pvt)
278 static int ranks[4] = { 1, 2, 4, -EINVAL };
280 return ranks[(pvt->info.max_dod >> 2) & 0x3];
283 static inline int maxnumbank(struct i7core_pvt *pvt)
285 static int banks[4] = { 4, 8, 16, -EINVAL };
287 return banks[(pvt->info.max_dod >> 4) & 0x3];
290 static inline int maxnumrow(struct i7core_pvt *pvt)
292 static int rows[8] = {
293 1 << 12, 1 << 13, 1 << 14, 1 << 15,
294 1 << 16, -EINVAL, -EINVAL, -EINVAL,
297 return rows[((pvt->info.max_dod >> 6) & 0x7)];
300 static inline int maxnumcol(struct i7core_pvt *pvt)
302 static int cols[8] = {
303 1 << 10, 1 << 11, 1 << 12, -EINVAL,
305 return cols[((pvt->info.max_dod >> 9) & 0x3) << 12];
309 /****************************************************************************
310 Memory check routines
311 ****************************************************************************/
312 static int i7core_get_active_channels(int *channels)
314 struct pci_dev *pdev = NULL;
320 for (i = 0; i < N_DEVS; i++) {
321 if (!pci_devs[i].pdev)
324 if (PCI_SLOT(pci_devs[i].pdev->devfn) == 3 &&
325 PCI_FUNC(pci_devs[i].pdev->devfn) == 0) {
326 pdev = pci_devs[i].pdev;
332 i7core_printk(KERN_ERR, "Couldn't find fn 3.0!!!\n");
336 /* Device 3 function 0 reads */
337 pci_read_config_dword(pdev, MC_STATUS, &status);
338 pci_read_config_dword(pdev, MC_CONTROL, &control);
340 for (i = 0; i < NUM_CHANS; i++) {
341 /* Check if the channel is active */
342 if (!(control & (1 << (8 + i))))
345 /* Check if the channel is disabled */
346 if (status & (1 << i)) {
353 debugf0("Number of active channels: %d\n", *channels);
358 static int get_dimm_config(struct mem_ctl_info *mci)
360 struct i7core_pvt *pvt = mci->pvt_info;
361 struct csrow_info *csr;
362 struct pci_dev *pdev = pvt->pci_mcr[0];
369 /* Device 3 function 0 reads */
370 pci_read_config_dword(pdev, MC_CONTROL, &pvt->info.mc_control);
371 pci_read_config_dword(pdev, MC_STATUS, &pvt->info.mc_status);
372 pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod);
373 pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map);
375 debugf0("MC control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
376 pvt->info.mc_control, pvt->info.mc_status,
377 pvt->info.max_dod, pvt->info.ch_map);
379 if (ECC_ENABLED(pvt)) {
380 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4);
382 mode = EDAC_S8ECD8ED;
384 mode = EDAC_S4ECD4ED;
386 debugf0("ECC disabled\n");
390 /* FIXME: need to handle the error codes */
391 debugf0("DOD Maximum limits: DIMMS: %d, %d-ranked, %d-banked\n",
392 maxnumdimms(pvt), maxnumrank(pvt), maxnumbank(pvt));
393 debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n",
394 maxnumrow(pvt), maxnumcol(pvt));
396 debugf0("Memory channel configuration:\n");
398 for (i = 0; i < NUM_CHANS; i++) {
401 if (!CH_ACTIVE(pvt, i)) {
402 debugf0("Channel %i is not active\n", i);
405 if (CH_DISABLED(pvt, i)) {
406 debugf0("Channel %i is disabled\n", i);
410 /* Devices 4-6 function 0 */
411 pci_read_config_dword(pvt->pci_ch[i][0],
412 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
414 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;
416 if (data & THREE_DIMMS_PRESENT)
417 pvt->channel[i].dimms = 3;
418 else if (data & SINGLE_QUAD_RANK_PRESENT)
419 pvt->channel[i].dimms = 1;
421 pvt->channel[i].dimms = 2;
423 debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
424 "%d ranks, %d %cDIMMs, offset = %d\n\t"
425 "present: %i, numbank: %#x, numrank: %#x, "
426 "numrow: %#x, numcol: %#x\n",
428 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
430 pvt->channel[i].ranks, pvt->channel[i].dimms,
431 (data & REGISTERED_DIMM)? 'R' : 'U',
434 NUMBANK(data), NUMRANK(data),
435 NUMROW(data), NUMCOL(data));
437 pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
438 pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
439 pci_read_config_dword(pdev, MC_SAG_CH_2, &value[2]);
440 pci_read_config_dword(pdev, MC_SAG_CH_3, &value[3]);
441 pci_read_config_dword(pdev, MC_SAG_CH_4, &value[4]);
442 pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]);
443 pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]);
444 pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]);
445 printk("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i);
446 for (j = 0; j < 8; j++)
447 printk("\t\t%#x\t%#x\t%#x\n",
448 (value[j] >> 27) & 0x1,
449 (value[j] >> 24) & 0x7,
450 (value[j] && ((1 << 24) - 1)));
452 csr = &mci->csrows[csrow];
458 csr->csrow_idx = csrow;
459 csr->dtype = DEV_X8; /* FIXME: check this */
461 if (data & REGISTERED_DIMM)
462 csr->mtype = MEM_RDDR3;
464 csr->mtype = MEM_DDR3;
465 csr->edac_mode = mode;
473 /****************************************************************************
474 Error insertion routines
475 ****************************************************************************/
477 /* The i7core has independent error injection features per channel.
478 However, to have a simpler code, we don't allow enabling error injection
479 on more than one channel.
480 Also, since a change at an inject parameter will be applied only at enable,
481 we're disabling error injection on all write calls to the sysfs nodes that
482 controls the error code injection.
484 static int disable_inject(struct mem_ctl_info *mci)
486 struct i7core_pvt *pvt = mci->pvt_info;
488 pvt->inject.enable = 0;
490 if (!pvt->pci_ch[pvt->inject.channel][0])
493 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
494 MC_CHANNEL_ERROR_MASK, 0);
500 * i7core inject inject.section
502 * accept and store error injection inject.section value
503 * bit 0 - refers to the lower 32-byte half cacheline
504 * bit 1 - refers to the upper 32-byte half cacheline
506 static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
507 const char *data, size_t count)
509 struct i7core_pvt *pvt = mci->pvt_info;
513 if (pvt->inject.enable)
516 rc = strict_strtoul(data, 10, &value);
517 if ((rc < 0) || (value > 3))
520 pvt->inject.section = (u32) value;
524 static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
527 struct i7core_pvt *pvt = mci->pvt_info;
528 return sprintf(data, "0x%08x\n", pvt->inject.section);
534 * accept and store error injection inject.section value
535 * bit 0 - repeat enable - Enable error repetition
536 * bit 1 - inject ECC error
537 * bit 2 - inject parity error
539 static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
540 const char *data, size_t count)
542 struct i7core_pvt *pvt = mci->pvt_info;
546 if (pvt->inject.enable)
549 rc = strict_strtoul(data, 10, &value);
550 if ((rc < 0) || (value > 7))
553 pvt->inject.type = (u32) value;
557 static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
560 struct i7core_pvt *pvt = mci->pvt_info;
561 return sprintf(data, "0x%08x\n", pvt->inject.type);
565 * i7core_inject_inject.eccmask_store
567 * The type of error (UE/CE) will depend on the inject.eccmask value:
568 * Any bits set to a 1 will flip the corresponding ECC bit
569 * Correctable errors can be injected by flipping 1 bit or the bits within
570 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
571 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
572 * uncorrectable error to be injected.
574 static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
575 const char *data, size_t count)
577 struct i7core_pvt *pvt = mci->pvt_info;
581 if (pvt->inject.enable)
584 rc = strict_strtoul(data, 10, &value);
588 pvt->inject.eccmask = (u32) value;
592 static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
595 struct i7core_pvt *pvt = mci->pvt_info;
596 return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
602 * The type of error (UE/CE) will depend on the inject.eccmask value:
603 * Any bits set to a 1 will flip the corresponding ECC bit
604 * Correctable errors can be injected by flipping 1 bit or the bits within
605 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
606 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
607 * uncorrectable error to be injected.
609 static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
610 const char *data, size_t count)
612 struct i7core_pvt *pvt = mci->pvt_info;
617 if (pvt->inject.enable)
621 cmd = strsep((char **) &data, ":");
624 val = strsep((char **) &data, " \n\t");
628 if (!strcasecmp(val,"any"))
631 rc = strict_strtol(val, 10, &value);
632 if ((rc < 0) || (value < 0))
636 if (!strcasecmp(cmd,"channel")) {
638 pvt->inject.channel = value;
641 } else if (!strcasecmp(cmd,"dimm")) {
643 pvt->inject.dimm = value;
646 } else if (!strcasecmp(cmd,"rank")) {
648 pvt->inject.rank = value;
651 } else if (!strcasecmp(cmd,"bank")) {
653 pvt->inject.bank = value;
656 } else if (!strcasecmp(cmd,"page")) {
658 pvt->inject.page = value;
661 } else if (!strcasecmp(cmd,"col") ||
662 !strcasecmp(cmd,"column")) {
664 pvt->inject.col = value;
673 static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
676 struct i7core_pvt *pvt = mci->pvt_info;
677 char channel[4], dimm[4], bank[4], rank[4], page[7], col[7];
679 if (pvt->inject.channel < 0)
680 sprintf(channel, "any");
682 sprintf(channel, "%d", pvt->inject.channel);
683 if (pvt->inject.dimm < 0)
684 sprintf(dimm, "any");
686 sprintf(dimm, "%d", pvt->inject.dimm);
687 if (pvt->inject.bank < 0)
688 sprintf(bank, "any");
690 sprintf(bank, "%d", pvt->inject.bank);
691 if (pvt->inject.rank < 0)
692 sprintf(rank, "any");
694 sprintf(rank, "%d", pvt->inject.rank);
695 if (pvt->inject.page < 0)
696 sprintf(page, "any");
698 sprintf(page, "0x%04x", pvt->inject.page);
699 if (pvt->inject.col < 0)
702 sprintf(col, "0x%04x", pvt->inject.col);
704 return sprintf(data, "channel: %s\ndimm: %s\nbank: %s\n"
705 "rank: %s\npage: %s\ncolumn: %s\n",
706 channel, dimm, bank, rank, page, col);
710 * This routine prepares the Memory Controller for error injection.
711 * The error will be injected when some process tries to write to the
712 * memory that matches the given criteria.
713 * The criteria can be set in terms of a mask where dimm, rank, bank, page
714 * and col can be specified.
715 * A -1 value for any of the mask items will make the MCU to ignore
716 * that matching criteria for error injection.
718 * It should be noticed that the error will only happen after a write operation
719 * on a memory that matches the condition. if REPEAT_EN is not enabled at
720 * inject mask, then it will produce just one error. Otherwise, it will repeat
721 * until the injectmask would be cleaned.
723 * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
724 * is reliable enough to check if the MC is using the
725 * three channels. However, this is not clear at the datasheet.
727 static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
728 const char *data, size_t count)
730 struct i7core_pvt *pvt = mci->pvt_info;
736 if (!pvt->pci_ch[pvt->inject.channel][0])
739 rc = strict_strtoul(data, 10, &enable);
744 pvt->inject.enable = 1;
750 /* Sets pvt->inject.dimm mask */
751 if (pvt->inject.dimm < 0)
754 if (pvt->channel[pvt->inject.channel].dimms > 2)
755 mask |= (pvt->inject.dimm & 0x3L) << 35;
757 mask |= (pvt->inject.dimm & 0x1L) << 36;
760 /* Sets pvt->inject.rank mask */
761 if (pvt->inject.rank < 0)
764 if (pvt->channel[pvt->inject.channel].dimms > 2)
765 mask |= (pvt->inject.rank & 0x1L) << 34;
767 mask |= (pvt->inject.rank & 0x3L) << 34;
770 /* Sets pvt->inject.bank mask */
771 if (pvt->inject.bank < 0)
774 mask |= (pvt->inject.bank & 0x15L) << 30;
776 /* Sets pvt->inject.page mask */
777 if (pvt->inject.page < 0)
780 mask |= (pvt->inject.page & 0xffffL) << 14;
782 /* Sets pvt->inject.column mask */
783 if (pvt->inject.col < 0)
786 mask |= (pvt->inject.col & 0x3fffL);
789 pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0],
790 MC_CHANNEL_ADDR_MATCH, mask);
792 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
793 MC_CHANNEL_ADDR_MATCH, mask);
794 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
795 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
801 pci_read_config_qword(pvt->pci_ch[pvt->inject.channel][0],
802 MC_CHANNEL_ADDR_MATCH, &rdmask);
803 debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n",
806 u32 rdmask1, rdmask2;
808 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
809 MC_CHANNEL_ADDR_MATCH, &rdmask1);
810 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
811 MC_CHANNEL_ADDR_MATCH + 4, &rdmask2);
813 debugf0("Inject addr match write 0x%016llx, read: 0x%08x%08x\n",
814 mask, rdmask1, rdmask2);
818 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
819 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
823 * bits 1-2: MASK_HALF_CACHELINE
825 * bit 4: INJECT_ADDR_PARITY
828 injectmask = (pvt->inject.type & 1) |
829 (pvt->inject.section & 0x3) << 1 |
830 (pvt->inject.type & 0x6) << (3 - 1);
832 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
833 MC_CHANNEL_ERROR_MASK, injectmask);
835 debugf0("Error inject addr match 0x%016llx, ecc 0x%08x, inject 0x%08x\n",
836 mask, pvt->inject.eccmask, injectmask);
843 static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
846 struct i7core_pvt *pvt = mci->pvt_info;
849 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
850 MC_CHANNEL_ERROR_MASK, &injectmask);
852 debugf0("Inject error read: 0x%018x\n", injectmask);
854 if (injectmask & 0x0c)
855 pvt->inject.enable = 1;
857 return sprintf(data, "%d\n", pvt->inject.enable);
860 static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
862 struct i7core_pvt *pvt = mci->pvt_info;
864 if (!pvt->ce_count_available)
865 return sprintf(data, "unavailable\n");
867 return sprintf(data, "dimm0: %lu\ndimm1: %lu\ndimm2: %lu\n",
876 static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
880 .name = "inject_section",
881 .mode = (S_IRUGO | S_IWUSR)
883 .show = i7core_inject_section_show,
884 .store = i7core_inject_section_store,
887 .name = "inject_type",
888 .mode = (S_IRUGO | S_IWUSR)
890 .show = i7core_inject_type_show,
891 .store = i7core_inject_type_store,
894 .name = "inject_eccmask",
895 .mode = (S_IRUGO | S_IWUSR)
897 .show = i7core_inject_eccmask_show,
898 .store = i7core_inject_eccmask_store,
901 .name = "inject_addrmatch",
902 .mode = (S_IRUGO | S_IWUSR)
904 .show = i7core_inject_addrmatch_show,
905 .store = i7core_inject_addrmatch_store,
908 .name = "inject_enable",
909 .mode = (S_IRUGO | S_IWUSR)
911 .show = i7core_inject_enable_show,
912 .store = i7core_inject_enable_store,
915 .name = "corrected_error_counts",
916 .mode = (S_IRUGO | S_IWUSR)
918 .show = i7core_ce_regs_show,
923 /****************************************************************************
924 Device initialization routines: put/get, init/exit
925 ****************************************************************************/
928 * i7core_put_devices 'put' all the devices that we have
931 static void i7core_put_devices(void)
935 for (i = 0; i < N_DEVS; i++)
936 pci_dev_put(pci_devs[i].pdev);
940 * i7core_get_devices Find and perform 'get' operation on the MCH's
941 * device/functions we want to reference for this driver
943 * Need to 'get' device 16 func 1 and func 2
945 static int i7core_get_devices(void)
948 struct pci_dev *pdev = NULL;
950 for (i = 0; i < N_DEVS; i++) {
951 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
952 pci_devs[i].dev_id, NULL);
954 pci_devs[i].pdev = pdev;
956 i7core_printk(KERN_ERR,
957 "Device not found: PCI ID %04x:%04x "
958 "(dev %d, func %d)\n",
959 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
960 pci_devs[i].dev,pci_devs[i].func);
962 /* Dev 3 function 2 only exists on chips with RDIMMs */
963 if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
966 /* End of list, leave */
972 if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[i].dev ||
973 PCI_FUNC(pdev->devfn) != pci_devs[i].func)) {
974 i7core_printk(KERN_ERR,
975 "Device PCI ID %04x:%04x "
976 "has fn %d.%d instead of fn %d.%d\n",
977 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
978 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
979 pci_devs[i].dev, pci_devs[i].func);
984 /* Be sure that the device is enabled */
985 rc = pci_enable_device(pdev);
986 if (unlikely(rc < 0)) {
987 i7core_printk(KERN_ERR,
988 "Couldn't enable PCI ID %04x:%04x "
990 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
991 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
995 i7core_printk(KERN_INFO,
996 "Registered device %0x:%0x fn %d.%d\n",
997 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
998 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1004 i7core_put_devices();
1008 static int mci_bind_devs(struct mem_ctl_info *mci)
1010 struct i7core_pvt *pvt = mci->pvt_info;
1011 struct pci_dev *pdev;
1014 for (i = 0; i < N_DEVS; i++) {
1015 pdev = pci_devs[i].pdev;
1019 func = PCI_FUNC(pdev->devfn);
1020 slot = PCI_SLOT(pdev->devfn);
1022 if (unlikely(func > MAX_MCR_FUNC))
1024 pvt->pci_mcr[func] = pdev;
1025 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1026 if (unlikely(func > MAX_CHAN_FUNC))
1028 pvt->pci_ch[slot - 4][func] = pdev;
1032 debugf0("Associated fn %d.%d, dev = %p\n",
1033 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev);
1038 i7core_printk(KERN_ERR, "Device %d, function %d "
1039 "is out of the expected range\n",
1044 /****************************************************************************
1045 Error check routines
1046 ****************************************************************************/
1048 /* This function is based on the device 3 function 4 registers as described on:
1049 * Intel Xeon Processor 5500 Series Datasheet Volume 2
1050 * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
1051 * also available at:
1052 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
1054 static void check_mc_test_err(struct mem_ctl_info *mci)
1056 struct i7core_pvt *pvt = mci->pvt_info;
1058 int new0, new1, new2;
1060 if (!pvt->pci_mcr[4]) {
1061 debugf0("%s MCR registers not found\n",__func__);
1065 /* Corrected error reads */
1066 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1);
1067 pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0);
1069 /* Store the new values */
1070 new2 = DIMM2_COR_ERR(rcv1);
1071 new1 = DIMM1_COR_ERR(rcv0);
1072 new0 = DIMM0_COR_ERR(rcv0);
1074 debugf2("%s CE rcv1=0x%08x rcv0=0x%08x, %d %d %d\n",
1075 (pvt->ce_count_available ? "UPDATE" : "READ"),
1076 rcv1, rcv0, new0, new1, new2);
1078 /* Updates CE counters if it is not the first time here */
1079 if (pvt->ce_count_available) {
1080 /* Updates CE counters */
1081 int add0, add1, add2;
1083 add2 = new2 - pvt->last_ce_count[2];
1084 add1 = new1 - pvt->last_ce_count[1];
1085 add0 = new0 - pvt->last_ce_count[0];
1089 pvt->ce_count[2] += add2;
1093 pvt->ce_count[1] += add1;
1097 pvt->ce_count[0] += add0;
1099 pvt->ce_count_available = 1;
1101 /* Store the new values */
1102 pvt->last_ce_count[2] = new2;
1103 pvt->last_ce_count[1] = new1;
1104 pvt->last_ce_count[0] = new0;
1108 * i7core_check_error Retrieve and process errors reported by the
1109 * hardware. Called by the Core module.
1111 static void i7core_check_error(struct mem_ctl_info *mci)
1113 check_mc_test_err(mci);
1117 * i7core_probe Probe for ONE instance of device to see if it is
1120 * 0 for FOUND a device
1121 * < 0 for error code
1123 static int __devinit i7core_probe(struct pci_dev *pdev,
1124 const struct pci_device_id *id)
1126 struct mem_ctl_info *mci;
1127 struct i7core_pvt *pvt;
1128 int num_channels = 0;
1130 int dev_idx = id->driver_data;
1133 if (unlikely(dev_idx >= ARRAY_SIZE(i7core_devs)))
1136 /* get the pci devices we want to reserve for our use */
1137 rc = i7core_get_devices();
1138 if (unlikely(rc < 0))
1141 /* Check the number of active and not disabled channels */
1142 rc = i7core_get_active_channels(&num_channels);
1143 if (unlikely (rc < 0))
1146 /* FIXME: we currently don't know the number of csrows */
1147 num_csrows = num_channels;
1149 /* allocate a new MC control structure */
1150 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
1151 if (unlikely (!mci)) {
1156 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1158 mci->dev = &pdev->dev; /* record ptr to the generic device */
1160 pvt = mci->pvt_info;
1161 memset(pvt, 0, sizeof(*pvt));
1164 mci->mtype_cap = MEM_FLAG_DDR3; /* FIXME: how to handle RDDR3? */
1165 mci->edac_ctl_cap = EDAC_FLAG_NONE;
1166 mci->edac_cap = EDAC_FLAG_NONE;
1167 mci->mod_name = "i7core_edac.c";
1168 mci->mod_ver = I7CORE_REVISION;
1169 mci->ctl_name = i7core_devs[dev_idx].ctl_name;
1170 mci->dev_name = pci_name(pdev);
1171 mci->ctl_page_to_phys = NULL;
1172 mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
1173 /* Set the function pointer to an actual operation function */
1174 mci->edac_check = i7core_check_error;
1176 /* Store pci devices at mci for faster access */
1177 rc = mci_bind_devs(mci);
1178 if (unlikely (rc < 0))
1181 /* Get dimm basic config */
1182 get_dimm_config(mci);
1184 /* add this new MC control structure to EDAC's list of MCs */
1185 if (unlikely(edac_mc_add_mc(mci))) {
1186 debugf0("MC: " __FILE__
1187 ": %s(): failed edac_mc_add_mc()\n", __func__);
1188 /* FIXME: perhaps some code should go here that disables error
1189 * reporting if we just enabled it
1196 /* allocating generic PCI control info */
1197 i7core_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
1198 if (unlikely (!i7core_pci)) {
1200 "%s(): Unable to create PCI control\n",
1203 "%s(): PCI error report via EDAC not setup\n",
1207 /* Default error mask is any memory */
1208 pvt->inject.channel = 0;
1209 pvt->inject.dimm = -1;
1210 pvt->inject.rank = -1;
1211 pvt->inject.bank = -1;
1212 pvt->inject.page = -1;
1213 pvt->inject.col = -1;
1215 i7core_printk(KERN_INFO, "Driver loaded.\n");
1223 i7core_put_devices();
1228 * i7core_remove destructor for one instance of device
1231 static void __devexit i7core_remove(struct pci_dev *pdev)
1233 struct mem_ctl_info *mci;
1235 debugf0(__FILE__ ": %s()\n", __func__);
1238 edac_pci_release_generic_ctl(i7core_pci);
1240 mci = edac_mc_del_mc(&pdev->dev);
1245 /* retrieve references to resources, and free those resources */
1246 i7core_put_devices();
1251 MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
1254 * i7core_driver pci_driver structure for this module
1257 static struct pci_driver i7core_driver = {
1258 .name = "i7core_edac",
1259 .probe = i7core_probe,
1260 .remove = __devexit_p(i7core_remove),
1261 .id_table = i7core_pci_tbl,
1265 * i7core_init Module entry function
1266 * Try to initialize this module for its devices
1268 static int __init i7core_init(void)
1272 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1274 /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1277 pci_rc = pci_register_driver(&i7core_driver);
1279 return (pci_rc < 0) ? pci_rc : 0;
1283 * i7core_exit() Module exit function
1284 * Unregister the driver
1286 static void __exit i7core_exit(void)
1288 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1289 pci_unregister_driver(&i7core_driver);
1292 module_init(i7core_init);
1293 module_exit(i7core_exit);
1295 MODULE_LICENSE("GPL");
1296 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1297 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
1298 MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
1301 module_param(edac_op_state, int, 0444);
1302 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");