Re: [PATCH 1/9] mm: Introduce new vm_insert_range API

2018-11-16 Thread Souptick Joarder
On Fri, Nov 16, 2018 at 11:59 PM Mike Rapoport  wrote:
>
> On Thu, Nov 15, 2018 at 09:15:30PM +0530, Souptick Joarder wrote:
> > Previouly drivers have their own way of mapping range of
> > kernel pages/memory into user vma and this was done by
> > invoking vm_insert_page() within a loop.
> >
> > As this pattern is common across different drivers, it can
> > be generalized by creating a new function and use it across
> > the drivers.
> >
> > vm_insert_range is the new API which will be used to map a
> > range of kernel memory/pages to user vma.
> >
> > Signed-off-by: Souptick Joarder 
> > Reviewed-by: Matthew Wilcox 
> > ---
> >  include/linux/mm_types.h |  3 +++
> >  mm/memory.c  | 28 
> >  mm/nommu.c   |  7 +++
> >  3 files changed, 38 insertions(+)
> >
> > diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> > index 5ed8f62..15ae24f 100644
> > --- a/include/linux/mm_types.h
> > +++ b/include/linux/mm_types.h
> > @@ -523,6 +523,9 @@ extern void tlb_gather_mmu(struct mmu_gather *tlb, 
> > struct mm_struct *mm,
> >  extern void tlb_finish_mmu(struct mmu_gather *tlb,
> >   unsigned long start, unsigned long end);
> >
> > +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> > + struct page **pages, unsigned long page_count);
> > +
> >  static inline void init_tlb_flush_pending(struct mm_struct *mm)
> >  {
> >   atomic_set(>tlb_flush_pending, 0);
> > diff --git a/mm/memory.c b/mm/memory.c
> > index 15c417e..da904ed 100644
> > --- a/mm/memory.c
> > +++ b/mm/memory.c
> > @@ -1478,6 +1478,34 @@ static int insert_page(struct vm_area_struct *vma, 
> > unsigned long addr,
> >  }
> >
> >  /**
> > + * vm_insert_range - insert range of kernel pages into user vma
> > + * @vma: user vma to map to
> > + * @addr: target user address of this page
> > + * @pages: pointer to array of source kernel pages
> > + * @page_count: no. of pages need to insert into user vma
> > + *
> > + * This allows drivers to insert range of kernel pages they've allocated
> > + * into a user vma. This is a generic function which drivers can use
> > + * rather than using their own way of mapping range of kernel pages into
> > + * user vma.
>
> Please add the return value and context descriptions.
>
> > + */
> > +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> > + struct page **pages, unsigned long page_count)
> > +{
> > + unsigned long uaddr = addr;
> > + int ret = 0, i;
> > +
> > + for (i = 0; i < page_count; i++) {
> > + ret = vm_insert_page(vma, uaddr, pages[i]);
> > + if (ret < 0)
> > + return ret;
> > + uaddr += PAGE_SIZE;
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +/**
> >   * vm_insert_page - insert single page into user vma
> >   * @vma: user vma to map to
> >   * @addr: target user address of this page
> > diff --git a/mm/nommu.c b/mm/nommu.c
> > index 749276b..d6ef5c7 100644
> > --- a/mm/nommu.c
> > +++ b/mm/nommu.c
> > @@ -473,6 +473,13 @@ int vm_insert_page(struct vm_area_struct *vma, 
> > unsigned long addr,
> >  }
> >  EXPORT_SYMBOL(vm_insert_page);
> >
> > +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> > + struct page **pages, unsigned long page_count)
> > +{
> > + return -EINVAL;
> > +}
> > +EXPORT_SYMBOL(vm_insert_range);
> > +
> >  /*
> >   *  sys_brk() for the most part doesn't need the global kernel
> >   *  lock, except when an application is doing something nasty
> > --
> > 1.9.1
> >
>
> --
> Sincerely yours,
> Mike.
>

Sure I will wait for some time to get additional review comments and
add all of those requested changes in v2.

Any further feedback on driver changes as part of this patch series ?
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 6/8] vfio/mdev: Add iommu place holders in mdev_device

2018-11-16 Thread Lu Baolu

Hi,

On 11/16/18 4:57 PM, Christoph Hellwig wrote:

On Fri, Nov 16, 2018 at 09:20:48AM +0800, Lu Baolu wrote:

Please keep symbols mdev_set/get_iommu_device(dev, iommu_device) non-GPL
same as other exported symbols from mdev_core module.


Yes. It will be fixed in the next version.


No.  mdev shall not be used to circumvent the exports in the generic
vfio code.


Get it now. Thanks a lot.

Best regards,
Lu Baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v3 14/15] iommu/mediatek: Constify iommu_ops

2018-11-16 Thread Yong Wu
From: Arvind Yadav 

iommu_ops are not supposed to change at runtime.
Functions 'iommu_device_set_ops' and 'bus_set_iommu' working with
const iommu_ops provided by . So mark the non-const
structs as const.

Signed-off-by: Arvind Yadav 
Signed-off-by: Yong Wu 
[Yong: Change the title to iommu/mediatek: xx]
---
 drivers/iommu/mtk_iommu.c| 4 ++--
 drivers/iommu/mtk_iommu_v1.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 63406c5..5775e8f 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -119,7 +119,7 @@ struct mtk_iommu_domain {
struct iommu_domain domain;
 };
 
-static struct iommu_ops mtk_iommu_ops;
+static const struct iommu_ops mtk_iommu_ops;
 
 static LIST_HEAD(m4ulist); /* List all the M4U HWs */
 
@@ -503,7 +503,7 @@ static int mtk_iommu_of_xlate(struct device *dev, struct 
of_phandle_args *args)
return iommu_fwspec_add_ids(dev, args->args, 1);
 }
 
-static struct iommu_ops mtk_iommu_ops = {
+static const struct iommu_ops mtk_iommu_ops = {
.domain_alloc   = mtk_iommu_domain_alloc,
.domain_free= mtk_iommu_domain_free,
.attach_dev = mtk_iommu_attach_device,
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 0e78084..27867b8 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -362,7 +362,7 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct 
iommu_domain *domain,
return pa;
 }
 
-static struct iommu_ops mtk_iommu_ops;
+static const struct iommu_ops mtk_iommu_ops;
 
 /*
  * MTK generation one iommu HW only support one iommu domain, and all the 
client
@@ -524,7 +524,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
return 0;
 }
 
-static struct iommu_ops mtk_iommu_ops = {
+static const struct iommu_ops mtk_iommu_ops = {
.domain_alloc   = mtk_iommu_domain_alloc,
.domain_free= mtk_iommu_domain_free,
.attach_dev = mtk_iommu_attach_device,
-- 
1.9.1

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


[PATCH v3 15/15] iommu/mediatek: Switch to SPDX license identifier

2018-11-16 Thread Yong Wu
Switch to SPDX license identifier for MediaTek iommu/smi and their
header files.

Signed-off-by: Yong Wu 
Reviewed-by: Rob Herring 
---
 drivers/iommu/mtk_iommu.c |  9 +
 drivers/iommu/mtk_iommu.h | 10 +-
 drivers/iommu/mtk_iommu_v1.c  | 10 +-
 drivers/memory/mtk-smi.c  | 10 +-
 include/dt-bindings/memory/mt2701-larb-port.h | 10 +-
 include/dt-bindings/memory/mt8173-larb-port.h | 10 +-
 include/soc/mediatek/smi.h| 10 +-
 7 files changed, 7 insertions(+), 62 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 5775e8f..01fe39f 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2015-2016 MediaTek Inc.
  * Author: Yong Wu 
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 #include 
 #include 
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index dfe9a07..d8bfba5 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015-2016 MediaTek Inc.
  * Author: Honghui Zhang 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _MTK_IOMMU_H_
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 27867b8..6571e5c 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2015-2016 MediaTek Inc.
  * Author: Honghui Zhang 
  *
  * Based on driver/iommu/mtk_iommu.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 #include 
 #include 
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index e0265fe..30a3e00 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2015-2016 MediaTek Inc.
  * Author: Yong Wu 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 #include 
 #include 
diff --git a/include/dt-bindings/memory/mt2701-larb-port.h 
b/include/dt-bindings/memory/mt2701-larb-port.h
index 6764d74..c511f0f 100644
--- a/include/dt-bindings/memory/mt2701-larb-port.h
+++ b/include/dt-bindings/memory/mt2701-larb-port.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015 MediaTek Inc.
  * Author: Honghui Zhang 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifndef _MT2701_LARB_PORT_H_
diff --git a/include/dt-bindings/memory/mt8173-larb-port.h 
b/include/dt-bindings/memory/mt8173-larb-port.h
index 111b4b0..a62bfeb 100644
--- a/include/dt-bindings/memory/mt8173-larb-port.h
+++ b/include/dt-bindings/memory/mt8173-larb-port.h
@@ -1,15 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2015-2016 MediaTek Inc.
  * Author: Yong Wu 
- *
- * This program is free software; you can 

[PATCH v3 13/15] memory: mtk-smi: Get rid of need_larbid

2018-11-16 Thread Yong Wu
The "mediatek,larb-id" has already been parsed in MTK IOMMU driver.
It's no need to parse it again in SMI driver. Only clean some codes.
This patch is fit for all the current mt2701, mt2712, mt7623, mt8173
and mt8183.

Signed-off-by: Yong Wu 
---
 drivers/memory/mtk-smi.c | 27 ++-
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index e4daabb..e0265fe 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -67,7 +67,6 @@ struct mtk_smi_common_plat {
 };
 
 struct mtk_smi_larb_gen {
-   bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
void (*config_port)(struct device *);
unsigned int larb_special_mask; /* The special larbs mask. */
@@ -152,18 +151,9 @@ void mtk_smi_larb_put(struct device *larbdev)
struct mtk_smi_iommu *smi_iommu = data;
unsigned int i;
 
-   if (larb->larb_gen->need_larbid) {
-   larb->mmu = _iommu->larb_imu[larb->larbid].mmu;
-   return 0;
-   }
-
-   /*
-* If there is no larbid property, Loop to find the corresponding
-* iommu information.
-*/
-   for (i = 0; i < smi_iommu->larb_nr; i++) {
+   for (i = 0; i < MTK_LARB_NR_MAX; i++) {
if (dev == smi_iommu->larb_imu[i].dev) {
-   /* The 'mmu' may be updated in iommu-attach/detach. */
+   larb->larbid = i;
larb->mmu = _iommu->larb_imu[i].mmu;
return 0;
}
@@ -242,7 +232,6 @@ static void mtk_smi_larb_config_port_gen1(struct device 
*dev)
 };
 
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
-   .need_larbid = true,
.port_in_larb = {
LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
@@ -251,13 +240,11 @@ static void mtk_smi_larb_config_port_gen1(struct device 
*dev)
 };
 
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
-   .need_larbid = true,
.config_port = mtk_smi_larb_config_port_gen2_general,
.larb_special_mask = BIT(8) | BIT(9), /* bdpsys */
 };
 
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
-   .need_larbid = true,
.config_port = mtk_smi_larb_config_port_gen2_general,
.larb_special_mask = BIT(2) | BIT(3) | BIT(7), /* IPU0 | IPU1 | CCU */
 };
@@ -289,7 +276,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
struct device *dev = >dev;
struct device_node *smi_node;
struct platform_device *smi_pdev;
-   int err;
 
larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
if (!larb)
@@ -316,15 +302,6 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
return PTR_ERR(larb->smi.clk_gals0);
larb->smi.dev = dev;
 
-   if (larb->larb_gen->need_larbid) {
-   err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
-  >larbid);
-   if (err) {
-   dev_err(dev, "missing larbid property\n");
-   return err;
-   }
-   }
-
smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
if (!smi_node)
return -EINVAL;
-- 
1.9.1

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


[PATCH v3 11/15] iommu/mediatek: Add VLD_PA_RANGE register backup when suspend

2018-11-16 Thread Yong Wu
The register VLD_PA_RNG(0x118) was forgot to backup while adding 4GB
mode support for mt2712. this patch add it.

Fixes: 30e2fccf9512 ("iommu/mediatek: Enlarge the validate PA range
for 4GB mode")
Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 2 ++
 drivers/iommu/mtk_iommu.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 9d6c8db..735fefc 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -721,6 +721,7 @@ static int __maybe_unused mtk_iommu_suspend(struct device 
*dev)
reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
+   reg->vld_pa_range = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
clk_disable_unprepare(data->bclk);
return 0;
 }
@@ -745,6 +746,7 @@ static int __maybe_unused mtk_iommu_resume(struct device 
*dev)
writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
+   writel_relaxed(reg->vld_pa_range, base + REG_MMU_VLD_PA_RNG);
if (m4u_dom)
writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
   base + REG_MMU_PT_BASE_ADDR);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index e5fd8ee..dfe9a07 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -33,6 +33,7 @@ struct mtk_iommu_suspend_reg {
u32 int_control0;
u32 int_main_control;
u32 ivrp_paddr;
+   u32 vld_pa_range;
 };
 
 enum mtk_iommu_plat {
-- 
1.9.1

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


[PATCH v3 12/15] iommu/mediatek: Add shutdown callback

2018-11-16 Thread Yong Wu
In the reboot burning test, if some Multimedia HW has something wrong,
It may keep send the invalid request to IOMMU. In order to avoid
affect the reboot flow, we add the shutdown callback to disable
M4U HW when shutdown.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 735fefc..63406c5 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -708,6 +708,11 @@ static int mtk_iommu_remove(struct platform_device *pdev)
return 0;
 }
 
+static void mtk_iommu_shutdown(struct platform_device *pdev)
+{
+   mtk_iommu_remove(pdev);
+}
+
 static int __maybe_unused mtk_iommu_suspend(struct device *dev)
 {
struct mtk_iommu_data *data = dev_get_drvdata(dev);
@@ -783,6 +788,7 @@ static int __maybe_unused mtk_iommu_resume(struct device 
*dev)
 static struct platform_driver mtk_iommu_driver = {
.probe  = mtk_iommu_probe,
.remove = mtk_iommu_remove,
+   .shutdown = mtk_iommu_shutdown,
.driver = {
.name = "mtk-iommu",
.of_match_table = of_match_ptr(mtk_iommu_of_ids),
-- 
1.9.1

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


[PATCH v3 10/15] memory: mtk-smi: Add bus_sel for mt8183

2018-11-16 Thread Yong Wu
There are 2 mmu cells in a M4U HW. we could adjust some larbs entering
mmu0 or mmu1 to balance the bandwidth via the smi-common register
SMI_BUS_SEL(0x220)(Each larb occupy 2 bits).

In mt8183, For better performance, we switch larb1/2/3/7 to enter
mmu1 while the others still keep enter mmu0.

In mt8173 and mt2712, we don't get the performance issue,
Keep its default value(0x0), that means all the larbs enter mmu0.

Signed-off-by: Yong Wu 
---
 drivers/memory/mtk-smi.c | 29 ++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 3e6e0a8..e4daabb 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -49,6 +49,12 @@
 #define SMI_LARB_NONSEC_CON(id)(0x380 + ((id) * 4))
 #define F_MMU_EN   BIT(0)
 
+/* SMI COMMON */
+#define SMI_BUS_SEL0x220
+#define SMI_BUS_LARB_SHIFT(larbid) ((larbid) << 1)
+/* All are MMU0 defaultly. Only specialize mmu1 here. */
+#define F_MMU1_LARB(larbid)(0x1 << SMI_BUS_LARB_SHIFT(larbid))
+
 enum mtk_smi_gen {
MTK_SMI_GEN1,
MTK_SMI_GEN2
@@ -56,6 +62,8 @@ enum mtk_smi_gen {
 
 struct mtk_smi_common_plat {
enum mtk_smi_gen gen;
+
+   u32 bus_sel; /* Balance some larbs to enter mmu0 or mmu1 */
 };
 
 struct mtk_smi_larb_gen {
@@ -70,8 +78,8 @@ struct mtk_smi {
struct clk  *clk_apb, *clk_smi;
struct clk  *clk_gals0, *clk_gals1;
struct clk  *clk_async; /*only needed by mt2701*/
-   void __iomem*smi_ao_base;
-
+   void __iomem*smi_ao_base; /* only for gen1 */
+   void __iomem*base;/* only for gen2 */
const struct mtk_smi_common_plat *plat;
 };
 
@@ -401,6 +409,12 @@ static int __maybe_unused mtk_smi_larb_suspend(struct 
device *dev)
.gen = MTK_SMI_GEN2,
 };
 
+static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
+   .gen = MTK_SMI_GEN2,
+   .bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(3) | F_MMU1_LARB(4) |
+  F_MMU1_LARB(7),
+};
+
 static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
@@ -416,7 +430,7 @@ static int __maybe_unused mtk_smi_larb_suspend(struct 
device *dev)
},
{
.compatible = "mediatek,mt8183-smi-common",
-   .data = _smi_common_gen2,
+   .data = _smi_common_mt8183,
},
{}
 };
@@ -473,6 +487,11 @@ static int mtk_smi_common_probe(struct platform_device 
*pdev)
ret = clk_prepare_enable(common->clk_async);
if (ret)
return ret;
+   } else {
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   common->base = devm_ioremap_resource(dev, res);
+   if (IS_ERR(common->base))
+   return PTR_ERR(common->base);
}
pm_runtime_enable(dev);
platform_set_drvdata(pdev, common);
@@ -488,6 +507,7 @@ static int mtk_smi_common_remove(struct platform_device 
*pdev)
 static int __maybe_unused mtk_smi_common_resume(struct device *dev)
 {
struct mtk_smi *common = dev_get_drvdata(dev);
+   u32 bus_sel = common->plat->bus_sel;
int ret;
 
ret = mtk_smi_clk_enable(common);
@@ -495,6 +515,9 @@ static int __maybe_unused mtk_smi_common_resume(struct 
device *dev)
dev_err(common->dev, "Failed to enable clock(%d).\n", ret);
return ret;
}
+
+   if (common->plat->gen == MTK_SMI_GEN2 && bus_sel)
+   writel(bus_sel, common->base + SMI_BUS_SEL);
return 0;
 }
 
-- 
1.9.1

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


[PATCH v3 09/15] memory: mtk-smi: Use a struct for the platform data for smi-common

2018-11-16 Thread Yong Wu
Use a struct as the platform special data instead of the enumeration.

Also there is a minor change that moving the position of
"enum mtk_smi_gen" definition, this is because we expect define
"struct mtk_smi_common_plat" before it is referred.

This is a prepare patch for adding bus_sel for mt8183.

Signed-off-by: Yong Wu 
---
 drivers/memory/mtk-smi.c | 37 +
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 7cf4573..3e6e0a8 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -49,6 +49,15 @@
 #define SMI_LARB_NONSEC_CON(id)(0x380 + ((id) * 4))
 #define F_MMU_EN   BIT(0)
 
+enum mtk_smi_gen {
+   MTK_SMI_GEN1,
+   MTK_SMI_GEN2
+};
+
+struct mtk_smi_common_plat {
+   enum mtk_smi_gen gen;
+};
+
 struct mtk_smi_larb_gen {
bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
@@ -62,6 +71,8 @@ struct mtk_smi {
struct clk  *clk_gals0, *clk_gals1;
struct clk  *clk_async; /*only needed by mt2701*/
void __iomem*smi_ao_base;
+
+   const struct mtk_smi_common_plat *plat;
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
@@ -73,11 +84,6 @@ struct mtk_smi_larb { /* larb: local arbiter */
u32 *mmu;
 };
 
-enum mtk_smi_gen {
-   MTK_SMI_GEN1,
-   MTK_SMI_GEN2
-};
-
 static int mtk_smi_clk_enable(const struct mtk_smi *smi)
 {
int ret;
@@ -387,22 +393,30 @@ static int __maybe_unused mtk_smi_larb_suspend(struct 
device *dev)
}
 };
 
+static const struct mtk_smi_common_plat mtk_smi_common_gen1 = {
+   .gen = MTK_SMI_GEN1,
+};
+
+static const struct mtk_smi_common_plat mtk_smi_common_gen2 = {
+   .gen = MTK_SMI_GEN2,
+};
+
 static const struct of_device_id mtk_smi_common_of_ids[] = {
{
.compatible = "mediatek,mt8173-smi-common",
-   .data = (void *)MTK_SMI_GEN2
+   .data = _smi_common_gen2,
},
{
.compatible = "mediatek,mt2701-smi-common",
-   .data = (void *)MTK_SMI_GEN1
+   .data = _smi_common_gen1,
},
{
.compatible = "mediatek,mt2712-smi-common",
-   .data = (void *)MTK_SMI_GEN2
+   .data = _smi_common_gen2,
},
{
.compatible = "mediatek,mt8183-smi-common",
-   .data = (void *)MTK_SMI_GEN2
+   .data = _smi_common_gen2,
},
{}
 };
@@ -412,13 +426,13 @@ static int mtk_smi_common_probe(struct platform_device 
*pdev)
struct device *dev = >dev;
struct mtk_smi *common;
struct resource *res;
-   enum mtk_smi_gen smi_gen;
int ret;
 
common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
if (!common)
return -ENOMEM;
common->dev = dev;
+   common->plat = of_device_get_match_data(dev);
 
common->clk_apb = devm_clk_get(dev, "apb");
if (IS_ERR(common->clk_apb))
@@ -446,8 +460,7 @@ static int mtk_smi_common_probe(struct platform_device 
*pdev)
 * clock into emi clock domain, but for mtk smi gen2, there's no smi ao
 * base.
 */
-   smi_gen = (enum mtk_smi_gen)of_device_get_match_data(dev);
-   if (smi_gen == MTK_SMI_GEN1) {
+   if (common->plat->gen == MTK_SMI_GEN1) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
common->smi_ao_base = devm_ioremap_resource(dev, res);
if (IS_ERR(common->smi_ao_base))
-- 
1.9.1

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


[PATCH v3 08/15] memory: mtk-smi: Invoke pm runtime_callback to enable clocks

2018-11-16 Thread Yong Wu
This patch only move the clk_prepare_enable and config_port into the
runtime suspend/resume callback. It doesn't change the code content
and sequence.

This is a prepare patch for adjusting SMI_BUS_SEL for mt8183.
(SMI_BUS_SEL need to be restored after smi-common resume every time.)
Also it gives a chance to get rid of mtk_smi_larb_get/put which could
be a next topic.

Signed-off-by: Yong Wu 
---
 drivers/memory/mtk-smi.c | 113 ++-
 1 file changed, 72 insertions(+), 41 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 979153b..7cf4573 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -78,17 +78,13 @@ enum mtk_smi_gen {
MTK_SMI_GEN2
 };
 
-static int mtk_smi_enable(const struct mtk_smi *smi)
+static int mtk_smi_clk_enable(const struct mtk_smi *smi)
 {
int ret;
 
-   ret = pm_runtime_get_sync(smi->dev);
-   if (ret < 0)
-   return ret;
-
ret = clk_prepare_enable(smi->clk_apb);
if (ret)
-   goto err_put_pm;
+   return ret;
 
ret = clk_prepare_enable(smi->clk_smi);
if (ret)
@@ -110,59 +106,28 @@ static int mtk_smi_enable(const struct mtk_smi *smi)
clk_disable_unprepare(smi->clk_smi);
 err_disable_apb:
clk_disable_unprepare(smi->clk_apb);
-err_put_pm:
-   pm_runtime_put_sync(smi->dev);
return ret;
 }
 
-static void mtk_smi_disable(const struct mtk_smi *smi)
+static void mtk_smi_clk_disable(const struct mtk_smi *smi)
 {
clk_disable_unprepare(smi->clk_gals1);
clk_disable_unprepare(smi->clk_gals0);
clk_disable_unprepare(smi->clk_smi);
clk_disable_unprepare(smi->clk_apb);
-   pm_runtime_put_sync(smi->dev);
 }
 
 int mtk_smi_larb_get(struct device *larbdev)
 {
-   struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
-   const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
-   struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
-   int ret;
+   int ret = pm_runtime_get_sync(larbdev);
 
-   /* Enable the smi-common's power and clocks */
-   ret = mtk_smi_enable(common);
-   if (ret)
-   return ret;
-
-   /* Enable the larb's power and clocks */
-   ret = mtk_smi_enable(>smi);
-   if (ret) {
-   mtk_smi_disable(common);
-   return ret;
-   }
-
-   /* Configure the iommu info for this larb */
-   larb_gen->config_port(larbdev);
-
-   return 0;
+   return (ret < 0) ? ret : 0;
 }
 EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
 
 void mtk_smi_larb_put(struct device *larbdev)
 {
-   struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
-   struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
-
-   /*
-* Don't de-configure the iommu info for this larb since there may be
-* several modules in this larb.
-* The iommu info will be reset after power off.
-*/
-
-   mtk_smi_disable(>smi);
-   mtk_smi_disable(common);
+   pm_runtime_put_sync(larbdev);
 }
 EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
 
@@ -373,12 +338,52 @@ static int mtk_smi_larb_remove(struct platform_device 
*pdev)
return 0;
 }
 
+static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
+{
+   struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+   const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+   int ret;
+
+   /* Power on smi-common. */
+   ret = pm_runtime_get_sync(larb->smi_common_dev);
+   if (ret < 0) {
+   dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret);
+   return ret;
+   }
+
+   ret = mtk_smi_clk_enable(>smi);
+   if (ret < 0) {
+   dev_err(dev, "Failed to enable clock(%d).\n", ret);
+   pm_runtime_put_sync(larb->smi_common_dev);
+   return ret;
+   }
+
+   /* Configure the basic setting for this larb */
+   larb_gen->config_port(dev);
+
+   return 0;
+}
+
+static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
+{
+   struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+   mtk_smi_clk_disable(>smi);
+   pm_runtime_put_sync(larb->smi_common_dev);
+   return 0;
+}
+
+static const struct dev_pm_ops smi_larb_pm_ops = {
+   SET_RUNTIME_PM_OPS(mtk_smi_larb_suspend, mtk_smi_larb_resume, NULL)
+};
+
 static struct platform_driver mtk_smi_larb_driver = {
.probe  = mtk_smi_larb_probe,
.remove = mtk_smi_larb_remove,
.driver = {
.name = "mtk-smi-larb",
.of_match_table = mtk_smi_larb_of_ids,
+   .pm = _larb_pm_ops,
}
 };
 
@@ -467,12 +472,38 @@ static int mtk_smi_common_remove(struct platform_device 
*pdev)
return 0;
 }
 
+static int __maybe_unused mtk_smi_common_resume(struct device *dev)
+{
+   struct mtk_smi *common = dev_get_drvdata(dev);
+   int ret;
+
+   

[PATCH v3 06/15] iommu/mediatek: Add mt8183 IOMMU support

2018-11-16 Thread Yong Wu
The M4U IP blocks in mt8183 is MediaTek's generation2 M4U which use
the ARM Short-descriptor like mt8173, and most of the HW registers
are the same.

Here list main changes in mt8183:
1) mt8183 has only one M4U HW like mt8173.
2) mt8183 don't have its "bclk" clock, the M4U use the EMI clock
which has already been enabled before kernel.
3) mt8183 can support the dram over 4GB, but it don't call this "4GB
mode".
4) mt8183 pgtable base register(0x0) extend bit[1:0] which represent
the bit[33:32] in the physical address of the pgtable base, But the
standard ttbr0[1] means the S bit which is enabled defaultly, Hence,
we add a mask.
5) mt8183 HW has a GALS modules, the SMI should add "gals" clock
support.
6) the larb-id in smi-common has been remapped. This means the
larb-id reported in the mtk_iommu_isr is not the real larb-id, here
is the remapping relationship of mt8183:
   M4U
|
-
|   SMI common  |
-0-7-5-6-1-2--3-4- <- Id remapped
 | | | | | |  | |
larb0 larb1 IPU0  IPU1 larb4 larb5  larb6  CCU
disp  vdec  img   cam   venc  imgcam
As above, larb0 connects with the id 0 in smi-common.
  larb1 connects with the id 7 in smi-common.
  ...
Take a example, if the larb-id reported in the mtk_iommu_isr is 7,
actually it is larb1(vdec).

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 38 --
 drivers/iommu/mtk_iommu.h |  5 +
 drivers/memory/mtk-smi.c  | 47 +++
 3 files changed, 80 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 9165b05..0021ecd 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -36,6 +36,7 @@
 #include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR   0x000
+#define MMU_PT_ADDR_MASK   GENMASK(31, 7)
 
 #define REG_MMU_INVALIDATE 0x020
 #define F_ALL_INVLD0x2
@@ -54,7 +55,7 @@
 #define REG_MMU_CTRL_REG   0x110
 #define F_MMU_PREFETCH_RT_REPLACE_MOD  BIT(4)
 #define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
-   ((data)->plat_data->m4u_plat == M4U_MT2712 ? 4 : 5)
+   ((data)->plat_data->m4u_plat == M4U_MT8173 ? 5 : 4)
 /* It's named by F_MMU_TF_PROT_SEL in mt2712. */
 #define F_MMU_TF_PROTECT_SEL(prot, data) \
(((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
@@ -220,6 +221,9 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
fault_port = F_MMU0_INT_ID_PORT_ID(regval);
 
+   if (data->plat_data->larbid_remap_enable)
+   fault_larb = data->plat_data->larbid_remapped[fault_larb];
+
if (report_iommu_fault(>domain, data->dev, fault_iova,
   write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
dev_err_ratelimited(
@@ -344,7 +348,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
/* Update the pgtable base address register of the M4U HW */
if (!data->m4u_dom) {
data->m4u_dom = dom;
-   writel(dom->cfg.arm_v7s_cfg.ttbr[0],
+   writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK,
   data->base + REG_MMU_PT_BASE_ADDR);
}
 
@@ -507,6 +511,7 @@ static int mtk_iommu_of_xlate(struct device *dev, struct 
of_phandle_args *args)
 
 static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
 {
+   enum mtk_iommu_plat m4u_plat = data->plat_data->m4u_plat;
u32 regval;
int ret;
 
@@ -517,7 +522,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
}
 
regval = F_MMU_TF_PROTECT_SEL(2, data);
-   if (data->plat_data->m4u_plat == M4U_MT8173)
+   if (m4u_plat == M4U_MT8173)
regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
 
@@ -538,14 +543,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
 
-   if (data->plat_data->m4u_plat == M4U_MT8173)
+   if (m4u_plat == M4U_MT8173)
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
 upper_32_bits(data->protect_base);
writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
 
-   if (data->enable_4GB && data->plat_data->m4u_plat != M4U_MT8173) {
+   if (data->enable_4GB && m4u_plat == M4U_MT2712) {
/*
 * If 4GB mode is enabled, the validate PA range is from
 * 0x1__ to 0x1__. here record 

[PATCH v3 05/15] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode

2018-11-16 Thread Yong Wu
MediaTek extend the arm v7s descriptor to support the dram over 4GB.

In the mt2712 and mt8173, it's called "4GB mode", the physical address
is from 0x4000_ to 0x1_3fff_, but from EMI point of view, it
is remapped to high address from 0x1__ to 0x1__, the
bit32 is always enabled. thus, in the M4U, we always enable the bit9
for all PTEs which means to enable bit32 of physical address.

but in mt8183, M4U support the dram from 0x4000_ to 0x3__
which isn't remaped. We extend the PTEs: the bit9 represent bit32 of
PA and the bit4 represent bit33 of PA. Meanwhile the iova still is
32bits.

In order to unify code, in the "4GB mode", we add the bit32 for the
physical address manually in our driver.

Correspondingly, Adding bit32 and bit33 for the PA in the iova_to_phys
has to been moved into v7s.

Regarding whether the pagetable address could be over 4GB, the mt8183
support it while the previous mt8173 don't. thus keep it as is.

Signed-off-by: Yong Wu 
Reviewed-by: Robin Murphy 
---
 drivers/iommu/io-pgtable-arm-v7s.c | 31 ---
 drivers/iommu/io-pgtable.h |  7 +++
 drivers/iommu/mtk_iommu.c  | 14 --
 drivers/iommu/mtk_iommu.h  |  1 +
 4 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
b/drivers/iommu/io-pgtable-arm-v7s.c
index 03bb7b9..a006fe7 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -124,7 +124,9 @@
 #define ARM_V7S_TEX_MASK   0x7
 #define ARM_V7S_ATTR_TEX(val)  (((val) & ARM_V7S_TEX_MASK) << 
ARM_V7S_TEX_SHIFT)
 
-#define ARM_V7S_ATTR_MTK_4GB   BIT(9) /* MTK extend it for 4GB mode */
+/* MediaTek extend the two bits below for over 4GB mode */
+#define ARM_V7S_ATTR_MTK_PA_BIT32  BIT(9)
+#define ARM_V7S_ATTR_MTK_PA_BIT33  BIT(4)
 
 /* *well, except for TEX on level 2 large pages, of course :( */
 #define ARM_V7S_CONT_PAGE_TEX_SHIFT6
@@ -183,13 +185,22 @@ static dma_addr_t __arm_v7s_dma_addr(void *pages)
 static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
struct io_pgtable_cfg *cfg)
 {
-   return paddr & ARM_V7S_LVL_MASK(lvl);
+   arm_v7s_iopte pte = paddr & ARM_V7S_LVL_MASK(lvl);
+
+   if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
+   if (paddr & BIT_ULL(32))
+   pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
+   if (paddr & BIT_ULL(33))
+   pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
+   }
+   return pte;
 }
 
 static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
  struct io_pgtable_cfg *cfg)
 {
arm_v7s_iopte mask;
+   phys_addr_t paddr;
 
if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
mask = ARM_V7S_TABLE_MASK;
@@ -198,7 +209,14 @@ static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int 
lvl,
else
mask = ARM_V7S_LVL_MASK(lvl);
 
-   return pte & mask;
+   paddr = pte & mask;
+   if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
+   if (pte & ARM_V7S_ATTR_MTK_PA_BIT32)
+   paddr |= BIT_ULL(32);
+   if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
+   paddr |= BIT_ULL(33);
+   }
+   return paddr;
 }
 
 static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl,
@@ -315,9 +333,6 @@ static arm_v7s_iopte arm_v7s_prot_to_pte(int prot, int lvl,
if (lvl == 1 && (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS))
pte |= ARM_V7S_ATTR_NS_SECTION;
 
-   if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)
-   pte |= ARM_V7S_ATTR_MTK_4GB;
-
return pte;
 }
 
@@ -504,7 +519,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned 
long iova,
if (!(prot & (IOMMU_READ | IOMMU_WRITE)))
return 0;
 
-   if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr)))
+   if (WARN_ON(upper_32_bits(iova)) ||
+   WARN_ON(upper_32_bits(paddr) &&
+   !(iop->cfg.quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB)))
return -ERANGE;
 
ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd);
diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h
index 47d5ae5..69db115 100644
--- a/drivers/iommu/io-pgtable.h
+++ b/drivers/iommu/io-pgtable.h
@@ -62,10 +62,9 @@ struct io_pgtable_cfg {
 *  (unmapped) entries but the hardware might do so anyway, perform
 *  TLB maintenance when mapping as well as when unmapping.
 *
-* IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all
-*  PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit
-*  when the SoC is in "4GB mode" and they can only access the high
-*  remap of DRAM (0x1_ to 0x1_).
+* IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) MediaTek IOMMUs 

[PATCH v3 07/15] iommu/mediatek: Add mmu1 support

2018-11-16 Thread Yong Wu
Normally the M4U HW connect EMI with smi. the diagram is like below:
  EMI
   |
  M4U
   |
smi-common
   |
   -
   ||| |...
larb0 larb1  larb2 larb3

Actually there are 2 mmu cells in the M4U HW, like this diagram:

  EMI
   -
| |
   mmu0  mmu1 <- M4U
| |
   -
   |
smi-common
   |
   -
   ||| |...
larb0 larb1  larb2 larb3

This patch add support for mmu1. In order to get better performance,
we could adjust some larbs go to mmu1 while the others still go to
mmu0. This is controlled by a SMI COMMON register SMI_BUS_SEL(0x220).

mt2712, mt8173 and mt8183 M4U HW all have 2 mmu cells. the default
value of that register is 0 which means all the larbs go to mmu0
defaultly.

This is a prepare patch for adjust SMI_BUS_SEL for mt8183.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 47 +--
 1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 0021ecd..9d6c8db 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -74,27 +74,32 @@
 #define F_MISS_FIFO_ERR_INT_EN BIT(6)
 #define F_INT_CLR_BIT  BIT(12)
 
-#define REG_MMU_INT_MAIN_CONTROL   0x124
-#define F_INT_TRANSLATION_FAULTBIT(0)
-#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
-#define F_INT_INVALID_PA_FAULT BIT(2)
-#define F_INT_ENTRY_REPLACEMENT_FAULT  BIT(3)
-#define F_INT_TLB_MISS_FAULT   BIT(4)
-#define F_INT_MISS_TRANSACTION_FIFO_FAULT  BIT(5)
-#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT   BIT(6)
+#define REG_MMU_INT_MAIN_CONTROL   0x124 /* mmu0 | mmu1 */
+#define F_INT_TRANSLATION_FAULT(BIT(0) | BIT(7))
+#define F_INT_MAIN_MULTI_HIT_FAULT (BIT(1) | BIT(8))
+#define F_INT_INVALID_PA_FAULT (BIT(2) | BIT(9))
+#define F_INT_ENTRY_REPLACEMENT_FAULT  (BIT(3) | BIT(10))
+#define F_INT_TLB_MISS_FAULT   (BIT(4) | BIT(11))
+#define F_INT_MISS_TRANSACTION_FIFO_FAULT  (BIT(5) | BIT(12))
+#define F_INT_PRETETCH_TRANSATION_FIFO_FAULT   (BIT(6) | BIT(13))
 
 #define REG_MMU_CPE_DONE   0x12C
 
 #define REG_MMU_FAULT_ST1  0x134
+#define F_REG_MMU0_FAULT_MASK  GENMASK(6, 0)
+#define F_REG_MMU1_FAULT_MASK  GENMASK(13, 7)
 
-#define REG_MMU_FAULT_VA   0x13c
+#define REG_MMU0_FAULT_VA  0x13c
 #define F_MMU_FAULT_VA_WRITE_BIT   BIT(1)
 #define F_MMU_FAULT_VA_LAYER_BIT   BIT(0)
 
-#define REG_MMU_INVLD_PA   0x140
-#define REG_MMU_INT_ID 0x150
-#define F_MMU0_INT_ID_LARB_ID(a)   (((a) >> 7) & 0x7)
-#define F_MMU0_INT_ID_PORT_ID(a)   (((a) >> 2) & 0x1f)
+#define REG_MMU0_INVLD_PA  0x140
+#define REG_MMU1_FAULT_VA  0x144
+#define REG_MMU1_INVLD_PA  0x148
+#define REG_MMU0_INT_ID0x150
+#define REG_MMU1_INT_ID0x154
+#define F_MMU_INT_ID_LARB_ID(a)(((a) >> 7) & 0x7)
+#define F_MMU_INT_ID_PORT_ID(a)(((a) >> 2) & 0x1f)
 
 #define MTK_PROTECT_PA_ALIGN   128
 
@@ -213,13 +218,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
 
/* Read error info from registers */
int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
-   fault_iova = readl_relaxed(data->base + REG_MMU_FAULT_VA);
+   if (int_state & F_REG_MMU0_FAULT_MASK) {
+   regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
+   fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
+   fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
+   } else {
+   regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
+   fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
+   fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
+   }
layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
-   fault_pa = readl_relaxed(data->base + REG_MMU_INVLD_PA);
-   regval = readl_relaxed(data->base + REG_MMU_INT_ID);
-   fault_larb = F_MMU0_INT_ID_LARB_ID(regval);
-   fault_port = F_MMU0_INT_ID_PORT_ID(regval);
+   fault_larb = F_MMU_INT_ID_LARB_ID(regval);
+   fault_port = F_MMU_INT_ID_PORT_ID(regval);
 
if (data->plat_data->larbid_remap_enable)
fault_larb = data->plat_data->larbid_remapped[fault_larb];
-- 

[PATCH v3 02/15] iommu/mediatek: Use a struct as the platform data

2018-11-16 Thread Yong Wu
Use a struct as the platform special data instead of the enumeration.
This is a prepare patch for adding mt8183 iommu support.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 24 
 drivers/iommu/mtk_iommu.h |  6 +-
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 44bd5b9..a8d85c8 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -54,7 +54,7 @@
 #define REG_MMU_CTRL_REG   0x110
 #define F_MMU_PREFETCH_RT_REPLACE_MOD  BIT(4)
 #define F_MMU_TF_PROTECT_SEL_SHIFT(data) \
-   ((data)->m4u_plat == M4U_MT2712 ? 4 : 5)
+   ((data)->plat_data->m4u_plat == M4U_MT2712 ? 4 : 5)
 /* It's named by F_MMU_TF_PROT_SEL in mt2712. */
 #define F_MMU_TF_PROTECT_SEL(prot, data) \
(((prot) & 0x3) << F_MMU_TF_PROTECT_SEL_SHIFT(data))
@@ -517,7 +517,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
}
 
regval = F_MMU_TF_PROTECT_SEL(2, data);
-   if (data->m4u_plat == M4U_MT8173)
+   if (data->plat_data->m4u_plat == M4U_MT8173)
regval |= F_MMU_PREFETCH_RT_REPLACE_MOD;
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
 
@@ -538,14 +538,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
 
-   if (data->m4u_plat == M4U_MT8173)
+   if (data->plat_data->m4u_plat == M4U_MT8173)
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
 upper_32_bits(data->protect_base);
writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
 
-   if (data->enable_4GB && data->m4u_plat != M4U_MT8173) {
+   if (data->enable_4GB && data->plat_data->m4u_plat != M4U_MT8173) {
/*
 * If 4GB mode is enabled, the validate PA range is from
 * 0x1__ to 0x1__. here record bit[32:30].
@@ -556,7 +556,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
 
/* It's MISC control register whose default value is ok except mt8173.*/
-   if (data->m4u_plat == M4U_MT8173)
+   if (data->plat_data->m4u_plat == M4U_MT8173)
writel_relaxed(0, data->base + REG_MMU_STANDARD_AXI_MODE);
 
if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
@@ -589,7 +589,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
data->dev = dev;
-   data->m4u_plat = (enum mtk_iommu_plat)of_device_get_match_data(dev);
+   data->plat_data = of_device_get_match_data(dev);
 
/* Protect memory. HW will access here while translation fault.*/
protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
@@ -733,9 +733,17 @@ static int __maybe_unused mtk_iommu_resume(struct device 
*dev)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_iommu_suspend, mtk_iommu_resume)
 };
 
+static const struct mtk_iommu_plat_data mt2712_data = {
+   .m4u_plat = M4U_MT2712,
+};
+
+static const struct mtk_iommu_plat_data mt8173_data = {
+   .m4u_plat = M4U_MT8173,
+};
+
 static const struct of_device_id mtk_iommu_of_ids[] = {
-   { .compatible = "mediatek,mt2712-m4u", .data = (void *)M4U_MT2712},
-   { .compatible = "mediatek,mt8173-m4u", .data = (void *)M4U_MT8173},
+   { .compatible = "mediatek,mt2712-m4u", .data = _data},
+   { .compatible = "mediatek,mt8173-m4u", .data = _data},
{}
 };
 
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 778498b..333a0ef 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -41,6 +41,10 @@ enum mtk_iommu_plat {
M4U_MT8173,
 };
 
+struct mtk_iommu_plat_data {
+   enum mtk_iommu_plat m4u_plat;
+};
+
 struct mtk_iommu_domain;
 
 struct mtk_iommu_data {
@@ -57,7 +61,7 @@ struct mtk_iommu_data {
booltlb_flush_active;
 
struct iommu_device iommu;
-   enum mtk_iommu_plat m4u_plat;
+   const struct mtk_iommu_plat_data *plat_data;
 
struct list_headlist;
 };
-- 
1.9.1

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


[PATCH v3 01/15] dt-bindings: mediatek: Add binding for mt8183 IOMMU and SMI

2018-11-16 Thread Yong Wu
This patch adds decriptions for mt8183 IOMMU and SMI.

mt8183 has only one M4U like mt8173 and is also MTK IOMMU gen2 which
uses ARM Short-Descriptor translation table format.

The mt8183 M4U-SMI HW diagram is as below:

  EMI
   |
  M4U
   |
   --
   ||
   gals0-rx   gals1-rx
   ||
   ||
   gals0-tx   gals1-tx
   ||
  
   SMI Common
  
   |
  +-+-++-+-+---+---+
  | | || | |   |   |
  | |  gals-rx  gals-rx  |   gals-rx gals-rx gals-rx
  | | || | |   |   |
  | | || | |   |   |
  | |  gals-tx  gals-tx  |   gals-tx gals-tx gals-tx
  | | || | |   |   |
larb0 larb1  IPU0IPU1  larb4  larb5  larb6CCU
disp  vdec   img camvenc   imgcam

All the connections are HW fixed, SW can NOT adjust it.

Compared with mt8173, we add a GALS(Global Async Local Sync) module
between SMI-common and M4U, and additional GALS between larb2/3/5/6
and SMI-common. GALS can help synchronize for the modules in different
clock frequency, it can be seen as a "asynchronous fifo".

GALS can only help transfer the command/data while it doesn't have
the configuring register, thus it has the special "smi" clock and it
doesn't have the "apb" clock. From the diagram above, we add "gals0"
and "gals1" clocks for smi-common and add a "gals" clock for smi-larb.

>From the diagram above, IPU0/IPU1(Image Processor Unit) and CCU(Camera
Control Unit) is connected with smi-common directly, we can take them
as "larb2", "larb3" and "larb7", and their register spaces are
different with the normal larb.

Signed-off-by: Yong Wu 
Reviewed-by: Rob Herring 
---
 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  15 ++-
 .../memory-controllers/mediatek,smi-common.txt |  11 +-
 .../memory-controllers/mediatek,smi-larb.txt   |   3 +
 include/dt-bindings/memory/mt8183-larb-port.h  | 130 +
 4 files changed, 153 insertions(+), 6 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt8183-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt 
b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index 6922db5..c5140cc 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -36,6 +36,10 @@ each local arbiter.
 like display, video decode, and camera. And there are different ports
 in each larb. Take a example, There are many ports like MC, PP, VLD in the
 video decode local arbiter, all these ports are according to the video HW.
+  In some Socs, there may be a GALS(Global Async Local Sync) module between
+smi-common and m4u, and additional GALS module between smi-larb and
+smi-common. GALS can been seen as a "asynchronous fifo" which could help
+synchronize for the modules in different clock frequency.
 
 Required properties:
 - compatible : must be one of the following string:
@@ -44,18 +48,23 @@ Required properties:
"mediatek,mt7623-m4u", "mediatek,mt2701-m4u" for mt7623 which uses
 generation one m4u HW.
"mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
+   "mediatek,mt8183-m4u" for mt8183 which uses generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
 - clocks : must contain one entry for each clock-names.
-- clock-names : must be "bclk", It is the block clock of m4u.
+- clock-names : Only 1 optional clock:
+  - "bclk": the block clock of m4u.
+  Note that m4u use the EMI clock which always has been enabled before kernel
+  if there is no this "bclk".
 - mediatek,larbs : List of phandle to the local arbiters in the current Socs.
Refer to bindings/memory-controllers/mediatek,smi-larb.txt. It must sort
according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
Specifies the mtk_m4u_id as defined in
dt-binding/memory/mt2701-larb-port.h for mt2701, mt7623
-   dt-binding/memory/mt2712-larb-port.h for mt2712, and
-   dt-binding/memory/mt8173-larb-port.h for mt8173.
+   dt-binding/memory/mt2712-larb-port.h for mt2712,
+   dt-binding/memory/mt8173-larb-port.h for mt8173, and
+   dt-binding/memory/mt8183-larb-port.h for mt8183.
 
 Example:
iommu: iommu@10205000 {
diff --git 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt 

[PATCH v3 04/15] iommu/io-pgtable-arm-v7s: Add paddr_to_iopte and iopte_to_paddr helpers

2018-11-16 Thread Yong Wu
Add two helper functions: paddr_to_iopte and iopte_to_paddr.

Signed-off-by: Yong Wu 
Reviewed-by: Robin Murphy 
---
 drivers/iommu/io-pgtable-arm-v7s.c | 45 --
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
b/drivers/iommu/io-pgtable-arm-v7s.c
index 445c3bd..03bb7b9 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -173,18 +173,38 @@ struct arm_v7s_io_pgtable {
spinlock_t  split_lock;
 };
 
+static bool arm_v7s_pte_is_cont(arm_v7s_iopte pte, int lvl);
+
 static dma_addr_t __arm_v7s_dma_addr(void *pages)
 {
return (dma_addr_t)virt_to_phys(pages);
 }
 
-static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl)
+static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
+   struct io_pgtable_cfg *cfg)
 {
+   return paddr & ARM_V7S_LVL_MASK(lvl);
+}
+
+static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
+ struct io_pgtable_cfg *cfg)
+{
+   arm_v7s_iopte mask;
+
if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
-   pte &= ARM_V7S_TABLE_MASK;
+   mask = ARM_V7S_TABLE_MASK;
+   else if (arm_v7s_pte_is_cont(pte, lvl))
+   mask = ARM_V7S_LVL_MASK(lvl) * ARM_V7S_CONT_PAGES;
else
-   pte &= ARM_V7S_LVL_MASK(lvl);
-   return phys_to_virt(pte);
+   mask = ARM_V7S_LVL_MASK(lvl);
+
+   return pte & mask;
+}
+
+static arm_v7s_iopte *iopte_deref(arm_v7s_iopte pte, int lvl,
+ struct arm_v7s_io_pgtable *data)
+{
+   return phys_to_virt(iopte_to_paddr(pte, lvl, >iop.cfg));
 }
 
 static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
@@ -396,7 +416,7 @@ static int arm_v7s_init_pte(struct arm_v7s_io_pgtable *data,
if (num_entries > 1)
pte = arm_v7s_pte_to_cont(pte, lvl);
 
-   pte |= paddr & ARM_V7S_LVL_MASK(lvl);
+   pte |= paddr_to_iopte(paddr, lvl, cfg);
 
__arm_v7s_set_pte(ptep, pte, num_entries, cfg);
return 0;
@@ -462,7 +482,7 @@ static int __arm_v7s_map(struct arm_v7s_io_pgtable *data, 
unsigned long iova,
}
 
if (ARM_V7S_PTE_IS_TABLE(pte, lvl)) {
-   cptep = iopte_deref(pte, lvl);
+   cptep = iopte_deref(pte, lvl, data);
} else if (pte) {
/* We require an unmap first */
WARN_ON(!selftest_running);
@@ -512,7 +532,8 @@ static void arm_v7s_free_pgtable(struct io_pgtable *iop)
arm_v7s_iopte pte = data->pgd[i];
 
if (ARM_V7S_PTE_IS_TABLE(pte, 1))
-   __arm_v7s_free_table(iopte_deref(pte, 1), 2, data);
+   __arm_v7s_free_table(iopte_deref(pte, 1, data),
+2, data);
}
__arm_v7s_free_table(data->pgd, 1, data);
kmem_cache_destroy(data->l2_tables);
@@ -582,7 +603,7 @@ static size_t arm_v7s_split_blk_unmap(struct 
arm_v7s_io_pgtable *data,
if (!ARM_V7S_PTE_IS_TABLE(pte, 1))
return 0;
 
-   tablep = iopte_deref(pte, 1);
+   tablep = iopte_deref(pte, 1, data);
return __arm_v7s_unmap(data, iova, size, 2, tablep);
}
 
@@ -641,7 +662,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable 
*data,
io_pgtable_tlb_add_flush(iop, iova, blk_size,
ARM_V7S_BLOCK_SIZE(lvl + 1), false);
io_pgtable_tlb_sync(iop);
-   ptep = iopte_deref(pte[i], lvl);
+   ptep = iopte_deref(pte[i], lvl, data);
__arm_v7s_free_table(ptep, lvl + 1, data);
} else if (iop->cfg.quirks & 
IO_PGTABLE_QUIRK_NON_STRICT) {
/*
@@ -666,7 +687,7 @@ static size_t __arm_v7s_unmap(struct arm_v7s_io_pgtable 
*data,
}
 
/* Keep on walkin' */
-   ptep = iopte_deref(pte[0], lvl);
+   ptep = iopte_deref(pte[0], lvl, data);
return __arm_v7s_unmap(data, iova, size, lvl + 1, ptep);
 }
 
@@ -692,7 +713,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct 
io_pgtable_ops *ops,
do {
ptep += ARM_V7S_LVL_IDX(iova, ++lvl);
pte = READ_ONCE(*ptep);
-   ptep = iopte_deref(pte, lvl);
+   ptep = iopte_deref(pte, lvl, data);
} while (ARM_V7S_PTE_IS_TABLE(pte, lvl));
 
if (!ARM_V7S_PTE_IS_VALID(pte))
@@ -701,7 +722,7 @@ static phys_addr_t arm_v7s_iova_to_phys(struct 
io_pgtable_ops *ops,
mask = ARM_V7S_LVL_MASK(lvl);
if (arm_v7s_pte_is_cont(pte, lvl))
mask *= ARM_V7S_CONT_PAGES;
-   return (pte & mask) | (iova & ~mask);
+   return iopte_to_paddr(pte, lvl, >iop.cfg) | (iova & ~mask);
 }
 
 static 

[PATCH v3 03/15] memory: mtk-smi: Use a general config_port interface

2018-11-16 Thread Yong Wu
The config_port of mt2712 and mt8183 are the same. Use a general
config_port interface instead.

In addition, in mt2712, larb8 and larb9 are the bdpsys larbs which
are not the normal larb, their register space are different from the
normal one. thus, we can not call the general config_port. In mt8183,
IPU0/1 and CCU connect with smi-common directly, they also are not
the normal larb. Hence, we add a "larb_special_mask" for these special
larbs.

This is also a prepare patch for adding mt8183 SMI support.

Signed-off-by: Yong Wu 
---
 drivers/memory/mtk-smi.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 8f2d152..e37e54b 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -53,6 +53,7 @@ struct mtk_smi_larb_gen {
bool need_larbid;
int port_in_larb[MTK_LARB_NR_MAX + 1];
void (*config_port)(struct device *);
+   unsigned int larb_special_mask; /* The special larbs mask. */
 };
 
 struct mtk_smi {
@@ -176,17 +177,13 @@ void mtk_smi_larb_put(struct device *larbdev)
return -ENODEV;
 }
 
-static void mtk_smi_larb_config_port_mt2712(struct device *dev)
+static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
 {
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
u32 reg;
int i;
 
-   /*
-* larb 8/9 is the bdpsys larb, the iommu_en is enabled defaultly.
-* Don't need to set it again.
-*/
-   if (larb->larbid == 8 || larb->larbid == 9)
+   if (BIT(larb->larbid) & larb->larb_gen->larb_special_mask)
return;
 
for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
@@ -261,7 +258,8 @@ static void mtk_smi_larb_config_port_gen1(struct device 
*dev)
 
 static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
.need_larbid = true,
-   .config_port = mtk_smi_larb_config_port_mt2712,
+   .config_port = mtk_smi_larb_config_port_gen2_general,
+   .larb_special_mask = BIT(8) | BIT(9), /* bdpsys */
 };
 
 static const struct of_device_id mtk_smi_larb_of_ids[] = {
-- 
1.9.1

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


[PATCH v3 00/15] MT8183 IOMMU SUPPORT

2018-11-16 Thread Yong Wu
This patchset mainly adds support for mt8183 IOMMU and SMI.

mt8183 has only one M4U like mt8173 and is also MTK IOMMU gen2 which
uses ARM Short-Descriptor translation table format.

The mt8183 M4U-SMI HW diagram is as below:

  EMI
   |
  M4U
   |
   --
   ||
   gals0-rx   gals1-rx
   ||
   ||
   gals0-tx   gals1-tx
   ||
  
   SMI Common
  
   |
  +-+-++-+-+---+---+
  | | || | |   |   |
  | |  gals-rx  gals-rx  |   gals-rx gals-rx gals-rx
  | | || | |   |   |
  | | || | |   |   |
  | |  gals-tx  gals-tx  |   gals-tx gals-tx gals-tx
  | | || | |   |   |
larb0 larb1  IPU0IPU1  larb4  larb5  larb6CCU
disp  vdec   img camvenc   imgcam

All the connections are HW fixed, SW can NOT adjust it.

Compared with mt8173, we add a GALS(Global Async Local Sync) module
between SMI-common and M4U, and additional GALS between larb2/3/5/6
and SMI-common. GALS can help synchronize for the modules in different
clock frequency, it can be seen as a "asynchronous fifo".

GALS can only help transfer the command/data while it doesn't have
the configuring register, thus it has the special "smi" clock and it
doesn't have the "apb" clock. From the diagram above, we add "gals0"
and "gals1" clocks for smi-common and add a "gals" clock for smi-larb.

>From the diagram above, IPU0/IPU1(Image Processor Unit) and CCU(Camera
Control Unit) is connected with smi-common directly, we can take them
as "larb2", "larb3" and "larb7", and their register spaces are
different with the normal larb.

This is the general purpose of each patch in this patchset:
the patch 1/2/3/4/5/6 add the iommu/smi support for mt8183;
the patch 7/8/9/10 add mmu1 support;
the last patches contain some minor changes:
   -patch 11 fix a issue.
   -patch 12 improve the code flow(add shutdown).
   -patch 13 cleanup some smi codes(delete need_larbid).
   -patch 14 switch to SPDX license.
   -patch 15 Constify iommu_ops.
this patchset don't contain the dtsi part since it need depend on the
ccf and power-domain nodes which has not been accepted.

Change notes:

v3: 1) rebase on v4.20-rc1.
2) In the dt-binding, add a minor string "mt7623" which also use gen1
   since Matthias added it in v4.20.
3) About v7s:
   a) for paddr_to_pte, change the param from "arm_v7s_io_pgtable" to
  "arm_pgtable_cfg", according to Robin suggestion.
   b) Don't use CONFIG_PHYS_ADDR_T_64BIT.
   c) add a little comment(pgtable address still don't over 4GB) in the
  commit message of the patch "Extend MediaTek 4GB Mode".
4) add "iommu/mediatek: Constify iommu_ops" into this patchset. this may
   be helpful for review and merge.
   
https://lists.linuxfoundation.org/pipermail/iommu/2018-October/030637.html

v2: https://lists.linuxfoundation.org/pipermail/iommu/2018-September/030164.html
1) Fix typo in the commit message of dt-binding.
2) Change larb2/larb3 to the special larbs.
3) Refactor the larb-id remapped array(larbid_remapped), then we
don't need add the new function(mtk_iommu_get_larbid).
4) Add a new patch for v7s two helpers(paddr_to_iopte and
iopte_to_paddr).
5) Change some comment for MTK 4GB mode.

v1: base on v4.19-rc1.
http://lists.infradead.org/pipermail/linux-mediatek/2018-September/014881.html

Arvind Yadav (1):
  iommu/mediatek: Constify iommu_ops

Yong Wu (14):
  dt-bindings: mediatek: Add binding for mt8183 IOMMU and SMI
  iommu/mediatek: Use a struct as the platform data
  memory: mtk-smi: Use a general config_port interface
  iommu/io-pgtable-arm-v7s: Add paddr_to_iopte and iopte_to_paddr
helpers
  iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode
  iommu/mediatek: Add mt8183 IOMMU support
  iommu/mediatek: Add mmu1 support
  memory: mtk-smi: Invoke pm runtime_callback to enable clocks
  memory: mtk-smi: Use a struct for the platform data for smi-common
  memory: mtk-smi: Add bus_sel for mt8183
  iommu/mediatek: Add VLD_PA_RANGE register backup when suspend
  iommu/mediatek: Add shutdown callback
  memory: mtk-smi: Get rid of need_larbid
  iommu/mediatek: Switch to SPDX license identifier

 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  15 +-
 .../memory-controllers/mediatek,smi-common.txt |  11 +-
 .../memory-controllers/mediatek,smi-larb.txt   |   3 +
 drivers/iommu/io-pgtable-arm-v7s.c |  72 --
 drivers/iommu/io-pgtable.h |   7 +-
 drivers/iommu/mtk_iommu.c  

Re: [PATCH v4 3/7] of: Allow the iommu-map property to omit untranslated devices

2018-11-16 Thread Rob Herring
On Thu, 15 Nov 2018 16:52:30 +, Jean-Philippe Brucker wrote:
> In PCI root complex nodes, the iommu-map property describes the IOMMU that
> translates each endpoint. On some platforms, the IOMMU itself is presented
> as a PCI endpoint (e.g. AMD IOMMU and virtio-iommu). This isn't supported
> by the current OF driver, which expects all endpoints to have an IOMMU.
> Allow the iommu-map property to have gaps.
> 
> Relaxing of_map_rid() also allows the msi-map property to have gaps, which
> is invalid since MSIs always reach an MSI controller. In that case
> pci_msi_setup_msi_irqs() will return an error when attempting to find the
> device's MSI domain.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/of/base.c | 10 +++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 

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


Re: [PATCH v4 5/7] iommu: Add virtio-iommu driver

2018-11-16 Thread Jean-Philippe Brucker
Hi Eric,

On 16/11/2018 06:08, Auger Eric wrote:
>> +struct viommu_domain {
>> +struct iommu_domain domain;
>> +struct viommu_dev   *viommu;
>> +struct mutexmutex;
> same naming/comment as in smmu driver may help here
> struct mutex init_mutex; /* Protects viommu pointer */

ok

>> +unsigned intid;
>> +
>> +spinlock_t  mappings_lock;
>> +struct rb_root_cached   mappings;
>> +
>> +unsigned long   nr_endpoints;
>> +};
>> +
>> +struct viommu_endpoint {
>> +struct viommu_dev   *viommu;
>> +struct viommu_domain*vdomain;
>> +};
>> +
>> +struct viommu_request {
>> +struct list_headlist;
>> +void*writeback;
>> +unsigned intwrite_offset;
>> +unsigned intlen;
>> +charbuf[];
>> +};
>> +
>> +#define to_viommu_domain(domain)\
>> +container_of(domain, struct viommu_domain, domain)
>> +
>> +static int viommu_get_req_errno(void *buf, size_t len)
>> +{
>> +struct virtio_iommu_req_tail *tail = buf + len - sizeof(*tail);
>> +
>> +switch (tail->status) {
>> +case VIRTIO_IOMMU_S_OK:
>> +return 0;
>> +case VIRTIO_IOMMU_S_UNSUPP:
>> +return -ENOSYS;
>> +case VIRTIO_IOMMU_S_INVAL:
>> +return -EINVAL;
>> +case VIRTIO_IOMMU_S_RANGE:
>> +return -ERANGE;
>> +case VIRTIO_IOMMU_S_NOENT:
>> +return -ENOENT;
>> +case VIRTIO_IOMMU_S_FAULT:
>> +return -EFAULT;
>> +case VIRTIO_IOMMU_S_IOERR:
>> +case VIRTIO_IOMMU_S_DEVERR:
>> +default:
>> +return -EIO;
>> +}
>> +}
>> +
>> +static void viommu_set_req_status(void *buf, size_t len, int status)
>> +{
>> +struct virtio_iommu_req_tail *tail = buf + len - sizeof(*tail);
>> +
>> +tail->status = status;
>> +}
>> +
>> +static off_t viommu_get_req_offset(struct viommu_dev *viommu,
>> +   struct virtio_iommu_req_head *req,
>> +   size_t len)
> nit: viommu_get_write_desc_offset would be more self-explanatory?

ok

>> +{
>> +size_t tail_size = sizeof(struct virtio_iommu_req_tail);
>> +
>> +return len - tail_size;
>> +}
>> +
>> +/*
>> + * __viommu_sync_req - Complete all in-flight requests
>> + *
>> + * Wait for all added requests to complete. When this function returns, all
>> + * requests that were in-flight at the time of the call have completed.
>> + */
>> +static int __viommu_sync_req(struct viommu_dev *viommu)
>> +{
>> +int ret = 0;
>> +unsigned int len;
>> +size_t write_len;
>> +struct viommu_request *req;
>> +struct virtqueue *vq = viommu->vqs[VIOMMU_REQUEST_VQ];
>> +
>> +assert_spin_locked(>request_lock);
>> +
>> +virtqueue_kick(vq);
>> +
>> +while (!list_empty(>requests)) {
>> +len = 0;
>> +req = virtqueue_get_buf(vq, );
>> +if (!req)
>> +continue;
>> +
>> +if (!len)
>> +viommu_set_req_status(req->buf, req->len,
>> +  VIRTIO_IOMMU_S_IOERR);
>> +
>> +write_len = req->len - req->write_offset;
>> +if (req->writeback && len >= write_len)
> I don't get "len >= write_len". Is it valid for the device to write more
> than write_len? If it writes less than write_len, the status is not set,
> is it?

No on both counts, I'll change this to ==

There is a problem in the spec regarding this: to get the status, the
driver expects the device to set len to the size of the whole writeable
part of the buffer, even if it only filled a few properties. But the
device doesn't have to do it at the moment. I need to change this sentence:

The device MAY fill the remaining bytes of properties, if any,
with zeroes.

Into somthing like:

The device SHOULD fill the remaining bytes of properties, if
any, with zeroes.

The QEMU and kvmtool devices already do this.

>> +memcpy(req->writeback, req->buf + req->write_offset,
>> +   write_len);
>> +
>> +list_del(>list);
>> +kfree(req);
>> +}
>> +
>> +return ret;
>> +}
>> +
>> +static int viommu_sync_req(struct viommu_dev *viommu)
>> +{
>> +int ret;
>> +unsigned long flags;
>> +
>> +spin_lock_irqsave(>request_lock, flags);
>> +ret = __viommu_sync_req(viommu);
>> +if (ret)
>> +dev_dbg(viommu->dev, "could not sync requests (%d)\n", ret);
>> +spin_unlock_irqrestore(>request_lock, flags);
>> +
>> +return ret;
>> +}
>> +
>> +/*
>> + * __viommu_add_request - Add one request to the queue
>> + * @buf: pointer to the request buffer
>> + * @len: length of the request buffer
>> + * @writeback: copy data back to the buffer when the request 

Re: [PATCH 1/9] mm: Introduce new vm_insert_range API

2018-11-16 Thread Mike Rapoport
On Thu, Nov 15, 2018 at 09:15:30PM +0530, Souptick Joarder wrote:
> Previouly drivers have their own way of mapping range of
> kernel pages/memory into user vma and this was done by
> invoking vm_insert_page() within a loop.
> 
> As this pattern is common across different drivers, it can
> be generalized by creating a new function and use it across
> the drivers.
> 
> vm_insert_range is the new API which will be used to map a
> range of kernel memory/pages to user vma.
> 
> Signed-off-by: Souptick Joarder 
> Reviewed-by: Matthew Wilcox 
> ---
>  include/linux/mm_types.h |  3 +++
>  mm/memory.c  | 28 
>  mm/nommu.c   |  7 +++
>  3 files changed, 38 insertions(+)
> 
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 5ed8f62..15ae24f 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -523,6 +523,9 @@ extern void tlb_gather_mmu(struct mmu_gather *tlb, struct 
> mm_struct *mm,
>  extern void tlb_finish_mmu(struct mmu_gather *tlb,
>   unsigned long start, unsigned long end);
> 
> +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> + struct page **pages, unsigned long page_count);
> +
>  static inline void init_tlb_flush_pending(struct mm_struct *mm)
>  {
>   atomic_set(>tlb_flush_pending, 0);
> diff --git a/mm/memory.c b/mm/memory.c
> index 15c417e..da904ed 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -1478,6 +1478,34 @@ static int insert_page(struct vm_area_struct *vma, 
> unsigned long addr,
>  }
> 
>  /**
> + * vm_insert_range - insert range of kernel pages into user vma
> + * @vma: user vma to map to
> + * @addr: target user address of this page
> + * @pages: pointer to array of source kernel pages
> + * @page_count: no. of pages need to insert into user vma
> + *
> + * This allows drivers to insert range of kernel pages they've allocated
> + * into a user vma. This is a generic function which drivers can use
> + * rather than using their own way of mapping range of kernel pages into
> + * user vma.

Please add the return value and context descriptions.

> + */
> +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> + struct page **pages, unsigned long page_count)
> +{
> + unsigned long uaddr = addr;
> + int ret = 0, i;
> +
> + for (i = 0; i < page_count; i++) {
> + ret = vm_insert_page(vma, uaddr, pages[i]);
> + if (ret < 0)
> + return ret;
> + uaddr += PAGE_SIZE;
> + }
> +
> + return ret;
> +}
> +
> +/**
>   * vm_insert_page - insert single page into user vma
>   * @vma: user vma to map to
>   * @addr: target user address of this page
> diff --git a/mm/nommu.c b/mm/nommu.c
> index 749276b..d6ef5c7 100644
> --- a/mm/nommu.c
> +++ b/mm/nommu.c
> @@ -473,6 +473,13 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned 
> long addr,
>  }
>  EXPORT_SYMBOL(vm_insert_page);
> 
> +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> + struct page **pages, unsigned long page_count)
> +{
> + return -EINVAL;
> +}
> +EXPORT_SYMBOL(vm_insert_range);
> +
>  /*
>   *  sys_brk() for the most part doesn't need the global kernel
>   *  lock, except when an application is doing something nasty
> -- 
> 1.9.1
> 

-- 
Sincerely yours,
Mike.

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


Re: [PATCH 1/9] mm: Introduce new vm_insert_range API

2018-11-16 Thread Slavomir Kaslev
On Thu, Nov 15, 2018 at 5:42 PM Souptick Joarder  wrote:
>
> Previouly drivers have their own way of mapping range of
> kernel pages/memory into user vma and this was done by
> invoking vm_insert_page() within a loop.
>
> As this pattern is common across different drivers, it can
> be generalized by creating a new function and use it across
> the drivers.
>
> vm_insert_range is the new API which will be used to map a
> range of kernel memory/pages to user vma.
>
> Signed-off-by: Souptick Joarder 
> Reviewed-by: Matthew Wilcox 
> ---
>  include/linux/mm_types.h |  3 +++
>  mm/memory.c  | 28 
>  mm/nommu.c   |  7 +++
>  3 files changed, 38 insertions(+)
>
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 5ed8f62..15ae24f 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -523,6 +523,9 @@ extern void tlb_gather_mmu(struct mmu_gather *tlb, struct 
> mm_struct *mm,
>  extern void tlb_finish_mmu(struct mmu_gather *tlb,
> unsigned long start, unsigned long end);
>
> +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> +   struct page **pages, unsigned long page_count);
> +
>  static inline void init_tlb_flush_pending(struct mm_struct *mm)
>  {
> atomic_set(>tlb_flush_pending, 0);
> diff --git a/mm/memory.c b/mm/memory.c
> index 15c417e..da904ed 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -1478,6 +1478,34 @@ static int insert_page(struct vm_area_struct *vma, 
> unsigned long addr,
>  }
>
>  /**
> + * vm_insert_range - insert range of kernel pages into user vma
> + * @vma: user vma to map to
> + * @addr: target user address of this page
> + * @pages: pointer to array of source kernel pages
> + * @page_count: no. of pages need to insert into user vma
> + *
> + * This allows drivers to insert range of kernel pages they've allocated
> + * into a user vma. This is a generic function which drivers can use
> + * rather than using their own way of mapping range of kernel pages into
> + * user vma.
> + */
> +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> +   struct page **pages, unsigned long page_count)
> +{
> +   unsigned long uaddr = addr;
> +   int ret = 0, i;
> +
> +   for (i = 0; i < page_count; i++) {
> +   ret = vm_insert_page(vma, uaddr, pages[i]);
> +   if (ret < 0)
> +   return ret;
> +   uaddr += PAGE_SIZE;
> +   }
> +
> +   return ret;
> +}

+ EXPORT_SYMBOL(vm_insert_range);

> +
> +/**
>   * vm_insert_page - insert single page into user vma
>   * @vma: user vma to map to
>   * @addr: target user address of this page
> diff --git a/mm/nommu.c b/mm/nommu.c
> index 749276b..d6ef5c7 100644
> --- a/mm/nommu.c
> +++ b/mm/nommu.c
> @@ -473,6 +473,13 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned 
> long addr,
>  }
>  EXPORT_SYMBOL(vm_insert_page);
>
> +int vm_insert_range(struct vm_area_struct *vma, unsigned long addr,
> +   struct page **pages, unsigned long page_count)
> +{
> +   return -EINVAL;
> +}
> +EXPORT_SYMBOL(vm_insert_range);
> +
>  /*
>   *  sys_brk() for the most part doesn't need the global kernel
>   *  lock, except when an application is doing something nasty
> --
> 1.9.1
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/9] mm: Introduce new vm_insert_range API

2018-11-16 Thread Randy Dunlap
On 11/16/18 12:15 AM, Souptick Joarder wrote:
> On Fri, Nov 16, 2018 at 12:11 PM Matthew Wilcox  wrote:
>>
>> On Fri, Nov 16, 2018 at 11:00:30AM +0530, Souptick Joarder wrote:
>>> On Thu, Nov 15, 2018 at 11:44 PM Randy Dunlap  wrote:
 On 11/15/18 7:45 AM, Souptick Joarder wrote:
 What is the opposite of vm_insert_range() or even of vm_insert_page()?
 or is there no need for that?
>>>
>>> There is no opposite function of vm_insert_range() / vm_insert_page().
>>> My understanding is, in case of any error, mmap handlers will return the
>>> err to user process and user space will decide the next action. So next
>>> time when mmap handler is getting invoked it will map from the beginning.
>>> Correct me if I am wrong.
>>
>> The opposite function, I suppose, is unmap_region().
>>
 s/no./number/
>>>
>>> I didn't get it ??
>>
>> This is a 'sed' expression.  's' is the 'substitute' command; the /
>> is a separator, 'no.' is what you wrote, and 'number' is what Randy
>> is recommending instead.
> 
> Ok. Will change it in v2.

Thanks.

> + for (i = 0; i < page_count; i++) {
> + ret = vm_insert_page(vma, uaddr, pages[i]);
> + if (ret < 0)
> + return ret;

 For a non-trivial value of page_count:
 Is it a problem if vm_insert_page() succeeds for several pages
 and then fails?
>>>
>>> No, it will be considered as total failure and mmap handler will return
>>> the err to user space.
>>
>> I think what Randy means is "What happens to the inserted pages?" and
>> the answer is that mmap_region() jumps to the 'unmap_and_free_vma'
>> label, which is an accurate name.

which says:

/* Undo any partial mapping done by a device driver. */
unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);

and that is what I was missing.  Thanks.

> Sorry for incorrect understanding of the question.

No problem.


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


Re: [PATCH 2/2] arch: switch the default on ARCH_HAS_SG_CHAIN

2018-11-16 Thread Palmer Dabbelt

On Fri, 09 Nov 2018 01:00:08 PST (-0800), Christoph Hellwig wrote:

These days architectures are mostly out of the business of dealing with
struct scatterlist at all, unless they have architecture specific iommu
drivers.  Replace the ARCH_HAS_SG_CHAIN symbol with a ARCH_NO_SG_CHAIN
one only enabled for architectures with horrible legacy iommu drivers
like alpha and parisc, and conditionally for arm which wants to keep it
disable for legacy platforms.

Signed-off-by: Christoph Hellwig 
---
 .../features/io/sg-chain/arch-support.txt | 33 ---
 arch/alpha/Kconfig|  1 +
 arch/arc/Kconfig  |  1 -
 arch/arm/Kconfig  |  2 +-
 arch/arm64/Kconfig|  1 -
 arch/ia64/Kconfig |  1 -
 arch/parisc/Kconfig   |  1 +
 arch/powerpc/Kconfig  |  1 -
 arch/s390/Kconfig |  1 -
 arch/sparc/Kconfig|  1 -
 arch/x86/Kconfig  |  1 -
 arch/xtensa/Kconfig   |  1 -
 include/linux/scatterlist.h   |  6 ++--
 lib/Kconfig   |  2 +-
 lib/scatterlist.c |  2 +-
 15 files changed, 8 insertions(+), 47 deletions(-)
 delete mode 100644 Documentation/features/io/sg-chain/arch-support.txt


As far as I can tell, it looks like m68k, mips, and powerpc mention an IOMMU in 
their ports, don't set ARCH_HAS_SG_CHAIN, and with this patch set won't set 
ARCH_NO_SG_CHAIN.  The issue is that I'm not sure how to determine what 
constitutes a horrible legacy IOMMU, at least with respect to not being able to 
use scatterlist chaining.


I poked through the 68k stuff (sun3 and sun3x) and the only thing I see that's 
odd is that DVMA_PAGE_SHIFT is 13.  That matches PAGE_SHIFT for the subarch, 
though, so I don't think it's an issue.  It looks like the mention in MIPS is 
trivial, so that should be fine.  There's a lot in the PC port so I just 
glanced at it.  I assume it's OK, but I did see an explicit mention of SG in 
their generic IOMMU.  There's a lot of flavors here so I'm not sure how well 
they all work.


I don't really think that's enough for my reviewed-by tag, so feel free to give 
me some pointers if you're looking for one -- I'd be happy to lean about 
IOMMUs (particularly broken ones, as that might help prevent us from designing 
a broken one), I'm just not sure what I'm looking for.


I'm going to assume you're going to merge this and I'll drop the RISC-V patch 
that turns on ARCH_HAS_SG_CHAIN.


Thanks!


diff --git a/Documentation/features/io/sg-chain/arch-support.txt 
b/Documentation/features/io/sg-chain/arch-support.txt
deleted file mode 100644
index 6554f0372c3f..
--- a/Documentation/features/io/sg-chain/arch-support.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Feature name:  sg-chain
-# Kconfig:   ARCH_HAS_SG_CHAIN
-# description:   arch supports chained scatter-gather lists
-#
----
-| arch |status|
----
-|   alpha: | TODO |
-| arc: |  ok  |
-| arm: |  ok  |
-|   arm64: |  ok  |
-| c6x: | TODO |
-|   h8300: | TODO |
-| hexagon: | TODO |
-|ia64: |  ok  |
-|m68k: | TODO |
-|  microblaze: | TODO |
-|mips: | TODO |
-|   nds32: | TODO |
-|   nios2: | TODO |
-|openrisc: | TODO |
-|  parisc: | TODO |
-| powerpc: |  ok  |
-|   riscv: | TODO |
-|s390: |  ok  |
-|  sh: | TODO |
-|   sparc: |  ok  |
-|  um: | TODO |
-|   unicore32: | TODO |
-| x86: |  ok  |
-|  xtensa: | TODO |
----
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 5b4f88363453..a7e748a46c18 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -5,6 +5,7 @@ config ALPHA
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_NO_PREEMPT
+   select ARCH_NO_SG_CHAIN
select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_AOUT
select HAVE_IDE
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index c9e2a1323536..fd48d698da29 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -13,7 +13,6 @@ config ARC
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
-   select ARCH_HAS_SG_CHAIN
select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 91be74d8df65..199eb62230b0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -19,6 +19,7 @@ config ARM
select ARCH_HAVE_CUSTOM_GPIO_H
select 

Re: [PATCH v4 0/7] Add virtio-iommu driver

2018-11-16 Thread Auger Eric
Hi Jean,
On 11/15/18 5:52 PM, Jean-Philippe Brucker wrote:
> Implement the virtio-iommu driver, following specification v0.8 [1].
> 
> Changes since v3 [2]:
> * Rebase onto v4.20-rc2. Patch 3 now touches drivers/of/base.c instead
>   of drivers/pci/of.c, since the map_rid() function has moved.
> * Removed the request timeout, that depended on DEBUG.
> * Other small fixes addressing comments on v3.
> 
> You can find Linux driver and kvmtool device on my virtio-iommu/v0.8.1
> branches [3]. You can also test it with the latest version of Eric's
> QEMU device [4].

Tested-by: Eric Auger 

this was tested with qemu
(https://github.com/eauger/qemu/tree/v3.1.0-rc1-virtio-iommu-v0.8.1)

Thanks

Eric
> 
> [1] Virtio-iommu specification v0.8, sources and pdf
> git://linux-arm.org/virtio-iommu.git virtio-iommu/v0.8
> http://jpbrucker.net/virtio-iommu/spec/v0.8/virtio-iommu-v0.8.pdf
> 
> [2] [PATCH v3 0/7] Add virtio-iommu driver
> https://www.spinics.net/lists/linux-pci/msg77110.html
> 
> [3] git://linux-arm.org/linux-jpb.git virtio-iommu/v0.8.1
> git://linux-arm.org/kvmtool-jpb.git virtio-iommu/v0.8.1
> 
> [4] [RFC v8 00/18] VIRTIO-IOMMU device
> https://www.mail-archive.com/qemu-devel@nongnu.org/msg572637.html
> 
> Jean-Philippe Brucker (7):
>   dt-bindings: virtio-mmio: Add IOMMU description
>   dt-bindings: virtio: Add virtio-pci-iommu node
>   of: Allow the iommu-map property to omit untranslated devices
>   PCI: OF: Initialize dev->fwnode appropriately
>   iommu: Add virtio-iommu driver
>   iommu/virtio: Add probe request
>   iommu/virtio: Add event queue
> 
>  .../devicetree/bindings/virtio/iommu.txt  |   66 +
>  .../devicetree/bindings/virtio/mmio.txt   |   30 +
>  MAINTAINERS   |7 +
>  drivers/iommu/Kconfig |   11 +
>  drivers/iommu/Makefile|1 +
>  drivers/iommu/virtio-iommu.c  | 1160 +
>  drivers/of/base.c |   10 +-
>  drivers/pci/of.c  |7 +
>  include/uapi/linux/virtio_ids.h   |1 +
>  include/uapi/linux/virtio_iommu.h |  161 +++
>  10 files changed, 1451 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/virtio/iommu.txt
>  create mode 100644 drivers/iommu/virtio-iommu.c
>  create mode 100644 include/uapi/linux/virtio_iommu.h
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 00/21] IOMMU: Tegra GART driver clean up and optimization

2018-11-16 Thread Dmitry Osipenko
On 01.10.2018 1:48, Dmitry Osipenko wrote:
> Hello,
> 
> This patch-series integrates the GART (IOMMU) driver with the Memory
> Controller driver, that allows to report the name of a faulty memory
> client on GART page fault. A major code clean up and performance
> optimization is performed in this series as well.
> 
> Changelog:
> 
> v5: Addressed review comments from Thierry Reding to v4. Added WARN_ON() to
> make sure that active domain isn't getting released, kept include headers
> where necessary, etc.. All changes are quite minor.
> 
> Added new patch "memory: tegra: Use relaxed versions of readl/writel".
> 
> v4: In the v3 Rob Herring requested to make device-tree binding changes
> backwards-compatible with the older kernels, that is achieved by
> changing the 'compatible' value of the DT node.
> 
> The code-refactoring patches got some more (minor) polish.
> 
> Added new patch "memory: tegra: Use of_device_get_match_data()".
> 
> v3: Memory Controller integration part has been reworked and now GART's
> device-tree binding is changed. Adding Rob Herring for the device-tree
> changes reviewing.
> 
> GART now disallows more than one active domain at a time.
> 
> Fixed "spinlock recursion", "NULL pointer dereference" and "detaching
> of all devices from inactive domains".
> 
> New code-refactoring patches.
> 
> The previously standalone patch "memory: tegra: Don't invoke Tegra30+
> specific memory timing setup on Tegra20" is now included into this
> series because there is a dependency on that patch and it wasn't applied
> yet.
> 
> v2: Addressed review comments from Robin Murphy to v1 by moving devices
> iommu_fwspec check to gart_iommu_add_device().
> 
> Dropped the "Provide single domain and group for all devices" patch from
> the series for now because after some more considering it became not
> exactly apparent whether that is what we need, that was also suggested
> by Robin Murphy in the review comment. Maybe something like a runtime
> IOMMU usage for devices would be a better solution, allowing to implement
> transparent context switching of virtual IOMMU domains.
> 
> Some very minor code cleanups, reworded commit messages.
> 
> Dmitry Osipenko (21):
>   iommu/tegra: gart: Remove pr_fmt and clean up includes
>   iommu/tegra: gart: Clean up driver probe errors handling
>   iommu/tegra: gart: Ignore devices without IOMMU phandle in DT
>   iommu: Introduce iotlb_sync_map callback
>   iommu/tegra: gart: Optimize mapping / unmapping performance
>   dt-bindings: memory: tegra: Squash tegra20-gart into tegra20-mc
>   ARM: dts: tegra20: Update Memory Controller node to the new binding
>   memory: tegra: Don't invoke Tegra30+ specific memory timing setup on
> Tegra20
>   memory: tegra: Adapt to Tegra20 device-tree binding changes
>   memory: tegra: Read client ID on GART page fault
>   memory: tegra: Use of_device_get_match_data()
>   memory: tegra: Use relaxed versions of readl/writel
>   iommu/tegra: gart: Integrate with Memory Controller driver
>   iommu/tegra: gart: Fix spinlock recursion
>   iommu/tegra: gart: Fix NULL pointer dereference
>   iommu/tegra: gart: Allow only one active domain at a time
>   iommu/tegra: gart: Don't use managed resources
>   iommu/tegra: gart: Prepend error/debug messages with "gart:"
>   iommu/tegra: gart: Don't detach devices from inactive domains
>   iommu/tegra: gart: Simplify clients-tracking code
>   iommu/tegra: gart: Perform code refactoring
> 
>  .../bindings/iommu/nvidia,tegra20-gart.txt|  14 -
>  .../memory-controllers/nvidia,tegra20-mc.txt  |  27 +-
>  arch/arm/boot/dts/tegra20.dtsi|  15 +-
>  drivers/iommu/Kconfig |   1 +
>  drivers/iommu/iommu.c |   8 +-
>  drivers/iommu/tegra-gart.c| 489 +++---
>  drivers/memory/tegra/mc.c |  93 +++-
>  drivers/memory/tegra/mc.h |  10 +-
>  include/linux/iommu.h |   1 +
>  include/soc/tegra/mc.h|  29 +-
>  10 files changed, 306 insertions(+), 381 deletions(-)
>  delete mode 100644 
> Documentation/devicetree/bindings/iommu/nvidia,tegra20-gart.txt
> 

Hello Thierry,

This patchset should be in a good shape, could you please take a look at the 
(minor) changes done in v5 and give r-b/ack to the remaining patches? Will be 
very nice if this series could finally land, especially in the light of 
upcoming DRM/HOST1x (re-)work.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[RESEND PATCH v17 5/5] iommu/arm-smmu: Add support for qcom, smmu-v2 variant

2018-11-16 Thread Vivek Gautam
qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
clock and power requirements.
On msm8996, multiple cores, viz. mdss, video, etc. use this
smmu. On sdm845, this smmu is used with gpu.
Add bindings for the same.

Signed-off-by: Vivek Gautam 
Reviewed-by: Rob Herring 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
---
 drivers/iommu/arm-smmu.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 2098c3141f5f..d315ca637097 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -120,6 +120,7 @@ enum arm_smmu_implementation {
GENERIC_SMMU,
ARM_MMU500,
CAVIUM_SMMUV2,
+   QCOM_SMMUV2,
 };
 
 struct arm_smmu_s2cr {
@@ -2026,6 +2027,17 @@ ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, 
GENERIC_SMMU);
 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 = _generic_v1 },
{ .compatible = "arm,smmu-v2", .data = _generic_v2 },
@@ -2033,6 +2045,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,mmu-401", .data = _mmu401 },
{ .compatible = "arm,mmu-500", .data = _mmu500 },
{ .compatible = "cavium,smmu-v2", .data = _smmuv2 },
+   { .compatible = "qcom,smmu-v2", .data = _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@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[RESEND PATCH v17 1/5] iommu/arm-smmu: Add pm_runtime/sleep ops

2018-11-16 Thread Vivek Gautam
From: Sricharan R 

The smmu needs to be functional only when the respective
master's using it are active. The device_link feature
helps to track such functional dependencies, so that the
iommu gets powered when the master device enables itself
using pm_runtime. So by adapting the smmu driver for
runtime pm, above said dependency can be addressed.

This patch adds the pm runtime/sleep callbacks to the
driver and also the functions to parse the smmu clocks
from DT and enable them in resume/suspend.

Also, while we enable the runtime pm add a pm sleep suspend
callback that pushes devices to low power state by turning
the clocks off in a system sleep.
Also add corresponding clock enable path in resume callback.

Signed-off-by: Sricharan R 
Signed-off-by: Archit Taneja 
[vivek: rework for clock and pm ops]
Signed-off-by: Vivek Gautam 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
---
 drivers/iommu/arm-smmu.c | 77 ++--
 1 file changed, 74 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 5a28ae892504..f7ab7ce87a94 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -48,6 +48,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -206,6 +207,8 @@ struct arm_smmu_device {
u32 num_global_irqs;
u32 num_context_irqs;
unsigned int*irqs;
+   struct clk_bulk_data*clks;
+   int num_clks;
 
u32 cavium_id_base; /* Specific to Cavium */
 
@@ -1944,10 +1947,12 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
 struct arm_smmu_match_data {
enum arm_smmu_arch_version version;
enum arm_smmu_implementation model;
+   const char * const *clks;
+   int num_clks;
 };
 
 #define ARM_SMMU_MATCH_DATA(name, ver, imp)\
-static struct arm_smmu_match_data name = { .version = ver, .model = imp }
+static const struct arm_smmu_match_data name = { .version = ver, .model = imp }
 
 ARM_SMMU_MATCH_DATA(smmu_generic_v1, ARM_SMMU_V1, GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, GENERIC_SMMU);
@@ -1966,6 +1971,23 @@ static const struct of_device_id arm_smmu_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
 
+static void arm_smmu_fill_clk_data(struct arm_smmu_device *smmu,
+  const char * const *clks)
+{
+   int i;
+
+   if (smmu->num_clks < 1)
+   return;
+
+   smmu->clks = devm_kcalloc(smmu->dev, smmu->num_clks,
+ sizeof(*smmu->clks), GFP_KERNEL);
+   if (!smmu->clks)
+   return;
+
+   for (i = 0; i < smmu->num_clks; i++)
+   smmu->clks[i].id = clks[i];
+}
+
 #ifdef CONFIG_ACPI
 static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
 {
@@ -2048,6 +2070,9 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev,
data = of_device_get_match_data(dev);
smmu->version = data->version;
smmu->model = data->model;
+   smmu->num_clks = data->num_clks;
+
+   arm_smmu_fill_clk_data(smmu, data->clks);
 
parse_driver_options(smmu);
 
@@ -2150,6 +2175,14 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
smmu->irqs[i] = irq;
}
 
+   err = devm_clk_bulk_get(smmu->dev, smmu->num_clks, smmu->clks);
+   if (err)
+   return err;
+
+   err = clk_bulk_prepare_enable(smmu->num_clks, smmu->clks);
+   if (err)
+   return err;
+
err = arm_smmu_device_cfg_probe(smmu);
if (err)
return err;
@@ -2236,6 +2269,9 @@ static int arm_smmu_device_remove(struct platform_device 
*pdev)
 
/* Turn the thing off */
writel(sCR0_CLIENTPD, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
+
+   clk_bulk_disable_unprepare(smmu->num_clks, smmu->clks);
+
return 0;
 }
 
@@ -2244,15 +2280,50 @@ static void arm_smmu_device_shutdown(struct 
platform_device *pdev)
arm_smmu_device_remove(pdev);
 }
 
-static int __maybe_unused arm_smmu_pm_resume(struct device *dev)
+static int __maybe_unused arm_smmu_runtime_resume(struct device *dev)
 {
struct arm_smmu_device *smmu = dev_get_drvdata(dev);
+   int ret;
+
+   ret = clk_bulk_enable(smmu->num_clks, smmu->clks);
+   if (ret)
+   return ret;
 
arm_smmu_device_reset(smmu);
+
return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(arm_smmu_pm_ops, NULL, arm_smmu_pm_resume);
+static int __maybe_unused arm_smmu_runtime_suspend(struct device *dev)
+{
+   struct arm_smmu_device *smmu = dev_get_drvdata(dev);
+
+   clk_bulk_disable(smmu->num_clks, smmu->clks);
+
+   return 0;
+}
+
+static int __maybe_unused arm_smmu_pm_resume(struct device *dev)
+{
+   

[RESEND PATCH v17 2/5] iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device

2018-11-16 Thread Vivek Gautam
From: Sricharan R 

The smmu device probe/remove and add/remove master device callbacks
gets called when the smmu is not linked to its master, that is without
the context of the master device. So calling runtime apis in those places
separately.
Global locks are also initialized before enabling runtime pm as the
runtime_resume() calls device_reset() which does tlb_sync_global()
that ultimately requires locks to be initialized.

Signed-off-by: Sricharan R 
[vivek: Cleanup pm runtime calls]
Signed-off-by: Vivek Gautam 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
---
 drivers/iommu/arm-smmu.c | 101 ++-
 1 file changed, 91 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index f7ab7ce87a94..cae88c9f83ca 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -270,6 +270,20 @@ static struct arm_smmu_option_prop arm_smmu_options[] = {
{ 0, NULL},
 };
 
+static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu)
+{
+   if (pm_runtime_enabled(smmu->dev))
+   return pm_runtime_get_sync(smmu->dev);
+
+   return 0;
+}
+
+static inline void arm_smmu_rpm_put(struct arm_smmu_device *smmu)
+{
+   if (pm_runtime_enabled(smmu->dev))
+   pm_runtime_put(smmu->dev);
+}
+
 static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
 {
return container_of(dom, struct arm_smmu_domain, domain);
@@ -929,11 +943,15 @@ static void arm_smmu_destroy_domain_context(struct 
iommu_domain *domain)
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_device *smmu = smmu_domain->smmu;
struct arm_smmu_cfg *cfg = _domain->cfg;
-   int irq;
+   int ret, irq;
 
if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY)
return;
 
+   ret = arm_smmu_rpm_get(smmu);
+   if (ret < 0)
+   return;
+
/*
 * Disable the context bank and free the page tables before freeing
 * it.
@@ -948,6 +966,8 @@ static void arm_smmu_destroy_domain_context(struct 
iommu_domain *domain)
 
free_io_pgtable_ops(smmu_domain->pgtbl_ops);
__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
+
+   arm_smmu_rpm_put(smmu);
 }
 
 static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
@@ -1229,10 +1249,15 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
return -ENODEV;
 
smmu = fwspec_smmu(fwspec);
+
+   ret = arm_smmu_rpm_get(smmu);
+   if (ret < 0)
+   return ret;
+
/* Ensure that the domain is finalised */
ret = arm_smmu_init_domain_context(domain, smmu);
if (ret < 0)
-   return ret;
+   goto rpm_put;
 
/*
 * Sanity check the domain. We don't support domains across
@@ -1242,49 +1267,74 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
dev_err(dev,
"cannot attach to SMMU %s whilst already attached to 
domain on SMMU %s\n",
dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
-   return -EINVAL;
+   ret = -EINVAL;
+   goto rpm_put;
}
 
/* Looks ok, so add the device to the domain */
-   return arm_smmu_domain_add_master(smmu_domain, fwspec);
+   ret = arm_smmu_domain_add_master(smmu_domain, fwspec);
+
+rpm_put:
+   arm_smmu_rpm_put(smmu);
+   return ret;
 }
 
 static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t size, int prot)
 {
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
+   struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
+   int ret;
 
if (!ops)
return -ENODEV;
 
-   return ops->map(ops, iova, paddr, size, prot);
+   arm_smmu_rpm_get(smmu);
+   ret = ops->map(ops, iova, paddr, size, prot);
+   arm_smmu_rpm_put(smmu);
+
+   return ret;
 }
 
 static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 size_t size)
 {
struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
+   struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
+   size_t ret;
 
if (!ops)
return 0;
 
-   return ops->unmap(ops, iova, size);
+   arm_smmu_rpm_get(smmu);
+   ret = ops->unmap(ops, iova, size);
+   arm_smmu_rpm_put(smmu);
+
+   return ret;
 }
 
 static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
 {
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+   struct arm_smmu_device *smmu = smmu_domain->smmu;
 
-   if (smmu_domain->tlb_ops)
+   if (smmu_domain->tlb_ops) {
+   arm_smmu_rpm_get(smmu);

[RESEND PATCH v17 3/5] iommu/arm-smmu: Add the device_link between masters and smmu

2018-11-16 Thread Vivek Gautam
From: Sricharan R 

Finally add the device link between the master device and
smmu, so that the smmu gets runtime enabled/disabled only when the
master needs it. This is done from add_device callback which gets
called once when the master is added to the smmu.

Signed-off-by: Sricharan R 
Signed-off-by: Vivek Gautam 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
---
 drivers/iommu/arm-smmu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index cae88c9f83ca..2098c3141f5f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1493,6 +1493,9 @@ static int arm_smmu_add_device(struct device *dev)
 
iommu_device_link(>iommu, dev);
 
+   device_link_add(dev, smmu->dev,
+   DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_SUPPLIER);
+
return 0;
 
 out_cfg_free:
-- 
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


[RESEND PATCH v17 4/5] dt-bindings: arm-smmu: Add bindings for qcom, smmu-v2

2018-11-16 Thread Vivek Gautam
Add bindings doc for Qcom's smmu-v2 implementation.

Signed-off-by: Vivek Gautam 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Rob Herring 
Reviewed-by: Robin Murphy 
---
 .../devicetree/bindings/iommu/arm,smmu.txt | 39 ++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 8a6ffce12af5..a6504b37cc21 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -17,10 +17,16 @@ 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.
 
+  Qcom SoCs must contain, as below, SoC-specific compatibles
+  along with "qcom,smmu-v2":
+  "qcom,msm8996-smmu-v2", "qcom,smmu-v2",
+  "qcom,sdm845-smmu-v2", "qcom,smmu-v2".
+
 - reg   : Base address and size of the SMMU.
 
 - #global-interrupts : The number of global interrupts exposed by the
@@ -71,6 +77,22 @@ conditions.
   or using stream matching with #iommu-cells = <2>, and
   may be ignored if present in such cases.
 
+- clock-names:List of the names of clocks input to the device. The
+  required list depends on particular implementation and
+  is as follows:
+  - for "qcom,smmu-v2":
+- "bus": clock required for downstream bus access and
+ for the smmu ptw,
+- "iface": clock required to access smmu's registers
+   through the TCU's programming interface.
+  - unspecified for other implementations.
+
+- clocks: Specifiers for all clocks listed in the clock-names property,
+  as per generic clock bindings.
+
+- power-domains:  Specifiers for power domains required to be powered on for
+  the SMMU to operate, as per generic power domain bindings.
+
 ** Deprecated properties:
 
 - mmu-masters (deprecated in favour of the generic "iommus" binding) :
@@ -137,3 +159,20 @@ conditions.
 iommu-map = <0  0 0x400>;
 ...
 };
+
+   /* Qcom's arm,smmu-v2 implementation */
+   smmu4: iommu@d0 {
+   compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
+   reg = <0xd0 0x1>;
+
+   #global-interrupts = <1>;
+   interrupts = ,
+,
+;
+   #iommu-cells = <1>;
+   power-domains = < MDSS_GDSC>;
+
+   clocks = < SMMU_MDP_AXI_CLK>,
+< SMMU_MDP_AHB_CLK>;
+   clock-names = "bus", "iface";
+   };
-- 
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


[RESEND PATCH v17 0/5] iommu/arm-smmu: Add runtime pm/sleep support

2018-11-16 Thread Vivek Gautam
Hi Will,
I am resending this series after we concluded on comments [1,2] on v16 of
this patch-series, and the subsequent patch [3] was posted.
Kindly merge this series.

Thanks
Vivek

Previous version of this patch series is @ [4].
Also refer to [4] for change logs for previous versions.

[1] https://lore.kernel.org/patchwork/patch/979430/
[2] https://lore.kernel.org/patchwork/patch/979433/
[3] https://lore.kernel.org/patchwork/patch/994194/
[4] https://lore.kernel.org/patchwork/cover/979429/

Sricharan R (3):
  iommu/arm-smmu: Add pm_runtime/sleep ops
  iommu/arm-smmu: Invoke pm_runtime during probe, add/remove device
  iommu/arm-smmu: Add the device_link between masters and smmu

Vivek Gautam (2):
  dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2
  iommu/arm-smmu: Add support for qcom,smmu-v2 variant

 .../devicetree/bindings/iommu/arm,smmu.txt |  39 +
 drivers/iommu/arm-smmu.c   | 192 +++--
 2 files changed, 219 insertions(+), 12 deletions(-)

-- 
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 1/4] PCI / ACPI: Identify external PCI devices

2018-11-16 Thread Lorenzo Pieralisi
On Thu, Nov 15, 2018 at 07:33:54PM +, mario.limoncie...@dell.com wrote:
> 
> 
> > -Original Message-
> > From: Mika Westerberg 
> > Sent: Thursday, November 15, 2018 1:01 PM
> > To: Lorenzo Pieralisi
> > Cc: Lukas Wunner; iommu@lists.linux-foundation.org; Joerg Roedel; David
> > Woodhouse; Lu Baolu; Ashok Raj; Bjorn Helgaas; Rafael J. Wysocki; Jacob jun 
> > Pan;
> > Andreas Noever; Michael Jamet; Yehezkel Bernat; Christian Kellner; 
> > Limonciello,
> > Mario; Anthony Wong; linux-a...@vger.kernel.org; linux-...@vger.kernel.org; 
> > linux-
> > ker...@vger.kernel.org
> > Subject: Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices
> > 
> > 
> > [EXTERNAL EMAIL]
> > 
> > On Thu, Nov 15, 2018 at 05:46:08PM +, Lorenzo Pieralisi wrote:
> > > Do you really need to parse it if the dev->is_thunderbolt check is enough 
> > > ?
> > 
> > Yes, we need to parse it one way or another. dev->is_thunderbolt is
> > based on heuristics which do not apply anymore when the thing gets
> > integrated in the SoC.
> > 
> > The _DSD is there already (on existing systems) and is being used by
> > Windows so I don't understand why we cannot take advantage of it? Every
> > new system with Thunderbolt ports will have it.

We have different opinions on this, there is no point in me reiterating
it over and over, I am against the approach taken to solve this problem
first in defining the bindings outside the ACPI specifications and
second by acquiescing to what has been done so that it will be done
over and over again.

I will raise the point in the appropriate forum, it is up to Bjorn
and Rafael to decide on this patch.

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


Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices

2018-11-16 Thread Mika Westerberg
On Fri, Nov 16, 2018 at 01:18:04AM -0800, Christoph Hellwig wrote:
> On Thu, Nov 15, 2018 at 09:10:26PM +0200, Mika Westerberg wrote:
> > FireWire is kind of different but there are connectors such as
> > ExpressCard and NVMe (over U.2 connector) which carry PCIe and are
> > relatively easy to access without need for a screwdriver. AFAIK some
> > eGPUs are also using some other proprietary (non-TBT) connector that
> > carries PCIe.
> 
> U.2 is a data center internal form factor with hot plug capability. If
> you enable an iommu for that by default you will make a lot of people
> very unhappy.

Well, it needs the other bit in ACPI DMAR table to be enabled by default
so I don't think anyone in data center domain will notice ;-)

> More importantly NVMe is now used for the current/next generation
> Compact Flash and SD cards, which contain full PCIe gen 3 links.

OK, thanks for the information - I did not know that. I guess those
belong to the "external" category as well.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices

2018-11-16 Thread Christoph Hellwig
On Thu, Nov 15, 2018 at 09:10:26PM +0200, Mika Westerberg wrote:
> FireWire is kind of different but there are connectors such as
> ExpressCard and NVMe (over U.2 connector) which carry PCIe and are
> relatively easy to access without need for a screwdriver. AFAIK some
> eGPUs are also using some other proprietary (non-TBT) connector that
> carries PCIe.

U.2 is a data center internal form factor with hot plug capability. If
you enable an iommu for that by default you will make a lot of people
very unhappy.

More importantly NVMe is now used for the current/next generation
Compact Flash and SD cards, which contain full PCIe gen 3 links.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 6/8] vfio/mdev: Add iommu place holders in mdev_device

2018-11-16 Thread Christoph Hellwig
On Fri, Nov 16, 2018 at 09:20:48AM +0800, Lu Baolu wrote:
> > Please keep symbols mdev_set/get_iommu_device(dev, iommu_device) non-GPL
> > same as other exported symbols from mdev_core module.
> 
> Yes. It will be fixed in the next version.

No.  mdev shall not be used to circumvent the exports in the generic
vfio code.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 6/7] iommu/virtio: Add probe request

2018-11-16 Thread Auger Eric
Hi Jean,

On 11/15/18 5:52 PM, Jean-Philippe Brucker wrote:
> When the device offers the probe feature, send a probe request for each
> device managed by the IOMMU. Extract RESV_MEM information. When we
> encounter a MSI doorbell region, set it up as a IOMMU_RESV_MSI region.
> This will tell other subsystems that there is no need to map the MSI
> doorbell in the virtio-iommu, because MSIs bypass it.
> 
> Signed-off-by: Jean-Philippe Brucker 
Reviewed-by: Eric Auger 

Thanks

Eric
> ---
>  drivers/iommu/virtio-iommu.c  | 156 --
>  include/uapi/linux/virtio_iommu.h |  38 
>  2 files changed, 188 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> index 2a9cb6285a1e..c547ebd79c43 100644
> --- a/drivers/iommu/virtio-iommu.c
> +++ b/drivers/iommu/virtio-iommu.c
> @@ -46,6 +46,7 @@ struct viommu_dev {
>   struct iommu_domain_geometrygeometry;
>   u64 pgsize_bitmap;
>   u8  domain_bits;
> + u32 probe_size;
>  };
>  
>  struct viommu_mapping {
> @@ -67,8 +68,10 @@ struct viommu_domain {
>  };
>  
>  struct viommu_endpoint {
> + struct device   *dev;
>   struct viommu_dev   *viommu;
>   struct viommu_domain*vdomain;
> + struct list_headresv_regions;
>  };
>  
>  struct viommu_request {
> @@ -119,6 +122,9 @@ static off_t viommu_get_req_offset(struct viommu_dev 
> *viommu,
>  {
>   size_t tail_size = sizeof(struct virtio_iommu_req_tail);
>  
> + if (req->type == VIRTIO_IOMMU_T_PROBE)
> + return len - viommu->probe_size - tail_size;
> +
>   return len - tail_size;
>  }
>  
> @@ -394,6 +400,110 @@ static int viommu_replay_mappings(struct viommu_domain 
> *vdomain)
>   return ret;
>  }
>  
> +static int viommu_add_resv_mem(struct viommu_endpoint *vdev,
> +struct virtio_iommu_probe_resv_mem *mem,
> +size_t len)
> +{
> + size_t size;
> + u64 start64, end64;
> + phys_addr_t start, end;
> + struct iommu_resv_region *region = NULL;
> + unsigned long prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
> +
> + start = start64 = le64_to_cpu(mem->start);
> + end = end64 = le64_to_cpu(mem->end);
> + size = end64 - start64 + 1;
> +
> + /* Catch any overflow, including the unlikely end64 - start64 + 1 = 0 */
> + if (start != start64 || end != end64 || size < end64 - start64)
> + return -EOVERFLOW;
> +
> + if (len < sizeof(*mem))
> + return -EINVAL;
> +
> + switch (mem->subtype) {
> + default:
> + dev_warn(vdev->dev, "unknown resv mem subtype 0x%x\n",
> +  mem->subtype);
> + /* Fall-through */
> + case VIRTIO_IOMMU_RESV_MEM_T_RESERVED:
> + region = iommu_alloc_resv_region(start, size, 0,
> +  IOMMU_RESV_RESERVED);
> + break;
> + case VIRTIO_IOMMU_RESV_MEM_T_MSI:
> + region = iommu_alloc_resv_region(start, size, prot,
> +  IOMMU_RESV_MSI);
> + break;
> + }
> + if (!region)
> + return -ENOMEM;
> +
> + list_add(>resv_regions, >list);
> + return 0;
> +}
> +
> +static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device 
> *dev)
> +{
> + int ret;
> + u16 type, len;
> + size_t cur = 0;
> + size_t probe_len;
> + struct virtio_iommu_req_probe *probe;
> + struct virtio_iommu_probe_property *prop;
> + struct iommu_fwspec *fwspec = dev->iommu_fwspec;
> + struct viommu_endpoint *vdev = fwspec->iommu_priv;
> +
> + if (!fwspec->num_ids)
> + return -EINVAL;
> +
> + probe_len = sizeof(*probe) + viommu->probe_size +
> + sizeof(struct virtio_iommu_req_tail);
> + probe = kzalloc(probe_len, GFP_KERNEL);
> + if (!probe)
> + return -ENOMEM;
> +
> + probe->head.type = VIRTIO_IOMMU_T_PROBE;
> + /*
> +  * For now, assume that properties of an endpoint that outputs multiple
> +  * IDs are consistent. Only probe the first one.
> +  */
> + probe->endpoint = cpu_to_le32(fwspec->ids[0]);
> +
> + ret = viommu_send_req_sync(viommu, probe, probe_len);
> + if (ret)
> + goto out_free;
> +
> + prop = (void *)probe->properties;
> + type = le16_to_cpu(prop->type) & VIRTIO_IOMMU_PROBE_T_MASK;
> +
> + while (type != VIRTIO_IOMMU_PROBE_T_NONE &&
> +cur < viommu->probe_size) {
> + len = le16_to_cpu(prop->length) + sizeof(*prop);
> +
> + switch (type) {
> + case VIRTIO_IOMMU_PROBE_T_RESV_MEM:
> + ret = viommu_add_resv_mem(vdev, (void *)prop, len);
> + break;
> + default:
> +  

Re: [PATCH 1/9] mm: Introduce new vm_insert_range API

2018-11-16 Thread Souptick Joarder
On Fri, Nov 16, 2018 at 12:11 PM Matthew Wilcox  wrote:
>
> On Fri, Nov 16, 2018 at 11:00:30AM +0530, Souptick Joarder wrote:
> > On Thu, Nov 15, 2018 at 11:44 PM Randy Dunlap  wrote:
> > > On 11/15/18 7:45 AM, Souptick Joarder wrote:
> > > What is the opposite of vm_insert_range() or even of vm_insert_page()?
> > > or is there no need for that?
> >
> > There is no opposite function of vm_insert_range() / vm_insert_page().
> > My understanding is, in case of any error, mmap handlers will return the
> > err to user process and user space will decide the next action. So next
> > time when mmap handler is getting invoked it will map from the beginning.
> > Correct me if I am wrong.
>
> The opposite function, I suppose, is unmap_region().
>
> > > s/no./number/
> >
> > I didn't get it ??
>
> This is a 'sed' expression.  's' is the 'substitute' command; the /
> is a separator, 'no.' is what you wrote, and 'number' is what Randy
> is recommending instead.

Ok. Will change it in v2.
>
> > > > + for (i = 0; i < page_count; i++) {
> > > > + ret = vm_insert_page(vma, uaddr, pages[i]);
> > > > + if (ret < 0)
> > > > + return ret;
> > >
> > > For a non-trivial value of page_count:
> > > Is it a problem if vm_insert_page() succeeds for several pages
> > > and then fails?
> >
> > No, it will be considered as total failure and mmap handler will return
> > the err to user space.
>
> I think what Randy means is "What happens to the inserted pages?" and
> the answer is that mmap_region() jumps to the 'unmap_and_free_vma'
> label, which is an accurate name.

Sorry for incorrect understanding of the question.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu