From: Russell King - ARM Linux <linux@arm.linux.org.uk> To: Kukjin Kim <kgene.kim@samsung.com> Cc: linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, Mark Brown <broonie@opensource.wolfsonmicro.com>, Boojin Kim <boojin.kim@samsung.com>, Vinod Koul <vinod.koul@intel.com>, Linus Walleij <linus.walleij@linaro.org>, Jassi Brar <jassisinghbrar@gmail.com>, Grant Likely <grant.likely@secretlab.ca>, Dan Williams <dan.j.williams@intel.com>, Liam Girdwood <lrg@ti.com> Subject: Re: [PATCH V2 03/12] DMA: PL330: Add DMA capabilities Date: Wed, 13 Jul 2011 10:14:03 +0100 [thread overview] Message-ID: <20110713091403.GI23270@n2100.arm.linux.org.uk> (raw) In-Reply-To: <1310546857-6304-4-git-send-email-kgene.kim@samsung.com> On Wed, Jul 13, 2011 at 05:47:28PM +0900, Kukjin Kim wrote: > +static void pl330_tasklet_cyclic(unsigned long data) > +{ > + struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; > + struct dma_pl330_desc *desc, *_dt; > + unsigned long flags; > + LIST_HEAD(list); > + > + spin_lock_irqsave(&pch->lock, flags); > + > + /* Pick up ripe tomatoes */ > + list_for_each_entry_safe(desc, _dt, &pch->work_list, node) > + if ((desc->status == DONE) && desc->cyclic) { > + dma_async_tx_callback callback; > + > + list_move_tail(&desc->node, &pch->work_list); > + pch->completed = desc->txd.cookie; > + > + desc->status = PREP; > + > + /* Try to submit a req imm. > + next to the last completed cookie */ > + fill_queue(pch); > + > + /* Make sure the PL330 Channel thread is active */ > + pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START); > + > + callback = desc->txd.callback; > + if (callback) > + callback(desc->txd.callback_param); How does this work when callbacks are allowed to queue new requests? Aren't you going to deadlock on the spinlock? I don't see 'list' being used in this function either. > + > + } > + > + spin_unlock_irqrestore(&pch->lock, flags); > +} > + > +static void pl330_cyclic_free(struct dma_pl330_chan *pch) > +{ > + struct dma_pl330_dmac *pdmac = pch->dmac; > + struct dma_pl330_desc *desc, *_dt; > + unsigned long flags; > + LIST_HEAD(list); > + > + spin_lock_irqsave(&pdmac->pool_lock, flags); > + > + list_for_each_entry_safe(desc, _dt, &pch->work_list, node) > + if (desc->cyclic) > + list_move_tail(&desc->node, &list); > + > + list_splice_tail_init(&list, &pdmac->desc_pool); As you're not using 'list' after this point, would 'list_splice_tail' do here? > + > + spin_unlock_irqrestore(&pdmac->pool_lock, flags); > + pch->cyclic_task = NULL; > +} > + > static void pl330_tasklet(unsigned long data) > { > struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; > @@ -227,6 +285,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) > > spin_unlock_irqrestore(&pch->lock, flags); > > + if (pch->cyclic_task) > + tasklet_schedule(pch->cyclic_task); > + else > tasklet_schedule(&pch->task); This 'tasklet_schedule' wants to be indented. > } > > @@ -256,25 +317,58 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) > static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) > { > struct dma_pl330_chan *pch = to_pchan(chan); > - struct dma_pl330_desc *desc; > + struct dma_pl330_desc *desc, *_dt; > unsigned long flags; > + struct dma_pl330_dmac *pdmac = pch->dmac; > + struct dma_slave_config *slave_config; > + struct dma_pl330_peri *peri; > + int i; > + LIST_HEAD(list); > > - /* Only supports DMA_TERMINATE_ALL */ > - if (cmd != DMA_TERMINATE_ALL) > - return -ENXIO; > - > - spin_lock_irqsave(&pch->lock, flags); > - > - /* FLUSH the PL330 Channel thread */ > - pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); > + switch (cmd) { > + case DMA_TERMINATE_ALL: > + spin_lock_irqsave(&pch->lock, flags); > > - /* Mark all desc done */ > - list_for_each_entry(desc, &pch->work_list, node) > - desc->status = DONE; > + /* FLUSH the PL330 Channel thread */ > + pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); > > - spin_unlock_irqrestore(&pch->lock, flags); > + /* Mark all desc done */ > + list_for_each_entry_safe(desc, _dt, &pch->work_list , node) { > + desc->status = DONE; > + pch->completed = desc->txd.cookie; > + list_move_tail(&desc->node, &list); > + } > > - pl330_tasklet((unsigned long) pch); > + list_splice_tail_init(&list, &pdmac->desc_pool); Again, would list_splice_tail() do here? > + spin_unlock_irqrestore(&pch->lock, flags); > + break; > + case DMA_SLAVE_CONFIG: > + slave_config = (struct dma_slave_config *)arg; > + peri = pch->chan.private; > + > + if (slave_config->direction == DMA_TO_DEVICE) { > + if (slave_config->dst_addr) > + peri->fifo_addr = slave_config->dst_addr; > + if (slave_config->dst_addr_width) { > + i = 0; > + while (slave_config->dst_addr_width != (1 << i)) > + i++; > + peri->burst_sz = i; > + } > + } else if (slave_config->direction == DMA_FROM_DEVICE) { > + if (slave_config->src_addr) > + peri->fifo_addr = slave_config->src_addr; > + if (slave_config->src_addr_width) { > + i = 0; > + while (slave_config->src_addr_width != (1 << i)) > + i++; > + peri->burst_sz = i; > + } > + } It would make more sense to store the M2P and P2M address/width/burst size separately, so you don't have to make DMA_SLAVE_CONFIG calls before every transfer.
WARNING: multiple messages have this Message-ID (diff)
From: linux@arm.linux.org.uk (Russell King - ARM Linux) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH V2 03/12] DMA: PL330: Add DMA capabilities Date: Wed, 13 Jul 2011 10:14:03 +0100 [thread overview] Message-ID: <20110713091403.GI23270@n2100.arm.linux.org.uk> (raw) In-Reply-To: <1310546857-6304-4-git-send-email-kgene.kim@samsung.com> On Wed, Jul 13, 2011 at 05:47:28PM +0900, Kukjin Kim wrote: > +static void pl330_tasklet_cyclic(unsigned long data) > +{ > + struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; > + struct dma_pl330_desc *desc, *_dt; > + unsigned long flags; > + LIST_HEAD(list); > + > + spin_lock_irqsave(&pch->lock, flags); > + > + /* Pick up ripe tomatoes */ > + list_for_each_entry_safe(desc, _dt, &pch->work_list, node) > + if ((desc->status == DONE) && desc->cyclic) { > + dma_async_tx_callback callback; > + > + list_move_tail(&desc->node, &pch->work_list); > + pch->completed = desc->txd.cookie; > + > + desc->status = PREP; > + > + /* Try to submit a req imm. > + next to the last completed cookie */ > + fill_queue(pch); > + > + /* Make sure the PL330 Channel thread is active */ > + pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START); > + > + callback = desc->txd.callback; > + if (callback) > + callback(desc->txd.callback_param); How does this work when callbacks are allowed to queue new requests? Aren't you going to deadlock on the spinlock? I don't see 'list' being used in this function either. > + > + } > + > + spin_unlock_irqrestore(&pch->lock, flags); > +} > + > +static void pl330_cyclic_free(struct dma_pl330_chan *pch) > +{ > + struct dma_pl330_dmac *pdmac = pch->dmac; > + struct dma_pl330_desc *desc, *_dt; > + unsigned long flags; > + LIST_HEAD(list); > + > + spin_lock_irqsave(&pdmac->pool_lock, flags); > + > + list_for_each_entry_safe(desc, _dt, &pch->work_list, node) > + if (desc->cyclic) > + list_move_tail(&desc->node, &list); > + > + list_splice_tail_init(&list, &pdmac->desc_pool); As you're not using 'list' after this point, would 'list_splice_tail' do here? > + > + spin_unlock_irqrestore(&pdmac->pool_lock, flags); > + pch->cyclic_task = NULL; > +} > + > static void pl330_tasklet(unsigned long data) > { > struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; > @@ -227,6 +285,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) > > spin_unlock_irqrestore(&pch->lock, flags); > > + if (pch->cyclic_task) > + tasklet_schedule(pch->cyclic_task); > + else > tasklet_schedule(&pch->task); This 'tasklet_schedule' wants to be indented. > } > > @@ -256,25 +317,58 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan) > static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) > { > struct dma_pl330_chan *pch = to_pchan(chan); > - struct dma_pl330_desc *desc; > + struct dma_pl330_desc *desc, *_dt; > unsigned long flags; > + struct dma_pl330_dmac *pdmac = pch->dmac; > + struct dma_slave_config *slave_config; > + struct dma_pl330_peri *peri; > + int i; > + LIST_HEAD(list); > > - /* Only supports DMA_TERMINATE_ALL */ > - if (cmd != DMA_TERMINATE_ALL) > - return -ENXIO; > - > - spin_lock_irqsave(&pch->lock, flags); > - > - /* FLUSH the PL330 Channel thread */ > - pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); > + switch (cmd) { > + case DMA_TERMINATE_ALL: > + spin_lock_irqsave(&pch->lock, flags); > > - /* Mark all desc done */ > - list_for_each_entry(desc, &pch->work_list, node) > - desc->status = DONE; > + /* FLUSH the PL330 Channel thread */ > + pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); > > - spin_unlock_irqrestore(&pch->lock, flags); > + /* Mark all desc done */ > + list_for_each_entry_safe(desc, _dt, &pch->work_list , node) { > + desc->status = DONE; > + pch->completed = desc->txd.cookie; > + list_move_tail(&desc->node, &list); > + } > > - pl330_tasklet((unsigned long) pch); > + list_splice_tail_init(&list, &pdmac->desc_pool); Again, would list_splice_tail() do here? > + spin_unlock_irqrestore(&pch->lock, flags); > + break; > + case DMA_SLAVE_CONFIG: > + slave_config = (struct dma_slave_config *)arg; > + peri = pch->chan.private; > + > + if (slave_config->direction == DMA_TO_DEVICE) { > + if (slave_config->dst_addr) > + peri->fifo_addr = slave_config->dst_addr; > + if (slave_config->dst_addr_width) { > + i = 0; > + while (slave_config->dst_addr_width != (1 << i)) > + i++; > + peri->burst_sz = i; > + } > + } else if (slave_config->direction == DMA_FROM_DEVICE) { > + if (slave_config->src_addr) > + peri->fifo_addr = slave_config->src_addr; > + if (slave_config->src_addr_width) { > + i = 0; > + while (slave_config->src_addr_width != (1 << i)) > + i++; > + peri->burst_sz = i; > + } > + } It would make more sense to store the M2P and P2M address/width/burst size separately, so you don't have to make DMA_SLAVE_CONFIG calls before every transfer.
next prev parent reply other threads:[~2011-07-13 9:14 UTC|newest] Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top 2011-07-13 8:47 [PATCH V2 00/12] To use DMA generic APIs for Samsung DMA Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 01/12] DMA: PL330: Add support runtime PM for PL330 DMAC Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 9:07 ` Russell King - ARM Linux 2011-07-13 9:07 ` Russell King - ARM Linux 2011-07-13 8:47 ` [PATCH V2 02/12] DMA: PL330: Update PL330 DMA API driver Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 03/12] DMA: PL330: Add DMA capabilities Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 9:14 ` Russell King - ARM Linux [this message] 2011-07-13 9:14 ` Russell King - ARM Linux 2011-07-13 11:04 ` boojin 2011-07-13 11:04 ` boojin 2011-07-15 4:45 ` Chanho Park 2011-07-15 4:45 ` Chanho Park 2011-07-16 1:11 ` Boojin Kim 2011-07-16 1:11 ` Boojin Kim 2011-07-13 8:47 ` [PATCH V2 04/12] ARM: SAMSUNG: Update to use PL330-DMA driver Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 05/12] ARM: SAMSUNG: Add common DMA operations Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-15 2:53 ` Grant Likely 2011-07-15 2:53 ` Grant Likely 2011-07-16 0:39 ` Boojin Kim 2011-07-16 0:39 ` Boojin Kim 2011-07-16 0:50 ` Grant Likely 2011-07-16 0:50 ` Grant Likely 2011-07-13 8:47 ` [PATCH V2 06/12] ARM: EXYNOS4: Use generic DMA PL330 driver Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 07/12] ARM: S5PV210: " Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 08/12] ARM: S5PC100: " Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 09/12] ARM: S5P64X0: " Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 10/12] ARM: SAMSUNG: Remove S3C-PL330-DMA driver Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 11/12] spi/s3c64xx: Add support DMA engine API Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 8:47 ` [PATCH V2 12/12] ASoC: Samsung: Update DMA interface Kukjin Kim 2011-07-13 8:47 ` Kukjin Kim 2011-07-13 23:57 ` Mark Brown 2011-07-13 23:57 ` Mark Brown 2011-07-16 0:01 ` Kukjin Kim 2011-07-16 0:01 ` Kukjin Kim
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=20110713091403.GI23270@n2100.arm.linux.org.uk \ --to=linux@arm.linux.org.uk \ --cc=boojin.kim@samsung.com \ --cc=broonie@opensource.wolfsonmicro.com \ --cc=dan.j.williams@intel.com \ --cc=grant.likely@secretlab.ca \ --cc=jassisinghbrar@gmail.com \ --cc=kgene.kim@samsung.com \ --cc=linus.walleij@linaro.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-samsung-soc@vger.kernel.org \ --cc=lrg@ti.com \ --cc=vinod.koul@intel.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: linkBe 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.