Message ID | 1305807191-11704-1-git-send-email-linus.walleij@stericsson.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Hi, > - /* FIXME: insert a timeout so we don't hang here indefinitely */ > - while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) > + > + timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); Won't you miss the transfer if you get interrupted here longer than SPI_POLLING_TIMEOUT? > + while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { > + if (time_after(jiffies, timeout)) { > + dev_warn(&pl022->adev->dev, > + "%s: timeout!\n", __func__); > + message->state = STATE_ERROR; > + goto out; > + } > readwriter(pl022); > + } Regards, Wolfram
On Thu, May 19, 2011 at 2:44 PM, Wolfram Sang <w.sang@pengutronix.de> wrote: > Hi, > >> - /* FIXME: insert a timeout so we don't hang here indefinitely */ >> - while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) >> + >> + timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); > > Won't you miss the transfer if you get interrupted here longer than > SPI_POLLING_TIMEOUT? Yeah... preempted for a second hm. >> + while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { >> + if (time_after(jiffies, timeout)) { >> + dev_warn(&pl022->adev->dev, >> + "%s: timeout!\n", __func__); >> + message->state = STATE_ERROR; >> + goto out; >> + } >> readwriter(pl022); >> + } What about we move readerwriter() above if (time_after...) then it atleast gets one chance to run even if we're preempted for 10 seconds. Any other design patterns that'd be better? Yours, Linus Walleij
> >> + while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { > >> + if (time_after(jiffies, timeout)) { > >> + dev_warn(&pl022->adev->dev, > >> + "%s: timeout!\n", __func__); > >> + message->state = STATE_ERROR; > >> + goto out; > >> + } > >> readwriter(pl022); > >> + } > > What about we move readerwriter() above if (time_after...) then it atleast > gets one chance to run even if we're preempted for 10 seconds. This will fix the initial problem, but still exit early if e.g. the preemption came on a subsequent iteration of the while loop, say during readwriter(). > > Any other design patterns that'd be better? A bit better might be: while (...) { time = jiffies; readwriter(); if (time_after(time, timeout)...) ... } So you continue triggering transfers as long as the last one was in the valid timespan. In case of an preemption, you made sure you tried the whole timespan (+ the jitter) which is probably better than stop trying too early. Regards, Wolfram
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 08de58e..1f84a8a 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -24,11 +24,6 @@ * GNU General Public License for more details. */ -/* - * TODO: - * - add timeout on polled transfers - */ - #include <linux/init.h> #include <linux/module.h> #include <linux/device.h> @@ -287,6 +282,8 @@ #define CLEAR_ALL_INTERRUPTS 0x3 +#define SPI_POLLING_TIMEOUT 1000 + /* * The type of reading going on on this chip @@ -1378,6 +1375,7 @@ static void do_polling_transfer(struct pl022 *pl022) struct spi_transfer *transfer = NULL; struct spi_transfer *previous = NULL; struct chip_data *chip; + unsigned long timeout; chip = pl022->cur_chip; message = pl022->cur_msg; @@ -1415,9 +1413,17 @@ static void do_polling_transfer(struct pl022 *pl022) SSP_CR1(pl022->virtbase)); dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n"); - /* FIXME: insert a timeout so we don't hang here indefinitely */ - while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) + + timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT); + while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) { + if (time_after(jiffies, timeout)) { + dev_warn(&pl022->adev->dev, + "%s: timeout!\n", __func__); + message->state = STATE_ERROR; + goto out; + } readwriter(pl022); + } /* Update total byte transferred */ message->actual_length += pl022->cur_transfer->len; @@ -1426,7 +1432,7 @@ static void do_polling_transfer(struct pl022 *pl022) /* Move to next transfer */ message->state = next_transfer(pl022); } - +out: /* Handle end of message */ if (message->state == STATE_DONE) message->status = 0;