* [PATCH] spi: Unlock a spinlock before calling into the controller driver.
@ 2012-06-22 23:53 Bryan Freed
2012-06-24 23:54 ` Olof Johansson
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Bryan Freed @ 2012-06-22 23:53 UTC (permalink / raw)
To: spi-devel-general; +Cc: grant.likely, linux-kernel, Bryan Freed
spi_pump_messages() calls into a controller driver with
unprepare_transfer_hardware() which is documented as "This may sleep".
As in the prepare_transfer_hardware() call below, we should release the
queue_lock spinlock before making the call.
Rework the logic a bit to hold queue_lock to protect the 'busy' flag,
then release it to call unprepare_transfer_hardware().
Signed-off-by: Bryan Freed <bfreed@chromium.org>
---
drivers/spi/spi.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fc0da39..f7f9df9 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -532,17 +532,16 @@ static void spi_pump_messages(struct kthread_work *work)
/* Lock queue and check for queue work */
spin_lock_irqsave(&master->queue_lock, flags);
if (list_empty(&master->queue) || !master->running) {
- if (master->busy && master->unprepare_transfer_hardware) {
- ret = master->unprepare_transfer_hardware(master);
- if (ret) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- dev_err(&master->dev,
- "failed to unprepare transfer hardware\n");
- return;
- }
+ if (!master->busy) {
+ spin_unlock_irqrestore(&master->queue_lock, flags);
+ return;
}
master->busy = false;
spin_unlock_irqrestore(&master->queue_lock, flags);
+ if (master->unprepare_transfer_hardware &&
+ master->unprepare_transfer_hardware(master))
+ dev_err(&master->dev,
+ "failed to unprepare transfer hardware\n");
return;
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] spi: Unlock a spinlock before calling into the controller driver.
2012-06-22 23:53 [PATCH] spi: Unlock a spinlock before calling into the controller driver Bryan Freed
@ 2012-06-24 23:54 ` Olof Johansson
[not found] ` <CAOesGMgq5HRz+pDFQtED5GPN0RUrON=_k_y4YHHzKrMkHnVk4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
[not found] ` <1340409205-23606-1-git-send-email-bfreed-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2013-03-13 18:17 ` [REPOST PATCH] " Doug Anderson
2 siblings, 1 reply; 7+ messages in thread
From: Olof Johansson @ 2012-06-24 23:54 UTC (permalink / raw)
To: Bryan Freed
Cc: spi-devel-general, grant.likely, linux-kernel, LinusW, Mark Brown
Hi,
(Adding Linus Walleij and Mark Brown since they were the ones doing
the queue changes).
On Fri, Jun 22, 2012 at 4:53 PM, Bryan Freed <bfreed@chromium.org> wrote:
> spi_pump_messages() calls into a controller driver with
> unprepare_transfer_hardware() which is documented as "This may sleep".
> As in the prepare_transfer_hardware() call below, we should release the
> queue_lock spinlock before making the call.
> Rework the logic a bit to hold queue_lock to protect the 'busy' flag,
> then release it to call unprepare_transfer_hardware().
>
> Signed-off-by: Bryan Freed <bfreed@chromium.org>
>
> ---
> drivers/spi/spi.c | 15 +++++++--------
> 1 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index fc0da39..f7f9df9 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -532,17 +532,16 @@ static void spi_pump_messages(struct kthread_work *work)
> /* Lock queue and check for queue work */
> spin_lock_irqsave(&master->queue_lock, flags);
> if (list_empty(&master->queue) || !master->running) {
> - if (master->busy && master->unprepare_transfer_hardware) {
> - ret = master->unprepare_transfer_hardware(master);
> - if (ret) {
> - spin_unlock_irqrestore(&master->queue_lock, flags);
> - dev_err(&master->dev,
> - "failed to unprepare transfer hardware\n");
> - return;
> - }
> + if (!master->busy) {
> + spin_unlock_irqrestore(&master->queue_lock, flags);
> + return;
> }
> master->busy = false;
> spin_unlock_irqrestore(&master->queue_lock, flags);
> + if (master->unprepare_transfer_hardware &&
> + master->unprepare_transfer_hardware(master))
> + dev_err(&master->dev,
> + "failed to unprepare transfer hardware\n");
I'm not sure this is safe to do. The lock is dropped for the prepare
side, but in that case we can be sure that the above code can't come
in and unprepare at the same time since there is per definition a
request on the queue at that time.
On the other hand, between the lock drop and the call to unprepare
above, another code path can come in and queue up a request and either
not do prepare properly, or there will be a prepare that races with
the unprepare.
It might make more sense to use a workqueue here and schedule a
unprepare call that way instead (and cancelling appropriately before
the prepare call if needed). I'm open for other suggestions as well.
-Olof
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] spi: Unlock a spinlock before calling into the controller driver.
[not found] ` <CAOesGMgq5HRz+pDFQtED5GPN0RUrON=_k_y4YHHzKrMkHnVk4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-06-25 17:07 ` Doug Anderson
[not found] ` <CAD=FV=UpBG8gmPjWDF0M9EMSvs4pg7icocMXJ1r3Lmi8frZsrg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 7+ messages in thread
From: Doug Anderson @ 2012-06-25 17:07 UTC (permalink / raw)
To: Olof Johansson
Cc: LinusW, Mark Brown, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Bryan Freed, spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
Olof,
On Sun, Jun 24, 2012 at 4:54 PM, Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org> wrote:
> I'm not sure this is safe to do. The lock is dropped for the prepare
> side, but in that case we can be sure that the above code can't come
> in and unprepare at the same time since there is per definition a
> request on the queue at that time.
I spent a bunch of time staring at the code and I'm pretty sure that
there's no race and that the code is safe (if not super obvious).
Specifically there should be only one instance of spi_pump_messages()
running at a time per master. That's because it's a kthread work
function. ...so we can't possibly get a prepare in the middle of the
unprepare when prepare is called because the only caller to
prepare/unprepare is spi_pump_messages().
I can't comment on whether it's better to do something like add a
workqueue (which might be more obvious / less fragile) or just to add
a comment. I will let others comment on that. :)
-Doug
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] spi: Unlock a spinlock before calling into the controller driver.
[not found] ` <CAD=FV=UpBG8gmPjWDF0M9EMSvs4pg7icocMXJ1r3Lmi8frZsrg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-06-25 18:56 ` Linus Walleij
0 siblings, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2012-06-25 18:56 UTC (permalink / raw)
To: Doug Anderson
Cc: Mark Brown, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Bryan Freed,
Olof Johansson,
spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
On Tue, Jun 26, 2012 at 1:07 AM, Doug Anderson <dianders-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> Specifically there should be only one instance of spi_pump_messages()
> running at a time per master. That's because it's a kthread work
> function. ...so we can't possibly get a prepare in the middle of the
> unprepare when prepare is called because the only caller to
> prepare/unprepare is spi_pump_messages().
Yes that's how the message pump is designed.
> I can't comment on whether it's better to do something like add a
> workqueue (which might be more obvious / less fragile) or just to add
> a comment. I will let others comment on that. :)
The message pump initially used a workqueue, but was converted
to a kthread because we needed to push the queue to run as
realtime for some important low-latency workloads across
SPI. The code is basically a tweaked workqueue if you dive down
in the implementation.
Yours,
Linus Walleij
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] spi: Unlock a spinlock before calling into the controller driver.
[not found] ` <1340409205-23606-1-git-send-email-bfreed-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2012-06-25 19:01 ` Linus Walleij
0 siblings, 0 replies; 7+ messages in thread
From: Linus Walleij @ 2012-06-25 19:01 UTC (permalink / raw)
To: Bryan Freed
Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Sat, Jun 23, 2012 at 7:53 AM, Bryan Freed <bfreed-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> spi_pump_messages() calls into a controller driver with
> unprepare_transfer_hardware() which is documented as "This may sleep".
> As in the prepare_transfer_hardware() call below, we should release the
> queue_lock spinlock before making the call.
> Rework the logic a bit to hold queue_lock to protect the 'busy' flag,
> then release it to call unprepare_transfer_hardware().
>
> Signed-off-by: Bryan Freed <bfreed-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Yes, this looks correct to me! Good catch.
Acked-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Yours,
Linus Walleij
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
^ permalink raw reply [flat|nested] 7+ messages in thread
* [REPOST PATCH] spi: Unlock a spinlock before calling into the controller driver.
2012-06-22 23:53 [PATCH] spi: Unlock a spinlock before calling into the controller driver Bryan Freed
2012-06-24 23:54 ` Olof Johansson
[not found] ` <1340409205-23606-1-git-send-email-bfreed-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2013-03-13 18:17 ` Doug Anderson
2013-04-01 13:24 ` Mark Brown
2 siblings, 1 reply; 7+ messages in thread
From: Doug Anderson @ 2013-03-13 18:17 UTC (permalink / raw)
To: Grant Likely
Cc: Linus Walleij, Mark Brown, Olof Johansson, Greg Kroah-Hartman,
Bryan Freed, Doug Anderson, spi-devel-general, linux-kernel
From: Bryan Freed <bfreed@chromium.org>
spi_pump_messages() calls into a controller driver with
unprepare_transfer_hardware() which is documented as "This may sleep".
As in the prepare_transfer_hardware() call below, we should release the
queue_lock spinlock before making the call.
Rework the logic a bit to hold queue_lock to protect the 'busy' flag,
then release it to call unprepare_transfer_hardware().
Signed-off-by: Bryan Freed <bfreed@chromium.org>
Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Doug Anderson <dianders@chromium.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
During a rebase we noticed that this old patch never actually landed
anywhere. I haven't gone through an reproduced the original bug on
ToT but I believe that this patch is still required. Perhaps it could
land somewhere? ;) Thanks!
drivers/spi/spi.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index f996c60..5b96250 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work)
/* Lock queue and check for queue work */
spin_lock_irqsave(&master->queue_lock, flags);
if (list_empty(&master->queue) || !master->running) {
- if (master->busy && master->unprepare_transfer_hardware) {
- ret = master->unprepare_transfer_hardware(master);
- if (ret) {
- spin_unlock_irqrestore(&master->queue_lock, flags);
- dev_err(&master->dev,
- "failed to unprepare transfer hardware\n");
- return;
- }
+ if (!master->busy) {
+ spin_unlock_irqrestore(&master->queue_lock, flags);
+ return;
}
master->busy = false;
spin_unlock_irqrestore(&master->queue_lock, flags);
+ if (master->unprepare_transfer_hardware &&
+ master->unprepare_transfer_hardware(master))
+ dev_err(&master->dev,
+ "failed to unprepare transfer hardware\n");
return;
}
--
1.8.1.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [REPOST PATCH] spi: Unlock a spinlock before calling into the controller driver.
2013-03-13 18:17 ` [REPOST PATCH] " Doug Anderson
@ 2013-04-01 13:24 ` Mark Brown
0 siblings, 0 replies; 7+ messages in thread
From: Mark Brown @ 2013-04-01 13:24 UTC (permalink / raw)
To: Doug Anderson
Cc: Grant Likely, Linus Walleij, Olof Johansson, Greg Kroah-Hartman,
Bryan Freed, spi-devel-general, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 863 bytes --]
On Wed, Mar 13, 2013 at 11:17:40AM -0700, Doug Anderson wrote:
> From: Bryan Freed <bfreed@chromium.org>
>
> spi_pump_messages() calls into a controller driver with
> unprepare_transfer_hardware() which is documented as "This may sleep".
> As in the prepare_transfer_hardware() call below, we should release the
> queue_lock spinlock before making the call.
> Rework the logic a bit to hold queue_lock to protect the 'busy' flag,
> then release it to call unprepare_transfer_hardware().
Applied, thanks. However...
> spin_unlock_irqrestore(&master->queue_lock, flags);
> + if (master->unprepare_transfer_hardware &&
> + master->unprepare_transfer_hardware(master))
> + dev_err(&master->dev,
> + "failed to unprepare transfer hardware\n");
...it'd be nicer to pay attention to and log the error code if we fail
to unprepare.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2013-04-01 13:24 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-22 23:53 [PATCH] spi: Unlock a spinlock before calling into the controller driver Bryan Freed
2012-06-24 23:54 ` Olof Johansson
[not found] ` <CAOesGMgq5HRz+pDFQtED5GPN0RUrON=_k_y4YHHzKrMkHnVk4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-06-25 17:07 ` Doug Anderson
[not found] ` <CAD=FV=UpBG8gmPjWDF0M9EMSvs4pg7icocMXJ1r3Lmi8frZsrg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-06-25 18:56 ` Linus Walleij
[not found] ` <1340409205-23606-1-git-send-email-bfreed-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2012-06-25 19:01 ` Linus Walleij
2013-03-13 18:17 ` [REPOST PATCH] " Doug Anderson
2013-04-01 13:24 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).