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