i7core_edac: Add more information about each active dimm
[safe/jmp/linux-2.6] / 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 /*
66  * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
67  * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
68  */
69
70 #define MC_TEST_ERR_RCV1        0x60
71   #define DIMM2_COR_ERR(r)                      ((r) & 0x7fff)
72
73 #define MC_TEST_ERR_RCV0        0x64
74   #define DIMM1_COR_ERR(r)                      (((r) >> 16) & 0x7fff)
75   #define DIMM0_COR_ERR(r)                      ((r) & 0x7fff)
76
77         /* OFFSETS for Devices 4,5 and 6 Function 0 */
78
79 #define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
80   #define THREE_DIMMS_PRESENT           (1 << 24)
81   #define SINGLE_QUAD_RANK_PRESENT      (1 << 23)
82   #define QUAD_RANK_PRESENT             (1 << 22)
83   #define REGISTERED_DIMM               (1 << 15)
84
85 #define MC_CHANNEL_MAPPER       0x60
86   #define RDLCH(r, ch)          ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
87   #define WRLCH(r, ch)          ((((r) >> (ch * 6)) & 0x07) - 1)
88
89 #define MC_CHANNEL_RANK_PRESENT 0x7c
90   #define RANK_PRESENT_MASK             0xffff
91
92 #define MC_CHANNEL_ADDR_MATCH   0xf0
93 #define MC_CHANNEL_ERROR_MASK   0xf8
94 #define MC_CHANNEL_ERROR_INJECT 0xfc
95   #define INJECT_ADDR_PARITY    0x10
96   #define INJECT_ECC            0x08
97   #define MASK_CACHELINE        0x06
98   #define MASK_FULL_CACHELINE   0x06
99   #define MASK_MSB32_CACHELINE  0x04
100   #define MASK_LSB32_CACHELINE  0x02
101   #define NO_MASK_CACHELINE     0x00
102   #define REPEAT_EN             0x01
103
104         /* OFFSETS for Devices 4,5 and 6 Function 1 */
105 #define MC_DOD_CH_DIMM0         0x48
106 #define MC_DOD_CH_DIMM1         0x4c
107 #define MC_DOD_CH_DIMM2         0x50
108   #define RANKOFFSET_MASK       ((1 << 12) | (1 << 11) | (1 << 10))
109   #define RANKOFFSET(x)         ((x & RANKOFFSET_MASK) >> 10)
110   #define DIMM_PRESENT_MASK     (1 << 9)
111   #define DIMM_PRESENT(x)       (((x) & DIMM_PRESENT_MASK) >> 9)
112   #define NUMBANK_MASK          ((1 << 8) | (1 << 7))
113   #define NUMBANK(x)            (((x) & NUMBANK_MASK) >> 7)
114   #define NUMRANK_MASK          ((1 << 6) | (1 << 5))
115   #define NUMRANK(x)            (((x) & NUMRANK_MASK) >> 5)
116   #define NUMROW_MASK           ((1 << 4) | (1 << 3))
117   #define NUMROW(x)             (((x) & NUMROW_MASK) >> 3)
118   #define NUMCOL_MASK           3
119   #define NUMCOL(x)             ((x) & NUMCOL_MASK)
120
121 #define MC_RANK_PRESENT         0x7c
122
123 #define MC_SAG_CH_0     0x80
124 #define MC_SAG_CH_1     0x84
125 #define MC_SAG_CH_2     0x88
126 #define MC_SAG_CH_3     0x8c
127 #define MC_SAG_CH_4     0x90
128 #define MC_SAG_CH_5     0x94
129 #define MC_SAG_CH_6     0x98
130 #define MC_SAG_CH_7     0x9c
131
132 #define MC_RIR_LIMIT_CH_0       0x40
133 #define MC_RIR_LIMIT_CH_1       0x44
134 #define MC_RIR_LIMIT_CH_2       0x48
135 #define MC_RIR_LIMIT_CH_3       0x4C
136 #define MC_RIR_LIMIT_CH_4       0x50
137 #define MC_RIR_LIMIT_CH_5       0x54
138 #define MC_RIR_LIMIT_CH_6       0x58
139 #define MC_RIR_LIMIT_CH_7       0x5C
140 #define MC_RIR_LIMIT_MASK       ((1 << 10) - 1)
141
142 #define MC_RIR_WAY_CH           0x80
143   #define MC_RIR_WAY_OFFSET_MASK        (((1 << 14) - 1) & ~0x7)
144   #define MC_RIR_WAY_RANK_MASK          0x7
145
146 /*
147  * i7core structs
148  */
149
150 #define NUM_CHANS 3
151 #define MAX_DIMMS 3             /* Max DIMMS per channel */
152 #define MAX_MCR_FUNC  4
153 #define MAX_CHAN_FUNC 3
154
155 struct i7core_info {
156         u32     mc_control;
157         u32     mc_status;
158         u32     max_dod;
159         u32     ch_map;
160 };
161
162
163 struct i7core_inject {
164         int     enable;
165
166         u32     section;
167         u32     type;
168         u32     eccmask;
169
170         /* Error address mask */
171         int channel, dimm, rank, bank, page, col;
172 };
173
174 struct i7core_channel {
175         u32             ranks;
176         u32             dimms;
177 };
178
179 struct pci_id_descr {
180         int             dev;
181         int             func;
182         int             dev_id;
183         struct pci_dev  *pdev;
184 };
185
186 struct i7core_pvt {
187         struct pci_dev          *pci_mcr[MAX_MCR_FUNC + 1];
188         struct pci_dev          *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1];
189         struct i7core_info      info;
190         struct i7core_inject    inject;
191         struct i7core_channel   channel[NUM_CHANS];
192         int                     channels; /* Number of active channels */
193
194         int             ce_count_available;
195         unsigned long   ce_count[MAX_DIMMS];    /* ECC corrected errors counts per dimm */
196         int             last_ce_count[MAX_DIMMS];
197
198 };
199
200 /* Device name and register DID (Device ID) */
201 struct i7core_dev_info {
202         const char *ctl_name;   /* name for this device */
203         u16 fsb_mapping_errors; /* DID for the branchmap,control */
204 };
205
206 #define PCI_DESCR(device, function, device_id)  \
207         .dev = (device),                        \
208         .func = (function),                     \
209         .dev_id = (device_id)
210
211 struct pci_id_descr pci_devs[] = {
212                 /* Memory controller */
213         { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR)     },
214         { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD)  },
215         { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS)  }, /* if RDIMM is supported */
216         { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
217
218                 /* Channel 0 */
219         { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
220         { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
221         { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
222         { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC)   },
223
224                 /* Channel 1 */
225         { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
226         { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
227         { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
228         { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC)   },
229
230                 /* Channel 2 */
231         { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
232         { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
233         { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
234         { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC)   },
235 };
236 #define N_DEVS ARRAY_SIZE(pci_devs)
237
238 /*
239  *      pci_device_id   table for which devices we are looking for
240  * This should match the first device at pci_devs table
241  */
242 static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
243         {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR)},
244         {0,}                    /* 0 terminated list. */
245 };
246
247
248 /* Table of devices attributes supported by this driver */
249 static const struct i7core_dev_info i7core_devs[] = {
250         {
251                 .ctl_name = "i7 Core",
252                 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7_MCR,
253         },
254 };
255
256 static struct edac_pci_ctl_info *i7core_pci;
257
258 /****************************************************************************
259                         Anciliary status routines
260  ****************************************************************************/
261
262         /* MC_CONTROL bits */
263 #define CH_ACTIVE(pvt, ch)      ((pvt)->info.mc_control & (1 << (8 + ch)))
264 #define ECCx8(pvt)              ((pvt)->info.mc_control & (1 << 1))
265
266         /* MC_STATUS bits */
267 #define ECC_ENABLED(pvt)        ((pvt)->info.mc_status & (1 << 3))
268 #define CH_DISABLED(pvt, ch)    ((pvt)->info.mc_status & (1 << ch))
269
270         /* MC_MAX_DOD read functions */
271 static inline int maxnumdimms(struct i7core_pvt *pvt)
272 {
273         return (pvt->info.max_dod & 0x3) + 1;
274 }
275
276 static inline int maxnumrank(struct i7core_pvt *pvt)
277 {
278         static int ranks[4] = { 1, 2, 4, -EINVAL };
279
280         return ranks[(pvt->info.max_dod >> 2) & 0x3];
281 }
282
283 static inline int maxnumbank(struct i7core_pvt *pvt)
284 {
285         static int banks[4] = { 4, 8, 16, -EINVAL };
286
287         return banks[(pvt->info.max_dod >> 4) & 0x3];
288 }
289
290 static inline int maxnumrow(struct i7core_pvt *pvt)
291 {
292         static int rows[8] = {
293                 1 << 12, 1 << 13, 1 << 14, 1 << 15,
294                 1 << 16, -EINVAL, -EINVAL, -EINVAL,
295         };
296
297         return rows[((pvt->info.max_dod >> 6) & 0x7)];
298 }
299
300 static inline int maxnumcol(struct i7core_pvt *pvt)
301 {
302         static int cols[8] = {
303                 1 << 10, 1 << 11, 1 << 12, -EINVAL,
304         };
305         return cols[((pvt->info.max_dod >> 9) & 0x3) << 12];
306 }
307
308
309 /****************************************************************************
310                         Memory check routines
311  ****************************************************************************/
312 static int i7core_get_active_channels(int *channels)
313 {
314         struct pci_dev *pdev = NULL;
315         int i;
316         u32 status, control;
317
318         *channels = 0;
319
320         for (i = 0; i < N_DEVS; i++) {
321                 if (!pci_devs[i].pdev)
322                         continue;
323
324                 if (PCI_SLOT(pci_devs[i].pdev->devfn) == 3 &&
325                     PCI_FUNC(pci_devs[i].pdev->devfn) == 0) {
326                         pdev = pci_devs[i].pdev;
327                         break;
328                 }
329         }
330
331         if (!pdev) {
332                 i7core_printk(KERN_ERR, "Couldn't find fn 3.0!!!\n");
333                 return -ENODEV;
334         }
335
336         /* Device 3 function 0 reads */
337         pci_read_config_dword(pdev, MC_STATUS, &status);
338         pci_read_config_dword(pdev, MC_CONTROL, &control);
339
340         for (i = 0; i < NUM_CHANS; i++) {
341                 /* Check if the channel is active */
342                 if (!(control & (1 << (8 + i))))
343                         continue;
344
345                 /* Check if the channel is disabled */
346                 if (status & (1 << i)) {
347                         continue;
348                 }
349
350                 (*channels)++;
351         }
352
353         debugf0("Number of active channels: %d\n", *channels);
354
355         return 0;
356 }
357
358 static int get_dimm_config(struct mem_ctl_info *mci)
359 {
360         struct i7core_pvt *pvt = mci->pvt_info;
361         struct csrow_info *csr;
362         struct pci_dev *pdev = pvt->pci_mcr[0];
363         int i, j, csrow = 0;
364         enum edac_type mode;
365
366         if (!pdev)
367                 return -ENODEV;
368
369         /* Device 3 function 0 reads */
370         pci_read_config_dword(pdev, MC_CONTROL, &pvt->info.mc_control);
371         pci_read_config_dword(pdev, MC_STATUS, &pvt->info.mc_status);
372         pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod);
373         pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map);
374
375         debugf0("MC control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
376                 pvt->info.mc_control, pvt->info.mc_status,
377                 pvt->info.max_dod, pvt->info.ch_map);
378
379         if (ECC_ENABLED(pvt)) {
380                 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4);
381                 if (ECCx8(pvt))
382                         mode = EDAC_S8ECD8ED;
383                 else
384                         mode = EDAC_S4ECD4ED;
385         } else {
386                 debugf0("ECC disabled\n");
387                 mode = EDAC_NONE;
388         }
389
390         /* FIXME: need to handle the error codes */
391         debugf0("DOD Maximum limits: DIMMS: %d, %d-ranked, %d-banked\n",
392                 maxnumdimms(pvt), maxnumrank(pvt), maxnumbank(pvt));
393         debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n",
394                 maxnumrow(pvt), maxnumcol(pvt));
395
396         debugf0("Memory channel configuration:\n");
397
398         for (i = 0; i < NUM_CHANS; i++) {
399                 u32 data, value[8];
400
401                 if (!CH_ACTIVE(pvt, i)) {
402                         debugf0("Channel %i is not active\n", i);
403                         continue;
404                 }
405                 if (CH_DISABLED(pvt, i)) {
406                         debugf0("Channel %i is disabled\n", i);
407                         continue;
408                 }
409
410                 /* Devices 4-6 function 0 */
411                 pci_read_config_dword(pvt->pci_ch[i][0],
412                                 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
413
414                 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;
415
416                 if (data & THREE_DIMMS_PRESENT)
417                         pvt->channel[i].dimms = 3;
418                 else if (data & SINGLE_QUAD_RANK_PRESENT)
419                         pvt->channel[i].dimms = 1;
420                 else
421                         pvt->channel[i].dimms = 2;
422
423                 debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
424                         "%d ranks, %d %cDIMMs, offset = %d\n\t"
425                         "present: %i, numbank: %#x, numrank: %#x, "
426                         "numrow: %#x, numcol: %#x\n",
427                         i,
428                         RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
429                         data,
430                         pvt->channel[i].ranks, pvt->channel[i].dimms,
431                         (data & REGISTERED_DIMM)? 'R' : 'U',
432                         RANKOFFSET(data),
433                         DIMM_PRESENT(data),
434                         NUMBANK(data), NUMRANK(data),
435                         NUMROW(data), NUMCOL(data));
436
437                         pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
438                         pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
439                         pci_read_config_dword(pdev, MC_SAG_CH_2, &value[2]);
440                         pci_read_config_dword(pdev, MC_SAG_CH_3, &value[3]);
441                         pci_read_config_dword(pdev, MC_SAG_CH_4, &value[4]);
442                         pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]);
443                         pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]);
444                         pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]);
445                         printk("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i);
446                         for (j = 0; j < 8; j++)
447                                 printk("\t\t%#x\t%#x\t%#x\n",
448                                         (value[j] >> 27) & 0x1,
449                                         (value[j] >> 24) & 0x7,
450                                         (value[j] && ((1 << 24) - 1)));
451
452                 csr = &mci->csrows[csrow];
453                 csr->first_page = 0;
454                 csr->last_page = 0;
455                 csr->page_mask = 0;
456                 csr->nr_pages = 0;
457                 csr->grain = 0;
458                 csr->csrow_idx = csrow;
459                 csr->dtype = DEV_X8;    /* FIXME: check this */
460
461                 if (data & REGISTERED_DIMM)
462                         csr->mtype = MEM_RDDR3;
463                 else
464                         csr->mtype = MEM_DDR3;
465                 csr->edac_mode = mode;
466
467                 csrow++;
468         }
469
470         return 0;
471 }
472
473 /****************************************************************************
474                         Error insertion routines
475  ****************************************************************************/
476
477 /* The i7core has independent error injection features per channel.
478    However, to have a simpler code, we don't allow enabling error injection
479    on more than one channel.
480    Also, since a change at an inject parameter will be applied only at enable,
481    we're disabling error injection on all write calls to the sysfs nodes that
482    controls the error code injection.
483  */
484 static int disable_inject(struct mem_ctl_info *mci)
485 {
486         struct i7core_pvt *pvt = mci->pvt_info;
487
488         pvt->inject.enable = 0;
489
490         if (!pvt->pci_ch[pvt->inject.channel][0])
491                 return -ENODEV;
492
493         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
494                                 MC_CHANNEL_ERROR_MASK, 0);
495
496         return 0;
497 }
498
499 /*
500  * i7core inject inject.section
501  *
502  *      accept and store error injection inject.section value
503  *      bit 0 - refers to the lower 32-byte half cacheline
504  *      bit 1 - refers to the upper 32-byte half cacheline
505  */
506 static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
507                                            const char *data, size_t count)
508 {
509         struct i7core_pvt *pvt = mci->pvt_info;
510         unsigned long value;
511         int rc;
512
513         if (pvt->inject.enable)
514                  disable_inject(mci);
515
516         rc = strict_strtoul(data, 10, &value);
517         if ((rc < 0) || (value > 3))
518                 return 0;
519
520         pvt->inject.section = (u32) value;
521         return count;
522 }
523
524 static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
525                                               char *data)
526 {
527         struct i7core_pvt *pvt = mci->pvt_info;
528         return sprintf(data, "0x%08x\n", pvt->inject.section);
529 }
530
531 /*
532  * i7core inject.type
533  *
534  *      accept and store error injection inject.section value
535  *      bit 0 - repeat enable - Enable error repetition
536  *      bit 1 - inject ECC error
537  *      bit 2 - inject parity error
538  */
539 static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
540                                         const char *data, size_t count)
541 {
542         struct i7core_pvt *pvt = mci->pvt_info;
543         unsigned long value;
544         int rc;
545
546         if (pvt->inject.enable)
547                  disable_inject(mci);
548
549         rc = strict_strtoul(data, 10, &value);
550         if ((rc < 0) || (value > 7))
551                 return 0;
552
553         pvt->inject.type = (u32) value;
554         return count;
555 }
556
557 static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
558                                               char *data)
559 {
560         struct i7core_pvt *pvt = mci->pvt_info;
561         return sprintf(data, "0x%08x\n", pvt->inject.type);
562 }
563
564 /*
565  * i7core_inject_inject.eccmask_store
566  *
567  * The type of error (UE/CE) will depend on the inject.eccmask value:
568  *   Any bits set to a 1 will flip the corresponding ECC bit
569  *   Correctable errors can be injected by flipping 1 bit or the bits within
570  *   a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
571  *   23:16 and 31:24). Flipping bits in two symbol pairs will cause an
572  *   uncorrectable error to be injected.
573  */
574 static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
575                                         const char *data, size_t count)
576 {
577         struct i7core_pvt *pvt = mci->pvt_info;
578         unsigned long value;
579         int rc;
580
581         if (pvt->inject.enable)
582                  disable_inject(mci);
583
584         rc = strict_strtoul(data, 10, &value);
585         if (rc < 0)
586                 return 0;
587
588         pvt->inject.eccmask = (u32) value;
589         return count;
590 }
591
592 static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
593                                               char *data)
594 {
595         struct i7core_pvt *pvt = mci->pvt_info;
596         return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
597 }
598
599 /*
600  * i7core_addrmatch
601  *
602  * The type of error (UE/CE) will depend on the inject.eccmask value:
603  *   Any bits set to a 1 will flip the corresponding ECC bit
604  *   Correctable errors can be injected by flipping 1 bit or the bits within
605  *   a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
606  *   23:16 and 31:24). Flipping bits in two symbol pairs will cause an
607  *   uncorrectable error to be injected.
608  */
609 static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
610                                         const char *data, size_t count)
611 {
612         struct i7core_pvt *pvt = mci->pvt_info;
613         char *cmd, *val;
614         long value;
615         int rc;
616
617         if (pvt->inject.enable)
618                  disable_inject(mci);
619
620         do {
621                 cmd = strsep((char **) &data, ":");
622                 if (!cmd)
623                         break;
624                 val = strsep((char **) &data, " \n\t");
625                 if (!val)
626                         return cmd - data;
627
628                 if (!strcasecmp(val,"any"))
629                         value = -1;
630                 else {
631                         rc = strict_strtol(val, 10, &value);
632                         if ((rc < 0) || (value < 0))
633                                 return cmd - data;
634                 }
635
636                 if (!strcasecmp(cmd,"channel")) {
637                         if (value < 3)
638                                 pvt->inject.channel = value;
639                         else
640                                 return cmd - data;
641                 } else if (!strcasecmp(cmd,"dimm")) {
642                         if (value < 4)
643                                 pvt->inject.dimm = value;
644                         else
645                                 return cmd - data;
646                 } else if (!strcasecmp(cmd,"rank")) {
647                         if (value < 4)
648                                 pvt->inject.rank = value;
649                         else
650                                 return cmd - data;
651                 } else if (!strcasecmp(cmd,"bank")) {
652                         if (value < 4)
653                                 pvt->inject.bank = value;
654                         else
655                                 return cmd - data;
656                 } else if (!strcasecmp(cmd,"page")) {
657                         if (value <= 0xffff)
658                                 pvt->inject.page = value;
659                         else
660                                 return cmd - data;
661                 } else if (!strcasecmp(cmd,"col") ||
662                            !strcasecmp(cmd,"column")) {
663                         if (value <= 0x3fff)
664                                 pvt->inject.col = value;
665                         else
666                                 return cmd - data;
667                 }
668         } while (1);
669
670         return count;
671 }
672
673 static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
674                                               char *data)
675 {
676         struct i7core_pvt *pvt = mci->pvt_info;
677         char channel[4], dimm[4], bank[4], rank[4], page[7], col[7];
678
679         if (pvt->inject.channel < 0)
680                 sprintf(channel, "any");
681         else
682                 sprintf(channel, "%d", pvt->inject.channel);
683         if (pvt->inject.dimm < 0)
684                 sprintf(dimm, "any");
685         else
686                 sprintf(dimm, "%d", pvt->inject.dimm);
687         if (pvt->inject.bank < 0)
688                 sprintf(bank, "any");
689         else
690                 sprintf(bank, "%d", pvt->inject.bank);
691         if (pvt->inject.rank < 0)
692                 sprintf(rank, "any");
693         else
694                 sprintf(rank, "%d", pvt->inject.rank);
695         if (pvt->inject.page < 0)
696                 sprintf(page, "any");
697         else
698                 sprintf(page, "0x%04x", pvt->inject.page);
699         if (pvt->inject.col < 0)
700                 sprintf(col, "any");
701         else
702                 sprintf(col, "0x%04x", pvt->inject.col);
703
704         return sprintf(data, "channel: %s\ndimm: %s\nbank: %s\n"
705                              "rank: %s\npage: %s\ncolumn: %s\n",
706                        channel, dimm, bank, rank, page, col);
707 }
708
709 /*
710  * This routine prepares the Memory Controller for error injection.
711  * The error will be injected when some process tries to write to the
712  * memory that matches the given criteria.
713  * The criteria can be set in terms of a mask where dimm, rank, bank, page
714  * and col can be specified.
715  * A -1 value for any of the mask items will make the MCU to ignore
716  * that matching criteria for error injection.
717  *
718  * It should be noticed that the error will only happen after a write operation
719  * on a memory that matches the condition. if REPEAT_EN is not enabled at
720  * inject mask, then it will produce just one error. Otherwise, it will repeat
721  * until the injectmask would be cleaned.
722  *
723  * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
724  *    is reliable enough to check if the MC is using the
725  *    three channels. However, this is not clear at the datasheet.
726  */
727 static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
728                                        const char *data, size_t count)
729 {
730         struct i7core_pvt *pvt = mci->pvt_info;
731         u32 injectmask;
732         u64 mask = 0;
733         int  rc;
734         long enable;
735
736         if (!pvt->pci_ch[pvt->inject.channel][0])
737                 return 0;
738
739         rc = strict_strtoul(data, 10, &enable);
740         if ((rc < 0))
741                 return 0;
742
743         if (enable) {
744                 pvt->inject.enable = 1;
745         } else {
746                 disable_inject(mci);
747                 return count;
748         }
749
750         /* Sets pvt->inject.dimm mask */
751         if (pvt->inject.dimm < 0)
752                 mask |= 1L << 41;
753         else {
754                 if (pvt->channel[pvt->inject.channel].dimms > 2)
755                         mask |= (pvt->inject.dimm & 0x3L) << 35;
756                 else
757                         mask |= (pvt->inject.dimm & 0x1L) << 36;
758         }
759
760         /* Sets pvt->inject.rank mask */
761         if (pvt->inject.rank < 0)
762                 mask |= 1L << 40;
763         else {
764                 if (pvt->channel[pvt->inject.channel].dimms > 2)
765                         mask |= (pvt->inject.rank & 0x1L) << 34;
766                 else
767                         mask |= (pvt->inject.rank & 0x3L) << 34;
768         }
769
770         /* Sets pvt->inject.bank mask */
771         if (pvt->inject.bank < 0)
772                 mask |= 1L << 39;
773         else
774                 mask |= (pvt->inject.bank & 0x15L) << 30;
775
776         /* Sets pvt->inject.page mask */
777         if (pvt->inject.page < 0)
778                 mask |= 1L << 38;
779         else
780                 mask |= (pvt->inject.page & 0xffffL) << 14;
781
782         /* Sets pvt->inject.column mask */
783         if (pvt->inject.col < 0)
784                 mask |= 1L << 37;
785         else
786                 mask |= (pvt->inject.col & 0x3fffL);
787
788 #if USE_QWORD
789         pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0],
790                                MC_CHANNEL_ADDR_MATCH, mask);
791 #else
792         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
793                                MC_CHANNEL_ADDR_MATCH, mask);
794         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
795                                MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
796 #endif
797
798 #if 1
799 #if USE_QWORD
800         u64 rdmask;
801         pci_read_config_qword(pvt->pci_ch[pvt->inject.channel][0],
802                                MC_CHANNEL_ADDR_MATCH, &rdmask);
803         debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n",
804                 mask, rdmask);
805 #else
806         u32 rdmask1, rdmask2;
807
808         pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
809                                MC_CHANNEL_ADDR_MATCH, &rdmask1);
810         pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
811                                MC_CHANNEL_ADDR_MATCH + 4, &rdmask2);
812
813         debugf0("Inject addr match write 0x%016llx, read: 0x%08x%08x\n",
814                 mask, rdmask1, rdmask2);
815 #endif
816 #endif
817
818         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
819                                MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
820
821         /*
822          * bit    0: REPEAT_EN
823          * bits 1-2: MASK_HALF_CACHELINE
824          * bit    3: INJECT_ECC
825          * bit    4: INJECT_ADDR_PARITY
826          */
827
828         injectmask = (pvt->inject.type & 1) |
829                      (pvt->inject.section & 0x3) << 1 |
830                      (pvt->inject.type & 0x6) << (3 - 1);
831
832         pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
833                                MC_CHANNEL_ERROR_MASK, injectmask);
834
835         debugf0("Error inject addr match 0x%016llx, ecc 0x%08x, inject 0x%08x\n",
836                 mask, pvt->inject.eccmask, injectmask);
837
838
839
840         return count;
841 }
842
843 static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
844                                         char *data)
845 {
846         struct i7core_pvt *pvt = mci->pvt_info;
847         u32 injectmask;
848
849         pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0],
850                                MC_CHANNEL_ERROR_MASK, &injectmask);
851
852         debugf0("Inject error read: 0x%018x\n", injectmask);
853
854         if (injectmask & 0x0c)
855                 pvt->inject.enable = 1;
856
857         return sprintf(data, "%d\n", pvt->inject.enable);
858 }
859
860 static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
861 {
862         struct i7core_pvt *pvt = mci->pvt_info;
863
864         if (!pvt->ce_count_available)
865                 return sprintf(data, "unavailable\n");
866
867         return sprintf(data, "dimm0: %lu\ndimm1: %lu\ndimm2: %lu\n",
868                         pvt->ce_count[0],
869                         pvt->ce_count[1],
870                         pvt->ce_count[2]);
871 }
872
873 /*
874  * Sysfs struct
875  */
876 static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
877
878         {
879                 .attr = {
880                         .name = "inject_section",
881                         .mode = (S_IRUGO | S_IWUSR)
882                 },
883                 .show  = i7core_inject_section_show,
884                 .store = i7core_inject_section_store,
885         }, {
886                 .attr = {
887                         .name = "inject_type",
888                         .mode = (S_IRUGO | S_IWUSR)
889                 },
890                 .show  = i7core_inject_type_show,
891                 .store = i7core_inject_type_store,
892         }, {
893                 .attr = {
894                         .name = "inject_eccmask",
895                         .mode = (S_IRUGO | S_IWUSR)
896                 },
897                 .show  = i7core_inject_eccmask_show,
898                 .store = i7core_inject_eccmask_store,
899         }, {
900                 .attr = {
901                         .name = "inject_addrmatch",
902                         .mode = (S_IRUGO | S_IWUSR)
903                 },
904                 .show  = i7core_inject_addrmatch_show,
905                 .store = i7core_inject_addrmatch_store,
906         }, {
907                 .attr = {
908                         .name = "inject_enable",
909                         .mode = (S_IRUGO | S_IWUSR)
910                 },
911                 .show  = i7core_inject_enable_show,
912                 .store = i7core_inject_enable_store,
913         }, {
914                 .attr = {
915                         .name = "corrected_error_counts",
916                         .mode = (S_IRUGO | S_IWUSR)
917                 },
918                 .show  = i7core_ce_regs_show,
919                 .store = NULL,
920         },
921 };
922
923 /****************************************************************************
924         Device initialization routines: put/get, init/exit
925  ****************************************************************************/
926
927 /*
928  *      i7core_put_devices      'put' all the devices that we have
929  *                              reserved via 'get'
930  */
931 static void i7core_put_devices(void)
932 {
933         int i;
934
935         for (i = 0; i < N_DEVS; i++)
936                 pci_dev_put(pci_devs[i].pdev);
937 }
938
939 /*
940  *      i7core_get_devices      Find and perform 'get' operation on the MCH's
941  *                      device/functions we want to reference for this driver
942  *
943  *                      Need to 'get' device 16 func 1 and func 2
944  */
945 static int i7core_get_devices(void)
946 {
947         int rc, i;
948         struct pci_dev *pdev = NULL;
949
950         for (i = 0; i < N_DEVS; i++) {
951                 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
952                                         pci_devs[i].dev_id, NULL);
953                 if (likely(pdev))
954                         pci_devs[i].pdev = pdev;
955                 else {
956                         i7core_printk(KERN_ERR,
957                                 "Device not found: PCI ID %04x:%04x "
958                                 "(dev %d, func %d)\n",
959                                 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
960                                 pci_devs[i].dev,pci_devs[i].func);
961
962                         /* Dev 3 function 2 only exists on chips with RDIMMs */
963                         if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
964                                 continue;
965
966                         /* End of list, leave */
967                         rc = -ENODEV;
968                         goto error;
969                 }
970
971                 /* Sanity check */
972                 if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[i].dev ||
973                              PCI_FUNC(pdev->devfn) != pci_devs[i].func)) {
974                         i7core_printk(KERN_ERR,
975                                 "Device PCI ID %04x:%04x "
976                                 "has fn %d.%d instead of fn %d.%d\n",
977                                 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
978                                 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
979                                 pci_devs[i].dev, pci_devs[i].func);
980                         rc = -EINVAL;
981                         goto error;
982                 }
983
984                 /* Be sure that the device is enabled */
985                 rc = pci_enable_device(pdev);
986                 if (unlikely(rc < 0)) {
987                         i7core_printk(KERN_ERR,
988                                 "Couldn't enable PCI ID %04x:%04x "
989                                 "fn %d.%d\n",
990                                 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
991                                 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
992                         goto error;
993                 }
994
995                 i7core_printk(KERN_INFO,
996                                 "Registered device %0x:%0x fn %d.%d\n",
997                                 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
998                                 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
999         }
1000
1001         return 0;
1002
1003 error:
1004         i7core_put_devices();
1005         return -EINVAL;
1006 }
1007
1008 static int mci_bind_devs(struct mem_ctl_info *mci)
1009 {
1010         struct i7core_pvt *pvt = mci->pvt_info;
1011         struct pci_dev *pdev;
1012         int i, func, slot;
1013
1014         for (i = 0; i < N_DEVS; i++) {
1015                 pdev = pci_devs[i].pdev;
1016                 if (!pdev)
1017                         continue;
1018
1019                 func = PCI_FUNC(pdev->devfn);
1020                 slot = PCI_SLOT(pdev->devfn);
1021                 if (slot == 3) {
1022                         if (unlikely(func > MAX_MCR_FUNC))
1023                                 goto error;
1024                         pvt->pci_mcr[func] = pdev;
1025                 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1026                         if (unlikely(func > MAX_CHAN_FUNC))
1027                                 goto error;
1028                         pvt->pci_ch[slot - 4][func] = pdev;
1029                 } else
1030                         goto error;
1031
1032                 debugf0("Associated fn %d.%d, dev = %p\n",
1033                         PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev);
1034         }
1035         return 0;
1036
1037 error:
1038         i7core_printk(KERN_ERR, "Device %d, function %d "
1039                       "is out of the expected range\n",
1040                       slot, func);
1041         return -EINVAL;
1042 }
1043
1044 /****************************************************************************
1045                         Error check routines
1046  ****************************************************************************/
1047
1048 /* This function is based on the device 3 function 4 registers as described on:
1049  * Intel Xeon Processor 5500 Series Datasheet Volume 2
1050  *      http://www.intel.com/Assets/PDF/datasheet/321322.pdf
1051  * also available at:
1052  *      http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
1053  */
1054 static void check_mc_test_err(struct mem_ctl_info *mci)
1055 {
1056         struct i7core_pvt *pvt = mci->pvt_info;
1057         u32 rcv1, rcv0;
1058         int new0, new1, new2;
1059
1060         if (!pvt->pci_mcr[4]) {
1061                 debugf0("%s MCR registers not found\n",__func__);
1062                 return;
1063         }
1064
1065         /* Corrected error reads */
1066         pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, &rcv1);
1067         pci_read_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, &rcv0);
1068
1069         /* Store the new values */
1070         new2 = DIMM2_COR_ERR(rcv1);
1071         new1 = DIMM1_COR_ERR(rcv0);
1072         new0 = DIMM0_COR_ERR(rcv0);
1073
1074         debugf2("%s CE rcv1=0x%08x rcv0=0x%08x, %d %d %d\n",
1075                 (pvt->ce_count_available ? "UPDATE" : "READ"),
1076                 rcv1, rcv0, new0, new1, new2);
1077
1078         /* Updates CE counters if it is not the first time here */
1079         if (pvt->ce_count_available) {
1080                 /* Updates CE counters */
1081                 int add0, add1, add2;
1082
1083                 add2 = new2 - pvt->last_ce_count[2];
1084                 add1 = new1 - pvt->last_ce_count[1];
1085                 add0 = new0 - pvt->last_ce_count[0];
1086
1087                 if (add2 < 0)
1088                         add2 += 0x7fff;
1089                 pvt->ce_count[2] += add2;
1090
1091                 if (add1 < 0)
1092                         add1 += 0x7fff;
1093                 pvt->ce_count[1] += add1;
1094
1095                 if (add0 < 0)
1096                         add0 += 0x7fff;
1097                 pvt->ce_count[0] += add0;
1098         } else
1099                 pvt->ce_count_available = 1;
1100
1101         /* Store the new values */
1102         pvt->last_ce_count[2] = new2;
1103         pvt->last_ce_count[1] = new1;
1104         pvt->last_ce_count[0] = new0;
1105 }
1106
1107 /*
1108  *      i7core_check_error      Retrieve and process errors reported by the
1109  *                              hardware. Called by the Core module.
1110  */
1111 static void i7core_check_error(struct mem_ctl_info *mci)
1112 {
1113         check_mc_test_err(mci);
1114 }
1115
1116 /*
1117  *      i7core_probe    Probe for ONE instance of device to see if it is
1118  *                      present.
1119  *      return:
1120  *              0 for FOUND a device
1121  *              < 0 for error code
1122  */
1123 static int __devinit i7core_probe(struct pci_dev *pdev,
1124                                   const struct pci_device_id *id)
1125 {
1126         struct mem_ctl_info *mci;
1127         struct i7core_pvt *pvt;
1128         int num_channels = 0;
1129         int num_csrows;
1130         int dev_idx = id->driver_data;
1131         int rc;
1132
1133         if (unlikely(dev_idx >= ARRAY_SIZE(i7core_devs)))
1134                 return -EINVAL;
1135
1136         /* get the pci devices we want to reserve for our use */
1137         rc = i7core_get_devices();
1138         if (unlikely(rc < 0))
1139                 return rc;
1140
1141         /* Check the number of active and not disabled channels */
1142         rc = i7core_get_active_channels(&num_channels);
1143         if (unlikely (rc < 0))
1144                 goto fail0;
1145
1146         /* FIXME: we currently don't know the number of csrows */
1147         num_csrows = num_channels;
1148
1149         /* allocate a new MC control structure */
1150         mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
1151         if (unlikely (!mci)) {
1152                 rc = -ENOMEM;
1153                 goto fail0;
1154         }
1155
1156         debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1157
1158         mci->dev = &pdev->dev;  /* record ptr to the generic device */
1159
1160         pvt = mci->pvt_info;
1161         memset(pvt, 0, sizeof(*pvt));
1162
1163         mci->mc_idx = 0;
1164         mci->mtype_cap = MEM_FLAG_DDR3;         /* FIXME: how to handle RDDR3? */
1165         mci->edac_ctl_cap = EDAC_FLAG_NONE;
1166         mci->edac_cap = EDAC_FLAG_NONE;
1167         mci->mod_name = "i7core_edac.c";
1168         mci->mod_ver = I7CORE_REVISION;
1169         mci->ctl_name = i7core_devs[dev_idx].ctl_name;
1170         mci->dev_name = pci_name(pdev);
1171         mci->ctl_page_to_phys = NULL;
1172         mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
1173         /* Set the function pointer to an actual operation function */
1174         mci->edac_check = i7core_check_error;
1175
1176         /* Store pci devices at mci for faster access */
1177         rc = mci_bind_devs(mci);
1178         if (unlikely (rc < 0))
1179                 goto fail1;
1180
1181         /* Get dimm basic config */
1182         get_dimm_config(mci);
1183
1184         /* add this new MC control structure to EDAC's list of MCs */
1185         if (unlikely(edac_mc_add_mc(mci))) {
1186                 debugf0("MC: " __FILE__
1187                         ": %s(): failed edac_mc_add_mc()\n", __func__);
1188                 /* FIXME: perhaps some code should go here that disables error
1189                  * reporting if we just enabled it
1190                  */
1191
1192                 rc = -EINVAL;
1193                 goto fail1;
1194         }
1195
1196         /* allocating generic PCI control info */
1197         i7core_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
1198         if (unlikely (!i7core_pci)) {
1199                 printk(KERN_WARNING
1200                         "%s(): Unable to create PCI control\n",
1201                         __func__);
1202                 printk(KERN_WARNING
1203                         "%s(): PCI error report via EDAC not setup\n",
1204                         __func__);
1205         }
1206
1207         /* Default error mask is any memory */
1208         pvt->inject.channel = 0;
1209         pvt->inject.dimm = -1;
1210         pvt->inject.rank = -1;
1211         pvt->inject.bank = -1;
1212         pvt->inject.page = -1;
1213         pvt->inject.col = -1;
1214
1215         i7core_printk(KERN_INFO, "Driver loaded.\n");
1216
1217         return 0;
1218
1219 fail1:
1220         edac_mc_free(mci);
1221
1222 fail0:
1223         i7core_put_devices();
1224         return rc;
1225 }
1226
1227 /*
1228  *      i7core_remove   destructor for one instance of device
1229  *
1230  */
1231 static void __devexit i7core_remove(struct pci_dev *pdev)
1232 {
1233         struct mem_ctl_info *mci;
1234
1235         debugf0(__FILE__ ": %s()\n", __func__);
1236
1237         if (i7core_pci)
1238                 edac_pci_release_generic_ctl(i7core_pci);
1239
1240         mci = edac_mc_del_mc(&pdev->dev);
1241
1242         if (!mci)
1243                 return;
1244
1245         /* retrieve references to resources, and free those resources */
1246         i7core_put_devices();
1247
1248         edac_mc_free(mci);
1249 }
1250
1251 MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
1252
1253 /*
1254  *      i7core_driver   pci_driver structure for this module
1255  *
1256  */
1257 static struct pci_driver i7core_driver = {
1258         .name     = "i7core_edac",
1259         .probe    = i7core_probe,
1260         .remove   = __devexit_p(i7core_remove),
1261         .id_table = i7core_pci_tbl,
1262 };
1263
1264 /*
1265  *      i7core_init             Module entry function
1266  *                      Try to initialize this module for its devices
1267  */
1268 static int __init i7core_init(void)
1269 {
1270         int pci_rc;
1271
1272         debugf2("MC: " __FILE__ ": %s()\n", __func__);
1273
1274         /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1275         opstate_init();
1276
1277         pci_rc = pci_register_driver(&i7core_driver);
1278
1279         return (pci_rc < 0) ? pci_rc : 0;
1280 }
1281
1282 /*
1283  *      i7core_exit()   Module exit function
1284  *                      Unregister the driver
1285  */
1286 static void __exit i7core_exit(void)
1287 {
1288         debugf2("MC: " __FILE__ ": %s()\n", __func__);
1289         pci_unregister_driver(&i7core_driver);
1290 }
1291
1292 module_init(i7core_init);
1293 module_exit(i7core_exit);
1294
1295 MODULE_LICENSE("GPL");
1296 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1297 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
1298 MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
1299                    I7CORE_REVISION);
1300
1301 module_param(edac_op_state, int, 0444);
1302 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");