devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
To: Vinod Koul <vkoul@kernel.org>
Cc: <robh+dt@kernel.org>, <nm@ti.com>, <ssantosh@kernel.org>,
	<dan.j.williams@intel.com>, <dmaengine@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<grygorii.strashko@ti.com>, <lokeshvutla@ti.com>,
	<t-kristo@ti.com>, <tony@atomide.com>, <j-keerthy@ti.com>,
	<vigneshr@ti.com>
Subject: Re: [PATCH v7 09/12] dmaengine: ti: New driver for K3 UDMA
Date: Mon, 23 Dec 2019 10:59:06 +0200	[thread overview]
Message-ID: <ea473fed-276f-6b71-070b-02ab1f51ed89@ti.com> (raw)
In-Reply-To: <20191223073425.GV2536@vkoul-mobl>



On 23/12/2019 9.34, Vinod Koul wrote:
> On 09-12-19, 11:43, Peter Ujfalusi wrote:
> 
>> +#include <linux/kernel.h>
>> +#include <linux/dmaengine.h>
>> +#include <linux/dma-mapping.h>
>> +#include <linux/dmapool.h>
>> +#include <linux/err.h>
>> +#include <linux/init.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/list.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/of.h>
>> +#include <linux/of_dma.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_irq.h>
> 
> to many of headers, do we need all!

I'll try to cut them back.

>> +static char *udma_get_dir_text(enum dma_transfer_direction dir)
>> +{
>> +	switch (dir) {
>> +	case DMA_DEV_TO_MEM:
>> +		return "DEV_TO_MEM";
>> +	case DMA_MEM_TO_DEV:
>> +		return "MEM_TO_DEV";
>> +	case DMA_MEM_TO_MEM:
>> +		return "MEM_TO_MEM";
>> +	case DMA_DEV_TO_DEV:
>> +		return "DEV_TO_DEV";
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return "invalid";
>> +}
> 
> this seems generic which other ppl may need, can we move it to core.

dmaengine_get_direction_text() to include/linux/dmaengine.h
This way client drivers can use it if they need it?

>> +static void udma_reset_uchan(struct udma_chan *uc)
>> +{
>> +	uc->state = UDMA_CHAN_IS_IDLE;
>> +	uc->remote_thread_id = -1;
>> +	uc->dir = DMA_MEM_TO_MEM;
>> +	uc->pkt_mode = false;
>> +	uc->ep_type = PSIL_EP_NATIVE;
>> +	uc->enable_acc32 = 0;
>> +	uc->enable_burst = 0;
>> +	uc->channel_tpl = 0;
>> +	uc->psd_size = 0;
>> +	uc->metadata_size = 0;
>> +	uc->hdesc_size = 0;
>> +	uc->notdpkt = 0;
> 
> rather than do setting zero, why note memset and then set the nonzero
> members only?

I have lots of other things in udma_chan which can not be memset, vchan
struct, tasklet, name (for irq), etc.

to use memset, I think I could move parameters under a new struct
(udma_chan_params) keeping only the state in udma_chan.


>> +static void udma_reset_counters(struct udma_chan *uc)
>> +{
>> +	u32 val;
>> +
>> +	if (uc->tchan) {
>> +		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_BCNT_REG);
>> +		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_BCNT_REG, val);
> 
> so you read back from UDMA_TCHAN_RT_BCNT_REG and write same value to
> it??

Yes, that's correct. This is how we can reset it. The counter is
decremented with the value you have written to the register.

>> +
>> +		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_SBCNT_REG);
>> +		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_SBCNT_REG, val);
>> +
>> +		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PCNT_REG);
>> +		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PCNT_REG, val);
>> +
>> +		val = udma_tchanrt_read(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG);
>> +		udma_tchanrt_write(uc->tchan, UDMA_TCHAN_RT_PEER_BCNT_REG, val);
>> +	}
>> +
>> +	if (uc->rchan) {
>> +		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_BCNT_REG);
>> +		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_BCNT_REG, val);
>> +
>> +		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_SBCNT_REG);
>> +		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_SBCNT_REG, val);
>> +
>> +		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PCNT_REG);
>> +		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PCNT_REG, val);
>> +
>> +		val = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_PEER_BCNT_REG);
>> +		udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_BCNT_REG, val);
> 
> True for all of these, what am I missing :)

Decrement on write.

> 
>> +static int udma_start(struct udma_chan *uc)
>> +{
>> +	struct virt_dma_desc *vd = vchan_next_desc(&uc->vc);
>> +
>> +	if (!vd) {
>> +		uc->desc = NULL;
>> +		return -ENOENT;
>> +	}
>> +
>> +	list_del(&vd->node);
>> +
>> +	uc->desc = to_udma_desc(&vd->tx);
>> +
>> +	/* Channel is already running and does not need reconfiguration */
>> +	if (udma_is_chan_running(uc) && !udma_chan_needs_reconfiguration(uc)) {
>> +		udma_start_desc(uc);
>> +		goto out;
> 
> How about the case where settings are different than the current one?

udma_chan_needs_reconfiguration() is checking that. I only need to
reconfigure UDMAP/PDMA if the settings have changed.

>> +static struct udma_desc *udma_alloc_tr_desc(struct udma_chan *uc,
>> +					    size_t tr_size, int tr_count,
>> +					    enum dma_transfer_direction dir)
>> +{
>> +	struct udma_hwdesc *hwdesc;
>> +	struct cppi5_desc_hdr_t *tr_desc;
>> +	struct udma_desc *d;
>> +	u32 reload_count = 0;
>> +	u32 ring_id;
>> +
>> +	switch (tr_size) {
>> +	case 16:
>> +	case 32:
>> +	case 64:
>> +	case 128:
>> +		break;
>> +	default:
>> +		dev_err(uc->ud->dev, "Unsupported TR size of %zu\n", tr_size);
>> +		return NULL;
>> +	}
>> +
>> +	/* We have only one descriptor containing multiple TRs */
>> +	d = kzalloc(sizeof(*d) + sizeof(d->hwdesc[0]), GFP_ATOMIC);
> 
> this is invoked from prep_ so should use GFP_NOWAIT, we dont use
> GFP_ATOMIC :)

Ok. btw: EDMA and sDMA driver is using GFP_ATOMIC :o

> 
>> +static struct udma_desc *
>> +udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>> +		      unsigned int sglen, enum dma_transfer_direction dir,
>> +		      unsigned long tx_flags, void *context)
>> +{
>> +	enum dma_slave_buswidth dev_width;
>> +	struct scatterlist *sgent;
>> +	struct udma_desc *d;
>> +	size_t tr_size;
>> +	struct cppi5_tr_type1_t *tr_req = NULL;
>> +	unsigned int i;
>> +	u32 burst;
>> +
>> +	if (dir == DMA_DEV_TO_MEM) {
>> +		dev_width = uc->cfg.src_addr_width;
>> +		burst = uc->cfg.src_maxburst;
>> +	} else if (dir == DMA_MEM_TO_DEV) {
>> +		dev_width = uc->cfg.dst_addr_width;
>> +		burst = uc->cfg.dst_maxburst;
>> +	} else {
>> +		dev_err(uc->ud->dev, "%s: bad direction?\n", __func__);
>> +		return NULL;
>> +	}
>> +
>> +	if (!burst)
>> +		burst = 1;
>> +
>> +	/* Now allocate and setup the descriptor. */
>> +	tr_size = sizeof(struct cppi5_tr_type1_t);
>> +	d = udma_alloc_tr_desc(uc, tr_size, sglen, dir);
>> +	if (!d)
>> +		return NULL;
>> +
>> +	d->sglen = sglen;
>> +
>> +	tr_req = (struct cppi5_tr_type1_t *)d->hwdesc[0].tr_req_base;
> 
> cast away from void *?

True, it is not needed.

>> +static int udma_configure_statictr(struct udma_chan *uc, struct udma_desc *d,
>> +				   enum dma_slave_buswidth dev_width,
>> +				   u16 elcnt)
>> +{
>> +	if (uc->ep_type != PSIL_EP_PDMA_XY)
>> +		return 0;
>> +
>> +	/* Bus width translates to the element size (ES) */
>> +	switch (dev_width) {
>> +	case DMA_SLAVE_BUSWIDTH_1_BYTE:
>> +		d->static_tr.elsize = 0;
>> +		break;
>> +	case DMA_SLAVE_BUSWIDTH_2_BYTES:
>> +		d->static_tr.elsize = 1;
>> +		break;
>> +	case DMA_SLAVE_BUSWIDTH_3_BYTES:
>> +		d->static_tr.elsize = 2;
>> +		break;
>> +	case DMA_SLAVE_BUSWIDTH_4_BYTES:
>> +		d->static_tr.elsize = 3;
>> +		break;
>> +	case DMA_SLAVE_BUSWIDTH_8_BYTES:
>> +		d->static_tr.elsize = 4;
> 
> seems like ffs(dev_width) to me?

Not really:
ffs(DMA_SLAVE_BUSWIDTH_1_BYTE) = 1
ffs(DMA_SLAVE_BUSWIDTH_2_BYTES) = 2
ffs(DMA_SLAVE_BUSWIDTH_3_BYTES) = 1
ffs(DMA_SLAVE_BUSWIDTH_4_BYTES) = 3
ffs(DMA_SLAVE_BUSWIDTH_8_BYTES) = 4

> 
>> +static struct udma_desc *
>> +udma_prep_slave_sg_pkt(struct udma_chan *uc, struct scatterlist *sgl,
>> +		       unsigned int sglen, enum dma_transfer_direction dir,
>> +		       unsigned long tx_flags, void *context)
>> +{
>> +	struct scatterlist *sgent;
>> +	struct cppi5_host_desc_t *h_desc = NULL;
>> +	struct udma_desc *d;
>> +	u32 ring_id;
>> +	unsigned int i;
>> +
>> +	d = kzalloc(sizeof(*d) + sglen * sizeof(d->hwdesc[0]), GFP_ATOMIC);
> 
> GFP_NOWAIT here and few other places

Yes, I have fixed them up by this time.

> 
>> +static struct udma_desc *
>> +udma_prep_dma_cyclic_pkt(struct udma_chan *uc, dma_addr_t buf_addr,
>> +			 size_t buf_len, size_t period_len,
>> +			 enum dma_transfer_direction dir, unsigned long flags)
>> +{
>> +	struct udma_desc *d;
>> +	u32 ring_id;
>> +	int i;
>> +	int periods = buf_len / period_len;
>> +
>> +	if (periods > (K3_UDMA_DEFAULT_RING_SIZE - 1))
>> +		return NULL;
>> +
>> +	if (period_len > 0x3FFFFF)
> 
> Magic?

I'll add a define to cppi5. It is the packet length limit.

> 
>> +static enum dma_status udma_tx_status(struct dma_chan *chan,
>> +				      dma_cookie_t cookie,
>> +				      struct dma_tx_state *txstate)
>> +{
>> +	struct udma_chan *uc = to_udma_chan(chan);
>> +	enum dma_status ret;
>> +	unsigned long flags;
>> +
>> +	spin_lock_irqsave(&uc->vc.lock, flags);
>> +
>> +	ret = dma_cookie_status(chan, cookie, txstate);
>> +
>> +	if (!udma_is_chan_running(uc))
>> +		ret = DMA_COMPLETE;
> 
> Even for paused, not started channel? Not sure what will be return on those cases

Hrm, if the channel is not started yet, then I think it should be still
DMA_IN_PROGRESS, right?
The udma_is_chan_running() can be dropped from here.
I did missed the DMA_PAUSED state.

-	if (!udma_is_chan_running(uc))
-		ret = DMA_COMPLETE;
+	if (ret == DMA_IN_PROGRESS && udma_is_chan_paused(uc))
+		ret = DMA_PAUSED;


- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

  reply	other threads:[~2019-12-23  8:59 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-09  9:43 [PATCH v7 00/12] dmaengine/soc: Add Texas Instruments UDMA support Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 01/12] bindings: soc: ti: add documentation for k3 ringacc Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 02/12] soc: ti: k3: add navss ringacc driver Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 03/12] dmaengine: doc: Add sections for per descriptor metadata support Peter Ujfalusi
2019-12-20  8:28   ` Vinod Koul
2019-12-20  9:52     ` Peter Ujfalusi
2019-12-20 10:14       ` Vinod Koul
2019-12-09  9:43 ` [PATCH v7 04/12] dmaengine: Add metadata_ops for dma_async_tx_descriptor Peter Ujfalusi
2019-12-20  8:32   ` Vinod Koul
2019-12-20  8:48     ` Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 05/12] dmaengine: Add support for reporting DMA cached data amount Peter Ujfalusi
2019-12-20  8:37   ` Vinod Koul
2019-12-20  8:49     ` Peter Ujfalusi
2019-12-20  9:57       ` Vinod Koul
2019-12-20 10:13         ` Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 06/12] dmaengine: ti: Add cppi5 header for K3 NAVSS/UDMA Peter Ujfalusi
2019-12-20  9:54   ` Vinod Koul
2019-12-20 10:42     ` Peter Ujfalusi
2019-12-23  7:11       ` Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 07/12] dmaengine: ti: k3 PSI-L remote endpoint configuration Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 08/12] dt-bindings: dma: ti: Add document for K3 UDMA Peter Ujfalusi
2019-12-23  6:53   ` Vinod Koul
2019-12-09  9:43 ` [PATCH v7 09/12] dmaengine: ti: New driver " Peter Ujfalusi
2019-12-23  7:34   ` Vinod Koul
2019-12-23  8:59     ` Peter Ujfalusi [this message]
2019-12-23 11:26       ` Vinod Koul
2019-12-09  9:43 ` [PATCH v7 10/12] dmaengine: ti: k3-udma: Add glue layer for non DMAengine users Peter Ujfalusi
2019-12-09  9:43 ` [PATCH v7 11/12] firmware: ti_sci: rm: Add support for tx_tdtype parameter for tx channel Peter Ujfalusi
2019-12-11 10:24   ` Tero Kristo
2019-12-09  9:43 ` [PATCH v7 12/12] dmaengine: ti: k3-udma: Wait for peer teardown completion if supported Peter Ujfalusi
2019-12-11 10:43 ` [PATCH v7 00/12] dmaengine/soc: Add Texas Instruments UDMA support Keerthy
2019-12-12  8:46 ` Peter Ujfalusi
2019-12-12 10:55   ` Tero Kristo
2019-12-12 10:57     ` Tero Kristo
2019-12-16 10:05   ` Peter Ujfalusi
2019-12-12 18:01 ` Grygorii Strashko

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=ea473fed-276f-6b71-070b-02ab1f51ed89@ti.com \
    --to=peter.ujfalusi@ti.com \
    --cc=dan.j.williams@intel.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=grygorii.strashko@ti.com \
    --cc=j-keerthy@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lokeshvutla@ti.com \
    --cc=nm@ti.com \
    --cc=robh+dt@kernel.org \
    --cc=ssantosh@kernel.org \
    --cc=t-kristo@ti.com \
    --cc=tony@atomide.com \
    --cc=vigneshr@ti.com \
    --cc=vkoul@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;
as well as URLs for NNTP newsgroup(s).