[PATCH v2 4/4] fbdev: defio: Move pageref array to struct fb_deferred_io_state
From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2026-02-24 08:27:11
Also in:
dri-devel
Subsystem:
arc framebuffer driver, framebuffer core, framebuffer layer, the rest · Maintainers:
Jaya Kumar, Simona Vetter, Helge Deller, Linus Torvalds
The pageref array stores all pageref structures for a device's defio helpers. Move it into struct fb_deferred_io_state to not expose it to drivers. v2: - use kvzalloc_objs() Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/video/fbdev/core/fb_defio.c | 55 ++++++++++++++--------------- include/linux/fb.h | 2 -- 2 files changed, 27 insertions(+), 30 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index 35ac13727da1..a12dd25ab697 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c@@ -41,28 +41,46 @@ struct fb_deferred_io_state { /* fields protected by lock */ struct fb_info *info; struct list_head pagereflist; /* list of pagerefs for touched pages */ + unsigned long npagerefs; + struct fb_deferred_io_pageref *pagerefs; }; -static struct fb_deferred_io_state *fb_deferred_io_state_alloc(void) +static struct fb_deferred_io_state *fb_deferred_io_state_alloc(unsigned long len) { struct fb_deferred_io_state *fbdefio_state; + struct fb_deferred_io_pageref *pagerefs; + unsigned long npagerefs; fbdefio_state = kzalloc_obj(*fbdefio_state); if (!fbdefio_state) return NULL; + npagerefs = DIV_ROUND_UP(len, PAGE_SIZE); + + /* alloc a page ref for each page of the display memory */ + pagerefs = kvzalloc_objs(*pagerefs, npagerefs); + if (!pagerefs) + goto err_kfree; + fbdefio_state->npagerefs = npagerefs; + fbdefio_state->pagerefs = pagerefs; + kref_init(&fbdefio_state->ref); mutex_init(&fbdefio_state->lock); INIT_LIST_HEAD(&fbdefio_state->pagereflist); return fbdefio_state; + +err_kfree: + kfree(fbdefio_state); + return NULL; } static void fb_deferred_io_state_release(struct fb_deferred_io_state *fbdefio_state) { WARN_ON(!list_empty(&fbdefio_state->pagereflist)); mutex_destroy(&fbdefio_state->lock); + kvfree(fbdefio_state->pagerefs); kfree(fbdefio_state); }
@@ -125,18 +143,19 @@ static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long return page; } -static struct fb_deferred_io_pageref *fb_deferred_io_pageref_lookup(struct fb_info *info, - unsigned long offset, - struct page *page) +static struct fb_deferred_io_pageref * +fb_deferred_io_pageref_lookup(struct fb_deferred_io_state *fbdefio_state, unsigned long offset, + struct page *page) { + struct fb_info *info = fbdefio_state->info; unsigned long pgoff = offset >> PAGE_SHIFT; struct fb_deferred_io_pageref *pageref; - if (fb_WARN_ON_ONCE(info, pgoff >= info->npagerefs)) + if (fb_WARN_ON_ONCE(info, pgoff >= fbdefio_state->npagerefs)) return NULL; /* incorrect allocation size */ /* 1:1 mapping between pageref and page offset */ - pageref = &info->pagerefs[pgoff]; + pageref = &fbdefio_state->pagerefs[pgoff]; if (pageref->page) goto out;
@@ -160,7 +179,7 @@ static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info struct list_head *pos = &fbdefio_state->pagereflist; struct fb_deferred_io_pageref *pageref, *cur; - pageref = fb_deferred_io_pageref_lookup(info, offset, page); + pageref = fb_deferred_io_pageref_lookup(fbdefio_state, offset, page); if (!pageref) return NULL;
@@ -397,16 +416,13 @@ int fb_deferred_io_init(struct fb_info *info) { struct fb_deferred_io *fbdefio = info->fbdefio; struct fb_deferred_io_state *fbdefio_state; - struct fb_deferred_io_pageref *pagerefs; - unsigned long npagerefs; - int ret; BUG_ON(!fbdefio); if (WARN_ON(!info->fix.smem_len)) return -EINVAL; - fbdefio_state = fb_deferred_io_state_alloc(); + fbdefio_state = fb_deferred_io_state_alloc(info->fix.smem_len); if (!fbdefio_state) return -ENOMEM; fbdefio_state->info = info;
@@ -415,24 +431,9 @@ int fb_deferred_io_init(struct fb_info *info) if (fbdefio->delay == 0) /* set a default of 1 s */ fbdefio->delay = HZ; - npagerefs = DIV_ROUND_UP(info->fix.smem_len, PAGE_SIZE); - - /* alloc a page ref for each page of the display memory */ - pagerefs = kvzalloc_objs(*pagerefs, npagerefs); - if (!pagerefs) { - ret = -ENOMEM; - goto err; - } - info->npagerefs = npagerefs; - info->pagerefs = pagerefs; - info->fbdefio_state = fbdefio_state; return 0; - -err: - fb_deferred_io_state_release(fbdefio_state); - return ret; } EXPORT_SYMBOL_GPL(fb_deferred_io_init);
@@ -475,7 +476,5 @@ void fb_deferred_io_cleanup(struct fb_info *info) mutex_unlock(&fbdefio_state->lock); fb_deferred_io_state_put(fbdefio_state); - - kvfree(info->pagerefs); } EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 2791777f3a50..b27943719fab 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h@@ -482,8 +482,6 @@ struct fb_info { #ifdef CONFIG_FB_DEFERRED_IO struct delayed_work deferred_work; - unsigned long npagerefs; - struct fb_deferred_io_pageref *pagerefs; struct fb_deferred_io *fbdefio; struct fb_deferred_io_state *fbdefio_state; #endif
--
2.52.0