aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/i82875p_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/i82875p_edac.c')
-rw-r--r--drivers/edac/i82875p_edac.c112
1 files changed, 51 insertions, 61 deletions
diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c
index aad1900a4689..0aec92698f17 100644
--- a/drivers/edac/i82875p_edac.c
+++ b/drivers/edac/i82875p_edac.c
@@ -13,26 +13,19 @@
13 * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com 13 * Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
14 */ 14 */
15 15
16
17#include <linux/config.h> 16#include <linux/config.h>
18#include <linux/module.h> 17#include <linux/module.h>
19#include <linux/init.h> 18#include <linux/init.h>
20
21#include <linux/pci.h> 19#include <linux/pci.h>
22#include <linux/pci_ids.h> 20#include <linux/pci_ids.h>
23
24#include <linux/slab.h> 21#include <linux/slab.h>
25
26#include "edac_mc.h" 22#include "edac_mc.h"
27 23
28
29#define i82875p_printk(level, fmt, arg...) \ 24#define i82875p_printk(level, fmt, arg...) \
30 edac_printk(level, "i82875p", fmt, ##arg) 25 edac_printk(level, "i82875p", fmt, ##arg)
31
32 26
33#define i82875p_mc_printk(mci, level, fmt, arg...) \ 27#define i82875p_mc_printk(mci, level, fmt, arg...) \
34 edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg) 28 edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg)
35
36 29
37#ifndef PCI_DEVICE_ID_INTEL_82875_0 30#ifndef PCI_DEVICE_ID_INTEL_82875_0
38#define PCI_DEVICE_ID_INTEL_82875_0 0x2578 31#define PCI_DEVICE_ID_INTEL_82875_0 0x2578
@@ -42,11 +35,9 @@
42#define PCI_DEVICE_ID_INTEL_82875_6 0x257e 35#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
43#endif /* PCI_DEVICE_ID_INTEL_82875_6 */ 36#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
44 37
45
46/* four csrows in dual channel, eight in single channel */ 38/* four csrows in dual channel, eight in single channel */
47#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans)) 39#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
48 40
49
50/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */ 41/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
51#define I82875P_EAP 0x58 /* Error Address Pointer (32b) 42#define I82875P_EAP 0x58 /* Error Address Pointer (32b)
52 * 43 *
@@ -95,7 +86,6 @@
95 * 0 reserved 86 * 0 reserved
96 */ 87 */
97 88
98
99/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */ 89/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
100#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b) 90#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b)
101 * 91 *
@@ -159,23 +149,19 @@
159 * 1:0 DRAM type 01=DDR 149 * 1:0 DRAM type 01=DDR
160 */ 150 */
161 151
162
163enum i82875p_chips { 152enum i82875p_chips {
164 I82875P = 0, 153 I82875P = 0,
165}; 154};
166 155
167
168struct i82875p_pvt { 156struct i82875p_pvt {
169 struct pci_dev *ovrfl_pdev; 157 struct pci_dev *ovrfl_pdev;
170 void __iomem *ovrfl_window; 158 void __iomem *ovrfl_window;
171}; 159};
172 160
173
174struct i82875p_dev_info { 161struct i82875p_dev_info {
175 const char *ctl_name; 162 const char *ctl_name;
176}; 163};
177 164
178
179struct i82875p_error_info { 165struct i82875p_error_info {
180 u16 errsts; 166 u16 errsts;
181 u32 eap; 167 u32 eap;
@@ -184,17 +170,19 @@ struct i82875p_error_info {
184 u16 errsts2; 170 u16 errsts2;
185}; 171};
186 172
187
188static const struct i82875p_dev_info i82875p_devs[] = { 173static const struct i82875p_dev_info i82875p_devs[] = {
189 [I82875P] = { 174 [I82875P] = {
190 .ctl_name = "i82875p"}, 175 .ctl_name = "i82875p"
176 },
191}; 177};
192 178
193static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code 179static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code has
194 has already registered driver */ 180 * already registered driver
181 */
182
195static int i82875p_registered = 1; 183static int i82875p_registered = 1;
196 184
197static void i82875p_get_error_info (struct mem_ctl_info *mci, 185static void i82875p_get_error_info(struct mem_ctl_info *mci,
198 struct i82875p_error_info *info) 186 struct i82875p_error_info *info)
199{ 187{
200 /* 188 /*
@@ -218,15 +206,16 @@ static void i82875p_get_error_info (struct mem_ctl_info *mci,
218 */ 206 */
219 if (!(info->errsts2 & 0x0081)) 207 if (!(info->errsts2 & 0x0081))
220 return; 208 return;
209
221 if ((info->errsts ^ info->errsts2) & 0x0081) { 210 if ((info->errsts ^ info->errsts2) & 0x0081) {
222 pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap); 211 pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
223 pci_read_config_byte(mci->pdev, I82875P_DES, &info->des); 212 pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
224 pci_read_config_byte(mci->pdev, I82875P_DERRSYN, 213 pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
225 &info->derrsyn); 214 &info->derrsyn);
226 } 215 }
227} 216}
228 217
229static int i82875p_process_error_info (struct mem_ctl_info *mci, 218static int i82875p_process_error_info(struct mem_ctl_info *mci,
230 struct i82875p_error_info *info, int handle_errors) 219 struct i82875p_error_info *info, int handle_errors)
231{ 220{
232 int row, multi_chan; 221 int row, multi_chan;
@@ -251,13 +240,12 @@ static int i82875p_process_error_info (struct mem_ctl_info *mci,
251 edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE"); 240 edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
252 else 241 else
253 edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 242 edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
254 multi_chan ? (info->des & 0x1) : 0, 243 multi_chan ? (info->des & 0x1) : 0,
255 "i82875p CE"); 244 "i82875p CE");
256 245
257 return 1; 246 return 1;
258} 247}
259 248
260
261static void i82875p_check(struct mem_ctl_info *mci) 249static void i82875p_check(struct mem_ctl_info *mci)
262{ 250{
263 struct i82875p_error_info info; 251 struct i82875p_error_info info;
@@ -267,7 +255,6 @@ static void i82875p_check(struct mem_ctl_info *mci)
267 i82875p_process_error_info(mci, &info, 1); 255 i82875p_process_error_info(mci, &info, 1);
268} 256}
269 257
270
271#ifdef CONFIG_PROC_FS 258#ifdef CONFIG_PROC_FS
272extern int pci_proc_attach_device(struct pci_dev *); 259extern int pci_proc_attach_device(struct pci_dev *);
273#endif 260#endif
@@ -281,7 +268,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
281 unsigned long last_cumul_size; 268 unsigned long last_cumul_size;
282 struct pci_dev *ovrfl_pdev; 269 struct pci_dev *ovrfl_pdev;
283 void __iomem *ovrfl_window = NULL; 270 void __iomem *ovrfl_window = NULL;
284
285 u32 drc; 271 u32 drc;
286 u32 drc_chan; /* Number of channels 0=1chan,1=2chan */ 272 u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
287 u32 nr_chans; 273 u32 nr_chans;
@@ -289,7 +275,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
289 struct i82875p_error_info discard; 275 struct i82875p_error_info discard;
290 276
291 debugf0("%s()\n", __func__); 277 debugf0("%s()\n", __func__);
292
293 ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL); 278 ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
294 279
295 if (!ovrfl_pdev) { 280 if (!ovrfl_pdev) {
@@ -301,22 +286,23 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
301 */ 286 */
302 pci_write_bits8(pdev, 0xf4, 0x2, 0x2); 287 pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
303 ovrfl_pdev = 288 ovrfl_pdev =
304 pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0)); 289 pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
290
305 if (!ovrfl_pdev) 291 if (!ovrfl_pdev)
306 return -ENODEV; 292 return -ENODEV;
307 } 293 }
294
308#ifdef CONFIG_PROC_FS 295#ifdef CONFIG_PROC_FS
309 if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) { 296 if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
310 i82875p_printk(KERN_ERR, 297 i82875p_printk(KERN_ERR,
311 "%s(): Failed to attach overflow device\n", 298 "%s(): Failed to attach overflow device\n", __func__);
312 __func__);
313 return -ENODEV; 299 return -ENODEV;
314 } 300 }
315#endif /* CONFIG_PROC_FS */ 301#endif
302 /* CONFIG_PROC_FS */
316 if (pci_enable_device(ovrfl_pdev)) { 303 if (pci_enable_device(ovrfl_pdev)) {
317 i82875p_printk(KERN_ERR, 304 i82875p_printk(KERN_ERR,
318 "%s(): Failed to enable overflow device\n", 305 "%s(): Failed to enable overflow device\n", __func__);
319 __func__);
320 return -ENODEV; 306 return -ENODEV;
321 } 307 }
322 308
@@ -325,13 +311,14 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
325 goto fail0; 311 goto fail0;
326#endif 312#endif
327 } 313 }
314
328 /* cache is irrelevant for PCI bus reads/writes */ 315 /* cache is irrelevant for PCI bus reads/writes */
329 ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0), 316 ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
330 pci_resource_len(ovrfl_pdev, 0)); 317 pci_resource_len(ovrfl_pdev, 0));
331 318
332 if (!ovrfl_window) { 319 if (!ovrfl_window) {
333 i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n", 320 i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n",
334 __func__); 321 __func__);
335 goto fail1; 322 goto fail1;
336 } 323 }
337 324
@@ -339,10 +326,10 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
339 drc = readl(ovrfl_window + I82875P_DRC); 326 drc = readl(ovrfl_window + I82875P_DRC);
340 drc_chan = ((drc >> 21) & 0x1); 327 drc_chan = ((drc >> 21) & 0x1);
341 nr_chans = drc_chan + 1; 328 nr_chans = drc_chan + 1;
342 drc_ddim = (drc >> 18) & 0x1;
343 329
330 drc_ddim = (drc >> 18) & 0x1;
344 mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans), 331 mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
345 nr_chans); 332 nr_chans);
346 333
347 if (!mci) { 334 if (!mci) {
348 rc = -ENOMEM; 335 rc = -ENOMEM;
@@ -350,10 +337,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
350 } 337 }
351 338
352 debugf3("%s(): init mci\n", __func__); 339 debugf3("%s(): init mci\n", __func__);
353
354 mci->pdev = pdev; 340 mci->pdev = pdev;
355 mci->mtype_cap = MEM_FLAG_DDR; 341 mci->mtype_cap = MEM_FLAG_DDR;
356
357 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; 342 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
358 mci->edac_cap = EDAC_FLAG_UNKNOWN; 343 mci->edac_cap = EDAC_FLAG_UNKNOWN;
359 /* adjust FLAGS */ 344 /* adjust FLAGS */
@@ -363,9 +348,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
363 mci->ctl_name = i82875p_devs[dev_idx].ctl_name; 348 mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
364 mci->edac_check = i82875p_check; 349 mci->edac_check = i82875p_check;
365 mci->ctl_page_to_phys = NULL; 350 mci->ctl_page_to_phys = NULL;
366
367 debugf3("%s(): init pvt\n", __func__); 351 debugf3("%s(): init pvt\n", __func__);
368
369 pvt = (struct i82875p_pvt *) mci->pvt_info; 352 pvt = (struct i82875p_pvt *) mci->pvt_info;
370 pvt->ovrfl_pdev = ovrfl_pdev; 353 pvt->ovrfl_pdev = ovrfl_pdev;
371 pvt->ovrfl_window = ovrfl_window; 354 pvt->ovrfl_window = ovrfl_window;
@@ -385,6 +368,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
385 cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); 368 cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
386 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, 369 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
387 cumul_size); 370 cumul_size);
371
388 if (cumul_size == last_cumul_size) 372 if (cumul_size == last_cumul_size)
389 continue; /* not populated */ 373 continue; /* not populated */
390 374
@@ -392,7 +376,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
392 csrow->last_page = cumul_size - 1; 376 csrow->last_page = cumul_size - 1;
393 csrow->nr_pages = cumul_size - last_cumul_size; 377 csrow->nr_pages = cumul_size - last_cumul_size;
394 last_cumul_size = cumul_size; 378 last_cumul_size = cumul_size;
395 csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ 379 csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
396 csrow->mtype = MEM_DDR; 380 csrow->mtype = MEM_DDR;
397 csrow->dtype = DEV_UNKNOWN; 381 csrow->dtype = DEV_UNKNOWN;
398 csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE; 382 csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
@@ -426,25 +410,26 @@ fail0:
426 return rc; 410 return rc;
427} 411}
428 412
429
430/* returns count (>= 0), or negative on error */ 413/* returns count (>= 0), or negative on error */
431static int __devinit i82875p_init_one(struct pci_dev *pdev, 414static int __devinit i82875p_init_one(struct pci_dev *pdev,
432 const struct pci_device_id *ent) 415 const struct pci_device_id *ent)
433{ 416{
434 int rc; 417 int rc;
435 418
436 debugf0("%s()\n", __func__); 419 debugf0("%s()\n", __func__);
437
438 i82875p_printk(KERN_INFO, "i82875p init one\n"); 420 i82875p_printk(KERN_INFO, "i82875p init one\n");
439 if(pci_enable_device(pdev) < 0) 421
422 if (pci_enable_device(pdev) < 0)
440 return -EIO; 423 return -EIO;
424
441 rc = i82875p_probe1(pdev, ent->driver_data); 425 rc = i82875p_probe1(pdev, ent->driver_data);
426
442 if (mci_pdev == NULL) 427 if (mci_pdev == NULL)
443 mci_pdev = pci_dev_get(pdev); 428 mci_pdev = pci_dev_get(pdev);
429
444 return rc; 430 return rc;
445} 431}
446 432
447
448static void __devexit i82875p_remove_one(struct pci_dev *pdev) 433static void __devexit i82875p_remove_one(struct pci_dev *pdev)
449{ 434{
450 struct mem_ctl_info *mci; 435 struct mem_ctl_info *mci;
@@ -456,6 +441,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
456 return; 441 return;
457 442
458 pvt = (struct i82875p_pvt *) mci->pvt_info; 443 pvt = (struct i82875p_pvt *) mci->pvt_info;
444
459 if (pvt->ovrfl_window) 445 if (pvt->ovrfl_window)
460 iounmap(pvt->ovrfl_window); 446 iounmap(pvt->ovrfl_window);
461 447
@@ -470,16 +456,18 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
470 edac_mc_free(mci); 456 edac_mc_free(mci);
471} 457}
472 458
473
474static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = { 459static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
475 {PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 460 {
476 I82875P}, 461 PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
477 {0,} /* 0 terminated list. */ 462 I82875P
463 },
464 {
465 0,
466 } /* 0 terminated list. */
478}; 467};
479 468
480MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl); 469MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
481 470
482
483static struct pci_driver i82875p_driver = { 471static struct pci_driver i82875p_driver = {
484 .name = EDAC_MOD_STR, 472 .name = EDAC_MOD_STR,
485 .probe = i82875p_init_one, 473 .probe = i82875p_init_one,
@@ -487,31 +475,35 @@ static struct pci_driver i82875p_driver = {
487 .id_table = i82875p_pci_tbl, 475 .id_table = i82875p_pci_tbl,
488}; 476};
489 477
490
491static int __init i82875p_init(void) 478static int __init i82875p_init(void)
492{ 479{
493 int pci_rc; 480 int pci_rc;
494 481
495 debugf3("%s()\n", __func__); 482 debugf3("%s()\n", __func__);
496 pci_rc = pci_register_driver(&i82875p_driver); 483 pci_rc = pci_register_driver(&i82875p_driver);
484
497 if (pci_rc < 0) 485 if (pci_rc < 0)
498 goto fail0; 486 goto fail0;
487
499 if (mci_pdev == NULL) { 488 if (mci_pdev == NULL) {
500 mci_pdev = 489 mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
501 pci_get_device(PCI_VENDOR_ID_INTEL, 490 PCI_DEVICE_ID_INTEL_82875_0, NULL);
502 PCI_DEVICE_ID_INTEL_82875_0, NULL); 491
503 if (!mci_pdev) { 492 if (!mci_pdev) {
504 debugf0("875p pci_get_device fail\n"); 493 debugf0("875p pci_get_device fail\n");
505 pci_rc = -ENODEV; 494 pci_rc = -ENODEV;
506 goto fail1; 495 goto fail1;
507 } 496 }
497
508 pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl); 498 pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
499
509 if (pci_rc < 0) { 500 if (pci_rc < 0) {
510 debugf0("875p init fail\n"); 501 debugf0("875p init fail\n");
511 pci_rc = -ENODEV; 502 pci_rc = -ENODEV;
512 goto fail1; 503 goto fail1;
513 } 504 }
514 } 505 }
506
515 return 0; 507 return 0;
516 508
517fail1: 509fail1:
@@ -524,23 +516,21 @@ fail0:
524 return pci_rc; 516 return pci_rc;
525} 517}
526 518
527
528static void __exit i82875p_exit(void) 519static void __exit i82875p_exit(void)
529{ 520{
530 debugf3("%s()\n", __func__); 521 debugf3("%s()\n", __func__);
531 522
532 pci_unregister_driver(&i82875p_driver); 523 pci_unregister_driver(&i82875p_driver);
524
533 if (!i82875p_registered) { 525 if (!i82875p_registered) {
534 i82875p_remove_one(mci_pdev); 526 i82875p_remove_one(mci_pdev);
535 pci_dev_put(mci_pdev); 527 pci_dev_put(mci_pdev);
536 } 528 }
537} 529}
538 530
539
540module_init(i82875p_init); 531module_init(i82875p_init);
541module_exit(i82875p_exit); 532module_exit(i82875p_exit);
542 533
543
544MODULE_LICENSE("GPL"); 534MODULE_LICENSE("GPL");
545MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); 535MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
546MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers"); 536MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");