aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/amd64_edac.c59
-rw-r--r--drivers/edac/amd64_edac.h14
2 files changed, 49 insertions, 24 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 9efa88a9fdf5..9bc0299e8c74 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -18,6 +18,7 @@ static struct msr __percpu *msrs;
18/* Per-node driver instances */ 18/* Per-node driver instances */
19static struct mem_ctl_info **mcis; 19static struct mem_ctl_info **mcis;
20static struct amd64_pvt **pvts; 20static struct amd64_pvt **pvts;
21static struct ecc_settings **ecc_stngs;
21 22
22/* 23/*
23 * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and 24 * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and
@@ -2293,7 +2294,7 @@ out:
2293 return ret; 2294 return ret;
2294} 2295}
2295 2296
2296static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) 2297static int amd64_toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on)
2297{ 2298{
2298 cpumask_var_t cmask; 2299 cpumask_var_t cmask;
2299 int cpu; 2300 int cpu;
@@ -2303,7 +2304,7 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
2303 return false; 2304 return false;
2304 } 2305 }
2305 2306
2306 get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); 2307 get_cpus_on_this_dct_cpumask(cmask, nid);
2307 2308
2308 rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); 2309 rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
2309 2310
@@ -2313,14 +2314,14 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
2313 2314
2314 if (on) { 2315 if (on) {
2315 if (reg->l & K8_MSR_MCGCTL_NBE) 2316 if (reg->l & K8_MSR_MCGCTL_NBE)
2316 pvt->flags.nb_mce_enable = 1; 2317 s->flags.nb_mce_enable = 1;
2317 2318
2318 reg->l |= K8_MSR_MCGCTL_NBE; 2319 reg->l |= K8_MSR_MCGCTL_NBE;
2319 } else { 2320 } else {
2320 /* 2321 /*
2321 * Turn off NB MCE reporting only when it was off before 2322 * Turn off NB MCE reporting only when it was off before
2322 */ 2323 */
2323 if (!pvt->flags.nb_mce_enable) 2324 if (!s->flags.nb_mce_enable)
2324 reg->l &= ~K8_MSR_MCGCTL_NBE; 2325 reg->l &= ~K8_MSR_MCGCTL_NBE;
2325 } 2326 }
2326 } 2327 }
@@ -2334,18 +2335,20 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on)
2334static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) 2335static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
2335{ 2336{
2336 struct amd64_pvt *pvt = mci->pvt_info; 2337 struct amd64_pvt *pvt = mci->pvt_info;
2338 u8 nid = pvt->mc_node_id;
2339 struct ecc_settings *s = ecc_stngs[nid];
2337 u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; 2340 u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
2338 2341
2339 amd64_read_pci_cfg(pvt->F3, K8_NBCTL, &value); 2342 amd64_read_pci_cfg(pvt->F3, K8_NBCTL, &value);
2340 2343
2341 /* turn on UECCn and CECCEn bits */ 2344 /* turn on UECCEn and CECCEn bits */
2342 pvt->old_nbctl = value & mask; 2345 s->old_nbctl = value & mask;
2343 pvt->nbctl_mcgctl_saved = 1; 2346 s->nbctl_valid = true;
2344 2347
2345 value |= mask; 2348 value |= mask;
2346 pci_write_config_dword(pvt->F3, K8_NBCTL, value); 2349 pci_write_config_dword(pvt->F3, K8_NBCTL, value);
2347 2350
2348 if (amd64_toggle_ecc_err_reporting(pvt, ON)) 2351 if (amd64_toggle_ecc_err_reporting(s, nid, ON))
2349 amd64_warn("Error enabling ECC reporting over MCGCTL!\n"); 2352 amd64_warn("Error enabling ECC reporting over MCGCTL!\n");
2350 2353
2351 amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &value); 2354 amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &value);
@@ -2357,7 +2360,7 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
2357 if (!(value & K8_NBCFG_ECC_ENABLE)) { 2360 if (!(value & K8_NBCFG_ECC_ENABLE)) {
2358 amd64_warn("DRAM ECC disabled on this node, enabling...\n"); 2361 amd64_warn("DRAM ECC disabled on this node, enabling...\n");
2359 2362
2360 pvt->flags.nb_ecc_prev = 0; 2363 s->flags.nb_ecc_prev = 0;
2361 2364
2362 /* Attempt to turn on DRAM ECC Enable */ 2365 /* Attempt to turn on DRAM ECC Enable */
2363 value |= K8_NBCFG_ECC_ENABLE; 2366 value |= K8_NBCFG_ECC_ENABLE;
@@ -2372,7 +2375,7 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
2372 amd64_info("Hardware accepted DRAM ECC Enable\n"); 2375 amd64_info("Hardware accepted DRAM ECC Enable\n");
2373 } 2376 }
2374 } else { 2377 } else {
2375 pvt->flags.nb_ecc_prev = 1; 2378 s->flags.nb_ecc_prev = 1;
2376 } 2379 }
2377 2380
2378 debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, 2381 debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value,
@@ -2384,26 +2387,28 @@ static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci)
2384 2387
2385static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) 2388static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt)
2386{ 2389{
2390 u8 nid = pvt->mc_node_id;
2391 struct ecc_settings *s = ecc_stngs[nid];
2387 u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; 2392 u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
2388 2393
2389 if (!pvt->nbctl_mcgctl_saved) 2394 if (!s->nbctl_valid)
2390 return; 2395 return;
2391 2396
2392 amd64_read_pci_cfg(pvt->F3, K8_NBCTL, &value); 2397 amd64_read_pci_cfg(pvt->F3, K8_NBCTL, &value);
2393 value &= ~mask; 2398 value &= ~mask;
2394 value |= pvt->old_nbctl; 2399 value |= s->old_nbctl;
2395 2400
2396 pci_write_config_dword(pvt->F3, K8_NBCTL, value); 2401 pci_write_config_dword(pvt->F3, K8_NBCTL, value);
2397 2402
2398 /* restore previous BIOS DRAM ECC "off" setting which we force-enabled */ 2403 /* restore previous BIOS DRAM ECC "off" setting we force-enabled */
2399 if (!pvt->flags.nb_ecc_prev) { 2404 if (!s->flags.nb_ecc_prev) {
2400 amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &value); 2405 amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &value);
2401 value &= ~K8_NBCFG_ECC_ENABLE; 2406 value &= ~K8_NBCFG_ECC_ENABLE;
2402 pci_write_config_dword(pvt->F3, K8_NBCFG, value); 2407 pci_write_config_dword(pvt->F3, K8_NBCFG, value);
2403 } 2408 }
2404 2409
2405 /* restore the NB Enable MCGCTL bit */ 2410 /* restore the NB Enable MCGCTL bit */
2406 if (amd64_toggle_ecc_err_reporting(pvt, OFF)) 2411 if (amd64_toggle_ecc_err_reporting(s, nid, OFF))
2407 amd64_warn("Error restoring NB MCGCTL settings!\n"); 2412 amd64_warn("Error restoring NB MCGCTL settings!\n");
2408} 2413}
2409 2414
@@ -2654,6 +2659,8 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev,
2654 const struct pci_device_id *mc_type) 2659 const struct pci_device_id *mc_type)
2655{ 2660{
2656 int ret = 0; 2661 int ret = 0;
2662 u8 nid = get_node_id(pdev);
2663 struct ecc_settings *s;
2657 2664
2658 ret = pci_enable_device(pdev); 2665 ret = pci_enable_device(pdev);
2659 if (ret < 0) { 2666 if (ret < 0) {
@@ -2661,9 +2668,16 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev,
2661 return -EIO; 2668 return -EIO;
2662 } 2669 }
2663 2670
2671 ret = -ENOMEM;
2672 s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL);
2673 if (!s)
2674 return ret;
2675
2676 ecc_stngs[nid] = s;
2677
2664 ret = amd64_probe_one_instance(pdev); 2678 ret = amd64_probe_one_instance(pdev);
2665 if (ret < 0) 2679 if (ret < 0)
2666 amd64_err("Error probing instance: %d\n", get_node_id(pdev)); 2680 amd64_err("Error probing instance: %d\n", nid);
2667 2681
2668 return ret; 2682 return ret;
2669} 2683}
@@ -2688,6 +2702,9 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev)
2688 amd_report_gart_errors(false); 2702 amd_report_gart_errors(false);
2689 amd_unregister_ecc_decoder(amd64_decode_bus_error); 2703 amd_unregister_ecc_decoder(amd64_decode_bus_error);
2690 2704
2705 kfree(ecc_stngs[pvt->mc_node_id]);
2706 ecc_stngs[pvt->mc_node_id] = NULL;
2707
2691 /* Free the EDAC CORE resources */ 2708 /* Free the EDAC CORE resources */
2692 mci->pvt_info = NULL; 2709 mci->pvt_info = NULL;
2693 mcis[pvt->mc_node_id] = NULL; 2710 mcis[pvt->mc_node_id] = NULL;
@@ -2767,9 +2784,10 @@ static int __init amd64_edac_init(void)
2767 goto err_ret; 2784 goto err_ret;
2768 2785
2769 err = -ENOMEM; 2786 err = -ENOMEM;
2770 pvts = kzalloc(amd_nb_num() * sizeof(pvts[0]), GFP_KERNEL); 2787 pvts = kzalloc(amd_nb_num() * sizeof(pvts[0]), GFP_KERNEL);
2771 mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL); 2788 mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
2772 if (!(pvts && mcis)) 2789 ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
2790 if (!(pvts && mcis && ecc_stngs))
2773 goto err_ret; 2791 goto err_ret;
2774 2792
2775 msrs = msrs_alloc(); 2793 msrs = msrs_alloc();
@@ -2820,6 +2838,9 @@ static void __exit amd64_edac_exit(void)
2820 2838
2821 pci_unregister_driver(&amd64_pci_driver); 2839 pci_unregister_driver(&amd64_pci_driver);
2822 2840
2841 kfree(ecc_stngs);
2842 ecc_stngs = NULL;
2843
2823 kfree(mcis); 2844 kfree(mcis);
2824 mcis = NULL; 2845 mcis = NULL;
2825 2846
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 4bc6f183d97c..b76dce96e8e6 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -461,17 +461,21 @@ struct amd64_pvt {
461 /* place to store error injection parameters prior to issue */ 461 /* place to store error injection parameters prior to issue */
462 struct error_injection injection; 462 struct error_injection injection;
463 463
464 /* Save old hw registers' values before we modified them */
465 u32 nbctl_mcgctl_saved; /* When true, following 2 are valid */
466 u32 old_nbctl;
467
468 /* DCT per-family scrubrate setting */ 464 /* DCT per-family scrubrate setting */
469 u32 min_scrubrate; 465 u32 min_scrubrate;
470 466
471 /* family name this instance is running on */ 467 /* family name this instance is running on */
472 const char *ctl_name; 468 const char *ctl_name;
473 469
474 /* misc settings */ 470};
471
472/*
473 * per-node ECC settings descriptor
474 */
475struct ecc_settings {
476 u32 old_nbctl;
477 bool nbctl_valid;
478
475 struct flags { 479 struct flags {
476 unsigned long nb_mce_enable:1; 480 unsigned long nb_mce_enable:1;
477 unsigned long nb_ecc_prev:1; 481 unsigned long nb_ecc_prev:1;