Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Revert "fb_defio: Remove custom address_space_operations"

Commit ccf953d8f3d6 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

authored by

Matthew Wilcox and committed by
Daniel Vetter
0b78f8bc 8124c8a6

+42
+35
drivers/video/fbdev/core/fb_defio.c
··· 52 52 return VM_FAULT_SIGBUS; 53 53 54 54 get_page(page); 55 + 56 + if (vmf->vma->vm_file) 57 + page->mapping = vmf->vma->vm_file->f_mapping; 58 + else 59 + printk(KERN_ERR "no mapping available\n"); 60 + 61 + BUG_ON(!page->mapping); 55 62 page->index = vmf->pgoff; 56 63 57 64 vmf->page = page; ··· 151 144 .page_mkwrite = fb_deferred_io_mkwrite, 152 145 }; 153 146 147 + static int fb_deferred_io_set_page_dirty(struct page *page) 148 + { 149 + if (!PageDirty(page)) 150 + SetPageDirty(page); 151 + return 0; 152 + } 153 + 154 + static const struct address_space_operations fb_deferred_io_aops = { 155 + .set_page_dirty = fb_deferred_io_set_page_dirty, 156 + }; 157 + 154 158 int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) 155 159 { 156 160 vma->vm_ops = &fb_deferred_io_vm_ops; ··· 212 194 } 213 195 EXPORT_SYMBOL_GPL(fb_deferred_io_init); 214 196 197 + void fb_deferred_io_open(struct fb_info *info, 198 + struct inode *inode, 199 + struct file *file) 200 + { 201 + file->f_mapping->a_ops = &fb_deferred_io_aops; 202 + } 203 + EXPORT_SYMBOL_GPL(fb_deferred_io_open); 204 + 215 205 void fb_deferred_io_cleanup(struct fb_info *info) 216 206 { 217 207 struct fb_deferred_io *fbdefio = info->fbdefio; 208 + struct page *page; 209 + int i; 218 210 219 211 BUG_ON(!fbdefio); 220 212 cancel_delayed_work_sync(&info->deferred_work); 213 + 214 + /* clear out the mapping that we setup */ 215 + for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { 216 + page = fb_deferred_io_page(info, i); 217 + page->mapping = NULL; 218 + } 219 + 221 220 mutex_destroy(&fbdefio->lock); 222 221 } 223 222 EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
+4
drivers/video/fbdev/core/fbmem.c
··· 1415 1415 if (res) 1416 1416 module_put(info->fbops->owner); 1417 1417 } 1418 + #ifdef CONFIG_FB_DEFERRED_IO 1419 + if (info->fbdefio) 1420 + fb_deferred_io_open(info, inode, file); 1421 + #endif 1418 1422 out: 1419 1423 unlock_fb_info(info); 1420 1424 if (res)
+3
include/linux/fb.h
··· 659 659 /* drivers/video/fb_defio.c */ 660 660 int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma); 661 661 extern void fb_deferred_io_init(struct fb_info *info); 662 + extern void fb_deferred_io_open(struct fb_info *info, 663 + struct inode *inode, 664 + struct file *file); 662 665 extern void fb_deferred_io_cleanup(struct fb_info *info); 663 666 extern int fb_deferred_io_fsync(struct file *file, loff_t start, 664 667 loff_t end, int datasync);