diff options
-rw-r--r-- | MAINTAINERS | 8 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.c | 5 | ||||
-rw-r--r-- | drivers/edac/edac_mc.c | 7 | ||||
-rw-r--r-- | drivers/edac/edac_mc.h | 8 | ||||
-rw-r--r-- | drivers/edac/ghes_edac.c | 137 | ||||
-rw-r--r-- | drivers/edac/i7core_edac.c | 11 | ||||
-rw-r--r-- | drivers/edac/pnd2_edac.c | 9 | ||||
-rw-r--r-- | drivers/edac/sb_edac.c | 43 | ||||
-rw-r--r-- | drivers/edac/skx_edac.c | 30 | ||||
-rw-r--r-- | drivers/edac/thunderx_edac.c | 25 |
10 files changed, 158 insertions, 125 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index fd2464ba3454..48d8f05bf92b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4906,13 +4906,19 @@ L: linux-edac@vger.kernel.org | |||
4906 | S: Maintained | 4906 | S: Maintained |
4907 | F: drivers/edac/highbank* | 4907 | F: drivers/edac/highbank* |
4908 | 4908 | ||
4909 | EDAC-CAVIUM | 4909 | EDAC-CAVIUM OCTEON |
4910 | M: Ralf Baechle <ralf@linux-mips.org> | 4910 | M: Ralf Baechle <ralf@linux-mips.org> |
4911 | M: David Daney <david.daney@cavium.com> | 4911 | M: David Daney <david.daney@cavium.com> |
4912 | L: linux-edac@vger.kernel.org | 4912 | L: linux-edac@vger.kernel.org |
4913 | L: linux-mips@linux-mips.org | 4913 | L: linux-mips@linux-mips.org |
4914 | S: Supported | 4914 | S: Supported |
4915 | F: drivers/edac/octeon_edac* | 4915 | F: drivers/edac/octeon_edac* |
4916 | |||
4917 | EDAC-CAVIUM THUNDERX | ||
4918 | M: David Daney <david.daney@cavium.com> | ||
4919 | M: Jan Glauber <jglauber@cavium.com> | ||
4920 | L: linux-edac@vger.kernel.org | ||
4921 | S: Supported | ||
4916 | F: drivers/edac/thunderx_edac* | 4922 | F: drivers/edac/thunderx_edac* |
4917 | 4923 | ||
4918 | EDAC-CORE | 4924 | EDAC-CORE |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ac2f30295efe..8b16ec595fa7 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -3434,9 +3434,14 @@ MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids); | |||
3434 | 3434 | ||
3435 | static int __init amd64_edac_init(void) | 3435 | static int __init amd64_edac_init(void) |
3436 | { | 3436 | { |
3437 | const char *owner; | ||
3437 | int err = -ENODEV; | 3438 | int err = -ENODEV; |
3438 | int i; | 3439 | int i; |
3439 | 3440 | ||
3441 | owner = edac_get_owner(); | ||
3442 | if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) | ||
3443 | return -EBUSY; | ||
3444 | |||
3440 | if (!x86_match_cpu(amd64_cpuids)) | 3445 | if (!x86_match_cpu(amd64_cpuids)) |
3441 | return -ENODEV; | 3446 | return -ENODEV; |
3442 | 3447 | ||
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 480072139b7a..48193f5f3b56 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -53,7 +53,7 @@ static LIST_HEAD(mc_devices); | |||
53 | * Used to lock EDAC MC to just one module, avoiding two drivers e. g. | 53 | * Used to lock EDAC MC to just one module, avoiding two drivers e. g. |
54 | * apei/ghes and i7core_edac to be used at the same time. | 54 | * apei/ghes and i7core_edac to be used at the same time. |
55 | */ | 55 | */ |
56 | static void const *edac_mc_owner; | 56 | static const char *edac_mc_owner; |
57 | 57 | ||
58 | static struct bus_type mc_bus[EDAC_MAX_MCS]; | 58 | static struct bus_type mc_bus[EDAC_MAX_MCS]; |
59 | 59 | ||
@@ -701,6 +701,11 @@ unlock: | |||
701 | } | 701 | } |
702 | EXPORT_SYMBOL(edac_mc_find); | 702 | EXPORT_SYMBOL(edac_mc_find); |
703 | 703 | ||
704 | const char *edac_get_owner(void) | ||
705 | { | ||
706 | return edac_mc_owner; | ||
707 | } | ||
708 | EXPORT_SYMBOL_GPL(edac_get_owner); | ||
704 | 709 | ||
705 | /* FIXME - should a warning be printed if no error detection? correction? */ | 710 | /* FIXME - should a warning be printed if no error detection? correction? */ |
706 | int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, | 711 | int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, |
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h index 5357800e418d..4165e15995ad 100644 --- a/drivers/edac/edac_mc.h +++ b/drivers/edac/edac_mc.h | |||
@@ -128,6 +128,14 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, | |||
128 | unsigned sz_pvt); | 128 | unsigned sz_pvt); |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * edac_get_owner - Return the owner's mod_name of EDAC MC | ||
132 | * | ||
133 | * Returns: | ||
134 | * Pointer to mod_name string when EDAC MC is owned. NULL otherwise. | ||
135 | */ | ||
136 | extern const char *edac_get_owner(void); | ||
137 | |||
138 | /* | ||
131 | * edac_mc_add_mc_with_groups() - Insert the @mci structure into the mci | 139 | * edac_mc_add_mc_with_groups() - Insert the @mci structure into the mci |
132 | * global list and create sysfs entries associated with @mci structure. | 140 | * global list and create sysfs entries associated with @mci structure. |
133 | * | 141 | * |
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index 6f80eb65c26c..68b6ee18bea6 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c | |||
@@ -28,10 +28,19 @@ struct ghes_edac_pvt { | |||
28 | char msg[80]; | 28 | char msg[80]; |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static LIST_HEAD(ghes_reglist); | 31 | static atomic_t ghes_init = ATOMIC_INIT(0); |
32 | static DEFINE_MUTEX(ghes_edac_lock); | 32 | static struct ghes_edac_pvt *ghes_pvt; |
33 | static int ghes_edac_mc_num; | ||
34 | 33 | ||
34 | /* | ||
35 | * Sync with other, potentially concurrent callers of | ||
36 | * ghes_edac_report_mem_error(). We don't know what the | ||
37 | * "inventive" firmware would do. | ||
38 | */ | ||
39 | static DEFINE_SPINLOCK(ghes_lock); | ||
40 | |||
41 | /* "ghes_edac.force_load=1" skips the platform check */ | ||
42 | static bool __read_mostly force_load; | ||
43 | module_param(force_load, bool, 0); | ||
35 | 44 | ||
36 | /* Memory Device - Type 17 of SMBIOS spec */ | 45 | /* Memory Device - Type 17 of SMBIOS spec */ |
37 | struct memdev_dmi_entry { | 46 | struct memdev_dmi_entry { |
@@ -169,18 +178,26 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | |||
169 | enum hw_event_mc_err_type type; | 178 | enum hw_event_mc_err_type type; |
170 | struct edac_raw_error_desc *e; | 179 | struct edac_raw_error_desc *e; |
171 | struct mem_ctl_info *mci; | 180 | struct mem_ctl_info *mci; |
172 | struct ghes_edac_pvt *pvt = NULL; | 181 | struct ghes_edac_pvt *pvt = ghes_pvt; |
182 | unsigned long flags; | ||
173 | char *p; | 183 | char *p; |
174 | u8 grain_bits; | 184 | u8 grain_bits; |
175 | 185 | ||
176 | list_for_each_entry(pvt, &ghes_reglist, list) { | ||
177 | if (ghes == pvt->ghes) | ||
178 | break; | ||
179 | } | ||
180 | if (!pvt) { | 186 | if (!pvt) { |
181 | pr_err("Internal error: Can't find EDAC structure\n"); | 187 | pr_err("Internal error: Can't find EDAC structure\n"); |
182 | return; | 188 | return; |
183 | } | 189 | } |
190 | |||
191 | /* | ||
192 | * We can do the locking below because GHES defers error processing | ||
193 | * from NMI to IRQ context. Whenever that changes, we'd at least | ||
194 | * know. | ||
195 | */ | ||
196 | if (WARN_ON_ONCE(in_nmi())) | ||
197 | return; | ||
198 | |||
199 | spin_lock_irqsave(&ghes_lock, flags); | ||
200 | |||
184 | mci = pvt->mci; | 201 | mci = pvt->mci; |
185 | e = &mci->error_desc; | 202 | e = &mci->error_desc; |
186 | 203 | ||
@@ -398,10 +415,17 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | |||
398 | (e->page_frame_number << PAGE_SHIFT) | e->offset_in_page, | 415 | (e->page_frame_number << PAGE_SHIFT) | e->offset_in_page, |
399 | grain_bits, e->syndrome, pvt->detail_location); | 416 | grain_bits, e->syndrome, pvt->detail_location); |
400 | 417 | ||
401 | /* Report the error via EDAC API */ | ||
402 | edac_raw_mc_handle_error(type, mci, e); | 418 | edac_raw_mc_handle_error(type, mci, e); |
419 | spin_unlock_irqrestore(&ghes_lock, flags); | ||
403 | } | 420 | } |
404 | EXPORT_SYMBOL_GPL(ghes_edac_report_mem_error); | 421 | |
422 | /* | ||
423 | * Known systems that are safe to enable this module. | ||
424 | */ | ||
425 | static struct acpi_platform_list plat_list[] = { | ||
426 | {"HPE ", "Server ", 0, ACPI_SIG_FADT, all_versions}, | ||
427 | { } /* End */ | ||
428 | }; | ||
405 | 429 | ||
406 | int ghes_edac_register(struct ghes *ghes, struct device *dev) | 430 | int ghes_edac_register(struct ghes *ghes, struct device *dev) |
407 | { | 431 | { |
@@ -409,8 +433,19 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) | |||
409 | int rc, num_dimm = 0; | 433 | int rc, num_dimm = 0; |
410 | struct mem_ctl_info *mci; | 434 | struct mem_ctl_info *mci; |
411 | struct edac_mc_layer layers[1]; | 435 | struct edac_mc_layer layers[1]; |
412 | struct ghes_edac_pvt *pvt; | ||
413 | struct ghes_edac_dimm_fill dimm_fill; | 436 | struct ghes_edac_dimm_fill dimm_fill; |
437 | int idx; | ||
438 | |||
439 | /* Check if safe to enable on this system */ | ||
440 | idx = acpi_match_platform_list(plat_list); | ||
441 | if (!force_load && idx < 0) | ||
442 | return 0; | ||
443 | |||
444 | /* | ||
445 | * We have only one logical memory controller to which all DIMMs belong. | ||
446 | */ | ||
447 | if (atomic_inc_return(&ghes_init) > 1) | ||
448 | return 0; | ||
414 | 449 | ||
415 | /* Get the number of DIMMs */ | 450 | /* Get the number of DIMMs */ |
416 | dmi_walk(ghes_edac_count_dimms, &num_dimm); | 451 | dmi_walk(ghes_edac_count_dimms, &num_dimm); |
@@ -425,26 +460,17 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) | |||
425 | layers[0].size = num_dimm; | 460 | layers[0].size = num_dimm; |
426 | layers[0].is_virt_csrow = true; | 461 | layers[0].is_virt_csrow = true; |
427 | 462 | ||
428 | /* | 463 | mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(struct ghes_edac_pvt)); |
429 | * We need to serialize edac_mc_alloc() and edac_mc_add_mc(), | ||
430 | * to avoid duplicated memory controller numbers | ||
431 | */ | ||
432 | mutex_lock(&ghes_edac_lock); | ||
433 | mci = edac_mc_alloc(ghes_edac_mc_num, ARRAY_SIZE(layers), layers, | ||
434 | sizeof(*pvt)); | ||
435 | if (!mci) { | 464 | if (!mci) { |
436 | pr_info("Can't allocate memory for EDAC data\n"); | 465 | pr_info("Can't allocate memory for EDAC data\n"); |
437 | mutex_unlock(&ghes_edac_lock); | ||
438 | return -ENOMEM; | 466 | return -ENOMEM; |
439 | } | 467 | } |
440 | 468 | ||
441 | pvt = mci->pvt_info; | 469 | ghes_pvt = mci->pvt_info; |
442 | memset(pvt, 0, sizeof(*pvt)); | 470 | ghes_pvt->ghes = ghes; |
443 | list_add_tail(&pvt->list, &ghes_reglist); | 471 | ghes_pvt->mci = mci; |
444 | pvt->ghes = ghes; | ||
445 | pvt->mci = mci; | ||
446 | mci->pdev = dev; | ||
447 | 472 | ||
473 | mci->pdev = dev; | ||
448 | mci->mtype_cap = MEM_FLAG_EMPTY; | 474 | mci->mtype_cap = MEM_FLAG_EMPTY; |
449 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 475 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
450 | mci->edac_cap = EDAC_FLAG_NONE; | 476 | mci->edac_cap = EDAC_FLAG_NONE; |
@@ -452,36 +478,23 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) | |||
452 | mci->ctl_name = "ghes_edac"; | 478 | mci->ctl_name = "ghes_edac"; |
453 | mci->dev_name = "ghes"; | 479 | mci->dev_name = "ghes"; |
454 | 480 | ||
455 | if (!ghes_edac_mc_num) { | 481 | if (fake) { |
456 | if (!fake) { | 482 | pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n"); |
457 | pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n"); | 483 | pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n"); |
458 | pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n"); | 484 | pr_info("work on such system. Use this driver with caution\n"); |
459 | pr_info("So, the end result of using this driver varies from vendor to vendor.\n"); | 485 | } else if (idx < 0) { |
460 | pr_info("If you find incorrect reports, please contact your hardware vendor\n"); | 486 | pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n"); |
461 | pr_info("to correct its BIOS.\n"); | 487 | pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n"); |
462 | pr_info("This system has %d DIMM sockets.\n", | 488 | pr_info("So, the end result of using this driver varies from vendor to vendor.\n"); |
463 | num_dimm); | 489 | pr_info("If you find incorrect reports, please contact your hardware vendor\n"); |
464 | } else { | 490 | pr_info("to correct its BIOS.\n"); |
465 | pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n"); | 491 | pr_info("This system has %d DIMM sockets.\n", num_dimm); |
466 | pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n"); | ||
467 | pr_info("work on such system. Use this driver with caution\n"); | ||
468 | } | ||
469 | } | 492 | } |
470 | 493 | ||
471 | if (!fake) { | 494 | if (!fake) { |
472 | /* | 495 | dimm_fill.count = 0; |
473 | * Fill DIMM info from DMI for the memory controller #0 | 496 | dimm_fill.mci = mci; |
474 | * | 497 | dmi_walk(ghes_edac_dmidecode, &dimm_fill); |
475 | * Keep it in blank for the other memory controllers, as | ||
476 | * there's no reliable way to properly credit each DIMM to | ||
477 | * the memory controller, as different BIOSes fill the | ||
478 | * DMI bank location fields on different ways | ||
479 | */ | ||
480 | if (!ghes_edac_mc_num) { | ||
481 | dimm_fill.count = 0; | ||
482 | dimm_fill.mci = mci; | ||
483 | dmi_walk(ghes_edac_dmidecode, &dimm_fill); | ||
484 | } | ||
485 | } else { | 498 | } else { |
486 | struct dimm_info *dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, | 499 | struct dimm_info *dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, |
487 | mci->n_layers, 0, 0, 0); | 500 | mci->n_layers, 0, 0, 0); |
@@ -497,28 +510,16 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) | |||
497 | if (rc < 0) { | 510 | if (rc < 0) { |
498 | pr_info("Can't register at EDAC core\n"); | 511 | pr_info("Can't register at EDAC core\n"); |
499 | edac_mc_free(mci); | 512 | edac_mc_free(mci); |
500 | mutex_unlock(&ghes_edac_lock); | ||
501 | return -ENODEV; | 513 | return -ENODEV; |
502 | } | 514 | } |
503 | |||
504 | ghes_edac_mc_num++; | ||
505 | mutex_unlock(&ghes_edac_lock); | ||
506 | return 0; | 515 | return 0; |
507 | } | 516 | } |
508 | EXPORT_SYMBOL_GPL(ghes_edac_register); | ||
509 | 517 | ||
510 | void ghes_edac_unregister(struct ghes *ghes) | 518 | void ghes_edac_unregister(struct ghes *ghes) |
511 | { | 519 | { |
512 | struct mem_ctl_info *mci; | 520 | struct mem_ctl_info *mci; |
513 | struct ghes_edac_pvt *pvt, *tmp; | 521 | |
514 | 522 | mci = ghes_pvt->mci; | |
515 | list_for_each_entry_safe(pvt, tmp, &ghes_reglist, list) { | 523 | edac_mc_del_mc(mci->pdev); |
516 | if (ghes == pvt->ghes) { | 524 | edac_mc_free(mci); |
517 | mci = pvt->mci; | ||
518 | edac_mc_del_mc(mci->pdev); | ||
519 | edac_mc_free(mci); | ||
520 | list_del(&pvt->list); | ||
521 | } | ||
522 | } | ||
523 | } | 525 | } |
524 | EXPORT_SYMBOL_GPL(ghes_edac_unregister); | ||
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index c16c3b931b3d..8c5540160a23 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -2159,8 +2159,13 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) | |||
2159 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 2159 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
2160 | mci->edac_cap = EDAC_FLAG_NONE; | 2160 | mci->edac_cap = EDAC_FLAG_NONE; |
2161 | mci->mod_name = "i7core_edac.c"; | 2161 | mci->mod_name = "i7core_edac.c"; |
2162 | mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d", | 2162 | |
2163 | i7core_dev->socket); | 2163 | mci->ctl_name = kasprintf(GFP_KERNEL, "i7 core #%d", i7core_dev->socket); |
2164 | if (!mci->ctl_name) { | ||
2165 | rc = -ENOMEM; | ||
2166 | goto fail1; | ||
2167 | } | ||
2168 | |||
2164 | mci->dev_name = pci_name(i7core_dev->pdev[0]); | 2169 | mci->dev_name = pci_name(i7core_dev->pdev[0]); |
2165 | mci->ctl_page_to_phys = NULL; | 2170 | mci->ctl_page_to_phys = NULL; |
2166 | 2171 | ||
@@ -2214,6 +2219,8 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) | |||
2214 | 2219 | ||
2215 | fail0: | 2220 | fail0: |
2216 | kfree(mci->ctl_name); | 2221 | kfree(mci->ctl_name); |
2222 | |||
2223 | fail1: | ||
2217 | edac_mc_free(mci); | 2224 | edac_mc_free(mci); |
2218 | i7core_dev->mci = NULL; | 2225 | i7core_dev->mci = NULL; |
2219 | return rc; | 2226 | return rc; |
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index 4395c84cdcbf..df28b65358d2 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include "edac_module.h" | 45 | #include "edac_module.h" |
46 | #include "pnd2_edac.h" | 46 | #include "pnd2_edac.h" |
47 | 47 | ||
48 | #define EDAC_MOD_STR "pnd2_edac" | ||
49 | |||
48 | #define APL_NUM_CHANNELS 4 | 50 | #define APL_NUM_CHANNELS 4 |
49 | #define DNV_NUM_CHANNELS 2 | 51 | #define DNV_NUM_CHANNELS 2 |
50 | #define DNV_MAX_DIMMS 2 /* Max DIMMs per channel */ | 52 | #define DNV_MAX_DIMMS 2 /* Max DIMMs per channel */ |
@@ -1355,7 +1357,7 @@ static int pnd2_register_mci(struct mem_ctl_info **ppmci) | |||
1355 | pvt = mci->pvt_info; | 1357 | pvt = mci->pvt_info; |
1356 | memset(pvt, 0, sizeof(*pvt)); | 1358 | memset(pvt, 0, sizeof(*pvt)); |
1357 | 1359 | ||
1358 | mci->mod_name = "pnd2_edac.c"; | 1360 | mci->mod_name = EDAC_MOD_STR; |
1359 | mci->dev_name = ops->name; | 1361 | mci->dev_name = ops->name; |
1360 | mci->ctl_name = "Pondicherry2"; | 1362 | mci->ctl_name = "Pondicherry2"; |
1361 | 1363 | ||
@@ -1547,10 +1549,15 @@ MODULE_DEVICE_TABLE(x86cpu, pnd2_cpuids); | |||
1547 | static int __init pnd2_init(void) | 1549 | static int __init pnd2_init(void) |
1548 | { | 1550 | { |
1549 | const struct x86_cpu_id *id; | 1551 | const struct x86_cpu_id *id; |
1552 | const char *owner; | ||
1550 | int rc; | 1553 | int rc; |
1551 | 1554 | ||
1552 | edac_dbg(2, "\n"); | 1555 | edac_dbg(2, "\n"); |
1553 | 1556 | ||
1557 | owner = edac_get_owner(); | ||
1558 | if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) | ||
1559 | return -EBUSY; | ||
1560 | |||
1554 | id = x86_match_cpu(pnd2_cpuids); | 1561 | id = x86_match_cpu(pnd2_cpuids); |
1555 | if (!id) | 1562 | if (!id) |
1556 | return -ENODEV; | 1563 | return -ENODEV; |
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index dc0591654011..f34430f99fd8 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c | |||
@@ -36,7 +36,7 @@ static LIST_HEAD(sbridge_edac_list); | |||
36 | * Alter this version for the module when modifications are made | 36 | * Alter this version for the module when modifications are made |
37 | */ | 37 | */ |
38 | #define SBRIDGE_REVISION " Ver: 1.1.2 " | 38 | #define SBRIDGE_REVISION " Ver: 1.1.2 " |
39 | #define EDAC_MOD_STR "sbridge_edac" | 39 | #define EDAC_MOD_STR "sb_edac" |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Debug macros | 42 | * Debug macros |
@@ -462,6 +462,7 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = { | |||
462 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { | 462 | static const struct pci_id_descr pci_dev_descr_ibridge[] = { |
463 | /* Processor Home Agent */ | 463 | /* Processor Home Agent */ |
464 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0, IMC0) }, | 464 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0, IMC0) }, |
465 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1, IMC1) }, | ||
465 | 466 | ||
466 | /* Memory controller */ | 467 | /* Memory controller */ |
467 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0, IMC0) }, | 468 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0, IMC0) }, |
@@ -472,7 +473,6 @@ static const struct pci_id_descr pci_dev_descr_ibridge[] = { | |||
472 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0, IMC0) }, | 473 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0, IMC0) }, |
473 | 474 | ||
474 | /* Optional, mode 2HA */ | 475 | /* Optional, mode 2HA */ |
475 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1, IMC1) }, | ||
476 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1, IMC1) }, | 476 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1, IMC1) }, |
477 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1, IMC1) }, | 477 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1, IMC1) }, |
478 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1, IMC1) }, | 478 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1, IMC1) }, |
@@ -1318,9 +1318,7 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes) | |||
1318 | int cur_reg_start; | 1318 | int cur_reg_start; |
1319 | int mc; | 1319 | int mc; |
1320 | int channel; | 1320 | int channel; |
1321 | int way; | ||
1322 | int participants[KNL_MAX_CHANNELS]; | 1321 | int participants[KNL_MAX_CHANNELS]; |
1323 | int participant_count = 0; | ||
1324 | 1322 | ||
1325 | for (i = 0; i < KNL_MAX_CHANNELS; i++) | 1323 | for (i = 0; i < KNL_MAX_CHANNELS; i++) |
1326 | mc_sizes[i] = 0; | 1324 | mc_sizes[i] = 0; |
@@ -1495,21 +1493,14 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes) | |||
1495 | * this channel mapped to the given target? | 1493 | * this channel mapped to the given target? |
1496 | */ | 1494 | */ |
1497 | for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) { | 1495 | for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) { |
1498 | for (way = 0; way < intrlv_ways; way++) { | 1496 | int target; |
1499 | int target; | 1497 | int cha; |
1500 | int cha; | ||
1501 | |||
1502 | if (KNL_MOD3(dram_rule)) | ||
1503 | target = way; | ||
1504 | else | ||
1505 | target = 0x7 & sad_pkg( | ||
1506 | pvt->info.interleave_pkg, interleave_reg, way); | ||
1507 | 1498 | ||
1499 | for (target = 0; target < KNL_MAX_CHANNELS; target++) { | ||
1508 | for (cha = 0; cha < KNL_MAX_CHAS; cha++) { | 1500 | for (cha = 0; cha < KNL_MAX_CHAS; cha++) { |
1509 | if (knl_get_mc_route(target, | 1501 | if (knl_get_mc_route(target, |
1510 | mc_route_reg[cha]) == channel | 1502 | mc_route_reg[cha]) == channel |
1511 | && !participants[channel]) { | 1503 | && !participants[channel]) { |
1512 | participant_count++; | ||
1513 | participants[channel] = 1; | 1504 | participants[channel] = 1; |
1514 | break; | 1505 | break; |
1515 | } | 1506 | } |
@@ -1517,10 +1508,6 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes) | |||
1517 | } | 1508 | } |
1518 | } | 1509 | } |
1519 | 1510 | ||
1520 | if (participant_count != intrlv_ways) | ||
1521 | edac_dbg(0, "participant_count (%d) != interleave_ways (%d): DIMM size may be incorrect\n", | ||
1522 | participant_count, intrlv_ways); | ||
1523 | |||
1524 | for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) { | 1511 | for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) { |
1525 | mc = knl_channel_mc(channel); | 1512 | mc = knl_channel_mc(channel); |
1526 | if (participants[channel]) { | 1513 | if (participants[channel]) { |
@@ -2291,6 +2278,13 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
2291 | next_imc: | 2278 | next_imc: |
2292 | sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); | 2279 | sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); |
2293 | if (!sbridge_dev) { | 2280 | if (!sbridge_dev) { |
2281 | /* If the HA1 wasn't found, don't create EDAC second memory controller */ | ||
2282 | if (dev_descr->dom == IMC1 && devno != 1) { | ||
2283 | edac_dbg(0, "Skip IMC1: %04x:%04x (since HA1 was absent)\n", | ||
2284 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); | ||
2285 | pci_dev_put(pdev); | ||
2286 | return 0; | ||
2287 | } | ||
2294 | 2288 | ||
2295 | if (dev_descr->dom == SOCK) | 2289 | if (dev_descr->dom == SOCK) |
2296 | goto out_imc; | 2290 | goto out_imc; |
@@ -2491,6 +2485,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci, | |||
2491 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: | 2485 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA: |
2492 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA: | 2486 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA: |
2493 | pvt->pci_ta = pdev; | 2487 | pvt->pci_ta = pdev; |
2488 | break; | ||
2494 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: | 2489 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS: |
2495 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS: | 2490 | case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS: |
2496 | pvt->pci_ras = pdev; | 2491 | pvt->pci_ras = pdev; |
@@ -3155,7 +3150,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
3155 | MEM_FLAG_DDR4 : MEM_FLAG_DDR3; | 3150 | MEM_FLAG_DDR4 : MEM_FLAG_DDR3; |
3156 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 3151 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
3157 | mci->edac_cap = EDAC_FLAG_NONE; | 3152 | mci->edac_cap = EDAC_FLAG_NONE; |
3158 | mci->mod_name = "sb_edac.c"; | 3153 | mci->mod_name = EDAC_MOD_STR; |
3159 | mci->dev_name = pci_name(pdev); | 3154 | mci->dev_name = pci_name(pdev); |
3160 | mci->ctl_page_to_phys = NULL; | 3155 | mci->ctl_page_to_phys = NULL; |
3161 | 3156 | ||
@@ -3287,6 +3282,11 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
3287 | break; | 3282 | break; |
3288 | } | 3283 | } |
3289 | 3284 | ||
3285 | if (!mci->ctl_name) { | ||
3286 | rc = -ENOMEM; | ||
3287 | goto fail0; | ||
3288 | } | ||
3289 | |||
3290 | /* Get dimm basic config and the memory layout */ | 3290 | /* Get dimm basic config and the memory layout */ |
3291 | rc = get_dimm_config(mci); | 3291 | rc = get_dimm_config(mci); |
3292 | if (rc < 0) { | 3292 | if (rc < 0) { |
@@ -3402,10 +3402,15 @@ static void sbridge_remove(void) | |||
3402 | static int __init sbridge_init(void) | 3402 | static int __init sbridge_init(void) |
3403 | { | 3403 | { |
3404 | const struct x86_cpu_id *id; | 3404 | const struct x86_cpu_id *id; |
3405 | const char *owner; | ||
3405 | int rc; | 3406 | int rc; |
3406 | 3407 | ||
3407 | edac_dbg(2, "\n"); | 3408 | edac_dbg(2, "\n"); |
3408 | 3409 | ||
3410 | owner = edac_get_owner(); | ||
3411 | if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) | ||
3412 | return -EBUSY; | ||
3413 | |||
3409 | id = x86_match_cpu(sbridge_cpuids); | 3414 | id = x86_match_cpu(sbridge_cpuids); |
3410 | if (!id) | 3415 | if (!id) |
3411 | return -ENODEV; | 3416 | return -ENODEV; |
diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index 16dea97568a1..912c4930c9ef 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c | |||
@@ -31,6 +31,8 @@ | |||
31 | 31 | ||
32 | #include "edac_module.h" | 32 | #include "edac_module.h" |
33 | 33 | ||
34 | #define EDAC_MOD_STR "skx_edac" | ||
35 | |||
34 | /* | 36 | /* |
35 | * Debug macros | 37 | * Debug macros |
36 | */ | 38 | */ |
@@ -65,6 +67,7 @@ static u64 skx_tolm, skx_tohm; | |||
65 | struct skx_dev { | 67 | struct skx_dev { |
66 | struct list_head list; | 68 | struct list_head list; |
67 | u8 bus[4]; | 69 | u8 bus[4]; |
70 | int seg; | ||
68 | struct pci_dev *sad_all; | 71 | struct pci_dev *sad_all; |
69 | struct pci_dev *util_all; | 72 | struct pci_dev *util_all; |
70 | u32 mcroute; | 73 | u32 mcroute; |
@@ -110,12 +113,12 @@ struct decoded_addr { | |||
110 | int bank_group; | 113 | int bank_group; |
111 | }; | 114 | }; |
112 | 115 | ||
113 | static struct skx_dev *get_skx_dev(u8 bus, u8 idx) | 116 | static struct skx_dev *get_skx_dev(struct pci_bus *bus, u8 idx) |
114 | { | 117 | { |
115 | struct skx_dev *d; | 118 | struct skx_dev *d; |
116 | 119 | ||
117 | list_for_each_entry(d, &skx_edac_list, list) { | 120 | list_for_each_entry(d, &skx_edac_list, list) { |
118 | if (d->bus[idx] == bus) | 121 | if (d->seg == pci_domain_nr(bus) && d->bus[idx] == bus->number) |
119 | return d; | 122 | return d; |
120 | } | 123 | } |
121 | 124 | ||
@@ -172,6 +175,7 @@ static int get_all_bus_mappings(void) | |||
172 | pci_dev_put(pdev); | 175 | pci_dev_put(pdev); |
173 | return -ENOMEM; | 176 | return -ENOMEM; |
174 | } | 177 | } |
178 | d->seg = pci_domain_nr(pdev->bus); | ||
175 | pci_read_config_dword(pdev, 0xCC, ®); | 179 | pci_read_config_dword(pdev, 0xCC, ®); |
176 | d->bus[0] = GET_BITFIELD(reg, 0, 7); | 180 | d->bus[0] = GET_BITFIELD(reg, 0, 7); |
177 | d->bus[1] = GET_BITFIELD(reg, 8, 15); | 181 | d->bus[1] = GET_BITFIELD(reg, 8, 15); |
@@ -207,7 +211,7 @@ static int get_all_munits(const struct munit *m) | |||
207 | if (i == NUM_IMC) | 211 | if (i == NUM_IMC) |
208 | goto fail; | 212 | goto fail; |
209 | } | 213 | } |
210 | d = get_skx_dev(pdev->bus->number, m->busidx); | 214 | d = get_skx_dev(pdev->bus, m->busidx); |
211 | if (!d) | 215 | if (!d) |
212 | goto fail; | 216 | goto fail; |
213 | 217 | ||
@@ -299,7 +303,7 @@ static int get_dimm_attr(u32 reg, int lobit, int hibit, int add, int minval, | |||
299 | 303 | ||
300 | #define IS_DIMM_PRESENT(mtr) GET_BITFIELD((mtr), 15, 15) | 304 | #define IS_DIMM_PRESENT(mtr) GET_BITFIELD((mtr), 15, 15) |
301 | 305 | ||
302 | #define numrank(reg) get_dimm_attr((reg), 12, 13, 0, 1, 2, "ranks") | 306 | #define numrank(reg) get_dimm_attr((reg), 12, 13, 0, 0, 2, "ranks") |
303 | #define numrow(reg) get_dimm_attr((reg), 2, 4, 12, 1, 6, "rows") | 307 | #define numrow(reg) get_dimm_attr((reg), 2, 4, 12, 1, 6, "rows") |
304 | #define numcol(reg) get_dimm_attr((reg), 0, 1, 10, 0, 2, "cols") | 308 | #define numcol(reg) get_dimm_attr((reg), 0, 1, 10, 0, 2, "cols") |
305 | 309 | ||
@@ -360,7 +364,7 @@ static int get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm, | |||
360 | 364 | ||
361 | edac_dbg(0, "mc#%d: channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", | 365 | edac_dbg(0, "mc#%d: channel %d, dimm %d, %lld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n", |
362 | imc->mc, chan, dimmno, size, npages, | 366 | imc->mc, chan, dimmno, size, npages, |
363 | banks, ranks, rows, cols); | 367 | banks, 1 << ranks, rows, cols); |
364 | 368 | ||
365 | imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0); | 369 | imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0); |
366 | imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9); | 370 | imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9); |
@@ -464,12 +468,16 @@ static int skx_register_mci(struct skx_imc *imc) | |||
464 | pvt = mci->pvt_info; | 468 | pvt = mci->pvt_info; |
465 | pvt->imc = imc; | 469 | pvt->imc = imc; |
466 | 470 | ||
467 | mci->ctl_name = kasprintf(GFP_KERNEL, "Skylake Socket#%d IMC#%d", | 471 | mci->ctl_name = kasprintf(GFP_KERNEL, "Skylake Socket#%d IMC#%d", imc->node_id, imc->lmc); |
468 | imc->node_id, imc->lmc); | 472 | if (!mci->ctl_name) { |
473 | rc = -ENOMEM; | ||
474 | goto fail0; | ||
475 | } | ||
476 | |||
469 | mci->mtype_cap = MEM_FLAG_DDR4; | 477 | mci->mtype_cap = MEM_FLAG_DDR4; |
470 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 478 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
471 | mci->edac_cap = EDAC_FLAG_NONE; | 479 | mci->edac_cap = EDAC_FLAG_NONE; |
472 | mci->mod_name = "skx_edac.c"; | 480 | mci->mod_name = EDAC_MOD_STR; |
473 | mci->dev_name = pci_name(imc->chan[0].cdev); | 481 | mci->dev_name = pci_name(imc->chan[0].cdev); |
474 | mci->ctl_page_to_phys = NULL; | 482 | mci->ctl_page_to_phys = NULL; |
475 | 483 | ||
@@ -491,6 +499,7 @@ static int skx_register_mci(struct skx_imc *imc) | |||
491 | 499 | ||
492 | fail: | 500 | fail: |
493 | kfree(mci->ctl_name); | 501 | kfree(mci->ctl_name); |
502 | fail0: | ||
494 | edac_mc_free(mci); | 503 | edac_mc_free(mci); |
495 | imc->mci = NULL; | 504 | imc->mci = NULL; |
496 | return rc; | 505 | return rc; |
@@ -1039,12 +1048,17 @@ static int __init skx_init(void) | |||
1039 | { | 1048 | { |
1040 | const struct x86_cpu_id *id; | 1049 | const struct x86_cpu_id *id; |
1041 | const struct munit *m; | 1050 | const struct munit *m; |
1051 | const char *owner; | ||
1042 | int rc = 0, i; | 1052 | int rc = 0, i; |
1043 | u8 mc = 0, src_id, node_id; | 1053 | u8 mc = 0, src_id, node_id; |
1044 | struct skx_dev *d; | 1054 | struct skx_dev *d; |
1045 | 1055 | ||
1046 | edac_dbg(2, "\n"); | 1056 | edac_dbg(2, "\n"); |
1047 | 1057 | ||
1058 | owner = edac_get_owner(); | ||
1059 | if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) | ||
1060 | return -EBUSY; | ||
1061 | |||
1048 | id = x86_match_cpu(skx_cpuids); | 1062 | id = x86_match_cpu(skx_cpuids); |
1049 | if (!id) | 1063 | if (!id) |
1050 | return -ENODEV; | 1064 | return -ENODEV; |
diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index f35d87519a3e..4803c6468bab 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c | |||
@@ -639,27 +639,6 @@ err_free: | |||
639 | return ret; | 639 | return ret; |
640 | } | 640 | } |
641 | 641 | ||
642 | #ifdef CONFIG_PM | ||
643 | static int thunderx_lmc_suspend(struct pci_dev *pdev, pm_message_t state) | ||
644 | { | ||
645 | pci_save_state(pdev); | ||
646 | pci_disable_device(pdev); | ||
647 | |||
648 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | static int thunderx_lmc_resume(struct pci_dev *pdev) | ||
654 | { | ||
655 | pci_set_power_state(pdev, PCI_D0); | ||
656 | pci_enable_wake(pdev, PCI_D0, 0); | ||
657 | pci_restore_state(pdev); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | #endif | ||
662 | |||
663 | static const struct pci_device_id thunderx_lmc_pci_tbl[] = { | 642 | static const struct pci_device_id thunderx_lmc_pci_tbl[] = { |
664 | { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_LMC) }, | 643 | { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_LMC) }, |
665 | { 0, }, | 644 | { 0, }, |
@@ -834,10 +813,6 @@ static struct pci_driver thunderx_lmc_driver = { | |||
834 | .name = "thunderx_lmc_edac", | 813 | .name = "thunderx_lmc_edac", |
835 | .probe = thunderx_lmc_probe, | 814 | .probe = thunderx_lmc_probe, |
836 | .remove = thunderx_lmc_remove, | 815 | .remove = thunderx_lmc_remove, |
837 | #ifdef CONFIG_PM | ||
838 | .suspend = thunderx_lmc_suspend, | ||
839 | .resume = thunderx_lmc_resume, | ||
840 | #endif | ||
841 | .id_table = thunderx_lmc_pci_tbl, | 816 | .id_table = thunderx_lmc_pci_tbl, |
842 | }; | 817 | }; |
843 | 818 | ||