Re: [PATCH 4.19 127/422] i2c: mediatek: Use DMA safe buffers for i2c transactions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On Tue, Nov 19, 2019 at 06:15:24AM +0100, Greg Kroah-Hartman wrote:
> From: Jun Gao <jun.gao@xxxxxxxxxxxx>
> 
> [ Upstream commit fc66b39fe36acfd06f716e338de7cd8f9550fad2 ]
> 
> DMA mode will always be used in i2c transactions, try to allocate
> a DMA safe buffer if the buf of struct i2c_msg used is not DMA safe.
> 
> Signed-off-by: Jun Gao <jun.gao@xxxxxxxxxxxx>
> Signed-off-by: Wolfram Sang <wsa@xxxxxxxxxxxxx>
> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

This patch requires the following additional commit:

commit bc1a7f75c85e226e82f183d30d75c357f92b6029
Author: Hsin-Yi Wang <hsinyi@xxxxxxxxxxxx>
Date:   Fri Feb 15 17:02:02 2019 +0800

    i2c: mediatek: modify threshold passed to i2c_get_dma_safe_msg_buf()

    DMA with zero-length transfers doesn't make sense and this HW doesn't
    support them at all, so increase the threshold.

    Fixes: fc66b39fe36a ("i2c: mediatek: Use DMA safe buffers for i2c transactions")
    Signed-off-by: Hsin-Yi Wang <hsinyi@xxxxxxxxxxxx>
    [wsa: reworded commit message]
    Signed-off-by: Wolfram Sang <wsa@xxxxxxxxxxxxx>

Please apply this commit.

Best regards,
  Nobuhiro

> ---
>  drivers/i2c/busses/i2c-mt65xx.c | 62 +++++++++++++++++++++++++++++----
>  1 file changed, 55 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
> index 1e57f58fcb001..a74ef76705e0c 100644
> --- a/drivers/i2c/busses/i2c-mt65xx.c
> +++ b/drivers/i2c/busses/i2c-mt65xx.c
> @@ -441,6 +441,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
>  	u16 control_reg;
>  	u16 restart_flag = 0;
>  	u32 reg_4g_mode;
> +	u8 *dma_rd_buf = NULL;
> +	u8 *dma_wr_buf = NULL;
>  	dma_addr_t rpaddr = 0;
>  	dma_addr_t wpaddr = 0;
>  	int ret;
> @@ -500,10 +502,18 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
>  	if (i2c->op == I2C_MASTER_RD) {
>  		writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
>  		writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON);
> -		rpaddr = dma_map_single(i2c->dev, msgs->buf,
> +
> +		dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
> +		if (!dma_rd_buf)
> +			return -ENOMEM;
> +
> +		rpaddr = dma_map_single(i2c->dev, dma_rd_buf,
>  					msgs->len, DMA_FROM_DEVICE);
> -		if (dma_mapping_error(i2c->dev, rpaddr))
> +		if (dma_mapping_error(i2c->dev, rpaddr)) {
> +			i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, false);
> +
>  			return -ENOMEM;
> +		}
>  
>  		if (i2c->dev_comp->support_33bits) {
>  			reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr);
> @@ -515,10 +525,18 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
>  	} else if (i2c->op == I2C_MASTER_WR) {
>  		writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
>  		writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON);
> -		wpaddr = dma_map_single(i2c->dev, msgs->buf,
> +
> +		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
> +		if (!dma_wr_buf)
> +			return -ENOMEM;
> +
> +		wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
>  					msgs->len, DMA_TO_DEVICE);
> -		if (dma_mapping_error(i2c->dev, wpaddr))
> +		if (dma_mapping_error(i2c->dev, wpaddr)) {
> +			i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
> +
>  			return -ENOMEM;
> +		}
>  
>  		if (i2c->dev_comp->support_33bits) {
>  			reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr);
> @@ -530,16 +548,39 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
>  	} else {
>  		writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
>  		writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON);
> -		wpaddr = dma_map_single(i2c->dev, msgs->buf,
> +
> +		dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 0);
> +		if (!dma_wr_buf)
> +			return -ENOMEM;
> +
> +		wpaddr = dma_map_single(i2c->dev, dma_wr_buf,
>  					msgs->len, DMA_TO_DEVICE);
> -		if (dma_mapping_error(i2c->dev, wpaddr))
> +		if (dma_mapping_error(i2c->dev, wpaddr)) {
> +			i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
> +
>  			return -ENOMEM;
> -		rpaddr = dma_map_single(i2c->dev, (msgs + 1)->buf,
> +		}
> +
> +		dma_rd_buf = i2c_get_dma_safe_msg_buf((msgs + 1), 0);
> +		if (!dma_rd_buf) {
> +			dma_unmap_single(i2c->dev, wpaddr,
> +					 msgs->len, DMA_TO_DEVICE);
> +
> +			i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
> +
> +			return -ENOMEM;
> +		}
> +
> +		rpaddr = dma_map_single(i2c->dev, dma_rd_buf,
>  					(msgs + 1)->len,
>  					DMA_FROM_DEVICE);
>  		if (dma_mapping_error(i2c->dev, rpaddr)) {
>  			dma_unmap_single(i2c->dev, wpaddr,
>  					 msgs->len, DMA_TO_DEVICE);
> +
> +			i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, false);
> +			i2c_put_dma_safe_msg_buf(dma_rd_buf, (msgs + 1), false);
> +
>  			return -ENOMEM;
>  		}
>  
> @@ -578,14 +619,21 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
>  	if (i2c->op == I2C_MASTER_WR) {
>  		dma_unmap_single(i2c->dev, wpaddr,
>  				 msgs->len, DMA_TO_DEVICE);
> +
> +		i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, true);
>  	} else if (i2c->op == I2C_MASTER_RD) {
>  		dma_unmap_single(i2c->dev, rpaddr,
>  				 msgs->len, DMA_FROM_DEVICE);
> +
> +		i2c_put_dma_safe_msg_buf(dma_rd_buf, msgs, true);
>  	} else {
>  		dma_unmap_single(i2c->dev, wpaddr, msgs->len,
>  				 DMA_TO_DEVICE);
>  		dma_unmap_single(i2c->dev, rpaddr, (msgs + 1)->len,
>  				 DMA_FROM_DEVICE);
> +
> +		i2c_put_dma_safe_msg_buf(dma_wr_buf, msgs, true);
> +		i2c_put_dma_safe_msg_buf(dma_rd_buf, (msgs + 1), true);
>  	}
>  
>  	if (ret == 0) {
> -- 
> 2.20.1
> 
> 
> 
> 



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux