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