Skip to content

Commit 0b78f8b

Browse files
Matthew Wilcoxdanvet
authored andcommitted
Revert "fb_defio: Remove custom address_space_operations"
Commit ccf953d 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 <[email protected]> Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Daniel Vetter <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 8124c8a commit 0b78f8b

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

drivers/video/fbdev/core/fb_defio.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
5252
return VM_FAULT_SIGBUS;
5353

5454
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);
5562
page->index = vmf->pgoff;
5663

5764
vmf->page = page;
@@ -144,6 +151,17 @@ static const struct vm_operations_struct fb_deferred_io_vm_ops = {
144151
.page_mkwrite = fb_deferred_io_mkwrite,
145152
};
146153

154+
static int fb_deferred_io_set_page_dirty(struct page *page)
155+
{
156+
if (!PageDirty(page))
157+
SetPageDirty(page);
158+
return 0;
159+
}
160+
161+
static const struct address_space_operations fb_deferred_io_aops = {
162+
.set_page_dirty = fb_deferred_io_set_page_dirty,
163+
};
164+
147165
int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
148166
{
149167
vma->vm_ops = &fb_deferred_io_vm_ops;
@@ -194,12 +212,29 @@ void fb_deferred_io_init(struct fb_info *info)
194212
}
195213
EXPORT_SYMBOL_GPL(fb_deferred_io_init);
196214

215+
void fb_deferred_io_open(struct fb_info *info,
216+
struct inode *inode,
217+
struct file *file)
218+
{
219+
file->f_mapping->a_ops = &fb_deferred_io_aops;
220+
}
221+
EXPORT_SYMBOL_GPL(fb_deferred_io_open);
222+
197223
void fb_deferred_io_cleanup(struct fb_info *info)
198224
{
199225
struct fb_deferred_io *fbdefio = info->fbdefio;
226+
struct page *page;
227+
int i;
200228

201229
BUG_ON(!fbdefio);
202230
cancel_delayed_work_sync(&info->deferred_work);
231+
232+
/* clear out the mapping that we setup */
233+
for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
234+
page = fb_deferred_io_page(info, i);
235+
page->mapping = NULL;
236+
}
237+
203238
mutex_destroy(&fbdefio->lock);
204239
}
205240
EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);

drivers/video/fbdev/core/fbmem.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,10 @@ __releases(&info->lock)
14151415
if (res)
14161416
module_put(info->fbops->owner);
14171417
}
1418+
#ifdef CONFIG_FB_DEFERRED_IO
1419+
if (info->fbdefio)
1420+
fb_deferred_io_open(info, inode, file);
1421+
#endif
14181422
out:
14191423
unlock_fb_info(info);
14201424
if (res)

include/linux/fb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,9 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
659659
/* drivers/video/fb_defio.c */
660660
int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma);
661661
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);
662665
extern void fb_deferred_io_cleanup(struct fb_info *info);
663666
extern int fb_deferred_io_fsync(struct file *file, loff_t start,
664667
loff_t end, int datasync);

0 commit comments

Comments
 (0)