diff options
author | Maxime Ripard <maxime@cerno.tech> | 2023-05-12 09:47:12 +0200 |
---|---|---|
committer | Maxime Ripard <maxime@cerno.tech> | 2023-05-12 09:47:12 +0200 |
commit | 50282fd57bcd3525c9d81eef58df8718e4337c6d (patch) | |
tree | 9795dfdb1a9b66904d9320f33c9216683d10576a /drivers/gpu/drm/drm_fb_helper.c | |
parent | ad81e23426a651eb89a4b306e1c4169e6308c124 (diff) | |
parent | ac9a78681b921877518763ba0e89202254349d1b (diff) | |
download | linux-50282fd57bcd3525c9d81eef58df8718e4337c6d.tar.gz linux-50282fd57bcd3525c9d81eef58df8718e4337c6d.tar.bz2 linux-50282fd57bcd3525c9d81eef58df8718e4337c6d.zip |
Merge drm/drm-fixes into drm-misc-fixes
Let's bring 6.4-rc1 in drm-misc-fixes to start the new fix cycle.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 116 |
1 files changed, 77 insertions, 39 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 883f31db1143..6bb1b8b27d7a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -60,16 +60,17 @@ MODULE_PARM_DESC(drm_fbdev_overalloc, * In order to keep user-space compatibility, we want in certain use-cases * to keep leaking the fbdev physical address to the user-space program * handling the fbdev buffer. - * This is a bad habit essentially kept into closed source opengl driver - * that should really be moved into open-source upstream projects instead - * of using legacy physical addresses in user space to communicate with - * other out-of-tree kernel modules. + * + * This is a bad habit, essentially kept to support closed-source OpenGL + * drivers that should really be moved into open-source upstream projects + * instead of using legacy physical addresses in user space to communicate + * with other out-of-tree kernel modules. * * This module_param *should* be removed as soon as possible and be * considered as a broken and legacy behaviour from a modern fbdev device. */ -#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM) static bool drm_leak_fbdev_smem; +#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM) module_param_unsafe(drm_leak_fbdev_smem, bool, 0600); MODULE_PARM_DESC(drm_leak_fbdev_smem, "Allow unsafe leaking fbdev physical smem address [default=false]"); @@ -539,6 +540,29 @@ err_release: EXPORT_SYMBOL(drm_fb_helper_alloc_info); /** + * drm_fb_helper_release_info - release fb_info and its members + * @fb_helper: driver-allocated fbdev helper + * + * A helper to release fb_info and the member cmap. Drivers do not + * need to release the allocated fb_info structure themselves, this is + * automatically done when calling drm_fb_helper_fini(). + */ +void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) +{ + struct fb_info *info = fb_helper->info; + + if (!info) + return; + + fb_helper->info = NULL; + + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); +} +EXPORT_SYMBOL(drm_fb_helper_release_info); + +/** * drm_fb_helper_unregister_info - unregister fb_info framebuffer device * @fb_helper: driver-allocated fbdev helper, can be NULL * @@ -561,8 +585,6 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_info); */ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) { - struct fb_info *info; - if (!fb_helper) return; @@ -574,13 +596,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) cancel_work_sync(&fb_helper->resume_work); cancel_work_sync(&fb_helper->damage_work); - info = fb_helper->info; - if (info) { - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } - fb_helper->info = NULL; + drm_fb_helper_release_info(fb_helper); mutex_lock(&kernel_fb_helper_lock); if (!list_empty(&fb_helper->kernel_fb_list)) { @@ -665,7 +681,7 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off, void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist) { struct drm_fb_helper *helper = info->par; - unsigned long start, end, min_off, max_off; + unsigned long start, end, min_off, max_off, total_size; struct fb_deferred_io_pageref *pageref; struct drm_rect damage_area; @@ -683,7 +699,11 @@ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagerefli * of the screen and account for non-existing scanlines. Hence, * keep the covered memory area within the screen buffer. */ - max_off = min(max_off, info->screen_size); + if (info->screen_size) + total_size = info->screen_size; + else + total_size = info->fix.smem_len; + max_off = min(max_off, total_size); if (min_off < max_off) { drm_fb_helper_memory_range_to_clip(info, min_off, max_off - min_off, &damage_area); @@ -1525,6 +1545,27 @@ static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, } } +static void __fill_var(struct fb_var_screeninfo *var, + struct drm_framebuffer *fb) +{ + int i; + + var->xres_virtual = fb->width; + var->yres_virtual = fb->height; + var->accel_flags = FB_ACCELF_TEXT; + var->bits_per_pixel = drm_format_info_bpp(fb->format, 0); + + var->height = var->width = 0; + var->left_margin = var->right_margin = 0; + var->upper_margin = var->lower_margin = 0; + var->hsync_len = var->vsync_len = 0; + var->sync = var->vmode = 0; + var->rotate = 0; + var->colorspace = 0; + for (i = 0; i < 4; i++) + var->reserved[i] = 0; +} + /** * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var * @var: screeninfo to check @@ -1577,6 +1618,23 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return -EINVAL; } + __fill_var(var, fb); + + /* + * fb_pan_display() validates this, but fb_set_par() doesn't and just + * falls over. Note that __fill_var above adjusts y/res_virtual. + */ + if (var->yoffset > var->yres_virtual - var->yres || + var->xoffset > var->xres_virtual - var->xres) + return -EINVAL; + + /* We neither support grayscale nor FOURCC (also stored in here). */ + if (var->grayscale > 0) + return -EINVAL; + + if (var->nonstd) + return -EINVAL; + /* * Workaround for SDL 1.2, which is known to be setting all pixel format * fields values to zero in some cases. We treat this situation as a @@ -1592,11 +1650,6 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, } /* - * Likewise, bits_per_pixel should be rounded up to a supported value. - */ - var->bits_per_pixel = bpp; - - /* * drm fbdev emulation doesn't support changing the pixel format at all, * so reject all pixel format changing requests. */ @@ -1626,11 +1679,6 @@ int drm_fb_helper_set_par(struct fb_info *info) if (oops_in_progress) return -EBUSY; - if (var->pixclock != 0) { - drm_err(fb_helper->dev, "PIXEL CLOCK SET\n"); - return -EINVAL; - } - /* * Normally we want to make sure that a kms master takes precedence over * fbdev, to avoid fbdev flickering and occasionally stealing the @@ -1972,10 +2020,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper) return ret; } -#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM) - fb_helper->hint_leak_smem_start = drm_leak_fbdev_smem; -#endif - /* push down into drivers */ ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); if (ret < 0) @@ -2028,12 +2072,9 @@ static void drm_fb_helper_fill_var(struct fb_info *info, } info->pseudo_palette = fb_helper->pseudo_palette; - info->var.xres_virtual = fb->width; - info->var.yres_virtual = fb->height; - info->var.bits_per_pixel = drm_format_info_bpp(format, 0); - info->var.accel_flags = FB_ACCELF_TEXT; info->var.xoffset = 0; info->var.yoffset = 0; + __fill_var(&info->var, fb); info->var.activate = FB_ACTIVATE_NOW; drm_fb_helper_fill_pixel_fmt(&info->var, format); @@ -2174,11 +2215,8 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper) info = fb_helper->info; info->var.pixclock = 0; - /* Shamelessly allow physical address leaking to userspace */ -#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM) - if (!fb_helper->hint_leak_smem_start) -#endif - /* don't leak any physical addresses to userspace */ + + if (!drm_leak_fbdev_smem) info->flags |= FBINFO_HIDE_SMEM_START; /* Need to drop locks to avoid recursive deadlock in |