Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 198346
b: refs/heads/master
c: 49bbd81
h: refs/heads/master
v: v3
  • Loading branch information
Albert Herranz authored and Linus Torvalds committed May 25, 2010
1 parent ef9e023 commit 1470014
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0d5b02641faade3dfd376abdcffbd8ccb03c7a91
refs/heads/master: 49bbd815fd8ba26d0354900b783b767c7f47c816
40 changes: 32 additions & 8 deletions trunk/drivers/video/fb_defio.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,41 @@ static void fb_deferred_io_work(struct work_struct *work)
{
struct fb_info *info = container_of(work, struct fb_info,
deferred_work.work);
struct list_head *node, *next;
struct page *cur;
struct fb_deferred_io *fbdefio = info->fbdefio;
struct page *page, *tmp_page;
struct list_head *node, *tmp_node;
struct list_head non_dirty;

INIT_LIST_HEAD(&non_dirty);

/* here we mkclean the pages, then do all deferred IO */
mutex_lock(&fbdefio->lock);
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
lock_page(cur);
page_mkclean(cur);
unlock_page(cur);
list_for_each_entry_safe(page, tmp_page, &fbdefio->pagelist, lru) {
lock_page(page);
/*
* The workqueue callback can be triggered after a
* ->page_mkwrite() call but before the PTE has been marked
* dirty. In this case page_mkclean() won't "rearm" the page.
*
* To avoid this, remove those "non-dirty" pages from the
* pagelist before calling the driver's callback, then add
* them back to get processed on the next work iteration.
* At that time, their PTEs will hopefully be dirty for real.
*/
if (!page_mkclean(page))
list_move_tail(&page->lru, &non_dirty);
unlock_page(page);
}

/* driver's callback with pagelist */
fbdefio->deferred_io(info, &fbdefio->pagelist);

/* clear the list */
list_for_each_safe(node, next, &fbdefio->pagelist) {
/* clear the list... */
list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
list_del(node);
}
/* ... and add back the "non-dirty" pages to the list */
list_splice_tail(&non_dirty, &fbdefio->pagelist);
mutex_unlock(&fbdefio->lock);
}

Expand Down Expand Up @@ -202,13 +218,21 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open);
void fb_deferred_io_cleanup(struct fb_info *info)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct list_head *node, *tmp_node;
struct page *page;
int i;

BUG_ON(!fbdefio);
cancel_delayed_work(&info->deferred_work);
flush_scheduled_work();

/* the list may have still some non-dirty pages at this point */
mutex_lock(&fbdefio->lock);
list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
list_del(node);
}
mutex_unlock(&fbdefio->lock);

/* 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);
Expand Down

0 comments on commit 1470014

Please sign in to comment.