summaryrefslogtreecommitdiff
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index e0531baf2782..e19512ffc40e 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -552,6 +552,9 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n)
struct boardinfo *bi;
int i;
+ if (!n)
+ return -EINVAL;
+
bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
if (!bi)
return -ENOMEM;
@@ -789,27 +792,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);
+ 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;
- }
+ 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);
@@ -848,6 +859,7 @@ out:
/**
* spi_finalize_current_transfer - report completion of a transfer
+ * @master: the master reporting completion
*
* Called by SPI drivers using the core transfer_one_message()
* implementation to notify it that the current interrupt driven