All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: Wolfram Sang <wsa+renesas@sang-engineering.com>
Cc: <linux-i2c@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linux-renesas-soc@vger.kernel.org>, <linux-iio@vger.kernel.org>,
	<linux-input@vger.kernel.org>, <linux-media@vger.kernel.org>,
	Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH v6 6/9] i2c: smbus: use DMA safe buffers for emulated SMBus transactions
Date: Sat, 11 Nov 2017 00:13:26 +0000	[thread overview]
Message-ID: <20171111001326.0000349b@huawei.com> (raw)
In-Reply-To: <20171104202009.3818-7-wsa+renesas@sang-engineering.com>

On Sat, 4 Nov 2017 21:20:06 +0100
Wolfram Sang <wsa+renesas@sang-engineering.com> wrote:

> For all block commands, try to allocate a DMA safe buffer and mark it
> accordingly. Only use the stack, if the buffers cannot be allocated.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>

Hmm. Interesting balance here as this adds allocations to paths where the i2c
master can't take advantage.  Not ideal, but perhaps not worth the hassle
of working around it?

It's only for the block calls I guess so not that major an issue.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
>  drivers/i2c/i2c-core-smbus.c | 45 ++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 39 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
> index 4bb9927afd0106..931c274fe26809 100644
> --- a/drivers/i2c/i2c-core-smbus.c
> +++ b/drivers/i2c/i2c-core-smbus.c
> @@ -18,6 +18,7 @@
>  #include <linux/err.h>
>  #include <linux/i2c.h>
>  #include <linux/i2c-smbus.h>
> +#include <linux/slab.h>
>  
>  #define CREATE_TRACE_POINTS
>  #include <trace/events/smbus.h>
> @@ -291,6 +292,22 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,
>  }
>  EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
>  
> +static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)
> +{
> +	bool is_read = msg->flags & I2C_M_RD;
> +	unsigned char *dma_buf;
> +
> +	dma_buf = kzalloc(I2C_SMBUS_BLOCK_MAX + (is_read ? 2 : 3), GFP_KERNEL);
> +	if (!dma_buf)
> +		return;
> +
> +	msg->buf = dma_buf;
> +	msg->flags |= I2C_M_DMA_SAFE;
> +
> +	if (init_val)
> +		msg->buf[0] = init_val;
> +
> +}
>  /* Simulate a SMBus command using the i2c protocol
>     No checking of parameters is done!  */
>  static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
> @@ -368,6 +385,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  			msg[1].flags |= I2C_M_RECV_LEN;
>  			msg[1].len = 1; /* block length will be added by
>  					   the underlying bus driver */
> +			i2c_smbus_try_get_dmabuf(&msg[1], 0);
>  		} else {
>  			msg[0].len = data->block[0] + 2;
>  			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
> @@ -376,8 +394,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  					data->block[0]);
>  				return -EINVAL;
>  			}
> +
> +			i2c_smbus_try_get_dmabuf(&msg[0], command);
>  			for (i = 1; i < msg[0].len; i++)
> -				msgbuf0[i] = data->block[i-1];
> +				msg[0].buf[i] = data->block[i-1];
>  		}
>  		break;
>  	case I2C_SMBUS_BLOCK_PROC_CALL:
> @@ -389,16 +409,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  				data->block[0]);
>  			return -EINVAL;
>  		}
> +
>  		msg[0].len = data->block[0] + 2;
> +		i2c_smbus_try_get_dmabuf(&msg[0], command);
>  		for (i = 1; i < msg[0].len; i++)
> -			msgbuf0[i] = data->block[i-1];
> +			msg[0].buf[i] = data->block[i-1];
> +
>  		msg[1].flags |= I2C_M_RECV_LEN;
>  		msg[1].len = 1; /* block length will be added by
>  				   the underlying bus driver */
> +		i2c_smbus_try_get_dmabuf(&msg[1], 0);
>  		break;
>  	case I2C_SMBUS_I2C_BLOCK_DATA:
>  		if (read_write == I2C_SMBUS_READ) {
>  			msg[1].len = data->block[0];
> +			i2c_smbus_try_get_dmabuf(&msg[1], 0);
>  		} else {
>  			msg[0].len = data->block[0] + 1;
>  			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
> @@ -407,8 +432,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  					data->block[0]);
>  				return -EINVAL;
>  			}
> +
> +			i2c_smbus_try_get_dmabuf(&msg[0], command);
>  			for (i = 1; i <= data->block[0]; i++)
> -				msgbuf0[i] = data->block[i];
> +				msg[0].buf[i] = data->block[i];
>  		}
>  		break;
>  	default:
> @@ -456,14 +483,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  			break;
>  		case I2C_SMBUS_I2C_BLOCK_DATA:
>  			for (i = 0; i < data->block[0]; i++)
> -				data->block[i+1] = msgbuf1[i];
> +				data->block[i+1] = msg[1].buf[i];
>  			break;
>  		case I2C_SMBUS_BLOCK_DATA:
>  		case I2C_SMBUS_BLOCK_PROC_CALL:
> -			for (i = 0; i < msgbuf1[0] + 1; i++)
> -				data->block[i] = msgbuf1[i];
> +			for (i = 0; i < msg[1].buf[0] + 1; i++)
> +				data->block[i] = msg[1].buf[i];
>  			break;
>  		}
> +
> +	if (msg[0].flags & I2C_M_DMA_SAFE)
> +		kfree(msg[0].buf);
> +	if (msg[1].flags & I2C_M_DMA_SAFE)
> +		kfree(msg[1].buf);
> +
>  	return 0;
>  }
>  

WARNING: multiple messages have this Message-ID (diff)
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: Wolfram Sang <wsa+renesas@sang-engineering.com>
Cc: linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-renesas-soc@vger.kernel.org, linux-iio@vger.kernel.org,
	linux-input@vger.kernel.org, linux-media@vger.kernel.org,
	Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH v6 6/9] i2c: smbus: use DMA safe buffers for emulated SMBus transactions
Date: Sat, 11 Nov 2017 00:13:26 +0000	[thread overview]
Message-ID: <20171111001326.0000349b@huawei.com> (raw)
In-Reply-To: <20171104202009.3818-7-wsa+renesas@sang-engineering.com>

On Sat, 4 Nov 2017 21:20:06 +0100
Wolfram Sang <wsa+renesas@sang-engineering.com> wrote:

> For all block commands, try to allocate a DMA safe buffer and mark it
> accordingly. Only use the stack, if the buffers cannot be allocated.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>

Hmm. Interesting balance here as this adds allocations to paths where the i2c
master can't take advantage.  Not ideal, but perhaps not worth the hassle
of working around it?

It's only for the block calls I guess so not that major an issue.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
> ---
>  drivers/i2c/i2c-core-smbus.c | 45 ++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 39 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
> index 4bb9927afd0106..931c274fe26809 100644
> --- a/drivers/i2c/i2c-core-smbus.c
> +++ b/drivers/i2c/i2c-core-smbus.c
> @@ -18,6 +18,7 @@
>  #include <linux/err.h>
>  #include <linux/i2c.h>
>  #include <linux/i2c-smbus.h>
> +#include <linux/slab.h>
>  
>  #define CREATE_TRACE_POINTS
>  #include <trace/events/smbus.h>
> @@ -291,6 +292,22 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,
>  }
>  EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
>  
> +static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)
> +{
> +	bool is_read = msg->flags & I2C_M_RD;
> +	unsigned char *dma_buf;
> +
> +	dma_buf = kzalloc(I2C_SMBUS_BLOCK_MAX + (is_read ? 2 : 3), GFP_KERNEL);
> +	if (!dma_buf)
> +		return;
> +
> +	msg->buf = dma_buf;
> +	msg->flags |= I2C_M_DMA_SAFE;
> +
> +	if (init_val)
> +		msg->buf[0] = init_val;
> +
> +}
>  /* Simulate a SMBus command using the i2c protocol
>     No checking of parameters is done!  */
>  static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
> @@ -368,6 +385,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  			msg[1].flags |= I2C_M_RECV_LEN;
>  			msg[1].len = 1; /* block length will be added by
>  					   the underlying bus driver */
> +			i2c_smbus_try_get_dmabuf(&msg[1], 0);
>  		} else {
>  			msg[0].len = data->block[0] + 2;
>  			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
> @@ -376,8 +394,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  					data->block[0]);
>  				return -EINVAL;
>  			}
> +
> +			i2c_smbus_try_get_dmabuf(&msg[0], command);
>  			for (i = 1; i < msg[0].len; i++)
> -				msgbuf0[i] = data->block[i-1];
> +				msg[0].buf[i] = data->block[i-1];
>  		}
>  		break;
>  	case I2C_SMBUS_BLOCK_PROC_CALL:
> @@ -389,16 +409,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  				data->block[0]);
>  			return -EINVAL;
>  		}
> +
>  		msg[0].len = data->block[0] + 2;
> +		i2c_smbus_try_get_dmabuf(&msg[0], command);
>  		for (i = 1; i < msg[0].len; i++)
> -			msgbuf0[i] = data->block[i-1];
> +			msg[0].buf[i] = data->block[i-1];
> +
>  		msg[1].flags |= I2C_M_RECV_LEN;
>  		msg[1].len = 1; /* block length will be added by
>  				   the underlying bus driver */
> +		i2c_smbus_try_get_dmabuf(&msg[1], 0);
>  		break;
>  	case I2C_SMBUS_I2C_BLOCK_DATA:
>  		if (read_write == I2C_SMBUS_READ) {
>  			msg[1].len = data->block[0];
> +			i2c_smbus_try_get_dmabuf(&msg[1], 0);
>  		} else {
>  			msg[0].len = data->block[0] + 1;
>  			if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
> @@ -407,8 +432,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  					data->block[0]);
>  				return -EINVAL;
>  			}
> +
> +			i2c_smbus_try_get_dmabuf(&msg[0], command);
>  			for (i = 1; i <= data->block[0]; i++)
> -				msgbuf0[i] = data->block[i];
> +				msg[0].buf[i] = data->block[i];
>  		}
>  		break;
>  	default:
> @@ -456,14 +483,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
>  			break;
>  		case I2C_SMBUS_I2C_BLOCK_DATA:
>  			for (i = 0; i < data->block[0]; i++)
> -				data->block[i+1] = msgbuf1[i];
> +				data->block[i+1] = msg[1].buf[i];
>  			break;
>  		case I2C_SMBUS_BLOCK_DATA:
>  		case I2C_SMBUS_BLOCK_PROC_CALL:
> -			for (i = 0; i < msgbuf1[0] + 1; i++)
> -				data->block[i] = msgbuf1[i];
> +			for (i = 0; i < msg[1].buf[0] + 1; i++)
> +				data->block[i] = msg[1].buf[i];
>  			break;
>  		}
> +
> +	if (msg[0].flags & I2C_M_DMA_SAFE)
> +		kfree(msg[0].buf);
> +	if (msg[1].flags & I2C_M_DMA_SAFE)
> +		kfree(msg[1].buf);
> +
>  	return 0;
>  }
>  

  reply	other threads:[~2017-11-11  0:13 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-04 20:20 [PATCH v6 0/9] i2c: document DMA handling and add helpers for it Wolfram Sang
2017-11-04 20:20 ` Wolfram Sang
2017-11-04 20:20 ` [PATCH v6 1/9] i2c: add a message flag for DMA safe buffers Wolfram Sang
2017-11-04 20:20 ` [PATCH v6 2/9] i2c: add helpers to ease DMA handling Wolfram Sang
2017-11-04 20:20   ` Wolfram Sang
2017-11-04 20:20 ` [PATCH v6 3/9] i2c: dev: mark RDWR buffers as DMA_SAFE Wolfram Sang
2017-11-04 20:20   ` Wolfram Sang
2017-11-04 20:20 ` [PATCH v6 4/9] i2c: refactor i2c_master_{send_recv} Wolfram Sang
2017-11-11  0:03   ` Jonathan Cameron
2017-11-11  0:03     ` Jonathan Cameron
2017-11-04 20:20 ` [PATCH v6 5/9] i2c: add i2c_master_{send|recv}_dmasafe Wolfram Sang
2017-11-11  0:08   ` Jonathan Cameron
2017-11-11  0:08     ` Jonathan Cameron
2017-11-04 20:20 ` [PATCH v6 6/9] i2c: smbus: use DMA safe buffers for emulated SMBus transactions Wolfram Sang
2017-11-11  0:13   ` Jonathan Cameron [this message]
2017-11-11  0:13     ` Jonathan Cameron
2017-11-04 20:20 ` [PATCH v6 7/9] i2c: add docs to clarify DMA handling Wolfram Sang
2017-11-04 20:20 ` [PATCH v6 8/9] i2c: sh_mobile: use core helper to decide when to use DMA Wolfram Sang
2017-11-04 20:20 ` [PATCH v6 9/9] i2c: rcar: skip DMA if buffer is not safe Wolfram Sang
2017-11-08 22:50 ` [PATCH v6 0/9] i2c: document DMA handling and add helpers for it Mark Brown
2017-11-27 18:51   ` Wolfram Sang
2017-11-28 15:34     ` Mark Brown
2017-12-03 19:43       ` Wolfram Sang
2017-12-04 22:05         ` Mark Brown
2017-12-04 22:05           ` Mark Brown
2017-12-05 11:00           ` Jonathan Cameron
2017-12-05 11:00             ` Jonathan Cameron
2017-12-04 21:25 ` Wolfram Sang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171111001326.0000349b@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=broonie@kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=wsa+renesas@sang-engineering.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.