summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-11-14 00:44:15 +0100
committerMark Brown <broonie@linaro.org>2013-11-24 15:04:17 +0100
commit90808738fd242ef2533e86f2f481bebe8a7aa11b (patch)
tree9a5debdf86da3fe08616f56c3c1246fe95f6f7d1
parentLinux 3.13-rc1 (diff)
downloadlinux-90808738fd242ef2533e86f2f481bebe8a7aa11b.tar.xz
linux-90808738fd242ef2533e86f2f481bebe8a7aa11b.zip
spi: Factor validation and initialisation of messages outside lock
Currently we do a bunch of per-message validation and initialisation in __spi_async() which is called with the bus lock held. Since none of this validation depends on the current bus status there's no need to hold the lock to do it so split it out into a separate __spi_validate() function which is called prior to taking the bus lock. This could be slightly neater but keep things simple for now to show the code motion clearly. Based on observations from Martin Sperl. Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/spi/spi.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 18cc625d887f..857ee8c407b1 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1596,15 +1596,11 @@ int spi_setup(struct spi_device *spi)
}
EXPORT_SYMBOL_GPL(spi_setup);
-static int __spi_async(struct spi_device *spi, struct spi_message *message)
+static int __spi_validate(struct spi_device *spi, struct spi_message *message)
{
struct spi_master *master = spi->master;
struct spi_transfer *xfer;
- message->spi = spi;
-
- trace_spi_message_submit(message);
-
if (list_empty(&message->transfers))
return -EINVAL;
if (!message->complete)
@@ -1705,6 +1701,18 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
}
message->status = -EINPROGRESS;
+
+ return 0;
+}
+
+static int __spi_async(struct spi_device *spi, struct spi_message *message)
+{
+ struct spi_master *master = spi->master;
+
+ message->spi = spi;
+
+ trace_spi_message_submit(message);
+
return master->transfer(spi, message);
}
@@ -1743,6 +1751,10 @@ int spi_async(struct spi_device *spi, struct spi_message *message)
int ret;
unsigned long flags;
+ ret = __spi_validate(spi, message);
+ if (ret != 0)
+ return ret;
+
spin_lock_irqsave(&master->bus_lock_spinlock, flags);
if (master->bus_lock_flag)
@@ -1791,6 +1803,10 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message)
int ret;
unsigned long flags;
+ ret = __spi_validate(spi, message);
+ if (ret != 0)
+ return ret;
+
spin_lock_irqsave(&master->bus_lock_spinlock, flags);
ret = __spi_async(spi, message);