Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: sysfb: Add sysfb_disable() helper function

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

+66 -6
+6
Documentation/driver-api/firmware/other_interfaces.rst
··· 13 13 .. kernel-doc:: drivers/firmware/edd.c 14 14 :internal: 15 15 16 + Generic System Framebuffers Interface 17 + ------------------------------------- 18 + 19 + .. kernel-doc:: drivers/firmware/sysfb.c 20 + :export: 21 + 16 22 Intel Stratix10 SoC Service Layer 17 23 --------------------------------- 18 24 Some features of the Intel Stratix10 SoC require a level of privilege
+48 -6
drivers/firmware/sysfb.c
··· 34 34 #include <linux/screen_info.h> 35 35 #include <linux/sysfb.h> 36 36 37 + static struct platform_device *pd; 38 + static DEFINE_MUTEX(disable_lock); 39 + static bool disabled; 40 + 41 + static bool sysfb_unregister(void) 42 + { 43 + if (IS_ERR_OR_NULL(pd)) 44 + return false; 45 + 46 + platform_device_unregister(pd); 47 + pd = NULL; 48 + 49 + return true; 50 + } 51 + 52 + /** 53 + * sysfb_disable() - disable the Generic System Framebuffers support 54 + * 55 + * This disables the registration of system framebuffer devices that match the 56 + * generic drivers that make use of the system framebuffer set up by firmware. 57 + * 58 + * It also unregisters a device if this was already registered by sysfb_init(). 59 + * 60 + * Context: The function can sleep. A @disable_lock mutex is acquired to serialize 61 + * against sysfb_init(), that registers a system framebuffer device. 62 + */ 63 + void sysfb_disable(void) 64 + { 65 + mutex_lock(&disable_lock); 66 + sysfb_unregister(); 67 + disabled = true; 68 + mutex_unlock(&disable_lock); 69 + } 70 + EXPORT_SYMBOL_GPL(sysfb_disable); 71 + 37 72 static __init int sysfb_init(void) 38 73 { 39 74 struct screen_info *si = &screen_info; 40 75 struct simplefb_platform_data mode; 41 - struct platform_device *pd; 42 76 const char *name; 43 77 bool compatible; 44 - int ret; 78 + int ret = 0; 79 + 80 + mutex_lock(&disable_lock); 81 + if (disabled) 82 + goto unlock_mutex; 45 83 46 84 /* try to create a simple-framebuffer device */ 47 85 compatible = sysfb_parse_mode(si, &mode); 48 86 if (compatible) { 49 87 pd = sysfb_create_simplefb(si, &mode); 50 88 if (!IS_ERR(pd)) 51 - return 0; 89 + goto unlock_mutex; 52 90 } 53 91 54 92 /* if the FB is incompatible, create a legacy framebuffer device */ ··· 98 60 name = "platform-framebuffer"; 99 61 100 62 pd = platform_device_alloc(name, 0); 101 - if (!pd) 102 - return -ENOMEM; 63 + if (!pd) { 64 + ret = -ENOMEM; 65 + goto unlock_mutex; 66 + } 103 67 104 68 sysfb_apply_efi_quirks(pd); 105 69 ··· 113 73 if (ret) 114 74 goto err; 115 75 116 - return 0; 76 + goto unlock_mutex; 117 77 err: 118 78 platform_device_put(pd); 79 + unlock_mutex: 80 + mutex_unlock(&disable_lock); 119 81 return ret; 120 82 } 121 83
+12
include/linux/sysfb.h
··· 55 55 int flags; 56 56 }; 57 57 58 + #ifdef CONFIG_SYSFB 59 + 60 + void sysfb_disable(void); 61 + 62 + #else /* CONFIG_SYSFB */ 63 + 64 + static inline void sysfb_disable(void) 65 + { 66 + } 67 + 68 + #endif /* CONFIG_SYSFB */ 69 + 58 70 #ifdef CONFIG_EFI 59 71 60 72 extern struct efifb_dmi_info efifb_dmi_list[];