i7core_edac: need mci->edac_check, otherwise module removal doesn't work
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / edac / i7core_edac.c
blob190596af601a98854faaea913b34f196cee93a68
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
19 * also available at:
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 */
34 #define USE_QWORD 1
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 */
43 #undef debugf0
44 #define debugf0(fmt, arg...) edac_printk(KERN_INFO, "i7core", fmt, ##arg)
47 * Debug macros
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
65 /* OFFSETS for Devices 4,5 and 6 Function 0 */
67 #define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
68 #define THREE_DIMMS_PRESENT (1 << 24)
69 #define SINGLE_QUAD_RANK_PRESENT (1 << 23)
70 #define QUAD_RANK_PRESENT (1 << 22)
71 #define REGISTERED_DIMM (1 << 15)
73 #define MC_CHANNEL_MAPPER 0x60
74 #define RDLCH(r, ch) ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
75 #define WRLCH(r, ch) ((((r) >> (ch * 6)) & 0x07) - 1)
77 #define MC_CHANNEL_RANK_PRESENT 0x7c
78 #define RANK_PRESENT_MASK 0xffff
80 #define MC_CHANNEL_ADDR_MATCH 0xf0
81 #define MC_CHANNEL_ERROR_MASK 0xf8
82 #define MC_CHANNEL_ERROR_INJECT 0xfc
83 #define INJECT_ADDR_PARITY 0x10
84 #define INJECT_ECC 0x08
85 #define MASK_CACHELINE 0x06
86 #define MASK_FULL_CACHELINE 0x06
87 #define MASK_MSB32_CACHELINE 0x04
88 #define MASK_LSB32_CACHELINE 0x02
89 #define NO_MASK_CACHELINE 0x00
90 #define REPEAT_EN 0x01
92 /* OFFSETS for Devices 4,5 and 6 Function 1 */
93 #define MC_DOD_CH_DIMM0 0x48
94 #define MC_DOD_CH_DIMM1 0x4c
95 #define MC_DOD_CH_DIMM2 0x50
96 #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10))
97 #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10)
98 #define DIMM_PRESENT_MASK (1 << 9)
99 #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9)
100 #define NUMBANK_MASK ((1 << 8) | (1 << 7))
101 #define NUMBANK(x) (((x) & NUMBANK_MASK) >> 7)
102 #define NUMRANK_MASK ((1 << 6) | (1 << 5))
103 #define NUMRANK(x) (((x) & NUMRANK_MASK) >> 5)
104 #define NUMROW_MASK ((1 << 4) | (1 << 3))
105 #define NUMROW(x) (((x) & NUMROW_MASK) >> 3)
106 #define NUMCOL_MASK 3
107 #define NUMCOL(x) ((x) & NUMCOL_MASK)
109 #define MC_RANK_PRESENT 0x7c
111 #define MC_SAG_CH_0 0x80
112 #define MC_SAG_CH_1 0x84
113 #define MC_SAG_CH_2 0x88
114 #define MC_SAG_CH_3 0x8c
115 #define MC_SAG_CH_4 0x90
116 #define MC_SAG_CH_5 0x94
117 #define MC_SAG_CH_6 0x98
118 #define MC_SAG_CH_7 0x9c
120 #define MC_RIR_LIMIT_CH_0 0x40
121 #define MC_RIR_LIMIT_CH_1 0x44
122 #define MC_RIR_LIMIT_CH_2 0x48
123 #define MC_RIR_LIMIT_CH_3 0x4C
124 #define MC_RIR_LIMIT_CH_4 0x50
125 #define MC_RIR_LIMIT_CH_5 0x54
126 #define MC_RIR_LIMIT_CH_6 0x58
127 #define MC_RIR_LIMIT_CH_7 0x5C
128 #define MC_RIR_LIMIT_MASK ((1 << 10) - 1)
130 #define MC_RIR_WAY_CH 0x80
131 #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7)
132 #define MC_RIR_WAY_RANK_MASK 0x7
135 * i7core structs
138 #define NUM_CHANS 3
139 #define NUM_MCR_FUNCS 4
140 #define NUM_CHAN_FUNCS 3
142 struct i7core_info {
143 u32 mc_control;
144 u32 mc_status;
145 u32 max_dod;
146 u32 ch_map;
150 struct i7core_inject {
151 int enable;
153 u32 section;
154 u32 type;
155 u32 eccmask;
157 /* Error address mask */
158 int channel, dimm, rank, bank, page, col;
161 struct i7core_channel {
162 u32 ranks;
163 u32 dimms;
166 struct pci_id_descr {
167 int dev;
168 int func;
169 int dev_id;
170 struct pci_dev *pdev;
173 struct i7core_pvt {
174 struct pci_dev *pci_mcr[NUM_MCR_FUNCS];
175 struct pci_dev *pci_ch[NUM_CHANS][NUM_CHAN_FUNCS];
176 struct i7core_info info;
177 struct i7core_inject inject;
178 struct i7core_channel channel[NUM_CHANS];
181 /* Device name and register DID (Device ID) */
182 struct i7core_dev_info {
183 const char *ctl_name; /* name for this device */
184 u16 fsb_mapping_errors; /* DID for the branchmap,control */
187 #define PCI_DESCR(device, function, device_id) \
188 .dev = (device), \
189 .func = (function), \
190 .dev_id = (device_id)
192 struct pci_id_descr pci_devs[] = {
193 /* Memory controller */
194 { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
195 { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
196 { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM is supported */
197 { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
199 /* Channel 0 */
200 { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
201 { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
202 { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
203 { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC) },
205 /* Channel 1 */
206 { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
207 { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
208 { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
209 { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC) },
211 /* Channel 2 */
212 { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
213 { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
214 { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
215 { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
217 #define N_DEVS ARRAY_SIZE(pci_devs)
220 * pci_device_id table for which devices we are looking for
221 * This should match the first device at pci_devs table
223 static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
224 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR)},
225 {0,} /* 0 terminated list. */
229 /* Table of devices attributes supported by this driver */
230 static const struct i7core_dev_info i7core_devs[] = {
232 .ctl_name = "i7 Core",
233 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7_MCR,
237 static struct edac_pci_ctl_info *i7core_pci;
239 /****************************************************************************
240 Anciliary status routines
241 ****************************************************************************/
243 /* MC_CONTROL bits */
244 #define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & 1 << (8 + ch))
245 #define ECCx8(pvt) ((pvt)->info.mc_control & 1 << 1)
247 /* MC_STATUS bits */
248 #define ECC_ENABLED(pvt) ((pvt)->info.mc_status & 1 << 3)
249 #define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & 1 << ch)
251 /* MC_MAX_DOD read functions */
252 static inline int maxnumdimms(struct i7core_pvt *pvt)
254 return (pvt->info.max_dod & 0x3) + 1;
257 static inline int maxnumrank(struct i7core_pvt *pvt)
259 static int ranks[4] = { 1, 2, 4, -EINVAL };
261 return ranks[(pvt->info.max_dod >> 2) & 0x3];
264 static inline int maxnumbank(struct i7core_pvt *pvt)
266 static int banks[4] = { 4, 8, 16, -EINVAL };
268 return banks[(pvt->info.max_dod >> 4) & 0x3];
271 static inline int maxnumrow(struct i7core_pvt *pvt)
273 static int rows[8] = {
274 1 << 12, 1 << 13, 1 << 14, 1 << 15,
275 1 << 16, -EINVAL, -EINVAL, -EINVAL,
278 return rows[((pvt->info.max_dod >> 6) & 0x7)];
281 static inline int maxnumcol(struct i7core_pvt *pvt)
283 static int cols[8] = {
284 1 << 10, 1 << 11, 1 << 12, -EINVAL,
286 return cols[((pvt->info.max_dod >> 9) & 0x3) << 12];
290 /****************************************************************************
291 Memory check routines
292 ****************************************************************************/
293 static int get_dimm_config(struct mem_ctl_info *mci)
295 struct i7core_pvt *pvt = mci->pvt_info;
296 int i;
298 if (!pvt->pci_mcr[0])
299 return -ENODEV;
301 /* Device 3 function 0 reads */
302 pci_read_config_dword(pvt->pci_mcr[0], MC_CONTROL,
303 &pvt->info.mc_control);
304 pci_read_config_dword(pvt->pci_mcr[0], MC_STATUS,
305 &pvt->info.mc_status);
306 pci_read_config_dword(pvt->pci_mcr[0], MC_MAX_DOD,
307 &pvt->info.max_dod);
308 pci_read_config_dword(pvt->pci_mcr[0], MC_CHANNEL_MAPPER,
309 &pvt->info.ch_map);
311 debugf0("MC control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
312 pvt->info.mc_control, pvt->info.mc_status,
313 pvt->info.max_dod, pvt->info.ch_map);
315 if (ECC_ENABLED(pvt))
316 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4);
317 else
318 debugf0("ECC disabled\n");
320 /* FIXME: need to handle the error codes */
321 debugf0("DOD Maximum limits: DIMMS: %d, %d-ranked, %d-banked\n",
322 maxnumdimms(pvt), maxnumrank(pvt), maxnumbank(pvt));
323 debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n",
324 maxnumrow(pvt), maxnumcol(pvt));
326 debugf0("Memory channel configuration:\n");
328 for (i = 0; i < NUM_CHANS; i++) {
329 u32 data;
331 if (!CH_ACTIVE(pvt, i)) {
332 debugf0("Channel %i is not active\n", i);
333 continue;
335 if (CH_DISABLED(pvt, i)) {
336 debugf0("Channel %i is disabled\n", i);
337 continue;
340 /* Devices 4-6 function 0 */
341 pci_read_config_dword(pvt->pci_ch[i][0],
342 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
344 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;
346 if (data & THREE_DIMMS_PRESENT)
347 pvt->channel[i].dimms = 3;
348 else if (data & SINGLE_QUAD_RANK_PRESENT)
349 pvt->channel[i].dimms = 1;
350 else
351 pvt->channel[i].dimms = 2;
353 debugf0("Ch%d (0x%08x): rd ch %d, wr ch %d, "
354 "%d ranks, %d %cDIMMs\n",
355 i, data,
356 RDLCH(pvt->info.ch_map, i),
357 WRLCH(pvt->info.ch_map, i),
358 pvt->channel[i].ranks, pvt->channel[i].dimms,
359 (data & REGISTERED_DIMM)? 'R' : 'U' );
362 return 0;
365 /****************************************************************************
366 Error insertion routines
367 ****************************************************************************/
369 /* The i7core has independent error injection features per channel.
370 However, to have a simpler code, we don't allow enabling error injection
371 on more than one channel.
372 Also, since a change at an inject parameter will be applied only at enable,
373 we're disabling error injection on all write calls to the sysfs nodes that
374 controls the error code injection.
376 static int disable_inject(struct mem_ctl_info *mci)
378 struct i7core_pvt *pvt = mci->pvt_info;
380 pvt->inject.enable = 0;
382 if (!pvt->pci_ch[pvt->inject.channel][0])
383 return -ENODEV;
385 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
386 MC_CHANNEL_ERROR_MASK, 0);
388 return 0;
392 * i7core inject inject.section
394 * accept and store error injection inject.section value
395 * bit 0 - refers to the lower 32-byte half cacheline
396 * bit 1 - refers to the upper 32-byte half cacheline
398 static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
399 const char *data, size_t count)
401 struct i7core_pvt *pvt = mci->pvt_info;
402 unsigned long value;
403 int rc;
405 if (pvt->inject.enable)
406 disable_inject(mci);
408 rc = strict_strtoul(data, 10, &value);
409 if ((rc < 0) || (value > 3))
410 return 0;
412 pvt->inject.section = (u32) value;
413 return count;
416 static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
417 char *data)
419 struct i7core_pvt *pvt = mci->pvt_info;
420 return sprintf(data, "0x%08x\n", pvt->inject.section);
424 * i7core inject.type
426 * accept and store error injection inject.section value
427 * bit 0 - repeat enable - Enable error repetition
428 * bit 1 - inject ECC error
429 * bit 2 - inject parity error
431 static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
432 const char *data, size_t count)
434 struct i7core_pvt *pvt = mci->pvt_info;
435 unsigned long value;
436 int rc;
438 if (pvt->inject.enable)
439 disable_inject(mci);
441 rc = strict_strtoul(data, 10, &value);
442 if ((rc < 0) || (value > 7))
443 return 0;
445 pvt->inject.type = (u32) value;
446 return count;
449 static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
450 char *data)
452 struct i7core_pvt *pvt = mci->pvt_info;
453 return sprintf(data, "0x%08x\n", pvt->inject.type);
457 * i7core_inject_inject.eccmask_store
459 * The type of error (UE/CE) will depend on the inject.eccmask value:
460 * Any bits set to a 1 will flip the corresponding ECC bit
461 * Correctable errors can be injected by flipping 1 bit or the bits within
462 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
463 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
464 * uncorrectable error to be injected.
466 static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
467 const char *data, size_t count)
469 struct i7core_pvt *pvt = mci->pvt_info;
470 unsigned long value;
471 int rc;
473 if (pvt->inject.enable)
474 disable_inject(mci);
476 rc = strict_strtoul(data, 10, &value);
477 if (rc < 0)
478 return 0;
480 pvt->inject.eccmask = (u32) value;
481 return count;
484 static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
485 char *data)
487 struct i7core_pvt *pvt = mci->pvt_info;
488 return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
492 * i7core_addrmatch
494 * The type of error (UE/CE) will depend on the inject.eccmask value:
495 * Any bits set to a 1 will flip the corresponding ECC bit
496 * Correctable errors can be injected by flipping 1 bit or the bits within
497 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
498 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
499 * uncorrectable error to be injected.
501 static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
502 const char *data, size_t count)
504 struct i7core_pvt *pvt = mci->pvt_info;
505 char *cmd, *val;
506 long value;
507 int rc;
509 if (pvt->inject.enable)
510 disable_inject(mci);
512 do {
513 cmd = strsep((char **) &data, ":");
514 if (!cmd)
515 break;
516 val = strsep((char **) &data, " \n\t");
517 if (!val)
518 return cmd - data;
520 if (!strcasecmp(val,"any"))
521 value = -1;
522 else {
523 rc = strict_strtol(val, 10, &value);
524 if ((rc < 0) || (value < 0))
525 return cmd - data;
528 if (!strcasecmp(cmd,"channel")) {
529 if (value < 3)
530 pvt->inject.channel = value;
531 else
532 return cmd - data;
533 } else if (!strcasecmp(cmd,"dimm")) {
534 if (value < 4)
535 pvt->inject.dimm = value;
536 else
537 return cmd - data;
538 } else if (!strcasecmp(cmd,"rank")) {
539 if (value < 4)
540 pvt->inject.rank = value;
541 else
542 return cmd - data;
543 } else if (!strcasecmp(cmd,"bank")) {
544 if (value < 4)
545 pvt->inject.bank = value;
546 else
547 return cmd - data;
548 } else if (!strcasecmp(cmd,"page")) {
549 if (value <= 0xffff)
550 pvt->inject.page = value;
551 else
552 return cmd - data;
553 } else if (!strcasecmp(cmd,"col") ||
554 !strcasecmp(cmd,"column")) {
555 if (value <= 0x3fff)
556 pvt->inject.col = value;
557 else
558 return cmd - data;
560 } while (1);
562 return count;
565 static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
566 char *data)
568 struct i7core_pvt *pvt = mci->pvt_info;
569 char channel[4], dimm[4], bank[4], rank[4], page[7], col[7];
571 if (pvt->inject.channel < 0)
572 sprintf(channel, "any");
573 else
574 sprintf(channel, "%d", pvt->inject.channel);
575 if (pvt->inject.dimm < 0)
576 sprintf(dimm, "any");
577 else
578 sprintf(dimm, "%d", pvt->inject.dimm);
579 if (pvt->inject.bank < 0)
580 sprintf(bank, "any");
581 else
582 sprintf(bank, "%d", pvt->inject.bank);
583 if (pvt->inject.rank < 0)
584 sprintf(rank, "any");
585 else
586 sprintf(rank, "%d", pvt->inject.rank);
587 if (pvt->inject.page < 0)
588 sprintf(page, "any");
589 else
590 sprintf(page, "0x%04x", pvt->inject.page);
591 if (pvt->inject.col < 0)
592 sprintf(col, "any");
593 else
594 sprintf(col, "0x%04x", pvt->inject.col);
596 return sprintf(data, "channel: %s\ndimm: %s\nbank: %s\n"
597 "rank: %s\npage: %s\ncolumn: %s\n",
598 channel, dimm, bank, rank, page, col);
602 * This routine prepares the Memory Controller for error injection.
603 * The error will be injected when some process tries to write to the
604 * memory that matches the given criteria.
605 * The criteria can be set in terms of a mask where dimm, rank, bank, page
606 * and col can be specified.
607 * A -1 value for any of the mask items will make the MCU to ignore
608 * that matching criteria for error injection.
610 * It should be noticed that the error will only happen after a write operation
611 * on a memory that matches the condition. if REPEAT_EN is not enabled at
612 * inject mask, then it will produce just one error. Otherwise, it will repeat
613 * until the injectmask would be cleaned.
615 * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
616 * is reliable enough to check if the MC is using the
617 * three channels. However, this is not clear at the datasheet.
619 static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
620 const char *data, size_t count)
622 struct i7core_pvt *pvt = mci->pvt_info;
623 u32 injectmask;
624 u64 mask = 0;
625 int rc;
626 long enable;
628 if (!pvt->pci_ch[pvt->inject.channel][0])
629 return 0;
631 rc = strict_strtoul(data, 10, &enable);
632 if ((rc < 0))
633 return 0;
635 if (enable) {
636 pvt->inject.enable = 1;
637 } else {
638 disable_inject(mci);
639 return count;
642 /* Sets pvt->inject.dimm mask */
643 if (pvt->inject.dimm < 0)
644 mask |= 1L << 41;
645 else {
646 if (pvt->channel[pvt->inject.channel].dimms > 2)
647 mask |= (pvt->inject.dimm & 0x3L) << 35;
648 else
649 mask |= (pvt->inject.dimm & 0x1L) << 36;
652 /* Sets pvt->inject.rank mask */
653 if (pvt->inject.rank < 0)
654 mask |= 1L << 40;
655 else {
656 if (pvt->channel[pvt->inject.channel].dimms > 2)
657 mask |= (pvt->inject.rank & 0x1L) << 34;
658 else
659 mask |= (pvt->inject.rank & 0x3L) << 34;
662 /* Sets pvt->inject.bank mask */
663 if (pvt->inject.bank < 0)
664 mask |= 1L << 39;
665 else
666 mask |= (pvt->inject.bank & 0x15L) << 30;
668 /* Sets pvt->inject.page mask */
669 if (pvt->inject.page < 0)
670 mask |= 1L << 38;
671 else
672 mask |= (pvt->inject.page & 0xffffL) << 14;
674 /* Sets pvt->inject.column mask */
675 if (pvt->inject.col < 0)
676 mask |= 1L << 37;
677 else
678 mask |= (pvt->inject.col & 0x3fffL);
680 #if USE_QWORD
681 pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0],
682 MC_CHANNEL_ADDR_MATCH, mask);
683 #else
684 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
685 MC_CHANNEL_ADDR_MATCH, mask);
686 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
687 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
688 #endif
690 #if 1
691 #if USE_QWORD
692 u64 rdmask;
693 pci_read_config_qword(pvt->pci_ch[pvt->inject.channel][0],
694 MC_CHANNEL_ADDR_MATCH, &rdmask);
695 debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n",
696 mask, rdmask);
697 #else
698 u32 rdmask1, rdmask2;
700 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
701 MC_CHANNEL_ADDR_MATCH, &rdmask1);
702 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
703 MC_CHANNEL_ADDR_MATCH + 4, &rdmask2);
705 debugf0("Inject addr match write 0x%016llx, read: 0x%08x%08x\n",
706 mask, rdmask1, rdmask2);
707 #endif
708 #endif
710 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
711 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
714 * bit 0: REPEAT_EN
715 * bits 1-2: MASK_HALF_CACHELINE
716 * bit 3: INJECT_ECC
717 * bit 4: INJECT_ADDR_PARITY
720 injectmask = (pvt->inject.type & 1) |
721 (pvt->inject.section & 0x3) << 1 |
722 (pvt->inject.type & 0x6) << (3 - 1);
724 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
725 MC_CHANNEL_ERROR_MASK, injectmask);
727 debugf0("Error inject addr match 0x%016llx, ecc 0x%08x, inject 0x%08x\n",
728 mask, pvt->inject.eccmask, injectmask);
732 return count;
735 static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
736 char *data)
738 struct i7core_pvt *pvt = mci->pvt_info;
739 u32 injectmask;
741 pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
742 MC_CHANNEL_ERROR_MASK, &injectmask);
744 debugf0("Inject error read: 0x%018x\n", injectmask);
746 if (injectmask & 0x0c)
747 pvt->inject.enable = 1;
749 return sprintf(data, "%d\n", pvt->inject.enable);
753 * Sysfs struct
755 static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
758 .attr = {
759 .name = "inject_section",
760 .mode = (S_IRUGO | S_IWUSR)
762 .show = i7core_inject_section_show,
763 .store = i7core_inject_section_store,
764 }, {
765 .attr = {
766 .name = "inject_type",
767 .mode = (S_IRUGO | S_IWUSR)
769 .show = i7core_inject_type_show,
770 .store = i7core_inject_type_store,
771 }, {
772 .attr = {
773 .name = "inject_eccmask",
774 .mode = (S_IRUGO | S_IWUSR)
776 .show = i7core_inject_eccmask_show,
777 .store = i7core_inject_eccmask_store,
778 }, {
779 .attr = {
780 .name = "inject_addrmatch",
781 .mode = (S_IRUGO | S_IWUSR)
783 .show = i7core_inject_addrmatch_show,
784 .store = i7core_inject_addrmatch_store,
785 }, {
786 .attr = {
787 .name = "inject_enable",
788 .mode = (S_IRUGO | S_IWUSR)
790 .show = i7core_inject_enable_show,
791 .store = i7core_inject_enable_store,
795 /****************************************************************************
796 Device initialization routines: put/get, init/exit
797 ****************************************************************************/
800 * i7core_put_devices 'put' all the devices that we have
801 * reserved via 'get'
803 static void i7core_put_devices(void)
805 int i;
807 for (i = 0; i < N_DEVS; i++)
808 pci_dev_put(pci_devs[i].pdev);
812 * i7core_get_devices Find and perform 'get' operation on the MCH's
813 * device/functions we want to reference for this driver
815 * Need to 'get' device 16 func 1 and func 2
817 static int i7core_get_devices(struct mem_ctl_info *mci, struct pci_dev *mcidev)
819 struct i7core_pvt *pvt = mci->pvt_info;
820 int rc, i,func;
821 struct pci_dev *pdev = NULL;
823 pvt = mci->pvt_info;
824 memset(pvt, 0, sizeof(*pvt));
826 for (i = 0; i < N_DEVS; i++) {
827 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
828 pci_devs[i].dev_id, NULL);
829 if (!pdev) {
830 /* End of list, leave */
831 i7core_printk(KERN_ERR,
832 "Device not found: PCI ID %04x:%04x "
833 "(dev %d, func %d)\n",
834 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
835 pci_devs[i].dev,pci_devs[i].func);
836 if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
837 continue; /* Only on chips with RDIMMs */
838 else
839 i7core_put_devices();
841 pci_devs[i].pdev = pdev;
843 rc = pci_enable_device(pdev);
844 if (rc < 0) {
845 i7core_printk(KERN_ERR,
846 "Couldn't enable PCI ID %04x:%04x "
847 "(dev %d, func %d)\n",
848 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
849 pci_devs[i].dev, pci_devs[i].func);
850 i7core_put_devices();
851 return rc;
853 /* Sanity check */
854 if (PCI_FUNC(pdev->devfn) != pci_devs[i].func) {
855 i7core_printk(KERN_ERR,
856 "Device PCI ID %04x:%04x "
857 "has function %d instead of %d\n",
858 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
859 PCI_FUNC(pdev->devfn), pci_devs[i].func);
860 i7core_put_devices();
861 return -EINVAL;
864 i7core_printk(KERN_INFO,
865 "Registered device %0x:%0x fn=%0x %0x\n",
866 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
867 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
869 func = PCI_FUNC(pdev->devfn);
870 if (pci_devs[i].dev < 4) {
871 pvt->pci_mcr[func] = pdev;
872 } else {
873 pvt->pci_ch[pci_devs[i].dev - 4][func] = pdev;
877 i7core_printk(KERN_INFO, "Driver loaded.\n");
879 return 0;
883 * i7core_check_error Retrieve and process errors reported by the
884 * hardware. Called by the Core module.
886 static void i7core_check_error(struct mem_ctl_info *mci)
888 /* FIXME: need a real code here */
892 * i7core_probe Probe for ONE instance of device to see if it is
893 * present.
894 * return:
895 * 0 for FOUND a device
896 * < 0 for error code
898 static int __devinit i7core_probe(struct pci_dev *pdev,
899 const struct pci_device_id *id)
901 struct mem_ctl_info *mci;
902 struct i7core_pvt *pvt;
903 int num_channels;
904 int num_csrows;
905 int num_dimms_per_channel;
906 int dev_idx = id->driver_data;
908 if (dev_idx >= ARRAY_SIZE(i7core_devs))
909 return -EINVAL;
911 num_channels = NUM_CHANS;
913 /* FIXME: FAKE data, since we currently don't now how to get this */
914 num_dimms_per_channel = 4;
915 num_csrows = num_dimms_per_channel;
917 /* allocate a new MC control structure */
918 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
919 if (mci == NULL)
920 return -ENOMEM;
922 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
924 /* 'get' the pci devices we want to reserve for our use */
925 if (i7core_get_devices(mci, pdev))
926 goto fail0;
928 mci->dev = &pdev->dev; /* record ptr to the generic device */
930 pvt = mci->pvt_info;
932 // pvt->system_address = pdev; /* Record this device in our private */
933 // pvt->maxch = num_channels;
934 // pvt->maxdimmperch = num_dimms_per_channel;
936 mci->mc_idx = 0;
937 mci->mtype_cap = MEM_FLAG_FB_DDR2; /* FIXME: it uses DDR3 */
938 mci->edac_ctl_cap = EDAC_FLAG_NONE;
939 mci->edac_cap = EDAC_FLAG_NONE;
940 mci->mod_name = "i7core_edac.c";
941 mci->mod_ver = I7CORE_REVISION;
942 mci->ctl_name = i7core_devs[dev_idx].ctl_name;
943 mci->dev_name = pci_name(pdev);
944 mci->ctl_page_to_phys = NULL;
945 mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
947 /* Set the function pointer to an actual operation function */
948 mci->edac_check = i7core_check_error;
950 /* add this new MC control structure to EDAC's list of MCs */
951 if (edac_mc_add_mc(mci)) {
952 debugf0("MC: " __FILE__
953 ": %s(): failed edac_mc_add_mc()\n", __func__);
954 /* FIXME: perhaps some code should go here that disables error
955 * reporting if we just enabled it
957 goto fail1;
960 /* allocating generic PCI control info */
961 i7core_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
962 if (!i7core_pci) {
963 printk(KERN_WARNING
964 "%s(): Unable to create PCI control\n",
965 __func__);
966 printk(KERN_WARNING
967 "%s(): PCI error report via EDAC not setup\n",
968 __func__);
971 /* Default error mask is any memory */
972 pvt->inject.channel = -1;
973 pvt->inject.dimm = -1;
974 pvt->inject.rank = -1;
975 pvt->inject.bank = -1;
976 pvt->inject.page = -1;
977 pvt->inject.col = -1;
979 /* Get dimm basic config */
980 get_dimm_config(mci);
982 return 0;
984 fail1:
985 i7core_put_devices();
987 fail0:
988 edac_mc_free(mci);
989 return -ENODEV;
993 * i7core_remove destructor for one instance of device
996 static void __devexit i7core_remove(struct pci_dev *pdev)
998 struct mem_ctl_info *mci;
1000 debugf0(__FILE__ ": %s()\n", __func__);
1002 if (i7core_pci)
1003 edac_pci_release_generic_ctl(i7core_pci);
1005 mci = edac_mc_del_mc(&pdev->dev);
1007 if (!mci)
1008 return;
1010 /* retrieve references to resources, and free those resources */
1011 i7core_put_devices();
1013 edac_mc_free(mci);
1016 MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
1019 * i7core_driver pci_driver structure for this module
1022 static struct pci_driver i7core_driver = {
1023 .name = "i7core_edac",
1024 .probe = i7core_probe,
1025 .remove = __devexit_p(i7core_remove),
1026 .id_table = i7core_pci_tbl,
1030 * i7core_init Module entry function
1031 * Try to initialize this module for its devices
1033 static int __init i7core_init(void)
1035 int pci_rc;
1037 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1039 /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1040 opstate_init();
1042 pci_rc = pci_register_driver(&i7core_driver);
1044 return (pci_rc < 0) ? pci_rc : 0;
1048 * i7core_exit() Module exit function
1049 * Unregister the driver
1051 static void __exit i7core_exit(void)
1053 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1054 pci_unregister_driver(&i7core_driver);
1057 module_init(i7core_init);
1058 module_exit(i7core_exit);
1060 MODULE_LICENSE("GPL");
1061 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1062 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
1063 MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
1064 I7CORE_REVISION);
1066 module_param(edac_op_state, int, 0444);
1067 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");