From: Vinod Koul <vkoul@kernel.org>
To: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Cc: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org,
Eugeniy Paltsev <eugeniy.paltsev@synopsys.com>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Joao Pinto <joao.pinto@synopsys.com>
Subject: [RFC,1/6] dma: Add Synopsys eDMA IP core driver
Date: Mon, 17 Dec 2018 12:21:20 +0530 [thread overview]
Message-ID: <20181217065120.GH2472@vkoul-mobl> (raw)
On 12-12-18, 12:13, Gustavo Pimentel wrote:
> Add Synopsys eDMA IP core driver to kernel.
>
> This core driver, initializes and configures the eDMA IP using vma-helpers
> functions and dma-engine subsystem.
>
> Also creates an abstration layer through callbacks allowing different
> registers mappings in the future, organized in to versions.
>
> This driver can be compile as built-in or external module in kernel.
>
> To enable this driver just select DW_EDMA option in kernel configuration,
> however it requires and selects automatically DMA_ENGINE and
> DMA_VIRTUAL_CHANNELS option too.
The subsystem name is dmaengine: so please use that tag. If you are not
aware then git log for that subsystem helps you with the patterns
expected
I did a quick look at the patch, I have highlighted few concerns and
they repeat in similar code patterns in this patch
> +#include "dw-edma-core.h"
> +#include "../dmaengine.h"
> +#include "../virt-dma.h"
> +
> +#define DRV_CORE_NAME "dw-edma-core"
Why is this required?
> +
> +#define SET(reg, name, val) \
> + reg.name = val
> +
> +#define SET_BOTH_CH(name, value) \
> + do { \
> + SET(dw->wr_edma, name, value); \
> + SET(dw->rd_edma, name, value); \
> + } while (0)
I am not sure how this helps, makes things not explicit..
> +static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
> +{
> + struct dw_edma_chan *chan = chunk->chan;
> + struct dw_edma_burst *burst;
> +
> + burst = kzalloc(sizeof(struct dw_edma_burst), GFP_NOWAIT);
> + if (unlikely(!burst)) {
> + dev_err(chan2dev(chan), ": fail to alloc new burst\n");
no need to log mem alloc failures
> + return NULL;
> + }
> +
> + INIT_LIST_HEAD(&burst->list);
> + burst->sar = 0;
> + burst->dar = 0;
> + burst->sz = 0;
you did kzalloc right?
> +
> + if (chunk->burst) {
> + atomic_inc(&chunk->bursts_alloc);
why does this need atomic variables?
> +static void dw_edma_free_burst(struct dw_edma_chunk *chunk)
> +{
> + struct dw_edma_burst *child, *_next;
> +
> + if (!chunk->burst)
> + return;
> +
> + // Remove all the list elements
We dont use C99 style comments, please use
/* single line */
and
/*
* multi
* line
*/
> +static void start_transfer(struct dw_edma_chan *chan)
> +{
> + struct virt_dma_desc *vd;
> + struct dw_edma_desc *desc;
> + struct dw_edma_chunk *child, *_next;
> + const struct dw_edma_core_ops *ops = chan2ops(chan);
> +
> + vd = vchan_next_desc(&chan->vc);
> + if (!vd)
> + return;
> +
> + desc = vd2dw_edma_desc(vd);
> + if (!desc)
> + return;
> +
> + list_for_each_entry_safe(child, _next, &desc->chunk->list, list) {
> + ops->start(child, !desc->xfer_sz);
> + desc->xfer_sz += child->sz;
> + dev_dbg(chan2dev(chan),
> + ": transfer of %u bytes started\n", child->sz);
> +
> + dw_edma_free_burst(child);
> + if (atomic_read(&child->bursts_alloc))
> + dev_dbg(chan2dev(chan),
> + ": %d bursts still allocated\n",
> + atomic_read(&child->bursts_alloc));
> + list_del(&child->list);
> + kfree(child);
> + atomic_dec(&desc->chunks_alloc);
> +
> + return;
> + }
> +}
> +
> +static int dw_edma_device_config(struct dma_chan *dchan,
> + struct dma_slave_config *config)
please align to preceding brace. Also running checkpatch with --strict
option helps, warning checkpatch is a guidebook and not a rule book!
> +{
> + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
> + const struct dw_edma_core_ops *ops = chan2ops(chan);
> + enum dma_transfer_direction dir;
> + unsigned long flags;
> + int err = 0;
> +
> + spin_lock_irqsave(&chan->vc.lock, flags);
> +
> + if (!config) {
> + err = -EINVAL;
> + goto err_config;
> + }
> +
> + if (chan->configured) {
> + dev_err(chan2dev(chan), ": channel already configured\n");
> + err = -EPERM;
> + goto err_config;
> + }
> +
> + dir = config->direction;
Direction is depreciated, I have already removed the usages, so please
do not add new ones.
You need to take direction for respective prep_ calls
> + if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE) {
> + dev_info(chan2dev(chan),
> + ": direction DMA_DEV_TO_MEM (EDMA_DIR_WRITE)\n");
> + chan->p_addr = config->src_addr;
> + } else if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ) {
> + dev_info(chan2dev(chan),
> + ": direction DMA_MEM_TO_DEV (EDMA_DIR_READ)\n");
> + chan->p_addr = config->dst_addr;
> + } else {
> + dev_err(chan2dev(chan), ": invalid direction\n");
> + err = -EINVAL;
> + goto err_config;
> + }
This should be removed
> +
> + dev_info(chan2dev(chan),
> + ": src_addr(physical) = 0x%.16x\n", config->src_addr);
> + dev_info(chan2dev(chan),
> + ": dst_addr(physical) = 0x%.16x\n", config->dst_addr);
You have too many logs, it is good for bringup and initial work but not
suited for production.
> +
> + err = ops->device_config(dchan);
okay what does this callback do. You are already under and dmaengine fwk
so what is the need to add one more abstraction layer, can you explain
that in details please
> +static int dw_edma_device_pause(struct dma_chan *dchan)
> +{
> + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
> + unsigned long flags;
> + int err = 0;
> +
> + spin_lock_irqsave(&chan->vc.lock, flags);
> +
> + if (!chan->configured) {
> + dev_err(dchan2dev(dchan), ": channel not configured\n");
> + err = -EPERM;
> + goto err_pause;
> + }
> +
> + switch (chan->status) {
> + case EDMA_ST_IDLE:
> + dev_err(dchan2dev(dchan), ": channel is idle\n");
> + err = -EPERM;
> + goto err_pause;
> + case EDMA_ST_PAUSE:
> + dev_err(dchan2dev(dchan), ": channel is already paused\n");
> + err = -EPERM;
> + goto err_pause;
> + case EDMA_ST_BUSY:
> + // Only acceptable state
> + break;
Doesn't it look as overkill to use switch for single acceptable case.
Why not do
if (chan->status != EDMA_ST_BUSY) {
err = -EPERM;
...
}
> + default:
> + dev_err(dchan2dev(dchan), ": invalid status state\n");
> + err = -EINVAL;
> + goto err_pause;
> + }
> +
> + switch (chan->request) {
what is the need to track channel status and channel requests?
next reply other threads:[~2018-12-17 6:51 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-17 6:51 Vinod Koul [this message]
-- strict thread matches above, loose matches on Subject: below --
2019-01-03 14:53 [RFC,1/6] dma: Add Synopsys eDMA IP core driver Vinod Koul
2019-01-03 12:55 Gustavo Pimentel
2019-01-03 12:45 Vinod Koul
2019-01-03 9:53 Gustavo Pimentel
2018-12-18 10:58 Gustavo Pimentel
2018-12-18 3:54 Vinod Koul
2018-12-17 15:56 Gustavo Pimentel
2018-12-17 7:23 Vinod Koul
2018-12-13 11:03 Gustavo Pimentel
2018-12-12 23:00 Bjorn Helgaas
2018-12-12 11:13 Gustavo Pimentel
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=20181217065120.GH2472@vkoul-mobl \
--to=vkoul@kernel.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=dmaengine@vger.kernel.org \
--cc=eugeniy.paltsev@synopsys.com \
--cc=gustavo.pimentel@synopsys.com \
--cc=joao.pinto@synopsys.com \
--cc=linux-pci@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox