]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/edac/i7core_edac.c
i7core: check if the memory error is fatal or non-fatal
[net-next-2.6.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>
d5381642
MCC
30#include <linux/edac_mce.h>
31#include <linux/spinlock.h>
a0c36a1f
MCC
32
33#include "edac_core.h"
34
7b029d03 35/* To use the new pci_[read/write]_config_qword instead of two dword */
e9bd2e73 36#define USE_QWORD 0
a0c36a1f
MCC
37
38/*
39 * Alter this version for the module when modifications are made
40 */
41#define I7CORE_REVISION " Ver: 1.0.0 " __DATE__
42#define EDAC_MOD_STR "i7core_edac"
43
44/* HACK: temporary, just to enable all logs, for now */
45#undef debugf0
46#define debugf0(fmt, arg...) edac_printk(KERN_INFO, "i7core", fmt, ##arg)
47
48/*
49 * Debug macros
50 */
51#define i7core_printk(level, fmt, arg...) \
52 edac_printk(level, "i7core", fmt, ##arg)
53
54#define i7core_mc_printk(mci, level, fmt, arg...) \
55 edac_mc_chipset_printk(mci, level, "i7core", fmt, ##arg)
56
57/*
58 * i7core Memory Controller Registers
59 */
60
e9bd2e73
MCC
61 /* OFFSETS for Device 0 Function 0 */
62
63#define MC_CFG_CONTROL 0x90
64
a0c36a1f
MCC
65 /* OFFSETS for Device 3 Function 0 */
66
67#define MC_CONTROL 0x48
68#define MC_STATUS 0x4c
69#define MC_MAX_DOD 0x64
70
442305b1
MCC
71/*
72 * OFFSETS for Device 3 Function 4, as inicated on Xeon 5500 datasheet:
73 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
74 */
75
76#define MC_TEST_ERR_RCV1 0x60
77 #define DIMM2_COR_ERR(r) ((r) & 0x7fff)
78
79#define MC_TEST_ERR_RCV0 0x64
80 #define DIMM1_COR_ERR(r) (((r) >> 16) & 0x7fff)
81 #define DIMM0_COR_ERR(r) ((r) & 0x7fff)
82
a0c36a1f
MCC
83 /* OFFSETS for Devices 4,5 and 6 Function 0 */
84
0b2b7b7e
MCC
85#define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
86 #define THREE_DIMMS_PRESENT (1 << 24)
87 #define SINGLE_QUAD_RANK_PRESENT (1 << 23)
88 #define QUAD_RANK_PRESENT (1 << 22)
89 #define REGISTERED_DIMM (1 << 15)
90
f122a892
MCC
91#define MC_CHANNEL_MAPPER 0x60
92 #define RDLCH(r, ch) ((((r) >> (3 + (ch * 6))) & 0x07) - 1)
93 #define WRLCH(r, ch) ((((r) >> (ch * 6)) & 0x07) - 1)
94
0b2b7b7e
MCC
95#define MC_CHANNEL_RANK_PRESENT 0x7c
96 #define RANK_PRESENT_MASK 0xffff
97
a0c36a1f 98#define MC_CHANNEL_ADDR_MATCH 0xf0
194a40fe
MCC
99#define MC_CHANNEL_ERROR_MASK 0xf8
100#define MC_CHANNEL_ERROR_INJECT 0xfc
101 #define INJECT_ADDR_PARITY 0x10
102 #define INJECT_ECC 0x08
103 #define MASK_CACHELINE 0x06
104 #define MASK_FULL_CACHELINE 0x06
105 #define MASK_MSB32_CACHELINE 0x04
106 #define MASK_LSB32_CACHELINE 0x02
107 #define NO_MASK_CACHELINE 0x00
108 #define REPEAT_EN 0x01
a0c36a1f 109
0b2b7b7e
MCC
110 /* OFFSETS for Devices 4,5 and 6 Function 1 */
111#define MC_DOD_CH_DIMM0 0x48
112#define MC_DOD_CH_DIMM1 0x4c
113#define MC_DOD_CH_DIMM2 0x50
114 #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10))
115 #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10)
116 #define DIMM_PRESENT_MASK (1 << 9)
117 #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9)
854d3349
MCC
118 #define MC_DOD_NUMBANK_MASK ((1 << 8) | (1 << 7))
119 #define MC_DOD_NUMBANK(x) (((x) & MC_DOD_NUMBANK_MASK) >> 7)
120 #define MC_DOD_NUMRANK_MASK ((1 << 6) | (1 << 5))
121 #define MC_DOD_NUMRANK(x) (((x) & MC_DOD_NUMRANK_MASK) >> 5)
41fcb7fe 122 #define MC_DOD_NUMROW_MASK ((1 << 4) | (1 << 3) | (1 << 2))
5566cb7c 123 #define MC_DOD_NUMROW(x) (((x) & MC_DOD_NUMROW_MASK) >> 2)
854d3349
MCC
124 #define MC_DOD_NUMCOL_MASK 3
125 #define MC_DOD_NUMCOL(x) ((x) & MC_DOD_NUMCOL_MASK)
0b2b7b7e 126
f122a892
MCC
127#define MC_RANK_PRESENT 0x7c
128
0b2b7b7e
MCC
129#define MC_SAG_CH_0 0x80
130#define MC_SAG_CH_1 0x84
131#define MC_SAG_CH_2 0x88
132#define MC_SAG_CH_3 0x8c
133#define MC_SAG_CH_4 0x90
134#define MC_SAG_CH_5 0x94
135#define MC_SAG_CH_6 0x98
136#define MC_SAG_CH_7 0x9c
137
138#define MC_RIR_LIMIT_CH_0 0x40
139#define MC_RIR_LIMIT_CH_1 0x44
140#define MC_RIR_LIMIT_CH_2 0x48
141#define MC_RIR_LIMIT_CH_3 0x4C
142#define MC_RIR_LIMIT_CH_4 0x50
143#define MC_RIR_LIMIT_CH_5 0x54
144#define MC_RIR_LIMIT_CH_6 0x58
145#define MC_RIR_LIMIT_CH_7 0x5C
146#define MC_RIR_LIMIT_MASK ((1 << 10) - 1)
147
148#define MC_RIR_WAY_CH 0x80
149 #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7)
150 #define MC_RIR_WAY_RANK_MASK 0x7
151
a0c36a1f
MCC
152/*
153 * i7core structs
154 */
155
156#define NUM_CHANS 3
442305b1 157#define MAX_DIMMS 3 /* Max DIMMS per channel */
67166af4 158#define NUM_SOCKETS 2 /* Max number of MC sockets */
442305b1
MCC
159#define MAX_MCR_FUNC 4
160#define MAX_CHAN_FUNC 3
a0c36a1f
MCC
161
162struct i7core_info {
163 u32 mc_control;
164 u32 mc_status;
165 u32 max_dod;
f122a892 166 u32 ch_map;
a0c36a1f
MCC
167};
168
194a40fe
MCC
169
170struct i7core_inject {
171 int enable;
172
67166af4 173 u8 socket;
194a40fe
MCC
174 u32 section;
175 u32 type;
176 u32 eccmask;
177
178 /* Error address mask */
179 int channel, dimm, rank, bank, page, col;
180};
181
0b2b7b7e 182struct i7core_channel {
442305b1
MCC
183 u32 ranks;
184 u32 dimms;
0b2b7b7e
MCC
185};
186
8f331907
MCC
187struct pci_id_descr {
188 int dev;
189 int func;
190 int dev_id;
67166af4 191 struct pci_dev *pdev[NUM_SOCKETS];
8f331907
MCC
192};
193
a0c36a1f 194struct i7core_pvt {
67166af4
MCC
195 struct pci_dev *pci_noncore[NUM_SOCKETS];
196 struct pci_dev *pci_mcr[NUM_SOCKETS][MAX_MCR_FUNC + 1];
197 struct pci_dev *pci_ch[NUM_SOCKETS][NUM_CHANS][MAX_CHAN_FUNC + 1];
198
a0c36a1f 199 struct i7core_info info;
194a40fe 200 struct i7core_inject inject;
67166af4
MCC
201 struct i7core_channel channel[NUM_SOCKETS][NUM_CHANS];
202
203 int sockets; /* Number of sockets */
ef708b53 204 int channels; /* Number of active channels */
442305b1 205
67166af4
MCC
206 int ce_count_available[NUM_SOCKETS];
207 /* ECC corrected errors counts per dimm */
208 unsigned long ce_count[NUM_SOCKETS][MAX_DIMMS];
209 int last_ce_count[NUM_SOCKETS][MAX_DIMMS];
442305b1 210
d5381642
MCC
211 /* mcelog glue */
212 struct edac_mce edac_mce;
213 struct mce mce_entry[MCE_LOG_LEN];
214 unsigned mce_count;
215 spinlock_t mce_lock;
a0c36a1f
MCC
216};
217
218/* Device name and register DID (Device ID) */
219struct i7core_dev_info {
220 const char *ctl_name; /* name for this device */
221 u16 fsb_mapping_errors; /* DID for the branchmap,control */
222};
223
8f331907
MCC
224#define PCI_DESCR(device, function, device_id) \
225 .dev = (device), \
226 .func = (function), \
227 .dev_id = (device_id)
228
229struct pci_id_descr pci_devs[] = {
230 /* Memory controller */
231 { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
232 { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
233 { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM is supported */
234 { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
235
236 /* Channel 0 */
237 { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
238 { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
239 { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
240 { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC) },
241
242 /* Channel 1 */
243 { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
244 { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
245 { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
246 { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC) },
247
248 /* Channel 2 */
249 { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
250 { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
251 { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
252 { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
310cbb72
MCC
253
254 /* Generic Non-core registers */
255 /*
256 * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
257 * On Xeon 55xx, however, it has a different id (8086:2c40). So,
258 * the probing code needs to test for the other address in case of
259 * failure of this one
260 */
261 { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) },
262
a0c36a1f 263};
8f331907
MCC
264#define N_DEVS ARRAY_SIZE(pci_devs)
265
266/*
267 * pci_device_id table for which devices we are looking for
268 * This should match the first device at pci_devs table
269 */
270static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
d1fd4fb6 271 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)},
8f331907
MCC
272 {0,} /* 0 terminated list. */
273};
274
a0c36a1f
MCC
275
276/* Table of devices attributes supported by this driver */
277static const struct i7core_dev_info i7core_devs[] = {
278 {
279 .ctl_name = "i7 Core",
280 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I7_MCR,
281 },
282};
283
284static struct edac_pci_ctl_info *i7core_pci;
285
286/****************************************************************************
287 Anciliary status routines
288 ****************************************************************************/
289
290 /* MC_CONTROL bits */
ef708b53
MCC
291#define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & (1 << (8 + ch)))
292#define ECCx8(pvt) ((pvt)->info.mc_control & (1 << 1))
a0c36a1f
MCC
293
294 /* MC_STATUS bits */
ef708b53
MCC
295#define ECC_ENABLED(pvt) ((pvt)->info.mc_status & (1 << 3))
296#define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & (1 << ch))
a0c36a1f
MCC
297
298 /* MC_MAX_DOD read functions */
854d3349 299static inline int numdimms(u32 dimms)
a0c36a1f 300{
854d3349 301 return (dimms & 0x3) + 1;
a0c36a1f
MCC
302}
303
854d3349 304static inline int numrank(u32 rank)
a0c36a1f
MCC
305{
306 static int ranks[4] = { 1, 2, 4, -EINVAL };
307
854d3349 308 return ranks[rank & 0x3];
a0c36a1f
MCC
309}
310
854d3349 311static inline int numbank(u32 bank)
a0c36a1f
MCC
312{
313 static int banks[4] = { 4, 8, 16, -EINVAL };
314
854d3349 315 return banks[bank & 0x3];
a0c36a1f
MCC
316}
317
854d3349 318static inline int numrow(u32 row)
a0c36a1f
MCC
319{
320 static int rows[8] = {
321 1 << 12, 1 << 13, 1 << 14, 1 << 15,
322 1 << 16, -EINVAL, -EINVAL, -EINVAL,
323 };
324
854d3349 325 return rows[row & 0x7];
a0c36a1f
MCC
326}
327
854d3349 328static inline int numcol(u32 col)
a0c36a1f
MCC
329{
330 static int cols[8] = {
331 1 << 10, 1 << 11, 1 << 12, -EINVAL,
332 };
854d3349 333 return cols[col & 0x3];
a0c36a1f
MCC
334}
335
194a40fe 336
a0c36a1f
MCC
337/****************************************************************************
338 Memory check routines
339 ****************************************************************************/
67166af4
MCC
340static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
341 unsigned func)
ef708b53 342{
ef708b53 343 int i;
ef708b53
MCC
344
345 for (i = 0; i < N_DEVS; i++) {
67166af4 346 if (!pci_devs[i].pdev[socket])
ef708b53
MCC
347 continue;
348
67166af4
MCC
349 if (PCI_SLOT(pci_devs[i].pdev[socket]->devfn) == slot &&
350 PCI_FUNC(pci_devs[i].pdev[socket]->devfn) == func) {
351 return pci_devs[i].pdev[socket];
ef708b53
MCC
352 }
353 }
354
eb94fc40
MCC
355 return NULL;
356}
357
67166af4
MCC
358static int i7core_get_active_channels(u8 socket, unsigned *channels,
359 unsigned *csrows)
eb94fc40
MCC
360{
361 struct pci_dev *pdev = NULL;
362 int i, j;
363 u32 status, control;
364
365 *channels = 0;
366 *csrows = 0;
367
67166af4 368 pdev = get_pdev_slot_func(socket, 3, 0);
b7c76151 369 if (!pdev) {
67166af4
MCC
370 i7core_printk(KERN_ERR, "Couldn't find socket %d fn 3.0!!!\n",
371 socket);
ef708b53 372 return -ENODEV;
b7c76151 373 }
ef708b53
MCC
374
375 /* Device 3 function 0 reads */
376 pci_read_config_dword(pdev, MC_STATUS, &status);
377 pci_read_config_dword(pdev, MC_CONTROL, &control);
378
379 for (i = 0; i < NUM_CHANS; i++) {
eb94fc40 380 u32 dimm_dod[3];
ef708b53
MCC
381 /* Check if the channel is active */
382 if (!(control & (1 << (8 + i))))
383 continue;
384
385 /* Check if the channel is disabled */
41fcb7fe 386 if (status & (1 << i))
ef708b53 387 continue;
ef708b53 388
67166af4 389 pdev = get_pdev_slot_func(socket, i + 4, 1);
eb94fc40 390 if (!pdev) {
67166af4
MCC
391 i7core_printk(KERN_ERR, "Couldn't find socket %d "
392 "fn %d.%d!!!\n",
393 socket, i + 4, 1);
eb94fc40
MCC
394 return -ENODEV;
395 }
396 /* Devices 4-6 function 1 */
397 pci_read_config_dword(pdev,
398 MC_DOD_CH_DIMM0, &dimm_dod[0]);
399 pci_read_config_dword(pdev,
400 MC_DOD_CH_DIMM1, &dimm_dod[1]);
401 pci_read_config_dword(pdev,
402 MC_DOD_CH_DIMM2, &dimm_dod[2]);
403
ef708b53 404 (*channels)++;
eb94fc40
MCC
405
406 for (j = 0; j < 3; j++) {
407 if (!DIMM_PRESENT(dimm_dod[j]))
408 continue;
409 (*csrows)++;
410 }
ef708b53
MCC
411 }
412
67166af4
MCC
413 debugf0("Number of active channels on socked %d: %d\n",
414 socket, *channels);
1c6fed80 415
ef708b53
MCC
416 return 0;
417}
418
ba6c5c62 419static int get_dimm_config(struct mem_ctl_info *mci, int *csrow, u8 socket)
a0c36a1f
MCC
420{
421 struct i7core_pvt *pvt = mci->pvt_info;
1c6fed80 422 struct csrow_info *csr;
854d3349 423 struct pci_dev *pdev;
ba6c5c62 424 int i, j;
5566cb7c 425 unsigned long last_page = 0;
1c6fed80 426 enum edac_type mode;
854d3349 427 enum mem_type mtype;
a0c36a1f 428
854d3349 429 /* Get data from the MC register, function 0 */
67166af4 430 pdev = pvt->pci_mcr[socket][0];
7dd6953c 431 if (!pdev)
8f331907
MCC
432 return -ENODEV;
433
f122a892 434 /* Device 3 function 0 reads */
7dd6953c
MCC
435 pci_read_config_dword(pdev, MC_CONTROL, &pvt->info.mc_control);
436 pci_read_config_dword(pdev, MC_STATUS, &pvt->info.mc_status);
437 pci_read_config_dword(pdev, MC_MAX_DOD, &pvt->info.max_dod);
438 pci_read_config_dword(pdev, MC_CHANNEL_MAPPER, &pvt->info.ch_map);
f122a892
MCC
439
440 debugf0("MC control=0x%08x status=0x%08x dod=0x%08x map=0x%08x\n",
441 pvt->info.mc_control, pvt->info.mc_status,
442 pvt->info.max_dod, pvt->info.ch_map);
a0c36a1f 443
1c6fed80 444 if (ECC_ENABLED(pvt)) {
41fcb7fe 445 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt) ? 8 : 4);
1c6fed80
MCC
446 if (ECCx8(pvt))
447 mode = EDAC_S8ECD8ED;
448 else
449 mode = EDAC_S4ECD4ED;
450 } else {
a0c36a1f 451 debugf0("ECC disabled\n");
1c6fed80
MCC
452 mode = EDAC_NONE;
453 }
a0c36a1f
MCC
454
455 /* FIXME: need to handle the error codes */
854d3349
MCC
456 debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked\n",
457 numdimms(pvt->info.max_dod),
458 numrank(pvt->info.max_dod >> 2),
459 numbank(pvt->info.max_dod >> 4));
460 debugf0("DOD Max rows x colums = 0x%x x 0x%x\n",
461 numrow(pvt->info.max_dod >> 6),
462 numcol(pvt->info.max_dod >> 9));
a0c36a1f 463
0b2b7b7e
MCC
464 debugf0("Memory channel configuration:\n");
465
466 for (i = 0; i < NUM_CHANS; i++) {
854d3349 467 u32 data, dimm_dod[3], value[8];
0b2b7b7e
MCC
468
469 if (!CH_ACTIVE(pvt, i)) {
470 debugf0("Channel %i is not active\n", i);
471 continue;
472 }
473 if (CH_DISABLED(pvt, i)) {
474 debugf0("Channel %i is disabled\n", i);
475 continue;
476 }
477
f122a892 478 /* Devices 4-6 function 0 */
67166af4 479 pci_read_config_dword(pvt->pci_ch[socket][i][0],
0b2b7b7e
MCC
480 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
481
67166af4
MCC
482 pvt->channel[socket][i].ranks = (data & QUAD_RANK_PRESENT) ?
483 4 : 2;
0b2b7b7e 484
854d3349
MCC
485 if (data & REGISTERED_DIMM)
486 mtype = MEM_RDDR3;
487 else
488 mtype = MEM_DDR3;
489#if 0
0b2b7b7e
MCC
490 if (data & THREE_DIMMS_PRESENT)
491 pvt->channel[i].dimms = 3;
492 else if (data & SINGLE_QUAD_RANK_PRESENT)
493 pvt->channel[i].dimms = 1;
494 else
495 pvt->channel[i].dimms = 2;
854d3349
MCC
496#endif
497
498 /* Devices 4-6 function 1 */
67166af4 499 pci_read_config_dword(pvt->pci_ch[socket][i][1],
854d3349 500 MC_DOD_CH_DIMM0, &dimm_dod[0]);
67166af4 501 pci_read_config_dword(pvt->pci_ch[socket][i][1],
854d3349 502 MC_DOD_CH_DIMM1, &dimm_dod[1]);
67166af4 503 pci_read_config_dword(pvt->pci_ch[socket][i][1],
854d3349 504 MC_DOD_CH_DIMM2, &dimm_dod[2]);
0b2b7b7e 505
1c6fed80 506 debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
854d3349 507 "%d ranks, %cDIMMs\n",
1c6fed80
MCC
508 i,
509 RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
510 data,
67166af4 511 pvt->channel[socket][i].ranks,
41fcb7fe 512 (data & REGISTERED_DIMM) ? 'R' : 'U');
854d3349
MCC
513
514 for (j = 0; j < 3; j++) {
515 u32 banks, ranks, rows, cols;
5566cb7c 516 u32 size, npages;
854d3349
MCC
517
518 if (!DIMM_PRESENT(dimm_dod[j]))
519 continue;
520
521 banks = numbank(MC_DOD_NUMBANK(dimm_dod[j]));
522 ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j]));
523 rows = numrow(MC_DOD_NUMROW(dimm_dod[j]));
524 cols = numcol(MC_DOD_NUMCOL(dimm_dod[j]));
525
5566cb7c
MCC
526 /* DDR3 has 8 I/O banks */
527 size = (rows * cols * banks * ranks) >> (20 - 3);
528
67166af4 529 pvt->channel[socket][i].dimms++;
854d3349 530
5566cb7c
MCC
531 debugf0("\tdimm %d (0x%08x) %d Mb offset: %x, "
532 "numbank: %d,\n\t\t"
533 "numrank: %d, numrow: %#x, numcol: %#x\n",
534 j, dimm_dod[j], size,
854d3349
MCC
535 RANKOFFSET(dimm_dod[j]),
536 banks, ranks, rows, cols);
537
eb94fc40
MCC
538#if PAGE_SHIFT > 20
539 npages = size >> (PAGE_SHIFT - 20);
540#else
541 npages = size << (20 - PAGE_SHIFT);
542#endif
5566cb7c 543
ba6c5c62 544 csr = &mci->csrows[*csrow];
5566cb7c
MCC
545 csr->first_page = last_page + 1;
546 last_page += npages;
547 csr->last_page = last_page;
548 csr->nr_pages = npages;
549
854d3349 550 csr->page_mask = 0;
eb94fc40 551 csr->grain = 8;
ba6c5c62 552 csr->csrow_idx = *csrow;
eb94fc40
MCC
553 csr->nr_channels = 1;
554
555 csr->channels[0].chan_idx = i;
556 csr->channels[0].ce_count = 0;
854d3349
MCC
557
558 switch (banks) {
559 case 4:
560 csr->dtype = DEV_X4;
561 break;
562 case 8:
563 csr->dtype = DEV_X8;
564 break;
565 case 16:
566 csr->dtype = DEV_X16;
567 break;
568 default:
569 csr->dtype = DEV_UNKNOWN;
570 }
571
572 csr->edac_mode = mode;
573 csr->mtype = mtype;
574
ba6c5c62 575 (*csrow)++;
854d3349 576 }
1c6fed80 577
854d3349
MCC
578 pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
579 pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
580 pci_read_config_dword(pdev, MC_SAG_CH_2, &value[2]);
581 pci_read_config_dword(pdev, MC_SAG_CH_3, &value[3]);
582 pci_read_config_dword(pdev, MC_SAG_CH_4, &value[4]);
583 pci_read_config_dword(pdev, MC_SAG_CH_5, &value[5]);
584 pci_read_config_dword(pdev, MC_SAG_CH_6, &value[6]);
585 pci_read_config_dword(pdev, MC_SAG_CH_7, &value[7]);
41fcb7fe 586 debugf0("\t[%i] DIVBY3\tREMOVED\tOFFSET\n", i);
854d3349 587 for (j = 0; j < 8; j++)
41fcb7fe 588 debugf0("\t\t%#x\t%#x\t%#x\n",
854d3349
MCC
589 (value[j] >> 27) & 0x1,
590 (value[j] >> 24) & 0x7,
591 (value[j] && ((1 << 24) - 1)));
0b2b7b7e
MCC
592 }
593
a0c36a1f
MCC
594 return 0;
595}
596
194a40fe
MCC
597/****************************************************************************
598 Error insertion routines
599 ****************************************************************************/
600
601/* The i7core has independent error injection features per channel.
602 However, to have a simpler code, we don't allow enabling error injection
603 on more than one channel.
604 Also, since a change at an inject parameter will be applied only at enable,
605 we're disabling error injection on all write calls to the sysfs nodes that
606 controls the error code injection.
607 */
8f331907 608static int disable_inject(struct mem_ctl_info *mci)
194a40fe
MCC
609{
610 struct i7core_pvt *pvt = mci->pvt_info;
611
612 pvt->inject.enable = 0;
613
67166af4 614 if (!pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0])
8f331907
MCC
615 return -ENODEV;
616
67166af4 617 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
194a40fe 618 MC_CHANNEL_ERROR_MASK, 0);
8f331907
MCC
619
620 return 0;
194a40fe
MCC
621}
622
67166af4
MCC
623/*
624 * i7core inject inject.socket
625 *
626 * accept and store error injection inject.socket value
627 */
628static ssize_t i7core_inject_socket_store(struct mem_ctl_info *mci,
629 const char *data, size_t count)
630{
631 struct i7core_pvt *pvt = mci->pvt_info;
632 unsigned long value;
633 int rc;
634
635 rc = strict_strtoul(data, 10, &value);
636 if ((rc < 0) || (value > pvt->sockets))
637 return 0;
638
639 pvt->inject.section = (u32) value;
640 return count;
641}
642
643static ssize_t i7core_inject_socket_show(struct mem_ctl_info *mci,
644 char *data)
645{
646 struct i7core_pvt *pvt = mci->pvt_info;
647 return sprintf(data, "%d\n", pvt->inject.socket);
648}
649
194a40fe
MCC
650/*
651 * i7core inject inject.section
652 *
653 * accept and store error injection inject.section value
654 * bit 0 - refers to the lower 32-byte half cacheline
655 * bit 1 - refers to the upper 32-byte half cacheline
656 */
657static ssize_t i7core_inject_section_store(struct mem_ctl_info *mci,
658 const char *data, size_t count)
659{
660 struct i7core_pvt *pvt = mci->pvt_info;
661 unsigned long value;
662 int rc;
663
664 if (pvt->inject.enable)
41fcb7fe 665 disable_inject(mci);
194a40fe
MCC
666
667 rc = strict_strtoul(data, 10, &value);
668 if ((rc < 0) || (value > 3))
669 return 0;
670
671 pvt->inject.section = (u32) value;
672 return count;
673}
674
675static ssize_t i7core_inject_section_show(struct mem_ctl_info *mci,
676 char *data)
677{
678 struct i7core_pvt *pvt = mci->pvt_info;
679 return sprintf(data, "0x%08x\n", pvt->inject.section);
680}
681
682/*
683 * i7core inject.type
684 *
685 * accept and store error injection inject.section value
686 * bit 0 - repeat enable - Enable error repetition
687 * bit 1 - inject ECC error
688 * bit 2 - inject parity error
689 */
690static ssize_t i7core_inject_type_store(struct mem_ctl_info *mci,
691 const char *data, size_t count)
692{
693 struct i7core_pvt *pvt = mci->pvt_info;
694 unsigned long value;
695 int rc;
696
697 if (pvt->inject.enable)
41fcb7fe 698 disable_inject(mci);
194a40fe
MCC
699
700 rc = strict_strtoul(data, 10, &value);
701 if ((rc < 0) || (value > 7))
702 return 0;
703
704 pvt->inject.type = (u32) value;
705 return count;
706}
707
708static ssize_t i7core_inject_type_show(struct mem_ctl_info *mci,
709 char *data)
710{
711 struct i7core_pvt *pvt = mci->pvt_info;
712 return sprintf(data, "0x%08x\n", pvt->inject.type);
713}
714
715/*
716 * i7core_inject_inject.eccmask_store
717 *
718 * The type of error (UE/CE) will depend on the inject.eccmask value:
719 * Any bits set to a 1 will flip the corresponding ECC bit
720 * Correctable errors can be injected by flipping 1 bit or the bits within
721 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
722 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
723 * uncorrectable error to be injected.
724 */
725static ssize_t i7core_inject_eccmask_store(struct mem_ctl_info *mci,
726 const char *data, size_t count)
727{
728 struct i7core_pvt *pvt = mci->pvt_info;
729 unsigned long value;
730 int rc;
731
732 if (pvt->inject.enable)
41fcb7fe 733 disable_inject(mci);
194a40fe
MCC
734
735 rc = strict_strtoul(data, 10, &value);
736 if (rc < 0)
737 return 0;
738
739 pvt->inject.eccmask = (u32) value;
740 return count;
741}
742
743static ssize_t i7core_inject_eccmask_show(struct mem_ctl_info *mci,
744 char *data)
745{
746 struct i7core_pvt *pvt = mci->pvt_info;
747 return sprintf(data, "0x%08x\n", pvt->inject.eccmask);
748}
749
750/*
751 * i7core_addrmatch
752 *
753 * The type of error (UE/CE) will depend on the inject.eccmask value:
754 * Any bits set to a 1 will flip the corresponding ECC bit
755 * Correctable errors can be injected by flipping 1 bit or the bits within
756 * a symbol pair (2 consecutive aligned 8-bit pairs - i.e. 7:0 and 15:8 or
757 * 23:16 and 31:24). Flipping bits in two symbol pairs will cause an
758 * uncorrectable error to be injected.
759 */
760static ssize_t i7core_inject_addrmatch_store(struct mem_ctl_info *mci,
761 const char *data, size_t count)
762{
763 struct i7core_pvt *pvt = mci->pvt_info;
764 char *cmd, *val;
765 long value;
766 int rc;
767
768 if (pvt->inject.enable)
41fcb7fe 769 disable_inject(mci);
194a40fe
MCC
770
771 do {
772 cmd = strsep((char **) &data, ":");
773 if (!cmd)
774 break;
775 val = strsep((char **) &data, " \n\t");
776 if (!val)
777 return cmd - data;
778
41fcb7fe 779 if (!strcasecmp(val, "any"))
194a40fe
MCC
780 value = -1;
781 else {
782 rc = strict_strtol(val, 10, &value);
783 if ((rc < 0) || (value < 0))
784 return cmd - data;
785 }
786
41fcb7fe 787 if (!strcasecmp(cmd, "channel")) {
194a40fe
MCC
788 if (value < 3)
789 pvt->inject.channel = value;
790 else
791 return cmd - data;
41fcb7fe 792 } else if (!strcasecmp(cmd, "dimm")) {
194a40fe
MCC
793 if (value < 4)
794 pvt->inject.dimm = value;
795 else
796 return cmd - data;
41fcb7fe 797 } else if (!strcasecmp(cmd, "rank")) {
194a40fe
MCC
798 if (value < 4)
799 pvt->inject.rank = value;
800 else
801 return cmd - data;
41fcb7fe 802 } else if (!strcasecmp(cmd, "bank")) {
194a40fe
MCC
803 if (value < 4)
804 pvt->inject.bank = value;
805 else
806 return cmd - data;
41fcb7fe 807 } else if (!strcasecmp(cmd, "page")) {
194a40fe
MCC
808 if (value <= 0xffff)
809 pvt->inject.page = value;
810 else
811 return cmd - data;
41fcb7fe
MCC
812 } else if (!strcasecmp(cmd, "col") ||
813 !strcasecmp(cmd, "column")) {
194a40fe
MCC
814 if (value <= 0x3fff)
815 pvt->inject.col = value;
816 else
817 return cmd - data;
818 }
819 } while (1);
820
821 return count;
822}
823
824static ssize_t i7core_inject_addrmatch_show(struct mem_ctl_info *mci,
825 char *data)
826{
827 struct i7core_pvt *pvt = mci->pvt_info;
828 char channel[4], dimm[4], bank[4], rank[4], page[7], col[7];
829
830 if (pvt->inject.channel < 0)
831 sprintf(channel, "any");
832 else
833 sprintf(channel, "%d", pvt->inject.channel);
834 if (pvt->inject.dimm < 0)
835 sprintf(dimm, "any");
836 else
837 sprintf(dimm, "%d", pvt->inject.dimm);
838 if (pvt->inject.bank < 0)
839 sprintf(bank, "any");
840 else
841 sprintf(bank, "%d", pvt->inject.bank);
842 if (pvt->inject.rank < 0)
843 sprintf(rank, "any");
844 else
845 sprintf(rank, "%d", pvt->inject.rank);
846 if (pvt->inject.page < 0)
847 sprintf(page, "any");
848 else
849 sprintf(page, "0x%04x", pvt->inject.page);
850 if (pvt->inject.col < 0)
851 sprintf(col, "any");
852 else
853 sprintf(col, "0x%04x", pvt->inject.col);
854
855 return sprintf(data, "channel: %s\ndimm: %s\nbank: %s\n"
856 "rank: %s\npage: %s\ncolumn: %s\n",
857 channel, dimm, bank, rank, page, col);
858}
859
860/*
861 * This routine prepares the Memory Controller for error injection.
862 * The error will be injected when some process tries to write to the
863 * memory that matches the given criteria.
864 * The criteria can be set in terms of a mask where dimm, rank, bank, page
865 * and col can be specified.
866 * A -1 value for any of the mask items will make the MCU to ignore
867 * that matching criteria for error injection.
868 *
869 * It should be noticed that the error will only happen after a write operation
870 * on a memory that matches the condition. if REPEAT_EN is not enabled at
871 * inject mask, then it will produce just one error. Otherwise, it will repeat
872 * until the injectmask would be cleaned.
873 *
874 * FIXME: This routine assumes that MAXNUMDIMMS value of MC_MAX_DOD
875 * is reliable enough to check if the MC is using the
876 * three channels. However, this is not clear at the datasheet.
877 */
878static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
879 const char *data, size_t count)
880{
881 struct i7core_pvt *pvt = mci->pvt_info;
882 u32 injectmask;
883 u64 mask = 0;
884 int rc;
885 long enable;
886
67166af4 887 if (!pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0])
8f331907
MCC
888 return 0;
889
194a40fe
MCC
890 rc = strict_strtoul(data, 10, &enable);
891 if ((rc < 0))
892 return 0;
893
894 if (enable) {
895 pvt->inject.enable = 1;
896 } else {
897 disable_inject(mci);
898 return count;
899 }
900
901 /* Sets pvt->inject.dimm mask */
902 if (pvt->inject.dimm < 0)
7b029d03 903 mask |= 1L << 41;
194a40fe 904 else {
67166af4 905 if (pvt->channel[pvt->inject.socket][pvt->inject.channel].dimms > 2)
7b029d03 906 mask |= (pvt->inject.dimm & 0x3L) << 35;
194a40fe 907 else
7b029d03 908 mask |= (pvt->inject.dimm & 0x1L) << 36;
194a40fe
MCC
909 }
910
911 /* Sets pvt->inject.rank mask */
912 if (pvt->inject.rank < 0)
7b029d03 913 mask |= 1L << 40;
194a40fe 914 else {
67166af4 915 if (pvt->channel[pvt->inject.socket][pvt->inject.channel].dimms > 2)
7b029d03 916 mask |= (pvt->inject.rank & 0x1L) << 34;
194a40fe 917 else
7b029d03 918 mask |= (pvt->inject.rank & 0x3L) << 34;
194a40fe
MCC
919 }
920
921 /* Sets pvt->inject.bank mask */
922 if (pvt->inject.bank < 0)
7b029d03 923 mask |= 1L << 39;
194a40fe 924 else
7b029d03 925 mask |= (pvt->inject.bank & 0x15L) << 30;
194a40fe
MCC
926
927 /* Sets pvt->inject.page mask */
928 if (pvt->inject.page < 0)
7b029d03 929 mask |= 1L << 38;
194a40fe 930 else
7b029d03 931 mask |= (pvt->inject.page & 0xffffL) << 14;
194a40fe
MCC
932
933 /* Sets pvt->inject.column mask */
934 if (pvt->inject.col < 0)
7b029d03 935 mask |= 1L << 37;
194a40fe 936 else
7b029d03 937 mask |= (pvt->inject.col & 0x3fffL);
194a40fe 938
e9bd2e73 939 /* Unlock writes to registers */
67166af4
MCC
940 pci_write_config_dword(pvt->pci_noncore[pvt->inject.socket],
941 MC_CFG_CONTROL, 0x2);
e9bd2e73
MCC
942 msleep(100);
943
944 /* Zeroes error count registers */
67166af4
MCC
945 pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4],
946 MC_TEST_ERR_RCV1, 0);
947 pci_write_config_dword(pvt->pci_mcr[pvt->inject.socket][4],
948 MC_TEST_ERR_RCV0, 0);
949 pvt->ce_count_available[pvt->inject.socket] = 0;
e9bd2e73
MCC
950
951
7b029d03 952#if USE_QWORD
67166af4 953 pci_write_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
194a40fe 954 MC_CHANNEL_ADDR_MATCH, mask);
7b029d03 955#else
67166af4 956 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
7b029d03 957 MC_CHANNEL_ADDR_MATCH, mask);
67166af4 958 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
7b029d03
MCC
959 MC_CHANNEL_ADDR_MATCH + 4, mask >> 32L);
960#endif
961
962#if 1
963#if USE_QWORD
964 u64 rdmask;
67166af4 965 pci_read_config_qword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
7b029d03
MCC
966 MC_CHANNEL_ADDR_MATCH, &rdmask);
967 debugf0("Inject addr match write 0x%016llx, read: 0x%016llx\n",
968 mask, rdmask);
969#else
970 u32 rdmask1, rdmask2;
971
67166af4 972 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
7b029d03 973 MC_CHANNEL_ADDR_MATCH, &rdmask1);
67166af4 974 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
7b029d03
MCC
975 MC_CHANNEL_ADDR_MATCH + 4, &rdmask2);
976
d5381642 977 debugf0("Inject addr match write 0x%016llx, read: 0x%08x 0x%08x\n",
7b029d03
MCC
978 mask, rdmask1, rdmask2);
979#endif
980#endif
194a40fe 981
67166af4 982 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
194a40fe
MCC
983 MC_CHANNEL_ERROR_MASK, pvt->inject.eccmask);
984
985 /*
986 * bit 0: REPEAT_EN
987 * bits 1-2: MASK_HALF_CACHELINE
988 * bit 3: INJECT_ECC
989 * bit 4: INJECT_ADDR_PARITY
990 */
991
7b029d03
MCC
992 injectmask = (pvt->inject.type & 1) |
993 (pvt->inject.section & 0x3) << 1 |
194a40fe
MCC
994 (pvt->inject.type & 0x6) << (3 - 1);
995
67166af4 996 pci_write_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
194a40fe
MCC
997 MC_CHANNEL_ERROR_MASK, injectmask);
998
e9bd2e73
MCC
999#if 0
1000 /* lock writes to registers */
1001 pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0);
1002#endif
41fcb7fe
MCC
1003 debugf0("Error inject addr match 0x%016llx, ecc 0x%08x,"
1004 " inject 0x%08x\n",
194a40fe
MCC
1005 mask, pvt->inject.eccmask, injectmask);
1006
7b029d03 1007
194a40fe
MCC
1008 return count;
1009}
1010
1011static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci,
1012 char *data)
1013{
1014 struct i7core_pvt *pvt = mci->pvt_info;
7b029d03
MCC
1015 u32 injectmask;
1016
67166af4 1017 pci_read_config_dword(pvt->pci_ch[pvt->inject.socket][pvt->inject.channel][0],
7b029d03
MCC
1018 MC_CHANNEL_ERROR_MASK, &injectmask);
1019
1020 debugf0("Inject error read: 0x%018x\n", injectmask);
1021
1022 if (injectmask & 0x0c)
1023 pvt->inject.enable = 1;
1024
194a40fe
MCC
1025 return sprintf(data, "%d\n", pvt->inject.enable);
1026}
1027
442305b1
MCC
1028static ssize_t i7core_ce_regs_show(struct mem_ctl_info *mci, char *data)
1029{
67166af4 1030 unsigned i, count, total = 0;
442305b1
MCC
1031 struct i7core_pvt *pvt = mci->pvt_info;
1032
67166af4
MCC
1033 for (i = 0; i < pvt->sockets; i++) {
1034 if (!pvt->ce_count_available[i])
1035 count = sprintf(data, "socket 0 data unavailable\n");
1036 else
1037 count = sprintf(data, "socket %d, dimm0: %lu\n"
1038 "dimm1: %lu\ndimm2: %lu\n",
1039 i,
1040 pvt->ce_count[i][0],
1041 pvt->ce_count[i][1],
1042 pvt->ce_count[i][2]);
1043 data += count;
1044 total += count;
1045 }
442305b1 1046
67166af4 1047 return total;
442305b1
MCC
1048}
1049
194a40fe
MCC
1050/*
1051 * Sysfs struct
1052 */
1053static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
194a40fe 1054 {
67166af4
MCC
1055 .attr = {
1056 .name = "inject_socket",
1057 .mode = (S_IRUGO | S_IWUSR)
1058 },
1059 .show = i7core_inject_socket_show,
1060 .store = i7core_inject_socket_store,
1061 }, {
194a40fe
MCC
1062 .attr = {
1063 .name = "inject_section",
1064 .mode = (S_IRUGO | S_IWUSR)
1065 },
1066 .show = i7core_inject_section_show,
1067 .store = i7core_inject_section_store,
1068 }, {
1069 .attr = {
1070 .name = "inject_type",
1071 .mode = (S_IRUGO | S_IWUSR)
1072 },
1073 .show = i7core_inject_type_show,
1074 .store = i7core_inject_type_store,
1075 }, {
1076 .attr = {
1077 .name = "inject_eccmask",
1078 .mode = (S_IRUGO | S_IWUSR)
1079 },
1080 .show = i7core_inject_eccmask_show,
1081 .store = i7core_inject_eccmask_store,
1082 }, {
1083 .attr = {
1084 .name = "inject_addrmatch",
1085 .mode = (S_IRUGO | S_IWUSR)
1086 },
1087 .show = i7core_inject_addrmatch_show,
1088 .store = i7core_inject_addrmatch_store,
1089 }, {
1090 .attr = {
1091 .name = "inject_enable",
1092 .mode = (S_IRUGO | S_IWUSR)
1093 },
1094 .show = i7core_inject_enable_show,
1095 .store = i7core_inject_enable_store,
442305b1
MCC
1096 }, {
1097 .attr = {
1098 .name = "corrected_error_counts",
1099 .mode = (S_IRUGO | S_IWUSR)
1100 },
1101 .show = i7core_ce_regs_show,
1102 .store = NULL,
194a40fe
MCC
1103 },
1104};
1105
a0c36a1f
MCC
1106/****************************************************************************
1107 Device initialization routines: put/get, init/exit
1108 ****************************************************************************/
1109
1110/*
1111 * i7core_put_devices 'put' all the devices that we have
1112 * reserved via 'get'
1113 */
8f331907 1114static void i7core_put_devices(void)
a0c36a1f 1115{
67166af4 1116 int i, j;
a0c36a1f 1117
67166af4
MCC
1118 for (i = 0; i < NUM_SOCKETS; i++)
1119 for (j = 0; j < N_DEVS; j++)
1120 pci_dev_put(pci_devs[j].pdev[i]);
a0c36a1f
MCC
1121}
1122
1123/*
1124 * i7core_get_devices Find and perform 'get' operation on the MCH's
1125 * device/functions we want to reference for this driver
1126 *
1127 * Need to 'get' device 16 func 1 and func 2
1128 */
ef708b53 1129static int i7core_get_devices(void)
a0c36a1f 1130{
ef708b53 1131 int rc, i;
8f331907 1132 struct pci_dev *pdev = NULL;
67166af4
MCC
1133 u8 bus = 0;
1134 u8 socket = 0;
a0c36a1f 1135
8f331907
MCC
1136 for (i = 0; i < N_DEVS; i++) {
1137 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1138 pci_devs[i].dev_id, NULL);
d1fd4fb6
MCC
1139
1140 if (!pdev && !i) {
1141 pcibios_scan_specific_bus(254);
1142 pcibios_scan_specific_bus(255);
1143
1144 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1145 pci_devs[i].dev_id, NULL);
1146 }
1147
310cbb72
MCC
1148 /*
1149 * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
1150 * is at addr 8086:2c40, instead of 8086:2c41. So, we need
1151 * to probe for the alternate address in case of failure
1152 */
1153 if (pci_devs[i].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE
1154 && !pdev)
1155 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
1156 PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, NULL);
1157
67166af4
MCC
1158 if (likely(pdev)) {
1159 bus = pdev->bus->number;
1160
1161 if (bus == 0x3f)
1162 socket = 0;
1163 else
1164 socket = 255 - bus;
1165
1166 if (socket >= NUM_SOCKETS) {
1167 i7core_printk(KERN_ERR,
1168 "Found unexpected socket for "
1169 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1170 bus, pci_devs[i].dev, pci_devs[i].func,
1171 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
1172
1173 rc = -ENODEV;
1174 goto error;
1175 }
1176
1177 pci_devs[i].pdev[socket] = pdev;
1178 } else {
8f331907 1179 i7core_printk(KERN_ERR,
67166af4
MCC
1180 "Device not found: "
1181 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1182 bus, pci_devs[i].dev, pci_devs[i].func,
1183 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
ef708b53
MCC
1184
1185 /* Dev 3 function 2 only exists on chips with RDIMMs */
8f331907 1186 if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
ef708b53
MCC
1187 continue;
1188
1189 /* End of list, leave */
1190 rc = -ENODEV;
1191 goto error;
8f331907 1192 }
8f331907 1193
ef708b53
MCC
1194 /* Sanity check */
1195 if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[i].dev ||
1196 PCI_FUNC(pdev->devfn) != pci_devs[i].func)) {
8f331907 1197 i7core_printk(KERN_ERR,
ef708b53
MCC
1198 "Device PCI ID %04x:%04x "
1199 "has fn %d.%d instead of fn %d.%d\n",
8f331907 1200 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
ef708b53 1201 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
8f331907 1202 pci_devs[i].dev, pci_devs[i].func);
ef708b53
MCC
1203 rc = -EINVAL;
1204 goto error;
8f331907 1205 }
ef708b53
MCC
1206
1207 /* Be sure that the device is enabled */
1208 rc = pci_enable_device(pdev);
1209 if (unlikely(rc < 0)) {
8f331907 1210 i7core_printk(KERN_ERR,
ef708b53
MCC
1211 "Couldn't enable PCI ID %04x:%04x "
1212 "fn %d.%d\n",
8f331907 1213 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
ef708b53
MCC
1214 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1215 goto error;
8f331907 1216 }
a0c36a1f 1217
8f331907 1218 i7core_printk(KERN_INFO,
67166af4
MCC
1219 "Registered socket %d "
1220 "dev %02x:%02x.%d PCI ID %04x:%04x\n",
1221 socket, bus, pci_devs[i].dev, pci_devs[i].func,
1222 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
ef708b53
MCC
1223 }
1224
1225 return 0;
1226
1227error:
1228 i7core_put_devices();
1229 return -EINVAL;
1230}
1231
1232static int mci_bind_devs(struct mem_ctl_info *mci)
1233{
1234 struct i7core_pvt *pvt = mci->pvt_info;
1235 struct pci_dev *pdev;
67166af4 1236 int i, j, func, slot;
ef708b53 1237
67166af4
MCC
1238 for (i = 0; i < pvt->sockets; i++) {
1239 for (j = 0; j < N_DEVS; j++) {
1240 pdev = pci_devs[j].pdev[i];
1241 if (!pdev)
1242 continue;
8f331907 1243
67166af4
MCC
1244 func = PCI_FUNC(pdev->devfn);
1245 slot = PCI_SLOT(pdev->devfn);
1246 if (slot == 3) {
1247 if (unlikely(func > MAX_MCR_FUNC))
1248 goto error;
1249 pvt->pci_mcr[i][func] = pdev;
1250 } else if (likely(slot >= 4 && slot < 4 + NUM_CHANS)) {
1251 if (unlikely(func > MAX_CHAN_FUNC))
1252 goto error;
1253 pvt->pci_ch[i][slot - 4][func] = pdev;
1254 } else if (!slot && !func)
1255 pvt->pci_noncore[i] = pdev;
1256 else
ef708b53 1257 goto error;
ef708b53 1258
67166af4
MCC
1259 debugf0("Associated fn %d.%d, dev = %p, socket %d\n",
1260 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
1261 pdev, i);
1262 }
a0c36a1f 1263 }
e9bd2e73 1264
a0c36a1f 1265 return 0;
ef708b53
MCC
1266
1267error:
1268 i7core_printk(KERN_ERR, "Device %d, function %d "
1269 "is out of the expected range\n",
1270 slot, func);
1271 return -EINVAL;
a0c36a1f
MCC
1272}
1273
442305b1
MCC
1274/****************************************************************************
1275 Error check routines
1276 ****************************************************************************/
1277
1278/* This function is based on the device 3 function 4 registers as described on:
1279 * Intel Xeon Processor 5500 Series Datasheet Volume 2
1280 * http://www.intel.com/Assets/PDF/datasheet/321322.pdf
1281 * also available at:
1282 * http://www.arrownac.com/manufacturers/intel/s/nehalem/5500-datasheet-v2.pdf
1283 */
67166af4 1284static void check_mc_test_err(struct mem_ctl_info *mci, u8 socket)
442305b1
MCC
1285{
1286 struct i7core_pvt *pvt = mci->pvt_info;
1287 u32 rcv1, rcv0;
1288 int new0, new1, new2;
1289
67166af4 1290 if (!pvt->pci_mcr[socket][4]) {
442305b1
MCC
1291 debugf0("%s MCR registers not found\n",__func__);
1292 return;
1293 }
1294
1295 /* Corrected error reads */
67166af4
MCC
1296 pci_read_config_dword(pvt->pci_mcr[socket][4], MC_TEST_ERR_RCV1, &rcv1);
1297 pci_read_config_dword(pvt->pci_mcr[socket][4], MC_TEST_ERR_RCV0, &rcv0);
442305b1
MCC
1298
1299 /* Store the new values */
1300 new2 = DIMM2_COR_ERR(rcv1);
1301 new1 = DIMM1_COR_ERR(rcv0);
1302 new0 = DIMM0_COR_ERR(rcv0);
1303
d5381642 1304#if 0
442305b1
MCC
1305 debugf2("%s CE rcv1=0x%08x rcv0=0x%08x, %d %d %d\n",
1306 (pvt->ce_count_available ? "UPDATE" : "READ"),
1307 rcv1, rcv0, new0, new1, new2);
d5381642 1308#endif
442305b1
MCC
1309
1310 /* Updates CE counters if it is not the first time here */
67166af4 1311 if (pvt->ce_count_available[socket]) {
442305b1
MCC
1312 /* Updates CE counters */
1313 int add0, add1, add2;
1314
67166af4
MCC
1315 add2 = new2 - pvt->last_ce_count[socket][2];
1316 add1 = new1 - pvt->last_ce_count[socket][1];
1317 add0 = new0 - pvt->last_ce_count[socket][0];
442305b1
MCC
1318
1319 if (add2 < 0)
1320 add2 += 0x7fff;
67166af4 1321 pvt->ce_count[socket][2] += add2;
442305b1
MCC
1322
1323 if (add1 < 0)
1324 add1 += 0x7fff;
67166af4 1325 pvt->ce_count[socket][1] += add1;
442305b1
MCC
1326
1327 if (add0 < 0)
1328 add0 += 0x7fff;
67166af4 1329 pvt->ce_count[socket][0] += add0;
442305b1 1330 } else
67166af4 1331 pvt->ce_count_available[socket] = 1;
442305b1
MCC
1332
1333 /* Store the new values */
67166af4
MCC
1334 pvt->last_ce_count[socket][2] = new2;
1335 pvt->last_ce_count[socket][1] = new1;
1336 pvt->last_ce_count[socket][0] = new0;
442305b1
MCC
1337}
1338
8a2f118e
MCC
1339/*
1340 * According with tables E-11 and E-12 of chapter E.3.3 of Intel 64 and IA-32
1341 * Architectures Software Developer’s Manual Volume 3B.
f237fcf2
MCC
1342 * Nehalem are defined as family 0x06, model 0x1a
1343 *
1344 * The MCA registers used here are the following ones:
8a2f118e 1345 * struct mce field MCA Register
f237fcf2
MCC
1346 * m->status MSR_IA32_MC8_STATUS
1347 * m->addr MSR_IA32_MC8_ADDR
1348 * m->misc MSR_IA32_MC8_MISC
8a2f118e
MCC
1349 * In the case of Nehalem, the error information is masked at .status and .misc
1350 * fields
1351 */
d5381642
MCC
1352static void i7core_mce_output_error(struct mem_ctl_info *mci,
1353 struct mce *m)
1354{
c5d34528 1355 char *type;
8a2f118e
MCC
1356 char *err, *msg;
1357 unsigned long error = m->status & 0x1ff0000l;
1358 u32 core_err_cnt = (m->status >> 38) && 0x7fff;
1359 u32 dimm = (m->misc >> 16) & 0x3;
1360 u32 channel = (m->misc >> 18) & 0x3;
1361 u32 syndrome = m->misc >> 32;
1362 u32 errnum = find_first_bit(&error, 32);
1363
c5d34528
MCC
1364 if (m->mcgstatus & 1)
1365 type = "FATAL";
1366 else
1367 type = "NON_FATAL";
1368
8a2f118e
MCC
1369 switch (errnum) {
1370 case 16:
1371 err = "read ECC error";
1372 break;
1373 case 17:
1374 err = "RAS ECC error";
1375 break;
1376 case 18:
1377 err = "write parity error";
1378 break;
1379 case 19:
1380 err = "redundacy loss";
1381 break;
1382 case 20:
1383 err = "reserved";
1384 break;
1385 case 21:
1386 err = "memory range error";
1387 break;
1388 case 22:
1389 err = "RTID out of range";
1390 break;
1391 case 23:
1392 err = "address parity error";
1393 break;
1394 case 24:
1395 err = "byte enable parity error";
1396 break;
1397 default:
1398 err = "unknown";
d5381642 1399 }
d5381642 1400
f237fcf2 1401 /* FIXME: should convert addr into bank and rank information */
8a2f118e 1402 msg = kasprintf(GFP_ATOMIC,
f237fcf2
MCC
1403 "%s (addr = 0x%08llx Dimm=%d, Channel=%d, "
1404 "syndrome=0x%08x, count=%d Err=%d (%s))\n",
1405 type, (long long) m->addr, dimm, channel,
8a2f118e
MCC
1406 syndrome, core_err_cnt,errnum, err);
1407
1408 debugf0("%s", msg);
d5381642
MCC
1409
1410 /* Call the helper to output message */
8a2f118e
MCC
1411 edac_mc_handle_fbd_ue(mci, 0 /* FIXME: should be rank here */,
1412 0, 0 /* FIXME: should be channel here */, msg);
1413
1414 kfree(msg);
d5381642
MCC
1415}
1416
87d1d272
MCC
1417/*
1418 * i7core_check_error Retrieve and process errors reported by the
1419 * hardware. Called by the Core module.
1420 */
1421static void i7core_check_error(struct mem_ctl_info *mci)
1422{
d5381642
MCC
1423 struct i7core_pvt *pvt = mci->pvt_info;
1424 int i;
1425 unsigned count = 0;
1426 struct mce *m = NULL;
1427 unsigned long flags;
1428
1429 debugf0(__FILE__ ": %s()\n", __func__);
1430
1431 /* Copy all mce errors into a temporary buffer */
1432 spin_lock_irqsave(&pvt->mce_lock, flags);
1433 if (pvt->mce_count) {
1434 m = kmalloc(sizeof(*m) * pvt->mce_count, GFP_ATOMIC);
1435 if (m) {
1436 count = pvt->mce_count;
1437 memcpy(m, &pvt->mce_entry, sizeof(*m) * count);
1438 }
1439 pvt->mce_count = 0;
1440 }
1441 spin_unlock_irqrestore(&pvt->mce_lock, flags);
1442
1443 /* proccess mcelog errors */
1444 for (i = 0; i < count; i++)
1445 i7core_mce_output_error(mci, &m[i]);
1446
1447 kfree(m);
1448
1449 /* check memory count errors */
67166af4
MCC
1450 for (i = 0; i < pvt->sockets; i++)
1451 check_mc_test_err(mci, i);
87d1d272
MCC
1452}
1453
d5381642
MCC
1454/*
1455 * i7core_mce_check_error Replicates mcelog routine to get errors
1456 * This routine simply queues mcelog errors, and
1457 * return. The error itself should be handled later
1458 * by i7core_check_error.
1459 */
1460static int i7core_mce_check_error(void *priv, struct mce *mce)
1461{
c5d34528
MCC
1462 struct mem_ctl_info *mci = priv;
1463 struct i7core_pvt *pvt = mci->pvt_info;
d5381642
MCC
1464 unsigned long flags;
1465
1466 debugf0(__FILE__ ": %s()\n", __func__);
1467
8a2f118e
MCC
1468 /*
1469 * Just let mcelog handle it if the error is
1470 * outside the memory controller
1471 */
1472 if (((mce->status & 0xffff) >> 7) != 1)
1473 return 0;
1474
f237fcf2
MCC
1475 /* Bank 8 registers are the only ones that we know how to handle */
1476 if (mce->bank != 8)
1477 return 0;
1478
d5381642
MCC
1479 spin_lock_irqsave(&pvt->mce_lock, flags);
1480 if (pvt->mce_count < MCE_LOG_LEN) {
1481 memcpy(&pvt->mce_entry[pvt->mce_count], mce, sizeof(*mce));
1482 pvt->mce_count++;
1483 }
1484 spin_unlock_irqrestore(&pvt->mce_lock, flags);
1485
c5d34528
MCC
1486 /* Handle fatal errors immediately */
1487 if (mce->mcgstatus & 1)
1488 i7core_check_error(mci);
1489
d5381642 1490 /* Advice mcelog that the error were handled */
8a2f118e 1491 return 1;
d5381642
MCC
1492}
1493
a0c36a1f
MCC
1494/*
1495 * i7core_probe Probe for ONE instance of device to see if it is
1496 * present.
1497 * return:
1498 * 0 for FOUND a device
1499 * < 0 for error code
1500 */
1501static int __devinit i7core_probe(struct pci_dev *pdev,
1502 const struct pci_device_id *id)
1503{
1504 struct mem_ctl_info *mci;
1505 struct i7core_pvt *pvt;
67166af4
MCC
1506 int num_channels = 0;
1507 int num_csrows = 0;
ba6c5c62 1508 int csrow = 0;
a0c36a1f 1509 int dev_idx = id->driver_data;
67166af4
MCC
1510 int rc, i;
1511 u8 sockets;
a0c36a1f 1512
ef708b53 1513 if (unlikely(dev_idx >= ARRAY_SIZE(i7core_devs)))
a0c36a1f
MCC
1514 return -EINVAL;
1515
ef708b53 1516 /* get the pci devices we want to reserve for our use */
b7c76151
MCC
1517 rc = i7core_get_devices();
1518 if (unlikely(rc < 0))
1519 return rc;
ef708b53 1520
67166af4
MCC
1521 sockets = 1;
1522 for (i = NUM_SOCKETS - 1; i > 0; i--)
1523 if (pci_devs[0].pdev[i]) {
1524 sockets = i + 1;
1525 break;
1526 }
1527
1528 for (i = 0; i < sockets; i++) {
1529 int channels;
1530 int csrows;
1531
1532 /* Check the number of active and not disabled channels */
1533 rc = i7core_get_active_channels(i, &channels, &csrows);
1534 if (unlikely(rc < 0))
1535 goto fail0;
1536
1537 num_channels += channels;
1538 num_csrows += csrows;
1539 }
a0c36a1f 1540
a0c36a1f
MCC
1541 /* allocate a new MC control structure */
1542 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels, 0);
41fcb7fe 1543 if (unlikely(!mci)) {
b7c76151
MCC
1544 rc = -ENOMEM;
1545 goto fail0;
1546 }
a0c36a1f
MCC
1547
1548 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1549
194a40fe 1550 mci->dev = &pdev->dev; /* record ptr to the generic device */
a0c36a1f 1551 pvt = mci->pvt_info;
ef708b53 1552 memset(pvt, 0, sizeof(*pvt));
67166af4 1553 pvt->sockets = sockets;
a0c36a1f 1554 mci->mc_idx = 0;
67166af4 1555
41fcb7fe
MCC
1556 /*
1557 * FIXME: how to handle RDDR3 at MCI level? It is possible to have
1558 * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
1559 * memory channels
1560 */
1561 mci->mtype_cap = MEM_FLAG_DDR3;
a0c36a1f
MCC
1562 mci->edac_ctl_cap = EDAC_FLAG_NONE;
1563 mci->edac_cap = EDAC_FLAG_NONE;
1564 mci->mod_name = "i7core_edac.c";
1565 mci->mod_ver = I7CORE_REVISION;
1566 mci->ctl_name = i7core_devs[dev_idx].ctl_name;
1567 mci->dev_name = pci_name(pdev);
1568 mci->ctl_page_to_phys = NULL;
194a40fe 1569 mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
87d1d272
MCC
1570 /* Set the function pointer to an actual operation function */
1571 mci->edac_check = i7core_check_error;
8f331907 1572
ef708b53 1573 /* Store pci devices at mci for faster access */
b7c76151 1574 rc = mci_bind_devs(mci);
41fcb7fe 1575 if (unlikely(rc < 0))
ef708b53
MCC
1576 goto fail1;
1577
1578 /* Get dimm basic config */
67166af4 1579 for (i = 0; i < sockets; i++)
ba6c5c62 1580 get_dimm_config(mci, &csrow, i);
ef708b53 1581
a0c36a1f 1582 /* add this new MC control structure to EDAC's list of MCs */
b7c76151 1583 if (unlikely(edac_mc_add_mc(mci))) {
a0c36a1f
MCC
1584 debugf0("MC: " __FILE__
1585 ": %s(): failed edac_mc_add_mc()\n", __func__);
1586 /* FIXME: perhaps some code should go here that disables error
1587 * reporting if we just enabled it
1588 */
b7c76151
MCC
1589
1590 rc = -EINVAL;
a0c36a1f
MCC
1591 goto fail1;
1592 }
1593
1594 /* allocating generic PCI control info */
1595 i7core_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
41fcb7fe 1596 if (unlikely(!i7core_pci)) {
a0c36a1f
MCC
1597 printk(KERN_WARNING
1598 "%s(): Unable to create PCI control\n",
1599 __func__);
1600 printk(KERN_WARNING
1601 "%s(): PCI error report via EDAC not setup\n",
1602 __func__);
1603 }
1604
194a40fe 1605 /* Default error mask is any memory */
ef708b53 1606 pvt->inject.channel = 0;
194a40fe
MCC
1607 pvt->inject.dimm = -1;
1608 pvt->inject.rank = -1;
1609 pvt->inject.bank = -1;
1610 pvt->inject.page = -1;
1611 pvt->inject.col = -1;
1612
d5381642 1613 /* Registers on edac_mce in order to receive memory errors */
c5d34528 1614 pvt->edac_mce.priv = mci;
d5381642
MCC
1615 pvt->edac_mce.check_error = i7core_mce_check_error;
1616 spin_lock_init(&pvt->mce_lock);
1617
1618 rc = edac_mce_register(&pvt->edac_mce);
1619 if (unlikely (rc < 0)) {
1620 debugf0("MC: " __FILE__
1621 ": %s(): failed edac_mce_register()\n", __func__);
1622 goto fail1;
1623 }
1624
ef708b53 1625 i7core_printk(KERN_INFO, "Driver loaded.\n");
8f331907 1626
a0c36a1f
MCC
1627 return 0;
1628
1629fail1:
b7c76151 1630 edac_mc_free(mci);
a0c36a1f
MCC
1631
1632fail0:
b7c76151
MCC
1633 i7core_put_devices();
1634 return rc;
a0c36a1f
MCC
1635}
1636
1637/*
1638 * i7core_remove destructor for one instance of device
1639 *
1640 */
1641static void __devexit i7core_remove(struct pci_dev *pdev)
1642{
1643 struct mem_ctl_info *mci;
d5381642 1644 struct i7core_pvt *pvt;
a0c36a1f
MCC
1645
1646 debugf0(__FILE__ ": %s()\n", __func__);
1647
1648 if (i7core_pci)
1649 edac_pci_release_generic_ctl(i7core_pci);
1650
87d1d272 1651
d5381642 1652 mci = edac_mc_del_mc(&pdev->dev);
a0c36a1f
MCC
1653 if (!mci)
1654 return;
1655
d5381642
MCC
1656 /* Unregisters on edac_mce in order to receive memory errors */
1657 pvt = mci->pvt_info;
1658 edac_mce_unregister(&pvt->edac_mce);
1659
a0c36a1f 1660 /* retrieve references to resources, and free those resources */
8f331907 1661 i7core_put_devices();
a0c36a1f
MCC
1662
1663 edac_mc_free(mci);
1664}
1665
a0c36a1f
MCC
1666MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
1667
1668/*
1669 * i7core_driver pci_driver structure for this module
1670 *
1671 */
1672static struct pci_driver i7core_driver = {
1673 .name = "i7core_edac",
1674 .probe = i7core_probe,
1675 .remove = __devexit_p(i7core_remove),
1676 .id_table = i7core_pci_tbl,
1677};
1678
1679/*
1680 * i7core_init Module entry function
1681 * Try to initialize this module for its devices
1682 */
1683static int __init i7core_init(void)
1684{
1685 int pci_rc;
1686
1687 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1688
1689 /* Ensure that the OPSTATE is set correctly for POLL or NMI */
1690 opstate_init();
1691
1692 pci_rc = pci_register_driver(&i7core_driver);
1693
1694 return (pci_rc < 0) ? pci_rc : 0;
1695}
1696
1697/*
1698 * i7core_exit() Module exit function
1699 * Unregister the driver
1700 */
1701static void __exit i7core_exit(void)
1702{
1703 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1704 pci_unregister_driver(&i7core_driver);
1705}
1706
1707module_init(i7core_init);
1708module_exit(i7core_exit);
1709
1710MODULE_LICENSE("GPL");
1711MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
1712MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
1713MODULE_DESCRIPTION("MC Driver for Intel i7 Core memory controllers - "
1714 I7CORE_REVISION);
1715
1716module_param(edac_op_state, int, 0444);
1717MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");