Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Robert Richter
On 08.05.17 10:59:46, Robin Murphy wrote:
> On 08/05/17 10:17, Linu Cherian wrote:
> > This actually results in more lines of changes. If you think the below
> > approach is still better, will post a V4 of this series with this change.
> 
> Why not just do this?:
> 
> static inline unsigned long page1_offset_adjust(
>   unsigned long off, struct arm_smmu_device *smmu)
> {
>   if (off > SZ_64K && ARM_SMMU_PAGE0_REGS_ONLY(smmu))
>   return (off - SZ_64K);
> 
>   return off;
> }
> 
> AFAICS that should be the least disruptive way to go about it.

Yeah, let's go with this.

Thanks Robin,

-Robert


Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Robert Richter
On 08.05.17 10:59:46, Robin Murphy wrote:
> On 08/05/17 10:17, Linu Cherian wrote:
> > This actually results in more lines of changes. If you think the below
> > approach is still better, will post a V4 of this series with this change.
> 
> Why not just do this?:
> 
> static inline unsigned long page1_offset_adjust(
>   unsigned long off, struct arm_smmu_device *smmu)
> {
>   if (off > SZ_64K && ARM_SMMU_PAGE0_REGS_ONLY(smmu))
>   return (off - SZ_64K);
> 
>   return off;
> }
> 
> AFAICS that should be the least disruptive way to go about it.

Yeah, let's go with this.

Thanks Robin,

-Robert


Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Robin Murphy
On 08/05/17 10:17, Linu Cherian wrote:
> On Sat May 06, 2017 at 01:03:28AM +0200, Robert Richter wrote:
>> On 05.05.17 17:38:05, Geetha sowjanya wrote:
>>> From: Linu Cherian 
>>>
>>> Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
>>> and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
>>>
>>> This option when turned on, replaces all page 1 offsets used for
>>> EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
>>>
>>> Signed-off-by: Linu Cherian 
>>> Signed-off-by: Geetha Sowjanya 
>>> ---
>>>  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
>>>  drivers/iommu/arm-smmu-v3.c| 44 
>>> --
>>>  2 files changed, 38 insertions(+), 12 deletions(-)
>>
>>> @@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct 
>>> arm_smmu_device *smmu)
>>> if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>>> return 0;
>>>  
>>> -   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
>>> -  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
>>> +   return arm_smmu_init_one_queue(smmu, >priq.q,
>>> +  ARM_SMMU_PRIQ_PROD(smmu),
>>> +  ARM_SMMU_PRIQ_CONS(smmu),
>>> +  PRIQ_ENT_DWORDS);
>>
>> I would also suggest Robin's idea from the v1 review here. This works
>> if we rework arm_smmu_init_one_queue() to pass addresses instead of
>> offsets.
>>
>> This would make these widespread offset calculations obsolete.
>>
> 
> Have pasted here the relevant changes for doing fixups on smmu base instead
> of offset to get feedback. 
> 
> This actually results in more lines of changes. If you think the below
> approach is still better, will post a V4 of this series with this change.

Why not just do this?:

static inline unsigned long page1_offset_adjust(
unsigned long off, struct arm_smmu_device *smmu)
{
if (off > SZ_64K && ARM_SMMU_PAGE0_REGS_ONLY(smmu))
return (off - SZ_64K);

return off;
}

AFAICS that should be the least disruptive way to go about it.

Robin.

> 
> 
> +static inline unsigned long arm_smmu_page1_base(
> + struct arm_smmu_device *smmu)
> +{
> + if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
> + return smmu->base;
> + else
> + return smmu->base + SZ_64K;
> +}
> +
> 
> @@ -1948,8 +1962,8 @@ static void arm_smmu_put_resv_regions(struct device 
> *dev,
>  /* Probing and initialisation functions */
>  static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
>  struct arm_smmu_queue *q,
> -unsigned long prod_off,
> -unsigned long cons_off,
> +unsigned long prod_addr,
> +unsigned long cons_addr,
>  size_t dwords)
>  {
>   size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
> @@ -1961,8 +1975,8 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>   return -ENOMEM;
>   }
>  
> - q->prod_reg = smmu->base + prod_off;
> - q->cons_reg = smmu->base + cons_off;
> + q->prod_reg = prod_addr;
> + q->cons_reg = cons_addr;
>   q->ent_dwords   = dwords;
>  
>   q->q_base  = Q_BASE_RWA;
> @@ -1977,17 +1991,25 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>  static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
>  {
>   int ret;
> + unsigned long page1_base, page0_base;
> +
> + page0_base = smmu->base;
> + page1_base = arm_smmu_page1_base(smmu);
>  
>   /* cmdq */
>   spin_lock_init(>cmdq.lock);
> - ret = arm_smmu_init_one_queue(smmu, >cmdq.q, ARM_SMMU_CMDQ_PROD,
> -   ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >cmdq.q, 
> +   page0_base + ARM_SMMU_CMDQ_PROD,
> +   page0_base + ARM_SMMU_CMDQ_CONS, 
> +   CMDQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
>   /* evtq */
> - ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
> -   ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >evtq.q,
> +   page1_base + ARM_SMMU_EVTQ_PROD,
> +   page1_base + ARM_SMMU_EVTQ_CONS,
> +   EVTQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
> @@ -1995,8 +2017,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
> *smmu)
>   if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>   return 0;
>  
> - return arm_smmu_init_one_queue(smmu, 

Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Robin Murphy
On 08/05/17 10:17, Linu Cherian wrote:
> On Sat May 06, 2017 at 01:03:28AM +0200, Robert Richter wrote:
>> On 05.05.17 17:38:05, Geetha sowjanya wrote:
>>> From: Linu Cherian 
>>>
>>> Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
>>> and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
>>>
>>> This option when turned on, replaces all page 1 offsets used for
>>> EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
>>>
>>> Signed-off-by: Linu Cherian 
>>> Signed-off-by: Geetha Sowjanya 
>>> ---
>>>  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
>>>  drivers/iommu/arm-smmu-v3.c| 44 
>>> --
>>>  2 files changed, 38 insertions(+), 12 deletions(-)
>>
>>> @@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct 
>>> arm_smmu_device *smmu)
>>> if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>>> return 0;
>>>  
>>> -   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
>>> -  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
>>> +   return arm_smmu_init_one_queue(smmu, >priq.q,
>>> +  ARM_SMMU_PRIQ_PROD(smmu),
>>> +  ARM_SMMU_PRIQ_CONS(smmu),
>>> +  PRIQ_ENT_DWORDS);
>>
>> I would also suggest Robin's idea from the v1 review here. This works
>> if we rework arm_smmu_init_one_queue() to pass addresses instead of
>> offsets.
>>
>> This would make these widespread offset calculations obsolete.
>>
> 
> Have pasted here the relevant changes for doing fixups on smmu base instead
> of offset to get feedback. 
> 
> This actually results in more lines of changes. If you think the below
> approach is still better, will post a V4 of this series with this change.

Why not just do this?:

static inline unsigned long page1_offset_adjust(
unsigned long off, struct arm_smmu_device *smmu)
{
if (off > SZ_64K && ARM_SMMU_PAGE0_REGS_ONLY(smmu))
return (off - SZ_64K);

return off;
}

AFAICS that should be the least disruptive way to go about it.

Robin.

> 
> 
> +static inline unsigned long arm_smmu_page1_base(
> + struct arm_smmu_device *smmu)
> +{
> + if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
> + return smmu->base;
> + else
> + return smmu->base + SZ_64K;
> +}
> +
> 
> @@ -1948,8 +1962,8 @@ static void arm_smmu_put_resv_regions(struct device 
> *dev,
>  /* Probing and initialisation functions */
>  static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
>  struct arm_smmu_queue *q,
> -unsigned long prod_off,
> -unsigned long cons_off,
> +unsigned long prod_addr,
> +unsigned long cons_addr,
>  size_t dwords)
>  {
>   size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
> @@ -1961,8 +1975,8 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>   return -ENOMEM;
>   }
>  
> - q->prod_reg = smmu->base + prod_off;
> - q->cons_reg = smmu->base + cons_off;
> + q->prod_reg = prod_addr;
> + q->cons_reg = cons_addr;
>   q->ent_dwords   = dwords;
>  
>   q->q_base  = Q_BASE_RWA;
> @@ -1977,17 +1991,25 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>  static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
>  {
>   int ret;
> + unsigned long page1_base, page0_base;
> +
> + page0_base = smmu->base;
> + page1_base = arm_smmu_page1_base(smmu);
>  
>   /* cmdq */
>   spin_lock_init(>cmdq.lock);
> - ret = arm_smmu_init_one_queue(smmu, >cmdq.q, ARM_SMMU_CMDQ_PROD,
> -   ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >cmdq.q, 
> +   page0_base + ARM_SMMU_CMDQ_PROD,
> +   page0_base + ARM_SMMU_CMDQ_CONS, 
> +   CMDQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
>   /* evtq */
> - ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
> -   ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >evtq.q,
> +   page1_base + ARM_SMMU_EVTQ_PROD,
> +   page1_base + ARM_SMMU_EVTQ_CONS,
> +   EVTQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
> @@ -1995,8 +2017,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
> *smmu)
>   if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>   return 0;
>  
> - return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> -ARM_SMMU_PRIQ_CONS, 

Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Robert Richter
On 08.05.17 14:47:39, Linu Cherian wrote:
> Have pasted here the relevant changes for doing fixups on smmu base instead
> of offset to get feedback. 

To me this looks better than the ARM_SMMU_EVTQ_*() macros. It still
needs some more shaping (e.g. maybe remove page1_base var and call
arm_smmu_page1_base() directly).

But let's see what others say first.

Thanks,

-Robert

> 
> This actually results in more lines of changes. If you think the below
> approach is still better, will post a V4 of this series with this change.
> 
> 
> +static inline unsigned long arm_smmu_page1_base(
> + struct arm_smmu_device *smmu)
> +{
> + if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
> + return smmu->base;
> + else
> + return smmu->base + SZ_64K;
> +}
> +
> 
> @@ -1948,8 +1962,8 @@ static void arm_smmu_put_resv_regions(struct device 
> *dev,
>  /* Probing and initialisation functions */
>  static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
>  struct arm_smmu_queue *q,
> -unsigned long prod_off,
> -unsigned long cons_off,
> +unsigned long prod_addr,
> +unsigned long cons_addr,
>  size_t dwords)
>  {
>   size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
> @@ -1961,8 +1975,8 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>   return -ENOMEM;
>   }
>  
> - q->prod_reg = smmu->base + prod_off;
> - q->cons_reg = smmu->base + cons_off;
> + q->prod_reg = prod_addr;
> + q->cons_reg = cons_addr;
>   q->ent_dwords   = dwords;
>  
>   q->q_base  = Q_BASE_RWA;
> @@ -1977,17 +1991,25 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>  static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
>  {
>   int ret;
> + unsigned long page1_base, page0_base;
> +
> + page0_base = smmu->base;
> + page1_base = arm_smmu_page1_base(smmu);
>  
>   /* cmdq */
>   spin_lock_init(>cmdq.lock);
> - ret = arm_smmu_init_one_queue(smmu, >cmdq.q, ARM_SMMU_CMDQ_PROD,
> -   ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >cmdq.q, 
> +   page0_base + ARM_SMMU_CMDQ_PROD,
> +   page0_base + ARM_SMMU_CMDQ_CONS, 
> +   CMDQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
>   /* evtq */
> - ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
> -   ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >evtq.q,
> +   page1_base + ARM_SMMU_EVTQ_PROD,
> +   page1_base + ARM_SMMU_EVTQ_CONS,
> +   EVTQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
> @@ -1995,8 +2017,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
> *smmu)
>   if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>   return 0;
>  
> - return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> -ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
> + return arm_smmu_init_one_queue(smmu, >priq.q,
> +page1_base + ARM_SMMU_PRIQ_PROD,
> +page1_base + ARM_SMMU_PRIQ_CONS,
> +PRIQ_ENT_DWORDS);
>  }
> 
> 
> 
> @@ -2301,8 +2349,11 @@ static int arm_smmu_device_reset(struct 
> arm_smmu_device *smmu, bool bypass)
>  {
>   int ret;
>   u32 reg, enables;
> + unsigned long page1_base;
>   struct arm_smmu_cmdq_ent cmd;
>  
> + page1_base = arm_smmu_page1_base(smmu);
> +
>   /* Clear CR0 and sync (disables SMMU and queue processing) */
>   reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
>   if (reg & CR0_SMMUEN)
> @@ -2363,8 +2414,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
> *smmu, bool bypass)
>  
>   /* Event queue */
>   writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
> - writel_relaxed(smmu->evtq.q.prod, smmu->base + ARM_SMMU_EVTQ_PROD);
> - writel_relaxed(smmu->evtq.q.cons, smmu->base + ARM_SMMU_EVTQ_CONS);
> + writel_relaxed(smmu->evtq.q.prod, page1_base + ARM_SMMU_EVTQ_PROD);
> + writel_relaxed(smmu->evtq.q.cons, page1_base + ARM_SMMU_EVTQ_CONS);
>  
>   enables |= CR0_EVTQEN;
>   ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
> @@ -2379,9 +2430,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
> *smmu, bool bypass)
>   writeq_relaxed(smmu->priq.q.q_base,
>  smmu->base + ARM_SMMU_PRIQ_qBASE);
>   writel_relaxed(smmu->priq.q.prod,
> -

Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Robert Richter
On 08.05.17 14:47:39, Linu Cherian wrote:
> Have pasted here the relevant changes for doing fixups on smmu base instead
> of offset to get feedback. 

To me this looks better than the ARM_SMMU_EVTQ_*() macros. It still
needs some more shaping (e.g. maybe remove page1_base var and call
arm_smmu_page1_base() directly).

But let's see what others say first.

Thanks,

-Robert

> 
> This actually results in more lines of changes. If you think the below
> approach is still better, will post a V4 of this series with this change.
> 
> 
> +static inline unsigned long arm_smmu_page1_base(
> + struct arm_smmu_device *smmu)
> +{
> + if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
> + return smmu->base;
> + else
> + return smmu->base + SZ_64K;
> +}
> +
> 
> @@ -1948,8 +1962,8 @@ static void arm_smmu_put_resv_regions(struct device 
> *dev,
>  /* Probing and initialisation functions */
>  static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
>  struct arm_smmu_queue *q,
> -unsigned long prod_off,
> -unsigned long cons_off,
> +unsigned long prod_addr,
> +unsigned long cons_addr,
>  size_t dwords)
>  {
>   size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
> @@ -1961,8 +1975,8 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>   return -ENOMEM;
>   }
>  
> - q->prod_reg = smmu->base + prod_off;
> - q->cons_reg = smmu->base + cons_off;
> + q->prod_reg = prod_addr;
> + q->cons_reg = cons_addr;
>   q->ent_dwords   = dwords;
>  
>   q->q_base  = Q_BASE_RWA;
> @@ -1977,17 +1991,25 @@ static int arm_smmu_init_one_queue(struct 
> arm_smmu_device *smmu,
>  static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
>  {
>   int ret;
> + unsigned long page1_base, page0_base;
> +
> + page0_base = smmu->base;
> + page1_base = arm_smmu_page1_base(smmu);
>  
>   /* cmdq */
>   spin_lock_init(>cmdq.lock);
> - ret = arm_smmu_init_one_queue(smmu, >cmdq.q, ARM_SMMU_CMDQ_PROD,
> -   ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >cmdq.q, 
> +   page0_base + ARM_SMMU_CMDQ_PROD,
> +   page0_base + ARM_SMMU_CMDQ_CONS, 
> +   CMDQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
>   /* evtq */
> - ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
> -   ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
> + ret = arm_smmu_init_one_queue(smmu, >evtq.q,
> +   page1_base + ARM_SMMU_EVTQ_PROD,
> +   page1_base + ARM_SMMU_EVTQ_CONS,
> +   EVTQ_ENT_DWORDS);
>   if (ret)
>   return ret;
>  
> @@ -1995,8 +2017,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
> *smmu)
>   if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>   return 0;
>  
> - return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> -ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
> + return arm_smmu_init_one_queue(smmu, >priq.q,
> +page1_base + ARM_SMMU_PRIQ_PROD,
> +page1_base + ARM_SMMU_PRIQ_CONS,
> +PRIQ_ENT_DWORDS);
>  }
> 
> 
> 
> @@ -2301,8 +2349,11 @@ static int arm_smmu_device_reset(struct 
> arm_smmu_device *smmu, bool bypass)
>  {
>   int ret;
>   u32 reg, enables;
> + unsigned long page1_base;
>   struct arm_smmu_cmdq_ent cmd;
>  
> + page1_base = arm_smmu_page1_base(smmu);
> +
>   /* Clear CR0 and sync (disables SMMU and queue processing) */
>   reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
>   if (reg & CR0_SMMUEN)
> @@ -2363,8 +2414,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
> *smmu, bool bypass)
>  
>   /* Event queue */
>   writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
> - writel_relaxed(smmu->evtq.q.prod, smmu->base + ARM_SMMU_EVTQ_PROD);
> - writel_relaxed(smmu->evtq.q.cons, smmu->base + ARM_SMMU_EVTQ_CONS);
> + writel_relaxed(smmu->evtq.q.prod, page1_base + ARM_SMMU_EVTQ_PROD);
> + writel_relaxed(smmu->evtq.q.cons, page1_base + ARM_SMMU_EVTQ_CONS);
>  
>   enables |= CR0_EVTQEN;
>   ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
> @@ -2379,9 +2430,9 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
> *smmu, bool bypass)
>   writeq_relaxed(smmu->priq.q.q_base,
>  smmu->base + ARM_SMMU_PRIQ_qBASE);
>   writel_relaxed(smmu->priq.q.prod,
> -

Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Linu Cherian
On Sat May 06, 2017 at 01:03:28AM +0200, Robert Richter wrote:
> On 05.05.17 17:38:05, Geetha sowjanya wrote:
> > From: Linu Cherian 
> > 
> > Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
> > and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
> > 
> > This option when turned on, replaces all page 1 offsets used for
> > EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
> > 
> > Signed-off-by: Linu Cherian 
> > Signed-off-by: Geetha Sowjanya 
> > ---
> >  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
> >  drivers/iommu/arm-smmu-v3.c| 44 
> > --
> >  2 files changed, 38 insertions(+), 12 deletions(-)
> 
> > @@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct 
> > arm_smmu_device *smmu)
> > if (!(smmu->features & ARM_SMMU_FEAT_PRI))
> > return 0;
> >  
> > -   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> > -  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
> > +   return arm_smmu_init_one_queue(smmu, >priq.q,
> > +  ARM_SMMU_PRIQ_PROD(smmu),
> > +  ARM_SMMU_PRIQ_CONS(smmu),
> > +  PRIQ_ENT_DWORDS);
> 
> I would also suggest Robin's idea from the v1 review here. This works
> if we rework arm_smmu_init_one_queue() to pass addresses instead of
> offsets.
> 
> This would make these widespread offset calculations obsolete.
>

Have pasted here the relevant changes for doing fixups on smmu base instead
of offset to get feedback. 

This actually results in more lines of changes. If you think the below
approach is still better, will post a V4 of this series with this change.


+static inline unsigned long arm_smmu_page1_base(
+   struct arm_smmu_device *smmu)
+{
+   if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
+   return smmu->base;
+   else
+   return smmu->base + SZ_64K;
+}
+

@@ -1948,8 +1962,8 @@ static void arm_smmu_put_resv_regions(struct device *dev,
 /* Probing and initialisation functions */
 static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
   struct arm_smmu_queue *q,
-  unsigned long prod_off,
-  unsigned long cons_off,
+  unsigned long prod_addr,
+  unsigned long cons_addr,
   size_t dwords)
 {
size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
@@ -1961,8 +1975,8 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device 
*smmu,
return -ENOMEM;
}
 
-   q->prod_reg = smmu->base + prod_off;
-   q->cons_reg = smmu->base + cons_off;
+   q->prod_reg = prod_addr;
+   q->cons_reg = cons_addr;
q->ent_dwords   = dwords;
 
q->q_base  = Q_BASE_RWA;
@@ -1977,17 +1991,25 @@ static int arm_smmu_init_one_queue(struct 
arm_smmu_device *smmu,
 static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
 {
int ret;
+   unsigned long page1_base, page0_base;
+
+   page0_base = smmu->base;
+   page1_base = arm_smmu_page1_base(smmu);
 
/* cmdq */
spin_lock_init(>cmdq.lock);
-   ret = arm_smmu_init_one_queue(smmu, >cmdq.q, ARM_SMMU_CMDQ_PROD,
- ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
+   ret = arm_smmu_init_one_queue(smmu, >cmdq.q, 
+ page0_base + ARM_SMMU_CMDQ_PROD,
+ page0_base + ARM_SMMU_CMDQ_CONS, 
+ CMDQ_ENT_DWORDS);
if (ret)
return ret;
 
/* evtq */
-   ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
- ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
+   ret = arm_smmu_init_one_queue(smmu, >evtq.q,
+ page1_base + ARM_SMMU_EVTQ_PROD,
+ page1_base + ARM_SMMU_EVTQ_CONS,
+ EVTQ_ENT_DWORDS);
if (ret)
return ret;
 
@@ -1995,8 +2017,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
if (!(smmu->features & ARM_SMMU_FEAT_PRI))
return 0;
 
-   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
-  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
+   return arm_smmu_init_one_queue(smmu, >priq.q,
+  page1_base + ARM_SMMU_PRIQ_PROD,
+  page1_base + ARM_SMMU_PRIQ_CONS,
+  PRIQ_ENT_DWORDS);
 }



@@ -2301,8 +2349,11 @@ static int arm_smmu_device_reset(struct 

Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-08 Thread Linu Cherian
On Sat May 06, 2017 at 01:03:28AM +0200, Robert Richter wrote:
> On 05.05.17 17:38:05, Geetha sowjanya wrote:
> > From: Linu Cherian 
> > 
> > Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
> > and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
> > 
> > This option when turned on, replaces all page 1 offsets used for
> > EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
> > 
> > Signed-off-by: Linu Cherian 
> > Signed-off-by: Geetha Sowjanya 
> > ---
> >  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
> >  drivers/iommu/arm-smmu-v3.c| 44 
> > --
> >  2 files changed, 38 insertions(+), 12 deletions(-)
> 
> > @@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct 
> > arm_smmu_device *smmu)
> > if (!(smmu->features & ARM_SMMU_FEAT_PRI))
> > return 0;
> >  
> > -   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> > -  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
> > +   return arm_smmu_init_one_queue(smmu, >priq.q,
> > +  ARM_SMMU_PRIQ_PROD(smmu),
> > +  ARM_SMMU_PRIQ_CONS(smmu),
> > +  PRIQ_ENT_DWORDS);
> 
> I would also suggest Robin's idea from the v1 review here. This works
> if we rework arm_smmu_init_one_queue() to pass addresses instead of
> offsets.
> 
> This would make these widespread offset calculations obsolete.
>

Have pasted here the relevant changes for doing fixups on smmu base instead
of offset to get feedback. 

This actually results in more lines of changes. If you think the below
approach is still better, will post a V4 of this series with this change.


+static inline unsigned long arm_smmu_page1_base(
+   struct arm_smmu_device *smmu)
+{
+   if (ARM_SMMU_PAGE0_REGS_ONLY(smmu))
+   return smmu->base;
+   else
+   return smmu->base + SZ_64K;
+}
+

@@ -1948,8 +1962,8 @@ static void arm_smmu_put_resv_regions(struct device *dev,
 /* Probing and initialisation functions */
 static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
   struct arm_smmu_queue *q,
-  unsigned long prod_off,
-  unsigned long cons_off,
+  unsigned long prod_addr,
+  unsigned long cons_addr,
   size_t dwords)
 {
size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
@@ -1961,8 +1975,8 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device 
*smmu,
return -ENOMEM;
}
 
-   q->prod_reg = smmu->base + prod_off;
-   q->cons_reg = smmu->base + cons_off;
+   q->prod_reg = prod_addr;
+   q->cons_reg = cons_addr;
q->ent_dwords   = dwords;
 
q->q_base  = Q_BASE_RWA;
@@ -1977,17 +1991,25 @@ static int arm_smmu_init_one_queue(struct 
arm_smmu_device *smmu,
 static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
 {
int ret;
+   unsigned long page1_base, page0_base;
+
+   page0_base = smmu->base;
+   page1_base = arm_smmu_page1_base(smmu);
 
/* cmdq */
spin_lock_init(>cmdq.lock);
-   ret = arm_smmu_init_one_queue(smmu, >cmdq.q, ARM_SMMU_CMDQ_PROD,
- ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
+   ret = arm_smmu_init_one_queue(smmu, >cmdq.q, 
+ page0_base + ARM_SMMU_CMDQ_PROD,
+ page0_base + ARM_SMMU_CMDQ_CONS, 
+ CMDQ_ENT_DWORDS);
if (ret)
return ret;
 
/* evtq */
-   ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
- ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
+   ret = arm_smmu_init_one_queue(smmu, >evtq.q,
+ page1_base + ARM_SMMU_EVTQ_PROD,
+ page1_base + ARM_SMMU_EVTQ_CONS,
+ EVTQ_ENT_DWORDS);
if (ret)
return ret;
 
@@ -1995,8 +2017,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
if (!(smmu->features & ARM_SMMU_FEAT_PRI))
return 0;
 
-   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
-  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
+   return arm_smmu_init_one_queue(smmu, >priq.q,
+  page1_base + ARM_SMMU_PRIQ_PROD,
+  page1_base + ARM_SMMU_PRIQ_CONS,
+  PRIQ_ENT_DWORDS);
 }



@@ -2301,8 +2349,11 @@ static int arm_smmu_device_reset(struct arm_smmu_device 
*smmu, bool bypass)
 {
int ret;
u32 reg, enables;
+   

Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-05 Thread Robert Richter
On 05.05.17 17:38:05, Geetha sowjanya wrote:
> From: Linu Cherian 
> 
> Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
> and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
> 
> This option when turned on, replaces all page 1 offsets used for
> EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
> 
> Signed-off-by: Linu Cherian 
> Signed-off-by: Geetha Sowjanya 
> ---
>  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
>  drivers/iommu/arm-smmu-v3.c| 44 
> --
>  2 files changed, 38 insertions(+), 12 deletions(-)

> @@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
> *smmu)
>   if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>   return 0;
>  
> - return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> -ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
> + return arm_smmu_init_one_queue(smmu, >priq.q,
> +ARM_SMMU_PRIQ_PROD(smmu),
> +ARM_SMMU_PRIQ_CONS(smmu),
> +PRIQ_ENT_DWORDS);

I would also suggest Robin's idea from the v1 review here. This works
if we rework arm_smmu_init_one_queue() to pass addresses instead of
offsets.

This would make these widespread offset calculations obsolete.

-Robert


Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-05 Thread Robert Richter
On 05.05.17 17:38:05, Geetha sowjanya wrote:
> From: Linu Cherian 
> 
> Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
> and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
> 
> This option when turned on, replaces all page 1 offsets used for
> EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
> 
> Signed-off-by: Linu Cherian 
> Signed-off-by: Geetha Sowjanya 
> ---
>  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
>  drivers/iommu/arm-smmu-v3.c| 44 
> --
>  2 files changed, 38 insertions(+), 12 deletions(-)

> @@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
> *smmu)
>   if (!(smmu->features & ARM_SMMU_FEAT_PRI))
>   return 0;
>  
> - return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
> -ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
> + return arm_smmu_init_one_queue(smmu, >priq.q,
> +ARM_SMMU_PRIQ_PROD(smmu),
> +ARM_SMMU_PRIQ_CONS(smmu),
> +PRIQ_ENT_DWORDS);

I would also suggest Robin's idea from the v1 review here. This works
if we rework arm_smmu_init_one_queue() to pass addresses instead of
offsets.

This would make these widespread offset calculations obsolete.

-Robert


Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-05 Thread Robert Richter
On 05.05.17 17:38:05, Geetha sowjanya wrote:
> From: Linu Cherian 
> 
> Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
> and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
> 
> This option when turned on, replaces all page 1 offsets used for
> EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
> 
> Signed-off-by: Linu Cherian 
> Signed-off-by: Geetha Sowjanya 
> ---
>  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
>  drivers/iommu/arm-smmu-v3.c| 44 
> --
>  2 files changed, 38 insertions(+), 12 deletions(-)

> @@ -412,6 +412,9 @@
>  #define MSI_IOVA_BASE0x800
>  #define MSI_IOVA_LENGTH  0x10
>  
> +#define ARM_SMMU_PAGE0_REGS_ONLY(smmu)   \
> + ((smmu)->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY)

Why hide the check behind this macro? Maybe make
ARM_SMMU_OPT_PAGE0_REGS_ONLY shorter a bit instead?

-Robert


Re: [PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-05 Thread Robert Richter
On 05.05.17 17:38:05, Geetha sowjanya wrote:
> From: Linu Cherian 
> 
> Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
> and PAGE0_REGS_ONLY option will be enabled as an errata workaround.
> 
> This option when turned on, replaces all page 1 offsets used for
> EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.
> 
> Signed-off-by: Linu Cherian 
> Signed-off-by: Geetha Sowjanya 
> ---
>  .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
>  drivers/iommu/arm-smmu-v3.c| 44 
> --
>  2 files changed, 38 insertions(+), 12 deletions(-)

> @@ -412,6 +412,9 @@
>  #define MSI_IOVA_BASE0x800
>  #define MSI_IOVA_LENGTH  0x10
>  
> +#define ARM_SMMU_PAGE0_REGS_ONLY(smmu)   \
> + ((smmu)->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY)

Why hide the check behind this macro? Maybe make
ARM_SMMU_OPT_PAGE0_REGS_ONLY shorter a bit instead?

-Robert


[PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-05 Thread Geetha sowjanya
From: Linu Cherian 

Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
and PAGE0_REGS_ONLY option will be enabled as an errata workaround.

This option when turned on, replaces all page 1 offsets used for
EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.

Signed-off-by: Linu Cherian 
Signed-off-by: Geetha Sowjanya 
---
 .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
 drivers/iommu/arm-smmu-v3.c| 44 --
 2 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
index be57550..e6da62b 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
@@ -49,6 +49,12 @@ the PCIe specification.
 - hisilicon,broken-prefetch-cmd
 : Avoid sending CMD_PREFETCH_* commands to the SMMU.
 
+- cavium-cn99xx,broken-page1-regspace
+: Replaces all page 1 offsets used for EVTQ_PROD/CONS,
+   PRIQ_PROD/CONS register access 
with page 0 offsets.
+   Set for Caviun ThunderX2 
silicon that doesn't support
+   SMMU page1 register space.
+
 ** Example
 
 smmu@2b40 {
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 380969a..107b4a6 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -176,15 +176,15 @@
 #define ARM_SMMU_CMDQ_CONS 0x9c
 
 #define ARM_SMMU_EVTQ_BASE 0xa0
-#define ARM_SMMU_EVTQ_PROD 0x100a8
-#define ARM_SMMU_EVTQ_CONS 0x100ac
+#define ARM_SMMU_EVTQ_PROD(smmu)   (page1_offset_adjust(0x100a8, smmu))
+#define ARM_SMMU_EVTQ_CONS(smmu)   (page1_offset_adjust(0x100ac, smmu))
 #define ARM_SMMU_EVTQ_IRQ_CFG0 0xb0
 #define ARM_SMMU_EVTQ_IRQ_CFG1 0xb8
 #define ARM_SMMU_EVTQ_IRQ_CFG2 0xbc
 
 #define ARM_SMMU_PRIQ_BASE 0xc0
-#define ARM_SMMU_PRIQ_PROD 0x100c8
-#define ARM_SMMU_PRIQ_CONS 0x100cc
+#define ARM_SMMU_PRIQ_PROD(smmu)   (page1_offset_adjust(0x100c8, smmu))
+#define ARM_SMMU_PRIQ_CONS(smmu)   (page1_offset_adjust(0x100cc, smmu))
 #define ARM_SMMU_PRIQ_IRQ_CFG0 0xd0
 #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
@@ -412,6 +412,9 @@
 #define MSI_IOVA_BASE  0x800
 #define MSI_IOVA_LENGTH0x10
 
+#define ARM_SMMU_PAGE0_REGS_ONLY(smmu) \
+   ((smmu)->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY)
+
 static bool disable_bypass;
 module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO);
 MODULE_PARM_DESC(disable_bypass,
@@ -597,6 +600,7 @@ struct arm_smmu_device {
u32 features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
+#define ARM_SMMU_OPT_PAGE0_REGS_ONLY(1 << 1)
u32 options;
 
struct arm_smmu_cmdqcmdq;
@@ -663,9 +667,19 @@ struct arm_smmu_option_prop {
 
 static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
+   { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium-cn99xx,broken-page1-regspace"},
{ 0, NULL},
 };
 
+static inline unsigned long page1_offset_adjust(
+   unsigned long off, struct arm_smmu_device *smmu)
+{
+   if (!ARM_SMMU_PAGE0_REGS_ONLY(smmu))
+   return off;
+   else
+   return (off - SZ_64K);
+}
+
 static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
 {
return container_of(dom, struct arm_smmu_domain, domain);
@@ -1986,8 +2000,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
return ret;
 
/* evtq */
-   ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
- ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
+   ret = arm_smmu_init_one_queue(smmu, >evtq.q,
+ ARM_SMMU_EVTQ_PROD(smmu),
+ ARM_SMMU_EVTQ_CONS(smmu),
+ EVTQ_ENT_DWORDS);
if (ret)
return ret;
 
@@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
if (!(smmu->features & ARM_SMMU_FEAT_PRI))
return 0;
 
-   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
-  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
+   return arm_smmu_init_one_queue(smmu, >priq.q,
+  ARM_SMMU_PRIQ_PROD(smmu),
+  

[PATCH v3 1/7] iommu/arm-smmu-v3: Introduce SMMU option PAGE0_REGS_ONLY for ThunderX2 errata #74

2017-05-05 Thread Geetha sowjanya
From: Linu Cherian 

Cavium ThunderX2 SMMU implementation doesn't support page 1 register space
and PAGE0_REGS_ONLY option will be enabled as an errata workaround.

This option when turned on, replaces all page 1 offsets used for
EVTQ_PROD/CONS, PRIQ_PROD/CONS register access with page 0 offsets.

Signed-off-by: Linu Cherian 
Signed-off-by: Geetha Sowjanya 
---
 .../devicetree/bindings/iommu/arm,smmu-v3.txt  |  6 +++
 drivers/iommu/arm-smmu-v3.c| 44 --
 2 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
index be57550..e6da62b 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
@@ -49,6 +49,12 @@ the PCIe specification.
 - hisilicon,broken-prefetch-cmd
 : Avoid sending CMD_PREFETCH_* commands to the SMMU.
 
+- cavium-cn99xx,broken-page1-regspace
+: Replaces all page 1 offsets used for EVTQ_PROD/CONS,
+   PRIQ_PROD/CONS register access 
with page 0 offsets.
+   Set for Caviun ThunderX2 
silicon that doesn't support
+   SMMU page1 register space.
+
 ** Example
 
 smmu@2b40 {
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 380969a..107b4a6 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -176,15 +176,15 @@
 #define ARM_SMMU_CMDQ_CONS 0x9c
 
 #define ARM_SMMU_EVTQ_BASE 0xa0
-#define ARM_SMMU_EVTQ_PROD 0x100a8
-#define ARM_SMMU_EVTQ_CONS 0x100ac
+#define ARM_SMMU_EVTQ_PROD(smmu)   (page1_offset_adjust(0x100a8, smmu))
+#define ARM_SMMU_EVTQ_CONS(smmu)   (page1_offset_adjust(0x100ac, smmu))
 #define ARM_SMMU_EVTQ_IRQ_CFG0 0xb0
 #define ARM_SMMU_EVTQ_IRQ_CFG1 0xb8
 #define ARM_SMMU_EVTQ_IRQ_CFG2 0xbc
 
 #define ARM_SMMU_PRIQ_BASE 0xc0
-#define ARM_SMMU_PRIQ_PROD 0x100c8
-#define ARM_SMMU_PRIQ_CONS 0x100cc
+#define ARM_SMMU_PRIQ_PROD(smmu)   (page1_offset_adjust(0x100c8, smmu))
+#define ARM_SMMU_PRIQ_CONS(smmu)   (page1_offset_adjust(0x100cc, smmu))
 #define ARM_SMMU_PRIQ_IRQ_CFG0 0xd0
 #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
@@ -412,6 +412,9 @@
 #define MSI_IOVA_BASE  0x800
 #define MSI_IOVA_LENGTH0x10
 
+#define ARM_SMMU_PAGE0_REGS_ONLY(smmu) \
+   ((smmu)->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY)
+
 static bool disable_bypass;
 module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO);
 MODULE_PARM_DESC(disable_bypass,
@@ -597,6 +600,7 @@ struct arm_smmu_device {
u32 features;
 
 #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
+#define ARM_SMMU_OPT_PAGE0_REGS_ONLY(1 << 1)
u32 options;
 
struct arm_smmu_cmdqcmdq;
@@ -663,9 +667,19 @@ struct arm_smmu_option_prop {
 
 static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
+   { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium-cn99xx,broken-page1-regspace"},
{ 0, NULL},
 };
 
+static inline unsigned long page1_offset_adjust(
+   unsigned long off, struct arm_smmu_device *smmu)
+{
+   if (!ARM_SMMU_PAGE0_REGS_ONLY(smmu))
+   return off;
+   else
+   return (off - SZ_64K);
+}
+
 static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
 {
return container_of(dom, struct arm_smmu_domain, domain);
@@ -1986,8 +2000,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
return ret;
 
/* evtq */
-   ret = arm_smmu_init_one_queue(smmu, >evtq.q, ARM_SMMU_EVTQ_PROD,
- ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
+   ret = arm_smmu_init_one_queue(smmu, >evtq.q,
+ ARM_SMMU_EVTQ_PROD(smmu),
+ ARM_SMMU_EVTQ_CONS(smmu),
+ EVTQ_ENT_DWORDS);
if (ret)
return ret;
 
@@ -1995,8 +2011,10 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
if (!(smmu->features & ARM_SMMU_FEAT_PRI))
return 0;
 
-   return arm_smmu_init_one_queue(smmu, >priq.q, ARM_SMMU_PRIQ_PROD,
-  ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
+   return arm_smmu_init_one_queue(smmu, >priq.q,
+  ARM_SMMU_PRIQ_PROD(smmu),
+  ARM_SMMU_PRIQ_CONS(smmu),
+  PRIQ_ENT_DWORDS);
 }