static void long_seq_test_free_end_io_fn(struct request *rq, int err) { struct test_request *test_rq; struct test_data *ptd = test_get_test_data(); if (rq) test_rq = (struct test_request *)rq->elv.priv[0]; else { test_pr_err("%s: error: NULL request", __func__); return; } BUG_ON(!test_rq); spin_lock_irq(&ptd->lock); ptd->dispatched_count--; list_del_init(&test_rq->queuelist); __blk_put_request(ptd->req_q, test_rq->rq); spin_unlock_irq(&ptd->lock); kfree(test_rq->bios_buffer); kfree(test_rq); utd->completed_req_count++; test_pr_err("%s: request %d completed, err=%d", __func__, test_rq->req_id, err); check_test_completion(); }
static int ufs_test_debugfs_init(void) { struct dentry *utils_root, *tests_root; utils_root = test_iosched_get_debugfs_utils_root(); tests_root = test_iosched_get_debugfs_tests_root(); if (!utils_root || !tests_root) { test_pr_err("%s: Failed to create debugfs root.", __func__); return -EINVAL; } utd->debug.random_test_seed = debugfs_create_u32("random_test_seed", S_IRUGO | S_IWUGO, utils_root, &utd->random_test_seed); if (!utd->debug.random_test_seed) { test_pr_err("%s: Could not create debugfs random_test_seed.", __func__); return -ENOMEM; } utd->debug.write_read_test = debugfs_create_file("write_read_test", S_IRUGO | S_IWUGO, tests_root, NULL, &write_read_test_ops); if (!utd->debug.write_read_test) { debugfs_remove(utd->debug.random_test_seed); test_pr_err("%s: Could not create debugfs write_read_test.", __func__); return -ENOMEM; } return 0; }
static int ufs_test_run_write_read_test(struct test_data *td) { int ret = 0; unsigned int start_sec; unsigned int num_bios; struct request_queue *q = td->req_q; start_sec = td->start_sector + sizeof(int) * BIO_U32_SIZE * td->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 */ test_pr_info( "%s: Adding a write request with %d bios to Q, req_id=%d" , __func__, num_bios, td->wr_rd_next_req_id); utd->write_completed = false; ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec, num_bios, TEST_PATTERN_5A, ufs_test_write_read_test_end_io_fn); if (ret) { test_pr_err("%s: failed to add a write request", __func__); return ret; } /* waiting for the write request to finish */ blk_run_queue(q); wait_event(utd->wait_q, utd->write_completed); /* Adding a read request*/ test_pr_info("%s: Adding a read request to Q", __func__); ret = test_iosched_add_wr_rd_test_req(0, READ, start_sec, num_bios, TEST_PATTERN_5A, NULL); if (ret) { test_pr_err("%s: failed to add a read request", __func__); return ret; } blk_run_queue(q); return ret; }
static int run_long_seq_test(struct test_data *td) { int ret = 0; int direction; static unsigned int inserted_requests; BUG_ON(!td); td->test_count = 0; utd->completed_req_count = 0; inserted_requests = 0; if (td->test_info.testcase == TEST_LONG_SEQUENTIAL_READ) direction = READ; else direction = WRITE; test_pr_info("%s: Adding %d requests, first req_id=%d", __func__, LONG_SEQ_TEST_NUM_REQS, td->wr_rd_next_req_id); do { /* * since our requests come from a pool containing 128 * requests, we don't want to exhaust this quantity, * therefore we add up to QUEUE_MAX_REQUESTS (which * includes a safety margin) and then call the mmc layer * to fetch them */ if (td->test_count >= QUEUE_MAX_REQUESTS) { blk_run_queue(td->req_q); continue; } ret = test_iosched_add_wr_rd_test_req(0, direction, td->start_sector, TEST_MAX_BIOS_PER_REQ, TEST_PATTERN_5A, long_seq_test_free_end_io_fn); if (ret) { test_pr_err("%s: failed to create request" , __func__); break; } inserted_requests++; td->test_info.test_byte_count += (TEST_MAX_BIOS_PER_REQ * sizeof(unsigned int) * BIO_U32_SIZE); } while (inserted_requests < LONG_SEQ_TEST_NUM_REQS); /* in this case the queue will not run in the above loop */ if (LONG_SEQ_TEST_NUM_REQS < QUEUE_MAX_REQUESTS) blk_run_queue(td->req_q); return ret; }
static char *ufs_test_get_test_case_str(struct test_data *td) { if (!td) { test_pr_err("%s: NULL td", __func__); return NULL; } switch (td->test_info.testcase) { case UFS_TEST_WRITE_READ_TEST: return "UFS write read test"; break; default: return "Unknown test"; } }
int __init ufs_test_init(void) { utd = kzalloc(sizeof(struct ufs_test_data), GFP_KERNEL); if (!utd) { test_pr_err("%s: failed to allocate ufs_test_data", __func__); return -ENODEV; } 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); return 0; }
static int run_long_seq_test(struct test_data *td) { int ret = 0; int direction; static unsigned int inserted_requests; BUG_ON(!td); td->test_count = 0; utd->completed_req_count = 0; inserted_requests = 0; if (td->test_info.testcase == TEST_LONG_SEQUENTIAL_READ) direction = READ; else direction = WRITE; test_pr_info("%s: Adding %d requests, first req_id=%d", __func__, LONG_SEQ_TEST_NUM_REQS, td->wr_rd_next_req_id); do { if (td->test_count >= QUEUE_MAX_REQUESTS) { blk_run_queue(td->req_q); continue; } ret = test_iosched_add_wr_rd_test_req(0, direction, td->start_sector, TEST_MAX_BIOS_PER_REQ, TEST_PATTERN_5A, long_seq_test_free_end_io_fn); if (ret) { test_pr_err("%s: failed to create request" , __func__); break; } inserted_requests++; td->test_info.test_byte_count += (TEST_MAX_BIOS_PER_REQ * sizeof(unsigned int) * BIO_U32_SIZE); } while (inserted_requests < LONG_SEQ_TEST_NUM_REQS); if (LONG_SEQ_TEST_NUM_REQS < QUEUE_MAX_REQUESTS) blk_run_queue(td->req_q); return ret; }
static ssize_t ufs_test_write_read_test_write_cb(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int ret = 0; int i; int number; sscanf(buf, "%d", &number); if (number <= 0) number = 1; test_pr_info("%s:the test will run for %d iterations.", __func__, number); memset(&utd->test_info, 0, sizeof(struct test_info)); /* Initializing test */ utd->test_info.data = utd; utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str; utd->test_info.testcase = UFS_TEST_WRITE_READ_TEST; utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk; utd->test_info.run_test_fn = ufs_test_run_write_read_test; /* Running the test multiple times */ for (i = 0; i < number; ++i) { ret = test_iosched_start_test(&utd->test_info); if (ret) { test_pr_err("%s: Test failed.", __func__); return ret; } } test_pr_info("%s: Completed all the ufs test iterations.", __func__); return count; }
static int ufs_test_debugfs_init(void) { struct dentry *utils_root, *tests_root; int ret = 0; utils_root = test_iosched_get_debugfs_utils_root(); tests_root = test_iosched_get_debugfs_tests_root(); if (!utils_root || !tests_root) { test_pr_err("%s: Failed to create debugfs root.", __func__); ret = -EINVAL; goto exit; } utd->debug.random_test_seed = debugfs_create_u32("random_test_seed", S_IRUGO | S_IWUGO, utils_root, &utd->random_test_seed); if (!utd->debug.random_test_seed) { test_pr_err("%s: Could not create debugfs random_test_seed.", __func__); ret = -ENOMEM; goto exit; } utd->debug.write_read_test = debugfs_create_file("ufs_write_read_test", S_IRUGO | S_IWUGO, tests_root, NULL, &write_read_test_ops); if (!utd->debug.write_read_test) { ret = -ENOMEM; goto exit_err; } utd->debug.long_sequential_read_test = debugfs_create_file( "ufs_long_sequential_read_test", S_IRUGO | S_IWUGO, tests_root, NULL, &long_sequential_read_test_ops); if (!utd->debug.long_sequential_read_test) { ret = -ENOMEM; goto exit_err; } utd->debug.long_sequential_write_test = debugfs_create_file( "ufs_long_sequential_write_test", S_IRUGO | S_IWUGO, tests_root, NULL, &long_sequential_write_test_ops); if (!utd->debug.long_sequential_write_test) { ret = -ENOMEM; goto exit_err; } goto exit; exit_err: debugfs_remove_recursive(tests_root); exit: return ret; }