| From cdb86f51e92d9e90b0cb021a75a40314290b0872 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 7 Jun 2022 20:23:35 +0200 |
| Subject: firmware: sysfb: Add sysfb_disable() helper function |
| |
| From: Javier Martinez Canillas <javierm@redhat.com> |
| |
| [ Upstream commit bde376e9de3c0bc55eedc8956b0f114c05531595 ] |
| |
| This can be used by subsystems to unregister a platform device registered |
| by sysfb and also to disable future platform device registration in sysfb. |
| |
| Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> |
| Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Link: https://patchwork.freedesktop.org/patch/msgid/20220607182338.344270-3-javierm@redhat.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../driver-api/firmware/other_interfaces.rst | 6 +++ |
| drivers/firmware/sysfb.c | 54 ++++++++++++++++--- |
| include/linux/sysfb.h | 12 +++++ |
| 3 files changed, 66 insertions(+), 6 deletions(-) |
| |
| diff --git a/Documentation/driver-api/firmware/other_interfaces.rst b/Documentation/driver-api/firmware/other_interfaces.rst |
| index b81794e0cfbb..06ac89adaafb 100644 |
| --- a/Documentation/driver-api/firmware/other_interfaces.rst |
| +++ b/Documentation/driver-api/firmware/other_interfaces.rst |
| @@ -13,6 +13,12 @@ EDD Interfaces |
| .. kernel-doc:: drivers/firmware/edd.c |
| :internal: |
| |
| +Generic System Framebuffers Interface |
| +------------------------------------- |
| + |
| +.. kernel-doc:: drivers/firmware/sysfb.c |
| + :export: |
| + |
| Intel Stratix10 SoC Service Layer |
| --------------------------------- |
| Some features of the Intel Stratix10 SoC require a level of privilege |
| diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c |
| index b032f40a92de..1f276f108cc9 100644 |
| --- a/drivers/firmware/sysfb.c |
| +++ b/drivers/firmware/sysfb.c |
| @@ -34,21 +34,59 @@ |
| #include <linux/screen_info.h> |
| #include <linux/sysfb.h> |
| |
| +static struct platform_device *pd; |
| +static DEFINE_MUTEX(disable_lock); |
| +static bool disabled; |
| + |
| +static bool sysfb_unregister(void) |
| +{ |
| + if (IS_ERR_OR_NULL(pd)) |
| + return false; |
| + |
| + platform_device_unregister(pd); |
| + pd = NULL; |
| + |
| + return true; |
| +} |
| + |
| +/** |
| + * sysfb_disable() - disable the Generic System Framebuffers support |
| + * |
| + * This disables the registration of system framebuffer devices that match the |
| + * generic drivers that make use of the system framebuffer set up by firmware. |
| + * |
| + * It also unregisters a device if this was already registered by sysfb_init(). |
| + * |
| + * Context: The function can sleep. A @disable_lock mutex is acquired to serialize |
| + * against sysfb_init(), that registers a system framebuffer device. |
| + */ |
| +void sysfb_disable(void) |
| +{ |
| + mutex_lock(&disable_lock); |
| + sysfb_unregister(); |
| + disabled = true; |
| + mutex_unlock(&disable_lock); |
| +} |
| +EXPORT_SYMBOL_GPL(sysfb_disable); |
| + |
| static __init int sysfb_init(void) |
| { |
| struct screen_info *si = &screen_info; |
| struct simplefb_platform_data mode; |
| - struct platform_device *pd; |
| const char *name; |
| bool compatible; |
| - int ret; |
| + int ret = 0; |
| + |
| + mutex_lock(&disable_lock); |
| + if (disabled) |
| + goto unlock_mutex; |
| |
| /* try to create a simple-framebuffer device */ |
| compatible = sysfb_parse_mode(si, &mode); |
| if (compatible) { |
| pd = sysfb_create_simplefb(si, &mode); |
| if (!IS_ERR(pd)) |
| - return 0; |
| + goto unlock_mutex; |
| } |
| |
| /* if the FB is incompatible, create a legacy framebuffer device */ |
| @@ -60,8 +98,10 @@ static __init int sysfb_init(void) |
| name = "platform-framebuffer"; |
| |
| pd = platform_device_alloc(name, 0); |
| - if (!pd) |
| - return -ENOMEM; |
| + if (!pd) { |
| + ret = -ENOMEM; |
| + goto unlock_mutex; |
| + } |
| |
| sysfb_apply_efi_quirks(pd); |
| |
| @@ -73,9 +113,11 @@ static __init int sysfb_init(void) |
| if (ret) |
| goto err; |
| |
| - return 0; |
| + goto unlock_mutex; |
| err: |
| platform_device_put(pd); |
| +unlock_mutex: |
| + mutex_unlock(&disable_lock); |
| return ret; |
| } |
| |
| diff --git a/include/linux/sysfb.h b/include/linux/sysfb.h |
| index 708152e9037b..8ba8b5be5567 100644 |
| --- a/include/linux/sysfb.h |
| +++ b/include/linux/sysfb.h |
| @@ -55,6 +55,18 @@ struct efifb_dmi_info { |
| int flags; |
| }; |
| |
| +#ifdef CONFIG_SYSFB |
| + |
| +void sysfb_disable(void); |
| + |
| +#else /* CONFIG_SYSFB */ |
| + |
| +static inline void sysfb_disable(void) |
| +{ |
| +} |
| + |
| +#endif /* CONFIG_SYSFB */ |
| + |
| #ifdef CONFIG_EFI |
| |
| extern struct efifb_dmi_info efifb_dmi_list[]; |
| -- |
| 2.35.1 |
| |