Re: [PATCH v5 1/6] base: power: runtime: Export pm_runtime_get/put_suppliers

2018-01-11 Thread Vivek Gautam



On 01/12/2018 04:23 AM, Rafael J. Wysocki wrote:

On Tue, Jan 9, 2018 at 11:01 AM, Vivek Gautam
 wrote:

The device link allows the pm framework to tie the supplier and
consumer. So, whenever the consumer is powered-on the supplier
is powered-on first.

There are however cases in which the consumer wants to power-on
the supplier, but not itself.
E.g., A Graphics or multimedia driver wants to power-on the SMMU
to unmap a buffer and finish the TLB operations without powering
on itself. Some of these unmap requests are coming from the
user space when the controller itself is not powered-up, and it
can be huge penalty in terms of power and latency to power-up
the graphics/mm controllers.
There can be an argument that the supplier should handle this case
on its own and there should not be a need for the consumer to
power-on the supplier. But as discussed on the thread [1] about
ARM-SMMU runtime pm, we don't want to introduce runtime pm calls
in atomic path in arm_smmu_unmap.

[1] https://patchwork.kernel.org/patch/9827825/

Signed-off-by: Vivek Gautam 

Acked-by: Rafael J. Wysocki 

Please feel free to route this along with the rest of the series.


Thanks Rafael.

regards
Vivek



Thanks!


---

  * This is v2 of the patch [1]. Adding it to this patch series.
[1] https://patchwork.kernel.org/patch/10102447/

  drivers/base/power/runtime.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 6e89b51ea3d9..06a2a88fe866 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1579,6 +1579,7 @@ void pm_runtime_get_suppliers(struct device *dev)

 device_links_read_unlock(idx);
  }
+EXPORT_SYMBOL_GPL(pm_runtime_get_suppliers);

  /**
   * pm_runtime_put_suppliers - Drop references to supplier devices.
@@ -1597,6 +1598,7 @@ void pm_runtime_put_suppliers(struct device *dev)

 device_links_read_unlock(idx);
  }
+EXPORT_SYMBOL_GPL(pm_runtime_put_suppliers);

  void pm_runtime_new_link(struct device *dev)
  {
--
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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


Re: [PATCH v5 5/6] iommu/arm-smmu: Add support for qcom,smmu-v2 variant

2018-01-11 Thread Vivek Gautam

Hi Rob,


On 01/12/2018 03:53 AM, Rob Herring wrote:

On Tue, Jan 09, 2018 at 03:31:48PM +0530, Vivek Gautam wrote:

qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
clock and power requirements. This smmu core is used with
multiple masters on msm8996, viz. mdss, video, etc.
Add bindings for the same.

Signed-off-by: Vivek Gautam 
---

  * Major change in this patch -
Changed compatible string from 'qcom,msm8996-smmu-v2' to
'qcom,smmu-v2' to reflect the IP version rather than the
platform on which it is used.

The bugs and how things are connected are all the same? I'd suggest you
keep both strings.


Sure,
compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";




The same IP is used across multiple platforms including msm8996,
and sdm845 etc.

But for only 2 or so platforms a fallback is not really worth it. You'll
probably be on SMMUv3 before too long...

Right. There's msm8998 as well, but as you said keeping both strings
will make more sense.
Thanks.

Best regards
Vivek

[snip]

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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


Re: [PATCH 1/9] iommu/of: Drop early initialisation hooks

2018-01-11 Thread JeffyChen

Hi Robin,

Thnaks for your reply.

On 01/11/2018 08:24 PM, Robin Murphy wrote:

Hi Jeffy,

On 11/01/18 11:14, JeffyChen wrote:

Hi Marek,

Thanks for your reply.

On 01/11/2018 05:40 PM, Marek Szyprowski wrote:

Hi Jeffy,

On 2018-01-11 09:22, Jeffy Chen wrote:

With the probe-deferral mechanism, early initialisation hooks are no
longer needed.

Suggested-by: Robin Murphy 


In fact, shortly after I said that I had a "how hard can it be?" moment
and took a crack at it myself - sorry, I should probably have cc'd you
on that series[1].


hmmm, i'll drop this patch in the next version.

and maybe rebase my patch[9] (iommu/rockchip: Use OF_IOMMU to attach 
devices automatically) on that series



Signed-off-by: Jeffy Chen 
---

  drivers/iommu/arm-smmu-v3.c  |  2 +-
  drivers/iommu/arm-smmu.c | 12 ++--
  drivers/iommu/exynos-iommu.c |  2 +-


For Exynos IOMMU:
Acked-by: Marek Szyprowski 

IPMMU and MSM IOMMU are no longer multi-platform safe after this patch.
It breaks them in the same way as my commit 928055a01b3f ("iommu/exynos:
Remove custom platform device registration code") broke Exynos IOMMU.

You need a similar fix for them:
https://www.spinics.net/lists/arm-kernel/msg627648.html


hmmm, right, i did saw this fix in the rockchip iommu driver too.

and there're also some other iommu drivers put bus_set_iommu in their
probe() to avoid that.

maybe we can do it in the iommu framework?

for example:
1/ add a bus type member to struct iommu_device
2/ and a iommu_device_set_bus()
3/ do the bus_set_iommu stuff in iommu_device_register()
4/ undo bus_set_iommu in iommu_device_unregister()


Ultimately we'd like to get rid of the bus relationship altogether, so I
don't think it's really worth adding more infrastructure around it.
Having of-iommu-based drivers set bus ops at probe time, and others
conditionally from an initcall, is pretty clean and simple, so I'd
rather stick with that approach for now.

ok, make sense:)


Robin.

[1]
https://lists.linuxfoundation.org/pipermail/iommu/2018-January/025395.html






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


Re: [PATCH 2/9] iommu/rockchip: Fix error handling in attach

2018-01-11 Thread JeffyChen

Hi Robin,

thanks for your reply.

On 01/11/2018 11:47 PM, Robin Murphy wrote:


+for (i = 0; i < iommu->num_irq; i++) {
+ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
+   IRQF_SHARED, dev_name(dev), iommu);


Why aren't we simply requesting the IRQ once in rk_iommu_probe()? Given
that the hardware doesn't handle multiple translation contexts, there
doesn't seem to be much point in being this dynamic about it.


it make sense, will do it in next version:)

Robin.



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


Re: [PATCH v5 1/6] base: power: runtime: Export pm_runtime_get/put_suppliers

2018-01-11 Thread Rafael J. Wysocki
On Tue, Jan 9, 2018 at 11:01 AM, Vivek Gautam
 wrote:
> The device link allows the pm framework to tie the supplier and
> consumer. So, whenever the consumer is powered-on the supplier
> is powered-on first.
>
> There are however cases in which the consumer wants to power-on
> the supplier, but not itself.
> E.g., A Graphics or multimedia driver wants to power-on the SMMU
> to unmap a buffer and finish the TLB operations without powering
> on itself. Some of these unmap requests are coming from the
> user space when the controller itself is not powered-up, and it
> can be huge penalty in terms of power and latency to power-up
> the graphics/mm controllers.
> There can be an argument that the supplier should handle this case
> on its own and there should not be a need for the consumer to
> power-on the supplier. But as discussed on the thread [1] about
> ARM-SMMU runtime pm, we don't want to introduce runtime pm calls
> in atomic path in arm_smmu_unmap.
>
> [1] https://patchwork.kernel.org/patch/9827825/
>
> Signed-off-by: Vivek Gautam 

Acked-by: Rafael J. Wysocki 

Please feel free to route this along with the rest of the series.

Thanks!

> ---
>
>  * This is v2 of the patch [1]. Adding it to this patch series.
>[1] https://patchwork.kernel.org/patch/10102447/
>
>  drivers/base/power/runtime.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
> index 6e89b51ea3d9..06a2a88fe866 100644
> --- a/drivers/base/power/runtime.c
> +++ b/drivers/base/power/runtime.c
> @@ -1579,6 +1579,7 @@ void pm_runtime_get_suppliers(struct device *dev)
>
> device_links_read_unlock(idx);
>  }
> +EXPORT_SYMBOL_GPL(pm_runtime_get_suppliers);
>
>  /**
>   * pm_runtime_put_suppliers - Drop references to supplier devices.
> @@ -1597,6 +1598,7 @@ void pm_runtime_put_suppliers(struct device *dev)
>
> device_links_read_unlock(idx);
>  }
> +EXPORT_SYMBOL_GPL(pm_runtime_put_suppliers);
>
>  void pm_runtime_new_link(struct device *dev)
>  {
> --
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 5/6] iommu/arm-smmu: Add support for qcom,smmu-v2 variant

2018-01-11 Thread Rob Herring
On Tue, Jan 09, 2018 at 03:31:48PM +0530, Vivek Gautam wrote:
> qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
> clock and power requirements. This smmu core is used with
> multiple masters on msm8996, viz. mdss, video, etc.
> Add bindings for the same.
> 
> Signed-off-by: Vivek Gautam 
> ---
> 
>  * Major change in this patch -
>Changed compatible string from 'qcom,msm8996-smmu-v2' to
>'qcom,smmu-v2' to reflect the IP version rather than the
>platform on which it is used.

The bugs and how things are connected are all the same? I'd suggest you 
keep both strings.

>The same IP is used across multiple platforms including msm8996,
>and sdm845 etc.

But for only 2 or so platforms a fallback is not really worth it. You'll 
probably be on SMMUv3 before too long...

> 
>  .../devicetree/bindings/iommu/arm,smmu.txt | 35 
> ++
>  drivers/iommu/arm-smmu.c   | 13 
>  2 files changed, 48 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt 
> b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
> index 8a6ffce12af5..e4951288c87c 100644
> --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
> @@ -17,6 +17,7 @@ conditions.
>  "arm,mmu-401"
>  "arm,mmu-500"
>  "cavium,smmu-v2"
> +"qcom,smmu-v2"
>  
>depending on the particular implementation and/or the
>version of the architecture implemented.
> @@ -71,6 +72,23 @@ conditions.
>or using stream matching with #iommu-cells = <2>, and
>may be ignored if present in such cases.
>  
> +- clock-names:Should be "bus", and "iface" for "qcom,smmu-v2"
> +  implementation.
> +
> +  "bus" clock for "qcom,smmu-v2" is required for downstream
> +  bus access and for the smmu ptw.
> +
> +  "iface" clock is required to access smmu's registers 
> through
> +  the TCU's programming interface.
> +
> +- clocks: Phandles for respective clocks described by clock-names.
> +
> +- power-domains:  Phandles to SMMU's power domain specifier. This is
> +  required even if SMMU belongs to the master's power
> +  domain, as the SMMU will have to be enabled and
> +  accessed before master gets enabled and linked to its
> +  SMMU.
> +
>  ** Deprecated properties:
>  
>  - mmu-masters (deprecated in favour of the generic "iommus" binding) :
> @@ -137,3 +155,20 @@ conditions.
>  iommu-map = <0 &smmu3 0 0x400>;
>  ...
>  };
> +
> + /* Qcom's arm,smmu-v2 implementation */
> + smmu4: iommu {
> + compatible = "qcom,smmu-v2";
> + reg = <0xd0 0x1>;
> +
> + #global-interrupts = <1>;
> + interrupts = ,
> +  ,
> +  ;
> + #iommu-cells = <1>;
> + power-domains = <&mmcc MDSS_GDSC>;
> +
> + clocks = <&mmcc SMMU_MDP_AXI_CLK>,
> +  <&mmcc SMMU_MDP_AHB_CLK>;
> + clock-names = "bus", "iface";
> + };
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 33bbcfedb896..2ade214c41bc 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -119,6 +119,7 @@ enum arm_smmu_implementation {
>   GENERIC_SMMU,
>   ARM_MMU500,
>   CAVIUM_SMMUV2,
> + QCOM_SMMUV2,
>  };
>  
>  struct arm_smmu_s2cr {
> @@ -1971,6 +1972,17 @@ struct arm_smmu_match_data {
>  ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
>  ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
>  
> +static const char * const qcom_smmuv2_clks[] = {
> + "bus", "iface",
> +};
> +
> +static const struct arm_smmu_match_data qcom_smmuv2 = {
> + .version = ARM_SMMU_V2,
> + .model = QCOM_SMMUV2,
> + .clks = qcom_smmuv2_clks,
> + .num_clks = ARRAY_SIZE(qcom_smmuv2_clks),
> +};
> +
>  static const struct of_device_id arm_smmu_of_match[] = {
>   { .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
>   { .compatible = "arm,smmu-v2", .data = &smmu_generic_v2 },
> @@ -1978,6 +1990,7 @@ struct arm_smmu_match_data {
>   { .compatible = "arm,mmu-401", .data = &arm_mmu401 },
>   { .compatible = "arm,mmu-500", .data = &arm_mmu500 },
>   { .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },
> + { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 },
>   { },
>  };
>  MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
> -- 
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> 
___
iommu mailing list
iommu@l

Re: [PATCH v3 08/16] iommu: introduce device fault data

2018-01-11 Thread Jacob Pan
On Wed, 10 Jan 2018 11:41:58 +
Jean-Philippe Brucker  wrote:

> Hi Jacob,
> 
> On 17/11/17 18:55, Jacob Pan wrote:
> [...]
> > +/**
> > + * struct iommu_fault_event - Generic per device fault data
> > + *
> > + * - PCI and non-PCI devices
> > + * - Recoverable faults (e.g. page request), information based on
> > PCI ATS
> > + * and PASID spec.
> > + * - Un-recoverable faults of device interest
> > + * - DMA remapping and IRQ remapping faults
> > +
> > + * @type contains fault type.
> > + * @reason fault reasons if relevant outside IOMMU driver, IOMMU
> > driver internal
> > + * faults are not reported
> > + * @addr: tells the offending page address
> > + * @pasid: contains process address space ID, used in shared
> > virtual memory(SVM)
> > + * @rid: requestor ID
> > + * @page_req_group_id: page request group index
> > + * @last_req: last request in a page request group
> > + * @pasid_valid: indicates if the PRQ has a valid PASID
> > + * @prot: page access protection flag, e.g. IOMMU_FAULT_READ,
> > IOMMU_FAULT_WRITE
> > + * @device_private: if present, uniquely identify device-specific
> > + *  private data for an individual page request.
> > + * @iommu_private: used by the IOMMU driver for storing
> > fault-specific
> > + * data. Users should not modify this field before
> > + * sending the fault response.
> > + */
> > +struct iommu_fault_event {
> > +   enum iommu_fault_type type;
> > +   enum iommu_fault_reason reason;
> > +   u64 addr;
> > +   u32 pasid;
> > +   u32 page_req_group_id : 9;  
> 
> As I've been rebasing my work onto your series, I have a few more
> comments about this structure. Is there any advantage in limiting the
> PRGI as a bitfield? PCI uses 9 bits, but others might need more. For
> instance ARM Stall uses 16-bit IDs to identify a fault event.
> 
> Could you please make it a u32 (as well as in page_response_msg), and
> could page_req_group_id be renamed to simply "id"?
> 
sure, I will make it u32 in v4 version of the patchset. I was using PCI
standard as a base with no specific advantage.
I am running into little bit problem with testing, so perhaps next week.
> > +   u32 last_req : 1;
> > +   u32 pasid_valid : 1;  
> I noticed that page_response_msg in patch 15/16 calls this bit
> "pasid_present". Could you rename it to "pasid_valid" for consistency?
> 
make sense.
> Thanks,
> Jean

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


Re: [PATCH 2/9] iommu/rockchip: Fix error handling in attach

2018-01-11 Thread Robin Murphy

On 11/01/18 08:22, Jeffy Chen wrote:

From: Tomasz Figa 

Currently if the driver encounters an error while attaching device, it
will leave the IOMMU in an inconsistent state. Even though it shouldn't
really happen in reality, let's just add proper error path to keep
things consistent.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
---

  drivers/iommu/rockchip-iommu.c | 26 +-
  1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9d991c2d8767..ee805e1dfba7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -826,17 +826,10 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
  
  	ret = rk_iommu_force_reset(iommu);

if (ret)
-   return ret;
+   goto err_disable_stall;
  
  	iommu->domain = domain;
  
-	for (i = 0; i < iommu->num_irq; i++) {

-   ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
-  IRQF_SHARED, dev_name(dev), iommu);
-   if (ret)
-   return ret;
-   }
-
for (i = 0; i < iommu->num_mmu; i++) {
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
   rk_domain->dt_dma);
@@ -844,9 +837,16 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 
RK_MMU_IRQ_MASK);
}
  
+	for (i = 0; i < iommu->num_irq; i++) {

+   ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
+  IRQF_SHARED, dev_name(dev), iommu);


Why aren't we simply requesting the IRQ once in rk_iommu_probe()? Given 
that the hardware doesn't handle multiple translation contexts, there 
doesn't seem to be much point in being this dynamic about it.


Robin.


+   if (ret)
+   goto err_free_irq;
+   }
+
ret = rk_iommu_enable_paging(iommu);
if (ret)
-   return ret;
+   goto err_free_irq;
  
  	spin_lock_irqsave(&rk_domain->iommus_lock, flags);

list_add_tail(&iommu->node, &rk_domain->iommus);
@@ -857,6 +857,14 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
rk_iommu_disable_stall(iommu);
  
  	return 0;

+
+err_free_irq:
+   while (i--)
+   devm_free_irq(iommu->dev, iommu->irq[i], iommu);
+err_disable_stall:
+   rk_iommu_disable_stall(iommu);
+
+   return ret;
  }
  
  static void rk_iommu_detach_device(struct iommu_domain *domain,



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


Re: [PATCH 1/9] iommu/of: Drop early initialisation hooks

2018-01-11 Thread Marek Szyprowski

Hi Jeffy,

On 2018-01-11 12:14, JeffyChen wrote:

Hi Marek,

Thanks for your reply.

On 01/11/2018 05:40 PM, Marek Szyprowski wrote:

Hi Jeffy,

On 2018-01-11 09:22, Jeffy Chen wrote:

With the probe-deferral mechanism, early initialisation hooks are no
longer needed.

Suggested-by: Robin Murphy 
Signed-off-by: Jeffy Chen 
---

  drivers/iommu/arm-smmu-v3.c  |  2 +-
  drivers/iommu/arm-smmu.c | 12 ++--
  drivers/iommu/exynos-iommu.c |  2 +-


For Exynos IOMMU:
Acked-by: Marek Szyprowski 

IPMMU and MSM IOMMU are no longer multi-platform safe after this patch.
It breaks them in the same way as my commit 928055a01b3f ("iommu/exynos:
Remove custom platform device registration code") broke Exynos IOMMU.

You need a similar fix for them:
https://www.spinics.net/lists/arm-kernel/msg627648.html


hmmm, right, i did saw this fix in the rockchip iommu driver too.

and there're also some other iommu drivers put bus_set_iommu in their 
probe() to avoid that.


maybe we can do it in the iommu framework?

for example:
1/ add a bus type member to struct iommu_device
2/ and a iommu_device_set_bus()
3/ do the bus_set_iommu stuff in iommu_device_register()
4/ undo bus_set_iommu in iommu_device_unregister()


Frankly, in case the device-tree based systems bus_set_iommu()
should not be needed at all. However for some legacy reasons it
is still required by a few bits of code (at least it was needed
some time ago). Probably it would be best if this is finally
resolved.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland

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

Re: [PATCH 1/9] iommu/of: Drop early initialisation hooks

2018-01-11 Thread Robin Murphy

Hi Jeffy,

On 11/01/18 11:14, JeffyChen wrote:

Hi Marek,

Thanks for your reply.

On 01/11/2018 05:40 PM, Marek Szyprowski wrote:

Hi Jeffy,

On 2018-01-11 09:22, Jeffy Chen wrote:

With the probe-deferral mechanism, early initialisation hooks are no
longer needed.

Suggested-by: Robin Murphy 


In fact, shortly after I said that I had a "how hard can it be?" moment 
and took a crack at it myself - sorry, I should probably have cc'd you 
on that series[1].



Signed-off-by: Jeffy Chen 
---

  drivers/iommu/arm-smmu-v3.c  |  2 +-
  drivers/iommu/arm-smmu.c | 12 ++--
  drivers/iommu/exynos-iommu.c |  2 +-


For Exynos IOMMU:
Acked-by: Marek Szyprowski 

IPMMU and MSM IOMMU are no longer multi-platform safe after this patch.
It breaks them in the same way as my commit 928055a01b3f ("iommu/exynos:
Remove custom platform device registration code") broke Exynos IOMMU.

You need a similar fix for them:
https://www.spinics.net/lists/arm-kernel/msg627648.html


hmmm, right, i did saw this fix in the rockchip iommu driver too.

and there're also some other iommu drivers put bus_set_iommu in their 
probe() to avoid that.


maybe we can do it in the iommu framework?

for example:
1/ add a bus type member to struct iommu_device
2/ and a iommu_device_set_bus()
3/ do the bus_set_iommu stuff in iommu_device_register()
4/ undo bus_set_iommu in iommu_device_unregister()


Ultimately we'd like to get rid of the bus relationship altogether, so I 
don't think it's really worth adding more infrastructure around it. 
Having of-iommu-based drivers set bus ops at probe time, and others 
conditionally from an initcall, is pretty clean and simple, so I'd 
rather stick with that approach for now.


Robin.

[1] 
https://lists.linuxfoundation.org/pipermail/iommu/2018-January/025395.html

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

Re: [PATCH 1/9] iommu/of: Drop early initialisation hooks

2018-01-11 Thread JeffyChen

Hi Marek,

Thanks for your reply.

On 01/11/2018 05:40 PM, Marek Szyprowski wrote:

Hi Jeffy,

On 2018-01-11 09:22, Jeffy Chen wrote:

With the probe-deferral mechanism, early initialisation hooks are no
longer needed.

Suggested-by: Robin Murphy 
Signed-off-by: Jeffy Chen 
---

  drivers/iommu/arm-smmu-v3.c  |  2 +-
  drivers/iommu/arm-smmu.c | 12 ++--
  drivers/iommu/exynos-iommu.c |  2 +-


For Exynos IOMMU:
Acked-by: Marek Szyprowski 

IPMMU and MSM IOMMU are no longer multi-platform safe after this patch.
It breaks them in the same way as my commit 928055a01b3f ("iommu/exynos:
Remove custom platform device registration code") broke Exynos IOMMU.

You need a similar fix for them:
https://www.spinics.net/lists/arm-kernel/msg627648.html


hmmm, right, i did saw this fix in the rockchip iommu driver too.

and there're also some other iommu drivers put bus_set_iommu in their 
probe() to avoid that.


maybe we can do it in the iommu framework?

for example:
1/ add a bus type member to struct iommu_device
2/ and a iommu_device_set_bus()
3/ do the bus_set_iommu stuff in iommu_device_register()
4/ undo bus_set_iommu in iommu_device_unregister()



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


Re: [PATCH 1/9] iommu/of: Drop early initialisation hooks

2018-01-11 Thread Marek Szyprowski

Hi Jeffy,

On 2018-01-11 09:22, Jeffy Chen wrote:

With the probe-deferral mechanism, early initialisation hooks are no
longer needed.

Suggested-by: Robin Murphy 
Signed-off-by: Jeffy Chen 
---

  drivers/iommu/arm-smmu-v3.c  |  2 +-
  drivers/iommu/arm-smmu.c | 12 ++--
  drivers/iommu/exynos-iommu.c |  2 +-


For Exynos IOMMU:
Acked-by: Marek Szyprowski 

IPMMU and MSM IOMMU are no longer multi-platform safe after this patch.
It breaks them in the same way as my commit 928055a01b3f ("iommu/exynos:
Remove custom platform device registration code") broke Exynos IOMMU.

You need a similar fix for them:
https://www.spinics.net/lists/arm-kernel/msg627648.html


  drivers/iommu/ipmmu-vmsa.c   | 17 ++---
  drivers/iommu/msm_iommu.c| 24 +++-
  drivers/iommu/of_iommu.c | 16 
  drivers/iommu/qcom_iommu.c   |  2 +-
  include/linux/of_iommu.h |  6 ++
  8 files changed, 20 insertions(+), 61 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 744592d330ca..3f2f1fc68b52 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2971,7 +2971,7 @@ static struct platform_driver arm_smmu_driver = {
  };
  module_platform_driver(arm_smmu_driver);
  
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);

+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3");
  
  MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");

  MODULE_AUTHOR("Will Deacon ");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 78d4c6b8f1ba..69e7c60792a8 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2211,12 +2211,12 @@ static struct platform_driver arm_smmu_driver = {
  };
  module_platform_driver(arm_smmu_driver);
  
-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL);

-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL);
-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL);
-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL);
-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL);
-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL);
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1");
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2");
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400");
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401");
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500");
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2");
  
  MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");

  MODULE_AUTHOR("Will Deacon ");
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 79c45650f8de..1c7f926fad0e 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1394,4 +1394,4 @@ static int __init exynos_iommu_init(void)
  }
  core_initcall(exynos_iommu_init);
  
-IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL);

+IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu");
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 8dce3a9de9d8..07b711bb4b16 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -1081,12 +1081,8 @@ static struct platform_driver ipmmu_driver = {
  
  static int __init ipmmu_init(void)

  {
-   static bool setup_done;
int ret;
  
-	if (setup_done)

-   return 0;
-
ret = platform_driver_register(&ipmmu_driver);
if (ret < 0)
return ret;
@@ -1096,7 +1092,6 @@ static int __init ipmmu_init(void)
bus_set_iommu(&platform_bus_type, &ipmmu_ops);
  #endif
  
-	setup_done = true;

return 0;
  }
  
@@ -1109,16 +1104,8 @@ subsys_initcall(ipmmu_init);

  module_exit(ipmmu_exit);
  
  #ifdef CONFIG_IOMMU_DMA

-static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
-{
-   ipmmu_init();
-   return 0;
-}
-
-IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
-ipmmu_vmsa_iommu_of_setup);
-IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
-ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa");
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795");
  #endif
  
  MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 04f4d51ffacb..a41d4251b0a9 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -856,7 +856,7 @@ static struct platform_driver msm_iommu_driver = {
.remove = msm_iommu_remove,
  };
  
-static int __init msm_iommu_driver_init(void)

+static int __init msm_iommu_init(void)
  {
int ret;
  
@@ -864,30 +864,20 @@ static int __init msm_iommu_driver_init(void)

if (ret != 0)
pr_err("Failed to register IOMMU driver\n");
  
+	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);

+
return ret;
  }
  
-static void __exit msm_iommu_driver_exit(void)

+static void __exit msm_iommu_exit(void)
  {
   

[PATCH 9/9] iommu/rockchip: Use OF_IOMMU to attach devices automatically

2018-01-11 Thread Jeffy Chen
Converts the rockchip-iommu driver to use the OF_IOMMU infrastructure,
which allows attaching master devices to their IOMMUs automatically
according to DT properties.

Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ab18a80fdd12..c375a2522bfd 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1091,6 +1092,13 @@ static struct iommu_group *rk_iommu_device_group(struct 
device *dev)
return ERR_PTR(ret);
 }
 
+static int rk_iommu_of_xlate(struct device *dev,
+struct of_phandle_args *spec)
+{
+   /* We don't have any phandle args, so just return 0. */
+   return 0;
+}
+
 static const struct iommu_ops rk_iommu_ops = {
.domain_alloc = rk_iommu_domain_alloc,
.domain_free = rk_iommu_domain_free,
@@ -1104,6 +1112,7 @@ static const struct iommu_ops rk_iommu_ops = {
.iova_to_phys = rk_iommu_iova_to_phys,
.device_group = rk_iommu_device_group,
.pgsize_bitmap = RK_IOMMU_PGSIZE_BITMAP,
+   .of_xlate = rk_iommu_of_xlate,
 };
 
 static int rk_iommu_probe(struct platform_device *pdev)
@@ -1166,6 +1175,8 @@ static int rk_iommu_probe(struct platform_device *pdev)
return err;
 
iommu_device_set_ops(&iommu->iommu, &rk_iommu_ops);
+   iommu_device_set_fwnode(&iommu->iommu, &dev->of_node->fwnode);
+
err = iommu_device_register(&iommu->iommu);
if (err) {
iommu_device_sysfs_remove(&iommu->iommu);
@@ -1241,6 +1252,8 @@ static void __exit rk_iommu_exit(void)
 subsys_initcall(rk_iommu_init);
 module_exit(rk_iommu_exit);
 
+IOMMU_OF_DECLARE(rk_iommu_of, "rockchip,iommu");
+
 MODULE_DESCRIPTION("IOMMU API for Rockchip");
 MODULE_AUTHOR("Simon Xue  and Daniel Kurtz 
");
 MODULE_ALIAS("platform:rockchip-iommu");
-- 
2.11.0


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


[PATCH 8/9] iommu/rockchip: Use IOMMU device for dma mapping operations

2018-01-11 Thread Jeffy Chen
Use the first registered IOMMU device for dma mapping operations, and
drop the domain platform device.

This is similar to exynos iommu driver.

Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 96 --
 1 file changed, 28 insertions(+), 68 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 86f8190d7bed..ab18a80fdd12 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -76,7 +76,6 @@
 
 struct rk_iommu_domain {
struct list_head iommus;
-   struct platform_device *pdev;
u32 *dt; /* page directory table */
dma_addr_t dt_dma;
spinlock_t iommus_lock; /* lock for iommus list */
@@ -97,12 +96,14 @@ struct rk_iommu {
struct iommu_domain *domain; /* domain to which iommu is attached */
 };
 
+static struct device *dma_dev;
+
 static inline void rk_table_flush(struct rk_iommu_domain *dom, dma_addr_t dma,
  unsigned int count)
 {
size_t size = count * sizeof(u32); /* count of u32 entry */
 
-   dma_sync_single_for_device(&dom->pdev->dev, dma, size, DMA_TO_DEVICE);
+   dma_sync_single_for_device(dma_dev, dma, size, DMA_TO_DEVICE);
 }
 
 static struct rk_iommu_domain *to_rk_domain(struct iommu_domain *dom)
@@ -606,7 +607,6 @@ static void rk_iommu_zap_iova_first_last(struct 
rk_iommu_domain *rk_domain,
 static u32 *rk_dte_get_page_table(struct rk_iommu_domain *rk_domain,
  dma_addr_t iova)
 {
-   struct device *dev = &rk_domain->pdev->dev;
u32 *page_table, *dte_addr;
u32 dte_index, dte;
phys_addr_t pt_phys;
@@ -624,9 +624,9 @@ static u32 *rk_dte_get_page_table(struct rk_iommu_domain 
*rk_domain,
if (!page_table)
return ERR_PTR(-ENOMEM);
 
-   pt_dma = dma_map_single(dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
-   if (dma_mapping_error(dev, pt_dma)) {
-   dev_err(dev, "DMA mapping error while allocating page table\n");
+   pt_dma = dma_map_single(dma_dev, page_table, SPAGE_SIZE, DMA_TO_DEVICE);
+   if (dma_mapping_error(dma_dev, pt_dma)) {
+   dev_err(dma_dev, "DMA mapping error while allocating page 
table\n");
free_page((unsigned long)page_table);
return ERR_PTR(-ENOMEM);
}
@@ -905,29 +905,20 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
 {
struct rk_iommu_domain *rk_domain;
-   struct platform_device *pdev;
-   struct device *iommu_dev;
 
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
 
-   /* Register a pdev per domain, so DMA API can base on this *dev
-* even some virtual master doesn't have an iommu slave
-*/
-   pdev = platform_device_register_simple("rk_iommu_domain",
-  PLATFORM_DEVID_AUTO, NULL, 0);
-   if (IS_ERR(pdev))
+   if (!dma_dev)
return NULL;
 
-   rk_domain = devm_kzalloc(&pdev->dev, sizeof(*rk_domain), GFP_KERNEL);
+   rk_domain = devm_kzalloc(dma_dev, sizeof(*rk_domain), GFP_KERNEL);
if (!rk_domain)
-   goto err_unreg_pdev;
-
-   rk_domain->pdev = pdev;
+   return NULL;
 
if (type == IOMMU_DOMAIN_DMA &&
iommu_get_dma_cookie(&rk_domain->domain))
-   goto err_unreg_pdev;
+   return NULL;
 
/*
 * rk32xx iommus use a 2 level pagetable.
@@ -938,11 +929,10 @@ static struct iommu_domain 
*rk_iommu_domain_alloc(unsigned type)
if (!rk_domain->dt)
goto err_put_cookie;
 
-   iommu_dev = &pdev->dev;
-   rk_domain->dt_dma = dma_map_single(iommu_dev, rk_domain->dt,
+   rk_domain->dt_dma = dma_map_single(dma_dev, rk_domain->dt,
   SPAGE_SIZE, DMA_TO_DEVICE);
-   if (dma_mapping_error(iommu_dev, rk_domain->dt_dma)) {
-   dev_err(iommu_dev, "DMA map error for DT\n");
+   if (dma_mapping_error(dma_dev, rk_domain->dt_dma)) {
+   dev_err(dma_dev, "DMA map error for DT\n");
goto err_free_dt;
}
 
@@ -963,8 +953,6 @@ static struct iommu_domain *rk_iommu_domain_alloc(unsigned 
type)
 err_put_cookie:
if (type == IOMMU_DOMAIN_DMA)
iommu_put_dma_cookie(&rk_domain->domain);
-err_unreg_pdev:
-   platform_device_unregister(pdev);
 
return NULL;
 }
@@ -981,20 +969,18 @@ static void rk_iommu_domain_free(struct iommu_domain 
*domain)
if (rk_dte_is_pt_valid(dte)) {
phys_addr_t pt_phys = rk_dte_pt_address(dte);
u32 *page_table = phys_to_virt(pt_phys);
-   dma_unmap_single(&rk_domain->pdev->dev, pt_phys,
+   dma_unmap_single(dma_dev, pt_phy

[PATCH 7/9] iommu/rockchip: Use iommu_group_get_for_dev() for add_device

2018-01-11 Thread Jeffy Chen
From: Tomasz Figa 

IOMMU drivers are supposed to call this function instead of manually
creating a group in their .add_device callback. This behavior is not
strictly required by ARM DMA mapping implementation, but ARM64 already
relies on it. This patch fixes the rockchip-iommu driver to comply with
this requirement.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 122 +
 1 file changed, 64 insertions(+), 58 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index cfeafbf54096..86f8190d7bed 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -802,6 +802,40 @@ static struct rk_iommu *rk_iommu_from_dev(struct device 
*dev)
return rk_iommu;
 }
 
+static void rk_iommu_detach_device(struct iommu_domain *domain,
+  struct device *dev)
+{
+   struct rk_iommu *iommu;
+   struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
+   unsigned long flags;
+   int i;
+
+   /* Allow 'virtual devices' (eg drm) to detach from domain */
+   iommu = rk_iommu_from_dev(dev);
+   if (!iommu)
+   return;
+
+   spin_lock_irqsave(&rk_domain->iommus_lock, flags);
+   list_del_init(&iommu->node);
+   spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
+
+   /* Ignore error while disabling, just keep going */
+   rk_iommu_enable_stall(iommu);
+   rk_iommu_disable_paging(iommu);
+   for (i = 0; i < iommu->num_mmu; i++) {
+   rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0);
+   rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
+   }
+   rk_iommu_disable_stall(iommu);
+
+   for (i = 0; i < iommu->num_irq; i++)
+   devm_free_irq(iommu->dev, iommu->irq[i], iommu);
+
+   iommu->domain = NULL;
+
+   dev_dbg(dev, "Detached from iommu domain\n");
+}
+
 static int rk_iommu_attach_device(struct iommu_domain *domain,
  struct device *dev)
 {
@@ -818,6 +852,9 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
if (!iommu)
return 0;
 
+   if (iommu->domain)
+   rk_iommu_detach_device(domain, dev);
+
ret = rk_iommu_enable_stall(iommu);
if (ret)
return ret;
@@ -865,40 +902,6 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
return ret;
 }
 
-static void rk_iommu_detach_device(struct iommu_domain *domain,
-  struct device *dev)
-{
-   struct rk_iommu *iommu;
-   struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
-   unsigned long flags;
-   int i;
-
-   /* Allow 'virtual devices' (eg drm) to detach from domain */
-   iommu = rk_iommu_from_dev(dev);
-   if (!iommu)
-   return;
-
-   spin_lock_irqsave(&rk_domain->iommus_lock, flags);
-   list_del_init(&iommu->node);
-   spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
-
-   /* Ignore error while disabling, just keep going */
-   rk_iommu_enable_stall(iommu);
-   rk_iommu_disable_paging(iommu);
-   for (i = 0; i < iommu->num_mmu; i++) {
-   rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 0);
-   rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, 0);
-   }
-   rk_iommu_disable_stall(iommu);
-
-   for (i = 0; i < iommu->num_irq; i++)
-   devm_free_irq(iommu->dev, iommu->irq[i], iommu);
-
-   iommu->domain = NULL;
-
-   dev_dbg(dev, "Detached from iommu domain\n");
-}
-
 static struct iommu_domain *rk_iommu_domain_alloc(unsigned type)
 {
struct rk_iommu_domain *rk_domain;
@@ -1049,41 +1052,20 @@ static int rk_iommu_add_device(struct device *dev)
 {
struct iommu_group *group;
struct rk_iommu *iommu;
-   int ret;
 
if (!rk_iommu_is_dev_iommu_master(dev))
return -ENODEV;
 
-   group = iommu_group_get(dev);
-   if (!group) {
-   group = iommu_group_alloc();
-   if (IS_ERR(group)) {
-   dev_err(dev, "Failed to allocate IOMMU group\n");
-   return PTR_ERR(group);
-   }
-   }
-
-   ret = iommu_group_add_device(group, dev);
-   if (ret)
-   goto err_put_group;
-
-   ret = rk_iommu_group_set_iommudata(group, dev);
-   if (ret)
-   goto err_remove_device;
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+   return PTR_ERR(group);
 
iommu = rk_iommu_from_dev(dev);
if (iommu)
iommu_device_link(&iommu->iommu, dev);
 
iommu_group_put(group);
-
return 0;
-
-err_remove_device:
-   iommu_group_remove_device(dev);
-err_put_group:
-   iommu_group_put(group);
-   return ret;
 }
 
 static void rk_iommu_remove_device(stru

[PATCH 6/9] iommu/rockchip: Fix TLB flush of secondary IOMMUs

2018-01-11 Thread Jeffy Chen
From: Tomasz Figa 

Due to the bug in current code, only first IOMMU has the TLB lines
flushed in rk_iommu_zap_lines. This patch fixes the inner loop to
execute for all IOMMUs and properly flush the TLB.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 6b797e085340..cfeafbf54096 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -274,19 +274,21 @@ static void rk_iommu_base_command(void __iomem *base, u32 
command)
 {
writel(command, base + RK_MMU_COMMAND);
 }
-static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova,
+static void rk_iommu_zap_lines(struct rk_iommu *iommu, dma_addr_t iova_start,
   size_t size)
 {
int i;
-
-   dma_addr_t iova_end = iova + size;
+   dma_addr_t iova_end = iova_start + size;
/*
 * TODO(djkurtz): Figure out when it is more efficient to shootdown the
 * entire iotlb rather than iterate over individual iovas.
 */
-   for (i = 0; i < iommu->num_mmu; i++)
-   for (; iova < iova_end; iova += SPAGE_SIZE)
+   for (i = 0; i < iommu->num_mmu; i++) {
+   dma_addr_t iova;
+
+   for (iova = iova_start; iova < iova_end; iova += SPAGE_SIZE)
rk_iommu_write(iommu->bases[i], RK_MMU_ZAP_ONE_LINE, 
iova);
+   }
 }
 
 static bool rk_iommu_is_stall_active(struct rk_iommu *iommu)
-- 
2.11.0


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


[PATCH 5/9] iommu/rockchip: Use iopoll helpers to wait for hardware

2018-01-11 Thread Jeffy Chen
From: Tomasz Figa 

This patch converts the rockchip-iommu driver to use the in-kernel
iopoll helpers to wait for certain status bits to change in registers
instead of an open-coded custom macro.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 68 --
 1 file changed, 32 insertions(+), 36 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 5f141390b4d7..6b797e085340 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -13,7 +13,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -36,7 +36,8 @@
 #define RK_MMU_AUTO_GATING 0x24
 
 #define DTE_ADDR_DUMMY 0xCAFEBABE
-#define FORCE_RESET_TIMEOUT100 /* ms */
+#define FORCE_RESET_TIMEOUT10  /* us */
+#define POLL_TIMEOUT   1000/* us */
 
 /* RK_MMU_STATUS fields */
 #define RK_MMU_STATUS_PAGING_ENABLED   BIT(0)
@@ -73,8 +74,6 @@
   */
 #define RK_IOMMU_PGSIZE_BITMAP 0x007ff000
 
-#define IOMMU_REG_POLL_COUNT_FAST 1000
-
 struct rk_iommu_domain {
struct list_head iommus;
struct platform_device *pdev;
@@ -111,27 +110,6 @@ static struct rk_iommu_domain *to_rk_domain(struct 
iommu_domain *dom)
return container_of(dom, struct rk_iommu_domain, domain);
 }
 
-/**
- * Inspired by _wait_for in intel_drv.h
- * This is NOT safe for use in interrupt context.
- *
- * Note that it's important that we check the condition again after having
- * timed out, since the timeout could be due to preemption or similar and
- * we've never had a chance to check the condition before the timeout.
- */
-#define rk_wait_for(COND, MS) ({ \
-   unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;   \
-   int ret__ = 0;  \
-   while (!(COND)) {   \
-   if (time_after(jiffies, timeout__)) {   \
-   ret__ = (COND) ? 0 : -ETIMEDOUT;\
-   break;  \
-   }   \
-   usleep_range(50, 100);  \
-   }   \
-   ret__;  \
-})
-
 /*
  * The Rockchip rk3288 iommu uses a 2-level page table.
  * The first level is the "Directory Table" (DT).
@@ -335,9 +313,21 @@ static bool rk_iommu_is_paging_enabled(struct rk_iommu 
*iommu)
return enable;
 }
 
+static bool rk_iommu_is_reset_done(struct rk_iommu *iommu)
+{
+   bool done = true;
+   int i;
+
+   for (i = 0; i < iommu->num_mmu; i++)
+   done &= rk_iommu_read(iommu->bases[i], RK_MMU_DTE_ADDR) == 0;
+
+   return done;
+}
+
 static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (rk_iommu_is_stall_active(iommu))
return 0;
@@ -348,7 +338,8 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_STALL);
 
-   ret = rk_wait_for(rk_iommu_is_stall_active(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+val, 100, POLL_TIMEOUT);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Enable stall request timed out, 
status: %#08x\n",
@@ -360,13 +351,15 @@ static int rk_iommu_enable_stall(struct rk_iommu *iommu)
 static int rk_iommu_disable_stall(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (!rk_iommu_is_stall_active(iommu))
return 0;
 
rk_iommu_command(iommu, RK_MMU_CMD_DISABLE_STALL);
 
-   ret = rk_wait_for(!rk_iommu_is_stall_active(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_stall_active, iommu, val,
+!val, 100, POLL_TIMEOUT);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Disable stall request timed out, 
status: %#08x\n",
@@ -378,13 +371,15 @@ static int rk_iommu_disable_stall(struct rk_iommu *iommu)
 static int rk_iommu_enable_paging(struct rk_iommu *iommu)
 {
int ret, i;
+   bool val;
 
if (rk_iommu_is_paging_enabled(iommu))
return 0;
 
rk_iommu_command(iommu, RK_MMU_CMD_ENABLE_PAGING);
 
-   ret = rk_wait_for(rk_iommu_is_paging_enabled(iommu), 1);
+   ret = readx_poll_timeout(rk_iommu_is_paging_enabled, iommu, val,
+val, 100, POLL_TIMEOUT);
if (ret)
for (i = 0; i < iommu->num_mmu; i++)
dev_err(iommu->dev, "Enable paging request timed out, 
status: %#08

[PATCH 4/9] iommu/rockchip: Fix error handling in init

2018-01-11 Thread Jeffy Chen
It's hard to undo bus_set_iommu() in the error path, so move it to the
end of init call.

Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index a05844cabb45..5f141390b4d7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1247,17 +1247,25 @@ static int __init rk_iommu_init(void)
 
of_node_put(np);
 
-   ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
-   if (ret)
-   return ret;
-
ret = platform_driver_register(&rk_iommu_domain_driver);
if (ret)
return ret;
 
ret = platform_driver_register(&rk_iommu_driver);
if (ret)
-   platform_driver_unregister(&rk_iommu_domain_driver);
+   goto err_unreg_domain_drv;
+
+   ret = bus_set_iommu(&platform_bus_type, &rk_iommu_ops);
+   if (ret)
+   goto err_unreg_iommu_drv;
+
+   return 0;
+
+err_unreg_iommu_drv:
+   platform_driver_unregister(&rk_iommu_driver);
+err_unreg_domain_drv:
+   platform_driver_unregister(&rk_iommu_domain_driver);
+
return ret;
 }
 static void __exit rk_iommu_exit(void)
-- 
2.11.0


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


[PATCH 1/9] iommu/of: Drop early initialisation hooks

2018-01-11 Thread Jeffy Chen
With the probe-deferral mechanism, early initialisation hooks are no
longer needed.

Suggested-by: Robin Murphy 
Signed-off-by: Jeffy Chen 
---

 drivers/iommu/arm-smmu-v3.c  |  2 +-
 drivers/iommu/arm-smmu.c | 12 ++--
 drivers/iommu/exynos-iommu.c |  2 +-
 drivers/iommu/ipmmu-vmsa.c   | 17 ++---
 drivers/iommu/msm_iommu.c| 24 +++-
 drivers/iommu/of_iommu.c | 16 
 drivers/iommu/qcom_iommu.c   |  2 +-
 include/linux/of_iommu.h |  6 ++
 8 files changed, 20 insertions(+), 61 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 744592d330ca..3f2f1fc68b52 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2971,7 +2971,7 @@ static struct platform_driver arm_smmu_driver = {
 };
 module_platform_driver(arm_smmu_driver);
 
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);
+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3");
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon ");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 78d4c6b8f1ba..69e7c60792a8 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2211,12 +2211,12 @@ static struct platform_driver arm_smmu_driver = {
 };
 module_platform_driver(arm_smmu_driver);
 
-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL);
-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL);
-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL);
-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL);
-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL);
-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL);
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1");
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2");
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400");
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401");
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500");
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2");
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon ");
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 79c45650f8de..1c7f926fad0e 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1394,4 +1394,4 @@ static int __init exynos_iommu_init(void)
 }
 core_initcall(exynos_iommu_init);
 
-IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL);
+IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu");
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index 8dce3a9de9d8..07b711bb4b16 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -1081,12 +1081,8 @@ static struct platform_driver ipmmu_driver = {
 
 static int __init ipmmu_init(void)
 {
-   static bool setup_done;
int ret;
 
-   if (setup_done)
-   return 0;
-
ret = platform_driver_register(&ipmmu_driver);
if (ret < 0)
return ret;
@@ -1096,7 +1092,6 @@ static int __init ipmmu_init(void)
bus_set_iommu(&platform_bus_type, &ipmmu_ops);
 #endif
 
-   setup_done = true;
return 0;
 }
 
@@ -1109,16 +1104,8 @@ subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
 #ifdef CONFIG_IOMMU_DMA
-static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
-{
-   ipmmu_init();
-   return 0;
-}
-
-IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
-ipmmu_vmsa_iommu_of_setup);
-IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
-ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa");
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795");
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 04f4d51ffacb..a41d4251b0a9 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -856,7 +856,7 @@ static struct platform_driver msm_iommu_driver = {
.remove = msm_iommu_remove,
 };
 
-static int __init msm_iommu_driver_init(void)
+static int __init msm_iommu_init(void)
 {
int ret;
 
@@ -864,30 +864,20 @@ static int __init msm_iommu_driver_init(void)
if (ret != 0)
pr_err("Failed to register IOMMU driver\n");
 
+   bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
+
return ret;
 }
 
-static void __exit msm_iommu_driver_exit(void)
+static void __exit msm_iommu_exit(void)
 {
platform_driver_unregister(&msm_iommu_driver);
 }
 
-subsys_initcall(msm_iommu_driver_init);
-module_exit(msm_iommu_driver_exit);
-
-static int __init msm_iommu_init(void)
-{
-   bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
-   return 0;
-}
-
-static int __init msm_iommu_of_setup(struct device_node *np)
-{
-   msm_iommu_init();
-   return 0;
-}
+subsys_initcall(msm_iommu_init);
+module_exit(msm_iommu_exit);
 
-IOMMU_OF_DECLA

[PATCH 2/9] iommu/rockchip: Fix error handling in attach

2018-01-11 Thread Jeffy Chen
From: Tomasz Figa 

Currently if the driver encounters an error while attaching device, it
will leave the IOMMU in an inconsistent state. Even though it shouldn't
really happen in reality, let's just add proper error path to keep
things consistent.

Signed-off-by: Tomasz Figa 
Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 9d991c2d8767..ee805e1dfba7 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -826,17 +826,10 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
 
ret = rk_iommu_force_reset(iommu);
if (ret)
-   return ret;
+   goto err_disable_stall;
 
iommu->domain = domain;
 
-   for (i = 0; i < iommu->num_irq; i++) {
-   ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
-  IRQF_SHARED, dev_name(dev), iommu);
-   if (ret)
-   return ret;
-   }
-
for (i = 0; i < iommu->num_mmu; i++) {
rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR,
   rk_domain->dt_dma);
@@ -844,9 +837,16 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, 
RK_MMU_IRQ_MASK);
}
 
+   for (i = 0; i < iommu->num_irq; i++) {
+   ret = devm_request_irq(iommu->dev, iommu->irq[i], rk_iommu_irq,
+  IRQF_SHARED, dev_name(dev), iommu);
+   if (ret)
+   goto err_free_irq;
+   }
+
ret = rk_iommu_enable_paging(iommu);
if (ret)
-   return ret;
+   goto err_free_irq;
 
spin_lock_irqsave(&rk_domain->iommus_lock, flags);
list_add_tail(&iommu->node, &rk_domain->iommus);
@@ -857,6 +857,14 @@ static int rk_iommu_attach_device(struct iommu_domain 
*domain,
rk_iommu_disable_stall(iommu);
 
return 0;
+
+err_free_irq:
+   while (i--)
+   devm_free_irq(iommu->dev, iommu->irq[i], iommu);
+err_disable_stall:
+   rk_iommu_disable_stall(iommu);
+
+   return ret;
 }
 
 static void rk_iommu_detach_device(struct iommu_domain *domain,
-- 
2.11.0


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


[PATCH 3/9] iommu/rockchip: Fix error handling in probe

2018-01-11 Thread Jeffy Chen
Add missing iommu_device_sysfs_remove in error path.

Signed-off-by: Jeffy Chen 
---

 drivers/iommu/rockchip-iommu.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index ee805e1dfba7..a05844cabb45 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1201,8 +1201,12 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
iommu_device_set_ops(&iommu->iommu, &rk_iommu_ops);
err = iommu_device_register(&iommu->iommu);
+   if (err) {
+   iommu_device_sysfs_remove(&iommu->iommu);
+   return err;
+   }
 
-   return err;
+   return 0;
 }
 
 static int rk_iommu_remove(struct platform_device *pdev)
-- 
2.11.0


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


[PATCH 0/9] iommu/rockchip: Use OF_IOMMU

2018-01-11 Thread Jeffy Chen

This series fixes some issues in rockchip iommu driver, and add of_iommu
support in it.

Also drop of_iommu early initialisation hooks as Robin suggested.


Jeffy Chen (5):
  iommu/of: Drop early initialisation hooks
  iommu/rockchip: Fix error handling in probe
  iommu/rockchip: Fix error handling in init
  iommu/rockchip: Use IOMMU device for dma mapping operations
  iommu/rockchip: Use OF_IOMMU to attach devices automatically

Tomasz Figa (4):
  iommu/rockchip: Fix error handling in attach
  iommu/rockchip: Use iopoll helpers to wait for hardware
  iommu/rockchip: Fix TLB flush of secondary IOMMUs
  iommu/rockchip: Use iommu_group_get_for_dev() for add_device

 drivers/iommu/arm-smmu-v3.c|   2 +-
 drivers/iommu/arm-smmu.c   |  12 +-
 drivers/iommu/exynos-iommu.c   |   2 +-
 drivers/iommu/ipmmu-vmsa.c |  17 +--
 drivers/iommu/msm_iommu.c  |  24 +--
 drivers/iommu/of_iommu.c   |  16 --
 drivers/iommu/qcom_iommu.c |   2 +-
 drivers/iommu/rockchip-iommu.c | 331 -
 include/linux/of_iommu.h   |   6 +-
 9 files changed, 184 insertions(+), 228 deletions(-)

-- 
2.11.0


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