RE: [PATCH 5/5] Add DMA engine driver for Freescale MPC85xx processors.
From: Nelson, Shannon <hidden>
Date: 2007-09-07 16:00:42
Also in:
lkml
quoted hunk ↗ jump to hunk
From: Zhang Wei [mailto:wei.zhang@freescale.com]=20 Sent: Friday, September 07, 2007 3:54 AM To: paulus@samba.org; Nelson, Shannon Cc: linux-kernel@vger.kernel.org; linuxppc-dev@ozlabs.org;=20 galak@kernel.crashing.org; Zhang Wei; Ebony Zhu Subject: [PATCH 5/5] Add DMA engine driver for Freescale=20 MPC85xx processors. The driver implements DMA engine API for Freescale MPC85xx DMA controller, which could be used for MEM<-->MEM, IO_ADDR<-->MEM and IO_ADDR<-->IO_ADDR data transfer. The driver supports the Basic mode of Freescale MPC85xx DMA controller. The MPC85xx processors supported include MPC8540/60, MPC8555, MPC8548, MPC8641 and so on. The support for MPC83xx(MPC8349, MPC8360) is experimental. Signed-off-by: Zhang Wei <redacted> Signed-off-by: Ebony Zhu <redacted> --- drivers/dma/Kconfig | 8 + drivers/dma/Makefile | 1 + drivers/dma/fsldma.c | 995=20 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/dma/fsldma.h | 188 ++++++++++ 4 files changed, 1192 insertions(+), 0 deletions(-) create mode 100644 drivers/dma/fsldma.c create mode 100644 drivers/dma/fsldma.hdiff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 8f670da..a99e925 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig@@ -40,4 +40,12 @@ config INTEL_IOP_ADMA ---help--- Enable support for the Intel(R) IOP Series RAID engines.=20 +config FSL_DMA + bool "Freescale MPC85xx/MPC83xx DMA support" + depends on DMA_ENGINE && PPC + ---help--- + Enable support for the Freescale DMA engine. Now, it support + MPC8560/40, MPC8555, MPC8548 and MPC8641 processors. + The MPC8349, MPC8360 support is experimental. + endmenu
If this is experimental, perhaps you should mark the depends line as such depends on on DMA_ENGINE && PPC && EXPERIMENTAL [...]
+static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan)
+{
+ struct dma_chan *chan;
+ int err =3D 0;
+ dma_addr_t addr;
+ dma_cookie_t cookie;
+ u8 *src, *dest;
+ int i;
+ size_t test_size;
+ struct dma_async_tx_descriptor *tx1, *tx2, *tx3;
+ struct fsl_dma_device *fdev;
+
+ BUG_ON(!fsl_chan);
+
+ fdev =3D fsl_chan->device;
+ test_size =3D 4096;
+
+ src =3D kmalloc(test_size * 2, GFP_KERNEL);
+ if (!src) {
+ dev_err(fdev->dev,
+ "selftest: Can not alloc memory=20
for test!\n");
+ err =3D -ENOMEM;
+ goto out;
+ }
+
+ dest =3D src + test_size;
+
+ for (i =3D 0; i < test_size; i++)
+ src[i] =3D (u8) i;
+
+ chan =3D &fsl_chan->common;
+
+ if (fsl_dma_alloc_chan_resources(chan) < 1) {
+ dev_err(fdev->dev,
+ "selftest: Can not alloc=20
resources for DMA\n");
+ err =3D -ENODEV;
+ goto out;
+ }
+
+ /* TX 1 */
+ tx1 =3D fsl_dma_prep_memcpy(chan, test_size / 2, 0);
+ async_tx_ack(tx1);
+ addr =3D dma_map_single(chan->device->dev, src, test_size / 2,
+ DMA_TO_DEVICE);
+ fsl_dma_set_src(addr, tx1, 0);
+ addr =3D dma_map_single(chan->device->dev, dest, test_size / 2,
+ =09
DMA_FROM_DEVICE);
+ fsl_dma_set_dest(addr, tx1, 0);
+
+ cookie =3D fsl_dma_tx_submit(tx1);
+ fsl_dma_memcpy_issue_pending(chan);
+
+ while (fsl_dma_is_complete(chan, cookie, NULL, NULL)
+ !=3D DMA_SUCCESS);Is this guaranteed to finish? If there's something wrong and the DMA never completes, you've now hung this thread. This is why the ioat_dma engine does an msleep() and then checks once for completion. You might think about this...
+
+ /* Test free and re-alloc channel resources */
+ fsl_dma_free_chan_resources(chan);
+
+ if (fsl_dma_alloc_chan_resources(chan) < 1) {
+ dev_err(fdev->dev,
+ "selftest: Can not alloc=20
resources for DMA\n");
+ err =3D -ENODEV;
+ goto out;
+ }
+
+ /* Continue to test
+ * TX 2
+ */
+ tx2 =3D fsl_dma_prep_memcpy(chan, test_size / 4, 0);
+ async_tx_ack(tx2);
+ addr =3D dma_map_single(chan->device->dev, src + test_size / 2,
+ test_size / 4, DMA_TO_DEVICE);
+ fsl_dma_set_src(addr, tx2, 0);
+ addr =3D dma_map_single(chan->device->dev, dest + test_size / 2,
+ test_size / 4, DMA_FROM_DEVICE);
+ fsl_dma_set_dest(addr, tx2, 0);
+
+ /* TX 3 */
+ tx3 =3D fsl_dma_prep_memcpy(chan, test_size / 4, 0);
+ async_tx_ack(tx3);
+ addr =3D dma_map_single(chan->device->dev, src +=20
test_size * 3 / 4,
+ test_size / 4, DMA_TO_DEVICE);
+ fsl_dma_set_src(addr, tx3, 0);
+ addr =3D dma_map_single(chan->device->dev, dest +=20
test_size * 3 / 4,
+ test_size / 4, DMA_FROM_DEVICE);
+ fsl_dma_set_dest(addr, tx3, 0);
+
+ /* Test exchanging the prepared tx sort */
+ cookie =3D fsl_dma_tx_submit(tx3);
+ cookie =3D fsl_dma_tx_submit(tx2);
+
+ fsl_dma_memcpy_issue_pending(chan);
+ while (fsl_dma_is_complete(chan, cookie, NULL, NULL)
+ !=3D DMA_SUCCESS);Again, is it possible to hang your thread here? [...] sln -- =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Mr. Shannon Nelson LAN Access Division, Intel Corp. Shannon.Nelson@intel.com I don't speak for Intel (503) 712-7659 Parents can't afford to be squeamish.