summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/spi.c
diff options
context:
space:
mode:
authorRui Miguel Silva <rui.silva@linaro.org>2016-04-20 14:40:23 +0100
committerGreg Kroah-Hartman <gregkh@google.com>2016-04-21 08:34:00 +0900
commitd1d67714a4ece3c1438c9d7def324ee0424e7cbd (patch)
treec88d626c7c714d95d839454c5eef533f810a54e3 /drivers/staging/greybus/spi.c
parent0928b2e4401cebd7fd2b8aebc41be60dbe4c2ef3 (diff)
downloadop-kernel-dev-d1d67714a4ece3c1438c9d7def324ee0424e7cbd.zip
op-kernel-dev-d1d67714a4ece3c1438c9d7def324ee0424e7cbd.tar.gz
greybus: spi: use timeout request send operation
When transfer speed is too slow (less than 17Khz) the operation can take longer than the default greybus timeout. Because of this we need to use the request_send_sync_timeout and calculate the correct timeout for each operation. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> Tested-by: Philip Yang <philipy@bsquare.com> Tested-by: Axel Haslam <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/spi.c')
-rw-r--r--drivers/staging/greybus/spi.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c
index 0bae7f1..ce706ed 100644
--- a/drivers/staging/greybus/spi.c
+++ b/drivers/staging/greybus/spi.c
@@ -23,6 +23,7 @@ struct gb_spi {
u32 rx_xfer_offset;
u32 tx_xfer_offset;
u32 last_xfer_size;
+ unsigned int op_timeout;
u16 mode;
u16 flags;
u32 bits_per_word_mask;
@@ -38,6 +39,8 @@ struct gb_spi {
#define GB_SPI_STATE_OP_DONE ((void *)4)
#define GB_SPI_STATE_MSG_ERROR ((void *)-1)
+#define XFER_TIMEOUT_TOLERANCE 200
+
static struct spi_master *get_master_from_spi(struct gb_spi *spi)
{
return gb_connection_get_data(spi->connection);
@@ -95,6 +98,7 @@ static void clean_xfer_state(struct gb_spi *spi)
spi->rx_xfer_offset = 0;
spi->tx_xfer_offset = 0;
spi->last_xfer_size = 0;
+ spi->op_timeout = 0;
}
static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg)
@@ -112,6 +116,7 @@ static int setup_next_xfer(struct gb_spi *spi, struct spi_message *msg)
(spi->rx_xfer_offset + spi->last_xfer_size == last_xfer->len)) {
spi->tx_xfer_offset = 0;
spi->rx_xfer_offset = 0;
+ spi->op_timeout = 0;
if (last_xfer == list_last_entry(&msg->transfers,
struct spi_transfer,
transfer_list))
@@ -155,6 +160,7 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection,
u32 tx_size = 0, rx_size = 0, count = 0, xfer_len = 0, request_size;
u32 tx_xfer_size = 0, rx_xfer_size = 0, len;
u32 total_len = 0;
+ unsigned int xfer_timeout;
size_t data_max;
void *tx_data;
@@ -234,6 +240,13 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection,
else
xfer_len = xfer->len;
+ /* make sure we do not timeout in a slow transfer */
+ xfer_timeout = xfer_len * 8 * MSEC_PER_SEC / xfer->speed_hz;
+ xfer_timeout += GB_OPERATION_TIMEOUT_DEFAULT;
+
+ if (xfer_timeout > spi->op_timeout)
+ spi->op_timeout = xfer_timeout;
+
gb_xfer->speed_hz = cpu_to_le32(xfer->speed_hz);
gb_xfer->len = cpu_to_le32(xfer_len);
gb_xfer->delay_usecs = cpu_to_le16(xfer->delay_usecs);
@@ -322,7 +335,8 @@ static int gb_spi_transfer_one_message(struct spi_master *master,
continue;
}
- ret = gb_operation_request_send_sync(operation);
+ ret = gb_operation_request_send_sync_timeout(operation,
+ spi->op_timeout);
if (!ret) {
response = operation->response->payload;
if (response)
OpenPOWER on IntegriCloud