[Patch v2] iommu/vt-d: Adjsut the return value of the parse_ioapics_under_ir

2015-10-21 Thread Baoquan He
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

2015-10-21 Thread Yong Wu
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

2015-10-21 Thread Joerg Roedel
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

2015-10-21 Thread Joerg Roedel
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

2015-10-21 Thread Joerg Roedel
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()

2015-10-21 Thread Joerg Roedel
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

2015-10-21 Thread Joerg Roedel
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

2015-10-21 Thread Joerg Roedel
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

2015-10-21 Thread Joerg Roedel
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()

2015-10-21 Thread Joerg Roedel
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

2015-10-21 Thread Joerg Roedel
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()

2015-10-21 Thread Geert Uytterhoeven
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()

2015-10-21 Thread Benjamin Herrenschmidt
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.

2015-10-21 Thread Yong Wu
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

2015-10-21 Thread David Woodhouse
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