diff options
author | Mark Brown <broonie@linaro.org> | 2014-08-16 11:27:41 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-08-19 17:08:58 -0400 |
commit | 38ec10f60d9ca3a7eb3a5b52500a67479296b86f (patch) | |
tree | 1e09865555d0c2dadf6d81445ad7f3f766058815 /drivers/spi/spi.c | |
parent | 7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff) |
spi: Only call transfer_one() if we have buffers to transfer
Client drivers such as the ChomeOS EC driver sometimes use transfers with
no buffers and only a delay specified in order to allow a delay after the
assertion of /CS. Rather than require controller drivers handle this noop
case gracefully put checks in the core to ensure that we don't call into
the controller for such transfers.
Reported-by: Addy Ke <addy.ke@rock-chips.com>
Tested-by: Doug Anderson <dianders@chromium.org>
Reviewed-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e0531baf2782..0edccc82ece5 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -789,27 +789,35 @@ static int spi_transfer_one_message(struct spi_master *master, | |||
789 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 789 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
790 | trace_spi_transfer_start(msg, xfer); | 790 | trace_spi_transfer_start(msg, xfer); |
791 | 791 | ||
792 | reinit_completion(&master->xfer_completion); | 792 | if (xfer->tx_buf || xfer->rx_buf) { |
793 | 793 | reinit_completion(&master->xfer_completion); | |
794 | ret = master->transfer_one(master, msg->spi, xfer); | 794 | |
795 | if (ret < 0) { | 795 | ret = master->transfer_one(master, msg->spi, xfer); |
796 | dev_err(&msg->spi->dev, | 796 | if (ret < 0) { |
797 | "SPI transfer failed: %d\n", ret); | 797 | dev_err(&msg->spi->dev, |
798 | goto out; | 798 | "SPI transfer failed: %d\n", ret); |
799 | } | 799 | goto out; |
800 | } | ||
800 | 801 | ||
801 | if (ret > 0) { | 802 | if (ret > 0) { |
802 | ret = 0; | 803 | ret = 0; |
803 | ms = xfer->len * 8 * 1000 / xfer->speed_hz; | 804 | ms = xfer->len * 8 * 1000 / xfer->speed_hz; |
804 | ms += ms + 100; /* some tolerance */ | 805 | ms += ms + 100; /* some tolerance */ |
805 | 806 | ||
806 | ms = wait_for_completion_timeout(&master->xfer_completion, | 807 | ms = wait_for_completion_timeout(&master->xfer_completion, |
807 | msecs_to_jiffies(ms)); | 808 | msecs_to_jiffies(ms)); |
808 | } | 809 | } |
809 | 810 | ||
810 | if (ms == 0) { | 811 | if (ms == 0) { |
811 | dev_err(&msg->spi->dev, "SPI transfer timed out\n"); | 812 | dev_err(&msg->spi->dev, |
812 | msg->status = -ETIMEDOUT; | 813 | "SPI transfer timed out\n"); |
814 | msg->status = -ETIMEDOUT; | ||
815 | } | ||
816 | } else { | ||
817 | if (xfer->len) | ||
818 | dev_err(&msg->spi->dev, | ||
819 | "Bufferless transfer has length %u\n", | ||
820 | xfer->len); | ||
813 | } | 821 | } |
814 | 822 | ||
815 | trace_spi_transfer_stop(msg, xfer); | 823 | trace_spi_transfer_stop(msg, xfer); |