Commit 33253d9e authored by Thomas Zimmermann's avatar Thomas Zimmermann

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: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231127131655.4020-31-tzimmermann@suse.de
parent 76f92201
...@@ -314,20 +314,16 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, ...@@ -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) static int fb_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct fb_info *info = file_fb_info(file); struct fb_info *info = file_fb_info(file);
unsigned long mmio_pgoff; int res;
unsigned long start;
u32 len;
if (!info) if (!info)
return -ENODEV; return -ENODEV;
mutex_lock(&info->mm_lock); mutex_lock(&info->mm_lock);
if (info->fbops->fb_mmap) { if (info->fbops->fb_mmap) {
int res;
res = info->fbops->fb_mmap(info, vma); res = info->fbops->fb_mmap(info, vma);
mutex_unlock(&info->mm_lock);
return res;
#if IS_ENABLED(CONFIG_FB_DEFERRED_IO) #if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
} else if (info->fbdefio) { } else if (info->fbdefio) {
/* /*
...@@ -335,35 +331,15 @@ static int fb_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -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(). * 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"); dev_warn_once(info->dev, "fbdev mmap not set up for deferred I/O.\n");
mutex_unlock(&info->mm_lock); res = -ENODEV;
return -ENODEV;
#endif #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); mutex_unlock(&info->mm_lock);
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); return res;
vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start,
vma->vm_end, start);
return vm_iomap_memory(vma, start, len);
} }
static int fb_open(struct inode *inode, struct file *file) static int fb_open(struct inode *inode, struct file *file)
......
...@@ -132,5 +132,32 @@ ssize_t fb_io_write(struct fb_info *info, const char __user *buf, size_t count, ...@@ -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); 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_DESCRIPTION("Fbdev helpers for framebuffers in I/O memory");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -536,6 +536,7 @@ extern ssize_t fb_io_read(struct fb_info *info, char __user *buf, ...@@ -536,6 +536,7 @@ extern ssize_t fb_io_read(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos); size_t count, loff_t *ppos);
extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf, extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos); 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 \ #define __FB_DEFAULT_IOMEM_OPS_RDWR \
.fb_read = fb_io_read, \ .fb_read = fb_io_read, \
...@@ -547,7 +548,7 @@ extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf, ...@@ -547,7 +548,7 @@ extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf,
.fb_imageblit = cfb_imageblit .fb_imageblit = cfb_imageblit
#define __FB_DEFAULT_IOMEM_OPS_MMAP \ #define __FB_DEFAULT_IOMEM_OPS_MMAP \
.fb_mmap = NULL /* default implementation */ .fb_mmap = fb_io_mmap
#define FB_DEFAULT_IOMEM_OPS \ #define FB_DEFAULT_IOMEM_OPS \
__FB_DEFAULT_IOMEM_OPS_RDWR, \ __FB_DEFAULT_IOMEM_OPS_RDWR, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment