linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
  • * [PATCH AUTOSEL 4.4 068/174] spi: tegra114: fix for unpacked mode transfers
           [not found] <20200116174251.24326-1-sashal@kernel.org>
           [not found] ` <20200116174251.24326-1-sashal-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
    @ 2020-01-16 17:41 ` Sasha Levin
      2020-01-16 17:41 ` [PATCH AUTOSEL 4.4 094/174] spi: spi-fsl-spi: call spi_finalize_current_message() at the end Sasha Levin
      2020-01-16 17:42 ` [PATCH AUTOSEL 4.4 156/174] spi: atmel: fix handling of cs_change set on non-last xfer Sasha Levin
      3 siblings, 0 replies; 5+ messages in thread
    From: Sasha Levin @ 2020-01-16 17:41 UTC (permalink / raw)
      To: linux-kernel, stable
      Cc: Sowjanya Komatineni, Mark Brown, Sasha Levin, linux-spi,
    	linux-tegra
    
    From: Sowjanya Komatineni <skomatineni@nvidia.com>
    
    [ Upstream commit 1a89ac5b91895127f7c586ec5075c3753ca25501 ]
    
    Fixes: computation of actual bytes to fill/receive in/from FIFO in unpacked
    mode when transfer length is not a multiple of requested bits per word.
    
    unpacked mode transfers fails when the transfer includes partial bytes in
    the last word.
    
    Total words to be written/read to/from FIFO is computed based on transfer
    length and bits per word. Unpacked mode includes 0 padding bytes for partial
    words to align with bits per word and these extra bytes are also accounted
    for calculating bytes left to transfer in the current driver.
    
    This causes extra bytes access of tx/rx buffers along with buffer index
    position crossing actual length where remain_len becomes negative and due to
    unsigned type, negative value is a 32 bit representation of signed value
    and transferred bytes never meets the actual transfer length resulting in
    transfer timeout and a hang.
    
    This patch fixes this with proper computation of the actual bytes to fill in
    FIFO during transmit and the actual bytes to read from FIFO during receive
    ignoring 0 padded bytes.
    
    Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
     drivers/spi/spi-tegra114.c | 43 +++++++++++++++++++++++++++++++-------
     1 file changed, 36 insertions(+), 7 deletions(-)
    
    diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
    index d98c502a9c47..e37712bed0b2 100644
    --- a/drivers/spi/spi-tegra114.c
    +++ b/drivers/spi/spi-tegra114.c
    @@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
     				x |= (u32)(*tx_buf++) << (i * 8);
     			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
     		}
    +
    +		tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
     	} else {
    +		unsigned int write_bytes;
     		max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
     		written_words = max_n_32bit;
     		nbytes = written_words * tspi->bytes_per_word;
    +		if (nbytes > t->len - tspi->cur_pos)
    +			nbytes = t->len - tspi->cur_pos;
    +		write_bytes = nbytes;
     		for (count = 0; count < max_n_32bit; count++) {
     			u32 x = 0;
     
    @@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
     				x |= (u32)(*tx_buf++) << (i * 8);
     			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
     		}
    +
    +		tspi->cur_tx_pos += write_bytes;
     	}
    -	tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
    +
     	return written_words;
     }
     
    @@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
     			for (i = 0; len && (i < 4); i++, len--)
     				*rx_buf++ = (x >> i*8) & 0xFF;
     		}
    -		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
     		read_words += tspi->curr_dma_words;
    +		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
     	} else {
     		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
    +		u8 bytes_per_word = tspi->bytes_per_word;
    +		unsigned int read_bytes;
     
    +		len = rx_full_count * bytes_per_word;
    +		if (len > t->len - tspi->cur_pos)
    +			len = t->len - tspi->cur_pos;
    +		read_bytes = len;
     		for (count = 0; count < rx_full_count; count++) {
     			u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
     
    -			for (i = 0; (i < tspi->bytes_per_word); i++)
    +			for (i = 0; len && (i < bytes_per_word); i++, len--)
     				*rx_buf++ = (x >> (i*8)) & 0xFF;
     		}
    -		tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word;
     		read_words += rx_full_count;
    +		tspi->cur_rx_pos += read_bytes;
     	}
    +
     	return read_words;
     }
     
    @@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
     		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
     
     		memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
    +		tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
     	} else {
     		unsigned int i;
     		unsigned int count;
     		u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
     		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
    +		unsigned int write_bytes;
     
    +		if (consume > t->len - tspi->cur_pos)
    +			consume = t->len - tspi->cur_pos;
    +		write_bytes = consume;
     		for (count = 0; count < tspi->curr_dma_words; count++) {
     			u32 x = 0;
     
    @@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
     				x |= (u32)(*tx_buf++) << (i * 8);
     			tspi->tx_dma_buf[count] = x;
     		}
    +
    +		tspi->cur_tx_pos += write_bytes;
     	}
    -	tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
     
     	/* Make the dma buffer to read by dma */
     	dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
    @@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
     		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
     
     		memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
    +		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
     	} else {
     		unsigned int i;
     		unsigned int count;
     		unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
     		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
    +		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
    +		unsigned int read_bytes;
     
    +		if (consume > t->len - tspi->cur_pos)
    +			consume = t->len - tspi->cur_pos;
    +		read_bytes = consume;
     		for (count = 0; count < tspi->curr_dma_words; count++) {
     			u32 x = tspi->rx_dma_buf[count] & rx_mask;
     
    -			for (i = 0; (i < tspi->bytes_per_word); i++)
    +			for (i = 0; consume && (i < tspi->bytes_per_word);
    +							i++, consume--)
     				*rx_buf++ = (x >> (i*8)) & 0xFF;
     		}
    +
    +		tspi->cur_rx_pos += read_bytes;
     	}
    -	tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
     
     	/* Make the dma buffer to read by dma */
     	dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
    -- 
    2.20.1
    
    ^ permalink raw reply related	[flat|nested] 5+ messages in thread
  • * [PATCH AUTOSEL 4.4 094/174] spi: spi-fsl-spi: call spi_finalize_current_message() at the end
           [not found] <20200116174251.24326-1-sashal@kernel.org>
           [not found] ` <20200116174251.24326-1-sashal-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
      2020-01-16 17:41 ` [PATCH AUTOSEL 4.4 068/174] spi: tegra114: fix for unpacked mode transfers Sasha Levin
    @ 2020-01-16 17:41 ` Sasha Levin
      2020-01-16 17:42 ` [PATCH AUTOSEL 4.4 156/174] spi: atmel: fix handling of cs_change set on non-last xfer Sasha Levin
      3 siblings, 0 replies; 5+ messages in thread
    From: Sasha Levin @ 2020-01-16 17:41 UTC (permalink / raw)
      To: linux-kernel, stable; +Cc: Christophe Leroy, Mark Brown, Sasha Levin, linux-spi
    
    From: Christophe Leroy <christophe.leroy@c-s.fr>
    
    [ Upstream commit 44a042182cb1e9f7916e015c836967bf638b33c4 ]
    
    spi_finalize_current_message() shall be called once all
    actions are finished, otherwise the last actions might
    step over a newly started transfer.
    
    Fixes: c592becbe704 ("spi: fsl-(e)spi: migrate to generic master queueing")
    Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
     drivers/spi/spi-fsl-spi.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
    index 8b290d9d7935..5419de19859a 100644
    --- a/drivers/spi/spi-fsl-spi.c
    +++ b/drivers/spi/spi-fsl-spi.c
    @@ -408,7 +408,6 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
     	}
     
     	m->status = status;
    -	spi_finalize_current_message(master);
     
     	if (status || !cs_change) {
     		ndelay(nsecs);
    @@ -416,6 +415,7 @@ static int fsl_spi_do_one_msg(struct spi_master *master,
     	}
     
     	fsl_spi_setup_transfer(spi, NULL);
    +	spi_finalize_current_message(master);
     	return 0;
     }
     
    -- 
    2.20.1
    
    ^ permalink raw reply related	[flat|nested] 5+ messages in thread
  • * [PATCH AUTOSEL 4.4 156/174] spi: atmel: fix handling of cs_change set on non-last xfer
           [not found] <20200116174251.24326-1-sashal@kernel.org>
                       ` (2 preceding siblings ...)
      2020-01-16 17:41 ` [PATCH AUTOSEL 4.4 094/174] spi: spi-fsl-spi: call spi_finalize_current_message() at the end Sasha Levin
    @ 2020-01-16 17:42 ` Sasha Levin
      3 siblings, 0 replies; 5+ messages in thread
    From: Sasha Levin @ 2020-01-16 17:42 UTC (permalink / raw)
      To: linux-kernel, stable
      Cc: Mans Rullgard, Nicolas Ferre, Gregory CLEMENT, Mark Brown,
    	Sasha Levin, linux-spi, linux-arm-kernel
    
    From: Mans Rullgard <mans@mansr.com>
    
    [ Upstream commit fed8d8c7a6dc2a76d7764842853d81c770b0788e ]
    
    The driver does the wrong thing when cs_change is set on a non-last
    xfer in a message.  When cs_change is set, the driver deactivates the
    CS and leaves it off until a later xfer again has cs_change set whereas
    it should be briefly toggling CS off and on again.
    
    This patch brings the behaviour of the driver back in line with the
    documentation and common sense.  The delay of 10 us is the same as is
    used by the default spi_transfer_one_message() function in spi.c.
    [gregory: rebased on for-5.5 from spi tree]
    Fixes: 8090d6d1a415 ("spi: atmel: Refactor spi-atmel to use SPI framework queue")
    Signed-off-by: Mans Rullgard <mans@mansr.com>
    Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
    Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
    Link: https://lore.kernel.org/r/20191018153504.4249-1-gregory.clement@bootlin.com
    Signed-off-by: Mark Brown <broonie@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
     drivers/spi/spi-atmel.c | 10 +++-------
     1 file changed, 3 insertions(+), 7 deletions(-)
    
    diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c
    index 691c04b3e5b6..938840af9c50 100644
    --- a/drivers/spi/spi-atmel.c
    +++ b/drivers/spi/spi-atmel.c
    @@ -315,7 +315,6 @@ struct atmel_spi {
     	struct atmel_spi_dma	dma;
     
     	bool			keep_cs;
    -	bool			cs_active;
     
     	u32			fifo_size;
     };
    @@ -1404,11 +1403,9 @@ static int atmel_spi_one_transfer(struct spi_master *master,
     				 &msg->transfers)) {
     			as->keep_cs = true;
     		} else {
    -			as->cs_active = !as->cs_active;
    -			if (as->cs_active)
    -				cs_activate(as, msg->spi);
    -			else
    -				cs_deactivate(as, msg->spi);
    +			cs_deactivate(as, msg->spi);
    +			udelay(10);
    +			cs_activate(as, msg->spi);
     		}
     	}
     
    @@ -1431,7 +1428,6 @@ static int atmel_spi_transfer_one_message(struct spi_master *master,
     	atmel_spi_lock(as);
     	cs_activate(as, spi);
     
    -	as->cs_active = true;
     	as->keep_cs = false;
     
     	msg->status = 0;
    -- 
    2.20.1
    
    ^ permalink raw reply related	[flat|nested] 5+ messages in thread

  • end of thread, other threads:[~2020-01-16 17:42 UTC | newest]
    
    Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
    -- links below jump to the message on this page --
         [not found] <20200116174251.24326-1-sashal@kernel.org>
         [not found] ` <20200116174251.24326-1-sashal-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
    2020-01-16 17:41   ` [PATCH AUTOSEL 4.4 067/174] spi: tegra114: clear packed bit for unpacked mode Sasha Levin
    2020-01-16 17:41   ` [PATCH AUTOSEL 4.4 071/174] spi: bcm2835aux: fix driver to not allow 65535 (=-1) cs-gpios Sasha Levin
    2020-01-16 17:41 ` [PATCH AUTOSEL 4.4 068/174] spi: tegra114: fix for unpacked mode transfers Sasha Levin
    2020-01-16 17:41 ` [PATCH AUTOSEL 4.4 094/174] spi: spi-fsl-spi: call spi_finalize_current_message() at the end Sasha Levin
    2020-01-16 17:42 ` [PATCH AUTOSEL 4.4 156/174] spi: atmel: fix handling of cs_change set on non-last xfer Sasha Levin
    

    This is a public inbox, see mirroring instructions
    for how to clone and mirror all data and code used for this inbox;
    as well as URLs for NNTP newsgroup(s).