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.

Signed-off-by: Thomas Zimmermann <[email protected]>
---
 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 c6945b4422cc..c4be85f80d7d 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(sizeof(*fbdefio_state), GFP_KERNEL);
        if (!fbdefio_state)
                return NULL;
 
+       npagerefs = DIV_ROUND_UP(len, PAGE_SIZE);
+
+       /* alloc a page ref for each page of the display memory */
+       pagerefs = kvcalloc(npagerefs, sizeof(*pagerefs), GFP_KERNEL);
+       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 = kvcalloc(npagerefs, sizeof(*pagerefs), GFP_KERNEL);
-       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 2a9d05e51ff4..71e2759f3cfd 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -481,8 +481,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

Reply via email to