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

video: fb_defio: preserve user fb_ops

Modifying fb_ops directly to override fb_mmap with fb_deferred_io_mmap
and then resetting it to NULL afterwards causes problems all over the
place. First, it prevents making the fbops member of struct fb_info a
const pointer, which means we can't make struct fb_ops const
anywhere. Second, a few places have to go out of their way to restore
the original fb_mmap pointer that gets reset to NULL.

Since the only user of the fbops->fb_mmap hook is fb_mmap() in fbmem.c,
call fb_deferred_io_mmap() directly when deferred IO is enabled, and
avoid modifying fb_ops altogether.

Simply use info->fbdefio to determine whether deferred IO should be used
or not. This should be accurate enough for all use cases, although
perhaps not pedantically correct.

v2: Simplify considerably by calling fb_deferred_io_mmap() directly
(Daniel, Ville)

Cc: Jaya Kumar <jayalk@intworks.biz>
Cc: linux-fbdev@vger.kernel.org
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Acked-by: Noralf Trønnes <noralf@tronnes.org>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/022c82429da15d6450ff9ac1a897322ec3124db4.1575022735.git.jani.nikula@intel.com

+11 -7
-3
drivers/video/fbdev/core/fb_defio.c
··· 171 171 vma->vm_private_data = info; 172 172 return 0; 173 173 } 174 - EXPORT_SYMBOL(fb_deferred_io_mmap); 175 174 176 175 /* workqueue callback */ 177 176 static void fb_deferred_io_work(struct work_struct *work) ··· 205 206 206 207 BUG_ON(!fbdefio); 207 208 mutex_init(&fbdefio->lock); 208 - info->fbops->fb_mmap = fb_deferred_io_mmap; 209 209 INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work); 210 210 INIT_LIST_HEAD(&fbdefio->pagelist); 211 211 if (fbdefio->delay == 0) /* set a default of 1 s */ ··· 235 237 page->mapping = NULL; 236 238 } 237 239 238 - info->fbops->fb_mmap = NULL; 239 240 mutex_destroy(&fbdefio->lock); 240 241 } 241 242 EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
+11 -4
drivers/video/fbdev/core/fbmem.c
··· 1332 1332 fb_mmap(struct file *file, struct vm_area_struct * vma) 1333 1333 { 1334 1334 struct fb_info *info = file_fb_info(file); 1335 - struct fb_ops *fb; 1335 + int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma); 1336 1336 unsigned long mmio_pgoff; 1337 1337 unsigned long start; 1338 1338 u32 len; 1339 1339 1340 1340 if (!info) 1341 1341 return -ENODEV; 1342 - fb = info->fbops; 1343 1342 mutex_lock(&info->mm_lock); 1344 - if (fb->fb_mmap) { 1343 + 1344 + fb_mmap_fn = info->fbops->fb_mmap; 1345 + 1346 + #if IS_ENABLED(CONFIG_FB_DEFERRED_IO) 1347 + if (info->fbdefio) 1348 + fb_mmap_fn = fb_deferred_io_mmap; 1349 + #endif 1350 + 1351 + if (fb_mmap_fn) { 1345 1352 int res; 1346 1353 1347 1354 /* ··· 1356 1349 * SME protection is removed ahead of the call 1357 1350 */ 1358 1351 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1359 - res = fb->fb_mmap(info, vma); 1352 + res = fb_mmap_fn(info, vma); 1360 1353 mutex_unlock(&info->mm_lock); 1361 1354 return res; 1362 1355 }