From: Tony Lindgren <tony@atomide.com>
To: Russell King - ARM Linux <linux@arm.linux.org.uk>,
Grazvydas Ignotas <notasas@gmail.com>
Cc: linux-arm-kernel@lists.infradead.org, linux-omap@vger.kernel.org,
linux-mmc@vger.kernel.org
Subject: Re: [RFC 00/12] OMAP DMA engine conversion
Date: Tue, 24 Apr 2012 09:51:48 -0700 [thread overview]
Message-ID: <20120424165147.GP3739@atomide.com> (raw)
In-Reply-To: <20120424103858.GC25053@n2100.arm.linux.org.uk>
* Russell King - ARM Linux <linux@arm.linux.org.uk> [120424 03:42]:
> Here's another patch - for the OMAP NAND driver.
>
> One thing this doesn't do is configure up the source/destination bursts,
> which the old code did:
>
> omap_set_dma_dest_burst_mode(info->dma_ch,
> OMAP_DMA_DATA_BURST_16);
> omap_set_dma_src_burst_mode(info->dma_ch,
> OMAP_DMA_DATA_BURST_16);
Grazvydas, care to give this patch a go?
> In dma-engine speak, I'm using "burst" for the number of elements to
> transfer for each frame, with frame sync in place (in other words, the
> number of transfers to occur for every assertion of the DMA request.)
> That's how burst is defined on other DMA hardware, so I'm not entirely
> sure at the moment how critical (or what) the above bursts are doing,
> whether they're configuring the memory side of the transfer or not.
> I'll take a deeper look into that this evening, but in the mean time,
> what's below should be a direct conversion.
For omaps it enables multiple access.
> MTD does have this weirdness that it uses vmalloc regions and passes
> addresses in vmalloc regions into drivers - I've left that hack in but
> it is _highly_ undefined whether the DMA activity would be visible via
> the vmalloc mapping as things currently stand. (You're probably going
> to be okay with non-aliasing VIPT caches, but VIVT and aliasing VIPT
> caches are potential random data corruption candidates.) That's a
> short-coming across many MTD drivers, one which needs sorting out across
> the board.
>
> drivers/mtd/nand/omap2.c | 93 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 92 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index c2b0bba..bd4ed08 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -9,6 +9,7 @@
> */
>
> #include <linux/platform_device.h>
> +#include <linux/dmaengine.h>
> #include <linux/dma-mapping.h>
> #include <linux/delay.h>
> #include <linux/module.h>
> @@ -119,6 +120,7 @@ struct omap_nand_info {
> int gpmc_cs;
> unsigned long phys_base;
> struct completion comp;
> + struct dma_chan *dma;
> int dma_ch;
> int gpmc_irq;
> enum {
> @@ -336,6 +338,10 @@ static void omap_nand_dma_cb(int lch, u16 ch_status, void *data)
> {
> complete((struct completion *) data);
> }
> +static void omap_nand_dma_callback(void *data)
> +{
> + complete((struct completion *) data);
> +}
>
> /*
> * omap_nand_dma_transfer: configer and start dma transfer
> @@ -373,6 +379,56 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> addr = page_address(p1) + ((size_t)addr & ~PAGE_MASK);
> }
>
> + if (info->dma) {
> + struct dma_async_tx_descriptor *tx;
> + struct scatterlist sg;
> + unsigned n;
> +
> + sg_init_one(&sg, addr, len);
> + n = dma_map_sg(info->dma->device->dev, &sg, 1, dir);
> + if (n == 0) {
> + dev_err(&info->pdev->dev,
> + "Couldn't DMA map a %d byte buffer\n", len);
> + goto out_copy;
> + }
> +
> + tx = dmaengine_prep_slave_sg(info->dma, &sg, n,
> + is_write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
> + DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> + if (!tx) {
> + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir);
> + goto out_copy;
> + }
> + tx->callback = omap_nand_dma_callback;
> + tx->callback_param = &info->comp;
> + dmaengine_submit(tx);
> +
> + /* configure and start prefetch transfer */
> + ret = gpmc_prefetch_enable(info->gpmc_cs,
> + PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
> + if (ret) {
> + /* PFPW engine is busy, use cpu copy method */
> + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir);
> + goto out_copy;
> + }
> +
> + init_completion(&info->comp);
> + dma_async_issue_pending(info->dma);
> +
> + /* setup and start DMA using dma_addr */
> + wait_for_completion(&info->comp);
> + tim = 0;
> + limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
> + while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
> + cpu_relax();
> +
> + /* disable and stop the PFPW engine */
> + gpmc_prefetch_reset(info->gpmc_cs);
> +
> + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir);
> + return 0;
> + }
> +
> dma_addr = dma_map_single(&info->pdev->dev, addr, len, dir);
> if (dma_mapping_error(&info->pdev->dev, dma_addr)) {
> dev_err(&info->pdev->dev,
> @@ -405,7 +461,6 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> goto out_copy;
>
> init_completion(&info->comp);
> -
> omap_start_dma(info->dma_ch);
>
> /* setup and start DMA using dma_addr */
> @@ -925,12 +980,16 @@ static int omap_dev_ready(struct mtd_info *mtd)
> return 1;
> }
>
> +extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param);
> +
> static int __devinit omap_nand_probe(struct platform_device *pdev)
> {
> struct omap_nand_info *info;
> struct omap_nand_platform_data *pdata;
> int err;
> int i, offset;
> + dma_cap_mask_t mask;
> + unsigned sig;
>
> pdata = pdev->dev.platform_data;
> if (pdata == NULL) {
> @@ -1011,6 +1070,33 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
> break;
>
> case NAND_OMAP_PREFETCH_DMA:
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_SLAVE, mask);
> + sig = OMAP24XX_DMA_GPMC;
> + info->dma = dma_request_channel(mask, omap_dma_filter_fn, &sig);
> + if (!info->dma) {
> + dev_warn(&pdev->dev, "DMA engine request failed\n");
> + } else {
> + struct dma_slave_config cfg;
> + int rc;
> +
> + memset(&cfg, 0, sizeof(cfg));
> + cfg.src_addr = info->phys_base;
> + cfg.dst_addr = info->phys_base;
> + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + cfg.src_maxburst = 16;
> + cfg.dst_maxburst = 16;
> + rc = dmaengine_slave_config(info->dma, &cfg);
> + if (rc) {
> + dev_err(&pdev->dev, "DMA engine slave config failed: %d\n",
> + rc);
> + goto out_release_mem_region;
> + }
> + info->nand.read_buf = omap_read_buf_dma_pref;
> + info->nand.write_buf = omap_write_buf_dma_pref;
> + break;
> + }
> err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
> omap_nand_dma_cb, &info->comp, &info->dma_ch);
> if (err < 0) {
> @@ -1110,6 +1196,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
> return 0;
>
> out_release_mem_region:
> + if (info->dma)
> + dma_release_channel(info->dma);
> release_mem_region(info->phys_base, NAND_IO_SIZE);
> out_free_info:
> kfree(info);
> @@ -1127,6 +1215,9 @@ static int omap_nand_remove(struct platform_device *pdev)
> if (info->dma_ch != -1)
> omap_free_dma(info->dma_ch);
>
> + if (info->dma)
> + dma_release_channel(info->dma);
> +
> if (info->gpmc_irq)
> free_irq(info->gpmc_irq, info);
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
WARNING: multiple messages have this Message-ID (diff)
From: tony@atomide.com (Tony Lindgren)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC 00/12] OMAP DMA engine conversion
Date: Tue, 24 Apr 2012 09:51:48 -0700 [thread overview]
Message-ID: <20120424165147.GP3739@atomide.com> (raw)
In-Reply-To: <20120424103858.GC25053@n2100.arm.linux.org.uk>
* Russell King - ARM Linux <linux@arm.linux.org.uk> [120424 03:42]:
> Here's another patch - for the OMAP NAND driver.
>
> One thing this doesn't do is configure up the source/destination bursts,
> which the old code did:
>
> omap_set_dma_dest_burst_mode(info->dma_ch,
> OMAP_DMA_DATA_BURST_16);
> omap_set_dma_src_burst_mode(info->dma_ch,
> OMAP_DMA_DATA_BURST_16);
Grazvydas, care to give this patch a go?
> In dma-engine speak, I'm using "burst" for the number of elements to
> transfer for each frame, with frame sync in place (in other words, the
> number of transfers to occur for every assertion of the DMA request.)
> That's how burst is defined on other DMA hardware, so I'm not entirely
> sure at the moment how critical (or what) the above bursts are doing,
> whether they're configuring the memory side of the transfer or not.
> I'll take a deeper look into that this evening, but in the mean time,
> what's below should be a direct conversion.
For omaps it enables multiple access.
> MTD does have this weirdness that it uses vmalloc regions and passes
> addresses in vmalloc regions into drivers - I've left that hack in but
> it is _highly_ undefined whether the DMA activity would be visible via
> the vmalloc mapping as things currently stand. (You're probably going
> to be okay with non-aliasing VIPT caches, but VIVT and aliasing VIPT
> caches are potential random data corruption candidates.) That's a
> short-coming across many MTD drivers, one which needs sorting out across
> the board.
>
> drivers/mtd/nand/omap2.c | 93 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 92 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index c2b0bba..bd4ed08 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -9,6 +9,7 @@
> */
>
> #include <linux/platform_device.h>
> +#include <linux/dmaengine.h>
> #include <linux/dma-mapping.h>
> #include <linux/delay.h>
> #include <linux/module.h>
> @@ -119,6 +120,7 @@ struct omap_nand_info {
> int gpmc_cs;
> unsigned long phys_base;
> struct completion comp;
> + struct dma_chan *dma;
> int dma_ch;
> int gpmc_irq;
> enum {
> @@ -336,6 +338,10 @@ static void omap_nand_dma_cb(int lch, u16 ch_status, void *data)
> {
> complete((struct completion *) data);
> }
> +static void omap_nand_dma_callback(void *data)
> +{
> + complete((struct completion *) data);
> +}
>
> /*
> * omap_nand_dma_transfer: configer and start dma transfer
> @@ -373,6 +379,56 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> addr = page_address(p1) + ((size_t)addr & ~PAGE_MASK);
> }
>
> + if (info->dma) {
> + struct dma_async_tx_descriptor *tx;
> + struct scatterlist sg;
> + unsigned n;
> +
> + sg_init_one(&sg, addr, len);
> + n = dma_map_sg(info->dma->device->dev, &sg, 1, dir);
> + if (n == 0) {
> + dev_err(&info->pdev->dev,
> + "Couldn't DMA map a %d byte buffer\n", len);
> + goto out_copy;
> + }
> +
> + tx = dmaengine_prep_slave_sg(info->dma, &sg, n,
> + is_write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
> + DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> + if (!tx) {
> + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir);
> + goto out_copy;
> + }
> + tx->callback = omap_nand_dma_callback;
> + tx->callback_param = &info->comp;
> + dmaengine_submit(tx);
> +
> + /* configure and start prefetch transfer */
> + ret = gpmc_prefetch_enable(info->gpmc_cs,
> + PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
> + if (ret) {
> + /* PFPW engine is busy, use cpu copy method */
> + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir);
> + goto out_copy;
> + }
> +
> + init_completion(&info->comp);
> + dma_async_issue_pending(info->dma);
> +
> + /* setup and start DMA using dma_addr */
> + wait_for_completion(&info->comp);
> + tim = 0;
> + limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
> + while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
> + cpu_relax();
> +
> + /* disable and stop the PFPW engine */
> + gpmc_prefetch_reset(info->gpmc_cs);
> +
> + dma_unmap_sg(info->dma->device->dev, &sg, 1, dir);
> + return 0;
> + }
> +
> dma_addr = dma_map_single(&info->pdev->dev, addr, len, dir);
> if (dma_mapping_error(&info->pdev->dev, dma_addr)) {
> dev_err(&info->pdev->dev,
> @@ -405,7 +461,6 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
> goto out_copy;
>
> init_completion(&info->comp);
> -
> omap_start_dma(info->dma_ch);
>
> /* setup and start DMA using dma_addr */
> @@ -925,12 +980,16 @@ static int omap_dev_ready(struct mtd_info *mtd)
> return 1;
> }
>
> +extern bool omap_dma_filter_fn(struct dma_chan *chan, void *param);
> +
> static int __devinit omap_nand_probe(struct platform_device *pdev)
> {
> struct omap_nand_info *info;
> struct omap_nand_platform_data *pdata;
> int err;
> int i, offset;
> + dma_cap_mask_t mask;
> + unsigned sig;
>
> pdata = pdev->dev.platform_data;
> if (pdata == NULL) {
> @@ -1011,6 +1070,33 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
> break;
>
> case NAND_OMAP_PREFETCH_DMA:
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_SLAVE, mask);
> + sig = OMAP24XX_DMA_GPMC;
> + info->dma = dma_request_channel(mask, omap_dma_filter_fn, &sig);
> + if (!info->dma) {
> + dev_warn(&pdev->dev, "DMA engine request failed\n");
> + } else {
> + struct dma_slave_config cfg;
> + int rc;
> +
> + memset(&cfg, 0, sizeof(cfg));
> + cfg.src_addr = info->phys_base;
> + cfg.dst_addr = info->phys_base;
> + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + cfg.src_maxburst = 16;
> + cfg.dst_maxburst = 16;
> + rc = dmaengine_slave_config(info->dma, &cfg);
> + if (rc) {
> + dev_err(&pdev->dev, "DMA engine slave config failed: %d\n",
> + rc);
> + goto out_release_mem_region;
> + }
> + info->nand.read_buf = omap_read_buf_dma_pref;
> + info->nand.write_buf = omap_write_buf_dma_pref;
> + break;
> + }
> err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
> omap_nand_dma_cb, &info->comp, &info->dma_ch);
> if (err < 0) {
> @@ -1110,6 +1196,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
> return 0;
>
> out_release_mem_region:
> + if (info->dma)
> + dma_release_channel(info->dma);
> release_mem_region(info->phys_base, NAND_IO_SIZE);
> out_free_info:
> kfree(info);
> @@ -1127,6 +1215,9 @@ static int omap_nand_remove(struct platform_device *pdev)
> if (info->dma_ch != -1)
> omap_free_dma(info->dma_ch);
>
> + if (info->dma)
> + dma_release_channel(info->dma);
> +
> if (info->gpmc_irq)
> free_irq(info->gpmc_irq, info);
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2012-04-24 16:51 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-23 16:04 [RFC 00/12] OMAP DMA engine conversion Russell King - ARM Linux
2012-04-23 16:04 ` Russell King - ARM Linux
2012-04-23 16:04 ` [PATCH 01/12] ARM: OMAP: fix DMA vs memory ordering Russell King
2012-04-23 16:04 ` Russell King
2012-04-23 16:04 ` [PATCH 02/12] dmaengine: split out virtual channel DMA support from sa11x0 driver Russell King
2012-04-23 16:04 ` Russell King
2012-04-27 18:57 ` Linus Walleij
2012-04-27 18:57 ` Linus Walleij
2012-04-23 16:05 ` [PATCH 03/12] dmaengine: add OMAP DMA engine driver Russell King
2012-04-23 16:05 ` Russell King
2012-04-23 16:05 ` [PATCH 04/12] mmc: omap_hsmmc: release correct resource Russell King
2012-04-23 16:05 ` Russell King
2012-04-23 16:05 ` [PATCH 05/12] mmc: omap_hsmmc: add DMA engine support Russell King
2012-04-23 16:05 ` Russell King
2012-04-24 0:16 ` Tony Lindgren
2012-04-24 0:16 ` Tony Lindgren
2012-04-27 19:00 ` Linus Walleij
2012-04-27 19:00 ` Linus Walleij
2012-04-27 19:03 ` Russell King - ARM Linux
2012-04-27 19:03 ` Russell King - ARM Linux
2012-04-27 20:34 ` Linus Walleij
2012-04-27 20:34 ` Linus Walleij
2012-04-23 16:06 ` [PATCH 06/12] mmc: omap_hsmmc: remove private DMA API implementation Russell King
2012-04-23 16:06 ` Russell King
2012-04-24 0:17 ` Tony Lindgren
2012-04-24 0:17 ` Tony Lindgren
2012-04-24 21:51 ` Grazvydas Ignotas
2012-04-24 21:51 ` Grazvydas Ignotas
2012-04-24 22:05 ` Russell King - ARM Linux
2012-04-24 22:05 ` Russell King - ARM Linux
2012-04-23 16:06 ` [PATCH 07/12] mmc: omap: add DMA engine support Russell King
2012-04-23 16:06 ` Russell King
2012-04-24 0:13 ` Tony Lindgren
2012-04-24 0:13 ` Tony Lindgren
2012-04-28 16:37 ` Russell King - ARM Linux
2012-04-28 16:37 ` Russell King - ARM Linux
2012-04-30 15:59 ` Tony Lindgren
2012-04-30 15:59 ` Tony Lindgren
2012-04-23 16:06 ` [PATCH 08/12] mmc: omap: remove private DMA API implementation Russell King
2012-04-23 16:06 ` Russell King
2012-04-23 16:07 ` [PATCH 09/12] ARM: omap: remove mmc platform data dma_mask and initialization Russell King
2012-04-23 16:07 ` Russell King
2012-04-23 16:07 ` [PATCH 10/12] spi: omap2-mcspi: add DMA engine support Russell King
2012-04-23 16:07 ` Russell King
2012-04-27 17:20 ` Grant Likely
2012-04-27 17:20 ` Grant Likely
2012-04-23 16:07 ` [PATCH 11/12] spi: omap2-mcspi: remove private DMA API implementation Russell King
2012-04-23 16:07 ` Russell King
2012-04-23 16:08 ` [PATCH 12/12] Add removal of old OMAP private DMA implementation to feature removal Russell King
2012-04-23 16:08 ` Russell King
2012-04-24 0:17 ` Tony Lindgren
2012-04-24 0:17 ` Tony Lindgren
2012-04-27 20:19 ` Linus Walleij
2012-04-27 20:19 ` Linus Walleij
2012-04-24 10:38 ` [RFC 00/12] OMAP DMA engine conversion Russell King - ARM Linux
2012-04-24 10:38 ` Russell King - ARM Linux
2012-04-24 16:51 ` Tony Lindgren [this message]
2012-04-24 16:51 ` Tony Lindgren
2012-04-24 22:47 ` Grazvydas Ignotas
2012-04-24 22:47 ` Grazvydas Ignotas
2012-04-24 23:29 ` Russell King - ARM Linux
2012-04-24 23:29 ` Russell King - ARM Linux
2012-04-24 23:59 ` Grazvydas Ignotas
2012-04-24 23:59 ` Grazvydas Ignotas
2012-05-09 12:25 ` T Krishnamoorthy, Balaji
2012-05-09 12:25 ` T Krishnamoorthy, Balaji
2012-05-15 4:19 ` Vinod Koul
2012-05-15 4:19 ` Vinod Koul
2012-05-15 7:41 ` Russell King - ARM Linux
2012-05-15 7:41 ` Russell King - ARM Linux
2012-05-15 8:59 ` Vinod Koul
2012-05-15 8:59 ` Vinod Koul
2012-05-15 9:32 ` Russell King - ARM Linux
2012-05-15 9:32 ` Russell King - ARM Linux
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=20120424165147.GP3739@atomide.com \
--to=tony@atomide.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-mmc@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=notasas@gmail.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.