Blame view

drivers/edac/sb_edac.c 93.9 KB
122375508   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2
3
4
5
6
  /* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module
   *
   * This driver supports the memory controllers found on the Intel
   * processor family Sandy Bridge.
   *
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
7
   * Copyright (c) 2011 by:
37e59f876   Mauro Carvalho Chehab   [media, edac] Cha...
8
   *	 Mauro Carvalho Chehab
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
9
10
11
12
13
14
15
16
17
18
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/pci.h>
  #include <linux/pci_ids.h>
  #include <linux/slab.h>
  #include <linux/delay.h>
  #include <linux/edac.h>
  #include <linux/mmzone.h>
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
19
20
  #include <linux/smp.h>
  #include <linux/bitmap.h>
5b889e379   Mauro Carvalho Chehab   Fix sb_edac compi...
21
  #include <linux/math64.h>
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
22
23
  #include <linux/mod_devicetable.h>
  #include <asm/cpu_device_id.h>
20f4d6924   Dave Hansen   EDAC, {sb,skx}_ed...
24
  #include <asm/intel-family.h>
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
25
  #include <asm/processor.h>
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
26
  #include <asm/mce.h>
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
27

78d88e8a3   Mauro Carvalho Chehab   edac: rename edac...
28
  #include "edac_module.h"
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
29
30
31
  
  /* Static vars */
  static LIST_HEAD(sbridge_edac_list);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
32
33
34
35
  
  /*
   * Alter this version for the module when modifications are made
   */
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
36
  #define SBRIDGE_REVISION    " Ver: 1.1.2 "
301375e76   Toshi Kani   EDAC: Add owner c...
37
  #define EDAC_MOD_STR	    "sb_edac"
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  
  /*
   * Debug macros
   */
  #define sbridge_printk(level, fmt, arg...)			\
  	edac_printk(level, "sbridge", fmt, ##arg)
  
  #define sbridge_mc_printk(mci, level, fmt, arg...)		\
  	edac_mc_chipset_printk(mci, level, "sbridge", fmt, ##arg)
  
  /*
   * Get a bit field at register value <v>, from bit <lo> to bit <hi>
   */
  #define GET_BITFIELD(v, lo, hi)	\
10ef6b0df   Chen, Gong   bitops: Introduce...
52
  	(((v) & GENMASK_ULL(hi, lo)) >> (lo))
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
53

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
54
  /* Devices 12 Function 6, Offsets 0x80 to 0xcc */
464f1d829   Aristeu Rozanski   sb_edac: allow di...
55
  static const u32 sbridge_dram_rule[] = {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
56
57
58
  	0x80, 0x88, 0x90, 0x98, 0xa0,
  	0xa8, 0xb0, 0xb8, 0xc0, 0xc8,
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
59

4d715a805   Aristeu Rozanski   sb_edac: add supp...
60
61
62
63
64
65
  static const u32 ibridge_dram_rule[] = {
  	0x60, 0x68, 0x70, 0x78, 0x80,
  	0x88, 0x90, 0x98, 0xa0,	0xa8,
  	0xb0, 0xb8, 0xc0, 0xc8, 0xd0,
  	0xd8, 0xe0, 0xe8, 0xf0, 0xf8,
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
66

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
67
68
69
70
71
72
73
  static const u32 knl_dram_rule[] = {
  	0x60, 0x68, 0x70, 0x78, 0x80, /* 0-4 */
  	0x88, 0x90, 0x98, 0xa0, 0xa8, /* 5-9 */
  	0xb0, 0xb8, 0xc0, 0xc8, 0xd0, /* 10-14 */
  	0xd8, 0xe0, 0xe8, 0xf0, 0xf8, /* 15-19 */
  	0x100, 0x108, 0x110, 0x118,   /* 20-23 */
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
74
  #define DRAM_RULE_ENABLE(reg)	GET_BITFIELD(reg, 0,  0)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
75
  #define A7MODE(reg)		GET_BITFIELD(reg, 26, 26)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
76

c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
77
  static char *show_dram_attr(u32 attr)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
78
  {
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
79
  	switch (attr) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
80
81
82
83
84
85
86
87
88
89
  		case 0:
  			return "DRAM";
  		case 1:
  			return "MMCFG";
  		case 2:
  			return "NXM";
  		default:
  			return "unknown";
  	}
  }
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
90
  static const u32 sbridge_interleave_list[] = {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
91
92
93
  	0x84, 0x8c, 0x94, 0x9c, 0xa4,
  	0xac, 0xb4, 0xbc, 0xc4, 0xcc,
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
94

4d715a805   Aristeu Rozanski   sb_edac: add supp...
95
96
97
98
99
100
  static const u32 ibridge_interleave_list[] = {
  	0x64, 0x6c, 0x74, 0x7c, 0x84,
  	0x8c, 0x94, 0x9c, 0xa4, 0xac,
  	0xb4, 0xbc, 0xc4, 0xcc, 0xd4,
  	0xdc, 0xe4, 0xec, 0xf4, 0xfc,
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
101
102
103
104
105
106
107
  static const u32 knl_interleave_list[] = {
  	0x64, 0x6c, 0x74, 0x7c, 0x84, /* 0-4 */
  	0x8c, 0x94, 0x9c, 0xa4, 0xac, /* 5-9 */
  	0xb4, 0xbc, 0xc4, 0xcc, 0xd4, /* 10-14 */
  	0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */
  	0x104, 0x10c, 0x114, 0x11c,   /* 20-23 */
  };
6fd052665   Gustavo A. R. Silva   EDAC, sb_edac: Re...
108
109
110
111
  #define MAX_INTERLEAVE							\
  	(max_t(unsigned int, ARRAY_SIZE(sbridge_interleave_list),	\
  	       max_t(unsigned int, ARRAY_SIZE(ibridge_interleave_list),	\
  		     ARRAY_SIZE(knl_interleave_list))))
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
112

cc311991a   Aristeu Rozanski   sb_edac: rework s...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  struct interleave_pkg {
  	unsigned char start;
  	unsigned char end;
  };
  
  static const struct interleave_pkg sbridge_interleave_pkg[] = {
  	{ 0, 2 },
  	{ 3, 5 },
  	{ 8, 10 },
  	{ 11, 13 },
  	{ 16, 18 },
  	{ 19, 21 },
  	{ 24, 26 },
  	{ 27, 29 },
  };
4d715a805   Aristeu Rozanski   sb_edac: add supp...
128
129
130
131
132
133
134
135
136
137
  static const struct interleave_pkg ibridge_interleave_pkg[] = {
  	{ 0, 3 },
  	{ 4, 7 },
  	{ 8, 11 },
  	{ 12, 15 },
  	{ 16, 19 },
  	{ 20, 23 },
  	{ 24, 27 },
  	{ 28, 31 },
  };
cc311991a   Aristeu Rozanski   sb_edac: rework s...
138
139
  static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
  			  int interleave)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
140
  {
cc311991a   Aristeu Rozanski   sb_edac: rework s...
141
142
  	return GET_BITFIELD(reg, table[interleave].start,
  			    table[interleave].end);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
143
144
145
146
147
  }
  
  /* Devices 12 Function 7 */
  
  #define TOLM		0x80
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
148
  #define TOHM		0x84
f7cf2a22a   Tony Luck   sb_edac: Fix disc...
149
  #define HASWELL_TOLM	0xd0
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
150
151
  #define HASWELL_TOHM_0	0xd4
  #define HASWELL_TOHM_1	0xd8
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
152
153
154
  #define KNL_TOLM	0xd0
  #define KNL_TOHM_0	0xd4
  #define KNL_TOHM_1	0xd8
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
155
156
157
158
159
160
161
162
163
  
  #define GET_TOLM(reg)		((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ffffff)
  #define GET_TOHM(reg)		((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
  
  /* Device 13 Function 6 */
  
  #define SAD_TARGET	0xf0
  
  #define SOURCE_ID(reg)		GET_BITFIELD(reg, 9, 11)
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
164
  #define SOURCE_ID_KNL(reg)	GET_BITFIELD(reg, 12, 14)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
165
  #define SAD_CONTROL	0xf4
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  /* Device 14 function 0 */
  
  static const u32 tad_dram_rule[] = {
  	0x40, 0x44, 0x48, 0x4c,
  	0x50, 0x54, 0x58, 0x5c,
  	0x60, 0x64, 0x68, 0x6c,
  };
  #define MAX_TAD	ARRAY_SIZE(tad_dram_rule)
  
  #define TAD_LIMIT(reg)		((GET_BITFIELD(reg, 12, 31) << 26) | 0x3ffffff)
  #define TAD_SOCK(reg)		GET_BITFIELD(reg, 10, 11)
  #define TAD_CH(reg)		GET_BITFIELD(reg,  8,  9)
  #define TAD_TGT3(reg)		GET_BITFIELD(reg,  6,  7)
  #define TAD_TGT2(reg)		GET_BITFIELD(reg,  4,  5)
  #define TAD_TGT1(reg)		GET_BITFIELD(reg,  2,  3)
  #define TAD_TGT0(reg)		GET_BITFIELD(reg,  0,  1)
  
  /* Device 15, function 0 */
  
  #define MCMTR			0x7c
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
186
  #define KNL_MCMTR		0x624
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  
  #define IS_ECC_ENABLED(mcmtr)		GET_BITFIELD(mcmtr, 2, 2)
  #define IS_LOCKSTEP_ENABLED(mcmtr)	GET_BITFIELD(mcmtr, 1, 1)
  #define IS_CLOSE_PG(mcmtr)		GET_BITFIELD(mcmtr, 0, 0)
  
  /* Device 15, function 1 */
  
  #define RASENABLES		0xac
  #define IS_MIRROR_ENABLED(reg)		GET_BITFIELD(reg, 0, 0)
  
  /* Device 15, functions 2-5 */
  
  static const int mtr_regs[] = {
  	0x80, 0x84, 0x88,
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
202
  static const int knl_mtr_reg = 0xb60;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  #define RANK_DISABLE(mtr)		GET_BITFIELD(mtr, 16, 19)
  #define IS_DIMM_PRESENT(mtr)		GET_BITFIELD(mtr, 14, 14)
  #define RANK_CNT_BITS(mtr)		GET_BITFIELD(mtr, 12, 13)
  #define RANK_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 2, 4)
  #define COL_WIDTH_BITS(mtr)		GET_BITFIELD(mtr, 0, 1)
  
  static const u32 tad_ch_nilv_offset[] = {
  	0x90, 0x94, 0x98, 0x9c,
  	0xa0, 0xa4, 0xa8, 0xac,
  	0xb0, 0xb4, 0xb8, 0xbc,
  };
  #define CHN_IDX_OFFSET(reg)		GET_BITFIELD(reg, 28, 29)
  #define TAD_OFFSET(reg)			(GET_BITFIELD(reg,  6, 25) << 26)
  
  static const u32 rir_way_limit[] = {
  	0x108, 0x10c, 0x110, 0x114, 0x118,
  };
  #define MAX_RIR_RANGES ARRAY_SIZE(rir_way_limit)
  
  #define IS_RIR_VALID(reg)	GET_BITFIELD(reg, 31, 31)
  #define RIR_WAY(reg)		GET_BITFIELD(reg, 28, 29)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
224
225
226
227
228
229
230
231
232
233
  
  #define MAX_RIR_WAY	8
  
  static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
  	{ 0x120, 0x124, 0x128, 0x12c, 0x130, 0x134, 0x138, 0x13c },
  	{ 0x140, 0x144, 0x148, 0x14c, 0x150, 0x154, 0x158, 0x15c },
  	{ 0x160, 0x164, 0x168, 0x16c, 0x170, 0x174, 0x178, 0x17c },
  	{ 0x180, 0x184, 0x188, 0x18c, 0x190, 0x194, 0x198, 0x19c },
  	{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
  };
c7103f650   Tony Luck   EDAC, sb_edac: Fi...
234
235
236
237
238
  #define RIR_RNK_TGT(type, reg) (((type) == BROADWELL) ? \
  	GET_BITFIELD(reg, 20, 23) : GET_BITFIELD(reg, 16, 19))
  
  #define RIR_OFFSET(type, reg) (((type) == HASWELL || (type) == BROADWELL) ? \
  	GET_BITFIELD(reg,  2, 15) : GET_BITFIELD(reg,  2, 14))
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
239
240
241
242
243
244
  
  /* Device 16, functions 2-7 */
  
  /*
   * FIXME: Implement the error count reads directly
   */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
245
246
247
248
  #define RANK_ODD_OV(reg)		GET_BITFIELD(reg, 31, 31)
  #define RANK_ODD_ERR_CNT(reg)		GET_BITFIELD(reg, 16, 30)
  #define RANK_EVEN_OV(reg)		GET_BITFIELD(reg, 15, 15)
  #define RANK_EVEN_ERR_CNT(reg)		GET_BITFIELD(reg,  0, 14)
323014d85   Mauro Carvalho Chehab   EDAC: sb_edac: ge...
249
250
251
252
  #if 0 /* Currently unused*/
  static const u32 correrrcnt[] = {
  	0x104, 0x108, 0x10c, 0x110,
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
253
254
255
  static const u32 correrrthrsld[] = {
  	0x11c, 0x120, 0x124, 0x128,
  };
323014d85   Mauro Carvalho Chehab   EDAC: sb_edac: ge...
256
  #endif
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
257
258
259
260
261
262
  
  #define RANK_ODD_ERR_THRSLD(reg)	GET_BITFIELD(reg, 16, 30)
  #define RANK_EVEN_ERR_THRSLD(reg)	GET_BITFIELD(reg,  0, 14)
  
  
  /* Device 17, function 0 */
ef1e8d03b   Aristeu Rozanski   sb_edac: make RAN...
263
  #define SB_RANK_CFG_A		0x0328
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
264

4d715a805   Aristeu Rozanski   sb_edac: add supp...
265
  #define IB_RANK_CFG_A		0x0320
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
266

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
267
268
269
  /*
   * sbridge structs
   */
bf8486709   Anna Karbownik   EDAC, sb_edac: Fi...
270
  #define NUM_CHANNELS		6	/* Max channels per MC */
351fc4a99   Seth Jennings   sb_edac: avoid IN...
271
  #define MAX_DIMMS		3	/* Max DIMMS per channel */
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
272
273
274
  #define KNL_MAX_CHAS		38	/* KNL max num. of Cache Home Agents */
  #define KNL_MAX_CHANNELS	6	/* KNL max num. of PCI channels */
  #define KNL_MAX_EDCS		8	/* Embedded DRAM controllers */
351fc4a99   Seth Jennings   sb_edac: avoid IN...
275
  #define CHANNEL_UNSPECIFIED	0xf	/* Intel IA32 SDM 15-14 */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
276

4d715a805   Aristeu Rozanski   sb_edac: add supp...
277
278
279
  enum type {
  	SANDY_BRIDGE,
  	IVY_BRIDGE,
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
280
  	HASWELL,
1f39581a9   Tony Luck   sb_edac: Add supp...
281
  	BROADWELL,
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
282
  	KNIGHTS_LANDING,
4d715a805   Aristeu Rozanski   sb_edac: add supp...
283
  };
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
284
285
286
287
288
  enum domain {
  	IMC0 = 0,
  	IMC1,
  	SOCK,
  };
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
289
290
291
292
293
  enum mirroring_mode {
  	NON_MIRRORING,
  	ADDR_RANGE_MIRRORING,
  	FULL_MIRRORING,
  };
fb79a5092   Aristeu Rozanski   sb_edac: isolate ...
294
  struct sbridge_pvt;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
295
  struct sbridge_info {
4d715a805   Aristeu Rozanski   sb_edac: add supp...
296
  	enum type	type;
464f1d829   Aristeu Rozanski   sb_edac: allow di...
297
298
299
300
  	u32		mcmtr;
  	u32		rankcfgr;
  	u64		(*get_tolm)(struct sbridge_pvt *pvt);
  	u64		(*get_tohm)(struct sbridge_pvt *pvt);
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
301
  	u64		(*rir_limit)(u32 reg);
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
302
303
  	u64		(*sad_limit)(u32 reg);
  	u32		(*interleave_mode)(u32 reg);
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
304
  	u32		(*dram_attr)(u32 reg);
464f1d829   Aristeu Rozanski   sb_edac: allow di...
305
  	const u32	*dram_rule;
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
306
  	const u32	*interleave_list;
cc311991a   Aristeu Rozanski   sb_edac: rework s...
307
  	const struct interleave_pkg *interleave_pkg;
464f1d829   Aristeu Rozanski   sb_edac: allow di...
308
  	u8		max_sad;
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
309
  	u8		(*get_node_id)(struct sbridge_pvt *pvt);
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
310
  	u8		(*get_ha)(u8 bank);
9e3754461   Aristeu Rozanski   sb_edac: make mem...
311
  	enum mem_type	(*get_memory_type)(struct sbridge_pvt *pvt);
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
312
  	enum dev_type	(*get_width)(struct sbridge_pvt *pvt, u32 mtr);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
313
  	struct pci_dev	*pci_vtd;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
314
315
316
317
318
319
320
321
  };
  
  struct sbridge_channel {
  	u32		ranks;
  	u32		dimms;
  };
  
  struct pci_id_descr {
c41afdca2   Mauro Carvalho Chehab   sb_edac: Fix mix ...
322
  	int			dev_id;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
323
  	int			optional;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
324
  	enum domain		dom;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
325
326
327
328
  };
  
  struct pci_id_table {
  	const struct pci_id_descr	*descr;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
329
330
331
  	int				n_devs_per_imc;
  	int				n_devs_per_sock;
  	int				n_imcs_per_sock;
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
332
  	enum type			type;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
333
334
335
336
  };
  
  struct sbridge_dev {
  	struct list_head	list;
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
337
  	int			seg;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
338
339
340
  	u8			bus, mc;
  	u8			node_id, source_id;
  	struct pci_dev		**pdev;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
341
  	enum domain		dom;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
342
  	int			n_devs;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
343
  	int			i_devs;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
344
345
  	struct mem_ctl_info	*mci;
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
346
347
348
349
350
351
352
353
354
  struct knl_pvt {
  	struct pci_dev          *pci_cha[KNL_MAX_CHAS];
  	struct pci_dev          *pci_channel[KNL_MAX_CHANNELS];
  	struct pci_dev          *pci_mc0;
  	struct pci_dev          *pci_mc1;
  	struct pci_dev          *pci_mc0_misc;
  	struct pci_dev          *pci_mc1_misc;
  	struct pci_dev          *pci_mc_info; /* tolm, tohm */
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
355
  struct sbridge_pvt {
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
356
357
  	/* Devices per socket */
  	struct pci_dev		*pci_ddrio;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
358
  	struct pci_dev		*pci_sad0, *pci_sad1;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
359
  	struct pci_dev		*pci_br0, *pci_br1;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
360
361
  	/* Devices per memory controller */
  	struct pci_dev		*pci_ha, *pci_ta, *pci_ras;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
362
363
364
365
366
367
  	struct pci_dev		*pci_tad[NUM_CHANNELS];
  
  	struct sbridge_dev	*sbridge_dev;
  
  	struct sbridge_info	info;
  	struct sbridge_channel	channel[NUM_CHANNELS];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
368
  	/* Memory type detection */
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
369
  	bool			is_cur_addr_mirrored, is_lockstep, is_close_pg;
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
370
  	bool			is_chan_hash;
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
371
  	enum mirroring_mode	mirror_mode;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
372

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
373
374
  	/* Memory description */
  	u64			tolm, tohm;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
375
  	struct knl_pvt knl;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
376
  };
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
377
  #define PCI_DESCR(device_id, opt, domain)	\
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
378
  	.dev_id = (device_id),		\
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
379
380
  	.optional = opt,	\
  	.dom = domain
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
381
382
383
  
  static const struct pci_id_descr pci_dev_descr_sbridge[] = {
  		/* Processor Home Agent */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
384
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0,   0, IMC0) },
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
385
386
  
  		/* Memory controller */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
387
388
389
390
391
392
393
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA,    0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0,  0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1,  0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2,  0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3,  0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1, SOCK) },
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
394
395
  
  		/* System Address Decoder */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
396
397
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0,      0, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1,      0, SOCK) },
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
398
399
  
  		/* Broadcast Registers */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
400
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR,        0, SOCK) },
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
401
  };
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
402
  #define PCI_ID_TABLE_ENTRY(A, N, M, T) {	\
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
403
  	.descr = A,			\
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
404
405
406
  	.n_devs_per_imc = N,	\
  	.n_devs_per_sock = ARRAY_SIZE(A),	\
  	.n_imcs_per_sock = M,	\
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
407
408
  	.type = T			\
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
409
  static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
410
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, ARRAY_SIZE(pci_dev_descr_sbridge), 1, SANDY_BRIDGE),
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
411
412
  	{0,}			/* 0 terminated list. */
  };
4d715a805   Aristeu Rozanski   sb_edac: add supp...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  /* This changes depending if 1HA or 2HA:
   * 1HA:
   *	0x0eb8 (17.0) is DDRIO0
   * 2HA:
   *	0x0ebc (17.4) is DDRIO0
   */
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0	0x0eb8
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0	0x0ebc
  
  /* pci ids */
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0		0x0ea0
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA		0x0ea8
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS		0x0e71
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0	0x0eaa
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1	0x0eab
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2	0x0eac
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3	0x0ead
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_SAD			0x0ec8
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_BR0			0x0ec9
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_BR1			0x0eca
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1		0x0e60
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA		0x0e68
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS		0x0e79
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0	0x0e6a
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1	0x0e6b
7d375bffa   Tony Luck   sb_edac: Fix supp...
438
439
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2	0x0e6c
  #define PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3	0x0e6d
4d715a805   Aristeu Rozanski   sb_edac: add supp...
440
441
442
  
  static const struct pci_id_descr pci_dev_descr_ibridge[] = {
  		/* Processor Home Agent */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
443
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0,        0, IMC0) },
15cc3ae00   Qiuxu Zhuo   EDAC, sb_edac: Do...
444
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1,        1, IMC1) },
4d715a805   Aristeu Rozanski   sb_edac: add supp...
445
446
  
  		/* Memory controller */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
447
448
449
450
451
452
453
454
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA,     0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS,    0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3,   0, IMC0) },
  
  		/* Optional, mode 2HA */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
455
456
457
458
459
460
461
462
463
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA,     1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS,    1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3,   1, IMC1) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1, SOCK) },
4d715a805   Aristeu Rozanski   sb_edac: add supp...
464
465
  
  		/* System Address Decoder */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
466
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD,            0, SOCK) },
4d715a805   Aristeu Rozanski   sb_edac: add supp...
467
468
  
  		/* Broadcast Registers */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
469
470
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0,            1, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1,            0, SOCK) },
4d715a805   Aristeu Rozanski   sb_edac: add supp...
471

4d715a805   Aristeu Rozanski   sb_edac: add supp...
472
473
474
  };
  
  static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
475
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, 12, 2, IVY_BRIDGE),
4d715a805   Aristeu Rozanski   sb_edac: add supp...
476
477
  	{0,}			/* 0 terminated list. */
  };
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
  /* Haswell support */
  /* EN processor:
   *	- 1 IMC
   *	- 3 DDR3 channels, 2 DPC per channel
   * EP processor:
   *	- 1 or 2 IMC
   *	- 4 DDR4 channels, 3 DPC per channel
   * EP 4S processor:
   *	- 2 IMC
   *	- 4 DDR4 channels, 3 DPC per channel
   * EX processor:
   *	- 2 IMC
   *	- each IMC interfaces with a SMI 2 channel
   *	- each SMI channel interfaces with a scalable memory buffer
   *	- each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
   */
1f39581a9   Tony Luck   sb_edac: Add supp...
494
  #define HASWELL_DDRCRCLKCONTROLS 0xa10 /* Ditto on Broadwell */
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
495
496
497
498
499
  #define HASWELL_HASYSDEFEATURE2 0x84
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0	0x2fa0
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1	0x2f60
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA	0x2fa8
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
500
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM	0x2f71
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
501
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA	0x2f68
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
502
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM	0x2f79
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
503
504
505
506
507
508
509
510
511
512
513
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0 0x2ffc
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1 0x2ffd
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0 0x2faa
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1 0x2fab
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2 0x2fac
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3 0x2fad
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 0x2f6a
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1 0x2f6b
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd
7179385af   Aristeu Rozanski   sb_edac: look har...
514
515
516
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1 0x2fbf
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2 0x2fb9
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
517
518
  static const struct pci_id_descr pci_dev_descr_haswell[] = {
  	/* first item must be the HA */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0,      0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1,      1, IMC1) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1, IMC0) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1, IMC1) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0,   1, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1,   1, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2,   1, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3,   1, SOCK) },
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
542
543
544
  };
  
  static const struct pci_id_table pci_dev_descr_haswell_table[] = {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
545
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, 13, 2, HASWELL),
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
546
547
  	{0,}			/* 0 terminated list. */
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
548
549
550
  /* Knight's Landing Support */
  /*
   * KNL's memory channels are swizzled between memory controllers.
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
551
   * MC0 is mapped to CH3,4,5 and MC1 is mapped to CH0,1,2
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
552
   */
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
553
  #define knl_channel_remap(mc, chan) ((mc) ? (chan) : (chan) + 3)
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
554
555
556
557
  
  /* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_MC       0x7840
  /* DRAM channel stuff; bank addrs, dimmmtr, etc.. 2-8-2 - 2-9-4 (6 of these) */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
558
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN     0x7843
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  /* kdrwdbu TAD limits/offsets, MCMTR - 2-10-1, 2-11-1 (2 of these) */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_TA       0x7844
  /* CHA broadcast registers, dram rules - 1-29-0 (1 of these) */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0     0x782a
  /* SAD target - 1-29-1 (1 of these) */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1     0x782b
  /* Caching / Home Agent */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_CHA      0x782c
  /* Device with TOLM and TOHM, 0-5-0 (1 of these) */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM    0x7810
  
  /*
   * KNL differs from SB, IB, and Haswell in that it has multiple
   * instances of the same device with the same device ID, so we handle that
   * by creating as many copies in the table as we expect to find.
   * (Like device ID must be grouped together.)
   */
  
  static const struct pci_id_descr pci_dev_descr_knl[] = {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
578
579
580
581
582
583
584
  	[0 ... 1]   = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC,    0, IMC0)},
  	[2 ... 7]   = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN,  0, IMC0) },
  	[8]	    = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA,    0, IMC0) },
  	[9]	    = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0, IMC0) },
  	[10]	    = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0,  0, SOCK) },
  	[11]	    = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1,  0, SOCK) },
  	[12 ... 49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA,   0, SOCK) },
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
585
586
587
  };
  
  static const struct pci_id_table pci_dev_descr_knl_table[] = {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
588
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, ARRAY_SIZE(pci_dev_descr_knl), 1, KNIGHTS_LANDING),
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
589
590
  	{0,}
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
591
  /*
1f39581a9   Tony Luck   sb_edac: Add supp...
592
593
594
595
596
   * Broadwell support
   *
   * DE processor:
   *	- 1 IMC
   *	- 2 DDR3 channels, 2 DPC per channel
fa2ce64f8   Tony Luck   sb_edac: support ...
597
598
599
600
601
602
603
604
605
606
607
   * EP processor:
   *	- 1 or 2 IMC
   *	- 4 DDR4 channels, 3 DPC per channel
   * EP 4S processor:
   *	- 2 IMC
   *	- 4 DDR4 channels, 3 DPC per channel
   * EX processor:
   *	- 2 IMC
   *	- each IMC interfaces with a SMI 2 channel
   *	- each SMI channel interfaces with a scalable memory buffer
   *	- each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
1f39581a9   Tony Luck   sb_edac: Add supp...
608
609
610
   */
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC 0x6f28
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0	0x6fa0
fa2ce64f8   Tony Luck   sb_edac: support ...
611
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1	0x6f60
1f39581a9   Tony Luck   sb_edac: Add supp...
612
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA	0x6fa8
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
613
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM	0x6f71
fa2ce64f8   Tony Luck   sb_edac: support ...
614
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA	0x6f68
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
615
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM	0x6f79
1f39581a9   Tony Luck   sb_edac: Add supp...
616
617
618
619
620
621
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1 0x6fab
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2 0x6fac
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3 0x6fad
fa2ce64f8   Tony Luck   sb_edac: support ...
622
623
624
625
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0 0x6f6a
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1 0x6f6b
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2 0x6f6c
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3 0x6f6d
1f39581a9   Tony Luck   sb_edac: Add supp...
626
627
628
629
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0 0x6faf
  
  static const struct pci_id_descr pci_dev_descr_broadwell[] = {
  	/* first item must be the HA */
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0,      0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1,      1, IMC1) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM,   0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1, IMC0) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1, IMC0) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM,   1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1, IMC1) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1, IMC1) },
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0, SOCK) },
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0,   1, SOCK) },
1f39581a9   Tony Luck   sb_edac: Add supp...
650
651
652
  };
  
  static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
653
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, 10, 2, BROADWELL),
1f39581a9   Tony Luck   sb_edac: Add supp...
654
655
  	{0,}			/* 0 terminated list. */
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
656
657
  
  /****************************************************************************
15ed103a9   David Mackey   edac: Fix spellin...
658
  			Ancillary status routines
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
659
   ****************************************************************************/
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
660
  static inline int numrank(enum type type, u32 mtr)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
661
662
  {
  	int ranks = (1 << RANK_CNT_BITS(mtr));
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
663
  	int max = 4;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
664
  	if (type == HASWELL || type == BROADWELL || type == KNIGHTS_LANDING)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
665
  		max = 8;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
666

50d1bb936   Aristeu Rozanski   sb_edac: add supp...
667
668
669
670
  	if (ranks > max) {
  		edac_dbg(0, "Invalid number of ranks: %d (max = %i) raw value = %x (%04x)
  ",
  			 ranks, max, (unsigned int)RANK_CNT_BITS(mtr), mtr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
671
672
673
674
675
676
677
678
679
680
681
  		return -EINVAL;
  	}
  
  	return ranks;
  }
  
  static inline int numrow(u32 mtr)
  {
  	int rows = (RANK_WIDTH_BITS(mtr) + 12);
  
  	if (rows < 13 || rows > 18) {
956b9ba15   Joe Perches   edac: Convert deb...
682
683
684
  		edac_dbg(0, "Invalid number of rows: %d (should be between 14 and 17) raw value = %x (%04x)
  ",
  			 rows, (unsigned int)RANK_WIDTH_BITS(mtr), mtr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
685
686
687
688
689
690
691
692
693
694
695
  		return -EINVAL;
  	}
  
  	return 1 << rows;
  }
  
  static inline int numcol(u32 mtr)
  {
  	int cols = (COL_WIDTH_BITS(mtr) + 10);
  
  	if (cols > 12) {
956b9ba15   Joe Perches   edac: Convert deb...
696
697
698
  		edac_dbg(0, "Invalid number of cols: %d (max = 4) raw value = %x (%04x)
  ",
  			 cols, (unsigned int)COL_WIDTH_BITS(mtr), mtr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
699
700
701
702
703
  		return -EINVAL;
  	}
  
  	return 1 << cols;
  }
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
704
705
  static struct sbridge_dev *get_sbridge_dev(int seg, u8 bus, enum domain dom,
  					   int multi_bus,
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
706
  					   struct sbridge_dev *prev)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
707
708
  {
  	struct sbridge_dev *sbridge_dev;
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
709
710
711
712
713
714
715
716
  	/*
  	 * If we have devices scattered across several busses that pertain
  	 * to the same memory controller, we'll lump them all together.
  	 */
  	if (multi_bus) {
  		return list_first_entry_or_null(&sbridge_edac_list,
  				struct sbridge_dev, list);
  	}
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
717
718
719
720
  	sbridge_dev = list_entry(prev ? prev->list.next
  				      : sbridge_edac_list.next, struct sbridge_dev, list);
  
  	list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) {
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
721
722
  		if ((sbridge_dev->seg == seg) && (sbridge_dev->bus == bus) &&
  				(dom == SOCK || dom == sbridge_dev->dom))
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
723
724
725
726
727
  			return sbridge_dev;
  	}
  
  	return NULL;
  }
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
728
  static struct sbridge_dev *alloc_sbridge_dev(int seg, u8 bus, enum domain dom,
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
729
  					     const struct pci_id_table *table)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
730
731
732
733
734
735
  {
  	struct sbridge_dev *sbridge_dev;
  
  	sbridge_dev = kzalloc(sizeof(*sbridge_dev), GFP_KERNEL);
  	if (!sbridge_dev)
  		return NULL;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
736
737
738
  	sbridge_dev->pdev = kcalloc(table->n_devs_per_imc,
  				    sizeof(*sbridge_dev->pdev),
  				    GFP_KERNEL);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
739
740
741
742
  	if (!sbridge_dev->pdev) {
  		kfree(sbridge_dev);
  		return NULL;
  	}
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
743
  	sbridge_dev->seg = seg;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
744
  	sbridge_dev->bus = bus;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
745
  	sbridge_dev->dom = dom;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
746
  	sbridge_dev->n_devs = table->n_devs_per_imc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
747
748
749
750
751
752
753
754
755
756
757
  	list_add_tail(&sbridge_dev->list, &sbridge_edac_list);
  
  	return sbridge_dev;
  }
  
  static void free_sbridge_dev(struct sbridge_dev *sbridge_dev)
  {
  	list_del(&sbridge_dev->list);
  	kfree(sbridge_dev->pdev);
  	kfree(sbridge_dev);
  }
fb79a5092   Aristeu Rozanski   sb_edac: isolate ...
758
759
760
761
762
763
764
765
  static u64 sbridge_get_tolm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	/* Address range is 32:28 */
  	pci_read_config_dword(pvt->pci_sad1, TOLM, &reg);
  	return GET_TOLM(reg);
  }
8fd6a43ac   Aristeu Rozanski   sb_edac: isolate ...
766
767
768
769
770
771
772
  static u64 sbridge_get_tohm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	pci_read_config_dword(pvt->pci_sad1, TOHM, &reg);
  	return GET_TOHM(reg);
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
  static u64 ibridge_get_tolm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	pci_read_config_dword(pvt->pci_br1, TOLM, &reg);
  
  	return GET_TOLM(reg);
  }
  
  static u64 ibridge_get_tohm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	pci_read_config_dword(pvt->pci_br1, TOHM, &reg);
  
  	return GET_TOHM(reg);
  }
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
790
791
792
793
  static u64 rir_limit(u32 reg)
  {
  	return ((u64)GET_BITFIELD(reg,  1, 10) << 29) | 0x1fffffff;
  }
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
794
795
796
797
798
799
800
801
802
  static u64 sad_limit(u32 reg)
  {
  	return (GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff;
  }
  
  static u32 interleave_mode(u32 reg)
  {
  	return GET_BITFIELD(reg, 1, 1);
  }
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
803
804
805
806
  static u32 dram_attr(u32 reg)
  {
  	return GET_BITFIELD(reg, 2, 3);
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
807
808
809
810
811
812
813
814
815
  static u64 knl_sad_limit(u32 reg)
  {
  	return (GET_BITFIELD(reg, 7, 26) << 26) | 0x3ffffff;
  }
  
  static u32 knl_interleave_mode(u32 reg)
  {
  	return GET_BITFIELD(reg, 1, 2);
  }
127c1225b   Nicolas Iooss   EDAC, sb_edac: Ge...
816
817
818
  static const char * const knl_intlv_mode[] = {
  	"[8:6]", "[10:8]", "[14:12]", "[32:30]"
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
819

127c1225b   Nicolas Iooss   EDAC, sb_edac: Ge...
820
821
822
823
824
825
  static const char *get_intlv_mode_str(u32 reg, enum type t)
  {
  	if (t == KNIGHTS_LANDING)
  		return knl_intlv_mode[knl_interleave_mode(reg)];
  	else
  		return interleave_mode(reg) ? "[8:6]" : "[8:6]XOR[18:16]";
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
826
827
828
829
830
831
  }
  
  static u32 dram_attr_knl(u32 reg)
  {
  	return GET_BITFIELD(reg, 3, 4);
  }
9e3754461   Aristeu Rozanski   sb_edac: make mem...
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  	enum mem_type mtype;
  
  	if (pvt->pci_ddrio) {
  		pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
  				      &reg);
  		if (GET_BITFIELD(reg, 11, 11))
  			/* FIXME: Can also be LRDIMM */
  			mtype = MEM_RDDR3;
  		else
  			mtype = MEM_DDR3;
  	} else
  		mtype = MEM_UNKNOWN;
  
  	return mtype;
  }
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
  static enum mem_type haswell_get_memory_type(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  	bool registered = false;
  	enum mem_type mtype = MEM_UNKNOWN;
  
  	if (!pvt->pci_ddrio)
  		goto out;
  
  	pci_read_config_dword(pvt->pci_ddrio,
  			      HASWELL_DDRCRCLKCONTROLS, &reg);
  	/* Is_Rdimm */
  	if (GET_BITFIELD(reg, 16, 16))
  		registered = true;
  
  	pci_read_config_dword(pvt->pci_ta, MCMTR, &reg);
  	if (GET_BITFIELD(reg, 14, 14)) {
  		if (registered)
  			mtype = MEM_RDDR4;
  		else
  			mtype = MEM_DDR4;
  	} else {
  		if (registered)
  			mtype = MEM_RDDR3;
  		else
  			mtype = MEM_DDR3;
  	}
  
  out:
  	return mtype;
  }
45f4d3ab3   Hubert Chrzaniuk   EDAC, sb_edac: Se...
881
882
883
884
885
  static enum dev_type knl_get_width(struct sbridge_pvt *pvt, u32 mtr)
  {
  	/* for KNL value is fixed */
  	return DEV_X16;
  }
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
886
887
888
889
890
891
892
893
  static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
  {
  	/* there's no way to figure out */
  	return DEV_UNKNOWN;
  }
  
  static enum dev_type __ibridge_get_width(u32 mtr)
  {
fbd4ab780   Tom Rix   EDAC, sb_edac: Si...
894
  	enum dev_type type = DEV_UNKNOWN;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
895
896
  
  	switch (mtr) {
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
  	case 2:
  		type = DEV_X16;
  		break;
  	case 1:
  		type = DEV_X8;
  		break;
  	case 0:
  		type = DEV_X4;
  		break;
  	}
  
  	return type;
  }
  
  static enum dev_type ibridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
  {
  	/*
  	 * ddr3_width on the documentation but also valid for DDR4 on
  	 * Haswell
  	 */
  	return __ibridge_get_width(GET_BITFIELD(mtr, 7, 8));
  }
  
  static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr)
  {
  	/* ddr3_width on the documentation but also valid for DDR4 */
  	return __ibridge_get_width(GET_BITFIELD(mtr, 8, 9));
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
925
926
927
928
929
  static enum mem_type knl_get_memory_type(struct sbridge_pvt *pvt)
  {
  	/* DDR4 RDIMMS and LRDIMMS are supported */
  	return MEM_RDDR4;
  }
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
930
931
932
933
934
935
  static u8 get_node_id(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  	pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
  	return GET_BITFIELD(reg, 0, 2);
  }
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
936
937
938
939
940
941
942
  static u8 haswell_get_node_id(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, &reg);
  	return GET_BITFIELD(reg, 0, 3);
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
943
944
945
946
947
948
949
  static u8 knl_get_node_id(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, &reg);
  	return GET_BITFIELD(reg, 0, 2);
  }
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
  /*
   * Use the reporting bank number to determine which memory
   * controller (also known as "ha" for "home agent"). Sandy
   * Bridge only has one memory controller per socket, so the
   * answer is always zero.
   */
  static u8 sbridge_get_ha(u8 bank)
  {
  	return 0;
  }
  
  /*
   * On Ivy Bridge, Haswell and Broadwell the error may be in a
   * home agent bank (7, 8), or one of the per-channel memory
   * controller banks (9 .. 16).
   */
  static u8 ibridge_get_ha(u8 bank)
  {
  	switch (bank) {
  	case 7 ... 8:
  		return bank - 7;
  	case 9 ... 16:
  		return (bank - 9) / 4;
  	default:
c968ed085   Tony Luck   EDAC, sb_edac: Fi...
974
  		return 0xff;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
975
976
977
978
979
980
  	}
  }
  
  /* Not used, but included for safety/symmetry */
  static u8 knl_get_ha(u8 bank)
  {
c968ed085   Tony Luck   EDAC, sb_edac: Fi...
981
  	return 0xff;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
982
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
983

50d1bb936   Aristeu Rozanski   sb_edac: add supp...
984
985
986
  static u64 haswell_get_tolm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
f7cf2a22a   Tony Luck   sb_edac: Fix disc...
987
988
  	pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOLM, &reg);
  	return (GET_BITFIELD(reg, 26, 31) << 26) | 0x3ffffff;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
  }
  
  static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
  {
  	u64 rc;
  	u32 reg;
  
  	pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_0, &reg);
  	rc = GET_BITFIELD(reg, 26, 31);
  	pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, &reg);
  	rc = ((reg << 6) | rc) << 26;
  
  	return rc | 0x1ffffff;
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
  static u64 knl_get_tolm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
  
  	pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOLM, &reg);
  	return (GET_BITFIELD(reg, 26, 31) << 26) | 0x3ffffff;
  }
  
  static u64 knl_get_tohm(struct sbridge_pvt *pvt)
  {
  	u64 rc;
  	u32 reg_lo, reg_hi;
  
  	pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOHM_0, &reg_lo);
  	pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOHM_1, &reg_hi);
  	rc = ((u64)reg_hi << 32) | reg_lo;
  	return rc | 0x3ffffff;
  }
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1021
1022
1023
1024
  static u64 haswell_rir_limit(u32 reg)
  {
  	return (((u64)GET_BITFIELD(reg,  1, 11) + 1) << 29) - 1;
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1025
1026
1027
  static inline u8 sad_pkg_socket(u8 pkg)
  {
  	/* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
2ff3a308b   Aristeu Rozanski   sb_edac: fix sock...
1028
  	return ((pkg >> 3) << 2) | (pkg & 0x3);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1029
1030
1031
1032
1033
1034
  }
  
  static inline u8 sad_pkg_ha(u8 pkg)
  {
  	return (pkg >> 2) & 0x1;
  }
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
  static int haswell_chan_hash(int idx, u64 addr)
  {
  	int i;
  
  	/*
  	 * XOR even bits from 12:26 to bit0 of idx,
  	 *     odd bits from 13:27 to bit1
  	 */
  	for (i = 12; i < 28; i += 2)
  		idx ^= (addr >> i) & 3;
  
  	return idx;
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
  /* Low bits of TAD limit, and some metadata. */
  static const u32 knl_tad_dram_limit_lo[] = {
  	0x400, 0x500, 0x600, 0x700,
  	0x800, 0x900, 0xa00, 0xb00,
  };
  
  /* Low bits of TAD offset. */
  static const u32 knl_tad_dram_offset_lo[] = {
  	0x404, 0x504, 0x604, 0x704,
  	0x804, 0x904, 0xa04, 0xb04,
  };
  
  /* High 16 bits of TAD limit and offset. */
  static const u32 knl_tad_dram_hi[] = {
  	0x408, 0x508, 0x608, 0x708,
  	0x808, 0x908, 0xa08, 0xb08,
  };
  
  /* Number of ways a tad entry is interleaved. */
  static const u32 knl_tad_ways[] = {
  	8, 6, 4, 3, 2, 1,
  };
  
  /*
   * Retrieve the n'th Target Address Decode table entry
   * from the memory controller's TAD table.
   *
   * @pvt:	driver private data
   * @entry:	which entry you want to retrieve
   * @mc:		which memory controller (0 or 1)
   * @offset:	output tad range offset
   * @limit:	output address of first byte above tad range
   * @ways:	output number of interleave ways
   *
   * The offset value has curious semantics.  It's a sort of running total
   * of the sizes of all the memory regions that aren't mapped in this
   * tad table.
   */
  static int knl_get_tad(const struct sbridge_pvt *pvt,
  		const int entry,
  		const int mc,
  		u64 *offset,
  		u64 *limit,
  		int *ways)
  {
  	u32 reg_limit_lo, reg_offset_lo, reg_hi;
  	struct pci_dev *pci_mc;
  	int way_id;
  
  	switch (mc) {
  	case 0:
  		pci_mc = pvt->knl.pci_mc0;
  		break;
  	case 1:
  		pci_mc = pvt->knl.pci_mc1;
  		break;
  	default:
  		WARN_ON(1);
  		return -EINVAL;
  	}
  
  	pci_read_config_dword(pci_mc,
  			knl_tad_dram_limit_lo[entry], &reg_limit_lo);
  	pci_read_config_dword(pci_mc,
  			knl_tad_dram_offset_lo[entry], &reg_offset_lo);
  	pci_read_config_dword(pci_mc,
  			knl_tad_dram_hi[entry], &reg_hi);
  
  	/* Is this TAD entry enabled? */
  	if (!GET_BITFIELD(reg_limit_lo, 0, 0))
  		return -ENODEV;
  
  	way_id = GET_BITFIELD(reg_limit_lo, 3, 5);
  
  	if (way_id < ARRAY_SIZE(knl_tad_ways)) {
  		*ways = knl_tad_ways[way_id];
  	} else {
  		*ways = 0;
  		sbridge_printk(KERN_ERR,
  				"Unexpected value %d in mc_tad_limit_lo wayness field
  ",
  				way_id);
  		return -ENODEV;
  	}
  
  	/*
  	 * The least significant 6 bits of base and limit are truncated.
  	 * For limit, we fill the missing bits with 1s.
  	 */
  	*offset = ((u64) GET_BITFIELD(reg_offset_lo, 6, 31) << 6) |
  				((u64) GET_BITFIELD(reg_hi, 0,  15) << 32);
  	*limit = ((u64) GET_BITFIELD(reg_limit_lo,  6, 31) << 6) | 63 |
  				((u64) GET_BITFIELD(reg_hi, 16, 31) << 32);
  
  	return 0;
  }
  
  /* Determine which memory controller is responsible for a given channel. */
  static int knl_channel_mc(int channel)
  {
  	WARN_ON(channel < 0 || channel >= 6);
  
  	return channel < 3 ? 1 : 0;
  }
  
  /*
   * Get the Nth entry from EDC_ROUTE_TABLE register.
   * (This is the per-tile mapping of logical interleave targets to
   *  physical EDC modules.)
   *
   * entry 0: 0:2
   *       1: 3:5
   *       2: 6:8
   *       3: 9:11
   *       4: 12:14
   *       5: 15:17
   *       6: 18:20
   *       7: 21:23
   * reserved: 24:31
   */
  static u32 knl_get_edc_route(int entry, u32 reg)
  {
  	WARN_ON(entry >= KNL_MAX_EDCS);
  	return GET_BITFIELD(reg, entry*3, (entry*3)+2);
  }
  
  /*
   * Get the Nth entry from MC_ROUTE_TABLE register.
   * (This is the per-tile mapping of logical interleave targets to
   *  physical DRAM channels modules.)
   *
   * entry 0: mc 0:2   channel 18:19
   *       1: mc 3:5   channel 20:21
   *       2: mc 6:8   channel 22:23
   *       3: mc 9:11  channel 24:25
   *       4: mc 12:14 channel 26:27
   *       5: mc 15:17 channel 28:29
   * reserved: 30:31
   *
   * Though we have 3 bits to identify the MC, we should only see
   * the values 0 or 1.
   */
  
  static u32 knl_get_mc_route(int entry, u32 reg)
  {
  	int mc, chan;
  
  	WARN_ON(entry >= KNL_MAX_CHANNELS);
  
  	mc = GET_BITFIELD(reg, entry*3, (entry*3)+2);
  	chan = GET_BITFIELD(reg, (entry*2) + 18, (entry*2) + 18 + 1);
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
1199
  	return knl_channel_remap(mc, chan);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
  }
  
  /*
   * Render the EDC_ROUTE register in human-readable form.
   * Output string s should be at least KNL_MAX_EDCS*2 bytes.
   */
  static void knl_show_edc_route(u32 reg, char *s)
  {
  	int i;
  
  	for (i = 0; i < KNL_MAX_EDCS; i++) {
  		s[i*2] = knl_get_edc_route(i, reg) + '0';
  		s[i*2+1] = '-';
  	}
  
  	s[KNL_MAX_EDCS*2 - 1] = '\0';
  }
  
  /*
   * Render the MC_ROUTE register in human-readable form.
   * Output string s should be at least KNL_MAX_CHANNELS*2 bytes.
   */
  static void knl_show_mc_route(u32 reg, char *s)
  {
  	int i;
  
  	for (i = 0; i < KNL_MAX_CHANNELS; i++) {
  		s[i*2] = knl_get_mc_route(i, reg) + '0';
  		s[i*2+1] = '-';
  	}
  
  	s[KNL_MAX_CHANNELS*2 - 1] = '\0';
  }
  
  #define KNL_EDC_ROUTE 0xb8
  #define KNL_MC_ROUTE 0xb4
  
  /* Is this dram rule backed by regular DRAM in flat mode? */
  #define KNL_EDRAM(reg) GET_BITFIELD(reg, 29, 29)
  
  /* Is this dram rule cached? */
  #define KNL_CACHEABLE(reg) GET_BITFIELD(reg, 28, 28)
  
  /* Is this rule backed by edc ? */
  #define KNL_EDRAM_ONLY(reg) GET_BITFIELD(reg, 29, 29)
  
  /* Is this rule backed by DRAM, cacheable in EDRAM? */
  #define KNL_CACHEABLE(reg) GET_BITFIELD(reg, 28, 28)
  
  /* Is this rule mod3? */
  #define KNL_MOD3(reg) GET_BITFIELD(reg, 27, 27)
  
  /*
   * Figure out how big our RAM modules are.
   *
   * The DIMMMTR register in KNL doesn't tell us the size of the DIMMs, so we
   * have to figure this out from the SAD rules, interleave lists, route tables,
   * and TAD rules.
   *
   * SAD rules can have holes in them (e.g. the 3G-4G hole), so we have to
   * inspect the TAD rules to figure out how large the SAD regions really are.
   *
   * When we know the real size of a SAD region and how many ways it's
   * interleaved, we know the individual contribution of each channel to
   * TAD is size/ways.
   *
   * Finally, we have to check whether each channel participates in each SAD
   * region.
   *
   * Fortunately, KNL only supports one DIMM per channel, so once we know how
   * much memory the channel uses, we know the DIMM is at least that large.
   * (The BIOS might possibly choose not to map all available memory, in which
   * case we will underreport the size of the DIMM.)
   *
   * In theory, we could try to determine the EDC sizes as well, but that would
   * only work in flat mode, not in cache mode.
   *
   * @mc_sizes: Output sizes of channels (must have space for KNL_MAX_CHANNELS
   *            elements)
   */
  static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
  {
323014d85   Mauro Carvalho Chehab   EDAC: sb_edac: ge...
1282
  	u64 sad_base, sad_limit = 0;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  	u64 tad_base, tad_size, tad_limit, tad_deadspace, tad_livespace;
  	int sad_rule = 0;
  	int tad_rule = 0;
  	int intrlv_ways, tad_ways;
  	u32 first_pkg, pkg;
  	int i;
  	u64 sad_actual_size[2]; /* sad size accounting for holes, per mc */
  	u32 dram_rule, interleave_reg;
  	u32 mc_route_reg[KNL_MAX_CHAS];
  	u32 edc_route_reg[KNL_MAX_CHAS];
  	int edram_only;
  	char edc_route_string[KNL_MAX_EDCS*2];
  	char mc_route_string[KNL_MAX_CHANNELS*2];
  	int cur_reg_start;
  	int mc;
  	int channel;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1299
  	int participants[KNL_MAX_CHANNELS];
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
  
  	for (i = 0; i < KNL_MAX_CHANNELS; i++)
  		mc_sizes[i] = 0;
  
  	/* Read the EDC route table in each CHA. */
  	cur_reg_start = 0;
  	for (i = 0; i < KNL_MAX_CHAS; i++) {
  		pci_read_config_dword(pvt->knl.pci_cha[i],
  				KNL_EDC_ROUTE, &edc_route_reg[i]);
  
  		if (i > 0 && edc_route_reg[i] != edc_route_reg[i-1]) {
  			knl_show_edc_route(edc_route_reg[i-1],
  					edc_route_string);
  			if (cur_reg_start == i-1)
  				edac_dbg(0, "edc route table for CHA %d: %s
  ",
  					cur_reg_start, edc_route_string);
  			else
  				edac_dbg(0, "edc route table for CHA %d-%d: %s
  ",
  					cur_reg_start, i-1, edc_route_string);
  			cur_reg_start = i;
  		}
  	}
  	knl_show_edc_route(edc_route_reg[i-1], edc_route_string);
  	if (cur_reg_start == i-1)
  		edac_dbg(0, "edc route table for CHA %d: %s
  ",
  			cur_reg_start, edc_route_string);
  	else
  		edac_dbg(0, "edc route table for CHA %d-%d: %s
  ",
  			cur_reg_start, i-1, edc_route_string);
  
  	/* Read the MC route table in each CHA. */
  	cur_reg_start = 0;
  	for (i = 0; i < KNL_MAX_CHAS; i++) {
  		pci_read_config_dword(pvt->knl.pci_cha[i],
  			KNL_MC_ROUTE, &mc_route_reg[i]);
  
  		if (i > 0 && mc_route_reg[i] != mc_route_reg[i-1]) {
  			knl_show_mc_route(mc_route_reg[i-1], mc_route_string);
  			if (cur_reg_start == i-1)
  				edac_dbg(0, "mc route table for CHA %d: %s
  ",
  					cur_reg_start, mc_route_string);
  			else
  				edac_dbg(0, "mc route table for CHA %d-%d: %s
  ",
  					cur_reg_start, i-1, mc_route_string);
  			cur_reg_start = i;
  		}
  	}
  	knl_show_mc_route(mc_route_reg[i-1], mc_route_string);
  	if (cur_reg_start == i-1)
  		edac_dbg(0, "mc route table for CHA %d: %s
  ",
  			cur_reg_start, mc_route_string);
  	else
  		edac_dbg(0, "mc route table for CHA %d-%d: %s
  ",
  			cur_reg_start, i-1, mc_route_string);
  
  	/* Process DRAM rules */
  	for (sad_rule = 0; sad_rule < pvt->info.max_sad; sad_rule++) {
  		/* previous limit becomes the new base */
  		sad_base = sad_limit;
  
  		pci_read_config_dword(pvt->pci_sad0,
  			pvt->info.dram_rule[sad_rule], &dram_rule);
  
  		if (!DRAM_RULE_ENABLE(dram_rule))
  			break;
  
  		edram_only = KNL_EDRAM_ONLY(dram_rule);
  
  		sad_limit = pvt->info.sad_limit(dram_rule)+1;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
  
  		pci_read_config_dword(pvt->pci_sad0,
  			pvt->info.interleave_list[sad_rule], &interleave_reg);
  
  		/*
  		 * Find out how many ways this dram rule is interleaved.
  		 * We stop when we see the first channel again.
  		 */
  		first_pkg = sad_pkg(pvt->info.interleave_pkg,
  						interleave_reg, 0);
  		for (intrlv_ways = 1; intrlv_ways < 8; intrlv_ways++) {
  			pkg = sad_pkg(pvt->info.interleave_pkg,
  						interleave_reg, intrlv_ways);
  
  			if ((pkg & 0x8) == 0) {
  				/*
  				 * 0 bit means memory is non-local,
  				 * which KNL doesn't support
  				 */
  				edac_dbg(0, "Unexpected interleave target %d
  ",
  					pkg);
  				return -1;
  			}
  
  			if (pkg == first_pkg)
  				break;
  		}
  		if (KNL_MOD3(dram_rule))
  			intrlv_ways *= 3;
  
  		edac_dbg(3, "dram rule %d (base 0x%llx, limit 0x%llx), %d way interleave%s
  ",
  			sad_rule,
  			sad_base,
  			sad_limit,
  			intrlv_ways,
  			edram_only ? ", EDRAM" : "");
  
  		/*
  		 * Find out how big the SAD region really is by iterating
  		 * over TAD tables (SAD regions may contain holes).
  		 * Each memory controller might have a different TAD table, so
  		 * we have to look at both.
  		 *
  		 * Livespace is the memory that's mapped in this TAD table,
  		 * deadspace is the holes (this could be the MMIO hole, or it
  		 * could be memory that's mapped by the other TAD table but
  		 * not this one).
  		 */
  		for (mc = 0; mc < 2; mc++) {
  			sad_actual_size[mc] = 0;
  			tad_livespace = 0;
  			for (tad_rule = 0;
  					tad_rule < ARRAY_SIZE(
  						knl_tad_dram_limit_lo);
  					tad_rule++) {
  				if (knl_get_tad(pvt,
  						tad_rule,
  						mc,
  						&tad_deadspace,
  						&tad_limit,
  						&tad_ways))
  					break;
  
  				tad_size = (tad_limit+1) -
  					(tad_livespace + tad_deadspace);
  				tad_livespace += tad_size;
  				tad_base = (tad_limit+1) - tad_size;
  
  				if (tad_base < sad_base) {
  					if (tad_limit > sad_base)
  						edac_dbg(0, "TAD region overlaps lower SAD boundary -- TAD tables may be configured incorrectly.
  ");
  				} else if (tad_base < sad_limit) {
  					if (tad_limit+1 > sad_limit) {
  						edac_dbg(0, "TAD region overlaps upper SAD boundary -- TAD tables may be configured incorrectly.
  ");
  					} else {
  						/* TAD region is completely inside SAD region */
  						edac_dbg(3, "TAD region %d 0x%llx - 0x%llx (%lld bytes) table%d
  ",
  							tad_rule, tad_base,
  							tad_limit, tad_size,
  							mc);
  						sad_actual_size[mc] += tad_size;
  					}
  				}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
  			}
  		}
  
  		for (mc = 0; mc < 2; mc++) {
  			edac_dbg(3, " total TAD DRAM footprint in table%d : 0x%llx (%lld bytes)
  ",
  				mc, sad_actual_size[mc], sad_actual_size[mc]);
  		}
  
  		/* Ignore EDRAM rule */
  		if (edram_only)
  			continue;
  
  		/* Figure out which channels participate in interleave. */
  		for (channel = 0; channel < KNL_MAX_CHANNELS; channel++)
  			participants[channel] = 0;
  
  		/* For each channel, does at least one CHA have
  		 * this channel mapped to the given target?
  		 */
  		for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) {
24281a2f4   Luis Felipe Sandoval Castro   EDAC, sb_edac: Fi...
1486
1487
  			int target;
  			int cha;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1488

24281a2f4   Luis Felipe Sandoval Castro   EDAC, sb_edac: Fi...
1489
  			for (target = 0; target < KNL_MAX_CHANNELS; target++) {
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1490
1491
1492
  				for (cha = 0; cha < KNL_MAX_CHAS; cha++) {
  					if (knl_get_mc_route(target,
  						mc_route_reg[cha]) == channel
83bdaad4d   Hubert Chrzaniuk   EDAC, sb_edac: Fi...
1493
  						&& !participants[channel]) {
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1494
1495
1496
1497
1498
1499
  						participants[channel] = 1;
  						break;
  					}
  				}
  			}
  		}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
  		for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) {
  			mc = knl_channel_mc(channel);
  			if (participants[channel]) {
  				edac_dbg(4, "mc channel %d contributes %lld bytes via sad entry %d
  ",
  					channel,
  					sad_actual_size[mc]/intrlv_ways,
  					sad_rule);
  				mc_sizes[channel] +=
  					sad_actual_size[mc]/intrlv_ways;
  			}
  		}
  	}
  
  	return 0;
  }
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
  static void get_source_id(struct mem_ctl_info *mci)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	u32 reg;
  
  	if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL ||
  	    pvt->info.type == KNIGHTS_LANDING)
  		pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
  	else
  		pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
  
  	if (pvt->info.type == KNIGHTS_LANDING)
  		pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg);
  	else
  		pvt->sbridge_dev->source_id = SOURCE_ID(reg);
  }
4d475dde7   Qiuxu Zhuo   EDAC, sb_edac: Ch...
1532
1533
1534
  static int __populate_dimms(struct mem_ctl_info *mci,
  			    u64 knl_mc_sizes[KNL_MAX_CHANNELS],
  			    enum edac_type mode)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1535
1536
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1537
1538
1539
  	int channels = pvt->info.type == KNIGHTS_LANDING ? KNL_MAX_CHANNELS
  							 : NUM_CHANNELS;
  	unsigned int i, j, banks, ranks, rows, cols, npages;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
1540
  	struct dimm_info *dimm;
c6e13b528   Mark A. Grondona   EDAC: Fix incorre...
1541
  	enum mem_type mtype;
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1542
  	u64 size;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1543

9e3754461   Aristeu Rozanski   sb_edac: make mem...
1544
  	mtype = pvt->info.get_memory_type(pvt);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1545
  	if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4)
9e3754461   Aristeu Rozanski   sb_edac: make mem...
1546
1547
1548
  		edac_dbg(0, "Memory is registered
  ");
  	else if (mtype == MEM_UNKNOWN)
de4772c62   Tony Luck   edac: sb_edac.c s...
1549
1550
  		edac_dbg(0, "Cannot determine memory type
  ");
9e3754461   Aristeu Rozanski   sb_edac: make mem...
1551
1552
1553
  	else
  		edac_dbg(0, "Memory is unregistered
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1554

fec53af53   Tony Luck   sb_edac: Fix typo...
1555
  	if (mtype == MEM_DDR4 || mtype == MEM_RDDR4)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1556
1557
1558
  		banks = 16;
  	else
  		banks = 8;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1559

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1560
  	for (i = 0; i < channels; i++) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1561
  		u32 mtr;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
  		int max_dimms_per_channel;
  
  		if (pvt->info.type == KNIGHTS_LANDING) {
  			max_dimms_per_channel = 1;
  			if (!pvt->knl.pci_channel[i])
  				continue;
  		} else {
  			max_dimms_per_channel = ARRAY_SIZE(mtr_regs);
  			if (!pvt->pci_tad[i])
  				continue;
  		}
  
  		for (j = 0; j < max_dimms_per_channel; j++) {
bc9ad9e40   Robert Richter   EDAC: Replace EDA...
1575
  			dimm = edac_get_dimm(mci, i, j, 0);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1576
1577
1578
1579
1580
1581
1582
  			if (pvt->info.type == KNIGHTS_LANDING) {
  				pci_read_config_dword(pvt->knl.pci_channel[i],
  					knl_mtr_reg, &mtr);
  			} else {
  				pci_read_config_dword(pvt->pci_tad[i],
  					mtr_regs[j], &mtr);
  			}
956b9ba15   Joe Perches   edac: Convert deb...
1583
1584
  			edac_dbg(4, "Channel #%d  MTR%d = %x
  ", i, j, mtr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1585
  			if (IS_DIMM_PRESENT(mtr)) {
4d475dde7   Qiuxu Zhuo   EDAC, sb_edac: Ch...
1586
1587
1588
1589
1590
1591
1592
  				if (!IS_ECC_ENABLED(pvt->info.mcmtr)) {
  					sbridge_printk(KERN_ERR, "CPU SrcID #%d, Ha #%d, Channel #%d has DIMMs, but ECC is disabled
  ",
  						       pvt->sbridge_dev->source_id,
  						       pvt->sbridge_dev->dom, i);
  					return -ENODEV;
  				}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1593
  				pvt->channel[i].dimms++;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1594
  				ranks = numrank(pvt->info.type, mtr);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
  
  				if (pvt->info.type == KNIGHTS_LANDING) {
  					/* For DDR4, this is fixed. */
  					cols = 1 << 10;
  					rows = knl_mc_sizes[i] /
  						((u64) cols * ranks * banks * 8);
  				} else {
  					rows = numrow(mtr);
  					cols = numcol(mtr);
  				}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1605

deb09ddaf   Mauro Carvalho Chehab   sb_edac: Avoid ov...
1606
  				size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1607
  				npages = MiB_TO_PAGES(size);
6f6da1360   Qiuxu Zhuo   EDAC: Correct DIM...
1608
1609
  				edac_dbg(0, "mc#%d: ha %d channel %d, dimm %d, %lld MiB (%d pages) bank: %d, rank: %d, row: %#x, col: %#x
  ",
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
1610
  					 pvt->sbridge_dev->mc, pvt->sbridge_dev->dom, i, j,
956b9ba15   Joe Perches   edac: Convert deb...
1611
1612
  					 size, npages,
  					 banks, ranks, rows, cols);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1613

a895bf8b1   Mauro Carvalho Chehab   edac: move nr_pag...
1614
  				dimm->nr_pages = npages;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
1615
  				dimm->grain = 32;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
1616
  				dimm->dtype = pvt->info.get_width(pvt, mtr);
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
1617
1618
1619
  				dimm->mtype = mtype;
  				dimm->edac_mode = mode;
  				snprintf(dimm->label, sizeof(dimm->label),
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
1620
1621
  						 "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u",
  						 pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom, i, j);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1622
1623
1624
  			}
  		}
  	}
4d475dde7   Qiuxu Zhuo   EDAC, sb_edac: Ch...
1625
1626
  
  	return 0;
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1627
1628
1629
1630
1631
1632
1633
1634
  }
  
  static int get_dimm_config(struct mem_ctl_info *mci)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	u64 knl_mc_sizes[KNL_MAX_CHANNELS];
  	enum edac_type mode;
  	u32 reg;
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
  	pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
  	edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d
  ",
  		 pvt->sbridge_dev->mc,
  		 pvt->sbridge_dev->node_id,
  		 pvt->sbridge_dev->source_id);
  
  	/* KNL doesn't support mirroring or lockstep,
  	 * and is always closed page
  	 */
  	if (pvt->info.type == KNIGHTS_LANDING) {
  		mode = EDAC_S4ECD4ED;
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
1647
1648
  		pvt->mirror_mode = NON_MIRRORING;
  		pvt->is_cur_addr_mirrored = false;
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1649
1650
1651
  
  		if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
  			return -1;
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
1652
1653
1654
1655
1656
  		if (pci_read_config_dword(pvt->pci_ta, KNL_MCMTR, &pvt->info.mcmtr)) {
  			edac_dbg(0, "Failed to read KNL_MCMTR register
  ");
  			return -ENODEV;
  		}
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1657
  	} else {
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
  		if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
  			if (pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, &reg)) {
  				edac_dbg(0, "Failed to read HASWELL_HASYSDEFEATURE2 register
  ");
  				return -ENODEV;
  			}
  			pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21);
  			if (GET_BITFIELD(reg, 28, 28)) {
  				pvt->mirror_mode = ADDR_RANGE_MIRRORING;
  				edac_dbg(0, "Address range partial memory mirroring is enabled
  ");
  				goto next;
  			}
  		}
  		if (pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg)) {
  			edac_dbg(0, "Failed to read RASENABLES register
  ");
  			return -ENODEV;
  		}
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1677
  		if (IS_MIRROR_ENABLED(reg)) {
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
1678
1679
1680
  			pvt->mirror_mode = FULL_MIRRORING;
  			edac_dbg(0, "Full memory mirroring is enabled
  ");
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1681
  		} else {
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
1682
1683
1684
  			pvt->mirror_mode = NON_MIRRORING;
  			edac_dbg(0, "Memory mirroring is disabled
  ");
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1685
  		}
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
1686
1687
1688
1689
1690
1691
  next:
  		if (pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr)) {
  			edac_dbg(0, "Failed to read MCMTR register
  ");
  			return -ENODEV;
  		}
669652295   Borislav Petkov   EDAC, sb_edac: Ca...
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
  		if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
  			edac_dbg(0, "Lockstep is enabled
  ");
  			mode = EDAC_S8ECD8ED;
  			pvt->is_lockstep = true;
  		} else {
  			edac_dbg(0, "Lockstep is disabled
  ");
  			mode = EDAC_S4ECD4ED;
  			pvt->is_lockstep = false;
  		}
  		if (IS_CLOSE_PG(pvt->info.mcmtr)) {
  			edac_dbg(0, "address map is on closed page mode
  ");
  			pvt->is_close_pg = true;
  		} else {
  			edac_dbg(0, "address map is on open page mode
  ");
  			pvt->is_close_pg = false;
  		}
  	}
4d475dde7   Qiuxu Zhuo   EDAC, sb_edac: Ch...
1713
  	return __populate_dimms(mci, knl_mc_sizes, mode);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1714
1715
1716
1717
1718
1719
1720
1721
1722
  }
  
  static void get_memory_layout(const struct mem_ctl_info *mci)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	int i, j, k, n_sads, n_tads, sad_interl;
  	u32 reg;
  	u64 limit, prv = 0;
  	u64 tmp_mb;
8c0091002   Jim Snow   sb_edac: Fix erro...
1723
  	u32 gb, mb;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1724
1725
1726
1727
1728
  	u32 rir_way;
  
  	/*
  	 * Step 1) Get TOLM/TOHM ranges
  	 */
fb79a5092   Aristeu Rozanski   sb_edac: isolate ...
1729
  	pvt->tolm = pvt->info.get_tolm(pvt);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1730
  	tmp_mb = (1 + pvt->tolm) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1731
1732
1733
1734
  	gb = div_u64_rem(tmp_mb, 1024, &mb);
  	edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)
  ",
  		gb, (mb*1000)/1024, (u64)pvt->tolm);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1735
1736
  
  	/* Address range is already 45:25 */
8fd6a43ac   Aristeu Rozanski   sb_edac: isolate ...
1737
  	pvt->tohm = pvt->info.get_tohm(pvt);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1738
  	tmp_mb = (1 + pvt->tohm) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1739
1740
1741
1742
  	gb = div_u64_rem(tmp_mb, 1024, &mb);
  	edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)
  ",
  		gb, (mb*1000)/1024, (u64)pvt->tohm);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1743
1744
1745
1746
1747
1748
1749
1750
  
  	/*
  	 * Step 2) Get SAD range and SAD Interleave list
  	 * TAD registers contain the interleave wayness. However, it
  	 * seems simpler to just discover it indirectly, with the
  	 * algorithm bellow.
  	 */
  	prv = 0;
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1751
  	for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1752
  		/* SAD_LIMIT Address range is 45:26 */
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1753
  		pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1754
  				      &reg);
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1755
  		limit = pvt->info.sad_limit(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1756
1757
1758
1759
1760
1761
1762
1763
  
  		if (!DRAM_RULE_ENABLE(reg))
  			continue;
  
  		if (limit <= prv)
  			break;
  
  		tmp_mb = (limit + 1) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1764
  		gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1765
1766
1767
  		edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x
  ",
  			 n_sads,
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1768
  			 show_dram_attr(pvt->info.dram_attr(reg)),
8c0091002   Jim Snow   sb_edac: Fix erro...
1769
  			 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1770
  			 ((u64)tmp_mb) << 20L,
127c1225b   Nicolas Iooss   EDAC, sb_edac: Ge...
1771
  			 get_intlv_mode_str(reg, pvt->info.type),
956b9ba15   Joe Perches   edac: Convert deb...
1772
  			 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1773
  		prv = limit;
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
1774
  		pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1775
  				      &reg);
cc311991a   Aristeu Rozanski   sb_edac: rework s...
1776
  		sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1777
  		for (j = 0; j < 8; j++) {
cc311991a   Aristeu Rozanski   sb_edac: rework s...
1778
1779
  			u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, j);
  			if (j > 0 && sad_interl == pkg)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1780
  				break;
956b9ba15   Joe Perches   edac: Convert deb...
1781
1782
  			edac_dbg(0, "SAD#%d, interleave #%d: %d
  ",
cc311991a   Aristeu Rozanski   sb_edac: rework s...
1783
  				 n_sads, j, pkg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1784
1785
  		}
  	}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1786
1787
  	if (pvt->info.type == KNIGHTS_LANDING)
  		return;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1788
1789
1790
1791
1792
  	/*
  	 * Step 3) Get TAD range
  	 */
  	prv = 0;
  	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
1793
  		pci_read_config_dword(pvt->pci_ha, tad_dram_rule[n_tads], &reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1794
1795
1796
1797
  		limit = TAD_LIMIT(reg);
  		if (limit <= prv)
  			break;
  		tmp_mb = (limit + 1) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1798
  		gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1799
1800
  		edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x
  ",
8c0091002   Jim Snow   sb_edac: Fix erro...
1801
  			 n_tads, gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1802
  			 ((u64)tmp_mb) << 20L,
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
1803
1804
  			 (u32)(1 << TAD_SOCK(reg)),
  			 (u32)TAD_CH(reg) + 1,
956b9ba15   Joe Perches   edac: Convert deb...
1805
1806
1807
1808
1809
  			 (u32)TAD_TGT0(reg),
  			 (u32)TAD_TGT1(reg),
  			 (u32)TAD_TGT2(reg),
  			 (u32)TAD_TGT3(reg),
  			 reg);
7fae0db43   Hui Wang   edac: sb_edac: Fi...
1810
  		prv = limit;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
  	}
  
  	/*
  	 * Step 4) Get TAD offsets, per each channel
  	 */
  	for (i = 0; i < NUM_CHANNELS; i++) {
  		if (!pvt->channel[i].dimms)
  			continue;
  		for (j = 0; j < n_tads; j++) {
  			pci_read_config_dword(pvt->pci_tad[i],
  					      tad_ch_nilv_offset[j],
  					      &reg);
  			tmp_mb = TAD_OFFSET(reg) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1824
  			gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1825
1826
1827
  			edac_dbg(0, "TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x
  ",
  				 i, j,
8c0091002   Jim Snow   sb_edac: Fix erro...
1828
  				 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1829
1830
  				 ((u64)tmp_mb) << 20L,
  				 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
  		}
  	}
  
  	/*
  	 * Step 6) Get RIR Wayness/Limit, per each channel
  	 */
  	for (i = 0; i < NUM_CHANNELS; i++) {
  		if (!pvt->channel[i].dimms)
  			continue;
  		for (j = 0; j < MAX_RIR_RANGES; j++) {
  			pci_read_config_dword(pvt->pci_tad[i],
  					      rir_way_limit[j],
  					      &reg);
  
  			if (!IS_RIR_VALID(reg))
  				continue;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
1847
  			tmp_mb = pvt->info.rir_limit(reg) >> 20;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1848
  			rir_way = 1 << RIR_WAY(reg);
8c0091002   Jim Snow   sb_edac: Fix erro...
1849
  			gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1850
1851
1852
  			edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x
  ",
  				 i, j,
8c0091002   Jim Snow   sb_edac: Fix erro...
1853
  				 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1854
1855
1856
  				 ((u64)tmp_mb) << 20L,
  				 rir_way,
  				 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1857
1858
1859
1860
1861
  
  			for (k = 0; k < rir_way; k++) {
  				pci_read_config_dword(pvt->pci_tad[i],
  						      rir_offset[j][k],
  						      &reg);
c7103f650   Tony Luck   EDAC, sb_edac: Fi...
1862
  				tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1863

8c0091002   Jim Snow   sb_edac: Fix erro...
1864
  				gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1865
1866
1867
  				edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x
  ",
  					 i, j, k,
8c0091002   Jim Snow   sb_edac: Fix erro...
1868
  					 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1869
  					 ((u64)tmp_mb) << 20L,
c7103f650   Tony Luck   EDAC, sb_edac: Fi...
1870
  					 (u32)RIR_RNK_TGT(pvt->info.type, reg),
956b9ba15   Joe Perches   edac: Convert deb...
1871
  					 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1872
1873
1874
1875
  			}
  		}
  	}
  }
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
1876
  static struct mem_ctl_info *get_mci_for_node_id(u8 node_id, u8 ha)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1877
1878
1879
1880
  {
  	struct sbridge_dev *sbridge_dev;
  
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
1881
  		if (sbridge_dev->node_id == node_id && sbridge_dev->dom == ha)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1882
1883
1884
1885
1886
1887
1888
  			return sbridge_dev->mci;
  	}
  	return NULL;
  }
  
  static int get_memory_error_data(struct mem_ctl_info *mci,
  				 u64 addr,
7d375bffa   Tony Luck   sb_edac: Fix supp...
1889
  				 u8 *socket, u8 *ha,
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1890
1891
  				 long *channel_mask,
  				 u8 *rank,
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
1892
  				 char **area_type, char *msg)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1893
1894
1895
  {
  	struct mem_ctl_info	*new_mci;
  	struct sbridge_pvt *pvt = mci->pvt_info;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1896
  	struct pci_dev		*pci_ha;
c41afdca2   Mauro Carvalho Chehab   sb_edac: Fix mix ...
1897
  	int			n_rir, n_sads, n_tads, sad_way, sck_xch;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1898
  	int			sad_interl, idx, base_ch;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1899
  	int			interleave_mode, shiftup = 0;
6fd052665   Gustavo A. R. Silva   EDAC, sb_edac: Re...
1900
  	unsigned int		sad_interleave[MAX_INTERLEAVE];
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1901
  	u32			reg, dram_rule;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
1902
  	u8			ch_way, sck_way, pkg, sad_ha = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1903
1904
  	u32			tad_offset;
  	u32			rir_way;
8c0091002   Jim Snow   sb_edac: Fix erro...
1905
  	u32			mb, gb;
bd4b96836   Aristeu Rozanski   sb_edac: Shut up ...
1906
  	u64			ch_addr, offset, limit = 0, prv = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1907
1908
1909
1910
1911
1912
1913
1914
1915
  
  
  	/*
  	 * Step 0) Check if the address is at special memory ranges
  	 * The check bellow is probably enough to fill all cases where
  	 * the error is not inside a memory, except for the legacy
  	 * range (e. g. VGA addresses). It is unlikely, however, that the
  	 * memory controller would generate an error on that range.
  	 */
5b889e379   Mauro Carvalho Chehab   Fix sb_edac compi...
1916
  	if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1917
  		sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1918
1919
1920
1921
  		return -EINVAL;
  	}
  	if (addr >= (u64)pvt->tohm) {
  		sprintf(msg, "Error at MMIOH area, on addr 0x%016Lx", addr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1922
1923
1924
1925
1926
1927
  		return -EINVAL;
  	}
  
  	/*
  	 * Step 1) Get socket
  	 */
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1928
1929
  	for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) {
  		pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1930
1931
1932
1933
  				      &reg);
  
  		if (!DRAM_RULE_ENABLE(reg))
  			continue;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1934
  		limit = pvt->info.sad_limit(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1935
1936
  		if (limit <= prv) {
  			sprintf(msg, "Can't discover the memory socket");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1937
1938
1939
1940
1941
1942
  			return -EINVAL;
  		}
  		if  (addr <= limit)
  			break;
  		prv = limit;
  	}
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1943
  	if (n_sads == pvt->info.max_sad) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1944
  		sprintf(msg, "Can't discover the memory socket");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1945
1946
  		return -EINVAL;
  	}
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1947
  	dram_rule = reg;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1948
1949
  	*area_type = show_dram_attr(pvt->info.dram_attr(dram_rule));
  	interleave_mode = pvt->info.interleave_mode(dram_rule);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1950

ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
1951
  	pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1952
  			      &reg);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
  
  	if (pvt->info.type == SANDY_BRIDGE) {
  		sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0);
  		for (sad_way = 0; sad_way < 8; sad_way++) {
  			u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, sad_way);
  			if (sad_way > 0 && sad_interl == pkg)
  				break;
  			sad_interleave[sad_way] = pkg;
  			edac_dbg(0, "SAD interleave #%d: %d
  ",
  				 sad_way, sad_interleave[sad_way]);
  		}
  		edac_dbg(0, "mc#%d: Error detected on SAD#%d: address 0x%016Lx < 0x%016Lx, Interleave [%d:6]%s
  ",
  			 pvt->sbridge_dev->mc,
  			 n_sads,
  			 addr,
  			 limit,
  			 sad_way + 7,
  			 !interleave_mode ? "" : "XOR[18:16]");
  		if (interleave_mode)
  			idx = ((addr >> 6) ^ (addr >> 16)) & 7;
  		else
  			idx = (addr >> 6) & 7;
  		switch (sad_way) {
  		case 1:
  			idx = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1980
  			break;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
  		case 2:
  			idx = idx & 1;
  			break;
  		case 4:
  			idx = idx & 3;
  			break;
  		case 8:
  			break;
  		default:
  			sprintf(msg, "Can't discover socket interleave");
  			return -EINVAL;
  		}
  		*socket = sad_interleave[idx];
  		edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d
  ",
  			 idx, sad_way, *socket);
1f39581a9   Tony Luck   sb_edac: Add supp...
1997
  	} else if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1998
1999
2000
2001
2002
2003
2004
  		int bits, a7mode = A7MODE(dram_rule);
  
  		if (a7mode) {
  			/* A7 mode swaps P9 with P6 */
  			bits = GET_BITFIELD(addr, 7, 8) << 1;
  			bits |= GET_BITFIELD(addr, 9, 9);
  		} else
bb89e7141   Tony Luck   sb_edac: Fix a ty...
2005
  			bits = GET_BITFIELD(addr, 6, 8);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2006

bb89e7141   Tony Luck   sb_edac: Fix a ty...
2007
  		if (interleave_mode == 0) {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
  			/* interleave mode will XOR {8,7,6} with {18,17,16} */
  			idx = GET_BITFIELD(addr, 16, 18);
  			idx ^= bits;
  		} else
  			idx = bits;
  
  		pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
  		*socket = sad_pkg_socket(pkg);
  		sad_ha = sad_pkg_ha(pkg);
  
  		if (a7mode) {
  			/* MCChanShiftUpEnable */
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2020
  			pci_read_config_dword(pvt->pci_ha, HASWELL_HASYSDEFEATURE2, &reg);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2021
2022
2023
2024
2025
2026
  			shiftup = GET_BITFIELD(reg, 22, 22);
  		}
  
  		edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %i, shiftup: %i
  ",
  			 idx, *socket, sad_ha, shiftup);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2027
2028
  	} else {
  		/* Ivy Bridge's SAD mode doesn't support XOR interleave mode */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2029
  		idx = (addr >> 6) & 7;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2030
2031
2032
2033
2034
2035
  		pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
  		*socket = sad_pkg_socket(pkg);
  		sad_ha = sad_pkg_ha(pkg);
  		edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d
  ",
  			 idx, *socket, sad_ha);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2036
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2037

7d375bffa   Tony Luck   sb_edac: Fix supp...
2038
  	*ha = sad_ha;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2039
2040
2041
2042
  	/*
  	 * Move to the proper node structure, in order to access the
  	 * right PCI registers
  	 */
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2043
  	new_mci = get_mci_for_node_id(*socket, sad_ha);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2044
2045
2046
  	if (!new_mci) {
  		sprintf(msg, "Struct for socket #%u wasn't initialized",
  			*socket);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2047
2048
2049
2050
2051
2052
2053
2054
2055
  		return -EINVAL;
  	}
  	mci = new_mci;
  	pvt = mci->pvt_info;
  
  	/*
  	 * Step 2) Get memory channel
  	 */
  	prv = 0;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2056
  	pci_ha = pvt->pci_ha;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2057
  	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2058
  		pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], &reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2059
2060
2061
  		limit = TAD_LIMIT(reg);
  		if (limit <= prv) {
  			sprintf(msg, "Can't discover the memory channel");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2062
2063
2064
2065
2066
2067
  			return -EINVAL;
  		}
  		if  (addr <= limit)
  			break;
  		prv = limit;
  	}
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2068
2069
2070
2071
  	if (n_tads == MAX_TAD) {
  		sprintf(msg, "Can't discover the memory channel");
  		return -EINVAL;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2072
  	ch_way = TAD_CH(reg) + 1;
ff15e95c8   Tony Luck   x86 EDAC, sb_edac...
2073
  	sck_way = TAD_SOCK(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2074
2075
2076
  
  	if (ch_way == 3)
  		idx = addr >> 6;
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
2077
  	else {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2078
  		idx = (addr >> (6 + sck_way + shiftup)) & 0x3;
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
2079
2080
2081
  		if (pvt->is_chan_hash)
  			idx = haswell_chan_hash(idx, addr);
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
  	idx = idx % ch_way;
  
  	/*
  	 * FIXME: Shouldn't we use CHN_IDX_OFFSET() here, when ch_way == 3 ???
  	 */
  	switch (idx) {
  	case 0:
  		base_ch = TAD_TGT0(reg);
  		break;
  	case 1:
  		base_ch = TAD_TGT1(reg);
  		break;
  	case 2:
  		base_ch = TAD_TGT2(reg);
  		break;
  	case 3:
  		base_ch = TAD_TGT3(reg);
  		break;
  	default:
  		sprintf(msg, "Can't discover the TAD target");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2102
2103
2104
  		return -EINVAL;
  	}
  	*channel_mask = 1 << base_ch;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2105
  	pci_read_config_dword(pvt->pci_tad[base_ch], tad_ch_nilv_offset[n_tads], &tad_offset);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2106

039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2107
2108
  	if (pvt->mirror_mode == FULL_MIRRORING ||
  	    (pvt->mirror_mode == ADDR_RANGE_MIRRORING && n_tads == 0)) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2109
2110
2111
2112
  		*channel_mask |= 1 << ((base_ch + 2) % 4);
  		switch(ch_way) {
  		case 2:
  		case 4:
ff15e95c8   Tony Luck   x86 EDAC, sb_edac...
2113
  			sck_xch = (1 << sck_way) * (ch_way >> 1);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2114
2115
2116
  			break;
  		default:
  			sprintf(msg, "Invalid mirror set. Can't decode addr");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2117
2118
  			return -EINVAL;
  		}
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2119
2120
2121
  
  		pvt->is_cur_addr_mirrored = true;
  	} else {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2122
  		sck_xch = (1 << sck_way) * ch_way;
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2123
2124
  		pvt->is_cur_addr_mirrored = false;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2125
2126
2127
2128
2129
  
  	if (pvt->is_lockstep)
  		*channel_mask |= 1 << ((base_ch + 1) % 4);
  
  	offset = TAD_OFFSET(tad_offset);
956b9ba15   Joe Perches   edac: Convert deb...
2130
2131
2132
2133
2134
  	edac_dbg(0, "TAD#%d: address 0x%016Lx < 0x%016Lx, socket interleave %d, channel interleave %d (offset 0x%08Lx), index %d, base ch: %d, ch mask: 0x%02lx
  ",
  		 n_tads,
  		 addr,
  		 limit,
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
2135
  		 sck_way,
956b9ba15   Joe Perches   edac: Convert deb...
2136
2137
2138
2139
2140
  		 ch_way,
  		 offset,
  		 idx,
  		 base_ch,
  		 *channel_mask);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2141
2142
2143
2144
2145
2146
2147
  
  	/* Calculate channel address */
  	/* Remove the TAD offset */
  
  	if (offset > addr) {
  		sprintf(msg, "Can't calculate ch addr: TAD offset 0x%08Lx is too high for addr 0x%08Lx!",
  			offset, addr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2148
2149
  		return -EINVAL;
  	}
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
2150
2151
2152
  
  	ch_addr = addr - offset;
  	ch_addr >>= (6 + shiftup);
ff15e95c8   Tony Luck   x86 EDAC, sb_edac...
2153
  	ch_addr /= sck_xch;
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
2154
2155
  	ch_addr <<= (6 + shiftup);
  	ch_addr |= addr & ((1 << (6 + shiftup)) - 1);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2156
2157
2158
2159
2160
  
  	/*
  	 * Step 3) Decode rank
  	 */
  	for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2161
  		pci_read_config_dword(pvt->pci_tad[base_ch], rir_way_limit[n_rir], &reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2162
2163
2164
  
  		if (!IS_RIR_VALID(reg))
  			continue;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
2165
  		limit = pvt->info.rir_limit(reg);
8c0091002   Jim Snow   sb_edac: Fix erro...
2166
  		gb = div_u64_rem(limit >> 20, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
2167
2168
2169
  		edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d
  ",
  			 n_rir,
8c0091002   Jim Snow   sb_edac: Fix erro...
2170
  			 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
2171
2172
  			 limit,
  			 1 << RIR_WAY(reg));
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2173
2174
2175
2176
2177
2178
  		if  (ch_addr <= limit)
  			break;
  	}
  	if (n_rir == MAX_RIR_RANGES) {
  		sprintf(msg, "Can't discover the memory rank for ch addr 0x%08Lx",
  			ch_addr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2179
2180
2181
  		return -EINVAL;
  	}
  	rir_way = RIR_WAY(reg);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2182

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2183
2184
2185
2186
2187
  	if (pvt->is_close_pg)
  		idx = (ch_addr >> 6);
  	else
  		idx = (ch_addr >> 13);	/* FIXME: Datasheet says to shift by 15 */
  	idx %= 1 << rir_way;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2188
  	pci_read_config_dword(pvt->pci_tad[base_ch], rir_offset[n_rir][idx], &reg);
c7103f650   Tony Luck   EDAC, sb_edac: Fi...
2189
  	*rank = RIR_RNK_TGT(pvt->info.type, reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2190

956b9ba15   Joe Perches   edac: Convert deb...
2191
2192
2193
2194
2195
2196
2197
  	edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d
  ",
  		 n_rir,
  		 ch_addr,
  		 limit,
  		 rir_way,
  		 idx);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2198
2199
2200
  
  	return 0;
  }
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
  static int get_memory_error_data_from_mce(struct mem_ctl_info *mci,
  					  const struct mce *m, u8 *socket,
  					  u8 *ha, long *channel_mask,
  					  char *msg)
  {
  	u32 reg, channel = GET_BITFIELD(m->status, 0, 3);
  	struct mem_ctl_info *new_mci;
  	struct sbridge_pvt *pvt;
  	struct pci_dev *pci_ha;
  	bool tad0;
  
  	if (channel >= NUM_CHANNELS) {
  		sprintf(msg, "Invalid channel 0x%x", channel);
  		return -EINVAL;
  	}
  
  	pvt = mci->pvt_info;
  	if (!pvt->info.get_ha) {
  		sprintf(msg, "No get_ha()");
  		return -EINVAL;
  	}
  	*ha = pvt->info.get_ha(m->bank);
  	if (*ha != 0 && *ha != 1) {
  		sprintf(msg, "Impossible bank %d", m->bank);
  		return -EINVAL;
  	}
  
  	*socket = m->socketid;
  	new_mci = get_mci_for_node_id(*socket, *ha);
  	if (!new_mci) {
  		strcpy(msg, "mci socket got corrupted!");
  		return -EINVAL;
  	}
  
  	pvt = new_mci->pvt_info;
  	pci_ha = pvt->pci_ha;
  	pci_read_config_dword(pci_ha, tad_dram_rule[0], &reg);
  	tad0 = m->addr <= TAD_LIMIT(reg);
  
  	*channel_mask = 1 << channel;
  	if (pvt->mirror_mode == FULL_MIRRORING ||
  	    (pvt->mirror_mode == ADDR_RANGE_MIRRORING && tad0)) {
  		*channel_mask |= 1 << ((channel + 2) % 4);
  		pvt->is_cur_addr_mirrored = true;
  	} else {
  		pvt->is_cur_addr_mirrored = false;
  	}
  
  	if (pvt->is_lockstep)
  		*channel_mask |= 1 << ((channel + 1) % 4);
  
  	return 0;
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
  /****************************************************************************
  	Device initialization routines: put/get, init/exit
   ****************************************************************************/
  
  /*
   *	sbridge_put_all_devices	'put' all the devices that we have
   *				reserved via 'get'
   */
  static void sbridge_put_devices(struct sbridge_dev *sbridge_dev)
  {
  	int i;
956b9ba15   Joe Perches   edac: Convert deb...
2265
2266
  	edac_dbg(0, "
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2267
2268
2269
2270
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		struct pci_dev *pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
956b9ba15   Joe Perches   edac: Convert deb...
2271
2272
2273
2274
  		edac_dbg(0, "Removing dev %02x:%02x.%d
  ",
  			 pdev->bus->number,
  			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
  		pci_dev_put(pdev);
  	}
  }
  
  static void sbridge_put_all_devices(void)
  {
  	struct sbridge_dev *sbridge_dev, *tmp;
  
  	list_for_each_entry_safe(sbridge_dev, tmp, &sbridge_edac_list, list) {
  		sbridge_put_devices(sbridge_dev);
  		free_sbridge_dev(sbridge_dev);
  	}
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2288
2289
2290
  static int sbridge_get_onedevice(struct pci_dev **prev,
  				 u8 *num_mc,
  				 const struct pci_id_table *table,
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2291
2292
  				 const unsigned devno,
  				 const int multi_bus)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2293
  {
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2294
  	struct sbridge_dev *sbridge_dev = NULL;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2295
  	const struct pci_id_descr *dev_descr = &table->descr[devno];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2296
  	struct pci_dev *pdev = NULL;
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
2297
  	int seg = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2298
  	u8 bus = 0;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2299
  	int i = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2300

ec5a0b382   Jiang Liu   sb_edac: Degrade ...
2301
  	sbridge_printk(KERN_DEBUG,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2302
2303
  		"Seeking for: PCI ID %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
  		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  
  	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
  			      dev_descr->dev_id, *prev);
  
  	if (!pdev) {
  		if (*prev) {
  			*prev = pdev;
  			return 0;
  		}
  
  		if (dev_descr->optional)
  			return 0;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2317
  		/* if the HA wasn't found */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2318
2319
2320
2321
  		if (devno == 0)
  			return -ENODEV;
  
  		sbridge_printk(KERN_INFO,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2322
2323
  			"Device not found: %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2324
2325
2326
2327
2328
  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  
  		/* End of list, leave */
  		return -ENODEV;
  	}
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
2329
  	seg = pci_domain_nr(pdev->bus);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2330
  	bus = pdev->bus->number;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2331
  next_imc:
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
2332
2333
  	sbridge_dev = get_sbridge_dev(seg, bus, dev_descr->dom,
  				      multi_bus, sbridge_dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2334
  	if (!sbridge_dev) {
15cc3ae00   Qiuxu Zhuo   EDAC, sb_edac: Do...
2335
2336
2337
2338
2339
2340
2341
2342
  		/* If the HA1 wasn't found, don't create EDAC second memory controller */
  		if (dev_descr->dom == IMC1 && devno != 1) {
  			edac_dbg(0, "Skip IMC1: %04x:%04x (since HA1 was absent)
  ",
  				 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  			pci_dev_put(pdev);
  			return 0;
  		}
133e4455c   Qiuxu Zhuo   EDAC, sb_edac: Av...
2343
2344
2345
  
  		if (dev_descr->dom == SOCK)
  			goto out_imc;
190bd6e98   Masayoshi Mizuma   EDAC, sb_edac: Ad...
2346
  		sbridge_dev = alloc_sbridge_dev(seg, bus, dev_descr->dom, table);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2347
2348
2349
2350
2351
2352
  		if (!sbridge_dev) {
  			pci_dev_put(pdev);
  			return -ENOMEM;
  		}
  		(*num_mc)++;
  	}
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2353
  	if (sbridge_dev->pdev[sbridge_dev->i_devs]) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2354
  		sbridge_printk(KERN_ERR,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2355
2356
  			"Duplicated device for %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2357
2358
2359
2360
  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  		pci_dev_put(pdev);
  		return -ENODEV;
  	}
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2361
2362
2363
2364
2365
2366
2367
2368
  	sbridge_dev->pdev[sbridge_dev->i_devs++] = pdev;
  
  	/* pdev belongs to more than one IMC, do extra gets */
  	if (++i > 1)
  		pci_dev_get(pdev);
  
  	if (dev_descr->dom == SOCK && i < table->n_imcs_per_sock)
  		goto next_imc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2369

133e4455c   Qiuxu Zhuo   EDAC, sb_edac: Av...
2370
  out_imc:
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2371
2372
2373
  	/* Be sure that the device is enabled */
  	if (unlikely(pci_enable_device(pdev) < 0)) {
  		sbridge_printk(KERN_ERR,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2374
2375
  			"Couldn't enable %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2376
2377
2378
  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  		return -ENODEV;
  	}
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2379
2380
  	edac_dbg(0, "Detected %04x:%04x
  ",
956b9ba15   Joe Perches   edac: Convert deb...
2381
  		 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
  
  	/*
  	 * As stated on drivers/pci/search.c, the reference count for
  	 * @from is always decremented if it is not %NULL. So, as we need
  	 * to get all devices up to null, we need to do a get for the device
  	 */
  	pci_dev_get(pdev);
  
  	*prev = pdev;
  
  	return 0;
  }
5153a0f94   Aristeu Rozanski   sb_edac: enable m...
2394
2395
  /*
   * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2396
   *			     devices we want to reference for this driver.
5153a0f94   Aristeu Rozanski   sb_edac: enable m...
2397
   * @num_mc: pointer to the memory controllers count, to be incremented in case
c41afdca2   Mauro Carvalho Chehab   sb_edac: Fix mix ...
2398
   *	    of success.
5153a0f94   Aristeu Rozanski   sb_edac: enable m...
2399
2400
2401
2402
   * @table: model specific table
   *
   * returns 0 in case of success or error code
   */
0ba169ac3   Tony Luck   EDAC, sb_edac: Fi...
2403
2404
  static int sbridge_get_all_devices(u8 *num_mc,
  					const struct pci_id_table *table)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2405
2406
2407
  {
  	int i, rc;
  	struct pci_dev *pdev = NULL;
0ba169ac3   Tony Luck   EDAC, sb_edac: Fi...
2408
2409
  	int allow_dups = 0;
  	int multi_bus = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2410

0ba169ac3   Tony Luck   EDAC, sb_edac: Fi...
2411
2412
  	if (table->type == KNIGHTS_LANDING)
  		allow_dups = multi_bus = 1;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2413
  	while (table && table->descr) {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2414
  		for (i = 0; i < table->n_devs_per_sock; i++) {
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2415
2416
2417
2418
2419
  			if (!allow_dups || i == 0 ||
  					table->descr[i].dev_id !=
  						table->descr[i-1].dev_id) {
  				pdev = NULL;
  			}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2420
2421
  			do {
  				rc = sbridge_get_onedevice(&pdev, num_mc,
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2422
  							   table, i, multi_bus);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2423
2424
  				if (rc < 0) {
  					if (i == 0) {
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2425
  						i = table->n_devs_per_sock;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2426
2427
2428
2429
2430
  						break;
  					}
  					sbridge_put_all_devices();
  					return -ENODEV;
  				}
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2431
  			} while (pdev && !allow_dups);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2432
2433
2434
2435
2436
2437
  		}
  		table++;
  	}
  
  	return 0;
  }
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2438
2439
2440
2441
2442
2443
  /*
   * Device IDs for {SBRIDGE,IBRIDGE,HASWELL,BROADWELL}_IMC_HA0_TAD0 are in
   * the format: XXXa. So we can convert from a device to the corresponding
   * channel like this
   */
  #define TAD_DEV_TO_CHAN(dev) (((dev) & 0xf) - 0xa)
ea779b5a0   Aristeu Rozanski   sb_edac: rename m...
2444
2445
  static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
  				 struct sbridge_dev *sbridge_dev)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2446
2447
2448
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	struct pci_dev *pdev;
2900ea609   Seth Jennings   EDAC, sb_edac: Fi...
2449
  	u8 saw_chan_mask = 0;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2450
  	int i;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2451
2452
2453
2454
2455
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2456
2457
2458
2459
  
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0:
  			pvt->pci_sad0 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2460
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2461
2462
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1:
  			pvt->pci_sad1 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2463
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2464
2465
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_BR:
  			pvt->pci_br0 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2466
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2467
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2468
  			pvt->pci_ha = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2469
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
  			pvt->pci_ta = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS:
  			pvt->pci_ras = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0:
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1:
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
  		{
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2481
  			int id = TAD_DEV_TO_CHAN(pdev->device);
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2482
  			pvt->pci_tad[id] = pdev;
2900ea609   Seth Jennings   EDAC, sb_edac: Fi...
2483
  			saw_chan_mask |= 1 << id;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2484
2485
2486
2487
  		}
  			break;
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
  			pvt->pci_ddrio = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2488
2489
2490
2491
  			break;
  		default:
  			goto error;
  		}
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2492
2493
2494
  		edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p
  ",
  			 pdev->vendor, pdev->device,
956b9ba15   Joe Perches   edac: Convert deb...
2495
  			 sbridge_dev->bus,
956b9ba15   Joe Perches   edac: Convert deb...
2496
  			 pdev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2497
2498
2499
  	}
  
  	/* Check if everything were registered */
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2500
  	if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha ||
c7c35407c   Colin Ian King   EDAC, sb_edac: Re...
2501
  	    !pvt->pci_ras || !pvt->pci_ta)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2502
  		goto enodev;
2900ea609   Seth Jennings   EDAC, sb_edac: Fi...
2503
2504
  	if (saw_chan_mask != 0x0f)
  		goto enodev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2505
2506
2507
2508
2509
2510
2511
2512
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  
  error:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2513
2514
2515
  	sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x
  ",
  		       PCI_VENDOR_ID_INTEL, pdev->device);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2516
2517
  	return -EINVAL;
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2518
2519
2520
2521
  static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
  				 struct sbridge_dev *sbridge_dev)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2522
2523
  	struct pci_dev *pdev;
  	u8 saw_chan_mask = 0;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2524
  	int i;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2525
2526
2527
2528
2529
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2530

dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2531
2532
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2533
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2534
  			pvt->pci_ha = pdev;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2535
2536
  			break;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2537
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2538
  			pvt->pci_ta = pdev;
a8e9b186f   Gustavo A. R. Silva   EDAC, sb_edac: Fi...
2539
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2540
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2541
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2542
2543
  			pvt->pci_ras = pdev;
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2544
2545
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
7d375bffa   Tony Luck   sb_edac: Fix supp...
2546
2547
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2548
2549
2550
2551
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2552
  		{
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2553
  			int id = TAD_DEV_TO_CHAN(pdev->device);
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2554
  			pvt->pci_tad[id] = pdev;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2555
  			saw_chan_mask |= 1 << id;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2556
  		}
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2557
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2558
2559
2560
2561
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0:
  			pvt->pci_ddrio = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0:
7d375bffa   Tony Luck   sb_edac: Fix supp...
2562
  			pvt->pci_ddrio = pdev;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2563
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2564
2565
2566
2567
2568
2569
2570
2571
2572
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD:
  			pvt->pci_sad0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0:
  			pvt->pci_br0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
  			pvt->pci_br1 = pdev;
  			break;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
  		default:
  			goto error;
  		}
  
  		edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p
  ",
  			 sbridge_dev->bus,
  			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
  			 pdev);
  	}
  
  	/* Check if everything were registered */
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2585
  	if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_br0 ||
c7c35407c   Colin Ian King   EDAC, sb_edac: Re...
2586
  	    !pvt->pci_br1 || !pvt->pci_ras || !pvt->pci_ta)
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2587
  		goto enodev;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2588
2589
  	if (saw_chan_mask != 0x0f && /* -EN/-EX */
  	    saw_chan_mask != 0x03)   /* -EP */
7d375bffa   Tony Luck   sb_edac: Fix supp...
2590
  		goto enodev;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2591
2592
2593
2594
2595
2596
2597
2598
2599
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  
  error:
  	sbridge_printk(KERN_ERR,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2600
2601
2602
  		       "Unexpected device %02x:%02x
  ", PCI_VENDOR_ID_INTEL,
  			pdev->device);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2603
2604
  	return -EINVAL;
  }
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2605
2606
2607
2608
  static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
  				 struct sbridge_dev *sbridge_dev)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2609
2610
  	struct pci_dev *pdev;
  	u8 saw_chan_mask = 0;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2611
  	int i;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
  
  	/* there's only one device per system; not tied to any bus */
  	if (pvt->info.pci_vtd == NULL)
  		/* result will be checked later */
  		pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL,
  						   PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC,
  						   NULL);
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
  
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0:
  			pvt->pci_sad0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1:
  			pvt->pci_sad1 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2633
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2634
  			pvt->pci_ha = pdev;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2635
2636
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA:
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2637
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2638
2639
  			pvt->pci_ta = pdev;
  			break;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2640
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TM:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2641
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TM:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2642
2643
2644
  			pvt->pci_ras = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2645
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2646
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2647
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3:
7d375bffa   Tony Luck   sb_edac: Fix supp...
2648
2649
2650
2651
2652
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0:
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1:
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2:
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3:
  		{
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2653
  			int id = TAD_DEV_TO_CHAN(pdev->device);
7d375bffa   Tony Luck   sb_edac: Fix supp...
2654
2655
2656
  			pvt->pci_tad[id] = pdev;
  			saw_chan_mask |= 1 << id;
  		}
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2657
2658
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0:
7179385af   Aristeu Rozanski   sb_edac: look har...
2659
2660
2661
2662
2663
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1:
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2:
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3:
  			if (!pvt->pci_ddrio)
  				pvt->pci_ddrio = pdev;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2664
  			break;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
  		default:
  			break;
  		}
  
  		edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p
  ",
  			 sbridge_dev->bus,
  			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
  			 pdev);
  	}
  
  	/* Check if everything were registered */
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2677
  	if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 ||
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2678
2679
  	    !pvt->pci_ras  || !pvt->pci_ta || !pvt->info.pci_vtd)
  		goto enodev;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2680
2681
  	if (saw_chan_mask != 0x0f && /* -EN/-EX */
  	    saw_chan_mask != 0x03)   /* -EP */
7d375bffa   Tony Luck   sb_edac: Fix supp...
2682
  		goto enodev;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2683
2684
2685
2686
2687
2688
2689
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  }
1f39581a9   Tony Luck   sb_edac: Add supp...
2690
2691
2692
2693
2694
  static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
  				 struct sbridge_dev *sbridge_dev)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	struct pci_dev *pdev;
fa2ce64f8   Tony Luck   sb_edac: support ...
2695
  	u8 saw_chan_mask = 0;
1f39581a9   Tony Luck   sb_edac: Add supp...
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
  	int i;
  
  	/* there's only one device per system; not tied to any bus */
  	if (pvt->info.pci_vtd == NULL)
  		/* result will be checked later */
  		pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL,
  						   PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC,
  						   NULL);
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
  
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0:
  			pvt->pci_sad0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1:
  			pvt->pci_sad1 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2718
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2719
  			pvt->pci_ha = pdev;
1f39581a9   Tony Luck   sb_edac: Add supp...
2720
2721
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA:
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2722
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA:
1f39581a9   Tony Luck   sb_edac: Add supp...
2723
2724
  			pvt->pci_ta = pdev;
  			break;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2725
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TM:
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2726
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TM:
1f39581a9   Tony Luck   sb_edac: Add supp...
2727
2728
2729
  			pvt->pci_ras = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0:
1f39581a9   Tony Luck   sb_edac: Add supp...
2730
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1:
1f39581a9   Tony Luck   sb_edac: Add supp...
2731
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2:
1f39581a9   Tony Luck   sb_edac: Add supp...
2732
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3:
fa2ce64f8   Tony Luck   sb_edac: support ...
2733
2734
2735
2736
2737
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0:
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1:
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2:
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3:
  		{
d14e3a201   Qiuxu Zhuo   EDAC, sb_edac: Bu...
2738
  			int id = TAD_DEV_TO_CHAN(pdev->device);
fa2ce64f8   Tony Luck   sb_edac: support ...
2739
2740
2741
  			pvt->pci_tad[id] = pdev;
  			saw_chan_mask |= 1 << id;
  		}
1f39581a9   Tony Luck   sb_edac: Add supp...
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0:
  			pvt->pci_ddrio = pdev;
  			break;
  		default:
  			break;
  		}
  
  		edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p
  ",
  			 sbridge_dev->bus,
  			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
  			 pdev);
  	}
  
  	/* Check if everything were registered */
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2758
  	if (!pvt->pci_sad0 || !pvt->pci_ha || !pvt->pci_sad1 ||
1f39581a9   Tony Luck   sb_edac: Add supp...
2759
2760
  	    !pvt->pci_ras  || !pvt->pci_ta || !pvt->info.pci_vtd)
  		goto enodev;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
2761
2762
  	if (saw_chan_mask != 0x0f && /* -EN/-EX */
  	    saw_chan_mask != 0x03)   /* -EP */
fa2ce64f8   Tony Luck   sb_edac: support ...
2763
  		goto enodev;
1f39581a9   Tony Luck   sb_edac: Add supp...
2764
2765
2766
2767
2768
2769
2770
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
  static int knl_mci_bind_devs(struct mem_ctl_info *mci,
  			struct sbridge_dev *sbridge_dev)
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	struct pci_dev *pdev;
  	int dev, func;
  
  	int i;
  	int devidx;
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
  
  		/* Extract PCI device and function. */
  		dev = (pdev->devfn >> 3) & 0x1f;
  		func = pdev->devfn & 0x7;
  
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_MC:
  			if (dev == 8)
  				pvt->knl.pci_mc0 = pdev;
  			else if (dev == 9)
  				pvt->knl.pci_mc1 = pdev;
  			else {
  				sbridge_printk(KERN_ERR,
  					"Memory controller in unexpected place! (dev %d, fn %d)
  ",
  					dev, func);
  				continue;
  			}
  			break;
  
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0:
  			pvt->pci_sad0 = pdev;
  			break;
  
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1:
  			pvt->pci_sad1 = pdev;
  			break;
  
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_CHA:
  			/* There are one of these per tile, and range from
  			 * 1.14.0 to 1.18.5.
  			 */
  			devidx = ((dev-14)*8)+func;
  
  			if (devidx < 0 || devidx >= KNL_MAX_CHAS) {
  				sbridge_printk(KERN_ERR,
  					"Caching and Home Agent in unexpected place! (dev %d, fn %d)
  ",
  					dev, func);
  				continue;
  			}
  
  			WARN_ON(pvt->knl.pci_cha[devidx] != NULL);
  
  			pvt->knl.pci_cha[devidx] = pdev;
  			break;
00cf50d90   Qiuxu Zhuo   EDAC, sb_edac: Cl...
2831
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_CHAN:
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
  			devidx = -1;
  
  			/*
  			 *  MC0 channels 0-2 are device 9 function 2-4,
  			 *  MC1 channels 3-5 are device 8 function 2-4.
  			 */
  
  			if (dev == 9)
  				devidx = func-2;
  			else if (dev == 8)
  				devidx = 3 + (func-2);
  
  			if (devidx < 0 || devidx >= KNL_MAX_CHANNELS) {
  				sbridge_printk(KERN_ERR,
  					"DRAM Channel Registers in unexpected place! (dev %d, fn %d)
  ",
  					dev, func);
  				continue;
  			}
  
  			WARN_ON(pvt->knl.pci_channel[devidx] != NULL);
  			pvt->knl.pci_channel[devidx] = pdev;
  			break;
  
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM:
  			pvt->knl.pci_mc_info = pdev;
  			break;
  
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_TA:
  			pvt->pci_ta = pdev;
  			break;
  
  		default:
  			sbridge_printk(KERN_ERR, "Unexpected device %d
  ",
  				pdev->device);
  			break;
  		}
  	}
  
  	if (!pvt->knl.pci_mc0  || !pvt->knl.pci_mc1 ||
  	    !pvt->pci_sad0     || !pvt->pci_sad1    ||
  	    !pvt->pci_ta) {
  		goto enodev;
  	}
  
  	for (i = 0; i < KNL_MAX_CHANNELS; i++) {
  		if (!pvt->knl.pci_channel[i]) {
  			sbridge_printk(KERN_ERR, "Missing channel %d
  ", i);
  			goto enodev;
  		}
  	}
  
  	for (i = 0; i < KNL_MAX_CHAS; i++) {
  		if (!pvt->knl.pci_cha[i]) {
  			sbridge_printk(KERN_ERR, "Missing CHA %d
  ", i);
  			goto enodev;
  		}
  	}
  
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
  /****************************************************************************
  			Error check routines
   ****************************************************************************/
  
  /*
   * While Sandy Bridge has error count registers, SMI BIOS read values from
   * and resets the counters. So, they are not reliable for the OS to read
   * from them. So, we have no option but to just trust on whatever MCE is
   * telling us about the errors.
   */
  static void sbridge_mce_output_error(struct mem_ctl_info *mci,
  				    const struct mce *m)
  {
  	struct mem_ctl_info *new_mci;
  	struct sbridge_pvt *pvt = mci->pvt_info;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2916
  	enum hw_event_mc_err_type tp_event;
323014d85   Mauro Carvalho Chehab   EDAC: sb_edac: ge...
2917
  	char *optype, msg[256];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2918
2919
2920
  	bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
  	bool overflow = GET_BITFIELD(m->status, 62, 62);
  	bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2921
  	bool recoverable;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2922
2923
2924
2925
2926
  	u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
  	u32 mscod = GET_BITFIELD(m->status, 16, 31);
  	u32 errcode = GET_BITFIELD(m->status, 0, 15);
  	u32 channel = GET_BITFIELD(m->status, 0, 3);
  	u32 optypenum = GET_BITFIELD(m->status, 4, 6);
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
2927
2928
2929
2930
2931
2932
  	/*
  	 * Bits 5-0 of MCi_MISC give the least significant bit that is valid.
  	 * A value 6 is for cache line aligned address, a value 12 is for page
  	 * aligned address reported by patrol scrubber.
  	 */
  	u32 lsb = GET_BITFIELD(m->misc, 0, 5);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2933
  	long channel_mask, first_channel;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
2934
  	u8  rank = 0xff, socket, ha;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2935
  	int rc, dimm;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
2936
  	char *area_type = "DRAM";
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2937

fa2ce64f8   Tony Luck   sb_edac: support ...
2938
  	if (pvt->info.type != SANDY_BRIDGE)
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2939
2940
2941
  		recoverable = true;
  	else
  		recoverable = GET_BITFIELD(m->status, 56, 56);
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2942
  	if (uncorrected_error) {
432de7fd7   Tony Luck   EDAC, {i7core,sb,...
2943
  		core_err_cnt = 1;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2944
  		if (ripv) {
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2945
  			tp_event = HW_EVENT_ERR_UNCORRECTED;
45bc6098a   Tony Luck   EDAC/{i7core,sb,p...
2946
2947
  		} else {
  			tp_event = HW_EVENT_ERR_FATAL;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2948
2949
  		}
  	} else {
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2950
2951
  		tp_event = HW_EVENT_ERR_CORRECTED;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2952
2953
  
  	/*
15ed103a9   David Mackey   edac: Fix spellin...
2954
  	 * According with Table 15-9 of the Intel Architecture spec vol 3A,
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2955
2956
2957
2958
2959
2960
2961
2962
2963
  	 * memory errors should fit in this mask:
  	 *	000f 0000 1mmm cccc (binary)
  	 * where:
  	 *	f = Correction Report Filtering Bit. If 1, subsequent errors
  	 *	    won't be shown
  	 *	mmm = error type
  	 *	cccc = channel
  	 * If the mask doesn't match, report an error to the parsing logic
  	 */
dcc960b22   Qiuxu Zhuo   EDAC, sb_edac: Re...
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
  	switch (optypenum) {
  	case 0:
  		optype = "generic undef request error";
  		break;
  	case 1:
  		optype = "memory read error";
  		break;
  	case 2:
  		optype = "memory write error";
  		break;
  	case 3:
  		optype = "addr/cmd error";
  		break;
  	case 4:
  		optype = "memory scrubbing error";
  		break;
  	default:
  		optype = "reserved";
  		break;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2983
  	}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
  	if (pvt->info.type == KNIGHTS_LANDING) {
  		if (channel == 14) {
  			edac_dbg(0, "%s%s err_code:%04x:%04x EDRAM bank %d
  ",
  				overflow ? " OVERFLOW" : "",
  				(uncorrected_error && recoverable)
  				? " recoverable" : "",
  				mscod, errcode,
  				m->bank);
  		} else {
  			char A = *("A");
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
2995
2996
2997
2998
2999
3000
3001
  			/*
  			 * Reported channel is in range 0-2, so we can't map it
  			 * back to mc. To figure out mc we check machine check
  			 * bank register that reported this error.
  			 * bank15 means mc0 and bank16 means mc1.
  			 */
  			channel = knl_channel_remap(m->bank == 16, channel);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3002
  			channel_mask = 1 << channel;
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
3003

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
  			snprintf(msg, sizeof(msg),
  				"%s%s err_code:%04x:%04x channel:%d (DIMM_%c)",
  				overflow ? " OVERFLOW" : "",
  				(uncorrected_error && recoverable)
  				? " recoverable" : " ",
  				mscod, errcode, channel, A + channel);
  			edac_mc_handle_error(tp_event, mci, core_err_cnt,
  				m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
  				channel, 0, -1,
  				optype, msg);
  		}
  		return;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3016
  	} else if (lsb < 12) {
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3017
  		rc = get_memory_error_data(mci, m->addr, &socket, &ha,
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3018
3019
3020
3021
3022
  					   &channel_mask, &rank,
  					   &area_type, msg);
  	} else {
  		rc = get_memory_error_data_from_mce(mci, m, &socket, &ha,
  						    &channel_mask, msg);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3023
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3024
  	if (rc < 0)
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3025
  		goto err_parsing;
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3026
  	new_mci = get_mci_for_node_id(socket, ha);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3027
  	if (!new_mci) {
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3028
3029
  		strcpy(msg, "Error: socket got corrupted!");
  		goto err_parsing;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3030
3031
3032
3033
3034
  	}
  	mci = new_mci;
  	pvt = mci->pvt_info;
  
  	first_channel = find_first_bit(&channel_mask, NUM_CHANNELS);
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3035
3036
3037
  	if (rank == 0xff)
  		dimm = -1;
  	else if (rank < 4)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3038
3039
3040
3041
3042
  		dimm = 0;
  	else if (rank < 8)
  		dimm = 1;
  	else
  		dimm = 2;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3043
  	/*
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
3044
3045
3046
3047
  	 * FIXME: On some memory configurations (mirror, lockstep), the
  	 * Memory Controller can't point the error to a single DIMM. The
  	 * EDAC core should be handling the channel mask, in order to point
  	 * to the group of dimm's where the error may be happening.
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3048
  	 */
039d7af65   Qiuxu Zhuo   EDAC, sb_edac: Cl...
3049
  	if (!pvt->is_lockstep && !pvt->is_cur_addr_mirrored && !pvt->is_close_pg)
d7c660b7d   Aristeu Rozanski   sb_edac: make min...
3050
  		channel = first_channel;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3051
  	snprintf(msg, sizeof(msg),
7d375bffa   Tony Luck   sb_edac: Fix supp...
3052
  		 "%s%s area:%s err_code:%04x:%04x socket:%d ha:%d channel_mask:%ld rank:%d",
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
3053
3054
3055
3056
  		 overflow ? " OVERFLOW" : "",
  		 (uncorrected_error && recoverable) ? " recoverable" : "",
  		 area_type,
  		 mscod, errcode,
7d375bffa   Tony Luck   sb_edac: Fix supp...
3057
  		 socket, ha,
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
3058
3059
  		 channel_mask,
  		 rank);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3060

956b9ba15   Joe Perches   edac: Convert deb...
3061
3062
  	edac_dbg(0, "%s
  ", msg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3063

c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3064
  	/* FIXME: need support for channel mask */
351fc4a99   Seth Jennings   sb_edac: avoid IN...
3065
3066
  	if (channel == CHANNEL_UNSPECIFIED)
  		channel = -1;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3067
  	/* Call the helper to output message */
c10538396   Mauro Carvalho Chehab   sb_edac: properly...
3068
  	edac_mc_handle_error(tp_event, mci, core_err_cnt,
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3069
  			     m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3070
  			     channel, dimm, -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
3071
  			     optype, msg);
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3072
3073
  	return;
  err_parsing:
c10538396   Mauro Carvalho Chehab   sb_edac: properly...
3074
  	edac_mc_handle_error(tp_event, mci, core_err_cnt, 0, 0, 0,
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3075
  			     -1, -1, -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
3076
  			     msg, "");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3077

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3078
3079
3080
  }
  
  /*
ad08c4e97   Tony Luck   EDAC, sb_edac: Re...
3081
3082
   * Check that logging is enabled and that this is the right type
   * of error for us to handle.
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3083
   */
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3084
3085
  static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
  				   void *data)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3086
  {
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3087
3088
  	struct mce *mce = (struct mce *)data;
  	struct mem_ctl_info *mci;
cf40f80cb   Aristeu Rozanski   sb_edac: use "eve...
3089
  	char *type;
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3090

23ba710a0   Tony Luck   x86/mce: Fix all ...
3091
3092
  	if (mce->kflags & MCE_HANDLED_CEC)
  		return NOTIFY_DONE;
fd5210396   Chen, Gong   EDAC, sb_edac: Mo...
3093

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3094
3095
3096
3097
3098
3099
3100
  	/*
  	 * Just let mcelog handle it if the error is
  	 * outside the memory controller. A memory error
  	 * is indicated by bit 7 = 1 and bits = 8-11,13-15 = 0.
  	 * bit 12 has an special meaning.
  	 */
  	if ((mce->status & 0xefff) >> 7 != 1)
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3101
  		return NOTIFY_DONE;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3102

dcc960b22   Qiuxu Zhuo   EDAC, sb_edac: Re...
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
  	/* Check ADDRV bit in STATUS */
  	if (!GET_BITFIELD(mce->status, 58, 58))
  		return NOTIFY_DONE;
  
  	/* Check MISCV bit in STATUS */
  	if (!GET_BITFIELD(mce->status, 59, 59))
  		return NOTIFY_DONE;
  
  	/* Check address type in MISC (physical address only) */
  	if (GET_BITFIELD(mce->misc, 6, 8) != 2)
  		return NOTIFY_DONE;
  
  	mci = get_mci_for_node_id(mce->socketid, IMC0);
  	if (!mci)
  		return NOTIFY_DONE;
cf40f80cb   Aristeu Rozanski   sb_edac: use "eve...
3118
3119
3120
3121
  	if (mce->mcgstatus & MCG_STATUS_MCIP)
  		type = "Exception";
  	else
  		type = "Event";
49856dc97   Aristeu Rozanski   sb_edac: mark MCE...
3122
3123
  	sbridge_mc_printk(mci, KERN_DEBUG, "HANDLING MCE MEMORY ERROR
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3124

49856dc97   Aristeu Rozanski   sb_edac: mark MCE...
3125
3126
3127
3128
3129
3130
3131
  	sbridge_mc_printk(mci, KERN_DEBUG, "CPU %d: Machine Check %s: %Lx "
  			  "Bank %d: %016Lx
  ", mce->extcpu, type,
  			  mce->mcgstatus, mce->bank, mce->status);
  	sbridge_mc_printk(mci, KERN_DEBUG, "TSC %llx ", mce->tsc);
  	sbridge_mc_printk(mci, KERN_DEBUG, "ADDR %llx ", mce->addr);
  	sbridge_mc_printk(mci, KERN_DEBUG, "MISC %llx ", mce->misc);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3132

49856dc97   Aristeu Rozanski   sb_edac: mark MCE...
3133
3134
3135
3136
  	sbridge_mc_printk(mci, KERN_DEBUG, "PROCESSOR %u:%x TIME %llu SOCKET "
  			  "%u APIC %x
  ", mce->cpuvendor, mce->cpuid,
  			  mce->time, mce->socketid, mce->apicid);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3137

ad08c4e97   Tony Luck   EDAC, sb_edac: Re...
3138
  	sbridge_mce_output_error(mci, mce);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3139
3140
  
  	/* Advice mcelog that the error were handled */
23ba710a0   Tony Luck   x86/mce: Fix all ...
3141
3142
  	mce->kflags |= MCE_HANDLED_EDAC;
  	return NOTIFY_OK;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3143
  }
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3144
  static struct notifier_block sbridge_mce_dec = {
9026cc82b   Borislav Petkov   x86/ras, EDAC, ac...
3145
3146
  	.notifier_call	= sbridge_mce_check_error,
  	.priority	= MCE_PRIO_EDAC,
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3147
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3148
3149
3150
3151
3152
3153
3154
  /****************************************************************************
  			EDAC register/unregister logic
   ****************************************************************************/
  
  static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
  {
  	struct mem_ctl_info *mci = sbridge_dev->mci;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3155
3156
  
  	if (unlikely(!mci || !mci->pvt_info)) {
956b9ba15   Joe Perches   edac: Convert deb...
3157
3158
  		edac_dbg(0, "MC: dev = %p
  ", &sbridge_dev->pdev[0]->dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3159
3160
3161
3162
3163
  
  		sbridge_printk(KERN_ERR, "Couldn't find mci handler
  ");
  		return;
  	}
956b9ba15   Joe Perches   edac: Convert deb...
3164
3165
3166
  	edac_dbg(0, "MC: mci = %p, dev = %p
  ",
  		 mci, &sbridge_dev->pdev[0]->dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3167

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3168
  	/* Remove MC sysfs nodes */
fd687502d   Mauro Carvalho Chehab   edac: Rename the ...
3169
  	edac_mc_del_mc(mci->pdev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3170

956b9ba15   Joe Perches   edac: Convert deb...
3171
3172
  	edac_dbg(1, "%s: free mci struct
  ", mci->ctl_name);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3173
3174
3175
3176
  	kfree(mci->ctl_name);
  	edac_mc_free(mci);
  	sbridge_dev->mci = NULL;
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3177
  static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3178
3179
  {
  	struct mem_ctl_info *mci;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3180
  	struct edac_mc_layer layers[2];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3181
  	struct sbridge_pvt *pvt;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3182
  	struct pci_dev *pdev = sbridge_dev->pdev[0];
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3183
  	int rc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3184

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3185
  	/* allocate a new MC control structure */
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3186
  	layers[0].type = EDAC_MC_LAYER_CHANNEL;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3187
3188
  	layers[0].size = type == KNIGHTS_LANDING ?
  		KNL_MAX_CHANNELS : NUM_CHANNELS;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3189
3190
  	layers[0].is_virt_csrow = false;
  	layers[1].type = EDAC_MC_LAYER_SLOT;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3191
  	layers[1].size = type == KNIGHTS_LANDING ? 1 : MAX_DIMMS;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3192
  	layers[1].is_virt_csrow = true;
ca0907b9e   Mauro Carvalho Chehab   edac: Remove the ...
3193
  	mci = edac_mc_alloc(sbridge_dev->mc, ARRAY_SIZE(layers), layers,
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3194
  			    sizeof(*pvt));
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3195
3196
  	if (unlikely(!mci))
  		return -ENOMEM;
956b9ba15   Joe Perches   edac: Convert deb...
3197
3198
  	edac_dbg(0, "MC: mci = %p, dev = %p
  ",
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3199
  		 mci, &pdev->dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3200
3201
3202
3203
3204
3205
3206
  
  	pvt = mci->pvt_info;
  	memset(pvt, 0, sizeof(*pvt));
  
  	/* Associate sbridge_dev and mci for future usage */
  	pvt->sbridge_dev = sbridge_dev;
  	sbridge_dev->mci = mci;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3207
3208
  	mci->mtype_cap = type == KNIGHTS_LANDING ?
  		MEM_FLAG_DDR4 : MEM_FLAG_DDR3;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3209
3210
  	mci->edac_ctl_cap = EDAC_FLAG_NONE;
  	mci->edac_cap = EDAC_FLAG_NONE;
301375e76   Toshi Kani   EDAC: Add owner c...
3211
  	mci->mod_name = EDAC_MOD_STR;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3212
  	mci->dev_name = pci_name(pdev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3213
  	mci->ctl_page_to_phys = NULL;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3214
  	pvt->info.type = type;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3215
3216
  	switch (type) {
  	case IVY_BRIDGE:
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3217
3218
3219
3220
  		pvt->info.rankcfgr = IB_RANK_CFG_A;
  		pvt->info.get_tolm = ibridge_get_tolm;
  		pvt->info.get_tohm = ibridge_get_tohm;
  		pvt->info.dram_rule = ibridge_dram_rule;
9e3754461   Aristeu Rozanski   sb_edac: make mem...
3221
  		pvt->info.get_memory_type = get_memory_type;
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
3222
  		pvt->info.get_node_id = get_node_id;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3223
  		pvt->info.get_ha = ibridge_get_ha;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
3224
  		pvt->info.rir_limit = rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3225
3226
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3227
  		pvt->info.dram_attr = dram_attr;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3228
3229
  		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
  		pvt->info.interleave_list = ibridge_interleave_list;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3230
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3231
  		pvt->info.get_width = ibridge_get_width;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3232
3233
3234
3235
3236
  
  		/* Store pci devices at mci for faster access */
  		rc = ibridge_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3237
  		get_source_id(mci);
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3238
3239
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge SrcID#%d_Ha#%d",
  			pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3240
3241
  		break;
  	case SANDY_BRIDGE:
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3242
3243
3244
3245
  		pvt->info.rankcfgr = SB_RANK_CFG_A;
  		pvt->info.get_tolm = sbridge_get_tolm;
  		pvt->info.get_tohm = sbridge_get_tohm;
  		pvt->info.dram_rule = sbridge_dram_rule;
9e3754461   Aristeu Rozanski   sb_edac: make mem...
3246
  		pvt->info.get_memory_type = get_memory_type;
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
3247
  		pvt->info.get_node_id = get_node_id;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3248
  		pvt->info.get_ha = sbridge_get_ha;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
3249
  		pvt->info.rir_limit = rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3250
3251
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3252
  		pvt->info.dram_attr = dram_attr;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3253
3254
  		pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
  		pvt->info.interleave_list = sbridge_interleave_list;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3255
  		pvt->info.interleave_pkg = sbridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3256
  		pvt->info.get_width = sbridge_get_width;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3257
3258
3259
3260
3261
  
  		/* Store pci devices at mci for faster access */
  		rc = sbridge_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3262
  		get_source_id(mci);
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3263
3264
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge SrcID#%d_Ha#%d",
  			pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3265
3266
3267
3268
3269
3270
3271
3272
  		break;
  	case HASWELL:
  		/* rankcfgr isn't used */
  		pvt->info.get_tolm = haswell_get_tolm;
  		pvt->info.get_tohm = haswell_get_tohm;
  		pvt->info.dram_rule = ibridge_dram_rule;
  		pvt->info.get_memory_type = haswell_get_memory_type;
  		pvt->info.get_node_id = haswell_get_node_id;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3273
  		pvt->info.get_ha = ibridge_get_ha;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3274
  		pvt->info.rir_limit = haswell_rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3275
3276
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3277
  		pvt->info.dram_attr = dram_attr;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3278
3279
  		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
  		pvt->info.interleave_list = ibridge_interleave_list;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3280
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3281
  		pvt->info.get_width = ibridge_get_width;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3282

50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3283
3284
3285
3286
  		/* Store pci devices at mci for faster access */
  		rc = haswell_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3287
  		get_source_id(mci);
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3288
3289
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell SrcID#%d_Ha#%d",
  			pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3290
  		break;
1f39581a9   Tony Luck   sb_edac: Add supp...
3291
3292
3293
3294
3295
3296
3297
  	case BROADWELL:
  		/* rankcfgr isn't used */
  		pvt->info.get_tolm = haswell_get_tolm;
  		pvt->info.get_tohm = haswell_get_tohm;
  		pvt->info.dram_rule = ibridge_dram_rule;
  		pvt->info.get_memory_type = haswell_get_memory_type;
  		pvt->info.get_node_id = haswell_get_node_id;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3298
  		pvt->info.get_ha = ibridge_get_ha;
1f39581a9   Tony Luck   sb_edac: Add supp...
3299
  		pvt->info.rir_limit = haswell_rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3300
3301
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3302
  		pvt->info.dram_attr = dram_attr;
1f39581a9   Tony Luck   sb_edac: Add supp...
3303
3304
  		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
  		pvt->info.interleave_list = ibridge_interleave_list;
1f39581a9   Tony Luck   sb_edac: Add supp...
3305
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3306
  		pvt->info.get_width = broadwell_get_width;
1f39581a9   Tony Luck   sb_edac: Add supp...
3307
3308
3309
3310
3311
  
  		/* Store pci devices at mci for faster access */
  		rc = broadwell_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3312
  		get_source_id(mci);
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3313
3314
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell SrcID#%d_Ha#%d",
  			pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
1f39581a9   Tony Luck   sb_edac: Add supp...
3315
  		break;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3316
3317
3318
3319
3320
3321
3322
  	case KNIGHTS_LANDING:
  		/* pvt->info.rankcfgr == ??? */
  		pvt->info.get_tolm = knl_get_tolm;
  		pvt->info.get_tohm = knl_get_tohm;
  		pvt->info.dram_rule = knl_dram_rule;
  		pvt->info.get_memory_type = knl_get_memory_type;
  		pvt->info.get_node_id = knl_get_node_id;
8489b17ce   Qiuxu Zhuo   EDAC, sb_edac: Fi...
3323
  		pvt->info.get_ha = knl_get_ha;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3324
3325
3326
  		pvt->info.rir_limit = NULL;
  		pvt->info.sad_limit = knl_sad_limit;
  		pvt->info.interleave_mode = knl_interleave_mode;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3327
3328
3329
  		pvt->info.dram_attr = dram_attr_knl;
  		pvt->info.max_sad = ARRAY_SIZE(knl_dram_rule);
  		pvt->info.interleave_list = knl_interleave_list;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3330
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
45f4d3ab3   Hubert Chrzaniuk   EDAC, sb_edac: Se...
3331
  		pvt->info.get_width = knl_get_width;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3332
3333
3334
3335
  
  		rc = knl_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3336
  		get_source_id(mci);
e2f747b1f   Qiuxu Zhuo   EDAC, sb_edac: As...
3337
3338
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Knights Landing SrcID#%d_Ha#%d",
  			pvt->sbridge_dev->source_id, pvt->sbridge_dev->dom);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3339
  		break;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3340
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3341

75f029c3a   Arvind Yadav   EDAC: Handle retu...
3342
3343
3344
3345
  	if (!mci->ctl_name) {
  		rc = -ENOMEM;
  		goto fail0;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3346
  	/* Get dimm basic config and the memory layout */
4d475dde7   Qiuxu Zhuo   EDAC, sb_edac: Ch...
3347
3348
3349
3350
3351
3352
  	rc = get_dimm_config(mci);
  	if (rc < 0) {
  		edac_dbg(0, "MC: failed to get_dimm_config()
  ");
  		goto fail;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3353
3354
3355
  	get_memory_layout(mci);
  
  	/* record ptr to the generic device */
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3356
  	mci->pdev = &pdev->dev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3357
3358
3359
  
  	/* add this new MC control structure to EDAC's list of MCs */
  	if (unlikely(edac_mc_add_mc(mci))) {
956b9ba15   Joe Perches   edac: Convert deb...
3360
3361
  		edac_dbg(0, "MC: failed edac_mc_add_mc()
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3362
  		rc = -EINVAL;
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3363
  		goto fail;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3364
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3365
  	return 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3366

7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3367
  fail:
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3368
  	kfree(mci->ctl_name);
7fd562b75   Tony Luck   EDAC, sb_edac: Do...
3369
  fail0:
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3370
3371
3372
3373
  	edac_mc_free(mci);
  	sbridge_dev->mci = NULL;
  	return rc;
  }
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3374
  static const struct x86_cpu_id sbridge_cpuids[] = {
298426211   Thomas Gleixner   EDAC: Convert to ...
3375
3376
3377
3378
3379
3380
3381
  	X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, &pci_dev_descr_sbridge_table),
  	X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X,	  &pci_dev_descr_ibridge_table),
  	X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X,	  &pci_dev_descr_haswell_table),
  	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X,	  &pci_dev_descr_broadwell_table),
  	X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D,	  &pci_dev_descr_broadwell_table),
  	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,  &pci_dev_descr_knl_table),
  	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,  &pci_dev_descr_knl_table),
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3382
3383
3384
  	{ }
  };
  MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3385
  /*
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3386
   *	sbridge_probe	Get all devices and register memory controllers
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3387
3388
3389
3390
3391
   *			present.
   *	return:
   *		0 for FOUND a device
   *		< 0 for error code
   */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3392
  static int sbridge_probe(const struct x86_cpu_id *id)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3393
  {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3394
  	int rc = -ENODEV;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3395
3396
  	u8 mc, num_mc = 0;
  	struct sbridge_dev *sbridge_dev;
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3397
  	struct pci_id_table *ptable = (struct pci_id_table *)id->driver_data;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3398
3399
  
  	/* get the pci devices we want to reserve for our use */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3400
  	rc = sbridge_get_all_devices(&num_mc, ptable);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3401

11249e739   Borislav Petkov   sb_edac: Fix dete...
3402
  	if (unlikely(rc < 0)) {
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3403
3404
  		edac_dbg(0, "couldn't get all devices
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3405
  		goto fail0;
11249e739   Borislav Petkov   sb_edac: Fix dete...
3406
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3407
3408
3409
  	mc = 0;
  
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
956b9ba15   Joe Perches   edac: Convert deb...
3410
3411
3412
  		edac_dbg(0, "Registering MC#%d (%d of %d)
  ",
  			 mc, mc + 1, num_mc);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3413

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3414
  		sbridge_dev->mc = mc++;
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
3415
  		rc = sbridge_register_mci(sbridge_dev, ptable->type);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3416
3417
3418
  		if (unlikely(rc < 0))
  			goto fail1;
  	}
11249e739   Borislav Petkov   sb_edac: Fix dete...
3419
3420
  	sbridge_printk(KERN_INFO, "%s
  ", SBRIDGE_REVISION);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3421

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3422
3423
3424
3425
3426
3427
3428
3429
  	return 0;
  
  fail1:
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
  		sbridge_unregister_mci(sbridge_dev);
  
  	sbridge_put_all_devices();
  fail0:
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3430
3431
3432
3433
  	return rc;
  }
  
  /*
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3434
   *	sbridge_remove	cleanup
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3435
3436
   *
   */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3437
  static void sbridge_remove(void)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3438
3439
  {
  	struct sbridge_dev *sbridge_dev;
956b9ba15   Joe Perches   edac: Convert deb...
3440
3441
  	edac_dbg(0, "
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3442

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3443
3444
3445
3446
3447
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
  		sbridge_unregister_mci(sbridge_dev);
  
  	/* Release PCI resources */
  	sbridge_put_all_devices();
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3448
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3449
3450
3451
3452
3453
3454
  /*
   *	sbridge_init		Module entry function
   *			Try to initialize this module for its devices
   */
  static int __init sbridge_init(void)
  {
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3455
  	const struct x86_cpu_id *id;
301375e76   Toshi Kani   EDAC: Add owner c...
3456
  	const char *owner;
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3457
  	int rc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3458

956b9ba15   Joe Perches   edac: Convert deb...
3459
3460
  	edac_dbg(2, "
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3461

301375e76   Toshi Kani   EDAC: Add owner c...
3462
3463
3464
  	owner = edac_get_owner();
  	if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
  		return -EBUSY;
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3465
3466
3467
  	id = x86_match_cpu(sbridge_cpuids);
  	if (!id)
  		return -ENODEV;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3468
3469
  	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
  	opstate_init();
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3470
3471
3472
  	rc = sbridge_probe(id);
  
  	if (rc >= 0) {
e35fca479   Chen Gong   edac: avoid mce d...
3473
  		mce_register_decode_chain(&sbridge_mce_dec);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3474
  		return 0;
e35fca479   Chen Gong   edac: avoid mce d...
3475
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3476
3477
3478
  
  	sbridge_printk(KERN_ERR, "Failed to register device with error %d.
  ",
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3479
  		      rc);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3480

2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3481
  	return rc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3482
3483
3484
3485
3486
3487
3488
3489
  }
  
  /*
   *	sbridge_exit()	Module exit function
   *			Unregister the driver
   */
  static void __exit sbridge_exit(void)
  {
956b9ba15   Joe Perches   edac: Convert deb...
3490
3491
  	edac_dbg(2, "
  ");
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3492
  	sbridge_remove();
e35fca479   Chen Gong   edac: avoid mce d...
3493
  	mce_unregister_decode_chain(&sbridge_mce_dec);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3494
3495
3496
3497
3498
3499
3500
3501
3502
  }
  
  module_init(sbridge_init);
  module_exit(sbridge_exit);
  
  module_param(edac_op_state, int, 0444);
  MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
  
  MODULE_LICENSE("GPL");
37e59f876   Mauro Carvalho Chehab   [media, edac] Cha...
3503
  MODULE_AUTHOR("Mauro Carvalho Chehab");
7d4c1ea2b   Alexander A. Klimov   EDAC: Replace HTT...
3504
  MODULE_AUTHOR("Red Hat Inc. (https://www.redhat.com)");
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3505
  MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - "
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3506
  		   SBRIDGE_REVISION);