spi: Only call transfer_one() if we have buffers to transfer
authorMark Brown <broonie@linaro.org>
Sat, 16 Aug 2014 15:27:41 +0000 (16:27 +0100)
committerMark Brown <broonie@linaro.org>
Tue, 19 Aug 2014 21:08:58 +0000 (16:08 -0500)
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>
drivers/spi/spi.c

index e0531ba..0edccc8 100644 (file)
@@ -789,27 +789,35 @@ static int spi_transfer_one_message(struct spi_master *master,
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                trace_spi_transfer_start(msg, xfer);
 
-               reinit_completion(&master->xfer_completion);
-
-               ret = master->transfer_one(master, msg->spi, xfer);
-               if (ret < 0) {
-                       dev_err(&msg->spi->dev,
-                               "SPI transfer failed: %d\n", ret);
-                       goto out;
-               }
+               if (xfer->tx_buf || xfer->rx_buf) {
+                       reinit_completion(&master->xfer_completion);
+
+                       ret = master->transfer_one(master, msg->spi, xfer);
+                       if (ret < 0) {
+                               dev_err(&msg->spi->dev,
+                                       "SPI transfer failed: %d\n", ret);
+                               goto out;
+                       }
 
-               if (ret > 0) {
-                       ret = 0;
-                       ms = xfer->len * 8 * 1000 / xfer->speed_hz;
-                       ms += ms + 100; /* some tolerance */
+                       if (ret > 0) {
+                               ret = 0;
+                               ms = xfer->len * 8 * 1000 / xfer->speed_hz;
+                               ms += ms + 100; /* some tolerance */
 
-                       ms = wait_for_completion_timeout(&master->xfer_completion,
-                                                        msecs_to_jiffies(ms));
-               }
+                               ms = wait_for_completion_timeout(&master->xfer_completion,
+                                                                msecs_to_jiffies(ms));
+                       }
 
-               if (ms == 0) {
-                       dev_err(&msg->spi->dev, "SPI transfer timed out\n");
-                       msg->status = -ETIMEDOUT;
+                       if (ms == 0) {
+                               dev_err(&msg->spi->dev,
+                                       "SPI transfer timed out\n");
+                               msg->status = -ETIMEDOUT;
+                       }
+               } else {
+                       if (xfer->len)
+                               dev_err(&msg->spi->dev,
+                                       "Bufferless transfer has length %u\n",
+                                       xfer->len);
                }
 
                trace_spi_transfer_stop(msg, xfer);