[PATCH v4 2/2] staging: fbtft: cleanup error handling in fbtft_framebuffer_alloc()

From: Abdun Nihaal
Date: Tue Jul 01 2025 - 05:41:54 EST


The error handling in fbtft_framebuffer_alloc() mixes managed allocation
and plain allocation, and performs error handling in an order different
from the order in fbtft_framebuffer_release().

Fix them by moving vmem allocation closer to where it is used, and using
plain kzalloc() for txbuf allocation.

Suggested-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxx>
Suggested-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx>
Signed-off-by: Abdun Nihaal <abdun.nihaal@xxxxxxxxx>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
Reviewed-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx>
---
v3->v4:
- Added Reviewed-by tags

v2->v3:
- Remove the if check before kfree of txbuf.buf, because it is zero
initialized on allocation, and kfree is NULL aware.

Newly added in v2

drivers/staging/fbtft/fbtft-core.c | 31 +++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 8538b6bab6a5..9e7b84071174 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -568,18 +568,13 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
height = display->height;
}

- vmem_size = display->width * display->height * bpp / 8;
- vmem = vzalloc(vmem_size);
- if (!vmem)
- goto alloc_fail;
-
fbdefio = devm_kzalloc(dev, sizeof(struct fb_deferred_io), GFP_KERNEL);
if (!fbdefio)
- goto alloc_fail;
+ return NULL;

buf = devm_kzalloc(dev, 128, GFP_KERNEL);
if (!buf)
- goto alloc_fail;
+ return NULL;

if (display->gamma_num && display->gamma_len) {
gamma_curves = devm_kcalloc(dev,
@@ -588,12 +583,17 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
sizeof(gamma_curves[0]),
GFP_KERNEL);
if (!gamma_curves)
- goto alloc_fail;
+ return NULL;
}

info = framebuffer_alloc(sizeof(struct fbtft_par), dev);
if (!info)
- goto alloc_fail;
+ return NULL;
+
+ vmem_size = display->width * display->height * bpp / 8;
+ vmem = vzalloc(vmem_size);
+ if (!vmem)
+ goto release_framebuf;

info->screen_buffer = vmem;
info->fbops = &fbtft_ops;
@@ -613,7 +613,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
info->fix.accel = FB_ACCEL_NONE;
info->fix.smem_len = vmem_size;
if (fb_deferred_io_init(info))
- goto release_framebuf;
+ goto release_screen_buffer;

info->var.rotate = pdata->rotate;
info->var.xres = width;
@@ -668,7 +668,7 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
#endif

if (txbuflen > 0) {
- txbuf = devm_kzalloc(par->info->device, txbuflen, GFP_KERNEL);
+ txbuf = kzalloc(txbuflen, GFP_KERNEL);
if (!txbuf)
goto cleanup_deferred;
par->txbuf.buf = txbuf;
@@ -694,12 +694,10 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,

cleanup_deferred:
fb_deferred_io_cleanup(info);
+release_screen_buffer:
+ vfree(info->screen_buffer);
release_framebuf:
framebuffer_release(info);
-
-alloc_fail:
- vfree(vmem);
-
return NULL;
}
EXPORT_SYMBOL(fbtft_framebuffer_alloc);
@@ -712,6 +710,9 @@ EXPORT_SYMBOL(fbtft_framebuffer_alloc);
*/
void fbtft_framebuffer_release(struct fb_info *info)
{
+ struct fbtft_par *par = info->par;
+
+ kfree(par->txbuf.buf);
fb_deferred_io_cleanup(info);
vfree(info->screen_buffer);
framebuffer_release(info);
--
2.43.0