diff options
| -rw-r--r-- | drivers/edac/amd64_edac.c | 315 |
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 | } |
| 2456 | EXPORT_SYMBOL_GPL(amd64_process_error_info); | 2456 | EXPORT_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 | */ | ||
| 2462 | static 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 | */ | ||
| 2488 | static 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 | |||
| 2529 | static 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 | */ | ||
| 2539 | static 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 | |||
| 2636 | err_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 | */ | ||
| 2675 | static 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 | */ | ||
| 2707 | static 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 | ||
