Skip to content

Commit 802e7f1

Browse files
justin-hesuryasaimadhu
authored andcommitted
EDAC/ghes: Make ghes_edac a proper module
Commit dc4e8c0 ("ACPI: APEI: explicit init of HEST and GHES in apci_init()") introduced a bug leading to ghes_edac_register() to be invoked before edac_init(). Because at that time the bus "edac" hadn't been even registered, this created sysfs nodes as /devices/mc0 instead of /sys/devices/system/edac/mc/mc0 on an Ampere eMag server. Fix this by turning ghes_edac into a proper module. The list of GHES devices returned is not protected from being modified concurrently but it is pretty static as it gets created only during GHES init and latter is not a module so... [ bp: Massage. ] Fixes: dc4e8c0 ("ACPI: APEI: explicit init of HEST and GHES in apci_init()") Co-developed-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Jia He <justin.he@arm.com> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lore.kernel.org/r/20221010023559.69655-5-justin.he@arm.com
1 parent 9057a3f commit 802e7f1

4 files changed

Lines changed: 42 additions & 28 deletions

File tree

drivers/acpi/apei/ghes.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,8 +1392,6 @@ static int ghes_probe(struct platform_device *ghes_dev)
13921392

13931393
platform_set_drvdata(ghes_dev, ghes);
13941394

1395-
ghes_edac_register(ghes, &ghes_dev->dev);
1396-
13971395
ghes->dev = &ghes_dev->dev;
13981396

13991397
mutex_lock(&ghes_devs_mutex);
@@ -1462,8 +1460,6 @@ static int ghes_remove(struct platform_device *ghes_dev)
14621460

14631461
ghes_fini(ghes);
14641462

1465-
ghes_edac_unregister(ghes);
1466-
14671463
mutex_lock(&ghes_devs_mutex);
14681464
list_del(&ghes->elist);
14691465
mutex_unlock(&ghes_devs_mutex);

drivers/edac/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ config EDAC_DECODE_MCE
5353
has been initialized.
5454

5555
config EDAC_GHES
56-
bool "Output ACPI APEI/GHES BIOS detected errors via EDAC"
57-
depends on ACPI_APEI_GHES && (EDAC=y)
56+
tristate "Output ACPI APEI/GHES BIOS detected errors via EDAC"
57+
depends on ACPI_APEI_GHES
5858
select UEFI_CPER
5959
help
6060
Not all machines support hardware-driven error report. Some of those

drivers/edac/ghes_edac.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ static DEFINE_SPINLOCK(ghes_lock);
5656

5757
static bool system_scanned;
5858

59+
static struct list_head *ghes_devs;
60+
5961
/* Memory Device - Type 17 of SMBIOS spec */
6062
struct memdev_dmi_entry {
6163
u8 type;
@@ -383,7 +385,7 @@ static struct notifier_block ghes_edac_mem_err_nb = {
383385
.priority = 0,
384386
};
385387

386-
int ghes_edac_register(struct ghes *ghes, struct device *dev)
388+
static int ghes_edac_register(struct device *dev)
387389
{
388390
bool fake = false;
389391
struct mem_ctl_info *mci;
@@ -502,7 +504,7 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
502504
return rc;
503505
}
504506

505-
void ghes_edac_unregister(struct ghes *ghes)
507+
static void ghes_edac_unregister(struct ghes *ghes)
506508
{
507509
struct mem_ctl_info *mci;
508510
unsigned long flags;
@@ -535,3 +537,37 @@ void ghes_edac_unregister(struct ghes *ghes)
535537
unlock:
536538
mutex_unlock(&ghes_reg_mutex);
537539
}
540+
541+
static int __init ghes_edac_init(void)
542+
{
543+
struct ghes *g, *g_tmp;
544+
545+
ghes_devs = ghes_get_devices();
546+
if (!ghes_devs)
547+
return -ENODEV;
548+
549+
if (list_empty(ghes_devs)) {
550+
pr_info("GHES probing device list is empty");
551+
return -ENODEV;
552+
}
553+
554+
list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {
555+
ghes_edac_register(g->dev);
556+
}
557+
558+
return 0;
559+
}
560+
module_init(ghes_edac_init);
561+
562+
static void __exit ghes_edac_exit(void)
563+
{
564+
struct ghes *g, *g_tmp;
565+
566+
list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {
567+
ghes_edac_unregister(g);
568+
}
569+
}
570+
module_exit(ghes_edac_exit);
571+
572+
MODULE_LICENSE("GPL");
573+
MODULE_DESCRIPTION("Output ACPI APEI/GHES BIOS detected errors via EDAC");

include/acpi/ghes.h

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -71,32 +71,14 @@ int ghes_register_vendor_record_notifier(struct notifier_block *nb);
7171
* @nb: pointer to the notifier_block structure of the vendor record handler.
7272
*/
7373
void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
74-
#endif
75-
76-
int ghes_estatus_pool_init(int num_ghes);
77-
78-
/* From drivers/edac/ghes_edac.c */
79-
80-
#ifdef CONFIG_EDAC_GHES
81-
int ghes_edac_register(struct ghes *ghes, struct device *dev);
82-
83-
void ghes_edac_unregister(struct ghes *ghes);
8474

8575
struct list_head *ghes_get_devices(void);
86-
8776
#else
88-
static inline int ghes_edac_register(struct ghes *ghes, struct device *dev)
89-
{
90-
return -ENODEV;
91-
}
92-
93-
static inline void ghes_edac_unregister(struct ghes *ghes)
94-
{
95-
}
96-
9777
static inline struct list_head *ghes_get_devices(void) { return NULL; }
9878
#endif
9979

80+
int ghes_estatus_pool_init(int num_ghes);
81+
10082
static inline int acpi_hest_get_version(struct acpi_hest_generic_data *gdata)
10183
{
10284
return gdata->revision >> 8;

0 commit comments

Comments
 (0)