Revert "fb_defio: Remove custom address_space_operations"
Commit ccf953d8f3
makes framebuffers which use deferred I/O stop
displaying updates after the first one. This is because the pages
handled by fb_defio no longer have a page_mapping(). That prevents
page_mkclean() from marking the PTEs as clean, and so writes are only
noticed the first time.
Reported-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/YLZEhv0cpZp8uVE3@casper.infradead.org
This commit is contained in:
Родитель
8124c8a6b3
Коммит
0b78f8bcf4
|
@ -52,6 +52,13 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
|
||||||
return VM_FAULT_SIGBUS;
|
return VM_FAULT_SIGBUS;
|
||||||
|
|
||||||
get_page(page);
|
get_page(page);
|
||||||
|
|
||||||
|
if (vmf->vma->vm_file)
|
||||||
|
page->mapping = vmf->vma->vm_file->f_mapping;
|
||||||
|
else
|
||||||
|
printk(KERN_ERR "no mapping available\n");
|
||||||
|
|
||||||
|
BUG_ON(!page->mapping);
|
||||||
page->index = vmf->pgoff;
|
page->index = vmf->pgoff;
|
||||||
|
|
||||||
vmf->page = page;
|
vmf->page = page;
|
||||||
|
@ -144,6 +151,17 @@ static const struct vm_operations_struct fb_deferred_io_vm_ops = {
|
||||||
.page_mkwrite = fb_deferred_io_mkwrite,
|
.page_mkwrite = fb_deferred_io_mkwrite,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int fb_deferred_io_set_page_dirty(struct page *page)
|
||||||
|
{
|
||||||
|
if (!PageDirty(page))
|
||||||
|
SetPageDirty(page);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct address_space_operations fb_deferred_io_aops = {
|
||||||
|
.set_page_dirty = fb_deferred_io_set_page_dirty,
|
||||||
|
};
|
||||||
|
|
||||||
int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
vma->vm_ops = &fb_deferred_io_vm_ops;
|
vma->vm_ops = &fb_deferred_io_vm_ops;
|
||||||
|
@ -194,12 +212,29 @@ void fb_deferred_io_init(struct fb_info *info)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fb_deferred_io_init);
|
EXPORT_SYMBOL_GPL(fb_deferred_io_init);
|
||||||
|
|
||||||
|
void fb_deferred_io_open(struct fb_info *info,
|
||||||
|
struct inode *inode,
|
||||||
|
struct file *file)
|
||||||
|
{
|
||||||
|
file->f_mapping->a_ops = &fb_deferred_io_aops;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(fb_deferred_io_open);
|
||||||
|
|
||||||
void fb_deferred_io_cleanup(struct fb_info *info)
|
void fb_deferred_io_cleanup(struct fb_info *info)
|
||||||
{
|
{
|
||||||
struct fb_deferred_io *fbdefio = info->fbdefio;
|
struct fb_deferred_io *fbdefio = info->fbdefio;
|
||||||
|
struct page *page;
|
||||||
|
int i;
|
||||||
|
|
||||||
BUG_ON(!fbdefio);
|
BUG_ON(!fbdefio);
|
||||||
cancel_delayed_work_sync(&info->deferred_work);
|
cancel_delayed_work_sync(&info->deferred_work);
|
||||||
|
|
||||||
|
/* clear out the mapping that we setup */
|
||||||
|
for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
|
||||||
|
page = fb_deferred_io_page(info, i);
|
||||||
|
page->mapping = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_destroy(&fbdefio->lock);
|
mutex_destroy(&fbdefio->lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
|
EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
|
||||||
|
|
|
@ -1415,6 +1415,10 @@ __releases(&info->lock)
|
||||||
if (res)
|
if (res)
|
||||||
module_put(info->fbops->owner);
|
module_put(info->fbops->owner);
|
||||||
}
|
}
|
||||||
|
#ifdef CONFIG_FB_DEFERRED_IO
|
||||||
|
if (info->fbdefio)
|
||||||
|
fb_deferred_io_open(info, inode, file);
|
||||||
|
#endif
|
||||||
out:
|
out:
|
||||||
unlock_fb_info(info);
|
unlock_fb_info(info);
|
||||||
if (res)
|
if (res)
|
||||||
|
|
|
@ -659,6 +659,9 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
|
||||||
/* drivers/video/fb_defio.c */
|
/* drivers/video/fb_defio.c */
|
||||||
int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma);
|
int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma);
|
||||||
extern void fb_deferred_io_init(struct fb_info *info);
|
extern void fb_deferred_io_init(struct fb_info *info);
|
||||||
|
extern void fb_deferred_io_open(struct fb_info *info,
|
||||||
|
struct inode *inode,
|
||||||
|
struct file *file);
|
||||||
extern void fb_deferred_io_cleanup(struct fb_info *info);
|
extern void fb_deferred_io_cleanup(struct fb_info *info);
|
||||||
extern int fb_deferred_io_fsync(struct file *file, loff_t start,
|
extern int fb_deferred_io_fsync(struct file *file, loff_t start,
|
||||||
loff_t end, int datasync);
|
loff_t end, int datasync);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче