From: Dmitry Osipenko <digetx@gmail.com>
To: Vinod Koul <vinod.koul@intel.com>
Cc: Thierry Reding <thierry.reding@gmail.com>,
Jonathan Hunter <jonathanh@nvidia.com>,
Laxman Dewangan <ldewangan@nvidia.com>,
Peter De Schrijver <pdeschrijver@nvidia.com>,
Prashant Gaikwad <pgaikwad@nvidia.com>,
Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@codeaurora.org>,
Rob Herring <robh+dt@kernel.org>,
linux-tegra@vger.kernel.org, devicetree@vger.kernel.org,
dmaengine@vger.kernel.org, linux-clk@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v1 4/5] dmaengine: Add driver for NVIDIA Tegra AHB DMA controller
Date: Thu, 28 Sep 2017 15:17:52 +0300 [thread overview]
Message-ID: <8893ef75-a4c0-e918-a1f2-f374f318f9e0@gmail.com> (raw)
In-Reply-To: <20170928092949.GB30097@localhost>
On 28.09.2017 12:29, Vinod Koul wrote:
> On Tue, Sep 26, 2017 at 02:22:05AM +0300, Dmitry Osipenko wrote:
>
>> +config TEGRA20_AHB_DMA
>> + tristate "NVIDIA Tegra20 AHB DMA support"
>> + depends on ARCH_TEGRA
>
> Can we add COMPILE_TEST, helps me compile drivers
>
Good point.
>> +#include <linux/clk.h>
>> +#include <linux/delay.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_dma.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset.h>
>> +#include <linux/slab.h>
>> +#include <linux/spinlock.h>
>
> no vchan.h, so i presume we are not using that here, any reason why?
>
Jon Hunter asked the same question, I already reworked driver to use the
virt-dma. Turned out it is a really neat helper, -100 lines of driver code.
>> +
>> +#include "dmaengine.h"
>> +
>> +#define TEGRA_AHBDMA_CMD 0x0
>> +#define TEGRA_AHBDMA_CMD_ENABLE BIT(31)
>> +
>> +#define TEGRA_AHBDMA_IRQ_ENB_MASK 0x20
>> +#define TEGRA_AHBDMA_IRQ_ENB_CH(ch) BIT(ch)
>> +
>> +#define TEGRA_AHBDMA_CHANNEL_BASE(ch) (0x1000 + (ch) * 0x20)
>> +
>> +#define TEGRA_AHBDMA_CHANNEL_CSR 0x0
>> +#define TEGRA_AHBDMA_CHANNEL_ADDR_WRAP BIT(18)
>> +#define TEGRA_AHBDMA_CHANNEL_FLOW BIT(24)
>> +#define TEGRA_AHBDMA_CHANNEL_ONCE BIT(26)
>> +#define TEGRA_AHBDMA_CHANNEL_DIR_TO_XMB BIT(27)
>> +#define TEGRA_AHBDMA_CHANNEL_IE_EOC BIT(30)
>> +#define TEGRA_AHBDMA_CHANNEL_ENABLE BIT(31)
>> +#define TEGRA_AHBDMA_CHANNEL_REQ_SEL_SHIFT 16
>> +#define TEGRA_AHBDMA_CHANNEL_WCOUNT_MASK 0xFFFC
>
> GENMASK() ?
>
Okay.
>> +static void tegra_ahbdma_tasklet(unsigned long data)
>> +{
>> + struct tegra_ahbdma_tx_desc *tx = (struct tegra_ahbdma_tx_desc *)data;
>> + struct dma_async_tx_descriptor *desc = &tx->desc;
>> +
>> + dmaengine_desc_get_callback_invoke(desc, NULL);
>> +
>> + if (!tx->cyclic && !dmaengine_desc_test_reuse(desc))
>> + kfree(tx);
>
> lot of code here can be reduced if we use vchan
>
+1
>> +static struct dma_async_tx_descriptor *tegra_ahbdma_prep_dma_cyclic(
>> + struct dma_chan *chan,
>> + dma_addr_t buf_addr,
>> + size_t buf_len,
>> + size_t period_len,
>> + enum dma_transfer_direction dir,
>> + unsigned long flags)
>> +{
>> + struct tegra_ahbdma_tx_desc *tx;
>> +
>> + /* unimplemented */
>> + if (buf_len != period_len || buf_len > SZ_64K)
>> + return NULL;
>> +
>> + tx = kzalloc(sizeof(*tx), GFP_KERNEL);
>> + if (!tx)
>> + return NULL;
>> +
>> + dma_async_tx_descriptor_init(&tx->desc, chan);
>> +
>> + tx->desc.tx_submit = tegra_ahbdma_tx_submit;
>> + tx->mem_paddr = buf_addr;
>> + tx->size = buf_len;
>> + tx->flags = flags;
>> + tx->cyclic = true;
>> + tx->dir = dir;
>> +
>> + tasklet_init(&tx->tasklet, tegra_ahbdma_tasklet, (unsigned long)tx);
>
> why not precalulcate the register settings here. While submitting you are in
> hot path keeping dmaengine idle so faster you can submit, better the perf
>
I may argue that the perf impact isn't measurable, but I agree that
precalculated register value would be a bit cleaner. Thanks for the suggestion.
>> +static void tegra_ahbdma_issue_pending(struct dma_chan *chan)
>> +{
>> + struct tegra_ahbdma_chan *ahbdma_chan = to_ahbdma_chan(chan);
>> + struct tegra_ahbdma_tx_desc *tx;
>> + struct list_head *entry, *tmp;
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&ahbdma_chan->lock, flags);
>> +
>> + list_for_each_safe(entry, tmp, &ahbdma_chan->pending_list)
>> + list_move_tail(entry, &ahbdma_chan->active_list);
>> +
>> + if (completion_done(&ahbdma_chan->idling)) {
>> + tx = list_first_entry_or_null(&ahbdma_chan->active_list,
>> + struct tegra_ahbdma_tx_desc,
>> + node);
>> + if (tx) {
>> + tegra_ahbdma_submit_tx(ahbdma_chan, tx);
>
> what is chan is already running?
>
It can't run here, we just checked whether it is idling. That would be a HW bug.
>> + reinit_completion(&ahbdma_chan->idling);
>> + }
>> + }
>> +
>> + spin_unlock_irqrestore(&ahbdma_chan->lock, flags);
>> +}
>> +
>> +static enum dma_status tegra_ahbdma_tx_status(struct dma_chan *chan,
>> + dma_cookie_t cookie,
>> + struct dma_tx_state *state)
>> +{
>> + struct tegra_ahbdma_chan *ahbdma_chan = to_ahbdma_chan(chan);
>> + struct tegra_ahbdma_tx_desc *tx;
>> + enum dma_status cookie_status;
>> + unsigned long flags;
>> + size_t residual;
>> + u32 status;
>> +
>> + spin_lock_irqsave(&ahbdma_chan->lock, flags);
>> +
>> + cookie_status = dma_cookie_status(chan, cookie, state);
>> + if (cookie_status != DMA_COMPLETE) {
>
> residue can be NULL so check it before proceeding ahead
>
Yeah, I noticed it too and fixed it in the upcoming V2 yesterday.
>> +static int tegra_ahbdma_config(struct dma_chan *chan,
>> + struct dma_slave_config *sconfig)
>> +{
>> + struct tegra_ahbdma_chan *ahbdma_chan = to_ahbdma_chan(chan);
>> + enum dma_transfer_direction dir = sconfig->direction;
>> + u32 burst, ahb_seq, ahb_addr;
>> +
>> + if (sconfig->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
>> + sconfig->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
>> + return -EINVAL;
>> +
>> + if (dir == DMA_DEV_TO_MEM) {
>> + burst = sconfig->src_maxburst;
>> + ahb_addr = sconfig->src_addr;
>> + } else {
>> + burst = sconfig->dst_maxburst;
>> + ahb_addr = sconfig->dst_addr;
>> + }
>> +
>> + switch (burst) {
>> + case 1: burst = TEGRA_AHBDMA_CHANNEL_AHB_BURST_1; break;
>> + case 4: burst = TEGRA_AHBDMA_CHANNEL_AHB_BURST_4; break;
>> + case 8: burst = TEGRA_AHBDMA_CHANNEL_AHB_BURST_8; break;
>
> pls make this statement and break on subsequent lines, readablity matters
>
Okay.
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + ahb_seq = burst << TEGRA_AHBDMA_CHANNEL_AHB_BURST_SHIFT;
>> + ahb_seq |= TEGRA_AHBDMA_CHANNEL_ADDR_WRAP;
>> + ahb_seq |= TEGRA_AHBDMA_CHANNEL_INTR_ENB;
>> +
>> + writel_relaxed(ahb_seq,
>> + ahbdma_chan->regs + TEGRA_AHBDMA_CHANNEL_AHB_SEQ);
>> +
>> + writel_relaxed(ahb_addr,
>> + ahbdma_chan->regs + TEGRA_AHBDMA_CHANNEL_AHB_PTR);
>
> oh no, you don't write to HW here. This can be called anytime when you have
> txn running! You should save these and use them in prep_ calls.
>
Okay.
>> +static int tegra_ahbdma_remove(struct platform_device *pdev)
>> +{
>> + struct tegra_ahbdma *tdma = platform_get_drvdata(pdev);
>> +
>> + of_dma_controller_free(pdev->dev.of_node);
>> + dma_async_device_unregister(&tdma->dma_dev);
>> + clk_disable_unprepare(tdma->clk);
>
> not ensuring tasklets are killed and irq is freed so no more tasklets can
> run? I think that needs to be done...
>
Already fixed in V2 by using vchan_synchronize() that kills tasklet in
tegra_ahbdma_synchronize(). DMA core invokes synchronization upon channels
resource freeing.
>> +MODULE_DESCRIPTION("NVIDIA Tegra AHB DMA Controller driver");
>> +MODULE_AUTHOR("Dmitry Osipenko <digetx@gmail.com>");
>> +MODULE_LICENSE("GPL");
>
> MODULE_ALIAS?
>
Not needed, driver is "OF-only". It's default alias is "tegra20-ahb-dma".
--
Dmitry
next prev parent reply other threads:[~2017-09-28 12:18 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-25 23:22 [PATCH v1 0/5] NVIDIA Tegra AHB DMA controller driver Dmitry Osipenko
2017-09-25 23:22 ` [PATCH v1 1/5] clk: tegra: Add AHB DMA clock entry Dmitry Osipenko
2017-09-26 9:56 ` Peter De Schrijver
2017-09-26 14:46 ` Dmitry Osipenko
2017-09-27 8:36 ` Peter De Schrijver
2017-09-27 9:41 ` Dmitry Osipenko
2017-09-25 23:22 ` [PATCH v1 2/5] clk: tegra: Bump SCLK clock rate to 216MHz on Tegra20 Dmitry Osipenko
2017-09-26 10:01 ` Peter De Schrijver
2017-09-25 23:22 ` [PATCH v1 3/5] dt-bindings: Add DT bindings for NVIDIA Tegra AHB DMA controller Dmitry Osipenko
2017-09-26 14:50 ` Jon Hunter
2017-09-26 15:16 ` Dmitry Osipenko
2017-09-27 1:57 ` Dmitry Osipenko
2017-09-27 8:34 ` Jon Hunter
2017-09-27 12:12 ` Dmitry Osipenko
2017-09-27 13:44 ` Jon Hunter
2017-09-27 13:46 ` Jon Hunter
2017-09-27 14:29 ` Dmitry Osipenko
2017-09-27 23:32 ` Stephen Boyd
2017-09-28 8:33 ` Jon Hunter
2017-09-29 19:30 ` Stephen Warren
2017-09-30 3:11 ` Dmitry Osipenko
2017-10-02 17:05 ` Stephen Warren
2017-10-02 23:02 ` Dmitry Osipenko
2017-10-03 10:32 ` Jon Hunter
2017-10-03 12:07 ` Dmitry Osipenko
2017-10-03 12:19 ` Jon Hunter
2017-10-03 15:38 ` Stephen Warren
2017-10-03 17:04 ` Dmitry Osipenko
2017-10-05 20:33 ` Rob Herring
2017-10-05 21:30 ` Dmitry Osipenko
2017-09-25 23:22 ` [PATCH v1 4/5] dmaengine: Add driver " Dmitry Osipenko
2017-09-26 14:45 ` Jon Hunter
2017-09-26 16:06 ` Dmitry Osipenko
2017-09-26 21:37 ` Jon Hunter
2017-09-26 23:00 ` Dmitry Osipenko
2017-09-28 9:29 ` Vinod Koul
2017-09-28 12:17 ` Dmitry Osipenko [this message]
2017-09-28 14:06 ` Dmitry Osipenko
2017-09-28 14:35 ` Dmitry Osipenko
2017-09-28 16:22 ` Vinod Koul
2017-09-28 16:37 ` Dmitry Osipenko
2017-09-28 16:21 ` Vinod Koul
2017-09-25 23:22 ` [PATCH v1 5/5] ARM: dts: tegra: Add AHB DMA controller nodes Dmitry Osipenko
2017-09-28 9:31 ` [PATCH v1 0/5] NVIDIA Tegra AHB DMA controller driver Vinod Koul
2017-09-28 12:24 ` Dmitry Osipenko
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=8893ef75-a4c0-e918-a1f2-f374f318f9e0@gmail.com \
--to=digetx@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=jonathanh@nvidia.com \
--cc=ldewangan@nvidia.com \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=mturquette@baylibre.com \
--cc=pdeschrijver@nvidia.com \
--cc=pgaikwad@nvidia.com \
--cc=robh+dt@kernel.org \
--cc=sboyd@codeaurora.org \
--cc=thierry.reding@gmail.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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®