From ddde3c18b70061cc09b84a52624909349c212822 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:35 +0200 Subject: vt: More locking checks I honestly have no idea what the subtle differences between con_is_visible, con_is_fg (internal to vt.c) and con_is_bound are. But it looks like both vc->vc_display_fg and con_driver_map are protected by the console_lock, so probably better if we hold that when checking this. To do that I had to deinline the con_is_visible function. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Acked-by: Greg Kroah-Hartman Reviewed-by: Maarten Lankhorst Cc: Greg Kroah-Hartman Cc: Nicolas Pitre Cc: Martin Hostettler Cc: Adam Borowski Cc: Daniel Vetter Cc: Mikulas Patocka Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-5-daniel.vetter@ffwll.ch --- include/linux/console_struct.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index ed798e114663..24d4c16e3ae0 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -168,9 +168,6 @@ extern void vc_SAK(struct work_struct *work); #define CUR_DEFAULT CUR_UNDERLINE -static inline bool con_is_visible(const struct vc_data *vc) -{ - return *vc->vc_display_fg == vc; -} +bool con_is_visible(const struct vc_data *vc); #endif /* _LINUX_CONSOLE_STRUCT_H */ -- cgit v1.2.3 From 97b67986f1451c772b488d597310f95c14547cce Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:41 +0200 Subject: fbcon: call fbcon_fb_(un)registered directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit 6104c37094e729f3d4ce65797002112735d49cd1 Author: Daniel Vetter Date: Tue Aug 1 17:32:07 2017 +0200 fbcon: Make fbcon a built-time depency for fbdev we have a static dependency between fbcon and fbdev, and we can replace the indirection through the notifier chain with a function call. v2: Sam Ravnborg noticed that mach-pxa/am200epd.c has a notifier too, and listens to this. ... Looking at the code it seems to wait for some fb to show up, so that it can get the framebuffer base address from the fb_info struct. I suspect his is some firmware fbdev. Then it uses that information to let the real fbdev driver (metronomefb.c by the looks) get at the framebuffer memory. This doesn't looke like it's easy to fix (except by deleting the entire thing, seems untouched since 2008, we might be able to get away with that), so let's just stuff a few #ifdef into fb.h and fbmem.c and cry over them for a bit. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Greg Kroah-Hartman Cc: "Noralf Trønnes" Cc: Yisheng Xie Cc: Peter Rosin Cc: "Michał Mirosław" Cc: Thomas Zimmermann Cc: Mikulas Patocka Cc: linux-fbdev@vger.kernel.org Cc: Daniel Mack Cc: Haojian Zhuang Cc: Robert Jarzmik Cc: Konstantin Khorenko Cc: Prarit Bhargava Cc: Gerd Hoffmann Cc: Steve Sakoman Cc: Steve Sakoman Cc: linux-arm-kernel@lists.infradead.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-11-daniel.vetter@ffwll.ch --- arch/arm/mach-pxa/am200epd.c | 13 +++++++++++-- drivers/video/fbdev/core/fbcon.c | 14 +++----------- drivers/video/fbdev/core/fbmem.c | 24 +++++++++++++++++------- include/linux/fb.h | 7 +++++-- include/linux/fbcon.h | 4 ++++ 5 files changed, 40 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c index 50e18ed37fa6..cac0bb09db14 100644 --- a/arch/arm/mach-pxa/am200epd.c +++ b/arch/arm/mach-pxa/am200epd.c @@ -347,8 +347,17 @@ int __init am200_init(void) { int ret; - /* before anything else, we request notification for any fb - * creation events */ + /* + * Before anything else, we request notification for any fb + * creation events. + * + * FIXME: This is terrible and needs to be nuked. The notifier is used + * to get at the fb base address from the boot splash fb driver, which + * is then passed to metronomefb. Instaed of metronomfb or this board + * support file here figuring this out on their own. + * + * See also the #ifdef in fbmem.c. + */ fb_register_client(&am200_fb_notif); pxa2xx_mfp_config(ARRAY_AND_SIZE(am200_pin_config)); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 9c14eab77d99..c12fc98035e0 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -3119,14 +3119,14 @@ static int fbcon_fb_unbind(int idx) } /* called with console_lock held */ -static int fbcon_fb_unregistered(struct fb_info *info) +void fbcon_fb_unregistered(struct fb_info *info) { int i, idx; WARN_CONSOLE_UNLOCKED(); if (deferred_takeover) - return 0; + return; idx = info->node; for (i = first_fb_vc; i <= last_fb_vc; i++) { @@ -3155,8 +3155,6 @@ static int fbcon_fb_unregistered(struct fb_info *info) if (!num_registered_fb) do_unregister_con_driver(&fb_con); - - return 0; } /* called with console_lock held */ @@ -3215,7 +3213,7 @@ static inline void fbcon_select_primary(struct fb_info *info) #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ /* called with console_lock held */ -static int fbcon_fb_registered(struct fb_info *info) +int fbcon_fb_registered(struct fb_info *info) { int ret = 0, i, idx; @@ -3359,12 +3357,6 @@ static int fbcon_event_notify(struct notifier_block *self, idx = info->node; ret = fbcon_fb_unbind(idx); break; - case FB_EVENT_FB_REGISTERED: - ret = fbcon_fb_registered(info); - break; - case FB_EVENT_FB_UNREGISTERED: - ret = fbcon_fb_unregistered(info); - break; case FB_EVENT_SET_CONSOLE_MAP: /* called with console lock held */ con2fb = event->data; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 8ba674ffb3c9..bed7698ad18a 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1660,7 +1660,6 @@ MODULE_PARM_DESC(lockless_register_fb, static int do_register_framebuffer(struct fb_info *fb_info) { int i, ret; - struct fb_event event; struct fb_videomode mode; if (fb_check_foreignness(fb_info)) @@ -1723,7 +1722,14 @@ static int do_register_framebuffer(struct fb_info *fb_info) fb_add_videomode(&mode, &fb_info->modelist); registered_fb[i] = fb_info; - event.info = fb_info; +#ifdef CONFIG_GUMSTIX_AM200EPD + { + struct fb_event event; + event.info = fb_info; + fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); + } +#endif + if (!lockless_register_fb) console_lock(); else @@ -1732,9 +1738,8 @@ static int do_register_framebuffer(struct fb_info *fb_info) ret = -ENODEV; goto unlock_console; } - ret = 0; - fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); + ret = fbcon_fb_registered(fb_info); unlock_fb_info(fb_info); unlock_console: if (!lockless_register_fb) @@ -1771,7 +1776,6 @@ static int __unlink_framebuffer(struct fb_info *fb_info); static int do_unregister_framebuffer(struct fb_info *fb_info) { - struct fb_event event; int ret; ret = unbind_console(fb_info); @@ -1789,9 +1793,15 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) registered_fb[fb_info->node] = NULL; num_registered_fb--; fb_cleanup_device(fb_info); - event.info = fb_info; +#ifdef CONFIG_GUMSTIX_AM200EPD + { + struct fb_event event; + event.info = fb_info; + fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + } +#endif console_lock(); - fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + fbcon_fb_unregistered(fb_info); console_unlock(); /* this may free fb info */ diff --git a/include/linux/fb.h b/include/linux/fb.h index f52ef0ad6781..288175fafaf6 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -136,10 +136,13 @@ struct fb_cursor_user { #define FB_EVENT_RESUME 0x03 /* An entry from the modelist was removed */ #define FB_EVENT_MODE_DELETE 0x04 -/* A driver registered itself */ + +#ifdef CONFIG_GUMSTIX_AM200EPD +/* only used by mach-pxa/am200epd.c */ #define FB_EVENT_FB_REGISTERED 0x05 -/* A driver unregistered itself */ #define FB_EVENT_FB_UNREGISTERED 0x06 +#endif + /* CONSOLE-SPECIFIC: get console to framebuffer mapping */ #define FB_EVENT_GET_CONSOLE_MAP 0x07 /* CONSOLE-SPECIFIC: set console to framebuffer mapping */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index f68a7db14165..94a71e9e1257 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -4,9 +4,13 @@ #ifdef CONFIG_FRAMEBUFFER_CONSOLE void __init fb_console_init(void); void __exit fb_console_exit(void); +int fbcon_fb_registered(struct fb_info *info); +void fbcon_fb_unregistered(struct fb_info *info); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} +static inline int fbcon_fb_registered(struct fb_info *info) { return 0; } +static inline void fbcon_fb_unregistered(struct fb_info *info) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From cf4a3ae4ef3399179166a464af1d6b172225bef4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:47 +0200 Subject: fbdev: lock_fb_info cannot fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ever since commit c47747fde931c02455683bd00ea43eaa62f35b0e Author: Linus Torvalds Date: Wed May 11 14:58:34 2011 -0700 fbmem: make read/write/ioctl use the frame buffer at open time fbdev has gained proper refcounting for the fbinfo attached to any open files, which means that the backing driver (stored in fb_info->fbops) cannot untimely disappear anymore. The only thing that can happen is that the entire device just outright disappears and gets unregistered, but file_fb_info does check for that. Except that it's racy - it only checks once at the start of a file_ops, there's no guarantee that the underlying fbdev won't untimely disappear. Aside: A proper way to fix that race is probably to replicate the srcu trickery we've rolled out in drm. But given that this race has existed since forever it's probably not one we need to fix right away. do_unregister_framebuffer also nowhere clears fb_info->fbops, hence the check in lock_fb_info can't possible catch a disappearing fbdev later on. Long story short: Ever since the above commit the fb_info->fbops checks have essentially become dead code. Remove this all. Aside from the file_ops callbacks, and stuff called from there there's only register/unregister code left. If that goes wrong a driver managed to register/unregister a device instance twice or in the wrong order. That's just a driver bug. v2: - fb_mmap had an open-coded version of the fbinfo->fops check, because it doesn't need the fbinfo->lock. Delete that too. - Use the wrapper function in fb_open/release now, since no difference anymore. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Yisheng Xie Cc: Sergey Senozhatsky Cc: "Noralf Trønnes" Cc: Peter Rosin Cc: "Michał Mirosław" Cc: Mikulas Patocka Cc: "Gustavo A. R. Silva" Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-17-daniel.vetter@ffwll.ch --- drivers/video/fbdev/core/fbcmap.c | 6 +--- drivers/video/fbdev/core/fbcon.c | 3 +- drivers/video/fbdev/core/fbmem.c | 73 +++++++++------------------------------ include/linux/fb.h | 5 ++- 4 files changed, 23 insertions(+), 64 deletions(-) (limited to 'include') diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c index 2811c4afde01..e5ae33c1a8e8 100644 --- a/drivers/video/fbdev/core/fbcmap.c +++ b/drivers/video/fbdev/core/fbcmap.c @@ -285,11 +285,7 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) goto out; } umap.start = cmap->start; - if (!lock_fb_info(info)) { - rc = -ENODEV; - goto out; - } - + lock_fb_info(info); rc = fb_set_cmap(&umap, info); unlock_fb_info(info); out: diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index c12fc98035e0..f7f3eb0f1893 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2364,8 +2364,7 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, } - if (!lock_fb_info(info)) - return; + lock_fb_info(info); event.info = info; event.data = ␣ fb_notifier_call_chain(FB_EVENT_CONBLANK, &event); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index bed7698ad18a..d73762324ca2 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -80,17 +80,6 @@ static void put_fb_info(struct fb_info *fb_info) fb_info->fbops->fb_destroy(fb_info); } -int lock_fb_info(struct fb_info *info) -{ - mutex_lock(&info->lock); - if (!info->fbops) { - mutex_unlock(&info->lock); - return 0; - } - return 1; -} -EXPORT_SYMBOL(lock_fb_info); - /* * Helpers */ @@ -1121,8 +1110,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, switch (cmd) { case FBIOGET_VSCREENINFO: - if (!lock_fb_info(info)) - return -ENODEV; + lock_fb_info(info); var = info->var; unlock_fb_info(info); @@ -1132,10 +1120,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; console_lock(); - if (!lock_fb_info(info)) { - console_unlock(); - return -ENODEV; - } + lock_fb_info(info); info->flags |= FBINFO_MISC_USEREVENT; ret = fb_set_var(info, &var); info->flags &= ~FBINFO_MISC_USEREVENT; @@ -1145,8 +1130,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, ret = -EFAULT; break; case FBIOGET_FSCREENINFO: - if (!lock_fb_info(info)) - return -ENODEV; + lock_fb_info(info); fix = info->fix; if (info->flags & FBINFO_HIDE_SMEM_START) fix.smem_start = 0; @@ -1162,8 +1146,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, case FBIOGETCMAP: if (copy_from_user(&cmap, argp, sizeof(cmap))) return -EFAULT; - if (!lock_fb_info(info)) - return -ENODEV; + lock_fb_info(info); cmap_from = info->cmap; unlock_fb_info(info); ret = fb_cmap_to_user(&cmap_from, &cmap); @@ -1172,10 +1155,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; console_lock(); - if (!lock_fb_info(info)) { - console_unlock(); - return -ENODEV; - } + lock_fb_info(info); ret = fb_pan_display(info, &var); unlock_fb_info(info); console_unlock(); @@ -1192,8 +1172,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, return -EINVAL; con2fb.framebuffer = -1; event.data = &con2fb; - if (!lock_fb_info(info)) - return -ENODEV; + lock_fb_info(info); event.info = info; fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); unlock_fb_info(info); @@ -1214,10 +1193,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, } event.data = &con2fb; console_lock(); - if (!lock_fb_info(info)) { - console_unlock(); - return -ENODEV; - } + lock_fb_info(info); event.info = info; ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); unlock_fb_info(info); @@ -1225,10 +1201,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, break; case FBIOBLANK: console_lock(); - if (!lock_fb_info(info)) { - console_unlock(); - return -ENODEV; - } + lock_fb_info(info); info->flags |= FBINFO_MISC_USEREVENT; ret = fb_blank(info, arg); info->flags &= ~FBINFO_MISC_USEREVENT; @@ -1236,8 +1209,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, console_unlock(); break; default: - if (!lock_fb_info(info)) - return -ENODEV; + lock_fb_info(info); fb = info->fbops; if (fb->fb_ioctl) ret = fb->fb_ioctl(info, cmd, arg); @@ -1357,8 +1329,7 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, { struct fb_fix_screeninfo fix; - if (!lock_fb_info(info)) - return -ENODEV; + lock_fb_info(info); fix = info->fix; if (info->flags & FBINFO_HIDE_SMEM_START) fix.smem_start = 0; @@ -1418,8 +1389,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) if (!info) return -ENODEV; fb = info->fbops; - if (!fb) - return -ENODEV; mutex_lock(&info->mm_lock); if (fb->fb_mmap) { int res; @@ -1483,7 +1452,7 @@ __releases(&info->lock) if (IS_ERR(info)) return PTR_ERR(info); - mutex_lock(&info->lock); + lock_fb_info(info); if (!try_module_get(info->fbops->owner)) { res = -ENODEV; goto out; @@ -1499,7 +1468,7 @@ __releases(&info->lock) fb_deferred_io_open(info, inode, file); #endif out: - mutex_unlock(&info->lock); + unlock_fb_info(info); if (res) put_fb_info(info); return res; @@ -1512,11 +1481,11 @@ __releases(&info->lock) { struct fb_info * const info = file->private_data; - mutex_lock(&info->lock); + lock_fb_info(info); if (info->fbops->fb_release) info->fbops->fb_release(info,1); module_put(info->fbops->owner); - mutex_unlock(&info->lock); + unlock_fb_info(info); put_fb_info(info); return 0; } @@ -1734,14 +1703,10 @@ static int do_register_framebuffer(struct fb_info *fb_info) console_lock(); else atomic_inc(&ignore_console_lock_warning); - if (!lock_fb_info(fb_info)) { - ret = -ENODEV; - goto unlock_console; - } - + lock_fb_info(fb_info); ret = fbcon_fb_registered(fb_info); unlock_fb_info(fb_info); -unlock_console: + if (!lockless_register_fb) console_unlock(); else @@ -1759,11 +1724,7 @@ static int unbind_console(struct fb_info *fb_info) return -EINVAL; console_lock(); - if (!lock_fb_info(fb_info)) { - console_unlock(); - return -ENODEV; - } - + lock_fb_info(fb_info); event.info = fb_info; ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); unlock_fb_info(fb_info); diff --git a/include/linux/fb.h b/include/linux/fb.h index 288175fafaf6..aa8f18163151 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -663,7 +663,10 @@ extern struct class *fb_class; for (i = 0; i < FB_MAX; i++) \ if (!registered_fb[i]) {} else -extern int lock_fb_info(struct fb_info *info); +static inline void lock_fb_info(struct fb_info *info) +{ + mutex_lock(&info->lock); +} static inline void unlock_fb_info(struct fb_info *info) { -- cgit v1.2.3 From 0e0f3250d4402d60f4571d076ab27d5af049853e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:48 +0200 Subject: fbcon: call fbcon_fb_bind directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also remove the error return value. That's all errors for either driver bugs (trying to unbind something that isn't bound), or errors of the new driver that will take over. There's nothing the outgoing driver can do about this anyway, so switch over to void. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Sergey Senozhatsky Cc: Peter Rosin Cc: Kees Cook Cc: Konstantin Khorenko Cc: Yisheng Xie Cc: "Michał Mirosław" Cc: Mikulas Patocka Cc: Thomas Zimmermann Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-18-daniel.vetter@ffwll.ch --- drivers/video/fbdev/core/fbcon.c | 24 +++++++----------------- drivers/video/fbdev/core/fbmem.c | 7 ++----- include/linux/fb.h | 2 -- include/linux/fbcon.h | 2 ++ 4 files changed, 11 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index f7f3eb0f1893..d1e37afa6f80 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -3046,7 +3046,7 @@ static int fbcon_mode_deleted(struct fb_info *info, } #ifdef CONFIG_VT_HW_CONSOLE_BINDING -static int fbcon_unbind(void) +static void fbcon_unbind(void) { int ret; @@ -3055,25 +3055,21 @@ static int fbcon_unbind(void) if (!ret) fbcon_has_console_bind = 0; - - return ret; } #else -static inline int fbcon_unbind(void) -{ - return -EINVAL; -} +static inline void fbcon_unbind(void) {} #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ /* called with console_lock held */ -static int fbcon_fb_unbind(int idx) +void fbcon_fb_unbind(struct fb_info *info) { int i, new_idx = -1, ret = 0; + int idx = info->node; WARN_CONSOLE_UNLOCKED(); if (!fbcon_has_console_bind) - return 0; + return; for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map[i] != idx && @@ -3106,15 +3102,13 @@ static int fbcon_fb_unbind(int idx) idx, 0); if (ret) { con2fb_map[i] = idx; - return ret; + return; } } } } - ret = fbcon_unbind(); + fbcon_unbind(); } - - return ret; } /* called with console_lock held */ @@ -3352,10 +3346,6 @@ static int fbcon_event_notify(struct notifier_block *self, mode = event->data; ret = fbcon_mode_deleted(info, mode); break; - case FB_EVENT_FB_UNBIND: - idx = info->node; - ret = fbcon_fb_unbind(idx); - break; case FB_EVENT_SET_CONSOLE_MAP: /* called with console lock held */ con2fb = event->data; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index d73762324ca2..f3fc2e5b193c 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1716,8 +1716,6 @@ static int do_register_framebuffer(struct fb_info *fb_info) static int unbind_console(struct fb_info *fb_info) { - struct fb_event event; - int ret; int i = fb_info->node; if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) @@ -1725,12 +1723,11 @@ static int unbind_console(struct fb_info *fb_info) console_lock(); lock_fb_info(fb_info); - event.info = fb_info; - ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); + fbcon_fb_unbind(fb_info); unlock_fb_info(fb_info); console_unlock(); - return ret; + return 0; } static int __unlink_framebuffer(struct fb_info *fb_info); diff --git a/include/linux/fb.h b/include/linux/fb.h index aa8f18163151..b6ce041d9e13 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -158,8 +158,6 @@ struct fb_cursor_user { #define FB_EVENT_CONBLANK 0x0C /* Get drawing requirements */ #define FB_EVENT_GET_REQ 0x0D -/* Unbind from the console if possible */ -#define FB_EVENT_FB_UNBIND 0x0E /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F /* A hardware display blank early change occurred */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index 94a71e9e1257..38d44fdb6d14 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -6,11 +6,13 @@ void __init fb_console_init(void); void __exit fb_console_exit(void); int fbcon_fb_registered(struct fb_info *info); void fbcon_fb_unregistered(struct fb_info *info); +void fbcon_fb_unbind(struct fb_info *info); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} static inline int fbcon_fb_registered(struct fb_info *info) { return 0; } static inline void fbcon_fb_unregistered(struct fb_info *info) {} +static inline void fbcon_fb_unbind(struct fb_info *info) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From deb00d2785bedd379caa7aaf18c1ffb824580b9d Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:49 +0200 Subject: fbdev: make unregister/unlink functions not fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Except for driver bugs (which we'll catch with a WARN_ON) this is only to report failures of the new driver taking over the console. There's nothing the outgoing driver can do about that, and no one ever bothered to actually look at these return values. So remove them all. v2: fixup unregister_framebuffer in savagefb, fbtft, ivtvfb, and neofb drivers, reported by kbuild. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: "Michał Mirosław" Cc: Peter Rosin Cc: Hans de Goede Cc: Mikulas Patocka Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-19-daniel.vetter@ffwll.ch --- drivers/media/pci/ivtv/ivtvfb.c | 6 +-- drivers/staging/fbtft/fbtft-core.c | 4 +- drivers/video/fbdev/core/fbmem.c | 73 +++++++++------------------- drivers/video/fbdev/neofb.c | 9 +--- drivers/video/fbdev/savage/savagefb_driver.c | 9 +--- include/linux/fb.h | 4 +- 6 files changed, 31 insertions(+), 74 deletions(-) (limited to 'include') diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c index 66be490ec563..299ff032f528 100644 --- a/drivers/media/pci/ivtv/ivtvfb.c +++ b/drivers/media/pci/ivtv/ivtvfb.c @@ -1246,11 +1246,7 @@ static int ivtvfb_callback_cleanup(struct device *dev, void *p) struct osd_info *oi = itv->osd_info; if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { - IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", - itv->instance); - return 0; - } + unregister_framebuffer(&itv->osd_info->ivtvfb_info); IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); itv->ivtvfb_restore = NULL; ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 9b07badf4c6c..7cbc1bdd2d8a 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -891,7 +891,9 @@ int fbtft_unregister_framebuffer(struct fb_info *fb_info) if (par->fbtftops.unregister_backlight) par->fbtftops.unregister_backlight(par); fbtft_sysfs_exit(par); - return unregister_framebuffer(fb_info); + unregister_framebuffer(fb_info); + + return 0; } EXPORT_SYMBOL(fbtft_unregister_framebuffer); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index f3fc2e5b193c..f3bcad30d3ba 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1590,13 +1590,13 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, return false; } -static int do_unregister_framebuffer(struct fb_info *fb_info); +static void do_unregister_framebuffer(struct fb_info *fb_info); #define VGA_FB_PHYS 0xA0000 -static int do_remove_conflicting_framebuffers(struct apertures_struct *a, - const char *name, bool primary) +static void do_remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary) { - int i, ret; + int i; /* check all firmware fbs and kick off if the base addr overlaps */ for_each_registered_fb(i) { @@ -1612,13 +1612,9 @@ static int do_remove_conflicting_framebuffers(struct apertures_struct *a, printk(KERN_INFO "fb%d: switching to %s from %s\n", i, name, registered_fb[i]->fix.id); - ret = do_unregister_framebuffer(registered_fb[i]); - if (ret) - return ret; + do_unregister_framebuffer(registered_fb[i]); } } - - return 0; } static bool lockless_register_fb; @@ -1634,11 +1630,9 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (fb_check_foreignness(fb_info)) return -ENOSYS; - ret = do_remove_conflicting_framebuffers(fb_info->apertures, - fb_info->fix.id, - fb_is_primary_device(fb_info)); - if (ret) - return ret; + do_remove_conflicting_framebuffers(fb_info->apertures, + fb_info->fix.id, + fb_is_primary_device(fb_info)); if (num_registered_fb == FB_MAX) return -ENXIO; @@ -1714,32 +1708,25 @@ static int do_register_framebuffer(struct fb_info *fb_info) return ret; } -static int unbind_console(struct fb_info *fb_info) +static void unbind_console(struct fb_info *fb_info) { int i = fb_info->node; - if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) - return -EINVAL; + if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) + return; console_lock(); lock_fb_info(fb_info); fbcon_fb_unbind(fb_info); unlock_fb_info(fb_info); console_unlock(); - - return 0; } -static int __unlink_framebuffer(struct fb_info *fb_info); +static void __unlink_framebuffer(struct fb_info *fb_info); -static int do_unregister_framebuffer(struct fb_info *fb_info) +static void do_unregister_framebuffer(struct fb_info *fb_info) { - int ret; - - ret = unbind_console(fb_info); - - if (ret) - return -EINVAL; + unbind_console(fb_info); pm_vt_switch_unregister(fb_info->dev); @@ -1764,36 +1751,27 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) /* this may free fb info */ put_fb_info(fb_info); - return 0; } -static int __unlink_framebuffer(struct fb_info *fb_info) +static void __unlink_framebuffer(struct fb_info *fb_info) { int i; i = fb_info->node; - if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) - return -EINVAL; + if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) + return; if (fb_info->dev) { device_destroy(fb_class, MKDEV(FB_MAJOR, i)); fb_info->dev = NULL; } - - return 0; } -int unlink_framebuffer(struct fb_info *fb_info) +void unlink_framebuffer(struct fb_info *fb_info) { - int ret; - - ret = __unlink_framebuffer(fb_info); - if (ret) - return ret; + __unlink_framebuffer(fb_info); unbind_console(fb_info); - - return 0; } EXPORT_SYMBOL(unlink_framebuffer); @@ -1810,7 +1788,6 @@ EXPORT_SYMBOL(unlink_framebuffer); int remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary) { - int ret; bool do_free = false; if (!a) { @@ -1824,13 +1801,13 @@ int remove_conflicting_framebuffers(struct apertures_struct *a, } mutex_lock(®istration_lock); - ret = do_remove_conflicting_framebuffers(a, name, primary); + do_remove_conflicting_framebuffers(a, name, primary); mutex_unlock(®istration_lock); if (do_free) kfree(a); - return ret; + return 0; } EXPORT_SYMBOL(remove_conflicting_framebuffers); @@ -1927,16 +1904,12 @@ EXPORT_SYMBOL(register_framebuffer); * that the driver implements fb_open() and fb_release() to * check that no processes are using the device. */ -int +void unregister_framebuffer(struct fb_info *fb_info) { - int ret; - mutex_lock(®istration_lock); - ret = do_unregister_framebuffer(fb_info); + do_unregister_framebuffer(fb_info); mutex_unlock(®istration_lock); - - return ret; } EXPORT_SYMBOL(unregister_framebuffer); diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c index 5d3a444083f7..b770946a0920 100644 --- a/drivers/video/fbdev/neofb.c +++ b/drivers/video/fbdev/neofb.c @@ -2122,14 +2122,7 @@ static void neofb_remove(struct pci_dev *dev) DBG("neofb_remove"); if (info) { - /* - * If unregister_framebuffer fails, then - * we will be leaving hooks that could cause - * oopsen laying around. - */ - if (unregister_framebuffer(info)) - printk(KERN_WARNING - "neofb: danger danger! Oopsen imminent!\n"); + unregister_framebuffer(info); neo_unmap_video(info); fb_destroy_modedb(info->monspecs.modedb); diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index 47b78f0138c3..512789f5f884 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -2333,14 +2333,7 @@ static void savagefb_remove(struct pci_dev *dev) DBG("savagefb_remove"); if (info) { - /* - * If unregister_framebuffer fails, then - * we will be leaving hooks that could cause - * oopsen laying around. - */ - if (unregister_framebuffer(info)) - printk(KERN_WARNING "savagefb: danger danger! " - "Oopsen imminent!\n"); + unregister_framebuffer(info); #ifdef CONFIG_FB_SAVAGE_I2C savagefb_delete_i2c_busses(info); diff --git a/include/linux/fb.h b/include/linux/fb.h index b6ce041d9e13..b90cf7d56bd8 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -634,8 +634,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); -extern int unregister_framebuffer(struct fb_info *fb_info); -extern int unlink_framebuffer(struct fb_info *fb_info); +extern void unregister_framebuffer(struct fb_info *fb_info); +extern void unlink_framebuffer(struct fb_info *fb_info); extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, const char *name); extern int remove_conflicting_framebuffers(struct apertures_struct *a, -- cgit v1.2.3 From 50c5056356340c8b5be90440d2f32fec8c47a7c3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:52 +0200 Subject: fbdev: directly call fbcon_suspended/resumed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the sh_mobile notifier removed we can just directly call the fbcon code here. v2: Remove now unused local variable. v3: fixup !CONFIG_FRAMEBUFFER_CONSOLE, noticed by kbuild Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Greg Kroah-Hartman Cc: Prarit Bhargava Cc: Kees Cook Cc: Konstantin Khorenko Cc: Yisheng Xie Cc: "Michał Mirosław" Cc: Peter Rosin Cc: Mikulas Patocka Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-22-daniel.vetter@ffwll.ch --- drivers/video/fbdev/core/fbcon.c | 10 ++-------- drivers/video/fbdev/core/fbmem.c | 7 ++----- include/linux/fb.h | 8 -------- include/linux/fbcon.h | 4 ++++ 4 files changed, 8 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index d1e37afa6f80..9994111f2563 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2919,7 +2919,7 @@ static int fbcon_set_origin(struct vc_data *vc) return 0; } -static void fbcon_suspended(struct fb_info *info) +void fbcon_suspended(struct fb_info *info) { struct vc_data *vc = NULL; struct fbcon_ops *ops = info->fbcon_par; @@ -2932,7 +2932,7 @@ static void fbcon_suspended(struct fb_info *info) fbcon_cursor(vc, CM_ERASE); } -static void fbcon_resumed(struct fb_info *info) +void fbcon_resumed(struct fb_info *info) { struct vc_data *vc; struct fbcon_ops *ops = info->fbcon_par; @@ -3330,12 +3330,6 @@ static int fbcon_event_notify(struct notifier_block *self, int idx, ret = 0; switch(action) { - case FB_EVENT_SUSPEND: - fbcon_suspended(info); - break; - case FB_EVENT_RESUME: - fbcon_resumed(info); - break; case FB_EVENT_MODE_CHANGE: fbcon_modechanged(info); break; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index bee45e9405b8..73269dedcd45 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1917,17 +1917,14 @@ EXPORT_SYMBOL(unregister_framebuffer); */ void fb_set_suspend(struct fb_info *info, int state) { - struct fb_event event; - WARN_CONSOLE_UNLOCKED(); - event.info = info; if (state) { - fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); + fbcon_suspended(info); info->state = FBINFO_STATE_SUSPENDED; } else { info->state = FBINFO_STATE_RUNNING; - fb_notifier_call_chain(FB_EVENT_RESUME, &event); + fbcon_resumed(info); } } EXPORT_SYMBOL(fb_set_suspend); diff --git a/include/linux/fb.h b/include/linux/fb.h index b90cf7d56bd8..794b386415b7 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -126,14 +126,6 @@ struct fb_cursor_user { /* The resolution of the passed in fb_info about to change */ #define FB_EVENT_MODE_CHANGE 0x01 -/* The display on this fb_info is being suspended, no access to the - * framebuffer is allowed any more after that call returns - */ -#define FB_EVENT_SUSPEND 0x02 -/* The display on this fb_info was resumed, you can restore the display - * if you own it - */ -#define FB_EVENT_RESUME 0x03 /* An entry from the modelist was removed */ #define FB_EVENT_MODE_DELETE 0x04 diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index 38d44fdb6d14..790c42ec7b5d 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -7,12 +7,16 @@ void __exit fb_console_exit(void); int fbcon_fb_registered(struct fb_info *info); void fbcon_fb_unregistered(struct fb_info *info); void fbcon_fb_unbind(struct fb_info *info); +void fbcon_suspended(struct fb_info *info); +void fbcon_resumed(struct fb_info *info); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} static inline int fbcon_fb_registered(struct fb_info *info) { return 0; } static inline void fbcon_fb_unregistered(struct fb_info *info) {} static inline void fbcon_fb_unbind(struct fb_info *info) {} +static inline void fbcon_suspended(struct fb_info *info) {} +static inline void fbcon_resumed(struct fb_info *info) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From 13ff178ccd6d3b8074c542a911300b79c4eec255 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:53 +0200 Subject: fbcon: Call fbcon_mode_deleted/new_modelist directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'm not entirely clear on what new_modelist actually does, it seems exclusively for a sysfs interface. Which in the end does amount to a normal fb_set_par to check the mode, but then takes a different path in both fbmem.c and fbcon.c. I have no idea why these 2 paths are different, but then I also don't really want to find out. So just do the simple conversion to a direct function call. v2: static inline for the dummy versions, I forgot. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Mikulas Patocka Cc: Sergey Senozhatsky Cc: Kees Cook Cc: Peter Rosin Cc: Yisheng Xie Cc: "Michał Mirosław" Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-23-daniel.vetter@ffwll.ch --- drivers/video/fbdev/core/fbcon.c | 14 +++----------- drivers/video/fbdev/core/fbmem.c | 22 +++++++--------------- include/linux/fb.h | 5 ----- include/linux/fbcon.h | 6 ++++++ 4 files changed, 16 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 9994111f2563..24bd6cd270d5 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -3019,8 +3019,8 @@ static void fbcon_set_all_vcs(struct fb_info *info) fbcon_modechanged(info); } -static int fbcon_mode_deleted(struct fb_info *info, - struct fb_videomode *mode) +int fbcon_mode_deleted(struct fb_info *info, + struct fb_videomode *mode) { struct fb_info *fb_info; struct fbcon_display *p; @@ -3262,7 +3262,7 @@ static void fbcon_fb_blanked(struct fb_info *info, int blank) ops->blank_state = blank; } -static void fbcon_new_modelist(struct fb_info *info) +void fbcon_new_modelist(struct fb_info *info) { int i; struct vc_data *vc; @@ -3324,7 +3324,6 @@ static int fbcon_event_notify(struct notifier_block *self, { struct fb_event *event = data; struct fb_info *info = event->info; - struct fb_videomode *mode; struct fb_con2fbmap *con2fb; struct fb_blit_caps *caps; int idx, ret = 0; @@ -3336,10 +3335,6 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_MODE_CHANGE_ALL: fbcon_set_all_vcs(info); break; - case FB_EVENT_MODE_DELETE: - mode = event->data; - ret = fbcon_mode_deleted(info, mode); - break; case FB_EVENT_SET_CONSOLE_MAP: /* called with console lock held */ con2fb = event->data; @@ -3353,9 +3348,6 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_BLANK: fbcon_fb_blanked(info, *(int *)event->data); break; - case FB_EVENT_NEW_MODELIST: - fbcon_new_modelist(info); - break; case FB_EVENT_GET_REQ: caps = event->data; fbcon_get_requirement(info, caps); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 73269dedcd45..cbdd141e7695 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -966,16 +966,11 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) /* make sure we don't delete the videomode of current var */ ret = fb_mode_is_equal(&mode1, &mode2); - if (!ret) { - struct fb_event event; - - event.info = info; - event.data = &mode1; - ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event); - } + if (!ret) + fbcon_mode_deleted(info, &mode1); if (!ret) - fb_delete_videomode(&mode1, &info->modelist); + fb_delete_videomode(&mode1, &info->modelist); ret = (ret) ? -EINVAL : 0; @@ -1992,7 +1987,6 @@ subsys_initcall(fbmem_init); int fb_new_modelist(struct fb_info *info) { - struct fb_event event; struct fb_var_screeninfo var = info->var; struct list_head *pos, *n; struct fb_modelist *modelist; @@ -2012,14 +2006,12 @@ int fb_new_modelist(struct fb_info *info) } } - err = 1; + if (list_empty(&info->modelist)) + return 1; - if (!list_empty(&info->modelist)) { - event.info = info; - err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); - } + fbcon_new_modelist(info); - return err; + return 0; } MODULE_LICENSE("GPL"); diff --git a/include/linux/fb.h b/include/linux/fb.h index 794b386415b7..7a788ed8c7b5 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -126,8 +126,6 @@ struct fb_cursor_user { /* The resolution of the passed in fb_info about to change */ #define FB_EVENT_MODE_CHANGE 0x01 -/* An entry from the modelist was removed */ -#define FB_EVENT_MODE_DELETE 0x04 #ifdef CONFIG_GUMSTIX_AM200EPD /* only used by mach-pxa/am200epd.c */ @@ -142,9 +140,6 @@ struct fb_cursor_user { /* A hardware display blank change occurred */ #define FB_EVENT_BLANK 0x09 /* Private modelist is to be replaced */ -#define FB_EVENT_NEW_MODELIST 0x0A -/* The resolution of the passed in fb_info about to change and - all vc's should be changed */ #define FB_EVENT_MODE_CHANGE_ALL 0x0B /* A software display blank change occurred */ #define FB_EVENT_CONBLANK 0x0C diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index 790c42ec7b5d..c139834342f5 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -9,6 +9,9 @@ void fbcon_fb_unregistered(struct fb_info *info); void fbcon_fb_unbind(struct fb_info *info); void fbcon_suspended(struct fb_info *info); void fbcon_resumed(struct fb_info *info); +int fbcon_mode_deleted(struct fb_info *info, + struct fb_videomode *mode); +void fbcon_new_modelist(struct fb_info *info); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} @@ -17,6 +20,9 @@ static inline void fbcon_fb_unregistered(struct fb_info *info) {} static inline void fbcon_fb_unbind(struct fb_info *info) {} static inline void fbcon_suspended(struct fb_info *info) {} static inline void fbcon_resumed(struct fb_info *info) {} +static inline int fbcon_mode_deleted(struct fb_info *info, + struct fb_videomode *mode) { return 0; } +static inline void fbcon_new_modelist(struct fb_info *info) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From 0526c2239ad8ceef98652fe8e059044c24c62ea7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:54 +0200 Subject: fbdev: Call fbcon_get_requirement directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pretty simple case really. v2: Forgot to remove a break; v3: Add static inline to the dummy versions. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: "Steven Rostedt (VMware)" Cc: Prarit Bhargava Cc: Kees Cook Cc: Yisheng Xie Cc: "Michał Mirosław" Cc: Peter Rosin Cc: Mikulas Patocka Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-24-daniel.vetter@ffwll.ch --- drivers/video/fbdev/core/fbcon.c | 9 ++------- drivers/video/fbdev/core/fbmem.c | 5 +---- include/linux/fb.h | 2 -- include/linux/fbcon.h | 4 ++++ 4 files changed, 7 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 24bd6cd270d5..ee0bed9571aa 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -3283,8 +3283,8 @@ void fbcon_new_modelist(struct fb_info *info) } } -static void fbcon_get_requirement(struct fb_info *info, - struct fb_blit_caps *caps) +void fbcon_get_requirement(struct fb_info *info, + struct fb_blit_caps *caps) { struct vc_data *vc; struct fbcon_display *p; @@ -3325,7 +3325,6 @@ static int fbcon_event_notify(struct notifier_block *self, struct fb_event *event = data; struct fb_info *info = event->info; struct fb_con2fbmap *con2fb; - struct fb_blit_caps *caps; int idx, ret = 0; switch(action) { @@ -3348,10 +3347,6 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_BLANK: fbcon_fb_blanked(info, *(int *)event->data); break; - case FB_EVENT_GET_REQ: - caps = event->data; - fbcon_get_requirement(info, caps); - break; case FB_EVENT_REMAP_ALL_CONSOLE: idx = info->node; fbcon_remap_all(idx); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index cbdd141e7695..ddc0c16b8bbf 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -932,16 +932,13 @@ EXPORT_SYMBOL(fb_pan_display); static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, u32 activate) { - struct fb_event event; struct fb_blit_caps caps, fbcaps; int err = 0; memset(&caps, 0, sizeof(caps)); memset(&fbcaps, 0, sizeof(fbcaps)); caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; - event.info = info; - event.data = ∩︀ - fb_notifier_call_chain(FB_EVENT_GET_REQ, &event); + fbcon_get_requirement(info, &caps); info->fbops->fb_get_caps(info, &fbcaps, var); if (((fbcaps.x ^ caps.x) & caps.x) || diff --git a/include/linux/fb.h b/include/linux/fb.h index 7a788ed8c7b5..0d86aa31bf8d 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -143,8 +143,6 @@ struct fb_cursor_user { #define FB_EVENT_MODE_CHANGE_ALL 0x0B /* A software display blank change occurred */ #define FB_EVENT_CONBLANK 0x0C -/* Get drawing requirements */ -#define FB_EVENT_GET_REQ 0x0D /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F /* A hardware display blank early change occurred */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index c139834342f5..305e4f2eddac 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -12,6 +12,8 @@ void fbcon_resumed(struct fb_info *info); int fbcon_mode_deleted(struct fb_info *info, struct fb_videomode *mode); void fbcon_new_modelist(struct fb_info *info); +void fbcon_get_requirement(struct fb_info *info, + struct fb_blit_caps *caps); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} @@ -23,6 +25,8 @@ static inline void fbcon_resumed(struct fb_info *info) {} static inline int fbcon_mode_deleted(struct fb_info *info, struct fb_videomode *mode) { return 0; } static inline void fbcon_new_modelist(struct fb_info *info) {} +static inline void fbcon_get_requirement(struct fb_info *info, + struct fb_blit_caps *caps) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From 7a625549ea8c14be70bc7cfaf30215401bba6da0 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:55 +0200 Subject: Revert "backlight/fbcon: Add FB_EVENT_CONBLANK" This reverts commit 994efacdf9a087b52f71e620b58dfa526b0cf928. The justification is that if hw blanking fails (i.e. fbops->fb_blank) fails, then we still want to shut down the backlight. Which is exactly _not_ what fb_blank() does and so rather inconsistent if we end up with different behaviour between fbcon and direct fbdev usage. Given that the entire notifier maze is getting in the way anyway I figured it's simplest to revert this not well justified commit. v2: Add static inline to the dummy version. Cc: Richard Purdie Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Acked-by: Daniel Thompson Cc: Lee Jones Cc: Daniel Thompson Cc: Jingoo Han Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Yisheng Xie Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-25-daniel.vetter@ffwll.ch --- drivers/video/backlight/backlight.c | 2 +- drivers/video/fbdev/core/fbcon.c | 14 +------------- drivers/video/fbdev/core/fbmem.c | 1 + include/linux/fb.h | 4 +--- include/linux/fbcon.h | 2 ++ 5 files changed, 6 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 1ef8b6fd62ac..5dc07106a59e 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -47,7 +47,7 @@ static int fb_notifier_callback(struct notifier_block *self, int fb_blank = 0; /* If we aren't interested in this event, skip it immediately ... */ - if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) + if (event != FB_EVENT_BLANK) return 0; bd = container_of(self, struct backlight_device, fb_notif); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index ee0bed9571aa..be179b47d1c6 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2350,8 +2350,6 @@ static int fbcon_switch(struct vc_data *vc) static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, int blank) { - struct fb_event event; - if (blank) { unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; @@ -2362,13 +2360,6 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); vc->vc_video_erase_char = oldc; } - - - lock_fb_info(info); - event.info = info; - event.data = ␣ - fb_notifier_call_chain(FB_EVENT_CONBLANK, &event); - unlock_fb_info(info); } static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) @@ -3240,7 +3231,7 @@ int fbcon_fb_registered(struct fb_info *info) return ret; } -static void fbcon_fb_blanked(struct fb_info *info, int blank) +void fbcon_fb_blanked(struct fb_info *info, int blank) { struct fbcon_ops *ops = info->fbcon_par; struct vc_data *vc; @@ -3344,9 +3335,6 @@ static int fbcon_event_notify(struct notifier_block *self, con2fb = event->data; con2fb->framebuffer = con2fb_map[con2fb->console - 1]; break; - case FB_EVENT_BLANK: - fbcon_fb_blanked(info, *(int *)event->data); - break; case FB_EVENT_REMAP_ALL_CONSOLE: idx = info->node; fbcon_remap_all(idx); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index ddc0c16b8bbf..9366fbe99a58 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1068,6 +1068,7 @@ fb_blank(struct fb_info *info, int blank) event.data = ␣ early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event); + fbcon_fb_blanked(info, blank); if (info->fbops->fb_blank) ret = info->fbops->fb_blank(blank, info); diff --git a/include/linux/fb.h b/include/linux/fb.h index 0d86aa31bf8d..1e66fac3124f 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -137,12 +137,10 @@ struct fb_cursor_user { #define FB_EVENT_GET_CONSOLE_MAP 0x07 /* CONSOLE-SPECIFIC: set console to framebuffer mapping */ #define FB_EVENT_SET_CONSOLE_MAP 0x08 -/* A hardware display blank change occurred */ +/* A display blank is requested */ #define FB_EVENT_BLANK 0x09 /* Private modelist is to be replaced */ #define FB_EVENT_MODE_CHANGE_ALL 0x0B -/* A software display blank change occurred */ -#define FB_EVENT_CONBLANK 0x0C /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F /* A hardware display blank early change occurred */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index 305e4f2eddac..d67d7ec51ef9 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -14,6 +14,7 @@ int fbcon_mode_deleted(struct fb_info *info, void fbcon_new_modelist(struct fb_info *info); void fbcon_get_requirement(struct fb_info *info, struct fb_blit_caps *caps); +void fbcon_fb_blanked(struct fb_info *info, int blank); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} @@ -27,6 +28,7 @@ static inline int fbcon_mode_deleted(struct fb_info *info, static inline void fbcon_new_modelist(struct fb_info *info) {} static inline void fbcon_get_requirement(struct fb_info *info, struct fb_blit_caps *caps) {} +static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From 9e1467002630065ed86c65ea28bfc9194fff6f0e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:02:59 +0200 Subject: fbcon: replace FB_EVENT_MODE_CHANGE/_ALL with direct calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a new wrapper function for this, feels like there's some refactoring room here between the two modes. v2: backlight notifier is also interested in the mode change event, it calls lcd->set_mode, of which there are 3 implementations. Thanks to Maarten for spotting this. So we keep that. We can ditch the differentiation between mode change and all mode changes (because backlight notifier doesn't care), and we can drop the FBINFO_MISC_USEREVENT stuff too, because that's just to prevent recursion between fbmem.c and fbcon.c. While at it flatten the control flow a bit. v3: Need to add a static inline to the dummy function. v4: Add missing #include to sh_mob (Sam). Cc: Sam Ravnborg Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Acked-by: Daniel Thompson Cc: Maarten Lankhorst Cc: Lee Jones Cc: Daniel Thompson Cc: Jingoo Han Cc: Bartlomiej Zolnierkiewicz Cc: Daniel Vetter Cc: Hans de Goede Cc: Yisheng Xie Cc: "Michał Mirosław" Cc: Peter Rosin Cc: Mikulas Patocka Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-29-daniel.vetter@ffwll.ch --- drivers/video/backlight/lcd.c | 1 - drivers/video/fbdev/core/fbcon.c | 15 +++++++++------ drivers/video/fbdev/core/fbmem.c | 21 ++++++++++----------- drivers/video/fbdev/sh_mobile_lcdcfb.c | 12 ++---------- include/linux/fb.h | 2 -- include/linux/fbcon.h | 2 ++ 6 files changed, 23 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 151b18776add..ecdda06989d0 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -34,7 +34,6 @@ static int fb_notifier_callback(struct notifier_block *self, switch (event) { case FB_EVENT_BLANK: case FB_EVENT_MODE_CHANGE: - case FB_EVENT_MODE_CHANGE_ALL: case FB_EARLY_EVENT_BLANK: case FB_R_EARLY_EVENT_BLANK: break; diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 4afbc7d8c68c..1837985e1ffb 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -3009,6 +3009,15 @@ static void fbcon_set_all_vcs(struct fb_info *info) fbcon_modechanged(info); } + +void fbcon_update_vcs(struct fb_info *info, bool all) +{ + if (all) + fbcon_set_all_vcs(info); + else + fbcon_modechanged(info); +} + int fbcon_mode_deleted(struct fb_info *info, struct fb_videomode *mode) { @@ -3318,12 +3327,6 @@ static int fbcon_event_notify(struct notifier_block *self, int idx, ret = 0; switch(action) { - case FB_EVENT_MODE_CHANGE: - fbcon_modechanged(info); - break; - case FB_EVENT_MODE_CHANGE_ALL: - fbcon_set_all_vcs(info); - break; case FB_EVENT_SET_CONSOLE_MAP: /* called with console lock held */ con2fb = event->data; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 96805fe85332..dd1a708df1a7 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -957,6 +957,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) u32 activate; struct fb_var_screeninfo old_var; struct fb_videomode mode; + struct fb_event event; if (var->activate & FB_ACTIVATE_INV_MODE) { struct fb_videomode mode1, mode2; @@ -1039,19 +1040,17 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) !list_empty(&info->modelist)) ret = fb_add_videomode(&mode, &info->modelist); - if (!ret && (flags & FBINFO_MISC_USEREVENT)) { - struct fb_event event; - int evnt = (activate & FB_ACTIVATE_ALL) ? - FB_EVENT_MODE_CHANGE_ALL : - FB_EVENT_MODE_CHANGE; + if (ret) + return ret; - info->flags &= ~FBINFO_MISC_USEREVENT; - event.info = info; - event.data = &mode; - fb_notifier_call_chain(evnt, &event); - } + event.info = info; + event.data = &mode; + fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event); - return ret; + if (flags & FBINFO_MISC_USEREVENT) + fbcon_update_vcs(info, activate & FB_ACTIVATE_ALL); + + return 0; } EXPORT_SYMBOL(fb_set_var); diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index 015a02a29d37..b8454424910d 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -1757,8 +1758,6 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) struct sh_mobile_lcdc_chan *ch = info->par; struct fb_var_screeninfo var; struct fb_videomode mode; - struct fb_event event; - int evnt = FB_EVENT_MODE_CHANGE_ALL; if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) /* More framebuffer users are active */ @@ -1780,14 +1779,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) /* Couldn't reconfigure, hopefully, can continue as before */ return; - /* - * fb_set_var() calls the notifier change internally, only if - * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a - * user event, we have to call the chain ourselves. - */ - event.info = info; - event.data = &ch->display.mode; - fb_notifier_call_chain(evnt, &event); + fbcon_update_vcs(info, true); } /* diff --git a/include/linux/fb.h b/include/linux/fb.h index 1e66fac3124f..f9c212f9b661 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -139,8 +139,6 @@ struct fb_cursor_user { #define FB_EVENT_SET_CONSOLE_MAP 0x08 /* A display blank is requested */ #define FB_EVENT_BLANK 0x09 -/* Private modelist is to be replaced */ -#define FB_EVENT_MODE_CHANGE_ALL 0x0B /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F /* A hardware display blank early change occurred */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index d67d7ec51ef9..de31eeb22c97 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -15,6 +15,7 @@ void fbcon_new_modelist(struct fb_info *info); void fbcon_get_requirement(struct fb_info *info, struct fb_blit_caps *caps); void fbcon_fb_blanked(struct fb_info *info, int blank); +void fbcon_update_vcs(struct fb_info *info, bool all); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} @@ -29,6 +30,7 @@ static inline void fbcon_new_modelist(struct fb_info *info) {} static inline void fbcon_get_requirement(struct fb_info *info, struct fb_blit_caps *caps) {} static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} +static inline void fbcon_update_vcs(struct fb_info *info, bool all) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From 1cd51b5d200dec292577a4656803d8aeff54ad51 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:03:00 +0200 Subject: vgaswitcheroo: call fbcon_remap_all directly While at it, clean up the interface a bit and push the console locking into fbcon.c. v2: Remove now outdated comment (Lukas). v3: Forgot to add static inline to the dummy function. Acked-by: Lukas Wunner Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Lukas Wunner Cc: David Airlie Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: Bartlomiej Zolnierkiewicz Cc: Hans de Goede Cc: Yisheng Xie Cc: linux-fbdev@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-30-daniel.vetter@ffwll.ch --- drivers/gpu/vga/vga_switcheroo.c | 11 +++-------- drivers/video/fbdev/core/fbcon.c | 14 +++++--------- include/linux/fb.h | 2 -- include/linux/fbcon.h | 2 ++ 4 files changed, 10 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index a132c37d7334..65d7541c413a 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -736,14 +737,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) if (!active->driver_power_control) set_audio_state(active->id, VGA_SWITCHEROO_OFF); - if (new_client->fb_info) { - struct fb_event event; - - console_lock(); - event.info = new_client->fb_info; - fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); - console_unlock(); - } + if (new_client->fb_info) + fbcon_remap_all(new_client->fb_info); mutex_lock(&vgasr_priv.mux_hw_lock); ret = vgasr_priv.handler->switchto(new_client->id); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 1837985e1ffb..44779a4371ee 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -3149,17 +3149,16 @@ void fbcon_fb_unregistered(struct fb_info *info) do_unregister_con_driver(&fb_con); } -/* called with console_lock held */ -static void fbcon_remap_all(int idx) +void fbcon_remap_all(struct fb_info *info) { - int i; - - WARN_CONSOLE_UNLOCKED(); + int i, idx = info->node; + console_lock(); if (deferred_takeover) { for (i = first_fb_vc; i <= last_fb_vc; i++) con2fb_map_boot[i] = idx; fbcon_map_override(); + console_unlock(); return; } @@ -3172,6 +3171,7 @@ static void fbcon_remap_all(int idx) first_fb_vc + 1, last_fb_vc + 1); info_idx = idx; } + console_unlock(); } #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY @@ -3337,10 +3337,6 @@ static int fbcon_event_notify(struct notifier_block *self, con2fb = event->data; con2fb->framebuffer = con2fb_map[con2fb->console - 1]; break; - case FB_EVENT_REMAP_ALL_CONSOLE: - idx = info->node; - fbcon_remap_all(idx); - break; } return ret; } diff --git a/include/linux/fb.h b/include/linux/fb.h index f9c212f9b661..25e4b885f5b3 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -139,8 +139,6 @@ struct fb_cursor_user { #define FB_EVENT_SET_CONSOLE_MAP 0x08 /* A display blank is requested */ #define FB_EVENT_BLANK 0x09 -/* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ -#define FB_EVENT_REMAP_ALL_CONSOLE 0x0F /* A hardware display blank early change occurred */ #define FB_EARLY_EVENT_BLANK 0x10 /* A hardware display blank revert early change occurred */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index de31eeb22c97..69f900d289b2 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -16,6 +16,7 @@ void fbcon_get_requirement(struct fb_info *info, struct fb_blit_caps *caps); void fbcon_fb_blanked(struct fb_info *info, int blank); void fbcon_update_vcs(struct fb_info *info, bool all); +void fbcon_remap_all(struct fb_info *info); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} @@ -31,6 +32,7 @@ static inline void fbcon_get_requirement(struct fb_info *info, struct fb_blit_caps *caps) {} static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} static inline void fbcon_update_vcs(struct fb_info *info, bool all) {} +static inline void fbcon_remap_all(struct fb_info *info) {} #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3 From fe2d70d6f6ff038c20705c34695bd34ac072af14 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 28 May 2019 11:03:01 +0200 Subject: fbcon: Call con2fb_map functions directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are actually fbcon ioctls which just happen to be exposed through /dev/fb*. They completely ignore which fb_info they're called on, and I think the userspace tool even hardcodes to /dev/fb0. Hence just forward the entire thing to fbcon.c wholesale. Note that this patch drops the fb_lock/unlock on the set side. Since the ioctl can operate on any fb (as passed in through con2fb.framebuffer) this is bogus. Also note that fbcon.c in general never calls fb_lock on anything, so this has been badly broken already. With this the last user of the fbcon notifier callback is gone, and we can garbage collect that too. v2: add missing uaccess.h include (alpha fails to compile otherwise), reported by kbuild. v3: Remember to also drop the #defines (Maarten) v4: Add the static inline to dummy functions. Signed-off-by: Daniel Vetter Reviewed-by: Sam Ravnborg Reviewed-by: Maarten Lankhorst Cc: Maarten Lankhorst Cc: Daniel Vetter Cc: Bartlomiej Zolnierkiewicz Cc: Hans de Goede Cc: Yisheng Xie Cc: "Michał Mirosław" Cc: Peter Rosin Cc: Mikulas Patocka Link: https://patchwork.freedesktop.org/patch/msgid/20190528090304.9388-31-daniel.vetter@ffwll.ch --- drivers/video/fbdev/core/fbcon.c | 59 ++++++++++++++++++++++++---------------- drivers/video/fbdev/core/fbmem.c | 34 ++--------------------- include/linux/fb.h | 4 --- include/linux/fbcon.h | 4 +++ 4 files changed, 42 insertions(+), 59 deletions(-) (limited to 'include') diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 44779a4371ee..31d6a4e54436 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -76,6 +76,7 @@ #include #include #include /* For counting font checksums */ +#include #include #include @@ -3318,29 +3319,47 @@ void fbcon_get_requirement(struct fb_info *info, } } -static int fbcon_event_notify(struct notifier_block *self, - unsigned long action, void *data) +int fbcon_set_con2fb_map_ioctl(void __user *argp) { - struct fb_event *event = data; - struct fb_info *info = event->info; - struct fb_con2fbmap *con2fb; - int idx, ret = 0; + struct fb_con2fbmap con2fb; + int ret; - switch(action) { - case FB_EVENT_SET_CONSOLE_MAP: - /* called with console lock held */ - con2fb = event->data; - ret = set_con2fb_map(con2fb->console - 1, - con2fb->framebuffer, 1); - break; - case FB_EVENT_GET_CONSOLE_MAP: - con2fb = event->data; - con2fb->framebuffer = con2fb_map[con2fb->console - 1]; - break; + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) + return -EFAULT; + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) + return -EINVAL; + if (con2fb.framebuffer >= FB_MAX) + return -EINVAL; + if (!registered_fb[con2fb.framebuffer]) + request_module("fb%d", con2fb.framebuffer); + if (!registered_fb[con2fb.framebuffer]) { + return -EINVAL; } + + console_lock(); + ret = set_con2fb_map(con2fb.console - 1, + con2fb.framebuffer, 1); + console_unlock(); + return ret; } +int fbcon_get_con2fb_map_ioctl(void __user *argp) +{ + struct fb_con2fbmap con2fb; + + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) + return -EFAULT; + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) + return -EINVAL; + + console_lock(); + con2fb.framebuffer = con2fb_map[con2fb.console - 1]; + console_unlock(); + + return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; +} + /* * The console `switch' structure for the frame buffer based console */ @@ -3372,10 +3391,6 @@ static const struct consw fb_con = { .con_debug_leave = fbcon_debug_leave, }; -static struct notifier_block fbcon_event_notifier = { - .notifier_call = fbcon_event_notify, -}; - static ssize_t store_rotate(struct device *device, struct device_attribute *attr, const char *buf, size_t count) @@ -3648,7 +3663,6 @@ void __init fb_console_init(void) int i; console_lock(); - fb_register_client(&fbcon_event_notifier); fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon"); @@ -3684,7 +3698,6 @@ static void __exit fbcon_deinit_device(void) void __exit fb_console_exit(void) { console_lock(); - fb_unregister_client(&fbcon_event_notifier); fbcon_deinit_device(); device_destroy(fb_class, MKDEV(0, 0)); fbcon_exit(); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index dd1a708df1a7..64dd732021d8 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1092,10 +1092,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, struct fb_ops *fb; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; - struct fb_con2fbmap con2fb; struct fb_cmap cmap_from; struct fb_cmap_user cmap; - struct fb_event event; void __user *argp = (void __user *)arg; long ret = 0; @@ -1157,38 +1155,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, ret = -EINVAL; break; case FBIOGET_CON2FBMAP: - if (copy_from_user(&con2fb, argp, sizeof(con2fb))) - return -EFAULT; - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) - return -EINVAL; - con2fb.framebuffer = -1; - event.data = &con2fb; - lock_fb_info(info); - event.info = info; - fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); - unlock_fb_info(info); - ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; + ret = fbcon_get_con2fb_map_ioctl(argp); break; case FBIOPUT_CON2FBMAP: - if (copy_from_user(&con2fb, argp, sizeof(con2fb))) - return -EFAULT; - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) - return -EINVAL; - if (con2fb.framebuffer >= FB_MAX) - return -EINVAL; - if (!registered_fb[con2fb.framebuffer]) - request_module("fb%d", con2fb.framebuffer); - if (!registered_fb[con2fb.framebuffer]) { - ret = -EINVAL; - break; - } - event.data = &con2fb; - console_lock(); - lock_fb_info(info); - event.info = info; - ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); - unlock_fb_info(info); - console_unlock(); + ret = fbcon_set_con2fb_map_ioctl(argp); break; case FBIOBLANK: console_lock(); diff --git a/include/linux/fb.h b/include/linux/fb.h index 25e4b885f5b3..303771264644 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -133,10 +133,6 @@ struct fb_cursor_user { #define FB_EVENT_FB_UNREGISTERED 0x06 #endif -/* CONSOLE-SPECIFIC: get console to framebuffer mapping */ -#define FB_EVENT_GET_CONSOLE_MAP 0x07 -/* CONSOLE-SPECIFIC: set console to framebuffer mapping */ -#define FB_EVENT_SET_CONSOLE_MAP 0x08 /* A display blank is requested */ #define FB_EVENT_BLANK 0x09 /* A hardware display blank early change occurred */ diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h index 69f900d289b2..ff5596dd30f8 100644 --- a/include/linux/fbcon.h +++ b/include/linux/fbcon.h @@ -17,6 +17,8 @@ void fbcon_get_requirement(struct fb_info *info, void fbcon_fb_blanked(struct fb_info *info, int blank); void fbcon_update_vcs(struct fb_info *info, bool all); void fbcon_remap_all(struct fb_info *info); +int fbcon_set_con2fb_map_ioctl(void __user *argp); +int fbcon_get_con2fb_map_ioctl(void __user *argp); #else static inline void fb_console_init(void) {} static inline void fb_console_exit(void) {} @@ -33,6 +35,8 @@ static inline void fbcon_get_requirement(struct fb_info *info, static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} static inline void fbcon_update_vcs(struct fb_info *info, bool all) {} static inline void fbcon_remap_all(struct fb_info *info) {} +static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; } +static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; } #endif #endif /* _LINUX_FBCON_H */ -- cgit v1.2.3