aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2010-10-15 13:25:38 -0400
committerBorislav Petkov <borislav.petkov@amd.com>2011-01-07 05:34:03 -0500
commit360b7f3c602ed80ce8c6b2585dcb76883a440c17 (patch)
tree1737a8de8539548fc7a6ba965798234ba62c5ee7 /drivers
parent2299ef7114000f8e403797b7f9a972f54bc05fad (diff)
amd64_edac: Remove two-stage initialization
Now that all prerequisites are in place, drop the two-stage driver instances initialization in favor of the following simple init sequence: 1. Probe PCI device: we only test ECC capabilities here and if none exit early. 2. If the hw supports ECC and it is/can be enabled, we init the per-node instance. Remove "amd64_" prefix from static functions touched, while at it. There actually should be no visible functional change resulting from this patch. Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/edac/amd64_edac.c168
1 files changed, 68 insertions, 100 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 4632081eaea6..f621aa8becee 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -15,9 +15,13 @@ module_param(ecc_enable_override, int, 0644);
15 15
16static struct msr __percpu *msrs; 16static struct msr __percpu *msrs;
17 17
18/*
19 * count successfully initialized driver instances for setup_pci_device()
20 */
21static atomic_t drv_instances = ATOMIC_INIT(0);
22
18/* Per-node driver instances */ 23/* Per-node driver instances */
19static struct mem_ctl_info **mcis; 24static struct mem_ctl_info **mcis;
20static struct amd64_pvt **pvts;
21static struct ecc_settings **ecc_stngs; 25static struct ecc_settings **ecc_stngs;
22 26
23/* 27/*
@@ -1993,8 +1997,7 @@ void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
1993 * Use pvt->F2 which contains the F2 CPU PCI device to get the related 1997 * Use pvt->F2 which contains the F2 CPU PCI device to get the related
1994 * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. 1998 * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error.
1995 */ 1999 */
1996static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, u16 f1_id, 2000static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id)
1997 u16 f3_id)
1998{ 2001{
1999 /* Reserve the ADDRESS MAP Device */ 2002 /* Reserve the ADDRESS MAP Device */
2000 pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2); 2003 pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2);
@@ -2024,7 +2027,7 @@ static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, u16 f1_id,
2024 return 0; 2027 return 0;
2025} 2028}
2026 2029
2027static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt) 2030static void free_mc_sibling_devs(struct amd64_pvt *pvt)
2028{ 2031{
2029 pci_dev_put(pvt->F1); 2032 pci_dev_put(pvt->F1);
2030 pci_dev_put(pvt->F3); 2033 pci_dev_put(pvt->F3);
@@ -2034,7 +2037,7 @@ static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt)
2034 * Retrieve the hardware registers of the memory controller (this includes the 2037 * Retrieve the hardware registers of the memory controller (this includes the
2035 * 'Address Map' and 'Misc' device regs) 2038 * 'Address Map' and 'Misc' device regs)
2036 */ 2039 */
2037static void amd64_read_mc_registers(struct amd64_pvt *pvt) 2040static void read_mc_regs(struct amd64_pvt *pvt)
2038{ 2041{
2039 u64 msr_val; 2042 u64 msr_val;
2040 u32 tmp; 2043 u32 tmp;
@@ -2185,7 +2188,7 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt)
2185 * Initialize the array of csrow attribute instances, based on the values 2188 * Initialize the array of csrow attribute instances, based on the values
2186 * from pci config hardware registers. 2189 * from pci config hardware registers.
2187 */ 2190 */
2188static int amd64_init_csrows(struct mem_ctl_info *mci) 2191static int init_csrows(struct mem_ctl_info *mci)
2189{ 2192{
2190 struct csrow_info *csrow; 2193 struct csrow_info *csrow;
2191 struct amd64_pvt *pvt = mci->pvt_info; 2194 struct amd64_pvt *pvt = mci->pvt_info;
@@ -2388,26 +2391,25 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid,
2388 return ret; 2391 return ret;
2389} 2392}
2390 2393
2391static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) 2394static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid,
2395 struct pci_dev *F3)
2392{ 2396{
2393 u8 nid = pvt->mc_node_id;
2394 struct ecc_settings *s = ecc_stngs[nid];
2395 u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; 2397 u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
2396 2398
2397 if (!s->nbctl_valid) 2399 if (!s->nbctl_valid)
2398 return; 2400 return;
2399 2401
2400 amd64_read_pci_cfg(pvt->F3, K8_NBCTL, &value); 2402 amd64_read_pci_cfg(F3, K8_NBCTL, &value);
2401 value &= ~mask; 2403 value &= ~mask;
2402 value |= s->old_nbctl; 2404 value |= s->old_nbctl;
2403 2405
2404 pci_write_config_dword(pvt->F3, K8_NBCTL, value); 2406 pci_write_config_dword(F3, K8_NBCTL, value);
2405 2407
2406 /* restore previous BIOS DRAM ECC "off" setting we force-enabled */ 2408 /* restore previous BIOS DRAM ECC "off" setting we force-enabled */
2407 if (!s->flags.nb_ecc_prev) { 2409 if (!s->flags.nb_ecc_prev) {
2408 amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &value); 2410 amd64_read_pci_cfg(F3, K8_NBCFG, &value);
2409 value &= ~K8_NBCFG_ECC_ENABLE; 2411 value &= ~K8_NBCFG_ECC_ENABLE;
2410 pci_write_config_dword(pvt->F3, K8_NBCFG, value); 2412 pci_write_config_dword(F3, K8_NBCFG, value);
2411 } 2413 }
2412 2414
2413 /* restore the NB Enable MCGCTL bit */ 2415 /* restore the NB Enable MCGCTL bit */
@@ -2457,7 +2459,7 @@ struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) +
2457 2459
2458struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; 2460struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } };
2459 2461
2460static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci) 2462static void set_mc_sysfs_attrs(struct mem_ctl_info *mci)
2461{ 2463{
2462 unsigned int i = 0, j = 0; 2464 unsigned int i = 0, j = 0;
2463 2465
@@ -2472,7 +2474,7 @@ static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci)
2472 mci->mc_driver_sysfs_attributes = sysfs_attrs; 2474 mci->mc_driver_sysfs_attributes = sysfs_attrs;
2473} 2475}
2474 2476
2475static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) 2477static void setup_mci_misc_attrs(struct mem_ctl_info *mci)
2476{ 2478{
2477 struct amd64_pvt *pvt = mci->pvt_info; 2479 struct amd64_pvt *pvt = mci->pvt_info;
2478 2480
@@ -2538,14 +2540,16 @@ static int amd64_init_one_instance(struct pci_dev *F2)
2538{ 2540{
2539 struct amd64_pvt *pvt = NULL; 2541 struct amd64_pvt *pvt = NULL;
2540 struct amd64_family_type *fam_type = NULL; 2542 struct amd64_family_type *fam_type = NULL;
2543 struct mem_ctl_info *mci = NULL;
2541 int err = 0, ret; 2544 int err = 0, ret;
2545 u8 nid = get_node_id(F2);
2542 2546
2543 ret = -ENOMEM; 2547 ret = -ENOMEM;
2544 pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); 2548 pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
2545 if (!pvt) 2549 if (!pvt)
2546 goto err_exit; 2550 goto err_ret;
2547 2551
2548 pvt->mc_node_id = get_node_id(F2); 2552 pvt->mc_node_id = nid;
2549 pvt->F2 = F2; 2553 pvt->F2 = F2;
2550 2554
2551 ret = -EINVAL; 2555 ret = -EINVAL;
@@ -2554,61 +2558,36 @@ static int amd64_init_one_instance(struct pci_dev *F2)
2554 goto err_free; 2558 goto err_free;
2555 2559
2556 ret = -ENODEV; 2560 ret = -ENODEV;
2557 err = amd64_reserve_mc_sibling_devices(pvt, fam_type->f1_id, 2561 err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f3_id);
2558 fam_type->f3_id);
2559 if (err) 2562 if (err)
2560 goto err_free; 2563 goto err_free;
2561 2564
2562 /* 2565 read_mc_regs(pvt);
2563 * Save the pointer to the private data for use in 2nd initialization
2564 * stage
2565 */
2566 pvts[pvt->mc_node_id] = pvt;
2567
2568 return 0;
2569
2570err_free:
2571 kfree(pvt);
2572
2573err_exit:
2574 return ret;
2575}
2576
2577/*
2578 * This is the finishing stage of the init code. Needs to be performed after all
2579 * MCs' hardware have been prepped for accessing extended config space.
2580 */
2581static int amd64_init_2nd_stage(struct amd64_pvt *pvt)
2582{
2583 int node_id = pvt->mc_node_id;
2584 struct mem_ctl_info *mci;
2585 int ret = -ENODEV;
2586
2587 amd64_read_mc_registers(pvt);
2588 2566
2589 /* 2567 /*
2590 * We need to determine how many memory channels there are. Then use 2568 * We need to determine how many memory channels there are. Then use
2591 * that information for calculating the size of the dynamic instance 2569 * that information for calculating the size of the dynamic instance
2592 * tables in the 'mci' structure 2570 * tables in the 'mci' structure.
2593 */ 2571 */
2572 ret = -EINVAL;
2594 pvt->channel_count = pvt->ops->early_channel_count(pvt); 2573 pvt->channel_count = pvt->ops->early_channel_count(pvt);
2595 if (pvt->channel_count < 0) 2574 if (pvt->channel_count < 0)
2596 goto err_exit; 2575 goto err_siblings;
2597 2576
2598 ret = -ENOMEM; 2577 ret = -ENOMEM;
2599 mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id); 2578 mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, nid);
2600 if (!mci) 2579 if (!mci)
2601 goto err_exit; 2580 goto err_siblings;
2602 2581
2603 mci->pvt_info = pvt; 2582 mci->pvt_info = pvt;
2604
2605 mci->dev = &pvt->F2->dev; 2583 mci->dev = &pvt->F2->dev;
2606 amd64_setup_mci_misc_attributes(mci);
2607 2584
2608 if (amd64_init_csrows(mci)) 2585 setup_mci_misc_attrs(mci);
2586
2587 if (init_csrows(mci))
2609 mci->edac_cap = EDAC_FLAG_NONE; 2588 mci->edac_cap = EDAC_FLAG_NONE;
2610 2589
2611 amd64_set_mc_sysfs_attributes(mci); 2590 set_mc_sysfs_attrs(mci);
2612 2591
2613 ret = -ENODEV; 2592 ret = -ENODEV;
2614 if (edac_mc_add_mc(mci)) { 2593 if (edac_mc_add_mc(mci)) {
@@ -2616,34 +2595,31 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt)
2616 goto err_add_mc; 2595 goto err_add_mc;
2617 } 2596 }
2618 2597
2619 mcis[node_id] = mci;
2620 pvts[node_id] = NULL;
2621
2622 /* register stuff with EDAC MCE */ 2598 /* register stuff with EDAC MCE */
2623 if (report_gart_errors) 2599 if (report_gart_errors)
2624 amd_report_gart_errors(true); 2600 amd_report_gart_errors(true);
2625 2601
2626 amd_register_ecc_decoder(amd64_decode_bus_error); 2602 amd_register_ecc_decoder(amd64_decode_bus_error);
2627 2603
2604 mcis[nid] = mci;
2605
2606 atomic_inc(&drv_instances);
2607
2628 return 0; 2608 return 0;
2629 2609
2630err_add_mc: 2610err_add_mc:
2631 edac_mc_free(mci); 2611 edac_mc_free(mci);
2632 2612
2633err_exit: 2613err_siblings:
2634 debugf0("failure to init 2nd stage: ret=%d\n", ret); 2614 free_mc_sibling_devs(pvt);
2635 2615
2636 amd64_restore_ecc_error_reporting(pvt); 2616err_free:
2637 2617 kfree(pvt);
2638 amd64_free_mc_sibling_devices(pvt);
2639
2640 kfree(pvts[pvt->mc_node_id]);
2641 pvts[node_id] = NULL;
2642 2618
2619err_ret:
2643 return ret; 2620 return ret;
2644} 2621}
2645 2622
2646
2647static int __devinit amd64_probe_one_instance(struct pci_dev *pdev, 2623static int __devinit amd64_probe_one_instance(struct pci_dev *pdev,
2648 const struct pci_device_id *mc_type) 2624 const struct pci_device_id *mc_type)
2649{ 2625{
@@ -2678,8 +2654,10 @@ static int __devinit amd64_probe_one_instance(struct pci_dev *pdev,
2678 } 2654 }
2679 2655
2680 ret = amd64_init_one_instance(pdev); 2656 ret = amd64_init_one_instance(pdev);
2681 if (ret < 0) 2657 if (ret < 0) {
2682 amd64_err("Error probing instance: %d\n", nid); 2658 amd64_err("Error probing instance: %d\n", nid);
2659 restore_ecc_error_reporting(s, nid, F3);
2660 }
2683 2661
2684 return ret; 2662 return ret;
2685 2663
@@ -2695,6 +2673,9 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)
2695{ 2673{
2696 struct mem_ctl_info *mci; 2674 struct mem_ctl_info *mci;
2697 struct amd64_pvt *pvt; 2675 struct amd64_pvt *pvt;
2676 u8 nid = get_node_id(pdev);
2677 struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
2678 struct ecc_settings *s = ecc_stngs[nid];
2698 2679
2699 /* Remove from EDAC CORE tracking list */ 2680 /* Remove from EDAC CORE tracking list */
2700 mci = edac_mc_del_mc(&pdev->dev); 2681 mci = edac_mc_del_mc(&pdev->dev);
@@ -2703,20 +2684,20 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)
2703 2684
2704 pvt = mci->pvt_info; 2685 pvt = mci->pvt_info;
2705 2686
2706 amd64_restore_ecc_error_reporting(pvt); 2687 restore_ecc_error_reporting(s, nid, F3);
2707 2688
2708 amd64_free_mc_sibling_devices(pvt); 2689 free_mc_sibling_devs(pvt);
2709 2690
2710 /* unregister from EDAC MCE */ 2691 /* unregister from EDAC MCE */
2711 amd_report_gart_errors(false); 2692 amd_report_gart_errors(false);
2712 amd_unregister_ecc_decoder(amd64_decode_bus_error); 2693 amd_unregister_ecc_decoder(amd64_decode_bus_error);
2713 2694
2714 kfree(ecc_stngs[pvt->mc_node_id]); 2695 kfree(ecc_stngs[nid]);
2715 ecc_stngs[pvt->mc_node_id] = NULL; 2696 ecc_stngs[nid] = NULL;
2716 2697
2717 /* Free the EDAC CORE resources */ 2698 /* Free the EDAC CORE resources */
2718 mci->pvt_info = NULL; 2699 mci->pvt_info = NULL;
2719 mcis[pvt->mc_node_id] = NULL; 2700 mcis[nid] = NULL;
2720 2701
2721 kfree(pvt); 2702 kfree(pvt);
2722 edac_mc_free(mci); 2703 edac_mc_free(mci);
@@ -2755,7 +2736,7 @@ static struct pci_driver amd64_pci_driver = {
2755 .id_table = amd64_pci_table, 2736 .id_table = amd64_pci_table,
2756}; 2737};
2757 2738
2758static void amd64_setup_pci_device(void) 2739static void setup_pci_device(void)
2759{ 2740{
2760 struct mem_ctl_info *mci; 2741 struct mem_ctl_info *mci;
2761 struct amd64_pvt *pvt; 2742 struct amd64_pvt *pvt;
@@ -2782,8 +2763,7 @@ static void amd64_setup_pci_device(void)
2782 2763
2783static int __init amd64_edac_init(void) 2764static int __init amd64_edac_init(void)
2784{ 2765{
2785 int nb, err = -ENODEV; 2766 int err = -ENODEV;
2786 bool load_ok = false;
2787 2767
2788 edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); 2768 edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");
2789 2769
@@ -2793,49 +2773,40 @@ static int __init amd64_edac_init(void)
2793 goto err_ret; 2773 goto err_ret;
2794 2774
2795 err = -ENOMEM; 2775 err = -ENOMEM;
2796 pvts = kzalloc(amd_nb_num() * sizeof(pvts[0]), GFP_KERNEL);
2797 mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL); 2776 mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
2798 ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL); 2777 ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
2799 if (!(pvts && mcis && ecc_stngs)) 2778 if (!(mcis && ecc_stngs))
2800 goto err_ret; 2779 goto err_ret;
2801 2780
2802 msrs = msrs_alloc(); 2781 msrs = msrs_alloc();
2803 if (!msrs) 2782 if (!msrs)
2804 goto err_ret; 2783 goto err_free;
2805 2784
2806 err = pci_register_driver(&amd64_pci_driver); 2785 err = pci_register_driver(&amd64_pci_driver);
2807 if (err) 2786 if (err)
2808 goto err_pci; 2787 goto err_pci;
2809 2788
2810 /*
2811 * At this point, the array 'pvts[]' contains pointers to alloc'd
2812 * amd64_pvt structs. These will be used in the 2nd stage init function
2813 * to finish initialization of the MC instances.
2814 */
2815 err = -ENODEV; 2789 err = -ENODEV;
2816 for (nb = 0; nb < amd_nb_num(); nb++) { 2790 if (!atomic_read(&drv_instances))
2817 if (!pvts[nb]) 2791 goto err_no_instances;
2818 continue;
2819
2820 err = amd64_init_2nd_stage(pvts[nb]);
2821 if (err)
2822 goto err_2nd_stage;
2823
2824 load_ok = true;
2825 }
2826 2792
2827 if (load_ok) { 2793 setup_pci_device();
2828 amd64_setup_pci_device(); 2794 return 0;
2829 return 0;
2830 }
2831 2795
2832err_2nd_stage: 2796err_no_instances:
2833 pci_unregister_driver(&amd64_pci_driver); 2797 pci_unregister_driver(&amd64_pci_driver);
2834 2798
2835err_pci: 2799err_pci:
2836 msrs_free(msrs); 2800 msrs_free(msrs);
2837 msrs = NULL; 2801 msrs = NULL;
2838 2802
2803err_free:
2804 kfree(mcis);
2805 mcis = NULL;
2806
2807 kfree(ecc_stngs);
2808 ecc_stngs = NULL;
2809
2839err_ret: 2810err_ret:
2840 return err; 2811 return err;
2841} 2812}
@@ -2853,9 +2824,6 @@ static void __exit amd64_edac_exit(void)
2853 kfree(mcis); 2824 kfree(mcis);
2854 mcis = NULL; 2825 mcis = NULL;
2855 2826
2856 kfree(pvts);
2857 pvts = NULL;
2858
2859 msrs_free(msrs); 2827 msrs_free(msrs);
2860 msrs = NULL; 2828 msrs = NULL;
2861} 2829}