aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/e7xxx_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/e7xxx_edac.c')
-rw-r--r--drivers/edac/e7xxx_edac.c158
1 files changed, 82 insertions, 76 deletions
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c
index 1e282c843e77..9878379b4993 100644
--- a/drivers/edac/e7xxx_edac.c
+++ b/drivers/edac/e7xxx_edac.c
@@ -335,99 +335,61 @@ static void e7xxx_check(struct mem_ctl_info *mci)
335 e7xxx_process_error_info(mci, &info, 1); 335 e7xxx_process_error_info(mci, &info, 1);
336} 336}
337 337
338static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) 338/* Return 1 if dual channel mode is active. Else return 0. */
339static inline int dual_channel_active(u32 drc, int dev_idx)
339{ 340{
340 int rc = -ENODEV; 341 return (dev_idx == E7501) ? ((drc >> 22) & 0x1) : 1;
341 int index; 342}
342 u16 pci_data;
343 struct mem_ctl_info *mci = NULL;
344 struct e7xxx_pvt *pvt = NULL;
345 u32 drc;
346 int drc_chan = 1; /* Number of channels 0=1chan,1=2chan */
347 int drc_drbg = 1; /* DRB granularity 0=32mb,1=64mb */
348 int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
349 u32 dra;
350 unsigned long last_cumul_size;
351 struct e7xxx_error_info discard;
352
353 debugf0("%s(): mci\n", __func__);
354 343
355 /* need to find out the number of channels */
356 pci_read_config_dword(pdev, E7XXX_DRC, &drc);
357 344
345/* Return DRB granularity (0=32mb, 1=64mb). */
346static inline int drb_granularity(u32 drc, int dev_idx)
347{
358 /* only e7501 can be single channel */ 348 /* only e7501 can be single channel */
359 if (dev_idx == E7501) { 349 return (dev_idx == E7501) ? ((drc >> 18) & 0x3) : 1;
360 drc_chan = ((drc >> 22) & 0x1); 350}
361 drc_drbg = (drc >> 18) & 0x3;
362 }
363
364 drc_ddim = (drc >> 20) & 0x3;
365 mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
366
367 if (mci == NULL) {
368 rc = -ENOMEM;
369 goto fail;
370 }
371
372 debugf3("%s(): init mci\n", __func__);
373 mci->mtype_cap = MEM_FLAG_RDDR;
374 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
375 EDAC_FLAG_S4ECD4ED;
376 /* FIXME - what if different memory types are in different csrows? */
377 mci->mod_name = EDAC_MOD_STR;
378 mci->mod_ver = E7XXX_REVISION;
379 mci->dev = &pdev->dev;
380
381 debugf3("%s(): init pvt\n", __func__);
382 pvt = (struct e7xxx_pvt *) mci->pvt_info;
383 pvt->dev_info = &e7xxx_devs[dev_idx];
384 pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
385 pvt->dev_info->err_dev,
386 pvt->bridge_ck);
387 351
388 if (!pvt->bridge_ck) {
389 e7xxx_printk(KERN_ERR, "error reporting device not found:"
390 "vendor %x device 0x%x (broken BIOS?)\n",
391 PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
392 goto fail;
393 }
394 352
395 debugf3("%s(): more mci init\n", __func__); 353static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
396 mci->ctl_name = pvt->dev_info->ctl_name; 354 int dev_idx, u32 drc)
397 mci->edac_check = e7xxx_check; 355{
398 mci->ctl_page_to_phys = ctl_page_to_phys; 356 unsigned long last_cumul_size;
357 int index;
358 u8 value;
359 u32 dra, cumul_size;
360 int drc_chan, drc_drbg, drc_ddim, mem_dev;
361 struct csrow_info *csrow;
399 362
400 /* find out the device types */
401 pci_read_config_dword(pdev, E7XXX_DRA, &dra); 363 pci_read_config_dword(pdev, E7XXX_DRA, &dra);
364 drc_chan = dual_channel_active(drc, dev_idx);
365 drc_drbg = drb_granularity(drc, dev_idx);
366 drc_ddim = (drc >> 20) & 0x3;
367 last_cumul_size = 0;
402 368
403 /* 369 /* The dram row boundary (DRB) reg values are boundary address
404 * The dram row boundary (DRB) reg values are boundary address
405 * for each DRAM row with a granularity of 32 or 64MB (single/dual 370 * for each DRAM row with a granularity of 32 or 64MB (single/dual
406 * channel operation). DRB regs are cumulative; therefore DRB7 will 371 * channel operation). DRB regs are cumulative; therefore DRB7 will
407 * contain the total memory contained in all eight rows. 372 * contain the total memory contained in all eight rows.
408 */ 373 */
409 for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { 374 for (index = 0; index < mci->nr_csrows; index++) {
410 u8 value;
411 u32 cumul_size;
412 /* mem_dev 0=x8, 1=x4 */ 375 /* mem_dev 0=x8, 1=x4 */
413 int mem_dev = (dra >> (index * 4 + 3)) & 0x1; 376 mem_dev = (dra >> (index * 4 + 3)) & 0x1;
414 struct csrow_info *csrow = &mci->csrows[index]; 377 csrow = &mci->csrows[index];
415 378
416 pci_read_config_byte(pdev, E7XXX_DRB + index, &value); 379 pci_read_config_byte(pdev, E7XXX_DRB + index, &value);
417 /* convert a 64 or 32 MiB DRB to a page size. */ 380 /* convert a 64 or 32 MiB DRB to a page size. */
418 cumul_size = value << (25 + drc_drbg - PAGE_SHIFT); 381 cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
419 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index, 382 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
420 cumul_size); 383 cumul_size);
421
422 if (cumul_size == last_cumul_size) 384 if (cumul_size == last_cumul_size)
423 continue; /* not populated */ 385 continue; /* not populated */
424 386
425 csrow->first_page = last_cumul_size; 387 csrow->first_page = last_cumul_size;
426 csrow->last_page = cumul_size - 1; 388 csrow->last_page = cumul_size - 1;
427 csrow->nr_pages = cumul_size - last_cumul_size; 389 csrow->nr_pages = cumul_size - last_cumul_size;
428 last_cumul_size = cumul_size; 390 last_cumul_size = cumul_size;
429 csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */ 391 csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
430 csrow->mtype = MEM_RDDR; /* only one type supported */ 392 csrow->mtype = MEM_RDDR; /* only one type supported */
431 csrow->dtype = mem_dev ? DEV_X4 : DEV_X8; 393 csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
432 394
433 /* 395 /*
@@ -445,9 +407,54 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
445 } else 407 } else
446 csrow->edac_mode = EDAC_NONE; 408 csrow->edac_mode = EDAC_NONE;
447 } 409 }
410}
448 411
449 mci->edac_cap |= EDAC_FLAG_NONE; 412static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
413{
414 u16 pci_data;
415 struct mem_ctl_info *mci = NULL;
416 struct e7xxx_pvt *pvt = NULL;
417 u32 drc;
418 int drc_chan;
419 struct e7xxx_error_info discard;
420
421 debugf0("%s(): mci\n", __func__);
422 pci_read_config_dword(pdev, E7XXX_DRC, &drc);
423
424 drc_chan = dual_channel_active(drc, dev_idx);
425 mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
426
427 if (mci == NULL)
428 return -ENOMEM;
450 429
430 debugf3("%s(): init mci\n", __func__);
431 mci->mtype_cap = MEM_FLAG_RDDR;
432 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
433 EDAC_FLAG_S4ECD4ED;
434 /* FIXME - what if different memory types are in different csrows? */
435 mci->mod_name = EDAC_MOD_STR;
436 mci->mod_ver = E7XXX_REVISION;
437 mci->dev = &pdev->dev;
438 debugf3("%s(): init pvt\n", __func__);
439 pvt = (struct e7xxx_pvt *) mci->pvt_info;
440 pvt->dev_info = &e7xxx_devs[dev_idx];
441 pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
442 pvt->dev_info->err_dev,
443 pvt->bridge_ck);
444
445 if (!pvt->bridge_ck) {
446 e7xxx_printk(KERN_ERR, "error reporting device not found:"
447 "vendor %x device 0x%x (broken BIOS?)\n",
448 PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
449 goto fail0;
450 }
451
452 debugf3("%s(): more mci init\n", __func__);
453 mci->ctl_name = pvt->dev_info->ctl_name;
454 mci->edac_check = e7xxx_check;
455 mci->ctl_page_to_phys = ctl_page_to_phys;
456 e7xxx_init_csrows(mci, pdev, dev_idx, drc);
457 mci->edac_cap |= EDAC_FLAG_NONE;
451 debugf3("%s(): tolm, remapbase, remaplimit\n", __func__); 458 debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
452 /* load the top of low memory, remap base, and remap limit vars */ 459 /* load the top of low memory, remap base, and remap limit vars */
453 pci_read_config_word(pdev, E7XXX_TOLM, &pci_data); 460 pci_read_config_word(pdev, E7XXX_TOLM, &pci_data);
@@ -468,21 +475,20 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
468 */ 475 */
469 if (edac_mc_add_mc(mci,0)) { 476 if (edac_mc_add_mc(mci,0)) {
470 debugf3("%s(): failed edac_mc_add_mc()\n", __func__); 477 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
471 goto fail; 478 goto fail1;
472 } 479 }
473 480
474 /* get this far and it's successful */ 481 /* get this far and it's successful */
475 debugf3("%s(): success\n", __func__); 482 debugf3("%s(): success\n", __func__);
476 return 0; 483 return 0;
477 484
478fail: 485fail1:
479 if (mci != NULL) { 486 pci_dev_put(pvt->bridge_ck);
480 if(pvt != NULL && pvt->bridge_ck) 487
481 pci_dev_put(pvt->bridge_ck); 488fail0:
482 edac_mc_free(mci); 489 edac_mc_free(mci);
483 }
484 490
485 return rc; 491 return -ENODEV;
486} 492}
487 493
488/* returns count (>= 0), or negative on error */ 494/* returns count (>= 0), or negative on error */