diff mbox

[1/4] iommu/tegra-smmu: Add debugfs support

Message ID 1427450847-17719-1-git-send-email-thierry.reding@gmail.com
State Accepted
Headers show

Commit Message

Thierry Reding March 27, 2015, 10:07 a.m. UTC
From: Thierry Reding <treding@nvidia.com>

Provide clients and swgroups files in debugfs. These files show for
which clients IOMMU translation is enabled and which ASID is associated
with each SWGROUP.

Cc: Hiroshi Doyu <hdoyu@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/iommu/tegra-smmu.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
 include/soc/tegra/mc.h     |   5 +++
 2 files changed, 114 insertions(+)

Comments

Thierry Reding March 27, 2015, 10:15 a.m. UTC | #1
On Fri, Mar 27, 2015 at 11:07:24AM +0100, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
> 
> Provide clients and swgroups files in debugfs. These files show for
> which clients IOMMU translation is enabled and which ASID is associated
> with each SWGROUP.
> 
> Cc: Hiroshi Doyu <hdoyu@nvidia.com>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
>  drivers/iommu/tegra-smmu.c | 109 +++++++++++++++++++++++++++++++++++++++++++++
>  include/soc/tegra/mc.h     |   5 +++
>  2 files changed, 114 insertions(+)

Hi Joerg,

I forgot to mention that this patch depends on another patch that I plan
to take through the Tegra tree. That patch adds the group names that are
used by the debugfs support introduced here.

There are a couple of ways to solve this: omit this patch for v4.1 and
merge it for v4.2, at which point the dependency will have been merged.
That's obviously the simplest one and given that this is debugfs support
it isn't very critical, just nice to have.

Another possibility would be for you to ack this patch so that I can
take it into the same branch as the dependency. The remainder of this
series doesn't depend on either of the two patches, so they should be
fine for you to take into your tree.

Yet another alternative would be for me to provide a stable branch that
can be merged into the Tegra and IOMMU trees, but quite frankly I don't
think it's worth jumping through hoops like that for this particular
patch. I'd prefer either the first or second alternative, whichever
suits you best.

Thanks,
Thierry
Joerg Roedel March 31, 2015, 3:02 p.m. UTC | #2
Hi Thierry,

On Fri, Mar 27, 2015 at 11:15:41AM +0100, Thierry Reding wrote:
> Another possibility would be for you to ack this patch so that I can
> take it into the same branch as the dependency. The remainder of this
> series doesn't depend on either of the two patches, so they should be
> fine for you to take into your tree.

This solution sounds like the best one. You have my

	Acked-by: Joerg Roedel <jroedel@suse.de>

on the first patch. I merged patches 2-4 into the arm/tegra branch. As
you noticed there were conflict merging the branch into next. Please
have a look into my solution for that when I pushed it out later today
and let me know if it looks good and still works.


	Joerg

--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding April 14, 2015, 11:07 a.m. UTC | #3
On Tue, Mar 31, 2015 at 05:02:14PM +0200, Joerg Roedel wrote:
> Hi Thierry,
> 
> On Fri, Mar 27, 2015 at 11:15:41AM +0100, Thierry Reding wrote:
> > Another possibility would be for you to ack this patch so that I can
> > take it into the same branch as the dependency. The remainder of this
> > series doesn't depend on either of the two patches, so they should be
> > fine for you to take into your tree.
> 
> This solution sounds like the best one. You have my
> 
> 	Acked-by: Joerg Roedel <jroedel@suse.de>
> 
> on the first patch.

Thanks.

> I merged patches 2-4 into the arm/tegra branch. As
> you noticed there were conflict merging the branch into next. Please
> have a look into my solution for that when I pushed it out later today
> and let me know if it looks good and still works.

Yes, the resolution looks correct and I've been running linux-next
without issues for a couple of days now.

Thanks,
Thierry
diff mbox

Patch

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 6e134c7c227f..fff45b3d3e57 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -6,6 +6,7 @@ 
  * published by the Free Software Foundation.
  */
 
+#include <linux/debugfs.h>
 #include <linux/err.h>
 #include <linux/iommu.h>
 #include <linux/kernel.h>
@@ -28,6 +29,8 @@  struct tegra_smmu {
 	struct mutex lock;
 
 	struct list_head list;
+
+	struct dentry *debugfs;
 };
 
 struct tegra_smmu_as {
@@ -662,6 +665,103 @@  static void tegra_smmu_ahb_enable(void)
 	}
 }
 
+static int tegra_smmu_swgroups_show(struct seq_file *s, void *data)
+{
+	struct tegra_smmu *smmu = s->private;
+	unsigned int i;
+	u32 value;
+
+	seq_printf(s, "swgroup    enabled  ASID\n");
+	seq_printf(s, "------------------------\n");
+
+	for (i = 0; i < smmu->soc->num_swgroups; i++) {
+		const struct tegra_smmu_swgroup *group = &smmu->soc->swgroups[i];
+		const char *status;
+		unsigned int asid;
+
+		value = smmu_readl(smmu, group->reg);
+
+		if (value & SMMU_ASID_ENABLE)
+			status = "yes";
+		else
+			status = "no";
+
+		asid = value & SMMU_ASID_MASK;
+
+		seq_printf(s, "%-9s  %-7s  %#04x\n", group->name, status,
+			   asid);
+	}
+
+	return 0;
+}
+
+static int tegra_smmu_swgroups_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tegra_smmu_swgroups_show, inode->i_private);
+}
+
+static const struct file_operations tegra_smmu_swgroups_fops = {
+	.open = tegra_smmu_swgroups_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int tegra_smmu_clients_show(struct seq_file *s, void *data)
+{
+	struct tegra_smmu *smmu = s->private;
+	unsigned int i;
+	u32 value;
+
+	seq_printf(s, "client       enabled\n");
+	seq_printf(s, "--------------------\n");
+
+	for (i = 0; i < smmu->soc->num_clients; i++) {
+		const struct tegra_mc_client *client = &smmu->soc->clients[i];
+		const char *status;
+
+		value = smmu_readl(smmu, client->smmu.reg);
+
+		if (value & BIT(client->smmu.bit))
+			status = "yes";
+		else
+			status = "no";
+
+		seq_printf(s, "%-12s %s\n", client->name, status);
+	}
+
+	return 0;
+}
+
+static int tegra_smmu_clients_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tegra_smmu_clients_show, inode->i_private);
+}
+
+static const struct file_operations tegra_smmu_clients_fops = {
+	.open = tegra_smmu_clients_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void tegra_smmu_debugfs_init(struct tegra_smmu *smmu)
+{
+	smmu->debugfs = debugfs_create_dir("smmu", NULL);
+	if (!smmu->debugfs)
+		return;
+
+	debugfs_create_file("swgroups", S_IRUGO, smmu->debugfs, smmu,
+			    &tegra_smmu_swgroups_fops);
+	debugfs_create_file("clients", S_IRUGO, smmu->debugfs, smmu,
+			    &tegra_smmu_clients_fops);
+}
+
+static void tegra_smmu_debugfs_exit(struct tegra_smmu *smmu)
+{
+	debugfs_remove_recursive(smmu->debugfs);
+}
+
 struct tegra_smmu *tegra_smmu_probe(struct device *dev,
 				    const struct tegra_smmu_soc *soc,
 				    struct tegra_mc *mc)
@@ -728,5 +828,14 @@  struct tegra_smmu *tegra_smmu_probe(struct device *dev,
 	if (err < 0)
 		return ERR_PTR(err);
 
+	if (IS_ENABLED(CONFIG_DEBUG_FS))
+		tegra_smmu_debugfs_init(smmu);
+
 	return smmu;
 }
+
+void tegra_smmu_remove(struct tegra_smmu *smmu)
+{
+	if (IS_ENABLED(CONFIG_DEBUG_FS))
+		tegra_smmu_debugfs_exit(smmu);
+}
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 63deb8d9f82a..09a3dabf2ea7 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -71,6 +71,7 @@  struct tegra_smmu;
 struct tegra_smmu *tegra_smmu_probe(struct device *dev,
 				    const struct tegra_smmu_soc *soc,
 				    struct tegra_mc *mc);
+void tegra_smmu_remove(struct tegra_smmu *smmu);
 #else
 static inline struct tegra_smmu *
 tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc,
@@ -78,6 +79,10 @@  tegra_smmu_probe(struct device *dev, const struct tegra_smmu_soc *soc,
 {
 	return NULL;
 }
+
+static inline void tegra_smmu_remove(struct tegra_smmu *smmu)
+{
+}
 #endif
 
 struct tegra_mc_soc {