aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorDoug Thompson <dougthompson@xmission.com>2009-04-27 13:41:25 -0400
committerBorislav Petkov <borislav.petkov@amd.com>2009-06-10 06:19:00 -0400
commit0ec449ee95b20245fef4aa9fa2486456f1540514 (patch)
treed4a7951fccc5a45cb7c0c82edb05ef9e9107bfbd /drivers/edac
parentd27bf6fa369ca0272df10558d2f290d6fc72e675 (diff)
amd64_edac: add EDAC core-related initializers
Borislav: - add a amd64_free_mc_sibling_devices() helper instead of opencoding the release-path. - fix/cleanup comments - fix function return value patterns - cleanup debug calls Reviewed-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Doug Thompson <dougthompson@xmission.com> Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/amd64_edac.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 09991c8a6ee3..5a6e714b115e 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2455,4 +2455,319 @@ int amd64_process_error_info(struct mem_ctl_info *mci,
2455} 2455}
2456EXPORT_SYMBOL_GPL(amd64_process_error_info); 2456EXPORT_SYMBOL_GPL(amd64_process_error_info);
2457 2457
2458/*
2459 * The main polling 'check' function, called FROM the edac core to perform the
2460 * error checking and if an error is encountered, error processing.
2461 */
2462static void amd64_check(struct mem_ctl_info *mci)
2463{
2464 struct amd64_error_info_regs info;
2465
2466 if (amd64_get_error_info(mci, &info))
2467 amd64_process_error_info(mci, &info, 1);
2468}
2469
2470/*
2471 * Input:
2472 * 1) struct amd64_pvt which contains pvt->dram_f2_ctl pointer
2473 * 2) AMD Family index value
2474 *
2475 * Ouput:
2476 * Upon return of 0, the following filled in:
2477 *
2478 * struct pvt->addr_f1_ctl
2479 * struct pvt->misc_f3_ctl
2480 *
2481 * Filled in with related device funcitions of 'dram_f2_ctl'
2482 * These devices are "reserved" via the pci_get_device()
2483 *
2484 * Upon return of 1 (error status):
2485 *
2486 * Nothing reserved
2487 */
2488static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, int mc_idx)
2489{
2490 const struct amd64_family_type *amd64_dev = &amd64_family_types[mc_idx];
2491
2492 /* Reserve the ADDRESS MAP Device */
2493 pvt->addr_f1_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor,
2494 amd64_dev->addr_f1_ctl,
2495 pvt->dram_f2_ctl);
2496
2497 if (!pvt->addr_f1_ctl) {
2498 amd64_printk(KERN_ERR, "error address map device not found: "
2499 "vendor %x device 0x%x (broken BIOS?)\n",
2500 PCI_VENDOR_ID_AMD, amd64_dev->addr_f1_ctl);
2501 return 1;
2502 }
2503
2504 /* Reserve the MISC Device */
2505 pvt->misc_f3_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor,
2506 amd64_dev->misc_f3_ctl,
2507 pvt->dram_f2_ctl);
2508
2509 if (!pvt->misc_f3_ctl) {
2510 pci_dev_put(pvt->addr_f1_ctl);
2511 pvt->addr_f1_ctl = NULL;
2512
2513 amd64_printk(KERN_ERR, "error miscellaneous device not found: "
2514 "vendor %x device 0x%x (broken BIOS?)\n",
2515 PCI_VENDOR_ID_AMD, amd64_dev->misc_f3_ctl);
2516 return 1;
2517 }
2518
2519 debugf1(" Addr Map device PCI Bus ID:\t%s\n",
2520 pci_name(pvt->addr_f1_ctl));
2521 debugf1(" DRAM MEM-CTL PCI Bus ID:\t%s\n",
2522 pci_name(pvt->dram_f2_ctl));
2523 debugf1(" Misc device PCI Bus ID:\t%s\n",
2524 pci_name(pvt->misc_f3_ctl));
2525
2526 return 0;
2527}
2528
2529static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt)
2530{
2531 pci_dev_put(pvt->addr_f1_ctl);
2532 pci_dev_put(pvt->misc_f3_ctl);
2533}
2534
2535/*
2536 * Retrieve the hardware registers of the memory controller (this includes the
2537 * 'Address Map' and 'Misc' device regs)
2538 */
2539static void amd64_read_mc_registers(struct amd64_pvt *pvt)
2540{
2541 u64 msr_val;
2542 int dram, err = 0;
2543
2544 /*
2545 * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since
2546 * those are Read-As-Zero
2547 */
2548 rdmsrl(MSR_K8_TOP_MEM1, msr_val);
2549 pvt->top_mem = msr_val >> 23;
2550 debugf0(" TOP_MEM=0x%08llx\n", pvt->top_mem);
2551
2552 /* check first whether TOP_MEM2 is enabled */
2553 rdmsrl(MSR_K8_SYSCFG, msr_val);
2554 if (msr_val & (1U << 21)) {
2555 rdmsrl(MSR_K8_TOP_MEM2, msr_val);
2556 pvt->top_mem2 = msr_val >> 23;
2557 debugf0(" TOP_MEM2=0x%08llx\n", pvt->top_mem2);
2558 } else
2559 debugf0(" TOP_MEM2 disabled.\n");
2560
2561 amd64_cpu_display_info(pvt);
2562
2563 err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap);
2564 if (err)
2565 goto err_reg;
2566
2567 if (pvt->ops->read_dram_ctl_register)
2568 pvt->ops->read_dram_ctl_register(pvt);
2569
2570 for (dram = 0; dram < DRAM_REG_COUNT; dram++) {
2571 /*
2572 * Call CPU specific READ function to get the DRAM Base and
2573 * Limit values from the DCT.
2574 */
2575 pvt->ops->read_dram_base_limit(pvt, dram);
2576
2577 /*
2578 * Only print out debug info on rows with both R and W Enabled.
2579 * Normal processing, compiler should optimize this whole 'if'
2580 * debug output block away.
2581 */
2582 if (pvt->dram_rw_en[dram] != 0) {
2583 debugf1(" DRAM_BASE[%d]: 0x%8.08x-%8.08x "
2584 "DRAM_LIMIT: 0x%8.08x-%8.08x\n",
2585 dram,
2586 (u32)(pvt->dram_base[dram] >> 32),
2587 (u32)(pvt->dram_base[dram] & 0xFFFFFFFF),
2588 (u32)(pvt->dram_limit[dram] >> 32),
2589 (u32)(pvt->dram_limit[dram] & 0xFFFFFFFF));
2590 debugf1(" IntlvEn=%s %s %s "
2591 "IntlvSel=%d DstNode=%d\n",
2592 pvt->dram_IntlvEn[dram] ?
2593 "Enabled" : "Disabled",
2594 (pvt->dram_rw_en[dram] & 0x2) ? "W" : "!W",
2595 (pvt->dram_rw_en[dram] & 0x1) ? "R" : "!R",
2596 pvt->dram_IntlvSel[dram],
2597 pvt->dram_DstNode[dram]);
2598 }
2599 }
2600
2601 amd64_read_dct_base_mask(pvt);
2602
2603 err = pci_read_config_dword(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar);
2604 if (err)
2605 goto err_reg;
2606
2607 amd64_read_dbam_reg(pvt);
2608
2609 err = pci_read_config_dword(pvt->misc_f3_ctl,
2610 F10_ONLINE_SPARE, &pvt->online_spare);
2611 if (err)
2612 goto err_reg;
2613
2614 err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0);
2615 if (err)
2616 goto err_reg;
2617
2618 err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0);
2619 if (err)
2620 goto err_reg;
2621
2622 if (!dct_ganging_enabled(pvt)) {
2623 err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1,
2624 &pvt->dclr1);
2625 if (err)
2626 goto err_reg;
2627
2628 err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_1,
2629 &pvt->dchr1);
2630 if (err)
2631 goto err_reg;
2632 }
2633
2634 amd64_dump_misc_regs(pvt);
2635
2636err_reg:
2637 debugf0("Reading an MC register failed\n");
2638
2639}
2640
2641/*
2642 * NOTE: CPU Revision Dependent code
2643 *
2644 * Input:
2645 * @csrow_nr ChipSelect Row Number (0..CHIPSELECT_COUNT-1)
2646 * k8 private pointer to -->
2647 * DRAM Bank Address mapping register
2648 * node_id
2649 * DCL register where dual_channel_active is
2650 *
2651 * The DBAM register consists of 4 sets of 4 bits each definitions:
2652 *
2653 * Bits: CSROWs
2654 * 0-3 CSROWs 0 and 1
2655 * 4-7 CSROWs 2 and 3
2656 * 8-11 CSROWs 4 and 5
2657 * 12-15 CSROWs 6 and 7
2658 *
2659 * Values range from: 0 to 15
2660 * The meaning of the values depends on CPU revision and dual-channel state,
2661 * see relevant BKDG more info.
2662 *
2663 * The memory controller provides for total of only 8 CSROWs in its current
2664 * architecture. Each "pair" of CSROWs normally represents just one DIMM in
2665 * single channel or two (2) DIMMs in dual channel mode.
2666 *
2667 * The following code logic collapses the various tables for CSROW based on CPU
2668 * revision.
2669 *
2670 * Returns:
2671 * The number of PAGE_SIZE pages on the specified CSROW number it
2672 * encompasses
2673 *
2674 */
2675static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt)
2676{
2677 u32 dram_map, nr_pages;
2678
2679 /*
2680 * The math on this doesn't look right on the surface because x/2*4 can
2681 * be simplified to x*2 but this expression makes use of the fact that
2682 * it is integral math where 1/2=0. This intermediate value becomes the
2683 * number of bits to shift the DBAM register to extract the proper CSROW
2684 * field.
2685 */
2686 dram_map = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF;
2687
2688 nr_pages = pvt->ops->dbam_map_to_pages(pvt, dram_map);
2689
2690 /*
2691 * If dual channel then double the memory size of single channel.
2692 * Channel count is 1 or 2
2693 */
2694 nr_pages <<= (pvt->channel_count - 1);
2695
2696 debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, dram_map);
2697 debugf0(" nr_pages= %u channel-count = %d\n",
2698 nr_pages, pvt->channel_count);
2699
2700 return nr_pages;
2701}
2702
2703/*
2704 * Initialize the array of csrow attribute instances, based on the values
2705 * from pci config hardware registers.
2706 */
2707static int amd64_init_csrows(struct mem_ctl_info *mci)
2708{
2709 struct csrow_info *csrow;
2710 struct amd64_pvt *pvt;
2711 u64 input_addr_min, input_addr_max, sys_addr;
2712 int i, err = 0, empty = 1;
2713
2714 pvt = mci->pvt_info;
2715
2716 err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg);
2717 if (err)
2718 debugf0("Reading K8_NBCFG failed\n");
2719
2720 debugf0("NBCFG= 0x%x CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg,
2721 (pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled",
2722 (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"
2723 );
2724
2725 for (i = 0; i < CHIPSELECT_COUNT; i++) {
2726 csrow = &mci->csrows[i];
2727
2728 if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) {
2729 debugf1("----CSROW %d EMPTY for node %d\n", i,
2730 pvt->mc_node_id);
2731 continue;
2732 }
2733
2734 debugf1("----CSROW %d VALID for MC node %d\n",
2735 i, pvt->mc_node_id);
2736
2737 empty = 0;
2738 csrow->nr_pages = amd64_csrow_nr_pages(i, pvt);
2739 find_csrow_limits(mci, i, &input_addr_min, &input_addr_max);
2740 sys_addr = input_addr_to_sys_addr(mci, input_addr_min);
2741 csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT);
2742 sys_addr = input_addr_to_sys_addr(mci, input_addr_max);
2743 csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT);
2744 csrow->page_mask = ~mask_from_dct_mask(pvt, i);
2745 /* 8 bytes of resolution */
2746
2747 csrow->mtype = amd64_determine_memory_type(pvt);
2748
2749 debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i);
2750 debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n",
2751 (unsigned long)input_addr_min,
2752 (unsigned long)input_addr_max);
2753 debugf1(" sys_addr: 0x%lx page_mask: 0x%lx\n",
2754 (unsigned long)sys_addr, csrow->page_mask);
2755 debugf1(" nr_pages: %u first_page: 0x%lx "
2756 "last_page: 0x%lx\n",
2757 (unsigned)csrow->nr_pages,
2758 csrow->first_page, csrow->last_page);
2759
2760 /*
2761 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
2762 */
2763 if (pvt->nbcfg & K8_NBCFG_ECC_ENABLE)
2764 csrow->edac_mode =
2765 (pvt->nbcfg & K8_NBCFG_CHIPKILL) ?
2766 EDAC_S4ECD4ED : EDAC_SECDED;
2767 else
2768 csrow->edac_mode = EDAC_NONE;
2769 }
2770
2771 return empty;
2772}
2458 2773