Re: [PATCH v3 6/6] iommu/ipmmu-vmsa: Add utlb_offset_base

2019-11-06 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your patch,

On 2019-11-06 11:35:50 +0900, Yoshihiro Shimoda wrote:
> Since we will have changed memory mapping of the IPMMU in the future,
> this patch adds a utlb_offset_base into struct ipmmu_features
> for IMUCTR and IMUASID registers. No behavior change.
> 
> Signed-off-by: Yoshihiro Shimoda 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 82da486..c813436 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -52,6 +52,7 @@ struct ipmmu_features {
>   bool cache_snoop;
>   unsigned int ctx_offset_base;
>   unsigned int ctx_offset_stride;
> + unsigned int utlb_offset_base;
>  };
>  
>  struct ipmmu_vmsa_device {
> @@ -232,7 +233,7 @@ static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain 
> *domain,
>  
>  static u32 ipmmu_utlb_reg(struct ipmmu_vmsa_device *mmu, unsigned int reg)
>  {
> - return reg;
> + return mmu->features->utlb_offset_base + reg;
>  }
>  
>  static void ipmmu_imuasid_write(struct ipmmu_vmsa_device *mmu,
> @@ -958,6 +959,7 @@ static const struct ipmmu_features ipmmu_features_default 
> = {
>   .cache_snoop = true,
>   .ctx_offset_base = 0,
>   .ctx_offset_stride = 0x40,
> + .utlb_offset_base = 0,
>  };
>  
>  static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
> @@ -971,6 +973,7 @@ static const struct ipmmu_features 
> ipmmu_features_rcar_gen3 = {
>   .cache_snoop = false,
>   .ctx_offset_base = 0,
>   .ctx_offset_stride = 0x40,
> + .utlb_offset_base = 0,
>  };
>  
>  static const struct of_device_id ipmmu_of_ids[] = {
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 5/6] iommu/ipmmu-vmsa: Add helper functions for "uTLB" registers

2019-11-06 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your work,

On 2019-11-06 11:35:49 +0900, Yoshihiro Shimoda wrote:
> Since we will have changed memory mapping of the IPMMU in the future,
> This patch adds helper functions ipmmu_utlb_reg() and
> ipmmu_imu{asid,ctr}_write() for "uTLB" registers. No behavior change.
> 
> Signed-off-by: Yoshihiro Shimoda 
> Reviewed-by: Geert Uytterhoeven 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 26 +-
>  1 file changed, 21 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 8e2ca1c..82da486 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -230,6 +230,23 @@ static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain 
> *domain,
>   ipmmu_ctx_write(domain->mmu->root, domain->context_id, reg, data);
>  }
>  
> +static u32 ipmmu_utlb_reg(struct ipmmu_vmsa_device *mmu, unsigned int reg)
> +{
> + return reg;
> +}
> +
> +static void ipmmu_imuasid_write(struct ipmmu_vmsa_device *mmu,
> + unsigned int utlb, u32 data)
> +{
> + ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUASID(utlb)), data);
> +}
> +
> +static void ipmmu_imuctr_write(struct ipmmu_vmsa_device *mmu,
> +unsigned int utlb, u32 data)
> +{
> + ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUCTR(utlb)), data);
> +}
> +
>  /* 
> -
>   * TLB and microTLB Management
>   */
> @@ -275,11 +292,10 @@ static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain 
> *domain,
>*/
>  
>   /* TODO: What should we set the ASID to ? */
> - ipmmu_write(mmu, IMUASID(utlb), 0);
> + ipmmu_imuasid_write(mmu, utlb, 0);
>   /* TODO: Do we need to flush the microTLB ? */
> - ipmmu_write(mmu, IMUCTR(utlb),
> - IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
> - IMUCTR_MMUEN);
> + ipmmu_imuctr_write(mmu, utlb, IMUCTR_TTSEL_MMU(domain->context_id) |
> +   IMUCTR_FLUSH | IMUCTR_MMUEN);
>   mmu->utlb_ctx[utlb] = domain->context_id;
>  }
>  
> @@ -291,7 +307,7 @@ static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain 
> *domain,
>  {
>   struct ipmmu_vmsa_device *mmu = domain->mmu;
>  
> - ipmmu_write(mmu, IMUCTR(utlb), 0);
> + ipmmu_imuctr_write(mmu, utlb, 0);
>   mmu->utlb_ctx[utlb] = IPMMU_CTX_INVALID;
>  }
>  
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 4/6] iommu/ipmmu-vmsa: Calculate context registers' offset instead of a macro

2019-11-06 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your patch,

On 2019-11-06 11:35:48 +0900, Yoshihiro Shimoda wrote:
> Since we will have changed memory mapping of the IPMMU in the future,
> this patch uses ipmmu_features values instead of a macro to
> calculate context registers offset. No behavior change.
> 
> Signed-off-by: Yoshihiro Shimoda 
> Reviewed-by: Geert Uytterhoeven 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 11 ---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index c4fcfda..8e2ca1c 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -50,6 +50,8 @@ struct ipmmu_features {
>   bool twobit_imttbcr_sl0;
>   bool reserved_context;
>   bool cache_snoop;
> + unsigned int ctx_offset_base;
> + unsigned int ctx_offset_stride;
>  };
>  
>  struct ipmmu_vmsa_device {
> @@ -99,8 +101,6 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  
>  #define IM_NS_ALIAS_OFFSET   0x800
>  
> -#define IM_CTX_SIZE  0x40
> -
>  /* MMU "context" registers */
>  #define IMCTR0x  /* R-Car Gen2/3 
> */
>  #define IMCTR_INTEN  (1 << 2)/* R-Car Gen2/3 */
> @@ -193,7 +193,8 @@ static void ipmmu_write(struct ipmmu_vmsa_device *mmu, 
> unsigned int offset,
>  static unsigned int ipmmu_ctx_reg(struct ipmmu_vmsa_device *mmu,
> unsigned int context_id, unsigned int reg)
>  {
> - return context_id * IM_CTX_SIZE + reg;
> + return mmu->features->ctx_offset_base +
> +context_id * mmu->features->ctx_offset_stride + reg;
>  }
>  
>  static u32 ipmmu_ctx_read(struct ipmmu_vmsa_device *mmu,
> @@ -939,6 +940,8 @@ static const struct ipmmu_features ipmmu_features_default 
> = {
>   .twobit_imttbcr_sl0 = false,
>   .reserved_context = false,
>   .cache_snoop = true,
> + .ctx_offset_base = 0,
> + .ctx_offset_stride = 0x40,
>  };
>  
>  static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
> @@ -950,6 +953,8 @@ static const struct ipmmu_features 
> ipmmu_features_rcar_gen3 = {
>   .twobit_imttbcr_sl0 = true,
>   .reserved_context = true,
>   .cache_snoop = false,
> + .ctx_offset_base = 0,
> + .ctx_offset_stride = 0x40,
>  };
>  
>  static const struct of_device_id ipmmu_of_ids[] = {
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 3/6] iommu/ipmmu-vmsa: Add helper functions for MMU "context" registers

2019-11-06 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your work,

On 2019-11-06 11:35:47 +0900, Yoshihiro Shimoda wrote:
> Since we will have changed memory mapping of the IPMMU in the future,
> This patch adds helper functions ipmmu_ctx_{reg,read,write}()
> for MMU "context" registers. No behavior change.
> 
> Signed-off-by: Yoshihiro Shimoda 
> Reviewed-by: Geert Uytterhoeven 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 32 +++-
>  1 file changed, 23 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 79975e1..c4fcfda 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -190,29 +190,43 @@ static void ipmmu_write(struct ipmmu_vmsa_device *mmu, 
> unsigned int offset,
>   iowrite32(data, mmu->base + offset);
>  }
>  
> +static unsigned int ipmmu_ctx_reg(struct ipmmu_vmsa_device *mmu,
> +   unsigned int context_id, unsigned int reg)
> +{
> + return context_id * IM_CTX_SIZE + reg;
> +}
> +
> +static u32 ipmmu_ctx_read(struct ipmmu_vmsa_device *mmu,
> +   unsigned int context_id, unsigned int reg)
> +{
> + return ipmmu_read(mmu, ipmmu_ctx_reg(mmu, context_id, reg));
> +}
> +
> +static void ipmmu_ctx_write(struct ipmmu_vmsa_device *mmu,
> + unsigned int context_id, unsigned int reg, u32 data)
> +{
> + ipmmu_write(mmu, ipmmu_ctx_reg(mmu, context_id, reg), data);
> +}
> +
>  static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
>  unsigned int reg)
>  {
> - return ipmmu_read(domain->mmu->root,
> -   domain->context_id * IM_CTX_SIZE + reg);
> + return ipmmu_ctx_read(domain->mmu->root, domain->context_id, reg);
>  }
>  
>  static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
>unsigned int reg, u32 data)
>  {
> - ipmmu_write(domain->mmu->root,
> - domain->context_id * IM_CTX_SIZE + reg, data);
> + ipmmu_ctx_write(domain->mmu->root, domain->context_id, reg, data);
>  }
>  
>  static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
>   unsigned int reg, u32 data)
>  {
>   if (domain->mmu != domain->mmu->root)
> - ipmmu_write(domain->mmu,
> - domain->context_id * IM_CTX_SIZE + reg, data);
> + ipmmu_ctx_write(domain->mmu, domain->context_id, reg, data);
>  
> - ipmmu_write(domain->mmu->root,
> - domain->context_id * IM_CTX_SIZE + reg, data);
> + ipmmu_ctx_write(domain->mmu->root, domain->context_id, reg, data);
>  }
>  
>  /* 
> -
> @@ -913,7 +927,7 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device 
> *mmu)
>  
>   /* Disable all contexts. */
>   for (i = 0; i < mmu->num_ctx; ++i)
> - ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
> + ipmmu_ctx_write(mmu, i, IMCTR, 0);
>  }
>  
>  static const struct ipmmu_features ipmmu_features_default = {
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 2/6] iommu/ipmmu-vmsa: tidyup register definitions

2019-11-06 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your patch,

On 2019-11-06 11:35:46 +0900, Yoshihiro Shimoda wrote:
> To support different registers memory mapping hardware easily
> in the future, this patch tidies up the register definitions
> as below:
>  - Add comments to state to which SoCs or SoC families they apply
>  - Add categories about MMU "context" and uTLB registers
> 
> No change behavior.
> 
> Signed-off-by: Yoshihiro Shimoda 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 58 
> --
>  1 file changed, 30 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index c4ec166..79975e1 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -101,47 +101,49 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  
>  #define IM_CTX_SIZE  0x40
>  
> -#define IMCTR0x
> -#define IMCTR_INTEN  (1 << 2)
> -#define IMCTR_FLUSH  (1 << 1)
> -#define IMCTR_MMUEN  (1 << 0)
> -
> -#define IMTTBCR  0x0008
> -#define IMTTBCR_EAE  (1 << 31)
> +/* MMU "context" registers */
> +#define IMCTR0x  /* R-Car Gen2/3 
> */
> +#define IMCTR_INTEN  (1 << 2)/* R-Car Gen2/3 */
> +#define IMCTR_FLUSH  (1 << 1)/* R-Car Gen2/3 */
> +#define IMCTR_MMUEN  (1 << 0)/* R-Car Gen2/3 */
> +
> +#define IMTTBCR  0x0008  /* R-Car Gen2/3 
> */
> +#define IMTTBCR_EAE  (1 << 31)   /* R-Car Gen2/3 */
>  #define IMTTBCR_SH0_INNER_SHAREABLE  (3 << 12)   /* R-Car Gen2 only */
>  #define IMTTBCR_ORGN0_WB_WA  (1 << 10)   /* R-Car Gen2 only */
>  #define IMTTBCR_IRGN0_WB_WA  (1 << 8)/* R-Car Gen2 only */
>  #define IMTTBCR_SL0_TWOBIT_LVL_1 (2 << 6)/* R-Car Gen3 only */
> -#define IMTTBCR_SL0_LVL_1(1 << 4)
> +#define IMTTBCR_SL0_LVL_1(1 << 4)/* R-Car Gen2 only */
>  
> -#define IMBUSCR  0x000c
> -#define IMBUSCR_DVM  (1 << 2)
> -#define IMBUSCR_BUSSEL_MASK  (3 << 0)
> +#define IMBUSCR  0x000c  /* R-Car Gen2 
> only */
> +#define IMBUSCR_DVM  (1 << 2)/* R-Car Gen2 only */
> +#define IMBUSCR_BUSSEL_MASK  (3 << 0)/* R-Car Gen2 only */
>  
> -#define IMTTLBR0 0x0010
> -#define IMTTUBR0 0x0014
> +#define IMTTLBR0 0x0010  /* R-Car Gen2/3 */
> +#define IMTTUBR0 0x0014  /* R-Car Gen2/3 */
>  
> -#define IMSTR0x0020
> -#define IMSTR_MHIT   (1 << 4)
> -#define IMSTR_ABORT  (1 << 2)
> -#define IMSTR_PF (1 << 1)
> -#define IMSTR_TF (1 << 0)
> +#define IMSTR0x0020  /* R-Car Gen2/3 
> */
> +#define IMSTR_MHIT   (1 << 4)/* R-Car Gen2/3 */
> +#define IMSTR_ABORT  (1 << 2)/* R-Car Gen2/3 */
> +#define IMSTR_PF (1 << 1)/* R-Car Gen2/3 */
> +#define IMSTR_TF (1 << 0)/* R-Car Gen2/3 */
>  
> -#define IMMAIR0  0x0028
> +#define IMMAIR0  0x0028  /* R-Car Gen2/3 
> */
>  
> -#define IMELAR   0x0030  /* IMEAR on R-Car Gen2 
> */
> -#define IMEUAR   0x0034  /* R-Car Gen3 only */
> +#define IMELAR   0x0030  /* R-Car 
> Gen2/3, IMEAR on R-Car Gen2 */
> +#define IMEUAR   0x0034  /* R-Car Gen3 
> only */
>  
> +/* uTLB registers */
>  #define IMUCTR(n)((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
> -#define IMUCTR0(n)   (0x0300 + ((n) * 16))
> -#define IMUCTR32(n)  (0x0600 + (((n) - 32) * 16))
> -#define IMUCTR_TTSEL_MMU(n)  ((n) << 4)
> -#define IMUCTR_FLUSH (1 << 1)
> -#define IMUCTR_MMUEN (1 << 0)
> +#define IMUCTR0(n)   (0x0300 + ((n) * 16))   /* 
> R-Car Gen2/3 */
> +#define IMUCTR32(n)  (0x0600 + (((n)

Re: [PATCH v3 1/6] iommu/ipmmu-vmsa: Remove all unused register definitions

2019-11-06 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your work.

On 2019-11-06 11:35:45 +0900, Yoshihiro Shimoda wrote:
> To support different registers memory mapping hardware easily
> in the future, this patch removes all unused register
> definitions.
> 
> Signed-off-by: Yoshihiro Shimoda 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 76 
> --
>  1 file changed, 76 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 5904c23..c4ec166 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -102,122 +102,46 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct 
> device *dev)
>  #define IM_CTX_SIZE  0x40
>  
>  #define IMCTR0x
> -#define IMCTR_TRE(1 << 17)
> -#define IMCTR_AFE(1 << 16)
> -#define IMCTR_RTSEL_MASK (3 << 4)
> -#define IMCTR_RTSEL_SHIFT4
> -#define IMCTR_TREN   (1 << 3)
>  #define IMCTR_INTEN  (1 << 2)
>  #define IMCTR_FLUSH  (1 << 1)
>  #define IMCTR_MMUEN  (1 << 0)
>  
> -#define IMCAAR   0x0004
> -
>  #define IMTTBCR  0x0008
>  #define IMTTBCR_EAE  (1 << 31)
> -#define IMTTBCR_PMB  (1 << 30)
> -#define IMTTBCR_SH1_NON_SHAREABLE(0 << 28)   /* R-Car Gen2 only */
> -#define IMTTBCR_SH1_OUTER_SHAREABLE  (2 << 28)   /* R-Car Gen2 only */
> -#define IMTTBCR_SH1_INNER_SHAREABLE  (3 << 28)   /* R-Car Gen2 only */
> -#define IMTTBCR_SH1_MASK (3 << 28)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN1_NC (0 << 26)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN1_WB_WA  (1 << 26)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN1_WT (2 << 26)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN1_WB (3 << 26)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN1_MASK   (3 << 26)   /* R-Car Gen2 only */
> -#define IMTTBCR_IRGN1_NC (0 << 24)   /* R-Car Gen2 only */
> -#define IMTTBCR_IRGN1_WB_WA  (1 << 24)   /* R-Car Gen2 only */
> -#define IMTTBCR_IRGN1_WT (2 << 24)   /* R-Car Gen2 only */
> -#define IMTTBCR_IRGN1_WB (3 << 24)   /* R-Car Gen2 only */
> -#define IMTTBCR_IRGN1_MASK   (3 << 24)   /* R-Car Gen2 only */
> -#define IMTTBCR_TSZ1_MASK(7 << 16)
> -#define IMTTBCR_TSZ1_SHIFT   16
> -#define IMTTBCR_SH0_NON_SHAREABLE(0 << 12)   /* R-Car Gen2 only */
> -#define IMTTBCR_SH0_OUTER_SHAREABLE  (2 << 12)   /* R-Car Gen2 only */
>  #define IMTTBCR_SH0_INNER_SHAREABLE  (3 << 12)   /* R-Car Gen2 only */
> -#define IMTTBCR_SH0_MASK (3 << 12)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN0_NC (0 << 10)   /* R-Car Gen2 only */
>  #define IMTTBCR_ORGN0_WB_WA  (1 << 10)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN0_WT (2 << 10)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN0_WB (3 << 10)   /* R-Car Gen2 only */
> -#define IMTTBCR_ORGN0_MASK   (3 << 10)   /* R-Car Gen2 only */
> -#define IMTTBCR_IRGN0_NC (0 << 8)/* R-Car Gen2 only */
>  #define IMTTBCR_IRGN0_WB_WA  (1 << 8)/* R-Car Gen2 only */
> -#define IMTTBCR_IRGN0_WT (2 << 8)/* R-Car Gen2 only */
> -#define IMTTBCR_IRGN0_WB (3 << 8)/* R-Car Gen2 only */
> -#define IMTTBCR_IRGN0_MASK   (3 << 8)/* R-Car Gen2 only */
> -#define IMTTBCR_SL0_TWOBIT_LVL_3 (0 << 6)/* R-Car Gen3 only */
> -#define IMTTBCR_SL0_TWOBIT_LVL_2 (1 << 6)/* R-Car Gen3 only */
>  #define IMTTBCR_SL0_TWOBIT_LVL_1 (2 << 6)/* R-Car Gen3 only */
> -#define IMTTBCR_SL0_LVL_2(0 << 4)
>  #define IMTTBCR_SL0_LVL_1(1 << 4)
> -#define IMTTBCR_TSZ0_MASK(7 << 0)
> -#define IMTTBCR_TSZ0_SHIFT   O
>  
>  #define IMBUSCR  0x000c
>  #define IMBUSCR_DVM  (1 << 2)
> -#define IMBUSCR_BUSSEL_SYS   (0 << 0)
> -#define IMBUSCR_BUSSEL_CCI   (1 << 0)
> -#define IMBUSCR_BUSSEL_IMCAAR(2 << 0)
> -#define IMBUSCR_BUSSEL_CCI_IMCAAR(3 << 0)
>  #define IMBUSCR_BUSSEL_MASK  (3 << 0)

Re: [PATCH 3/3] iommu/ipmmu-vmsa: Add utlb_offset_base

2019-10-09 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your patch.

On 2019-10-09 17:26:49 +0900, Yoshihiro Shimoda wrote:
> Since we will have changed memory mapping of the IPMMU in the future,
> this patch adds a utlb_offset_base into struct ipmmu_features
> for IMUCTR and IMUASID registers.
> No behavior change.
> 
> Signed-off-by: Yoshihiro Shimoda 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 14 +++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 76fb250..bc00e58 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -52,6 +52,7 @@ struct ipmmu_features {
>   bool cache_snoop;
>   u32 ctx_offset_base;
>   u32 ctx_offset_stride;
> + u32 utlb_offset_base;
>  };
>  
>  struct ipmmu_vmsa_device {
> @@ -285,6 +286,11 @@ static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain 
> *domain,
>   ipmmu_ctx_write_root(domain, reg, data);
>  }
>  
> +static u32 ipmmu_utlb_reg(struct ipmmu_vmsa_device *mmu, unsigned int reg)
> +{
> + return mmu->features->utlb_offset_base + reg;
> +}
> +
>  /* 
> -
>   * TLB and microTLB Management
>   */
> @@ -330,9 +336,9 @@ static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain 
> *domain,
>*/
>  
>   /* TODO: What should we set the ASID to ? */
> - ipmmu_write(mmu, IMUASID(utlb), 0);
> + ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUASID(utlb)), 0);
>   /* TODO: Do we need to flush the microTLB ? */
> - ipmmu_write(mmu, IMUCTR(utlb),
> + ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUCTR(utlb)),
>   IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH |
>   IMUCTR_MMUEN);
>   mmu->utlb_ctx[utlb] = domain->context_id;
> @@ -346,7 +352,7 @@ static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain 
> *domain,
>  {
>   struct ipmmu_vmsa_device *mmu = domain->mmu;
>  
> - ipmmu_write(mmu, IMUCTR(utlb), 0);
> + ipmmu_write(mmu, ipmmu_utlb_reg(mmu, IMUCTR(utlb)), 0);
>   mmu->utlb_ctx[utlb] = IPMMU_CTX_INVALID;
>  }
>  
> @@ -995,6 +1001,7 @@ static const struct ipmmu_features 
> ipmmu_features_default = {
>   .cache_snoop = true,
>   .ctx_offset_base = 0,
>   .ctx_offset_stride = 0x40,
> + .utlb_offset_base = 0,
>  };
>  
>  static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
> @@ -1008,6 +1015,7 @@ static const struct ipmmu_features 
> ipmmu_features_rcar_gen3 = {
>   .cache_snoop = false,
>   .ctx_offset_base = 0,
>   .ctx_offset_stride = 0x40,
> + .utlb_offset_base = 0,
>  };
>  
>  static const struct of_device_id ipmmu_of_ids[] = {
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund


Re: [PATCH 2/3] iommu/ipmmu-vmsa: Calculate context registers' offset instead of a macro

2019-10-09 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your patch.

On 2019-10-09 17:26:48 +0900, Yoshihiro Shimoda wrote:
> Since we will have changed memory mapping of the IPMMU in the future,
> this patch uses ipmmu_features values instead of a macro to
> calculate context registers offset. No behavior change.
> 
> Signed-off-by: Yoshihiro Shimoda 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 27 +++
>  1 file changed, 19 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index dd554c2..76fb250 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -50,6 +50,8 @@ struct ipmmu_features {
>   bool twobit_imttbcr_sl0;
>   bool reserved_context;
>   bool cache_snoop;
> + u32 ctx_offset_base;
> + u32 ctx_offset_stride;
>  };
>  
>  struct ipmmu_vmsa_device {
> @@ -99,8 +101,6 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  
>  #define IM_NS_ALIAS_OFFSET   0x800
>  
> -#define IM_CTX_SIZE  0x40
> -
>  #define IMCTR0x
>  #define IMCTR_TRE(1 << 17)
>  #define IMCTR_AFE(1 << 16)
> @@ -253,18 +253,25 @@ static void ipmmu_write(struct ipmmu_vmsa_device *mmu, 
> unsigned int offset,
>   iowrite32(data, mmu->base + offset);
>  }
>  
> +static u32 ipmmu_ctx_reg(struct ipmmu_vmsa_device *mmu, unsigned int 
> context_id,
> +  unsigned int reg)
> +{
> + return mmu->features->ctx_offset_base +
> +context_id * mmu->features->ctx_offset_stride + reg;
> +}
> +
>  static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
>  unsigned int reg)
>  {
>   return ipmmu_read(domain->mmu->root,
> -   domain->context_id * IM_CTX_SIZE + reg);
> +   ipmmu_ctx_reg(domain->mmu, domain->context_id, reg));
>  }
>  
>  static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
>unsigned int reg, u32 data)
>  {
>   ipmmu_write(domain->mmu->root,
> - domain->context_id * IM_CTX_SIZE + reg, data);
> + ipmmu_ctx_reg(domain->mmu, domain->context_id, reg), data);
>  }
>  
>  static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
> @@ -272,10 +279,10 @@ static void ipmmu_ctx_write_all(struct 
> ipmmu_vmsa_domain *domain,
>  {
>   if (domain->mmu != domain->mmu->root)
>   ipmmu_write(domain->mmu,
> - domain->context_id * IM_CTX_SIZE + reg, data);
> + ipmmu_ctx_reg(domain->mmu, domain->context_id, reg),
> + data);
>  
> - ipmmu_write(domain->mmu->root,
> - domain->context_id * IM_CTX_SIZE + reg, data);
> + ipmmu_ctx_write_root(domain, reg, data);
>  }
>  
>  /* 
> -
> @@ -974,7 +981,7 @@ static void ipmmu_device_reset(struct ipmmu_vmsa_device 
> *mmu)
>  
>   /* Disable all contexts. */
>   for (i = 0; i < mmu->num_ctx; ++i)
> - ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
> + ipmmu_write(mmu, ipmmu_ctx_reg(mmu, i, IMCTR), 0);
>  }
>  
>  static const struct ipmmu_features ipmmu_features_default = {
> @@ -986,6 +993,8 @@ static const struct ipmmu_features ipmmu_features_default 
> = {
>   .twobit_imttbcr_sl0 = false,
>   .reserved_context = false,
>   .cache_snoop = true,
> + .ctx_offset_base = 0,
> + .ctx_offset_stride = 0x40,
>  };
>  
>  static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
> @@ -997,6 +1006,8 @@ static const struct ipmmu_features 
> ipmmu_features_rcar_gen3 = {
>   .twobit_imttbcr_sl0 = true,
>   .reserved_context = true,
>   .cache_snoop = false,
> + .ctx_offset_base = 0,
> + .ctx_offset_stride = 0x40,
>  };
>  
>  static const struct of_device_id ipmmu_of_ids[] = {
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund


Re: [PATCH 1/3] iommu/ipmmu-vmsa: Remove some unused register declarations

2019-10-09 Thread Niklas Söderlund
Hi Shimoda-san,

Thanks for your patch.

On 2019-10-09 17:26:47 +0900, Yoshihiro Shimoda wrote:
> To support different registers memory mapping hardware easily
> in the future, this patch removes some unused register
> declarations.
> 
> Signed-off-by: Yoshihiro Shimoda 

Reviewed-by: Niklas Söderlund 

> ---
>  drivers/iommu/ipmmu-vmsa.c | 11 ---
>  1 file changed, 11 deletions(-)
> 
> diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
> index 9da8309..dd554c2 100644
> --- a/drivers/iommu/ipmmu-vmsa.c
> +++ b/drivers/iommu/ipmmu-vmsa.c
> @@ -104,8 +104,6 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  #define IMCTR0x
>  #define IMCTR_TRE(1 << 17)
>  #define IMCTR_AFE(1 << 16)
> -#define IMCTR_RTSEL_MASK (3 << 4)
> -#define IMCTR_RTSEL_SHIFT4
>  #define IMCTR_TREN   (1 << 3)
>  #define IMCTR_INTEN  (1 << 2)
>  #define IMCTR_FLUSH  (1 << 1)
> @@ -115,7 +113,6 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  
>  #define IMTTBCR  0x0008
>  #define IMTTBCR_EAE  (1 << 31)
> -#define IMTTBCR_PMB  (1 << 30)
>  #define IMTTBCR_SH1_NON_SHAREABLE(0 << 28)   /* R-Car Gen2 only */
>  #define IMTTBCR_SH1_OUTER_SHAREABLE  (2 << 28)   /* R-Car Gen2 only */
>  #define IMTTBCR_SH1_INNER_SHAREABLE  (3 << 28)   /* R-Car Gen2 only */
> @@ -193,12 +190,6 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  #define IMELAR   0x0030  /* IMEAR on R-Car Gen2 
> */
>  #define IMEUAR   0x0034  /* R-Car Gen3 only */
>  
> -#define IMPCTR   0x0200
> -#define IMPSTR   0x0208
> -#define IMPEAR   0x020c
> -#define IMPMBA(n)(0x0280 + ((n) * 4))
> -#define IMPMBD(n)(0x02c0 + ((n) * 4))
> -
>  #define IMUCTR(n)((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
>  #define IMUCTR0(n)   (0x0300 + ((n) * 16))
>  #define IMUCTR32(n)  (0x0600 + (((n) - 32) * 16))
> @@ -206,8 +197,6 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device 
> *dev)
>  #define IMUCTR_FIXADD_MASK   (0xff << 16)
>  #define IMUCTR_FIXADD_SHIFT  16
>  #define IMUCTR_TTSEL_MMU(n)  ((n) << 4)
> -#define IMUCTR_TTSEL_PMB (8 << 4)
> -#define IMUCTR_TTSEL_MASK(15 << 4)
>  #define IMUCTR_FLUSH (1 << 1)
>  #define IMUCTR_MMUEN (1 << 0)
>  
> -- 
> 2.7.4
> 

-- 
Regards,
Niklas Söderlund


Re: [PATCH] dma-mapping: fix return type of dma_set_max_seg_size()

2018-11-26 Thread Niklas Söderlund
On 2018-11-02 11:22:54 +0100, Niklas Söderlund wrote:
> Hi,
> 
> A gentle ping on this patch.

A slightly harder ping :-)

> 
> On 2018-08-29 23:29:21 +0200, Niklas Söderlund wrote:
> > The function dma_set_max_seg_size() can return either 0 on success or
> > -EIO on error. Change its return type from unsigned int to int to
> > capture this.
> > 
> > Signed-off-by: Niklas Söderlund 
> > ---
> >  include/linux/dma-mapping.h | 3 +--
> >  1 file changed, 1 insertion(+), 2 deletions(-)
> > 
> > diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> > index 1db6a6b46d0d3dbd..669cde2fa8723ac5 100644
> > --- a/include/linux/dma-mapping.h
> > +++ b/include/linux/dma-mapping.h
> > @@ -674,8 +674,7 @@ static inline unsigned int dma_get_max_seg_size(struct 
> > device *dev)
> > return SZ_64K;
> >  }
> >  
> > -static inline unsigned int dma_set_max_seg_size(struct device *dev,
> > -   unsigned int size)
> > +static inline int dma_set_max_seg_size(struct device *dev, unsigned int 
> > size)
> >  {
> >     if (dev->dma_parms) {
> > dev->dma_parms->max_segment_size = size;
> > -- 
> > 2.18.0
> > 
> 
> -- 
> Regards,
> Niklas Söderlund

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] dma-mapping: fix return type of dma_set_max_seg_size()

2018-11-02 Thread Niklas Söderlund
Hi,

A gentle ping on this patch.

On 2018-08-29 23:29:21 +0200, Niklas Söderlund wrote:
> The function dma_set_max_seg_size() can return either 0 on success or
> -EIO on error. Change its return type from unsigned int to int to
> capture this.
> 
> Signed-off-by: Niklas Söderlund 
> ---
>  include/linux/dma-mapping.h | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
> index 1db6a6b46d0d3dbd..669cde2fa8723ac5 100644
> --- a/include/linux/dma-mapping.h
> +++ b/include/linux/dma-mapping.h
> @@ -674,8 +674,7 @@ static inline unsigned int dma_get_max_seg_size(struct 
> device *dev)
>   return SZ_64K;
>  }
>  
> -static inline unsigned int dma_set_max_seg_size(struct device *dev,
> - unsigned int size)
> +static inline int dma_set_max_seg_size(struct device *dev, unsigned int size)
>  {
>   if (dev->dma_parms) {
>   dev->dma_parms->max_segment_size = size;
> -- 
> 2.18.0
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] dma-mapping: fix return type of dma_set_max_seg_size()

2018-08-29 Thread Niklas Söderlund
The function dma_set_max_seg_size() can return either 0 on success or
-EIO on error. Change its return type from unsigned int to int to
capture this.

Signed-off-by: Niklas Söderlund 
---
 include/linux/dma-mapping.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 1db6a6b46d0d3dbd..669cde2fa8723ac5 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -674,8 +674,7 @@ static inline unsigned int dma_get_max_seg_size(struct 
device *dev)
return SZ_64K;
 }
 
-static inline unsigned int dma_set_max_seg_size(struct device *dev,
-   unsigned int size)
+static inline int dma_set_max_seg_size(struct device *dev, unsigned int size)
 {
if (dev->dma_parms) {
dev->dma_parms->max_segment_size = size;
-- 
2.18.0

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCHv9 6/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2017-01-09 Thread Niklas Söderlund
Hi Laurent,

On 2017-01-02 01:08:04 +0200, Laurent Pinchart wrote:
> Hi Niklas,
> 
> On Monday 05 Sep 2016 12:52:44 Laurent Pinchart wrote:
> > On Wednesday 10 Aug 2016 13:22:19 Niklas Söderlund wrote:
> > > Enable slave transfers to a device behind a IPMMU by mapping the slave
> > > addresses using the dma-mapping API.
> > > 
> > > Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
> > > ---
> > > drivers/dma/sh/rcar-dmac.c | 82 -
> > > 1 file changed, 74 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> > > index cf983a9..22a5e40 100644
> > > --- a/drivers/dma/sh/rcar-dmac.c
> > > +++ b/drivers/dma/sh/rcar-dmac.c
> 
> [snip]
> 
> > > +static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
> > > + enum dma_transfer_direction dir)
> > > +{
> > > + struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
> > > + struct rcar_dmac_chan_map *map = >map;
> > > + phys_addr_t dev_addr;
> > > + size_t dev_size;
> > > + enum dma_data_direction dev_dir;
> > > +
> > > + if (dir == DMA_DEV_TO_MEM) {
> > > + dev_addr = rchan->src.slave_addr;
> > > + dev_size = rchan->src.xfer_size;
> > > + dev_dir = DMA_TO_DEVICE;
> > 
> > Shouldn't this be DMA_FROM_DEVICE, and DMA_TO_DEVICE below ?
> 
> This comment can be ignored (thank you Robin for the explanation), but ...
> 
> > > + } else {
> > > + dev_addr = rchan->dst.slave_addr;
> > > + dev_size = rchan->dst.xfer_size;
> > > + dev_dir = DMA_FROM_DEVICE;
> > > + }
> > > +
> > > + /* Reuse current map if possible. */
> > > + if (dev_addr == map->slave.slave_addr &&
> > > + dev_size == map->slave.xfer_size &&
> > > + dev_dir == map->dir)
> > > + return 0;
> > > +
> > > + /* Remove old mapping if present. */
> > > + if (map->slave.xfer_size)
> > > + dma_unmap_resource(chan->device->dev, map->addr,
> > > +map->slave.xfer_size, map->dir, 0);
> > 
> > Unless I'm mistaken the resource will not be unmapped when freeing channel
> > resources, will it ?
> 
> I believe this one still needs to be addressed.

I believe you are correct, I will look in to it and hopefully submit a 
patch to address it. Thanks for brining it up.

> 
> > > + map->slave.xfer_size = 0;
> > > +
> > > + /* Create new slave address map. */
> > > + map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
> > > +  dev_dir, 0);
> > > +
> > > + if (dma_mapping_error(chan->device->dev, map->addr)) {
> > > + dev_err(chan->device->dev,
> > > + "chan%u: failed to map %zx@%pap", rchan->index,
> > > + dev_size, _addr);
> > > + return -EIO;
> > > + }
> > > +
> > > + dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
> > > + rchan->index, dev_size, _addr, >addr,
> > 
> > > + dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" :
> > "DMA_FROM_DEVICE");
> > 
> > > +
> > > + map->slave.slave_addr = dev_addr;
> > > + map->slave.xfer_size = dev_size;
> > > + map->dir = dev_dir;
> > > +
> > > + return 0;
> > > +}
> 
> [snip]
> 
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] dma-debug: fix ia64 build, use PHYS_PFN

2016-09-29 Thread Niklas Söderlund
kbuild test robot reports:

   lib/dma-debug.c: In function 'debug_dma_map_resource':
>> lib/dma-debug.c:1541:16: error: implicit declaration of function 
>> '__phys_to_pfn' [-Werror=implicit-function-declaration]
 entry->pfn  = __phys_to_pfn(addr);
   ^

ia64 does not provide __phys_to_pfn(), use the PHYS_PFN() alias.

Fixes: 0e74b34dfc3318bf ("dma-debug: add support for resource mappings")
Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 lib/dma-debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 2ba086b..59e7586 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -1514,7 +1514,7 @@ void debug_dma_map_resource(struct device *dev, 
phys_addr_t addr, size_t size,
 
entry->type = dma_debug_resource;
entry->dev  = dev;
-   entry->pfn  = __phys_to_pfn(addr);
+   entry->pfn  = PHYS_PFN(addr);
entry->offset   = offset_in_page(addr);
entry->size = size;
entry->dev_addr = dma_addr;
-- 
2.9.3

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH 0/2] dma-mapping: fix ia64 and m32r build error and warnings

2016-09-29 Thread Niklas Söderlund
On 2016-09-29 17:40:04 +0530, Vinod Koul wrote:
> On Thu, Sep 29, 2016 at 12:02:38PM +0200, Niklas Söderlund wrote:
> > From: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
> > 
> > Hi Vindo,
> 
> :(

I'm sorry, my hands sometimes moves faster then my head.

> 
> > 
> > This small series fixes the build error and warnings for ia64 and m32r 
> > which kbuild test robot found and where introduced in the series 
> > '[PATCHv9 0/6] dmaengine: rcar-dmac: add iommu support for slave 
> > transfers'.
> 
> Applied both

Thanks.

> 
> Thanks
> -- 
> ~Vinod

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 2/2] dma-mapping: fix m32r build warning

2016-09-29 Thread Niklas Söderlund
From: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>

kbuild test robot reports:

   In file included from include/linux/skbuff.h:34:0,
from include/linux/icmpv6.h:4,
from include/linux/ipv6.h:75,
from include/net/ipv6.h:16,
from include/linux/sunrpc/clnt.h:27,
from include/linux/nfs_fs.h:30,
from fs/lockd/clntlock.c:13:
   include/linux/dma-mapping.h: In function 'dma_map_resource':
>> include/linux/dma-mapping.h:274:16: warning: unused variable 'pfn' 
>> [-Wunused-variable]
 unsigned long pfn = __phys_to_pfn(phys_addr);
   ^~~

The pfn value is only used once in the call to pfn_valid(), remove the
variable and calculate the pfn when it's needed. Note that the kbuild
report is old and PHYS_PFN() is now used instead of __phys_to_pfn() to
calculate the pfn.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index ff7c87f..642cb4c 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -271,13 +271,12 @@ static inline dma_addr_t dma_map_resource(struct device 
*dev,
  unsigned long attrs)
 {
struct dma_map_ops *ops = get_dma_ops(dev);
-   unsigned long pfn = PHYS_PFN(phys_addr);
dma_addr_t addr;
 
BUG_ON(!valid_dma_direction(dir));
 
/* Don't allow RAM to be mapped */
-   BUG_ON(pfn_valid(pfn));
+   BUG_ON(pfn_valid(PHYS_PFN(phys_addr)));
 
addr = phys_addr;
if (ops->map_resource)
-- 
2.9.3

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH 0/2] dma-mapping: fix ia64 and m32r build error and warnings

2016-09-29 Thread Niklas Söderlund
From: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>

Hi Vindo,

This small series fixes the build error and warnings for ia64 and m32r 
which kbuild test robot found and where introduced in the series 
'[PATCHv9 0/6] dmaengine: rcar-dmac: add iommu support for slave 
transfers'.

It is based ontop of:

git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/slave-dma.git next

The fixes are only compile tested for the ia64 and m32r architecture to 
show that the error and warnings are fixed. It is tested on ARM to prove 
that the intended functionality still works.

Kbuild test robot found one more class of warnings for the patch series 
mentioned above for the balackfin arch.

   include/linux/dma-mapping.h: In function 'dma_map_resource':
>> include/asm-generic/page.h:90:32: warning: comparison of unsigned expression 
>> >= 0 is always true [-Wtype-limits]
#define pfn_valid(pfn)  ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - 
ARCH_PFN_OFFSET) < max_mapnr)
   ^

These warnings are not addressed in this series since they are not new 
or unique to original patch. They come from how pfn_valid() is 
implemented in include/asm-generic/page.h, if ARCH_PFN_OFFSET is 0 the 
warning is triggered. On the kbuild blackfin build it is defined as 
'(0x0 >> 12)' so any invocation of pfn_valid() will trigger it.

I tried to fix it but was unable to find a good solution. There is a 
MIPS specific fix for this in commit 95486e4 (MIPS: Fix flood of 
warnings about comparsion being always true.), but a similar fix for 
asm-generic seems to tricky for me to attempt since the macro needs to 
be turned into a static inline function and that might be harmful.  I 
also toyed with the solution of '#if ARCH_PFN_OFFSET == 0' to provided 
an alternative pfn_valid() macro, but since ARCH_PFN_OFFSET is defined 
as an expression and not a constant that wont work. If you can think of 
another way I be happy to try that out and see if I can make it work.

Niklas Söderlund (2):
  dma-mapping: fix ia64 build, use PHYS_PFN
  dma-mapping: fix m32r build warning

 include/linux/dma-mapping.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

-- 
2.9.3

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH 1/2] dma-mapping: fix ia64 build, use PHYS_PFN

2016-09-29 Thread Niklas Söderlund
From: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>

kbuild test robot reports:

   In file included from include/linux/skbuff.h:34:0,
from include/linux/tcp.h:21,
from drivers/net/ethernet/amd/xgbe/xgbe-drv.c:119:
   include/linux/dma-mapping.h: In function 'dma_map_resource':
>> include/linux/dma-mapping.h:274:22: error: implicit declaration of function 
>> '__phys_to_pfn' [-Werror=implicit-function-declaration]
 unsigned long pfn = __phys_to_pfn(phys_addr);
 ^

ia64 does not provide __phys_to_pfn(), use the PHYS_PFN() alias.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 6e00c7f..ff7c87f 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -271,7 +271,7 @@ static inline dma_addr_t dma_map_resource(struct device 
*dev,
  unsigned long attrs)
 {
struct dma_map_ops *ops = get_dma_ops(dev);
-   unsigned long pfn = __phys_to_pfn(phys_addr);
+   unsigned long pfn = PHYS_PFN(phys_addr);
dma_addr_t addr;
 
BUG_ON(!valid_dma_direction(dir));
-- 
2.9.3

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCHv9 0/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-09-23 Thread Niklas Söderlund
Hi Vinod,

On 2016-09-15 21:56:51 +0530, Vinod Koul wrote:
> On Wed, Aug 10, 2016 at 11:07:10PM +0530, Vinod Koul wrote:
> > On Wed, Aug 10, 2016 at 01:22:13PM +0200, Niklas Söderlund wrote:
> > > Hi,
> > > 
> > > This series tries to solve the problem with DMA with device registers
> > > (MMIO registers) that are behind an IOMMU for the rcar-dmac driver. A
> > > recent patch '9575632 (dmaengine: make slave address physical)'
> > > clarifies that DMA slave address provided by clients is the physical
> > > address. This puts the task of mapping the DMA slave address from a
> > > phys_addr_t to a dma_addr_t on the DMA engine.
> > > 
> > > Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
> > > the same and no special care is needed. However if you have a IOMMU you
> > > need to map the DMA slave phys_addr_t to a dma_addr_t using something
> > > like this.
> > > 
> > > This series is based on top of v4.8-rc1. And I'm hoping to be able to 
> > > collect a
> > > Ack from Russell King on patch 4/6 that adds the ARM specific part and 
> > > then be
> > > able to take the whole series through the dmaengine tree. If this is not 
> > > the
> > > best route I'm more then happy to do it another way.
> > > 
> > > It's tested on a Koelsch with CONFIG_IPMMU_VMSA and by enabling the
> > > ipmmu_ds node in r8a7791.dtsi. I verified operation by interacting with
> > > /dev/mmcblk1, i2c and the serial console which are devices behind the
> > > iommu.
> > 
> > As I said in last one, the dmaengine parts look fine to me. But to go thru
> > dmaengine tree I would need ACK on non dmaengine patches.
> 
> I havent heard back from this one and I am inclined to merge this one now.
> If anyone has any objects, please speak up now...

I'm just curios, do you plan to merge this series with Arnds Ack? If not 
is there anything I can do to help move the series in the right 
direction?

> 
> Also ACKs welcome...
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCHv9 4/6] arm: dma-mapping: add {map,unmap}_resource for iommu ops

2016-08-23 Thread Niklas Söderlund
Hi Russell,

If you have the time can you please have a look at this patch? This 
series have been out for some time now and Vinod is willing to take it 
through the dmaengine tree but a ACK is needed on this patch from you 
first.

On 2016-08-10 13:22:17 +0200, Niklas Söderlund wrote:
> Add methods to map/unmap device resources addresses for dma_map_ops that
> are IOMMU aware. This is needed to map a device MMIO register from a
> physical address.
> 
> Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
> Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> ---
>  arch/arm/mm/dma-mapping.c | 63 
> +++
>  1 file changed, 63 insertions(+)
> 
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index c6834c0..746eb29 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -2014,6 +2014,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
> dma_addr_t handle,
>   __free_iova(mapping, iova, len);
>  }
>  
> +/**
> + * arm_iommu_map_resource - map a device resource for DMA
> + * @dev: valid struct device pointer
> + * @phys_addr: physical address of resource
> + * @size: size of resource to map
> + * @dir: DMA transfer direction
> + */
> +static dma_addr_t arm_iommu_map_resource(struct device *dev,
> + phys_addr_t phys_addr, size_t size,
> + enum dma_data_direction dir, unsigned long attrs)
> +{
> + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
> + dma_addr_t dma_addr;
> + int ret, prot;
> + phys_addr_t addr = phys_addr & PAGE_MASK;
> + unsigned int offset = phys_addr & ~PAGE_MASK;
> + size_t len = PAGE_ALIGN(size + offset);
> +
> + dma_addr = __alloc_iova(mapping, len);
> + if (dma_addr == DMA_ERROR_CODE)
> + return dma_addr;
> +
> + prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
> +
> + ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
> + if (ret < 0)
> + goto fail;
> +
> + return dma_addr + offset;
> +fail:
> + __free_iova(mapping, dma_addr, len);
> + return DMA_ERROR_CODE;
> +}
> +
> +/**
> + * arm_iommu_unmap_resource - unmap a device DMA resource
> + * @dev: valid struct device pointer
> + * @dma_handle: DMA address to resource
> + * @size: size of resource to map
> + * @dir: DMA transfer direction
> + */
> +static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t 
> dma_handle,
> + size_t size, enum dma_data_direction dir,
> + unsigned long attrs)
> +{
> + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
> + dma_addr_t iova = dma_handle & PAGE_MASK;
> + unsigned int offset = dma_handle & ~PAGE_MASK;
> + size_t len = PAGE_ALIGN(size + offset);
> +
> + if (!iova)
> + return;
> +
> + iommu_unmap(mapping->domain, iova, len);
> + __free_iova(mapping, iova, len);
> +}
> +
>  static void arm_iommu_sync_single_for_cpu(struct device *dev,
>   dma_addr_t handle, size_t size, enum dma_data_direction dir)
>  {
> @@ -2057,6 +2114,9 @@ struct dma_map_ops iommu_ops = {
>   .unmap_sg   = arm_iommu_unmap_sg,
>   .sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
>   .sync_sg_for_device = arm_iommu_sync_sg_for_device,
> +
> + .map_resource   = arm_iommu_map_resource,
> + .unmap_resource = arm_iommu_unmap_resource,
>  };
>  
>  struct dma_map_ops iommu_coherent_ops = {
> @@ -2070,6 +2130,9 @@ struct dma_map_ops iommu_coherent_ops = {
>  
>   .map_sg = arm_coherent_iommu_map_sg,
>   .unmap_sg   = arm_coherent_iommu_unmap_sg,
> +
> + .map_resource   = arm_iommu_map_resource,
> + .unmap_resource = arm_iommu_unmap_resource,
>  };
>  
>  /**
> -- 
> 2.9.2
> 

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv9 0/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-08-10 Thread Niklas Söderlund
nvolving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas Söderlund (6):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-debug: add support for resource mappings
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers

 Documentation/DMA-API.txt   |  22 +++--
 arch/arm/mm/dma-mapping.c   |  63 
 drivers/dma/sh/rcar-dmac.c  | 116 +++-
 include/linux/dma-debug.h   |  19 
 include/linux/dma-mapping.h |  42 
 lib/dma-debug.c |  52 +++-
 6 files changed, 285 insertions(+), 29 deletions(-)

-- 
2.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv9 2/6] dma-debug: add support for resource mappings

2016-08-10 Thread Niklas Söderlund
A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-debug.h | 19 +
 lib/dma-debug.c   | 52 +--
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index fe8cb61..c7d844f 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, 
size_t size,
 extern void debug_dma_free_coherent(struct device *dev, size_t size,
void *virt, dma_addr_t addr);
 
+extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+  size_t size, int direction,
+  dma_addr_t dma_addr);
+
+extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+size_t size, int direction);
+
 extern void debug_dma_sync_single_for_cpu(struct device *dev,
  dma_addr_t dma_handle, size_t size,
  int direction);
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device 
*dev, size_t size,
 {
 }
 
+static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+ size_t size, int direction,
+ dma_addr_t dma_addr)
+{
+}
+
+static inline void debug_dma_unmap_resource(struct device *dev,
+   dma_addr_t dma_addr, size_t size,
+   int direction)
+{
+}
+
 static inline void debug_dma_sync_single_for_cpu(struct device *dev,
 dma_addr_t dma_handle,
 size_t size, int direction)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index fcfa193..2ba086b 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -43,6 +43,7 @@ enum {
dma_debug_page,
dma_debug_sg,
dma_debug_coherent,
+   dma_debug_resource,
 };
 
 enum map_err_types {
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = {
[MAP_ERR_CHECKED] = "dma map error checked",
 };
 
-static const char *type2name[4] = { "single", "page",
-   "scather-gather", "coherent" };
+static const char *type2name[5] = { "single", "page",
+   "scather-gather", "coherent",
+   "resource" };
 
 static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
   "DMA_FROM_DEVICE", "DMA_NONE" };
@@ -399,6 +401,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
 
 static unsigned long long phys_addr(struct dma_debug_entry *entry)
 {
+   if (entry->type == dma_debug_resource)
+   return __pfn_to_phys(entry->pfn) + entry->offset;
+
return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
 }
 
@@ -1495,6 +1500,49 @@ void debug_dma_free_coherent(struct device *dev, size_t 
size,
 }
 EXPORT_SYMBOL(debug_dma_free_coherent);
 
+void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
+   int direction, dma_addr_t dma_addr)
+{
+   struct dma_debug_entry *entry;
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   entry = dma_entry_alloc();
+   if (!entry)
+   return;
+
+   entry->type = dma_debug_resource;
+   entry->dev  = dev;
+   entry->pfn  = __phys_to_pfn(addr);
+   entry->offset   = offset_in_page(addr);
+   entry->size = size;
+   entry->dev_addr = dma_addr;
+   entry->direction= direction;
+   entry->map_err_type = MAP_ERR_NOT_CHECKED;
+
+   add_dma_entry(entry);
+}
+EXPORT_SYMBOL(debug_dma_map_resource);
+
+void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+   struct dma_debug_entry ref = {
+   .type   = dma_debug_resource,
+   .dev= dev,
+   .dev_addr   = dma_addr,
+   .size   = size,
+   .direction  = direction,
+   };
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   check_unmap();
+}
+EXPORT_SYMBO

[PATCHv9 4/6] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-08-10 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index c6834c0..746eb29 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2014,6 +2014,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, unsigned long attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   unsigned int offset = phys_addr & ~PAGE_MASK;
+   size_t len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, len);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, len);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   unsigned long attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   unsigned int offset = dma_handle & ~PAGE_MASK;
+   size_t len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -2057,6 +2114,9 @@ struct dma_map_ops iommu_ops = {
.unmap_sg   = arm_iommu_unmap_sg,
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
+
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
 };
 
 struct dma_map_ops iommu_coherent_ops = {
@@ -2070,6 +2130,9 @@ struct dma_map_ops iommu_coherent_ops = {
 
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
+
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
 };
 
 /**
-- 
2.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv9 5/6] dmaengine: rcar-dmac: group slave configuration

2016-08-10 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 0dd9538..cf983a9 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   phys_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1040,7 +1046,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1095,7 +1101,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1112,10 +1118,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv9 3/6] dma-mapping: add dma_{map,unmap}_resource

2016-08-10 Thread Niklas Söderlund
Map/Unmap a device MMIO resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 Documentation/DMA-API.txt   | 22 +-
 include/linux/dma-mapping.h | 36 
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 1d26eeb6..6b20128 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,26 @@ and  parameters are provided to do partial page 
mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+enum dma_data_direction dir, unsigned long attrs)
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+  enum dma_data_direction dir, unsigned long attrs)
+
+API for mapping and unmapping for MMIO resources. All the notes and
+warnings for the other mapping APIs apply here. The API should only be
+used to map device MMIO resources, mapping of RAM is not permitted.
+
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
 
int
dma_map_sg(struct device *dev, struct scatterlist *sg,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3bd27f..9a07882 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -264,6 +264,42 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ unsigned long attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+   dma_addr_t addr;
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   addr = phys_addr;
+   if (ops->map_resource)
+   addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   debug_dma_map_resource(dev, phys_addr, size, dir, addr);
+
+   return addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+   debug_dma_unmap_resource(dev, addr, size, dir);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv9 6/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-08-10 Thread Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 82 +-
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index cf983a9..22a5e40 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+   dma_addr_t addr;
+   enum dma_data_direction dir;
+   struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+   struct rcar_dmac_chan_map map;
int mid_rid;
 
spinlock_t lock;
@@ -1029,13 +1042,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, 
dma_addr_t dma_dest,
  DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+   enum dma_transfer_direction dir)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac_chan_map *map = >map;
+   phys_addr_t dev_addr;
+   size_t dev_size;
+   enum dma_data_direction dev_dir;
+
+   if (dir == DMA_DEV_TO_MEM) {
+   dev_addr = rchan->src.slave_addr;
+   dev_size = rchan->src.xfer_size;
+   dev_dir = DMA_TO_DEVICE;
+   } else {
+   dev_addr = rchan->dst.slave_addr;
+   dev_size = rchan->dst.xfer_size;
+   dev_dir = DMA_FROM_DEVICE;
+   }
+
+   /* Reuse current map if possible. */
+   if (dev_addr == map->slave.slave_addr &&
+   dev_size == map->slave.xfer_size &&
+   dev_dir == map->dir)
+   return 0;
+
+   /* Remove old mapping if present. */
+   if (map->slave.xfer_size)
+   dma_unmap_resource(chan->device->dev, map->addr,
+  map->slave.xfer_size, map->dir, 0);
+   map->slave.xfer_size = 0;
+
+   /* Create new slave address map. */
+   map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+dev_dir, 0);
+
+   if (dma_mapping_error(chan->device->dev, map->addr)) {
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   dev_size, _addr);
+   return -EIO;
+   }
+
+   dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+   rchan->index, dev_size, _addr, >addr,
+   dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+   map->slave.slave_addr = dev_addr;
+   map->slave.xfer_size = dev_size;
+   map->dir = dev_dir;
+
+   return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-   dma_addr_t dev_addr;
 
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1045,9 +1110,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
return NULL;
}
 
-   dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src.slave_addr : rchan->dst.slave_addr;
-   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
+   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
  dir, flags, false);
 }
 
@@ -1061,7 +1127,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
-   dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
 
@@ -1073,6 +1138,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return NULL;
}
 
+   if (rcar_dmac_map_slave_addr(chan, dir))
+ 

[PATCHv9 1/6] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-08-10 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index c44f8ee..e3bd27f 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -95,6 +95,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 unsigned long attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  unsigned long attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  unsigned long attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.9.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCHv8 0/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-06-16 Thread Niklas Söderlund
Hi Russell,

I was wondering if you have time to look at this series?
Especially patch 4/6 which you had some good review comments on in v7.

On 2016-06-07 09:54:07 +0200, Niklas Söderlund wrote:
> Hi,
> 
> This series tries to solve the problem with DMA with device registers
> (MMIO registers) that are behind an IOMMU for the rcar-dmac driver. A
> recent patch '9575632 (dmaengine: make slave address physical)'
> clarifies that DMA slave address provided by clients is the physical
> address. This puts the task of mapping the DMA slave address from a
> phys_addr_t to a dma_addr_t on the DMA engine.
> 
> Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
> the same and no special care is needed. However if you have a IOMMU you
> need to map the DMA slave phys_addr_t to a dma_addr_t using something
> like this.
> 
> This series is based on top of v4.7-rc1. And I'm hoping to be able to collect 
> a 
> Ack from Russell King on patch 4/6 that adds the ARM specific part and then 
> be 
> able to take the whole series through the dmaengine tree. If this is not the 
> best route I'm more then happy to do it another way.
> 
> It's tested on a Koelsch with CONFIG_IPMMU_VMSA and by enabling the
> ipmmu_ds node in r8a7791.dtsi. I verified operation by interacting with
> /dev/mmcblk1, i2c and the serial console which are devices behind the
> iommu.
> 
> Furthermore I have audited to the best of my ability all call paths
> involved to make sure that the dma_addr_t obtained from
> dma_map_resource() to is not used in a way where it would be expected
> for the mapping to be RAM (have a struct page). Many thanks to Christoph
> Hellwig and Laurent Pinchart for there input in this effort.
> 
>   * drivers/dma/sh/rcar-dmac.c
> Once the phys_addr_t is mapped to a dma_addr_t using
> dma_map_resource() it is only used to check that the transferee do not
> cross 4GB boundaries and then only directly written to HW registers.
> 
>   * drivers/iommu/iommu.c
> - iommu_map()
>   Check that it's align to min page size or return -EINVAL then calls
>   domain->ops->map()
> 
>   * drivers/iommu/ipmmu-vmsa.c
> - ipmmu_map()
>   No logic only calls domain->ops->map()
> 
>   * drivers/iommu/io-pgtable-arm.c
> - arm_lpae_map()
>   No logic only calls __arm_lpae_map()
> - __arm_lpae_map()
>   No logic only calls arm_lpae_init_pte()
> - arm_lpae_init_pte()
>   Used to get a pte:
> pte |= pfn_to_iopte(paddr >> data->pg_shift, data);
> 
>   * drivers/iommu/io-pgtable-arm-v7s.c
> - arm_v7s_map()
>   No logic only calls __arm_v7s_map()
> - __arm_v7s_map()
>   No logic only calls arm_v7s_init_pte()
> - arm_v7s_init_pte
>   Used to get a pte:
> pte |= paddr & ARM_V7S_LVL_MASK(lvl);
> 
>   * ARM dma-mapping
> - dma_unmap_*
>   Only valid unmap is dma_unmap_resource() all others are an invalid
>   use case.
> - dma_sync_single_*
>   Invalid use case, memory that is mapped is device memory
> - dma_common_mmap() and dma_mmap_attrs()
>   Invalid use case
> - dma_common_get_sgtable() and dma_get_sgtable_attrs()
>   Invalid use case, only for dma_alloc_* allocated memory,
> - dma_mapping_error()
>   OK
> 
> * Changes since v7
> - Use size_t instead of int for length in arm_iommu_map_resource() and 
>   arm_iommu_unmap_resource().
> - Fix bug in arm_iommu_map_resource() where wrong variable where passed to 
>   __alloc_iova(). Thanks to Russell King for pointing out both errors.
> 
> * Changes since v6
> - Use offset_in_page() and __pfn_to_phys(). This fixed a bug in the
>   lib/dma-debug.c. Thanks to Konrad Rzeszutek Wilk for finding it and Robin
>   Murphy for suggesting offset_in_page().
> - Rebased on top of v4.7-rc1.
> - Dropped DT patches which enabled the IPMMU on Renesas Koelsch and Lager. 
> Will
>   post them separately at a later time.
> 
> * Changes since v5
> - Add dma-debug work which adds a new mapping type for the resource
>   mapping which correctly can be translated to a physical address.
> - Drop patches from Robin Murphy since they now are accepted in the
>   iommu repository and base the series on that tree instead.
> - Add a review tag from Laurent.
> 
> * Changes since v4
> - Move the mapping from phys_addr_t to dma_addr_t from slave_config to the
>   prepare calls. This way we know the direction of the mapping and don't have
>   to use DMA_BIDIRECTIONAL. Thanks Vinod for suggesting this.
> - To be clear that the data type for slave addresses are changed add a patch
>   that only changes the data type to phys_addr_t.
> - Fixed up com

[PATCHv8 4/6] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-06-07 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ff7ed56..7e9c8eb 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1951,6 +1951,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   unsigned int offset = phys_addr & ~PAGE_MASK;
+   size_t len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, len);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, len);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   unsigned int offset = dma_handle & ~PAGE_MASK;
+   size_t len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1994,6 +2051,9 @@ struct dma_map_ops iommu_ops = {
.unmap_sg   = arm_iommu_unmap_sg,
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
+
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
 };
 
 struct dma_map_ops iommu_coherent_ops = {
@@ -2007,6 +2067,9 @@ struct dma_map_ops iommu_coherent_ops = {
 
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
+
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
 };
 
 /**
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv8 2/6] dma-debug: add support for resource mappings

2016-06-07 Thread Niklas Söderlund
A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-debug.h | 19 +
 lib/dma-debug.c   | 52 +--
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index fe8cb61..c7d844f 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, 
size_t size,
 extern void debug_dma_free_coherent(struct device *dev, size_t size,
void *virt, dma_addr_t addr);
 
+extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+  size_t size, int direction,
+  dma_addr_t dma_addr);
+
+extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+size_t size, int direction);
+
 extern void debug_dma_sync_single_for_cpu(struct device *dev,
  dma_addr_t dma_handle, size_t size,
  int direction);
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device 
*dev, size_t size,
 {
 }
 
+static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+ size_t size, int direction,
+ dma_addr_t dma_addr)
+{
+}
+
+static inline void debug_dma_unmap_resource(struct device *dev,
+   dma_addr_t dma_addr, size_t size,
+   int direction)
+{
+}
+
 static inline void debug_dma_sync_single_for_cpu(struct device *dev,
 dma_addr_t dma_handle,
 size_t size, int direction)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 51a76af..ce75fba 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -43,6 +43,7 @@ enum {
dma_debug_page,
dma_debug_sg,
dma_debug_coherent,
+   dma_debug_resource,
 };
 
 enum map_err_types {
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = {
[MAP_ERR_CHECKED] = "dma map error checked",
 };
 
-static const char *type2name[4] = { "single", "page",
-   "scather-gather", "coherent" };
+static const char *type2name[5] = { "single", "page",
+   "scather-gather", "coherent",
+   "resource" };
 
 static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
   "DMA_FROM_DEVICE", "DMA_NONE" };
@@ -397,6 +399,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
 
 static unsigned long long phys_addr(struct dma_debug_entry *entry)
 {
+   if (entry->type == dma_debug_resource)
+   return __pfn_to_phys(entry->pfn) + entry->offset;
+
return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
 }
 
@@ -1493,6 +1498,49 @@ void debug_dma_free_coherent(struct device *dev, size_t 
size,
 }
 EXPORT_SYMBOL(debug_dma_free_coherent);
 
+void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
+   int direction, dma_addr_t dma_addr)
+{
+   struct dma_debug_entry *entry;
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   entry = dma_entry_alloc();
+   if (!entry)
+   return;
+
+   entry->type = dma_debug_resource;
+   entry->dev  = dev;
+   entry->pfn  = __phys_to_pfn(addr);
+   entry->offset   = offset_in_page(addr);
+   entry->size = size;
+   entry->dev_addr = dma_addr;
+   entry->direction= direction;
+   entry->map_err_type = MAP_ERR_NOT_CHECKED;
+
+   add_dma_entry(entry);
+}
+EXPORT_SYMBOL(debug_dma_map_resource);
+
+void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+   struct dma_debug_entry ref = {
+   .type   = dma_debug_resource,
+   .dev= dev,
+   .dev_addr   = dma_addr,
+   .size   = size,
+   .direction  = direction,
+   };
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   check_unmap();
+}
+EXPORT_SYMBO

[PATCHv8 6/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-06-07 Thread Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 82 +-
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b0c3bb2..8592598 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+   dma_addr_t addr;
+   enum dma_data_direction dir;
+   struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+   struct rcar_dmac_chan_map map;
int mid_rid;
 
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, 
dma_addr_t dma_dest,
  DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+   enum dma_transfer_direction dir)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac_chan_map *map = >map;
+   phys_addr_t dev_addr;
+   size_t dev_size;
+   enum dma_data_direction dev_dir;
+
+   if (dir == DMA_DEV_TO_MEM) {
+   dev_addr = rchan->src.slave_addr;
+   dev_size = rchan->src.xfer_size;
+   dev_dir = DMA_TO_DEVICE;
+   } else {
+   dev_addr = rchan->dst.slave_addr;
+   dev_size = rchan->dst.xfer_size;
+   dev_dir = DMA_FROM_DEVICE;
+   }
+
+   /* Reuse current map if possible. */
+   if (dev_addr == map->slave.slave_addr &&
+   dev_size == map->slave.xfer_size &&
+   dev_dir == map->dir)
+   return 0;
+
+   /* Remove old mapping if present. */
+   if (map->slave.xfer_size)
+   dma_unmap_resource(chan->device->dev, map->addr,
+  map->slave.xfer_size, map->dir, NULL);
+   map->slave.xfer_size = 0;
+
+   /* Create new slave address map. */
+   map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+dev_dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, map->addr)) {
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   dev_size, _addr);
+   return -EIO;
+   }
+
+   dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+   rchan->index, dev_size, _addr, >addr,
+   dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+   map->slave.slave_addr = dev_addr;
+   map->slave.xfer_size = dev_size;
+   map->dir = dev_dir;
+
+   return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-   dma_addr_t dev_addr;
 
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
return NULL;
}
 
-   dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src.slave_addr : rchan->dst.slave_addr;
-   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
+   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
  dir, flags, false);
 }
 
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
-   dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
 
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return NULL;
}
 
+   if (rcar_dmac_map_slave_addr(chan, dir))
+ 

[PATCHv8 5/6] dmaengine: rcar-dmac: group slave configuration

2016-06-07 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index dfb1792..b0c3bb2 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   phys_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv8 1/6] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-06-07 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index c980a92..a11ff9d 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv8 3/6] dma-mapping: add dma_{map,unmap}_resource

2016-06-07 Thread Niklas Söderlund
Map/Unmap a device MMIO resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 Documentation/DMA-API.txt   | 22 +-
 include/linux/dma-mapping.h | 36 
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..c7e5f99 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,26 @@ and  parameters are provided to do partial page 
mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+enum dma_data_direction dir, struct dma_attrs *attrs)
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+  enum dma_data_direction dir, struct dma_attrs *attrs)
+
+API for mapping and unmapping for MMIO resources. All the notes and
+warnings for the other mapping APIs apply here. The API should only be
+used to map device MMIO resources, mapping of RAM is not permitted.
+
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
 
int
dma_map_sg(struct device *dev, struct scatterlist *sg,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index a11ff9d..4c381ba 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -218,6 +218,42 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+   dma_addr_t addr;
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   addr = phys_addr;
+   if (ops->map_resource)
+   addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   debug_dma_map_resource(dev, phys_addr, size, dir, addr);
+
+   return addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+   debug_dma_unmap_resource(dev, addr, size, dir);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv8 0/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-06-07 Thread Niklas Söderlund
nt and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas Söderlund (6):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-debug: add support for resource mappings
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers

 Documentation/DMA-API.txt   |  22 +++--
 arch/arm/mm/dma-mapping.c   |  63 
 drivers/dma/sh/rcar-dmac.c  | 116 +++-
 include/linux/dma-debug.h   |  19 
 include/linux/dma-mapping.h |  42 
 lib/dma-debug.c |  52 +++-
 6 files changed, 285 insertions(+), 29 deletions(-)

-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCHv7 0/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-06-02 Thread Niklas Söderlund
Hi Vinod,

On 2016-06-01 23:36:11 +0530, Vinod Koul wrote:
> On Wed, Jun 01, 2016 at 05:22:23PM +0200, Niklas Söderlund wrote:
> > Hi,
> > 
> > [In this v7 series I have tried to address the questions raised by 
> > Christoph 
> > Hellwig and I hope it can awnser your concernes regarding dma-debug.]
> > 
> > This series tries to solve the problem with DMA with device registers
> > (MMIO registers) that are behind an IOMMU for the rcar-dmac driver. A
> > recent patch '9575632 (dmaengine: make slave address physical)'
> > clarifies that DMA slave address provided by clients is the physical
> > address. This puts the task of mapping the DMA slave address from a
> > phys_addr_t to a dma_addr_t on the DMA engine.
> > 
> > Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
> > the same and no special care is needed. However if you have a IOMMU you
> > need to map the DMA slave phys_addr_t to a dma_addr_t using something
> > like this.
> > 
> > This series is based on top of v4.7-rc1.
> 
> The dmanegine bits looks okay to me. Btw how is the merge planned for this?
> Do you wnat this to be merged thru dmaengine tree or something else?

Yes, since the arm specific patch are depending on other parts of the 
series I was hoping to be able to get Russells Ack on it and then try to 
get it all in through the dmaengine tree.

If you see a better way I'm happy to do it that way, let me know what 
you think. I hold off v8 that adresses the issues Russell brought up a 
few days untill I know what you think is best.

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCHv7 4/6] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-06-02 Thread Niklas Söderlund
Hi Russell,

Thanks for your feedback.

On 2016-06-01 17:16:06 +0100, Russell King - ARM Linux wrote:
> On Wed, Jun 01, 2016 at 05:22:27PM +0200, Niklas Söderlund wrote:
> > +static dma_addr_t arm_iommu_map_resource(struct device *dev,
> > +   phys_addr_t phys_addr, size_t size,
> > +   enum dma_data_direction dir, struct dma_attrs *attrs)
> > +{
> > +   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
> > +   dma_addr_t dma_addr;
> > +   int ret, prot;
> > +   phys_addr_t addr = phys_addr & PAGE_MASK;
> > +   int offset = phys_addr & ~PAGE_MASK;
> > +   int len = PAGE_ALIGN(size + offset);
> 
> Shouldn't both of these be unsigned - preferably size_t for len?

I have looked at arm_coherent_iommu_map_page() when writing this where 
len is int. But I do agree that it should probably be size_t and offset 
should be unsigned. Will fix this.

> 
> > +
> > +   dma_addr = __alloc_iova(mapping, size);
> 
> Is this really correct?  What if size = 4095 and offset = 10?  Do we
> really only need one IOVA page for such a mapping (I count two pages.)
> Shouldn't this be "len" ?

Wops, you are correct it should be len not size.

> 
> > +   if (dma_addr == DMA_ERROR_CODE)
> > +   return dma_addr;
> > +
> > +   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
> > +
> > +   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
> > +   if (ret < 0)
> > +   goto fail;
> > +
> > +   return dma_addr + offset;
> > +fail:
> > +   __free_iova(mapping, dma_addr, size);
> 
> Shouldn't this be "len" as well?

Yes.

> 
> > +   return DMA_ERROR_CODE;
> > +}
> > +
> > +/**
> > + * arm_iommu_unmap_resource - unmap a device DMA resource
> > + * @dev: valid struct device pointer
> > + * @dma_handle: DMA address to resource
> > + * @size: size of resource to map
> > + * @dir: DMA transfer direction
> > + */
> > +static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t 
> > dma_handle,
> > +   size_t size, enum dma_data_direction dir,
> > +   struct dma_attrs *attrs)
> > +{
> > +   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
> > +   dma_addr_t iova = dma_handle & PAGE_MASK;
> > +   int offset = dma_handle & ~PAGE_MASK;
> > +   int len = PAGE_ALIGN(size + offset);
> 
> unsigned/size_t again.

Will fix.

> 
> > +
> > +   if (!iova)
> > +   return;
> > +
> > +   iommu_unmap(mapping->domain, iova, len);
> > +   __free_iova(mapping, iova, len);
> 
> Here, you free "len" bytes of iova, which is different from above.

Yes you are correct. By using len instead of size in 
arm_iommu_map_resource() the sizes do match.

> 
> > +}
> > +
> >  static void arm_iommu_sync_single_for_cpu(struct device *dev,
> > dma_addr_t handle, size_t size, enum dma_data_direction dir)
> >  {
> > @@ -1994,6 +2051,9 @@ struct dma_map_ops iommu_ops = {
> > .unmap_sg   = arm_iommu_unmap_sg,
> > .sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
> > .sync_sg_for_device = arm_iommu_sync_sg_for_device,
> > +
> > +   .map_resource   = arm_iommu_map_resource,
> > +   .unmap_resource = arm_iommu_unmap_resource,
> >  };
> >  
> >  struct dma_map_ops iommu_coherent_ops = {
> > @@ -2007,6 +2067,9 @@ struct dma_map_ops iommu_coherent_ops = {
> >  
> > .map_sg = arm_coherent_iommu_map_sg,
> > .unmap_sg   = arm_coherent_iommu_unmap_sg,
> > +
> > +   .map_resource   = arm_iommu_map_resource,
> > +   .unmap_resource = arm_iommu_unmap_resource,
> >  };
> >  
> >  /**
> > -- 
> > 2.8.2
> > 
> > 
> > ___
> > linux-arm-kernel mailing list
> > linux-arm-ker...@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> -- 
> RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> according to speedtest.net.

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv7 3/6] dma-mapping: add dma_{map,unmap}_resource

2016-06-01 Thread Niklas Söderlund
Map/Unmap a device MMIO resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 Documentation/DMA-API.txt   | 22 +-
 include/linux/dma-mapping.h | 36 
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..c7e5f99 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,26 @@ and  parameters are provided to do partial page 
mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+enum dma_data_direction dir, struct dma_attrs *attrs)
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+  enum dma_data_direction dir, struct dma_attrs *attrs)
+
+API for mapping and unmapping for MMIO resources. All the notes and
+warnings for the other mapping APIs apply here. The API should only be
+used to map device MMIO resources, mapping of RAM is not permitted.
+
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
 
int
dma_map_sg(struct device *dev, struct scatterlist *sg,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index a11ff9d..4c381ba 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -218,6 +218,42 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+   dma_addr_t addr;
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   addr = phys_addr;
+   if (ops->map_resource)
+   addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   debug_dma_map_resource(dev, phys_addr, size, dir, addr);
+
+   return addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+   debug_dma_unmap_resource(dev, addr, size, dir);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv7 6/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-06-01 Thread Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 82 +-
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b0c3bb2..8592598 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+   dma_addr_t addr;
+   enum dma_data_direction dir;
+   struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+   struct rcar_dmac_chan_map map;
int mid_rid;
 
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, 
dma_addr_t dma_dest,
  DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+   enum dma_transfer_direction dir)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac_chan_map *map = >map;
+   phys_addr_t dev_addr;
+   size_t dev_size;
+   enum dma_data_direction dev_dir;
+
+   if (dir == DMA_DEV_TO_MEM) {
+   dev_addr = rchan->src.slave_addr;
+   dev_size = rchan->src.xfer_size;
+   dev_dir = DMA_TO_DEVICE;
+   } else {
+   dev_addr = rchan->dst.slave_addr;
+   dev_size = rchan->dst.xfer_size;
+   dev_dir = DMA_FROM_DEVICE;
+   }
+
+   /* Reuse current map if possible. */
+   if (dev_addr == map->slave.slave_addr &&
+   dev_size == map->slave.xfer_size &&
+   dev_dir == map->dir)
+   return 0;
+
+   /* Remove old mapping if present. */
+   if (map->slave.xfer_size)
+   dma_unmap_resource(chan->device->dev, map->addr,
+  map->slave.xfer_size, map->dir, NULL);
+   map->slave.xfer_size = 0;
+
+   /* Create new slave address map. */
+   map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+dev_dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, map->addr)) {
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   dev_size, _addr);
+   return -EIO;
+   }
+
+   dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+   rchan->index, dev_size, _addr, >addr,
+   dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+   map->slave.slave_addr = dev_addr;
+   map->slave.xfer_size = dev_size;
+   map->dir = dev_dir;
+
+   return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-   dma_addr_t dev_addr;
 
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
return NULL;
}
 
-   dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src.slave_addr : rchan->dst.slave_addr;
-   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
+   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
  dir, flags, false);
 }
 
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
-   dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
 
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return NULL;
}
 
+   if (rcar_dmac_map_slave_addr(chan, dir))
+ 

[PATCHv7 4/6] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-06-01 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index ff7ed56..8f12ec8 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1951,6 +1951,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1994,6 +2051,9 @@ struct dma_map_ops iommu_ops = {
.unmap_sg   = arm_iommu_unmap_sg,
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
+
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
 };
 
 struct dma_map_ops iommu_coherent_ops = {
@@ -2007,6 +2067,9 @@ struct dma_map_ops iommu_coherent_ops = {
 
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
+
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
 };
 
 /**
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv7 5/6] dmaengine: rcar-dmac: group slave configuration

2016-06-01 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index dfb1792..b0c3bb2 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   phys_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv7 1/6] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-06-01 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index c980a92..a11ff9d 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv7 2/6] dma-debug: add support for resource mappings

2016-06-01 Thread Niklas Söderlund
A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-debug.h | 19 +
 lib/dma-debug.c   | 52 +--
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index fe8cb61..c7d844f 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, 
size_t size,
 extern void debug_dma_free_coherent(struct device *dev, size_t size,
void *virt, dma_addr_t addr);
 
+extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+  size_t size, int direction,
+  dma_addr_t dma_addr);
+
+extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+size_t size, int direction);
+
 extern void debug_dma_sync_single_for_cpu(struct device *dev,
  dma_addr_t dma_handle, size_t size,
  int direction);
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device 
*dev, size_t size,
 {
 }
 
+static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+ size_t size, int direction,
+ dma_addr_t dma_addr)
+{
+}
+
+static inline void debug_dma_unmap_resource(struct device *dev,
+   dma_addr_t dma_addr, size_t size,
+   int direction)
+{
+}
+
 static inline void debug_dma_sync_single_for_cpu(struct device *dev,
 dma_addr_t dma_handle,
 size_t size, int direction)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 51a76af..ce75fba 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -43,6 +43,7 @@ enum {
dma_debug_page,
dma_debug_sg,
dma_debug_coherent,
+   dma_debug_resource,
 };
 
 enum map_err_types {
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = {
[MAP_ERR_CHECKED] = "dma map error checked",
 };
 
-static const char *type2name[4] = { "single", "page",
-   "scather-gather", "coherent" };
+static const char *type2name[5] = { "single", "page",
+   "scather-gather", "coherent",
+   "resource" };
 
 static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
   "DMA_FROM_DEVICE", "DMA_NONE" };
@@ -397,6 +399,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
 
 static unsigned long long phys_addr(struct dma_debug_entry *entry)
 {
+   if (entry->type == dma_debug_resource)
+   return __pfn_to_phys(entry->pfn) + entry->offset;
+
return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
 }
 
@@ -1493,6 +1498,49 @@ void debug_dma_free_coherent(struct device *dev, size_t 
size,
 }
 EXPORT_SYMBOL(debug_dma_free_coherent);
 
+void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
+   int direction, dma_addr_t dma_addr)
+{
+   struct dma_debug_entry *entry;
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   entry = dma_entry_alloc();
+   if (!entry)
+   return;
+
+   entry->type = dma_debug_resource;
+   entry->dev  = dev;
+   entry->pfn  = __phys_to_pfn(addr);
+   entry->offset   = offset_in_page(addr);
+   entry->size = size;
+   entry->dev_addr = dma_addr;
+   entry->direction= direction;
+   entry->map_err_type = MAP_ERR_NOT_CHECKED;
+
+   add_dma_entry(entry);
+}
+EXPORT_SYMBOL(debug_dma_map_resource);
+
+void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+   struct dma_debug_entry ref = {
+   .type   = dma_debug_resource,
+   .dev= dev,
+   .dev_addr   = dma_addr,
+   .size   = size,
+   .direction  = direction,
+   };
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   check_unmap();
+}
+EXPORT_SYMBO

[PATCHv7 0/6] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-06-01 Thread Niklas Söderlund
ac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.


Niklas Söderlund (6):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-debug: add support for resource mappings
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers

 Documentation/DMA-API.txt   |  22 +++--
 arch/arm/mm/dma-mapping.c   |  63 
 drivers/dma/sh/rcar-dmac.c  | 116 +++-
 include/linux/dma-debug.h   |  19 
 include/linux/dma-mapping.h |  42 
 lib/dma-debug.c |  52 +++-
 6 files changed, 285 insertions(+), 29 deletions(-)

-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-05-19 Thread Niklas Söderlund
Hi Konrad,

Thanks for your feedback.

On 2016-05-17 10:54:45 -0400, Konrad Rzeszutek Wilk wrote:
> >  
> > -In some circumstances dma_map_single() and dma_map_page() will fail to 
> > create
> > -a mapping. A driver can check for these errors by testing the returned
> > -DMA address with dma_mapping_error(). A non-zero return value means the 
> > mapping
> > -could not be created and the driver should take appropriate action (e.g.
> > -reduce current DMA mapping usage or delay and try again later).
> > +In some circumstances dma_map_single(), dma_map_page() and 
> > dma_map_resource()
> > +will fail to create a mapping. A driver can check for these errors by 
> > testing
> > +the returned DMA address with dma_mapping_error(). A non-zero return value
> > +means the mapping could not be created and the driver should take 
> > appropriate
> > +action (e.g. reduce current DMA mapping usage or delay and try again 
> > later).
> 
> This looks like it belongs to another patch?

No it is correct (at least intended to be in this patch). All it really 
do is inject dma_map_resource() (which is added in this patch) as one of 
the calls which return dma_addr_t should be checked for error using 
dma_mapping_error().  But yes the change effect all lines in the 
paragraph due to line wrapping.

Hum or maybe I'm misunderstanding your question.

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCHv6 2/8] dma-debug: add support for resource mappings

2016-05-19 Thread Niklas Söderlund
Hi Konrad,

Thanks for your feedback.

On 2016-05-17 10:50:02 -0400, Konrad Rzeszutek Wilk wrote:
> > +void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t 
> > size,
> > +   int direction, dma_addr_t dma_addr)
> > +{
> > +   struct dma_debug_entry *entry;
> > +
> > +   if (unlikely(dma_debug_disabled()))
> > +   return;
> > +
> > +   entry = dma_entry_alloc();
> > +   if (!entry)
> > +   return;
> > +
> > +   entry->type = dma_debug_resource;
> > +   entry->dev  = dev;
> > +   entry->pfn  = __phys_to_pfn(addr);
> > +   entry->offset   = addr - PHYS_PFN(entry->pfn);
> 
> Is that right? 

You are correct that should be:

   entry->offset = addr - PFN_PHYS(entry->pfn);

Or even better:

   entry->offset = addr - __pfn_to_phys(entry->pfn);

I will address this and resend late next week, still hoping for some 
more feedback.

> 
> __phys_to_pfn(addr) is PHYS_PFN(addr), so what you get here is
> 
> addr - PHYS_PFN(PHYS_PFN(addr)) ?
> 
> 
> > +   entry->size = size;
> > +   entry->dev_addr = dma_addr;
> > +   entry->direction    = direction;
> > +   entry->map_err_type = MAP_ERR_NOT_CHECKED;
> > +
> > +   add_dma_entry(entry);
> > +}
> > +EXPORT_SYMBOL(debug_dma_map_resource);
> > +

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCHv6 8/8] ARM: dts: r8a7791: add iommus to dmac0 and dmac1

2016-05-09 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7791.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 4f01b64..dc81c90 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -313,6 +313,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -344,6 +359,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv6 4/8] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-05-09 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index deac58d..d5fe32b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1962,6 +1962,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -2006,6 +2063,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -2021,6 +2081,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv6 5/8] dmaengine: rcar-dmac: group slave configuration

2016-05-09 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index dfb1792..b0c3bb2 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   phys_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv6 6/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-05-09 Thread Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 82 +-
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b0c3bb2..8592598 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+   dma_addr_t addr;
+   enum dma_data_direction dir;
+   struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+   struct rcar_dmac_chan_map map;
int mid_rid;
 
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, 
dma_addr_t dma_dest,
  DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+   enum dma_transfer_direction dir)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac_chan_map *map = >map;
+   phys_addr_t dev_addr;
+   size_t dev_size;
+   enum dma_data_direction dev_dir;
+
+   if (dir == DMA_DEV_TO_MEM) {
+   dev_addr = rchan->src.slave_addr;
+   dev_size = rchan->src.xfer_size;
+   dev_dir = DMA_TO_DEVICE;
+   } else {
+   dev_addr = rchan->dst.slave_addr;
+   dev_size = rchan->dst.xfer_size;
+   dev_dir = DMA_FROM_DEVICE;
+   }
+
+   /* Reuse current map if possible. */
+   if (dev_addr == map->slave.slave_addr &&
+   dev_size == map->slave.xfer_size &&
+   dev_dir == map->dir)
+   return 0;
+
+   /* Remove old mapping if present. */
+   if (map->slave.xfer_size)
+   dma_unmap_resource(chan->device->dev, map->addr,
+  map->slave.xfer_size, map->dir, NULL);
+   map->slave.xfer_size = 0;
+
+   /* Create new slave address map. */
+   map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+dev_dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, map->addr)) {
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   dev_size, _addr);
+   return -EIO;
+   }
+
+   dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+   rchan->index, dev_size, _addr, >addr,
+   dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+   map->slave.slave_addr = dev_addr;
+   map->slave.xfer_size = dev_size;
+   map->dir = dev_dir;
+
+   return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-   dma_addr_t dev_addr;
 
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
return NULL;
}
 
-   dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src.slave_addr : rchan->dst.slave_addr;
-   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
+   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
  dir, flags, false);
 }
 
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
-   dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
 
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return NULL;
}
 
+   if (rcar_dmac_map_slave_addr(chan, dir))
+ 

[PATCHv6 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-05-09 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 404ef2b..2912320 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -336,6 +336,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -367,6 +382,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-05-09 Thread Niklas Söderlund
Map/Unmap a device MMIO resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 Documentation/DMA-API.txt   | 22 +-
 include/linux/dma-mapping.h | 36 
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..c7e5f99 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,26 @@ and  parameters are provided to do partial page 
mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+enum dma_data_direction dir, struct dma_attrs *attrs)
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+  enum dma_data_direction dir, struct dma_attrs *attrs)
+
+API for mapping and unmapping for MMIO resources. All the notes and
+warnings for the other mapping APIs apply here. The API should only be
+used to map device MMIO resources, mapping of RAM is not permitted.
+
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
 
int
dma_map_sg(struct device *dev, struct scatterlist *sg,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 8617fa1..dd228ce 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -218,6 +218,42 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+   dma_addr_t addr;
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   addr = phys_addr;
+   if (ops->map_resource)
+   addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   debug_dma_map_resource(dev, phys_addr, size, dir, addr);
+
+   return addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+   debug_dma_unmap_resource(dev, addr, size, dir);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv6 2/8] dma-debug: add support for resource mappings

2016-05-09 Thread Niklas Söderlund
A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-debug.h | 19 +
 lib/dma-debug.c   | 52 +--
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index fe8cb61..c7d844f 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, 
size_t size,
 extern void debug_dma_free_coherent(struct device *dev, size_t size,
void *virt, dma_addr_t addr);
 
+extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+  size_t size, int direction,
+  dma_addr_t dma_addr);
+
+extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+size_t size, int direction);
+
 extern void debug_dma_sync_single_for_cpu(struct device *dev,
  dma_addr_t dma_handle, size_t size,
  int direction);
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device 
*dev, size_t size,
 {
 }
 
+static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+ size_t size, int direction,
+ dma_addr_t dma_addr)
+{
+}
+
+static inline void debug_dma_unmap_resource(struct device *dev,
+   dma_addr_t dma_addr, size_t size,
+   int direction)
+{
+}
+
 static inline void debug_dma_sync_single_for_cpu(struct device *dev,
 dma_addr_t dma_handle,
 size_t size, int direction)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 4a1515f..fb12d5c 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -43,6 +43,7 @@ enum {
dma_debug_page,
dma_debug_sg,
dma_debug_coherent,
+   dma_debug_resource,
 };
 
 enum map_err_types {
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = {
[MAP_ERR_CHECKED] = "dma map error checked",
 };
 
-static const char *type2name[4] = { "single", "page",
-   "scather-gather", "coherent" };
+static const char *type2name[5] = { "single", "page",
+   "scather-gather", "coherent",
+   "resource" };
 
 static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
   "DMA_FROM_DEVICE", "DMA_NONE" };
@@ -397,6 +399,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
 
 static unsigned long long phys_addr(struct dma_debug_entry *entry)
 {
+   if (entry->type == dma_debug_resource)
+   return PHYS_PFN(entry->pfn) + entry->offset;
+
return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
 }
 
@@ -1493,6 +1498,49 @@ void debug_dma_free_coherent(struct device *dev, size_t 
size,
 }
 EXPORT_SYMBOL(debug_dma_free_coherent);
 
+void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
+   int direction, dma_addr_t dma_addr)
+{
+   struct dma_debug_entry *entry;
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   entry = dma_entry_alloc();
+   if (!entry)
+   return;
+
+   entry->type = dma_debug_resource;
+   entry->dev  = dev;
+   entry->pfn  = __phys_to_pfn(addr);
+   entry->offset   = addr - PHYS_PFN(entry->pfn);
+   entry->size = size;
+   entry->dev_addr = dma_addr;
+   entry->direction= direction;
+   entry->map_err_type = MAP_ERR_NOT_CHECKED;
+
+   add_dma_entry(entry);
+}
+EXPORT_SYMBOL(debug_dma_map_resource);
+
+void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+   struct dma_debug_entry ref = {
+   .type   = dma_debug_resource,
+   .dev= dev,
+   .dev_addr   = dma_addr,
+   .size   = size,
+   .direction  = direction,
+   };
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   check_unmap();
+}
+EXPORT_SY

[PATCHv6 0/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-05-09 Thread Niklas Söderlund
ce_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas Söderlund (8):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-debug: add support for resource mappings
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

 Documentation/DMA-API.txt  |  22 ++--
 arch/arm/boot/dts/r8a7790.dtsi |  30 +++
 arch/arm/boot/dts/r8a7791.dtsi |  30 +++
 arch/arm/mm/dma-mapping.c  |  63 ++
 drivers/dma/sh/rcar-dmac.c | 116 +
 include/linux/dma-debug.h  |  19 +++
 include/linux/dma-mapping.h|  42 +++
 lib/dma-debug.c|  52 +-
 8 files changed, 345 insertions(+), 29 deletions(-)

-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCHv6 1/8] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-05-09 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0e4d3a6..8617fa1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH 0/2] Fix incorrect warning from dma-debug

2016-05-08 Thread Niklas Söderlund
Hi,

While using CONFIG_DMA_API_DEBUG i came across this warning which I
think is a false positive. As shown dma_sync_single_for_device() are
called from the dma_map_single() call path. This triggers the warning
since the dma-debug code have not yet been made aware of the mapping.

I try to solve this by introducing __dma_sync_single_for_device() which
do not call into the dma-debug code. I'm no expert and this might be a
bad way of solving the problem but it allowed me to keep working.

[ cut here ]
WARNING: CPU: 0 PID: 1 at lib/dma-debug.c:1209 check_sync+0x154/0x5e4
ipmmu-vmsa e674.mmu: DMA-API: device driver tries to sync DMA memory it has 
not allocated [device address=0x6e89b008] [size=8 bytes]
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc5-00012-g52e78c1-dirty #1
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[] (dump_backtrace) from [] (show_stack+0x18/0x1c)
 r7:c03ebad0 r6:0009 r5:6093 r4:
[] (show_stack) from [] (dump_stack+0x84/0xa4)
[] (dump_stack) from [] (__warn+0xd0/0x100)
 r5: r4:ef05dac8
[] (__warn) from [] (warn_slowpath_fmt+0x40/0x48)
 r9:0001 r8: r7:c0c69c40 r6:c0c02754 r5:ef05db78 r4:ef222810
[] (warn_slowpath_fmt) from [] (check_sync+0x154/0x5e4)
 r3:c0945b6f r2:c0936e85
[] (check_sync) from [] 
(debug_dma_sync_single_for_device+0x64/0x70)
 r10:0009 r9:000c r8:ee89b008 r7: r6:6e89b008 r5:
 r4:6e89b008
[] (debug_dma_sync_single_for_device) from [] 
(__arm_lpae_set_pte.part.0+0x80/0x8c)
 r5:0001 r4:ef222810
[] (__arm_lpae_set_pte.part.0) from [] 
(__arm_lpae_map+0x298/0x2f0)
 r7:0008 r6:ef25e000 r4:ee898500
[] (__arm_lpae_map) from [] (arm_lpae_map+0xcc/0xe4)
 r10:c0465f40 r9:1000 r8:4000 r7: r6:6f25c000 r5:
 r4:08c0
[] (arm_lpae_map) from [] (ipmmu_map+0x38/0x40)
 r7:4000 r6: r5:1000 r4:c0465a4c
[] (ipmmu_map) from [] (iommu_map+0xf8/0x15c)
 r4:ee895608
[] (iommu_map) from [] 
(arm_coherent_iommu_map_page+0x1d4/0x2d4)
 r10:ef386940 r9:1000 r8: r7: r6:4000 r5:
 r4:
[] (arm_coherent_iommu_map_page) from [] 
(arm_iommu_map_page+0x6c/0x74)
 r10:c0c61f44 r9:ef19d210 r8:0001 r7:1000 r6: r5:ec5ddb80
 r4:
[] (arm_iommu_map_page) from [] 
(sh_msiof_spi_probe+0x430/0x7b0)
 r9: r8:c0213624 r7:ef19d210 r6:ef242800 r5:ef1b4010 r4:ef242af0
[] (sh_msiof_spi_probe) from [] 
(platform_drv_probe+0x58/0xa8)
 r10: r9: r8:c0c1f8d4 r7:c0c7e910 r6:c0c1f8d4 r5:ef1b4010
 r4:c04f7934
[] (platform_drv_probe) from [] 
(driver_probe_device+0x13c/0x2a4)
 r7:c0c7e910 r6: r5:c0c7e900 r4:ef1b4010
[] (driver_probe_device) from [] (__driver_attach+0x88/0xac)
 r9:c0c34000 r8:c0a3c010 r7:c0c1cf08 r6:c0c1f8d4 r5:ef1b4044 r4:ef1b4010
[] (__driver_attach) from [] (bus_for_each_dev+0x74/0x98)
 r7:c0c1cf08 r6:c049e8f0 r5:c0c1f8d4 r4:
[] (bus_for_each_dev) from [] (driver_attach+0x20/0x28)
 r6:ef1cc200 r5: r4:c0c1f8d4
[] (driver_attach) from [] (bus_add_driver+0xd4/0x1e4)
[] (bus_add_driver) from [] (driver_register+0xa4/0xe8)
 r7:c0a3c010 r6: r5:c0a1e400 r4:c0c1f8d4
[] (driver_register) from [] 
(__platform_driver_register+0x38/0x4c)
 r5:c0a1e400 r4:ee958fc0
[] (__platform_driver_register) from [] 
(sh_msiof_spi_drv_init+0x18/0x20)
[] (sh_msiof_spi_drv_init) from [] 
(do_one_initcall+0x10c/0x1c0)
[] (do_one_initcall) from [] 
(kernel_init_freeable+0x128/0x1f4)
 r9:c0c34000 r8:c0c34000 r7:c0a47e60 r6:c0a3c83c r5:00bd r4:0006
[] (kernel_init_freeable) from [] (kernel_init+0x10/0x118)
 r9:[1.879529] ata1: link resume succeeded after 1 retries
 r8: r7: r6: r5:c071066c r4:
[] (kernel_init) from [] (ret_from_fork+0x14/0x2c)
 r5:c071066c r4:
---[ end trace 6eb9a3df3009d491 ]---

Niklas Söderlund (2):
  dma-mapping: add __dma_sync_single_for_device()
  iommu/io-pgtable-arm: use __dma_sync_single_for_device()

 drivers/iommu/io-pgtable-arm.c | 2 +-
 include/linux/dma-mapping.h| 9 -
 2 files changed, 9 insertions(+), 2 deletions(-)

--
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH 2/2] iommu/io-pgtable-arm: use __dma_sync_single_for_device()

2016-05-08 Thread Niklas Söderlund
The call to dma_sync_single_for_device() can be reached from
dma_map_single(). If CONFIG_DMA_API_DEBUG is enabled this would result
in a check that the mapping being synced is valid. Since the call to
dma_map_single is not yet completed the mapping is not recorded in
dma-debug and the check fails and a warning is printed. Avoid this
warning by calling __dma_sync_single_for_device() which don't preform
this check.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/iommu/io-pgtable-arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index f433b51..3da8102 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -255,7 +255,7 @@ static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, 
arm_lpae_iopte pte,
*ptep = pte;
 
if (!selftest_running)
-   dma_sync_single_for_device(cfg->iommu_dev,
+   __dma_sync_single_for_device(cfg->iommu_dev,
   __arm_lpae_dma_addr(ptep),
   sizeof(pte), DMA_TO_DEVICE);
 }
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH 1/2] dma-mapping: add __dma_sync_single_for_device()

2016-05-08 Thread Niklas Söderlund
Some users of the DMA mapping API calls dma_sync_single_for_device()
from the dma_map_single() call path. This will cause false warning
printouts if CONFIG_DMA_API_DEBUG are enabled.

The reason for the warning are that debug_dma_sync_single_for_device()
will be called before debug_dma_map_page() so the new mapping can't be
found and are believed to be invalid. Add __dma_sync_single_for_device()
that don't call into debug_dma_sync_single_for_device() and can be used
in these situations.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9ea9aba..0e4d3a6 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -224,7 +224,7 @@ static inline void dma_sync_single_for_cpu(struct device 
*dev, dma_addr_t addr,
debug_dma_sync_single_for_cpu(dev, addr, size, dir);
 }
 
-static inline void dma_sync_single_for_device(struct device *dev,
+static inline void __dma_sync_single_for_device(struct device *dev,
  dma_addr_t addr, size_t size,
  enum dma_data_direction dir)
 {
@@ -233,6 +233,13 @@ static inline void dma_sync_single_for_device(struct 
device *dev,
BUG_ON(!valid_dma_direction(dir));
if (ops->sync_single_for_device)
ops->sync_single_for_device(dev, addr, size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+ dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+   __dma_sync_single_for_device(dev, addr, size, dir);
debug_dma_sync_single_for_device(dev, addr, size, dir);
 }
 
-- 
2.8.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource

2016-04-26 Thread Niklas Söderlund
Hi Christoph,

On 2016-04-25 12:10:04 -0700, Christoph Hellwig wrote:
> On Mon, Apr 25, 2016 at 04:26:19PM +0200, Niklas S?derlund wrote:
> > I have followed the call path from the usage in 
> > drivers/dma/sh/rcar-dmac.c and made sure the dma_addr_t is not used in a 
> > bad way.
> 
> The dma-debug routines are called from the generic code in
> include/linux/dma-mapping.h, and from my reading of the other patches
> in your series you are calling it for these as well.

You are correct I have not consider that dma_mapping_error() call in to 
lib/dma-debug.c. I will see if I can make the dma_mapping_error() safe 
to use with a dma_addr_t obtained from dma_map_resource() and post a new 
series.

Thanks for pointing this out!

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource

2016-04-25 Thread Niklas Söderlund
Hi Christoph,

On 2016-04-21 06:49:42 -0700, Christoph Hellwig wrote:
> On Wed, Apr 13, 2016 at 03:29:17PM +0200, Niklas S?derlund wrote:
> > > Yes, it would be good to do an audit of all the ARM dma_ops as well
> > > as generic code like drivers/base/dma-*.c, lib/dma-debug.c and
> > > include/linux/dma-*.h
> 
> What about things like the phys_addr() helper in lib/dma-debug.c?  That
> was in fact what prompted my question for an audit, and it seems
> to not even feature on your list.  What patterns / symbols did you look
> for?


I have followed the call path from the usage in 
drivers/dma/sh/rcar-dmac.c and made sure the dma_addr_t is not used in a 
bad way.

I also looked at the dma-mapping API and ruled out that the only 
function that make sens to use with a dma_addr_t from dma_map_resource() 
are dma_unmap_resource() and dma_mapping_error(). With that I can't see 
how a dma_addr_t would end up in lib/dma-debug.c. But I might be missing 
something?

In the big picture do you feel the approach I have is the correct way to 
solve my problem? Provided we can work out this issues ofc?

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource

2016-03-11 Thread Niklas Söderlund
Hi all,

Thanks for your comments.

On 2016-03-11 03:15:22 -0800, Christoph Hellwig wrote:
> On Thu, Mar 10, 2016 at 10:47:10PM -0800, Dan Williams wrote:
> > I think it is confusing to use the dma_ prefix for this peer-to-peer
> > mmio functionality.  dma_addr_t is a device's view of host memory.
> > Something like bus_addr_t bus_map_resource().  Doesn't this routine
> > also need the source device in addition to the target device?  The
> > resource address is from the perspective of the host cpu, it may be a
> > different address space in the view of two devices relative to each
> > other.
> 
> Is it supposed to be per-mmio?  It's in dma-mapping ops, and has dma
> in the name, so I suspected it's for some form of peer dma.  But given
> that our dma APIs reuqire a struct page backing I have no idea how this
> even supposed to work, and this little documentation blurb still doesn't
> clear that up.
> 
> So for now I'd like to NAK this patch until the use case can be
> explained clearly, and actually works.

I can explain the use case and maybe we can figure out if this approach 
is the correct one to solve it.

The problem is that I have devices behind an IOMMU which I would like to 
use with DMA. Vinod recently moved forward with his and Linus Walleij
patch '[PATCH] dmaengine: use phys_addr_t for slave configuration' which 
clarifies that the DMA slave address provided by a client is the 
physical address. This puts the task of mapping the DMA slave address 
from a phys_addr_t to a dma_addr_t on the DMA engine.

Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are 
the same and no special care is needed. However if you have a IOMMU you 
need to map the DMA slave phys_addr_t to a dma_addr_t using something 
like this. Is it not very similar to dma_map_single() where one maps 
processor virtual memory (instead if MMIO) so that it can be used with 
DMA slaves?

-- 
Regards,
Niklas Söderlund
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 9/9] ARM: dts: r8a7791: add iommus to dmac0 and dmac1

2016-03-07 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7791.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index c6bee4a..341c460 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -283,6 +283,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -314,6 +329,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 4/9] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-03-07 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 1/9] iommu: Add MMIO mapping type

2016-03-07 Thread Niklas Söderlund
From: Robin Murphy <robin.mur...@arm.com>

On some platforms, MMIO regions might need slightly different treatment
compared to mapping regular memory; add the notion of MMIO mappings to
the IOMMU API's memory type flags, so that callers can let the IOMMU
drivers know to do the right thing.

Signed-off-by: Robin Murphy <robin.mur...@arm.com>
Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/iommu/io-pgtable-arm.c | 9 +++--
 include/linux/iommu.h  | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 381ca5a..9c19989 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -355,7 +355,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
arm_lpae_io_pgtable *data,
if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
pte |= ARM_LPAE_PTE_AP_RDONLY;
 
-   if (prot & IOMMU_CACHE)
+   if (prot & IOMMU_MMIO)
+   pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
+   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
+   else if (prot & IOMMU_CACHE)
pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
<< ARM_LPAE_PTE_ATTRINDX_SHIFT);
} else {
@@ -364,7 +367,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
arm_lpae_io_pgtable *data,
pte |= ARM_LPAE_PTE_HAP_READ;
if (prot & IOMMU_WRITE)
pte |= ARM_LPAE_PTE_HAP_WRITE;
-   if (prot & IOMMU_CACHE)
+   if (prot & IOMMU_MMIO)
+   pte |= ARM_LPAE_PTE_MEMATTR_DEV;
+   else if (prot & IOMMU_CACHE)
pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
else
pte |= ARM_LPAE_PTE_MEMATTR_NC;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a5c539f..34b6432 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -30,6 +30,7 @@
 #define IOMMU_WRITE(1 << 1)
 #define IOMMU_CACHE(1 << 2) /* DMA cache coherency */
 #define IOMMU_NOEXEC   (1 << 3)
+#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */
 
 struct iommu_ops;
 struct iommu_group;
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 8/9] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-03-07 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 26772f7..c600daa 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -325,6 +340,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 7/9] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-03-07 Thread Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 82 +-
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b3911fe..56816e3 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+   dma_addr_t addr;
+   enum dma_data_direction dir;
+   struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+   struct rcar_dmac_chan_map map;
int mid_rid;
 
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, 
dma_addr_t dma_dest,
  DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+   enum dma_transfer_direction dir)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac_chan_map *map = >map;
+   phys_addr_t dev_addr;
+   size_t dev_size;
+   enum dma_data_direction dev_dir;
+
+   if (dir == DMA_DEV_TO_MEM) {
+   dev_addr = rchan->src.slave_addr;
+   dev_size = rchan->src.xfer_size;
+   dev_dir = DMA_TO_DEVICE;
+   } else {
+   dev_addr = rchan->dst.slave_addr;
+   dev_size = rchan->dst.xfer_size;
+   dev_dir = DMA_FROM_DEVICE;
+   }
+
+   /* Reuse current map if possible. */
+   if (dev_addr == map->slave.slave_addr &&
+   dev_size == map->slave.xfer_size &&
+   dev_dir == map->dir)
+   return 0;
+
+   /* Remove old mapping if present. */
+   if (map->slave.xfer_size)
+   dma_unmap_resource(chan->device->dev, map->addr,
+  map->slave.xfer_size, map->dir, NULL);
+   map->slave.xfer_size = 0;
+
+   /* Create new slave address map. */
+   map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+dev_dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, map->addr)) {
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   dev_size, _addr);
+   return -EIO;
+   }
+
+   dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+   rchan->index, dev_size, _addr, >addr,
+   dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+   map->slave.slave_addr = dev_addr;
+   map->slave.xfer_size = dev_size;
+   map->dir = dev_dir;
+
+   return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-   dma_addr_t dev_addr;
 
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
return NULL;
}
 
-   dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src.slave_addr : rchan->dst.slave_addr;
-   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
+   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
  dir, flags, false);
 }
 
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
-   dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
 
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return NULL;
}
 
+   if (rcar_dmac_map_slave_addr(chan, dir))
+ 

[PATCH v5 0/9] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-03-07 Thread Niklas Söderlund
Hi,

This series add iommu support to rcar-dmac. It's tested on Koelsch with
CONFIG_IPMMU_VMSA and by enabling the ipmmu_ds node in r8a7791.dtsi. I
verified operation by interacting with /dev/mmcblk1 and the serial
console which both are devices behind the iommu.

The series depends patch '[PATCH] dmaengine: use phys_addr_t for slave
configuration'.

* Changes since v4
- Move the mapping from phys_addr_t to dma_addr_t from slave_config to the
  prepare calls. This way we know the direction of the mapping and don't have
  to use DMA_BIDIRECTIONAL. Thanks Vinod for suggesting this.
- To be clear that the data type for slave addresses are changed add a patch
  that only changes the data type to phys_addr_t.
- Fixed up commit messages.

* Changes since v3
- Folded in a fix from Robin to his patch.
- Added a check to make sure dma_map_resource can not be used to map RAM as
  pointed out by Robin. I use BUG_ON to enforce this. It might not be the best
  method but I saw no other good way since DMA_ERROR_CODE might not be defined
  on all platforms.
- Added comment about that DTS changes will disable 2 DMA channels due to a HW
  (?) but in the DMAC.
- Dropped the use of dma_attrs, no longer needed.
- Collected Acked-by and Reviewed-by from Laurent.
- Various indentation fix ups.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas Söderlund (8):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: slave address are physical
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

Robin Murphy (1):
  iommu: Add MMIO mapping type

 arch/arm/boot/dts/r8a7790.dtsi |  30 +++
 arch/arm/boot/dts/r8a7791.dtsi |  30 +++
 arch/arm/mm/dma-mapping.c  |  63 ++
 drivers/dma/sh/rcar-dmac.c | 116 +
 drivers/iommu/io-pgtable-arm.c |   9 +++-
 include/linux/dma-mapping.h|  38 ++
 include/linux/iommu.h  |   1 +
 7 files changed, 263 insertions(+), 24 deletions(-)

--
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical

2016-03-07 Thread Niklas Söderlund
Slave addresses coming from a client is physical not dma. Store the
address using the correct data type. This is in preparation for hooking
up the dma-mapping API to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..01cf82f 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -144,8 +144,8 @@ struct rcar_dmac_chan {
 
unsigned int src_xfer_size;
unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   phys_addr_t src_slave_addr;
+   phys_addr_t dst_slave_addr;
int mid_rid;
 
spinlock_t lock;
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource

2016-03-07 Thread Niklas Söderlund
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 32 
 1 file changed, 32 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..cc305d1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,38 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   if (ops->map_resource)
+   return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration

2016-03-07 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 01cf82f..b3911fe 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   phys_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   phys_addr_t src_slave_addr;
-   phys_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.7.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-02-16 Thread Niklas Söderlund
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 32 
 1 file changed, 32 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..cc305d1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,38 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   if (ops->map_resource)
+   return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 2/8] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-02-16 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 75857cd..e3aba4e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 0/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-16 Thread Niklas Söderlund
Hi,

This series add iommu support to rcar-dmac. It's tested on Koelsch with
CONFIG_IPMMU_VMSA and by enabling the ipmmu_ds node in r8a7791.dtsi. I verified
operation by interacting with /dev/mmcblk1  which is a device behind the iommu.

The series depends on out of tree patch '[PATCH] dmaengine: use phys_addr_t for
slave configuration' which Vinod now have moved forward whit, thanks!

* Changes since v3
- Folded in a fix from Robin to his patch.
- Added a check to make sure dma_map_resource can not be used to map RAM as
  pointed out by Robin. I use BUG_ON to enforce this. It might not be the best
  method but I saw no other good way since DMA_ERROR_CODE might not be defined
  on all platforms.
- Added comment about that DTS changes will disable 2 DMA channels due to a HW
  (?) but in the DMAC.
- Dropped the use of dma_attrs, no longer needed.
- Collected Acked-by and Reviewed-by from Laurent.
- Various indentation fix ups.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.


Niklas Söderlund (7):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

Robin Murphy (1):
  iommu: Add MMIO mapping type

 arch/arm/boot/dts/r8a7790.dtsi | 30 
 arch/arm/boot/dts/r8a7791.dtsi | 30 
 arch/arm/mm/dma-mapping.c  | 63 
 drivers/dma/sh/rcar-dmac.c | 81 +-
 drivers/iommu/io-pgtable-arm.c |  9 +++--
 include/linux/dma-mapping.h| 38 
 include/linux/iommu.h  |  1 +
 7 files changed, 233 insertions(+), 19 deletions(-)

--
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 4/8] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-02-16 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-02-16 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 7dfd393..048bbf8 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -325,6 +340,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 6/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-16 Thread Niklas Söderlund
Enable slave transfers to devices behind IPMMU:s by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 52 +-
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 743873c..6a24847 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1106,21 +1106,63 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return desc;
 }
 
+static int rcar_dmac_set_slave_addr(struct dma_chan *chan,
+struct rcar_dmac_chan_slave *slave,
+phys_addr_t addr, size_t size)
+{
+   enum dma_data_direction dir;
+
+   /*
+* We can't know the direction at this time, see documentation for
+* 'direction' in struct dma_slave_config.
+*/
+   dir = DMA_BIDIRECTIONAL;
+
+   if (slave->xfer_size) {
+   dma_unmap_resource(chan->device->dev, slave->slave_addr,
+  slave->xfer_size, dir, NULL);
+   slave->slave_addr = 0;
+   slave->xfer_size = 0;
+   }
+
+   if (size) {
+   slave->slave_addr = dma_map_resource(chan->device->dev, addr,
+   size, dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, slave->slave_addr)) {
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   size, );
+   return -EIO;
+   }
+
+   slave->xfer_size = size;
+   }
+
+   return 0;
+}
+
 static int rcar_dmac_device_config(struct dma_chan *chan,
   struct dma_slave_config *cfg)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   int ret;
 
/*
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src.slave_addr = cfg->src_addr;
-   rchan->dst.slave_addr = cfg->dst_addr;
-   rchan->src.xfer_size = cfg->src_addr_width;
-   rchan->dst.xfer_size = cfg->dst_addr_width;
 
-   return 0;
+   ret = rcar_dmac_set_slave_addr(chan, >src, cfg->src_addr,
+  cfg->src_addr_width);
+   if (ret)
+   return ret;
+
+   ret = rcar_dmac_set_slave_addr(chan, >dst, cfg->dst_addr,
+  cfg->dst_addr_width);
+   return ret;
 }
 
 static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v4 5/8] dmaengine: rcar-dmac: group slave configuration

2016-02-16 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
---
 drivers/dma/sh/rcar-dmac.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..743873c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,21 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   dma_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +149,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +798,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1043,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1098,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1115,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-16 Thread Niklas Söderlund
* Robin Murphy <robin.mur...@arm.com> [2016-02-16 12:43:40 +]:

> On 16/02/16 12:06, Niklas Söderlund wrote:
> >Hi Robin,
> >
> >Thanks for your update patch I will include it in my next version. But
> >I'm sorry I do not understand, is your modification an addition or a
> >substitution to your original patch?
>
> Apologies for being confusing - that was a diff on top of the existing
> patch, to be folded in. My original patch was only handling IOMMU_MMIO for
> stage 2 PTEs, so we also need the extra code to handle the different way of
> setting the appropriate memory type in stage 1 PTEs.

That's what I though but wanted to be clear, thanks for clarifying. I
will fold the diff into your patch and keep your SoB line and send it
out with my series, hope that's a OK way for me to handle it.

Once more thanks for your patch and feedback.

>
> Robin.
>
> >* Robin Murphy <robin.mur...@arm.com> [2016-02-11 15:57:26 +]:
> >
> >>On 11/02/16 00:02, Laurent Pinchart wrote:
> >>>Hi Niklas,
> >>>
> >>>Thank you for the patch.
> >>>
> >>>On Wednesday 10 February 2016 01:57:51 Niklas Söderlund wrote:
> >>>>From: Robin Murphy <robin.mur...@arm.com>
> >>>>
> >>>>On some platforms, MMIO regions might need slightly different treatment
> >>>>compared to mapping regular memory; add the notion of MMIO mappings to
> >>>>the IOMMU API's memory type flags, so that callers can let the IOMMU
> >>>>drivers know to do the right thing.
> >>>>
> >>>>Signed-off-by: Robin Murphy <robin.mur...@arm.com>
> >>>>Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> >>>
> >>>Answering the question from the cover letter, yes, it's totally fine to 
> >>>pick
> >>>the ack, that's actually expected.
> >>>
> >>>>---
> >>>>  drivers/iommu/io-pgtable-arm.c | 4 +++-
> >>>>  include/linux/iommu.h  | 1 +
> >>>
> >>>You might be asked to split this patch in two.
> >>
> >>Worse than that, you might also be asked to fix it up when the silly author
> >>remembers that he did this on a stage-2-only ARM SMMU, and the attributes
> >>for the stage 1 tables that the IPMMU uses are in a different code path:
> >>
> >>--->8---
> >>diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> >>index 5b5c299..7622c6e 100644
> >>--- a/drivers/iommu/io-pgtable-arm.c
> >>+++ b/drivers/iommu/io-pgtable-arm.c
> >>@@ -354,7 +354,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> >>arm_lpae_io_pgtable *data,
> >> if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
> >> pte |= ARM_LPAE_PTE_AP_RDONLY;
> >>
> >>-   if (prot & IOMMU_CACHE)
> >>+   if (prot & IOMMU_MMIO)
> >>+   pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
> >>+   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> >>+   else if (prot & IOMMU_CACHE)
> >> pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
> >> << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> >> } else {
> >>--->8---
> >>
> >>Sorry for the bother,
> >>Robin.
> >>
> >>>>  2 files changed, 4 insertions(+), 1 deletion(-)
> >>>>
> >>>>diff --git a/drivers/iommu/io-pgtable-arm.c 
> >>>>b/drivers/iommu/io-pgtable-arm.c
> >>>>index 381ca5a..3ff4f87 100644
> >>>>--- a/drivers/iommu/io-pgtable-arm.c
> >>>>+++ b/drivers/iommu/io-pgtable-arm.c
> >>>>@@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> >>>>arm_lpae_io_pgtable *data, pte |= ARM_LPAE_PTE_HAP_READ;
> >>>>  if (prot & IOMMU_WRITE)
> >>>>  pte |= ARM_LPAE_PTE_HAP_WRITE;
> >>>>- if (prot & IOMMU_CACHE)
> >>>>+ if (prot & IOMMU_MMIO)
> >>>>+ pte |= ARM_LPAE_PTE_MEMATTR_DEV;
> >>>>+ else if (prot & IOMMU_CACHE)
> >>>>  pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
> >>>>  else
> >>>>  pte |= ARM_LPAE_PTE_MEMATTR_NC;
> >>>>diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> >>>>index a5c539f..34b6432 100644
> >>>>--- a/include/linux/iommu.h
> >>>>+++ b/include/linux/iommu.h
> >>>>@@ -30,6 +30,7 @@
> >>>>  #define IOMMU_WRITE (1 << 1)
> >>>>  #define IOMMU_CACHE (1 << 2) /* DMA cache coherency */
> >>>>  #define IOMMU_NOEXEC(1 << 3)
> >>>>+#define IOMMU_MMIO   (1 << 4) /* e.g. things like MSI doorbells */
> >>>>
> >>>>  struct iommu_ops;
> >>>>  struct iommu_group;
> >>>
> >>
> >
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-16 Thread Niklas Söderlund
Hi Robin,

Thanks for your update patch I will include it in my next version. But
I'm sorry I do not understand, is your modification an addition or a
substitution to your original patch?

* Robin Murphy <robin.mur...@arm.com> [2016-02-11 15:57:26 +]:

> On 11/02/16 00:02, Laurent Pinchart wrote:
> >Hi Niklas,
> >
> >Thank you for the patch.
> >
> >On Wednesday 10 February 2016 01:57:51 Niklas Söderlund wrote:
> >>From: Robin Murphy <robin.mur...@arm.com>
> >>
> >>On some platforms, MMIO regions might need slightly different treatment
> >>compared to mapping regular memory; add the notion of MMIO mappings to
> >>the IOMMU API's memory type flags, so that callers can let the IOMMU
> >>drivers know to do the right thing.
> >>
> >>Signed-off-by: Robin Murphy <robin.mur...@arm.com>
> >>Acked-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
> >
> >Answering the question from the cover letter, yes, it's totally fine to pick
> >the ack, that's actually expected.
> >
> >>---
> >>  drivers/iommu/io-pgtable-arm.c | 4 +++-
> >>  include/linux/iommu.h  | 1 +
> >
> >You might be asked to split this patch in two.
>
> Worse than that, you might also be asked to fix it up when the silly author
> remembers that he did this on a stage-2-only ARM SMMU, and the attributes
> for the stage 1 tables that the IPMMU uses are in a different code path:
>
> --->8---
> diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> index 5b5c299..7622c6e 100644
> --- a/drivers/iommu/io-pgtable-arm.c
> +++ b/drivers/iommu/io-pgtable-arm.c
> @@ -354,7 +354,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> arm_lpae_io_pgtable *data,
> if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
> pte |= ARM_LPAE_PTE_AP_RDONLY;
>
> -   if (prot & IOMMU_CACHE)
> +   if (prot & IOMMU_MMIO)
> +   pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV
> +   << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> +   else if (prot & IOMMU_CACHE)
> pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
> << ARM_LPAE_PTE_ATTRINDX_SHIFT);
> } else {
> --->8---
>
> Sorry for the bother,
> Robin.
>
> >>  2 files changed, 4 insertions(+), 1 deletion(-)
> >>
> >>diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> >>index 381ca5a..3ff4f87 100644
> >>--- a/drivers/iommu/io-pgtable-arm.c
> >>+++ b/drivers/iommu/io-pgtable-arm.c
> >>@@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct
> >>arm_lpae_io_pgtable *data, pte |= ARM_LPAE_PTE_HAP_READ;
> >>if (prot & IOMMU_WRITE)
> >>pte |= ARM_LPAE_PTE_HAP_WRITE;
> >>-   if (prot & IOMMU_CACHE)
> >>+   if (prot & IOMMU_MMIO)
> >>+   pte |= ARM_LPAE_PTE_MEMATTR_DEV;
> >>+   else if (prot & IOMMU_CACHE)
> >>pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
> >>else
> >>pte |= ARM_LPAE_PTE_MEMATTR_NC;
> >>diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> >>index a5c539f..34b6432 100644
> >>--- a/include/linux/iommu.h
> >>+++ b/include/linux/iommu.h
> >>@@ -30,6 +30,7 @@
> >>  #define IOMMU_WRITE   (1 << 1)
> >>  #define IOMMU_CACHE   (1 << 2) /* DMA cache coherency */
> >>  #define IOMMU_NOEXEC  (1 << 3)
> >>+#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */
> >>
> >>  struct iommu_ops;
> >>  struct iommu_group;
> >
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-02-12 Thread Niklas Söderlund
Hi Simon,

* Simon Horman  [2016-02-10 18:55:59 +0100]:

> Hi Niklas,
>
> I am deferring accepting this and the similar patch for the r8a7791 pending
> acceptance of the driver changes earlier in this series. Please let me know
> if you prefer a different course of action.

That sounds good, thanks.

>
> I notice that the devel branch of there renesas tree there are
> dmac nodes for the r8a7793, r8a7794 and r8a7795. Is this change,
> also suitable for those SoCs? If so, do you plan to update them?
> If not I'll add it to my todo list.

I planed to update all effected SoCs once the dependencies for this
series where accepted. But if you want to keep track of this I'm happy.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 4/8] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-02-09 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 2/8] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-02-09 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to map be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 75857cd..e3aba4e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 8/8] ARM: dts: r8a7791: add iommus to dmac0 and dmac1

2016-02-09 Thread Niklas Söderlund
Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 arch/arm/boot/dts/r8a7791.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 2a369dd..6dff061 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -283,6 +283,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -314,6 +329,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-02-09 Thread Niklas Söderlund
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 include/linux/dma-mapping.h | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..21bf986 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,33 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->map_resource)
+   return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-09 Thread Niklas Söderlund
From: Robin Murphy 

On some platforms, MMIO regions might need slightly different treatment
compared to mapping regular memory; add the notion of MMIO mappings to
the IOMMU API's memory type flags, so that callers can let the IOMMU
drivers know to do the right thing.

Signed-off-by: Robin Murphy 
Acked-by: Laurent Pinchart 
---
 drivers/iommu/io-pgtable-arm.c | 4 +++-
 include/linux/iommu.h  | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 381ca5a..3ff4f87 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
arm_lpae_io_pgtable *data,
pte |= ARM_LPAE_PTE_HAP_READ;
if (prot & IOMMU_WRITE)
pte |= ARM_LPAE_PTE_HAP_WRITE;
-   if (prot & IOMMU_CACHE)
+   if (prot & IOMMU_MMIO)
+   pte |= ARM_LPAE_PTE_MEMATTR_DEV;
+   else if (prot & IOMMU_CACHE)
pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
else
pte |= ARM_LPAE_PTE_MEMATTR_NC;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a5c539f..34b6432 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -30,6 +30,7 @@
 #define IOMMU_WRITE(1 << 1)
 #define IOMMU_CACHE(1 << 2) /* DMA cache coherency */
 #define IOMMU_NOEXEC   (1 << 3)
+#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */
 
 struct iommu_ops;
 struct iommu_group;
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 5/8] dmaengine: rcar-dmac: group slave configuration

2016-02-09 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..743873c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,21 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   dma_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +149,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +798,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1043,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1098,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1115,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-02-09 Thread Niklas Söderlund
Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 7dfd393..048bbf8 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -325,6 +340,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 6/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-09 Thread Niklas Söderlund
Enable slave transfers to devices behind IPMMU:s by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund <niklas.soderlund+rene...@ragnatech.se>
---
 drivers/dma/sh/rcar-dmac.c | 57 ++
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 743873c..268407c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1106,21 +1106,68 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return desc;
 }
 
+static int rcar_dmac_set_slave_addr(struct dma_chan *chan,
+struct rcar_dmac_chan_slave *slave,
+phys_addr_t addr, size_t size)
+{
+   struct dma_attrs attrs;
+   enum dma_data_direction dir;
+
+   init_dma_attrs();
+   dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, );
+   dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, );
+
+   /*
+* We can't know the direction at this time, see documentation for
+* 'direction' in struct dma_slave_config.
+*/
+   dir = DMA_BIDIRECTIONAL;
+
+   if (slave->xfer_size) {
+   dma_unmap_resource(chan->device->dev, slave->slave_addr,
+   slave->xfer_size, dir, );
+   slave->slave_addr = 0;
+   slave->xfer_size = 0;
+   }
+
+   if (size) {
+   slave->slave_addr = dma_map_resource(chan->device->dev, addr,
+   size, dir, );
+
+   if (dma_mapping_error(chan->device->dev, slave->slave_addr)) {
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap",
+   rchan->index, size, );
+   return -EIO;
+   }
+
+   slave->xfer_size = size;
+   }
+
+   return 0;
+}
+
 static int rcar_dmac_device_config(struct dma_chan *chan,
   struct dma_slave_config *cfg)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   int ret;
 
/*
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src.slave_addr = cfg->src_addr;
-   rchan->dst.slave_addr = cfg->dst_addr;
-   rchan->src.xfer_size = cfg->src_addr_width;
-   rchan->dst.xfer_size = cfg->dst_addr_width;
 
-   return 0;
+   ret = rcar_dmac_set_slave_addr(chan, >src, cfg->src_addr,
+   cfg->src_addr_width);
+   if (ret)
+   return ret;
+
+   ret = rcar_dmac_set_slave_addr(chan, >dst, cfg->dst_addr,
+   cfg->dst_addr_width);
+   return ret;
 }
 
 static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
-- 
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v3 0/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-09 Thread Niklas Söderlund
Hi,

This series add iommu support to rcar-dmac. It's tested on koelsch with
CONFIG_IPMMU_VMSA and by enabling the ipmmu_ds node in r8a7791.dtsi. I
verified operation by interacting with /dev/mmcblk1  which is a device
behind the iommu.

The series depends on out of tree patch '[PATCH] dmaengine: use
phys_addr_t for slave configuration' which currently is under review.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas Söderlund (7):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

Robin Murphy (1):
  iommu: Add MMIO mapping type

 arch/arm/boot/dts/r8a7790.dtsi | 30 +++
 arch/arm/boot/dts/r8a7791.dtsi | 30 +++
 arch/arm/mm/dma-mapping.c  | 63 +++
 drivers/dma/sh/rcar-dmac.c | 86 +-
 drivers/iommu/io-pgtable-arm.c |  4 +-
 include/linux/dma-mapping.h| 33 
 include/linux/iommu.h  |  1 +
 7 files changed, 229 insertions(+), 18 deletions(-)

--
2.7.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu