Message ID | d15187348e7d7f76b7a1adf95aa5e3e3ecfc10b4.1702890493.git.namcao@linutronix.de |
---|---|
State | New |
Headers | show |
Series | fix LCD diplays sporadically not work | expand |
On 12/18/23 10:57, Nam Cao wrote: > The driver's fsync() is supposed to flush any pending operation to > hardware. It is implemented in this driver by cancelling the queued > deferred IO first, then schedule it for "immediate execution" by calling > schedule_delayed_work() again with delay=0. However, setting delay=0 > only means the work is scheduled immediately, it does not mean the work > is executed immediately. There is no guarantee that the work is finished > after schedule_delayed_work() returns. After this driver's fsync() > returns, there can still be pending work. Furthermore, if close() is > called by users immediately after fsync(), the pending work gets > cancelled and fsync() may do nothing. > > To ensure that the deferred IO completes, use flush_delayed_work() > instead. Write operations to this driver either write to the device > directly, or invoke schedule_delayed_work(); so by flushing the > workqueue, it can be guaranteed that all previous writes make it to the > device. > > Fixes: 5e841b88d23d ("fb: fsync() method for deferred I/O flush.") > Cc: stable@vger.kernel.org > Signed-off-by: Nam Cao <namcao@linutronix.de> > Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> > --- > drivers/video/fbdev/core/fb_defio.c | 6 +----- > 1 file changed, 1 insertion(+), 5 deletions(-) both patches applied to fbdev for-next git tree. Thanks! Helge
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 274f5d0fa247..6c8b81c452f0 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -132,11 +132,7 @@ int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasy return 0; inode_lock(inode); - /* Kill off the delayed work */ - cancel_delayed_work_sync(&info->deferred_work); - - /* Run it immediately */ - schedule_delayed_work(&info->deferred_work, 0); + flush_delayed_work(&info->deferred_work); inode_unlock(inode); return 0;