Skip to content

Commit

Permalink
spi: bcm2835: fix overflow in calculation of transfer time
Browse files Browse the repository at this point in the history
This resulted in the use of polling mode when other approaches
(dma or interrupts) would have been more appropriate.

Happened for transfers longer than 477 bytes.

Reported-by: Noralf Tronnes <noralf@tronnes.org>
Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
msperl authored and broonie committed Jul 29, 2015
1 parent acace73 commit 0122a51
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions drivers/spi/spi-bcm2835.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
struct spi_device *spi,
struct spi_transfer *tfr,
u32 cs,
unsigned long xfer_time_us)
unsigned long long xfer_time_us)
{
struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long timeout;
Expand Down Expand Up @@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
{
struct bcm2835_spi *bs = spi_master_get_devdata(master);
unsigned long spi_hz, clk_hz, cdiv;
unsigned long spi_used_hz, xfer_time_us;
unsigned long spi_used_hz;
unsigned long long xfer_time_us;
u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);

/* set clock */
Expand Down Expand Up @@ -573,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
bs->rx_len = tfr->len;

/* calculate the estimated time in us the transfer runs */
xfer_time_us = tfr->len
xfer_time_us = (unsigned long long)tfr->len
* 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
* 1000000 / spi_used_hz;
* 1000000;
do_div(xfer_time_us, spi_used_hz);

/* for short requests run polling*/
if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
Expand Down

0 comments on commit 0122a51

Please sign in to comment.