EDAC/ghes: Make ghes_edac a proper module
Commitdc4e8c07e9
("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:dc4e8c07e9
("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
This commit is contained in:
parent
9057a3f7ac
commit
802e7f1dfe
|
@ -1392,8 +1392,6 @@ static int ghes_probe(struct platform_device *ghes_dev)
|
|||
|
||||
platform_set_drvdata(ghes_dev, ghes);
|
||||
|
||||
ghes_edac_register(ghes, &ghes_dev->dev);
|
||||
|
||||
ghes->dev = &ghes_dev->dev;
|
||||
|
||||
mutex_lock(&ghes_devs_mutex);
|
||||
|
@ -1462,8 +1460,6 @@ static int ghes_remove(struct platform_device *ghes_dev)
|
|||
|
||||
ghes_fini(ghes);
|
||||
|
||||
ghes_edac_unregister(ghes);
|
||||
|
||||
mutex_lock(&ghes_devs_mutex);
|
||||
list_del(&ghes->elist);
|
||||
mutex_unlock(&ghes_devs_mutex);
|
||||
|
|
|
@ -53,8 +53,8 @@ config EDAC_DECODE_MCE
|
|||
has been initialized.
|
||||
|
||||
config EDAC_GHES
|
||||
bool "Output ACPI APEI/GHES BIOS detected errors via EDAC"
|
||||
depends on ACPI_APEI_GHES && (EDAC=y)
|
||||
tristate "Output ACPI APEI/GHES BIOS detected errors via EDAC"
|
||||
depends on ACPI_APEI_GHES
|
||||
select UEFI_CPER
|
||||
help
|
||||
Not all machines support hardware-driven error report. Some of those
|
||||
|
|
|
@ -56,6 +56,8 @@ static DEFINE_SPINLOCK(ghes_lock);
|
|||
|
||||
static bool system_scanned;
|
||||
|
||||
static struct list_head *ghes_devs;
|
||||
|
||||
/* Memory Device - Type 17 of SMBIOS spec */
|
||||
struct memdev_dmi_entry {
|
||||
u8 type;
|
||||
|
@ -383,7 +385,7 @@ static struct notifier_block ghes_edac_mem_err_nb = {
|
|||
.priority = 0,
|
||||
};
|
||||
|
||||
int ghes_edac_register(struct ghes *ghes, struct device *dev)
|
||||
static int ghes_edac_register(struct device *dev)
|
||||
{
|
||||
bool fake = false;
|
||||
struct mem_ctl_info *mci;
|
||||
|
@ -502,7 +504,7 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
void ghes_edac_unregister(struct ghes *ghes)
|
||||
static void ghes_edac_unregister(struct ghes *ghes)
|
||||
{
|
||||
struct mem_ctl_info *mci;
|
||||
unsigned long flags;
|
||||
|
@ -535,3 +537,37 @@ void ghes_edac_unregister(struct ghes *ghes)
|
|||
unlock:
|
||||
mutex_unlock(&ghes_reg_mutex);
|
||||
}
|
||||
|
||||
static int __init ghes_edac_init(void)
|
||||
{
|
||||
struct ghes *g, *g_tmp;
|
||||
|
||||
ghes_devs = ghes_get_devices();
|
||||
if (!ghes_devs)
|
||||
return -ENODEV;
|
||||
|
||||
if (list_empty(ghes_devs)) {
|
||||
pr_info("GHES probing device list is empty");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {
|
||||
ghes_edac_register(g->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(ghes_edac_init);
|
||||
|
||||
static void __exit ghes_edac_exit(void)
|
||||
{
|
||||
struct ghes *g, *g_tmp;
|
||||
|
||||
list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {
|
||||
ghes_edac_unregister(g);
|
||||
}
|
||||
}
|
||||
module_exit(ghes_edac_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Output ACPI APEI/GHES BIOS detected errors via EDAC");
|
||||
|
|
|
@ -71,32 +71,14 @@ int ghes_register_vendor_record_notifier(struct notifier_block *nb);
|
|||
* @nb: pointer to the notifier_block structure of the vendor record handler.
|
||||
*/
|
||||
void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
|
||||
|
||||
struct list_head *ghes_get_devices(void);
|
||||
#else
|
||||
static inline struct list_head *ghes_get_devices(void) { return NULL; }
|
||||
#endif
|
||||
|
||||
int ghes_estatus_pool_init(int num_ghes);
|
||||
|
||||
/* From drivers/edac/ghes_edac.c */
|
||||
|
||||
#ifdef CONFIG_EDAC_GHES
|
||||
int ghes_edac_register(struct ghes *ghes, struct device *dev);
|
||||
|
||||
void ghes_edac_unregister(struct ghes *ghes);
|
||||
|
||||
struct list_head *ghes_get_devices(void);
|
||||
|
||||
#else
|
||||
static inline int ghes_edac_register(struct ghes *ghes, struct device *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void ghes_edac_unregister(struct ghes *ghes)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct list_head *ghes_get_devices(void) { return NULL; }
|
||||
#endif
|
||||
|
||||
static inline int acpi_hest_get_version(struct acpi_hest_generic_data *gdata)
|
||||
{
|
||||
return gdata->revision >> 8;
|
||||
|
|
Loading…
Reference in New Issue