Commit e2d8b428 authored by Thomas Zimmermann's avatar Thomas Zimmermann

fbdev: Use pageref offset for deferred-I/O writeback

Use pageref->offset instead of page->index for deferred-I/O writeback
where appropriate. Distinguishes between file-mapping offset and video-
memory offset. While at it, also remove unnecessary references to
struct page.

Fbdev's deferred-I/O code uses the two related page->index and
pageref->offset. The former is the page offset in the mapped file,
the latter is the byte offset in the video memory (or fbdev screen
buffer). It's the same value for fbdev drivers, but for DRM the values
can be different. Because GEM buffer objects are mapped at an offset
in the DRM device file, page->index has this offset added to it as well.
We currently don't hit this case in DRM, because all affected mappings
of GEM memory are performed with an internal, intermediate shadow buffer.

The value of page->index is required by page_mkclean(), which we
call to reset the mappings during the writeback phase of the deferred
I/O. The value of pageref->offset is for conveniently getting an offset
into video memory in fb helpers.

v4:
	* fix commit message (Javier)
Suggested-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220429100834.18898-6-tzimmermann@suse.de
parent e80eec1b
...@@ -327,8 +327,7 @@ static void vmw_deferred_io(struct fb_info *info, struct list_head *pagereflist) ...@@ -327,8 +327,7 @@ static void vmw_deferred_io(struct fb_info *info, struct list_head *pagereflist)
min = ULONG_MAX; min = ULONG_MAX;
max = 0; max = 0;
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *page = pageref->page; start = pageref->offset;
start = page->index << PAGE_SHIFT;
end = start + PAGE_SIZE - 1; end = start + PAGE_SIZE - 1;
min = min(min, start); min = min(min, start);
max = max(max, end); max = max(max, end);
......
...@@ -327,7 +327,6 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflis ...@@ -327,7 +327,6 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflis
struct fbtft_par *par = info->par; struct fbtft_par *par = info->par;
unsigned int dirty_lines_start, dirty_lines_end; unsigned int dirty_lines_start, dirty_lines_end;
struct fb_deferred_io_pageref *pageref; struct fb_deferred_io_pageref *pageref;
unsigned long index;
unsigned int y_low = 0, y_high = 0; unsigned int y_low = 0, y_high = 0;
int count = 0; int count = 0;
...@@ -341,14 +340,12 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflis ...@@ -341,14 +340,12 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagereflis
/* Mark display lines as dirty */ /* Mark display lines as dirty */
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *page = pageref->page;
count++; count++;
index = page->index << PAGE_SHIFT; y_low = pageref->offset / info->fix.line_length;
y_low = index / info->fix.line_length; y_high = (pageref->offset + PAGE_SIZE - 1) / info->fix.line_length;
y_high = (index + PAGE_SIZE - 1) / info->fix.line_length;
dev_dbg(info->device, dev_dbg(info->device,
"page->index=%lu y_low=%d y_high=%d\n", "page->index=%lu y_low=%d y_high=%d\n",
page->index, y_low, y_high); pageref->page->index, y_low, y_high);
if (y_high > info->var.yres - 1) if (y_high > info->var.yres - 1)
y_high = info->var.yres - 1; y_high = info->var.yres - 1;
if (y_low < dirty_lines_start) if (y_low < dirty_lines_start)
......
...@@ -932,7 +932,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) ...@@ -932,7 +932,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
static void broadsheetfb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist) static void broadsheetfb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{ {
u16 y1 = 0, h = 0; u16 y1 = 0, h = 0;
int prev_index = -1; unsigned long prev_offset = ULONG_MAX;
struct fb_deferred_io_pageref *pageref; struct fb_deferred_io_pageref *pageref;
int h_inc; int h_inc;
u16 yres = info->var.yres; u16 yres = info->var.yres;
...@@ -943,22 +943,21 @@ static void broadsheetfb_dpy_deferred_io(struct fb_info *info, struct list_head ...@@ -943,22 +943,21 @@ static void broadsheetfb_dpy_deferred_io(struct fb_info *info, struct list_head
/* walk the written page list and swizzle the data */ /* walk the written page list and swizzle the data */
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *cur = pageref->page; if (prev_offset == ULONG_MAX) {
if (prev_index < 0) {
/* just starting so assign first page */ /* just starting so assign first page */
y1 = (cur->index << PAGE_SHIFT) / xres; y1 = pageref->offset / xres;
h = h_inc; h = h_inc;
} else if ((prev_index + 1) == cur->index) { } else if ((prev_offset + PAGE_SIZE) == pageref->offset) {
/* this page is consecutive so increase our height */ /* this page is consecutive so increase our height */
h += h_inc; h += h_inc;
} else { } else {
/* page not consecutive, issue previous update first */ /* page not consecutive, issue previous update first */
broadsheetfb_dpy_update_pages(info->par, y1, y1 + h); broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
/* start over with our non consecutive page */ /* start over with our non consecutive page */
y1 = (cur->index << PAGE_SHIFT) / xres; y1 = pageref->offset / xres;
h = h_inc; h = h_inc;
} }
prev_index = cur->index; prev_offset = pageref->offset;
} }
/* if we still have any pages to update we do so now */ /* if we still have any pages to update we do so now */
......
...@@ -437,8 +437,7 @@ static void synthvid_deferred_io(struct fb_info *p, struct list_head *pagereflis ...@@ -437,8 +437,7 @@ static void synthvid_deferred_io(struct fb_info *p, struct list_head *pagereflis
* value to yres. * value to yres.
*/ */
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *page = pageref->page; start = pageref->offset;
start = page->index << PAGE_SHIFT;
end = start + PAGE_SIZE - 1; end = start + PAGE_SIZE - 1;
y1 = start / p->fix.line_length; y1 = start / p->fix.line_length;
y2 = end / p->fix.line_length; y2 = end / p->fix.line_length;
......
...@@ -473,11 +473,10 @@ static void metronomefb_dpy_deferred_io(struct fb_info *info, struct list_head * ...@@ -473,11 +473,10 @@ static void metronomefb_dpy_deferred_io(struct fb_info *info, struct list_head *
/* walk the written page list and swizzle the data */ /* walk the written page list and swizzle the data */
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *cur = pageref->page; unsigned long pgoffset = pageref->offset >> PAGE_SHIFT;
cksum = metronomefb_dpy_update_page(par, cksum = metronomefb_dpy_update_page(par, pageref->offset);
(cur->index << PAGE_SHIFT)); par->metromem_img_csum -= par->csum_table[pgoffset];
par->metromem_img_csum -= par->csum_table[cur->index]; par->csum_table[pgoffset] = cksum;
par->csum_table[cur->index] = cksum;
par->metromem_img_csum += cksum; par->metromem_img_csum += cksum;
} }
......
...@@ -445,8 +445,7 @@ static int sh_mobile_lcdc_sginit(struct fb_info *info, struct list_head *pageref ...@@ -445,8 +445,7 @@ static int sh_mobile_lcdc_sginit(struct fb_info *info, struct list_head *pageref
sg_init_table(ch->sglist, nr_pages_max); sg_init_table(ch->sglist, nr_pages_max);
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *page = pageref->page; sg_set_page(&ch->sglist[nr_pages++], pageref->page, PAGE_SIZE, 0);
sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
} }
return nr_pages; return nr_pages;
......
...@@ -970,10 +970,9 @@ static void ufx_dpy_deferred_io(struct fb_info *info, struct list_head *pagerefl ...@@ -970,10 +970,9 @@ static void ufx_dpy_deferred_io(struct fb_info *info, struct list_head *pagerefl
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
/* create a rectangle of full screen width that encloses the /* create a rectangle of full screen width that encloses the
* entire dirty framebuffer page */ * entire dirty framebuffer page */
struct page *cur = pageref->page;
const int x = 0; const int x = 0;
const int width = dev->info->var.xres; const int width = dev->info->var.xres;
const int y = (cur->index << PAGE_SHIFT) / (width * 2); const int y = pageref->offset / (width * 2);
int height = (PAGE_SIZE / (width * 2)) + 1; int height = (PAGE_SIZE / (width * 2)) + 1;
height = min(height, (int)(dev->info->var.yres - y)); height = min(height, (int)(dev->info->var.yres - y));
......
...@@ -810,11 +810,9 @@ static void dlfb_dpy_deferred_io(struct fb_info *info, struct list_head *pageref ...@@ -810,11 +810,9 @@ static void dlfb_dpy_deferred_io(struct fb_info *info, struct list_head *pageref
/* walk the written page list and render each to device */ /* walk the written page list and render each to device */
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *cur = pageref->page;
if (dlfb_render_hline(dlfb, &urb, (char *) info->fix.smem_start, if (dlfb_render_hline(dlfb, &urb, (char *) info->fix.smem_start,
&cmd, cur->index << PAGE_SHIFT, &cmd, pageref->offset, PAGE_SIZE,
PAGE_SIZE, &bytes_identical, &bytes_sent)) &bytes_identical, &bytes_sent))
goto error; goto error;
bytes_rendered += PAGE_SIZE; bytes_rendered += PAGE_SIZE;
} }
......
...@@ -191,8 +191,7 @@ static void xenfb_deferred_io(struct fb_info *fb_info, struct list_head *pageref ...@@ -191,8 +191,7 @@ static void xenfb_deferred_io(struct fb_info *fb_info, struct list_head *pageref
miny = INT_MAX; miny = INT_MAX;
maxy = 0; maxy = 0;
list_for_each_entry(pageref, pagereflist, list) { list_for_each_entry(pageref, pagereflist, list) {
struct page *page = pageref->page; beg = pageref->offset;
beg = page->index << PAGE_SHIFT;
end = beg + PAGE_SIZE - 1; end = beg + PAGE_SIZE - 1;
y1 = beg / fb_info->fix.line_length; y1 = beg / fb_info->fix.line_length;
y2 = end / fb_info->fix.line_length; y2 = end / fb_info->fix.line_length;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment