Blame view

drivers/edac/sb_edac.c 91 KB
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1
2
3
4
5
6
7
8
9
  /* Intel Sandy Bridge -EN/-EP/-EX Memory Controller kernel module
   *
   * This driver supports the memory controllers found on the Intel
   * processor family Sandy Bridge.
   *
   * This file may be distributed under the terms of the
   * GNU General Public License version 2 only.
   *
   * Copyright (c) 2011 by:
37e59f876   Mauro Carvalho Chehab   [media, edac] Cha...
10
   *	 Mauro Carvalho Chehab
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
11
12
13
14
15
16
17
18
19
20
   */
  
  #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...
21
22
  #include <linux/smp.h>
  #include <linux/bitmap.h>
5b889e379   Mauro Carvalho Chehab   Fix sb_edac compi...
23
  #include <linux/math64.h>
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
24
25
  #include <linux/mod_devicetable.h>
  #include <asm/cpu_device_id.h>
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
26
  #include <asm/processor.h>
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
27
  #include <asm/mce.h>
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
28
29
30
31
32
  
  #include "edac_core.h"
  
  /* Static vars */
  static LIST_HEAD(sbridge_edac_list);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
33
34
35
36
  
  /*
   * Alter this version for the module when modifications are made
   */
7d375bffa   Tony Luck   sb_edac: Fix supp...
37
  #define SBRIDGE_REVISION    " Ver: 1.1.1 "
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
  #define EDAC_MOD_STR      "sbridge_edac"
  
  /*
   * 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...
53
  	(((v) & GENMASK_ULL(hi, lo)) >> (lo))
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
54

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

4d715a805   Aristeu Rozanski   sb_edac: add supp...
61
62
63
64
65
66
  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...
67

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
68
69
70
71
72
73
74
  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...
75
  #define DRAM_RULE_ENABLE(reg)	GET_BITFIELD(reg, 0,  0)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
76
  #define A7MODE(reg)		GET_BITFIELD(reg, 26, 26)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
77

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

4d715a805   Aristeu Rozanski   sb_edac: add supp...
96
97
98
99
100
101
  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...
102
103
104
105
106
107
108
  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 */
  };
cc311991a   Aristeu Rozanski   sb_edac: rework s...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  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...
124
125
126
127
128
129
130
131
132
133
  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...
134
135
  static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
  			  int interleave)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
136
  {
cc311991a   Aristeu Rozanski   sb_edac: rework s...
137
138
  	return GET_BITFIELD(reg, table[interleave].start,
  			    table[interleave].end);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
139
140
141
142
143
  }
  
  /* Devices 12 Function 7 */
  
  #define TOLM		0x80
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
144
  #define TOHM		0x84
f7cf2a22a   Tony Luck   sb_edac: Fix disc...
145
  #define HASWELL_TOLM	0xd0
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
146
147
  #define HASWELL_TOHM_0	0xd4
  #define HASWELL_TOHM_1	0xd8
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
148
149
150
  #define KNL_TOLM	0xd0
  #define KNL_TOHM_0	0xd4
  #define KNL_TOHM_1	0xd8
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
151
152
153
154
155
156
157
158
159
  
  #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...
160
  #define SOURCE_ID_KNL(reg)	GET_BITFIELD(reg, 12, 14)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
161
  #define SAD_CONTROL	0xf4
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  /* 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...
182
  #define KNL_MCMTR		0x624
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  
  #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...
198
  static const int knl_mtr_reg = 0xb60;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  #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...
220
221
222
223
224
225
226
227
228
229
  
  #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...
230
231
232
233
234
  #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...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  
  /* Device 16, functions 2-7 */
  
  /*
   * FIXME: Implement the error count reads directly
   */
  
  static const u32 correrrcnt[] = {
  	0x104, 0x108, 0x10c, 0x110,
  };
  
  #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)
  
  static const u32 correrrthrsld[] = {
  	0x11c, 0x120, 0x124, 0x128,
  };
  
  #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...
260
  #define SB_RANK_CFG_A		0x0328
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
261

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

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
264
265
266
  /*
   * sbridge structs
   */
7d375bffa   Tony Luck   sb_edac: Fix supp...
267
  #define NUM_CHANNELS		8	/* 2MC per socket, four chan per MC */
351fc4a99   Seth Jennings   sb_edac: avoid IN...
268
  #define MAX_DIMMS		3	/* Max DIMMS per channel */
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
269
270
271
  #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...
272
  #define CHANNEL_UNSPECIFIED	0xf	/* Intel IA32 SDM 15-14 */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
273

4d715a805   Aristeu Rozanski   sb_edac: add supp...
274
275
276
  enum type {
  	SANDY_BRIDGE,
  	IVY_BRIDGE,
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
277
  	HASWELL,
1f39581a9   Tony Luck   sb_edac: Add supp...
278
  	BROADWELL,
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
279
  	KNIGHTS_LANDING,
4d715a805   Aristeu Rozanski   sb_edac: add supp...
280
  };
fb79a5092   Aristeu Rozanski   sb_edac: isolate ...
281
  struct sbridge_pvt;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
282
  struct sbridge_info {
4d715a805   Aristeu Rozanski   sb_edac: add supp...
283
  	enum type	type;
464f1d829   Aristeu Rozanski   sb_edac: allow di...
284
285
286
287
  	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...
288
  	u64		(*rir_limit)(u32 reg);
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
289
290
291
292
  	u64		(*sad_limit)(u32 reg);
  	u32		(*interleave_mode)(u32 reg);
  	char*		(*show_interleave_mode)(u32 reg);
  	u32		(*dram_attr)(u32 reg);
464f1d829   Aristeu Rozanski   sb_edac: allow di...
293
  	const u32	*dram_rule;
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
294
  	const u32	*interleave_list;
cc311991a   Aristeu Rozanski   sb_edac: rework s...
295
  	const struct interleave_pkg *interleave_pkg;
464f1d829   Aristeu Rozanski   sb_edac: allow di...
296
  	u8		max_sad;
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
297
  	u8		max_interleave;
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
298
  	u8		(*get_node_id)(struct sbridge_pvt *pvt);
9e3754461   Aristeu Rozanski   sb_edac: make mem...
299
  	enum mem_type	(*get_memory_type)(struct sbridge_pvt *pvt);
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
300
  	enum dev_type	(*get_width)(struct sbridge_pvt *pvt, u32 mtr);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
301
  	struct pci_dev	*pci_vtd;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
302
303
304
305
306
307
308
309
  };
  
  struct sbridge_channel {
  	u32		ranks;
  	u32		dimms;
  };
  
  struct pci_id_descr {
c41afdca2   Mauro Carvalho Chehab   sb_edac: Fix mix ...
310
  	int			dev_id;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
311
312
313
314
315
316
  	int			optional;
  };
  
  struct pci_id_table {
  	const struct pci_id_descr	*descr;
  	int				n_devs;
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
317
  	enum type			type;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
318
319
320
321
322
323
324
325
326
327
  };
  
  struct sbridge_dev {
  	struct list_head	list;
  	u8			bus, mc;
  	u8			node_id, source_id;
  	struct pci_dev		**pdev;
  	int			n_devs;
  	struct mem_ctl_info	*mci;
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
328
329
330
331
332
333
334
335
336
  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...
337
338
  struct sbridge_pvt {
  	struct pci_dev		*pci_ta, *pci_ddrio, *pci_ras;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
339
340
341
  	struct pci_dev		*pci_sad0, *pci_sad1;
  	struct pci_dev		*pci_ha0, *pci_ha1;
  	struct pci_dev		*pci_br0, *pci_br1;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
342
  	struct pci_dev		*pci_ha1_ta;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
343
344
345
346
347
348
  	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...
349
350
  	/* Memory type detection */
  	bool			is_mirrored, is_lockstep, is_close_pg;
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
351
  	bool			is_chan_hash;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
352

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
353
354
  	/* Memory description */
  	u64			tolm, tohm;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
355
  	struct knl_pvt knl;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
356
  };
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
357
358
  #define PCI_DESCR(device_id, opt)	\
  	.dev_id = (device_id),		\
de4772c62   Tony Luck   edac: sb_edac.c s...
359
  	.optional = opt
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
360
361
362
  
  static const struct pci_id_descr pci_dev_descr_sbridge[] = {
  		/* Processor Home Agent */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
363
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)	},
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
364
365
  
  		/* Memory controller */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
366
367
368
369
370
371
372
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)	},
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
373
374
  
  		/* System Address Decoder */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
375
376
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)	},
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
377
378
  
  		/* Broadcast Registers */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
379
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)		},
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
380
  };
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
381
382
383
384
385
  #define PCI_ID_TABLE_ENTRY(A, T) {	\
  	.descr = A,			\
  	.n_devs = ARRAY_SIZE(A),	\
  	.type = T			\
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
386
  static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
387
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE),
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
388
389
  	{0,}			/* 0 terminated list. */
  };
4d715a805   Aristeu Rozanski   sb_edac: add supp...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  /* 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...
415
416
  #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...
417
418
419
  
  static const struct pci_id_descr pci_dev_descr_ibridge[] = {
  		/* Processor Home Agent */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
420
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)		},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
421
422
  
  		/* Memory controller */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
423
424
425
426
427
428
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)		},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)		},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0)	},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
429
430
  
  		/* System Address Decoder */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
431
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)			},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
432
433
  
  		/* Broadcast Registers */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
434
435
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)			},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)			},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
436
437
  
  		/* Optional, mode 2HA */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
438
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)		},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
439
  #if 0
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
440
441
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1)	},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
442
  #endif
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
443
444
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1)	},
7d375bffa   Tony Luck   sb_edac: Fix supp...
445
446
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD2, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD3, 1)	},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
447

dbc954ddd   Aristeu Rozanski   sb_edac: search d...
448
449
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1)	},
4d715a805   Aristeu Rozanski   sb_edac: add supp...
450
451
452
  };
  
  static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
453
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE),
4d715a805   Aristeu Rozanski   sb_edac: add supp...
454
455
  	{0,}			/* 0 terminated list. */
  };
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  /* 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...
472
  #define HASWELL_DDRCRCLKCONTROLS 0xa10 /* Ditto on Broadwell */
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
  #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
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL 0x2f71
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA	0x2f68
  #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL 0x2f79
  #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...
492
493
494
  #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...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  static const struct pci_id_descr pci_dev_descr_haswell[] = {
  	/* first item must be the HA */
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0)		},
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_CBO_SAD1, 0)	},
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1, 1)		},
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA, 0)		},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1)	},
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1)		},
7179385af   Aristeu Rozanski   sb_edac: look har...
512
513
514
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1)		},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1)		},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1)		},
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
515
516
517
518
519
520
521
522
523
524
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1)		},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD1, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3, 1)	},
  };
  
  static const struct pci_id_table pci_dev_descr_haswell_table[] = {
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
525
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL),
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
526
527
  	{0,}			/* 0 terminated list. */
  };
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
528
529
530
  /* Knight's Landing Support */
  /*
   * KNL's memory channels are swizzled between memory controllers.
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
531
   * MC0 is mapped to CH3,4,5 and MC1 is mapped to CH0,1,2
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
532
   */
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
533
  #define knl_channel_remap(mc, chan) ((mc) ? (chan) : (chan) + 3)
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
  
  /* 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) */
  #define PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL  0x7843
  /* 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[] = {
  	[0]         = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0) },
  	[1]         = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0) },
  	[2 ... 3]   = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0)},
  	[4 ... 41]  = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0) },
  	[42 ... 47] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL, 0) },
  	[48]        = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0) },
  	[49]        = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0) },
  };
  
  static const struct pci_id_table pci_dev_descr_knl_table[] = {
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
568
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING),
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
569
570
  	{0,}
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
571
  /*
1f39581a9   Tony Luck   sb_edac: Add supp...
572
573
574
575
576
   * Broadwell support
   *
   * DE processor:
   *	- 1 IMC
   *	- 2 DDR3 channels, 2 DPC per channel
fa2ce64f8   Tony Luck   sb_edac: support ...
577
578
579
580
581
582
583
584
585
586
587
   * 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...
588
589
590
   */
  #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 ...
591
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1	0x6f60
1f39581a9   Tony Luck   sb_edac: Add supp...
592
593
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA	0x6fa8
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL 0x6f71
fa2ce64f8   Tony Luck   sb_edac: support ...
594
595
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA	0x6f68
  #define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL 0x6f79
1f39581a9   Tony Luck   sb_edac: Add supp...
596
597
598
599
600
601
  #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 ...
602
603
604
605
  #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...
606
607
608
609
610
611
612
613
  #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 */
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0)		},
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0)	},
fa2ce64f8   Tony Luck   sb_edac: support ...
614
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1, 1)		},
1f39581a9   Tony Luck   sb_edac: Add supp...
615
616
617
618
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0)	},
fa2ce64f8   Tony Luck   sb_edac: support ...
619
620
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 1)	},
1f39581a9   Tony Luck   sb_edac: Add supp...
621
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1)	},
fa2ce64f8   Tony Luck   sb_edac: support ...
622
623
624
625
626
627
628
  
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_THERMAL, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD1, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD2, 1)	},
  	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD3, 1)	},
1f39581a9   Tony Luck   sb_edac: Add supp...
629
630
631
  };
  
  static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
632
  	PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL),
1f39581a9   Tony Luck   sb_edac: Add supp...
633
634
  	{0,}			/* 0 terminated list. */
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
635
636
  
  /****************************************************************************
15ed103a9   David Mackey   edac: Fix spellin...
637
  			Ancillary status routines
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
638
   ****************************************************************************/
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
639
  static inline int numrank(enum type type, u32 mtr)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
640
641
  {
  	int ranks = (1 << RANK_CNT_BITS(mtr));
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
642
  	int max = 4;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
643
  	if (type == HASWELL || type == BROADWELL || type == KNIGHTS_LANDING)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
644
  		max = 8;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
645

50d1bb936   Aristeu Rozanski   sb_edac: add supp...
646
647
648
649
  	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...
650
651
652
653
654
655
656
657
658
659
660
  		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...
661
662
663
  		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...
664
665
666
667
668
669
670
671
672
673
674
  		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...
675
676
677
  		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...
678
679
680
681
682
  		return -EINVAL;
  	}
  
  	return 1 << cols;
  }
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
683
  static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
684
685
  {
  	struct sbridge_dev *sbridge_dev;
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
686
687
688
689
690
691
692
693
  	/*
  	 * 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);
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
  		if (sbridge_dev->bus == bus)
  			return sbridge_dev;
  	}
  
  	return NULL;
  }
  
  static struct sbridge_dev *alloc_sbridge_dev(u8 bus,
  					   const struct pci_id_table *table)
  {
  	struct sbridge_dev *sbridge_dev;
  
  	sbridge_dev = kzalloc(sizeof(*sbridge_dev), GFP_KERNEL);
  	if (!sbridge_dev)
  		return NULL;
  
  	sbridge_dev->pdev = kzalloc(sizeof(*sbridge_dev->pdev) * table->n_devs,
  				   GFP_KERNEL);
  	if (!sbridge_dev->pdev) {
  		kfree(sbridge_dev);
  		return NULL;
  	}
  
  	sbridge_dev->bus = bus;
  	sbridge_dev->n_devs = table->n_devs;
  	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 ...
731
732
733
734
735
736
737
738
  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 ...
739
740
741
742
743
744
745
  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...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
  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...
763
764
765
766
  static u64 rir_limit(u32 reg)
  {
  	return ((u64)GET_BITFIELD(reg,  1, 10) << 29) | 0x1fffffff;
  }
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  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);
  }
  
  char *show_interleave_mode(u32 reg)
  {
  	return interleave_mode(reg) ? "8:6" : "[8:6]XOR[18:16]";
  }
  
  static u32 dram_attr(u32 reg)
  {
  	return GET_BITFIELD(reg, 2, 3);
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
  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);
  }
  
  static char *knl_show_interleave_mode(u32 reg)
  {
  	char *s;
  
  	switch (knl_interleave_mode(reg)) {
  	case 0:
  		s = "use address bits [8:6]";
  		break;
  	case 1:
  		s = "use address bits [10:8]";
  		break;
  	case 2:
  		s = "use address bits [14:12]";
  		break;
  	case 3:
  		s = "use address bits [32:30]";
  		break;
  	default:
  		WARN_ON(1);
  		break;
  	}
  
  	return s;
  }
  
  static u32 dram_attr_knl(u32 reg)
  {
  	return GET_BITFIELD(reg, 3, 4);
  }
9e3754461   Aristeu Rozanski   sb_edac: make mem...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
  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...
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
  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...
874
875
876
877
878
  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...
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
  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)
  {
  	enum dev_type type;
  
  	switch (mtr) {
  	case 3:
  		type = DEV_UNKNOWN;
  		break;
  	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...
921
922
923
924
925
  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...
926
927
928
929
930
931
  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...
932
933
934
935
936
937
938
  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...
939
940
941
942
943
944
945
  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);
  }
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
946
947
948
  static u64 haswell_get_tolm(struct sbridge_pvt *pvt)
  {
  	u32 reg;
f7cf2a22a   Tony Luck   sb_edac: Fix disc...
949
950
  	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...
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  }
  
  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...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
  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...
983
984
985
986
  static u64 haswell_rir_limit(u32 reg)
  {
  	return (((u64)GET_BITFIELD(reg,  1, 11) + 1) << 29) - 1;
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
987
988
989
  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...
990
  	return ((pkg >> 3) << 2) | (pkg & 0x3);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
991
992
993
994
995
996
  }
  
  static inline u8 sad_pkg_ha(u8 pkg)
  {
  	return (pkg >> 2) & 0x1;
  }
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
  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;
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1010
1011
1012
  /****************************************************************************
  			Memory check routines
   ****************************************************************************/
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1013
  static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1014
  {
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1015
  	struct pci_dev *pdev = NULL;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1016

dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1017
1018
1019
1020
1021
  	do {
  		pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
  		if (pdev && pdev->bus->number == bus)
  			break;
  	} while (pdev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1022

dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1023
  	return pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1024
1025
1026
  }
  
  /**
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
1027
   * check_if_ecc_is_active() - Checks if ECC is active
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1028
1029
1030
1031
   * @bus:	Device bus
   * @type:	Memory controller type
   * returns: 0 in case ECC is active, -ENODEV if it can't be determined or
   *	    disabled
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1032
   */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1033
  static int check_if_ecc_is_active(const u8 bus, enum type type)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1034
1035
  {
  	struct pci_dev *pdev = NULL;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1036
  	u32 mcmtr, id;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1037

1f39581a9   Tony Luck   sb_edac: Add supp...
1038
1039
  	switch (type) {
  	case IVY_BRIDGE:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1040
  		id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
1f39581a9   Tony Luck   sb_edac: Add supp...
1041
1042
  		break;
  	case HASWELL:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1043
  		id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
1f39581a9   Tony Luck   sb_edac: Add supp...
1044
1045
  		break;
  	case SANDY_BRIDGE:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1046
  		id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
1f39581a9   Tony Luck   sb_edac: Add supp...
1047
1048
1049
1050
  		break;
  	case BROADWELL:
  		id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
  		break;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1051
1052
1053
1054
1055
1056
1057
  	case KNIGHTS_LANDING:
  		/*
  		 * KNL doesn't group things by bus the same way
  		 * SB/IB/Haswell does.
  		 */
  		id = PCI_DEVICE_ID_INTEL_KNL_IMC_TA;
  		break;
1f39581a9   Tony Luck   sb_edac: Add supp...
1058
1059
1060
  	default:
  		return -ENODEV;
  	}
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1061

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1062
1063
1064
1065
  	if (type != KNIGHTS_LANDING)
  		pdev = get_pdev_same_bus(bus, id);
  	else
  		pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, 0);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1066
1067
  	if (!pdev) {
  		sbridge_printk(KERN_ERR, "Couldn't find PCI device "
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
1068
1069
1070
  					"%04x:%04x! on bus %02d
  ",
  					PCI_VENDOR_ID_INTEL, id, bus);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1071
1072
  		return -ENODEV;
  	}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1073
1074
  	pci_read_config_dword(pdev,
  			type == KNIGHTS_LANDING ? KNL_MCMTR : MCMTR, &mcmtr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1075
1076
1077
1078
1079
  	if (!IS_ECC_ENABLED(mcmtr)) {
  		sbridge_printk(KERN_ERR, "ECC is disabled. Aborting
  ");
  		return -ENODEV;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1080
1081
  	return 0;
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
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
1199
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
  /* 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...
1233
  	return knl_channel_remap(mc, chan);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
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
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
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
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
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
  }
  
  /*
   * 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)
  {
  	u64 sad_base, sad_size, sad_limit = 0;
  	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;
  	int way;
  	int participants[KNL_MAX_CHANNELS];
  	int participant_count = 0;
  
  	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;
  		sad_size = sad_limit - sad_base;
  
  		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;
  					}
  				}
  				tad_base = tad_limit+1;
  			}
  		}
  
  		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++) {
  			for (way = 0; way < intrlv_ways; way++) {
  				int target;
  				int cha;
  
  				if (KNL_MOD3(dram_rule))
  					target = way;
  				else
  					target = 0x7 & sad_pkg(
  				pvt->info.interleave_pkg, interleave_reg, way);
  
  				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...
1537
  						&& !participants[channel]) {
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
  						participant_count++;
  						participants[channel] = 1;
  						break;
  					}
  				}
  			}
  		}
  
  		if (participant_count != intrlv_ways)
  			edac_dbg(0, "participant_count (%d) != interleave_ways (%d): DIMM size may be incorrect
  ",
  				participant_count, intrlv_ways);
  
  		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;
  }
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
1567
  static int get_dimm_config(struct mem_ctl_info *mci)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1568
1569
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
1570
  	struct dimm_info *dimm;
deb09ddaf   Mauro Carvalho Chehab   sb_edac: Avoid ov...
1571
1572
  	unsigned i, j, banks, ranks, rows, cols, npages;
  	u64 size;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1573
1574
  	u32 reg;
  	enum edac_type mode;
c6e13b528   Mark A. Grondona   EDAC: Fix incorre...
1575
  	enum mem_type mtype;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1576
1577
1578
  	int channels = pvt->info.type == KNIGHTS_LANDING ?
  		KNL_MAX_CHANNELS : NUM_CHANNELS;
  	u64 knl_mc_sizes[KNL_MAX_CHANNELS];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1579

ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
1580
1581
1582
1583
  	if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
  		pci_read_config_dword(pvt->pci_ha0, HASWELL_HASYSDEFEATURE2, &reg);
  		pvt->is_chan_hash = GET_BITFIELD(reg, 21, 21);
  	}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1584
1585
  	if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL ||
  			pvt->info.type == KNIGHTS_LANDING)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1586
1587
1588
  		pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
  	else
  		pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1589
1590
1591
1592
  	if (pvt->info.type == KNIGHTS_LANDING)
  		pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg);
  	else
  		pvt->sbridge_dev->source_id = SOURCE_ID(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1593

f14d6892e   Aristeu Rozanski   sb_edac: make nod...
1594
  	pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
956b9ba15   Joe Perches   edac: Convert deb...
1595
1596
1597
1598
1599
  	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);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1600

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1601
1602
1603
1604
1605
  	/* KNL doesn't support mirroring or lockstep,
  	 * and is always closed page
  	 */
  	if (pvt->info.type == KNIGHTS_LANDING) {
  		mode = EDAC_S4ECD4ED;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1606
  		pvt->is_mirrored = false;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1607

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1608
1609
  		if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
  			return -1;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1610
  	} else {
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
  		pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
  		if (IS_MIRROR_ENABLED(reg)) {
  			edac_dbg(0, "Memory mirror is enabled
  ");
  			pvt->is_mirrored = true;
  		} else {
  			edac_dbg(0, "Memory mirror is disabled
  ");
  			pvt->is_mirrored = false;
  		}
  
  		pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
  		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;
  		}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1643
  	}
9e3754461   Aristeu Rozanski   sb_edac: make mem...
1644
  	mtype = pvt->info.get_memory_type(pvt);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1645
  	if (mtype == MEM_RDDR3 || mtype == MEM_RDDR4)
9e3754461   Aristeu Rozanski   sb_edac: make mem...
1646
1647
1648
  		edac_dbg(0, "Memory is registered
  ");
  	else if (mtype == MEM_UNKNOWN)
de4772c62   Tony Luck   edac: sb_edac.c s...
1649
1650
  		edac_dbg(0, "Cannot determine memory type
  ");
9e3754461   Aristeu Rozanski   sb_edac: make mem...
1651
1652
1653
  	else
  		edac_dbg(0, "Memory is unregistered
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1654

fec53af53   Tony Luck   sb_edac: Fix typo...
1655
  	if (mtype == MEM_DDR4 || mtype == MEM_RDDR4)
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1656
1657
1658
  		banks = 16;
  	else
  		banks = 8;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1659

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1660
  	for (i = 0; i < channels; i++) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1661
  		u32 mtr;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
  		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++) {
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
1675
1676
  			dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers,
  				       i, j, 0);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1677
1678
1679
1680
1681
1682
1683
  			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...
1684
1685
  			edac_dbg(4, "Channel #%d  MTR%d = %x
  ", i, j, mtr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1686
1687
  			if (IS_DIMM_PRESENT(mtr)) {
  				pvt->channel[i].dimms++;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1688
  				ranks = numrank(pvt->info.type, mtr);
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
  
  				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...
1699

deb09ddaf   Mauro Carvalho Chehab   sb_edac: Avoid ov...
1700
  				size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1701
  				npages = MiB_TO_PAGES(size);
7d375bffa   Tony Luck   sb_edac: Fix supp...
1702
1703
1704
  				edac_dbg(0, "mc#%d: ha %d channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x
  ",
  					 pvt->sbridge_dev->mc, i/4, i%4, j,
956b9ba15   Joe Perches   edac: Convert deb...
1705
1706
  					 size, npages,
  					 banks, ranks, rows, cols);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1707

a895bf8b1   Mauro Carvalho Chehab   edac: move nr_pag...
1708
  				dimm->nr_pages = npages;
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
1709
  				dimm->grain = 32;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
1710
  				dimm->dtype = pvt->info.get_width(pvt, mtr);
084a4fcce   Mauro Carvalho Chehab   edac: move dimm p...
1711
1712
1713
  				dimm->mtype = mtype;
  				dimm->edac_mode = mode;
  				snprintf(dimm->label, sizeof(dimm->label),
7d375bffa   Tony Luck   sb_edac: Fix supp...
1714
1715
  					 "CPU_SrcID#%u_Ha#%u_Chan#%u_DIMM#%u",
  					 pvt->sbridge_dev->source_id, i/4, i%4, j);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
  			}
  		}
  	}
  
  	return 0;
  }
  
  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...
1730
  	u32 gb, mb;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1731
1732
1733
1734
1735
  	u32 rir_way;
  
  	/*
  	 * Step 1) Get TOLM/TOHM ranges
  	 */
fb79a5092   Aristeu Rozanski   sb_edac: isolate ...
1736
  	pvt->tolm = pvt->info.get_tolm(pvt);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1737
  	tmp_mb = (1 + pvt->tolm) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1738
1739
1740
1741
  	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...
1742
1743
  
  	/* Address range is already 45:25 */
8fd6a43ac   Aristeu Rozanski   sb_edac: isolate ...
1744
  	pvt->tohm = pvt->info.get_tohm(pvt);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1745
  	tmp_mb = (1 + pvt->tohm) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1746
1747
1748
1749
  	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...
1750
1751
1752
1753
1754
1755
1756
1757
  
  	/*
  	 * 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...
1758
  	for (n_sads = 0; n_sads < pvt->info.max_sad; n_sads++) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1759
  		/* SAD_LIMIT Address range is 45:26 */
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1760
  		pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1761
  				      &reg);
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1762
  		limit = pvt->info.sad_limit(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1763
1764
1765
1766
1767
1768
1769
1770
  
  		if (!DRAM_RULE_ENABLE(reg))
  			continue;
  
  		if (limit <= prv)
  			break;
  
  		tmp_mb = (limit + 1) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1771
  		gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1772
1773
1774
  		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...
1775
  			 show_dram_attr(pvt->info.dram_attr(reg)),
8c0091002   Jim Snow   sb_edac: Fix erro...
1776
  			 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1777
  			 ((u64)tmp_mb) << 20L,
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1778
  			 pvt->info.show_interleave_mode(reg),
956b9ba15   Joe Perches   edac: Convert deb...
1779
  			 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1780
  		prv = limit;
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
1781
  		pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1782
  				      &reg);
cc311991a   Aristeu Rozanski   sb_edac: rework s...
1783
  		sad_interl = sad_pkg(pvt->info.interleave_pkg, reg, 0);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1784
  		for (j = 0; j < 8; j++) {
cc311991a   Aristeu Rozanski   sb_edac: rework s...
1785
1786
  			u32 pkg = sad_pkg(pvt->info.interleave_pkg, reg, j);
  			if (j > 0 && sad_interl == pkg)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1787
  				break;
956b9ba15   Joe Perches   edac: Convert deb...
1788
1789
  			edac_dbg(0, "SAD#%d, interleave #%d: %d
  ",
cc311991a   Aristeu Rozanski   sb_edac: rework s...
1790
  				 n_sads, j, pkg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1791
1792
  		}
  	}
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
1793
1794
  	if (pvt->info.type == KNIGHTS_LANDING)
  		return;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
  	/*
  	 * Step 3) Get TAD range
  	 */
  	prv = 0;
  	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
  		pci_read_config_dword(pvt->pci_ha0, tad_dram_rule[n_tads],
  				      &reg);
  		limit = TAD_LIMIT(reg);
  		if (limit <= prv)
  			break;
  		tmp_mb = (limit + 1) >> 20;
8c0091002   Jim Snow   sb_edac: Fix erro...
1806
  		gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1807
1808
  		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...
1809
  			 n_tads, gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1810
  			 ((u64)tmp_mb) << 20L,
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
1811
1812
  			 (u32)(1 << TAD_SOCK(reg)),
  			 (u32)TAD_CH(reg) + 1,
956b9ba15   Joe Perches   edac: Convert deb...
1813
1814
1815
1816
1817
  			 (u32)TAD_TGT0(reg),
  			 (u32)TAD_TGT1(reg),
  			 (u32)TAD_TGT2(reg),
  			 (u32)TAD_TGT3(reg),
  			 reg);
7fae0db43   Hui Wang   edac: sb_edac: Fi...
1818
  		prv = limit;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
  	}
  
  	/*
  	 * 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...
1832
  			gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1833
1834
1835
  			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...
1836
  				 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1837
1838
  				 ((u64)tmp_mb) << 20L,
  				 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
  		}
  	}
  
  	/*
  	 * 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...
1855
  			tmp_mb = pvt->info.rir_limit(reg) >> 20;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1856
  			rir_way = 1 << RIR_WAY(reg);
8c0091002   Jim Snow   sb_edac: Fix erro...
1857
  			gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1858
1859
1860
  			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...
1861
  				 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1862
1863
1864
  				 ((u64)tmp_mb) << 20L,
  				 rir_way,
  				 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1865
1866
1867
1868
1869
  
  			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...
1870
  				tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1871

8c0091002   Jim Snow   sb_edac: Fix erro...
1872
  				gb = div_u64_rem(tmp_mb, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
1873
1874
1875
  				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...
1876
  					 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
1877
  					 ((u64)tmp_mb) << 20L,
c7103f650   Tony Luck   EDAC, sb_edac: Fi...
1878
  					 (u32)RIR_RNK_TGT(pvt->info.type, reg),
956b9ba15   Joe Perches   edac: Convert deb...
1879
  					 reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1880
1881
1882
1883
  			}
  		}
  	}
  }
8112c0cdf   Rashika Kheria   sb_edac: Mark get...
1884
  static struct mem_ctl_info *get_mci_for_node_id(u8 node_id)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
  {
  	struct sbridge_dev *sbridge_dev;
  
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
  		if (sbridge_dev->node_id == node_id)
  			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...
1897
  				 u8 *socket, u8 *ha,
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1898
1899
  				 long *channel_mask,
  				 u8 *rank,
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
1900
  				 char **area_type, char *msg)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1901
1902
1903
  {
  	struct mem_ctl_info	*new_mci;
  	struct sbridge_pvt *pvt = mci->pvt_info;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1904
  	struct pci_dev		*pci_ha;
c41afdca2   Mauro Carvalho Chehab   sb_edac: Fix mix ...
1905
  	int			n_rir, n_sads, n_tads, sad_way, sck_xch;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1906
  	int			sad_interl, idx, base_ch;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1907
  	int			interleave_mode, shiftup = 0;
ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
1908
  	unsigned		sad_interleave[pvt->info.max_interleave];
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1909
  	u32			reg, dram_rule;
7d375bffa   Tony Luck   sb_edac: Fix supp...
1910
  	u8			ch_way, sck_way, pkg, sad_ha = 0, ch_add = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1911
1912
  	u32			tad_offset;
  	u32			rir_way;
8c0091002   Jim Snow   sb_edac: Fix erro...
1913
  	u32			mb, gb;
bd4b96836   Aristeu Rozanski   sb_edac: Shut up ...
1914
  	u64			ch_addr, offset, limit = 0, prv = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1915
1916
1917
1918
1919
1920
1921
1922
1923
  
  
  	/*
  	 * 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...
1924
  	if ((addr > (u64) pvt->tolm) && (addr < (1LL << 32))) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1925
  		sprintf(msg, "Error at TOLM area, on addr 0x%08Lx", addr);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1926
1927
1928
1929
  		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...
1930
1931
1932
1933
1934
1935
  		return -EINVAL;
  	}
  
  	/*
  	 * Step 1) Get socket
  	 */
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1936
1937
  	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...
1938
1939
1940
1941
  				      &reg);
  
  		if (!DRAM_RULE_ENABLE(reg))
  			continue;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1942
  		limit = pvt->info.sad_limit(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1943
1944
  		if (limit <= prv) {
  			sprintf(msg, "Can't discover the memory socket");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1945
1946
1947
1948
1949
1950
  			return -EINVAL;
  		}
  		if  (addr <= limit)
  			break;
  		prv = limit;
  	}
464f1d829   Aristeu Rozanski   sb_edac: allow di...
1951
  	if (n_sads == pvt->info.max_sad) {
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1952
  		sprintf(msg, "Can't discover the memory socket");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1953
1954
  		return -EINVAL;
  	}
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
1955
  	dram_rule = reg;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
1956
1957
  	*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...
1958

ef1ce51e7   Aristeu Rozanski   sb_edac: allow di...
1959
  	pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
1960
  			      &reg);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
  
  	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...
1988
  			break;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
  		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...
2005
  	} else if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2006
2007
2008
2009
2010
2011
2012
  		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...
2013
  			bits = GET_BITFIELD(addr, 6, 8);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2014

bb89e7141   Tony Luck   sb_edac: Fix a ty...
2015
  		if (interleave_mode == 0) {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2016
2017
2018
2019
2020
2021
2022
2023
2024
  			/* 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);
7d375bffa   Tony Luck   sb_edac: Fix supp...
2025
2026
  		if (sad_ha)
  			ch_add = 4;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
  
  		if (a7mode) {
  			/* MCChanShiftUpEnable */
  			pci_read_config_dword(pvt->pci_ha0,
  					      HASWELL_HASYSDEFEATURE2, &reg);
  			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...
2038
2039
  	} else {
  		/* Ivy Bridge's SAD mode doesn't support XOR interleave mode */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2040
  		idx = (addr >> 6) & 7;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2041
2042
2043
  		pkg = sad_pkg(pvt->info.interleave_pkg, reg, idx);
  		*socket = sad_pkg_socket(pkg);
  		sad_ha = sad_pkg_ha(pkg);
7d375bffa   Tony Luck   sb_edac: Fix supp...
2044
2045
  		if (sad_ha)
  			ch_add = 4;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2046
2047
2048
  		edac_dbg(0, "SAD interleave package: %d = CPU socket %d, HA %d
  ",
  			 idx, *socket, sad_ha);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2049
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2050

7d375bffa   Tony Luck   sb_edac: Fix supp...
2051
  	*ha = sad_ha;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2052
2053
2054
2055
2056
2057
2058
2059
  	/*
  	 * Move to the proper node structure, in order to access the
  	 * right PCI registers
  	 */
  	new_mci = get_mci_for_node_id(*socket);
  	if (!new_mci) {
  		sprintf(msg, "Struct for socket #%u wasn't initialized",
  			*socket);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2060
2061
2062
2063
2064
2065
2066
2067
2068
  		return -EINVAL;
  	}
  	mci = new_mci;
  	pvt = mci->pvt_info;
  
  	/*
  	 * Step 2) Get memory channel
  	 */
  	prv = 0;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2069
2070
2071
2072
2073
2074
2075
2076
  	if (pvt->info.type == SANDY_BRIDGE)
  		pci_ha = pvt->pci_ha0;
  	else {
  		if (sad_ha)
  			pci_ha = pvt->pci_ha1;
  		else
  			pci_ha = pvt->pci_ha0;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2077
  	for (n_tads = 0; n_tads < MAX_TAD; n_tads++) {
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2078
  		pci_read_config_dword(pci_ha, tad_dram_rule[n_tads], &reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2079
2080
2081
  		limit = TAD_LIMIT(reg);
  		if (limit <= prv) {
  			sprintf(msg, "Can't discover the memory channel");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2082
2083
2084
2085
2086
2087
  			return -EINVAL;
  		}
  		if  (addr <= limit)
  			break;
  		prv = limit;
  	}
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2088
2089
2090
2091
  	if (n_tads == MAX_TAD) {
  		sprintf(msg, "Can't discover the memory channel");
  		return -EINVAL;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2092
  	ch_way = TAD_CH(reg) + 1;
ff15e95c8   Tony Luck   x86 EDAC, sb_edac...
2093
  	sck_way = TAD_SOCK(reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2094
2095
2096
  
  	if (ch_way == 3)
  		idx = addr >> 6;
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
2097
  	else {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2098
  		idx = (addr >> (6 + sck_way + shiftup)) & 0x3;
ea5dfb5fa   Tony Luck   x86 EDAC, sb_edac...
2099
2100
2101
  		if (pvt->is_chan_hash)
  			idx = haswell_chan_hash(idx, addr);
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
  	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...
2122
2123
2124
  		return -EINVAL;
  	}
  	*channel_mask = 1 << base_ch;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2125
  	pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2126
2127
  				tad_ch_nilv_offset[n_tads],
  				&tad_offset);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2128
2129
2130
2131
2132
  	if (pvt->is_mirrored) {
  		*channel_mask |= 1 << ((base_ch + 2) % 4);
  		switch(ch_way) {
  		case 2:
  		case 4:
ff15e95c8   Tony Luck   x86 EDAC, sb_edac...
2133
  			sck_xch = (1 << sck_way) * (ch_way >> 1);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2134
2135
2136
  			break;
  		default:
  			sprintf(msg, "Invalid mirror set. Can't decode addr");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2137
2138
2139
2140
2141
2142
2143
2144
2145
  			return -EINVAL;
  		}
  	} else
  		sck_xch = (1 << sck_way) * ch_way;
  
  	if (pvt->is_lockstep)
  		*channel_mask |= 1 << ((base_ch + 1) % 4);
  
  	offset = TAD_OFFSET(tad_offset);
956b9ba15   Joe Perches   edac: Convert deb...
2146
2147
2148
2149
2150
  	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...
2151
  		 sck_way,
956b9ba15   Joe Perches   edac: Convert deb...
2152
2153
2154
2155
2156
  		 ch_way,
  		 offset,
  		 idx,
  		 base_ch,
  		 *channel_mask);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2157
2158
2159
2160
2161
2162
2163
  
  	/* 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...
2164
2165
  		return -EINVAL;
  	}
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
2166
2167
2168
  
  	ch_addr = addr - offset;
  	ch_addr >>= (6 + shiftup);
ff15e95c8   Tony Luck   x86 EDAC, sb_edac...
2169
  	ch_addr /= sck_xch;
eb1af3b71   Tony Luck   EDAC/sb_edac: Fix...
2170
2171
  	ch_addr <<= (6 + shiftup);
  	ch_addr |= addr & ((1 << (6 + shiftup)) - 1);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2172
2173
2174
2175
2176
  
  	/*
  	 * Step 3) Decode rank
  	 */
  	for (n_rir = 0; n_rir < MAX_RIR_RANGES; n_rir++) {
7d375bffa   Tony Luck   sb_edac: Fix supp...
2177
  		pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2178
2179
2180
2181
2182
  				      rir_way_limit[n_rir],
  				      &reg);
  
  		if (!IS_RIR_VALID(reg))
  			continue;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
2183
  		limit = pvt->info.rir_limit(reg);
8c0091002   Jim Snow   sb_edac: Fix erro...
2184
  		gb = div_u64_rem(limit >> 20, 1024, &mb);
956b9ba15   Joe Perches   edac: Convert deb...
2185
2186
2187
  		edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d
  ",
  			 n_rir,
8c0091002   Jim Snow   sb_edac: Fix erro...
2188
  			 gb, (mb*1000)/1024,
956b9ba15   Joe Perches   edac: Convert deb...
2189
2190
  			 limit,
  			 1 << RIR_WAY(reg));
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2191
2192
2193
2194
2195
2196
  		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...
2197
2198
2199
  		return -EINVAL;
  	}
  	rir_way = RIR_WAY(reg);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2200

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2201
2202
2203
2204
2205
  	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;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2206
  	pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2207
2208
  			      rir_offset[n_rir][idx],
  			      &reg);
c7103f650   Tony Luck   EDAC, sb_edac: Fi...
2209
  	*rank = RIR_RNK_TGT(pvt->info.type, reg);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2210

956b9ba15   Joe Perches   edac: Convert deb...
2211
2212
2213
2214
2215
2216
2217
  	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...
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
  
  	return 0;
  }
  
  /****************************************************************************
  	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...
2233
2234
  	edac_dbg(0, "
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2235
2236
2237
2238
  	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...
2239
2240
2241
2242
  		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...
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
  		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...
2256
2257
2258
  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...
2259
2260
  				 const unsigned devno,
  				 const int multi_bus)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2261
2262
2263
  {
  	struct sbridge_dev *sbridge_dev;
  	const struct pci_id_descr *dev_descr = &table->descr[devno];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2264
2265
  	struct pci_dev *pdev = NULL;
  	u8 bus = 0;
ec5a0b382   Jiang Liu   sb_edac: Degrade ...
2266
  	sbridge_printk(KERN_DEBUG,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2267
2268
  		"Seeking for: PCI ID %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
  		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...
2282
  		/* if the HA wasn't found */
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2283
2284
2285
2286
  		if (devno == 0)
  			return -ENODEV;
  
  		sbridge_printk(KERN_INFO,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2287
2288
  			"Device not found: %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2289
2290
2291
2292
2293
2294
  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  
  		/* End of list, leave */
  		return -ENODEV;
  	}
  	bus = pdev->bus->number;
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2295
  	sbridge_dev = get_sbridge_dev(bus, multi_bus);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
  	if (!sbridge_dev) {
  		sbridge_dev = alloc_sbridge_dev(bus, table);
  		if (!sbridge_dev) {
  			pci_dev_put(pdev);
  			return -ENOMEM;
  		}
  		(*num_mc)++;
  	}
  
  	if (sbridge_dev->pdev[devno]) {
  		sbridge_printk(KERN_ERR,
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2307
2308
  			"Duplicated device for %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2309
2310
2311
2312
2313
2314
  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  		pci_dev_put(pdev);
  		return -ENODEV;
  	}
  
  	sbridge_dev->pdev[devno] = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2315
2316
2317
  	/* 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...
2318
2319
  			"Couldn't enable %04x:%04x
  ",
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2320
2321
2322
  			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
  		return -ENODEV;
  	}
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2323
2324
  	edac_dbg(0, "Detected %04x:%04x
  ",
956b9ba15   Joe Perches   edac: Convert deb...
2325
  		 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
  
  	/*
  	 * 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...
2338
2339
  /*
   * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2340
   *			     devices we want to reference for this driver.
5153a0f94   Aristeu Rozanski   sb_edac: enable m...
2341
   * @num_mc: pointer to the memory controllers count, to be incremented in case
c41afdca2   Mauro Carvalho Chehab   sb_edac: Fix mix ...
2342
   *	    of success.
5153a0f94   Aristeu Rozanski   sb_edac: enable m...
2343
2344
2345
2346
   * @table: model specific table
   *
   * returns 0 in case of success or error code
   */
0ba169ac3   Tony Luck   EDAC, sb_edac: Fi...
2347
2348
  static int sbridge_get_all_devices(u8 *num_mc,
  					const struct pci_id_table *table)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2349
2350
2351
  {
  	int i, rc;
  	struct pci_dev *pdev = NULL;
0ba169ac3   Tony Luck   EDAC, sb_edac: Fi...
2352
2353
  	int allow_dups = 0;
  	int multi_bus = 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2354

0ba169ac3   Tony Luck   EDAC, sb_edac: Fi...
2355
2356
  	if (table->type == KNIGHTS_LANDING)
  		allow_dups = multi_bus = 1;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2357
2358
  	while (table && table->descr) {
  		for (i = 0; i < table->n_devs; i++) {
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2359
2360
2361
2362
2363
  			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...
2364
2365
  			do {
  				rc = sbridge_get_onedevice(&pdev, num_mc,
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2366
  							   table, i, multi_bus);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2367
2368
2369
2370
2371
2372
2373
2374
  				if (rc < 0) {
  					if (i == 0) {
  						i = table->n_devs;
  						break;
  					}
  					sbridge_put_all_devices();
  					return -ENODEV;
  				}
c1979ba25   Jim Snow   EDAC, sb_edac: Ad...
2375
  			} while (pdev && !allow_dups);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2376
2377
2378
2379
2380
2381
  		}
  		table++;
  	}
  
  	return 0;
  }
ea779b5a0   Aristeu Rozanski   sb_edac: rename m...
2382
2383
  static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
  				 struct sbridge_dev *sbridge_dev)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2384
2385
2386
  {
  	struct sbridge_pvt *pvt = mci->pvt_info;
  	struct pci_dev *pdev;
2900ea609   Seth Jennings   EDAC, sb_edac: Fi...
2387
  	u8 saw_chan_mask = 0;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2388
  	int i;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2389
2390
2391
2392
2393
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2394
2395
2396
2397
  
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0:
  			pvt->pci_sad0 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2398
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2399
2400
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1:
  			pvt->pci_sad1 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2401
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2402
2403
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_BR:
  			pvt->pci_br0 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2404
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2405
2406
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
  			pvt->pci_ha0 = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2407
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
  		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:
  		{
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
  			pvt->pci_tad[id] = pdev;
2900ea609   Seth Jennings   EDAC, sb_edac: Fi...
2421
  			saw_chan_mask |= 1 << id;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2422
2423
2424
2425
  		}
  			break;
  		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
  			pvt->pci_ddrio = pdev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2426
2427
2428
2429
  			break;
  		default:
  			goto error;
  		}
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2430
2431
2432
  		edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p
  ",
  			 pdev->vendor, pdev->device,
956b9ba15   Joe Perches   edac: Convert deb...
2433
  			 sbridge_dev->bus,
956b9ba15   Joe Perches   edac: Convert deb...
2434
  			 pdev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2435
2436
2437
2438
  	}
  
  	/* Check if everything were registered */
  	if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 ||
c7c35407c   Colin Ian King   EDAC, sb_edac: Re...
2439
  	    !pvt->pci_ras || !pvt->pci_ta)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2440
  		goto enodev;
2900ea609   Seth Jennings   EDAC, sb_edac: Fi...
2441
2442
  	if (saw_chan_mask != 0x0f)
  		goto enodev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2443
2444
2445
2446
2447
2448
2449
2450
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  
  error:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2451
2452
2453
  	sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x
  ",
  		       PCI_VENDOR_ID_INTEL, pdev->device);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2454
2455
  	return -EINVAL;
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2456
2457
2458
2459
  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...
2460
2461
  	struct pci_dev *pdev;
  	u8 saw_chan_mask = 0;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2462
  	int i;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2463
2464
2465
2466
2467
  
  	for (i = 0; i < sbridge_dev->n_devs; i++) {
  		pdev = sbridge_dev->pdev[i];
  		if (!pdev)
  			continue;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2468

dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2469
2470
2471
2472
2473
2474
2475
2476
2477
  		switch (pdev->device) {
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
  			pvt->pci_ha0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
  			pvt->pci_ta = pdev;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
  			pvt->pci_ras = pdev;
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2478
2479
  		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...
2480
2481
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2482
2483
2484
  		{
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0;
  			pvt->pci_tad[id] = pdev;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2485
  			saw_chan_mask |= 1 << id;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2486
  		}
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2487
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2488
2489
2490
2491
  		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...
2492
  			pvt->pci_ddrio = pdev;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2493
  			break;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
  		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;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
  			pvt->pci_ha1 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
  		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
7d375bffa   Tony Luck   sb_edac: Fix supp...
2508
2509
  		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...
2510
  		{
7d375bffa   Tony Luck   sb_edac: Fix supp...
2511
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 4;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2512
  			pvt->pci_tad[id] = pdev;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2513
  			saw_chan_mask |= 1 << id;
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
2514
2515
  		}
  			break;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
  		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 */
  	if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_br0 ||
c7c35407c   Colin Ian King   EDAC, sb_edac: Re...
2529
  	    !pvt->pci_br1 || !pvt->pci_ras || !pvt->pci_ta)
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2530
  		goto enodev;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2531
2532
2533
2534
  	if (saw_chan_mask != 0x0f && /* -EN */
  	    saw_chan_mask != 0x33 && /* -EP */
  	    saw_chan_mask != 0xff)   /* -EX */
  		goto enodev;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2535
2536
2537
2538
2539
2540
2541
2542
2543
  	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...
2544
2545
2546
  		       "Unexpected device %02x:%02x
  ", PCI_VENDOR_ID_INTEL,
  			pdev->device);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2547
2548
  	return -EINVAL;
  }
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2549
2550
2551
2552
  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...
2553
2554
  	struct pci_dev *pdev;
  	u8 saw_chan_mask = 0;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2555
  	int i;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
  
  	/* 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:
  			pvt->pci_ha0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA:
  			pvt->pci_ta = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_THERMAL:
  			pvt->pci_ras = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2586
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD1:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2587
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD2:
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2588
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3:
7d375bffa   Tony Luck   sb_edac: Fix supp...
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
  		{
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD0;
  
  			pvt->pci_tad[id] = pdev;
  			saw_chan_mask |= 1 << id;
  		}
  			break;
  		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:
  		{
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD0 + 4;
  
  			pvt->pci_tad[id] = pdev;
  			saw_chan_mask |= 1 << id;
  		}
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2606
2607
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0:
7179385af   Aristeu Rozanski   sb_edac: look har...
2608
2609
2610
2611
2612
  		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...
2613
2614
2615
2616
2617
2618
2619
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1:
  			pvt->pci_ha1 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA:
  			pvt->pci_ha1_ta = pdev;
  			break;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
  		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 */
  	if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
  	    !pvt->pci_ras  || !pvt->pci_ta || !pvt->info.pci_vtd)
  		goto enodev;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2635
2636
2637
2638
  	if (saw_chan_mask != 0x0f && /* -EN */
  	    saw_chan_mask != 0x33 && /* -EP */
  	    saw_chan_mask != 0xff)   /* -EX */
  		goto enodev;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
2639
2640
2641
2642
2643
2644
2645
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  }
1f39581a9   Tony Luck   sb_edac: Add supp...
2646
2647
2648
2649
2650
  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 ...
2651
  	u8 saw_chan_mask = 0;
1f39581a9   Tony Luck   sb_edac: Add supp...
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
  	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:
  			pvt->pci_ha0 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA:
  			pvt->pci_ta = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL:
  			pvt->pci_ras = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0:
1f39581a9   Tony Luck   sb_edac: Add supp...
2683
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1:
1f39581a9   Tony Luck   sb_edac: Add supp...
2684
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2:
1f39581a9   Tony Luck   sb_edac: Add supp...
2685
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3:
fa2ce64f8   Tony Luck   sb_edac: support ...
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
  		{
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0;
  			pvt->pci_tad[id] = pdev;
  			saw_chan_mask |= 1 << id;
  		}
  			break;
  		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:
  		{
  			int id = pdev->device - PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TAD0 + 4;
  			pvt->pci_tad[id] = pdev;
  			saw_chan_mask |= 1 << id;
  		}
1f39581a9   Tony Luck   sb_edac: Add supp...
2701
2702
2703
2704
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0:
  			pvt->pci_ddrio = pdev;
  			break;
fa2ce64f8   Tony Luck   sb_edac: support ...
2705
2706
2707
2708
2709
2710
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1:
  			pvt->pci_ha1 = pdev;
  			break;
  		case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA1_TA:
  			pvt->pci_ha1_ta = pdev;
  			break;
1f39581a9   Tony Luck   sb_edac: Add supp...
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
  		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 */
  	if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
  	    !pvt->pci_ras  || !pvt->pci_ta || !pvt->info.pci_vtd)
  		goto enodev;
fa2ce64f8   Tony Luck   sb_edac: support ...
2726
2727
2728
2729
  	if (saw_chan_mask != 0x0f && /* -EN */
  	    saw_chan_mask != 0x33 && /* -EP */
  	    saw_chan_mask != 0xff)   /* -EX */
  		goto enodev;
1f39581a9   Tony Luck   sb_edac: Add supp...
2730
2731
2732
2733
2734
2735
2736
  	return 0;
  
  enodev:
  	sbridge_printk(KERN_ERR, "Some needed devices are missing
  ");
  	return -ENODEV;
  }
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
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
2831
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
  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;
  
  		case PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL:
  			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...
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
  /****************************************************************************
  			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 ...
2883
  	enum hw_event_mc_err_type tp_event;
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
2884
  	char *type, *optype, msg[256];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2885
2886
2887
  	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...
2888
  	bool recoverable;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2889
2890
2891
2892
2893
2894
  	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);
  	long channel_mask, first_channel;
7d375bffa   Tony Luck   sb_edac: Fix supp...
2895
  	u8  rank, socket, ha;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2896
  	int rc, dimm;
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
2897
  	char *area_type = NULL;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2898

fa2ce64f8   Tony Luck   sb_edac: support ...
2899
  	if (pvt->info.type != SANDY_BRIDGE)
4d715a805   Aristeu Rozanski   sb_edac: add supp...
2900
2901
2902
  		recoverable = true;
  	else
  		recoverable = GET_BITFIELD(m->status, 56, 56);
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
  	if (uncorrected_error) {
  		if (ripv) {
  			type = "FATAL";
  			tp_event = HW_EVENT_ERR_FATAL;
  		} else {
  			type = "NON_FATAL";
  			tp_event = HW_EVENT_ERR_UNCORRECTED;
  		}
  	} else {
  		type = "CORRECTED";
  		tp_event = HW_EVENT_ERR_CORRECTED;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2915
2916
  
  	/*
15ed103a9   David Mackey   edac: Fix spellin...
2917
  	 * According with Table 15-9 of the Intel Architecture spec vol 3A,
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
  	 * 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
  	 */
  	if (! ((errcode & 0xef80) == 0x80)) {
  		optype = "Can't parse: it is not a mem";
  	} else {
  		switch (optypenum) {
  		case 0:
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2932
  			optype = "generic undef request error";
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2933
2934
  			break;
  		case 1:
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2935
  			optype = "memory read error";
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2936
2937
  			break;
  		case 2:
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2938
  			optype = "memory write error";
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2939
2940
  			break;
  		case 3:
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2941
  			optype = "addr/cmd error";
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2942
2943
  			break;
  		case 4:
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2944
  			optype = "memory scrubbing error";
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2945
2946
2947
2948
2949
2950
  			break;
  		default:
  			optype = "reserved";
  			break;
  		}
  	}
be3036d22   Aristeu Rozanski   sb_edac: avoid de...
2951
2952
2953
  	/* Only decode errors with an valid address (ADDRV) */
  	if (!GET_BITFIELD(m->status, 58, 58))
  		return;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
  	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...
2965
2966
2967
2968
2969
2970
2971
  			/*
  			 * 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...
2972
  			channel_mask = 1 << channel;
c5b48fa7e   Lukasz Odzioba   EDAC, sb_edac: Fi...
2973

d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
  			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;
  	} else {
  		rc = get_memory_error_data(mci, m->addr, &socket, &ha,
  				&channel_mask, &rank, &area_type, msg);
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2990
  	if (rc < 0)
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2991
  		goto err_parsing;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2992
2993
  	new_mci = get_mci_for_node_id(socket);
  	if (!new_mci) {
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
2994
2995
  		strcpy(msg, "Error: socket got corrupted!");
  		goto err_parsing;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
  	}
  	mci = new_mci;
  	pvt = mci->pvt_info;
  
  	first_channel = find_first_bit(&channel_mask, NUM_CHANNELS);
  
  	if (rank < 4)
  		dimm = 0;
  	else if (rank < 8)
  		dimm = 1;
  	else
  		dimm = 2;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3008
3009
  
  	/*
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
3010
3011
3012
3013
  	 * 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...
3014
  	 */
d7c660b7d   Aristeu Rozanski   sb_edac: make min...
3015
3016
  	if (!pvt->is_lockstep && !pvt->is_mirrored && !pvt->is_close_pg)
  		channel = first_channel;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3017
  	snprintf(msg, sizeof(msg),
7d375bffa   Tony Luck   sb_edac: Fix supp...
3018
  		 "%s%s area:%s err_code:%04x:%04x socket:%d ha:%d channel_mask:%ld rank:%d",
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
3019
3020
3021
3022
  		 overflow ? " OVERFLOW" : "",
  		 (uncorrected_error && recoverable) ? " recoverable" : "",
  		 area_type,
  		 mscod, errcode,
7d375bffa   Tony Luck   sb_edac: Fix supp...
3023
  		 socket, ha,
e17a2f42a   Mauro Carvalho Chehab   edac: Cleanup the...
3024
3025
  		 channel_mask,
  		 rank);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3026

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

c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3030
  	/* FIXME: need support for channel mask */
351fc4a99   Seth Jennings   sb_edac: avoid IN...
3031
3032
  	if (channel == CHANNEL_UNSPECIFIED)
  		channel = -1;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3033
  	/* Call the helper to output message */
c10538396   Mauro Carvalho Chehab   sb_edac: properly...
3034
  	edac_mc_handle_error(tp_event, mci, core_err_cnt,
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3035
  			     m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
7d375bffa   Tony Luck   sb_edac: Fix supp...
3036
  			     4*ha+channel, dimm, -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
3037
  			     optype, msg);
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3038
3039
  	return;
  err_parsing:
c10538396   Mauro Carvalho Chehab   sb_edac: properly...
3040
  	edac_mc_handle_error(tp_event, mci, core_err_cnt, 0, 0, 0,
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3041
  			     -1, -1, -1,
03f7eae80   Mauro Carvalho Chehab   edac: remove arch...
3042
  			     msg, "");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3043

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3044
3045
3046
  }
  
  /*
ad08c4e97   Tony Luck   EDAC, sb_edac: Re...
3047
3048
   * 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...
3049
   */
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3050
3051
  static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
  				   void *data)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3052
  {
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3053
3054
3055
  	struct mce *mce = (struct mce *)data;
  	struct mem_ctl_info *mci;
  	struct sbridge_pvt *pvt;
cf40f80cb   Aristeu Rozanski   sb_edac: use "eve...
3056
  	char *type;
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3057

fd5210396   Chen, Gong   EDAC, sb_edac: Mo...
3058
3059
  	if (get_edac_report_status() == EDAC_REPORTING_DISABLED)
  		return NOTIFY_DONE;
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3060
3061
  	mci = get_mci_for_node_id(mce->socketid);
  	if (!mci)
c4fc1956f   Tony Luck   EDAC: i7core, sb_...
3062
  		return NOTIFY_DONE;
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3063
  	pvt = mci->pvt_info;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3064
3065
3066
3067
3068
3069
3070
3071
  
  	/*
  	 * 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...
3072
  		return NOTIFY_DONE;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3073

cf40f80cb   Aristeu Rozanski   sb_edac: use "eve...
3074
3075
3076
3077
  	if (mce->mcgstatus & MCG_STATUS_MCIP)
  		type = "Exception";
  	else
  		type = "Event";
49856dc97   Aristeu Rozanski   sb_edac: mark MCE...
3078
3079
  	sbridge_mc_printk(mci, KERN_DEBUG, "HANDLING MCE MEMORY ERROR
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3080

49856dc97   Aristeu Rozanski   sb_edac: mark MCE...
3081
3082
3083
3084
3085
3086
3087
  	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...
3088

49856dc97   Aristeu Rozanski   sb_edac: mark MCE...
3089
3090
3091
3092
  	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...
3093

ad08c4e97   Tony Luck   EDAC, sb_edac: Re...
3094
  	sbridge_mce_output_error(mci, mce);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3095
3096
  
  	/* Advice mcelog that the error were handled */
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3097
  	return NOTIFY_STOP;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3098
  }
3d78c9af7   Mauro Carvalho Chehab   edac: sb_edac: Ad...
3099
3100
3101
  static struct notifier_block sbridge_mce_dec = {
  	.notifier_call      = sbridge_mce_check_error,
  };
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
  /****************************************************************************
  			EDAC register/unregister logic
   ****************************************************************************/
  
  static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
  {
  	struct mem_ctl_info *mci = sbridge_dev->mci;
  	struct sbridge_pvt *pvt;
  
  	if (unlikely(!mci || !mci->pvt_info)) {
956b9ba15   Joe Perches   edac: Convert deb...
3112
3113
  		edac_dbg(0, "MC: dev = %p
  ", &sbridge_dev->pdev[0]->dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3114
3115
3116
3117
3118
3119
3120
  
  		sbridge_printk(KERN_ERR, "Couldn't find mci handler
  ");
  		return;
  	}
  
  	pvt = mci->pvt_info;
956b9ba15   Joe Perches   edac: Convert deb...
3121
3122
3123
  	edac_dbg(0, "MC: mci = %p, dev = %p
  ",
  		 mci, &sbridge_dev->pdev[0]->dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3124

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

956b9ba15   Joe Perches   edac: Convert deb...
3128
3129
  	edac_dbg(1, "%s: free mci struct
  ", mci->ctl_name);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3130
3131
3132
3133
  	kfree(mci->ctl_name);
  	edac_mc_free(mci);
  	sbridge_dev->mci = NULL;
  }
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3134
  static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3135
3136
  {
  	struct mem_ctl_info *mci;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3137
  	struct edac_mc_layer layers[2];
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3138
  	struct sbridge_pvt *pvt;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3139
  	struct pci_dev *pdev = sbridge_dev->pdev[0];
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3140
  	int rc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3141
3142
  
  	/* Check the number of active and not disabled channels */
dbc954ddd   Aristeu Rozanski   sb_edac: search d...
3143
  	rc = check_if_ecc_is_active(sbridge_dev->bus, type);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3144
3145
3146
3147
  	if (unlikely(rc < 0))
  		return rc;
  
  	/* allocate a new MC control structure */
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3148
  	layers[0].type = EDAC_MC_LAYER_CHANNEL;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3149
3150
  	layers[0].size = type == KNIGHTS_LANDING ?
  		KNL_MAX_CHANNELS : NUM_CHANNELS;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3151
3152
  	layers[0].is_virt_csrow = false;
  	layers[1].type = EDAC_MC_LAYER_SLOT;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3153
  	layers[1].size = type == KNIGHTS_LANDING ? 1 : MAX_DIMMS;
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3154
  	layers[1].is_virt_csrow = true;
ca0907b9e   Mauro Carvalho Chehab   edac: Remove the ...
3155
  	mci = edac_mc_alloc(sbridge_dev->mc, ARRAY_SIZE(layers), layers,
c36e3e776   Mauro Carvalho Chehab   sb_edac: convert ...
3156
  			    sizeof(*pvt));
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3157
3158
  	if (unlikely(!mci))
  		return -ENOMEM;
956b9ba15   Joe Perches   edac: Convert deb...
3159
3160
  	edac_dbg(0, "MC: mci = %p, dev = %p
  ",
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3161
  		 mci, &pdev->dev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3162
3163
3164
3165
3166
3167
3168
  
  	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...
3169
3170
  	mci->mtype_cap = type == KNIGHTS_LANDING ?
  		MEM_FLAG_DDR4 : MEM_FLAG_DDR3;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3171
3172
3173
3174
  	mci->edac_ctl_cap = EDAC_FLAG_NONE;
  	mci->edac_cap = EDAC_FLAG_NONE;
  	mci->mod_name = "sbridge_edac.c";
  	mci->mod_ver = SBRIDGE_REVISION;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3175
  	mci->dev_name = pci_name(pdev);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3176
  	mci->ctl_page_to_phys = NULL;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3177
  	pvt->info.type = type;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3178
3179
  	switch (type) {
  	case IVY_BRIDGE:
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3180
3181
3182
3183
  		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...
3184
  		pvt->info.get_memory_type = get_memory_type;
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
3185
  		pvt->info.get_node_id = get_node_id;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
3186
  		pvt->info.rir_limit = rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3187
3188
3189
3190
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
  		pvt->info.show_interleave_mode = show_interleave_mode;
  		pvt->info.dram_attr = dram_attr;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3191
3192
3193
3194
  		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
  		pvt->info.interleave_list = ibridge_interleave_list;
  		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3195
  		pvt->info.get_width = ibridge_get_width;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3196
3197
3198
3199
3200
3201
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx);
  
  		/* Store pci devices at mci for faster access */
  		rc = ibridge_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3202
3203
  		break;
  	case SANDY_BRIDGE:
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3204
3205
3206
3207
  		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...
3208
  		pvt->info.get_memory_type = get_memory_type;
f14d6892e   Aristeu Rozanski   sb_edac: make nod...
3209
  		pvt->info.get_node_id = get_node_id;
b976bcf24   Aristeu Rozanski   sb_edac: make RIR...
3210
  		pvt->info.rir_limit = rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3211
3212
3213
3214
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
  		pvt->info.show_interleave_mode = show_interleave_mode;
  		pvt->info.dram_attr = dram_attr;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3215
3216
3217
3218
  		pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
  		pvt->info.interleave_list = sbridge_interleave_list;
  		pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
  		pvt->info.interleave_pkg = sbridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3219
  		pvt->info.get_width = sbridge_get_width;
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3220
3221
3222
3223
3224
3225
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx);
  
  		/* Store pci devices at mci for faster access */
  		rc = sbridge_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3226
3227
3228
3229
3230
3231
3232
3233
3234
  		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;
  		pvt->info.rir_limit = haswell_rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3235
3236
3237
3238
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
  		pvt->info.show_interleave_mode = show_interleave_mode;
  		pvt->info.dram_attr = dram_attr;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3239
3240
3241
3242
  		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
  		pvt->info.interleave_list = ibridge_interleave_list;
  		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3243
  		pvt->info.get_width = ibridge_get_width;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3244
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx);
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3245

50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3246
3247
3248
3249
3250
  		/* Store pci devices at mci for faster access */
  		rc = haswell_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
  		break;
1f39581a9   Tony Luck   sb_edac: Add supp...
3251
3252
3253
3254
3255
3256
3257
3258
  	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;
  		pvt->info.rir_limit = haswell_rir_limit;
c59f9c06b   Jim Snow   EDAC, sb_edac: Vi...
3259
3260
3261
3262
  		pvt->info.sad_limit = sad_limit;
  		pvt->info.interleave_mode = interleave_mode;
  		pvt->info.show_interleave_mode = show_interleave_mode;
  		pvt->info.dram_attr = dram_attr;
1f39581a9   Tony Luck   sb_edac: Add supp...
3263
3264
3265
3266
  		pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
  		pvt->info.interleave_list = ibridge_interleave_list;
  		pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
12f0721c5   Aristeu Rozanski   sb_edac: correctl...
3267
  		pvt->info.get_width = broadwell_get_width;
1f39581a9   Tony Luck   sb_edac: Add supp...
3268
3269
3270
3271
3272
3273
3274
  		mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
  
  		/* Store pci devices at mci for faster access */
  		rc = broadwell_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
  		break;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
  	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;
  		pvt->info.rir_limit = NULL;
  		pvt->info.sad_limit = knl_sad_limit;
  		pvt->info.interleave_mode = knl_interleave_mode;
  		pvt->info.show_interleave_mode = knl_show_interleave_mode;
  		pvt->info.dram_attr = dram_attr_knl;
  		pvt->info.max_sad = ARRAY_SIZE(knl_dram_rule);
  		pvt->info.interleave_list = knl_interleave_list;
  		pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list);
  		pvt->info.interleave_pkg = ibridge_interleave_pkg;
45f4d3ab3   Hubert Chrzaniuk   EDAC, sb_edac: Se...
3291
  		pvt->info.get_width = knl_get_width;
d0cdf9003   Jim Snow   EDAC, sb_edac: Ad...
3292
3293
3294
3295
3296
3297
3298
  		mci->ctl_name = kasprintf(GFP_KERNEL,
  			"Knights Landing Socket#%d", mci->mc_idx);
  
  		rc = knl_mci_bind_devs(mci, sbridge_dev);
  		if (unlikely(rc < 0))
  			goto fail0;
  		break;
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3299
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3300
3301
3302
3303
3304
3305
  
  	/* Get dimm basic config and the memory layout */
  	get_dimm_config(mci);
  	get_memory_layout(mci);
  
  	/* record ptr to the generic device */
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3306
  	mci->pdev = &pdev->dev;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3307
3308
3309
  
  	/* 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...
3310
3311
  		edac_dbg(0, "MC: failed edac_mc_add_mc()
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3312
3313
3314
  		rc = -EINVAL;
  		goto fail0;
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3315
  	return 0;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3316
3317
3318
3319
3320
3321
3322
  
  fail0:
  	kfree(mci->ctl_name);
  	edac_mc_free(mci);
  	sbridge_dev->mci = NULL;
  	return rc;
  }
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3323
3324
  #define ICPU(model, table) \
  	{ X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table }
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3325
3326
3327
3328
3329
  static const struct x86_cpu_id sbridge_cpuids[] = {
  	ICPU(0x2d, pci_dev_descr_sbridge_table),	/* SANDY_BRIDGE */
  	ICPU(0x3e, pci_dev_descr_ibridge_table),	/* IVY_BRIDGE */
  	ICPU(0x3f, pci_dev_descr_haswell_table),	/* HASWELL */
  	ICPU(0x4f, pci_dev_descr_broadwell_table),	/* BROADWELL */
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
3330
  	ICPU(0x56, pci_dev_descr_broadwell_table),	/* BROADWELL-DE */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3331
3332
3333
3334
  	ICPU(0x57, pci_dev_descr_knl_table),		/* KNIGHTS_LANDING */
  	{ }
  };
  MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3335
  /*
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3336
   *	sbridge_probe	Get all devices and register memory controllers
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3337
3338
3339
3340
3341
   *			present.
   *	return:
   *		0 for FOUND a device
   *		< 0 for error code
   */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3342
  static int sbridge_probe(const struct x86_cpu_id *id)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3343
  {
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3344
  	int rc = -ENODEV;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3345
3346
  	u8 mc, num_mc = 0;
  	struct sbridge_dev *sbridge_dev;
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3347
  	struct pci_id_table *ptable = (struct pci_id_table *)id->driver_data;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3348
3349
  
  	/* get the pci devices we want to reserve for our use */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3350
  	rc = sbridge_get_all_devices(&num_mc, ptable);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3351

11249e739   Borislav Petkov   sb_edac: Fix dete...
3352
  	if (unlikely(rc < 0)) {
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3353
3354
  		edac_dbg(0, "couldn't get all devices
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3355
  		goto fail0;
11249e739   Borislav Petkov   sb_edac: Fix dete...
3356
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3357
3358
3359
  	mc = 0;
  
  	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
956b9ba15   Joe Perches   edac: Convert deb...
3360
3361
3362
  		edac_dbg(0, "Registering MC#%d (%d of %d)
  ",
  			 mc, mc + 1, num_mc);
50d1bb936   Aristeu Rozanski   sb_edac: add supp...
3363

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3364
  		sbridge_dev->mc = mc++;
665f05e0b   Tony Luck   EDAC, sb_edac: Re...
3365
  		rc = sbridge_register_mci(sbridge_dev, ptable->type);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3366
3367
3368
  		if (unlikely(rc < 0))
  			goto fail1;
  	}
11249e739   Borislav Petkov   sb_edac: Fix dete...
3369
3370
  	sbridge_printk(KERN_INFO, "%s
  ", SBRIDGE_REVISION);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3371

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3372
3373
3374
3375
3376
3377
3378
3379
  	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...
3380
3381
3382
3383
  	return rc;
  }
  
  /*
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3384
   *	sbridge_remove	cleanup
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3385
3386
   *
   */
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3387
  static void sbridge_remove(void)
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3388
3389
  {
  	struct sbridge_dev *sbridge_dev;
956b9ba15   Joe Perches   edac: Convert deb...
3390
3391
  	edac_dbg(0, "
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3392

eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3393
3394
3395
3396
3397
  	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...
3398
  }
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3399
3400
3401
3402
3403
3404
  /*
   *	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...
3405
3406
  	const struct x86_cpu_id *id;
  	int rc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3407

956b9ba15   Joe Perches   edac: Convert deb...
3408
3409
  	edac_dbg(2, "
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3410

2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3411
3412
3413
  	id = x86_match_cpu(sbridge_cpuids);
  	if (!id)
  		return -ENODEV;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3414
3415
  	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
  	opstate_init();
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3416
3417
3418
  	rc = sbridge_probe(id);
  
  	if (rc >= 0) {
e35fca479   Chen Gong   edac: avoid mce d...
3419
  		mce_register_decode_chain(&sbridge_mce_dec);
fd5210396   Chen, Gong   EDAC, sb_edac: Mo...
3420
3421
3422
  		if (get_edac_report_status() == EDAC_REPORTING_DISABLED)
  			sbridge_printk(KERN_WARNING, "Loading driver, error reporting disabled.
  ");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3423
  		return 0;
e35fca479   Chen Gong   edac: avoid mce d...
3424
  	}
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3425
3426
3427
  
  	sbridge_printk(KERN_ERR, "Failed to register device with error %d.
  ",
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3428
  		      rc);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3429

2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3430
  	return rc;
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3431
3432
3433
3434
3435
3436
3437
3438
  }
  
  /*
   *	sbridge_exit()	Module exit function
   *			Unregister the driver
   */
  static void __exit sbridge_exit(void)
  {
956b9ba15   Joe Perches   edac: Convert deb...
3439
3440
  	edac_dbg(2, "
  ");
2c1ea4c70   Tony Luck   EDAC, sb_edac: Us...
3441
  	sbridge_remove();
e35fca479   Chen Gong   edac: avoid mce d...
3442
  	mce_unregister_decode_chain(&sbridge_mce_dec);
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3443
3444
3445
3446
3447
3448
3449
3450
3451
  }
  
  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...
3452
  MODULE_AUTHOR("Mauro Carvalho Chehab");
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3453
  MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
4d715a805   Aristeu Rozanski   sb_edac: add supp...
3454
  MODULE_DESCRIPTION("MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers - "
eebf11a01   Mauro Carvalho Chehab   edac: Add an expe...
3455
  		   SBRIDGE_REVISION);