Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ca04418 authored by Michael Adisumarta's avatar Michael Adisumarta Committed by Gerrit - the friendly Code Review server
Browse files

msm: ipa4: IPA unit tests debugfs deadlock fix



Fix debugfs deadlock issue by doing read and write operations
on a work queue.

Change-Id: Ic3046e1f3ca0d2a5eaa9aeb983dace75c9be7e72
CRs-Fixed: 2128605
Signed-off-by: default avatarMichael Adisumarta <madisuma@codeaurora.org>
parent 3fafba6f
Loading
Loading
Loading
Loading
+89 −8
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
 * @ipa_dbgfs_root: IPA root debugfs folder
 * @test_dbgfs_root: UT root debugfs folder. Sub-folder of IPA root
 * @test_dbgfs_suites: Suites root debugfs folder. Sub-folder of UT root
 * @wq: workqueue struct for write operations
 */
struct ipa_ut_context {
	bool inited;
@@ -43,6 +44,17 @@ struct ipa_ut_context {
	struct dentry *ipa_dbgfs_root;
	struct dentry *test_dbgfs_root;
	struct dentry *test_dbgfs_suites;
	struct workqueue_struct *wq;
};

/**
 * struct ipa_ut_dbgfs_test_write_work_ctx - work_queue context
 * @dbgfs: work_struct for the write_work
 * @file: file  to be writen to
 */
struct ipa_ut_dbgfs_test_write_work_ctx {
	struct work_struct dbgfs_work;
	struct file *file;
};

static ssize_t ipa_ut_dbgfs_enable_read(struct file *file,
@@ -183,8 +195,9 @@ static void ipa_ut_show_suite_exec_summary(const struct ipa_ut_suite *suite)
}

/**
 * ipa_ut_dbgfs_meta_test_write() - Debugfs write func for a for a meta test
 * @params: write fops
 * ipa_ut_dbgfs_meta_test_write_work_func() - Debugfs write func for a
 * for a meta test
 * @params: work struct containing write fops and completion object
 *
 * Used to run all/regression tests in a suite
 * Create log buffer that the test can use to store ongoing logs
@@ -202,19 +215,24 @@ static void ipa_ut_show_suite_exec_summary(const struct ipa_ut_suite *suite)
 *
 * Return: Negative in failure, given characters amount in success
 */
static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
	const char __user *buf, size_t count, loff_t *ppos)
static void ipa_ut_dbgfs_meta_test_write_work_func(struct work_struct *work)
{
	struct ipa_ut_dbgfs_test_write_work_ctx *write_work_ctx;
	struct ipa_ut_suite *suite;
	struct file *file;
	int i;
	enum ipa_hw_type ipa_ver;
	int rc = 0;
	long meta_type;
	bool tst_fail = false;

	write_work_ctx = container_of(work, struct
		ipa_ut_dbgfs_test_write_work_ctx, dbgfs_work);

	IPA_UT_DBG("Entry\n");

	mutex_lock(&ipa_ut_ctx->lock);
	file = write_work_ctx->file;
	if (file == NULL) {
		rc = -EFAULT;
		goto unlock_mutex;
@@ -332,7 +350,37 @@ static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
	_IPA_UT_TEST_LOG_BUF_NAME = NULL;
unlock_mutex:
	mutex_unlock(&ipa_ut_ctx->lock);
	return ((!rc && !tst_fail) ? count : -EFAULT);
	kfree(write_work_ctx);
}

/*
 * ipa_ut_dbgfs_meta_test_write() - Debugfs write func for a for a meta test
 * @params: write fops
 *
 * Run all tests in a suite using a work queue so it does not race with
 * debugfs_remove_recursive
 *
 * Return: Negative if failure. Amount of characters written if success.
 */
static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
	const char __user *buf, size_t count, loff_t *ppos)
{
	struct ipa_ut_dbgfs_test_write_work_ctx *write_work_ctx;

	write_work_ctx = kzalloc(sizeof(*write_work_ctx), GFP_KERNEL);
	if (!write_work_ctx) {
		IPA_UT_ERR("kzalloc err.\n");
		return -ENOMEM;
	}

	write_work_ctx->file = file;

	INIT_WORK(&write_work_ctx->dbgfs_work,
		ipa_ut_dbgfs_meta_test_write_work_func);

	queue_work(ipa_ut_ctx->wq, &write_work_ctx->dbgfs_work);

	return count;
}

/**
@@ -462,18 +510,23 @@ static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
 *
 * Return: Negative in failure, given characters amount in success
 */
static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
	const char __user *buf, size_t count, loff_t *ppos)
static void ipa_ut_dbgfs_test_write_work_func(struct work_struct *work)
{
	struct ipa_ut_dbgfs_test_write_work_ctx *write_work_ctx;
	struct ipa_ut_test *test;
	struct ipa_ut_suite *suite;
	struct file *file;
	bool tst_fail = false;
	int rc = 0;
	enum ipa_hw_type ipa_ver;

	write_work_ctx = container_of(work, struct
		ipa_ut_dbgfs_test_write_work_ctx, dbgfs_work);

	IPA_UT_DBG("Entry\n");

	mutex_lock(&ipa_ut_ctx->lock);
	file = write_work_ctx->file;
	if (file == NULL) {
		rc = -EFAULT;
		goto unlock_mutex;
@@ -566,9 +619,29 @@ static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
	_IPA_UT_TEST_LOG_BUF_NAME = NULL;
unlock_mutex:
	mutex_unlock(&ipa_ut_ctx->lock);
	return ((!rc && !tst_fail) ? count : -EFAULT);
	kfree(write_work_ctx);
}

static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
	const char __user *buf, size_t count, loff_t *ppos)
{
	struct ipa_ut_dbgfs_test_write_work_ctx *write_work_ctx;

	write_work_ctx = kzalloc(sizeof(*write_work_ctx), GFP_KERNEL);
	if (!write_work_ctx) {
		IPA_UT_ERR("kzalloc err.\n");
		return -ENOMEM;
	}

	write_work_ctx->file = file;

	INIT_WORK(&write_work_ctx->dbgfs_work,
		ipa_ut_dbgfs_test_write_work_func);

	queue_work(ipa_ut_ctx->wq, &write_work_ctx->dbgfs_work);

	return count;
}
/**
 * ipa_ut_dbgfs_test_read() - Debugfs read function for a test
 * @params: read fops
@@ -893,6 +966,13 @@ static int ipa_ut_framework_init(void)
		}
	}

	ipa_ut_ctx->wq = create_singlethread_workqueue("ipa_ut_dbgfs");
	if (!ipa_ut_ctx->wq) {
		IPA_UT_ERR("create workqueue failed\n");
		ret = -ENOMEM;
		goto unlock_mutex;
	}

	ipa_ut_ctx->test_dbgfs_root = debugfs_create_dir("test",
		ipa_ut_ctx->ipa_dbgfs_root);
	if (!ipa_ut_ctx->test_dbgfs_root ||
@@ -935,6 +1015,7 @@ static void ipa_ut_framework_destroy(void)
	IPA_UT_DBG("Entry\n");

	mutex_lock(&ipa_ut_ctx->lock);
	destroy_workqueue(ipa_ut_ctx->wq);
	if (ipa_ut_ctx->enabled)
		ipa_ut_framework_disable();
	if (ipa_ut_ctx->inited)