aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRanganathan Desikan <rdesikan@jetzbroadband.com>2007-07-19 04:50:31 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:57 -0400
commit420390f06a5afd3e130b960ef99bc4bd4286e535 (patch)
tree34db30fc625e6c812533da2fa5c89018ce0db3e7
parentbf52fa4a26567bfbf5b1d30f84cf0226e61d26cd (diff)
drivers/edac: new i82975x driver
New EDAC driver for the i82975x memory controller chipset Used on ASUS motherboards [akpm@linux-foundation.org: fix multiple coding-style bloopers] Signed-off-by: <arvind@acarlab.com> Signed-off-by: Ranganathan Desikan <rdesikan@jetzbroadband.com> Signed-off-by: Doug Thompson <dougthompson@xmission.com> Cc: Greg KH <greg@kroah.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/edac/Kconfig7
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/i82975x_edac.c666
3 files changed, 674 insertions, 0 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 43570d41f27c..1724c41d2414 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -88,6 +88,13 @@ config EDAC_I82875P
88 Support for error detection and correction on the Intel 88 Support for error detection and correction on the Intel
89 DP82785P and E7210 server chipsets. 89 DP82785P and E7210 server chipsets.
90 90
91config EDAC_I82975X
92 tristate "Intel 82975x (D82975x)"
93 depends on EDAC_MM_EDAC && PCI && X86
94 help
95 Support for error detection and correction on the Intel
96 DP82975x server chipsets.
97
91config EDAC_I3000 98config EDAC_I3000
92 tristate "Intel 3000/3010" 99 tristate "Intel 3000/3010"
93 depends on EDAC_MM_EDAC && PCI && X86_32 100 depends on EDAC_MM_EDAC && PCI && X86_32
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index bc437f3b9d6e..02c09f0ff157 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
23obj-$(CONFIG_EDAC_E752X) += e752x_edac.o 23obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
24obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o 24obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
25obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o 25obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
26obj-$(CONFIG_EDAC_I82975X) += i82975x_edac.o
26obj-$(CONFIG_EDAC_I3000) += i3000_edac.o 27obj-$(CONFIG_EDAC_I3000) += i3000_edac.o
27obj-$(CONFIG_EDAC_I82860) += i82860_edac.o 28obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
28obj-$(CONFIG_EDAC_R82600) += r82600_edac.o 29obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c
new file mode 100644
index 000000000000..0ee888456932
--- /dev/null
+++ b/drivers/edac/i82975x_edac.c
@@ -0,0 +1,666 @@
1/*
2 * Intel 82975X Memory Controller kernel module
3 * (C) 2007 aCarLab (India) Pvt. Ltd. (http://acarlab.com)
4 * (C) 2007 jetzbroadband (http://jetzbroadband.com)
5 * This file may be distributed under the terms of the
6 * GNU General Public License.
7 *
8 * Written by Arvind R.
9 * Copied from i82875p_edac.c source:
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/pci.h>
15#include <linux/pci_ids.h>
16#include <linux/slab.h>
17
18#include "edac_core.h"
19
20#define I82975X_REVISION " Ver: 1.0.0 " __DATE__
21#define EDAC_MOD_STR "i82975x_edac"
22
23#define i82975x_printk(level, fmt, arg...) \
24 edac_printk(level, "i82975x", fmt, ##arg)
25
26#define i82975x_mc_printk(mci, level, fmt, arg...) \
27 edac_mc_chipset_printk(mci, level, "i82975x", fmt, ##arg)
28
29#ifndef PCI_DEVICE_ID_INTEL_82975_0
30#define PCI_DEVICE_ID_INTEL_82975_0 0x277c
31#endif /* PCI_DEVICE_ID_INTEL_82975_0 */
32
33#define I82975X_NR_CSROWS(nr_chans) (8/(nr_chans))
34
35/* Intel 82975X register addresses - device 0 function 0 - DRAM Controller */
36#define I82975X_EAP 0x58 /* Dram Error Address Pointer (32b)
37 *
38 * 31:7 128 byte cache-line address
39 * 6:1 reserved
40 * 0 0: CH0; 1: CH1
41 */
42
43#define I82975X_DERRSYN 0x5c /* Dram Error SYNdrome (8b)
44 *
45 * 7:0 DRAM ECC Syndrome
46 */
47
48#define I82975X_DES 0x5d /* Dram ERRor DeSTination (8b)
49 * 0h: Processor Memory Reads
50 * 1h:7h reserved
51 * More - See Page 65 of Intel DocSheet.
52 */
53
54#define I82975X_ERRSTS 0xc8 /* Error Status Register (16b)
55 *
56 * 15:12 reserved
57 * 11 Thermal Sensor Event
58 * 10 reserved
59 * 9 non-DRAM lock error (ndlock)
60 * 8 Refresh Timeout
61 * 7:2 reserved
62 * 1 ECC UE (multibit DRAM error)
63 * 0 ECC CE (singlebit DRAM error)
64 */
65
66/* Error Reporting is supported by 3 mechanisms:
67 1. DMI SERR generation ( ERRCMD )
68 2. SMI DMI generation ( SMICMD )
69 3. SCI DMI generation ( SCICMD )
70NOTE: Only ONE of the three must be enabled
71*/
72#define I82975X_ERRCMD 0xca /* Error Command (16b)
73 *
74 * 15:12 reserved
75 * 11 Thermal Sensor Event
76 * 10 reserved
77 * 9 non-DRAM lock error (ndlock)
78 * 8 Refresh Timeout
79 * 7:2 reserved
80 * 1 ECC UE (multibit DRAM error)
81 * 0 ECC CE (singlebit DRAM error)
82 */
83
84#define I82975X_SMICMD 0xcc /* Error Command (16b)
85 *
86 * 15:2 reserved
87 * 1 ECC UE (multibit DRAM error)
88 * 0 ECC CE (singlebit DRAM error)
89 */
90
91#define I82975X_SCICMD 0xce /* Error Command (16b)
92 *
93 * 15:2 reserved
94 * 1 ECC UE (multibit DRAM error)
95 * 0 ECC CE (singlebit DRAM error)
96 */
97
98#define I82975X_XEAP 0xfc /* Extended Dram Error Address Pointer (8b)
99 *
100 * 7:1 reserved
101 * 0 Bit32 of the Dram Error Address
102 */
103
104#define I82975X_MCHBAR 0x44 /*
105 *
106 * 31:14 Base Addr of 16K memory-mapped
107 * configuration space
108 * 13:1 reserverd
109 * 0 mem-mapped config space enable
110 */
111
112/* NOTE: Following addresses have to indexed using MCHBAR offset (44h, 32b) */
113/* Intel 82975x memory mapped register space */
114
115#define I82975X_DRB_SHIFT 25 /* fixed 32MiB grain */
116
117#define I82975X_DRB 0x100 /* DRAM Row Boundary (8b x 8)
118 *
119 * 7 set to 1 in highest DRB of
120 * channel if 4GB in ch.
121 * 6:2 upper boundary of rank in
122 * 32MB grains
123 * 1:0 set to 0
124 */
125#define I82975X_DRB_CH0R0 0x100
126#define I82975X_DRB_CH0R1 0x101
127#define I82975X_DRB_CH0R2 0x102
128#define I82975X_DRB_CH0R3 0x103
129#define I82975X_DRB_CH1R0 0x180
130#define I82975X_DRB_CH1R1 0x181
131#define I82975X_DRB_CH1R2 0x182
132#define I82975X_DRB_CH1R3 0x183
133
134
135#define I82975X_DRA 0x108 /* DRAM Row Attribute (4b x 8)
136 * defines the PAGE SIZE to be used
137 * for the rank
138 * 7 reserved
139 * 6:4 row attr of odd rank, i.e. 1
140 * 3 reserved
141 * 2:0 row attr of even rank, i.e. 0
142 *
143 * 000 = unpopulated
144 * 001 = reserved
145 * 010 = 4KiB
146 * 011 = 8KiB
147 * 100 = 16KiB
148 * others = reserved
149 */
150#define I82975X_DRA_CH0R01 0x108
151#define I82975X_DRA_CH0R23 0x109
152#define I82975X_DRA_CH1R01 0x188
153#define I82975X_DRA_CH1R23 0x189
154
155
156#define I82975X_BNKARC 0x10e /* Type of device in each rank - Bank Arch (16b)
157 *
158 * 15:8 reserved
159 * 7:6 Rank 3 architecture
160 * 5:4 Rank 2 architecture
161 * 3:2 Rank 1 architecture
162 * 1:0 Rank 0 architecture
163 *
164 * 00 => x16 devices; i.e 4 banks
165 * 01 => x8 devices; i.e 8 banks
166 */
167#define I82975X_C0BNKARC 0x10e
168#define I82975X_C1BNKARC 0x18e
169
170
171
172#define I82975X_DRC 0x120 /* DRAM Controller Mode0 (32b)
173 *
174 * 31:30 reserved
175 * 29 init complete
176 * 28:11 reserved, according to Intel
177 * 22:21 number of channels
178 * 00=1 01=2 in 82875
179 * seems to be ECC mode
180 * bits in 82975 in Asus
181 * P5W
182 * 19:18 Data Integ Mode
183 * 00=none 01=ECC in 82875
184 * 10:8 refresh mode
185 * 7 reserved
186 * 6:4 mode select
187 * 3:2 reserved
188 * 1:0 DRAM type 10=Second Revision
189 * DDR2 SDRAM
190 * 00, 01, 11 reserved
191 */
192#define I82975X_DRC_CH0M0 0x120
193#define I82975X_DRC_CH1M0 0x1A0
194
195
196#define I82975X_DRC_M1 0x124 /* DRAM Controller Mode1 (32b)
197 * 31 0=Standard Address Map
198 * 1=Enhanced Address Map
199 * 30:0 reserved
200 */
201
202#define I82975X_DRC_CH0M1 0x124
203#define I82975X_DRC_CH1M1 0x1A4
204
205enum i82975x_chips {
206 I82975X = 0,
207};
208
209struct i82975x_pvt {
210 void __iomem *mch_window;
211};
212
213struct i82975x_dev_info {
214 const char *ctl_name;
215};
216
217struct i82975x_error_info {
218 u16 errsts;
219 u32 eap;
220 u8 des;
221 u8 derrsyn;
222 u16 errsts2;
223 u8 chan; /* the channel is bit 0 of EAP */
224 u8 xeap; /* extended eap bit */
225};
226
227static const struct i82975x_dev_info i82975x_devs[] = {
228 [I82975X] = {
229 .ctl_name = "i82975x"
230 },
231};
232
233static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has
234 * already registered driver
235 */
236
237static int i82975x_registered = 1;
238
239static void i82975x_get_error_info(struct mem_ctl_info *mci,
240 struct i82975x_error_info *info)
241{
242 struct pci_dev *pdev;
243
244 pdev = to_pci_dev(mci->dev);
245
246 /*
247 * This is a mess because there is no atomic way to read all the
248 * registers at once and the registers can transition from CE being
249 * overwritten by UE.
250 */
251 pci_read_config_word(pdev, I82975X_ERRSTS, &info->errsts);
252 pci_read_config_dword(pdev, I82975X_EAP, &info->eap);
253 pci_read_config_byte(pdev, I82975X_XEAP, &info->xeap);
254 pci_read_config_byte(pdev, I82975X_DES, &info->des);
255 pci_read_config_byte(pdev, I82975X_DERRSYN, &info->derrsyn);
256 pci_read_config_word(pdev, I82975X_ERRSTS, &info->errsts2);
257
258 pci_write_bits16(pdev, I82975X_ERRSTS, 0x0003, 0x0003);
259
260 /*
261 * If the error is the same then we can for both reads then
262 * the first set of reads is valid. If there is a change then
263 * there is a CE no info and the second set of reads is valid
264 * and should be UE info.
265 */
266 if (!(info->errsts2 & 0x0003))
267 return;
268
269 if ((info->errsts ^ info->errsts2) & 0x0003) {
270 pci_read_config_dword(pdev, I82975X_EAP, &info->eap);
271 pci_read_config_byte(pdev, I82975X_XEAP, &info->xeap);
272 pci_read_config_byte(pdev, I82975X_DES, &info->des);
273 pci_read_config_byte(pdev, I82975X_DERRSYN,
274 &info->derrsyn);
275 }
276}
277
278static int i82975x_process_error_info(struct mem_ctl_info *mci,
279 struct i82975x_error_info *info, int handle_errors)
280{
281 int row, multi_chan, chan;
282
283 multi_chan = mci->csrows[0].nr_channels - 1;
284
285 if (!(info->errsts2 & 0x0003))
286 return 0;
287
288 if (!handle_errors)
289 return 1;
290
291 if ((info->errsts ^ info->errsts2) & 0x0003) {
292 edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
293 info->errsts = info->errsts2;
294 }
295
296 chan = info->eap & 1;
297 info->eap >>= 1;
298 if (info->xeap )
299 info->eap |= 0x80000000;
300 info->eap >>= PAGE_SHIFT;
301 row = edac_mc_find_csrow_by_page(mci, info->eap);
302
303 if (info->errsts & 0x0002)
304 edac_mc_handle_ue(mci, info->eap, 0, row, "i82975x UE");
305 else
306 edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
307 multi_chan ? chan : 0,
308 "i82975x CE");
309
310 return 1;
311}
312
313static void i82975x_check(struct mem_ctl_info *mci)
314{
315 struct i82975x_error_info info;
316
317 debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
318 i82975x_get_error_info(mci, &info);
319 i82975x_process_error_info(mci, &info, 1);
320}
321
322/* Return 1 if dual channel mode is active. Else return 0. */
323static int dual_channel_active(void __iomem *mch_window)
324{
325 /*
326 * We treat interleaved-symmetric configuration as dual-channel - EAP's
327 * bit-0 giving the channel of the error location.
328 *
329 * All other configurations are treated as single channel - the EAP's
330 * bit-0 will resolve ok in symmetric area of mixed
331 * (symmetric/asymmetric) configurations
332 */
333 u8 drb[4][2];
334 int row;
335 int dualch;
336
337 for (dualch = 1, row = 0; dualch && (row < 4); row++) {
338 drb[row][0] = readb(mch_window + I82975X_DRB + row);
339 drb[row][1] = readb(mch_window + I82975X_DRB + row + 0x80);
340 dualch = dualch && (drb[row][0] == drb[row][1]);
341 }
342 return dualch;
343}
344
345static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
346{
347 /*
348 * ASUS P5W DH either does not program this register or programs
349 * it wrong!
350 * ECC is possible on i92975x ONLY with DEV_X8 which should mean 'val'
351 * for each rank should be 01b - the LSB of the word should be 0x55;
352 * but it reads 0!
353 */
354 return DEV_X8;
355}
356
357static void i82975x_init_csrows(struct mem_ctl_info *mci,
358 struct pci_dev *pdev, void __iomem *mch_window)
359{
360 struct csrow_info *csrow;
361 unsigned long last_cumul_size;
362 u8 value;
363 u32 cumul_size;
364 int index;
365
366 last_cumul_size = 0;
367
368 /*
369 * 82875 comment:
370 * The dram row boundary (DRB) reg values are boundary address
371 * for each DRAM row with a granularity of 32 or 64MB (single/dual
372 * channel operation). DRB regs are cumulative; therefore DRB7 will
373 * contain the total memory contained in all eight rows.
374 *
375 * FIXME:
376 * EDAC currently works for Dual-channel Interleaved configuration.
377 * Other configurations, which the chip supports, need fixing/testing.
378 *
379 */
380
381 for (index = 0; index < mci->nr_csrows; index++) {
382 csrow = &mci->csrows[index];
383
384 value = readb(mch_window + I82975X_DRB + index +
385 ((index >= 4) ? 0x80 : 0));
386 cumul_size = value;
387 cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT);
388 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
389 cumul_size);
390 if (cumul_size == last_cumul_size)
391 continue; /* not populated */
392
393 csrow->first_page = last_cumul_size;
394 csrow->last_page = cumul_size - 1;
395 csrow->nr_pages = cumul_size - last_cumul_size;
396 last_cumul_size = cumul_size;
397 csrow->grain = 1 << 7; /* I82975X_EAP has 128B resolution */
398 csrow->mtype = MEM_DDR; /* i82975x supports only DDR2 */
399 csrow->dtype = i82975x_dram_type(mch_window, index);
400 csrow->edac_mode = EDAC_SECDED; /* only supported */
401 }
402}
403
404/* #define i82975x_DEBUG_IOMEM */
405
406#ifdef i82975x_DEBUG_IOMEM
407static void i82975x_print_dram_timings(void __iomem *mch_window)
408{
409 /*
410 * The register meanings are from Intel specs;
411 * (shows 13-5-5-5 for 800-DDR2)
412 * Asus P5W Bios reports 15-5-4-4
413 * What's your religion?
414 */
415 static const int caslats[4] = { 5, 4, 3, 6 };
416 u32 dtreg[2];
417
418 dtreg[0] = readl(mch_window + 0x114);
419 dtreg[1] = readl(mch_window + 0x194);
420 i82975x_printk(KERN_INFO, "DRAM Timings : Ch0 Ch1\n"
421 " RAS Active Min = %d %d\n"
422 " CAS latency = %d %d\n"
423 " RAS to CAS = %d %d\n"
424 " RAS precharge = %d %d\n",
425 (dtreg[0] >> 19 ) & 0x0f,
426 (dtreg[1] >> 19) & 0x0f,
427 caslats[(dtreg[0] >> 8) & 0x03],
428 caslats[(dtreg[1] >> 8) & 0x03],
429 ((dtreg[0] >> 4) & 0x07) + 2,
430 ((dtreg[1] >> 4) & 0x07) + 2,
431 (dtreg[0] & 0x07) + 2,
432 (dtreg[1] & 0x07) + 2
433 );
434
435}
436#endif
437
438static int i82975x_probe1(struct pci_dev *pdev, int dev_idx)
439{
440 int rc = -ENODEV;
441 struct mem_ctl_info *mci;
442 struct i82975x_pvt *pvt;
443 void __iomem *mch_window;
444 u32 mchbar;
445 u32 drc[2];
446 struct i82975x_error_info discard;
447 int chans;
448#ifdef i82975x_DEBUG_IOMEM
449 u8 c0drb[4];
450 u8 c1drb[4];
451#endif
452
453 debugf0("%s()\n", __func__);
454
455 pci_read_config_dword(pdev, I82975X_MCHBAR, &mchbar);
456 if (!(mchbar & 1)) {
457 debugf3("%s(): failed, MCHBAR disabled!\n", __func__);
458 goto fail0;
459 }
460 mchbar &= 0xffffc000; /* bits 31:14 used for 16K window */
461 mch_window = ioremap_nocache(mchbar, 0x1000);
462
463#ifdef i82975x_DEBUG_IOMEM
464 i82975x_printk(KERN_INFO, "MCHBAR real = %0x, remapped = %p\n",
465 mchbar, mch_window);
466
467 c0drb[0] = readb(mch_window + I82975X_DRB_CH0R0);
468 c0drb[1] = readb(mch_window + I82975X_DRB_CH0R1);
469 c0drb[2] = readb(mch_window + I82975X_DRB_CH0R2);
470 c0drb[3] = readb(mch_window + I82975X_DRB_CH0R3);
471 c1drb[0] = readb(mch_window + I82975X_DRB_CH1R0);
472 c1drb[1] = readb(mch_window + I82975X_DRB_CH1R1);
473 c1drb[2] = readb(mch_window + I82975X_DRB_CH1R2);
474 c1drb[3] = readb(mch_window + I82975X_DRB_CH1R3);
475 i82975x_printk(KERN_INFO, "DRBCH0R0 = 0x%02x\n", c0drb[0]);
476 i82975x_printk(KERN_INFO, "DRBCH0R1 = 0x%02x\n", c0drb[1]);
477 i82975x_printk(KERN_INFO, "DRBCH0R2 = 0x%02x\n", c0drb[2]);
478 i82975x_printk(KERN_INFO, "DRBCH0R3 = 0x%02x\n", c0drb[3]);
479 i82975x_printk(KERN_INFO, "DRBCH1R0 = 0x%02x\n", c1drb[0]);
480 i82975x_printk(KERN_INFO, "DRBCH1R1 = 0x%02x\n", c1drb[1]);
481 i82975x_printk(KERN_INFO, "DRBCH1R2 = 0x%02x\n", c1drb[2]);
482 i82975x_printk(KERN_INFO, "DRBCH1R3 = 0x%02x\n", c1drb[3]);
483#endif
484
485 drc[0] = readl(mch_window + I82975X_DRC_CH0M0);
486 drc[1] = readl(mch_window + I82975X_DRC_CH1M0);
487#ifdef i82975x_DEBUG_IOMEM
488 i82975x_printk(KERN_INFO, "DRC_CH0 = %0x, %s\n", drc[0],
489 ((drc[0] >> 21) & 3) == 1 ?
490 "ECC enabled" : "ECC disabled");
491 i82975x_printk(KERN_INFO, "DRC_CH1 = %0x, %s\n", drc[1],
492 ((drc[1] >> 21) & 3) == 1 ?
493 "ECC enabled" : "ECC disabled");
494
495 i82975x_printk(KERN_INFO, "C0 BNKARC = %0x\n",
496 readw(mch_window + I82975X_C0BNKARC));
497 i82975x_printk(KERN_INFO, "C1 BNKARC = %0x\n",
498 readw(mch_window + I82975X_C1BNKARC));
499 i82975x_print_dram_timings(mch_window);
500 goto fail1;
501#endif
502 if (!(((drc[0] >> 21) & 3) == 1 || ((drc[1] >> 21) & 3) == 1)) {
503 i82975x_printk(KERN_INFO, "ECC disabled on both channels.\n");
504 goto fail1;
505 }
506
507 chans = dual_channel_active(mch_window) + 1;
508
509 /* assuming only one controller, index thus is 0 */
510 mci = edac_mc_alloc(sizeof(*pvt), I82975X_NR_CSROWS(chans),
511 chans, 0);
512 if (!mci) {
513 rc = -ENOMEM;
514 goto fail1;
515 }
516
517 debugf3("%s(): init mci\n", __func__);
518 mci->dev = &pdev->dev;
519 mci->mtype_cap = MEM_FLAG_DDR;
520 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
521 mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
522 mci->mod_name = EDAC_MOD_STR;
523 mci->mod_ver = I82975X_REVISION;
524 mci->ctl_name = i82975x_devs[dev_idx].ctl_name;
525 mci->edac_check = i82975x_check;
526 mci->ctl_page_to_phys = NULL;
527 debugf3("%s(): init pvt\n", __func__);
528 pvt = (struct i82975x_pvt *) mci->pvt_info;
529 pvt->mch_window = mch_window;
530 i82975x_init_csrows(mci, pdev, mch_window);
531 i82975x_get_error_info(mci, &discard); /* clear counters */
532
533 /* finalize this instance of memory controller with edac core */
534 if (edac_mc_add_mc(mci)) {
535 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
536 goto fail2;
537 }
538
539 /* get this far and it's successful */
540 debugf3("%s(): success\n", __func__);
541 return 0;
542
543fail2:
544 edac_mc_free(mci);
545
546fail1:
547 iounmap(mch_window);
548fail0:
549 return rc;
550}
551
552/* returns count (>= 0), or negative on error */
553static int __devinit i82975x_init_one(struct pci_dev *pdev,
554 const struct pci_device_id *ent)
555{
556 int rc;
557
558 debugf0("%s()\n", __func__);
559
560 if (pci_enable_device(pdev) < 0)
561 return -EIO;
562
563 rc = i82975x_probe1(pdev, ent->driver_data);
564
565 if (mci_pdev == NULL)
566 mci_pdev = pci_dev_get(pdev);
567
568 return rc;
569}
570
571static void __devexit i82975x_remove_one(struct pci_dev *pdev)
572{
573 struct mem_ctl_info *mci;
574 struct i82975x_pvt *pvt;
575
576 debugf0("%s()\n", __func__);
577
578 mci = edac_mc_del_mc(&pdev->dev);
579 if (mci == NULL)
580 return;
581
582 pvt = mci->pvt_info;
583 if (pvt->mch_window)
584 iounmap( pvt->mch_window );
585
586 edac_mc_free(mci);
587}
588
589static const struct pci_device_id i82975x_pci_tbl[] __devinitdata = {
590 {
591 PCI_VEND_DEV(INTEL, 82975_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
592 I82975X
593 },
594 {
595 0,
596 } /* 0 terminated list. */
597};
598
599MODULE_DEVICE_TABLE(pci, i82975x_pci_tbl);
600
601static struct pci_driver i82975x_driver = {
602 .name = EDAC_MOD_STR,
603 .probe = i82975x_init_one,
604 .remove = __devexit_p(i82975x_remove_one),
605 .id_table = i82975x_pci_tbl,
606};
607
608static int __init i82975x_init(void)
609{
610 int pci_rc;
611
612 debugf3("%s()\n", __func__);
613
614 pci_rc = pci_register_driver(&i82975x_driver);
615 if (pci_rc < 0)
616 goto fail0;
617
618 if (mci_pdev == NULL) {
619 mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
620 PCI_DEVICE_ID_INTEL_82975_0, NULL);
621
622 if (!mci_pdev) {
623 debugf0("i82975x pci_get_device fail\n");
624 pci_rc = -ENODEV;
625 goto fail1;
626 }
627
628 pci_rc = i82975x_init_one(mci_pdev, i82975x_pci_tbl);
629
630 if (pci_rc < 0) {
631 debugf0("i82975x init fail\n");
632 pci_rc = -ENODEV;
633 goto fail1;
634 }
635 }
636
637 return 0;
638
639fail1:
640 pci_unregister_driver(&i82975x_driver);
641
642fail0:
643 if (mci_pdev != NULL)
644 pci_dev_put(mci_pdev);
645
646 return pci_rc;
647}
648
649static void __exit i82975x_exit(void)
650{
651 debugf3("%s()\n", __func__);
652
653 pci_unregister_driver(&i82975x_driver);
654
655 if (!i82975x_registered) {
656 i82975x_remove_one(mci_pdev);
657 pci_dev_put(mci_pdev);
658 }
659}
660
661module_init(i82975x_init);
662module_exit(i82975x_exit);
663
664MODULE_LICENSE("GPL");
665MODULE_AUTHOR("Arvind R. <arvind@acarlab.com>");
666MODULE_DESCRIPTION("MC support for Intel 82975 memory hub controllers");