i7core_edac: A few fixes at error injection code
[pandora-kernel.git] / drivers / edac / i7core_edac.c
1 /* Intel 7 core  Memory Controller kernel module (Nehalem)
2  *
3  * This file may be distributed under the terms of the
4  * GNU General Public License version 2 only.
5  *
6  * Copyright (c) 2009 by:
7  *       Mauro Carvalho Chehab <mchehab@redhat.com>
8  *
9  * Red Hat Inc. http://www.redhat.com
10  *
11  * Forked and adapted from the i5400_edac driver
12  *
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
21  */
22
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>
30
31 #include "edac_core.h"
32
33 /* To use the new pci_[read/write]_config_qword instead of two dword */
34 #define USE_QWORD 1
35
36 /*
37  * Alter this version for the module when modifications are made
38  */
39 #define I7CORE_REVISION    " Ver: 1.0.0 " __DATE__
40 #define EDAC_MOD_STR      "i7core_edac"
41
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)
45
46 /*
47  * Debug macros
48  */
49 #define i7core_printk(level, fmt, arg...)                       \
50         edac_printk(level, "i7core", fmt, ##arg)
51
52 #define i7core_mc_printk(mci, level, fmt, arg...)               \
53         edac_mc_chipset_printk(mci, level, "i7core", fmt, ##arg)
54
55 /*
56  * i7core Memory Controller Registers
57  */
58
59         /* OFFSETS for Device 3 Function 0 */
60
61 #define MC_CONTROL      0x48
62 #define MC_STATUS       0x4c
63 #define MC_MAX_DOD      0x64
64
65         /* OFFSETS for Devices 4,5 and 6 Function 0 */
66
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)
72
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)
76
77 #define MC_CHANNEL_RANK_PRESENT 0x7c
78   #define RANK_PRESENT_MASK             0xffff
79
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
91
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)
108
109 #define MC_RANK_PRESENT         0x7c
110
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
119
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)
129
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
133
134 /*
135  * i7core structs
136  */
137
138 #define NUM_CHANS 3
139 #define NUM_MCR_FUNCS  4
140 #define NUM_CHAN_FUNCS 3
141
142 struct i7core_info {
143         u32     mc_control;
144         u32     mc_status;
145         u32     max_dod;
146         u32     ch_map;
147 };
148
149
150 struct i7core_inject {
151         int     enable;
152
153         u32     section;
154         u32     type;
155         u32     eccmask;
156
157         /* Error address mask */
158         int channel, dimm, rank, bank, page, col;
159 };
160
161 struct i7core_channel {
162         u32 ranks;
163         u32 dimms;
164 };
165
166 struct pci_id_descr {
167         int             dev;
168         int             func;
169         int             dev_id;
170         struct pci_dev  *pdev;
171 };
172
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];
179 };
180
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 */
185 };
186
187 #define PCI_DESCR(device, function, device_id)  \
188         .dev = (device),                        \
189         .func = (function),                     \
190         .dev_id = (device_id)
191
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) },
198
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)   },
204
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)   },
210
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)   },
216 };
217 #define N_DEVS ARRAY_SIZE(pci_devs)
218
219 /*
220  *      pci_device_id   table for which devices we are looking for
221  * This should match the first device at pci_devs table
222  */
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. */
226 };
227
228
229 /* Table of devices attributes supported by this driver */
230 static const struct i7core_dev_info i7core_devs[] = {
231         {
232                 .ctl_name = "i7 Core",
233                 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7_MCR,
234         },
235 };
236
237 static struct edac_pci_ctl_info *i7core_pci;
238
239 /****************************************************************************
240                         Anciliary status routines
241  ****************************************************************************/
242
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)
246
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)
250
251         /* MC_MAX_DOD read functions */
252 static inline int maxnumdimms(struct i7core_pvt *pvt)
253 {
254         return (pvt->info.max_dod & 0x3) + 1;
255 }
256
257 static inline int maxnumrank(struct i7core_pvt *pvt)
258 {
259         static int ranks[4] = { 1, 2, 4, -EINVAL };
260
261         return ranks[(pvt->info.max_dod >> 2) & 0x3];
262 }
263
264 static inline int maxnumbank(struct i7core_pvt *pvt)
265 {
266         static int banks[4] = { 4, 8, 16, -EINVAL };
267
268         return banks[(pvt->info.max_dod >> 4) & 0x3];
269 }
270
271 static inline int maxnumrow(struct i7core_pvt *pvt)
272 {
273         static int rows[8] = {
274                 1 << 12, 1 << 13, 1 << 14, 1 << 15,
275                 1 << 16, -EINVAL, -EINVAL, -EINVAL,
276         };
277
278         return rows[((pvt->info.max_dod >> 6) & 0x7)];
279 }
280
281 static inline int maxnumcol(struct i7core_pvt *pvt)
282 {
283         static int cols[8] = {
284                 1 << 10, 1 << 11, 1 << 12, -EINVAL,
285         };
286         return cols[((pvt->info.max_dod >> 9) & 0x3) << 12];
287 }
288
289
290 /****************************************************************************
291                         Memory check routines
292  ****************************************************************************/
293 static int get_dimm_config(struct mem_ctl_info *mci)
294 {
295         struct i7core_pvt *pvt = mci->pvt_info;
296         int i;
297
298         if (!pvt->pci_mcr[0])
299                 return -ENODEV;
300
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);
310
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);
314
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");
319
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));
325
326         debugf0("Memory channel configuration:\n");
327
328         for (i = 0; i < NUM_CHANS; i++) {
329                 u32 data;
330
331                 if (!CH_ACTIVE(pvt, i)) {
332                         debugf0("Channel %i is not active\n", i);
333                         continue;
334                 }
335                 if (CH_DISABLED(pvt, i)) {
336                         debugf0("Channel %i is disabled\n", i);
337                         continue;
338                 }
339
340                 /* Devices 4-6 function 0 */
341                 pci_read_config_dword(pvt->pci_ch[i][0],
342                                 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
343
344                 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;
345
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;
352
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' );
360         }
361
362         return 0;
363 }
364
365 /****************************************************************************
366                         Error insertion routines
367  ****************************************************************************/
368
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.
375  */
376 static int disable_inject(struct mem_ctl_info *mci)
377 {
378         struct i7core_pvt *pvt = mci->pvt_info;
379
380         pvt->inject.enable = 0;
381
382         if (!pvt->pci_ch[pvt->inject.channel][0])
383                 return -ENODEV;
384
385         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
386                                 MC_CHANNEL_ERROR_MASK, 0);
387
388         return 0;
389 }
390
391 /*
392  * i7core inject inject.section
393  *
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
397  */
398 static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
399                                            const char *data, size_t count)
400 {
401         struct i7core_pvt *pvt = mci->pvt_info;
402         unsigned long value;
403         int rc;
404
405         if (pvt->inject.enable)
406                  disable_inject(mci);
407
408         rc = strict_strtoul(data, 10, &value);
409         if ((rc < 0) || (value > 3))
410                 return 0;
411
412         pvt->inject.section = (u32) value;
413         return count;
414 }
415
416 static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
417                                               char *data)
418 {
419         struct i7core_pvt *pvt = mci->pvt_info;
420         return sprintf(data, "0x%08x\n", pvt->inject.section);
421 }
422
423 /*
424  * i7core inject.type
425  *
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
430  */
431 static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
432                                         const char *data, size_t count)
433 {
434         struct i7core_pvt *pvt = mci->pvt_info;
435         unsigned long value;
436         int rc;
437
438         if (pvt->inject.enable)
439                  disable_inject(mci);
440
441         rc = strict_strtoul(data, 10, &value);
442         if ((rc < 0) || (value > 7))
443                 return 0;
444
445         pvt->inject.type = (u32) value;
446         return count;
447 }
448
449 static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
450                                               char *data)
451 {
452         struct i7core_pvt *pvt = mci->pvt_info;
453         return sprintf(data, "0x%08x\n", pvt->inject.type);
454 }
455
456 /*
457  * i7core_inject_inject.eccmask_store
458  *
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.
465  */
466 static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
467                                         const char *data, size_t count)
468 {
469         struct i7core_pvt *pvt = mci->pvt_info;
470         unsigned long value;
471         int rc;
472
473         if (pvt->inject.enable)
474                  disable_inject(mci);
475
476         rc = strict_strtoul(data, 10, &value);
477         if (rc < 0)
478                 return 0;
479
480         pvt->inject.eccmask = (u32) value;
481         return count;
482 }
483
484 static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
485                                               char *data)
486 {
487         struct i7core_pvt *pvt = mci->pvt_info;
488         return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
489 }
490
491 /*
492  * i7core_addrmatch
493  *
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.
500  */
501 static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
502                                         const char *data, size_t count)
503 {
504         struct i7core_pvt *pvt = mci->pvt_info;
505         char *cmd, *val;
506         long value;
507         int rc;
508
509         if (pvt->inject.enable)
510                  disable_inject(mci);
511
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;
519
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;
526                 }
527
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;
559                 }
560         } while (1);
561
562         return count;
563 }
564
565 static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
566                                               char *data)
567 {
568         struct i7core_pvt *pvt = mci->pvt_info;
569         char channel[4], dimm[4], bank[4], rank[4], page[7], col[7];
570
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);
595
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);
599 }
600
601 /*
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.
609  *
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.
614  *
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.
618  */
619 static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
620                                        const char *data, size_t count)
621 {
622         struct i7core_pvt *pvt = mci->pvt_info;
623         u32 injectmask;
624         u64 mask = 0;
625         int  rc;
626         long enable;
627
628         if (!pvt->pci_ch[pvt->inject.channel][0])
629                 return 0;
630
631         rc = strict_strtoul(data, 10, &enable);
632         if ((rc < 0))
633                 return 0;
634
635         if (enable) {
636                 pvt->inject.enable = 1;
637         } else {
638                 disable_inject(mci);
639                 return count;
640         }
641
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;
650         }
651
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;
660         }
661
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;
667
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;
673
674         /* Sets pvt->inject.column mask */
675         if (pvt->inject.col < 0)
676                 mask |= 1L << 37;
677         else
678                 mask |= (pvt->inject.col & 0x3fffL);
679
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
689
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;
699
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);
704
705         debugf0("Inject addr match write 0x%016llx, read: 0x%08x%08x\n",
706                 mask, rdmask1, rdmask2);
707 #endif
708 #endif
709
710         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
711                                MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
712
713         /*
714          * bit    0: REPEAT_EN
715          * bits 1-2: MASK_HALF_CACHELINE
716          * bit    3: INJECT_ECC
717          * bit    4: INJECT_ADDR_PARITY
718          */
719
720         injectmask = (pvt->inject.type & 1) |
721                      (pvt->inject.section & 0x3) << 1 |
722                      (pvt->inject.type & 0x6) << (3 - 1);
723
724         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
725                                MC_CHANNEL_ERROR_MASK, injectmask);
726
727         debugf0("Error inject addr match 0x%016llx, ecc 0x%08x, inject 0x%08x\n",
728                 mask, pvt->inject.eccmask, injectmask);
729
730
731
732         return count;
733 }
734
735 static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
736                                         char *data)
737 {
738         struct i7core_pvt *pvt = mci->pvt_info;
739         u32 injectmask;
740
741         pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
742                                MC_CHANNEL_ERROR_MASK, &injectmask);
743
744         debugf0("Inject error read: 0x%018x\n", injectmask);
745
746         if (injectmask & 0x0c)
747                 pvt->inject.enable = 1;
748
749         return sprintf(data, "%d\n", pvt->inject.enable);
750 }
751
752 /*
753  * Sysfs struct
754  */
755 static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
756
757         {
758                 .attr = {
759                         .name = "inject_section",
760                         .mode = (S_IRUGO | S_IWUSR)
761                 },
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)
768                 },
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)
775                 },
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)
782                 },
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)
789                 },
790                 .show  = i7core_inject_enable_show,
791                 .store = i7core_inject_enable_store,
792         },
793 };
794
795 /****************************************************************************
796         Device initialization routines: put/get, init/exit
797  ****************************************************************************/
798
799 /*
800  *      i7core_put_devices      'put' all the devices that we have
801  *                              reserved via 'get'
802  */
803 static void i7core_put_devices(void)
804 {
805         int i;
806
807         for (i = 0; i < N_DEVS; i++)
808                 pci_dev_put(pci_devs[i].pdev);
809 }
810
811 /*
812  *      i7core_get_devices      Find and perform 'get' operation on the MCH's
813  *                      device/functions we want to reference for this driver
814  *
815  *                      Need to 'get' device 16 func 1 and func 2
816  */
817 static int i7core_get_devices(struct mem_ctl_info *mci, struct pci_dev *mcidev)
818 {
819         struct i7core_pvt *pvt = mci->pvt_info;
820         int rc, i,func;
821         struct pci_dev *pdev = NULL;
822
823         pvt = mci->pvt_info;
824         memset(pvt, 0, sizeof(*pvt));
825
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();
840                 }
841                 pci_devs[i].pdev = pdev;
842
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;
852                 }
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;
862                 }
863
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));
868
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;
874                 }
875         }
876
877         i7core_printk(KERN_INFO, "Driver loaded.\n");
878
879         return 0;
880 }
881
882 /*
883  *      i7core_probe    Probe for ONE instance of device to see if it is
884  *                      present.
885  *      return:
886  *              0 for FOUND a device
887  *              < 0 for error code
888  */
889 static int __devinit i7core_probe(struct pci_dev *pdev,
890                                   const struct pci_device_id *id)
891 {
892         struct mem_ctl_info *mci;
893         struct i7core_pvt *pvt;
894         int num_channels;
895         int num_csrows;
896         int num_dimms_per_channel;
897         int dev_idx = id->driver_data;
898
899         if (dev_idx >= ARRAY_SIZE(i7core_devs))
900                 return -EINVAL;
901
902         num_channels = NUM_CHANS;
903
904         /* FIXME: FAKE data, since we currently don't now how to get this */
905         num_dimms_per_channel = 4;
906         num_csrows = num_dimms_per_channel;
907
908         /* allocate a new MC control structure */
909         mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
910         if (mci == NULL)
911                 return -ENOMEM;
912
913         debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
914
915         mci->dev = &pdev->dev;  /* record ptr to the generic device */
916         dev_set_drvdata(mci->dev, mci);
917
918         pvt = mci->pvt_info;
919
920 //      pvt->system_address = pdev;     /* Record this device in our private */
921 //      pvt->maxch = num_channels;
922 //      pvt->maxdimmperch = num_dimms_per_channel;
923
924         mci->mc_idx = 0;
925         mci->mtype_cap = MEM_FLAG_FB_DDR2;      /* FIXME: it uses DDR3 */
926         mci->edac_ctl_cap = EDAC_FLAG_NONE;
927         mci->edac_cap = EDAC_FLAG_NONE;
928         mci->mod_name = "i7core_edac.c";
929         mci->mod_ver = I7CORE_REVISION;
930         mci->ctl_name = i7core_devs[dev_idx].ctl_name;
931         mci->dev_name = pci_name(pdev);
932         mci->ctl_page_to_phys = NULL;
933         mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
934
935         /* 'get' the pci devices we want to reserve for our use */
936         if (i7core_get_devices(mci, pdev))
937                 goto fail0;
938
939         /* add this new MC control structure to EDAC's list of MCs */
940         if (edac_mc_add_mc(mci)) {
941                 debugf0("MC: " __FILE__
942                         ": %s(): failed edac_mc_add_mc()\n", __func__);
943                 /* FIXME: perhaps some code should go here that disables error
944                  * reporting if we just enabled it
945                  */
946                 goto fail1;
947         }
948
949         /* allocating generic PCI control info */
950         i7core_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
951         if (!i7core_pci) {
952                 printk(KERN_WARNING
953                         "%s(): Unable to create PCI control\n",
954                         __func__);
955                 printk(KERN_WARNING
956                         "%s(): PCI error report via EDAC not setup\n",
957                         __func__);
958         }
959
960         /* Default error mask is any memory */
961         pvt->inject.channel = -1;
962         pvt->inject.dimm = -1;
963         pvt->inject.rank = -1;
964         pvt->inject.bank = -1;
965         pvt->inject.page = -1;
966         pvt->inject.col = -1;
967
968         /* Get dimm basic config */
969         get_dimm_config(mci);
970
971         return 0;
972
973 fail1:
974         i7core_put_devices();
975
976 fail0:
977         edac_mc_free(mci);
978         return -ENODEV;
979 }
980
981 /*
982  *      i7core_remove   destructor for one instance of device
983  *
984  */
985 static void __devexit i7core_remove(struct pci_dev *pdev)
986 {
987         struct mem_ctl_info *mci;
988
989         debugf0(__FILE__ ": %s()\n", __func__);
990
991         if (i7core_pci)
992                 edac_pci_release_generic_ctl(i7core_pci);
993
994         mci = edac_mc_del_mc(&pdev->dev);
995         if (!mci)
996                 return;
997
998         /* retrieve references to resources, and free those resources */
999         i7core_put_devices();
1000
1001         edac_mc_free(mci);
1002 }
1003
1004 MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
1005
1006 /*
1007  *      i7core_driver   pci_driver structure for this module
1008  *
1009  */
1010 static struct pci_driver i7core_driver = {
1011         .name     = "i7core_edac",
1012         .probe    = i7core_probe,
1013         .remove   = __devexit_p(i7core_remove),
1014         .id_table = i7core_pci_tbl,
1015 };
1016
1017 /*
1018  *      i7core_init             Module entry function
1019  *                      Try to initialize this module for its devices
1020  */
1021 static int __init i7core_init(void)
1022 {
1023         int pci_rc;
1024
1025         debugf2("MC: " __FILE__ ": %s()\n", __func__);
1026
1027         /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1028         opstate_init();
1029
1030         pci_rc = pci_register_driver(&i7core_driver);
1031
1032         return (pci_rc < 0) ? pci_rc : 0;
1033 }
1034
1035 /*
1036  *      i7core_exit()   Module exit function
1037  *                      Unregister the driver
1038  */
1039 static void __exit i7core_exit(void)
1040 {
1041         debugf2("MC: " __FILE__ ": %s()\n", __func__);
1042         pci_unregister_driver(&i7core_driver);
1043 }
1044
1045 module_init(i7core_init);
1046 module_exit(i7core_exit);
1047
1048 MODULE_LICENSE("GPL");
1049 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1050 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
1051 MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
1052                    I7CORE_REVISION);
1053
1054 module_param(edac_op_state, int, 0444);
1055 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");