fbdev: Move default fb_mmap code into helper function
authorThomas Zimmermann <tzimmermann@suse.de>
Mon, 27 Nov 2023 13:15:59 +0000 (14:15 +0100)
committerThomas Zimmermann <tzimmermann@suse.de>
Wed, 29 Nov 2023 11:20:49 +0000 (12:20 +0100)
Move the default fb_mmap code for I/O address spaces into the helper
function fb_io_mmap(). The helper can either be called via struct
fb_ops.fb_mmap or as the default if no fb_mmap has been set. Also
set the new helper in __FB_DEFAULT_IOMEM_OPS_MMAP.

In the mid-term, fb_io_mmap() is supposed to become optional. Fbdev
drivers will initialize their struct fb_ops.fb_mmap to the helper
and select a corresponding Kconfig token. The helper can then be made
optional at compile time.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231127131655.4020-31-tzimmermann@suse.de
drivers/video/fbdev/core/fb_chrdev.c
drivers/video/fbdev/core/fb_io_fops.c
include/linux/fb.h

index b73a122950a940c3b16f992117dc897cb77a3f9f..089441c9d810f96b74a730878c8d5c3fc48902fa 100644 (file)
@@ -314,20 +314,16 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
 static int fb_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct fb_info *info = file_fb_info(file);
-       unsigned long mmio_pgoff;
-       unsigned long start;
-       u32 len;
+       int res;
 
        if (!info)
                return -ENODEV;
+
        mutex_lock(&info->mm_lock);
 
        if (info->fbops->fb_mmap) {
-               int res;
 
                res = info->fbops->fb_mmap(info, vma);
-               mutex_unlock(&info->mm_lock);
-               return res;
 #if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
        } else if (info->fbdefio) {
                /*
@@ -335,35 +331,15 @@ static int fb_mmap(struct file *file, struct vm_area_struct *vma)
                 * minimum, point struct fb_ops.fb_mmap to fb_deferred_io_mmap().
                 */
                dev_warn_once(info->dev, "fbdev mmap not set up for deferred I/O.\n");
-               mutex_unlock(&info->mm_lock);
-               return -ENODEV;
+               res = -ENODEV;
 #endif
+       } else {
+               res = fb_io_mmap(info, vma);
        }
 
-       /*
-        * Ugh. This can be either the frame buffer mapping, or
-        * if pgoff points past it, the mmio mapping.
-        */
-       start = info->fix.smem_start;
-       len = info->fix.smem_len;
-       mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
-       if (vma->vm_pgoff >= mmio_pgoff) {
-               if (info->var.accel_flags) {
-                       mutex_unlock(&info->mm_lock);
-                       return -EINVAL;
-               }
-
-               vma->vm_pgoff -= mmio_pgoff;
-               start = info->fix.mmio_start;
-               len = info->fix.mmio_len;
-       }
        mutex_unlock(&info->mm_lock);
 
-       vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-       vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start,
-                                              vma->vm_end, start);
-
-       return vm_iomap_memory(vma, start, len);
+       return res;
 }
 
 static int fb_open(struct inode *inode, struct file *file)
index 871b829521af356cbb2f203d766e8275ecf7e750..60805e43914e52ecc3590870be2875e9f1f8e593 100644 (file)
@@ -132,5 +132,32 @@ ssize_t fb_io_write(struct fb_info *info, const char __user *buf, size_t count,
 }
 EXPORT_SYMBOL(fb_io_write);
 
+int fb_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+       unsigned long start = info->fix.smem_start;
+       u32 len = info->fix.smem_len;
+       unsigned long mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+
+       /*
+        * This can be either the framebuffer mapping, or if pgoff points
+        * past it, the mmio mapping.
+        */
+       if (vma->vm_pgoff >= mmio_pgoff) {
+               if (info->var.accel_flags)
+                       return -EINVAL;
+
+               vma->vm_pgoff -= mmio_pgoff;
+               start = info->fix.mmio_start;
+               len = info->fix.mmio_len;
+       }
+
+       vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+       vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start,
+                                              vma->vm_end, start);
+
+       return vm_iomap_memory(vma, start, len);
+}
+EXPORT_SYMBOL(fb_io_mmap);
+
 MODULE_DESCRIPTION("Fbdev helpers for framebuffers in I/O memory");
 MODULE_LICENSE("GPL");
index 94e2c44c6569988106aa01dbe522f02b854a92f7..a36d05b576b0ccd7a97051ff3ed8bea8a644b99a 100644 (file)
@@ -536,6 +536,7 @@ extern ssize_t fb_io_read(struct fb_info *info, char __user *buf,
                          size_t count, loff_t *ppos);
 extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf,
                           size_t count, loff_t *ppos);
+int fb_io_mmap(struct fb_info *info, struct vm_area_struct *vma);
 
 #define __FB_DEFAULT_IOMEM_OPS_RDWR \
        .fb_read        = fb_io_read, \
@@ -547,7 +548,7 @@ extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf,
        .fb_imageblit   = cfb_imageblit
 
 #define __FB_DEFAULT_IOMEM_OPS_MMAP \
-       .fb_mmap        = NULL /* default implementation */
+       .fb_mmap        = fb_io_mmap
 
 #define FB_DEFAULT_IOMEM_OPS \
        __FB_DEFAULT_IOMEM_OPS_RDWR, \