diff mbox series

dma: ti: k3-udma: Workaround errata i2234

Message ID 20211209180715.27998-1-vigneshr@ti.com (mailing list archive)
State Changes Requested
Headers show
Series dma: ti: k3-udma: Workaround errata i2234 | expand

Commit Message

Vignesh Raghavendra Dec. 9, 2021, 6:07 p.m. UTC
Per [1], UDMA TR15 transactions may hang if ICNT0 is less than 64B
Work around is to set EOL flag is to 1 for ICNT0.

Since, there is no performance penalty / side effects of setting EOL
flag event ICNTO > 64B, just set the flag for all UDMAP TR15
descriptors.

[1] https://www.ti.com/lit/er/sprz455a/sprz455a.pdf
Errata doc for J721E DRA829/TDA4VM Processors Silicon Revision 1.1/1.0 (Rev. A)

Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
---
 drivers/dma/ti/k3-udma.c     | 48 +++++++++++++++++++-----------------
 include/linux/dma/ti-cppi5.h |  1 +
 2 files changed, 27 insertions(+), 22 deletions(-)

Comments

Péter Ujfalusi Dec. 10, 2021, 3:22 p.m. UTC | #1
Hi Vignesh,

On 09/12/2021 20:07, Vignesh Raghavendra wrote:
> Per [1], UDMA TR15 transactions may hang if ICNT0 is less than 64B
> Work around is to set EOL flag is to 1 for ICNT0.
> 
> Since, there is no performance penalty / side effects of setting EOL
> flag event ICNTO > 64B, just set the flag for all UDMAP TR15
> descriptors.

PDMAs and CSI does not send EOL? If you set it the EOL to one then when
it arrives the remaining icnt0 is skipped...

> 
> [1] https://www.ti.com/lit/er/sprz455a/sprz455a.pdf
> Errata doc for J721E DRA829/TDA4VM Processors Silicon Revision 1.1/1.0 (Rev. A)
> 
> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
> ---
>  drivers/dma/ti/k3-udma.c     | 48 +++++++++++++++++++-----------------
>  include/linux/dma/ti-cppi5.h |  1 +
>  2 files changed, 27 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
> index 6e56d1cef5ee..d65c4cc5fbf7 100644
> --- a/drivers/dma/ti/k3-udma.c
> +++ b/drivers/dma/ti/k3-udma.c
> @@ -2863,6 +2863,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  	struct udma_desc *d;
>  	struct cppi5_tr_type1_t *tr_req = NULL;
>  	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  	unsigned int i;
>  	size_t tr_size;
>  	int num_tr = 0;
> @@ -2885,10 +2886,12 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  	d->sglen = sglen;
>  
> -	if (uc->ud->match_data->type == DMA_TYPE_UDMA)
> +	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
>  		asel = 0;
> -	else
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
> +	} else {
>  		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
> +	}
>  
>  	tr_req = d->hwdesc[0].tr_req_base;
>  	for_each_sg(sgl, sgent, sglen, i) {
> @@ -2906,7 +2909,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1, false,
>  			      false, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
> +		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  
>  		sg_addr |= asel;
>  		tr_req[tr_idx].addr = sg_addr;
> @@ -2919,8 +2922,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
>  				      false, false,
>  				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  
>  			tr_req[tr_idx].addr = sg_addr + tr0_cnt1 * tr0_cnt0;
>  			tr_req[tr_idx].icnt0 = tr1_cnt0;
> @@ -2932,8 +2934,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  		d->residue += sg_dma_len(sgent);
>  	}
>  
> -	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
> -			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
> +	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
>  
>  	return d;
>  }
> @@ -2947,6 +2948,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  	struct scatterlist *sgent;
>  	struct cppi5_tr_type15_t *tr_req = NULL;
>  	enum dma_slave_buswidth dev_width;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  	u16 tr_cnt0, tr_cnt1;
>  	dma_addr_t dev_addr;
>  	struct udma_desc *d;
> @@ -3017,6 +3019,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
>  		asel = 0;
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
>  	} else {
>  		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
>  		dev_addr |= asel;
> @@ -3040,7 +3043,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15, false,
>  			      true, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
> +		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  		cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
>  				     uc->config.tr_trigger_type,
>  				     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC, 0, 0);
> @@ -3086,8 +3089,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15,
>  				      false, true,
>  				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  			cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
>  					     uc->config.tr_trigger_type,
>  					     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC,
> @@ -3131,8 +3133,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  		d->residue += sg_len;
>  	}
>  
> -	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
> -			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
> +	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
>  
>  	return d;
>  }
> @@ -3454,6 +3455,7 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  	struct cppi5_tr_type1_t *tr_req;
>  	unsigned int periods = buf_len / period_len;
>  	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  	unsigned int i;
>  	int num_tr;
>  
> @@ -3472,11 +3474,13 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  		return NULL;
>  
>  	tr_req = d->hwdesc[0].tr_req_base;
> -	if (uc->ud->match_data->type == DMA_TYPE_UDMA)
> +	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
>  		period_addr = buf_addr;
> -	else
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
> +	} else {
>  		period_addr = buf_addr |
>  			((u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT);
> +	}
>  
>  	for (i = 0; i < periods; i++) {
>  		int tr_idx = i * num_tr;
> @@ -3490,8 +3494,7 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  		tr_req[tr_idx].dim1 = tr0_cnt0;
>  
>  		if (num_tr == 2) {
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  			tr_idx++;
>  
>  			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
> @@ -3505,8 +3508,7 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  		}
>  
>  		if (!(flags & DMA_PREP_INTERRUPT))
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  
>  		period_addr += period_len;
>  	}
> @@ -3659,6 +3661,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  	int num_tr;
>  	size_t tr_size = sizeof(struct cppi5_tr_type15_t);
>  	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  
>  	if (uc->config.dir != DMA_MEM_TO_MEM) {
>  		dev_err(chan->device->dev,
> @@ -3689,13 +3692,15 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  	if (uc->ud->match_data->type != DMA_TYPE_UDMA) {
>  		src |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
>  		dest |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
> +	} else {
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
>  	}
>  
>  	tr_req = d->hwdesc[0].tr_req_base;
>  
>  	cppi5_tr_init(&tr_req[0].flags, CPPI5_TR_TYPE15, false, true,
>  		      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -	cppi5_tr_csf_set(&tr_req[0].flags, CPPI5_TR_CSF_SUPR_EVT);
> +	cppi5_tr_csf_set(&tr_req[0].flags, csf);
>  
>  	tr_req[0].addr = src;
>  	tr_req[0].icnt0 = tr0_cnt0;
> @@ -3714,7 +3719,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  	if (num_tr == 2) {
>  		cppi5_tr_init(&tr_req[1].flags, CPPI5_TR_TYPE15, false, true,
>  			      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -		cppi5_tr_csf_set(&tr_req[1].flags, CPPI5_TR_CSF_SUPR_EVT);
> +		cppi5_tr_csf_set(&tr_req[1].flags, csf);
>  
>  		tr_req[1].addr = src + tr0_cnt1 * tr0_cnt0;
>  		tr_req[1].icnt0 = tr1_cnt0;
> @@ -3729,8 +3734,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  		tr_req[1].dicnt3 = 1;
>  	}
>  
> -	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags,
> -			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
> +	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags, csf | CPPI5_TR_CSF_EOP);
>  
>  	if (uc->config.metadata_size)
>  		d->vd.tx.metadata_ops = &metadata_ops;
> diff --git a/include/linux/dma/ti-cppi5.h b/include/linux/dma/ti-cppi5.h
> index efa2f0309f00..c53c0f6e3b1a 100644
> --- a/include/linux/dma/ti-cppi5.h
> +++ b/include/linux/dma/ti-cppi5.h
> @@ -616,6 +616,7 @@ static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc)
>  #define   CPPI5_TR_CSF_SUPR_EVT			BIT(2)
>  #define   CPPI5_TR_CSF_EOL_ADV_SHIFT		(4U)
>  #define   CPPI5_TR_CSF_EOL_ADV_MASK		GENMASK(6, 4)
> +#define   CPPI5_TR_CSF_EOL_ICNT0		BIT(4)

the correct expression is: (1 << CPPI5_TR_CSF_EOL_ADV_SHIFT)
as EOL = 1 is what you want to set.
EOL = 2 will clear icnt0 and 1 on EOL.
3 will do the same for icnt 0, 1 and 2
4 will skip the remainin tr.

>  #define   CPPI5_TR_CSF_EOP			BIT(7)
>  
>  /**
>
Vinod Koul Dec. 13, 2021, 5:36 a.m. UTC | #2
On 09-12-21, 23:37, Vignesh Raghavendra wrote:
> Per [1], UDMA TR15 transactions may hang if ICNT0 is less than 64B
> Work around is to set EOL flag is to 1 for ICNT0.
> 
> Since, there is no performance penalty / side effects of setting EOL
> flag event ICNTO > 64B, just set the flag for all UDMAP TR15
> descriptors.

s/dma/dmaengine

> 
> [1] https://www.ti.com/lit/er/sprz455a/sprz455a.pdf
> Errata doc for J721E DRA829/TDA4VM Processors Silicon Revision 1.1/1.0 (Rev. A)
> 
> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
> ---
>  drivers/dma/ti/k3-udma.c     | 48 +++++++++++++++++++-----------------
>  include/linux/dma/ti-cppi5.h |  1 +
>  2 files changed, 27 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
> index 6e56d1cef5ee..d65c4cc5fbf7 100644
> --- a/drivers/dma/ti/k3-udma.c
> +++ b/drivers/dma/ti/k3-udma.c
> @@ -2863,6 +2863,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  	struct udma_desc *d;
>  	struct cppi5_tr_type1_t *tr_req = NULL;
>  	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  	unsigned int i;
>  	size_t tr_size;
>  	int num_tr = 0;
> @@ -2885,10 +2886,12 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  	d->sglen = sglen;
>  
> -	if (uc->ud->match_data->type == DMA_TYPE_UDMA)
> +	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
>  		asel = 0;
> -	else
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
> +	} else {
>  		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
> +	}
>  
>  	tr_req = d->hwdesc[0].tr_req_base;
>  	for_each_sg(sgl, sgent, sglen, i) {
> @@ -2906,7 +2909,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1, false,
>  			      false, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
> +		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  
>  		sg_addr |= asel;
>  		tr_req[tr_idx].addr = sg_addr;
> @@ -2919,8 +2922,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
>  				      false, false,
>  				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  
>  			tr_req[tr_idx].addr = sg_addr + tr0_cnt1 * tr0_cnt0;
>  			tr_req[tr_idx].icnt0 = tr1_cnt0;
> @@ -2932,8 +2934,7 @@ udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  		d->residue += sg_dma_len(sgent);
>  	}
>  
> -	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
> -			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
> +	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
>  
>  	return d;
>  }
> @@ -2947,6 +2948,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  	struct scatterlist *sgent;
>  	struct cppi5_tr_type15_t *tr_req = NULL;
>  	enum dma_slave_buswidth dev_width;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  	u16 tr_cnt0, tr_cnt1;
>  	dma_addr_t dev_addr;
>  	struct udma_desc *d;
> @@ -3017,6 +3019,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
>  		asel = 0;
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
>  	} else {
>  		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
>  		dev_addr |= asel;
> @@ -3040,7 +3043,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  
>  		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15, false,
>  			      true, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
> +		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  		cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
>  				     uc->config.tr_trigger_type,
>  				     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC, 0, 0);
> @@ -3086,8 +3089,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15,
>  				      false, true,
>  				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  			cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
>  					     uc->config.tr_trigger_type,
>  					     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC,
> @@ -3131,8 +3133,7 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
>  		d->residue += sg_len;
>  	}
>  
> -	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
> -			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
> +	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
>  
>  	return d;
>  }
> @@ -3454,6 +3455,7 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  	struct cppi5_tr_type1_t *tr_req;
>  	unsigned int periods = buf_len / period_len;
>  	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  	unsigned int i;
>  	int num_tr;
>  
> @@ -3472,11 +3474,13 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  		return NULL;
>  
>  	tr_req = d->hwdesc[0].tr_req_base;
> -	if (uc->ud->match_data->type == DMA_TYPE_UDMA)
> +	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
>  		period_addr = buf_addr;
> -	else
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
> +	} else {
>  		period_addr = buf_addr |
>  			((u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT);
> +	}
>  
>  	for (i = 0; i < periods; i++) {
>  		int tr_idx = i * num_tr;
> @@ -3490,8 +3494,7 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  		tr_req[tr_idx].dim1 = tr0_cnt0;
>  
>  		if (num_tr == 2) {
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  			tr_idx++;
>  
>  			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
> @@ -3505,8 +3508,7 @@ udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
>  		}
>  
>  		if (!(flags & DMA_PREP_INTERRUPT))
> -			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
> -					 CPPI5_TR_CSF_SUPR_EVT);
> +			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
>  
>  		period_addr += period_len;
>  	}
> @@ -3659,6 +3661,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  	int num_tr;
>  	size_t tr_size = sizeof(struct cppi5_tr_type15_t);
>  	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
> +	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
>  
>  	if (uc->config.dir != DMA_MEM_TO_MEM) {
>  		dev_err(chan->device->dev,
> @@ -3689,13 +3692,15 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  	if (uc->ud->match_data->type != DMA_TYPE_UDMA) {
>  		src |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
>  		dest |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
> +	} else {
> +		csf |= CPPI5_TR_CSF_EOL_ICNT0;
>  	}
>  
>  	tr_req = d->hwdesc[0].tr_req_base;
>  
>  	cppi5_tr_init(&tr_req[0].flags, CPPI5_TR_TYPE15, false, true,
>  		      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -	cppi5_tr_csf_set(&tr_req[0].flags, CPPI5_TR_CSF_SUPR_EVT);
> +	cppi5_tr_csf_set(&tr_req[0].flags, csf);
>  
>  	tr_req[0].addr = src;
>  	tr_req[0].icnt0 = tr0_cnt0;
> @@ -3714,7 +3719,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  	if (num_tr == 2) {
>  		cppi5_tr_init(&tr_req[1].flags, CPPI5_TR_TYPE15, false, true,
>  			      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
> -		cppi5_tr_csf_set(&tr_req[1].flags, CPPI5_TR_CSF_SUPR_EVT);
> +		cppi5_tr_csf_set(&tr_req[1].flags, csf);
>  
>  		tr_req[1].addr = src + tr0_cnt1 * tr0_cnt0;
>  		tr_req[1].icnt0 = tr1_cnt0;
> @@ -3729,8 +3734,7 @@ udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
>  		tr_req[1].dicnt3 = 1;
>  	}
>  
> -	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags,
> -			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
> +	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags, csf | CPPI5_TR_CSF_EOP);
>  
>  	if (uc->config.metadata_size)
>  		d->vd.tx.metadata_ops = &metadata_ops;
> diff --git a/include/linux/dma/ti-cppi5.h b/include/linux/dma/ti-cppi5.h
> index efa2f0309f00..c53c0f6e3b1a 100644
> --- a/include/linux/dma/ti-cppi5.h
> +++ b/include/linux/dma/ti-cppi5.h
> @@ -616,6 +616,7 @@ static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc)
>  #define   CPPI5_TR_CSF_SUPR_EVT			BIT(2)
>  #define   CPPI5_TR_CSF_EOL_ADV_SHIFT		(4U)
>  #define   CPPI5_TR_CSF_EOL_ADV_MASK		GENMASK(6, 4)
> +#define   CPPI5_TR_CSF_EOL_ICNT0		BIT(4)
>  #define   CPPI5_TR_CSF_EOP			BIT(7)
>  
>  /**
> -- 
> 2.34.1
Jayesh Choudhary March 23, 2023, 11:55 a.m. UTC | #3
Hello Peter,

On 10/12/21 20:52, Péter Ujfalusi wrote:
> Hi Vignesh,
> 
> On 09/12/2021 20:07, Vignesh Raghavendra wrote:
>> Per [1], UDMA TR15 transactions may hang if ICNT0 is less than 64B
>> Work around is to set EOL flag is to 1 for ICNT0.
>>
>> Since, there is no performance penalty / side effects of setting EOL
>> flag event ICNTO > 64B, just set the flag for all UDMAP TR15
>> descriptors.
> 
> PDMAs and CSI does not send EOL? If you set it the EOL to one then when
> it arrives the remaining icnt0 is skipped...

I am planning to respin v2 for this.
Will fix this in v2.

> 
>>
>> [1] https://www.ti.com/lit/er/sprz455a/sprz455a.pdf
>> Errata doc for J721E DRA829/TDA4VM Processors Silicon Revision 1.1/1.0 (Rev. A)
>>
>> Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
>> ---
>>   drivers/dma/ti/k3-udma.c     | 48 +++++++++++++++++++-----------------
>>   include/linux/dma/ti-cppi5.h |  1 +
>>   2 files changed, 27 insertions(+), 22 deletions(-)
>>

[...]

>> diff --git a/include/linux/dma/ti-cppi5.h b/include/linux/dma/ti-cppi5.h
>> index efa2f0309f00..c53c0f6e3b1a 100644
>> --- a/include/linux/dma/ti-cppi5.h
>> +++ b/include/linux/dma/ti-cppi5.h
>> @@ -616,6 +616,7 @@ static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc)
>>   #define   CPPI5_TR_CSF_SUPR_EVT			BIT(2)
>>   #define   CPPI5_TR_CSF_EOL_ADV_SHIFT		(4U)
>>   #define   CPPI5_TR_CSF_EOL_ADV_MASK		GENMASK(6, 4)
>> +#define   CPPI5_TR_CSF_EOL_ICNT0		BIT(4)
> 
> the correct expression is: (1 << CPPI5_TR_CSF_EOL_ADV_SHIFT)

Both these expressions expands to the same value
(CPPI5_TR_CSF_EOL_ADV_SHIFT = 4U)

And according to the linux checkpatch, the usage of BIT macro
is preferred so I will keep it the same.

Warm regards,
-Jayesh

> as EOL = 1 is what you want to set.
> EOL = 2 will clear icnt0 and 1 on EOL.
> 3 will do the same for icnt 0, 1 and 2
> 4 will skip the remainin tr.
> 
>>   #define   CPPI5_TR_CSF_EOP			BIT(7)
>>   
>>   /**
>>
>
diff mbox series

Patch

diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 6e56d1cef5ee..d65c4cc5fbf7 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -2863,6 +2863,7 @@  udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 	struct udma_desc *d;
 	struct cppi5_tr_type1_t *tr_req = NULL;
 	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
+	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
 	unsigned int i;
 	size_t tr_size;
 	int num_tr = 0;
@@ -2885,10 +2886,12 @@  udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 
 	d->sglen = sglen;
 
-	if (uc->ud->match_data->type == DMA_TYPE_UDMA)
+	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
 		asel = 0;
-	else
+		csf |= CPPI5_TR_CSF_EOL_ICNT0;
+	} else {
 		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
+	}
 
 	tr_req = d->hwdesc[0].tr_req_base;
 	for_each_sg(sgl, sgent, sglen, i) {
@@ -2906,7 +2909,7 @@  udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 
 		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1, false,
 			      false, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
+		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 
 		sg_addr |= asel;
 		tr_req[tr_idx].addr = sg_addr;
@@ -2919,8 +2922,7 @@  udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
 				      false, false,
 				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
-					 CPPI5_TR_CSF_SUPR_EVT);
+			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 
 			tr_req[tr_idx].addr = sg_addr + tr0_cnt1 * tr0_cnt0;
 			tr_req[tr_idx].icnt0 = tr1_cnt0;
@@ -2932,8 +2934,7 @@  udma_prep_slave_sg_tr(struct udma_chan *uc, struct scatterlist *sgl,
 		d->residue += sg_dma_len(sgent);
 	}
 
-	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
-			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
+	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
 
 	return d;
 }
@@ -2947,6 +2948,7 @@  udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
 	struct scatterlist *sgent;
 	struct cppi5_tr_type15_t *tr_req = NULL;
 	enum dma_slave_buswidth dev_width;
+	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
 	u16 tr_cnt0, tr_cnt1;
 	dma_addr_t dev_addr;
 	struct udma_desc *d;
@@ -3017,6 +3019,7 @@  udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
 
 	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
 		asel = 0;
+		csf |= CPPI5_TR_CSF_EOL_ICNT0;
 	} else {
 		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
 		dev_addr |= asel;
@@ -3040,7 +3043,7 @@  udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
 
 		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15, false,
 			      true, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
+		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 		cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
 				     uc->config.tr_trigger_type,
 				     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC, 0, 0);
@@ -3086,8 +3089,7 @@  udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
 			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15,
 				      false, true,
 				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
-					 CPPI5_TR_CSF_SUPR_EVT);
+			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 			cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
 					     uc->config.tr_trigger_type,
 					     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC,
@@ -3131,8 +3133,7 @@  udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
 		d->residue += sg_len;
 	}
 
-	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
-			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
+	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
 
 	return d;
 }
@@ -3454,6 +3455,7 @@  udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
 	struct cppi5_tr_type1_t *tr_req;
 	unsigned int periods = buf_len / period_len;
 	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
+	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
 	unsigned int i;
 	int num_tr;
 
@@ -3472,11 +3474,13 @@  udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
 		return NULL;
 
 	tr_req = d->hwdesc[0].tr_req_base;
-	if (uc->ud->match_data->type == DMA_TYPE_UDMA)
+	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
 		period_addr = buf_addr;
-	else
+		csf |= CPPI5_TR_CSF_EOL_ICNT0;
+	} else {
 		period_addr = buf_addr |
 			((u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT);
+	}
 
 	for (i = 0; i < periods; i++) {
 		int tr_idx = i * num_tr;
@@ -3490,8 +3494,7 @@  udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
 		tr_req[tr_idx].dim1 = tr0_cnt0;
 
 		if (num_tr == 2) {
-			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
-					 CPPI5_TR_CSF_SUPR_EVT);
+			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 			tr_idx++;
 
 			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE1,
@@ -3505,8 +3508,7 @@  udma_prep_dma_cyclic_tr(struct udma_chan *uc, dma_addr_t buf_addr,
 		}
 
 		if (!(flags & DMA_PREP_INTERRUPT))
-			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
-					 CPPI5_TR_CSF_SUPR_EVT);
+			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 
 		period_addr += period_len;
 	}
@@ -3659,6 +3661,7 @@  udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 	int num_tr;
 	size_t tr_size = sizeof(struct cppi5_tr_type15_t);
 	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
+	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
 
 	if (uc->config.dir != DMA_MEM_TO_MEM) {
 		dev_err(chan->device->dev,
@@ -3689,13 +3692,15 @@  udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 	if (uc->ud->match_data->type != DMA_TYPE_UDMA) {
 		src |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
 		dest |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
+	} else {
+		csf |= CPPI5_TR_CSF_EOL_ICNT0;
 	}
 
 	tr_req = d->hwdesc[0].tr_req_base;
 
 	cppi5_tr_init(&tr_req[0].flags, CPPI5_TR_TYPE15, false, true,
 		      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-	cppi5_tr_csf_set(&tr_req[0].flags, CPPI5_TR_CSF_SUPR_EVT);
+	cppi5_tr_csf_set(&tr_req[0].flags, csf);
 
 	tr_req[0].addr = src;
 	tr_req[0].icnt0 = tr0_cnt0;
@@ -3714,7 +3719,7 @@  udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 	if (num_tr == 2) {
 		cppi5_tr_init(&tr_req[1].flags, CPPI5_TR_TYPE15, false, true,
 			      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-		cppi5_tr_csf_set(&tr_req[1].flags, CPPI5_TR_CSF_SUPR_EVT);
+		cppi5_tr_csf_set(&tr_req[1].flags, csf);
 
 		tr_req[1].addr = src + tr0_cnt1 * tr0_cnt0;
 		tr_req[1].icnt0 = tr1_cnt0;
@@ -3729,8 +3734,7 @@  udma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 		tr_req[1].dicnt3 = 1;
 	}
 
-	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags,
-			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
+	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags, csf | CPPI5_TR_CSF_EOP);
 
 	if (uc->config.metadata_size)
 		d->vd.tx.metadata_ops = &metadata_ops;
diff --git a/include/linux/dma/ti-cppi5.h b/include/linux/dma/ti-cppi5.h
index efa2f0309f00..c53c0f6e3b1a 100644
--- a/include/linux/dma/ti-cppi5.h
+++ b/include/linux/dma/ti-cppi5.h
@@ -616,6 +616,7 @@  static inline void *cppi5_hdesc_get_swdata(struct cppi5_host_desc_t *desc)
 #define   CPPI5_TR_CSF_SUPR_EVT			BIT(2)
 #define   CPPI5_TR_CSF_EOL_ADV_SHIFT		(4U)
 #define   CPPI5_TR_CSF_EOL_ADV_MASK		GENMASK(6, 4)
+#define   CPPI5_TR_CSF_EOL_ICNT0		BIT(4)
 #define   CPPI5_TR_CSF_EOP			BIT(7)
 
 /**