From 90808738fd242ef2533e86f2f481bebe8a7aa11b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 13 Nov 2013 23:44:15 +0000 Subject: 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 --- drivers/spi/spi.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/spi/spi.c') 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); -- cgit v1.2.2 From 368ca4e0c75612c0a4d6bbcef7efb944604340c2 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 26 Dec 2013 21:51:06 -0800 Subject: spi: Eliminate 3WIRE spi_transfer check Checking for SPI_3WIRE isn't needed. spi_setup() already prevents 3WIRE mode from being combined with DUAL or QUAD mode support. So there is no need to differentiate between a single bit device with SPI_3WIRE set and one with without. It doesn't change the allowed bit widths. Signed-off-by: Trent Piepho Signed-off-by: Mark Brown --- drivers/spi/spi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 857ee8c407b1..2cd9fdc9c7f9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1678,9 +1678,6 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) if ((xfer->tx_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_TX_QUAD)) return -EINVAL; - if ((spi->mode & SPI_3WIRE) && - (xfer->tx_nbits != SPI_NBITS_SINGLE)) - return -EINVAL; } /* check transfer rx_nbits */ if (xfer->rx_buf) { @@ -1694,9 +1691,6 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) if ((xfer->rx_nbits == SPI_NBITS_QUAD) && !(spi->mode & SPI_RX_QUAD)) return -EINVAL; - if ((spi->mode & SPI_3WIRE) && - (xfer->rx_nbits != SPI_NBITS_SINGLE)) - return -EINVAL; } } -- cgit v1.2.2 From 1cfd97f93e36b3f8b5d2a26147aaccae0c847a9c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 2 Jan 2014 15:16:40 +0800 Subject: spi: core: Use list_first_entry_or_null() instead of open-coded Use list_first_entry_or_null() to save a few lines. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2cd9fdc9c7f9..401cd66770f9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -791,11 +791,8 @@ struct spi_message *spi_get_next_queued_message(struct spi_master *master) /* get a pointer to the next message, if any */ spin_lock_irqsave(&master->queue_lock, flags); - if (list_empty(&master->queue)) - next = NULL; - else - next = list_entry(master->queue.next, - struct spi_message, queue); + next = list_first_entry_or_null(&master->queue, struct spi_message, + queue); spin_unlock_irqrestore(&master->queue_lock, flags); return next; -- cgit v1.2.2 From a89e2d2754246645959f1a2f91e37e9b367bfd36 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 9 Jan 2014 16:03:58 +0800 Subject: spi: core: Use list_first_entry to extract head of queue For slightly better readability. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 401cd66770f9..36bfa7f820a6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -685,7 +685,7 @@ static void spi_pump_messages(struct kthread_work *work) } /* Extract head of queue */ master->cur_msg = - list_entry(master->queue.next, struct spi_message, queue); + list_first_entry(&master->queue, struct spi_message, queue); list_del_init(&master->cur_msg->queue); if (master->busy) -- cgit v1.2.2 From 1afd9989a6a2561183be82e420d4d2f3889b7ee7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 12 Jan 2014 14:00:29 +0100 Subject: spi: core: Improve tx/rx_nbits check comments - Rephrase the comments about tx/rx_nbits validity checks, - Remove the stale comment about SPI_3WIRE (the code it refers to was removed in commit 368ca4e0c75612c0a4d6bbcef7efb944604340c2 ("spi: Eliminate 3WIRE spi_transfer check")). Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- drivers/spi/spi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 36bfa7f820a6..9f26797e4319 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1660,9 +1660,8 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) if (xfer->rx_buf && !xfer->rx_nbits) xfer->rx_nbits = SPI_NBITS_SINGLE; /* check transfer tx/rx_nbits: - * 1. keep the value is not out of single, dual and quad - * 2. keep tx/rx_nbits is contained by mode in spi_device - * 3. if SPI_3WIRE, tx/rx_nbits should be in single + * 1. check the value matches one of single, dual and quad + * 2. check tx/rx_nbits match the mode in spi_device */ if (xfer->tx_buf) { if (xfer->tx_nbits != SPI_NBITS_SINGLE && -- cgit v1.2.2