[PATCH v2] firmware: arm_sdei: Make sdei_unregister_ghes() return void
Rafael J. Wysocki
rafael at kernel.org
Wed Dec 21 05:53:05 PST 2022
On Tue, Dec 20, 2022 at 4:45 PM Uwe Kleine-König
<u.kleine-koenig at pengutronix.de> wrote:
>
> Unregistering a ghes shouldn't fail (because how can firmware refuse to
> disable an event on unregister). And the callers are not really in a
> position to handle errors. (Note: The return value of platform remove
> callbacks is ignored.) So make sdei_unregister_ghes() return void and
> add warnings at the few locations that can theoretically fail.
>
> !IS_ENABLED(CONFIG_ACPI_APEI_GHES) and
> !IS_ENABLED(CONFIG_ARM_SDE_INTERFACE) cannot be hit here, because if
> these aren't given, ghex_probe() already fails and so ghes_remove()
> isn't called.
>
> This change improves the behaviour in the error case. Without it the
> platform code emits a very generic (and so very unhelpful) error
> message. Now the warning is at least helpful.
>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
> ---
> Hello,
>
> Changes since (implicit) v1: Add the if (...) BUG() part to fix a linker
> error with CONFIG_ARM_SDE_INTERFACE disabled.
>
> Best regards
> Uwe
>
> drivers/acpi/apei/ghes.c | 19 ++++++++++++-------
> drivers/firmware/arm_sdei.c | 14 +++++++-------
> include/linux/arm_sdei.h | 2 +-
> 3 files changed, 20 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
> index 066dc1f5c235..7d705930e21b 100644
> --- a/drivers/acpi/apei/ghes.c
> +++ b/drivers/acpi/apei/ghes.c
> @@ -1275,12 +1275,20 @@ static int apei_sdei_register_ghes(struct ghes *ghes)
> ghes_sdei_critical_callback);
> }
>
> -static int apei_sdei_unregister_ghes(struct ghes *ghes)
> +static void apei_sdei_unregister_ghes(struct ghes *ghes)
> {
> + /*
> + * If CONFIG_ARM_SDE_INTERFACE isn't enabled apei_sdei_register_ghes()
> + * cannot have been called successfully. So ghes_remove() won't be
> + * called because either ghes_probe() failed or the notify type isn't
> + * ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED.
> + * Note the if statement below is necessary to prevent a linker error as
> + * the compiler has no chance to understand the above correlation.
> + */
> if (!IS_ENABLED(CONFIG_ARM_SDE_INTERFACE))
> - return -EOPNOTSUPP;
> + BUG();
Well, you could just provide an empty stub for the !CONFIG_ARM_SDE_INTERFACE.
It would be cleaner and probably fewer lines of code too.
>
> - return sdei_unregister_ghes(ghes);
> + sdei_unregister_ghes(ghes);
> }
>
> static int ghes_probe(struct platform_device *ghes_dev)
> @@ -1421,7 +1429,6 @@ static int ghes_probe(struct platform_device *ghes_dev)
>
> static int ghes_remove(struct platform_device *ghes_dev)
> {
> - int rc;
> struct ghes *ghes;
> struct acpi_hest_generic *generic;
>
> @@ -1455,9 +1462,7 @@ static int ghes_remove(struct platform_device *ghes_dev)
> ghes_nmi_remove(ghes);
> break;
> case ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED:
> - rc = apei_sdei_unregister_ghes(ghes);
> - if (rc)
> - return rc;
> + apei_sdei_unregister_ghes(ghes);
> break;
> default:
> BUG();
> diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c
> index 1e1a51510e83..7af619464183 100644
> --- a/drivers/firmware/arm_sdei.c
> +++ b/drivers/firmware/arm_sdei.c
> @@ -889,7 +889,7 @@ int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
> return err;
> }
>
> -int sdei_unregister_ghes(struct ghes *ghes)
> +void sdei_unregister_ghes(struct ghes *ghes)
> {
> int i;
> int err;
> @@ -897,16 +897,15 @@ int sdei_unregister_ghes(struct ghes *ghes)
>
> might_sleep();
>
> - if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
> - return -EOPNOTSUPP;
> -
> /*
> * The event may be running on another CPU. Disable it
> * to stop new events, then try to unregister a few times.
> */
> err = sdei_event_disable(event_num);
> - if (err)
> - return err;
> + if (err) {
> + dev_warn(ghes->dev, "Failed to disable event %u: %pe\n", event_num, ERR_PTR(err));
> + return;
> + }
>
> for (i = 0; i < 3; i++) {
> err = sdei_event_unregister(event_num);
> @@ -916,7 +915,8 @@ int sdei_unregister_ghes(struct ghes *ghes)
> schedule();
> }
>
> - return err;
> + if (err)
> + dev_warn(ghes->dev, "Failed to disable event %u: %pe\n", event_num, ERR_PTR(err));
> }
>
> static int sdei_get_conduit(struct platform_device *pdev)
> diff --git a/include/linux/arm_sdei.h b/include/linux/arm_sdei.h
> index 14dc461b0e82..0812af4530a4 100644
> --- a/include/linux/arm_sdei.h
> +++ b/include/linux/arm_sdei.h
> @@ -40,7 +40,7 @@ int sdei_event_disable(u32 event_num);
> /* GHES register/unregister helpers */
> int sdei_register_ghes(struct ghes *ghes, sdei_event_callback *normal_cb,
> sdei_event_callback *critical_cb);
> -int sdei_unregister_ghes(struct ghes *ghes);
> +void sdei_unregister_ghes(struct ghes *ghes);
>
> #ifdef CONFIG_ARM_SDE_INTERFACE
> /* For use by arch code when CPU hotplug notifiers are not appropriate. */
> --
> 2.38.1
>
More information about the linux-arm-kernel
mailing list