blob: 03c58a4ee2d62e018e045098e43ed72bffe6b16b [file] [log] [blame]
Dolev Ravivd7c3cbe2013-02-11 11:58:14 +02001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/blkdev.h>
16#include <linux/debugfs.h>
17#include <linux/test-iosched.h>
18#include <scsi/scsi_device.h>
19#include <scsi/scsi_cmnd.h>
20#include <../sd.h>
21
22#define MODULE_NAME "ufs_test"
23
24#define TEST_MAX_BIOS_PER_REQ 120
25#define LARGE_PRIME_1 1103515367
26#define LARGE_PRIME_2 35757
27#define DEFAULT_NUM_OF_BIOS 2
28
29#define test_pr_debug(fmt, args...) pr_debug("%s: "fmt"\n", MODULE_NAME, args)
30#define test_pr_info(fmt, args...) pr_info("%s: "fmt"\n", MODULE_NAME, args)
31#define test_pr_err(fmt, args...) pr_err("%s: "fmt"\n", MODULE_NAME, args)
32
33enum ufs_test_testcases {
34 UFS_TEST_WRITE_READ_TEST,
35};
36
37struct ufs_test_debug {
38 struct dentry *write_read_test; /* basic test */
39 struct dentry *random_test_seed; /* parameters in utils */
40};
41
42struct ufs_test_data {
43 /* Data structure for debugfs dentrys */
44 struct ufs_test_debug debug;
45 /*
46 * Data structure containing individual test information, including
47 * self-defined specific data
48 */
49 struct test_info test_info;
50 /* device test */
51 struct blk_dev_test_type bdt;
52 /* A wait queue for OPs to complete */
53 wait_queue_head_t wait_q;
54 /* a flag for read compleation */
55 bool read_completed;
56 /* a flag for write compleation */
57 bool write_completed;
58 /*
59 * To determine the number of r/w bios. When seed = 0, random is
60 * disabled and 2 BIOs are written.
61 */
62 unsigned int random_test_seed;
63};
64
65static struct ufs_test_data *utd;
66
67static bool message_repeat;
68
69static char *ufs_test_get_test_case_str(struct test_data *td)
70{
71 if (!td) {
72 test_pr_err("%s: NULL td", __func__);
73 return NULL;
74 }
75
76 switch (td->test_info.testcase) {
77 case UFS_TEST_WRITE_READ_TEST:
78 return "UFS write read test";
79 break;
80 default:
81 return "Unknown test";
82 }
83}
84
85static unsigned int ufs_test_pseudo_random_seed(unsigned int *seed_number,
86 unsigned int min_val, unsigned int max_val)
87{
88 int ret = 0;
89
90 if (!seed_number)
91 return 0;
92
93 *seed_number = ((unsigned int) (((unsigned long) *seed_number
94 * (unsigned long) LARGE_PRIME_1) + LARGE_PRIME_2));
95 ret = (unsigned int) ((*seed_number) % max_val);
96
97 return (ret > min_val ? ret : min_val);
98}
99
100static void ufs_test_pseudo_rnd_size(unsigned int *seed,
101 unsigned int *num_of_bios)
102{
103 *num_of_bios = ufs_test_pseudo_random_seed(seed, 1,
104 TEST_MAX_BIOS_PER_REQ);
105 if (!(*num_of_bios))
106 *num_of_bios = DEFAULT_NUM_OF_BIOS;
107}
108
109static void ufs_test_write_read_test_end_io_fn(struct request *rq, int err)
110{
111 struct test_request *test_rq = (struct test_request *)rq->elv.priv[0];
112 BUG_ON(!test_rq);
113
114 test_rq->req_completed = 1;
115 test_rq->req_result = err;
116
117 test_pr_info("%s: request %d completed, err=%d",
118 __func__, test_rq->req_id, err);
119
120 utd->write_completed = true;
121 wake_up(&utd->wait_q);
122}
123
124static struct gendisk *ufs_test_get_rq_disk(void)
125{
126 struct request_queue *req_q = test_iosched_get_req_queue();
127 struct scsi_device *sd;
128 struct device *dev;
129 struct scsi_disk *sdkp;
130 struct gendisk *gd;
131
132 if (!req_q) {
133 test_pr_info("%s: Could not fetch request_queue", __func__);
134 gd = NULL;
135 goto exit;
136 }
137
138 sd = (struct scsi_device *)req_q->queuedata;
139
140 dev = &sd->sdev_gendev;
141 sdkp = scsi_disk_get_from_dev(dev);
142 if (!sdkp) {
143 test_pr_info("%s: Could not fatch scsi disk", __func__);
144 gd = NULL;
145 goto exit;
146 }
147
148 gd = sdkp->disk;
149exit:
150 return gd;
151}
152
153static int ufs_test_run_write_read_test(struct test_data *td)
154{
155 int ret = 0;
156 unsigned int start_sec;
157 unsigned int num_bios;
158 struct request_queue *q = td->req_q;
159
160
161 start_sec = td->start_sector + sizeof(int) * BIO_U32_SIZE
162 * td->num_of_write_bios;
163 if (utd->random_test_seed != 0)
164 ufs_test_pseudo_rnd_size(&utd->random_test_seed, &num_bios);
165 else
166 num_bios = DEFAULT_NUM_OF_BIOS;
167
168 /* Adding a write request */
169 test_pr_info("%s: Adding a write requests to Q, first req_id=%d",
170 __func__, td->wr_rd_next_req_id);
171
172 utd->write_completed = false;
173 ret = test_iosched_add_wr_rd_test_req(0, WRITE, start_sec,
174 num_bios, TEST_PATTERN_5A,
175 ufs_test_write_read_test_end_io_fn);
176
177 if (ret) {
178 test_pr_err("%s: failed to add a write request", __func__);
179 return ret;
180 }
181
182 /* waiting for the write request to finish */
183 blk_run_queue(q);
184 wait_event(utd->wait_q, utd->write_completed);
185
186 /* Adding a read request*/
187 test_pr_info("%s: Adding a read request to Q", __func__);
188
189 ret = test_iosched_add_wr_rd_test_req(0, READ, start_sec,
190 num_bios, TEST_PATTERN_5A, NULL);
191
192 if (ret) {
193 test_pr_err("%s: failed to add a read request", __func__);
194 return ret;
195 }
196
197 blk_run_queue(q);
198 return ret;
199}
200
201static
202int ufs_test_write_read_test_open_cb(struct inode *inode, struct file *file)
203{
204 file->private_data = inode->i_private;
205 message_repeat = 1;
206 test_pr_info("%s:UFS test initialized", __func__);
207 return 0;
208}
209
210static ssize_t ufs_test_write_read_test_write_cb(struct file *file,
211 const char __user *buf,
212 size_t count, loff_t *ppos)
213{
214 int ret = 0;
215 int i;
216 int number;
217
218 sscanf(buf, "%d", &number);
219
220 if (number <= 0)
221 number = 1;
222
223 test_pr_info("%s:the test will run for %d iterations.",
224 __func__, number);
225 memset(&utd->test_info, 0, sizeof(struct test_info));
226
227 /* Initializing test */
228 utd->test_info.data = utd;
229 utd->test_info.get_test_case_str_fn = ufs_test_get_test_case_str;
230 utd->test_info.testcase = UFS_TEST_WRITE_READ_TEST;
231 utd->test_info.get_rq_disk_fn = ufs_test_get_rq_disk;
232 utd->test_info.run_test_fn = ufs_test_run_write_read_test;
233
234 /* Running the test multiple times */
235 for (i = 0; i < number; ++i) {
236 ret = test_iosched_start_test(&utd->test_info);
237 if (ret) {
238 test_pr_err("%s: Test failed.", __func__);
239 return ret;
240 }
241 }
242
243 test_pr_info("%s: Completed all the ufs test iterations.", __func__);
244
245 return count;
246}
247
248static ssize_t ufs_test_write_read_test_read_cb(struct file *file,
249 char __user *buffer, size_t count, loff_t *offset)
250{
251 memset((void *) buffer, 0, count);
252
253 snprintf(buffer, count, "\nThis is a UFS write-read test for debug.\n");
254
255 if (message_repeat == 1) {
256 message_repeat = 0;
257 return strnlen(buffer, count);
258 } else
259 return 0;
260}
261
262const struct file_operations write_read_test_ops = {
263 .open = ufs_test_write_read_test_open_cb,
264 .write = ufs_test_write_read_test_write_cb,
265 .read = ufs_test_write_read_test_read_cb,
266};
267
268static void ufs_test_debugfs_cleanup(void)
269{
270 debugfs_remove(utd->debug.write_read_test);
271}
272
273static int ufs_test_debugfs_init(void)
274{
275 struct dentry *utils_root, *tests_root;
276
277 utils_root = test_iosched_get_debugfs_utils_root();
278 tests_root = test_iosched_get_debugfs_tests_root();
279
280 if (!utils_root || !tests_root) {
281 test_pr_err("%s: Failed to create debugfs root.", __func__);
282 return -EINVAL;
283 }
284
285 utd->debug.random_test_seed = debugfs_create_u32("random_test_seed",
286 S_IRUGO | S_IWUGO, utils_root, &utd->random_test_seed);
287
288 if (!utd->debug.random_test_seed) {
289 test_pr_err("%s: Could not create debugfs random_test_seed.",
290 __func__);
291 return -ENOMEM;
292 }
293
294 utd->debug.write_read_test = debugfs_create_file("write_read_test",
295 S_IRUGO | S_IWUGO, tests_root,
296 NULL, &write_read_test_ops);
297
298 if (!utd->debug.write_read_test) {
299 debugfs_remove(utd->debug.random_test_seed);
300 test_pr_err("%s: Could not create debugfs write_read_test.",
301 __func__);
302 return -ENOMEM;
303 }
304
305 return 0;
306}
307
308static void ufs_test_probe(void)
309{
310 ufs_test_debugfs_init();
311}
312
313static void ufs_test_remove(void)
314{
315 ufs_test_debugfs_cleanup();
316}
317
318int __init ufs_test_init(void)
319{
320 utd = kzalloc(sizeof(struct ufs_test_data), GFP_KERNEL);
321 if (!utd) {
322 test_pr_err("%s: failed to allocate ufs_test_data", __func__);
323 return -ENODEV;
324 }
325
326 init_waitqueue_head(&utd->wait_q);
327 utd->bdt.init_fn = ufs_test_probe;
328 utd->bdt.exit_fn = ufs_test_remove;
329 INIT_LIST_HEAD(&utd->bdt.list);
330 test_iosched_register(&utd->bdt);
331
332 return 0;
333}
334EXPORT_SYMBOL_GPL(ufs_test_init);
335
336static void __exit ufs_test_exit(void)
337{
338 test_iosched_unregister(&utd->bdt);
339 kfree(utd);
340}
341module_init(ufs_test_init)
342;
343module_exit(ufs_test_exit)
344;
345
346MODULE_LICENSE("GPL v2");
347MODULE_DESCRIPTION("UFC test");
348