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;
|
||||
|
||||
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;
|
||||
|
||||
vmf->page = page;
|
||||
|
@ -144,6 +151,17 @@ static const struct vm_operations_struct fb_deferred_io_vm_ops = {
|
|||
.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)
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
struct fb_deferred_io *fbdefio = info->fbdefio;
|
||||
struct page *page;
|
||||
int i;
|
||||
|
||||
BUG_ON(!fbdefio);
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
|
||||
|
|
|
@ -1415,6 +1415,10 @@ __releases(&info->lock)
|
|||
if (res)
|
||||
module_put(info->fbops->owner);
|
||||
}
|
||||
#ifdef CONFIG_FB_DEFERRED_IO
|
||||
if (info->fbdefio)
|
||||
fb_deferred_io_open(info, inode, file);
|
||||
#endif
|
||||
out:
|
||||
unlock_fb_info(info);
|
||||
if (res)
|
||||
|
|
|
@ -659,6 +659,9 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
|
|||
/* drivers/video/fb_defio.c */
|
||||
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_open(struct fb_info *info,
|
||||
struct inode *inode,
|
||||
struct file *file);
|
||||
extern void fb_deferred_io_cleanup(struct fb_info *info);
|
||||
extern int fb_deferred_io_fsync(struct file *file, loff_t start,
|
||||
loff_t end, int datasync);
|
||||
|
|
Загрузка…
Ссылка в новой задаче