Re: [PATCH] dmaengine: fsl-edma: dma map slave device address
On 18-01-19, 12:06, Laurentiu Tudor wrote: > This mapping needs to be created in order for slave dma transfers > to work on systems with SMMU. The implementation mostly mimics the > one in pl330 dma driver, authored by Robin Murphy. Applied, thanks -- ~Vinod ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] dmaengine: fsl-edma: dma map slave device address
Hi Angelo, On 18.01.2019 23:50, Angelo Dureghello wrote: > Hi Laurentiu, > > On Fri, Jan 18, 2019 at 12:06:23PM +0200, Laurentiu Tudor wrote: >> This mapping needs to be created in order for slave dma transfers >> to work on systems with SMMU. The implementation mostly mimics the >> one in pl330 dma driver, authored by Robin Murphy. >> >> Signed-off-by: Laurentiu Tudor >> Suggested-by: Robin Murphy >> --- >> Original approach was to add the missing mappings in the i2c client driver, >> see here for discussion: >> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.ozlabs.org%2Fpatch%2F1026013%2Fdata=02%7C01%7Claurentiu.tudor%40nxp.com%7C7861dfe95dfb4fceeb8208d67d907488%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C1%7C636834456718898365sdata=XM5shQdcIRgFLtCmuRuFtViR6ttPDWI%2BNHXoPi68Xs8%3Dreserved=0 >> >> drivers/dma/fsl-edma-common.c | 66 --- >> drivers/dma/fsl-edma-common.h | 4 +++ >> drivers/dma/fsl-edma.c| 1 + >> drivers/dma/mcf-edma.c| 1 + >> 4 files changed, 68 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c >> index 8876c4c1bb2c..0e95ee24b6d4 100644 >> --- a/drivers/dma/fsl-edma-common.c >> +++ b/drivers/dma/fsl-edma-common.c >> @@ -6,6 +6,7 @@ >> #include >> #include >> #include >> +#include >> >> #include "fsl-edma-common.h" >> >> @@ -173,12 +174,62 @@ int fsl_edma_resume(struct dma_chan *chan) >> } >> EXPORT_SYMBOL_GPL(fsl_edma_resume); >> >> +static void fsl_edma_unprep_slave_dma(struct fsl_edma_chan *fsl_chan) >> +{ >> +if (fsl_chan->dma_dir != DMA_NONE) >> +dma_unmap_resource(fsl_chan->vchan.chan.device->dev, >> + fsl_chan->dma_dev_addr, >> + fsl_chan->dma_dev_size, >> + fsl_chan->dma_dir, 0); >> +fsl_chan->dma_dir = DMA_NONE; >> +} >> + >> +static bool fsl_edma_prep_slave_dma(struct fsl_edma_chan *fsl_chan, >> +enum dma_transfer_direction dir) >> +{ >> +struct device *dev = fsl_chan->vchan.chan.device->dev; >> +enum dma_data_direction dma_dir; >> +phys_addr_t addr = 0; >> +u32 size = 0; >> + >> +switch (dir) { >> +case DMA_MEM_TO_DEV: >> +dma_dir = DMA_FROM_DEVICE; >> +addr = fsl_chan->cfg.dst_addr; >> +size = fsl_chan->cfg.dst_maxburst; >> +break; >> +case DMA_DEV_TO_MEM: >> +dma_dir = DMA_TO_DEVICE; >> +addr = fsl_chan->cfg.src_addr; >> +size = fsl_chan->cfg.src_maxburst; >> +break; >> +default: >> +dma_dir = DMA_NONE; >> +break; >> +} >> + >> +/* Already mapped for this config? */ >> +if (fsl_chan->dma_dir == dma_dir) >> +return true; >> + >> +fsl_edma_unprep_slave_dma(fsl_chan); >> + >> +fsl_chan->dma_dev_addr = dma_map_resource(dev, addr, size, dma_dir, 0); >> +if (dma_mapping_error(dev, fsl_chan->dma_dev_addr)) >> +return false; >> +fsl_chan->dma_dev_size = size; >> +fsl_chan->dma_dir = dma_dir; >> + >> +return true; >> +} >> + >> int fsl_edma_slave_config(struct dma_chan *chan, >> struct dma_slave_config *cfg) >> { >> struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); >> >> memcpy(_chan->cfg, cfg, sizeof(*cfg)); >> +fsl_edma_unprep_slave_dma(fsl_chan); >> >> return 0; >> } >> @@ -378,6 +429,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic( >> if (!is_slave_direction(direction)) >> return NULL; >> >> +if (!fsl_edma_prep_slave_dma(fsl_chan, direction)) >> +return NULL; >> + >> sg_len = buf_len / period_len; >> fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len); >> if (!fsl_desc) >> @@ -409,11 +463,11 @@ struct dma_async_tx_descriptor >> *fsl_edma_prep_dma_cyclic( >> >> if (direction == DMA_MEM_TO_DEV) { >> src_addr = dma_buf_next; >> -dst_addr = fsl_chan->cfg.dst_addr; >> +dst_addr = fsl_chan->dma_dev_addr; >> soff = fsl_chan->cfg.dst_addr_width; >> doff = 0; >> } else { >> -src_addr = fsl_chan->cfg.src_addr; >> +src_addr = fsl_chan->dma_dev_addr; >> dst_addr = dma_buf_next; >> soff = 0; >> doff = fsl_chan->cfg.src_addr_width; >> @@ -444,6 +498,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg( >> if (!is_slave_direction(direction)) >> return NULL; >> >> +if (!fsl_edma_prep_slave_dma(fsl_chan, direction)) >> +return NULL; >> + >> fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len); >> if (!fsl_desc) >> return NULL; >> @@ -468,11 +525,11 @@
Re: [PATCH] dmaengine: fsl-edma: dma map slave device address
Hi Laurentiu, On Fri, Jan 18, 2019 at 12:06:23PM +0200, Laurentiu Tudor wrote: > This mapping needs to be created in order for slave dma transfers > to work on systems with SMMU. The implementation mostly mimics the > one in pl330 dma driver, authored by Robin Murphy. > > Signed-off-by: Laurentiu Tudor > Suggested-by: Robin Murphy > --- > Original approach was to add the missing mappings in the i2c client driver, > see here for discussion: https://patchwork.ozlabs.org/patch/1026013/ > > drivers/dma/fsl-edma-common.c | 66 --- > drivers/dma/fsl-edma-common.h | 4 +++ > drivers/dma/fsl-edma.c| 1 + > drivers/dma/mcf-edma.c| 1 + > 4 files changed, 68 insertions(+), 4 deletions(-) > > diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c > index 8876c4c1bb2c..0e95ee24b6d4 100644 > --- a/drivers/dma/fsl-edma-common.c > +++ b/drivers/dma/fsl-edma-common.c > @@ -6,6 +6,7 @@ > #include > #include > #include > +#include > > #include "fsl-edma-common.h" > > @@ -173,12 +174,62 @@ int fsl_edma_resume(struct dma_chan *chan) > } > EXPORT_SYMBOL_GPL(fsl_edma_resume); > > +static void fsl_edma_unprep_slave_dma(struct fsl_edma_chan *fsl_chan) > +{ > + if (fsl_chan->dma_dir != DMA_NONE) > + dma_unmap_resource(fsl_chan->vchan.chan.device->dev, > +fsl_chan->dma_dev_addr, > +fsl_chan->dma_dev_size, > +fsl_chan->dma_dir, 0); > + fsl_chan->dma_dir = DMA_NONE; > +} > + > +static bool fsl_edma_prep_slave_dma(struct fsl_edma_chan *fsl_chan, > + enum dma_transfer_direction dir) > +{ > + struct device *dev = fsl_chan->vchan.chan.device->dev; > + enum dma_data_direction dma_dir; > + phys_addr_t addr = 0; > + u32 size = 0; > + > + switch (dir) { > + case DMA_MEM_TO_DEV: > + dma_dir = DMA_FROM_DEVICE; > + addr = fsl_chan->cfg.dst_addr; > + size = fsl_chan->cfg.dst_maxburst; > + break; > + case DMA_DEV_TO_MEM: > + dma_dir = DMA_TO_DEVICE; > + addr = fsl_chan->cfg.src_addr; > + size = fsl_chan->cfg.src_maxburst; > + break; > + default: > + dma_dir = DMA_NONE; > + break; > + } > + > + /* Already mapped for this config? */ > + if (fsl_chan->dma_dir == dma_dir) > + return true; > + > + fsl_edma_unprep_slave_dma(fsl_chan); > + > + fsl_chan->dma_dev_addr = dma_map_resource(dev, addr, size, dma_dir, 0); > + if (dma_mapping_error(dev, fsl_chan->dma_dev_addr)) > + return false; > + fsl_chan->dma_dev_size = size; > + fsl_chan->dma_dir = dma_dir; > + > + return true; > +} > + > int fsl_edma_slave_config(struct dma_chan *chan, >struct dma_slave_config *cfg) > { > struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); > > memcpy(_chan->cfg, cfg, sizeof(*cfg)); > + fsl_edma_unprep_slave_dma(fsl_chan); > > return 0; > } > @@ -378,6 +429,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic( > if (!is_slave_direction(direction)) > return NULL; > > + if (!fsl_edma_prep_slave_dma(fsl_chan, direction)) > + return NULL; > + > sg_len = buf_len / period_len; > fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len); > if (!fsl_desc) > @@ -409,11 +463,11 @@ struct dma_async_tx_descriptor > *fsl_edma_prep_dma_cyclic( > > if (direction == DMA_MEM_TO_DEV) { > src_addr = dma_buf_next; > - dst_addr = fsl_chan->cfg.dst_addr; > + dst_addr = fsl_chan->dma_dev_addr; > soff = fsl_chan->cfg.dst_addr_width; > doff = 0; > } else { > - src_addr = fsl_chan->cfg.src_addr; > + src_addr = fsl_chan->dma_dev_addr; > dst_addr = dma_buf_next; > soff = 0; > doff = fsl_chan->cfg.src_addr_width; > @@ -444,6 +498,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg( > if (!is_slave_direction(direction)) > return NULL; > > + if (!fsl_edma_prep_slave_dma(fsl_chan, direction)) > + return NULL; > + > fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len); > if (!fsl_desc) > return NULL; > @@ -468,11 +525,11 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg( > > if (direction == DMA_MEM_TO_DEV) { > src_addr = sg_dma_address(sg); > - dst_addr = fsl_chan->cfg.dst_addr; > + dst_addr = fsl_chan->dma_dev_addr; > soff = fsl_chan->cfg.dst_addr_width; > doff = 0; > } else { > -