Commit 719bd654 authored by Michal Suchanek's avatar Michal Suchanek Committed by Mark Brown

spi: sunxi: fix transfer timeout

The trasfer timeout is fixed at 1000 ms. Reading a 4Mbyte flash over
1MHz SPI bus takes way longer than that. Calculate the timeout from the
actual time the transfer is supposed to take and multiply by 2 for good
measure.
Signed-off-by: default avatarMichal Suchanek <hramrach@gmail.com>
Acked-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
parent 6d9fe44b
...@@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master, ...@@ -173,6 +173,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
{ {
struct sun4i_spi *sspi = spi_master_get_devdata(master); struct sun4i_spi *sspi = spi_master_get_devdata(master);
unsigned int mclk_rate, div, timeout; unsigned int mclk_rate, div, timeout;
unsigned int start, end, tx_time;
unsigned int tx_len = 0; unsigned int tx_len = 0;
int ret = 0; int ret = 0;
u32 reg; u32 reg;
...@@ -286,9 +287,16 @@ static int sun4i_spi_transfer_one(struct spi_master *master, ...@@ -286,9 +287,16 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
reg = sun4i_spi_read(sspi, SUN4I_CTL_REG); reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH); sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
start = jiffies;
timeout = wait_for_completion_timeout(&sspi->done, timeout = wait_for_completion_timeout(&sspi->done,
msecs_to_jiffies(1000)); msecs_to_jiffies(tx_time));
end = jiffies;
if (!timeout) { if (!timeout) {
dev_warn(&master->dev,
"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
dev_name(&spi->dev), tfr->len, tfr->speed_hz,
jiffies_to_msecs(end - start), tx_time);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto out; goto out;
} }
......
...@@ -160,6 +160,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -160,6 +160,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
{ {
struct sun6i_spi *sspi = spi_master_get_devdata(master); struct sun6i_spi *sspi = spi_master_get_devdata(master);
unsigned int mclk_rate, div, timeout; unsigned int mclk_rate, div, timeout;
unsigned int start, end, tx_time;
unsigned int tx_len = 0; unsigned int tx_len = 0;
int ret = 0; int ret = 0;
u32 reg; u32 reg;
...@@ -269,9 +270,16 @@ static int sun6i_spi_transfer_one(struct spi_master *master, ...@@ -269,9 +270,16 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH); sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
start = jiffies;
timeout = wait_for_completion_timeout(&sspi->done, timeout = wait_for_completion_timeout(&sspi->done,
msecs_to_jiffies(1000)); msecs_to_jiffies(tx_time));
end = jiffies;
if (!timeout) { if (!timeout) {
dev_warn(&master->dev,
"%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
dev_name(&spi->dev), tfr->len, tfr->speed_hz,
jiffies_to_msecs(end - start), tx_time);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment