summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r--drivers/scsi/ufs/ufs_test.c378
1 files changed, 215 insertions, 163 deletions
diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c
index 576d41af59bd..1754fa7fc89f 100644
--- a/drivers/scsi/ufs/ufs_test.c
+++ b/drivers/scsi/ufs/ufs_test.c
@@ -28,6 +28,7 @@
#include "ufs.h"
#define MODULE_NAME "ufs_test"
+#define UFS_TEST_BLK_DEV_TYPE_PREFIX "sd"
#define TEST_MAX_BIOS_PER_REQ 128
#define TEST_MAX_SECTOR_RANGE (10*1024*1024) /* 5GB */
@@ -72,7 +73,7 @@ static ssize_t ufs_test_ ## test_name ## _write(struct file *file, \
const char __user *buf, size_t count, loff_t *ppos) \
{ return ufs_test_write(file, buf, count, ppos, \
UFS_TEST_ ## upper_case_name); } \
-const struct file_operations ufs_test_ ## test_name ## _ops = { \
+static const struct file_operations ufs_test_ ## test_name ## _ops = { \
.open = ufs_test_ ## test_name ## _open, \
.read = seq_read, \
.write = ufs_test_ ## test_name ## _write, \
@@ -111,6 +112,9 @@ enum ufs_test_stage {
UFS_TEST_LUN_DEPTH_DONE_ISSUING_REQ,
};
+/* device test */
+static struct blk_dev_test_type *ufs_bdt;
+
struct ufs_test_data {
/* Data structure for debugfs dentrys */
struct dentry **test_list;
@@ -119,8 +123,7 @@ struct ufs_test_data {
* self-defined specific data
*/
struct test_info test_info;
- /* device test */
- struct blk_dev_test_type bdt;
+
/* A wait queue for OPs to complete */
wait_queue_head_t wait_q;
/* a flag for write compleation */
@@ -141,9 +144,9 @@ struct ufs_test_data {
int fail_threads;
atomic_t outstanding_threads;
struct completion outstanding_complete;
-};
-static struct ufs_test_data *utd;
+ struct test_iosched *test_iosched;
+};
static int ufs_test_add_test(struct ufs_test_data *utd,
enum ufs_test_testcases test_id, char *test_str,
@@ -155,7 +158,7 @@ static int ufs_test_add_test(struct ufs_test_data *utd,
if (test_id >= NUM_TESTS)
return -EINVAL;
- tests_root = test_iosched_get_debugfs_tests_root();
+ tests_root = utd->test_iosched->debug.debug_tests_root;
if (!tests_root) {
pr_err("%s: Failed to create debugfs root.", __func__);
return -EINVAL;
@@ -163,7 +166,7 @@ static int ufs_test_add_test(struct ufs_test_data *utd,
utd->test_list[test_id] = debugfs_create_file(test_str,
S_IRUGO | S_IWUGO, tests_root,
- NULL, test_fops);
+ utd, test_fops);
if (!utd->test_list[test_id]) {
pr_err("%s: Could not create the test %s", test_str,
__func__);
@@ -183,7 +186,7 @@ static int ufs_test_add_test(struct ufs_test_data *utd,
* @run_q: the maximum number of request to hold in queue (before run_queue())
*/
struct test_scenario {
- struct test_data *td;
+ struct test_iosched *test_iosched;
int direction;
int toggle_direction;
int total_req;
@@ -213,28 +216,22 @@ static struct test_scenario test_scenario[SCEN_RANDOM_MAX] = {
};
static
-struct test_scenario *get_scenario(struct test_data *td, enum scenario_id id)
+struct test_scenario *get_scenario(struct test_iosched *test_iosched,
+ enum scenario_id id)
{
struct test_scenario *ret = &test_scenario[id];
- ret->td = td;
+ ret->test_iosched = test_iosched;
return ret;
}
-static char *ufs_test_get_test_case_str(struct test_data *td)
+static char *ufs_test_get_test_case_str(int testcase)
{
- if (!td) {
- pr_err("%s: NULL td", __func__);
- return NULL;
- }
-
- switch (td->test_info.testcase) {
+ switch (testcase) {
case UFS_TEST_WRITE_READ_TEST:
return "UFS write read test";
- break;
case UFS_TEST_MULTI_QUERY:
return "Test multiple queries at the same time";
- break;
case UFS_TEST_LONG_RANDOM_READ:
return "UFS long random read test";
case UFS_TEST_LONG_RANDOM_WRITE:
@@ -243,22 +240,16 @@ static char *ufs_test_get_test_case_str(struct test_data *td)
return "UFS random data integrity test";
case UFS_TEST_LONG_SEQUENTIAL_READ:
return "UFS long sequential read test";
- break;
case UFS_TEST_LONG_SEQUENTIAL_WRITE:
return "UFS long sequential write test";
- break;
case UFS_TEST_LONG_SEQUENTIAL_MIXED:
return "UFS long sequential mixed test";
- break;
case UFS_TEST_PARALLEL_READ_AND_WRITE:
return "UFS parallel read and write test";
- break;
case UFS_TEST_LUN_DEPTH:
return "UFS LUN depth test";
- break;
- default:
- return "Unknown test";
}
+ return "Unknown test";
}
static unsigned int ufs_test_pseudo_random_seed(unsigned int *seed_number,
@@ -316,15 +307,15 @@ static void ufs_test_pseudo_rnd_size(unsigned int *seed,
*num_of_bios = DEFAULT_NUM_OF_BIOS;
}
-static inline int ufs_test_pm_runtime_cfg_sync(struct test_data *td,
- bool enable)
+static inline int ufs_test_pm_runtime_cfg_sync(struct test_iosched *tios,
+ bool enable)
{
struct scsi_device *sdev;
struct ufs_hba *hba;
int ret;
- BUG_ON(!td || !td->req_q || !td->req_q->queuedata);
- sdev = (struct scsi_device *)td->req_q->queuedata;
+ BUG_ON(!tios || !tios->req_q || !tios->req_q->queuedata);
+ sdev = (struct scsi_device *)tios->req_q->queuedata;
BUG_ON(!sdev->host);
hba = shost_priv(sdev->host);
BUG_ON(!hba);
@@ -449,9 +440,9 @@ static int ufs_test_show(struct seq_file *file, int test_case)
return 0;
}
-static struct gendisk *ufs_test_get_rq_disk(void)
+static struct gendisk *ufs_test_get_rq_disk(struct test_iosched *test_iosched)
{
- struct request_queue *req_q = test_iosched_get_req_queue();
+ struct request_queue *req_q = test_iosched->req_q;
struct scsi_device *sd;
if (!req_q) {
@@ -471,9 +462,9 @@ exit:
return NULL;
}
-static int ufs_test_put_gendisk(struct test_data *td)
+static int ufs_test_put_gendisk(struct test_iosched *test_iosched)
{
- struct request_queue *req_q = test_iosched_get_req_queue();
+ struct request_queue *req_q = test_iosched->req_q;
struct scsi_device *sd;
int ret = 0;
@@ -496,24 +487,26 @@ exit:
return ret;
}
-static int ufs_test_prepare(struct test_data *td)
+static int ufs_test_prepare(struct test_iosched *tios)
{
- return ufs_test_pm_runtime_cfg_sync(td, true);
+ return ufs_test_pm_runtime_cfg_sync(tios, true);
}
-static int ufs_test_post(struct test_data *td)
+static int ufs_test_post(struct test_iosched *tios)
{
int ret;
- ret = ufs_test_pm_runtime_cfg_sync(td, false);
+ ret = ufs_test_pm_runtime_cfg_sync(tios, false);
if (!ret)
- ret = ufs_test_put_gendisk(td);
+ ret = ufs_test_put_gendisk(tios);
return ret;
}
-static int ufs_test_check_result(struct test_data *td)
+static int ufs_test_check_result(struct test_iosched *test_iosched)
{
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
+
if (utd->test_stage == UFS_TEST_ERROR) {
pr_err("%s: An error occurred during the test.", __func__);
return TEST_FAILED;
@@ -528,8 +521,10 @@ static int ufs_test_check_result(struct test_data *td)
return 0;
}
-static bool ufs_write_read_completion(void)
+static bool ufs_write_read_completion(struct test_iosched *test_iosched)
{
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
+
if (!utd->queue_complete) {
utd->queue_complete = true;
wake_up(&utd->wait_q);
@@ -538,29 +533,28 @@ static bool ufs_write_read_completion(void)
return true;
}
-static int ufs_test_run_write_read_test(struct test_data *td)
+static int ufs_test_run_write_read_test(struct test_iosched *test_iosched)
{
int ret = 0;
unsigned int start_sec;
unsigned int num_bios;
- struct request_queue *q = td->req_q;
+ struct request_queue *q = test_iosched->req_q;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
- start_sec = td->start_sector + sizeof(int) * BIO_U32_SIZE
- * td->num_of_write_bios;
+ start_sec = test_iosched->start_sector + sizeof(int) * BIO_U32_SIZE
+ * test_iosched->num_of_write_bios;
if (utd->random_test_seed != 0)
ufs_test_pseudo_rnd_size(&utd->random_test_seed, &num_bios);
else
num_bios = DEFAULT_NUM_OF_BIOS;
/* Adding a write request */
- pr_info(
- "%s: Adding a write request with %d bios to Q, req_id=%d"
- , __func__, num_bios, td->wr_rd_next_req_id);
+ pr_info("%s: Adding a write request with %d bios to Q, req_id=%d",
+ __func__, num_bios, test_iosched->wr_rd_next_req_id);
utd->queue_complete = false;
- ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec, num_bios,
- TEST_PATTERN_5A, NULL);
-
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0, WRITE, start_sec,
+ num_bios, TEST_PATTERN_5A, NULL);
if (ret) {
pr_err("%s: failed to add a write request", __func__);
return ret;
@@ -573,9 +567,8 @@ static int ufs_test_run_write_read_test(struct test_data *td)
/* Adding a read request*/
pr_info("%s: Adding a read request to Q", __func__);
- ret = test_iosched_add_wr_rd_test_req(0, READ, start_sec,
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0, READ, start_sec,
num_bios, TEST_PATTERN_5A, NULL);
-
if (ret) {
pr_err("%s: failed to add a read request", __func__);
return ret;
@@ -585,7 +578,7 @@ static int ufs_test_run_write_read_test(struct test_data *td)
return ret;
}
-static void ufs_test_thread_complete(int result)
+static void ufs_test_thread_complete(struct ufs_test_data *utd, int result)
{
if (result)
utd->fail_threads++;
@@ -597,13 +590,21 @@ static void ufs_test_thread_complete(int result)
static void ufs_test_random_async_query(void *data, async_cookie_t cookie)
{
int op;
- struct ufs_hba *hba = (struct ufs_hba *)data;
+ struct test_iosched *test_iosched = data;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
+ struct scsi_device *sdev;
+ struct ufs_hba *hba;
int buff_len = QUERY_DESC_UNIT_MAX_SIZE;
u8 desc_buf[QUERY_DESC_UNIT_MAX_SIZE];
bool flag;
u32 att;
int ret = 0;
+ sdev = (struct scsi_device *)test_iosched->req_q->queuedata;
+ BUG_ON(!sdev->host);
+ hba = shost_priv(sdev->host);
+ BUG_ON(!hba);
+
op = ufs_test_pseudo_random_seed(&utd->random_test_seed, 1, 8);
/*
* When write data (descriptor/attribute/flag) queries are issued,
@@ -660,23 +661,23 @@ static void ufs_test_random_async_query(void *data, async_cookie_t cookie)
pr_err("%s: Query thread with op %d, failed with err %d.",
__func__, op, ret);
- ufs_test_thread_complete(ret);
+ ufs_test_thread_complete(utd, ret);
}
static void scenario_free_end_io_fn(struct request *rq, int err)
{
struct test_request *test_rq;
- struct test_data *ptd = test_get_test_data();
+ struct test_iosched *test_iosched = rq->q->elevator->elevator_data;
BUG_ON(!rq);
test_rq = (struct test_request *)rq->elv.priv[0];
BUG_ON(!test_rq);
- spin_lock_irq(&ptd->lock);
- ptd->dispatched_count--;
+ spin_lock_irq(&test_iosched->lock);
+ test_iosched->dispatched_count--;
list_del_init(&test_rq->queuelist);
- __blk_put_request(ptd->req_q, test_rq->rq);
- spin_unlock_irq(&ptd->lock);
+ __blk_put_request(test_iosched->req_q, test_rq->rq);
+ spin_unlock_irq(&test_iosched->lock);
kfree(test_rq->bios_buffer);
kfree(test_rq);
@@ -685,17 +686,19 @@ static void scenario_free_end_io_fn(struct request *rq, int err)
pr_err("%s: request %d completed, err=%d", __func__,
test_rq->req_id, err);
- check_test_completion();
+ check_test_completion(test_iosched);
}
-static bool ufs_test_multi_thread_completion(void)
+static bool ufs_test_multi_thread_completion(struct test_iosched *test_iosched)
{
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
return atomic_read(&utd->outstanding_threads) <= 0 &&
utd->test_stage != UFS_TEST_LUN_DEPTH_TEST_RUNNING;
}
-static bool long_rand_test_check_completion(void)
+static bool long_rand_test_check_completion(struct test_iosched *test_iosched)
{
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
if (utd->completed_req_count > LONG_RAND_TEST_NUM_REQS) {
pr_err("%s: Error: Completed more requests than total test requests.\nTerminating test."
, __func__);
@@ -704,8 +707,9 @@ static bool long_rand_test_check_completion(void)
return (utd->completed_req_count == LONG_RAND_TEST_NUM_REQS);
}
-static bool long_seq_test_check_completion(void)
+static bool long_seq_test_check_completion(struct test_iosched *test_iosched)
{
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
if (utd->completed_req_count > LONG_SEQ_TEST_NUM_REQS) {
pr_err("%s: Error: Completed more requests than total test requests"
, __func__);
@@ -736,10 +740,14 @@ static inline int ufs_test_toggle_direction(int toggle_factor, int iteration)
static void ufs_test_run_scenario(void *data, async_cookie_t cookie)
{
struct test_scenario *ts = (struct test_scenario *)data;
- int ret = 0, i, start_sec;
+ struct test_iosched *test_iosched = ts->test_iosched;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
+ int start_sec;
+ int i;
+ int ret = 0;
BUG_ON(!ts);
- start_sec = ts->td->start_sector;
+ start_sec = ts->test_iosched->start_sector;
for (i = 0; i < ts->total_req; i++) {
int num_bios = DEFAULT_NUM_OF_BIOS;
@@ -753,11 +761,12 @@ static void ufs_test_run_scenario(void *data, async_cookie_t cookie)
/* use randomly generated requests */
if (ts->rnd_req && utd->random_test_seed != 0)
pseudo_rnd_sector_and_size(&utd->random_test_seed,
- ts->td->start_sector, &start_sec, &num_bios);
+ ts->test_iosched->start_sector, &start_sec,
+ &num_bios);
- ret = test_iosched_add_wr_rd_test_req(0, direction, start_sec,
- num_bios, TEST_PATTERN_5A,
- scenario_free_end_io_fn);
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0,
+ direction, start_sec, num_bios, TEST_PATTERN_5A,
+ scenario_free_end_io_fn);
if (ret) {
pr_err("%s: failed to create request" , __func__);
break;
@@ -768,33 +777,36 @@ static void ufs_test_run_scenario(void *data, async_cookie_t cookie)
* when the requests pool is exhausted
*/
- if (ts->td->dispatched_count >= QUEUE_MAX_REQUESTS ||
+ if (test_iosched->dispatched_count >= QUEUE_MAX_REQUESTS ||
(ts->run_q && !(i % ts->run_q)))
- blk_post_runtime_resume(ts->td->req_q, 0);
+ blk_post_runtime_resume(test_iosched->req_q, 0);
}
- blk_post_runtime_resume(ts->td->req_q, 0);
- ufs_test_thread_complete(ret);
+ blk_post_runtime_resume(test_iosched->req_q, 0);
+ ufs_test_thread_complete(utd, ret);
}
-static int ufs_test_run_multi_query_test(struct test_data *td)
+static int ufs_test_run_multi_query_test(struct test_iosched *test_iosched)
{
int i;
+ struct ufs_test_data *utd;
struct scsi_device *sdev;
struct ufs_hba *hba;
- BUG_ON(!td || !td->req_q || !td->req_q->queuedata);
- sdev = (struct scsi_device *)td->req_q->queuedata;
+ BUG_ON(!test_iosched || !test_iosched->req_q ||
+ !test_iosched->req_q->queuedata);
+ sdev = (struct scsi_device *)test_iosched->req_q->queuedata;
BUG_ON(!sdev->host);
hba = shost_priv(sdev->host);
BUG_ON(!hba);
+ utd = test_iosched->blk_dev_test_data;
atomic_set(&utd->outstanding_threads, 0);
utd->fail_threads = 0;
init_completion(&utd->outstanding_complete);
for (i = 0; i < MAX_PARALLEL_QUERIES; ++i) {
atomic_inc(&utd->outstanding_threads);
- async_schedule(ufs_test_random_async_query, hba);
+ async_schedule(ufs_test_random_async_query, test_iosched);
}
if (!wait_for_completion_timeout(&utd->outstanding_complete,
@@ -802,18 +814,20 @@ static int ufs_test_run_multi_query_test(struct test_data *td)
pr_err("%s: Multi-query test timed-out %d threads left",
__func__, atomic_read(&utd->outstanding_threads));
}
- test_iosched_mark_test_completion();
+ test_iosched_mark_test_completion(test_iosched);
return 0;
}
-static int ufs_test_run_parallel_read_and_write_test(struct test_data *td)
+static int ufs_test_run_parallel_read_and_write_test(
+ struct test_iosched *test_iosched)
{
struct test_scenario *read_data, *write_data;
int i;
bool changed_seed = false;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
- read_data = get_scenario(td, SCEN_RANDOM_READ_50);
- write_data = get_scenario(td, SCEN_RANDOM_WRITE_50);
+ read_data = get_scenario(test_iosched, SCEN_RANDOM_READ_50);
+ write_data = get_scenario(test_iosched, SCEN_RANDOM_WRITE_50);
/* allow randomness even if user forgot */
if (utd->random_test_seed <= 0) {
@@ -836,7 +850,7 @@ static int ufs_test_run_parallel_read_and_write_test(struct test_data *td)
pr_err("%s: Multi-thread test timed-out %d threads left",
__func__, atomic_read(&utd->outstanding_threads));
}
- check_test_completion();
+ check_test_completion(test_iosched);
/* clear random seed if changed */
if (changed_seed)
@@ -847,6 +861,7 @@ static int ufs_test_run_parallel_read_and_write_test(struct test_data *td)
static void ufs_test_run_synchronous_scenario(struct test_scenario *read_data)
{
+ struct ufs_test_data *utd = read_data->test_iosched->blk_dev_test_data;
init_completion(&utd->outstanding_complete);
atomic_set(&utd->outstanding_threads, 1);
async_schedule(ufs_test_run_scenario, read_data);
@@ -857,18 +872,21 @@ static void ufs_test_run_synchronous_scenario(struct test_scenario *read_data)
}
}
-static int ufs_test_run_lun_depth_test(struct test_data *td)
+static int ufs_test_run_lun_depth_test(struct test_iosched *test_iosched)
{
struct test_scenario *read_data, *write_data;
struct scsi_device *sdev;
bool changed_seed = false;
int i = 0, num_req[LUN_DEPTH_TEST_SIZE];
int lun_qdepth, nutrs, num_scenarios;
+ struct ufs_test_data *utd;
- BUG_ON(!td || !td->req_q || !td->req_q->queuedata);
- sdev = (struct scsi_device *)td->req_q->queuedata;
+ BUG_ON(!test_iosched || !test_iosched->req_q ||
+ !test_iosched->req_q->queuedata);
+ sdev = (struct scsi_device *)test_iosched->req_q->queuedata;
lun_qdepth = sdev->max_queue_depth;
nutrs = sdev->host->can_queue;
+ utd = test_iosched->blk_dev_test_data;
/* allow randomness even if user forgot */
if (utd->random_test_seed <= 0) {
@@ -901,8 +919,8 @@ static int ufs_test_run_lun_depth_test(struct test_data *td)
num_scenarios = i;
utd->test_stage = UFS_TEST_LUN_DEPTH_TEST_RUNNING;
utd->fail_threads = 0;
- read_data = get_scenario(td, SCEN_RANDOM_READ_32_NO_FLUSH);
- write_data = get_scenario(td, SCEN_RANDOM_WRITE_32_NO_FLUSH);
+ read_data = get_scenario(test_iosched, SCEN_RANDOM_READ_32_NO_FLUSH);
+ write_data = get_scenario(test_iosched, SCEN_RANDOM_WRITE_32_NO_FLUSH);
for (i = 0; i < num_scenarios; i++) {
int reqs = num_req[i];
@@ -915,7 +933,7 @@ static int ufs_test_run_lun_depth_test(struct test_data *td)
}
utd->test_stage = UFS_TEST_LUN_DEPTH_DONE_ISSUING_REQ;
- check_test_completion();
+ check_test_completion(test_iosched);
/* clear random seed if changed */
if (changed_seed)
@@ -927,22 +945,23 @@ static int ufs_test_run_lun_depth_test(struct test_data *td)
static void long_test_free_end_io_fn(struct request *rq, int err)
{
struct test_request *test_rq;
- struct test_data *ptd = test_get_test_data();
+ struct test_iosched *test_iosched = rq->q->elevator->elevator_data;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
- if (rq) {
- test_rq = (struct test_request *)rq->elv.priv[0];
- } else {
+ if (!rq) {
pr_err("%s: error: NULL request", __func__);
return;
}
+ test_rq = (struct test_request *)rq->elv.priv[0];
+
BUG_ON(!test_rq);
- spin_lock_irq(&ptd->lock);
- ptd->dispatched_count--;
+ spin_lock_irq(&test_iosched->lock);
+ test_iosched->dispatched_count--;
list_del_init(&test_rq->queuelist);
- __blk_put_request(ptd->req_q, test_rq->rq);
- spin_unlock_irq(&ptd->lock);
+ __blk_put_request(test_iosched->req_q, test_rq->rq);
+ spin_unlock_irq(&test_iosched->lock);
if (utd->test_stage == UFS_TEST_LONG_SEQUENTIAL_MIXED_STAGE2 &&
rq_data_dir(rq) == READ &&
@@ -950,7 +969,7 @@ static void long_test_free_end_io_fn(struct request *rq, int err)
/* if the pattern does not match */
pr_err("%s: read pattern not as expected", __func__);
utd->test_stage = UFS_TEST_ERROR;
- check_test_completion();
+ check_test_completion(test_iosched);
return;
}
@@ -962,7 +981,7 @@ static void long_test_free_end_io_fn(struct request *rq, int err)
pr_err("%s: request %d completed, err=%d", __func__,
test_rq->req_id, err);
- check_test_completion();
+ check_test_completion(test_iosched);
}
/**
@@ -974,23 +993,24 @@ static void long_test_free_end_io_fn(struct request *rq, int err)
* 1. Only read/write (STAGE_1 or no stage)
* 2. Simultaneous read and write to the same LBAs (STAGE_2)
*/
-static int run_long_test(struct test_data *td)
+static int run_long_test(struct test_iosched *test_iosched)
{
int ret = 0;
int direction, long_test_num_requests, num_bios_per_request;
static unsigned int inserted_requests;
u32 sector, seed, num_bios, seq_sector_delta;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
- BUG_ON(!td);
- sector = td->start_sector;
+ BUG_ON(!test_iosched);
+ sector = test_iosched->start_sector;
if (utd->test_stage != UFS_TEST_LONG_SEQUENTIAL_MIXED_STAGE2) {
- td->test_count = 0;
+ test_iosched->test_count = 0;
utd->completed_req_count = 0;
inserted_requests = 0;
}
/* Set test parameters */
- switch (td->test_info.testcase) {
+ switch (test_iosched->test_info.testcase) {
case UFS_TEST_LONG_RANDOM_READ:
num_bios_per_request = 1;
long_test_num_requests = LONG_RAND_TEST_NUM_REQS;
@@ -1019,7 +1039,7 @@ static int run_long_test(struct test_data *td)
seed = utd->random_test_seed ? utd->random_test_seed : MAGIC_SEED;
pr_info("%s: Adding %d requests, first req_id=%d", __func__,
- long_test_num_requests, td->wr_rd_next_req_id);
+ long_test_num_requests, test_iosched->wr_rd_next_req_id);
do {
/*
@@ -1029,12 +1049,12 @@ static int run_long_test(struct test_data *td)
* includes a safety margin) and then call the block layer
* to fetch them
*/
- if (td->test_count >= QUEUE_MAX_REQUESTS) {
- blk_post_runtime_resume(td->req_q, 0);
+ if (test_iosched->test_count >= QUEUE_MAX_REQUESTS) {
+ blk_post_runtime_resume(test_iosched->req_q, 0);
continue;
}
- switch (td->test_info.testcase) {
+ switch (test_iosched->test_info.testcase) {
case UFS_TEST_LONG_SEQUENTIAL_READ:
case UFS_TEST_LONG_SEQUENTIAL_WRITE:
case UFS_TEST_LONG_SEQUENTIAL_MIXED:
@@ -1044,24 +1064,24 @@ static int run_long_test(struct test_data *td)
break;
case UFS_TEST_LONG_RANDOM_READ:
case UFS_TEST_LONG_RANDOM_WRITE:
- pseudo_rnd_sector_and_size(&seed, td->start_sector,
- &sector, &num_bios);
+ pseudo_rnd_sector_and_size(&seed,
+ test_iosched->start_sector, &sector, &num_bios);
default:
break;
}
- ret = test_iosched_add_wr_rd_test_req(0, direction, sector,
- num_bios_per_request, TEST_PATTERN_5A,
- long_test_free_end_io_fn);
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0,
+ direction, sector, num_bios_per_request,
+ TEST_PATTERN_5A, long_test_free_end_io_fn);
if (ret) {
pr_err("%s: failed to create request" , __func__);
break;
}
inserted_requests++;
if (utd->test_stage == UFS_TEST_LONG_SEQUENTIAL_MIXED_STAGE2) {
- ret = test_iosched_add_wr_rd_test_req(0, READ, sector,
- num_bios_per_request, TEST_PATTERN_5A,
- long_test_free_end_io_fn);
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0,
+ READ, sector, num_bios_per_request,
+ TEST_PATTERN_5A, long_test_free_end_io_fn);
if (ret) {
pr_err("%s: failed to create request" ,
__func__);
@@ -1074,31 +1094,33 @@ static int run_long_test(struct test_data *td)
/* in this case the queue will not run in the above loop */
if (long_test_num_requests < QUEUE_MAX_REQUESTS)
- blk_post_runtime_resume(td->req_q, 0);
+ blk_post_runtime_resume(test_iosched->req_q, 0);
return ret;
}
-static int run_mixed_long_seq_test(struct test_data *td)
+static int run_mixed_long_seq_test(struct test_iosched *test_iosched)
{
int ret;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
utd->test_stage = UFS_TEST_LONG_SEQUENTIAL_MIXED_STAGE1;
- ret = run_long_test(td);
+ ret = run_long_test(test_iosched);
if (ret)
goto out;
pr_info("%s: First write iteration completed.", __func__);
pr_info("%s: Starting mixed write and reads sequence.", __func__);
utd->test_stage = UFS_TEST_LONG_SEQUENTIAL_MIXED_STAGE2;
- ret = run_long_test(td);
+ ret = run_long_test(test_iosched);
out:
return ret;
}
-static int long_rand_test_calc_iops(struct test_data *td)
+static int long_rand_test_calc_iops(struct test_iosched *test_iosched)
{
unsigned long mtime, num_ios, iops;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
mtime = ktime_to_ms(utd->test_info.test_duration);
num_ios = utd->completed_req_count;
@@ -1113,13 +1135,14 @@ static int long_rand_test_calc_iops(struct test_data *td)
pr_info("%s: IOPS: %lu IOP/sec\n", __func__, iops);
- return ufs_test_post(td);
+ return ufs_test_post(test_iosched);
}
-static int long_seq_test_calc_throughput(struct test_data *td)
+static int long_seq_test_calc_throughput(struct test_iosched *test_iosched)
{
unsigned long fraction, integer;
unsigned long mtime, byte_count;
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
mtime = ktime_to_ms(utd->test_info.test_duration);
byte_count = utd->test_info.test_byte_count;
@@ -1141,15 +1164,15 @@ static int long_seq_test_calc_throughput(struct test_data *td)
pr_info("%s: Throughput: %lu.%lu MiB/sec\n", __func__, integer,
fraction);
- return ufs_test_post(td);
+ return ufs_test_post(test_iosched);
}
-static bool ufs_data_integrity_completion(void)
+static bool ufs_data_integrity_completion(struct test_iosched *test_iosched)
{
- struct test_data *ptd = test_get_test_data();
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
bool ret = false;
- if (!ptd->dispatched_count) {
+ if (!test_iosched->dispatched_count) {
/* q is empty in this case */
if (!utd->queue_complete) {
utd->queue_complete = true;
@@ -1163,15 +1186,16 @@ static bool ufs_data_integrity_completion(void)
return ret;
}
-static int ufs_test_run_data_integrity_test(struct test_data *td)
+static int ufs_test_run_data_integrity_test(struct test_iosched *test_iosched)
{
int ret = 0;
int i, j;
unsigned int start_sec, num_bios, retries = NUM_UNLUCKY_RETRIES;
- struct request_queue *q = td->req_q;
+ struct request_queue *q = test_iosched->req_q;
int sectors[QUEUE_MAX_REQUESTS] = {0};
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
- start_sec = td->start_sector;
+ start_sec = test_iosched->start_sector;
utd->queue_complete = false;
if (utd->random_test_seed != 0) {
@@ -1183,13 +1207,14 @@ static int ufs_test_run_data_integrity_test(struct test_data *td)
/* Adding write requests */
pr_info("%s: Adding %d write requests, first req_id=%d", __func__,
- QUEUE_MAX_REQUESTS, td->wr_rd_next_req_id);
+ QUEUE_MAX_REQUESTS, test_iosched->wr_rd_next_req_id);
for (i = 0; i < QUEUE_MAX_REQUESTS; i++) {
/* make sure that we didn't draw the same start_sector twice */
while (retries--) {
pseudo_rnd_sector_and_size(&utd->random_test_seed,
- td->start_sector, &start_sec, &num_bios);
+ test_iosched->start_sector, &start_sec,
+ &num_bios);
sectors[i] = start_sec;
for (j = 0; (j < i) && (sectors[i] != sectors[j]); j++)
/* just increment j */;
@@ -1204,8 +1229,8 @@ static int ufs_test_run_data_integrity_test(struct test_data *td)
}
retries = NUM_UNLUCKY_RETRIES;
- ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec, 1, i,
- long_test_free_end_io_fn);
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0, WRITE,
+ start_sec, 1, i, long_test_free_end_io_fn);
if (ret) {
pr_err("%s: failed to add a write request", __func__);
@@ -1219,11 +1244,11 @@ static int ufs_test_run_data_integrity_test(struct test_data *td)
/* Adding read requests */
pr_info("%s: Adding %d read requests, first req_id=%d", __func__,
- QUEUE_MAX_REQUESTS, td->wr_rd_next_req_id);
+ QUEUE_MAX_REQUESTS, test_iosched->wr_rd_next_req_id);
for (i = 0; i < QUEUE_MAX_REQUESTS; i++) {
- ret = test_iosched_add_wr_rd_test_req(0, READ, sectors[i],
- 1, i, long_test_free_end_io_fn);
+ ret = test_iosched_add_wr_rd_test_req(test_iosched, 0, READ,
+ sectors[i], 1, i, long_test_free_end_io_fn);
if (ret) {
pr_err("%s: failed to add a read request", __func__);
@@ -1241,6 +1266,8 @@ static ssize_t ufs_test_write(struct file *file, const char __user *buf,
int ret = 0;
int i;
int number;
+ struct seq_file *seq_f = file->private_data;
+ struct ufs_test_data *utd = seq_f->private;
ret = kstrtoint_from_user(buf, count, 0, &number);
if (ret < 0) {
@@ -1322,7 +1349,8 @@ static ssize_t ufs_test_write(struct file *file, const char __user *buf,
pr_info("%s: ====================", __func__);
utd->test_info.test_byte_count = 0;
- ret = test_iosched_start_test(&utd->test_info);
+ ret = test_iosched_start_test(utd->test_iosched,
+ &utd->test_info);
if (ret) {
pr_err("%s: Test failed, err=%d.", __func__, ret);
return ret;
@@ -1348,19 +1376,21 @@ TEST_OPS(long_sequential_mixed, LONG_SEQUENTIAL_MIXED);
TEST_OPS(parallel_read_and_write, PARALLEL_READ_AND_WRITE);
TEST_OPS(lun_depth, LUN_DEPTH);
-static void ufs_test_debugfs_cleanup(void)
+static void ufs_test_debugfs_cleanup(struct test_iosched *test_iosched)
{
- debugfs_remove_recursive(test_iosched_get_debugfs_tests_root());
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
+ debugfs_remove_recursive(test_iosched->debug.debug_root);
kfree(utd->test_list);
}
-static int ufs_test_debugfs_init(void)
+static int ufs_test_debugfs_init(struct ufs_test_data *utd)
{
struct dentry *utils_root, *tests_root;
int ret = 0;
+ struct test_iosched *ts = utd->test_iosched;
- utils_root = test_iosched_get_debugfs_utils_root();
- tests_root = test_iosched_get_debugfs_tests_root();
+ utils_root = ts->debug.debug_utils_root;
+ tests_root = ts->debug.debug_tests_root;
utd->test_list = kmalloc(sizeof(struct dentry *) * NUM_TESTS,
GFP_KERNEL);
@@ -1419,34 +1449,57 @@ static int ufs_test_debugfs_init(void)
goto exit;
exit_err:
- ufs_test_debugfs_cleanup();
+ ufs_test_debugfs_cleanup(ts);
exit:
return ret;
}
-static void ufs_test_probe(void)
+static int ufs_test_probe(struct test_iosched *test_iosched)
{
- ufs_test_debugfs_init();
+ struct ufs_test_data *utd;
+ int ret;
+
+ utd = kzalloc(sizeof(*utd), GFP_KERNEL);
+ if (!utd) {
+ pr_err("%s: failed to allocate ufs test data\n", __func__);
+ return -ENOMEM;
+ }
+
+ init_waitqueue_head(&utd->wait_q);
+ utd->test_iosched = test_iosched;
+ test_iosched->blk_dev_test_data = utd;
+
+ ret = ufs_test_debugfs_init(utd);
+ if (ret) {
+ pr_err("%s: failed to init debug-fs entries, ret=%d\n",
+ __func__, ret);
+ kfree(utd);
+ }
+
+ return ret;
}
-static void ufs_test_remove(void)
+static void ufs_test_remove(struct test_iosched *test_iosched)
{
- ufs_test_debugfs_cleanup();
+ struct ufs_test_data *utd = test_iosched->blk_dev_test_data;
+
+ ufs_test_debugfs_cleanup(test_iosched);
+ test_iosched->blk_dev_test_data = NULL;
+ kfree(utd);
}
-int __init ufs_test_init(void)
+static int __init ufs_test_init(void)
{
- utd = kzalloc(sizeof(struct ufs_test_data), GFP_KERNEL);
- if (!utd) {
- pr_err("%s: failed to allocate ufs_test_data", __func__);
- return -ENODEV;
- }
+ ufs_bdt = kzalloc(sizeof(*ufs_bdt), GFP_KERNEL);
+ if (!ufs_bdt)
+ return -ENOMEM;
- init_waitqueue_head(&utd->wait_q);
- utd->bdt.init_fn = ufs_test_probe;
- utd->bdt.exit_fn = ufs_test_remove;
- INIT_LIST_HEAD(&utd->bdt.list);
- test_iosched_register(&utd->bdt);
+ ufs_bdt->type_prefix = UFS_TEST_BLK_DEV_TYPE_PREFIX;
+ ufs_bdt->init_fn = ufs_test_probe;
+ ufs_bdt->exit_fn = ufs_test_remove;
+ INIT_LIST_HEAD(&ufs_bdt->list);
+
+ test_iosched_register(ufs_bdt);
return 0;
}
@@ -1454,12 +1507,11 @@ EXPORT_SYMBOL_GPL(ufs_test_init);
static void __exit ufs_test_exit(void)
{
- test_iosched_unregister(&utd->bdt);
- kfree(utd);
+ test_iosched_unregister(ufs_bdt);
+ kfree(ufs_bdt);
}
module_init(ufs_test_init);
module_exit(ufs_test_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("UFC test");
-