summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Zimmermann <tzimmermann@suse.de>2023-11-27 14:15:59 +0100
committerThomas Zimmermann <tzimmermann@suse.de>2023-11-29 12:20:49 +0100
commit33253d9e01d40542f07aaf718a655893cd2949e5 (patch)
treef3f0873961e38878d426484fbaa62325ffe0bb36
parentfbdev: Push pgprot_decrypted() into mmap implementations (diff)
downloadlinux-33253d9e01d40542f07aaf718a655893cd2949e5.tar.xz
linux-33253d9e01d40542f07aaf718a655893cd2949e5.zip
fbdev: Move default fb_mmap code into helper function
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
-rw-r--r--drivers/video/fbdev/core/fb_chrdev.c36
-rw-r--r--drivers/video/fbdev/core/fb_io_fops.c27
-rw-r--r--include/linux/fb.h3
3 files changed, 35 insertions, 31 deletions
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index b73a122950a9..089441c9d810 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -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)
diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c
index 871b829521af..60805e43914e 100644
--- a/drivers/video/fbdev/core/fb_io_fops.c
+++ b/drivers/video/fbdev/core/fb_io_fops.c
@@ -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");
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 94e2c44c6569..a36d05b576b0 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -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, \