Re: [PATCH] dmaengine: fsl-edma: dma map slave device address

2019-02-03 Thread Vinod Koul
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

2019-01-21 Thread Laurentiu Tudor
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

2019-01-18 Thread Angelo Dureghello
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 {
> - 

[PATCH] dmaengine: fsl-edma: dma map slave device address

2019-01-18 Thread Laurentiu Tudor
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 {
-   src_addr = fsl_chan->cfg.src_addr;
+   src_addr = fsl_chan->dma_dev_addr;
dst_addr = sg_dma_address(sg);
soff = 0;