iommu/iommu-debug: Don't add debugfs entries until we init
The attachment tracking code adds a node to debugfs every time a client attaches a domain to an IOMMU device. The problem is that clients can start making those attachments during early boot, before iommu-debug initializes (including setting up the root debugfs directory for the attachment tracking), which means they get stuck in the root debugfs directory. Trying to initialize iommu-debug earlier than all possible IOMMU clients is tricky, so fix this by only installing debugfs entries onces we've initialized, installing debugfs entries for any early attachments at initialization time. Change-Id: I8364015346105187e0c8f787fc2b4155d72b3584 Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
This commit is contained in:
parent
844ca444df
commit
f0abe72924
1 changed files with 54 additions and 26 deletions
|
@ -96,35 +96,29 @@ iommu_debug_attachment_trigger_fault_fops = {
|
||||||
.write = iommu_debug_attachment_trigger_fault_write,
|
.write = iommu_debug_attachment_trigger_fault_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
void iommu_debug_attach_device(struct iommu_domain *domain,
|
/* should be called with iommu_debug_attachments_lock locked */
|
||||||
struct device *dev)
|
static int iommu_debug_attach_add_debugfs(
|
||||||
|
struct iommu_debug_attachment *attach)
|
||||||
{
|
{
|
||||||
struct iommu_debug_attachment *attach;
|
|
||||||
char *attach_name;
|
|
||||||
uuid_le uuid;
|
uuid_le uuid;
|
||||||
|
char *attach_name;
|
||||||
mutex_lock(&iommu_debug_attachments_lock);
|
struct device *dev = attach->dev;
|
||||||
|
struct iommu_domain *domain = attach->domain;
|
||||||
|
|
||||||
uuid_le_gen(&uuid);
|
uuid_le_gen(&uuid);
|
||||||
attach_name = kasprintf(GFP_KERNEL, "%s-%pUl", dev_name(dev), uuid.b);
|
attach_name = kasprintf(GFP_KERNEL, "%s-%pUl", dev_name(dev), uuid.b);
|
||||||
if (!attach_name)
|
if (!attach_name)
|
||||||
goto err_unlock;
|
return -ENOMEM;
|
||||||
|
|
||||||
attach = kmalloc(sizeof(*attach), GFP_KERNEL);
|
|
||||||
if (!attach)
|
|
||||||
goto err_free_attach_name;
|
|
||||||
|
|
||||||
attach->domain = domain;
|
|
||||||
attach->dev = dev;
|
|
||||||
|
|
||||||
attach->dentry = debugfs_create_dir(attach_name,
|
attach->dentry = debugfs_create_dir(attach_name,
|
||||||
debugfs_attachments_dir);
|
debugfs_attachments_dir);
|
||||||
if (!attach->dentry) {
|
if (!attach->dentry) {
|
||||||
pr_err("Couldn't create iommu/attachments/%s debugfs directory for domain 0x%p\n",
|
pr_err("Couldn't create iommu/attachments/%s debugfs directory for domain 0x%p\n",
|
||||||
attach_name, domain);
|
attach_name, domain);
|
||||||
kfree(attach);
|
kfree(attach_name);
|
||||||
goto err_free_attach_name;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
kfree(attach_name);
|
||||||
|
|
||||||
if (!debugfs_create_file(
|
if (!debugfs_create_file(
|
||||||
"info", S_IRUSR, attach->dentry, attach,
|
"info", S_IRUSR, attach->dentry, attach,
|
||||||
|
@ -142,16 +136,39 @@ void iommu_debug_attach_device(struct iommu_domain *domain,
|
||||||
goto err_rmdir;
|
goto err_rmdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_add(&attach->list, &iommu_debug_attachments);
|
return 0;
|
||||||
kfree(attach_name);
|
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
|
||||||
return;
|
|
||||||
err_rmdir:
|
err_rmdir:
|
||||||
debugfs_remove_recursive(attach->dentry);
|
debugfs_remove_recursive(attach->dentry);
|
||||||
kfree(attach);
|
return -EIO;
|
||||||
err_free_attach_name:
|
}
|
||||||
kfree(attach_name);
|
|
||||||
err_unlock:
|
void iommu_debug_attach_device(struct iommu_domain *domain,
|
||||||
|
struct device *dev)
|
||||||
|
{
|
||||||
|
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 = dev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
list_add(&attach->list, &iommu_debug_attachments);
|
||||||
|
out_unlock:
|
||||||
mutex_unlock(&iommu_debug_attachments_lock);
|
mutex_unlock(&iommu_debug_attachments_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,14 +195,25 @@ void iommu_debug_detach_device(struct iommu_domain *domain,
|
||||||
|
|
||||||
static int iommu_debug_init_tracking(void)
|
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",
|
debugfs_attachments_dir = debugfs_create_dir("attachments",
|
||||||
debugfs_top_dir);
|
debugfs_top_dir);
|
||||||
if (!debugfs_attachments_dir) {
|
if (!debugfs_attachments_dir) {
|
||||||
pr_err("Couldn't create iommu/attachments debugfs directory\n");
|
pr_err("Couldn't create iommu/attachments debugfs directory\n");
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
/* set up debugfs entries for attachments made during early boot */
|
||||||
|
list_for_each_entry(attach, &iommu_debug_attachments, list)
|
||||||
|
iommu_debug_attach_add_debugfs(attach);
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&iommu_debug_attachments_lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline int iommu_debug_init_tracking(void) { return 0; }
|
static inline int iommu_debug_init_tracking(void) { return 0; }
|
||||||
|
|
Loading…
Add table
Reference in a new issue