|
@@ -246,6 +246,12 @@ struct smmu_as {
|
|
|
spinlock_t client_lock; /* for client list */
|
|
|
};
|
|
|
|
|
|
+struct smmu_debugfs_info {
|
|
|
+ struct smmu_device *smmu;
|
|
|
+ int mc;
|
|
|
+ int cache;
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* Per SMMU device - IOMMU device
|
|
|
*/
|
|
@@ -267,6 +273,7 @@ struct smmu_device {
|
|
|
unsigned long asid_security;
|
|
|
|
|
|
struct dentry *debugfs_root;
|
|
|
+ struct smmu_debugfs_info *debugfs_info;
|
|
|
|
|
|
struct device_node *ahb;
|
|
|
|
|
@@ -917,9 +924,10 @@ static ssize_t smmu_debugfs_stats_write(struct file *file,
|
|
|
const char __user *buffer,
|
|
|
size_t count, loff_t *pos)
|
|
|
{
|
|
|
+ struct smmu_debugfs_info *info;
|
|
|
struct smmu_device *smmu;
|
|
|
struct dentry *dent;
|
|
|
- int i, cache, mc;
|
|
|
+ int i;
|
|
|
enum {
|
|
|
_OFF = 0,
|
|
|
_ON,
|
|
@@ -947,11 +955,10 @@ static ssize_t smmu_debugfs_stats_write(struct file *file,
|
|
|
return -EINVAL;
|
|
|
|
|
|
dent = file->f_dentry;
|
|
|
- cache = (int)dent->d_inode->i_private;
|
|
|
- mc = (int)dent->d_parent->d_inode->i_private;
|
|
|
- smmu = dent->d_parent->d_parent->d_inode->i_private;
|
|
|
+ info = dent->d_inode->i_private;
|
|
|
+ smmu = info->smmu;
|
|
|
|
|
|
- offs = SMMU_CACHE_CONFIG(cache);
|
|
|
+ offs = SMMU_CACHE_CONFIG(info->cache);
|
|
|
val = smmu_read(smmu, offs);
|
|
|
switch (i) {
|
|
|
case _OFF:
|
|
@@ -983,21 +990,21 @@ static ssize_t smmu_debugfs_stats_write(struct file *file,
|
|
|
|
|
|
static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
|
|
|
{
|
|
|
+ struct smmu_debugfs_info *info;
|
|
|
struct smmu_device *smmu;
|
|
|
struct dentry *dent;
|
|
|
- int i, cache, mc;
|
|
|
+ int i;
|
|
|
const char * const stats[] = { "hit", "miss", };
|
|
|
|
|
|
dent = d_find_alias(s->private);
|
|
|
- cache = (int)dent->d_inode->i_private;
|
|
|
- mc = (int)dent->d_parent->d_inode->i_private;
|
|
|
- smmu = dent->d_parent->d_parent->d_inode->i_private;
|
|
|
+ info = dent->d_inode->i_private;
|
|
|
+ smmu = info->smmu;
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(stats); i++) {
|
|
|
u32 val;
|
|
|
size_t offs;
|
|
|
|
|
|
- offs = SMMU_STATS_CACHE_COUNT(mc, cache, i);
|
|
|
+ offs = SMMU_STATS_CACHE_COUNT(info->mc, info->cache, i);
|
|
|
val = smmu_read(smmu, offs);
|
|
|
seq_printf(s, "%s:%08x ", stats[i], val);
|
|
|
|
|
@@ -1025,16 +1032,22 @@ static const struct file_operations smmu_debugfs_stats_fops = {
|
|
|
static void smmu_debugfs_delete(struct smmu_device *smmu)
|
|
|
{
|
|
|
debugfs_remove_recursive(smmu->debugfs_root);
|
|
|
+ kfree(smmu->debugfs_info);
|
|
|
}
|
|
|
|
|
|
static void smmu_debugfs_create(struct smmu_device *smmu)
|
|
|
{
|
|
|
int i;
|
|
|
+ size_t bytes;
|
|
|
struct dentry *root;
|
|
|
|
|
|
- root = debugfs_create_file(dev_name(smmu->dev),
|
|
|
- S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
|
|
|
- NULL, smmu, NULL);
|
|
|
+ bytes = ARRAY_SIZE(smmu_debugfs_mc) * ARRAY_SIZE(smmu_debugfs_cache) *
|
|
|
+ sizeof(*smmu->debugfs_info);
|
|
|
+ smmu->debugfs_info = kmalloc(bytes, GFP_KERNEL);
|
|
|
+ if (!smmu->debugfs_info)
|
|
|
+ return;
|
|
|
+
|
|
|
+ root = debugfs_create_dir(dev_name(smmu->dev), NULL);
|
|
|
if (!root)
|
|
|
goto err_out;
|
|
|
smmu->debugfs_root = root;
|
|
@@ -1043,18 +1056,23 @@ static void smmu_debugfs_create(struct smmu_device *smmu)
|
|
|
int j;
|
|
|
struct dentry *mc;
|
|
|
|
|
|
- mc = debugfs_create_file(smmu_debugfs_mc[i],
|
|
|
- S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
|
|
|
- root, (void *)i, NULL);
|
|
|
+ mc = debugfs_create_dir(smmu_debugfs_mc[i], root);
|
|
|
if (!mc)
|
|
|
goto err_out;
|
|
|
|
|
|
for (j = 0; j < ARRAY_SIZE(smmu_debugfs_cache); j++) {
|
|
|
struct dentry *cache;
|
|
|
+ struct smmu_debugfs_info *info;
|
|
|
+
|
|
|
+ info = smmu->debugfs_info;
|
|
|
+ info += i * ARRAY_SIZE(smmu_debugfs_mc) + j;
|
|
|
+ info->smmu = smmu;
|
|
|
+ info->mc = i;
|
|
|
+ info->cache = j;
|
|
|
|
|
|
cache = debugfs_create_file(smmu_debugfs_cache[j],
|
|
|
S_IWUGO | S_IRUGO, mc,
|
|
|
- (void *)j,
|
|
|
+ (void *)info,
|
|
|
&smmu_debugfs_stats_fops);
|
|
|
if (!cache)
|
|
|
goto err_out;
|