Merge "iommu: iommu-debug: cleanup iommu debug"
This commit is contained in:
commit
d06a7d01d4
3 changed files with 74 additions and 364 deletions
|
@ -28,6 +28,7 @@
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/dma-iommu.h>
|
#include <asm/dma-iommu.h>
|
||||||
|
#include "iommu-debug.h"
|
||||||
|
|
||||||
#if defined(CONFIG_IOMMU_DEBUG_TRACKING) || defined(CONFIG_IOMMU_TESTS)
|
#if defined(CONFIG_IOMMU_DEBUG_TRACKING) || defined(CONFIG_IOMMU_TESTS)
|
||||||
|
|
||||||
|
@ -84,371 +85,58 @@ static const char *iommu_debug_attr_to_string(enum iommu_attr attr)
|
||||||
|
|
||||||
static DEFINE_MUTEX(iommu_debug_attachments_lock);
|
static DEFINE_MUTEX(iommu_debug_attachments_lock);
|
||||||
static LIST_HEAD(iommu_debug_attachments);
|
static LIST_HEAD(iommu_debug_attachments);
|
||||||
static struct dentry *debugfs_attachments_dir;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Each group may have more than one domain; but each domain may
|
||||||
|
* only have one group.
|
||||||
|
* Used by debug tools to display the name of the device(s) associated
|
||||||
|
* with a particular domain.
|
||||||
|
*/
|
||||||
struct iommu_debug_attachment {
|
struct iommu_debug_attachment {
|
||||||
struct iommu_domain *domain;
|
struct iommu_domain *domain;
|
||||||
struct device *dev;
|
struct iommu_group *group;
|
||||||
struct dentry *dentry;
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
unsigned long reg_offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int iommu_debug_attachment_info_show(struct seq_file *s, void *ignored)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *attach = s->private;
|
|
||||||
phys_addr_t pt_phys;
|
|
||||||
int secure_vmid;
|
|
||||||
|
|
||||||
seq_printf(s, "Domain: 0x%p\n", attach->domain);
|
|
||||||
if (iommu_domain_get_attr(attach->domain, DOMAIN_ATTR_PT_BASE_ADDR,
|
|
||||||
&pt_phys)) {
|
|
||||||
seq_puts(s, "PT_BASE_ADDR: (Unknown)\n");
|
|
||||||
} else {
|
|
||||||
void *pt_virt = phys_to_virt(pt_phys);
|
|
||||||
|
|
||||||
seq_printf(s, "PT_BASE_ADDR: virt=0x%p phys=%pa\n",
|
|
||||||
pt_virt, &pt_phys);
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_puts(s, "SECURE_VMID: ");
|
|
||||||
if (iommu_domain_get_attr(attach->domain,
|
|
||||||
DOMAIN_ATTR_SECURE_VMID,
|
|
||||||
&secure_vmid))
|
|
||||||
seq_puts(s, "(Unknown)\n");
|
|
||||||
else
|
|
||||||
seq_printf(s, "%s (0x%x)\n",
|
|
||||||
msm_secure_vmid_to_string(secure_vmid), secure_vmid);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iommu_debug_attachment_info_open(struct inode *inode,
|
|
||||||
struct file *file)
|
|
||||||
{
|
|
||||||
return single_open(file, iommu_debug_attachment_info_show,
|
|
||||||
inode->i_private);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations iommu_debug_attachment_info_fops = {
|
|
||||||
.open = iommu_debug_attachment_info_open,
|
|
||||||
.read = seq_read,
|
|
||||||
.llseek = seq_lseek,
|
|
||||||
.release = single_release,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t iommu_debug_attachment_trigger_fault_write(
|
|
||||||
struct file *file, const char __user *ubuf, size_t count,
|
|
||||||
loff_t *offset)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *attach = file->private_data;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (kstrtoul_from_user(ubuf, count, 0, &flags)) {
|
|
||||||
pr_err("Invalid flags format\n");
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
iommu_trigger_fault(attach->domain, flags);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations
|
|
||||||
iommu_debug_attachment_trigger_fault_fops = {
|
|
||||||
.open = simple_open,
|
|
||||||
.write = iommu_debug_attachment_trigger_fault_write,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t iommu_debug_attachment_reg_offset_write(
|
|
||||||
struct file *file, const char __user *ubuf, size_t count,
|
|
||||||
loff_t *offset)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *attach = file->private_data;
|
|
||||||
unsigned long reg_offset;
|
|
||||||
|
|
||||||
if (kstrtoul_from_user(ubuf, count, 0, ®_offset)) {
|
|
||||||
pr_err("Invalid reg_offset format\n");
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
attach->reg_offset = reg_offset;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations iommu_debug_attachment_reg_offset_fops = {
|
|
||||||
.open = simple_open,
|
|
||||||
.write = iommu_debug_attachment_reg_offset_write,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t iommu_debug_attachment_reg_read_read(
|
|
||||||
struct file *file, char __user *ubuf, size_t count, loff_t *offset)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *attach = file->private_data;
|
|
||||||
unsigned long val;
|
|
||||||
char *val_str;
|
|
||||||
ssize_t val_str_len;
|
|
||||||
|
|
||||||
if (*offset)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
val = iommu_reg_read(attach->domain, attach->reg_offset);
|
|
||||||
val_str = kasprintf(GFP_KERNEL, "0x%lx\n", val);
|
|
||||||
if (!val_str)
|
|
||||||
return -ENOMEM;
|
|
||||||
val_str_len = strlen(val_str);
|
|
||||||
|
|
||||||
if (copy_to_user(ubuf, val_str, val_str_len)) {
|
|
||||||
pr_err("copy_to_user failed\n");
|
|
||||||
val_str_len = -EFAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
*offset = 1; /* non-zero means we're done */
|
|
||||||
|
|
||||||
out:
|
|
||||||
kfree(val_str);
|
|
||||||
return val_str_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations iommu_debug_attachment_reg_read_fops = {
|
|
||||||
.open = simple_open,
|
|
||||||
.read = iommu_debug_attachment_reg_read_read,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t iommu_debug_attachment_reg_write_write(
|
|
||||||
struct file *file, const char __user *ubuf, size_t count,
|
|
||||||
loff_t *offset)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *attach = file->private_data;
|
|
||||||
unsigned long val;
|
|
||||||
|
|
||||||
if (kstrtoul_from_user(ubuf, count, 0, &val)) {
|
|
||||||
pr_err("Invalid val format\n");
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
iommu_reg_write(attach->domain, attach->reg_offset, val);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct file_operations iommu_debug_attachment_reg_write_fops = {
|
|
||||||
.open = simple_open,
|
|
||||||
.write = iommu_debug_attachment_reg_write_write,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* should be called with iommu_debug_attachments_lock locked */
|
|
||||||
static int iommu_debug_attach_add_debugfs(
|
|
||||||
struct iommu_debug_attachment *attach)
|
|
||||||
{
|
|
||||||
const char *attach_name;
|
|
||||||
struct device *dev = attach->dev;
|
|
||||||
struct iommu_domain *domain = attach->domain;
|
|
||||||
int is_dynamic;
|
|
||||||
|
|
||||||
if (iommu_domain_get_attr(domain, DOMAIN_ATTR_DYNAMIC, &is_dynamic))
|
|
||||||
is_dynamic = 0;
|
|
||||||
|
|
||||||
if (is_dynamic) {
|
|
||||||
uuid_le uuid;
|
|
||||||
|
|
||||||
uuid_le_gen(&uuid);
|
|
||||||
attach_name = kasprintf(GFP_KERNEL, "%s-%pUl", dev_name(dev),
|
|
||||||
uuid.b);
|
|
||||||
if (!attach_name)
|
|
||||||
return -ENOMEM;
|
|
||||||
} else {
|
|
||||||
attach_name = dev_name(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
attach->dentry = debugfs_create_dir(attach_name,
|
|
||||||
debugfs_attachments_dir);
|
|
||||||
if (!attach->dentry) {
|
|
||||||
pr_err("Couldn't create iommu/attachments/%s debugfs directory for domain 0x%p\n",
|
|
||||||
attach_name, domain);
|
|
||||||
if (is_dynamic)
|
|
||||||
kfree(attach_name);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dynamic)
|
|
||||||
kfree(attach_name);
|
|
||||||
|
|
||||||
if (!debugfs_create_file(
|
|
||||||
"info", S_IRUSR, attach->dentry, attach,
|
|
||||||
&iommu_debug_attachment_info_fops)) {
|
|
||||||
pr_err("Couldn't create iommu/attachments/%s/info debugfs file for domain 0x%p\n",
|
|
||||||
dev_name(dev), domain);
|
|
||||||
goto err_rmdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!debugfs_create_file(
|
|
||||||
"trigger_fault", S_IRUSR, attach->dentry, attach,
|
|
||||||
&iommu_debug_attachment_trigger_fault_fops)) {
|
|
||||||
pr_err("Couldn't create iommu/attachments/%s/trigger_fault debugfs file for domain 0x%p\n",
|
|
||||||
dev_name(dev), domain);
|
|
||||||
goto err_rmdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!debugfs_create_file(
|
|
||||||
"reg_offset", S_IRUSR, attach->dentry, attach,
|
|
||||||
&iommu_debug_attachment_reg_offset_fops)) {
|
|
||||||
pr_err("Couldn't create iommu/attachments/%s/reg_offset debugfs file for domain 0x%p\n",
|
|
||||||
dev_name(dev), domain);
|
|
||||||
goto err_rmdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!debugfs_create_file(
|
|
||||||
"reg_read", S_IRUSR, attach->dentry, attach,
|
|
||||||
&iommu_debug_attachment_reg_read_fops)) {
|
|
||||||
pr_err("Couldn't create iommu/attachments/%s/reg_read debugfs file for domain 0x%p\n",
|
|
||||||
dev_name(dev), domain);
|
|
||||||
goto err_rmdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!debugfs_create_file(
|
|
||||||
"reg_write", S_IRUSR, attach->dentry, attach,
|
|
||||||
&iommu_debug_attachment_reg_write_fops)) {
|
|
||||||
pr_err("Couldn't create iommu/attachments/%s/reg_write debugfs file for domain 0x%p\n",
|
|
||||||
dev_name(dev), domain);
|
|
||||||
goto err_rmdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_rmdir:
|
|
||||||
debugfs_remove_recursive(attach->dentry);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iommu_debug_domain_add(struct iommu_domain *domain)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *attach;
|
|
||||||
|
|
||||||
mutex_lock(&iommu_debug_attachments_lock);
|
|
||||||
|
|
||||||
attach = kmalloc(sizeof(*attach), GFP_KERNEL);
|
|
||||||
if (!attach)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
attach->domain = domain;
|
|
||||||
attach->dev = NULL;
|
|
||||||
list_add(&attach->list, &iommu_debug_attachments);
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iommu_debug_domain_remove(struct iommu_domain *domain)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *it;
|
|
||||||
|
|
||||||
mutex_lock(&iommu_debug_attachments_lock);
|
|
||||||
list_for_each_entry(it, &iommu_debug_attachments, list)
|
|
||||||
if (it->domain == domain && it->dev == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (&it->list == &iommu_debug_attachments) {
|
|
||||||
WARN(1, "Couldn't find debug attachment for domain=0x%p",
|
|
||||||
domain);
|
|
||||||
} else {
|
|
||||||
list_del(&it->list);
|
|
||||||
kfree(it);
|
|
||||||
}
|
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iommu_debug_attach_device(struct iommu_domain *domain,
|
void iommu_debug_attach_device(struct iommu_domain *domain,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
struct iommu_debug_attachment *attach;
|
struct iommu_debug_attachment *attach;
|
||||||
|
struct iommu_group *group;
|
||||||
|
|
||||||
|
group = iommu_group_get(dev);
|
||||||
|
if (!group)
|
||||||
|
return;
|
||||||
|
|
||||||
|
attach = kzalloc(sizeof(*attach), GFP_KERNEL);
|
||||||
|
if (!attach)
|
||||||
|
return;
|
||||||
|
|
||||||
|
attach->domain = domain;
|
||||||
|
attach->group = group;
|
||||||
|
INIT_LIST_HEAD(&attach->list);
|
||||||
|
|
||||||
mutex_lock(&iommu_debug_attachments_lock);
|
mutex_lock(&iommu_debug_attachments_lock);
|
||||||
|
list_add(&attach->list, &iommu_debug_attachments);
|
||||||
|
mutex_unlock(&iommu_debug_attachments_lock);
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry(attach, &iommu_debug_attachments, list)
|
void iommu_debug_domain_remove(struct iommu_domain *domain)
|
||||||
if (attach->domain == domain && attach->dev == NULL)
|
{
|
||||||
break;
|
struct iommu_debug_attachment *it, *tmp;
|
||||||
|
|
||||||
if (&attach->list == &iommu_debug_attachments) {
|
mutex_lock(&iommu_debug_attachments_lock);
|
||||||
WARN(1, "Couldn't find debug attachment for domain=0x%p dev=%s",
|
list_for_each_entry_safe(it, tmp, &iommu_debug_attachments, list) {
|
||||||
domain, dev_name(dev));
|
if (it->domain != domain)
|
||||||
} else {
|
continue;
|
||||||
attach->dev = dev;
|
list_del(&it->list);
|
||||||
|
iommu_group_put(it->group);
|
||||||
/*
|
kfree(it);
|
||||||
* we might not init until after other drivers start calling
|
|
||||||
* iommu_attach_device. Only set up the debugfs nodes if we've
|
|
||||||
* already init'd to avoid polluting the top-level debugfs
|
|
||||||
* directory (by calling debugfs_create_dir with a NULL
|
|
||||||
* parent). These will be flushed out later once we init.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (debugfs_attachments_dir)
|
|
||||||
iommu_debug_attach_add_debugfs(attach);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
mutex_unlock(&iommu_debug_attachments_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void iommu_debug_detach_device(struct iommu_domain *domain,
|
|
||||||
struct device *dev)
|
|
||||||
{
|
|
||||||
struct iommu_debug_attachment *it;
|
|
||||||
|
|
||||||
mutex_lock(&iommu_debug_attachments_lock);
|
|
||||||
list_for_each_entry(it, &iommu_debug_attachments, list)
|
|
||||||
if (it->domain == domain && it->dev == dev)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (&it->list == &iommu_debug_attachments) {
|
|
||||||
WARN(1, "Couldn't find debug attachment for domain=0x%p dev=%s",
|
|
||||||
domain, dev_name(dev));
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Just remove debugfs entry and mark dev as NULL on
|
|
||||||
* iommu_detach call. We would remove the actual
|
|
||||||
* attachment entry from the list only on domain_free call.
|
|
||||||
* This is to ensure we keep track of unattached domains too.
|
|
||||||
*/
|
|
||||||
|
|
||||||
debugfs_remove_recursive(it->dentry);
|
|
||||||
it->dev = NULL;
|
|
||||||
}
|
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iommu_debug_init_tracking(void)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
struct iommu_debug_attachment *attach;
|
|
||||||
|
|
||||||
mutex_lock(&iommu_debug_attachments_lock);
|
|
||||||
debugfs_attachments_dir = debugfs_create_dir("attachments",
|
|
||||||
iommu_debugfs_top);
|
|
||||||
if (!debugfs_attachments_dir) {
|
|
||||||
pr_err("Couldn't create iommu/attachments debugfs directory\n");
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up debugfs entries for attachments made during early boot */
|
|
||||||
list_for_each_entry(attach, &iommu_debug_attachments, list)
|
|
||||||
if (attach->dev)
|
|
||||||
iommu_debug_attach_add_debugfs(attach);
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iommu_debug_destroy_tracking(void)
|
|
||||||
{
|
|
||||||
debugfs_remove_recursive(debugfs_attachments_dir);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline int iommu_debug_init_tracking(void) { return 0; }
|
|
||||||
static inline void iommu_debug_destroy_tracking(void) { }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_IOMMU_TESTS
|
#ifdef CONFIG_IOMMU_TESTS
|
||||||
|
@ -479,6 +167,8 @@ struct iommu_debug_device {
|
||||||
u64 phys;
|
u64 phys;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
struct mutex clk_lock;
|
||||||
|
unsigned int clk_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int iommu_debug_build_phoney_sg_table(struct device *dev,
|
static int iommu_debug_build_phoney_sg_table(struct device *dev,
|
||||||
|
@ -1518,6 +1208,7 @@ static int iommu_debug_attach_do_attach(struct iommu_debug_device *ddev,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val = VMID_CP_CAMERA;
|
||||||
if (is_secure && iommu_domain_set_attr(ddev->domain,
|
if (is_secure && iommu_domain_set_attr(ddev->domain,
|
||||||
DOMAIN_ATTR_SECURE_VMID,
|
DOMAIN_ATTR_SECURE_VMID,
|
||||||
&val)) {
|
&val)) {
|
||||||
|
@ -1867,6 +1558,10 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
|
||||||
ssize_t retval;
|
ssize_t retval;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
|
|
||||||
|
if (kptr_restrict != 0) {
|
||||||
|
pr_err("kptr_restrict needs to be disabled.\n");
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
if (!ddev->domain) {
|
if (!ddev->domain) {
|
||||||
pr_err("No domain. Did you already attach?\n");
|
pr_err("No domain. Did you already attach?\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -2355,20 +2050,34 @@ static ssize_t iommu_debug_config_clocks_write(struct file *file,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ddev->clk_lock);
|
||||||
switch (buf) {
|
switch (buf) {
|
||||||
case '0':
|
case '0':
|
||||||
|
if (ddev->clk_count == 0) {
|
||||||
|
dev_err(dev, "Config clocks already disabled\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--ddev->clk_count > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
dev_err(dev, "Disabling config clocks\n");
|
dev_err(dev, "Disabling config clocks\n");
|
||||||
iommu_disable_config_clocks(ddev->domain);
|
iommu_disable_config_clocks(ddev->domain);
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
|
if (ddev->clk_count++ > 0)
|
||||||
|
break;
|
||||||
|
|
||||||
dev_err(dev, "Enabling config clocks\n");
|
dev_err(dev, "Enabling config clocks\n");
|
||||||
if (iommu_enable_config_clocks(ddev->domain))
|
if (iommu_enable_config_clocks(ddev->domain))
|
||||||
dev_err(dev, "Failed!\n");
|
dev_err(dev, "Failed!\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(dev, "Invalid value. Should be 0 or 1.\n");
|
dev_err(dev, "Invalid value. Should be 0 or 1.\n");
|
||||||
|
mutex_unlock(&ddev->clk_lock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&ddev->clk_lock);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
@ -2394,6 +2103,7 @@ static int snarf_iommu_devices(struct device *dev, const char *name)
|
||||||
ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
|
ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
|
||||||
if (!ddev)
|
if (!ddev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
mutex_init(&ddev->clk_lock);
|
||||||
ddev->dev = dev;
|
ddev->dev = dev;
|
||||||
dir = debugfs_create_dir(name, debugfs_tests_dir);
|
dir = debugfs_create_dir(name, debugfs_tests_dir);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
|
@ -2547,6 +2257,9 @@ err:
|
||||||
|
|
||||||
static int pass_iommu_devices(struct device *dev, void *ignored)
|
static int pass_iommu_devices(struct device *dev, void *ignored)
|
||||||
{
|
{
|
||||||
|
if (!of_device_is_compatible(dev->of_node, "iommu-debug-test"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!of_find_property(dev->of_node, "iommus", NULL))
|
if (!of_find_property(dev->of_node, "iommus", NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -2560,6 +2273,9 @@ static int iommu_debug_populate_devices(void)
|
||||||
const char *cb_name;
|
const char *cb_name;
|
||||||
|
|
||||||
for_each_compatible_node(np, NULL, "qcom,msm-smmu-v2-ctx") {
|
for_each_compatible_node(np, NULL, "qcom,msm-smmu-v2-ctx") {
|
||||||
|
if (!of_device_is_compatible(np, "iommu-debug-test"))
|
||||||
|
continue;
|
||||||
|
|
||||||
ret = of_property_read_string(np, "label", &cb_name);
|
ret = of_property_read_string(np, "label", &cb_name);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2625,9 +2341,6 @@ static struct platform_driver iommu_debug_driver = {
|
||||||
|
|
||||||
static int iommu_debug_init(void)
|
static int iommu_debug_init(void)
|
||||||
{
|
{
|
||||||
if (iommu_debug_init_tracking())
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (iommu_debug_init_tests())
|
if (iommu_debug_init_tests())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
@ -2637,7 +2350,6 @@ static int iommu_debug_init(void)
|
||||||
static void iommu_debug_exit(void)
|
static void iommu_debug_exit(void)
|
||||||
{
|
{
|
||||||
platform_driver_unregister(&iommu_debug_driver);
|
platform_driver_unregister(&iommu_debug_driver);
|
||||||
iommu_debug_destroy_tracking();
|
|
||||||
iommu_debug_destroy_tests();
|
iommu_debug_destroy_tests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
|
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef IOMMU_DEBUG_H
|
#ifndef IOMMU_DEBUG_H
|
||||||
#define IOMMU_DEBUG_H
|
#define IOMMU_DEBUG_H
|
||||||
|
|
||||||
#ifdef CONFIG_IOMMU_DEBUG_TRACKING
|
#ifdef CONFIG_IOMMU_DEBUG_TRACKING
|
||||||
|
|
||||||
void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev);
|
void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev);
|
||||||
void iommu_debug_detach_device(struct iommu_domain *domain, struct device *dev);
|
|
||||||
void iommu_debug_domain_add(struct iommu_domain *domain);
|
|
||||||
void iommu_debug_domain_remove(struct iommu_domain *domain);
|
void iommu_debug_domain_remove(struct iommu_domain *domain);
|
||||||
|
|
||||||
#else /* !CONFIG_IOMMU_DEBUG_TRACKING */
|
#else /* !CONFIG_IOMMU_DEBUG_TRACKING */
|
||||||
|
@ -15,15 +25,6 @@ static inline void iommu_debug_attach_device(struct iommu_domain *domain,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void iommu_debug_detach_device(struct iommu_domain *domain,
|
|
||||||
struct device *dev)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void iommu_debug_domain_add(struct iommu_domain *domain)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void iommu_debug_domain_remove(struct iommu_domain *domain)
|
static inline void iommu_debug_domain_remove(struct iommu_domain *domain)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1118,8 +1118,6 @@ static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
|
||||||
domain->ops = bus->iommu_ops;
|
domain->ops = bus->iommu_ops;
|
||||||
domain->type = type;
|
domain->type = type;
|
||||||
|
|
||||||
iommu_debug_domain_add(domain);
|
|
||||||
|
|
||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,7 +1184,6 @@ static void __iommu_detach_device(struct iommu_domain *domain,
|
||||||
if (unlikely(domain->ops->detach_dev == NULL))
|
if (unlikely(domain->ops->detach_dev == NULL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iommu_debug_detach_device(domain, dev);
|
|
||||||
domain->ops->detach_dev(domain, dev);
|
domain->ops->detach_dev(domain, dev);
|
||||||
trace_detach_device_from_domain(dev);
|
trace_detach_device_from_domain(dev);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue