msm: ipa: Add support for IPA unit-test framework
Add IPA unit-test framework. The framework supports definition and execution of tests that are grouped into suites according to IPA functional blocks. Debugfs file system is being used as a user interface. An example test suite is added for reference. Change-Id: Ide4ed54970c62f6485809c3bd63960536b4ace4f CRs-Fixed: 1040200 Signed-off-by: Ghanim Fodi <gfodi@codeaurora.org>
This commit is contained in:
parent
e94b446eac
commit
699fd2ab7f
12 changed files with 1476 additions and 1 deletions
|
@ -114,7 +114,6 @@ config IPA3
|
||||||
Kernel and user-space processes can call the IPA driver
|
Kernel and user-space processes can call the IPA driver
|
||||||
to configure IPA core.
|
to configure IPA core.
|
||||||
|
|
||||||
|
|
||||||
config RMNET_IPA3
|
config RMNET_IPA3
|
||||||
tristate "IPA3 RMNET WWAN Network Device"
|
tristate "IPA3 RMNET WWAN Network Device"
|
||||||
depends on IPA3 && MSM_QMI_INTERFACE
|
depends on IPA3 && MSM_QMI_INTERFACE
|
||||||
|
@ -124,6 +123,16 @@ config RMNET_IPA3
|
||||||
for RmNet Data Driver and also exchange of QMI messages between
|
for RmNet Data Driver and also exchange of QMI messages between
|
||||||
A7 and Q6 IPA-driver.
|
A7 and Q6 IPA-driver.
|
||||||
|
|
||||||
|
config IPA_UT
|
||||||
|
tristate "IPA Unit-Test Framework and Test Suites"
|
||||||
|
depends on IPA3 && DEBUG_FS
|
||||||
|
help
|
||||||
|
This Module implements IPA in-kernel test framework.
|
||||||
|
The framework supports defining and running tests, grouped
|
||||||
|
into suites according to the sub-unit of the IPA being tested.
|
||||||
|
The user interface to run and control the tests is debugfs file
|
||||||
|
system.
|
||||||
|
|
||||||
config SSM
|
config SSM
|
||||||
tristate "QTI Secure Service Module"
|
tristate "QTI Secure Service Module"
|
||||||
depends on QSEECOM
|
depends on QSEECOM
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
obj-$(CONFIG_IPA) += ipa_v2/ ipa_clients/ ipa_common
|
obj-$(CONFIG_IPA) += ipa_v2/ ipa_clients/ ipa_common
|
||||||
obj-$(CONFIG_IPA3) += ipa_v3/ ipa_clients/ ipa_common
|
obj-$(CONFIG_IPA3) += ipa_v3/ ipa_clients/ ipa_common
|
||||||
|
obj-$(CONFIG_IPA_UT) += test/
|
||||||
|
|
||||||
ipa_common += ipa_api.o ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o
|
ipa_common += ipa_api.o ipa_rm.o ipa_rm_dependency_graph.o ipa_rm_peers_list.o ipa_rm_resource.o ipa_rm_inactivity_timer.o
|
||||||
|
|
|
@ -2533,6 +2533,50 @@ int ipa_stop_gsi_channel(u32 clnt_hdl)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ipa_stop_gsi_channel);
|
EXPORT_SYMBOL(ipa_stop_gsi_channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_get_version_string() - Get string representation of IPA version
|
||||||
|
* @ver: IPA version
|
||||||
|
*
|
||||||
|
* Return: Constant string representation
|
||||||
|
*/
|
||||||
|
const char *ipa_get_version_string(enum ipa_hw_type ver)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
switch (ver) {
|
||||||
|
case IPA_HW_v1_0:
|
||||||
|
str = "1.0";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v1_1:
|
||||||
|
str = "1.1";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v2_0:
|
||||||
|
str = "2.0";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v2_1:
|
||||||
|
str = "2.1";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v2_5:
|
||||||
|
str = "2.5/2.6";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v2_6L:
|
||||||
|
str = "2.6L";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v3_0:
|
||||||
|
str = "3.0";
|
||||||
|
break;
|
||||||
|
case IPA_HW_v3_1:
|
||||||
|
str = "3.1";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Invalid version";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipa_get_version_string);
|
||||||
|
|
||||||
static struct of_device_id ipa_plat_drv_match[] = {
|
static struct of_device_id ipa_plat_drv_match[] = {
|
||||||
{ .compatible = "qcom,ipa", },
|
{ .compatible = "qcom,ipa", },
|
||||||
{ .compatible = "qcom,ipa-smmu-ap-cb", },
|
{ .compatible = "qcom,ipa-smmu-ap-cb", },
|
||||||
|
|
|
@ -355,5 +355,6 @@ u8 *ipa_write_16(u16 hw, u8 *dest);
|
||||||
u8 *ipa_write_8(u8 b, u8 *dest);
|
u8 *ipa_write_8(u8 b, u8 *dest);
|
||||||
u8 *ipa_pad_to_64(u8 *dest);
|
u8 *ipa_pad_to_64(u8 *dest);
|
||||||
u8 *ipa_pad_to_32(u8 *dest);
|
u8 *ipa_pad_to_32(u8 *dest);
|
||||||
|
const char *ipa_get_version_string(enum ipa_hw_type ver);
|
||||||
|
|
||||||
#endif /* _IPA_COMMON_I_H_ */
|
#endif /* _IPA_COMMON_I_H_ */
|
||||||
|
|
|
@ -2131,6 +2131,12 @@ void ipa3_debugfs_remove(void)
|
||||||
debugfs_remove_recursive(dent);
|
debugfs_remove_recursive(dent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dentry *ipa_debugfs_get_root(void)
|
||||||
|
{
|
||||||
|
return dent;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipa_debugfs_get_root);
|
||||||
|
|
||||||
#else /* !CONFIG_DEBUG_FS */
|
#else /* !CONFIG_DEBUG_FS */
|
||||||
void ipa3_debugfs_init(void) {}
|
void ipa3_debugfs_init(void) {}
|
||||||
void ipa3_debugfs_remove(void) {}
|
void ipa3_debugfs_remove(void) {}
|
||||||
|
|
|
@ -2012,4 +2012,5 @@ int ipa3_smmu_map_peer_buff(u64 iova, phys_addr_t phys_addr,
|
||||||
u32 size, bool map);
|
u32 size, bool map);
|
||||||
int ipa3_ntn_init(void);
|
int ipa3_ntn_init(void);
|
||||||
int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats);
|
int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats);
|
||||||
|
struct dentry *ipa_debugfs_get_root(void);
|
||||||
#endif /* _IPA3_I_H_ */
|
#endif /* _IPA3_I_H_ */
|
||||||
|
|
2
drivers/platform/msm/ipa/test/Makefile
Normal file
2
drivers/platform/msm/ipa/test/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
obj-$(CONFIG_IPA_UT) += ipa_ut_mod.o
|
||||||
|
ipa_ut_mod-y := ipa_ut_framework.o ipa_test_example.o
|
99
drivers/platform/msm/ipa/test/ipa_test_example.c
Normal file
99
drivers/platform/msm/ipa/test/ipa_test_example.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/* Copyright (c) 2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ipa_ut_framework.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example IPA Unit-test suite
|
||||||
|
* To be a reference for writing new suites and tests.
|
||||||
|
* This suite is also used as unit-test for the testing framework itself.
|
||||||
|
* Structure:
|
||||||
|
* 1- Define the setup and teardown functions
|
||||||
|
* Not Mandatory. Null may be used as well
|
||||||
|
* 2- For each test, define its Run() function
|
||||||
|
* 3- Use IPA_UT_DEFINE_SUITE_START() to start defining the suite
|
||||||
|
* 4- use IPA_UT_ADD_TEST() for adding tests within
|
||||||
|
* the suite definition block
|
||||||
|
* 5- IPA_UT_DEFINE_SUITE_END() close the suite definition
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int ipa_test_example_dummy;
|
||||||
|
|
||||||
|
static int ipa_test_example_suite_setup(void **ppriv)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Start Setup - set 0x1234F\n");
|
||||||
|
|
||||||
|
ipa_test_example_dummy = 0x1234F;
|
||||||
|
*ppriv = (void *)&ipa_test_example_dummy;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipa_test_example_teardown(void *priv)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Start Teardown\n");
|
||||||
|
IPA_UT_DBG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipa_test_example_test1(void *priv)
|
||||||
|
{
|
||||||
|
IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
|
||||||
|
ipa_test_example_dummy++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipa_test_example_test2(void *priv)
|
||||||
|
{
|
||||||
|
IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
|
||||||
|
ipa_test_example_dummy++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipa_test_example_test3(void *priv)
|
||||||
|
{
|
||||||
|
IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
|
||||||
|
ipa_test_example_dummy++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipa_test_example_test4(void *priv)
|
||||||
|
{
|
||||||
|
IPA_UT_LOG("priv=0x%p - value=0x%x\n", priv, *((int *)priv));
|
||||||
|
ipa_test_example_dummy++;
|
||||||
|
|
||||||
|
IPA_UT_TEST_FAIL_REPORT("failed on test");
|
||||||
|
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Suite definition block */
|
||||||
|
IPA_UT_DEFINE_SUITE_START(example, "Example suite",
|
||||||
|
ipa_test_example_suite_setup, ipa_test_example_teardown)
|
||||||
|
{
|
||||||
|
IPA_UT_ADD_TEST(test1, "This is test number 1",
|
||||||
|
ipa_test_example_test1, false, IPA_HW_v1_0, IPA_HW_MAX),
|
||||||
|
|
||||||
|
IPA_UT_ADD_TEST(test2, "This is test number 2",
|
||||||
|
ipa_test_example_test2, false, IPA_HW_v1_0, IPA_HW_MAX),
|
||||||
|
|
||||||
|
IPA_UT_ADD_TEST(test3, "This is test number 3",
|
||||||
|
ipa_test_example_test3, false, IPA_HW_v1_1, IPA_HW_v2_6),
|
||||||
|
|
||||||
|
IPA_UT_ADD_TEST(test4, "This is test number 4",
|
||||||
|
ipa_test_example_test4, false, IPA_HW_v1_1, IPA_HW_MAX),
|
||||||
|
|
||||||
|
} IPA_UT_DEFINE_SUITE_END(example);
|
969
drivers/platform/msm/ipa/test/ipa_ut_framework.c
Normal file
969
drivers/platform/msm/ipa/test/ipa_ut_framework.c
Normal file
|
@ -0,0 +1,969 @@
|
||||||
|
/* Copyright (c) 2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/ipa.h>
|
||||||
|
#include "../ipa_v3/ipa_i.h"
|
||||||
|
#include "ipa_ut_framework.h"
|
||||||
|
#include "ipa_ut_suite_list.h"
|
||||||
|
#include "ipa_ut_i.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define IPA_UT_DEBUG_WRITE_BUF_SIZE 256
|
||||||
|
#define IPA_UT_DEBUG_READ_BUF_SIZE 1024
|
||||||
|
|
||||||
|
#define IPA_UT_READ_WRITE_DBG_FILE_MODE \
|
||||||
|
(S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ipa_ut_context - I/S context
|
||||||
|
* @inited: Will wait till IPA is ready. Will create the enable file
|
||||||
|
* @enabled: All tests and suite debugfs files are created
|
||||||
|
* @lock: Lock for mutual exclustion
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
struct ipa_ut_context {
|
||||||
|
bool inited;
|
||||||
|
bool enabled;
|
||||||
|
struct mutex lock;
|
||||||
|
struct dentry *ipa_dbgfs_root;
|
||||||
|
struct dentry *test_dbgfs_root;
|
||||||
|
struct dentry *test_dbgfs_suites;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t ipa_ut_dbgfs_enable_read(struct file *file,
|
||||||
|
char __user *ubuf, size_t count, loff_t *ppos);
|
||||||
|
static ssize_t ipa_ut_dbgfs_enable_write(struct file *file,
|
||||||
|
const char __user *buf, size_t count, loff_t *ppos);
|
||||||
|
static ssize_t ipa_ut_dbgfs_test_read(struct file *file,
|
||||||
|
char __user *ubuf, size_t count, loff_t *ppos);
|
||||||
|
static ssize_t ipa_ut_dbgfs_test_write(struct file *file,
|
||||||
|
const char __user *buf, size_t count, loff_t *ppos);
|
||||||
|
static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
|
||||||
|
struct file *filp);
|
||||||
|
static int ipa_ut_dbgfs_regression_test_open(struct inode *inode,
|
||||||
|
struct file *filp);
|
||||||
|
static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file,
|
||||||
|
char __user *ubuf, size_t count, loff_t *ppos);
|
||||||
|
static ssize_t ipa_ut_dbgfs_meta_test_write(struct file *file,
|
||||||
|
const char __user *buf, size_t count, loff_t *ppos);
|
||||||
|
|
||||||
|
|
||||||
|
static const struct file_operations ipa_ut_dbgfs_enable_fops = {
|
||||||
|
.read = ipa_ut_dbgfs_enable_read,
|
||||||
|
.write = ipa_ut_dbgfs_enable_write,
|
||||||
|
};
|
||||||
|
static const struct file_operations ipa_ut_dbgfs_test_fops = {
|
||||||
|
.read = ipa_ut_dbgfs_test_read,
|
||||||
|
.write = ipa_ut_dbgfs_test_write,
|
||||||
|
};
|
||||||
|
static const struct file_operations ipa_ut_dbgfs_all_test_fops = {
|
||||||
|
.open = ipa_ut_dbgfs_all_test_open,
|
||||||
|
.read = ipa_ut_dbgfs_meta_test_read,
|
||||||
|
.write = ipa_ut_dbgfs_meta_test_write,
|
||||||
|
};
|
||||||
|
static const struct file_operations ipa_ut_dbgfs_regression_test_fops = {
|
||||||
|
.open = ipa_ut_dbgfs_regression_test_open,
|
||||||
|
.read = ipa_ut_dbgfs_meta_test_read,
|
||||||
|
.write = ipa_ut_dbgfs_meta_test_write,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ipa_ut_context *ipa_ut_ctx;
|
||||||
|
char *_IPA_UT_TEST_LOG_BUF_NAME;
|
||||||
|
struct ipa_ut_tst_fail_report _IPA_UT_TEST_FAIL_REPORT_DATA;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_show_suite_exec_summary() - Show tests run summary
|
||||||
|
* @suite: suite to print its running summary
|
||||||
|
*
|
||||||
|
* Print list of succeeded tests, failed tests and skipped tests
|
||||||
|
*
|
||||||
|
* Note: Assumes lock acquired
|
||||||
|
*/
|
||||||
|
static void ipa_ut_show_suite_exec_summary(const struct ipa_ut_suite *suite)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
ipa_assert_on(!suite);
|
||||||
|
|
||||||
|
pr_info("\n\n");
|
||||||
|
pr_info("\t Suite '%s' summary\n", suite->meta_data->name);
|
||||||
|
pr_info("===========================\n");
|
||||||
|
pr_info("Successful tests\n");
|
||||||
|
pr_info("----------------\n");
|
||||||
|
for (i = 0 ; i < suite->tests_cnt ; i++) {
|
||||||
|
if (suite->tests[i].res != IPA_UT_TEST_RES_SUCCESS)
|
||||||
|
continue;
|
||||||
|
pr_info("\t%s\n", suite->tests[i].name);
|
||||||
|
}
|
||||||
|
pr_info("\nFailed tests\n");
|
||||||
|
pr_info("------------\n");
|
||||||
|
for (i = 0 ; i < suite->tests_cnt ; i++) {
|
||||||
|
if (suite->tests[i].res != IPA_UT_TEST_RES_FAIL)
|
||||||
|
continue;
|
||||||
|
pr_info("\t%s\n", suite->tests[i].name);
|
||||||
|
}
|
||||||
|
pr_info("\nSkipped tests\n");
|
||||||
|
pr_info("-------------\n");
|
||||||
|
for (i = 0 ; i < suite->tests_cnt ; i++) {
|
||||||
|
if (suite->tests[i].res != IPA_UT_TEST_RES_SKIP)
|
||||||
|
continue;
|
||||||
|
pr_info("\t%s\n", suite->tests[i].name);
|
||||||
|
}
|
||||||
|
pr_info("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_meta_test_write() - Debugfs write func for a for a meta test
|
||||||
|
* @params: write fops
|
||||||
|
*
|
||||||
|
* Used to run all/regression tests in a suite
|
||||||
|
* Create log buffer that the test can use to store ongoing logs
|
||||||
|
* IPA clocks need to be voted.
|
||||||
|
* Run setup() once before running the tests and teardown() once after
|
||||||
|
* If no such call-backs then ignore it; if failed then fail the suite
|
||||||
|
* Print tests progress during running
|
||||||
|
* Test log and fail report will be showed only if the test failed.
|
||||||
|
* Finally show Summary of the suite tests running
|
||||||
|
*
|
||||||
|
* Note: If test supported IPA H/W version mismatch, skip it
|
||||||
|
* If a test lack run function, skip it
|
||||||
|
* If test doesn't belong to regression and it is regression run, skip it
|
||||||
|
* Note: Running mode: Do not stop running on failure
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
struct ipa_ut_suite *suite;
|
||||||
|
int i;
|
||||||
|
enum ipa_hw_type ipa_ver;
|
||||||
|
int rc = 0;
|
||||||
|
long meta_type;
|
||||||
|
bool tst_fail = false;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
suite = file->f_inode->i_private;
|
||||||
|
ipa_assert_on(!suite);
|
||||||
|
meta_type = (long)(file->private_data);
|
||||||
|
IPA_UT_DBG("Meta test type %ld\n", meta_type);
|
||||||
|
|
||||||
|
_IPA_UT_TEST_LOG_BUF_NAME = kzalloc(_IPA_UT_TEST_LOG_BUF_SIZE,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!_IPA_UT_TEST_LOG_BUF_NAME) {
|
||||||
|
IPA_UT_ERR("failed to allocate %d bytes\n",
|
||||||
|
_IPA_UT_TEST_LOG_BUF_SIZE);
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!suite->tests_cnt || !suite->tests) {
|
||||||
|
pr_info("No tests for suite '%s'\n", suite->meta_data->name);
|
||||||
|
goto free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ver = ipa_get_hw_type();
|
||||||
|
|
||||||
|
IPA_ACTIVE_CLIENTS_INC_SPECIAL("IPA_UT");
|
||||||
|
|
||||||
|
if (suite->meta_data->setup) {
|
||||||
|
pr_info("*** Suite '%s': Run setup ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = suite->meta_data->setup(&suite->meta_data->priv);
|
||||||
|
if (rc) {
|
||||||
|
IPA_UT_ERR("Setup failed for suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto release_clock;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pr_info("*** Suite '%s': No Setup ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("*** Suite '%s': Run %s tests ***\n\n",
|
||||||
|
suite->meta_data->name,
|
||||||
|
meta_type == IPA_UT_META_TEST_REGRESSION ? "regression" : "all"
|
||||||
|
);
|
||||||
|
for (i = 0 ; i < suite->tests_cnt ; i++) {
|
||||||
|
if (meta_type == IPA_UT_META_TEST_REGRESSION &&
|
||||||
|
!suite->tests[i].run_in_regression) {
|
||||||
|
pr_info(
|
||||||
|
"*** Test '%s': Skip - Not in regression ***\n\n"
|
||||||
|
, suite->tests[i].name);
|
||||||
|
suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (suite->tests[i].min_ipa_hw_ver > ipa_ver ||
|
||||||
|
suite->tests[i].max_ipa_hw_ver < ipa_ver) {
|
||||||
|
pr_info(
|
||||||
|
"*** Test '%s': Skip - IPA VER mismatch ***\n\n"
|
||||||
|
, suite->tests[i].name);
|
||||||
|
suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!suite->tests[i].run) {
|
||||||
|
pr_info(
|
||||||
|
"*** Test '%s': Skip - No Run function ***\n\n"
|
||||||
|
, suite->tests[i].name);
|
||||||
|
suite->tests[i].res = IPA_UT_TEST_RES_SKIP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_IPA_UT_TEST_LOG_BUF_NAME[0] = '\0';
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.valid = false;
|
||||||
|
pr_info("*** Test '%s': Running... ***\n",
|
||||||
|
suite->tests[i].name);
|
||||||
|
rc = suite->tests[i].run(suite->meta_data->priv);
|
||||||
|
if (rc) {
|
||||||
|
tst_fail = true;
|
||||||
|
suite->tests[i].res = IPA_UT_TEST_RES_FAIL;
|
||||||
|
pr_info("%s", _IPA_UT_TEST_LOG_BUF_NAME);
|
||||||
|
} else {
|
||||||
|
suite->tests[i].res = IPA_UT_TEST_RES_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info(">>>>>>**** TEST '%s': %s ****<<<<<<\n",
|
||||||
|
suite->tests[i].name, tst_fail ? "FAIL" : "SUCCESS");
|
||||||
|
|
||||||
|
if (tst_fail && _IPA_UT_TEST_FAIL_REPORT_DATA.valid) {
|
||||||
|
pr_info("*** FAIL INFO:\n");
|
||||||
|
pr_info("\tFILE = %s\n\tFUNC = %s()\n\tLINE = %d\n",
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.file,
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.func,
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.line);
|
||||||
|
pr_info("\t%s\n", _IPA_UT_TEST_FAIL_REPORT_DATA.info);
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suite->meta_data->teardown) {
|
||||||
|
pr_info("*** Suite '%s': Run Teardown ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = suite->meta_data->teardown(suite->meta_data->priv);
|
||||||
|
if (rc) {
|
||||||
|
IPA_UT_ERR("Teardown failed for suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto release_clock;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pr_info("*** Suite '%s': No Teardown ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ut_show_suite_exec_summary(suite);
|
||||||
|
|
||||||
|
release_clock:
|
||||||
|
IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IPA_UT");
|
||||||
|
free_mem:
|
||||||
|
kfree(_IPA_UT_TEST_LOG_BUF_NAME);
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return ((!rc && !tst_fail) ? count : -EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_meta_test_read() - Debugfs read func for a meta test
|
||||||
|
* @params: read fops
|
||||||
|
*
|
||||||
|
* Meta test, is a test that describes other test or bunch of tests.
|
||||||
|
* for example, the 'all' test. Running this test will run all
|
||||||
|
* the tests in the suite.
|
||||||
|
*
|
||||||
|
* Show information regard the suite. E.g. name and description
|
||||||
|
* If regression - List the regression tests names
|
||||||
|
*
|
||||||
|
* Return: Amount of characters written to user space buffer
|
||||||
|
*/
|
||||||
|
static ssize_t ipa_ut_dbgfs_meta_test_read(struct file *file,
|
||||||
|
char __user *ubuf, size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
struct ipa_ut_suite *suite;
|
||||||
|
int nbytes;
|
||||||
|
ssize_t cnt;
|
||||||
|
long meta_type;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
suite = file->f_inode->i_private;
|
||||||
|
ipa_assert_on(!suite);
|
||||||
|
meta_type = (long)(file->private_data);
|
||||||
|
IPA_UT_DBG("Meta test type %ld\n", meta_type);
|
||||||
|
|
||||||
|
buf = kmalloc(IPA_UT_DEBUG_READ_BUF_SIZE, GFP_KERNEL);
|
||||||
|
if (!buf) {
|
||||||
|
IPA_UT_ERR("failed to allocate %d bytes\n",
|
||||||
|
IPA_UT_DEBUG_READ_BUF_SIZE);
|
||||||
|
cnt = 0;
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_type == IPA_UT_META_TEST_ALL) {
|
||||||
|
nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
|
||||||
|
"\tMeta-test running all the tests in the suite:\n"
|
||||||
|
"\tSuite Name: %s\n"
|
||||||
|
"\tDescription: %s\n"
|
||||||
|
"\tNumber of test in suite: %zu\n",
|
||||||
|
suite->meta_data->name,
|
||||||
|
suite->meta_data->desc ?: "",
|
||||||
|
suite->tests_cnt);
|
||||||
|
} else {
|
||||||
|
nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
|
||||||
|
"\tMeta-test running regression tests in the suite:\n"
|
||||||
|
"\tSuite Name: %s\n"
|
||||||
|
"\tDescription: %s\n"
|
||||||
|
"\tRegression tests:\n",
|
||||||
|
suite->meta_data->name,
|
||||||
|
suite->meta_data->desc ?: "");
|
||||||
|
for (i = 0 ; i < suite->tests_cnt ; i++) {
|
||||||
|
if (!suite->tests[i].run_in_regression)
|
||||||
|
continue;
|
||||||
|
nbytes += scnprintf(buf + nbytes,
|
||||||
|
IPA_UT_DEBUG_READ_BUF_SIZE - nbytes,
|
||||||
|
"\t\t%s\n", suite->tests[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = simple_read_from_buffer(ubuf, count, ppos, buf, nbytes);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_regression_test_open() - Debugfs open function for
|
||||||
|
* 'regression' tests
|
||||||
|
* @params: open fops
|
||||||
|
*
|
||||||
|
* Mark "Regression tests" for meta-tests later operations.
|
||||||
|
*
|
||||||
|
* Return: Zero (always success).
|
||||||
|
*/
|
||||||
|
static int ipa_ut_dbgfs_regression_test_open(struct inode *inode,
|
||||||
|
struct file *filp)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
filp->private_data = (void *)(IPA_UT_META_TEST_REGRESSION);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_all_test_open() - Debugfs open function for 'all' tests
|
||||||
|
* @params: open fops
|
||||||
|
*
|
||||||
|
* Mark "All tests" for meta-tests later operations.
|
||||||
|
*
|
||||||
|
* Return: Zero (always success).
|
||||||
|
*/
|
||||||
|
static int ipa_ut_dbgfs_all_test_open(struct inode *inode,
|
||||||
|
struct file *filp)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
filp->private_data = (void *)(IPA_UT_META_TEST_ALL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_test_write() - Debugfs write function for a test
|
||||||
|
* @params: write fops
|
||||||
|
*
|
||||||
|
* Used to run a test.
|
||||||
|
* Create log buffer that the test can use to store ongoing logs
|
||||||
|
* IPA clocks need to be voted.
|
||||||
|
* Run setup() before the test and teardown() after the tests.
|
||||||
|
* If no such call-backs then ignore it; if failed then fail the test
|
||||||
|
* If all succeeds, no printing to user
|
||||||
|
* If failed, test logs and failure report will be printed to user
|
||||||
|
*
|
||||||
|
* Note: Test must has run function and it's supported IPA H/W version
|
||||||
|
* must be matching. Otherwise test will fail.
|
||||||
|
*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
struct ipa_ut_test *test;
|
||||||
|
struct ipa_ut_suite *suite;
|
||||||
|
bool tst_fail = false;
|
||||||
|
int rc = 0;
|
||||||
|
enum ipa_hw_type ipa_ver;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
test = file->f_inode->i_private;
|
||||||
|
ipa_assert_on(!test);
|
||||||
|
|
||||||
|
_IPA_UT_TEST_LOG_BUF_NAME = kzalloc(_IPA_UT_TEST_LOG_BUF_SIZE,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!_IPA_UT_TEST_LOG_BUF_NAME) {
|
||||||
|
IPA_UT_ERR("failed to allocate %d bytes\n",
|
||||||
|
_IPA_UT_TEST_LOG_BUF_SIZE);
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test->run) {
|
||||||
|
IPA_UT_ERR("*** Test %s - No run func ***\n",
|
||||||
|
test->name);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ver = ipa_get_hw_type();
|
||||||
|
if (test->min_ipa_hw_ver > ipa_ver ||
|
||||||
|
test->max_ipa_hw_ver < ipa_ver) {
|
||||||
|
IPA_UT_ERR("Cannot run test %s on IPA HW Ver %s\n",
|
||||||
|
test->name, ipa_get_version_string(ipa_ver));
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPA_ACTIVE_CLIENTS_INC_SPECIAL("IPA_UT");
|
||||||
|
|
||||||
|
suite = test->suite;
|
||||||
|
if (suite && suite->meta_data->setup) {
|
||||||
|
IPA_UT_DBG("*** Suite '%s': Run setup ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = suite->meta_data->setup(&suite->meta_data->priv);
|
||||||
|
if (rc) {
|
||||||
|
IPA_UT_ERR("Setup failed for suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto release_clock;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IPA_UT_DBG("*** Suite '%s': No Setup ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
IPA_UT_DBG("*** Test '%s': Running... ***\n", test->name);
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.valid = false;
|
||||||
|
rc = test->run(suite->meta_data->priv);
|
||||||
|
if (rc)
|
||||||
|
tst_fail = true;
|
||||||
|
IPA_UT_DBG("*** Test %s - ***\n", tst_fail ? "FAIL" : "SUCCESS");
|
||||||
|
if (tst_fail) {
|
||||||
|
pr_info("=================>>>>>>>>>>>\n");
|
||||||
|
pr_info("%s\n", _IPA_UT_TEST_LOG_BUF_NAME);
|
||||||
|
pr_info("**** TEST %s FAILED ****\n", test->name);
|
||||||
|
if (_IPA_UT_TEST_FAIL_REPORT_DATA.valid) {
|
||||||
|
pr_info("*** FAIL INFO:\n");
|
||||||
|
pr_info("\tFILE = %s\n\tFUNC = %s()\n\tLINE = %d\n",
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.file,
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.func,
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.line);
|
||||||
|
pr_info("\t%s\n", _IPA_UT_TEST_FAIL_REPORT_DATA.info);
|
||||||
|
}
|
||||||
|
pr_info("<<<<<<<<<<<=================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suite && suite->meta_data->teardown) {
|
||||||
|
IPA_UT_DBG("*** Suite '%s': Run Teardown ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = suite->meta_data->teardown(suite->meta_data->priv);
|
||||||
|
if (rc) {
|
||||||
|
IPA_UT_ERR("Teardown failed for suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto release_clock;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IPA_UT_DBG("*** Suite '%s': No Teardown ***\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
release_clock:
|
||||||
|
IPA_ACTIVE_CLIENTS_DEC_SPECIAL("IPA_UT");
|
||||||
|
free_mem:
|
||||||
|
kfree(_IPA_UT_TEST_LOG_BUF_NAME);
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return ((!rc && !tst_fail) ? count : -EFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_test_read() - Debugfs read function for a test
|
||||||
|
* @params: read fops
|
||||||
|
*
|
||||||
|
* print information regard the test. E.g. name and description
|
||||||
|
*
|
||||||
|
* Return: Amount of characters written to user space buffer
|
||||||
|
*/
|
||||||
|
static ssize_t ipa_ut_dbgfs_test_read(struct file *file, char __user *ubuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
struct ipa_ut_test *test;
|
||||||
|
int nbytes;
|
||||||
|
ssize_t cnt;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
test = file->f_inode->i_private;
|
||||||
|
ipa_assert_on(!test);
|
||||||
|
|
||||||
|
buf = kmalloc(IPA_UT_DEBUG_READ_BUF_SIZE, GFP_KERNEL);
|
||||||
|
if (!buf) {
|
||||||
|
IPA_UT_ERR("failed to allocate %d bytes\n",
|
||||||
|
IPA_UT_DEBUG_READ_BUF_SIZE);
|
||||||
|
cnt = 0;
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbytes = scnprintf(buf, IPA_UT_DEBUG_READ_BUF_SIZE,
|
||||||
|
"\t Test Name: %s\n"
|
||||||
|
"\t Description: %s\n"
|
||||||
|
"\t Suite Name: %s\n"
|
||||||
|
"\t Run In Regression: %s\n"
|
||||||
|
"\t Supported IPA versions: [%s -> %s]\n",
|
||||||
|
test->name, test->desc ?: "", test->suite->meta_data->name,
|
||||||
|
test->run_in_regression ? "Yes" : "No",
|
||||||
|
ipa_get_version_string(test->min_ipa_hw_ver),
|
||||||
|
test->max_ipa_hw_ver == IPA_HW_MAX ? "MAX" :
|
||||||
|
ipa_get_version_string(test->max_ipa_hw_ver));
|
||||||
|
|
||||||
|
if (nbytes > count)
|
||||||
|
IPA_UT_ERR("User buf too small - return partial info\n");
|
||||||
|
|
||||||
|
cnt = simple_read_from_buffer(ubuf, count, ppos, buf, nbytes);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_framework_load_suites() - Load tests and expose them to user space
|
||||||
|
*
|
||||||
|
* Creates debugfs folder for each suite and then file for each test in it.
|
||||||
|
* Create debugfs "all" file for each suite for meta-test to run all tests.
|
||||||
|
*
|
||||||
|
* Note: Assumes lock acquired
|
||||||
|
*
|
||||||
|
* Return: Zero in success, otherwise in failure
|
||||||
|
*/
|
||||||
|
int ipa_ut_framework_load_suites(void)
|
||||||
|
{
|
||||||
|
int suite_idx;
|
||||||
|
int tst_idx;
|
||||||
|
struct ipa_ut_suite *suite;
|
||||||
|
struct dentry *s_dent;
|
||||||
|
struct dentry *f_dent;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
for (suite_idx = IPA_UT_SUITE_FIRST_INDEX;
|
||||||
|
suite_idx < IPA_UT_SUITES_COUNT; suite_idx++) {
|
||||||
|
suite = IPA_UT_GET_SUITE(suite_idx);
|
||||||
|
|
||||||
|
if (!suite->meta_data->name) {
|
||||||
|
IPA_UT_ERR("No suite name\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_dent = debugfs_create_dir(suite->meta_data->name,
|
||||||
|
ipa_ut_ctx->test_dbgfs_suites);
|
||||||
|
|
||||||
|
if (!s_dent || IS_ERR(s_dent)) {
|
||||||
|
IPA_UT_ERR("fail create dbg entry - suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tst_idx = 0; tst_idx < suite->tests_cnt ; tst_idx++) {
|
||||||
|
if (!suite->tests[tst_idx].name) {
|
||||||
|
IPA_UT_ERR("No test name on suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
f_dent = debugfs_create_file(
|
||||||
|
suite->tests[tst_idx].name,
|
||||||
|
IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
|
||||||
|
&suite->tests[tst_idx],
|
||||||
|
&ipa_ut_dbgfs_test_fops);
|
||||||
|
if (!f_dent || IS_ERR(f_dent)) {
|
||||||
|
IPA_UT_ERR("fail create dbg entry - tst %s\n",
|
||||||
|
suite->tests[tst_idx].name);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* entry for meta-test all to run all tests in suites */
|
||||||
|
f_dent = debugfs_create_file(_IPA_UT_RUN_ALL_TEST_NAME,
|
||||||
|
IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
|
||||||
|
suite, &ipa_ut_dbgfs_all_test_fops);
|
||||||
|
if (!f_dent || IS_ERR(f_dent)) {
|
||||||
|
IPA_UT_ERR("fail to create dbg entry - %s\n",
|
||||||
|
_IPA_UT_RUN_ALL_TEST_NAME);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* entry for meta-test regression to run all regression
|
||||||
|
* tests in suites
|
||||||
|
*/
|
||||||
|
f_dent = debugfs_create_file(_IPA_UT_RUN_REGRESSION_TEST_NAME,
|
||||||
|
IPA_UT_READ_WRITE_DBG_FILE_MODE, s_dent,
|
||||||
|
suite, &ipa_ut_dbgfs_regression_test_fops);
|
||||||
|
if (!f_dent || IS_ERR(f_dent)) {
|
||||||
|
IPA_UT_ERR("fail to create dbg entry - %s\n",
|
||||||
|
_IPA_UT_RUN_ALL_TEST_NAME);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_framework_enable() - Enable the framework
|
||||||
|
*
|
||||||
|
* Creates the tests and suites debugfs entries and load them.
|
||||||
|
* This will expose the tests to user space.
|
||||||
|
*
|
||||||
|
* Return: Zero in success, otherwise in failure
|
||||||
|
*/
|
||||||
|
static int ipa_ut_framework_enable(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
|
||||||
|
if (ipa_ut_ctx->enabled) {
|
||||||
|
IPA_UT_ERR("Already enabled\n");
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ut_ctx->test_dbgfs_suites = debugfs_create_dir("suites",
|
||||||
|
ipa_ut_ctx->test_dbgfs_root);
|
||||||
|
if (!ipa_ut_ctx->test_dbgfs_suites ||
|
||||||
|
IS_ERR(ipa_ut_ctx->test_dbgfs_suites)) {
|
||||||
|
IPA_UT_ERR("failed to create suites debugfs dir\n");
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipa_ut_framework_load_suites()) {
|
||||||
|
IPA_UT_ERR("failed to load the suites into debugfs\n");
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto fail_clean_suites_dbgfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ut_ctx->enabled = true;
|
||||||
|
goto unlock_mutex;
|
||||||
|
|
||||||
|
fail_clean_suites_dbgfs:
|
||||||
|
debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_suites);
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_framework_disable() - Disable the framework
|
||||||
|
*
|
||||||
|
* Remove the tests and suites debugfs exposure.
|
||||||
|
*
|
||||||
|
* Return: Zero in success, otherwise in failure
|
||||||
|
*/
|
||||||
|
static int ipa_ut_framework_disable(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
|
||||||
|
if (!ipa_ut_ctx->enabled) {
|
||||||
|
IPA_UT_ERR("Already disabled\n");
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_suites);
|
||||||
|
|
||||||
|
ipa_ut_ctx->enabled = false;
|
||||||
|
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_enable_write() - Debugfs enable file write fops
|
||||||
|
* @params: write fops
|
||||||
|
*
|
||||||
|
* Input should be number. If 0, then disable. Otherwise enable.
|
||||||
|
*
|
||||||
|
* Return: if failed then negative value, if succeeds, amount of given chars
|
||||||
|
*/
|
||||||
|
static ssize_t ipa_ut_dbgfs_enable_write(struct file *file,
|
||||||
|
const char __user *buf, size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
char lcl_buf[IPA_UT_DEBUG_WRITE_BUF_SIZE];
|
||||||
|
s8 option = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
if (sizeof(lcl_buf) < count + 1) {
|
||||||
|
IPA_UT_ERR("No enough space\n");
|
||||||
|
return -E2BIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_from_user(lcl_buf, buf, count)) {
|
||||||
|
IPA_UT_ERR("fail to copy buf from user space\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcl_buf[count] = '\0';
|
||||||
|
if (kstrtos8(lcl_buf, 0, &option)) {
|
||||||
|
IPA_UT_ERR("fail convert str to s8\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option == 0)
|
||||||
|
ret = ipa_ut_framework_disable();
|
||||||
|
else
|
||||||
|
ret = ipa_ut_framework_enable();
|
||||||
|
|
||||||
|
return ret ?: count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_dbgfs_enable_read() - Debugfs enable file read fops
|
||||||
|
* @params: read fops
|
||||||
|
*
|
||||||
|
* To show to user space if the I/S is enabled or disabled.
|
||||||
|
*
|
||||||
|
* Return: amount of characters returned to user space
|
||||||
|
*/
|
||||||
|
static ssize_t ipa_ut_dbgfs_enable_read(struct file *file, char __user *ubuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
const char *status;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
status = ipa_ut_ctx->enabled ?
|
||||||
|
"Enabled - Write 0 to disable\n" :
|
||||||
|
"Disabled - Write 1 to enable\n";
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return simple_read_from_buffer(ubuf, count, ppos,
|
||||||
|
status, strlen(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_framework_init() - Unit-tests framework initialization
|
||||||
|
*
|
||||||
|
* Complete tests initialization: Each tests needs to point to it's
|
||||||
|
* corresponing suite.
|
||||||
|
* Creates the framework debugfs root directory under IPA directory.
|
||||||
|
* Create enable debugfs file - to enable/disable the framework.
|
||||||
|
*
|
||||||
|
* Return: Zero in success, otherwise in failure
|
||||||
|
*/
|
||||||
|
static int ipa_ut_framework_init(void)
|
||||||
|
{
|
||||||
|
struct dentry *dfile_enable;
|
||||||
|
int ret;
|
||||||
|
int suite_idx;
|
||||||
|
int test_idx;
|
||||||
|
struct ipa_ut_suite *suite;
|
||||||
|
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
ipa_assert_on(!ipa_ut_ctx);
|
||||||
|
|
||||||
|
ipa_ut_ctx->ipa_dbgfs_root = ipa_debugfs_get_root();
|
||||||
|
if (!ipa_ut_ctx->ipa_dbgfs_root) {
|
||||||
|
IPA_UT_ERR("No IPA debugfs root entry\n");
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
|
||||||
|
/* tests needs to point to their corresponding suites structures */
|
||||||
|
for (suite_idx = IPA_UT_SUITE_FIRST_INDEX;
|
||||||
|
suite_idx < IPA_UT_SUITES_COUNT; suite_idx++) {
|
||||||
|
suite = IPA_UT_GET_SUITE(suite_idx);
|
||||||
|
ipa_assert_on(!suite);
|
||||||
|
if (!suite->tests) {
|
||||||
|
IPA_UT_DBG("No tests for suite %s\n",
|
||||||
|
suite->meta_data->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (test_idx = 0; test_idx < suite->tests_cnt; test_idx++) {
|
||||||
|
suite->tests[test_idx].suite = suite;
|
||||||
|
IPA_UT_DBG("Updating test %s info for suite %s\n",
|
||||||
|
suite->tests[test_idx].name,
|
||||||
|
suite->meta_data->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ut_ctx->test_dbgfs_root = debugfs_create_dir("test",
|
||||||
|
ipa_ut_ctx->ipa_dbgfs_root);
|
||||||
|
if (!ipa_ut_ctx->test_dbgfs_root ||
|
||||||
|
IS_ERR(ipa_ut_ctx->test_dbgfs_root)) {
|
||||||
|
IPA_UT_ERR("failed to create test debugfs dir\n");
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto unlock_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
dfile_enable = debugfs_create_file("enable",
|
||||||
|
IPA_UT_READ_WRITE_DBG_FILE_MODE,
|
||||||
|
ipa_ut_ctx->test_dbgfs_root, 0, &ipa_ut_dbgfs_enable_fops);
|
||||||
|
if (!dfile_enable || IS_ERR(dfile_enable)) {
|
||||||
|
IPA_UT_ERR("failed to create enable debugfs file\n");
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto fail_clean_dbgfs;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipa_ut_ctx->inited = true;
|
||||||
|
IPA_UT_DBG("Done\n");
|
||||||
|
ret = 0;
|
||||||
|
goto unlock_mutex;
|
||||||
|
|
||||||
|
fail_clean_dbgfs:
|
||||||
|
debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_root);
|
||||||
|
unlock_mutex:
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_framework_destroy() - Destroy the UT framework info
|
||||||
|
*
|
||||||
|
* Disable it if enabled.
|
||||||
|
* Remove the debugfs entries using the root entry
|
||||||
|
*/
|
||||||
|
static void ipa_ut_framework_destroy(void)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
mutex_lock(&ipa_ut_ctx->lock);
|
||||||
|
if (ipa_ut_ctx->enabled)
|
||||||
|
ipa_ut_framework_disable();
|
||||||
|
if (ipa_ut_ctx->inited)
|
||||||
|
debugfs_remove_recursive(ipa_ut_ctx->test_dbgfs_root);
|
||||||
|
mutex_unlock(&ipa_ut_ctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_ipa_ready_cb() - IPA ready CB
|
||||||
|
*
|
||||||
|
* Once IPA is ready starting initializing the unit-test framework
|
||||||
|
*/
|
||||||
|
static void ipa_ut_ipa_ready_cb(void *user_data)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
(void)ipa_ut_framework_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_module_init() - Module init
|
||||||
|
*
|
||||||
|
* Create the framework context, wait for IPA driver readiness
|
||||||
|
* and Initialize it.
|
||||||
|
* If IPA driver already ready, continue initialization immediately.
|
||||||
|
* if not, wait for IPA ready notification by IPA driver context
|
||||||
|
*/
|
||||||
|
static int __init ipa_ut_module_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
IPA_UT_INFO("Loading IPA test module...\n");
|
||||||
|
|
||||||
|
ipa_ut_ctx = kzalloc(sizeof(struct ipa_ut_context), GFP_KERNEL);
|
||||||
|
if (!ipa_ut_ctx) {
|
||||||
|
IPA_UT_ERR("Failed to allocate ctx\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
mutex_init(&ipa_ut_ctx->lock);
|
||||||
|
|
||||||
|
if (!ipa_is_ready()) {
|
||||||
|
IPA_UT_DBG("IPA driver not ready, registering callback\n");
|
||||||
|
ret = ipa_register_ipa_ready_cb(ipa_ut_ipa_ready_cb, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we received -EEXIST, IPA has initialized. So we need
|
||||||
|
* to continue the initing process.
|
||||||
|
*/
|
||||||
|
if (ret != -EEXIST) {
|
||||||
|
if (ret) {
|
||||||
|
IPA_UT_ERR("IPA CB reg failed - %d\n", ret);
|
||||||
|
kfree(ipa_ut_ctx);
|
||||||
|
ipa_ut_ctx = NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ipa_ut_framework_init();
|
||||||
|
if (ret) {
|
||||||
|
IPA_UT_ERR("framework init failed\n");
|
||||||
|
kfree(ipa_ut_ctx);
|
||||||
|
ipa_ut_ctx = NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ipa_ut_module_exit() - Module exit function
|
||||||
|
*
|
||||||
|
* Destroys the Framework and removes its context
|
||||||
|
*/
|
||||||
|
static void ipa_ut_module_exit(void)
|
||||||
|
{
|
||||||
|
IPA_UT_DBG("Entry\n");
|
||||||
|
|
||||||
|
if (!ipa_ut_ctx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ipa_ut_framework_destroy();
|
||||||
|
kfree(ipa_ut_ctx);
|
||||||
|
ipa_ut_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(ipa_ut_module_init);
|
||||||
|
module_exit(ipa_ut_module_exit);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_DESCRIPTION("IPA Unit Test module");
|
222
drivers/platform/msm/ipa/test/ipa_ut_framework.h
Normal file
222
drivers/platform/msm/ipa/test/ipa_ut_framework.h
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
/* Copyright (c) 2016, 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 _IPA_UT_FRAMEWORK_H_
|
||||||
|
#define _IPA_UT_FRAMEWORK_H_
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include "../ipa_common_i.h"
|
||||||
|
#include "ipa_ut_i.h"
|
||||||
|
|
||||||
|
#define IPA_UT_DRV_NAME "ipa_ut"
|
||||||
|
|
||||||
|
#define IPA_UT_DBG(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
pr_debug(IPA_UT_DRV_NAME " %s:%d " fmt, \
|
||||||
|
__func__, __LINE__, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define IPA_UT_DBG_LOW(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
pr_debug(IPA_UT_DRV_NAME " %s:%d " fmt, \
|
||||||
|
__func__, __LINE__, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define IPA_UT_ERR(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
pr_err(IPA_UT_DRV_NAME " %s:%d " fmt, \
|
||||||
|
__func__, __LINE__, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define IPA_UT_INFO(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
pr_info(IPA_UT_DRV_NAME " %s:%d " fmt, \
|
||||||
|
__func__, __LINE__, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
|
||||||
|
IPA_UT_DRV_NAME " %s:%d " fmt, ## args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ipa_ut_tst_fail_report - Information on test failure
|
||||||
|
* @valid: When a test posts a report, valid will be marked true
|
||||||
|
* @file: File name containing the failed test.
|
||||||
|
* @line: Number of line in the file where the test failed.
|
||||||
|
* @func: Function where the test failed in.
|
||||||
|
* @info: Information about the failure.
|
||||||
|
*/
|
||||||
|
struct ipa_ut_tst_fail_report {
|
||||||
|
bool valid;
|
||||||
|
const char *file;
|
||||||
|
int line;
|
||||||
|
const char *func;
|
||||||
|
const char *info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report on test failure
|
||||||
|
* To be used by tests.
|
||||||
|
*/
|
||||||
|
#define IPA_UT_TEST_FAIL_REPORT(__info) \
|
||||||
|
do { \
|
||||||
|
extern struct ipa_ut_tst_fail_report \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA; \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.valid = true; \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.file = __FILENAME__; \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.line = __LINE__; \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.func = __func__; \
|
||||||
|
if (__info) \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.info = __info; \
|
||||||
|
else \
|
||||||
|
_IPA_UT_TEST_FAIL_REPORT_DATA.info = ""; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used by tests to log progress and ongoing information
|
||||||
|
* Logs are not printed to user, but saved to a buffer.
|
||||||
|
* I/S shall print the buffer at different occasions - e.g. in test failure
|
||||||
|
*/
|
||||||
|
#define IPA_UT_LOG(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
extern char *_IPA_UT_TEST_LOG_BUF_NAME; \
|
||||||
|
char __buf[512]; \
|
||||||
|
IPA_UT_DBG(fmt, args); \
|
||||||
|
scnprintf(__buf, sizeof(__buf), \
|
||||||
|
fmt, args); \
|
||||||
|
strlcat(_IPA_UT_TEST_LOG_BUF_NAME, __buf, sizeof(__buf)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ipa_ut_suite_meta - Suite meta-data
|
||||||
|
* @name: Suite unique name
|
||||||
|
* @desc: Suite description
|
||||||
|
* @setup: Setup Call-back of the suite
|
||||||
|
* @teardown: Teardown Call-back of the suite
|
||||||
|
* @priv: Private pointer of the suite
|
||||||
|
*
|
||||||
|
* Setup/Teardown will be called once for the suite when running a tests of it.
|
||||||
|
* priv field is shared between the Setup/Teardown and the tests
|
||||||
|
*/
|
||||||
|
struct ipa_ut_suite_meta {
|
||||||
|
char *name;
|
||||||
|
char *desc;
|
||||||
|
int (*setup)(void **ppriv);
|
||||||
|
int (*teardown)(void *priv);
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Test suite data structure declaration */
|
||||||
|
struct ipa_ut_suite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ipa_ut_test - Test information
|
||||||
|
* @name: Test name
|
||||||
|
* @desc: Test description
|
||||||
|
* @run: Test execution call-back
|
||||||
|
* @run_in_regression: To run this test as part of regression?
|
||||||
|
* @min_ipa_hw_ver: Minimum IPA H/W version where the test is supported?
|
||||||
|
* @max_ipa_hw_ver: Maximum IPA H/W version where the test is supported?
|
||||||
|
* @suite: Pointer to suite containing this test
|
||||||
|
* @res: Test execution result. Will be updated after running a test as part
|
||||||
|
* of suite tests run
|
||||||
|
*/
|
||||||
|
struct ipa_ut_test {
|
||||||
|
char *name;
|
||||||
|
char *desc;
|
||||||
|
int (*run)(void *priv);
|
||||||
|
bool run_in_regression;
|
||||||
|
int min_ipa_hw_ver;
|
||||||
|
int max_ipa_hw_ver;
|
||||||
|
struct ipa_ut_suite *suite;
|
||||||
|
enum ipa_ut_test_result res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct ipa_ut_suite - Suite information
|
||||||
|
* @meta_data: Pointer to meta-data structure of the suite
|
||||||
|
* @tests: Pointer to array of tests belongs to the suite
|
||||||
|
* @tests_cnt: Number of tests
|
||||||
|
*/
|
||||||
|
struct ipa_ut_suite {
|
||||||
|
struct ipa_ut_suite_meta *meta_data;
|
||||||
|
struct ipa_ut_test *tests;
|
||||||
|
size_t tests_cnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a test to a suite.
|
||||||
|
* Will add entry to tests array and update its info with
|
||||||
|
* the given info, thus adding new test.
|
||||||
|
*/
|
||||||
|
#define IPA_UT_ADD_TEST(__name, __desc, __run, __run_in_regression, \
|
||||||
|
__min_ipa_hw_ver, __max_ipa__hw_ver) \
|
||||||
|
{ \
|
||||||
|
.name = #__name, \
|
||||||
|
.desc = __desc, \
|
||||||
|
.run = __run, \
|
||||||
|
.run_in_regression = __run_in_regression, \
|
||||||
|
.min_ipa_hw_ver = __min_ipa_hw_ver, \
|
||||||
|
.max_ipa_hw_ver = __max_ipa__hw_ver, \
|
||||||
|
.suite = NULL, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declare a suite
|
||||||
|
* Every suite need to be declared before it is registered.
|
||||||
|
*/
|
||||||
|
#define IPA_UT_DECLARE_SUITE(__name) \
|
||||||
|
extern struct ipa_ut_suite _IPA_UT_SUITE_DATA(__name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a suite
|
||||||
|
* Registering a suite is mandatory so it will be considered.
|
||||||
|
*/
|
||||||
|
#define IPA_UT_REGISTER_SUITE(__name) \
|
||||||
|
(&_IPA_UT_SUITE_DATA(__name))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start/End suite definition
|
||||||
|
* Will create the suite global structures and adds adding tests to it.
|
||||||
|
* Use IPA_UT_ADD_TEST() with these macros to add tests when defining
|
||||||
|
* a suite
|
||||||
|
*/
|
||||||
|
#define IPA_UT_DEFINE_SUITE_START(__name, __desc, __setup, __teardown) \
|
||||||
|
static struct ipa_ut_suite_meta _IPA_UT_SUITE_META_DATA(__name) = \
|
||||||
|
{ \
|
||||||
|
.name = #__name, \
|
||||||
|
.desc = __desc, \
|
||||||
|
.setup = __setup, \
|
||||||
|
.teardown = __teardown, \
|
||||||
|
}; \
|
||||||
|
static struct ipa_ut_test _IPA_UT_SUITE_TESTS(__name)[] =
|
||||||
|
#define IPA_UT_DEFINE_SUITE_END(__name) \
|
||||||
|
; \
|
||||||
|
struct ipa_ut_suite _IPA_UT_SUITE_DATA(__name) = \
|
||||||
|
{ \
|
||||||
|
.meta_data = &_IPA_UT_SUITE_META_DATA(__name), \
|
||||||
|
.tests = _IPA_UT_SUITE_TESTS(__name), \
|
||||||
|
.tests_cnt = ARRAY_SIZE(_IPA_UT_SUITE_TESTS(__name)), \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _IPA_UT_FRAMEWORK_H_ */
|
86
drivers/platform/msm/ipa/test/ipa_ut_i.h
Normal file
86
drivers/platform/msm/ipa/test/ipa_ut_i.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/* Copyright (c) 2016, 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 _IPA_UT_I_H_
|
||||||
|
#define _IPA_UT_I_H_
|
||||||
|
|
||||||
|
/* Suite data global structure name */
|
||||||
|
#define _IPA_UT_SUITE_DATA(__name) ipa_ut_ ##__name ##_data
|
||||||
|
|
||||||
|
/* Suite meta-data global structure name */
|
||||||
|
#define _IPA_UT_SUITE_META_DATA(__name) ipa_ut_ ##__name ##_meta_data
|
||||||
|
|
||||||
|
/* Suite global array of tests */
|
||||||
|
#define _IPA_UT_SUITE_TESTS(__name) ipa_ut_ ##__name ##_tests
|
||||||
|
|
||||||
|
/* Global array of all suites */
|
||||||
|
#define _IPA_UT_ALL_SUITES ipa_ut_all_suites_data
|
||||||
|
|
||||||
|
/* Meta-test "all" name - test to run all tests in given suite */
|
||||||
|
#define _IPA_UT_RUN_ALL_TEST_NAME "all"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Meta-test "regression" name -
|
||||||
|
* test to run all regression tests in given suite
|
||||||
|
*/
|
||||||
|
#define _IPA_UT_RUN_REGRESSION_TEST_NAME "regression"
|
||||||
|
|
||||||
|
|
||||||
|
/* Test Log buffer name and size */
|
||||||
|
#define _IPA_UT_TEST_LOG_BUF_NAME ipa_ut_tst_log_buf
|
||||||
|
#define _IPA_UT_TEST_LOG_BUF_SIZE 2048
|
||||||
|
|
||||||
|
/* Global structure for test fail execution result information */
|
||||||
|
#define _IPA_UT_TEST_FAIL_REPORT_DATA ipa_ut_tst_fail_report_data
|
||||||
|
|
||||||
|
/* Start/End definitions of the array of suites */
|
||||||
|
#define IPA_UT_DEFINE_ALL_SUITES_START \
|
||||||
|
static struct ipa_ut_suite *_IPA_UT_ALL_SUITES[] =
|
||||||
|
#define IPA_UT_DEFINE_ALL_SUITES_END
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suites iterator - Array-like container
|
||||||
|
* First index, number of elements and element fetcher
|
||||||
|
*/
|
||||||
|
#define IPA_UT_SUITE_FIRST_INDEX 0
|
||||||
|
#define IPA_UT_SUITES_COUNT \
|
||||||
|
ARRAY_SIZE(_IPA_UT_ALL_SUITES)
|
||||||
|
#define IPA_UT_GET_SUITE(__index) \
|
||||||
|
_IPA_UT_ALL_SUITES[__index]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ipa_ut_test_result - Test execution result
|
||||||
|
* @IPA_UT_TEST_RES_FAIL: Test executed and failed
|
||||||
|
* @IPA_UT_TEST_RES_SUCCESS: Test executed and succeeded
|
||||||
|
* @IPA_UT_TEST_RES_SKIP: Test was not executed.
|
||||||
|
*
|
||||||
|
* When running all tests in a suite, a specific test could
|
||||||
|
* be skipped and not executed. For example due to mismatch of
|
||||||
|
* IPA H/W version.
|
||||||
|
*/
|
||||||
|
enum ipa_ut_test_result {
|
||||||
|
IPA_UT_TEST_RES_FAIL,
|
||||||
|
IPA_UT_TEST_RES_SUCCESS,
|
||||||
|
IPA_UT_TEST_RES_SKIP,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ipa_ut_meta_test_type - Type of suite meta-test
|
||||||
|
* @IPA_UT_META_TEST_ALL: Represents all tests in suite
|
||||||
|
* @IPA_UT_META_TEST_REGRESSION: Represents all regression tests in suite
|
||||||
|
*/
|
||||||
|
enum ipa_ut_meta_test_type {
|
||||||
|
IPA_UT_META_TEST_ALL,
|
||||||
|
IPA_UT_META_TEST_REGRESSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _IPA_UT_I_H_ */
|
35
drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
Normal file
35
drivers/platform/msm/ipa/test/ipa_ut_suite_list.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* Copyright (c) 2016, 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 _IPA_UT_SUITE_LIST_H_
|
||||||
|
#define _IPA_UT_SUITE_LIST_H_
|
||||||
|
|
||||||
|
#include "ipa_ut_framework.h"
|
||||||
|
#include "ipa_ut_i.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declare every suite here so that it will be found later below
|
||||||
|
* No importance for order.
|
||||||
|
*/
|
||||||
|
IPA_UT_DECLARE_SUITE(example);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register every suite inside the below block.
|
||||||
|
* Unregistered suites will be ignored
|
||||||
|
*/
|
||||||
|
IPA_UT_DEFINE_ALL_SUITES_START
|
||||||
|
{
|
||||||
|
IPA_UT_REGISTER_SUITE(example),
|
||||||
|
} IPA_UT_DEFINE_ALL_SUITES_END;
|
||||||
|
|
||||||
|
#endif /* _IPA_UT_SUITE_LIST_H_ */
|
Loading…
Add table
Reference in a new issue