[PATCH] dmaengine: at_xdmac: fix slave configuration issue
Ludovic Desroches
ludovic.desroches at atmel.com
Mon Apr 27 01:33:58 PDT 2015
Hi Vinod,
On Mon, Apr 27, 2015 at 09:03:28AM +0530, Vinod Koul wrote:
> On Thu, Apr 16, 2015 at 05:04:00PM +0200, Ludovic Desroches wrote:
> > When doing the slave configuration, an error is returned if the maxburst
> > value is not supported. The bug comes from the fact that we always check
> > the maxburst for both directions but in the case of an unidirectional
> > channel, only one is set.
> While setting the slave configuration we are not tied to a channel
> direction, the direction is passed usin prep_ method. So from that
> prespective a channle can be used for tx and rx with same slave config set.
>
> Now if we were invoking at_xdmac_set_slave_config from prep_ calls then it
> would have been fine but here we are checking when the slave config is set
> so this is not right. You should check maxburst at runtime then...
>
I don't understand why we should wait before checking the
configuration... Some channels are unidirectionnal so implicitly we know
the direction at configuration time because the device will fill only a
part of the dma_slave_config structure. For example, the atmel usart
requests a tx and a rx channels. When configuring the tx channel, only
the dst_ fields of the dma_slave_config structure are filled. Is it a
bad behavior?
The change introduced by this patch doesn't really care about the
direction, it only tells that if the device only fills src_ fields then
I don't have to check fields not configured.
Regards
Ludovic
> --
> ~Vinod
> > Signed-off-by: Ludovic Desroches <ludovic.desroches at atmel.com>
> > Cc: <stable at vger.kernel.org> # 3.19 and later
> > ---
> > drivers/dma/at_xdmac.c | 97 +++++++++++++++++++++++++++-----------------------
> > 1 file changed, 52 insertions(+), 45 deletions(-)
> >
> > diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
> > index d9891d3..30e161b 100644
> > --- a/drivers/dma/at_xdmac.c
> > +++ b/drivers/dma/at_xdmac.c
> > @@ -501,54 +501,61 @@ static int at_xdmac_set_slave_config(struct dma_chan *chan,
> > u8 dwidth;
> > int csize;
> >
> > - atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] =
> > - AT91_XDMAC_DT_PERID(atchan->perid)
> > - | AT_XDMAC_CC_DAM_INCREMENTED_AM
> > - | AT_XDMAC_CC_SAM_FIXED_AM
> > - | AT_XDMAC_CC_DIF(atchan->memif)
> > - | AT_XDMAC_CC_SIF(atchan->perif)
> > - | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
> > - | AT_XDMAC_CC_DSYNC_PER2MEM
> > - | AT_XDMAC_CC_MBSIZE_SIXTEEN
> > - | AT_XDMAC_CC_TYPE_PER_TRAN;
> > - csize = at_xdmac_csize(sconfig->src_maxburst);
> > - if (csize < 0) {
> > - dev_err(chan2dev(chan), "invalid src maxburst value\n");
> > - return -EINVAL;
> > - }
> > - atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_CSIZE(csize);
> > - dwidth = ffs(sconfig->src_addr_width) - 1;
> > - atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
> > -
> > -
> > - atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] =
> > - AT91_XDMAC_DT_PERID(atchan->perid)
> > - | AT_XDMAC_CC_DAM_FIXED_AM
> > - | AT_XDMAC_CC_SAM_INCREMENTED_AM
> > - | AT_XDMAC_CC_DIF(atchan->perif)
> > - | AT_XDMAC_CC_SIF(atchan->memif)
> > - | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
> > - | AT_XDMAC_CC_DSYNC_MEM2PER
> > - | AT_XDMAC_CC_MBSIZE_SIXTEEN
> > - | AT_XDMAC_CC_TYPE_PER_TRAN;
> > - csize = at_xdmac_csize(sconfig->dst_maxburst);
> > - if (csize < 0) {
> > - dev_err(chan2dev(chan), "invalid src maxburst value\n");
> > - return -EINVAL;
> > + if (sconfig->src_addr) {
> > + atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] =
> > + AT91_XDMAC_DT_PERID(atchan->perid)
> > + | AT_XDMAC_CC_DAM_INCREMENTED_AM
> > + | AT_XDMAC_CC_SAM_FIXED_AM
> > + | AT_XDMAC_CC_DIF(atchan->memif)
> > + | AT_XDMAC_CC_SIF(atchan->perif)
> > + | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
> > + | AT_XDMAC_CC_DSYNC_PER2MEM
> > + | AT_XDMAC_CC_MBSIZE_SIXTEEN
> > + | AT_XDMAC_CC_TYPE_PER_TRAN;
> > + csize = at_xdmac_csize(sconfig->src_maxburst);
> > + if (csize < 0) {
> > + dev_err(chan2dev(chan), "invalid src maxburst value\n");
> > + return -EINVAL;
> > + }
> > + atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_CSIZE(csize);
> > + dwidth = ffs(sconfig->src_addr_width) - 1;
> > + atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
> > + /* Src addr is needed to configure the link list descriptor. */
> > + atchan->per_src_addr = sconfig->src_addr;
> > +
> > + dev_dbg(chan2dev(chan),
> > + "%s: cfg[dev2mem]=0x%08x, per_src_addr=0x%08x\n",
> > + __func__, atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG],
> > + atchan->per_src_addr);
> > }
> > - atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_CSIZE(csize);
> > - dwidth = ffs(sconfig->dst_addr_width) - 1;
> > - atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
> >
> > - /* Src and dst addr are needed to configure the link list descriptor. */
> > - atchan->per_src_addr = sconfig->src_addr;
> > - atchan->per_dst_addr = sconfig->dst_addr;
> > + if (sconfig->dst_addr) {
> > + atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] =
> > + AT91_XDMAC_DT_PERID(atchan->perid)
> > + | AT_XDMAC_CC_DAM_FIXED_AM
> > + | AT_XDMAC_CC_SAM_INCREMENTED_AM
> > + | AT_XDMAC_CC_DIF(atchan->perif)
> > + | AT_XDMAC_CC_SIF(atchan->memif)
> > + | AT_XDMAC_CC_SWREQ_HWR_CONNECTED
> > + | AT_XDMAC_CC_DSYNC_MEM2PER
> > + | AT_XDMAC_CC_MBSIZE_SIXTEEN
> > + | AT_XDMAC_CC_TYPE_PER_TRAN;
> > + csize = at_xdmac_csize(sconfig->dst_maxburst);
> > + if (csize < 0) {
> > + dev_err(chan2dev(chan), "invalid src maxburst value\n");
> > + return -EINVAL;
> > + }
> > + atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_CSIZE(csize);
> > + dwidth = ffs(sconfig->dst_addr_width) - 1;
> > + atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG] |= AT_XDMAC_CC_DWIDTH(dwidth);
> > + /* Dst addr is needed to configure the link list descriptor. */
> > + atchan->per_dst_addr = sconfig->dst_addr;
> >
> > - dev_dbg(chan2dev(chan),
> > - "%s: cfg[dev2mem]=0x%08x, cfg[mem2dev]=0x%08x, per_src_addr=0x%08x, per_dst_addr=0x%08x\n",
> > - __func__, atchan->cfg[AT_XDMAC_DEV_TO_MEM_CFG],
> > - atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG],
> > - atchan->per_src_addr, atchan->per_dst_addr);
> > + dev_dbg(chan2dev(chan),
> > + "%s: cfg[mem2dev]=0x%08x, per_dst_addr=0x%08x\n",
> > + __func__, atchan->cfg[AT_XDMAC_MEM_TO_DEV_CFG],
> > + atchan->per_dst_addr);
> > + }
> >
> > return 0;
> > }
> > --
> > 2.2.0
> >
>
> --
More information about the linux-arm-kernel
mailing list