Blame view

drivers/edac/e752x_edac.c 39.7 KB
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Intel e752x Memory Controller kernel module
   * (C) 2004 Linux Networx (http://lnxi.com)
   * This file may be distributed under the terms of the
   * GNU General Public License.
   *
   * See "enum e752x_chips" below for supported chipsets
   *
   * Written by Tom Zimmerman
   *
   * Contributors:
   * 	Thayne Harbaugh at realmsys.com (?)
   * 	Wang Zhenyu at intel.com
   * 	Dave Jiang at mvista.com
   *
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
16
   * $Id: edac_e752x.c,v 1.5.2.11 2005/10/05 00:43:44 dsp_llnl Exp $
806c35f50   Alan Cox   [PATCH] EDAC: dri...
17
18
   *
   */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
19
20
  #include <linux/module.h>
  #include <linux/init.h>
806c35f50   Alan Cox   [PATCH] EDAC: dri...
21
22
  #include <linux/pci.h>
  #include <linux/pci_ids.h>
c0d121720   Dave Jiang   drivers/edac: add...
23
  #include <linux/edac.h>
20bcb7a81   Douglas Thompson   drivers/edac: mod...
24
  #include "edac_core.h"
806c35f50   Alan Cox   [PATCH] EDAC: dri...
25

152ba3942   Michal Marek   edac: Drop __DATE...
26
  #define E752X_REVISION	" Ver: 2.0.2"
929a40ec3   Doug Thompson   [PATCH] EDAC: fix...
27
  #define EDAC_MOD_STR	"e752x_edac"
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
28

10d33e9c3   Doug Thompson   edac: e752x fix t...
29
  static int report_non_memory_errors;
96941026a   mark gross   [PATCH] EDAC Coex...
30
  static int force_function_unhide;
94ee1cf5a   Peter Tyser   edac: add e752x p...
31
  static int sysbus_parity = -1;
96941026a   mark gross   [PATCH] EDAC Coex...
32

91b99041c   Dave Jiang   drivers/edac: upd...
33
  static struct edac_pci_ctl_info *e752x_pci;
537fba289   Dave Peterson   [PATCH] EDAC: pri...
34
  #define e752x_printk(level, fmt, arg...) \
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
35
  	edac_printk(level, "e752x", fmt, ##arg)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
36
37
  
  #define e752x_mc_printk(mci, level, fmt, arg...) \
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
38
  	edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
39

806c35f50   Alan Cox   [PATCH] EDAC: dri...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  #ifndef PCI_DEVICE_ID_INTEL_7520_0
  #define PCI_DEVICE_ID_INTEL_7520_0      0x3590
  #endif				/* PCI_DEVICE_ID_INTEL_7520_0      */
  
  #ifndef PCI_DEVICE_ID_INTEL_7520_1_ERR
  #define PCI_DEVICE_ID_INTEL_7520_1_ERR  0x3591
  #endif				/* PCI_DEVICE_ID_INTEL_7520_1_ERR  */
  
  #ifndef PCI_DEVICE_ID_INTEL_7525_0
  #define PCI_DEVICE_ID_INTEL_7525_0      0x359E
  #endif				/* PCI_DEVICE_ID_INTEL_7525_0      */
  
  #ifndef PCI_DEVICE_ID_INTEL_7525_1_ERR
  #define PCI_DEVICE_ID_INTEL_7525_1_ERR  0x3593
  #endif				/* PCI_DEVICE_ID_INTEL_7525_1_ERR  */
  
  #ifndef PCI_DEVICE_ID_INTEL_7320_0
  #define PCI_DEVICE_ID_INTEL_7320_0	0x3592
  #endif				/* PCI_DEVICE_ID_INTEL_7320_0 */
  
  #ifndef PCI_DEVICE_ID_INTEL_7320_1_ERR
  #define PCI_DEVICE_ID_INTEL_7320_1_ERR	0x3593
  #endif				/* PCI_DEVICE_ID_INTEL_7320_1_ERR */
5135b797c   Andrei Konovalov   edac: new support...
63
64
65
66
67
68
69
  #ifndef PCI_DEVICE_ID_INTEL_3100_0
  #define PCI_DEVICE_ID_INTEL_3100_0	0x35B0
  #endif				/* PCI_DEVICE_ID_INTEL_3100_0 */
  
  #ifndef PCI_DEVICE_ID_INTEL_3100_1_ERR
  #define PCI_DEVICE_ID_INTEL_3100_1_ERR	0x35B1
  #endif				/* PCI_DEVICE_ID_INTEL_3100_1_ERR */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
70
  #define E752X_NR_CSROWS		8	/* number of csrows */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
71
  /* E752X register addresses - device 0 function 0 */
8004fd2ad   Peter Tyser   edac: e752x: add ...
72
73
74
75
76
77
78
79
  #define E752X_MCHSCRB		0x52	/* Memory Scrub register (16b) */
  					/*
  					 * 6:5     Scrub Completion Count
  					 * 3:2     Scrub Rate (i3100 only)
  					 *      01=fast 10=normal
  					 * 1:0     Scrub Mode enable
  					 *      00=off 10=on
  					 */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  #define E752X_DRB		0x60	/* DRAM row boundary register (8b) */
  #define E752X_DRA		0x70	/* DRAM row attribute register (8b) */
  					/*
  					 * 31:30   Device width row 7
  					 *      01=x8 10=x4 11=x8 DDR2
  					 * 27:26   Device width row 6
  					 * 23:22   Device width row 5
  					 * 19:20   Device width row 4
  					 * 15:14   Device width row 3
  					 * 11:10   Device width row 2
  					 *  7:6    Device width row 1
  					 *  3:2    Device width row 0
  					 */
  #define E752X_DRC		0x7C	/* DRAM controller mode reg (32b) */
  					/* FIXME:IS THIS RIGHT? */
  					/*
  					 * 22    Number channels 0=1,1=2
  					 * 19:18 DRB Granularity 32/64MB
  					 */
  #define E752X_DRM		0x80	/* Dimm mapping register */
  #define E752X_DDRCSR		0x9A	/* DDR control and status reg (16b) */
  					/*
  					 * 14:12 1 single A, 2 single B, 3 dual
  					 */
  #define E752X_TOLM		0xC4	/* DRAM top of low memory reg (16b) */
  #define E752X_REMAPBASE		0xC6	/* DRAM remap base address reg (16b) */
  #define E752X_REMAPLIMIT	0xC8	/* DRAM remap limit address reg (16b) */
  #define E752X_REMAPOFFSET	0xCA	/* DRAM remap limit offset reg (16b) */
  
  /* E752X register addresses - device 0 function 1 */
  #define E752X_FERR_GLOBAL	0x40	/* Global first error register (32b) */
  #define E752X_NERR_GLOBAL	0x44	/* Global next error register (32b) */
  #define E752X_HI_FERR		0x50	/* Hub interface first error reg (8b) */
  #define E752X_HI_NERR		0x52	/* Hub interface next error reg (8b) */
  #define E752X_HI_ERRMASK	0x54	/* Hub interface error mask reg (8b) */
  #define E752X_HI_SMICMD		0x5A	/* Hub interface SMI command reg (8b) */
  #define E752X_SYSBUS_FERR	0x60	/* System buss first error reg (16b) */
  #define E752X_SYSBUS_NERR	0x62	/* System buss next error reg (16b) */
  #define E752X_SYSBUS_ERRMASK	0x64	/* System buss error mask reg (16b) */
  #define E752X_SYSBUS_SMICMD	0x6A	/* System buss SMI command reg (16b) */
  #define E752X_BUF_FERR		0x70	/* Memory buffer first error reg (8b) */
  #define E752X_BUF_NERR		0x72	/* Memory buffer next error reg (8b) */
  #define E752X_BUF_ERRMASK	0x74	/* Memory buffer error mask reg (8b) */
10d33e9c3   Doug Thompson   edac: e752x fix t...
123
  #define E752X_BUF_SMICMD	0x7A	/* Memory buffer SMI cmd reg (8b) */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
124
125
126
127
128
129
130
131
132
  #define E752X_DRAM_FERR		0x80	/* DRAM first error register (16b) */
  #define E752X_DRAM_NERR		0x82	/* DRAM next error register (16b) */
  #define E752X_DRAM_ERRMASK	0x84	/* DRAM error mask register (8b) */
  #define E752X_DRAM_SMICMD	0x8A	/* DRAM SMI command register (8b) */
  #define E752X_DRAM_RETR_ADD	0xAC	/* DRAM Retry address register (32b) */
  #define E752X_DRAM_SEC1_ADD	0xA0	/* DRAM first correctable memory */
  					/*     error address register (32b) */
  					/*
  					 * 31    Reserved
10d33e9c3   Doug Thompson   edac: e752x fix t...
133
  					 * 30:2  CE address (64 byte block 34:6
806c35f50   Alan Cox   [PATCH] EDAC: dri...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  					 * 1     Reserved
  					 * 0     HiLoCS
  					 */
  #define E752X_DRAM_SEC2_ADD	0xC8	/* DRAM first correctable memory */
  					/*     error address register (32b) */
  					/*
  					 * 31    Reserved
  					 * 30:2  CE address (64 byte block 34:6)
  					 * 1     Reserved
  					 * 0     HiLoCS
  					 */
  #define E752X_DRAM_DED_ADD	0xA4	/* DRAM first uncorrectable memory */
  					/*     error address register (32b) */
  					/*
  					 * 31    Reserved
  					 * 30:2  CE address (64 byte block 34:6)
  					 * 1     Reserved
  					 * 0     HiLoCS
  					 */
10d33e9c3   Doug Thompson   edac: e752x fix t...
153
  #define E752X_DRAM_SCRB_ADD	0xA8	/* DRAM 1st uncorrectable scrub mem */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
154
155
156
  					/*     error address register (32b) */
  					/*
  					 * 31    Reserved
10d33e9c3   Doug Thompson   edac: e752x fix t...
157
  					 * 30:2  CE address (64 byte block 34:6
806c35f50   Alan Cox   [PATCH] EDAC: dri...
158
159
160
161
162
163
164
165
  					 * 1     Reserved
  					 * 0     HiLoCS
  					 */
  #define E752X_DRAM_SEC1_SYNDROME 0xC4	/* DRAM first correctable memory */
  					/*     error syndrome register (16b) */
  #define E752X_DRAM_SEC2_SYNDROME 0xC6	/* DRAM second correctable memory */
  					/*     error syndrome register (16b) */
  #define E752X_DEVPRES1		0xF4	/* Device Present 1 register (8b) */
5135b797c   Andrei Konovalov   edac: new support...
166
167
168
169
170
  /* 3100 IMCH specific register addresses - device 0 function 1 */
  #define I3100_NSI_FERR		0x48	/* NSI first error reg (32b) */
  #define I3100_NSI_NERR		0x4C	/* NSI next error reg (32b) */
  #define I3100_NSI_SMICMD	0x54	/* NSI SMI command register (32b) */
  #define I3100_NSI_EMASK		0x90	/* NSI error mask register (32b) */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
171
172
173
174
175
176
177
178
  /* ICH5R register addresses - device 30 function 0 */
  #define ICH5R_PCI_STAT		0x06	/* PCI status register (16b) */
  #define ICH5R_PCI_2ND_STAT	0x1E	/* PCI status secondary reg (16b) */
  #define ICH5R_PCI_BRIDGE_CTL	0x3E	/* PCI bridge control register (16b) */
  
  enum e752x_chips {
  	E7520 = 0,
  	E7525 = 1,
5135b797c   Andrei Konovalov   edac: new support...
179
180
  	E7320 = 2,
  	I3100 = 3
806c35f50   Alan Cox   [PATCH] EDAC: dri...
181
  };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
182
183
184
185
186
187
188
189
190
191
192
193
  struct e752x_pvt {
  	struct pci_dev *bridge_ck;
  	struct pci_dev *dev_d0f0;
  	struct pci_dev *dev_d0f1;
  	u32 tolm;
  	u32 remapbase;
  	u32 remaplimit;
  	int mc_symmetric;
  	u8 map[8];
  	int map_type;
  	const struct e752x_dev_info *dev_info;
  };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
194
195
  struct e752x_dev_info {
  	u16 err_dev;
3847bccce   Dave Peterson   [PATCH] EDAC: e75...
196
  	u16 ctl_dev;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
197
198
199
200
201
202
  	const char *ctl_name;
  };
  
  struct e752x_error_info {
  	u32 ferr_global;
  	u32 nerr_global;
5135b797c   Andrei Konovalov   edac: new support...
203
204
205
206
  	u32 nsi_ferr;	/* 3100 only */
  	u32 nsi_nerr;	/* 3100 only */
  	u8 hi_ferr;	/* all but 3100 */
  	u8 hi_nerr;	/* all but 3100 */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  	u16 sysbus_ferr;
  	u16 sysbus_nerr;
  	u8 buf_ferr;
  	u8 buf_nerr;
  	u16 dram_ferr;
  	u16 dram_nerr;
  	u32 dram_sec1_add;
  	u32 dram_sec2_add;
  	u16 dram_sec1_syndrome;
  	u16 dram_sec2_syndrome;
  	u32 dram_ded_add;
  	u32 dram_scrb_add;
  	u32 dram_retr_add;
  };
  
  static const struct e752x_dev_info e752x_devs[] = {
  	[E7520] = {
052dfb45c   Douglas Thompson   drivers/edac: cle...
224
225
226
  		.err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
  		.ctl_dev = PCI_DEVICE_ID_INTEL_7520_0,
  		.ctl_name = "E7520"},
806c35f50   Alan Cox   [PATCH] EDAC: dri...
227
  	[E7525] = {
052dfb45c   Douglas Thompson   drivers/edac: cle...
228
229
230
  		.err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
  		.ctl_dev = PCI_DEVICE_ID_INTEL_7525_0,
  		.ctl_name = "E7525"},
806c35f50   Alan Cox   [PATCH] EDAC: dri...
231
  	[E7320] = {
052dfb45c   Douglas Thompson   drivers/edac: cle...
232
233
234
  		.err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
  		.ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
  		.ctl_name = "E7320"},
5135b797c   Andrei Konovalov   edac: new support...
235
236
237
238
  	[I3100] = {
  		.err_dev = PCI_DEVICE_ID_INTEL_3100_1_ERR,
  		.ctl_dev = PCI_DEVICE_ID_INTEL_3100_0,
  		.ctl_name = "3100"},
806c35f50   Alan Cox   [PATCH] EDAC: dri...
239
  };
8004fd2ad   Peter Tyser   edac: e752x: add ...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  /* Valid scrub rates for the e752x/3100 hardware memory scrubber. We
   * map the scrubbing bandwidth to a hardware register value. The 'set'
   * operation finds the 'matching or higher value'.  Note that scrubbing
   * on the e752x can only be enabled/disabled.  The 3100 supports
   * a normal and fast mode.
   */
  
  #define SDRATE_EOT 0xFFFFFFFF
  
  struct scrubrate {
  	u32 bandwidth;	/* bandwidth consumed by scrubbing in bytes/sec */
  	u16 scrubval;	/* register value for scrub rate */
  };
  
  /* Rate below assumes same performance as i3100 using PC3200 DDR2 in
   * normal mode.  e752x bridges don't support choosing normal or fast mode,
   * so the scrubbing bandwidth value isn't all that important - scrubbing is
   * either on or off.
   */
  static const struct scrubrate scrubrates_e752x[] = {
  	{0,		0x00},	/* Scrubbing Off */
  	{500000,	0x02},	/* Scrubbing On */
  	{SDRATE_EOT,	0x00}	/* End of Table */
  };
  
  /* Fast mode: 2 GByte PC3200 DDR2 scrubbed in 33s = 63161283 bytes/s
   * Normal mode: 125 (32000 / 256) times slower than fast mode.
   */
  static const struct scrubrate scrubrates_i3100[] = {
  	{0,		0x00},	/* Scrubbing Off */
  	{500000,	0x0a},	/* Normal mode - 32k clocks */
  	{62500000,	0x06},	/* Fast mode - 256 clocks */
  	{SDRATE_EOT,	0x00}	/* End of Table */
  };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
274
  static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
275
  				unsigned long page)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
276
277
  {
  	u32 remap;
203333cbb   Dave Jiang   drivers/edac: Lin...
278
  	struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
279

537fba289   Dave Peterson   [PATCH] EDAC: pri...
280
281
  	debugf3("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
282
283
284
  
  	if (page < pvt->tolm)
  		return page;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
285

806c35f50   Alan Cox   [PATCH] EDAC: dri...
286
287
  	if ((page >= 0x100000) && (page < pvt->remapbase))
  		return page;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
288

806c35f50   Alan Cox   [PATCH] EDAC: dri...
289
  	remap = (page - pvt->tolm) + pvt->remapbase;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
290

806c35f50   Alan Cox   [PATCH] EDAC: dri...
291
292
  	if (remap < pvt->remaplimit)
  		return remap;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
293

537fba289   Dave Peterson   [PATCH] EDAC: pri...
294
295
  	e752x_printk(KERN_ERR, "Invalid page %lx - out of range
  ", page);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
296
297
298
299
  	return pvt->tolm - 1;
  }
  
  static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
052dfb45c   Douglas Thompson   drivers/edac: cle...
300
  			u32 sec1_add, u16 sec1_syndrome)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
301
302
303
304
305
  {
  	u32 page;
  	int row;
  	int channel;
  	int i;
203333cbb   Dave Jiang   drivers/edac: Lin...
306
  	struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
307

537fba289   Dave Peterson   [PATCH] EDAC: pri...
308
309
  	debugf3("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
310
311
312
313
314
315
316
317
  
  	/* convert the addr to 4k page */
  	page = sec1_add >> (PAGE_SHIFT - 4);
  
  	/* FIXME - check for -1 */
  	if (pvt->mc_symmetric) {
  		/* chip select are bits 14 & 13 */
  		row = ((page >> 1) & 3);
537fba289   Dave Peterson   [PATCH] EDAC: pri...
318
  		e752x_printk(KERN_WARNING,
052dfb45c   Douglas Thompson   drivers/edac: cle...
319
320
321
322
323
  			"Test row %d Table %d %d %d %d %d %d %d %d
  ", row,
  			pvt->map[0], pvt->map[1], pvt->map[2], pvt->map[3],
  			pvt->map[4], pvt->map[5], pvt->map[6],
  			pvt->map[7]);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
324
325
326
327
328
329
  
  		/* test for channel remapping */
  		for (i = 0; i < 8; i++) {
  			if (pvt->map[i] == row)
  				break;
  		}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
330

537fba289   Dave Peterson   [PATCH] EDAC: pri...
331
332
  		e752x_printk(KERN_WARNING, "Test computed row %d
  ", i);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
333

806c35f50   Alan Cox   [PATCH] EDAC: dri...
334
335
336
  		if (i < 8)
  			row = i;
  		else
537fba289   Dave Peterson   [PATCH] EDAC: pri...
337
  			e752x_mc_printk(mci, KERN_WARNING,
203333cbb   Dave Jiang   drivers/edac: Lin...
338
339
340
  					"row %d not found in remap table
  ",
  					row);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
341
342
  	} else
  		row = edac_mc_find_csrow_by_page(mci, page);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
343

806c35f50   Alan Cox   [PATCH] EDAC: dri...
344
345
  	/* 0 = channel A, 1 = channel B */
  	channel = !(error_one & 1);
84db003f2   Mike Chan   [PATCH] EDAC: Fix...
346
347
  	/* e752x mc reads 34:6 of the DRAM linear address */
  	edac_mc_handle_ce(mci, page, offset_in_page(sec1_add << 4),
052dfb45c   Douglas Thompson   drivers/edac: cle...
348
  			sec1_syndrome, row, channel, "e752x CE");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
349
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
350
  static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
052dfb45c   Douglas Thompson   drivers/edac: cle...
351
352
  			u32 sec1_add, u16 sec1_syndrome, int *error_found,
  			int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
353
354
355
356
357
358
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
  }
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
359
  static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
052dfb45c   Douglas Thompson   drivers/edac: cle...
360
  			u32 ded_add, u32 scrb_add)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
361
362
363
  {
  	u32 error_2b, block_page;
  	int row;
203333cbb   Dave Jiang   drivers/edac: Lin...
364
  	struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
365

537fba289   Dave Peterson   [PATCH] EDAC: pri...
366
367
  	debugf3("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
368
369
370
  
  	if (error_one & 0x0202) {
  		error_2b = ded_add;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
371

806c35f50   Alan Cox   [PATCH] EDAC: dri...
372
373
  		/* convert to 4k address */
  		block_page = error_2b >> (PAGE_SHIFT - 4);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
374

806c35f50   Alan Cox   [PATCH] EDAC: dri...
375
  		row = pvt->mc_symmetric ?
052dfb45c   Douglas Thompson   drivers/edac: cle...
376
377
378
  		/* chip select are bits 14 & 13 */
  			((block_page >> 1) & 3) :
  			edac_mc_find_csrow_by_page(mci, block_page);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
379

84db003f2   Mike Chan   [PATCH] EDAC: Fix...
380
381
  		/* e752x mc reads 34:6 of the DRAM linear address */
  		edac_mc_handle_ue(mci, block_page,
052dfb45c   Douglas Thompson   drivers/edac: cle...
382
383
  				offset_in_page(error_2b << 4),
  				row, "e752x UE from Read");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
384
385
386
  	}
  	if (error_one & 0x0404) {
  		error_2b = scrb_add;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
387

806c35f50   Alan Cox   [PATCH] EDAC: dri...
388
389
  		/* convert to 4k address */
  		block_page = error_2b >> (PAGE_SHIFT - 4);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
390

806c35f50   Alan Cox   [PATCH] EDAC: dri...
391
  		row = pvt->mc_symmetric ?
052dfb45c   Douglas Thompson   drivers/edac: cle...
392
393
394
  		/* chip select are bits 14 & 13 */
  			((block_page >> 1) & 3) :
  			edac_mc_find_csrow_by_page(mci, block_page);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
395

84db003f2   Mike Chan   [PATCH] EDAC: Fix...
396
397
  		/* e752x mc reads 34:6 of the DRAM linear address */
  		edac_mc_handle_ue(mci, block_page,
052dfb45c   Douglas Thompson   drivers/edac: cle...
398
399
  				offset_in_page(error_2b << 4),
  				row, "e752x UE from Scruber");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
400
401
402
403
  	}
  }
  
  static inline void process_ue(struct mem_ctl_info *mci, u16 error_one,
052dfb45c   Douglas Thompson   drivers/edac: cle...
404
405
  			u32 ded_add, u32 scrb_add, int *error_found,
  			int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
406
407
408
409
410
411
412
413
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_process_ue(mci, error_one, ded_add, scrb_add);
  }
  
  static inline void process_ue_no_info_wr(struct mem_ctl_info *mci,
203333cbb   Dave Jiang   drivers/edac: Lin...
414
  					 int *error_found, int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
415
416
417
418
419
  {
  	*error_found = 1;
  
  	if (!handle_error)
  		return;
537fba289   Dave Peterson   [PATCH] EDAC: pri...
420
421
  	debugf3("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
422
423
424
425
  	edac_mc_handle_ue_no_info(mci, "e752x UE log memory write");
  }
  
  static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
203333cbb   Dave Jiang   drivers/edac: Lin...
426
  				 u32 retry_add)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
427
428
429
  {
  	u32 error_1b, page;
  	int row;
203333cbb   Dave Jiang   drivers/edac: Lin...
430
  	struct e752x_pvt *pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
431
432
  
  	error_1b = retry_add;
10d33e9c3   Doug Thompson   edac: e752x fix t...
433
434
435
436
  	page = error_1b >> (PAGE_SHIFT - 4);  /* convert the addr to 4k page */
  
  	/* chip select are bits 14 & 13 */
  	row = pvt->mc_symmetric ? ((page >> 1) & 3) :
052dfb45c   Douglas Thompson   drivers/edac: cle...
437
  		edac_mc_find_csrow_by_page(mci, page);
10d33e9c3   Doug Thompson   edac: e752x fix t...
438

537fba289   Dave Peterson   [PATCH] EDAC: pri...
439
  	e752x_mc_printk(mci, KERN_WARNING,
203333cbb   Dave Jiang   drivers/edac: Lin...
440
441
442
  			"CE page 0x%lx, row %d : Memory read retry
  ",
  			(long unsigned int)page, row);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
443
444
445
  }
  
  static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
052dfb45c   Douglas Thompson   drivers/edac: cle...
446
447
  				u32 retry_add, int *error_found,
  				int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
448
449
450
451
452
453
454
455
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_process_ded_retry(mci, error, retry_add);
  }
  
  static inline void process_threshold_ce(struct mem_ctl_info *mci, u16 error,
203333cbb   Dave Jiang   drivers/edac: Lin...
456
  					int *error_found, int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
457
458
459
460
  {
  	*error_found = 1;
  
  	if (handle_error)
537fba289   Dave Peterson   [PATCH] EDAC: pri...
461
462
  		e752x_mc_printk(mci, KERN_WARNING, "Memory threshold CE
  ");
806c35f50   Alan Cox   [PATCH] EDAC: dri...
463
  }
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
464
  static char *global_message[11] = {
10d33e9c3   Doug Thompson   edac: e752x fix t...
465
466
467
468
469
470
471
472
473
474
475
  	"PCI Express C1",
  	"PCI Express C",
  	"PCI Express B1",
  	"PCI Express B",
  	"PCI Express A1",
  	"PCI Express A",
  	"DMA Controller",
  	"HUB or NS Interface",
  	"System Bus",
  	"DRAM Controller",  /* 9th entry */
  	"Internal Buffer"
806c35f50   Alan Cox   [PATCH] EDAC: dri...
476
  };
10d33e9c3   Doug Thompson   edac: e752x fix t...
477
  #define DRAM_ENTRY	9
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
478
  static char *fatal_message[2] = { "Non-Fatal ", "Fatal " };
806c35f50   Alan Cox   [PATCH] EDAC: dri...
479
480
481
482
483
484
  
  static void do_global_error(int fatal, u32 errors)
  {
  	int i;
  
  	for (i = 0; i < 11; i++) {
10d33e9c3   Doug Thompson   edac: e752x fix t...
485
486
487
488
489
490
491
492
493
494
495
  		if (errors & (1 << i)) {
  			/* If the error is from DRAM Controller OR
  			 * we are to report ALL errors, then
  			 * report the error
  			 */
  			if ((i == DRAM_ENTRY) || report_non_memory_errors)
  				e752x_printk(KERN_WARNING, "%sError %s
  ",
  					fatal_message[fatal],
  					global_message[i]);
  		}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
496
497
498
499
  	}
  }
  
  static inline void global_error(int fatal, u32 errors, int *error_found,
203333cbb   Dave Jiang   drivers/edac: Lin...
500
  				int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
501
502
503
504
505
506
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_global_error(fatal, errors);
  }
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
507
  static char *hub_message[7] = {
806c35f50   Alan Cox   [PATCH] EDAC: dri...
508
509
510
511
512
513
514
515
516
517
518
519
  	"HI Address or Command Parity", "HI Illegal Access",
  	"HI Internal Parity", "Out of Range Access",
  	"HI Data Parity", "Enhanced Config Access",
  	"Hub Interface Target Abort"
  };
  
  static void do_hub_error(int fatal, u8 errors)
  {
  	int i;
  
  	for (i = 0; i < 7; i++) {
  		if (errors & (1 << i))
537fba289   Dave Peterson   [PATCH] EDAC: pri...
520
521
  			e752x_printk(KERN_WARNING, "%sError %s
  ",
052dfb45c   Douglas Thompson   drivers/edac: cle...
522
  				fatal_message[fatal], hub_message[i]);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
523
524
525
526
  	}
  }
  
  static inline void hub_error(int fatal, u8 errors, int *error_found,
052dfb45c   Douglas Thompson   drivers/edac: cle...
527
  			int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
528
529
530
531
532
533
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_hub_error(fatal, errors);
  }
5135b797c   Andrei Konovalov   edac: new support...
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
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
  #define NSI_FATAL_MASK		0x0c080081
  #define NSI_NON_FATAL_MASK	0x23a0ba64
  #define NSI_ERR_MASK		(NSI_FATAL_MASK | NSI_NON_FATAL_MASK)
  
  static char *nsi_message[30] = {
  	"NSI Link Down",	/* NSI_FERR/NSI_NERR bit 0, fatal error */
  	"",						/* reserved */
  	"NSI Parity Error",				/* bit 2, non-fatal */
  	"",						/* reserved */
  	"",						/* reserved */
  	"Correctable Error Message",			/* bit 5, non-fatal */
  	"Non-Fatal Error Message",			/* bit 6, non-fatal */
  	"Fatal Error Message",				/* bit 7, fatal */
  	"",						/* reserved */
  	"Receiver Error",				/* bit 9, non-fatal */
  	"",						/* reserved */
  	"Bad TLP",					/* bit 11, non-fatal */
  	"Bad DLLP",					/* bit 12, non-fatal */
  	"REPLAY_NUM Rollover",				/* bit 13, non-fatal */
  	"",						/* reserved */
  	"Replay Timer Timeout",				/* bit 15, non-fatal */
  	"",						/* reserved */
  	"",						/* reserved */
  	"",						/* reserved */
  	"Data Link Protocol Error",			/* bit 19, fatal */
  	"",						/* reserved */
  	"Poisoned TLP",					/* bit 21, non-fatal */
  	"",						/* reserved */
  	"Completion Timeout",				/* bit 23, non-fatal */
  	"Completer Abort",				/* bit 24, non-fatal */
  	"Unexpected Completion",			/* bit 25, non-fatal */
  	"Receiver Overflow",				/* bit 26, fatal */
  	"Malformed TLP",				/* bit 27, fatal */
  	"",						/* reserved */
  	"Unsupported Request"				/* bit 29, non-fatal */
  };
  
  static void do_nsi_error(int fatal, u32 errors)
  {
  	int i;
  
  	for (i = 0; i < 30; i++) {
  		if (errors & (1 << i))
  			printk(KERN_WARNING "%sError %s
  ",
  			       fatal_message[fatal], nsi_message[i]);
  	}
  }
  
  static inline void nsi_error(int fatal, u32 errors, int *error_found,
  		int handle_error)
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_nsi_error(fatal, errors);
  }
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
591
  static char *membuf_message[4] = {
806c35f50   Alan Cox   [PATCH] EDAC: dri...
592
593
594
595
596
597
598
599
600
601
602
603
  	"Internal PMWB to DRAM parity",
  	"Internal PMWB to System Bus Parity",
  	"Internal System Bus or IO to PMWB Parity",
  	"Internal DRAM to PMWB Parity"
  };
  
  static void do_membuf_error(u8 errors)
  {
  	int i;
  
  	for (i = 0; i < 4; i++) {
  		if (errors & (1 << i))
537fba289   Dave Peterson   [PATCH] EDAC: pri...
604
605
  			e752x_printk(KERN_WARNING, "Non-Fatal Error %s
  ",
052dfb45c   Douglas Thompson   drivers/edac: cle...
606
  				membuf_message[i]);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
607
608
609
610
611
612
613
614
615
616
  	}
  }
  
  static inline void membuf_error(u8 errors, int *error_found, int handle_error)
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_membuf_error(errors);
  }
e009356f7   Dave Peterson   [PATCH] EDAC: use...
617
  static char *sysbus_message[10] = {
806c35f50   Alan Cox   [PATCH] EDAC: dri...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
  	"Addr or Request Parity",
  	"Data Strobe Glitch",
  	"Addr Strobe Glitch",
  	"Data Parity",
  	"Addr Above TOM",
  	"Non DRAM Lock Error",
  	"MCERR", "BINIT",
  	"Memory Parity",
  	"IO Subsystem Parity"
  };
  
  static void do_sysbus_error(int fatal, u32 errors)
  {
  	int i;
  
  	for (i = 0; i < 10; i++) {
  		if (errors & (1 << i))
537fba289   Dave Peterson   [PATCH] EDAC: pri...
635
636
  			e752x_printk(KERN_WARNING, "%sError System Bus %s
  ",
052dfb45c   Douglas Thompson   drivers/edac: cle...
637
  				fatal_message[fatal], sysbus_message[i]);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
638
639
640
641
  	}
  }
  
  static inline void sysbus_error(int fatal, u32 errors, int *error_found,
203333cbb   Dave Jiang   drivers/edac: Lin...
642
  				int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
643
644
645
646
647
648
  {
  	*error_found = 1;
  
  	if (handle_error)
  		do_sysbus_error(fatal, errors);
  }
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
649
  static void e752x_check_hub_interface(struct e752x_error_info *info,
052dfb45c   Douglas Thompson   drivers/edac: cle...
650
  				int *error_found, int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
651
652
653
654
  {
  	u8 stat8;
  
  	//pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
655

806c35f50   Alan Cox   [PATCH] EDAC: dri...
656
  	stat8 = info->hi_ferr;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
657

203333cbb   Dave Jiang   drivers/edac: Lin...
658
  	if (stat8 & 0x7f) {	/* Error, so process */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
659
  		stat8 &= 0x7f;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
660

203333cbb   Dave Jiang   drivers/edac: Lin...
661
  		if (stat8 & 0x2b)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
662
  			hub_error(1, stat8 & 0x2b, error_found, handle_error);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
663

203333cbb   Dave Jiang   drivers/edac: Lin...
664
  		if (stat8 & 0x54)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
665
666
667
  			hub_error(0, stat8 & 0x54, error_found, handle_error);
  	}
  	//pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
668

806c35f50   Alan Cox   [PATCH] EDAC: dri...
669
  	stat8 = info->hi_nerr;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
670

203333cbb   Dave Jiang   drivers/edac: Lin...
671
  	if (stat8 & 0x7f) {	/* Error, so process */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
672
  		stat8 &= 0x7f;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
673

806c35f50   Alan Cox   [PATCH] EDAC: dri...
674
675
  		if (stat8 & 0x2b)
  			hub_error(1, stat8 & 0x2b, error_found, handle_error);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
676

203333cbb   Dave Jiang   drivers/edac: Lin...
677
  		if (stat8 & 0x54)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
678
679
680
  			hub_error(0, stat8 & 0x54, error_found, handle_error);
  	}
  }
5135b797c   Andrei Konovalov   edac: new support...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
  static void e752x_check_ns_interface(struct e752x_error_info *info,
  				int *error_found, int handle_error)
  {
  	u32 stat32;
  
  	stat32 = info->nsi_ferr;
  	if (stat32 & NSI_ERR_MASK) { /* Error, so process */
  		if (stat32 & NSI_FATAL_MASK)	/* check for fatal errors */
  			nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
  				  handle_error);
  		if (stat32 & NSI_NON_FATAL_MASK) /* check for non-fatal ones */
  			nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
  				  handle_error);
  	}
  	stat32 = info->nsi_nerr;
  	if (stat32 & NSI_ERR_MASK) {
  		if (stat32 & NSI_FATAL_MASK)
  			nsi_error(1, stat32 & NSI_FATAL_MASK, error_found,
  				  handle_error);
  		if (stat32 & NSI_NON_FATAL_MASK)
  			nsi_error(0, stat32 & NSI_NON_FATAL_MASK, error_found,
  				  handle_error);
  	}
  }
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
705
  static void e752x_check_sysbus(struct e752x_error_info *info,
052dfb45c   Douglas Thompson   drivers/edac: cle...
706
  			int *error_found, int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
707
708
709
710
711
712
713
  {
  	u32 stat32, error32;
  
  	//pci_read_config_dword(dev,E752X_SYSBUS_FERR,&stat32);
  	stat32 = info->sysbus_ferr + (info->sysbus_nerr << 16);
  
  	if (stat32 == 0)
203333cbb   Dave Jiang   drivers/edac: Lin...
714
  		return;		/* no errors */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
715
716
717
  
  	error32 = (stat32 >> 16) & 0x3ff;
  	stat32 = stat32 & 0x3ff;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
718

203333cbb   Dave Jiang   drivers/edac: Lin...
719
  	if (stat32 & 0x087)
dfb2a7637   Brian Pomerantz   [PATCH] EDAC: e75...
720
  		sysbus_error(1, stat32 & 0x087, error_found, handle_error);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
721

203333cbb   Dave Jiang   drivers/edac: Lin...
722
  	if (stat32 & 0x378)
dfb2a7637   Brian Pomerantz   [PATCH] EDAC: e75...
723
  		sysbus_error(0, stat32 & 0x378, error_found, handle_error);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
724

203333cbb   Dave Jiang   drivers/edac: Lin...
725
  	if (error32 & 0x087)
dfb2a7637   Brian Pomerantz   [PATCH] EDAC: e75...
726
  		sysbus_error(1, error32 & 0x087, error_found, handle_error);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
727

203333cbb   Dave Jiang   drivers/edac: Lin...
728
  	if (error32 & 0x378)
dfb2a7637   Brian Pomerantz   [PATCH] EDAC: e75...
729
  		sysbus_error(0, error32 & 0x378, error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
730
  }
203333cbb   Dave Jiang   drivers/edac: Lin...
731
  static void e752x_check_membuf(struct e752x_error_info *info,
052dfb45c   Douglas Thompson   drivers/edac: cle...
732
  			int *error_found, int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
733
734
735
736
  {
  	u8 stat8;
  
  	stat8 = info->buf_ferr;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
737

203333cbb   Dave Jiang   drivers/edac: Lin...
738
  	if (stat8 & 0x0f) {	/* Error, so process */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
739
740
741
  		stat8 &= 0x0f;
  		membuf_error(stat8, error_found, handle_error);
  	}
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
742

806c35f50   Alan Cox   [PATCH] EDAC: dri...
743
  	stat8 = info->buf_nerr;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
744

203333cbb   Dave Jiang   drivers/edac: Lin...
745
  	if (stat8 & 0x0f) {	/* Error, so process */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
746
747
748
749
  		stat8 &= 0x0f;
  		membuf_error(stat8, error_found, handle_error);
  	}
  }
203333cbb   Dave Jiang   drivers/edac: Lin...
750
  static void e752x_check_dram(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
751
752
  			struct e752x_error_info *info, int *error_found,
  			int handle_error)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
753
754
755
756
757
758
759
  {
  	u16 error_one, error_next;
  
  	error_one = info->dram_ferr;
  	error_next = info->dram_nerr;
  
  	/* decode and report errors */
203333cbb   Dave Jiang   drivers/edac: Lin...
760
  	if (error_one & 0x0101)	/* check first error correctable */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
761
  		process_ce(mci, error_one, info->dram_sec1_add,
052dfb45c   Douglas Thompson   drivers/edac: cle...
762
  			info->dram_sec1_syndrome, error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
763

203333cbb   Dave Jiang   drivers/edac: Lin...
764
  	if (error_next & 0x0101)	/* check next error correctable */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
765
  		process_ce(mci, error_next, info->dram_sec2_add,
052dfb45c   Douglas Thompson   drivers/edac: cle...
766
  			info->dram_sec2_syndrome, error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
767

203333cbb   Dave Jiang   drivers/edac: Lin...
768
  	if (error_one & 0x4040)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
769
  		process_ue_no_info_wr(mci, error_found, handle_error);
203333cbb   Dave Jiang   drivers/edac: Lin...
770
  	if (error_next & 0x4040)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
771
  		process_ue_no_info_wr(mci, error_found, handle_error);
203333cbb   Dave Jiang   drivers/edac: Lin...
772
  	if (error_one & 0x2020)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
773
  		process_ded_retry(mci, error_one, info->dram_retr_add,
052dfb45c   Douglas Thompson   drivers/edac: cle...
774
  				error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
775

203333cbb   Dave Jiang   drivers/edac: Lin...
776
  	if (error_next & 0x2020)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
777
  		process_ded_retry(mci, error_next, info->dram_retr_add,
052dfb45c   Douglas Thompson   drivers/edac: cle...
778
  				error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
779

203333cbb   Dave Jiang   drivers/edac: Lin...
780
781
  	if (error_one & 0x0808)
  		process_threshold_ce(mci, error_one, error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
782

203333cbb   Dave Jiang   drivers/edac: Lin...
783
  	if (error_next & 0x0808)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
784
  		process_threshold_ce(mci, error_next, error_found,
052dfb45c   Douglas Thompson   drivers/edac: cle...
785
  				handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
786

203333cbb   Dave Jiang   drivers/edac: Lin...
787
  	if (error_one & 0x0606)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
788
  		process_ue(mci, error_one, info->dram_ded_add,
052dfb45c   Douglas Thompson   drivers/edac: cle...
789
  			info->dram_scrb_add, error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
790

203333cbb   Dave Jiang   drivers/edac: Lin...
791
  	if (error_next & 0x0606)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
792
  		process_ue(mci, error_next, info->dram_ded_add,
052dfb45c   Douglas Thompson   drivers/edac: cle...
793
  			info->dram_scrb_add, error_found, handle_error);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
794
  }
203333cbb   Dave Jiang   drivers/edac: Lin...
795
796
  static void e752x_get_error_info(struct mem_ctl_info *mci,
  				 struct e752x_error_info *info)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
797
798
799
800
801
  {
  	struct pci_dev *dev;
  	struct e752x_pvt *pvt;
  
  	memset(info, 0, sizeof(*info));
203333cbb   Dave Jiang   drivers/edac: Lin...
802
  	pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
803
  	dev = pvt->dev_d0f1;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
804
805
806
  	pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
  
  	if (info->ferr_global) {
5135b797c   Andrei Konovalov   edac: new support...
807
808
809
810
811
812
813
814
815
  		if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
  			pci_read_config_dword(dev, I3100_NSI_FERR,
  					     &info->nsi_ferr);
  			info->hi_ferr = 0;
  		} else {
  			pci_read_config_byte(dev, E752X_HI_FERR,
  					     &info->hi_ferr);
  			info->nsi_ferr = 0;
  		}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
816
  		pci_read_config_word(dev, E752X_SYSBUS_FERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
817
  				&info->sysbus_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
818
  		pci_read_config_byte(dev, E752X_BUF_FERR, &info->buf_ferr);
203333cbb   Dave Jiang   drivers/edac: Lin...
819
  		pci_read_config_word(dev, E752X_DRAM_FERR, &info->dram_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
820
  		pci_read_config_dword(dev, E752X_DRAM_SEC1_ADD,
052dfb45c   Douglas Thompson   drivers/edac: cle...
821
  				&info->dram_sec1_add);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
822
  		pci_read_config_word(dev, E752X_DRAM_SEC1_SYNDROME,
052dfb45c   Douglas Thompson   drivers/edac: cle...
823
  				&info->dram_sec1_syndrome);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
824
  		pci_read_config_dword(dev, E752X_DRAM_DED_ADD,
052dfb45c   Douglas Thompson   drivers/edac: cle...
825
  				&info->dram_ded_add);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
826
  		pci_read_config_dword(dev, E752X_DRAM_SCRB_ADD,
052dfb45c   Douglas Thompson   drivers/edac: cle...
827
  				&info->dram_scrb_add);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
828
  		pci_read_config_dword(dev, E752X_DRAM_RETR_ADD,
052dfb45c   Douglas Thompson   drivers/edac: cle...
829
  				&info->dram_retr_add);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
830

5135b797c   Andrei Konovalov   edac: new support...
831
  		/* ignore the reserved bits just in case */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
832
833
  		if (info->hi_ferr & 0x7f)
  			pci_write_config_byte(dev, E752X_HI_FERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
834
  					info->hi_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
835

5135b797c   Andrei Konovalov   edac: new support...
836
837
838
  		if (info->nsi_ferr & NSI_ERR_MASK)
  			pci_write_config_dword(dev, I3100_NSI_FERR,
  					info->nsi_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
839
840
  		if (info->sysbus_ferr)
  			pci_write_config_word(dev, E752X_SYSBUS_FERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
841
  					info->sysbus_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
842
843
844
  
  		if (info->buf_ferr & 0x0f)
  			pci_write_config_byte(dev, E752X_BUF_FERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
845
  					info->buf_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
846
847
848
  
  		if (info->dram_ferr)
  			pci_write_bits16(pvt->bridge_ck, E752X_DRAM_FERR,
203333cbb   Dave Jiang   drivers/edac: Lin...
849
  					 info->dram_ferr, info->dram_ferr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
850
851
  
  		pci_write_config_dword(dev, E752X_FERR_GLOBAL,
052dfb45c   Douglas Thompson   drivers/edac: cle...
852
  				info->ferr_global);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
853
854
855
856
857
  	}
  
  	pci_read_config_dword(dev, E752X_NERR_GLOBAL, &info->nerr_global);
  
  	if (info->nerr_global) {
5135b797c   Andrei Konovalov   edac: new support...
858
859
860
861
862
863
864
865
866
  		if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
  			pci_read_config_dword(dev, I3100_NSI_NERR,
  					     &info->nsi_nerr);
  			info->hi_nerr = 0;
  		} else {
  			pci_read_config_byte(dev, E752X_HI_NERR,
  					     &info->hi_nerr);
  			info->nsi_nerr = 0;
  		}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
867
  		pci_read_config_word(dev, E752X_SYSBUS_NERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
868
  				&info->sysbus_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
869
  		pci_read_config_byte(dev, E752X_BUF_NERR, &info->buf_nerr);
203333cbb   Dave Jiang   drivers/edac: Lin...
870
  		pci_read_config_word(dev, E752X_DRAM_NERR, &info->dram_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
871
  		pci_read_config_dword(dev, E752X_DRAM_SEC2_ADD,
052dfb45c   Douglas Thompson   drivers/edac: cle...
872
  				&info->dram_sec2_add);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
873
  		pci_read_config_word(dev, E752X_DRAM_SEC2_SYNDROME,
052dfb45c   Douglas Thompson   drivers/edac: cle...
874
  				&info->dram_sec2_syndrome);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
875
876
877
  
  		if (info->hi_nerr & 0x7f)
  			pci_write_config_byte(dev, E752X_HI_NERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
878
  					info->hi_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
879

5135b797c   Andrei Konovalov   edac: new support...
880
881
882
  		if (info->nsi_nerr & NSI_ERR_MASK)
  			pci_write_config_dword(dev, I3100_NSI_NERR,
  					info->nsi_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
883
884
  		if (info->sysbus_nerr)
  			pci_write_config_word(dev, E752X_SYSBUS_NERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
885
  					info->sysbus_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
886
887
888
  
  		if (info->buf_nerr & 0x0f)
  			pci_write_config_byte(dev, E752X_BUF_NERR,
052dfb45c   Douglas Thompson   drivers/edac: cle...
889
  					info->buf_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
890
891
892
  
  		if (info->dram_nerr)
  			pci_write_bits16(pvt->bridge_ck, E752X_DRAM_NERR,
203333cbb   Dave Jiang   drivers/edac: Lin...
893
  					 info->dram_nerr, info->dram_nerr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
894
895
  
  		pci_write_config_dword(dev, E752X_NERR_GLOBAL,
052dfb45c   Douglas Thompson   drivers/edac: cle...
896
  				info->nerr_global);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
897
898
  	}
  }
203333cbb   Dave Jiang   drivers/edac: Lin...
899
  static int e752x_process_error_info(struct mem_ctl_info *mci,
052dfb45c   Douglas Thompson   drivers/edac: cle...
900
901
  				struct e752x_error_info *info,
  				int handle_errors)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
  {
  	u32 error32, stat32;
  	int error_found;
  
  	error_found = 0;
  	error32 = (info->ferr_global >> 18) & 0x3ff;
  	stat32 = (info->ferr_global >> 4) & 0x7ff;
  
  	if (error32)
  		global_error(1, error32, &error_found, handle_errors);
  
  	if (stat32)
  		global_error(0, stat32, &error_found, handle_errors);
  
  	error32 = (info->nerr_global >> 18) & 0x3ff;
  	stat32 = (info->nerr_global >> 4) & 0x7ff;
  
  	if (error32)
  		global_error(1, error32, &error_found, handle_errors);
  
  	if (stat32)
  		global_error(0, stat32, &error_found, handle_errors);
  
  	e752x_check_hub_interface(info, &error_found, handle_errors);
5135b797c   Andrei Konovalov   edac: new support...
926
  	e752x_check_ns_interface(info, &error_found, handle_errors);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
927
928
929
930
931
932
933
934
935
  	e752x_check_sysbus(info, &error_found, handle_errors);
  	e752x_check_membuf(info, &error_found, handle_errors);
  	e752x_check_dram(mci, info, &error_found, handle_errors);
  	return error_found;
  }
  
  static void e752x_check(struct mem_ctl_info *mci)
  {
  	struct e752x_error_info info;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
936

537fba289   Dave Peterson   [PATCH] EDAC: pri...
937
938
  	debugf3("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
939
940
941
  	e752x_get_error_info(mci, &info);
  	e752x_process_error_info(mci, &info, 1);
  }
8004fd2ad   Peter Tyser   edac: e752x: add ...
942
  /* Program byte/sec bandwidth scrub rate to hardware */
eba042a81   Borislav Petkov   edac, mc: Improve...
943
  static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw)
8004fd2ad   Peter Tyser   edac: e752x: add ...
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
  {
  	const struct scrubrate *scrubrates;
  	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
  	struct pci_dev *pdev = pvt->dev_d0f0;
  	int i;
  
  	if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0)
  		scrubrates = scrubrates_i3100;
  	else
  		scrubrates = scrubrates_e752x;
  
  	/* Translate the desired scrub rate to a e752x/3100 register value.
  	 * Search for the bandwidth that is equal or greater than the
  	 * desired rate and program the cooresponding register value.
  	 */
  	for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++)
eba042a81   Borislav Petkov   edac, mc: Improve...
960
  		if (scrubrates[i].bandwidth >= new_bw)
8004fd2ad   Peter Tyser   edac: e752x: add ...
961
962
963
964
965
966
  			break;
  
  	if (scrubrates[i].bandwidth == SDRATE_EOT)
  		return -1;
  
  	pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval);
390944439   Borislav Petkov   EDAC: Fixup scrub...
967
  	return scrubrates[i].bandwidth;
8004fd2ad   Peter Tyser   edac: e752x: add ...
968
969
970
  }
  
  /* Convert current scrub rate value into byte/sec bandwidth */
390944439   Borislav Petkov   EDAC: Fixup scrub...
971
  static int get_sdram_scrub_rate(struct mem_ctl_info *mci)
8004fd2ad   Peter Tyser   edac: e752x: add ...
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
  {
  	const struct scrubrate *scrubrates;
  	struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
  	struct pci_dev *pdev = pvt->dev_d0f0;
  	u16 scrubval;
  	int i;
  
  	if (pvt->dev_info->ctl_dev == PCI_DEVICE_ID_INTEL_3100_0)
  		scrubrates = scrubrates_i3100;
  	else
  		scrubrates = scrubrates_e752x;
  
  	/* Find the bandwidth matching the memory scrubber configuration */
  	pci_read_config_word(pdev, E752X_MCHSCRB, &scrubval);
  	scrubval = scrubval & 0x0f;
  
  	for (i = 0; scrubrates[i].bandwidth != SDRATE_EOT; i++)
  		if (scrubrates[i].scrubval == scrubval)
  			break;
  
  	if (scrubrates[i].bandwidth == SDRATE_EOT) {
  		e752x_printk(KERN_WARNING,
  			"Invalid sdram scrub control value: 0x%x
  ", scrubval);
  		return -1;
  	}
390944439   Borislav Petkov   EDAC: Fixup scrub...
998
  	return scrubrates[i].bandwidth;
8004fd2ad   Peter Tyser   edac: e752x: add ...
999

8004fd2ad   Peter Tyser   edac: e752x: add ...
1000
  }
131895251   Doug Thompson   [PATCH] EDAC: pro...
1001
1002
1003
1004
1005
  /* Return 1 if dual channel mode is active.  Else return 0. */
  static inline int dual_channel_active(u16 ddrcsr)
  {
  	return (((ddrcsr >> 12) & 3) == 3);
  }
7297c2617   Mark Grondona   drivers/edac: fix...
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  /* Remap csrow index numbers if map_type is "reverse"
   */
  static inline int remap_csrow_index(struct mem_ctl_info *mci, int index)
  {
  	struct e752x_pvt *pvt = mci->pvt_info;
  
  	if (!pvt->map_type)
  		return (7 - index);
  
  	return (index);
  }
131895251   Doug Thompson   [PATCH] EDAC: pro...
1017
  static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
052dfb45c   Douglas Thompson   drivers/edac: cle...
1018
  			u16 ddrcsr)
131895251   Doug Thompson   [PATCH] EDAC: pro...
1019
1020
1021
1022
  {
  	struct csrow_info *csrow;
  	unsigned long last_cumul_size;
  	int index, mem_dev, drc_chan;
203333cbb   Dave Jiang   drivers/edac: Lin...
1023
1024
  	int drc_drbg;		/* DRB granularity 0=64mb, 1=128mb */
  	int drc_ddim;		/* DRAM Data Integrity Mode 0=none, 2=edac */
131895251   Doug Thompson   [PATCH] EDAC: pro...
1025
1026
  	u8 value;
  	u32 dra, drc, cumul_size;
9962fd017   Brian Pomerantz   [PATCH] EDAC: e75...
1027
  	dra = 0;
203333cbb   Dave Jiang   drivers/edac: Lin...
1028
  	for (index = 0; index < 4; index++) {
9962fd017   Brian Pomerantz   [PATCH] EDAC: e75...
1029
  		u8 dra_reg;
203333cbb   Dave Jiang   drivers/edac: Lin...
1030
  		pci_read_config_byte(pdev, E752X_DRA + index, &dra_reg);
9962fd017   Brian Pomerantz   [PATCH] EDAC: e75...
1031
1032
  		dra |= dra_reg << (index * 8);
  	}
131895251   Doug Thompson   [PATCH] EDAC: pro...
1033
1034
  	pci_read_config_dword(pdev, E752X_DRC, &drc);
  	drc_chan = dual_channel_active(ddrcsr);
203333cbb   Dave Jiang   drivers/edac: Lin...
1035
  	drc_drbg = drc_chan + 1;	/* 128 in dual mode, 64 in single */
131895251   Doug Thompson   [PATCH] EDAC: pro...
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
  	drc_ddim = (drc >> 20) & 0x3;
  
  	/* The dram row boundary (DRB) reg values are boundary address for
  	 * each DRAM row with a granularity of 64 or 128MB (single/dual
  	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
  	 * contain the total memory contained in all eight rows.
  	 */
  	for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
  		/* mem_dev 0=x8, 1=x4 */
  		mem_dev = (dra >> (index * 4 + 2)) & 0x3;
7297c2617   Mark Grondona   drivers/edac: fix...
1046
  		csrow = &mci->csrows[remap_csrow_index(mci, index)];
131895251   Doug Thompson   [PATCH] EDAC: pro...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
  
  		mem_dev = (mem_dev == 2);
  		pci_read_config_byte(pdev, E752X_DRB + index, &value);
  		/* convert a 128 or 64 MiB DRB to a page size. */
  		cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
  		debugf3("%s(): (%d) cumul_size 0x%x
  ", __func__, index,
  			cumul_size);
  		if (cumul_size == last_cumul_size)
  			continue;	/* not populated */
  
  		csrow->first_page = last_cumul_size;
  		csrow->last_page = cumul_size - 1;
  		csrow->nr_pages = cumul_size - last_cumul_size;
  		last_cumul_size = cumul_size;
  		csrow->grain = 1 << 12;	/* 4KiB - resolution of CELOG */
  		csrow->mtype = MEM_RDDR;	/* only one type supported */
  		csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
  
  		/*
  		 * if single channel or x8 devices then SECDED
  		 * if dual channel and x4 then S4ECD4ED
  		 */
  		if (drc_ddim) {
  			if (drc_chan && mem_dev) {
  				csrow->edac_mode = EDAC_S4ECD4ED;
  				mci->edac_cap |= EDAC_FLAG_S4ECD4ED;
  			} else {
  				csrow->edac_mode = EDAC_SECDED;
  				mci->edac_cap |= EDAC_FLAG_SECDED;
  			}
  		} else
  			csrow->edac_mode = EDAC_NONE;
  	}
  }
  
  static void e752x_init_mem_map_table(struct pci_dev *pdev,
052dfb45c   Douglas Thompson   drivers/edac: cle...
1084
  				struct e752x_pvt *pvt)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1085
  {
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1086
  	int index;
7297c2617   Mark Grondona   drivers/edac: fix...
1087
  	u8 value, last, row;
131895251   Doug Thompson   [PATCH] EDAC: pro...
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
  
  	last = 0;
  	row = 0;
  
  	for (index = 0; index < 8; index += 2) {
  		pci_read_config_byte(pdev, E752X_DRB + index, &value);
  		/* test if there is a dimm in this slot */
  		if (value == last) {
  			/* no dimm in the slot, so flag it as empty */
  			pvt->map[index] = 0xff;
  			pvt->map[index + 1] = 0xff;
203333cbb   Dave Jiang   drivers/edac: Lin...
1099
  		} else {	/* there is a dimm in the slot */
131895251   Doug Thompson   [PATCH] EDAC: pro...
1100
1101
1102
1103
1104
1105
1106
  			pvt->map[index] = row;
  			row++;
  			last = value;
  			/* test the next value to see if the dimm is double
  			 * sided
  			 */
  			pci_read_config_byte(pdev, E752X_DRB + index + 1,
052dfb45c   Douglas Thompson   drivers/edac: cle...
1107
1108
1109
1110
1111
  					&value);
  
  			/* the dimm is single sided, so flag as empty */
  			/* this is a double sided dimm to save the next row #*/
  			pvt->map[index + 1] = (value == last) ? 0xff :	row;
131895251   Doug Thompson   [PATCH] EDAC: pro...
1112
1113
1114
1115
  			row++;
  			last = value;
  		}
  	}
131895251   Doug Thompson   [PATCH] EDAC: pro...
1116
1117
1118
1119
  }
  
  /* Return 0 on success or 1 on failure. */
  static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,
052dfb45c   Douglas Thompson   drivers/edac: cle...
1120
  			struct e752x_pvt *pvt)
131895251   Doug Thompson   [PATCH] EDAC: pro...
1121
1122
1123
1124
  {
  	struct pci_dev *dev;
  
  	pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
10d33e9c3   Doug Thompson   edac: e752x fix t...
1125
  				pvt->dev_info->err_dev, pvt->bridge_ck);
131895251   Doug Thompson   [PATCH] EDAC: pro...
1126
1127
1128
1129
1130
1131
1132
  
  	if (pvt->bridge_ck == NULL)
  		pvt->bridge_ck = pci_scan_single_device(pdev->bus,
  							PCI_DEVFN(0, 1));
  
  	if (pvt->bridge_ck == NULL) {
  		e752x_printk(KERN_ERR, "error reporting device not found:"
052dfb45c   Douglas Thompson   drivers/edac: cle...
1133
1134
1135
  			"vendor %x device 0x%x (broken BIOS?)
  ",
  			PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
131895251   Doug Thompson   [PATCH] EDAC: pro...
1136
1137
  		return 1;
  	}
10d33e9c3   Doug Thompson   edac: e752x fix t...
1138
1139
1140
  	dev = pci_get_device(PCI_VENDOR_ID_INTEL,
  				e752x_devs[dev_idx].ctl_dev,
  				NULL);
131895251   Doug Thompson   [PATCH] EDAC: pro...
1141
1142
1143
1144
1145
1146
1147
1148
  
  	if (dev == NULL)
  		goto fail;
  
  	pvt->dev_d0f0 = dev;
  	pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
  
  	return 0;
052dfb45c   Douglas Thompson   drivers/edac: cle...
1149
  fail:
131895251   Doug Thompson   [PATCH] EDAC: pro...
1150
1151
1152
  	pci_dev_put(pvt->bridge_ck);
  	return 1;
  }
94ee1cf5a   Peter Tyser   edac: add e752x p...
1153
1154
  /* Setup system bus parity mask register.
   * Sysbus parity supported on:
8de5c1a16   Konstantin Olifer   edac: e752x fsb ecc
1155
   * e7320/e7520/e7525 + Xeon
94ee1cf5a   Peter Tyser   edac: add e752x p...
1156
1157
1158
1159
1160
1161
   */
  static void e752x_init_sysbus_parity_mask(struct e752x_pvt *pvt)
  {
  	char *cpu_id = cpu_data(0).x86_model_id;
  	struct pci_dev *dev = pvt->dev_d0f1;
  	int enable = 1;
98a1708de   Martin Olsson   trivial: fix typo...
1162
  	/* Allow module parameter override, else see if CPU supports parity */
94ee1cf5a   Peter Tyser   edac: add e752x p...
1163
1164
  	if (sysbus_parity != -1) {
  		enable = sysbus_parity;
8de5c1a16   Konstantin Olifer   edac: e752x fsb ecc
1165
  	} else if (cpu_id[0] && !strstr(cpu_id, "Xeon")) {
94ee1cf5a   Peter Tyser   edac: add e752x p...
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
  		e752x_printk(KERN_INFO, "System Bus Parity not "
  			     "supported by CPU, disabling
  ");
  		enable = 0;
  	}
  
  	if (enable)
  		pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0000);
  	else
  		pci_write_config_word(dev, E752X_SYSBUS_ERRMASK, 0x0309);
  }
131895251   Doug Thompson   [PATCH] EDAC: pro...
1177
1178
1179
1180
1181
1182
  static void e752x_init_error_reporting_regs(struct e752x_pvt *pvt)
  {
  	struct pci_dev *dev;
  
  	dev = pvt->dev_d0f1;
  	/* Turn off error disable & SMI in case the BIOS turned it on */
5135b797c   Andrei Konovalov   edac: new support...
1183
1184
1185
1186
1187
1188
1189
  	if (pvt->dev_info->err_dev == PCI_DEVICE_ID_INTEL_3100_1_ERR) {
  		pci_write_config_dword(dev, I3100_NSI_EMASK, 0);
  		pci_write_config_dword(dev, I3100_NSI_SMICMD, 0);
  	} else {
  		pci_write_config_byte(dev, E752X_HI_ERRMASK, 0x00);
  		pci_write_config_byte(dev, E752X_HI_SMICMD, 0x00);
  	}
94ee1cf5a   Peter Tyser   edac: add e752x p...
1190
1191
  
  	e752x_init_sysbus_parity_mask(pvt);
131895251   Doug Thompson   [PATCH] EDAC: pro...
1192
1193
1194
1195
1196
1197
1198
1199
1200
  	pci_write_config_word(dev, E752X_SYSBUS_SMICMD, 0x00);
  	pci_write_config_byte(dev, E752X_BUF_ERRMASK, 0x00);
  	pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
  	pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
  	pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
  }
  
  static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
  {
3847bccce   Dave Peterson   [PATCH] EDAC: e75...
1201
  	u16 pci_data;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1202
  	u8 stat8;
131895251   Doug Thompson   [PATCH] EDAC: pro...
1203
1204
  	struct mem_ctl_info *mci;
  	struct e752x_pvt *pvt;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1205
  	u16 ddrcsr;
203333cbb   Dave Jiang   drivers/edac: Lin...
1206
  	int drc_chan;		/* Number of channels 0=1chan,1=2chan */
749ede574   Dave Peterson   [PATCH] EDAC: cle...
1207
  	struct e752x_error_info discard;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1208

537fba289   Dave Peterson   [PATCH] EDAC: pri...
1209
1210
  	debugf0("%s(): mci
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1211
1212
  	debugf0("Starting Probe1
  ");
96941026a   mark gross   [PATCH] EDAC Coex...
1213
1214
1215
1216
  	/* check to see if device 0 function 1 is enabled; if it isn't, we
  	 * assume the BIOS has reserved it for a reason and is expecting
  	 * exclusive access, we take care not to violate that assumption and
  	 * fail the probe. */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1217
  	pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
96941026a   mark gross   [PATCH] EDAC Coex...
1218
1219
  	if (!force_function_unhide && !(stat8 & (1 << 5))) {
  		printk(KERN_INFO "Contact your BIOS vendor to see if the "
052dfb45c   Douglas Thompson   drivers/edac: cle...
1220
1221
  			"E752x error registers can be safely un-hidden
  ");
f9b5a5d19   Aristeu Rozanski   drivers/edac: fix...
1222
  		return -ENODEV;
96941026a   mark gross   [PATCH] EDAC Coex...
1223
  	}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1224
1225
  	stat8 |= (1 << 5);
  	pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1226
1227
1228
  	pci_read_config_word(pdev, E752X_DDRCSR, &ddrcsr);
  	/* FIXME: should check >>12 or 0xf, true for all? */
  	/* Dual channel = 1, Single channel = 0 */
131895251   Doug Thompson   [PATCH] EDAC: pro...
1229
  	drc_chan = dual_channel_active(ddrcsr);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1230

b8f6f9755   Doug Thompson   drivers/edac: fix...
1231
  	mci = edac_mc_alloc(sizeof(*pvt), E752X_NR_CSROWS, drc_chan + 1, 0);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1232
1233
  
  	if (mci == NULL) {
131895251   Doug Thompson   [PATCH] EDAC: pro...
1234
  		return -ENOMEM;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1235
  	}
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1236
1237
  	debugf3("%s(): init mci
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1238
  	mci->mtype_cap = MEM_FLAG_RDDR;
5135b797c   Andrei Konovalov   edac: new support...
1239
1240
1241
  	/* 3100 IMCH supports SECDEC only */
  	mci->edac_ctl_cap = (dev_idx == I3100) ? EDAC_FLAG_SECDED :
  		(EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1242
  	/* FIXME - what if different memory types are in different csrows? */
680cbbbb0   Dave Peterson   [PATCH] EDAC: nam...
1243
  	mci->mod_name = EDAC_MOD_STR;
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
1244
1245
  	mci->mod_ver = E752X_REVISION;
  	mci->dev = &pdev->dev;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1246

537fba289   Dave Peterson   [PATCH] EDAC: pri...
1247
1248
  	debugf3("%s(): init pvt
  ", __func__);
203333cbb   Dave Jiang   drivers/edac: Lin...
1249
  	pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1250
  	pvt->dev_info = &e752x_devs[dev_idx];
131895251   Doug Thompson   [PATCH] EDAC: pro...
1251
  	pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1252

131895251   Doug Thompson   [PATCH] EDAC: pro...
1253
1254
1255
  	if (e752x_get_devs(pdev, dev_idx, pvt)) {
  		edac_mc_free(mci);
  		return -ENODEV;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1256
  	}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1257

537fba289   Dave Peterson   [PATCH] EDAC: pri...
1258
1259
  	debugf3("%s(): more mci init
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1260
  	mci->ctl_name = pvt->dev_info->ctl_name;
c4192705f   Dave Jiang   drivers/edac: add...
1261
  	mci->dev_name = pci_name(pdev);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1262
1263
  	mci->edac_check = e752x_check;
  	mci->ctl_page_to_phys = ctl_page_to_phys;
8004fd2ad   Peter Tyser   edac: e752x: add ...
1264
1265
  	mci->set_sdram_scrub_rate = set_sdram_scrub_rate;
  	mci->get_sdram_scrub_rate = get_sdram_scrub_rate;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1266

7297c2617   Mark Grondona   drivers/edac: fix...
1267
1268
1269
1270
  	/* set the map type.  1 = normal, 0 = reversed
  	 * Must be set before e752x_init_csrows in case csrow mapping
  	 * is reversed.
  	 */
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
1271
  	pci_read_config_byte(pdev, E752X_DRM, &stat8);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1272
  	pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
7297c2617   Mark Grondona   drivers/edac: fix...
1273
1274
  	e752x_init_csrows(mci, pdev, ddrcsr);
  	e752x_init_mem_map_table(pdev, pvt);
5135b797c   Andrei Konovalov   edac: new support...
1275
1276
1277
1278
  	if (dev_idx == I3100)
  		mci->edac_cap = EDAC_FLAG_SECDED; /* the only mode supported */
  	else
  		mci->edac_cap |= EDAC_FLAG_NONE;
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1279
1280
  	debugf3("%s(): tolm, remapbase, remaplimit
  ", __func__);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1281

806c35f50   Alan Cox   [PATCH] EDAC: dri...
1282
  	/* load the top of low memory, remap base, and remap limit vars */
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
1283
  	pci_read_config_word(pdev, E752X_TOLM, &pci_data);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1284
  	pvt->tolm = ((u32) pci_data) << 4;
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
1285
  	pci_read_config_word(pdev, E752X_REMAPBASE, &pci_data);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1286
  	pvt->remapbase = ((u32) pci_data) << 14;
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
1287
  	pci_read_config_word(pdev, E752X_REMAPLIMIT, &pci_data);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1288
  	pvt->remaplimit = ((u32) pci_data) << 14;
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1289
  	e752x_printk(KERN_INFO,
052dfb45c   Douglas Thompson   drivers/edac: cle...
1290
1291
1292
  			"tolm = %x, remapbase = %x, remaplimit = %x
  ",
  			pvt->tolm, pvt->remapbase, pvt->remaplimit);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1293

2d7bbb91c   Doug Thompson   [PATCH] EDAC: mc ...
1294
1295
1296
  	/* Here we assume that we will never see multiple instances of this
  	 * type of memory controller.  The ID is therefore hardcoded to 0.
  	 */
b8f6f9755   Doug Thompson   drivers/edac: fix...
1297
  	if (edac_mc_add_mc(mci)) {
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1298
1299
  		debugf3("%s(): failed edac_mc_add_mc()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1300
1301
  		goto fail;
  	}
131895251   Doug Thompson   [PATCH] EDAC: pro...
1302
  	e752x_init_error_reporting_regs(pvt);
203333cbb   Dave Jiang   drivers/edac: Lin...
1303
  	e752x_get_error_info(mci, &discard);	/* clear other MCH errors */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1304

91b99041c   Dave Jiang   drivers/edac: upd...
1305
1306
1307
1308
  	/* allocating generic PCI control info */
  	e752x_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
  	if (!e752x_pci) {
  		printk(KERN_WARNING
052dfb45c   Douglas Thompson   drivers/edac: cle...
1309
1310
  			"%s(): Unable to create PCI control
  ", __func__);
91b99041c   Dave Jiang   drivers/edac: upd...
1311
  		printk(KERN_WARNING
052dfb45c   Douglas Thompson   drivers/edac: cle...
1312
1313
1314
  			"%s(): PCI error report via EDAC not setup
  ",
  			__func__);
91b99041c   Dave Jiang   drivers/edac: upd...
1315
  	}
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1316
  	/* get this far and it's successful */
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1317
1318
  	debugf3("%s(): success
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1319
  	return 0;
052dfb45c   Douglas Thompson   drivers/edac: cle...
1320
  fail:
131895251   Doug Thompson   [PATCH] EDAC: pro...
1321
1322
1323
1324
  	pci_dev_put(pvt->dev_d0f0);
  	pci_dev_put(pvt->dev_d0f1);
  	pci_dev_put(pvt->bridge_ck);
  	edac_mc_free(mci);
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1325

131895251   Doug Thompson   [PATCH] EDAC: pro...
1326
  	return -ENODEV;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1327
1328
1329
1330
  }
  
  /* returns count (>= 0), or negative on error */
  static int __devinit e752x_init_one(struct pci_dev *pdev,
052dfb45c   Douglas Thompson   drivers/edac: cle...
1331
  				const struct pci_device_id *ent)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1332
  {
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1333
1334
  	debugf0("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1335
1336
  
  	/* wake up and enable device */
203333cbb   Dave Jiang   drivers/edac: Lin...
1337
  	if (pci_enable_device(pdev) < 0)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1338
  		return -EIO;
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1339

806c35f50   Alan Cox   [PATCH] EDAC: dri...
1340
1341
  	return e752x_probe1(pdev, ent->driver_data);
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1342
1343
1344
1345
  static void __devexit e752x_remove_one(struct pci_dev *pdev)
  {
  	struct mem_ctl_info *mci;
  	struct e752x_pvt *pvt;
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1346
1347
  	debugf0("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1348

91b99041c   Dave Jiang   drivers/edac: upd...
1349
1350
  	if (e752x_pci)
  		edac_pci_release_generic_ctl(e752x_pci);
37f04581a   Doug Thompson   [PATCH] EDAC: PCI...
1351
  	if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1352
  		return;
203333cbb   Dave Jiang   drivers/edac: Lin...
1353
  	pvt = (struct e752x_pvt *)mci->pvt_info;
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1354
1355
1356
1357
1358
  	pci_dev_put(pvt->dev_d0f0);
  	pci_dev_put(pvt->dev_d0f1);
  	pci_dev_put(pvt->bridge_ck);
  	edac_mc_free(mci);
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1359
  static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1360
  	{
203333cbb   Dave Jiang   drivers/edac: Lin...
1361
1362
  	 PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 E7520},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1363
  	{
203333cbb   Dave Jiang   drivers/edac: Lin...
1364
1365
  	 PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 E7525},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1366
  	{
203333cbb   Dave Jiang   drivers/edac: Lin...
1367
1368
  	 PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 E7320},
e7ecd8910   Dave Peterson   [PATCH] EDAC: for...
1369
  	{
5135b797c   Andrei Konovalov   edac: new support...
1370
1371
1372
  	 PCI_VEND_DEV(INTEL, 3100_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
  	 I3100},
  	{
203333cbb   Dave Jiang   drivers/edac: Lin...
1373
1374
  	 0,
  	 }			/* 0 terminated list. */
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1375
1376
1377
  };
  
  MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1378
  static struct pci_driver e752x_driver = {
680cbbbb0   Dave Peterson   [PATCH] EDAC: nam...
1379
  	.name = EDAC_MOD_STR,
0d38b049f   Randy Dunlap   [PATCH] edac: use...
1380
1381
1382
  	.probe = e752x_init_one,
  	.remove = __devexit_p(e752x_remove_one),
  	.id_table = e752x_pci_tbl,
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1383
  };
da9bb1d27   Alan Cox   [PATCH] EDAC: cor...
1384
  static int __init e752x_init(void)
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1385
1386
  {
  	int pci_rc;
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1387
1388
  	debugf3("%s()
  ", __func__);
c3c52bce6   Hitoshi Mitake   edac: fix module ...
1389
1390
1391
  
         /* Ensure that the OPSTATE is set correctly for POLL or NMI */
         opstate_init();
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1392
1393
1394
  	pci_rc = pci_register_driver(&e752x_driver);
  	return (pci_rc < 0) ? pci_rc : 0;
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1395
1396
  static void __exit e752x_exit(void)
  {
537fba289   Dave Peterson   [PATCH] EDAC: pri...
1397
1398
  	debugf3("%s()
  ", __func__);
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1399
1400
  	pci_unregister_driver(&e752x_driver);
  }
806c35f50   Alan Cox   [PATCH] EDAC: dri...
1401
1402
1403
1404
1405
1406
  module_init(e752x_init);
  module_exit(e752x_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman
  ");
5135b797c   Andrei Konovalov   edac: new support...
1407
  MODULE_DESCRIPTION("MC support for Intel e752x/3100 memory controllers");
96941026a   mark gross   [PATCH] EDAC Coex...
1408
1409
1410
  
  module_param(force_function_unhide, int, 0444);
  MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
10d33e9c3   Doug Thompson   edac: e752x fix t...
1411
1412
  		 " 1=force unhide and hope BIOS doesn't fight driver for "
  		"Dev0:Fun1 access");
c3c52bce6   Hitoshi Mitake   edac: fix module ...
1413

c0d121720   Dave Jiang   drivers/edac: add...
1414
1415
  module_param(edac_op_state, int, 0444);
  MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
94ee1cf5a   Peter Tyser   edac: add e752x p...
1416
1417
1418
1419
  
  module_param(sysbus_parity, int, 0444);
  MODULE_PARM_DESC(sysbus_parity, "0=disable system bus parity checking,"
  		" 1=enable system bus parity checking, default=auto-detect");
10d33e9c3   Doug Thompson   edac: e752x fix t...
1420
1421
1422
  module_param(report_non_memory_errors, int, 0644);
  MODULE_PARM_DESC(report_non_memory_errors, "0=disable non-memory error "
  		"reporting, 1=enable non-memory error reporting");