* [PATCH] spi: core: Fix deadlock when sending messages
@ 2016-03-08 9:49 Jon Hunter
[not found] ` <1457430543-15179-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Jon Hunter @ 2016-03-08 9:49 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, Jon Hunter
The function __spi_pump_messages() is called by spi_pump_messages() and
__spi_sync(). The function __spi_sync() has an argument 'bus_locked'
that indicates if it is called with the SPI bus mutex held or not. If
'bus_locked' is false then __spi_sync() will acquire the mutex itself.
Commit 556351f14e74 ("spi: introduce accelerated read support for spi
flash devices") made a change to acquire the SPI bus mutex within
__spi_pump_messages(). However, this change did not check to see if the
mutex is already held. If __spi_sync() is called with the mutex held
(ie. 'bus_locked' is true), then a deadlock occurs when
__spi_pump_messages() is called.
Fix this deadlock by passing the 'bus_locked' state from __spi_sync() to
__spi_pump_messages() and only acquire the mutex if not already held. In
the case where __spi_pump_messages() is called from spi_pump_messages()
it is assumed that the mutex is not held and so call
__spi_pump_messages() with 'bus_locked' set to false. Finally, move the
unlocking of the mutex to the end of the __spi_pump_messages() function
to simplify the code and only call cond_resched() if there are no
errors.
Fixes: 556351f14e74 ("spi: introduce accelerated read support for spi flash devices")
Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
This deadlock is seen on the Tegra124 Nyan Big chromebook and prevents
the board from booting -next.
drivers/spi/spi.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fe0196328aa0..e699fec9ddc5 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1062,7 +1062,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
* inside spi_sync(); the queue extraction handling at the top of the
* function should deal with this safely.
*/
-static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
+static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
+ bool bus_locked)
{
unsigned long flags;
bool was_busy = false;
@@ -1158,7 +1159,9 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
}
}
- mutex_lock(&master->bus_lock_mutex);
+ if (!bus_locked)
+ mutex_lock(&master->bus_lock_mutex);
+
trace_spi_message_start(master->cur_msg);
if (master->prepare_message) {
@@ -1168,8 +1171,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
"failed to prepare message: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
master->cur_msg_prepared = true;
}
@@ -1178,21 +1180,23 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
if (ret) {
master->cur_msg->status = ret;
spi_finalize_current_message(master);
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
ret = master->transfer_one_message(master, master->cur_msg);
if (ret) {
dev_err(&master->dev,
"failed to transfer one message from queue\n");
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
- mutex_unlock(&master->bus_lock_mutex);
+
+out:
+ if (!bus_locked)
+ mutex_unlock(&master->bus_lock_mutex);
/* Prod the scheduler in case transfer_one() was busy waiting */
- cond_resched();
+ if (!ret)
+ cond_resched();
}
/**
@@ -1204,7 +1208,7 @@ static void spi_pump_messages(struct kthread_work *work)
struct spi_master *master =
container_of(work, struct spi_master, pump_messages);
- __spi_pump_messages(master, true);
+ __spi_pump_messages(master, true, false);
}
static int spi_init_queue(struct spi_master *master)
@@ -2814,7 +2818,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
spi_sync_immediate);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
spi_sync_immediate);
- __spi_pump_messages(master, false);
+ __spi_pump_messages(master, false, bus_locked);
}
wait_for_completion(&done);
--
2.1.4
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] spi: core: Fix deadlock when sending messages
[not found] ` <1457430543-15179-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2016-03-08 9:50 ` Jon Hunter
2016-03-08 10:46 ` kbuild test robot
2016-03-08 12:28 ` [PATCH V2] " Jon Hunter
2 siblings, 0 replies; 5+ messages in thread
From: Jon Hunter @ 2016-03-08 9:50 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, vigneshr-l0cyMroinI0
Adding Vignesh ...
On 08/03/16 09:49, Jon Hunter wrote:
> The function __spi_pump_messages() is called by spi_pump_messages() and
> __spi_sync(). The function __spi_sync() has an argument 'bus_locked'
> that indicates if it is called with the SPI bus mutex held or not. If
> 'bus_locked' is false then __spi_sync() will acquire the mutex itself.
>
> Commit 556351f14e74 ("spi: introduce accelerated read support for spi
> flash devices") made a change to acquire the SPI bus mutex within
> __spi_pump_messages(). However, this change did not check to see if the
> mutex is already held. If __spi_sync() is called with the mutex held
> (ie. 'bus_locked' is true), then a deadlock occurs when
> __spi_pump_messages() is called.
>
> Fix this deadlock by passing the 'bus_locked' state from __spi_sync() to
> __spi_pump_messages() and only acquire the mutex if not already held. In
> the case where __spi_pump_messages() is called from spi_pump_messages()
> it is assumed that the mutex is not held and so call
> __spi_pump_messages() with 'bus_locked' set to false. Finally, move the
> unlocking of the mutex to the end of the __spi_pump_messages() function
> to simplify the code and only call cond_resched() if there are no
> errors.
>
> Fixes: 556351f14e74 ("spi: introduce accelerated read support for spi flash devices")
>
> Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> ---
>
> This deadlock is seen on the Tegra124 Nyan Big chromebook and prevents
> the board from booting -next.
>
> drivers/spi/spi.c | 28 ++++++++++++++++------------
> 1 file changed, 16 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index fe0196328aa0..e699fec9ddc5 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -1062,7 +1062,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
> * inside spi_sync(); the queue extraction handling at the top of the
> * function should deal with this safely.
> */
> -static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
> +static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
> + bool bus_locked)
> {
> unsigned long flags;
> bool was_busy = false;
> @@ -1158,7 +1159,9 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
> }
> }
>
> - mutex_lock(&master->bus_lock_mutex);
> + if (!bus_locked)
> + mutex_lock(&master->bus_lock_mutex);
> +
> trace_spi_message_start(master->cur_msg);
>
> if (master->prepare_message) {
> @@ -1168,8 +1171,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
> "failed to prepare message: %d\n", ret);
> master->cur_msg->status = ret;
> spi_finalize_current_message(master);
> - mutex_unlock(&master->bus_lock_mutex);
> - return;
> + goto out;
> }
> master->cur_msg_prepared = true;
> }
> @@ -1178,21 +1180,23 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
> if (ret) {
> master->cur_msg->status = ret;
> spi_finalize_current_message(master);
> - mutex_unlock(&master->bus_lock_mutex);
> - return;
> + goto out;
> }
>
> ret = master->transfer_one_message(master, master->cur_msg);
> if (ret) {
> dev_err(&master->dev,
> "failed to transfer one message from queue\n");
> - mutex_unlock(&master->bus_lock_mutex);
> - return;
> + goto out;
> }
> - mutex_unlock(&master->bus_lock_mutex);
> +
> +out:
> + if (!bus_locked)
> + mutex_unlock(&master->bus_lock_mutex);
>
> /* Prod the scheduler in case transfer_one() was busy waiting */
> - cond_resched();
> + if (!ret)
> + cond_resched();
> }
>
> /**
> @@ -1204,7 +1208,7 @@ static void spi_pump_messages(struct kthread_work *work)
> struct spi_master *master =
> container_of(work, struct spi_master, pump_messages);
>
> - __spi_pump_messages(master, true);
> + __spi_pump_messages(master, true, false);
> }
>
> static int spi_init_queue(struct spi_master *master)
> @@ -2814,7 +2818,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
> spi_sync_immediate);
> SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
> spi_sync_immediate);
> - __spi_pump_messages(master, false);
> + __spi_pump_messages(master, false, bus_locked);
> }
>
> wait_for_completion(&done);
>
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] spi: core: Fix deadlock when sending messages
[not found] ` <1457430543-15179-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-03-08 9:50 ` Jon Hunter
@ 2016-03-08 10:46 ` kbuild test robot
2016-03-08 12:28 ` [PATCH V2] " Jon Hunter
2 siblings, 0 replies; 5+ messages in thread
From: kbuild test robot @ 2016-03-08 10:46 UTC (permalink / raw)
To: Jon Hunter
Cc: kbuild-all-JC7UmRfGjtg, Mark Brown,
linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, Jon Hunter
[-- Attachment #1: Type: text/plain, Size: 3620 bytes --]
Hi Jon,
[auto build test WARNING on spi/for-next]
[also build test WARNING on next-20160308]
[cannot apply to v4.5-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]
url: https://github.com/0day-ci/linux/commits/Jon-Hunter/spi-core-Fix-deadlock-when-sending-messages/20160308-175230
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi for-next
reproduce: make htmldocs
All warnings (new ones prefixed by >>):
include/linux/init.h:1: warning: no structured comments found
kernel/sys.c:1: warning: no structured comments found
drivers/dma-buf/seqno-fence.c:1: warning: no structured comments found
drivers/dma-buf/reservation.c:1: warning: no structured comments found
include/linux/reservation.h:1: warning: no structured comments found
include/linux/spi/spi.h:933: error: Cannot parse struct or union!
>> drivers/spi/spi.c:1067: warning: No description found for parameter 'bus_locked'
drivers/spi/spi.c:2358: warning: No description found for parameter 'gfp'
>> drivers/spi/spi.c:1067: warning: No description found for parameter 'bus_locked'
drivers/spi/spi.c:2358: warning: No description found for parameter 'gfp'
vim +/bus_locked +1067 drivers/spi/spi.c
b158935f7 Mark Brown 2013-10-05 1051
ffbbdd213 Linus Walleij 2012-02-22 1052 /**
fc9e0f71f Mark Brown 2014-12-10 1053 * __spi_pump_messages - function which processes spi message queue
fc9e0f71f Mark Brown 2014-12-10 1054 * @master: master to process queue for
fc9e0f71f Mark Brown 2014-12-10 1055 * @in_kthread: true if we are in the context of the message pump thread
ffbbdd213 Linus Walleij 2012-02-22 1056 *
ffbbdd213 Linus Walleij 2012-02-22 1057 * This function checks if there is any spi message in the queue that
ffbbdd213 Linus Walleij 2012-02-22 1058 * needs processing and if so call out to the driver to initialize hardware
ffbbdd213 Linus Walleij 2012-02-22 1059 * and transfer each message.
ffbbdd213 Linus Walleij 2012-02-22 1060 *
0461a4149 Mark Brown 2014-12-09 1061 * Note that it is called both from the kthread itself and also from
0461a4149 Mark Brown 2014-12-09 1062 * inside spi_sync(); the queue extraction handling at the top of the
0461a4149 Mark Brown 2014-12-09 1063 * function should deal with this safely.
ffbbdd213 Linus Walleij 2012-02-22 1064 */
1f9706090 Jon Hunter 2016-03-08 1065 static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
1f9706090 Jon Hunter 2016-03-08 1066 bool bus_locked)
ffbbdd213 Linus Walleij 2012-02-22 @1067 {
ffbbdd213 Linus Walleij 2012-02-22 1068 unsigned long flags;
ffbbdd213 Linus Walleij 2012-02-22 1069 bool was_busy = false;
ffbbdd213 Linus Walleij 2012-02-22 1070 int ret;
ffbbdd213 Linus Walleij 2012-02-22 1071
983aee5d7 Mark Brown 2014-12-09 1072 /* Lock queue */
ffbbdd213 Linus Walleij 2012-02-22 1073 spin_lock_irqsave(&master->queue_lock, flags);
983aee5d7 Mark Brown 2014-12-09 1074
983aee5d7 Mark Brown 2014-12-09 1075 /* Make sure we are not already running a message */
:::::: The code at line 1067 was first introduced by commit
:::::: ffbbdd21329f3e15eeca6df2d4bc11c04d9d91c0 spi: create a message queueing infrastructure
:::::: TO: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
:::::: CC: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6229 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH V2] spi: core: Fix deadlock when sending messages
[not found] ` <1457430543-15179-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-03-08 9:50 ` Jon Hunter
2016-03-08 10:46 ` kbuild test robot
@ 2016-03-08 12:28 ` Jon Hunter
[not found] ` <1457440100-31546-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2 siblings, 1 reply; 5+ messages in thread
From: Jon Hunter @ 2016-03-08 12:28 UTC (permalink / raw)
To: Mark Brown, vigneshr-l0cyMroinI0
Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA, Jon Hunter
The function __spi_pump_messages() is called by spi_pump_messages() and
__spi_sync(). The function __spi_sync() has an argument 'bus_locked'
that indicates if it is called with the SPI bus mutex held or not. If
'bus_locked' is false then __spi_sync() will acquire the mutex itself.
Commit 556351f14e74 ("spi: introduce accelerated read support for spi
flash devices") made a change to acquire the SPI bus mutex within
__spi_pump_messages(). However, this change did not check to see if the
mutex is already held. If __spi_sync() is called with the mutex held
(ie. 'bus_locked' is true), then a deadlock occurs when
__spi_pump_messages() is called.
Fix this deadlock by passing the 'bus_locked' state from __spi_sync() to
__spi_pump_messages() and only acquire the mutex if not already held. In
the case where __spi_pump_messages() is called from spi_pump_messages()
it is assumed that the mutex is not held and so call
__spi_pump_messages() with 'bus_locked' set to false. Finally, move the
unlocking of the mutex to the end of the __spi_pump_messages() function
to simplify the code and only call cond_resched() if there are no
errors.
Fixes: 556351f14e74 ("spi: introduce accelerated read support for spi flash devices")
Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
Changes v1-v2:
- Updated kernel-doc for new parameter added to __spi_pump_messages()
drivers/spi/spi.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index fe0196328aa0..78b7e899ce76 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1053,6 +1053,7 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
* __spi_pump_messages - function which processes spi message queue
* @master: master to process queue for
* @in_kthread: true if we are in the context of the message pump thread
+ * @bus_locked: true if the bus mutex is held when calling this function
*
* This function checks if there is any spi message in the queue that
* needs processing and if so call out to the driver to initialize hardware
@@ -1062,7 +1063,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
* inside spi_sync(); the queue extraction handling at the top of the
* function should deal with this safely.
*/
-static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
+static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
+ bool bus_locked)
{
unsigned long flags;
bool was_busy = false;
@@ -1158,7 +1160,9 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
}
}
- mutex_lock(&master->bus_lock_mutex);
+ if (!bus_locked)
+ mutex_lock(&master->bus_lock_mutex);
+
trace_spi_message_start(master->cur_msg);
if (master->prepare_message) {
@@ -1168,8 +1172,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
"failed to prepare message: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
master->cur_msg_prepared = true;
}
@@ -1178,21 +1181,23 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
if (ret) {
master->cur_msg->status = ret;
spi_finalize_current_message(master);
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
ret = master->transfer_one_message(master, master->cur_msg);
if (ret) {
dev_err(&master->dev,
"failed to transfer one message from queue\n");
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
- mutex_unlock(&master->bus_lock_mutex);
+
+out:
+ if (!bus_locked)
+ mutex_unlock(&master->bus_lock_mutex);
/* Prod the scheduler in case transfer_one() was busy waiting */
- cond_resched();
+ if (!ret)
+ cond_resched();
}
/**
@@ -1204,7 +1209,7 @@ static void spi_pump_messages(struct kthread_work *work)
struct spi_master *master =
container_of(work, struct spi_master, pump_messages);
- __spi_pump_messages(master, true);
+ __spi_pump_messages(master, true, false);
}
static int spi_init_queue(struct spi_master *master)
@@ -2814,7 +2819,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
spi_sync_immediate);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
spi_sync_immediate);
- __spi_pump_messages(master, false);
+ __spi_pump_messages(master, false, bus_locked);
}
wait_for_completion(&done);
--
2.1.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Applied "spi: core: Fix deadlock when sending messages" to the spi tree
[not found] ` <1457440100-31546-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
@ 2016-03-09 2:34 ` Mark Brown
0 siblings, 0 replies; 5+ messages in thread
From: Mark Brown @ 2016-03-09 2:34 UTC (permalink / raw)
To: Jon Hunter, Mark Brown; +Cc: linux-spi-u79uwXL29TY76Z2rM5mHXA
The patch
spi: core: Fix deadlock when sending messages
has been applied to the spi tree at
git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 49023d2e4ead0fc9e0896331037746b267d46ad4 Mon Sep 17 00:00:00 2001
From: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Date: Tue, 8 Mar 2016 12:28:20 +0000
Subject: [PATCH] spi: core: Fix deadlock when sending messages
The function __spi_pump_messages() is called by spi_pump_messages() and
__spi_sync(). The function __spi_sync() has an argument 'bus_locked'
that indicates if it is called with the SPI bus mutex held or not. If
'bus_locked' is false then __spi_sync() will acquire the mutex itself.
Commit 556351f14e74 ("spi: introduce accelerated read support for spi
flash devices") made a change to acquire the SPI bus mutex within
__spi_pump_messages(). However, this change did not check to see if the
mutex is already held. If __spi_sync() is called with the mutex held
(ie. 'bus_locked' is true), then a deadlock occurs when
__spi_pump_messages() is called.
Fix this deadlock by passing the 'bus_locked' state from __spi_sync() to
__spi_pump_messages() and only acquire the mutex if not already held. In
the case where __spi_pump_messages() is called from spi_pump_messages()
it is assumed that the mutex is not held and so call
__spi_pump_messages() with 'bus_locked' set to false. Finally, move the
unlocking of the mutex to the end of the __spi_pump_messages() function
to simplify the code and only call cond_resched() if there are no
errors.
Fixes: 556351f14e74 ("spi: introduce accelerated read support for spi flash devices")
Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Mark Brown <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
drivers/spi/spi.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 0b2bbf144460..f565cc8901a6 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1047,6 +1047,7 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
* __spi_pump_messages - function which processes spi message queue
* @master: master to process queue for
* @in_kthread: true if we are in the context of the message pump thread
+ * @bus_locked: true if the bus mutex is held when calling this function
*
* This function checks if there is any spi message in the queue that
* needs processing and if so call out to the driver to initialize hardware
@@ -1056,7 +1057,8 @@ EXPORT_SYMBOL_GPL(spi_finalize_current_transfer);
* inside spi_sync(); the queue extraction handling at the top of the
* function should deal with this safely.
*/
-static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
+static void __spi_pump_messages(struct spi_master *master, bool in_kthread,
+ bool bus_locked)
{
unsigned long flags;
bool was_busy = false;
@@ -1152,7 +1154,9 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
}
}
- mutex_lock(&master->bus_lock_mutex);
+ if (!bus_locked)
+ mutex_lock(&master->bus_lock_mutex);
+
trace_spi_message_start(master->cur_msg);
if (master->prepare_message) {
@@ -1162,8 +1166,7 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
"failed to prepare message: %d\n", ret);
master->cur_msg->status = ret;
spi_finalize_current_message(master);
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
master->cur_msg_prepared = true;
}
@@ -1172,21 +1175,23 @@ static void __spi_pump_messages(struct spi_master *master, bool in_kthread)
if (ret) {
master->cur_msg->status = ret;
spi_finalize_current_message(master);
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
ret = master->transfer_one_message(master, master->cur_msg);
if (ret) {
dev_err(&master->dev,
"failed to transfer one message from queue\n");
- mutex_unlock(&master->bus_lock_mutex);
- return;
+ goto out;
}
- mutex_unlock(&master->bus_lock_mutex);
+
+out:
+ if (!bus_locked)
+ mutex_unlock(&master->bus_lock_mutex);
/* Prod the scheduler in case transfer_one() was busy waiting */
- cond_resched();
+ if (!ret)
+ cond_resched();
}
/**
@@ -1198,7 +1203,7 @@ static void spi_pump_messages(struct kthread_work *work)
struct spi_master *master =
container_of(work, struct spi_master, pump_messages);
- __spi_pump_messages(master, true);
+ __spi_pump_messages(master, true, false);
}
static int spi_init_queue(struct spi_master *master)
@@ -2462,7 +2467,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
spi_sync_immediate);
SPI_STATISTICS_INCREMENT_FIELD(&spi->statistics,
spi_sync_immediate);
- __spi_pump_messages(master, false);
+ __spi_pump_messages(master, false, bus_locked);
}
wait_for_completion(&done);
--
2.7.0
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2016-03-09 2:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-08 9:49 [PATCH] spi: core: Fix deadlock when sending messages Jon Hunter
[not found] ` <1457430543-15179-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-03-08 9:50 ` Jon Hunter
2016-03-08 10:46 ` kbuild test robot
2016-03-08 12:28 ` [PATCH V2] " Jon Hunter
[not found] ` <1457440100-31546-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2016-03-09 2:34 ` Applied "spi: core: Fix deadlock when sending messages" to the spi tree 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).