Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1667121 > unrolled thread
| Started by | Wolfram Sang <wsa+renesas@sang-engineering.com> |
|---|---|
| First post | 2017-06-15 20:40 +0200 |
| Last post | 2017-06-15 20:50 +0200 |
| Articles | 6 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH 0/4] i2c: document DMA handling and add helpers for it Wolfram Sang <wsa+renesas@sang-engineering.com> - 2017-06-15 20:40 +0200
[PATCH 1/4] i2c: add helpers to ease DMA handling Wolfram Sang <wsa+renesas@sang-engineering.com> - 2017-06-15 20:40 +0200
Re: [PATCH 1/4] i2c: add helpers to ease DMA handling Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-15 22:40 +0200
[PATCH 2/4] i2c: add docs to clarify DMA handling Wolfram Sang <wsa+renesas@sang-engineering.com> - 2017-06-15 20:40 +0200
Re: [PATCH 2/4] i2c: add docs to clarify DMA handling Geert Uytterhoeven <geert@linux-m68k.org> - 2017-06-15 22:40 +0200
Re: [PATCH 0/4] i2c: document DMA handling and add helpers for it Wolfram Sang <wsa@the-dreams.de> - 2017-06-15 20:50 +0200
| From | Wolfram Sang <wsa+renesas@sang-engineering.com> |
|---|---|
| Date | 2017-06-15 20:40 +0200 |
| Subject | [PATCH 0/4] i2c: document DMA handling and add helpers for it |
| Message-ID | <tSHQt-5ZL-9@gated-at.bofh.it> |
So, after revisiting old mail threads and taking part in a similar discussion on the USB list, here is what I cooked up to document and ease DMA handling for I2C within Linux. Please have a look at the documentation introduced in patch 2 for further details. The branch can be found here: git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/topic/i2c-core-dma And big kudos to Renesas Electronics for funding this work, thank you very much! Regards, Wolfram Changes since RFC: * the helper i2c_check_msg_for_dma() can optionally take a pointer and then it will attach a bounce buffer to it in case the message buffer is not DMA safe * a second helper was added. i2c_release_bounce_buf() will copy data back to the message buffer and release the bounce buffer * the documentation has been extended to match the above * no ifdeffery around CONFIG_DMA_API_DEBUG anymore. The I2C core behaviour should not depend on such symbols. * the i2c-sh_mobile driver has been updated to use bounce buffers Wolfram Sang (4): i2c: add helpers to ease DMA handling i2c: add docs to clarify DMA handling i2c: sh_mobile: use helper to decide if DMA is useful i2c: rcar: check for DMA-capable buffers Documentation/i2c/DMA-considerations | 37 ++++++++++++++++++++ drivers/i2c/busses/i2c-rcar.c | 18 +++++++--- drivers/i2c/busses/i2c-sh_mobile.c | 8 +++-- include/linux/i2c.h | 65 ++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 Documentation/i2c/DMA-considerations -- 2.11.0
[toc] | [next] | [standalone]
| From | Wolfram Sang <wsa+renesas@sang-engineering.com> |
|---|---|
| Date | 2017-06-15 20:40 +0200 |
| Subject | [PATCH 1/4] i2c: add helpers to ease DMA handling |
| Message-ID | <tSHQv-5ZL-59@gated-at.bofh.it> |
| In reply to | #1667121 |
One helper checks if DMA is suitable and optionally creates a bounce
buffer, if not. The other function returns the bounce buffer and makes
sure the data is properly copied back to the message.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
---
include/linux/i2c.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 65 insertions(+)
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 72d0ece70ed30d..7204d38eaff07c 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -33,7 +33,10 @@
#include <linux/rtmutex.h>
#include <linux/irqdomain.h> /* for Host Notify IRQ */
#include <linux/of.h> /* for struct device_node */
+#include <linux/slab.h>
#include <linux/swab.h> /* for swab16 */
+#include <linux/mm.h>
+#include <linux/sched/task_stack.h>
#include <uapi/linux/i2c.h>
extern struct bus_type i2c_bus_type;
@@ -764,6 +767,68 @@ static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
}
+/**
+ * i2c_check_msg_for_dma - check if a message is suitable for DMA
+ * @msg: the message to be checked
+ * @threshold: the amount of byte from which using DMA makes sense
+ * @ptr_for_bounce_buf: if not NULL, a bounce buffer will be attached to this
+ * ptr, if needed. The bounce buffer must be freed by the
+ * caller using i2c_release_bounce_buf().
+ *
+ * Return: -ERANGE if message is smaller than threshold
+ * -EFAULT if message buffer is not DMA capable and no bounce buffer
+ * was requested
+ * -ENOMEM if a bounce buffer could not be created
+ * 0 if message is suitable for DMA
+ *
+ * Note: This function should only be called from process context! It uses
+ * helper functions which work on the 'current' task.
+ */
+static inline int i2c_check_msg_for_dma(struct i2c_msg *msg, unsigned int threshold,
+ u8 **ptr_for_bounce_buf)
+{
+ if (ptr_for_bounce_buf)
+ *ptr_for_bounce_buf = NULL;
+
+ if (msg->len < threshold)
+ return -ERANGE;
+
+ if (!virt_addr_valid(msg->buf) || object_is_on_stack(msg->buf)) {
+ pr_debug("msg buffer to 0x%04x is not DMA safe%s\n", msg->addr,
+ ptr_for_bounce_buf ? ", trying bounce buffer" : "");
+ if (ptr_for_bounce_buf) {
+ if (msg->flags & I2C_M_RD)
+ *ptr_for_bounce_buf = kzalloc(msg->len, GFP_KERNEL);
+ else
+ *ptr_for_bounce_buf = kmemdup(msg->buf, msg->len,
+ GFP_KERNEL);
+ if (!*ptr_for_bounce_buf)
+ return -ENOMEM;
+ } else {
+ return -EFAULT;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * i2c_release_bounce_buf - copy data back from bounce buffer and release it
+ * @msg: the message to be copied back to
+ * @bounce_buf: the bounce buffer obtained from i2c_check_msg_for_dma().
+ * May be NULL.
+ */
+static inline void i2c_release_bounce_buf(struct i2c_msg *msg, u8 *bounce_buf)
+{
+ if (!bounce_buf)
+ return;
+
+ if (msg->flags & I2C_M_RD)
+ memcpy(msg->buf, bounce_buf, msg->len);
+
+ kfree(bounce_buf);
+}
+
int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr);
/**
* module_i2c_driver() - Helper macro for registering a modular I2C driver
--
2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-06-15 22:40 +0200 |
| Subject | Re: [PATCH 1/4] i2c: add helpers to ease DMA handling |
| Message-ID | <tSJIC-7cs-21@gated-at.bofh.it> |
| In reply to | #1667124 |
Hi Wolfram,
On Thu, Jun 15, 2017 at 8:30 PM, Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
> One helper checks if DMA is suitable and optionally creates a bounce
> buffer, if not. The other function returns the bounce buffer and makes
> sure the data is properly copied back to the message.
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -764,6 +767,68 @@ static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
> return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
> }
>
> +/**
> + * i2c_check_msg_for_dma - check if a message is suitable for DMA
> + * @msg: the message to be checked
> + * @threshold: the amount of byte from which using DMA makes sense
> + * @ptr_for_bounce_buf: if not NULL, a bounce buffer will be attached to this
> + * ptr, if needed. The bounce buffer must be freed by the
> + * caller using i2c_release_bounce_buf().
> + *
> + * Return: -ERANGE if message is smaller than threshold
> + * -EFAULT if message buffer is not DMA capable and no bounce buffer
> + * was requested
> + * -ENOMEM if a bounce buffer could not be created
> + * 0 if message is suitable for DMA
> + *
> + * Note: This function should only be called from process context! It uses
> + * helper functions which work on the 'current' task.
> + */
> +static inline int i2c_check_msg_for_dma(struct i2c_msg *msg, unsigned int threshold,
> + u8 **ptr_for_bounce_buf)
__must_check?
Isn't this function a bit large to be inlined?
> +/**
> + * i2c_release_bounce_buf - copy data back from bounce buffer and release it
> + * @msg: the message to be copied back to
> + * @bounce_buf: the bounce buffer obtained from i2c_check_msg_for_dma().
> + * May be NULL.
> + */
> +static inline void i2c_release_bounce_buf(struct i2c_msg *msg, u8 *bounce_buf)
This one is smaller.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
[toc] | [prev] | [next] | [standalone]
| From | Wolfram Sang <wsa+renesas@sang-engineering.com> |
|---|---|
| Date | 2017-06-15 20:40 +0200 |
| Subject | [PATCH 2/4] i2c: add docs to clarify DMA handling |
| Message-ID | <tSHQv-5ZL-65@gated-at.bofh.it> |
| In reply to | #1667121 |
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> --- Documentation/i2c/DMA-considerations | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Documentation/i2c/DMA-considerations diff --git a/Documentation/i2c/DMA-considerations b/Documentation/i2c/DMA-considerations new file mode 100644 index 00000000000000..92cdb6835ccf95 --- /dev/null +++ b/Documentation/i2c/DMA-considerations @@ -0,0 +1,37 @@ +Linux I2C and DMA +----------------- + +Given that I2C is a low-speed bus where largely small messages are transferred, +it is not considered a prime user of DMA access. At this time of writing, only +10% of I2C bus master drivers have DMA support implemented. And the vast +majority of transactions are so small that setting up DMA for it will likely +add more overhead than a plain PIO transfer. + +Therefore, it is *not* mandatory that the buffer of an I2C message is DMA safe. +It does not seem reasonable to apply additional burdens when the feature is so +rarely used. However, it is recommended to use a DMA-safe buffer if your +message size is likely applicable for DMA. Most drivers have this threshold +around 8 bytes. As of today, this is mostly an educated guess, however. + +To support this scenario, drivers wishing to implement DMA can use helper +functions from the I2C core. One checks if a message is DMA capable in terms of +size and memory type. It can optionally also create a bounce buffer: + + i2c_check_msg_for_dma(msg, threshold, &bounce_buf); + +The other one releases the bounce buffer ensuring data is copied back to the +message: + + i2c_release_bounce_buf(msg, bounce_buf); + +Please check the in-kernel documentation for details. The i2c-sh_mobile driver +can be used as a reference example. + +The bounce buffer handling from the core is generic and simple. It will always +allocate a new buffer. If you want a more sophisticated buffer handling (e.g. +reusing pre-allocated buffers), you can skip the generic handling from the core +and implement your own. + +If you plan to use DMA with I2C (or with any other bus, actually) make sure you +have CONFIG_DMA_API_DEBUG enabled during development. It can help you find +various issues which can be complex to debug otherwise. -- 2.11.0
[toc] | [prev] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-06-15 22:40 +0200 |
| Subject | Re: [PATCH 2/4] i2c: add docs to clarify DMA handling |
| Message-ID | <tSJIC-7cs-27@gated-at.bofh.it> |
| In reply to | #1667127 |
Hi Wolfram,
On Thu, Jun 15, 2017 at 8:30 PM, Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
> --- /dev/null
> +++ b/Documentation/i2c/DMA-considerations
> @@ -0,0 +1,37 @@
> +Linux I2C and DMA
> +-----------------
> +
> +Given that I2C is a low-speed bus where largely small messages are transferred,
> +it is not considered a prime user of DMA access. At this time of writing, only
> +10% of I2C bus master drivers have DMA support implemented. And the vast
> +majority of transactions are so small that setting up DMA for it will likely
> +add more overhead than a plain PIO transfer.
> +
> +Therefore, it is *not* mandatory that the buffer of an I2C message is DMA safe.
> +It does not seem reasonable to apply additional burdens when the feature is so
> +rarely used. However, it is recommended to use a DMA-safe buffer if your
> +message size is likely applicable for DMA. Most drivers have this threshold
> +around 8 bytes. As of today, this is mostly an educated guess, however.
> +
> +To support this scenario, drivers wishing to implement DMA can use helper
> +functions from the I2C core. One checks if a message is DMA capable in terms of
> +size and memory type. It can optionally also create a bounce buffer:
> +
> + i2c_check_msg_for_dma(msg, threshold, &bounce_buf);
Obviously the return value must be checked before proceeding.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
[toc] | [prev] | [next] | [standalone]
| From | Wolfram Sang <wsa@the-dreams.de> |
|---|---|
| Date | 2017-06-15 20:50 +0200 |
| Message-ID | <tSI0a-63s-23@gated-at.bofh.it> |
| In reply to | #1667121 |
[Multipart message — attachments visible in raw view] — view raw
On Thu, Jun 15, 2017 at 08:30:35PM +0200, Wolfram Sang wrote: > So, after revisiting old mail threads and taking part in a similar discussion > on the USB list, here is what I cooked up to document and ease DMA handling for > I2C within Linux. Please have a look at the documentation introduced in patch 2 > for further details. > > The branch can be found here: > > git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/topic/i2c-core-dma > > And big kudos to Renesas Electronics for funding this work, thank you very much! I forgot to write that those patches have been tested with a Renesas Salvator-X board (r8a7796/M3-W) and a Renesas Lager board (r8a7790/H2). A more detailed test description can be found here: http://elinux.org/Tests:I2C-core-DMA And sorry for the doubled Signed-offs below the patches. My mistake here, there should be only the ones from sang-engineering.com.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web