From: vinod.koul@intel.com (Vinod Koul)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
Date: Sun, 26 Jan 2014 19:54:36 +0530 [thread overview]
Message-ID: <20140126142436.GF10628@intel.com> (raw)
In-Reply-To: <1390409565-4200-2-git-send-email-sthokal@xilinx.com>
On Wed, Jan 22, 2014 at 10:22:45PM +0530, Srikanth Thokala wrote:
> This is the driver for the AXI Video Direct Memory Access (AXI
> VDMA) core, which is a soft Xilinx IP core that provides high-
> bandwidth direct memory access between memory and AXI4-Stream
> type video target peripherals. The core provides efficient two
> dimensional DMA operations with independent asynchronous read
ok here is tha catch, do you want to support interleaved API rather?
> +* DMA client + +Required properties: +- dmas: a list of <[Video DMA device
> phandle] [Channel ID]> pairs, + where Channel ID is '0' for write/tx and
> '1' for read/rx + channel. +- dma-names: a list of DMA channel names, one
> per "dmas" entry + +Example: +++++++++ + +vdmatest_0: vdmatest at 0 { +
> compatible ="xlnx,axi-vdma-test-1.00.a"; + dmas = <&axi_vdma_0 0 +
> &axi_vdma_0 1>; + dma-names = "vdma0", "vdma1"; +} ;
Need ack from DT folks. ALso would be better to split the binding to a separate
patch
> +/**
> + * struct xilinx_vdma_chan - Driver specific VDMA channel structure
> + * @xdev: Driver specific device structure
> + * @ctrl_offset: Control registers offset
> + * @desc_offset: TX descriptor registers offset
> + * @completed_cookie: Maximum cookie completed
> + * @cookie: The current cookie
> + * @lock: Descriptor operation lock
> + * @pending_list: Descriptors waiting
> + * @active_desc: Active descriptor
> + * @done_list: Complete descriptors
> + * @common: DMA common channel
> + * @desc_pool: Descriptors pool
> + * @dev: The dma device
> + * @irq: Channel IRQ
> + * @id: Channel ID
> + * @direction: Transfer direction
> + * @num_frms: Number of frames
> + * @has_sg: Support scatter transfers
> + * @genlock: Support genlock mode
> + * @err: Channel has errors
> + * @tasklet: Cleanup work after irq
> + * @config: Device configuration info
> + * @flush_on_fsync: Flush on Frame sync
> + */
> +struct xilinx_vdma_chan {
> + struct xilinx_vdma_device *xdev;
> + u32 ctrl_offset;
> + u32 desc_offset;
> + dma_cookie_t completed_cookie;
> + dma_cookie_t cookie;
> + spinlock_t lock;
> + struct list_head pending_list;
> + struct xilinx_vdma_tx_descriptor *active_desc;
> + struct list_head done_list;
> + struct dma_chan common;
> + struct dma_pool *desc_pool;
> + struct device *dev;
> + int irq;
> + int id;
> + enum dma_transfer_direction direction;
why should channel have a direction... descriptor should have direction and not
the channel!
> +/**
> + * xilinx_vdma_free_tx_descriptor - Free transaction descriptor
> + * @chan: Driver specific VDMA channel
> + * @desc: VDMA transaction descriptor
> + */
> +static void
> +xilinx_vdma_free_tx_descriptor(struct xilinx_vdma_chan *chan,
> + struct xilinx_vdma_tx_descriptor *desc)
> +{
> + struct xilinx_vdma_tx_segment *segment, *next;
> +
> + if (!desc)
> + return;
> +
> + list_for_each_entry_safe(segment, next, &desc->segments, node) {
do you want to use _safe. Isee that this is called for cleanup while lock held,
and in other case within another _safe iterator!
> + list_del(&segment->node);
> + xilinx_vdma_free_tx_segment(chan, segment);
> + }
> +
> + kfree(desc);
> +}
> +
> +/* Required functions */
> +
> + * xilinx_vdma_do_tasklet - Schedule completion tasklet
> + * @data: Pointer to the Xilinx VDMA channel structure
> + */
> +static void xilinx_vdma_do_tasklet(unsigned long data)
> +{
> + struct xilinx_vdma_chan *chan = (struct xilinx_vdma_chan *)data;
> +
> + xilinx_vdma_chan_desc_cleanup(chan);
> +}
> +
> +/**
> + * xilinx_vdma_alloc_chan_resources - Allocate channel resources
> + * @dchan: DMA channel
> + *
> + * Return: '1' on success and failure value on error
naaah, we dont do that, pls use standard notation of 0 on success
Also API wants you to return descriptors allocated here!
> + */
> +static int xilinx_vdma_alloc_chan_resources(struct dma_chan *dchan)
> +{
> + struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
> +
> + /* Has this channel already been allocated? */
> + if (chan->desc_pool)
> + return 1;
> +
> + /*
> + * We need the descriptor to be aligned to 64bytes
> + * for meeting Xilinx VDMA specification requirement.
> + */
> + chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
> + chan->dev,
> + sizeof(struct xilinx_vdma_tx_segment),
> + __alignof__(struct xilinx_vdma_tx_segment), 0);
> + if (!chan->desc_pool) {
> + dev_err(chan->dev,
> + "unable to allocate channel %d descriptor pool\n",
> + chan->id);
> + return -ENOMEM;
> + }
> +
> + tasklet_init(&chan->tasklet, xilinx_vdma_do_tasklet,
> + (unsigned long)chan);
> +
> + chan->completed_cookie = DMA_MIN_COOKIE;
> + chan->cookie = DMA_MIN_COOKIE;
Can you use virtual dma implementation to simplfy your implemenattion of lists,
cookies (driver/dma/virt-dma.c)
> + /* There is at least one descriptor free to be allocated */
???
> + return 1;
> +}
> +
> + * xilinx_vdma_tx_status - Get VDMA transaction status
> + * @dchan: DMA channel
> + * @cookie: Transaction identifier
> + * @txstate: Transaction state
> + *
> + * Return: DMA transaction status
> + */
> +static enum dma_status xilinx_vdma_tx_status(struct dma_chan *dchan,
> + dma_cookie_t cookie,
> + struct dma_tx_state *txstate)
> +{
> + struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
> + dma_cookie_t last_used;
> + dma_cookie_t last_complete;
> +
> + xilinx_vdma_chan_desc_cleanup(chan);
> +
> + last_used = dchan->cookie;
> + last_complete = chan->completed_cookie;
> +
> + dma_set_tx_state(txstate, last_complete, last_used, 0);
> +
> + return dma_async_is_complete(cookie, last_complete, last_used);
no residue calculation?
> +}
> +
> + * xilinx_vdma_start - Start VDMA channel
> + * @chan: Driver specific VDMA channel
> + */
> +static void xilinx_vdma_start(struct xilinx_vdma_chan *chan)
> +{
> + int loop = XILINX_VDMA_LOOP_COUNT + 1;
> +
> + vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP);
> +
> + /* Wait for the hardware to start */
> + while (loop--)
> + if (!(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
> + XILINX_VDMA_DMASR_HALTED))
> + break;
wouldnt do while be better than doing than increamenting loop by 1 above and
using in while!
> +
> + if (!loop) {
> + dev_err(chan->dev, "Cannot start channel %p: %x\n",
> + chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
> +
> + chan->err = true;
> + }
> +
> + return;
> +}
> +
> +/**
> + * xilinx_vdma_prep_slave_sg - prepare a descriptor for a DMA_SLAVE transaction
> + * @dchan: DMA channel
> + * @sgl: scatterlist to transfer to/from
> + * @sg_len: number of entries in @sgl
> + * @dir: DMA direction
> + * @flags: transfer ack flags
> + * @context: unused
> + *
> + * Return: Async transaction descriptor on success and NULL on failure
> + */
> +static struct dma_async_tx_descriptor *
> +xilinx_vdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
> + unsigned int sg_len, enum dma_transfer_direction dir,
> + unsigned long flags, void *context)
okay now am worried, this is supposed to memcpy DMA so why slave-sg??
Looking at the driver overall, IMHO we need to do:
- use the virt-dma to simplfy the cookie handling and perhpasn the descrptors
too!
- Perhpas use interleaved API..?
- I dont think we should use the slave API as this seems memcpy case!
--
~Vinod
WARNING: multiple messages have this Message-ID (diff)
From: Vinod Koul <vinod.koul@intel.com>
To: Srikanth Thokala <sthokal@xilinx.com>
Cc: dan.j.williams@intel.com, michal.simek@xilinx.com,
grant.likely@linaro.org, robh+dt@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
dmaengine@vger.kernel.org
Subject: Re: [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
Date: Sun, 26 Jan 2014 19:54:36 +0530 [thread overview]
Message-ID: <20140126142436.GF10628@intel.com> (raw)
In-Reply-To: <1390409565-4200-2-git-send-email-sthokal@xilinx.com>
On Wed, Jan 22, 2014 at 10:22:45PM +0530, Srikanth Thokala wrote:
> This is the driver for the AXI Video Direct Memory Access (AXI
> VDMA) core, which is a soft Xilinx IP core that provides high-
> bandwidth direct memory access between memory and AXI4-Stream
> type video target peripherals. The core provides efficient two
> dimensional DMA operations with independent asynchronous read
ok here is tha catch, do you want to support interleaved API rather?
> +* DMA client + +Required properties: +- dmas: a list of <[Video DMA device
> phandle] [Channel ID]> pairs, + where Channel ID is '0' for write/tx and
> '1' for read/rx + channel. +- dma-names: a list of DMA channel names, one
> per "dmas" entry + +Example: +++++++++ + +vdmatest_0: vdmatest@0 { +
> compatible ="xlnx,axi-vdma-test-1.00.a"; + dmas = <&axi_vdma_0 0 +
> &axi_vdma_0 1>; + dma-names = "vdma0", "vdma1"; +} ;
Need ack from DT folks. ALso would be better to split the binding to a separate
patch
> +/**
> + * struct xilinx_vdma_chan - Driver specific VDMA channel structure
> + * @xdev: Driver specific device structure
> + * @ctrl_offset: Control registers offset
> + * @desc_offset: TX descriptor registers offset
> + * @completed_cookie: Maximum cookie completed
> + * @cookie: The current cookie
> + * @lock: Descriptor operation lock
> + * @pending_list: Descriptors waiting
> + * @active_desc: Active descriptor
> + * @done_list: Complete descriptors
> + * @common: DMA common channel
> + * @desc_pool: Descriptors pool
> + * @dev: The dma device
> + * @irq: Channel IRQ
> + * @id: Channel ID
> + * @direction: Transfer direction
> + * @num_frms: Number of frames
> + * @has_sg: Support scatter transfers
> + * @genlock: Support genlock mode
> + * @err: Channel has errors
> + * @tasklet: Cleanup work after irq
> + * @config: Device configuration info
> + * @flush_on_fsync: Flush on Frame sync
> + */
> +struct xilinx_vdma_chan {
> + struct xilinx_vdma_device *xdev;
> + u32 ctrl_offset;
> + u32 desc_offset;
> + dma_cookie_t completed_cookie;
> + dma_cookie_t cookie;
> + spinlock_t lock;
> + struct list_head pending_list;
> + struct xilinx_vdma_tx_descriptor *active_desc;
> + struct list_head done_list;
> + struct dma_chan common;
> + struct dma_pool *desc_pool;
> + struct device *dev;
> + int irq;
> + int id;
> + enum dma_transfer_direction direction;
why should channel have a direction... descriptor should have direction and not
the channel!
> +/**
> + * xilinx_vdma_free_tx_descriptor - Free transaction descriptor
> + * @chan: Driver specific VDMA channel
> + * @desc: VDMA transaction descriptor
> + */
> +static void
> +xilinx_vdma_free_tx_descriptor(struct xilinx_vdma_chan *chan,
> + struct xilinx_vdma_tx_descriptor *desc)
> +{
> + struct xilinx_vdma_tx_segment *segment, *next;
> +
> + if (!desc)
> + return;
> +
> + list_for_each_entry_safe(segment, next, &desc->segments, node) {
do you want to use _safe. Isee that this is called for cleanup while lock held,
and in other case within another _safe iterator!
> + list_del(&segment->node);
> + xilinx_vdma_free_tx_segment(chan, segment);
> + }
> +
> + kfree(desc);
> +}
> +
> +/* Required functions */
> +
> + * xilinx_vdma_do_tasklet - Schedule completion tasklet
> + * @data: Pointer to the Xilinx VDMA channel structure
> + */
> +static void xilinx_vdma_do_tasklet(unsigned long data)
> +{
> + struct xilinx_vdma_chan *chan = (struct xilinx_vdma_chan *)data;
> +
> + xilinx_vdma_chan_desc_cleanup(chan);
> +}
> +
> +/**
> + * xilinx_vdma_alloc_chan_resources - Allocate channel resources
> + * @dchan: DMA channel
> + *
> + * Return: '1' on success and failure value on error
naaah, we dont do that, pls use standard notation of 0 on success
Also API wants you to return descriptors allocated here!
> + */
> +static int xilinx_vdma_alloc_chan_resources(struct dma_chan *dchan)
> +{
> + struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
> +
> + /* Has this channel already been allocated? */
> + if (chan->desc_pool)
> + return 1;
> +
> + /*
> + * We need the descriptor to be aligned to 64bytes
> + * for meeting Xilinx VDMA specification requirement.
> + */
> + chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
> + chan->dev,
> + sizeof(struct xilinx_vdma_tx_segment),
> + __alignof__(struct xilinx_vdma_tx_segment), 0);
> + if (!chan->desc_pool) {
> + dev_err(chan->dev,
> + "unable to allocate channel %d descriptor pool\n",
> + chan->id);
> + return -ENOMEM;
> + }
> +
> + tasklet_init(&chan->tasklet, xilinx_vdma_do_tasklet,
> + (unsigned long)chan);
> +
> + chan->completed_cookie = DMA_MIN_COOKIE;
> + chan->cookie = DMA_MIN_COOKIE;
Can you use virtual dma implementation to simplfy your implemenattion of lists,
cookies (driver/dma/virt-dma.c)
> + /* There is at least one descriptor free to be allocated */
???
> + return 1;
> +}
> +
> + * xilinx_vdma_tx_status - Get VDMA transaction status
> + * @dchan: DMA channel
> + * @cookie: Transaction identifier
> + * @txstate: Transaction state
> + *
> + * Return: DMA transaction status
> + */
> +static enum dma_status xilinx_vdma_tx_status(struct dma_chan *dchan,
> + dma_cookie_t cookie,
> + struct dma_tx_state *txstate)
> +{
> + struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
> + dma_cookie_t last_used;
> + dma_cookie_t last_complete;
> +
> + xilinx_vdma_chan_desc_cleanup(chan);
> +
> + last_used = dchan->cookie;
> + last_complete = chan->completed_cookie;
> +
> + dma_set_tx_state(txstate, last_complete, last_used, 0);
> +
> + return dma_async_is_complete(cookie, last_complete, last_used);
no residue calculation?
> +}
> +
> + * xilinx_vdma_start - Start VDMA channel
> + * @chan: Driver specific VDMA channel
> + */
> +static void xilinx_vdma_start(struct xilinx_vdma_chan *chan)
> +{
> + int loop = XILINX_VDMA_LOOP_COUNT + 1;
> +
> + vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP);
> +
> + /* Wait for the hardware to start */
> + while (loop--)
> + if (!(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
> + XILINX_VDMA_DMASR_HALTED))
> + break;
wouldnt do while be better than doing than increamenting loop by 1 above and
using in while!
> +
> + if (!loop) {
> + dev_err(chan->dev, "Cannot start channel %p: %x\n",
> + chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
> +
> + chan->err = true;
> + }
> +
> + return;
> +}
> +
> +/**
> + * xilinx_vdma_prep_slave_sg - prepare a descriptor for a DMA_SLAVE transaction
> + * @dchan: DMA channel
> + * @sgl: scatterlist to transfer to/from
> + * @sg_len: number of entries in @sgl
> + * @dir: DMA direction
> + * @flags: transfer ack flags
> + * @context: unused
> + *
> + * Return: Async transaction descriptor on success and NULL on failure
> + */
> +static struct dma_async_tx_descriptor *
> +xilinx_vdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
> + unsigned int sg_len, enum dma_transfer_direction dir,
> + unsigned long flags, void *context)
okay now am worried, this is supposed to memcpy DMA so why slave-sg??
Looking at the driver overall, IMHO we need to do:
- use the virt-dma to simplfy the cookie handling and perhpasn the descrptors
too!
- Perhpas use interleaved API..?
- I dont think we should use the slave API as this seems memcpy case!
--
~Vinod
next prev parent reply other threads:[~2014-01-26 14:24 UTC|newest]
Thread overview: 90+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-22 16:52 [PATCH v2] Add Xilinx AXI Video DMA Engine driver Srikanth Thokala
2014-01-22 16:52 ` Srikanth Thokala
2014-01-22 16:52 ` Srikanth Thokala
2014-01-22 16:52 ` [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support Srikanth Thokala
2014-01-22 16:52 ` Srikanth Thokala
2014-01-22 21:30 ` Levente Kurusa
2014-01-22 21:30 ` Levente Kurusa
2014-01-22 21:30 ` Levente Kurusa
2014-01-23 17:35 ` Srikanth Thokala
2014-01-23 17:35 ` Srikanth Thokala
2014-01-23 17:35 ` Srikanth Thokala
2014-01-23 11:25 ` Lars-Peter Clausen
2014-01-23 11:25 ` Lars-Peter Clausen
2014-01-23 13:38 ` Shevchenko, Andriy
2014-01-23 13:38 ` Shevchenko, Andriy
2014-01-23 13:38 ` Shevchenko, Andriy
2014-01-23 13:50 ` Lars-Peter Clausen
2014-01-23 13:50 ` Lars-Peter Clausen
2014-01-23 13:50 ` Lars-Peter Clausen
2014-01-23 14:00 ` Andy Shevchenko
2014-01-23 14:00 ` Andy Shevchenko
2014-01-23 14:00 ` Andy Shevchenko
2014-01-23 14:07 ` Lars-Peter Clausen
2014-01-23 14:07 ` Lars-Peter Clausen
2014-01-23 14:07 ` Lars-Peter Clausen
2014-01-26 14:03 ` Vinod Koul
2014-01-26 14:03 ` Vinod Koul
2014-01-26 14:03 ` Vinod Koul
2014-01-26 17:41 ` Lars-Peter Clausen
2014-01-26 17:41 ` Lars-Peter Clausen
2014-01-24 11:16 ` Srikanth Thokala
2014-01-24 11:16 ` Srikanth Thokala
2014-01-24 13:24 ` Lars-Peter Clausen
2014-01-24 13:24 ` Lars-Peter Clausen
2014-01-24 13:24 ` Lars-Peter Clausen
2014-01-26 13:59 ` Vinod Koul
2014-01-26 13:59 ` Vinod Koul
2014-01-26 17:39 ` Lars-Peter Clausen
2014-01-26 17:39 ` Lars-Peter Clausen
2014-01-26 17:39 ` Lars-Peter Clausen
2014-01-27 13:12 ` Srikanth Thokala
2014-01-27 13:12 ` Srikanth Thokala
2014-01-28 3:13 ` Vinod Koul
2014-01-28 3:13 ` Vinod Koul
2014-01-31 6:51 ` Srikanth Thokala
2014-01-31 6:51 ` Srikanth Thokala
2014-01-31 6:51 ` Srikanth Thokala
2014-02-05 16:25 ` Srikanth Thokala
2014-02-05 16:25 ` Srikanth Thokala
2014-02-05 16:30 ` Lars-Peter Clausen
2014-02-05 16:30 ` Lars-Peter Clausen
2014-02-05 16:30 ` Lars-Peter Clausen
2014-02-06 13:34 ` Srikanth Thokala
2014-02-06 13:34 ` Srikanth Thokala
2014-02-06 13:34 ` Srikanth Thokala
2014-02-06 15:53 ` Lars-Peter Clausen
2014-02-06 15:53 ` Lars-Peter Clausen
2014-02-06 15:53 ` Lars-Peter Clausen
2014-02-10 12:51 ` Srikanth Thokala
2014-02-10 12:51 ` Srikanth Thokala
2014-01-28 3:09 ` Vinod Koul
2014-01-28 3:09 ` Vinod Koul
2014-01-28 3:09 ` Vinod Koul
2014-01-27 11:06 ` Srikanth Thokala
2014-01-27 11:06 ` Srikanth Thokala
2014-01-27 11:06 ` Srikanth Thokala
2014-01-31 6:52 ` Srikanth Thokala
2014-01-31 6:52 ` Srikanth Thokala
2014-01-31 6:52 ` Srikanth Thokala
2014-02-04 5:28 ` Vinod Koul
2014-02-04 5:28 ` Vinod Koul
2014-02-04 5:28 ` Vinod Koul
2014-02-04 10:35 ` Srikanth Thokala
2014-02-04 10:35 ` Srikanth Thokala
2014-02-04 10:35 ` Srikanth Thokala
2014-01-31 17:44 ` Andy Gross
2014-01-31 17:44 ` Andy Gross
2014-02-01 18:23 ` Lars-Peter Clausen
2014-02-01 18:23 ` Lars-Peter Clausen
2014-02-01 18:23 ` Lars-Peter Clausen
2014-01-23 13:32 ` Andy Shevchenko
2014-01-23 13:32 ` Andy Shevchenko
2014-01-23 17:52 ` Srikanth Thokala
2014-01-23 17:52 ` Srikanth Thokala
2014-01-23 17:52 ` Srikanth Thokala
2014-01-26 14:24 ` Vinod Koul [this message]
2014-01-26 14:24 ` Vinod Koul
2014-01-26 17:46 ` Lars-Peter Clausen
2014-01-26 17:46 ` Lars-Peter Clausen
2014-01-26 17:46 ` Lars-Peter Clausen
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=20140126142436.GF10628@intel.com \
--to=vinod.koul@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
/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.