RE: [PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-05-21 Thread Makarand Pawagi
Hi Lorenzo,

> -Original Message-
> From: Laurentiu Tudor 
> Sent: Thursday, May 21, 2020 8:33 PM
> To: Lorenzo Pieralisi ; linux-arm-
> ker...@lists.infradead.org
> Cc: Diana Madalina Craciun (OSS) ; Makarand
> Pawagi ; iommu@lists.linux-foundation.org;
> linux-a...@vger.kernel.org; devicet...@vger.kernel.org; linux-
> p...@vger.kernel.org; Rob Herring ; Rafael J. Wysocki
> ; Joerg Roedel ; Hanjun Guo
> ; Bjorn Helgaas ; Sudeep
> Holla ; Robin Murphy ;
> Catalin Marinas ; Will Deacon ;
> Marc Zyngier 
> Subject: Re: [PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc
> 
> Hi Lorenzo,
> 
> On 5/21/2020 4:00 PM, Lorenzo Pieralisi wrote:
> > From: Diana Craciun 
> >
> > Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table to
> > extract memory and other resources.
> >
> > Interrupt (GIC ITS) information is extracted from the MADT table by
> > drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.
> >
> > IORT table is parsed to configure DMA.
> >
> > Signed-off-by: Makarand Pawagi 
> > Signed-off-by: Diana Craciun 
> > Signed-off-by: Laurentiu Tudor 
> > ---
> 
> The author of this patch should be Makarand. I think I accidentaly broke it 
> when
> we exchanged the patches. Very sorry about it.
> 
 
Will you be able to correct this or should I post another patch?

> ---
> Best Regards, Laurentiu
> 
> 
> >  drivers/bus/fsl-mc/fsl-mc-bus.c | 73 +++-
> >  drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +-
> >  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 75
> > -
> >  3 files changed, 150 insertions(+), 35 deletions(-)
> >
> > diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c
> > b/drivers/bus/fsl-mc/fsl-mc-bus.c index 824ff77bbe86..324d49d6df89
> > 100644
> > --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> > +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> > @@ -18,6 +18,8 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> > +#include 
> >
> >  #include "fsl-mc-private.h"
> >
> > @@ -38,6 +40,7 @@ struct fsl_mc {
> > struct fsl_mc_device *root_mc_bus_dev;
> > u8 num_translation_ranges;
> > struct fsl_mc_addr_translation_range *translation_ranges;
> > +   void *fsl_mc_regs;
> >  };
> >
> >  /**
> > @@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
> > phys_addr_t start_phys_addr;
> >  };
> >
> > +#define FSL_MC_FAPR0x28
> > +#define MC_FAPR_PL BIT(18)
> > +#define MC_FAPR_BMTBIT(17)
> > +
> >  /**
> >   * fsl_mc_bus_match - device to driver matching callback
> >   * @dev: the fsl-mc device to match against @@ -124,7 +131,10 @@
> > static int fsl_mc_dma_configure(struct device *dev)
> > while (dev_is_fsl_mc(dma_dev))
> > dma_dev = dma_dev->parent;
> >
> > -   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> > +   if (dev_of_node(dma_dev))
> > +   return of_dma_configure_id(dev, dma_dev->of_node, 0,
> _id);
> > +
> > +   return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, _id);
> >  }
> >
> >  static ssize_t modalias_show(struct device *dev, struct
> > device_attribute *attr, @@ -865,8 +875,11 @@ static int
> fsl_mc_bus_probe(struct platform_device *pdev)
> > struct fsl_mc_io *mc_io = NULL;
> > int container_id;
> > phys_addr_t mc_portal_phys_addr;
> > -   u32 mc_portal_size;
> > -   struct resource res;
> > +   u32 mc_portal_size, mc_stream_id;
> > +   struct resource *plat_res;
> > +
> > +   if (!iommu_present(_mc_bus_type))
> > +   return -EPROBE_DEFER;
> >
> > mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
> > if (!mc)
> > @@ -874,19 +887,33 @@ static int fsl_mc_bus_probe(struct
> > platform_device *pdev)
> >
> > platform_set_drvdata(pdev, mc);
> >
> > +   plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +   mc->fsl_mc_regs = devm_ioremap_resource(>dev, plat_res);
> > +   if (IS_ERR(mc->fsl_mc_regs))
> > +   return PTR_ERR(mc->fsl_mc_regs);
> > +
> > +   if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(>dev)) {
> > +   mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
> > +   /*
> > +* HW ORs the PL and BMT bit, places the result in bit 15 of
> > +* the StreamID and ORs in the ICID. Calculate it accordingly.
> > +*/
> > +   mc_stream_id = (mc_stream_id & 0x) |
> > +   ((mc_stream_id & (MC_FAPR_PL |
> MC_FAPR_BMT)) ?
> > +   0x4000 : 0);
> > +   error = acpi_dma_configure_id(>dev,
> DEV_DMA_COHERENT,
> > + _stream_id);
> > +   if (error)
> > +   dev_warn(>dev, "failed to configure
> dma: %d.\n",
> > +error);
> > +   }
> > +
> > /*
> >  * Get physical address of MC portal for the root DPRC:
> >  */
> > -   error = of_address_to_resource(pdev->dev.of_node, 0, );
> > -   if (error < 0) {
> > -   dev_err(>dev,
> > -   "of_address_to_resource() failed for %pOF\n",
> > -   

Re: [PATCH 0/2] Let pci_fixup_final access iommu_fwnode

2020-05-21 Thread Zhangfei Gao

Hi, Joerg

On 2020/5/12 下午12:08, Zhangfei Gao wrote:

Some platform devices appear as PCI but are
actually on the AMBA bus, and they need fixup in
drivers/pci/quirks.c handling iommu_fwnode.
So calling pci_fixup_final after iommu_fwnode is allocated.

For example:
Hisilicon platform device need fixup in
drivers/pci/quirks.c

+static void quirk_huawei_pcie_sva(struct pci_dev *pdev)
+{
+   struct iommu_fwspec *fwspec;
+
+   pdev->eetlp_prefix_path = 1;
+   fwspec = dev_iommu_fwspec_get(>dev);
+   if (fwspec)
+   fwspec->can_stall = 1;
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_HUAWEI, 0xa250, quirk_huawei_pcie_sva);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_HUAWEI, 0xa251, quirk_huawei_pcie_sva);
  


Zhangfei Gao (2):
   iommu/of: Let pci_fixup_final access iommu_fwnode
   ACPI/IORT: Let pci_fixup_final access iommu_fwnode

  drivers/acpi/arm64/iort.c | 1 +
  drivers/iommu/of_iommu.c  | 1 +
  2 files changed, 2 insertions(+)


Would you mind give any suggestion?

We need access fwspec->can_stall describing the platform device (a fake 
pcie) can support stall feature.

can_stall will be used arm_smmu_add_device [1].
And stall is not a pci feature, so no such member in struct pci_dev.

iommu_fwnode is allocated in iommu_fwspec_init, from of_pci_iommu_init 
or iort_pci_iommu_init.
The pci_fixup_device(pci_fixup_final, dev) in pci_bus_add_device is too 
early that  iommu_fwnode

is not allocated.
The pci_fixup_device(pci_fixup_enable, dev) in do_pci_enable_device is 
too late after


arm_smmu_add_device.


So the idea here is calling pci_fixup_device(pci_fixup_final) after
of_pci_iommu_init and iort_pci_iommu_init, where iommu_fwnode is allocated.



[1] https://www.spinics.net/lists/linux-pci/msg94559.html

Thanks

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

Re: [PATCH -next] iommu/vt-d: fix a GCC warning

2020-05-21 Thread Lu Baolu

Hi Qian,

Thanks!

On 5/22/20 5:50 AM, Qian Cai wrote:

The commit 6ee1b77ba3ac ("iommu/vt-d: Add svm/sva invalidate function")
introduced a GCC warning,

drivers/iommu/intel-iommu.c:5330:1: warning: 'static' is not at beginning of
declaration [-Wold-style-declaration]
  const static int
  ^

Signed-off-by: Qian Cai 


Fixes: 6ee1b77ba3ac0 ("iommu/vt-d: Add svm/sva invalidate function")
Acked-by: Lu Baolu 

Best regards,
baolu


---
  drivers/iommu/intel-iommu.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f75d7d9c231f..ff5a30a94679 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5327,7 +5327,7 @@ static void intel_iommu_aux_detach_device(struct 
iommu_domain *domain,
   * [IOMMU_CACHE_INV_TYPE_IOTLB][IOMMU_INV_GRANU_ADDR]
   */
  
-const static int

+static const int
  inv_type_granu_table[IOMMU_CACHE_INV_TYPE_NR][IOMMU_INV_GRANU_NR] = {
/*
 * PASID based IOTLB invalidation: PASID selective (per PASID),


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


[PATCH v5 1/5] iommu/arm-smmu: add NVIDIA implementation for dual ARM MMU-500 usage

2020-05-21 Thread Krishna Reddy
NVIDIA's Tegra194 soc uses two ARM MMU-500s together to interleave
IOVA accesses across them.
Add NVIDIA implementation for dual ARM MMU-500s and add new compatible
string for Tegra194 soc.

Signed-off-by: Krishna Reddy 
---
 MAINTAINERS |   2 +
 drivers/iommu/Makefile  |   2 +-
 drivers/iommu/arm-smmu-impl.c   |   3 +
 drivers/iommu/arm-smmu-nvidia.c | 161 
 drivers/iommu/arm-smmu.h|   1 +
 5 files changed, 168 insertions(+), 1 deletion(-)
 create mode 100644 drivers/iommu/arm-smmu-nvidia.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ecc0749810b0..0d8c966ecf17 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16560,9 +16560,11 @@ F: drivers/i2c/busses/i2c-tegra.c
 
 TEGRA IOMMU DRIVERS
 M: Thierry Reding 
+R: Krishna Reddy 
 L: linux-te...@vger.kernel.org
 S: Supported
 F: drivers/iommu/tegra*
+F: drivers/iommu/arm-smmu-nvidia.c
 
 TEGRA KBC DRIVER
 M: Laxman Dewangan 
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 57cf4ba5e27c..35542df00da7 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o 
amd_iommu_quirks.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm_smmu.o
-arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
+arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o arm-smmu-nvidia.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
diff --git a/drivers/iommu/arm-smmu-impl.c b/drivers/iommu/arm-smmu-impl.c
index 74d97a886e93..dcdd513323aa 100644
--- a/drivers/iommu/arm-smmu-impl.c
+++ b/drivers/iommu/arm-smmu-impl.c
@@ -158,6 +158,9 @@ struct arm_smmu_device *arm_smmu_impl_init(struct 
arm_smmu_device *smmu)
 */
switch (smmu->model) {
case ARM_MMU500:
+   if (of_device_is_compatible(smmu->dev->of_node,
+   "nvidia,tegra194-smmu-500"))
+   return nvidia_smmu_impl_init(smmu);
smmu->impl = _mmu500_impl;
break;
case CAVIUM_SMMUV2:
diff --git a/drivers/iommu/arm-smmu-nvidia.c b/drivers/iommu/arm-smmu-nvidia.c
new file mode 100644
index ..dafc293a4521
--- /dev/null
+++ b/drivers/iommu/arm-smmu-nvidia.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Nvidia ARM SMMU v2 implementation quirks
+// Copyright (C) 2019 NVIDIA CORPORATION.  All rights reserved.
+
+#define pr_fmt(fmt) "nvidia-smmu: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "arm-smmu.h"
+
+/* Tegra194 has three ARM MMU-500 Instances.
+ * Two of them are used together for Interleaved IOVA accesses and
+ * used by Non-Isochronous Hw devices for SMMU translations.
+ * Third one is used for SMMU translations from Isochronous HW devices.
+ * It is possible to use this Implementation to program either
+ * all three or two of the instances identically as desired through
+ * DT node.
+ *
+ * Programming all the three instances identically comes with redundant tlb
+ * invalidations as all three never need to be tlb invalidated for a HW device.
+ *
+ * When Linux Kernel supports multiple SMMU devices, The SMMU device used for
+ * Isochornous HW devices should be added as a separate ARM MMU-500 device
+ * in DT and be programmed independently for efficient tlb invalidates.
+ *
+ */
+#define MAX_SMMU_INSTANCES 3
+
+#define TLB_LOOP_TIMEOUT   100 /* 1s! */
+#define TLB_SPIN_COUNT 10
+
+struct nvidia_smmu {
+   struct arm_smmu_device  smmu;
+   unsigned intnum_inst;
+   void __iomem*bases[MAX_SMMU_INSTANCES];
+};
+
+#define to_nvidia_smmu(s) container_of(s, struct nvidia_smmu, smmu)
+
+#define nsmmu_page(smmu, inst, page) \
+   (((inst) ? to_nvidia_smmu(smmu)->bases[(inst)] : smmu->base) + \
+   ((page) << smmu->pgshift))
+
+static u32 nsmmu_read_reg(struct arm_smmu_device *smmu,
+ int page, int offset)
+{
+   return readl_relaxed(nsmmu_page(smmu, 0, page) + offset);
+}
+
+static void nsmmu_write_reg(struct arm_smmu_device *smmu,
+   int page, int offset, u32 val)
+{
+   unsigned int i;
+
+   for (i = 0; i < to_nvidia_smmu(smmu)->num_inst; i++)
+   writel_relaxed(val, nsmmu_page(smmu, i, page) + offset);
+}
+
+static u64 nsmmu_read_reg64(struct arm_smmu_device *smmu,
+   int page, int offset)
+{
+   return readq_relaxed(nsmmu_page(smmu, 0, page) + offset);
+}
+
+static void nsmmu_write_reg64(struct arm_smmu_device *smmu,
+ int page, int offset, u64 val)
+{
+   unsigned int i;
+
+   for (i = 0; i < to_nvidia_smmu(smmu)->num_inst; i++)
+   

[PATCH v5 3/5] iommu/arm-smmu: Add global/context fault implementation hooks

2020-05-21 Thread Krishna Reddy
Add global/context fault hooks to allow NVIDIA SMMU implementation
handle faults across multiple SMMUs.

Signed-off-by: Krishna Reddy 
---
 drivers/iommu/arm-smmu-nvidia.c | 100 
 drivers/iommu/arm-smmu.c|  11 +++-
 drivers/iommu/arm-smmu.h|   3 +
 3 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/arm-smmu-nvidia.c b/drivers/iommu/arm-smmu-nvidia.c
index dafc293a4521..5999b6a77099 100644
--- a/drivers/iommu/arm-smmu-nvidia.c
+++ b/drivers/iommu/arm-smmu-nvidia.c
@@ -117,6 +117,104 @@ static int nsmmu_reset(struct arm_smmu_device *smmu)
return 0;
 }
 
+static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
+{
+   return container_of(dom, struct arm_smmu_domain, domain);
+}
+
+static irqreturn_t nsmmu_global_fault_inst(int irq,
+  struct arm_smmu_device *smmu,
+  int inst)
+{
+   u32 gfsr, gfsynr0, gfsynr1, gfsynr2;
+
+   gfsr = readl_relaxed(nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
+   gfsynr0 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
+   ARM_SMMU_GR0_sGFSYNR0);
+   gfsynr1 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
+   ARM_SMMU_GR0_sGFSYNR1);
+   gfsynr2 = readl_relaxed(nsmmu_page(smmu, inst, 0) +
+   ARM_SMMU_GR0_sGFSYNR2);
+
+   if (!gfsr)
+   return IRQ_NONE;
+
+   dev_err_ratelimited(smmu->dev,
+   "Unexpected global fault, this could be serious\n");
+   dev_err_ratelimited(smmu->dev,
+   "\tGFSR 0x%08x, GFSYNR0 0x%08x, GFSYNR1 0x%08x, GFSYNR2 
0x%08x\n",
+   gfsr, gfsynr0, gfsynr1, gfsynr2);
+
+   writel_relaxed(gfsr, nsmmu_page(smmu, inst, 0) + ARM_SMMU_GR0_sGFSR);
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t nsmmu_global_fault(int irq, void *dev)
+{
+   int inst;
+   irqreturn_t irq_ret = IRQ_NONE;
+   struct arm_smmu_device *smmu = dev;
+
+   for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
+   irq_ret = nsmmu_global_fault_inst(irq, smmu, inst);
+   if (irq_ret == IRQ_HANDLED)
+   return irq_ret;
+   }
+
+   return irq_ret;
+}
+
+static irqreturn_t nsmmu_context_fault_bank(int irq,
+   struct arm_smmu_device *smmu,
+   int idx, int inst)
+{
+   u32 fsr, fsynr, cbfrsynra;
+   unsigned long iova;
+
+   fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR);
+   if (!(fsr & ARM_SMMU_FSR_FAULT))
+   return IRQ_NONE;
+
+   fsynr = readl_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
+ ARM_SMMU_CB_FSYNR0);
+   iova = readq_relaxed(nsmmu_page(smmu, inst, smmu->numpage + idx) +
+ARM_SMMU_CB_FAR);
+   cbfrsynra = readl_relaxed(nsmmu_page(smmu, inst, 1) +
+ ARM_SMMU_GR1_CBFRSYNRA(idx));
+
+   dev_err_ratelimited(smmu->dev,
+   "Unhandled context fault: fsr=0x%x, iova=0x%08lx, fsynr=0x%x, 
cbfrsynra=0x%x, cb=%d\n",
+   fsr, iova, fsynr, cbfrsynra, idx);
+
+   writel_relaxed(fsr, nsmmu_page(smmu, inst, smmu->numpage + idx) +
+   ARM_SMMU_CB_FSR);
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t nsmmu_context_fault(int irq, void *dev)
+{
+   int inst, idx;
+   irqreturn_t irq_ret = IRQ_NONE;
+   struct iommu_domain *domain = dev;
+   struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
+   struct arm_smmu_device *smmu = smmu_domain->smmu;
+
+   for (inst = 0; inst < to_nvidia_smmu(smmu)->num_inst; inst++) {
+   /* Interrupt line shared between all context faults.
+* Check for faults across all contexts.
+*/
+   for (idx = 0; idx < smmu->num_context_banks; idx++) {
+   irq_ret = nsmmu_context_fault_bank(irq, smmu,
+  idx, inst);
+
+   if (irq_ret == IRQ_HANDLED)
+   return irq_ret;
+   }
+   }
+
+   return irq_ret;
+}
+
 static const struct arm_smmu_impl nvidia_smmu_impl = {
.read_reg = nsmmu_read_reg,
.write_reg = nsmmu_write_reg,
@@ -124,6 +222,8 @@ static const struct arm_smmu_impl nvidia_smmu_impl = {
.write_reg64 = nsmmu_write_reg64,
.reset = nsmmu_reset,
.tlb_sync = nsmmu_tlb_sync,
+   .global_fault = nsmmu_global_fault,
+   .context_fault = nsmmu_context_fault,
 };
 
 struct arm_smmu_device *nvidia_smmu_impl_init(struct arm_smmu_device *smmu)
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index e622f4e33379..975faa57b659 100644
--- a/drivers/iommu/arm-smmu.c
+++ 

[PATCH v5 5/5] arm64: tegra: enable SMMU for SDHCI and EQOS on T194

2020-05-21 Thread Krishna Reddy
Enable SMMU translations for SDHCI and EQOS transactions on T194.

Signed-off-by: Krishna Reddy 
---
 arch/arm64/boot/dts/nvidia/tegra194.dtsi | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index f7c4399afb55..706bbb439dcd 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -59,6 +59,7 @@ ethernet@249 {
clock-names = "master_bus", "slave_bus", "rx", "tx", 
"ptp_ref";
resets = < TEGRA194_RESET_EQOS>;
reset-names = "eqos";
+   iommus = < TEGRA194_SID_EQOS>;
status = "disabled";
 
snps,write-requests = <1>;
@@ -457,6 +458,7 @@ sdmmc1: sdhci@340 {
clock-names = "sdhci";
resets = < TEGRA194_RESET_SDMMC1>;
reset-names = "sdhci";
+   iommus = < TEGRA194_SID_SDMMC1>;
nvidia,pad-autocal-pull-up-offset-3v3-timeout =
<0x07>;
nvidia,pad-autocal-pull-down-offset-3v3-timeout =
@@ -479,6 +481,7 @@ sdmmc3: sdhci@344 {
clock-names = "sdhci";
resets = < TEGRA194_RESET_SDMMC3>;
reset-names = "sdhci";
+   iommus = < TEGRA194_SID_SDMMC3>;
nvidia,pad-autocal-pull-up-offset-1v8 = <0x00>;
nvidia,pad-autocal-pull-down-offset-1v8 = <0x7a>;
nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
@@ -506,6 +509,7 @@ sdmmc4: sdhci@346 {
  < TEGRA194_CLK_PLLC4>;
resets = < TEGRA194_RESET_SDMMC4>;
reset-names = "sdhci";
+   iommus = < TEGRA194_SID_SDMMC4>;
nvidia,pad-autocal-pull-up-offset-hs400 = <0x00>;
nvidia,pad-autocal-pull-down-offset-hs400 = <0x00>;
nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x0a>;
-- 
2.26.2

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


[PATCH v5 0/5] Nvidia Arm SMMUv2 Implementation

2020-05-21 Thread Krishna Reddy
Changes in v5:
Rebased on top of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git 
next

v4 - https://lkml.org/lkml/2019/10/30/1054
v3 - https://lkml.org/lkml/2019/10/18/1601
v2 - https://lkml.org/lkml/2019/9/2/980
v1 - https://lkml.org/lkml/2019/8/29/1588

Krishna Reddy (5):
  iommu/arm-smmu: add NVIDIA implementation for dual ARM MMU-500 usage
  dt-bindings: arm-smmu: Add binding for Tegra194 SMMU
  iommu/arm-smmu: Add global/context fault implementation hooks
  arm64: tegra: Add DT node for T194 SMMU
  arm64: tegra: enable SMMU for SDHCI and EQOS on T194

 .../devicetree/bindings/iommu/arm,smmu.yaml   |   5 +
 MAINTAINERS   |   2 +
 arch/arm64/boot/dts/nvidia/tegra194.dtsi  |  81 ++
 drivers/iommu/Makefile|   2 +-
 drivers/iommu/arm-smmu-impl.c |   3 +
 drivers/iommu/arm-smmu-nvidia.c   | 261 ++
 drivers/iommu/arm-smmu.c  |  11 +-
 drivers/iommu/arm-smmu.h  |   4 +
 8 files changed, 366 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iommu/arm-smmu-nvidia.c


base-commit: 365f8d504da50feaebf826d180113529c9383670
-- 
2.26.2

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


[PATCH v5 4/5] arm64: tegra: Add DT node for T194 SMMU

2020-05-21 Thread Krishna Reddy
Add DT node for T194 SMMU to enable SMMU support.

Signed-off-by: Krishna Reddy 
---
 arch/arm64/boot/dts/nvidia/tegra194.dtsi | 77 
 1 file changed, 77 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi 
b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index f4ede86e32b4..f7c4399afb55 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -1620,6 +1620,83 @@ pcie@141a {
  0x8200 0x0  0x4000 0x1f 0x4000 0x0 
0xc000>; /* non-prefetchable memory (3GB) */
};
 
+   smmu: iommu@1200 {
+   compatible = "arm,mmu-500","nvidia,tegra194-smmu-500";
+   reg = <0 0x1200 0 0x80>,
+ <0 0x1100 0 0x80>,
+ <0 0x1000 0 0x80>;
+   interrupts = ,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+,
+;
+   stream-match-mask = <0x7f80>;
+   #global-interrupts = <3>;
+   #iommu-cells = <1>;
+   };
+
pcie_ep@1416 {
compatible = "nvidia,tegra194-pcie-ep", "snps,dw-pcie-ep";
power-domains = < TEGRA194_POWER_DOMAIN_PCIEX4A>;
-- 
2.26.2

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


[PATCH v5 2/5] dt-bindings: arm-smmu: Add binding for Tegra194 SMMU

2020-05-21 Thread Krishna Reddy
Add binding for NVIDIA's Tegra194 Soc SMMU that is based
on ARM MMU-500.

Signed-off-by: Krishna Reddy 
---
 Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml 
b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
index 6515dbe47508..78aba7dd5a61 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
@@ -37,6 +37,11 @@ properties:
   - qcom,sc7180-smmu-500
   - qcom,sdm845-smmu-500
   - const: arm,mmu-500
+  - description: NVIDIA SoCs that use more than one "arm,mmu-500"
+items:
+  - enum:
+  - nvdia,tegra194-smmu-500
+  - const: arm,mmu-500
   - items:
   - const: arm,mmu-500
   - const: arm,smmu-v2
-- 
2.26.2

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


Re: [PATCH 10/12] of/irq: Make of_msi_map_rid() PCI bus agnostic

2020-05-21 Thread Rob Herring
On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
 wrote:
>
> There is nothing PCI bus specific in the of_msi_map_rid()
> implementation other than the requester ID tag for the input
> ID space. Rename requester ID to a more generic ID so that
> the translation code can be used by all busses that require
> input/output ID translations.
>
> Leave a wrapper function of_msi_map_rid() in place to keep
> existing PCI code mapping requester ID syntactically unchanged.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Rob Herring 
> Cc: Marc Zyngier 
> ---
>  drivers/of/irq.c   | 28 ++--
>  include/linux/of_irq.h | 14 --
>  2 files changed, 26 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> index 48a40326984f..25d17b8a1a1a 100644
> --- a/drivers/of/irq.c
> +++ b/drivers/of/irq.c
> @@ -576,43 +576,43 @@ void __init of_irq_init(const struct of_device_id 
> *matches)
> }
>  }
>
> -static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
> -   u32 rid_in)
> +static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
> +   u32 id_in)
>  {
> struct device *parent_dev;
> -   u32 rid_out = rid_in;
> +   u32 id_out = id_in;
>
> /*
>  * Walk up the device parent links looking for one with a
>  * "msi-map" property.
>  */
> for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
> -   if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map",
> -   "msi-map-mask", np, _out))
> +   if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
> +   "msi-map-mask", np, _out))
> break;
> -   return rid_out;
> +   return id_out;
>  }
>
>  /**
> - * of_msi_map_rid - Map a MSI requester ID for a device.
> + * of_msi_map_id - Map a MSI ID for a device.
>   * @dev: device for which the mapping is to be done.
>   * @msi_np: device node of the expected msi controller.
> - * @rid_in: unmapped MSI requester ID for the device.
> + * @id_in: unmapped MSI ID for the device.
>   *
>   * Walk up the device hierarchy looking for devices with a "msi-map"
> - * property.  If found, apply the mapping to @rid_in.
> + * property.  If found, apply the mapping to @id_in.
>   *
> - * Returns the mapped MSI requester ID.
> + * Returns the mapped MSI ID.
>   */
> -u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 
> rid_in)
> +u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
>  {
> -   return __of_msi_map_rid(dev, _np, rid_in);
> +   return __of_msi_map_id(dev, _np, id_in);
>  }
>
>  /**
>   * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
>   * @dev: device for which the mapping is to be done.
> - * @rid: Requester ID for the device.
> + * @id: Device ID.
>   * @bus_token: Bus token
>   *
>   * Walk up the device hierarchy looking for devices with a "msi-map"
> @@ -625,7 +625,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct 
> device *dev, u32 id,
>  {
> struct device_node *np = NULL;
>
> -   __of_msi_map_rid(dev, , id);
> +   __of_msi_map_id(dev, , id);
> return irq_find_matching_host(np, bus_token);
>  }
>
> diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
> index 7142a3722758..cf9cb1e545ce 100644
> --- a/include/linux/of_irq.h
> +++ b/include/linux/of_irq.h
> @@ -55,7 +55,12 @@ extern struct irq_domain 
> *of_msi_map_get_device_domain(struct device *dev,
> u32 id,
> u32 bus_token);
>  extern void of_msi_configure(struct device *dev, struct device_node *np);
> -u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 
> rid_in);
> +u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in);
> +static inline u32 of_msi_map_rid(struct device *dev,
> +struct device_node *msi_np, u32 rid_in)
> +{
> +   return of_msi_map_id(dev, msi_np, rid_in);
> +}
>  #else
>  static inline int of_irq_count(struct device_node *dev)
>  {
> @@ -93,10 +98,15 @@ static inline struct irq_domain 
> *of_msi_map_get_device_domain(struct device *dev
>  static inline void of_msi_configure(struct device *dev, struct device_node 
> *np)
>  {
>  }
> +static inline u32 of_msi_map_id(struct device *dev,
> +struct device_node *msi_np, u32 id_in)
> +{
> +   return id_in;
> +}
>  static inline u32 of_msi_map_rid(struct device *dev,
>  struct device_node *msi_np, u32 rid_in)

Move this out of the ifdef and you only need it declared once.

But again, I think I'd just kill of_msi_map_rid.

>  {
> -   return rid_in;
> +   return of_msi_map_id(dev, 

Re: [PATCH 09/12] dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus

2020-05-21 Thread Rob Herring
On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
 wrote:
>
> From: Laurentiu Tudor 
>
> The existing bindings cannot be used to specify the relationship
> between fsl-mc devices and GIC ITSes.
>
> Add a generic binding for mapping fsl-mc devices to GIC ITSes, using
> msi-map property.
>
> Signed-off-by: Laurentiu Tudor 
> Cc: Rob Herring 
> ---
>  .../devicetree/bindings/misc/fsl,qoriq-mc.txt | 30 +--
>  1 file changed, 27 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt 
> b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
> index 9134e9bcca56..b0813b2d0493 100644
> --- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
> +++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
> @@ -18,9 +18,9 @@ same hardware "isolation context" and a 10-bit value called 
> an ICID
>  the requester.
>
>  The generic 'iommus' property is insufficient to describe the relationship
> -between ICIDs and IOMMUs, so an iommu-map property is used to define
> -the set of possible ICIDs under a root DPRC and how they map to
> -an IOMMU.
> +between ICIDs and IOMMUs, so the iommu-map and msi-map properties are used
> +to define the set of possible ICIDs under a root DPRC and how they map to
> +an IOMMU and a GIC ITS respectively.
>
>  For generic IOMMU bindings, see
>  Documentation/devicetree/bindings/iommu/iommu.txt.
> @@ -28,6 +28,9 @@ Documentation/devicetree/bindings/iommu/iommu.txt.
>  For arm-smmu binding, see:
>  Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
>
> +For GICv3 and GIC ITS bindings, see:
> +Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml.
> +
>  Required properties:
>
>  - compatible
> @@ -119,6 +122,15 @@ Optional properties:
>associated with the listed IOMMU, with the iommu-specifier
>(i - icid-base + iommu-base).
>
> +- msi-map: Maps an ICID to a GIC ITS and associated iommu-specifier
> +  data.
> +
> +  The property is an arbitrary number of tuples of
> +  (icid-base,iommu,iommu-base,length).

I'm confused because the example has GIC ITS phandle, not an IOMMU.

What is an iommu-base?

> +
> +  Any ICID in the interval [icid-base, icid-base + length) is
> +  associated with the listed GIC ITS, with the iommu-specifier
> +  (i - icid-base + iommu-base).
>  Example:
>
>  smmu: iommu@500 {
> @@ -128,6 +140,16 @@ Example:
> ...
>  };
>
> +   gic: interrupt-controller@600 {
> +   compatible = "arm,gic-v3";
> +   ...
> +   its: gic-its@602 {
> +   compatible = "arm,gic-v3-its";
> +   msi-controller;
> +   ...
> +   };
> +   };
> +
>  fsl_mc: fsl-mc@80c00 {
>  compatible = "fsl,qoriq-mc";
>  reg = <0x0008 0x0c00 0 0x40>,/* MC portal base */
> @@ -135,6 +157,8 @@ Example:
>  msi-parent = <>;
>  /* define map for ICIDs 23-64 */
>  iommu-map = <23  23 41>;
> +/* define msi map for ICIDs 23-64 */
> +msi-map = <23  23 41>;

Seeing 23 twice is odd. The numbers to the right of 'its' should be an
ITS number space.

>  #address-cells = <3>;
>  #size-cells = <1>;
>
> --
> 2.26.1
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 07/12] of/device: Add input id to of_dma_configure()

2020-05-21 Thread Rob Herring
On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
 wrote:
>
> Devices sitting on proprietary busses have a device ID space that
> is owned by the respective bus and related firmware bindings. In order
> to let the generic OF layer handle the input translations to
> an IOMMU id, for such busses the current of_dma_configure() interface
> should be extended in order to allow the bus layer to provide the
> device input id parameter - that is retrieved/assigned in bus
> specific code and firmware.
>
> Augment of_dma_configure() to add an optional input_id parameter,
> leaving current functionality unchanged.
>
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Rob Herring 
> Cc: Robin Murphy 
> Cc: Joerg Roedel 
> Cc: Laurentiu Tudor 
> ---
>  drivers/bus/fsl-mc/fsl-mc-bus.c |  4 ++-
>  drivers/iommu/of_iommu.c| 53 +
>  drivers/of/device.c |  8 +++--
>  include/linux/of_device.h   | 16 --
>  include/linux/of_iommu.h|  6 ++--
>  5 files changed, 60 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index 40526da5c6a6..8ead3f0238f2 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -118,11 +118,13 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
> kobj_uevent_env *env)
>  static int fsl_mc_dma_configure(struct device *dev)
>  {
> struct device *dma_dev = dev;
> +   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
> +   u32 input_id = mc_dev->icid;
>
> while (dev_is_fsl_mc(dma_dev))
> dma_dev = dma_dev->parent;
>
> -   return of_dma_configure(dev, dma_dev->of_node, 0);
> +   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
>  }
>
>  static ssize_t modalias_show(struct device *dev, struct device_attribute 
> *attr,
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index ad96b87137d6..4516d5bf6cc9 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -139,25 +139,53 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 
> alias, void *data)
> return err;
>  }
>
> -static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev,
> -   struct device_node *master_np)
> +static int of_iommu_configure_dev_id(struct device_node *master_np,
> +struct device *dev,
> +const u32 *id)

Should have read this patch before #6. I guess you could still make
of_pci_iommu_init() call
of_iommu_configure_dev_id.

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


Re: [PATCH 06/12] of/iommu: Make of_map_rid() PCI agnostic

2020-05-21 Thread Rob Herring
On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
 wrote:
>
> There is nothing PCI specific (other than the RID - requester ID)
> in the of_map_rid() implementation, so the same function can be
> reused for input/output IDs mapping for other busses just as well.
>
> Rename the RID instances/names to a generic "id" tag and provide
> an of_map_rid() wrapper function so that we can leave the existing
> (and legitimate) callers unchanged.

It's not all that clear to a casual observer that RID is a PCI thing,
so I don't know that keeping it buys much. And there's only 3 callers.

> No functionality change intended.
>
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Rob Herring 
> Cc: Joerg Roedel 
> Cc: Robin Murphy 
> Cc: Marc Zyngier 
> ---
>  drivers/iommu/of_iommu.c |  2 +-
>  drivers/of/base.c| 42 
>  include/linux/of.h   | 17 +++-
>  3 files changed, 38 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index 20738aacac89..ad96b87137d6 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -145,7 +145,7 @@ static int of_fsl_mc_iommu_init(struct fsl_mc_device 
> *mc_dev,
> struct of_phandle_args iommu_spec = { .args_count = 1 };
> int err;
>
> -   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
> +   err = of_map_id(master_np, mc_dev->icid, "iommu-map",

I'm not sure this is an improvement because I'd refactor this function
and of_pci_iommu_init() into a single function:

of_bus_iommu_init(struct device *dev, struct device_node *np, u32 id)

Then of_pci_iommu_init() becomes:

of_pci_iommu_init()
{
  return of_bus_iommu_init(info->dev, info->np, alias);
}

And replace of_fsl_mc_iommu_init call with:
err = of_bus_iommu_init(dev, master_np, to_fsl_mc_device(dev)->icid);

>  "iommu-map-mask", _spec.np,
>  iommu_spec.args);
> if (err)
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index ae03b1218b06..e000e17bd602 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2201,15 +2201,15 @@ int of_find_last_cache_level(unsigned int cpu)
>  }
>
>  /**
> - * of_map_rid - Translate a requester ID through a downstream mapping.
> + * of_map_id - Translate a requester ID through a downstream mapping.

Still a requester ID?

>   * @np: root complex device node.
> - * @rid: device requester ID to map.
> + * @id: device ID to map.
>   * @map_name: property name of the map to use.
>   * @map_mask_name: optional property name of the mask to use.
>   * @target: optional pointer to a target device node.
>   * @id_out: optional pointer to receive the translated ID.
>   *
> - * Given a device requester ID, look up the appropriate 
> implementation-defined
> + * Given a device ID, look up the appropriate implementation-defined
>   * platform ID and/or the target device which receives transactions on that
>   * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
>   * @id_out may be NULL if only the other is required. If @target points to
> @@ -2219,11 +2219,11 @@ int of_find_last_cache_level(unsigned int cpu)
>   *
>   * Return: 0 on success or a standard error code on failure.
>   */
> -int of_map_rid(struct device_node *np, u32 rid,
> +int of_map_id(struct device_node *np, u32 id,
>const char *map_name, const char *map_mask_name,
>struct device_node **target, u32 *id_out)
>  {
> -   u32 map_mask, masked_rid;
> +   u32 map_mask, masked_id;
> int map_len;
> const __be32 *map = NULL;
>
> @@ -2235,7 +2235,7 @@ int of_map_rid(struct device_node *np, u32 rid,
> if (target)
> return -ENODEV;
> /* Otherwise, no map implies no translation */
> -   *id_out = rid;
> +   *id_out = id;
> return 0;
> }
>
> @@ -2255,22 +2255,22 @@ int of_map_rid(struct device_node *np, u32 rid,
> if (map_mask_name)
> of_property_read_u32(np, map_mask_name, _mask);
>
> -   masked_rid = map_mask & rid;
> +   masked_id = map_mask & id;
> for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
> struct device_node *phandle_node;
> -   u32 rid_base = be32_to_cpup(map + 0);
> +   u32 id_base = be32_to_cpup(map + 0);
> u32 phandle = be32_to_cpup(map + 1);
> u32 out_base = be32_to_cpup(map + 2);
> -   u32 rid_len = be32_to_cpup(map + 3);
> +   u32 id_len = be32_to_cpup(map + 3);
>
> -   if (rid_base & ~map_mask) {
> -   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
> ignores rid-base (0x%x)\n",
> +   if (id_base & ~map_mask) {
> +   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
> ignores id-base (0x%x)\n",
> 

[PATCH -next] iommu/vt-d: fix a GCC warning

2020-05-21 Thread Qian Cai
The commit 6ee1b77ba3ac ("iommu/vt-d: Add svm/sva invalidate function")
introduced a GCC warning,

drivers/iommu/intel-iommu.c:5330:1: warning: 'static' is not at beginning of
declaration [-Wold-style-declaration]
 const static int
 ^

Signed-off-by: Qian Cai 
---
 drivers/iommu/intel-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f75d7d9c231f..ff5a30a94679 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5327,7 +5327,7 @@ static void intel_iommu_aux_detach_device(struct 
iommu_domain *domain,
  * [IOMMU_CACHE_INV_TYPE_IOTLB][IOMMU_INV_GRANU_ADDR]
  */
 
-const static int
+static const int
 inv_type_granu_table[IOMMU_CACHE_INV_TYPE_NR][IOMMU_INV_GRANU_NR] = {
/*
 * PASID based IOTLB invalidation: PASID selective (per PASID),
-- 
2.17.2 (Apple Git-113)

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


Re: [PATCH] iommu/dma: limit iova free size to unmmaped iova

2020-05-21 Thread Robin Murphy

On 2020-05-21 12:30, Prakash Gupta wrote:

Limit the iova size while freeing based on unmapped size. In absence of
this even with unmap failure, invalid iova is pushed to iova rcache and
subsequently can cause panic while rcache magazine is freed.


Can you elaborate on that panic?


Signed-off-by: Prakash Gupta 

:100644 100644 4959f5df21bd 098f7d377e04 M  drivers/iommu/dma-iommu.c

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 4959f5df21bd..098f7d377e04 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -472,7 +472,8 @@ static void __iommu_dma_unmap(struct device *dev, 
dma_addr_t dma_addr,
  
  	if (!cookie->fq_domain)

iommu_tlb_sync(domain, _gather);
-   iommu_dma_free_iova(cookie, dma_addr, size);
+   if (unmapped)
+   iommu_dma_free_iova(cookie, dma_addr, unmapped);


Frankly, if any part of the unmap fails then things have gone 
catastrophically wrong already, but either way this isn't right. The 
IOVA API doesn't support partial freeing - an IOVA *must* be freed with 
its original size, or not freed at all, otherwise it will corrupt the 
state of the rcaches and risk a cascade of further misbehaviour for 
future callers.


TBH my gut feeling here is that you're really just trying to treat a 
symptom of another bug elsewhere, namely some driver calling dma_unmap_* 
or dma_free_* with the wrong address or size in the first place.


Robin.


  }
  
  static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,



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


Re: [PATCH 02/12] ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic

2020-05-21 Thread Bjorn Helgaas
On Thu, May 21, 2020 at 01:59:58PM +0100, Lorenzo Pieralisi wrote:
> iort_get_device_domain() is PCI specific but it need not be,
> since it can be used to retrieve IRQ domain nexus of any kind
> by adding an irq_domain_bus_token input to it.
> 
> Make it PCI agnostic by also renaming the requestor ID input
> to a more generic ID name.
> 
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Will Deacon 
> Cc: Hanjun Guo 
> Cc: Bjorn Helgaas 
> Cc: Sudeep Holla 
> Cc: Catalin Marinas 
> Cc: Robin Murphy 
> Cc: "Rafael J. Wysocki" 
> Cc: Marc Zyngier 

Acked-by: Bjorn Helgaas# pci/msi.c

> ---
>  drivers/acpi/arm64/iort.c | 14 +++---
>  drivers/pci/msi.c |  3 ++-
>  include/linux/acpi_iort.h |  7 ---
>  3 files changed, 13 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 7cfd77b5e6e8..8f2a961c1364 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -567,7 +567,6 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
> device *dev)
>   node = iort_get_iort_node(dev->fwnode);
>   if (node)
>   return node;
> -
>   /*
>* if not, then it should be a platform device defined in
>* DSDT/SSDT (with Named Component node in IORT)
> @@ -658,13 +657,13 @@ static int __maybe_unused iort_find_its_base(u32 
> its_id, phys_addr_t *base)
>  /**
>   * iort_dev_find_its_id() - Find the ITS identifier for a device
>   * @dev: The device.
> - * @req_id: Device's requester ID
> + * @id: Device's ID
>   * @idx: Index of the ITS identifier list.
>   * @its_id: ITS identifier.
>   *
>   * Returns: 0 on success, appropriate error value otherwise
>   */
> -static int iort_dev_find_its_id(struct device *dev, u32 req_id,
> +static int iort_dev_find_its_id(struct device *dev, u32 id,
>   unsigned int idx, int *its_id)
>  {
>   struct acpi_iort_its_group *its;
> @@ -674,7 +673,7 @@ static int iort_dev_find_its_id(struct device *dev, u32 
> req_id,
>   if (!node)
>   return -ENXIO;
>  
> - node = iort_node_map_id(node, req_id, NULL, IORT_MSI_TYPE);
> + node = iort_node_map_id(node, id, NULL, IORT_MSI_TYPE);
>   if (!node)
>   return -ENXIO;
>  
> @@ -697,19 +696,20 @@ static int iort_dev_find_its_id(struct device *dev, u32 
> req_id,
>   *
>   * Returns: the MSI domain for this device, NULL otherwise
>   */
> -struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
> +struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
> +   enum irq_domain_bus_token bus_token)
>  {
>   struct fwnode_handle *handle;
>   int its_id;
>  
> - if (iort_dev_find_its_id(dev, req_id, 0, _id))
> + if (iort_dev_find_its_id(dev, id, 0, _id))
>   return NULL;
>  
>   handle = iort_find_domain_token(its_id);
>   if (!handle)
>   return NULL;
>  
> - return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
> + return irq_find_matching_fwnode(handle, bus_token);
>  }
>  
>  static void iort_set_device_domain(struct device *dev,
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index 6b43a5455c7a..74a91f52ecc0 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -1558,7 +1558,8 @@ struct irq_domain *pci_msi_get_device_domain(struct 
> pci_dev *pdev)
>   pci_for_each_dma_alias(pdev, get_msi_id_cb, );
>   dom = of_msi_map_get_device_domain(>dev, rid);
>   if (!dom)
> - dom = iort_get_device_domain(>dev, rid);
> + dom = iort_get_device_domain(>dev, rid,
> +  DOMAIN_BUS_PCI_MSI);
>   return dom;
>  }
>  #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 8e7e2ec37f1b..08ec6bd2297f 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -29,7 +29,8 @@ struct fwnode_handle *iort_find_domain_token(int trans_id);
>  #ifdef CONFIG_ACPI_IORT
>  void acpi_iort_init(void);
>  u32 iort_msi_map_rid(struct device *dev, u32 req_id);
> -struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
> +struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
> +   enum irq_domain_bus_token bus_token);
>  void acpi_configure_pmsi_domain(struct device *dev);
>  int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
>  /* IOMMU interface */
> @@ -40,8 +41,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head);
>  static inline void acpi_iort_init(void) { }
>  static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
>  { return req_id; }
> -static inline struct irq_domain *iort_get_device_domain(struct device *dev,
> - u32 req_id)
> +static inline struct 

Re: [PATCH 08/12] of/irq: make of_msi_map_get_device_domain() bus agnostic

2020-05-21 Thread Bjorn Helgaas
On Thu, May 21, 2020 at 02:00:04PM +0100, Lorenzo Pieralisi wrote:
> From: Diana Craciun 
> 
> of_msi_map_get_device_domain() is PCI specific but it need not be and
> can be easily changed to be bus agnostic in order to be used by other
> busses by adding an IRQ domain bus token as an input parameter.
> 
> Signed-off-by: Diana Craciun 
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Bjorn Helgaas 
> Cc: Rob Herring 
> Cc: Marc Zyngier 

Acked-by: Bjorn Helgaas# pci/msi.c

> ---
>  drivers/of/irq.c   | 8 +---
>  drivers/pci/msi.c  | 2 +-
>  include/linux/of_irq.h | 5 +++--
>  3 files changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> index a296eaf52a5b..48a40326984f 100644
> --- a/drivers/of/irq.c
> +++ b/drivers/of/irq.c
> @@ -613,18 +613,20 @@ u32 of_msi_map_rid(struct device *dev, struct 
> device_node *msi_np, u32 rid_in)
>   * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
>   * @dev: device for which the mapping is to be done.
>   * @rid: Requester ID for the device.
> + * @bus_token: Bus token
>   *
>   * Walk up the device hierarchy looking for devices with a "msi-map"
>   * property.
>   *
>   * Returns: the MSI domain for this device (or NULL on failure)
>   */
> -struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
> +struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
> + u32 bus_token)
>  {
>   struct device_node *np = NULL;
>  
> - __of_msi_map_rid(dev, , rid);
> - return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
> + __of_msi_map_rid(dev, , id);
> + return irq_find_matching_host(np, bus_token);
>  }
>  
>  /**
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index 74a91f52ecc0..9532e1d12d3f 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -1556,7 +1556,7 @@ struct irq_domain *pci_msi_get_device_domain(struct 
> pci_dev *pdev)
>   u32 rid = pci_dev_id(pdev);
>  
>   pci_for_each_dma_alias(pdev, get_msi_id_cb, );
> - dom = of_msi_map_get_device_domain(>dev, rid);
> + dom = of_msi_map_get_device_domain(>dev, rid, DOMAIN_BUS_PCI_MSI);
>   if (!dom)
>   dom = iort_get_device_domain(>dev, rid,
>DOMAIN_BUS_PCI_MSI);
> diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
> index 1214cabb2247..7142a3722758 100644
> --- a/include/linux/of_irq.h
> +++ b/include/linux/of_irq.h
> @@ -52,7 +52,8 @@ extern struct irq_domain *of_msi_get_domain(struct device 
> *dev,
>   struct device_node *np,
>   enum irq_domain_bus_token token);
>  extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
> -u32 rid);
> + u32 id,
> + u32 bus_token);
>  extern void of_msi_configure(struct device *dev, struct device_node *np);
>  u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 
> rid_in);
>  #else
> @@ -85,7 +86,7 @@ static inline struct irq_domain *of_msi_get_domain(struct 
> device *dev,
>   return NULL;
>  }
>  static inline struct irq_domain *of_msi_map_get_device_domain(struct device 
> *dev,
> -   u32 rid)
> + u32 id, u32 bus_token)
>  {
>   return NULL;
>  }
> -- 
> 2.26.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu/dma: limit iova free size to unmmaped iova

2020-05-21 Thread Andrew Morton
On Thu, 21 May 2020 17:00:04 +0530 Prakash Gupta  wrote:

> Limit the iova size while freeing based on unmapped size. In absence of
> this even with unmap failure, invalid iova is pushed to iova rcache and
> subsequently can cause panic while rcache magazine is freed.
> 
> Signed-off-by: Prakash Gupta 
> 

I think we need a cc:stable here?

> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -472,7 +472,8 @@ static void __iommu_dma_unmap(struct device *dev, 
> dma_addr_t dma_addr,
>  
>   if (!cookie->fq_domain)
>   iommu_tlb_sync(domain, _gather);
> - iommu_dma_free_iova(cookie, dma_addr, size);
> + if (unmapped)
> + iommu_dma_free_iova(cookie, dma_addr, unmapped);
>  }
>  
>  static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,

I'll assume that Joerg will handle this fix?
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/2] dt-bindings: arm-smmu: Add sc7180 compatible string

2020-05-21 Thread Will Deacon
On Mon, May 18, 2020 at 01:59:49PM -0700, Doug Anderson wrote:
> On Mon, May 18, 2020 at 7:39 AM Will Deacon  wrote:
> > On Fri, May 15, 2020 at 12:05:39PM -0700, Doug Anderson wrote:
> > > On Fri, May 1, 2020 at 3:30 AM Sharat Masetty  
> > > wrote:
> > > >
> > > > This patch simply adds a new compatible string for SC7180 platform.
> > > >
> > > > Signed-off-by: Sharat Masetty 
> > > > ---
> > > >  Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 1 +
> > > >  1 file changed, 1 insertion(+)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml 
> > > > b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> > > > index 6515dbe..986098b 100644
> > > > --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> > > > +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> > > > @@ -28,6 +28,7 @@ properties:
> > > >- enum:
> > > >- qcom,msm8996-smmu-v2
> > > >- qcom,msm8998-smmu-v2
> > > > +  - qcom,sc7180-smmu-v2
> > > >- qcom,sdm845-smmu-v2
> > > >- const: qcom,smmu-v2
> > >
> > > Is anything blocking this patch from landing now?
> >
> > I thought updates to the bindings usually went via Rob and the device-tree
> > tree, but neither of those are on cc.
> >
> > Perhaps resend with that fixed?
> 
> Ah, I guess I wasn't familiar with how things worked for this file, or
> maybe things have changed recently?  I'm used to most bindings going
> through the same tree as the drivers that use them.  Usually if things
> are at all complicated maintainers wait for an Ack from Rob (so he
> should have been CCed for sure) and then land.

Just to clear this up: I'm happy to take DT stuff like this, but preferably
with Rob's ack so that I know that (a) it's not a load of rubbish and (b) it
probably won't conflict with his tree. So having the DT folks omitted from
the CC list just rings alarm bells for me.

> In this case it actually looks like Bjorn landed it in the Qualcomm
> and I just didn't realize it.  That seems like it should be fine since
> it's in the middle of a clause that's all Qualcomm and the change
> shouldn't be controversial in any way.  :-)

Ok!

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


[GIT PULL] iommu/arm-smmu: Updates for 5.8

2020-05-21 Thread Will Deacon
Hi Joerg,

Please pull these Arm SMMU updates for 5.8. The branch is based on your
'core' branch from a little while ago.

Summary in the tag.

Cheers,

Will

--->8

The following changes since commit 1b032ec1ecbce6047af7d11c9db432e237cb17d8:

  iommu: Unexport iommu_group_get_for_dev() (2020-05-05 14:36:14 +0200)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git 
tags/arm-smmu-updates

for you to fetch changes up to 0299a1a81ca056e79c1a7fb751f936ec0d5c7afe:

  iommu/arm-smmu-v3: Manage ASIDs with xarray (2020-05-21 14:54:06 +0100)


Arm SMMU updates for 5.8

- Avoid mapping reserved MMIO space on SMMUv3, so that it can be claimed
  by the PMU driver

- Use xarray to manage ASIDs on SMMUv3

- Reword confusing shutdown message

- DT compatible string updates

- Allow implementations to override the default domain type


Andre Przywara (1):
  dt-bindings: arm-smmu: Allow mmu-400, smmu-v1 compatible

Chen Zhou (1):
  iommu/arm-smmu-v3: remove set but not used variable 'smmu'

Jean-Philippe Brucker (2):
  iommu/arm-smmu-v3: Don't reserve implementation defined register space
  iommu/arm-smmu-v3: Manage ASIDs with xarray

Jordan Crouse (1):
  iommu/arm-smmu: Allow client devices to select direct mapping

Sai Prakash Ranjan (3):
  iommu/arm-smmu: Make remove callback message more informative
  iommu: arm-smmu-impl: Convert to a generic reset implementation
  iommu/arm-smmu: Implement iommu_ops->def_domain_type call-back

Sibi Sankar (3):
  dt-bindings: remoteproc: qcom: Add iommus property
  arm64: dts: qcom: sdm845-cheza: Add iommus property
  iommu/arm-smmu-qcom: Request direct mapping for modem device

 .../devicetree/bindings/iommu/arm,smmu.yaml|  4 +-
 .../devicetree/bindings/remoteproc/qcom,q6v5.txt   |  3 +
 arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi |  5 ++
 drivers/iommu/arm-smmu-impl.c  |  8 ++-
 drivers/iommu/arm-smmu-qcom.c  | 37 -
 drivers/iommu/arm-smmu-v3.c| 64 +-
 drivers/iommu/arm-smmu.c   | 14 -
 drivers/iommu/arm-smmu.h   |  1 +
 8 files changed, 113 insertions(+), 23 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-05-21 Thread Laurentiu Tudor
Hi Lorenzo,

On 5/21/2020 4:00 PM, Lorenzo Pieralisi wrote:
> From: Diana Craciun 
> 
> Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table to
> extract memory and other resources.
> 
> Interrupt (GIC ITS) information is extracted from the MADT table
> by drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.
> 
> IORT table is parsed to configure DMA.
> 
> Signed-off-by: Makarand Pawagi 
> Signed-off-by: Diana Craciun 
> Signed-off-by: Laurentiu Tudor 
> ---

The author of this patch should be Makarand. I think I accidentaly broke
it when we exchanged the patches. Very sorry about it.

---
Best Regards, Laurentiu


>  drivers/bus/fsl-mc/fsl-mc-bus.c | 73 +++-
>  drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +-
>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 75 -
>  3 files changed, 150 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index 824ff77bbe86..324d49d6df89 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -18,6 +18,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  
>  #include "fsl-mc-private.h"
>  
> @@ -38,6 +40,7 @@ struct fsl_mc {
>   struct fsl_mc_device *root_mc_bus_dev;
>   u8 num_translation_ranges;
>   struct fsl_mc_addr_translation_range *translation_ranges;
> + void *fsl_mc_regs;
>  };
>  
>  /**
> @@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
>   phys_addr_t start_phys_addr;
>  };
>  
> +#define FSL_MC_FAPR  0x28
> +#define MC_FAPR_PL   BIT(18)
> +#define MC_FAPR_BMT  BIT(17)
> +
>  /**
>   * fsl_mc_bus_match - device to driver matching callback
>   * @dev: the fsl-mc device to match against
> @@ -124,7 +131,10 @@ static int fsl_mc_dma_configure(struct device *dev)
>   while (dev_is_fsl_mc(dma_dev))
>   dma_dev = dma_dev->parent;
>  
> - return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> + if (dev_of_node(dma_dev))
> + return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> +
> + return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, _id);
>  }
>  
>  static ssize_t modalias_show(struct device *dev, struct device_attribute 
> *attr,
> @@ -865,8 +875,11 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
>   struct fsl_mc_io *mc_io = NULL;
>   int container_id;
>   phys_addr_t mc_portal_phys_addr;
> - u32 mc_portal_size;
> - struct resource res;
> + u32 mc_portal_size, mc_stream_id;
> + struct resource *plat_res;
> +
> + if (!iommu_present(_mc_bus_type))
> + return -EPROBE_DEFER;
>  
>   mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
>   if (!mc)
> @@ -874,19 +887,33 @@ static int fsl_mc_bus_probe(struct platform_device 
> *pdev)
>  
>   platform_set_drvdata(pdev, mc);
>  
> + plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + mc->fsl_mc_regs = devm_ioremap_resource(>dev, plat_res);
> + if (IS_ERR(mc->fsl_mc_regs))
> + return PTR_ERR(mc->fsl_mc_regs);
> +
> + if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(>dev)) {
> + mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
> + /*
> +  * HW ORs the PL and BMT bit, places the result in bit 15 of
> +  * the StreamID and ORs in the ICID. Calculate it accordingly.
> +  */
> + mc_stream_id = (mc_stream_id & 0x) |
> + ((mc_stream_id & (MC_FAPR_PL | MC_FAPR_BMT)) ?
> + 0x4000 : 0);
> + error = acpi_dma_configure_id(>dev, DEV_DMA_COHERENT,
> +   _stream_id);
> + if (error)
> + dev_warn(>dev, "failed to configure dma: %d.\n",
> +  error);
> + }
> +
>   /*
>* Get physical address of MC portal for the root DPRC:
>*/
> - error = of_address_to_resource(pdev->dev.of_node, 0, );
> - if (error < 0) {
> - dev_err(>dev,
> - "of_address_to_resource() failed for %pOF\n",
> - pdev->dev.of_node);
> - return error;
> - }
> -
> - mc_portal_phys_addr = res.start;
> - mc_portal_size = resource_size();
> + plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mc_portal_phys_addr = plat_res->start;
> + mc_portal_size = resource_size(plat_res);
>   error = fsl_create_mc_io(>dev, mc_portal_phys_addr,
>mc_portal_size, NULL,
>FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, _io);
> @@ -903,11 +930,13 @@ static int fsl_mc_bus_probe(struct platform_device 
> *pdev)
>   dev_info(>dev, "MC firmware version: %u.%u.%u\n",
>mc_version.major, mc_version.minor, mc_version.revision);
>  
> - error = get_mc_addr_translation_ranges(>dev,
> - 

Re: [PATCH v7 13/24] iommu/arm-smmu-v3: Enable broadcast TLB maintenance

2020-05-21 Thread Marc Zyngier

On 2020-05-21 15:17, Will Deacon wrote:

[+Marc]

On Tue, May 19, 2020 at 07:54:51PM +0200, Jean-Philippe Brucker wrote:

The SMMUv3 can handle invalidation targeted at TLB entries with shared
ASIDs. If the implementation supports broadcast TLB maintenance, 
enable it
and keep track of it in a feature bit. The SMMU will then be affected 
by

inner-shareable TLB invalidations from other agents.

A major side-effect of this change is that stage-2 translation 
contexts
are now affected by all invalidations by VMID. VMIDs are all shared 
and
the only ways to prevent over-invalidation, since the stage-2 page 
tables
are not shared between CPU and SMMU, are to either disable BTM or 
allocate

different VMIDs. This patch does not address the problem.


This sounds like a potential performance issue, particularly as we 
expose
stage-2 contexts via VFIO directly. Maybe we could reserve some portion 
of

VMID space for the SMMU? Marc, what do you reckon?


Certainly doable when we have 16bits VMIDs. With smaller VMID spaces 
(like on
v8.0), this is a bit more difficult (we do have pretty large v8.0 
systems

around). How many VMID bits are we talking about?

M.
--
Jazz is not dead. It just smells funny...
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] iommu/dma: limit iova free size to unmmaped iova

2020-05-21 Thread Prakash Gupta
Limit the iova size while freeing based on unmapped size. In absence of
this even with unmap failure, invalid iova is pushed to iova rcache and
subsequently can cause panic while rcache magazine is freed.

Signed-off-by: Prakash Gupta 

:100644 100644 4959f5df21bd 098f7d377e04 M  drivers/iommu/dma-iommu.c

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 4959f5df21bd..098f7d377e04 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -472,7 +472,8 @@ static void __iommu_dma_unmap(struct device *dev, 
dma_addr_t dma_addr,
 
if (!cookie->fq_domain)
iommu_tlb_sync(domain, _gather);
-   iommu_dma_free_iova(cookie, dma_addr, size);
+   if (unmapped)
+   iommu_dma_free_iova(cookie, dma_addr, unmapped);
 }
 
 static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a
member of the 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 v7 13/24] iommu/arm-smmu-v3: Enable broadcast TLB maintenance

2020-05-21 Thread Will Deacon
[+Marc]

On Tue, May 19, 2020 at 07:54:51PM +0200, Jean-Philippe Brucker wrote:
> The SMMUv3 can handle invalidation targeted at TLB entries with shared
> ASIDs. If the implementation supports broadcast TLB maintenance, enable it
> and keep track of it in a feature bit. The SMMU will then be affected by
> inner-shareable TLB invalidations from other agents.
> 
> A major side-effect of this change is that stage-2 translation contexts
> are now affected by all invalidations by VMID. VMIDs are all shared and
> the only ways to prevent over-invalidation, since the stage-2 page tables
> are not shared between CPU and SMMU, are to either disable BTM or allocate
> different VMIDs. This patch does not address the problem.

This sounds like a potential performance issue, particularly as we expose
stage-2 contexts via VFIO directly. Maybe we could reserve some portion of
VMID space for the SMMU? Marc, what do you reckon?

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


Re: [PATCH v7 00/24] iommu: Shared Virtual Addressing for SMMUv3

2020-05-21 Thread Will Deacon
On Thu, May 21, 2020 at 11:35:14AM +0100, Will Deacon wrote:
> On Tue, May 19, 2020 at 07:54:38PM +0200, Jean-Philippe Brucker wrote:
> > Shared Virtual Addressing (SVA) allows to share process page tables with
> > devices using the IOMMU, PASIDs and I/O page faults. Add SVA support to
> > the Arm SMMUv3 driver.
> > 
> > Since v6 [1]:
> > * Rename ioasid_free() to ioasid_put() in patch 02, requiring changes to
> >   the Intel drivers.
> > * Use mmu_notifier_register() in patch 16 to avoid copying the ops and
> >   simplify the invalidate() notifier in patch 17.
> > * As a result, replace context spinlock with a mutex. Simplified locking in
> >   patch 11 (That patch still looks awful, but I think the series is more
> >   readable overall). And I've finally been able to remove the GFP_ATOMIC
> >   allocations.
> > * Use a single patch (04) for io-pgfault.c, since the code was simplified
> >   in v6. Fixed partial list in patch 04.
> 
> There's an awful lot here and it stretches across quite a few subsystems,
> with different git trees. What's the plan for merging it?
> 
> I'm happy to take some of the arm64 and smmu changes for 5.8, then perhaps
> we can review what's left and target 5.9? It would also be helpful to split
> that up into separate series where there aren't strong dependencies, I
> think.

Hmm, so the way the series is structured makes it quite difficult to apply
much of this at all :(

I've taken patch 5 into the arm64 tree and patch 8 into the smmu tree. I'll
leave a couple of Acks on some of the simpler patches, but I think this
really needs splitting up a bit to make it more manageable.

I also notice a bunch of TODOs that get introduced and then removed. Given
that the series needs to be bisectable, these shouldn't be needed and can
just be removed.

Thanks,

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


Re: [PATCH v7 14/24] iommu/arm-smmu-v3: Add SVA feature checking

2020-05-21 Thread Will Deacon
On Tue, May 19, 2020 at 07:54:52PM +0200, Jean-Philippe Brucker wrote:
> Aggregate all sanity-checks for sharing CPU page tables with the SMMU
> under a single ARM_SMMU_FEAT_SVA bit. For PCIe SVA, users also need to
> check FEAT_ATS and FEAT_PRI. For platform SVA, they will most likely have
> to check FEAT_STALLS.
> 
> Cc: Suzuki K Poulose 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/iommu/arm-smmu-v3.c | 72 +
>  1 file changed, 72 insertions(+)
> 
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 9332253e3608..a9f6f1d7014e 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -660,6 +660,7 @@ struct arm_smmu_device {
>  #define ARM_SMMU_FEAT_RANGE_INV  (1 << 15)
>  #define ARM_SMMU_FEAT_E2H(1 << 16)
>  #define ARM_SMMU_FEAT_BTM(1 << 17)
> +#define ARM_SMMU_FEAT_SVA(1 << 18)
>   u32 features;
>  
>  #define ARM_SMMU_OPT_SKIP_PREFETCH   (1 << 0)
> @@ -3935,6 +3936,74 @@ static int arm_smmu_device_reset(struct 
> arm_smmu_device *smmu, bool bypass)
>   return 0;
>  }
>  
> +static bool arm_smmu_supports_sva(struct arm_smmu_device *smmu)
> +{
> + unsigned long reg, fld;
> + unsigned long oas;
> + unsigned long asid_bits;
> +
> + u32 feat_mask = ARM_SMMU_FEAT_BTM | ARM_SMMU_FEAT_COHERENCY;

Aha -- here's the coherency check I missed!

> +
> + if ((smmu->features & feat_mask) != feat_mask)
> + return false;
> +
> + if (!(smmu->pgsize_bitmap & PAGE_SIZE))
> + return false;
> +
> + /*
> +  * Get the smallest PA size of all CPUs (sanitized by cpufeature). We're
> +  * not even pretending to support AArch32 here.
> +  */
> + reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
> + fld = cpuid_feature_extract_unsigned_field(reg, 
> ID_AA64MMFR0_PARANGE_SHIFT);
> + switch (fld) {
> + case 0x0:
> + oas = 32;
> + break;
> + case 0x1:
> + oas = 36;
> + break;
> + case 0x2:
> + oas = 40;
> + break;
> + case 0x3:
> + oas = 42;
> + break;
> + case 0x4:
> + oas = 44;
> + break;
> + case 0x5:
> + oas = 48;
> + break;
> + case 0x6:

We can use ID_AA64MMFR0_PARANGE_xx constants instead of the hardcoded hex
numbers here.

With that:

Acked-by: Will Deacon 

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


Re: [PATCH v7 07/24] iommu/io-pgtable-arm: Move some definitions to a header

2020-05-21 Thread Will Deacon
On Tue, May 19, 2020 at 07:54:45PM +0200, Jean-Philippe Brucker wrote:
> Extract some of the most generic TCR defines, so they can be reused by
> the page table sharing code.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/iommu/io-pgtable-arm.h | 30 ++
>  drivers/iommu/io-pgtable-arm.c | 27 ++-
>  MAINTAINERS|  3 +--
>  3 files changed, 33 insertions(+), 27 deletions(-)
>  create mode 100644 drivers/iommu/io-pgtable-arm.h

Acked-by: Will Deacon 

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


Re: [PATCH v7 12/24] iommu/arm-smmu-v3: Add support for VHE

2020-05-21 Thread Will Deacon
On Tue, May 19, 2020 at 07:54:50PM +0200, Jean-Philippe Brucker wrote:
> ARMv8.1 extensions added Virtualization Host Extensions (VHE), which allow
> to run a host kernel at EL2. When using normal DMA, Device and CPU address
> spaces are dissociated, and do not need to implement the same
> capabilities, so VHE hasn't been used in the SMMU until now.
> 
> With shared address spaces however, ASIDs are shared between MMU and SMMU,
> and broadcast TLB invalidations issued by a CPU are taken into account by
> the SMMU. TLB entries on both sides need to have identical exception level
> in order to be cleared with a single invalidation.
> 
> When the CPU is using VHE, enable VHE in the SMMU for all STEs. Normal DMA
> mappings will need to use TLBI_EL2 commands instead of TLBI_NH, but
> shouldn't be otherwise affected by this change.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/iommu/arm-smmu-v3.c | 31 ++-
>  1 file changed, 26 insertions(+), 5 deletions(-)

Acked-by: Will Deacon 

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


[PATCH 06/12] of/iommu: Make of_map_rid() PCI agnostic

2020-05-21 Thread Lorenzo Pieralisi
There is nothing PCI specific (other than the RID - requester ID)
in the of_map_rid() implementation, so the same function can be
reused for input/output IDs mapping for other busses just as well.

Rename the RID instances/names to a generic "id" tag and provide
an of_map_rid() wrapper function so that we can leave the existing
(and legitimate) callers unchanged.

No functionality change intended.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Joerg Roedel 
Cc: Robin Murphy 
Cc: Marc Zyngier 
---
 drivers/iommu/of_iommu.c |  2 +-
 drivers/of/base.c| 42 
 include/linux/of.h   | 17 +++-
 3 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 20738aacac89..ad96b87137d6 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -145,7 +145,7 @@ static int of_fsl_mc_iommu_init(struct fsl_mc_device 
*mc_dev,
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
+   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
 "iommu-map-mask", _spec.np,
 iommu_spec.args);
if (err)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ae03b1218b06..e000e17bd602 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2201,15 +2201,15 @@ int of_find_last_cache_level(unsigned int cpu)
 }
 
 /**
- * of_map_rid - Translate a requester ID through a downstream mapping.
+ * of_map_id - Translate a requester ID through a downstream mapping.
  * @np: root complex device node.
- * @rid: device requester ID to map.
+ * @id: device ID to map.
  * @map_name: property name of the map to use.
  * @map_mask_name: optional property name of the mask to use.
  * @target: optional pointer to a target device node.
  * @id_out: optional pointer to receive the translated ID.
  *
- * Given a device requester ID, look up the appropriate implementation-defined
+ * Given a device ID, look up the appropriate implementation-defined
  * platform ID and/or the target device which receives transactions on that
  * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
  * @id_out may be NULL if only the other is required. If @target points to
@@ -2219,11 +2219,11 @@ int of_find_last_cache_level(unsigned int cpu)
  *
  * Return: 0 on success or a standard error code on failure.
  */
-int of_map_rid(struct device_node *np, u32 rid,
+int of_map_id(struct device_node *np, u32 id,
   const char *map_name, const char *map_mask_name,
   struct device_node **target, u32 *id_out)
 {
-   u32 map_mask, masked_rid;
+   u32 map_mask, masked_id;
int map_len;
const __be32 *map = NULL;
 
@@ -2235,7 +2235,7 @@ int of_map_rid(struct device_node *np, u32 rid,
if (target)
return -ENODEV;
/* Otherwise, no map implies no translation */
-   *id_out = rid;
+   *id_out = id;
return 0;
}
 
@@ -2255,22 +2255,22 @@ int of_map_rid(struct device_node *np, u32 rid,
if (map_mask_name)
of_property_read_u32(np, map_mask_name, _mask);
 
-   masked_rid = map_mask & rid;
+   masked_id = map_mask & id;
for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
struct device_node *phandle_node;
-   u32 rid_base = be32_to_cpup(map + 0);
+   u32 id_base = be32_to_cpup(map + 0);
u32 phandle = be32_to_cpup(map + 1);
u32 out_base = be32_to_cpup(map + 2);
-   u32 rid_len = be32_to_cpup(map + 3);
+   u32 id_len = be32_to_cpup(map + 3);
 
-   if (rid_base & ~map_mask) {
-   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
ignores rid-base (0x%x)\n",
+   if (id_base & ~map_mask) {
+   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
ignores id-base (0x%x)\n",
np, map_name, map_name,
-   map_mask, rid_base);
+   map_mask, id_base);
return -EFAULT;
}
 
-   if (masked_rid < rid_base || masked_rid >= rid_base + rid_len)
+   if (masked_id < id_base || masked_id >= id_base + id_len)
continue;
 
phandle_node = of_find_node_by_phandle(phandle);
@@ -2288,20 +2288,20 @@ int of_map_rid(struct device_node *np, u32 rid,
}
 
if (id_out)
-   *id_out = masked_rid - rid_base + out_base;
+   *id_out = masked_id - id_base + out_base;
 
-   pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: 
%08x, length: %08x, rid: %08x -> %08x\n",
-   

[PATCH 04/12] ACPI/IORT: Remove useless PCI bus walk

2020-05-21 Thread Lorenzo Pieralisi
The PCI bus domain number (used in the iort_match_node_callback() -
pci_domain_nr() call) is cascaded through the PCI bus hierarchy at PCI
bus enumeration time, therefore there is no need in iort_find_dev_node()
to walk the PCI bus upwards to grab the root bus to be passed to
iort_scan_node(), the device->bus PCI bus pointer will do.

Remove this useless code.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index f346a785e0b5..ae9e1089d954 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -575,10 +575,7 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
  iort_match_node_callback, dev);
}
 
-   /* Find a PCI root bus */
pbus = to_pci_dev(dev)->bus;
-   while (!pci_is_root_bus(pbus))
-   pbus = pbus->parent;
 
return iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
  iort_match_node_callback, >dev);
-- 
2.26.1

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


[PATCH 03/12] ACPI/IORT: Make iort_msi_map_rid() PCI agnostic

2020-05-21 Thread Lorenzo Pieralisi
There is nothing PCI specific in iort_msi_map_rid(). Make it
a generic function, iort_msi_map_id() and provide a stub
for iort_msi_map_rid() on top of it to keep current users
unchanged.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 12 ++--
 include/linux/acpi_iort.h | 12 ++--
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 8f2a961c1364..f346a785e0b5 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -585,22 +585,22 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
 }
 
 /**
- * iort_msi_map_rid() - Map a MSI requester ID for a device
+ * iort_msi_map_id() - Map a MSI input ID for a device
  * @dev: The device for which the mapping is to be done.
- * @req_id: The device requester ID.
+ * @input_id: The device input ID.
  *
- * Returns: mapped MSI RID on success, input requester ID otherwise
+ * Returns: mapped MSI ID on success, input ID otherwise
  */
-u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+u32 iort_msi_map_id(struct device *dev, u32 input_id)
 {
struct acpi_iort_node *node;
u32 dev_id;
 
node = iort_find_dev_node(dev);
if (!node)
-   return req_id;
+   return input_id;
 
-   iort_node_map_id(node, req_id, _id, IORT_MSI_TYPE);
+   iort_node_map_id(node, input_id, _id, IORT_MSI_TYPE);
return dev_id;
 }
 
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 08ec6bd2297f..8c71f92b92ef 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -28,7 +28,11 @@ void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
-u32 iort_msi_map_rid(struct device *dev, u32 req_id);
+u32 iort_msi_map_id(struct device *dev, u32 id);
+static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+{
+   return iort_msi_map_id(dev, req_id);
+}
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
  enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
@@ -39,8 +43,12 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev);
 int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
*head);
 #else
 static inline void acpi_iort_init(void) { }
+static inline u32 iort_msi_map_id(struct device *dev, u32 id)
+{ return id; }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
-{ return req_id; }
+{
+   return iort_msi_map_id(dev, req_id);
+}
 static inline struct irq_domain *iort_get_device_domain(
struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
-- 
2.26.1

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


[PATCH 05/12] ACPI/IORT: Add an input ID to acpi_dma_configure()

2020-05-21 Thread Lorenzo Pieralisi
Some HW devices are created as child devices of proprietary busses,
that have a bus specific policy definining how the child devices
wires representing the devices ID are translated into IOMMU and
IRQ controllers device IDs.

Current IORT code provides translations for:

- PCI devices, where the device ID is well identified at bus level
  as the requester ID (RID)
- Platform devices that are endpoint devices where the device ID is
  retrieved from the ACPI object IORT mappings (Named components single
  mappings). A platform device is represented in IORT as a named
  component node

For devices that are child devices of proprietary busses the IORT
firmware represents the bus node as a named component node in IORT
and it is up to that named component node to define in/out bus
specific ID translations for the bus child devices that are
allocated and created in a bus specific manner.

In order to make IORT ID translations available for proprietary
bus child devices, the current ACPI (and IORT) code must be
augmented to provide an additional ID parameter to acpi_dma_configure()
representing the child devices input ID. This ID is bus specific
and it is retrieved in bus specific code.

By adding an ID parameter to acpi_dma_configure(), the IORT
code can map the child device ID to an IOMMU stream id through
the IORT named component representing the bus in/out ID mappings.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 59 +--
 drivers/acpi/scan.c   |  8 --
 include/acpi/acpi_bus.h   |  9 --
 include/linux/acpi.h  |  7 +
 include/linux/acpi_iort.h |  7 +++--
 5 files changed, 67 insertions(+), 23 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index ae9e1089d954..270c1a0cdeff 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1004,19 +1004,54 @@ static void iort_named_component_init(struct device 
*dev,
   nc->node_flags);
 }
 
+static int iort_nc_iommu_map(struct device *dev, struct acpi_iort_node *node)
+{
+   struct acpi_iort_node *parent;
+   int err = -ENODEV, i = 0;
+   u32 streamid = 0;
+
+   do {
+
+   parent = iort_node_map_platform_id(node, ,
+  IORT_IOMMU_TYPE,
+  i++);
+
+   if (parent)
+   err = iort_iommu_xlate(dev, parent, streamid);
+   } while (parent && !err);
+
+   return err;
+}
+
+static int iort_nc_iommu_map_id(struct device *dev,
+   struct acpi_iort_node *node,
+   const u32 *in_id)
+{
+   struct acpi_iort_node *parent;
+   u32 streamid;
+
+   parent = iort_node_map_id(node, *in_id, , IORT_IOMMU_TYPE);
+   if (parent)
+   return iort_iommu_xlate(dev, parent, streamid);
+
+   return -ENODEV;
+}
+
+
 /**
- * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ * iort_iommu_configure_id - Set-up IOMMU configuration for a device.
  *
  * @dev: device to configure
+ * @id_in: optional input id const value pointer
  *
  * Returns: iommu_ops pointer on configuration success
  *  NULL on configuration failure
  */
-const struct iommu_ops *iort_iommu_configure(struct device *dev)
+const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
+   const u32 *id_in)
 {
-   struct acpi_iort_node *node, *parent;
+   struct acpi_iort_node *node;
const struct iommu_ops *ops;
-   u32 streamid = 0;
int err = -ENODEV;
 
/*
@@ -1045,21 +1080,13 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
if (fwspec && iort_pci_rc_supports_ats(node))
fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
} else {
-   int i = 0;
-
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
  iort_match_node_callback, dev);
if (!node)
return NULL;
 
-   do {
-   parent = iort_node_map_platform_id(node, ,
-  IORT_IOMMU_TYPE,
-  i++);
-
-   if (parent)
-   err = iort_iommu_xlate(dev, parent, streamid);
-   } while (parent && !err);
+   err = id_in ? iort_nc_iommu_map_id(dev, node, id_in) :
+ iort_nc_iommu_map(dev, node);
 
if (!err)
iort_named_component_init(dev, node);
@@ -1084,6 +,7 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
 
 

[PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-05-21 Thread Lorenzo Pieralisi
From: Diana Craciun 

Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table to
extract memory and other resources.

Interrupt (GIC ITS) information is extracted from the MADT table
by drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.

IORT table is parsed to configure DMA.

Signed-off-by: Makarand Pawagi 
Signed-off-by: Diana Craciun 
Signed-off-by: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c | 73 +++-
 drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +-
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 75 -
 3 files changed, 150 insertions(+), 35 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 824ff77bbe86..324d49d6df89 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -18,6 +18,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "fsl-mc-private.h"
 
@@ -38,6 +40,7 @@ struct fsl_mc {
struct fsl_mc_device *root_mc_bus_dev;
u8 num_translation_ranges;
struct fsl_mc_addr_translation_range *translation_ranges;
+   void *fsl_mc_regs;
 };
 
 /**
@@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
phys_addr_t start_phys_addr;
 };
 
+#define FSL_MC_FAPR0x28
+#define MC_FAPR_PL BIT(18)
+#define MC_FAPR_BMTBIT(17)
+
 /**
  * fsl_mc_bus_match - device to driver matching callback
  * @dev: the fsl-mc device to match against
@@ -124,7 +131,10 @@ static int fsl_mc_dma_configure(struct device *dev)
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
 
-   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
+   if (dev_of_node(dma_dev))
+   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
+
+   return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, _id);
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
@@ -865,8 +875,11 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
struct fsl_mc_io *mc_io = NULL;
int container_id;
phys_addr_t mc_portal_phys_addr;
-   u32 mc_portal_size;
-   struct resource res;
+   u32 mc_portal_size, mc_stream_id;
+   struct resource *plat_res;
+
+   if (!iommu_present(_mc_bus_type))
+   return -EPROBE_DEFER;
 
mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
if (!mc)
@@ -874,19 +887,33 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, mc);
 
+   plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+   mc->fsl_mc_regs = devm_ioremap_resource(>dev, plat_res);
+   if (IS_ERR(mc->fsl_mc_regs))
+   return PTR_ERR(mc->fsl_mc_regs);
+
+   if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(>dev)) {
+   mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
+   /*
+* HW ORs the PL and BMT bit, places the result in bit 15 of
+* the StreamID and ORs in the ICID. Calculate it accordingly.
+*/
+   mc_stream_id = (mc_stream_id & 0x) |
+   ((mc_stream_id & (MC_FAPR_PL | MC_FAPR_BMT)) ?
+   0x4000 : 0);
+   error = acpi_dma_configure_id(>dev, DEV_DMA_COHERENT,
+ _stream_id);
+   if (error)
+   dev_warn(>dev, "failed to configure dma: %d.\n",
+error);
+   }
+
/*
 * Get physical address of MC portal for the root DPRC:
 */
-   error = of_address_to_resource(pdev->dev.of_node, 0, );
-   if (error < 0) {
-   dev_err(>dev,
-   "of_address_to_resource() failed for %pOF\n",
-   pdev->dev.of_node);
-   return error;
-   }
-
-   mc_portal_phys_addr = res.start;
-   mc_portal_size = resource_size();
+   plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   mc_portal_phys_addr = plat_res->start;
+   mc_portal_size = resource_size(plat_res);
error = fsl_create_mc_io(>dev, mc_portal_phys_addr,
 mc_portal_size, NULL,
 FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, _io);
@@ -903,11 +930,13 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
dev_info(>dev, "MC firmware version: %u.%u.%u\n",
 mc_version.major, mc_version.minor, mc_version.revision);
 
-   error = get_mc_addr_translation_ranges(>dev,
-  >translation_ranges,
-  >num_translation_ranges);
-   if (error < 0)
-   goto error_cleanup_mc_io;
+   if (dev_of_node(>dev)) {
+   error = get_mc_addr_translation_ranges(>dev,
+   

[PATCH 00/12] ACPI/OF: Upgrade MSI/IOMMU ID mapping APIs

2020-05-21 Thread Lorenzo Pieralisi
Firmware bindings provided in the ACPI IORT table[1] and device tree
bindings define rules to carry out input/output ID mappings - ie
retrieving an IOMMU/MSI controller input ID for a device with a given
ID.

At the moment these firmware bindings are used exclusively for PCI
devices and their requester ID to IOMMU/MSI id mapping but there is
nothing PCI specific in the ACPI and devicetree bindings that prevent
the firmware and kernel from using the firmware bindings to traslate
device IDs for any bus that requires its devices to carry out
input/output id translations.

The Freescale FSL bus is an example whereby the input/output ID
translation kernel code put in place for PCI can be reused for devices
attached to the bus that are not PCI devices.

This series updates the kernel code to make the MSI/IOMMU input/output
ID translation PCI agnostic and apply the resulting changes to the
device ID space provided by the Freescale FSL bus.

[1] 
http://infocenter.arm.com/help/topic/com.arm.doc.den0049d/DEN0049D_IO_Remapping_Table.pdf

Cc: Rob Herring 
Cc: "Rafael J. Wysocki" 
Cc: "Joerg Roedel 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Robin Murphy 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Marc Zyngier 

Diana Craciun (3):
  of/irq: make of_msi_map_get_device_domain() bus agnostic
  bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver
  bus: fsl-mc: Add ACPI support for fsl-mc

Laurentiu Tudor (1):
  dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus

Lorenzo Pieralisi (8):
  ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for
NC
  ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
  ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
  ACPI/IORT: Remove useless PCI bus walk
  ACPI/IORT: Add an input ID to acpi_dma_configure()
  of/iommu: Make of_map_rid() PCI agnostic
  of/device: Add input id to of_dma_configure()
  of/irq: Make of_msi_map_rid() PCI bus agnostic

 .../devicetree/bindings/misc/fsl,qoriq-mc.txt |  30 -
 drivers/acpi/arm64/iort.c | 108 --
 drivers/acpi/scan.c   |   8 +-
 drivers/bus/fsl-mc/dprc-driver.c  |  31 ++---
 drivers/bus/fsl-mc/fsl-mc-bus.c   |  79 +
 drivers/bus/fsl-mc/fsl-mc-msi.c   |  36 --
 drivers/bus/fsl-mc/fsl-mc-private.h   |   6 +-
 drivers/iommu/of_iommu.c  |  53 ++---
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c   |  88 +-
 drivers/of/base.c |  42 +++
 drivers/of/device.c   |   8 +-
 drivers/of/irq.c  |  34 +++---
 drivers/pci/msi.c |   5 +-
 include/acpi/acpi_bus.h   |   9 +-
 include/linux/acpi.h  |   7 ++
 include/linux/acpi_iort.h |  26 +++--
 include/linux/of.h|  17 ++-
 include/linux/of_device.h |  16 ++-
 include/linux/of_iommu.h  |   6 +-
 include/linux/of_irq.h|  19 ++-
 20 files changed, 451 insertions(+), 177 deletions(-)

-- 
2.26.1

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


[PATCH 10/12] of/irq: Make of_msi_map_rid() PCI bus agnostic

2020-05-21 Thread Lorenzo Pieralisi
There is nothing PCI bus specific in the of_msi_map_rid()
implementation other than the requester ID tag for the input
ID space. Rename requester ID to a more generic ID so that
the translation code can be used by all busses that require
input/output ID translations.

Leave a wrapper function of_msi_map_rid() in place to keep
existing PCI code mapping requester ID syntactically unchanged.

No functional change intended.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Marc Zyngier 
---
 drivers/of/irq.c   | 28 ++--
 include/linux/of_irq.h | 14 --
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 48a40326984f..25d17b8a1a1a 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -576,43 +576,43 @@ void __init of_irq_init(const struct of_device_id 
*matches)
}
 }
 
-static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
-   u32 rid_in)
+static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
+   u32 id_in)
 {
struct device *parent_dev;
-   u32 rid_out = rid_in;
+   u32 id_out = id_in;
 
/*
 * Walk up the device parent links looking for one with a
 * "msi-map" property.
 */
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
-   if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map",
-   "msi-map-mask", np, _out))
+   if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
+   "msi-map-mask", np, _out))
break;
-   return rid_out;
+   return id_out;
 }
 
 /**
- * of_msi_map_rid - Map a MSI requester ID for a device.
+ * of_msi_map_id - Map a MSI ID for a device.
  * @dev: device for which the mapping is to be done.
  * @msi_np: device node of the expected msi controller.
- * @rid_in: unmapped MSI requester ID for the device.
+ * @id_in: unmapped MSI ID for the device.
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
- * property.  If found, apply the mapping to @rid_in.
+ * property.  If found, apply the mapping to @id_in.
  *
- * Returns the mapped MSI requester ID.
+ * Returns the mapped MSI ID.
  */
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in)
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
 {
-   return __of_msi_map_rid(dev, _np, rid_in);
+   return __of_msi_map_id(dev, _np, id_in);
 }
 
 /**
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
- * @rid: Requester ID for the device.
+ * @id: Device ID.
  * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
@@ -625,7 +625,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct 
device *dev, u32 id,
 {
struct device_node *np = NULL;
 
-   __of_msi_map_rid(dev, , id);
+   __of_msi_map_id(dev, , id);
return irq_find_matching_host(np, bus_token);
 }
 
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 7142a3722758..cf9cb1e545ce 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -55,7 +55,12 @@ extern struct irq_domain 
*of_msi_map_get_device_domain(struct device *dev,
u32 id,
u32 bus_token);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in);
+static inline u32 of_msi_map_rid(struct device *dev,
+struct device_node *msi_np, u32 rid_in)
+{
+   return of_msi_map_id(dev, msi_np, rid_in);
+}
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
@@ -93,10 +98,15 @@ static inline struct irq_domain 
*of_msi_map_get_device_domain(struct device *dev
 static inline void of_msi_configure(struct device *dev, struct device_node *np)
 {
 }
+static inline u32 of_msi_map_id(struct device *dev,
+struct device_node *msi_np, u32 id_in)
+{
+   return id_in;
+}
 static inline u32 of_msi_map_rid(struct device *dev,
 struct device_node *msi_np, u32 rid_in)
 {
-   return rid_in;
+   return of_msi_map_id(dev, msi_np, rid_in);
 }
 #endif
 
-- 
2.26.1

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


[PATCH 08/12] of/irq: make of_msi_map_get_device_domain() bus agnostic

2020-05-21 Thread Lorenzo Pieralisi
From: Diana Craciun 

of_msi_map_get_device_domain() is PCI specific but it need not be and
can be easily changed to be bus agnostic in order to be used by other
busses by adding an IRQ domain bus token as an input parameter.

Signed-off-by: Diana Craciun 
Signed-off-by: Lorenzo Pieralisi 
Cc: Bjorn Helgaas 
Cc: Rob Herring 
Cc: Marc Zyngier 
---
 drivers/of/irq.c   | 8 +---
 drivers/pci/msi.c  | 2 +-
 include/linux/of_irq.h | 5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a296eaf52a5b..48a40326984f 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -613,18 +613,20 @@ u32 of_msi_map_rid(struct device *dev, struct device_node 
*msi_np, u32 rid_in)
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
  * @rid: Requester ID for the device.
+ * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
  * property.
  *
  * Returns: the MSI domain for this device (or NULL on failure)
  */
-struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
+struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
+   u32 bus_token)
 {
struct device_node *np = NULL;
 
-   __of_msi_map_rid(dev, , rid);
-   return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+   __of_msi_map_rid(dev, , id);
+   return irq_find_matching_host(np, bus_token);
 }
 
 /**
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 74a91f52ecc0..9532e1d12d3f 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1556,7 +1556,7 @@ struct irq_domain *pci_msi_get_device_domain(struct 
pci_dev *pdev)
u32 rid = pci_dev_id(pdev);
 
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
-   dom = of_msi_map_get_device_domain(>dev, rid);
+   dom = of_msi_map_get_device_domain(>dev, rid, DOMAIN_BUS_PCI_MSI);
if (!dom)
dom = iort_get_device_domain(>dev, rid,
 DOMAIN_BUS_PCI_MSI);
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 1214cabb2247..7142a3722758 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -52,7 +52,8 @@ extern struct irq_domain *of_msi_get_domain(struct device 
*dev,
struct device_node *np,
enum irq_domain_bus_token token);
 extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
-  u32 rid);
+   u32 id,
+   u32 bus_token);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
 u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 #else
@@ -85,7 +86,7 @@ static inline struct irq_domain *of_msi_get_domain(struct 
device *dev,
return NULL;
 }
 static inline struct irq_domain *of_msi_map_get_device_domain(struct device 
*dev,
- u32 rid)
+   u32 id, u32 bus_token)
 {
return NULL;
 }
-- 
2.26.1

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


[PATCH 02/12] ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic

2020-05-21 Thread Lorenzo Pieralisi
iort_get_device_domain() is PCI specific but it need not be,
since it can be used to retrieve IRQ domain nexus of any kind
by adding an irq_domain_bus_token input to it.

Make it PCI agnostic by also renaming the requestor ID input
to a more generic ID name.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Bjorn Helgaas 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
Cc: Marc Zyngier 
---
 drivers/acpi/arm64/iort.c | 14 +++---
 drivers/pci/msi.c |  3 ++-
 include/linux/acpi_iort.h |  7 ---
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 7cfd77b5e6e8..8f2a961c1364 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -567,7 +567,6 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
node = iort_get_iort_node(dev->fwnode);
if (node)
return node;
-
/*
 * if not, then it should be a platform device defined in
 * DSDT/SSDT (with Named Component node in IORT)
@@ -658,13 +657,13 @@ static int __maybe_unused iort_find_its_base(u32 its_id, 
phys_addr_t *base)
 /**
  * iort_dev_find_its_id() - Find the ITS identifier for a device
  * @dev: The device.
- * @req_id: Device's requester ID
+ * @id: Device's ID
  * @idx: Index of the ITS identifier list.
  * @its_id: ITS identifier.
  *
  * Returns: 0 on success, appropriate error value otherwise
  */
-static int iort_dev_find_its_id(struct device *dev, u32 req_id,
+static int iort_dev_find_its_id(struct device *dev, u32 id,
unsigned int idx, int *its_id)
 {
struct acpi_iort_its_group *its;
@@ -674,7 +673,7 @@ static int iort_dev_find_its_id(struct device *dev, u32 
req_id,
if (!node)
return -ENXIO;
 
-   node = iort_node_map_id(node, req_id, NULL, IORT_MSI_TYPE);
+   node = iort_node_map_id(node, id, NULL, IORT_MSI_TYPE);
if (!node)
return -ENXIO;
 
@@ -697,19 +696,20 @@ static int iort_dev_find_its_id(struct device *dev, u32 
req_id,
  *
  * Returns: the MSI domain for this device, NULL otherwise
  */
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+ enum irq_domain_bus_token bus_token)
 {
struct fwnode_handle *handle;
int its_id;
 
-   if (iort_dev_find_its_id(dev, req_id, 0, _id))
+   if (iort_dev_find_its_id(dev, id, 0, _id))
return NULL;
 
handle = iort_find_domain_token(its_id);
if (!handle)
return NULL;
 
-   return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
+   return irq_find_matching_fwnode(handle, bus_token);
 }
 
 static void iort_set_device_domain(struct device *dev,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 6b43a5455c7a..74a91f52ecc0 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1558,7 +1558,8 @@ struct irq_domain *pci_msi_get_device_domain(struct 
pci_dev *pdev)
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
dom = of_msi_map_get_device_domain(>dev, rid);
if (!dom)
-   dom = iort_get_device_domain(>dev, rid);
+   dom = iort_get_device_domain(>dev, rid,
+DOMAIN_BUS_PCI_MSI);
return dom;
 }
 #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 8e7e2ec37f1b..08ec6bd2297f 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -29,7 +29,8 @@ struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+ enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
@@ -40,8 +41,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
struct list_head *head);
 static inline void acpi_iort_init(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
-static inline struct irq_domain *iort_get_device_domain(struct device *dev,
-   u32 req_id)
+static inline struct irq_domain *iort_get_device_domain(
+   struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
 static inline void acpi_configure_pmsi_domain(struct device *dev) { }
 /* IOMMU interface */
-- 
2.26.1

___
iommu mailing 

[PATCH 01/12] ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for NC

2020-05-21 Thread Lorenzo Pieralisi
When the iort_match_node_callback is invoked for a named component
the match should be executed upon a device with an ACPI companion.

For devices with no ACPI companion set-up the ACPI device tree must be
walked in order to find the first parent node with a companion set and
check the parent node against the named component entry to check whether
there is a match and therefore an IORT node describing the in/out ID
translation for the device has been found.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 7d04424189df..7cfd77b5e6e8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -264,15 +264,31 @@ static acpi_status iort_match_node_callback(struct 
acpi_iort_node *node,
 
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
-   struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
+   struct acpi_device *adev;
struct acpi_iort_named_component *ncomp;
+   struct device *nc_dev = dev;
+
+   /*
+* Walk the device tree to find a device with an
+* ACPI companion; there is no point in scanning
+* IORT for a device matching a named component if
+* the device does not have an ACPI companion to
+* start with.
+*/
+   do {
+   adev = ACPI_COMPANION(nc_dev);
+   if (adev)
+   break;
+
+   nc_dev = nc_dev->parent;
+   } while (nc_dev);
 
if (!adev)
goto out;
 
status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, );
if (ACPI_FAILURE(status)) {
-   dev_warn(dev, "Can't get device full path name\n");
+   dev_warn(nc_dev, "Can't get device full path name\n");
goto out;
}
 
-- 
2.26.1

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


[PATCH 09/12] dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus

2020-05-21 Thread Lorenzo Pieralisi
From: Laurentiu Tudor 

The existing bindings cannot be used to specify the relationship
between fsl-mc devices and GIC ITSes.

Add a generic binding for mapping fsl-mc devices to GIC ITSes, using
msi-map property.

Signed-off-by: Laurentiu Tudor 
Cc: Rob Herring 
---
 .../devicetree/bindings/misc/fsl,qoriq-mc.txt | 30 +--
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt 
b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
index 9134e9bcca56..b0813b2d0493 100644
--- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
+++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
@@ -18,9 +18,9 @@ same hardware "isolation context" and a 10-bit value called 
an ICID
 the requester.
 
 The generic 'iommus' property is insufficient to describe the relationship
-between ICIDs and IOMMUs, so an iommu-map property is used to define
-the set of possible ICIDs under a root DPRC and how they map to
-an IOMMU.
+between ICIDs and IOMMUs, so the iommu-map and msi-map properties are used
+to define the set of possible ICIDs under a root DPRC and how they map to
+an IOMMU and a GIC ITS respectively.
 
 For generic IOMMU bindings, see
 Documentation/devicetree/bindings/iommu/iommu.txt.
@@ -28,6 +28,9 @@ Documentation/devicetree/bindings/iommu/iommu.txt.
 For arm-smmu binding, see:
 Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
 
+For GICv3 and GIC ITS bindings, see:
+Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml.
+
 Required properties:
 
 - compatible
@@ -119,6 +122,15 @@ Optional properties:
   associated with the listed IOMMU, with the iommu-specifier
   (i - icid-base + iommu-base).
 
+- msi-map: Maps an ICID to a GIC ITS and associated iommu-specifier
+  data.
+
+  The property is an arbitrary number of tuples of
+  (icid-base,iommu,iommu-base,length).
+
+  Any ICID in the interval [icid-base, icid-base + length) is
+  associated with the listed GIC ITS, with the iommu-specifier
+  (i - icid-base + iommu-base).
 Example:
 
 smmu: iommu@500 {
@@ -128,6 +140,16 @@ Example:
...
 };
 
+   gic: interrupt-controller@600 {
+   compatible = "arm,gic-v3";
+   ...
+   its: gic-its@602 {
+   compatible = "arm,gic-v3-its";
+   msi-controller;
+   ...
+   };
+   };
+
 fsl_mc: fsl-mc@80c00 {
 compatible = "fsl,qoriq-mc";
 reg = <0x0008 0x0c00 0 0x40>,/* MC portal base */
@@ -135,6 +157,8 @@ Example:
 msi-parent = <>;
 /* define map for ICIDs 23-64 */
 iommu-map = <23  23 41>;
+/* define msi map for ICIDs 23-64 */
+msi-map = <23  23 41>;
 #address-cells = <3>;
 #size-cells = <1>;
 
-- 
2.26.1

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


[PATCH 11/12] bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver

2020-05-21 Thread Lorenzo Pieralisi
From: Diana Craciun 

The DPRC driver is not taking into account the msi-map property
and assumes that the icid is the same as the stream ID. Although
this assumption is correct, generalize the code to include a
translation between icid and streamID.

Furthermore do not just copy the MSI domain from parent (for child
containers), but use the information provided by the msi-map property.

If the msi-map property is missing from the device tree retain the old
behaviour for backward compatibility ie the child DPRC objects
inherit the MSI domain from the parent.

Signed-off-by: Diana Craciun 
---
 drivers/bus/fsl-mc/dprc-driver.c| 31 ++---
 drivers/bus/fsl-mc/fsl-mc-bus.c |  4 +--
 drivers/bus/fsl-mc/fsl-mc-msi.c | 31 +
 drivers/bus/fsl-mc/fsl-mc-private.h |  6 ++--
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 15 +-
 5 files changed, 47 insertions(+), 40 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index c8b1c3842c1a..189bff2115a8 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -592,6 +592,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
bool mc_io_created = false;
bool msi_domain_set = false;
u16 major_ver, minor_ver;
+   struct irq_domain *mc_msi_domain;
 
if (!is_fsl_mc_bus_dprc(mc_dev))
return -EINVAL;
@@ -621,31 +622,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
return error;
 
mc_io_created = true;
+   }
 
-   /*
-* Inherit parent MSI domain:
-*/
-   dev_set_msi_domain(_dev->dev,
-  dev_get_msi_domain(parent_dev));
-   msi_domain_set = true;
+   mc_msi_domain = fsl_mc_find_msi_domain(_dev->dev);
+   if (!mc_msi_domain) {
+   dev_warn(_dev->dev,
+"WARNING: MC bus without interrupt support\n");
} else {
-   /*
-* This is a root DPRC
-*/
-   struct irq_domain *mc_msi_domain;
-
-   if (dev_is_fsl_mc(parent_dev))
-   return -EINVAL;
-
-   error = fsl_mc_find_msi_domain(parent_dev,
-  _msi_domain);
-   if (error < 0) {
-   dev_warn(_dev->dev,
-"WARNING: MC bus without interrupt support\n");
-   } else {
-   dev_set_msi_domain(_dev->dev, mc_msi_domain);
-   msi_domain_set = true;
-   }
+   dev_set_msi_domain(_dev->dev, mc_msi_domain);
+   msi_domain_set = true;
}
 
error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 8ead3f0238f2..824ff77bbe86 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -370,8 +370,8 @@ EXPORT_SYMBOL_GPL(fsl_mc_get_version);
 /**
  * fsl_mc_get_root_dprc - function to traverse to the root dprc
  */
-static void fsl_mc_get_root_dprc(struct device *dev,
-struct device **root_dprc_dev)
+void fsl_mc_get_root_dprc(struct device *dev,
+struct device **root_dprc_dev)
 {
if (!dev) {
*root_dprc_dev = NULL;
diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 8b9c66d7c4ff..e7bbff445a83 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -177,23 +177,30 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct 
fwnode_handle *fwnode,
return domain;
 }
 
-int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
-  struct irq_domain **mc_msi_domain)
+struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
 {
-   struct irq_domain *msi_domain;
-   struct device_node *mc_of_node = mc_platform_dev->of_node;
+   struct irq_domain *msi_domain = NULL;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
 
-   msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
-  DOMAIN_BUS_FSL_MC_MSI);
-   if (!msi_domain) {
-   pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
-  mc_of_node);
+   msi_domain = of_msi_map_get_device_domain(dev, mc_dev->icid,
+ DOMAIN_BUS_FSL_MC_MSI);
 
-   return -ENOENT;
+   /*
+* if the msi-map property is missing assume that all the
+* child containers inherit the domain from the parent
+*/
+   if (!msi_domain) {
+   struct device *root_dprc_dev;
+   struct device *bus_dev;
+
+   

[PATCH 07/12] of/device: Add input id to of_dma_configure()

2020-05-21 Thread Lorenzo Pieralisi
Devices sitting on proprietary busses have a device ID space that
is owned by the respective bus and related firmware bindings. In order
to let the generic OF layer handle the input translations to
an IOMMU id, for such busses the current of_dma_configure() interface
should be extended in order to allow the bus layer to provide the
device input id parameter - that is retrieved/assigned in bus
specific code and firmware.

Augment of_dma_configure() to add an optional input_id parameter,
leaving current functionality unchanged.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Robin Murphy 
Cc: Joerg Roedel 
Cc: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c |  4 ++-
 drivers/iommu/of_iommu.c| 53 +
 drivers/of/device.c |  8 +++--
 include/linux/of_device.h   | 16 --
 include/linux/of_iommu.h|  6 ++--
 5 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 40526da5c6a6..8ead3f0238f2 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -118,11 +118,13 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
kobj_uevent_env *env)
 static int fsl_mc_dma_configure(struct device *dev)
 {
struct device *dma_dev = dev;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   u32 input_id = mc_dev->icid;
 
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
 
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index ad96b87137d6..4516d5bf6cc9 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -139,25 +139,53 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 
alias, void *data)
return err;
 }
 
-static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev,
-   struct device_node *master_np)
+static int of_iommu_configure_dev_id(struct device_node *master_np,
+struct device *dev,
+const u32 *id)
 {
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
+   err = of_map_id(master_np, *id, "iommu-map",
 "iommu-map-mask", _spec.np,
 iommu_spec.args);
if (err)
return err == -ENODEV ? NO_IOMMU : err;
 
-   err = of_iommu_xlate(_dev->dev, _spec);
+   err = of_iommu_xlate(dev, _spec);
of_node_put(iommu_spec.np);
return err;
 }
 
+static int of_iommu_configure_dev(struct device_node *master_np,
+ struct device *dev)
+{
+   struct of_phandle_args iommu_spec;
+   int err = NO_IOMMU, idx = 0;
+
+   while (!of_parse_phandle_with_args(master_np, "iommus",
+  "#iommu-cells",
+  idx, _spec)) {
+   err = of_iommu_xlate(dev, _spec);
+   of_node_put(iommu_spec.np);
+   idx++;
+   if (err)
+   break;
+   }
+
+   return err;
+}
+
+static int of_iommu_configure_device(struct device_node *master_np,
+struct device *dev, const u32 *id)
+{
+   return (id) ? of_iommu_configure_dev_id(master_np, dev, id) :
+ of_iommu_configure_dev(master_np, dev);
+}
+
 const struct iommu_ops *of_iommu_configure(struct device *dev,
-  struct device_node *master_np)
+  struct device_node *master_np,
+  const u32 *id)
 {
const struct iommu_ops *ops = NULL;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -188,21 +216,8 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
pci_request_acs();
err = pci_for_each_dma_alias(to_pci_dev(dev),
 of_pci_iommu_init, );
-   } else if (dev_is_fsl_mc(dev)) {
-   err = of_fsl_mc_iommu_init(to_fsl_mc_device(dev), master_np);
} else {
-   struct of_phandle_args iommu_spec;
-   int idx = 0;
-
-   while (!of_parse_phandle_with_args(master_np, "iommus",
-  "#iommu-cells",
-  idx, _spec)) {
-   err = of_iommu_xlate(dev, _spec);
-   of_node_put(iommu_spec.np);
-   idx++;
-   if (err)
-   break;
-  

Re: [PATCH v7 18/24] iommu/arm-smmu-v3: Add support for Hardware Translation Table Update

2020-05-21 Thread Will Deacon
On Tue, May 19, 2020 at 07:54:56PM +0200, Jean-Philippe Brucker wrote:
> If the SMMU supports it and the kernel was built with HTTU support,
> enable hardware update of access and dirty flags. This is essential for
> shared page tables, to reduce the number of access faults on the fault
> queue. Normal DMA with io-pgtables doesn't currently use the access or
> dirty flags.
> 
> We can enable HTTU even if CPUs don't support it, because the kernel
> always checks for HW dirty bit and updates the PTE flags atomically.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/iommu/arm-smmu-v3.c | 24 +++-
>  1 file changed, 23 insertions(+), 1 deletion(-)

How does this work if the SMMU isn't cache coherent? I'm guessing we don't
want to enable any SVA stuff in that case, but I couldn't spot where that
was being enforced. Did I just miss it?

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


Re: [PATCH v7 00/24] iommu: Shared Virtual Addressing for SMMUv3

2020-05-21 Thread Will Deacon
Hi Jean-Philippe,

On Tue, May 19, 2020 at 07:54:38PM +0200, Jean-Philippe Brucker wrote:
> Shared Virtual Addressing (SVA) allows to share process page tables with
> devices using the IOMMU, PASIDs and I/O page faults. Add SVA support to
> the Arm SMMUv3 driver.
> 
> Since v6 [1]:
> * Rename ioasid_free() to ioasid_put() in patch 02, requiring changes to
>   the Intel drivers.
> * Use mmu_notifier_register() in patch 16 to avoid copying the ops and
>   simplify the invalidate() notifier in patch 17.
> * As a result, replace context spinlock with a mutex. Simplified locking in
>   patch 11 (That patch still looks awful, but I think the series is more
>   readable overall). And I've finally been able to remove the GFP_ATOMIC
>   allocations.
> * Use a single patch (04) for io-pgfault.c, since the code was simplified
>   in v6. Fixed partial list in patch 04.

There's an awful lot here and it stretches across quite a few subsystems,
with different git trees. What's the plan for merging it?

I'm happy to take some of the arm64 and smmu changes for 5.8, then perhaps
we can review what's left and target 5.9? It would also be helpful to split
that up into separate series where there aren't strong dependencies, I
think.

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


Re: [PATCH v2 3/4] iommu/arm-smmu-v3: Use pci_ats_supported()

2020-05-21 Thread Will Deacon
On Wed, May 20, 2020 at 05:22:02PM +0200, Jean-Philippe Brucker wrote:
> The new pci_ats_supported() function checks if a device supports ATS and
> is allowed to use it.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/iommu/arm-smmu-v3.c | 20 +++-
>  1 file changed, 7 insertions(+), 13 deletions(-)

Acked-by: Will Deacon 

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


Re: [PATCH 09/15] device core: Add ability to handle multiple dma offsets

2020-05-21 Thread Christoph Hellwig
On Wed, May 20, 2020 at 03:36:16PM -0700, Dan Williams wrote:
> Certainly blindly cc'ing everyone recommended by
> scripts/get_maintainers.pl is overkill, but finding that subset is a
> bit of an art.

Yes.  But I'd rather be not Cced and just find the complete thread on
a list.  But all the lists I'm on and have managed to read through
yesterday didn't have the full series either.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu