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