* [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset
@ 2017-12-12 13:47 Jia-Ju Bai
2017-12-15 14:16 ` Hans Verkuil
2017-12-15 14:51 ` Fabien DESSENNE
0 siblings, 2 replies; 7+ messages in thread
From: Jia-Ju Bai @ 2017-12-12 13:47 UTC (permalink / raw)
To: fabien.dessenne, mchehab; +Cc: linux-media, linux-kernel, Jia-Ju Bai
The driver may sleep under a spinlock.
The function call path is:
bdisp_device_run (acquire the spinlock)
bdisp_hw_reset
msleep --> may sleep
To fix it, msleep is replaced with mdelay.
This bug is found by my static analysis tool(DSAC) and checked by my code review.
Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
---
drivers/media/platform/sti/bdisp/bdisp-hw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/media/platform/sti/bdisp/bdisp-hw.c b/drivers/media/platform/sti/bdisp/bdisp-hw.c
index b7892f3..4b62ceb 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-hw.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-hw.c
@@ -382,7 +382,7 @@ int bdisp_hw_reset(struct bdisp_dev *bdisp)
for (i = 0; i < POLL_RST_MAX; i++) {
if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE)
break;
- msleep(POLL_RST_DELAY_MS);
+ mdelay(POLL_RST_DELAY_MS);
}
if (i == POLL_RST_MAX)
dev_err(bdisp->dev, "Reset timeout\n");
--
1.7.9.5
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset 2017-12-12 13:47 [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset Jia-Ju Bai @ 2017-12-15 14:16 ` Hans Verkuil 2017-12-15 14:51 ` Fabien DESSENNE 1 sibling, 0 replies; 7+ messages in thread From: Hans Verkuil @ 2017-12-15 14:16 UTC (permalink / raw) To: fabien.dessenne, Benjamin Gaignard Cc: Jia-Ju Bai, mchehab, linux-media, linux-kernel Fabien or Benjamin, can you take a look at these two patches? I'm a bit hesitant applying this since e.g. this bdisp_hw_reset() function might wait for up to a second, which is a mite long for an interrupt :-) Regards, Hans On 12/12/17 14:47, Jia-Ju Bai wrote: > The driver may sleep under a spinlock. > The function call path is: > bdisp_device_run (acquire the spinlock) > bdisp_hw_reset > msleep --> may sleep > > To fix it, msleep is replaced with mdelay. > > This bug is found by my static analysis tool(DSAC) and checked by my code review. > > Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com> > --- > drivers/media/platform/sti/bdisp/bdisp-hw.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/media/platform/sti/bdisp/bdisp-hw.c b/drivers/media/platform/sti/bdisp/bdisp-hw.c > index b7892f3..4b62ceb 100644 > --- a/drivers/media/platform/sti/bdisp/bdisp-hw.c > +++ b/drivers/media/platform/sti/bdisp/bdisp-hw.c > @@ -382,7 +382,7 @@ int bdisp_hw_reset(struct bdisp_dev *bdisp) > for (i = 0; i < POLL_RST_MAX; i++) { > if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE) > break; > - msleep(POLL_RST_DELAY_MS); > + mdelay(POLL_RST_DELAY_MS); > } > if (i == POLL_RST_MAX) > dev_err(bdisp->dev, "Reset timeout\n"); > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset 2017-12-12 13:47 [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset Jia-Ju Bai 2017-12-15 14:16 ` Hans Verkuil @ 2017-12-15 14:51 ` Fabien DESSENNE 2017-12-16 11:53 ` Jia-Ju Bai 1 sibling, 1 reply; 7+ messages in thread From: Fabien DESSENNE @ 2017-12-15 14:51 UTC (permalink / raw) To: Jia-Ju Bai, Mauro Carvalho Chehab Cc: linux-media, linux-kernel, Benjamin GAIGNARD, Hans Verkuil Hi On 12/12/17 14:47, Jia-Ju Bai wrote: > The driver may sleep under a spinlock. > The function call path is: > bdisp_device_run (acquire the spinlock) > bdisp_hw_reset > msleep --> may sleep > > To fix it, msleep is replaced with mdelay. May I suggest you to use readl_poll_timeout_atomic (instead of the whole "for" block): this fixes the problem and simplifies the code? > > This bug is found by my static analysis tool(DSAC) and checked by my code review. > > Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com> > --- > drivers/media/platform/sti/bdisp/bdisp-hw.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/media/platform/sti/bdisp/bdisp-hw.c b/drivers/media/platform/sti/bdisp/bdisp-hw.c > index b7892f3..4b62ceb 100644 > --- a/drivers/media/platform/sti/bdisp/bdisp-hw.c > +++ b/drivers/media/platform/sti/bdisp/bdisp-hw.c > @@ -382,7 +382,7 @@ int bdisp_hw_reset(struct bdisp_dev *bdisp) > for (i = 0; i < POLL_RST_MAX; i++) { > if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE) > break; > - msleep(POLL_RST_DELAY_MS); > + mdelay(POLL_RST_DELAY_MS); > } > if (i == POLL_RST_MAX) > dev_err(bdisp->dev, "Reset timeout\n"); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset 2017-12-15 14:51 ` Fabien DESSENNE @ 2017-12-16 11:53 ` Jia-Ju Bai 2017-12-16 14:14 ` Mauro Carvalho Chehab 0 siblings, 1 reply; 7+ messages in thread From: Jia-Ju Bai @ 2017-12-16 11:53 UTC (permalink / raw) To: Fabien DESSENNE, Mauro Carvalho Chehab Cc: linux-media, linux-kernel, Benjamin GAIGNARD, Hans Verkuil Hi, On 2017/12/15 22:51, Fabien DESSENNE wrote: > Hi > > On 12/12/17 14:47, Jia-Ju Bai wrote: >> The driver may sleep under a spinlock. >> The function call path is: >> bdisp_device_run (acquire the spinlock) >> bdisp_hw_reset >> msleep --> may sleep >> >> To fix it, msleep is replaced with mdelay. > May I suggest you to use readl_poll_timeout_atomic (instead of the whole > "for" block): this fixes the problem and simplifies the code? Okay, I have submitted a patch according to your advice. You can have a look :) Thanks, Jia-Ju Bai >> This bug is found by my static analysis tool(DSAC) and checked by my code review. >> >> Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com> >> --- >> drivers/media/platform/sti/bdisp/bdisp-hw.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/media/platform/sti/bdisp/bdisp-hw.c b/drivers/media/platform/sti/bdisp/bdisp-hw.c >> index b7892f3..4b62ceb 100644 >> --- a/drivers/media/platform/sti/bdisp/bdisp-hw.c >> +++ b/drivers/media/platform/sti/bdisp/bdisp-hw.c >> @@ -382,7 +382,7 @@ int bdisp_hw_reset(struct bdisp_dev *bdisp) >> for (i = 0; i < POLL_RST_MAX; i++) { >> if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE) >> break; >> - msleep(POLL_RST_DELAY_MS); >> + mdelay(POLL_RST_DELAY_MS); >> } >> if (i == POLL_RST_MAX) >> dev_err(bdisp->dev, "Reset timeout\n"); ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset 2017-12-16 11:53 ` Jia-Ju Bai @ 2017-12-16 14:14 ` Mauro Carvalho Chehab 2017-12-19 9:01 ` Fabien DESSENNE 0 siblings, 1 reply; 7+ messages in thread From: Mauro Carvalho Chehab @ 2017-12-16 14:14 UTC (permalink / raw) To: Jia-Ju Bai Cc: Fabien DESSENNE, linux-media, linux-kernel, Benjamin GAIGNARD, Hans Verkuil Em Sat, 16 Dec 2017 19:53:55 +0800 Jia-Ju Bai <baijiaju1990@gmail.com> escreveu: > Hi, > > On 2017/12/15 22:51, Fabien DESSENNE wrote: > > Hi > > > > On 12/12/17 14:47, Jia-Ju Bai wrote: > >> The driver may sleep under a spinlock. > >> The function call path is: > >> bdisp_device_run (acquire the spinlock) > >> bdisp_hw_reset > >> msleep --> may sleep > >> > >> To fix it, msleep is replaced with mdelay. > > May I suggest you to use readl_poll_timeout_atomic (instead of the whole > > "for" block): this fixes the problem and simplifies the code? > > Okay, I have submitted a patch according to your advice. > You can have a look :) This can still be usind mdelay() to wait for a long time. It doesn't seem wise to do that, as it could cause system contention. Couldn't this be reworked in a way to avoid having the spin locked while sleeping? Once we had a similar issue on Siano, and it was solved by this commit 3cdadc50bbe8f04c1231c8af614cafd7ddd622bf Author: Richard Zidlicky <rz@linux-m68k.org> Date: Tue Aug 24 09:52:36 2010 -0300 V4L/DVB: dvb: fix smscore_getbuffer() logic Drivers shouldn't sleep while holding a spinlock. A previous workaround were to release the spinlock before callinc schedule(). This patch uses a different approach: it just waits for the siano hardware to answer. Signed-off-by: Richard Zidlicky <rz@linux-m68k.org> Cc: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> The code as changed to use wait_event() at the kthread that was waiting for data to arrive. Only when the data is ready, the code with the spin lock is called. It made the driver a way more stable, and didn't add any penalties of needing to do long delays on a non-interruptible code. Thanks, Mauro ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset 2017-12-16 14:14 ` Mauro Carvalho Chehab @ 2017-12-19 9:01 ` Fabien DESSENNE 2017-12-19 9:40 ` Mauro Carvalho Chehab 0 siblings, 1 reply; 7+ messages in thread From: Fabien DESSENNE @ 2017-12-19 9:01 UTC (permalink / raw) To: Mauro Carvalho Chehab, Jia-Ju Bai Cc: linux-media, linux-kernel, Benjamin GAIGNARD, Hans Verkuil On 16/12/17 15:14, Mauro Carvalho Chehab wrote: > Em Sat, 16 Dec 2017 19:53:55 +0800 > Jia-Ju Bai <baijiaju1990@gmail.com> escreveu: > >> Hi, >> >> On 2017/12/15 22:51, Fabien DESSENNE wrote: >>> Hi >>> >>> On 12/12/17 14:47, Jia-Ju Bai wrote: >>>> The driver may sleep under a spinlock. >>>> The function call path is: >>>> bdisp_device_run (acquire the spinlock) >>>> bdisp_hw_reset >>>> msleep --> may sleep >>>> >>>> To fix it, msleep is replaced with mdelay. >>> May I suggest you to use readl_poll_timeout_atomic (instead of the whole >>> "for" block): this fixes the problem and simplifies the code? >> Okay, I have submitted a patch according to your advice. >> You can have a look :) > This can still be usind mdelay() to wait for a long time. > > It doesn't seem wise to do that, as it could cause system > contention. Couldn't this be reworked in a way to avoid > having the spin locked while sleeping? > > Once we had a similar issue on Siano, and it was solved by this > > commit 3cdadc50bbe8f04c1231c8af614cafd7ddd622bf > Author: Richard Zidlicky <rz@linux-m68k.org> > Date: Tue Aug 24 09:52:36 2010 -0300 > > V4L/DVB: dvb: fix smscore_getbuffer() logic > > Drivers shouldn't sleep while holding a spinlock. A previous workaround > were to release the spinlock before callinc schedule(). > > This patch uses a different approach: it just waits for the > siano hardware to answer. > > Signed-off-by: Richard Zidlicky <rz@linux-m68k.org> > Cc: stable@kernel.org > Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> > > The code as changed to use wait_event() at the kthread that was > waiting for data to arrive. Only when the data is ready, the > code with the spin lock is called. > > It made the driver a way more stable, and didn't add any penalties > of needing to do long delays on a non-interruptible code. > > Thanks, > Mauro I have checked what was done there but I cannot see a simple way to do the same in bdisp where the context is a bit different (the lock is taken out in the central device_run, not locally in hw_reset) without taking the risk to have unexpected side effects Moreover, the bdisp_hw_reset() function called from bdisp_device_run is not expected to last for a long time. The "one second" delay we are talking about is a very large timeout protection. From my past observations, the reset is applied instantly and we even never reach the msleep() call (not saying it never happens). For those two reasons, using readl_poll_timeout_atomic() seems to be the best option. BR Fabien ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset 2017-12-19 9:01 ` Fabien DESSENNE @ 2017-12-19 9:40 ` Mauro Carvalho Chehab 0 siblings, 0 replies; 7+ messages in thread From: Mauro Carvalho Chehab @ 2017-12-19 9:40 UTC (permalink / raw) To: Fabien DESSENNE Cc: Jia-Ju Bai, linux-media, linux-kernel, Benjamin GAIGNARD, Hans Verkuil Em Tue, 19 Dec 2017 09:01:41 +0000 Fabien DESSENNE <fabien.dessenne@st.com> escreveu: > On 16/12/17 15:14, Mauro Carvalho Chehab wrote: > > Em Sat, 16 Dec 2017 19:53:55 +0800 > > Jia-Ju Bai <baijiaju1990@gmail.com> escreveu: > > > >> Hi, > >> > >> On 2017/12/15 22:51, Fabien DESSENNE wrote: > >>> Hi > >>> > >>> On 12/12/17 14:47, Jia-Ju Bai wrote: > >>>> The driver may sleep under a spinlock. > >>>> The function call path is: > >>>> bdisp_device_run (acquire the spinlock) > >>>> bdisp_hw_reset > >>>> msleep --> may sleep > >>>> > >>>> To fix it, msleep is replaced with mdelay. > >>> May I suggest you to use readl_poll_timeout_atomic (instead of the whole > >>> "for" block): this fixes the problem and simplifies the code? > >> Okay, I have submitted a patch according to your advice. > >> You can have a look :) > > This can still be usind mdelay() to wait for a long time. > > > > It doesn't seem wise to do that, as it could cause system > > contention. Couldn't this be reworked in a way to avoid > > having the spin locked while sleeping? > > > > Once we had a similar issue on Siano, and it was solved by this > > > > commit 3cdadc50bbe8f04c1231c8af614cafd7ddd622bf > > Author: Richard Zidlicky <rz@linux-m68k.org> > > Date: Tue Aug 24 09:52:36 2010 -0300 > > > > V4L/DVB: dvb: fix smscore_getbuffer() logic > > > > Drivers shouldn't sleep while holding a spinlock. A previous workaround > > were to release the spinlock before callinc schedule(). > > > > This patch uses a different approach: it just waits for the > > siano hardware to answer. > > > > Signed-off-by: Richard Zidlicky <rz@linux-m68k.org> > > Cc: stable@kernel.org > > Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> > > > > The code as changed to use wait_event() at the kthread that was > > waiting for data to arrive. Only when the data is ready, the > > code with the spin lock is called. > > > > It made the driver a way more stable, and didn't add any penalties > > of needing to do long delays on a non-interruptible code. > > > > Thanks, > > Mauro > I have checked what was done there but I cannot see a simple way to do > the same in bdisp where the context is a bit different (the lock is > taken out in the central device_run, not locally in hw_reset) without > taking the risk to have unexpected side effects > > Moreover, the bdisp_hw_reset() function called from bdisp_device_run is > not expected to last for a long time. The "one second" delay we are > talking about is a very large timeout protection. From my past > observations, the reset is applied instantly and we even never reach the > msleep() call (not saying it never happens). > > For those two reasons, using readl_poll_timeout_atomic() seems to be the > best option. OK. The best is then to document it at the source code, for others to be aware, while reviewing the code, that, despite the large timeout, most of the time the reset happens without needing any delays. Thanks, Mauro ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-12-19 9:40 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-12-12 13:47 [PATCH 1/2] bdisp: Fix a possible sleep-in-atomic bug in bdisp_hw_reset Jia-Ju Bai 2017-12-15 14:16 ` Hans Verkuil 2017-12-15 14:51 ` Fabien DESSENNE 2017-12-16 11:53 ` Jia-Ju Bai 2017-12-16 14:14 ` Mauro Carvalho Chehab 2017-12-19 9:01 ` Fabien DESSENNE 2017-12-19 9:40 ` Mauro Carvalho Chehab
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®