Tests:I2C-core-DMA

!EARLY DRAFT!

This document describes how to test that the Linux I2C core properly handles DMA buffers. The I2C IP cores of a Renesas R-Car M3-W serve as examples here. =Setup=

Kernel Version and Configuration
Support for this feature is expected to land upstream in v4.14. It is currently available in a topic branch:

git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/topic/i2c-core-dma

The following kernel options need to be set in addition to the defconfig: CONFIG_DMA_API_DEBUG=y CONFIG_DMADEVICES_DEBUG=y

Hardware Environment

 * Salvator-X/r8a7796 (R-Car M3-W SoC)

Software Environment
Besides a busybox, the i2cdump utility from the i2c-tools package is needed.

=Testing=

We use the following command to to trigger DMA:

i2cdump -y -f 2 0x10 i # I2C/i2c-rcar i2cdump -y -f 7 0x50 i # IIC_DVFS/i2c-sh_mobile

Preparations
On the host, to get a Kernel branch without the I2C core DMA improvements, but with some DMA fixes for R-Car Gen3 I2C/IIC:

$ git checkout eec50514b00477 Note: checking out 'eec50514b00477'. ... HEAD is now at eec50514b00477... arm64: dts: r8a7796: add DMA for IIC_DVFS

IIC_DVFS/i2c-sh_mobile
On the target, with this Kernel, triggering an I2C access with DMA gives a stack dump: ... rcar-dmac e6700000.dma-controller: DMA-API: device driver maps memory from stack [addr=ffffffc636997cb0] [ cut here ] WARNING: CPU: 0 PID: 877 at lib/dma-debug.c:1188 check_for_stack+0xb0/0x100 ...
 * 1) i2cdump -y -f 7 0x50 i

I2C/i2c-rcar
This driver suffers from the same problem, yet DMA-DEBUG does not trigger. i2c-rcar maps new DMA buffers in interrupt context where likely a different task stack is in use. DMA-DEBUG can only detect stack usage from the current task. Still, the problem is present for i2c-rcar, too. The following patch makes it visible by temporarily mapping the buffer from the expected context: diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 8be3e6cb8fe686..6d10de8447066d 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -674,6 +674,9 @@ static void rcar_i2c_request_dma(struct rcar_i2c_priv *priv, 		priv->dma_rx = chan; 	else 		priv->dma_tx = chan; + +	dma_addr_t dma_addr = dma_map_single(chan->device->dev, msg->buf, msg->len, DMA_TO_DEVICE); +	dma_unmap_single(chan->device->dev, dma_addr, msg->len, DMA_TO_DEVICE); } static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)

gives:

... rcar-dmac e7310000.dma-controller: DMA-API: device driver maps memory from stack [addr=ffffffc63683bcd8] [ cut here ] WARNING: CPU: 1 PID: 877 at lib/dma-debug.c:1188 check_for_stack+0xb0/0x100 ...
 * 1) i2cdump -f -y 2 0x10 i

Summary
So, for both cases the DMA-DEBUG API detected the usage of the stack which is strongly discouraged. Still, DMA was used as one could see from all the DMA related debug output following the warning of the DMA-DEBUG API. The topic branch fully applied is about improving the situation.

after this task
WIP :)