Validate smart_update before creating the smart-panel thread, so the thread cannot exit independently before kthread_stop(). Use the freezer-safe stop API and stop the thread on removal and every probe error path after it has been created. Unregister the cpufreq notifier during removal.
Found by Sashiko AI review. Link: https://lore.kernel.org/dri-devel/[email protected] --- drivers/video/fbdev/pxafb.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index 1912cfce28d6..1b2a16590999 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -1248,20 +1248,10 @@ static int pxafb_smart_thread(void *arg) struct pxafb_info *fbi = arg; struct pxafb_mach_info *inf = fbi->inf; - if (!inf->smart_update) { - pr_err("%s: not properly initialized, thread terminated\n", - __func__); - return -EINVAL; - } - pr_debug("%s(): task starting\n", __func__); set_freezable(); - while (!kthread_should_stop()) { - - if (try_to_freeze()) - continue; - + while (!kthread_freezable_should_stop(NULL)) { mutex_lock(&fbi->ctrlr_lock); if (fbi->state == C_ENABLE) { @@ -1290,6 +1280,9 @@ static int pxafb_smart_init(struct pxafb_info *fbi) init_completion(&fbi->command_done); init_completion(&fbi->refresh_done); + if (!fbi->inf->smart_update) + return -EINVAL; + fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi, "lcd_refresh"); if (IS_ERR(fbi->smart_thread)) { @@ -1299,8 +1292,15 @@ static int pxafb_smart_init(struct pxafb_info *fbi) return 0; } + +static void pxafb_smart_exit(struct pxafb_info *fbi) +{ + if (!IS_ERR_OR_NULL(fbi->smart_thread)) + kthread_stop(fbi->smart_thread); +} #else static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; } +static inline void pxafb_smart_exit(struct pxafb_info *fbi) { } #endif /* CONFIG_FB_PXA_SMARTPANEL */ static void setup_parallel_timing(struct pxafb_info *fbi, @@ -2364,6 +2364,7 @@ static int pxafb_probe(struct platform_device *dev) if (fbi->fb.cmap.len) fb_dealloc_cmap(&fbi->fb.cmap); failed_free_mem: + pxafb_smart_exit(fbi); free_pages_exact(fbi->video_mem, fbi->video_mem_size); failed_free_dma: dma_free_coherent(&dev->dev, fbi->dma_buff_size, @@ -2382,6 +2383,11 @@ static void pxafb_remove(struct platform_device *dev) info = &fbi->fb; +#ifdef CONFIG_CPU_FREQ + cpufreq_unregister_notifier(&fbi->freq_transition, + CPUFREQ_TRANSITION_NOTIFIER); +#endif + pxafb_smart_exit(fbi); pxafb_overlay_exit(fbi); cancel_work_sync(&fbi->task); unregister_framebuffer(info); base-commit: d89e1d186ec9271bf78e62771779e9fc03bf0fc3 prerequisite-patch-id: 44b1c2680cb029871e123eb11eab7764a807ef24 prerequisite-patch-id: f4dfbbaaec2d208ac255451cf032c22f0e7fed2d prerequisite-patch-id: ff6a574f35399a0059df3a759cbd2a558d24300c prerequisite-patch-id: 784ec68755ba9ffc1d5693e1baff1f59d574c331 -- 2.56.0
