[PATCH v6 6/6] iommu/tegra-smmu: Add pagetable mappings to debugfs

2021-09-13 Thread Nicolin Chen
This patch dumps all active mapping entries from pagetable
to a debugfs directory named "mappings".

Attaching an example:

SWGROUP: hc
as->id: 0
as->attr: R|W|N
as->pd_dma: 0x80c03000
{
[index: 1023] 0xf0080c3e (count: 2)
{
PTE RANGE  | ATTR | PHYS   | IOVA   
| SIZE
[#1022, #1023] | 0x5  | 0x00010bbf1000 | 0xe000 
| 0x2000
}
}
Total PDE count: 1
Total PTE count: 2

Signed-off-by: Nicolin Chen 
---
 drivers/iommu/tegra-smmu.c | 145 +
 1 file changed, 145 insertions(+)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 68c34a4a0ecc..aac977e181f6 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -46,6 +46,7 @@ struct tegra_smmu {
struct list_head list;
 
struct dentry *debugfs;
+   struct dentry *debugfs_mappings;
 
struct iommu_device iommu;  /* IOMMU Core code handle */
 };
@@ -153,6 +154,9 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, 
unsigned long offset)
 
 #define SMMU_PDE_ATTR  (SMMU_PDE_READABLE | SMMU_PDE_WRITABLE | \
 SMMU_PDE_NONSECURE)
+#define SMMU_PTE_ATTR  (SMMU_PTE_READABLE | SMMU_PTE_WRITABLE | \
+SMMU_PTE_NONSECURE)
+#define SMMU_PTE_ATTR_SHIFT29
 
 static unsigned int iova_pd_index(unsigned long iova)
 {
@@ -164,6 +168,12 @@ static unsigned int iova_pt_index(unsigned long iova)
return (iova >> SMMU_PTE_SHIFT) & (SMMU_NUM_PTE - 1);
 }
 
+static unsigned long pd_pt_index_iova(unsigned int pd_index, unsigned int 
pt_index)
+{
+   return ((dma_addr_t)pd_index & (SMMU_NUM_PDE - 1)) << SMMU_PDE_SHIFT |
+  ((dma_addr_t)pt_index & (SMMU_NUM_PTE - 1)) << SMMU_PTE_SHIFT;
+}
+
 static bool smmu_dma_addr_valid(struct tegra_smmu *smmu, dma_addr_t addr)
 {
addr >>= 12;
@@ -496,6 +506,8 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu *smmu,
mutex_unlock(&smmu->lock);
 }
 
+static const struct file_operations tegra_smmu_debugfs_mappings_fops;
+
 static void tegra_smmu_attach_as(struct tegra_smmu *smmu,
 struct tegra_smmu_as *as,
 unsigned int swgroup)
@@ -517,6 +529,12 @@ static void tegra_smmu_attach_as(struct tegra_smmu *smmu,
dev_warn(smmu->dev,
 "overwriting group->as for swgroup: %s\n", 
swgrp->name);
group->as = as;
+
+   if (smmu->debugfs_mappings)
+   debugfs_create_file(group->swgrp->name, 0444,
+   smmu->debugfs_mappings, group,
+   &tegra_smmu_debugfs_mappings_fops);
+
break;
}
 
@@ -541,6 +559,12 @@ static void tegra_smmu_detach_as(struct tegra_smmu *smmu,
if (group->swgrp != swgrp)
continue;
group->as = NULL;
+
+   if (smmu->debugfs_mappings) {
+   d = debugfs_lookup(group->swgrp->name, 
smmu->debugfs_mappings);
+   debugfs_remove(d);
+   }
+
break;
}
 
@@ -1124,6 +1148,125 @@ static int tegra_smmu_clients_show(struct seq_file *s, 
void *data)
 
 DEFINE_SHOW_ATTRIBUTE(tegra_smmu_clients);
 
+static int tegra_smmu_debugfs_mappings_show(struct seq_file *s, void *data)
+{
+   struct tegra_smmu_group *group = s->private;
+   const struct tegra_smmu_swgroup *swgrp;
+   struct tegra_smmu_as *as;
+   struct tegra_smmu *smmu;
+   unsigned int pd_index;
+   unsigned int pt_index;
+   unsigned long flags;
+   u64 pte_count = 0;
+   u32 pde_count = 0;
+   u32 *pd, val;
+
+   if (!group || !group->as || !group->swgrp)
+   return 0;
+
+   swgrp = group->swgrp;
+   smmu = group->smmu;
+   as = group->as;
+
+   mutex_lock(&smmu->lock);
+
+   val = smmu_readl(smmu, swgrp->reg) & SMMU_ASID_ENABLE;
+   if (!val)
+   goto unlock;
+
+   pd = page_address(as->pd);
+   if (!pd)
+   goto unlock;
+
+   seq_printf(s, "\nSWGROUP: %s\n", swgrp->name);
+   seq_printf(s, "as->id: %d\nas->attr: %c|%c|%s\nas->pd_dma: %pad\n", 
as->id,
+  as->attr & SMMU_PD_READABLE ? 'R' : '-',
+  as->attr & SMMU_PD_WRITABLE ? 'W' : '-',
+  as->attr & SMMU_PD_NONSECURE ? "NS" : "S",
+  &as->pd_dma);
+   seq_puts(s, "{\n");
+
+   spin_lock_irqsave(&as->lock, flags);
+
+   for (pd_index = 0; pd_index < SMMU_NUM_PDE; pd_index++) {
+   struct page *pt_page;
+   unsigned int i;
+   u32 *addr;
+
+   /* An empty PDE should not have a pte use count */
+   WARN_ON_ONCE(!pd[pd_index] ^ !as->count[pd_index]);
+
+ 

[PATCH v6 5/6] iommu/tegra-smmu: Attach as pointer to tegra_smmu_group

2021-09-13 Thread Nicolin Chen
This could ease driver to access corresponding as pointer
when having tegra_smmu_group pointer only, which can help
new mappings debugfs nodes.

Also moving tegra_smmu_find_group_soc() upward, for using
it in new tegra_smmu_attach_as(); and it's better to have
all tegra_smmu_find_* functions together.

Signed-off-by: Nicolin Chen 
---
 drivers/iommu/tegra-smmu.c | 94 +++---
 1 file changed, 78 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 8fd4985ac91e..68c34a4a0ecc 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -24,6 +24,7 @@ struct tegra_smmu_group {
struct tegra_smmu *smmu;
const struct tegra_smmu_group_soc *group_soc;
const struct tegra_smmu_swgroup *swgrp;
+   struct tegra_smmu_as *as;
struct iommu_group *grp;
 };
 
@@ -349,6 +350,19 @@ tegra_smmu_find_swgrp(struct tegra_smmu *smmu, unsigned 
int swgroup)
return swgrp;
 }
 
+static const struct tegra_smmu_group_soc *
+tegra_smmu_find_group_soc(struct tegra_smmu *smmu, unsigned int swgroup)
+{
+   unsigned int i, j;
+
+   for (i = 0; i < smmu->soc->num_groups; i++)
+   for (j = 0; j < smmu->soc->groups[i].num_swgroups; j++)
+   if (smmu->soc->groups[i].swgroups[j] == swgroup)
+   return &smmu->soc->groups[i];
+
+   return NULL;
+}
+
 static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup,
  unsigned int asid)
 {
@@ -482,6 +496,57 @@ static void tegra_smmu_as_unprepare(struct tegra_smmu 
*smmu,
mutex_unlock(&smmu->lock);
 }
 
+static void tegra_smmu_attach_as(struct tegra_smmu *smmu,
+struct tegra_smmu_as *as,
+unsigned int swgroup)
+{
+   const struct tegra_smmu_swgroup *swgrp;
+   struct tegra_smmu_group *group;
+
+   /* Find swgrp according to the swgroup id */
+   swgrp = tegra_smmu_find_swgrp(smmu, swgroup);
+   if (!swgrp)
+   return;
+
+   mutex_lock(&smmu->lock);
+
+   list_for_each_entry(group, &smmu->groups, list) {
+   if (group->swgrp != swgrp)
+   continue;
+   if (group->as)
+   dev_warn(smmu->dev,
+"overwriting group->as for swgroup: %s\n", 
swgrp->name);
+   group->as = as;
+   break;
+   }
+
+   mutex_unlock(&smmu->lock);
+}
+
+static void tegra_smmu_detach_as(struct tegra_smmu *smmu,
+unsigned int swgroup)
+{
+   const struct tegra_smmu_swgroup *swgrp;
+   struct tegra_smmu_group *group;
+   struct dentry *d;
+
+   /* Find swgrp according to the swgroup id */
+   swgrp = tegra_smmu_find_swgrp(smmu, swgroup);
+   if (!swgrp)
+   return;
+
+   mutex_lock(&smmu->lock);
+
+   list_for_each_entry(group, &smmu->groups, list) {
+   if (group->swgrp != swgrp)
+   continue;
+   group->as = NULL;
+   break;
+   }
+
+   mutex_unlock(&smmu->lock);
+}
+
 static int tegra_smmu_attach_dev(struct iommu_domain *domain,
 struct device *dev)
 {
@@ -495,11 +560,15 @@ static int tegra_smmu_attach_dev(struct iommu_domain 
*domain,
return -ENOENT;
 
for (index = 0; index < fwspec->num_ids; index++) {
+   unsigned int swgroup = fwspec->ids[index];
+
err = tegra_smmu_as_prepare(smmu, as);
if (err)
goto disable;
 
-   tegra_smmu_enable(smmu, fwspec->ids[index], as->id);
+   tegra_smmu_attach_as(smmu, as, swgroup);
+
+   tegra_smmu_enable(smmu, swgroup, as->id);
}
 
if (index == 0)
@@ -509,7 +578,10 @@ static int tegra_smmu_attach_dev(struct iommu_domain 
*domain,
 
 disable:
while (index--) {
-   tegra_smmu_disable(smmu, fwspec->ids[index], as->id);
+   unsigned int swgroup = fwspec->ids[index];
+
+   tegra_smmu_disable(smmu, swgroup, as->id);
+   tegra_smmu_detach_as(smmu, swgroup);
tegra_smmu_as_unprepare(smmu, as);
}
 
@@ -527,7 +599,10 @@ static void tegra_smmu_detach_dev(struct iommu_domain 
*domain, struct device *de
return;
 
for (index = 0; index < fwspec->num_ids; index++) {
-   tegra_smmu_disable(smmu, fwspec->ids[index], as->id);
+   unsigned int swgroup = fwspec->ids[index];
+
+   tegra_smmu_disable(smmu, swgroup, as->id);
+   tegra_smmu_detach_as(smmu, swgroup);
tegra_smmu_as_unprepare(smmu, as);
}
 }
@@ -869,19 +944,6 @@ static struct iommu_device *tegra_smmu_probe_device(struct 
device *dev)
 
 static void tegra_smmu_release_device(struct device *d

[PATCH v6 4/6] iommu/tegra-smmu: Use swgrp pointer instead of swgroup id

2021-09-13 Thread Nicolin Chen
This patch changes in struct tegra_smmu_group to use swgrp
pointer instead of swgroup, as a preparational change for
the "mappings" debugfs feature.

Signed-off-by: Nicolin Chen 
---
 drivers/iommu/tegra-smmu.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 0f3883045ffa..8fd4985ac91e 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -23,8 +23,8 @@ struct tegra_smmu_group {
struct list_head list;
struct tegra_smmu *smmu;
const struct tegra_smmu_group_soc *group_soc;
+   const struct tegra_smmu_swgroup *swgrp;
struct iommu_group *grp;
-   unsigned int swgroup;
 };
 
 struct tegra_smmu {
@@ -897,18 +897,22 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
const struct tegra_smmu_group_soc *group_soc;
+   const struct tegra_smmu_swgroup *swgrp;
unsigned int swgroup = fwspec->ids[0];
struct tegra_smmu_group *group;
struct iommu_group *grp;
 
+   /* Find swgrp according to the swgroup id */
+   swgrp = tegra_smmu_find_swgrp(smmu, swgroup);
+
/* Find group_soc associating with swgroup */
group_soc = tegra_smmu_find_group_soc(smmu, swgroup);
 
mutex_lock(&smmu->lock);
 
-   /* Find existing iommu_group associating with swgroup or group_soc */
+   /* Find existing iommu_group associating with swgrp or group_soc */
list_for_each_entry(group, &smmu->groups, list)
-   if ((group->swgroup == swgroup) ||
+   if ((swgrp && group->swgrp == swgrp) ||
(group_soc && group->group_soc == group_soc)) {
grp = iommu_group_ref_get(group->grp);
mutex_unlock(&smmu->lock);
@@ -923,7 +927,7 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
 
INIT_LIST_HEAD(&group->list);
group->group_soc = group_soc;
-   group->swgroup = swgroup;
+   group->swgrp = swgrp;
group->smmu = smmu;
 
if (dev_is_pci(dev))
-- 
2.17.1

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


[PATCH v6 1/6] iommu/tegra-smmu: Rename struct iommu_group *group to *grp

2021-09-13 Thread Nicolin Chen
There are a few structs using "group" for their pointer instances.
This gets confusing sometimes. The instance of struct iommu_group
is used in local function with an alias "grp", which can separate
it from others.

So this patch simply renames "group" to "grp" as a cleanup.

Signed-off-by: Nicolin Chen 
---
 drivers/iommu/tegra-smmu.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 0a281833f611..6ebae635d3aa 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -23,7 +23,7 @@ struct tegra_smmu_group {
struct list_head list;
struct tegra_smmu *smmu;
const struct tegra_smmu_group_soc *soc;
-   struct iommu_group *group;
+   struct iommu_group *grp;
unsigned int swgroup;
 };
 
@@ -909,7 +909,7 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
/* Find existing iommu_group associating with swgroup or group_soc */
list_for_each_entry(group, &smmu->groups, list)
if ((group->swgroup == swgroup) || (soc && group->soc == soc)) {
-   grp = iommu_group_ref_get(group->group);
+   grp = iommu_group_ref_get(group->grp);
mutex_unlock(&smmu->lock);
return grp;
}
@@ -926,23 +926,23 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
group->soc = soc;
 
if (dev_is_pci(dev))
-   group->group = pci_device_group(dev);
+   group->grp = pci_device_group(dev);
else
-   group->group = generic_device_group(dev);
+   group->grp = generic_device_group(dev);
 
-   if (IS_ERR(group->group)) {
+   if (IS_ERR(group->grp)) {
devm_kfree(smmu->dev, group);
mutex_unlock(&smmu->lock);
return NULL;
}
 
-   iommu_group_set_iommudata(group->group, group, 
tegra_smmu_group_release);
+   iommu_group_set_iommudata(group->grp, group, tegra_smmu_group_release);
if (soc)
-   iommu_group_set_name(group->group, soc->name);
+   iommu_group_set_name(group->grp, soc->name);
list_add_tail(&group->list, &smmu->groups);
mutex_unlock(&smmu->lock);
 
-   return group->group;
+   return group->grp;
 }
 
 static int tegra_smmu_of_xlate(struct device *dev,
-- 
2.17.1

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


[PATCH v6 3/6] iommu/tegra-smmu: Rename struct tegra_smmu_swgroup *group to *swgrp

2021-09-13 Thread Nicolin Chen
There are both tegra_smmu_swgroup and tegra_smmu_group structs
using "group" for their pointer instances. This gets confusing
to read the driver sometimes.

So this patch renames "group" of struct tegra_smmu_swgroup to
"swgrp" as a cleanup. Also renames its "find" function.

Note that we already have "swgroup" being used for an unsigned
int type variable that is inside struct tegra_smmu_swgroup, so
it's not able to use "swgroup" but only something like "swgrp".

Signed-off-by: Nicolin Chen 
---
 drivers/iommu/tegra-smmu.c | 34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index a32ed347e25d..0f3883045ffa 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -334,35 +334,35 @@ static void tegra_smmu_domain_free(struct iommu_domain 
*domain)
 }
 
 static const struct tegra_smmu_swgroup *
-tegra_smmu_find_swgroup(struct tegra_smmu *smmu, unsigned int swgroup)
+tegra_smmu_find_swgrp(struct tegra_smmu *smmu, unsigned int swgroup)
 {
-   const struct tegra_smmu_swgroup *group = NULL;
+   const struct tegra_smmu_swgroup *swgrp = NULL;
unsigned int i;
 
for (i = 0; i < smmu->soc->num_swgroups; i++) {
if (smmu->soc->swgroups[i].swgroup == swgroup) {
-   group = &smmu->soc->swgroups[i];
+   swgrp = &smmu->soc->swgroups[i];
break;
}
}
 
-   return group;
+   return swgrp;
 }
 
 static void tegra_smmu_enable(struct tegra_smmu *smmu, unsigned int swgroup,
  unsigned int asid)
 {
-   const struct tegra_smmu_swgroup *group;
+   const struct tegra_smmu_swgroup *swgrp;
unsigned int i;
u32 value;
 
-   group = tegra_smmu_find_swgroup(smmu, swgroup);
-   if (group) {
-   value = smmu_readl(smmu, group->reg);
+   swgrp = tegra_smmu_find_swgrp(smmu, swgroup);
+   if (swgrp) {
+   value = smmu_readl(smmu, swgrp->reg);
value &= ~SMMU_ASID_MASK;
value |= SMMU_ASID_VALUE(asid);
value |= SMMU_ASID_ENABLE;
-   smmu_writel(smmu, value, group->reg);
+   smmu_writel(smmu, value, swgrp->reg);
} else {
pr_warn("%s group from swgroup %u not found\n", __func__,
swgroup);
@@ -385,17 +385,17 @@ static void tegra_smmu_enable(struct tegra_smmu *smmu, 
unsigned int swgroup,
 static void tegra_smmu_disable(struct tegra_smmu *smmu, unsigned int swgroup,
   unsigned int asid)
 {
-   const struct tegra_smmu_swgroup *group;
+   const struct tegra_smmu_swgroup *swgrp;
unsigned int i;
u32 value;
 
-   group = tegra_smmu_find_swgroup(smmu, swgroup);
-   if (group) {
-   value = smmu_readl(smmu, group->reg);
+   swgrp = tegra_smmu_find_swgrp(smmu, swgroup);
+   if (swgrp) {
+   value = smmu_readl(smmu, swgrp->reg);
value &= ~SMMU_ASID_MASK;
value |= SMMU_ASID_VALUE(asid);
value &= ~SMMU_ASID_ENABLE;
-   smmu_writel(smmu, value, group->reg);
+   smmu_writel(smmu, value, swgrp->reg);
}
 
for (i = 0; i < smmu->soc->num_clients; i++) {
@@ -1008,11 +1008,11 @@ static int tegra_smmu_swgroups_show(struct seq_file *s, 
void *data)
seq_printf(s, "\n");
 
for (i = 0; i < smmu->soc->num_swgroups; i++) {
-   const struct tegra_smmu_swgroup *group = 
&smmu->soc->swgroups[i];
+   const struct tegra_smmu_swgroup *swgrp = 
&smmu->soc->swgroups[i];
const char *status;
unsigned int asid;
 
-   value = smmu_readl(smmu, group->reg);
+   value = smmu_readl(smmu, swgrp->reg);
 
if (value & SMMU_ASID_ENABLE)
status = "yes";
@@ -1021,7 +1021,7 @@ static int tegra_smmu_swgroups_show(struct seq_file *s, 
void *data)
 
asid = value & SMMU_ASID_MASK;
 
-   seq_printf(s, "%-9s  %-7s  %#04x\n", group->name, status,
+   seq_printf(s, "%-9s  %-7s  %#04x\n", swgrp->name, status,
   asid);
}
 
-- 
2.17.1

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


[PATCH v6 2/6] iommu/tegra-smmu: Rename struct tegra_smmu_group_soc *soc to *group_soc

2021-09-13 Thread Nicolin Chen
There are both tegra_smmu_soc and tegra_smmu_group_soc using "soc"
for their pointer instances. This patch renames the one of struct
tegra_smmu_group_soc from "soc" to "group_soc" to distinguish it.

Signed-off-by: Nicolin Chen 
---
 drivers/iommu/tegra-smmu.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 6ebae635d3aa..a32ed347e25d 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -22,7 +22,7 @@
 struct tegra_smmu_group {
struct list_head list;
struct tegra_smmu *smmu;
-   const struct tegra_smmu_group_soc *soc;
+   const struct tegra_smmu_group_soc *group_soc;
struct iommu_group *grp;
unsigned int swgroup;
 };
@@ -870,7 +870,7 @@ static struct iommu_device *tegra_smmu_probe_device(struct 
device *dev)
 static void tegra_smmu_release_device(struct device *dev) {}
 
 static const struct tegra_smmu_group_soc *
-tegra_smmu_find_group(struct tegra_smmu *smmu, unsigned int swgroup)
+tegra_smmu_find_group_soc(struct tegra_smmu *smmu, unsigned int swgroup)
 {
unsigned int i, j;
 
@@ -896,19 +896,20 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
 {
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct tegra_smmu *smmu = dev_iommu_priv_get(dev);
-   const struct tegra_smmu_group_soc *soc;
+   const struct tegra_smmu_group_soc *group_soc;
unsigned int swgroup = fwspec->ids[0];
struct tegra_smmu_group *group;
struct iommu_group *grp;
 
/* Find group_soc associating with swgroup */
-   soc = tegra_smmu_find_group(smmu, swgroup);
+   group_soc = tegra_smmu_find_group_soc(smmu, swgroup);
 
mutex_lock(&smmu->lock);
 
/* Find existing iommu_group associating with swgroup or group_soc */
list_for_each_entry(group, &smmu->groups, list)
-   if ((group->swgroup == swgroup) || (soc && group->soc == soc)) {
+   if ((group->swgroup == swgroup) ||
+   (group_soc && group->group_soc == group_soc)) {
grp = iommu_group_ref_get(group->grp);
mutex_unlock(&smmu->lock);
return grp;
@@ -921,9 +922,9 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
}
 
INIT_LIST_HEAD(&group->list);
+   group->group_soc = group_soc;
group->swgroup = swgroup;
group->smmu = smmu;
-   group->soc = soc;
 
if (dev_is_pci(dev))
group->grp = pci_device_group(dev);
@@ -937,8 +938,8 @@ static struct iommu_group *tegra_smmu_device_group(struct 
device *dev)
}
 
iommu_group_set_iommudata(group->grp, group, tegra_smmu_group_release);
-   if (soc)
-   iommu_group_set_name(group->grp, soc->name);
+   if (group_soc)
+   iommu_group_set_name(group->grp, group_soc->name);
list_add_tail(&group->list, &smmu->groups);
mutex_unlock(&smmu->lock);
 
-- 
2.17.1

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


[PATCH v6 0/6] iommu/tegra-smmu: Add pagetable mappings to debugfs

2021-09-13 Thread Nicolin Chen
This series of patches adds a new mappings node to debugfs for
tegra-smmu driver. The first five patches are all preparational
changes for PATCH-6, based on Thierry's review feedback against
v5: https://lkml.org/lkml/2021/3/16/447

Changelog
v6:
 * Added PATCH1-3 for better naming conventions
 * Added PATCH4-5 to embed previous struct tegra_smmu_group_debug
   into struct tegra_smmu_group
 * Dropped parentheses at SMMU_PTE_ATTR_SHIFT
 * Dropped swgrp->reg print
 * Replaced ptb_reg contents with as->attr and as->pd_dma
 * Added "index" and "count" in the PD entries for readability
 * Removed Dmitry's Tested-by and Reviewed-by for the big change
   from v5 to v6.
v5: https://lkml.org/lkml/2021/3/15/2473
 * Fixed a typo in commit message
 * Split a long line into two lines
 * Rearranged variable defines by length
 * Added Tested-by and Reviewed-by from Dmitry
v4: https://lkml.org/lkml/2021/3/14/429
 * Changed %d to %u for unsigned variables
 * Fixed print format mismatch warnings on ARM32
v3: https://lkml.org/lkml/2021/3/14/30
 * Fixed PHYS and IOVA print formats
 * Changed variables to unsigned int type
 * Changed the table outputs to be compact
v2: https://lkml.org/lkml/2021/3/9/1382
 * Expanded mutex range to the entire function
 * Added as->lock to protect pagetable walkthrough
 * Replaced devm_kzalloc with devm_kcalloc for group_debug
 * Added "PTE RANGE" and "SIZE" columns to group contiguous mappings
 * Dropped as->count check
 * Added WARN_ON when as->count mismatches pd[pd_index]
v1: https://lkml.org/lkml/2020/9/26/70

Nicolin Chen (6):
  iommu/tegra-smmu: Rename struct iommu_group *group to *grp
  iommu/tegra-smmu: Rename struct tegra_smmu_group_soc *soc to
*group_soc
  iommu/tegra-smmu: Rename struct tegra_smmu_swgroup *group to *swgrp
  iommu/tegra-smmu: Use swgrp pointer instead of swgroup id
  iommu/tegra-smmu: Attach as pointer to tegra_smmu_group
  iommu/tegra-smmu: Add pagetable mappings to debugfs

 drivers/iommu/tegra-smmu.c | 312 +++--
 1 file changed, 262 insertions(+), 50 deletions(-)

-- 
2.17.1

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


Re: [PATCH v2] dma-debug: prevent an error message from causing runtime problems

2021-09-13 Thread Christoph Hellwig
Thanks a lot.

I've applied this with a little change to avoid breaking up the
printed string into two lines.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] iommu/dma: Tidy up Kconfig selects

2021-09-13 Thread Robin Murphy
Now that the dust has settled on converting all the x86 drivers to
iommu-dma, we can punt the Kconfig selection to arch code where it
was always intended to be.

CC: Christoph Hellwig 
CC: Marek Szyprowski 
CC: x...@kernel.org
CC: linux-i...@vger.kernel.org
Signed-off-by: Robin Murphy 
---
 arch/ia64/Kconfig   | 1 +
 arch/x86/Kconfig| 1 +
 drivers/iommu/Kconfig   | 1 -
 drivers/iommu/amd/Kconfig   | 1 -
 drivers/iommu/intel/Kconfig | 1 -
 5 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 045792cde481..56c00a0851ce 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -51,6 +51,7 @@ config IA64
select GENERIC_TIME_VSYSCALL
select LEGACY_TIMER_TICK
select SWIOTLB
+   select IOMMU_DMA if INTEL_IOMMU
select SYSCTL_ARCH_UNALIGN_NO_WARN
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4e001425..10ea941e7c80 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -247,6 +247,7 @@ config X86
select HAVE_USER_RETURN_NOTIFIER
select HAVE_GENERIC_VDSO
select HOTPLUG_SMT  if SMP
+   select IOMMU_DMAif IOMMU_SUPPORT
select IRQ_FORCED_THREADING
select NEED_SG_DMA_LENGTH
select PCI_DOMAINS  if PCI
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 124c41adeca1..3538a2f38b94 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -459,7 +459,6 @@ config VIRTIO_IOMMU
depends on VIRTIO
depends on (ARM64 || X86)
select IOMMU_API
-   select IOMMU_DMA
select INTERVAL_TREE
select ACPI_VIOT if ACPI
help
diff --git a/drivers/iommu/amd/Kconfig b/drivers/iommu/amd/Kconfig
index a3cbafb603f5..9b5fc3356bf2 100644
--- a/drivers/iommu/amd/Kconfig
+++ b/drivers/iommu/amd/Kconfig
@@ -9,7 +9,6 @@ config AMD_IOMMU
select PCI_PASID
select IOMMU_API
select IOMMU_IOVA
-   select IOMMU_DMA
select IOMMU_IO_PGTABLE
depends on X86_64 && PCI && ACPI && HAVE_CMPXCHG_DOUBLE
help
diff --git a/drivers/iommu/intel/Kconfig b/drivers/iommu/intel/Kconfig
index 0ddb77115be7..28c3e922ca27 100644
--- a/drivers/iommu/intel/Kconfig
+++ b/drivers/iommu/intel/Kconfig
@@ -16,7 +16,6 @@ config INTEL_IOMMU
select DMAR_TABLE
select SWIOTLB
select IOASID
-   select IOMMU_DMA
select PCI_ATS
help
  DMA remapping (DMAR) devices support enables independent address
-- 
2.25.1

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


[PATCH 2/2] iommu/dma: Unexport IOVA cookie management

2021-09-13 Thread Robin Murphy
IOVA cookies are now got and put by core code, so we no longer need to
export these to modular drivers. The export for getting MSI cookies
stays, since VFIO can still be a module, but it was already relying on
someone else putting them, so that aspect is unaffected.

Reviewed-by: Lu Baolu 
Reviewed-by: Jean-Philippe Brucker 
Signed-off-by: Robin Murphy 
---
 drivers/iommu/dma-iommu.c | 7 ---
 drivers/iommu/iommu.c | 3 +--
 2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 896bea04c347..26cb95d3830a 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -98,9 +98,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum 
iommu_dma_cookie_type type)
 /**
  * iommu_get_dma_cookie - Acquire DMA-API resources for a domain
  * @domain: IOMMU domain to prepare for DMA-API usage
- *
- * IOMMU drivers should normally call this from their domain_alloc
- * callback when domain->type == IOMMU_DOMAIN_DMA.
  */
 int iommu_get_dma_cookie(struct iommu_domain *domain)
 {
@@ -113,7 +110,6 @@ int iommu_get_dma_cookie(struct iommu_domain *domain)
 
return 0;
 }
-EXPORT_SYMBOL(iommu_get_dma_cookie);
 
 /**
  * iommu_get_msi_cookie - Acquire just MSI remapping resources
@@ -151,8 +147,6 @@ EXPORT_SYMBOL(iommu_get_msi_cookie);
  * iommu_put_dma_cookie - Release a domain's DMA mapping resources
  * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie() or
  *  iommu_get_msi_cookie()
- *
- * IOMMU drivers should normally call this from their domain_free callback.
  */
 void iommu_put_dma_cookie(struct iommu_domain *domain)
 {
@@ -172,7 +166,6 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
kfree(cookie);
domain->iova_cookie = NULL;
 }
-EXPORT_SYMBOL(iommu_put_dma_cookie);
 
 /**
  * iommu_dma_get_resv_regions - Reserved region driver helper
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3303d707bab4..a80f13867bed 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1953,8 +1953,7 @@ static struct iommu_domain *__iommu_domain_alloc(struct 
bus_type *bus,
/* Assume all sizes by default; the driver may override this later */
domain->pgsize_bitmap  = bus->iommu_ops->pgsize_bitmap;
 
-   /* Temporarily avoid -EEXIST while drivers still get their own cookies 
*/
-   if (iommu_is_dma_domain(domain) && !domain->iova_cookie && 
iommu_get_dma_cookie(domain)) {
+   if (iommu_is_dma_domain(domain) && iommu_get_dma_cookie(domain)) {
iommu_domain_free(domain);
domain = NULL;
}
-- 
2.25.1

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


[PATCH 1/2] iommu/dart: Clean up IOVA cookie crumbs

2021-09-13 Thread Robin Murphy
The addition of the DART driver crossed over with moving IOVA cookie
management into core code; clean up the now-unnecessary remnants here.

Acked-by: Sven Peter 
Tested-by: Sven Peter 
Signed-off-by: Robin Murphy 
---
 drivers/iommu/apple-dart.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index 559db9259e65..cdc2e83b2186 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -15,7 +15,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -596,7 +595,6 @@ static struct iommu_domain 
*apple_dart_domain_alloc(unsigned int type)
if (!dart_domain)
return NULL;
 
-   iommu_get_dma_cookie(&dart_domain->domain);
mutex_init(&dart_domain->init_lock);
 
/* no need to allocate pgtbl_ops or do any other finalization steps */
-- 
2.25.1

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


[PATCH 0/2] iommu: DMA domain epilogue

2021-09-13 Thread Robin Murphy
Hi Joerg,

As planned, here are the follow-up patches to resolve the merge of the
DART driver with the core changes. There's some argument for this being
5.15 fix material (the driver getting DMA cookies unconditionally is
still technically wrong), but in practice it shouldn't be an issue
either if you'd prefer to treat it as cleanup for 5.16. Your choice :)

Cheers,
Robin.


Robin Murphy (2):
  iommu/dart: Clean up IOVA cookie crumbs
  iommu/dma: Unexport IOVA cookie management

 drivers/iommu/apple-dart.c | 2 --
 drivers/iommu/dma-iommu.c  | 7 ---
 drivers/iommu/iommu.c  | 3 +--
 3 files changed, 1 insertion(+), 11 deletions(-)

-- 
2.25.1

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


Re: [PATCH v7 0/7] Fixes for dma-iommu swiotlb bounce buffers

2021-09-13 Thread David Stevens
Is there further feedback on these patches? Only patch 7 is still
pending review.

-David

On Mon, Aug 30, 2021 at 2:00 PM David Stevens  wrote:
>
> This patch set includes various fixes for dma-iommu's swiotlb bounce
> buffers for untrusted devices.
>
> The min_align_mask issue was found when running fio on an untrusted nvme
> device with bs=512. The other issues were found via code inspection, so
> I don't have any specific use cases where things were not working, nor
> any concrete performance numbers.
>
> There are two issues related to min_align_mask that this patch series
> does not attempt to fix. First, it does not address the case where
> min_align_mask is larger than the IOVA granule. Doing so requires
> changes to IOVA allocation, and is not specific to when swiotlb bounce
> buffers are used. This is not a problem in practice today, since the
> only driver which uses min_align_mask is nvme, which sets it to 4096.
>
> The second issue this series does not address is the fact that extra
> swiotlb slots adjacent to a bounce buffer can be exposed to untrusted
> devices whose drivers use min_align_mask. Fixing this requires being
> able to allocate padding slots at the beginning of a swiotlb allocation.
> This is a rather significant change that I am not comfortable making.
> Without being able to handle this, there is also little point to
> clearing the padding at the start of such a buffer, since we can only
> clear based on (IO_TLB_SIZE - 1) instead of iova_mask.
>
> v6 -> v7:
>  - Remove unsafe attempt to clear padding at start of swiotlb buffer
>  - Rewrite commit message for min_align_mask commit to better explain
>the problem it's fixing
>  - Rebase on iommu/core
>  - Acknowledge unsolved issues in cover letter
>
> v5 -> v6:
>  - Remove unnecessary line break
>  - Remove redundant config check
>
> v4 -> v5:
>  - Fix xen build error
>  - Move _swiotlb refactor into its own patch
>
> v3 -> v4:
>  - Fold _swiotlb functions into _page functions
>  - Add patch to align swiotlb buffer to iovad granule
>  - Combine if checks in iommu_dma_sync_sg_* functions
>
> v2 -> v3:
>  - Add new patch to address min_align_mask bug
>  - Set SKIP_CPU_SYNC flag after syncing in map/unmap
>  - Properly call arch_sync_dma_for_cpu in iommu_dma_sync_sg_for_cpu
>
> v1 -> v2:
>  - Split fixes into dedicated patches
>  - Less invasive changes to fix arch_sync when mapping
>  - Leave dev_is_untrusted check for strict iommu
>
> David Stevens (7):
>   dma-iommu: fix sync_sg with swiotlb
>   dma-iommu: fix arch_sync_dma for map
>   dma-iommu: skip extra sync during unmap w/swiotlb
>   dma-iommu: fold _swiotlb helpers into callers
>   dma-iommu: Check CONFIG_SWIOTLB more broadly
>   swiotlb: support aligned swiotlb buffers
>   dma-iommu: account for min_align_mask w/swiotlb
>
>  drivers/iommu/dma-iommu.c | 188 +-
>  drivers/xen/swiotlb-xen.c |   2 +-
>  include/linux/swiotlb.h   |   3 +-
>  kernel/dma/swiotlb.c  |  11 ++-
>  4 files changed, 93 insertions(+), 111 deletions(-)
>
> --
> 2.33.0.259.gc128427fd7-goog
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu