RE: [PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc
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
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
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
[+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
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
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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()
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
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
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()
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
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