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: Michal Suchanek <hramrach@gmail.com> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org
This commit is contained in:
parent
6d9fe44bd7
commit
719bd65420
|
@ -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,
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue