i7core_edac: need mci->edac_check, otherwise module removal doesn't work
[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_check_error      Retrieve and process errors reported by the
884  *                              hardware. Called by the Core module.
885  */
886 static void i7core_check_error(struct mem_ctl_info *mci)
887 {
888         /* FIXME: need a real code here */
889 }
890
891 /*
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
897  */
898 static int __devinit i7core_probe(struct pci_dev *pdev,
899                                   const struct pci_device_id *id)
900 {
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;
907
908         if (dev_idx >= ARRAY_SIZE(i7core_devs))
909                 return -EINVAL;
910
911         num_channels = NUM_CHANS;
912
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;
916
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;
921
922         debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
923
924         /* 'get' the pci devices we want to reserve for our use */
925         if (i7core_get_devices(mci, pdev))
926                 goto fail0;
927
928         mci->dev = &pdev->dev;  /* record ptr to the generic device */
929
930         pvt = mci->pvt_info;
931
932 //      pvt->system_address = pdev;     /* Record this device in our private */
933 //      pvt->maxch = num_channels;
934 //      pvt->maxdimmperch = num_dimms_per_channel;
935
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;
946
947         /* Set the function pointer to an actual operation function */
948         mci->edac_check = i7core_check_error;
949
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
956                  */
957                 goto fail1;
958         }
959
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__);
969         }
970
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;
978
979         /* Get dimm basic config */
980         get_dimm_config(mci);
981
982         return 0;
983
984 fail1:
985         i7core_put_devices();
986
987 fail0:
988         edac_mc_free(mci);
989         return -ENODEV;
990 }
991
992 /*
993  *      i7core_remove   destructor for one instance of device
994  *
995  */
996 static void __devexit i7core_remove(struct pci_dev *pdev)
997 {
998         struct mem_ctl_info *mci;
999
1000         debugf0(__FILE__ ": %s()\n", __func__);
1001
1002         if (i7core_pci)
1003                 edac_pci_release_generic_ctl(i7core_pci);
1004
1005         mci = edac_mc_del_mc(&pdev->dev);
1006
1007         if (!mci)
1008                 return;
1009
1010         /* retrieve references to resources, and free those resources */
1011         i7core_put_devices();
1012
1013         edac_mc_free(mci);
1014 }
1015
1016 MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
1017
1018 /*
1019  *      i7core_driver   pci_driver structure for this module
1020  *
1021  */
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,
1027 };
1028
1029 /*
1030  *      i7core_init             Module entry function
1031  *                      Try to initialize this module for its devices
1032  */
1033 static int __init i7core_init(void)
1034 {
1035         int pci_rc;
1036
1037         debugf2("MC: " __FILE__ ": %s()\n", __func__);
1038
1039         /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1040         opstate_init();
1041
1042         pci_rc = pci_register_driver(&i7core_driver);
1043
1044         return (pci_rc < 0) ? pci_rc : 0;
1045 }
1046
1047 /*
1048  *      i7core_exit()   Module exit function
1049  *                      Unregister the driver
1050  */
1051 static void __exit i7core_exit(void)
1052 {
1053         debugf2("MC: " __FILE__ ": %s()\n", __func__);
1054         pci_unregister_driver(&i7core_driver);
1055 }
1056
1057 module_init(i7core_init);
1058 module_exit(i7core_exit);
1059
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);
1065
1066 module_param(edac_op_state, int, 0444);
1067 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");