[Patch v2] iommu/vt-d: Adjsut the return value of the parse_ioapics_under_ir
Adjust the return value of parse_ioapics_under_ir as negative value representing failure and "0" representing succcess. Just make it consistent with other function implementation, and we can judge if calling is successfull by if (!parse_ioapics_under_ir()) style. Signed-off-by: Baoquan He --- v1->v2: Drop the patch 2/1 of v1 patchset since it's a wrong patch. Joerg suggested that replace "-1" with "-ENODEV" which is more specific. drivers/iommu/intel_irq_remapping.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 9ec4e0d..12b11be 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -672,7 +672,7 @@ static int __init intel_prepare_irq_remapping(void) if (!dmar_ir_support()) return -ENODEV; - if (parse_ioapics_under_ir() != 1) { + if (!parse_ioapics_under_ir()) { pr_info("Not enabling interrupt remapping\n"); goto error; } @@ -916,7 +916,7 @@ static int __init parse_ioapics_under_ir(void) } if (!ir_supported) - return 0; + return -ENODEV; for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { int ioapic_id = mpc_ioapic_id(ioapic_idx); @@ -928,7 +928,7 @@ static int __init parse_ioapics_under_ir(void) } } - return 1; + return 0; } static int __init ir_dev_scope_init(void) -- 2.1.0 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH v5 0/6] MT8173 IOMMU SUPPORT
On Wed, 2015-10-14 at 14:56 +0200, Joerg Roedel wrote: > On Fri, Oct 09, 2015 at 10:23:02AM +0800, Yong Wu wrote: > > Yong Wu (6): > > dt-bindings: iommu: Add binding for mediatek IOMMU > > dt-bindings: mediatek: Add smi dts binding > > iommu: add ARM short descriptor page table allocator > > memory: mediatek: Add SMI driver > > iommu/mediatek: Add mt8173 IOMMU driver > > dts: mt8173: Add iommu/smi nodes for mt8173 > > > > .../devicetree/bindings/iommu/mediatek,iommu.txt | 61 ++ > > .../memory-controllers/mediatek,smi-larb.txt | 25 + > > .../bindings/memory-controllers/mediatek,smi.txt | 24 + > > arch/arm64/boot/dts/mediatek/mt8173.dtsi | 81 ++ > > drivers/iommu/Kconfig | 33 + > > drivers/iommu/Makefile | 2 + > > drivers/iommu/io-pgtable-arm-short.c | 827 > > + > > drivers/iommu/io-pgtable-arm.c | 3 - > > drivers/iommu/io-pgtable.c | 3 + > > drivers/iommu/io-pgtable.h | 18 +- > > drivers/iommu/mtk_iommu.c | 767 > > +++ > > drivers/memory/Kconfig | 8 + > > drivers/memory/Makefile| 1 + > > drivers/memory/mtk-smi.c | 274 +++ > > include/dt-bindings/memory/mt8173-larb-port.h | 105 +++ > > include/soc/mediatek/smi.h | 60 ++ > > So this contains not only IOMMU code. Are the patches dependent on each > other or can the iommu parts be merged independently? > > Joerg > Hi Joerg, Sorry for reply late. The ARM short descriptor is independent. This one can be merged independently. But the mtk-iommu depend on the drivers/memory/mtk-smi.c(mtk-iommu has called a function of the mtk-smi). So if there is dependence here, How should we do to merge them? ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 7/8] iommu: Remove is_pci_dev() fall-back from iommu_group_get_for_dev
From: Joerg Roedel All callers of iommu_group_get_for_dev() provide a device_group call-back now, so this fall-back is no longer needed. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index a80c9c5..e2b5526 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -845,8 +845,6 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) if (ops && ops->device_group) group = ops->device_group(dev); - else if (dev_is_pci(dev)) - group = pci_device_group(dev); if (IS_ERR(group)) return group; -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 3/8] iommu: Add generic_device_group() function
From: Joerg Roedel This function can be used as a device_group call-back and just allocates one iommu-group per device. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 15 +++ include/linux/iommu.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index fdea700..a80c9c5 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -728,6 +728,21 @@ static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque) } /* + * Generic device_group call-back function. It just allocates one + * iommu-group per device. + */ +struct iommu_group *generic_device_group(struct device *dev) +{ + struct iommu_group *group; + + group = iommu_group_alloc(); + if (IS_ERR(group)) + return NULL; + + return group; +} + +/* * Use standard PCI bus topology, isolation features, and DMA alias quirks * to find or create an IOMMU group for a device. */ diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 8026e6a..c73824f 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -318,6 +318,8 @@ static inline size_t iommu_map_sg(struct iommu_domain *domain, /* PCI device grouping function */ extern struct iommu_group *pci_device_group(struct device *dev); +/* Generic device grouping function */ +extern struct iommu_group *generic_device_group(struct device *dev); #else /* CONFIG_IOMMU_API */ -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 4/8] iommu: Add device_group call-back to x86 iommu drivers
From: Joerg Roedel Set the device_group call-back to pci_device_group() for the Intel VT-d and the AMD IOMMU driver. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 1 + drivers/iommu/intel-iommu.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 08d2775..a76a3e5 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3198,6 +3198,7 @@ static const struct iommu_ops amd_iommu_ops = { .iova_to_phys = amd_iommu_iova_to_phys, .add_device = amd_iommu_add_device, .remove_device = amd_iommu_remove_device, + .device_group = pci_device_group, .get_dm_regions = amd_iommu_get_dm_regions, .put_dm_regions = amd_iommu_put_dm_regions, .pgsize_bitmap = AMD_IOMMU_PGSIZES, diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 35365f0..f2b276d 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4873,6 +4873,7 @@ static const struct iommu_ops intel_iommu_ops = { .iova_to_phys = intel_iommu_iova_to_phys, .add_device = intel_iommu_add_device, .remove_device = intel_iommu_remove_device, + .device_group = pci_device_group, .pgsize_bitmap = INTEL_IOMMU_PGSIZES, }; -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 8/8] iommu: Move default domain allocation to iommu_group_get_for_dev()
From: Joerg Roedel Now that the iommu core support for iommu groups is not pci-centric anymore, we can move default domain allocation to the bus independent iommu_group_get_for_dev() function. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 18 ++ 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index e2b5526..abae363 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -810,14 +810,6 @@ struct iommu_group *pci_device_group(struct device *dev) if (IS_ERR(group)) return NULL; - /* -* Try to allocate a default domain - needs support from the -* IOMMU driver. -*/ - group->default_domain = __iommu_domain_alloc(pdev->dev.bus, -IOMMU_DOMAIN_DMA); - group->domain = group->default_domain; - return group; } @@ -849,6 +841,16 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) if (IS_ERR(group)) return group; + /* +* Try to allocate a default domain - needs support from the +* IOMMU driver. +*/ + if (!group->default_domain) { + group->default_domain = __iommu_domain_alloc(dev->bus, +IOMMU_DOMAIN_DMA); + group->domain = group->default_domain; + } + ret = iommu_group_add_device(group, dev); if (ret) { iommu_group_put(group); -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 1/8] iommu: Revive device_group iommu-ops call-back
From: Joerg Roedel That call-back is currently unused, change it into a call-back function for finding the right IOMMU group for a device. This is a first step to remove the hard-coded PCI dependency in the iommu-group code. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 9 ++--- include/linux/iommu.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 049df49..5637463 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -814,6 +814,7 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev) */ struct iommu_group *iommu_group_get_for_dev(struct device *dev) { + const struct iommu_ops *ops = dev->bus->iommu_ops; struct iommu_group *group; int ret; @@ -821,10 +822,12 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) if (group) return group; - if (!dev_is_pci(dev)) - return ERR_PTR(-EINVAL); + group = ERR_PTR(-EINVAL); - group = iommu_group_get_for_pci_dev(to_pci_dev(dev)); + if (ops && ops->device_group) + group = ops->device_group(dev); + else if (dev_is_pci(dev)) + group = iommu_group_get_for_pci_dev(to_pci_dev(dev)); if (IS_ERR(group)) return group; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f9c1b6d..5a19952 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -167,7 +167,7 @@ struct iommu_ops { phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); - int (*device_group)(struct device *dev, unsigned int *groupid); + struct iommu_group *(*device_group)(struct device *dev); int (*domain_get_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); int (*domain_set_attr)(struct iommu_domain *domain, -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 6/8] iommu/arm-smmu: Switch to device_group call-back
From: Joerg Roedel This converts the ARM SMMU and the SMMUv3 driver to use the new device_group call-back. Cc: Will Deacon Signed-off-by: Joerg Roedel --- drivers/iommu/arm-smmu-v3.c | 1 + drivers/iommu/arm-smmu.c| 77 +++-- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 286e890..e9e591c 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -1902,6 +1902,7 @@ static struct iommu_ops arm_smmu_ops = { .iova_to_phys = arm_smmu_iova_to_phys, .add_device = arm_smmu_add_device, .remove_device = arm_smmu_remove_device, + .device_group = pci_device_group, .domain_get_attr= arm_smmu_domain_get_attr, .domain_set_attr= arm_smmu_domain_set_attr, .pgsize_bitmap = -1UL, /* Restricted during device attach */ diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 48a39df..b4c0629 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1292,33 +1292,25 @@ static void __arm_smmu_release_pci_iommudata(void *data) kfree(data); } -static int arm_smmu_add_pci_device(struct pci_dev *pdev) +static int arm_smmu_init_pci_device(struct pci_dev *pdev, + struct iommu_group *group) { - int i, ret; - u16 sid; - struct iommu_group *group; struct arm_smmu_master_cfg *cfg; - - group = iommu_group_get_for_dev(&pdev->dev); - if (IS_ERR(group)) - return PTR_ERR(group); + u16 sid; + int i; cfg = iommu_group_get_iommudata(group); if (!cfg) { cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) { - ret = -ENOMEM; - goto out_put_group; - } + if (!cfg) + return -ENOMEM; iommu_group_set_iommudata(group, cfg, __arm_smmu_release_pci_iommudata); } - if (cfg->num_streamids >= MAX_MASTER_STREAMIDS) { - ret = -ENOSPC; - goto out_put_group; - } + if (cfg->num_streamids >= MAX_MASTER_STREAMIDS) + return -ENOSPC; /* * Assume Stream ID == Requester ID for now. @@ -1334,16 +1326,13 @@ static int arm_smmu_add_pci_device(struct pci_dev *pdev) cfg->streamids[cfg->num_streamids++] = sid; return 0; -out_put_group: - iommu_group_put(group); - return ret; } -static int arm_smmu_add_platform_device(struct device *dev) +static int arm_smmu_init_platform_device(struct device *dev, +struct iommu_group *group) { - struct iommu_group *group; - struct arm_smmu_master *master; struct arm_smmu_device *smmu = find_smmu_for_device(dev); + struct arm_smmu_master *master; if (!smmu) return -ENODEV; @@ -1352,21 +1341,20 @@ static int arm_smmu_add_platform_device(struct device *dev) if (!master) return -ENODEV; - /* No automatic group creation for platform devices */ - group = iommu_group_alloc(); - if (IS_ERR(group)) - return PTR_ERR(group); - iommu_group_set_iommudata(group, &master->cfg, NULL); - return iommu_group_add_device(group, dev); + + return 0; } static int arm_smmu_add_device(struct device *dev) { - if (dev_is_pci(dev)) - return arm_smmu_add_pci_device(to_pci_dev(dev)); + struct iommu_group *group; - return arm_smmu_add_platform_device(dev); + group = iommu_group_get_for_dev(dev); + if (IS_ERR(group)) + return PTR_ERR(group); + + return 0; } static void arm_smmu_remove_device(struct device *dev) @@ -1374,6 +1362,32 @@ static void arm_smmu_remove_device(struct device *dev) iommu_group_remove_device(dev); } +static struct iommu_group *arm_smmu_device_group(struct device *dev) +{ + struct iommu_group *group; + int ret; + + if (dev_is_pci(dev)) + group = pci_device_group(dev); + else + group = generic_device_group(dev); + + if (IS_ERR(group)) + return group; + + if (dev_is_pci(dev)) + ret = arm_smmu_init_pci_device(to_pci_dev(dev), group); + else + ret = arm_smmu_init_platform_device(dev, group); + + if (ret) { + iommu_group_put(group); + group = ERR_PTR(ret); + } + + return group; +} + static int arm_smmu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr attr, void *data) { @@ -1430,6 +1444,7 @@ static struct iommu_ops arm_smmu_ops = { .iova_to_phys = arm_smmu
[PATCH 5/8] iommu/fsl: Convert to device_group call-back
From: Joerg Roedel Convert the fsl pamu driver to make use of the new device_group call-back. Cc: Varun Sethi Signed-off-by: Joerg Roedel --- drivers/iommu/fsl_pamu_domain.c | 41 - 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 1d45293..da0e1e3 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c @@ -923,7 +923,7 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev) pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl); /* We can partition PCIe devices so assign device group to the device */ if (pci_endpt_partioning) { - group = iommu_group_get_for_dev(&pdev->dev); + group = pci_device_group(&pdev->dev); /* * PCIe controller is not a paritionable entity @@ -956,44 +956,34 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev) return group; } -static int fsl_pamu_add_device(struct device *dev) +static struct iommu_group *fsl_pamu_device_group(struct device *dev) { struct iommu_group *group = ERR_PTR(-ENODEV); - struct pci_dev *pdev; - const u32 *prop; - int ret = 0, len; + int len; /* * For platform devices we allocate a separate group for * each of the devices. */ - if (dev_is_pci(dev)) { - pdev = to_pci_dev(dev); - /* Don't create device groups for virtual PCI bridges */ - if (pdev->subordinate) - return 0; + if (dev_is_pci(dev)) + group = get_pci_device_group(to_pci_dev(dev)); + else if (of_get_property(dev->of_node, "fsl,liodn", &len)) + group = get_device_iommu_group(dev); - group = get_pci_device_group(pdev); + return group; +} - } else { - prop = of_get_property(dev->of_node, "fsl,liodn", &len); - if (prop) - group = get_device_iommu_group(dev); - } +static int fsl_pamu_add_device(struct device *dev) +{ + struct iommu_group *group; + group = iommu_group_get_for_dev(dev); if (IS_ERR(group)) return PTR_ERR(group); - /* -* Check if device has already been added to an iommu group. -* Group could have already been created for a PCI device in -* the iommu_group_get_for_dev path. -*/ - if (!dev->iommu_group) - ret = iommu_group_add_device(group, dev); - iommu_group_put(group); - return ret; + + return 0; } static void fsl_pamu_remove_device(struct device *dev) @@ -1072,6 +1062,7 @@ static const struct iommu_ops fsl_pamu_ops = { .domain_get_attr = fsl_pamu_get_domain_attr, .add_device = fsl_pamu_add_device, .remove_device = fsl_pamu_remove_device, + .device_group = fsl_pamu_device_group, }; int __init pamu_domain_init(void) -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 2/8] iommu: Export and rename iommu_group_get_for_pci_dev()
From: Joerg Roedel Rename that function to pci_device_group() and export it, so that IOMMU drivers can use it as their device_group call-back. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 8 ++-- include/linux/iommu.h | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 5637463..fdea700 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -731,13 +731,17 @@ static int get_pci_alias_or_group(struct pci_dev *pdev, u16 alias, void *opaque) * Use standard PCI bus topology, isolation features, and DMA alias quirks * to find or create an IOMMU group for a device. */ -static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev) +struct iommu_group *pci_device_group(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct group_for_pci_data data; struct pci_bus *bus; struct iommu_group *group = NULL; u64 devfns[4] = { 0 }; + if (WARN_ON(!dev_is_pci(dev))) + return ERR_PTR(-EINVAL); + /* * Find the upstream DMA alias for the device. A device must not * be aliased due to topology in order to have its own IOMMU group. @@ -827,7 +831,7 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev) if (ops && ops->device_group) group = ops->device_group(dev); else if (dev_is_pci(dev)) - group = iommu_group_get_for_pci_dev(to_pci_dev(dev)); + group = pci_device_group(dev); if (IS_ERR(group)) return group; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 5a19952..8026e6a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -316,6 +316,9 @@ static inline size_t iommu_map_sg(struct iommu_domain *domain, return domain->ops->map_sg(domain, iova, sg, nents, prot); } +/* PCI device grouping function */ +extern struct iommu_group *pci_device_group(struct device *dev); + #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
[PATCH 0/8] iommu: Make core iommu-groups code more generic
Hi, this patch-set makes the core code for managing iommu-groups more generic by lifting its dependencies on PCI. The core function iommu_group_get_for_dev() had a hard dev_is_pci() check in it, followed by PCI specific handling. This check is removed in favour of the the revived device_group() iommu-ops call-back. With this call-back an IOMMU driver can define how the devices it manages are grouped together. Two functions, one generic and one for PCI devices, are provided that can be uses as a device_group() call-back or might be used in such a call-back. The existing drivers making use of the iommu_group_get_for_dev() function are converted to this call-back. Joerg Joerg Roedel (8): iommu: Revive device_group iommu-ops call-back iommu: Export and rename iommu_group_get_for_pci_dev() iommu: Add generic_device_group() function iommu: Add device_group call-back to x86 iommu drivers iommu/fsl: Convert to device_group call-back iommu/arm-smmu: Switch to device_group call-back iommu: Remove is_pci_dev() fall-back from iommu_group_get_for_dev iommu: Move default domain allocation to iommu_group_get_for_dev() drivers/iommu/amd_iommu.c | 1 + drivers/iommu/arm-smmu-v3.c | 1 + drivers/iommu/arm-smmu.c| 77 - drivers/iommu/fsl_pamu_domain.c | 41 +- drivers/iommu/intel-iommu.c | 1 + drivers/iommu/iommu.c | 46 +--- include/linux/iommu.h | 7 +++- 7 files changed, 105 insertions(+), 69 deletions(-) -- 1.9.1 ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH] iommu-common: fix return type of iommu_tbl_range_alloc()
Hi Andre, Jörg, On Fri, Sep 18, 2015 at 11:09 AM, Andre Przywara wrote: > Though iommu_tbl_range_alloc() is only used by Sparc code, the > function itself lives in lib/iommu-common.c and is thus included in > other architecture's code as well. > When compiled on a 32-bit architecture using 64-bit DMA addresses > (ARM with LPAE), there is a compiler warning about a type mismatch > between dma_addr_t and the return type of this function: > > In file included from /src/linux/include/linux/dma-mapping.h:86:0, > from /src/linux/lib/iommu-common.c:11: > /src/linux/lib/iommu-common.c: In function 'iommu_tbl_range_alloc': > /src/linux/arch/arm/include/asm/dma-mapping.h:16:24: warning: large integer > implicitly truncated to unsigned type [-Woverflow] > #define DMA_ERROR_CODE (~(dma_addr_t)0x0) > ^ > /src/linux/lib/iommu-common.c:127:10: note: in expansion of macro > 'DMA_ERROR_CODE' >return DMA_ERROR_CODE; While I welcome a fix for this annoying warning on arm... > --- a/lib/iommu-common.c > +++ b/lib/iommu-common.c > @@ -99,15 +99,16 @@ void iommu_tbl_pool_init(struct iommu_map_table *iommu, > } > EXPORT_SYMBOL(iommu_tbl_pool_init); > > -unsigned long iommu_tbl_range_alloc(struct device *dev, > - struct iommu_map_table *iommu, > - unsigned long npages, > - unsigned long *handle, > - unsigned long mask, > - unsigned int align_order) > +dma_addr_t iommu_tbl_range_alloc(struct device *dev, > +struct iommu_map_table *iommu, > +unsigned long npages, > +unsigned long *handle, > +unsigned long mask, > +unsigned int align_order) > { > unsigned int pool_hash = __this_cpu_read(iommu_hash_common); > - unsigned long n, end, start, limit, boundary_size; > + dma_addr_t n; > + unsigned long end, start, limit, boundary_size; ... this doesn't look like the right fix. Apparently 64-bit parisc doesn't set ARCH_DMA_ADDR_T_64BIT, hence assigning (64-bit) "unsigned long" to (32-bit) dma_addr_t will truncate the address. Does this function really need to return DMA_ERROR_CODE in case of failure? Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu
Re: [PATCH 09/22] PCI: Add pci_peer_traffic_supported()
On Tue, 2015-09-15 at 12:10 -0500, Will Davis wrote: > +bool pci_peer_traffic_supported(struct pci_dev *dev, struct pci_dev > *peer) > +{ > +>> struct pci_host_bridge *dev_host_bridge; > +>> struct pci_host_bridge *peer_host_bridge; > + > +>> /* > +>> * Disallow the peer-to-peer traffic if the devices do not share a > +>> * host bridge. The PCI specifications does not make any guarantees > +>> * about P2P capabilities between devices under separate domains. > +>> * > +>> * PCI Local Bus Specification Revision 3.0, section 3.10: > +>> *"Peer-to-peer transactions crossing multiple host bridges > +>> * PCI host bridges may, but are not required to, support PCI > +>> * peer-to-peer transactions that traverse multiple PCI host > +>> * bridges." > +>> */ > + dev_host_bridge = pci_find_host_bridge(dev->bus); > +>> peer_host_bridge = pci_find_host_bridge(peer->bus); > +>> if (dev_host_bridge != peer_host_bridge) > +>> > return false; This needs to be platform specific. Some architectures will allow routing between multiple bridges, some won't. > + /* > +>> > * Access Control Services (ACS) Checks > +>> > * > +>> > * ACS has a capability bit for P2P Request Redirects (RR), > +>> > * but unfortunately it doesn't tell us much about the real > +>> > * capabilities of the hardware. > +>> > * > +>> > * PCI Express Base Specification Revision 3.0, section > +>> > * 6.12.1.1: > +>> > *"ACS P2P Request Redirect: must be implemented by Root > +>> > * Ports that support peer-to-peer traffic with other > +>> > * Root Ports; [80]" > +>> > * but > +>> > *"[80] Root Port indication of ACS P2P Request Redirect > +>> > * or ACS P2P Completion Redirect support does not imply > +>> > * any particular level of peer-to-peer support by the > +>> > * Root Complex, or that peer-to-peer traffic is > +>> > * supported at all" > +>> > */ > +>> > struct pci_dev *rpdev = dev->bus->self; > +>> > struct pci_dev *rppeer = peer->bus->self; > +>> > struct pci_dev *common_upstream; > +>> > int pos; > +>> > u16 cap; > + > +>> > while ((rpdev) && (pci_is_pcie(rpdev)) && > +>> >(pci_pcie_type(rpdev) != PCI_EXP_TYPE_ROOT_PORT)) > +>> > > rpdev = rpdev->bus->self; > + > +>> > while ((rppeer) && (pci_is_pcie(rppeer)) && > +>> >(pci_pcie_type(rppeer) != PCI_EXP_TYPE_ROOT_PORT)) > +>> > > rppeer = rppeer->bus->self; > + > +>> > common_upstream = pci_find_common_upstream_dev(dev, peer); > + > +>> > /* > +>> > * If ACS is not implemented, we have no idea about P2P > +>> > * support. Optimistically allow this if there is a common > +>> > * upstream device. > +>> > */ > +>> > pos = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ACS); > +>> > if (!pos) > +>> > > return common_upstream != NULL; We might need a hook as well here. PLX switch may or may not allow it depending on some configuration bits. > + /* > +>> > * If the devices are under the same root port and have a > common > +>> > * upstream device, allow if the root port is further upstream > +>> > * from the common upstream device and the common upstream > +>> > * device has Upstream Forwarding disabled, or if the root > port > +>> > * is the common upstream device and ACS is not implemented. > +>> > */ > +>> > pci_read_config_word(rpdev, pos + PCI_ACS_CAP, &cap); > +>> > if ((rpdev == rppeer && common_upstream) && > +>> > (((common_upstream != rpdev) && > +>> > !pci_acs_enabled(common_upstream, PCI_ACS_UF)) || > +>> > ((common_upstream == rpdev) && ((cap & PCI_ACS_RR) == > 0 > +>> > > return true; > + > +>> > /* > +>> > * If ACS RR is implemented and disabled, allow only if the > +>> > * devices are under the same root port. > +>> > */ > +>> > if (cap & PCI_ACS_RR && !pci_acs_enabled(rpdev, PCI_ACS_RR)) > +>> > > return rpdev == rppeer; > + > +>> > /* > +>> > * If ACS RR is not implemented, or is implemented and > enabled, > +>> > * only allow if there's a translation agent enabled to do the > +>> > * redirect. > +>> > */ > +>> > return iommu_present(&pci_bus_type); > +>> } > + > +>> return false; > +} > + > #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE > static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM
Re: [PATCH v4 3/6] iommu: add ARM short descriptor page table allocator.
On Fri, 2015-10-09 at 19:19 +0100, Will Deacon wrote: > On Fri, Oct 09, 2015 at 06:41:51PM +0100, Robin Murphy wrote: > > On 09/10/15 16:57, Will Deacon wrote: > > >On Tue, Sep 22, 2015 at 03:12:47PM +0100, Yong Wu wrote: > > >> I would like to show you a problem I met, The recursion here may > > >>lead to stack overflow while we test FHD video decode. > > >> > > >> From the log, I get the internal variable in the error case: the > > >>"size" is 0x10, the "iova" is 0xfea0, but at that time the > > >>"blk_size" is 0x1000 as it was the map of small-page. so it enter the > > >>recursion here. > > >> > > >> After check the unmap flow, there is only a iommu_unmap in > > >>__iommu_dma_unmap, and it won't check the physical address align in > > >>iommu_unmap. > > > > > >That sounds like a bug in __iommu_dma_unmap. Robin? > > > > Isn't it just cf27ec930be9 again wearing different trousers? All I do is > > call iommu_unmap with the same total size that was mapped originally. > > I don't think it's the same as that issue, which was to do with installing > block mappings over the top of an existing table entry. The problem here > seems to be that we don't walk the page table properly on unmap. > > The long descriptor code has: > > /* If the size matches this level, we're in the right place */ > if (size == blk_size) { > __arm_lpae_set_pte(ptep, 0, &data->iop.cfg); > > if (!iopte_leaf(pte, lvl)) { > /* Also flush any partial walks */ > tlb->tlb_add_flush(iova, size, false, cookie); > tlb->tlb_sync(cookie); > ptep = iopte_deref(pte, data); > __arm_lpae_free_pgtable(data, lvl + 1, ptep); > } else { > tlb->tlb_add_flush(iova, size, true, cookie); > } > > return size; > } else if (iopte_leaf(pte, lvl)) { > /* >* Insert a table at the next level to map the old region, >* minus the part we want to unmap >*/ > return arm_lpae_split_blk_unmap(data, iova, size, > iopte_prot(pte), lvl, ptep, > blk_size); > } > > why doesn't something similar work for short descriptors? > > Will Hi Will, There are some different between long and short descriptor, I can not use it directly. 1. Long descriptor control the blk_size with 3 levels easily whose lvl1 is 4KB, lvl2 is 2MB and lvl3 is 1GB in stage 1. It have 3 levels pagetable, then it use 3 levels block_size here. It is ok. But I don't use the "level" in short descriptor. At the beginning of designing short, I planned to use 4 levels whose lvl1 is 4KB, lvl2 is 64KB, lvl3 is 1MB, lvl4 is 16MB in short descriptor. then the code may be more similar with long descriptor. But there is only 2 levels pagetable in short. if we use 4 levels here, It may lead to misunderstand. so I don't use the "level" and list the four case in map and unmap. (If you think short-descriptor could use 4 level like above, I can try it.) 2. Following the unmap in long, if it's not a leaf, we free the pagetable, then we can delete do-while. I have tested this: //=== static int arm_short_unmap(struct io_pgtable_ops *ops, unsigned long iova, size_t size) { struct arm_short_io_pgtable *data = io_pgtable_ops_to_data(ops); struct io_pgtable_cfg *cfg = &data->iop.cfg; void *cookie = data->iop.cookie; arm_short_iopte *pgd, *pte = NULL; arm_short_iopte pgd_tmp, pte_tmp = 0; unsigned int blk_size = 0, blk_base; bool empty = false, split = false; int i; blk_size = arm_short_iova_to_blk_size(ops, iova); if (WARN_ON(!blk_size)) return 0; blk_base = iova & ~(blk_size - 1); pgd = (arm_short_iopte *)data->pgd + ARM_SHORT_PGD_IDX(blk_base); if (size == SZ_1M || size == SZ_16M) {/* section or supersection */ for (i = 0; i < size/SZ_1M; i++, pgd++, blk_base += SZ_1M) { pgd_tmp = *pgd; __arm_short_set_pte(pgd, 0, 1, cfg); cfg->tlb->tlb_add_flush(blk_base, SZ_1M, true, cookie); cfg->tlb->tlb_sync(cookie); /* Lvl2 pgtable should be freed while current is pgtable */ if (ARM_SHORT_PGD_TYPE_IS_PGTABLE(pgd_tmp)) __arm_short_free_pgtable( ARM_SHORT_GET_PGTABLE_VA(pgd_tmp), ARM_SHORT_BYTES_PER_PTE, false, cfg); /* Split is needed while unmap 1M in supersection */ if (size == SZ_1M && blk_size == SZ_16M)
[GIT PULL] Minor intel-iommu fix for 4.3
Linus, please pull from git://git.infradead.org/intel-iommu.git for-linus-20151021 This contains a single fix, for when the IOMMU API is used to overlay an existing mapping comprised of 4KiB pages, with a mapping that can use superpages. For the *first* superpage in the new mapping, we were correctly¹ freeing the old bottom-level page table page and clearing the link to it, before installing the superpage. For subsequent superpages, however, we weren't. This causes a memory leak, and a warning about setting a PTE which is already set. ¹ Well, not *entirely* correctly. We just free the page table pages right there and then, which is wrong. In fact they should only be freed *after* the IOTLB is flushed so we know the hardware will no longer be looking at them and in fact I note that the IOTLB flush is completely missing from the intel_iommu_map() code path, although it needs to be there if it's permitted to overwrite existing mappings. Fixing those is somewhat more intrusive though, and will probably need to wait for 4.4 at this point. Christian Zander (1): iommu/vt-d: fix range computation when making room for large pages drivers/iommu/intel-iommu.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) -- David WoodhouseOpen Source Technology Centre david.woodho...@intel.com Intel Corporation smime.p7s Description: S/MIME cryptographic signature ___ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu