diff options
author | Magnus Templing <magnus.templing@stericsson.com> | 2011-05-19 12:05:34 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-05-20 02:43:07 -0400 |
commit | a18c266f8e43004c85c56b4077f6158fcadb7707 (patch) | |
tree | 9a1114717a81abc23a17449fd682ae24020dd1ba /drivers | |
parent | 78fab4c04c76b8c9327541bd270f82b85b42bbf7 (diff) |
spi/pl022: timeout on polled transfer v2
This adds the missing handling of polling timeouts and deletes
our last todo.
Signed-off-by: Magnus Templing <magnus.templing@stericsson.com>
Reviewed-by: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
[Fixups from review by Wolfram Sang]
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/amba-pl022.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 08de58e7f59f..18667de436f1 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -24,11 +24,6 @@ | |||
24 | * GNU General Public License for more details. | 24 | * GNU General Public License for more details. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | /* | ||
28 | * TODO: | ||
29 | * - add timeout on polled transfers | ||
30 | */ | ||
31 | |||
32 | #include <linux/init.h> | 27 | #include <linux/init.h> |
33 | #include <linux/module.h> | 28 | #include <linux/module.h> |
34 | #include <linux/device.h> | 29 | #include <linux/device.h> |
@@ -287,6 +282,8 @@ | |||
287 | 282 | ||
288 | #define CLEAR_ALL_INTERRUPTS 0x3 | 283 | #define CLEAR_ALL_INTERRUPTS 0x3 |
289 | 284 | ||
285 | #define SPI_POLLING_TIMEOUT 1000 | ||
286 | |||
290 | 287 | ||
291 | /* | 288 | /* |
292 | * The type of reading going on on this chip | 289 | * The type of reading going on on this chip |
@@ -1378,6 +1375,7 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1378 | struct spi_transfer *transfer = NULL; | 1375 | struct spi_transfer *transfer = NULL; |
1379 | struct spi_transfer *previous = NULL; | 1376 | struct spi_transfer *previous = NULL; |
1380 | struct chip_data *chip; | 1377 | struct chip_data *chip; |
1378 | unsigned long time, timeout; | ||
1381 | 1379 | ||
1382 | chip = pl022->cur_chip; | 1380 | chip = pl022->cur_chip; |
1383 | message = pl022->cur_msg; | 1381 | message = pl022->cur_msg; |
@@ -1415,9 +1413,18 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1415 | SSP_CR1(pl022->virtbase)); | 1413 | SSP_CR1(pl022->virtbase)); |
1416 | 1414 | ||
1417 | dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); | 1415 | dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); |
1418 | /* FIXME: insert a timeout so we don't hang here indefinitely */ | 1416 | |
1419 | while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) | 1417 | timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); |
1418 | while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { | ||
1419 | time = jiffies; | ||
1420 | readwriter(pl022); | 1420 | readwriter(pl022); |
1421 | if (time_after(time, timeout)) { | ||
1422 | dev_warn(&pl022->adev->dev, | ||
1423 | "%s: timeout!\n", __func__); | ||
1424 | message->state = STATE_ERROR; | ||
1425 | goto out; | ||
1426 | } | ||
1427 | } | ||
1421 | 1428 | ||
1422 | /* Update total byte transferred */ | 1429 | /* Update total byte transferred */ |
1423 | message->actual_length += pl022->cur_transfer->len; | 1430 | message->actual_length += pl022->cur_transfer->len; |
@@ -1426,7 +1433,7 @@ static void do_polling_transfer(struct pl022 *pl022) | |||
1426 | /* Move to next transfer */ | 1433 | /* Move to next transfer */ |
1427 | message->state = next_transfer(pl022); | 1434 | message->state = next_transfer(pl022); |
1428 | } | 1435 | } |
1429 | 1436 | out: | |
1430 | /* Handle end of message */ | 1437 | /* Handle end of message */ |
1431 | if (message->state == STATE_DONE) | 1438 | if (message->state == STATE_DONE) |
1432 | message->status = 0; | 1439 | message->status = 0; |