aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Uhlenkott <juhlenko@akamai.com>2007-07-19 04:49:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:54 -0400
commit535c6a53035d8911f6b90455550c5fde0da7b866 (patch)
treeadea5611dd32f312438b2447f70a7cf2e98b508c
parentc4192705fec85219086231a1c0fa61e8776e2c3b (diff)
drivers/edac: new inte 30x0 MC driver
Here's a driver for the Intel 3000 and 3010 memory controllers, relative to today's Sourceforge code drop. This has only had light testing (I've yet to actually see it handle a memory error) but it detects my hardware correctly. Signed-off-by: Jason Uhlenkott <juhlenko@akamai.com> Signed-off-by: Douglas Thompson <dougthompson@xmission.com> 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/i3000_edac.c493
-rw-r--r--include/linux/pci_ids.h1
4 files changed, 502 insertions, 0 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 3cfd9065a9b4..e8de70cb22c4 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_I3000
92 tristate "Intel 3000/3010"
93 depends on EDAC_MM_EDAC && PCI && X86_32
94 help
95 Support for error detection and correction on the Intel
96 3000 and 3010 server chipsets.
97
91config EDAC_I82860 98config EDAC_I82860
92 tristate "Intel 82860" 99 tristate "Intel 82860"
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 19d5ac724098..547ea135b64e 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
20obj-$(CONFIG_EDAC_E752X) += e752x_edac.o 20obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
21obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o 21obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
22obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o 22obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
23obj-$(CONFIG_EDAC_I3000) += i3000_edac.o
23obj-$(CONFIG_EDAC_I82860) += i82860_edac.o 24obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
24obj-$(CONFIG_EDAC_R82600) += r82600_edac.o 25obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
25 26
diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c
new file mode 100644
index 000000000000..570925d410a7
--- /dev/null
+++ b/drivers/edac/i3000_edac.c
@@ -0,0 +1,493 @@
1/*
2 * Intel 3000/3010 Memory Controller kernel module
3 * Copyright (C) 2007 Akamai Technologies, Inc.
4 * Shamelessly copied from:
5 * Intel D82875P Memory Controller kernel module
6 * (C) 2003 Linux Networx (http://lnxi.com)
7 *
8 * This file may be distributed under the terms of the
9 * GNU General Public License.
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#include "edac_core.h"
18
19#define I3000_REVISION "1.1"
20
21#define EDAC_MOD_STR "i3000_edac"
22
23#define I3000_RANKS 8
24#define I3000_RANKS_PER_CHANNEL 4
25#define I3000_CHANNELS 2
26
27/* Intel 3000 register addresses - device 0 function 0 - DRAM Controller */
28
29#define I3000_MCHBAR 0x44 /* MCH Memory Mapped Register BAR */
30#define I3000_MCHBAR_MASK 0xffffc000
31#define I3000_MMR_WINDOW_SIZE 16384
32
33#define I3000_EDEAP 0x70 /* Extended DRAM Error Address Pointer (8b)
34 *
35 * 7:1 reserved
36 * 0 bit 32 of address
37 */
38#define I3000_DEAP 0x58 /* DRAM Error Address Pointer (32b)
39 *
40 * 31:7 address
41 * 6:1 reserved
42 * 0 Error channel 0/1
43 */
44#define I3000_DEAP_GRAIN (1 << 7)
45#define I3000_DEAP_PFN(edeap, deap) ((((edeap) & 1) << (32 - PAGE_SHIFT)) | \
46 ((deap) >> PAGE_SHIFT))
47#define I3000_DEAP_OFFSET(deap) ((deap) & ~(I3000_DEAP_GRAIN-1) & ~PAGE_MASK)
48#define I3000_DEAP_CHANNEL(deap) ((deap) & 1)
49
50#define I3000_DERRSYN 0x5c /* DRAM Error Syndrome (8b)
51 *
52 * 7:0 DRAM ECC Syndrome
53 */
54
55#define I3000_ERRSTS 0xc8 /* Error Status Register (16b)
56 *
57 * 15:12 reserved
58 * 11 MCH Thermal Sensor Event for SMI/SCI/SERR
59 * 10 reserved
60 * 9 LOCK to non-DRAM Memory Flag (LCKF)
61 * 8 Received Refresh Timeout Flag (RRTOF)
62 * 7:2 reserved
63 * 1 Multiple-bit DRAM ECC Error Flag (DMERR)
64 * 0 Single-bit DRAM ECC Error Flag (DSERR)
65 */
66#define I3000_ERRSTS_BITS 0x0b03 /* bits which indicate errors */
67#define I3000_ERRSTS_UE 0x0002
68#define I3000_ERRSTS_CE 0x0001
69
70#define I3000_ERRCMD 0xca /* Error Command (16b)
71 *
72 * 15:12 reserved
73 * 11 SERR on MCH Thermal Sensor Event (TSESERR)
74 * 10 reserved
75 * 9 SERR on LOCK to non-DRAM Memory (LCKERR)
76 * 8 SERR on DRAM Refresh Timeout (DRTOERR)
77 * 7:2 reserved
78 * 1 SERR Multiple-Bit DRAM ECC Error (DMERR)
79 * 0 SERR on Single-Bit ECC Error (DSERR)
80 */
81
82/* Intel MMIO register space - device 0 function 0 - MMR space */
83
84#define I3000_DRB_SHIFT 25 /* 32MiB grain */
85
86#define I3000_C0DRB 0x100 /* Channel 0 DRAM Rank Boundary (8b x 4)
87 *
88 * 7:0 Channel 0 DRAM Rank Boundary Address
89 */
90#define I3000_C1DRB 0x180 /* Channel 1 DRAM Rank Boundary (8b x 4)
91 *
92 * 7:0 Channel 1 DRAM Rank Boundary Address
93 */
94
95#define I3000_C0DRA 0x108 /* Channel 0 DRAM Rank Attribute (8b x 2)
96 *
97 * 7 reserved
98 * 6:4 DRAM odd Rank Attribute
99 * 3 reserved
100 * 2:0 DRAM even Rank Attribute
101 *
102 * Each attribute defines the page
103 * size of the corresponding rank:
104 * 000: unpopulated
105 * 001: reserved
106 * 010: 4 KB
107 * 011: 8 KB
108 * 100: 16 KB
109 * Others: reserved
110 */
111#define I3000_C1DRA 0x188 /* Channel 1 DRAM Rank Attribute (8b x 2) */
112#define ODD_RANK_ATTRIB(dra) (((dra) & 0x70) >> 4)
113#define EVEN_RANK_ATTRIB(dra) ((dra) & 0x07)
114
115#define I3000_C0DRC0 0x120 /* DRAM Controller Mode 0 (32b)
116 *
117 * 31:30 reserved
118 * 29 Initialization Complete (IC)
119 * 28:11 reserved
120 * 10:8 Refresh Mode Select (RMS)
121 * 7 reserved
122 * 6:4 Mode Select (SMS)
123 * 3:2 reserved
124 * 1:0 DRAM Type (DT)
125 */
126
127#define I3000_C0DRC1 0x124 /* DRAM Controller Mode 1 (32b)
128 *
129 * 31 Enhanced Addressing Enable (ENHADE)
130 * 30:0 reserved
131 */
132
133
134enum i3000p_chips {
135 I3000 = 0,
136};
137
138struct i3000_dev_info {
139 const char *ctl_name;
140};
141
142struct i3000_error_info {
143 u16 errsts;
144 u8 derrsyn;
145 u8 edeap;
146 u32 deap;
147 u16 errsts2;
148};
149
150static const struct i3000_dev_info i3000_devs[] = {
151 [I3000] = {
152 .ctl_name = "i3000"
153 },
154};
155
156static struct pci_dev *mci_pdev = NULL;
157static int i3000_registered = 1;
158
159static void i3000_get_error_info(struct mem_ctl_info *mci,
160 struct i3000_error_info *info)
161{
162 struct pci_dev *pdev;
163
164 pdev = to_pci_dev(mci->dev);
165
166 /*
167 * This is a mess because there is no atomic way to read all the
168 * registers at once and the registers can transition from CE being
169 * overwritten by UE.
170 */
171 pci_read_config_word(pdev, I3000_ERRSTS, &info->errsts);
172 if (!(info->errsts & I3000_ERRSTS_BITS))
173 return;
174 pci_read_config_byte(pdev, I3000_EDEAP, &info->edeap);
175 pci_read_config_dword(pdev, I3000_DEAP, &info->deap);
176 pci_read_config_byte(pdev, I3000_DERRSYN, &info->derrsyn);
177 pci_read_config_word(pdev, I3000_ERRSTS, &info->errsts2);
178
179 /*
180 * If the error is the same for both reads then the first set
181 * of reads is valid. If there is a change then there is a CE
182 * with no info and the second set of reads is valid and
183 * should be UE info.
184 */
185 if ((info->errsts ^ info->errsts2) & I3000_ERRSTS_BITS) {
186 pci_read_config_byte(pdev, I3000_EDEAP,
187 &info->edeap);
188 pci_read_config_dword(pdev, I3000_DEAP,
189 &info->deap);
190 pci_read_config_byte(pdev, I3000_DERRSYN,
191 &info->derrsyn);
192 }
193
194 /* Clear any error bits.
195 * (Yes, we really clear bits by writing 1 to them.)
196 */
197 pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, I3000_ERRSTS_BITS);
198}
199
200static int i3000_process_error_info(struct mem_ctl_info *mci,
201 struct i3000_error_info *info, int handle_errors)
202{
203 int row, multi_chan;
204 int pfn, offset, channel;
205
206 multi_chan = mci->csrows[0].nr_channels - 1;
207
208 if (!(info->errsts & I3000_ERRSTS_BITS))
209 return 0;
210
211 if (!handle_errors)
212 return 1;
213
214 if ((info->errsts ^ info->errsts2) & I3000_ERRSTS_BITS) {
215 edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
216 info->errsts = info->errsts2;
217 }
218
219 pfn = I3000_DEAP_PFN(info->edeap, info->deap);
220 offset = I3000_DEAP_OFFSET(info->deap);
221 channel = I3000_DEAP_CHANNEL(info->deap);
222
223 row = edac_mc_find_csrow_by_page(mci, pfn);
224
225 if (info->errsts & I3000_ERRSTS_UE)
226 edac_mc_handle_ue(mci, pfn, offset, row, "i3000 UE");
227 else
228 edac_mc_handle_ce(mci, pfn, offset, info->derrsyn, row,
229 multi_chan ? channel : 0,
230 "i3000 CE");
231
232 return 1;
233}
234
235static void i3000_check(struct mem_ctl_info *mci)
236{
237 struct i3000_error_info info;
238
239 debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
240 i3000_get_error_info(mci, &info);
241 i3000_process_error_info(mci, &info, 1);
242}
243
244static int i3000_is_interleaved(const unsigned char *c0dra,
245 const unsigned char *c1dra,
246 const unsigned char *c0drb,
247 const unsigned char *c1drb)
248{
249 int i;
250
251 /* If the channels aren't populated identically then
252 * we're not interleaved.
253 */
254 for (i = 0; i < I3000_RANKS_PER_CHANNEL / 2; i++)
255 if (ODD_RANK_ATTRIB(c0dra[i]) != ODD_RANK_ATTRIB(c1dra[i]) ||
256 EVEN_RANK_ATTRIB(c0dra[i]) != EVEN_RANK_ATTRIB(c1dra[i]))
257 return 0;
258
259 /* If the rank boundaries for the two channels are different
260 * then we're not interleaved.
261 */
262 for (i = 0; i < I3000_RANKS_PER_CHANNEL; i++)
263 if (c0drb[i] != c1drb[i])
264 return 0;
265
266 return 1;
267}
268
269static int i3000_probe1(struct pci_dev *pdev, int dev_idx)
270{
271 int rc;
272 int i;
273 struct mem_ctl_info *mci = NULL;
274 unsigned long last_cumul_size;
275 int interleaved, nr_channels;
276 unsigned char dra[I3000_RANKS / 2], drb[I3000_RANKS];
277 unsigned char *c0dra = dra, *c1dra = &dra[I3000_RANKS_PER_CHANNEL / 2];
278 unsigned char *c0drb = drb, *c1drb = &drb[I3000_RANKS_PER_CHANNEL];
279 unsigned long mchbar;
280 void *window;
281
282 debugf0("MC: %s()\n", __func__);
283
284 pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *)&mchbar);
285 mchbar &= I3000_MCHBAR_MASK;
286 window = ioremap_nocache(mchbar, I3000_MMR_WINDOW_SIZE);
287 if (!window) {
288 printk(KERN_ERR "i3000: cannot map mmio space at 0x%lx\n", mchbar);
289 return -ENODEV;
290 }
291
292 c0dra[0] = readb(window + I3000_C0DRA + 0); /* ranks 0,1 */
293 c0dra[1] = readb(window + I3000_C0DRA + 1); /* ranks 2,3 */
294 c1dra[0] = readb(window + I3000_C1DRA + 0); /* ranks 0,1 */
295 c1dra[1] = readb(window + I3000_C1DRA + 1); /* ranks 2,3 */
296
297 for (i = 0; i < I3000_RANKS_PER_CHANNEL; i++) {
298 c0drb[i] = readb(window + I3000_C0DRB + i);
299 c1drb[i] = readb(window + I3000_C1DRB + i);
300 }
301
302 iounmap(window);
303
304 /* Figure out how many channels we have.
305 *
306 * If we have what the datasheet calls "asymmetric channels"
307 * (essentially the same as what was called "virtual single
308 * channel mode" in the i82875) then it's a single channel as
309 * far as EDAC is concerned.
310 */
311 interleaved = i3000_is_interleaved(c0dra, c1dra, c0drb, c1drb);
312 nr_channels = interleaved ? 2 : 1;
313 mci = edac_mc_alloc(0, I3000_RANKS / nr_channels, nr_channels);
314 if (!mci)
315 return -ENOMEM;
316
317 debugf3("MC: %s(): init mci\n", __func__);
318
319 mci->dev = &pdev->dev;
320 mci->mtype_cap = MEM_FLAG_DDR2;
321
322 mci->edac_ctl_cap = EDAC_FLAG_SECDED;
323 mci->edac_cap = EDAC_FLAG_SECDED;
324
325 mci->mod_name = EDAC_MOD_STR;
326 mci->mod_ver = I3000_REVISION;
327 mci->ctl_name = i3000_devs[dev_idx].ctl_name;
328 mci->dev_name = pci_name(pdev);
329 mci->edac_check = i3000_check;
330 mci->ctl_page_to_phys = NULL;
331
332 /*
333 * The dram rank boundary (DRB) reg values are boundary addresses
334 * for each DRAM rank with a granularity of 32MB. DRB regs are
335 * cumulative; the last one will contain the total memory
336 * contained in all ranks.
337 *
338 * If we're in interleaved mode then we're only walking through
339 * the ranks of controller 0, so we double all the values we see.
340 */
341 for (last_cumul_size = i = 0; i < mci->nr_csrows; i++) {
342 u8 value;
343 u32 cumul_size;
344 struct csrow_info *csrow = &mci->csrows[i];
345
346 value = drb[i];
347 cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT);
348 if (interleaved)
349 cumul_size <<= 1;
350 debugf3("MC: %s(): (%d) cumul_size 0x%x\n",
351 __func__, i, cumul_size);
352 if (cumul_size == last_cumul_size) {
353 csrow->mtype = MEM_EMPTY;
354 continue;
355 }
356
357 csrow->first_page = last_cumul_size;
358 csrow->last_page = cumul_size - 1;
359 csrow->nr_pages = cumul_size - last_cumul_size;
360 last_cumul_size = cumul_size;
361 csrow->grain = I3000_DEAP_GRAIN;
362 csrow->mtype = MEM_DDR2;
363 csrow->dtype = DEV_UNKNOWN;
364 csrow->edac_mode = EDAC_UNKNOWN;
365 }
366
367 /* Clear any error bits.
368 * (Yes, we really clear bits by writing 1 to them.)
369 */
370 pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, I3000_ERRSTS_BITS);
371
372 rc = -ENODEV;
373 if (edac_mc_add_mc(mci, 0)) {
374 debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__);
375 goto fail;
376 }
377
378 /* get this far and it's successful */
379 debugf3("MC: %s(): success\n", __func__);
380 return 0;
381
382 fail:
383 if (mci)
384 edac_mc_free(mci);
385
386 return rc;
387}
388
389/* returns count (>= 0), or negative on error */
390static int __devinit i3000_init_one(struct pci_dev *pdev,
391 const struct pci_device_id *ent)
392{
393 int rc;
394
395 debugf0("MC: %s()\n", __func__);
396
397 if (pci_enable_device(pdev) < 0)
398 return -EIO;
399
400 rc = i3000_probe1(pdev, ent->driver_data);
401 if (mci_pdev == NULL)
402 mci_pdev = pci_dev_get(pdev);
403
404 return rc;
405}
406
407static void __devexit i3000_remove_one(struct pci_dev *pdev)
408{
409 struct mem_ctl_info *mci;
410
411 debugf0("%s()\n", __func__);
412
413 if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
414 return;
415
416 edac_mc_free(mci);
417}
418
419static const struct pci_device_id i3000_pci_tbl[] __devinitdata = {
420 {
421 PCI_VEND_DEV(INTEL, 3000_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
422 I3000
423 },
424 {
425 0,
426 } /* 0 terminated list. */
427};
428
429MODULE_DEVICE_TABLE(pci, i3000_pci_tbl);
430
431static struct pci_driver i3000_driver = {
432 .name = EDAC_MOD_STR,
433 .probe = i3000_init_one,
434 .remove = __devexit_p(i3000_remove_one),
435 .id_table = i3000_pci_tbl,
436};
437
438static int __init i3000_init(void)
439{
440 int pci_rc;
441
442 debugf3("MC: %s()\n", __func__);
443 pci_rc = pci_register_driver(&i3000_driver);
444 if (pci_rc < 0)
445 goto fail0;
446
447 if (mci_pdev == NULL) {
448 i3000_registered = 0;
449 mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
450 PCI_DEVICE_ID_INTEL_3000_HB, NULL);
451 if (!mci_pdev) {
452 debugf0("i3000 pci_get_device fail\n");
453 pci_rc = -ENODEV;
454 goto fail1;
455 }
456
457 pci_rc = i3000_init_one(mci_pdev, i3000_pci_tbl);
458 if (pci_rc < 0) {
459 debugf0("i3000 init fail\n");
460 pci_rc = -ENODEV;
461 goto fail1;
462 }
463 }
464
465 return 0;
466
467fail1:
468 pci_unregister_driver(&i3000_driver);
469
470fail0:
471 if (mci_pdev)
472 pci_dev_put(mci_pdev);
473
474 return pci_rc;
475}
476
477static void __exit i3000_exit(void)
478{
479 debugf3("MC: %s()\n", __func__);
480
481 pci_unregister_driver(&i3000_driver);
482 if (!i3000_registered) {
483 i3000_remove_one(mci_pdev);
484 pci_dev_put(mci_pdev);
485 }
486}
487
488module_init(i3000_init);
489module_exit(i3000_exit);
490
491MODULE_LICENSE("GPL");
492MODULE_AUTHOR("Akamai Technologies Arthur Ulfeldt/Jason Uhlenkott");
493MODULE_DESCRIPTION("MC support for Intel 3000 memory hub controllers");
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 2c7add169539..7ec01b7525b6 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2209,6 +2209,7 @@
2209#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592 2209#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
2210#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770 2210#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770
2211#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772 2211#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772
2212#define PCI_DEVICE_ID_INTEL_3000_HB 0x2778
2212#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0 2213#define PCI_DEVICE_ID_INTEL_82945GM_HB 0x27A0
2213#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2 2214#define PCI_DEVICE_ID_INTEL_82945GM_IG 0x27A2
2214#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640 2215#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640