aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fb_defio.c40
1 files changed, 8 insertions, 32 deletions
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index 073c9b408cf7..137100ea8ad7 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -155,41 +155,25 @@ static void fb_deferred_io_work(struct work_struct *work)
155{ 155{
156 struct fb_info *info = container_of(work, struct fb_info, 156 struct fb_info *info = container_of(work, struct fb_info,
157 deferred_work.work); 157 deferred_work.work);
158 struct list_head *node, *next;
159 struct page *cur;
158 struct fb_deferred_io *fbdefio = info->fbdefio; 160 struct fb_deferred_io *fbdefio = info->fbdefio;
159 struct page *page, *tmp_page;
160 struct list_head *node, *tmp_node;
161 struct list_head non_dirty;
162
163 INIT_LIST_HEAD(&non_dirty);
164 161
165 /* here we mkclean the pages, then do all deferred IO */ 162 /* here we mkclean the pages, then do all deferred IO */
166 mutex_lock(&fbdefio->lock); 163 mutex_lock(&fbdefio->lock);
167 list_for_each_entry_safe(page, tmp_page, &fbdefio->pagelist, lru) { 164 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
168 lock_page(page); 165 lock_page(cur);
169 /* 166 page_mkclean(cur);
170 * The workqueue callback can be triggered after a 167 unlock_page(cur);
171 * ->page_mkwrite() call but before the PTE has been marked
172 * dirty. In this case page_mkclean() won't "rearm" the page.
173 *
174 * To avoid this, remove those "non-dirty" pages from the
175 * pagelist before calling the driver's callback, then add
176 * them back to get processed on the next work iteration.
177 * At that time, their PTEs will hopefully be dirty for real.
178 */
179 if (!page_mkclean(page))
180 list_move_tail(&page->lru, &non_dirty);
181 unlock_page(page);
182 } 168 }
183 169
184 /* driver's callback with pagelist */ 170 /* driver's callback with pagelist */
185 fbdefio->deferred_io(info, &fbdefio->pagelist); 171 fbdefio->deferred_io(info, &fbdefio->pagelist);
186 172
187 /* clear the list... */ 173 /* clear the list */
188 list_for_each_safe(node, tmp_node, &fbdefio->pagelist) { 174 list_for_each_safe(node, next, &fbdefio->pagelist) {
189 list_del(node); 175 list_del(node);
190 } 176 }
191 /* ... and add back the "non-dirty" pages to the list */
192 list_splice_tail(&non_dirty, &fbdefio->pagelist);
193 mutex_unlock(&fbdefio->lock); 177 mutex_unlock(&fbdefio->lock);
194} 178}
195 179
@@ -218,7 +202,6 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open);
218void fb_deferred_io_cleanup(struct fb_info *info) 202void fb_deferred_io_cleanup(struct fb_info *info)
219{ 203{
220 struct fb_deferred_io *fbdefio = info->fbdefio; 204 struct fb_deferred_io *fbdefio = info->fbdefio;
221 struct list_head *node, *tmp_node;
222 struct page *page; 205 struct page *page;
223 int i; 206 int i;
224 207
@@ -226,13 +209,6 @@ void fb_deferred_io_cleanup(struct fb_info *info)
226 cancel_delayed_work(&info->deferred_work); 209 cancel_delayed_work(&info->deferred_work);
227 flush_scheduled_work(); 210 flush_scheduled_work();
228 211
229 /* the list may have still some non-dirty pages at this point */
230 mutex_lock(&fbdefio->lock);
231 list_for_each_safe(node, tmp_node, &fbdefio->pagelist) {
232 list_del(node);
233 }
234 mutex_unlock(&fbdefio->lock);
235
236 /* clear out the mapping that we setup */ 212 /* clear out the mapping that we setup */
237 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { 213 for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) {
238 page = fb_deferred_io_page(info, i); 214 page = fb_deferred_io_page(info, i);