mmc_test.c revision b7ac2cf1cdf346b34cbc2104d386a9d29d12aa4c
1/*
2 *  linux/drivers/mmc/card/mmc_test.c
3 *
4 *  Copyright 2007-2008 Pierre Ossman
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 */
11
12#include <linux/mmc/core.h>
13#include <linux/mmc/card.h>
14#include <linux/mmc/host.h>
15#include <linux/mmc/mmc.h>
16
17#include <linux/scatterlist.h>
18
19#define RESULT_OK		0
20#define RESULT_FAIL		1
21#define RESULT_UNSUP_HOST	2
22#define RESULT_UNSUP_CARD	3
23
24#define BUFFER_ORDER		2
25#define BUFFER_SIZE		(PAGE_SIZE << BUFFER_ORDER)
26
27struct mmc_test_card {
28	struct mmc_card	*card;
29
30	u8		scratch[BUFFER_SIZE];
31	u8		*buffer;
32#ifdef CONFIG_HIGHMEM
33	struct page	*highmem;
34#endif
35};
36
37/*******************************************************************/
38/*  General helper functions                                       */
39/*******************************************************************/
40
41/*
42 * Configure correct block size in card
43 */
44static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
45{
46	struct mmc_command cmd;
47	int ret;
48
49	cmd.opcode = MMC_SET_BLOCKLEN;
50	cmd.arg = size;
51	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
52	ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
53	if (ret)
54		return ret;
55
56	return 0;
57}
58
59/*
60 * Fill in the mmc_request structure given a set of transfer parameters.
61 */
62static void mmc_test_prepare_mrq(struct mmc_test_card *test,
63	struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len,
64	unsigned dev_addr, unsigned blocks, unsigned blksz, int write)
65{
66	BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop);
67
68	if (blocks > 1) {
69		mrq->cmd->opcode = write ?
70			MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
71	} else {
72		mrq->cmd->opcode = write ?
73			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
74	}
75
76	mrq->cmd->arg = dev_addr;
77	mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
78
79	if (blocks == 1)
80		mrq->stop = NULL;
81	else {
82		mrq->stop->opcode = MMC_STOP_TRANSMISSION;
83		mrq->stop->arg = 0;
84		mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
85	}
86
87	mrq->data->blksz = blksz;
88	mrq->data->blocks = blocks;
89	mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
90	mrq->data->sg = sg;
91	mrq->data->sg_len = sg_len;
92
93	mmc_set_data_timeout(mrq->data, test->card);
94}
95
96/*
97 * Wait for the card to finish the busy state
98 */
99static int mmc_test_wait_busy(struct mmc_test_card *test)
100{
101	int ret, busy;
102	struct mmc_command cmd;
103
104	busy = 0;
105	do {
106		memset(&cmd, 0, sizeof(struct mmc_command));
107
108		cmd.opcode = MMC_SEND_STATUS;
109		cmd.arg = test->card->rca << 16;
110		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
111
112		ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
113		if (ret)
114			break;
115
116		if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
117			busy = 1;
118			printk(KERN_INFO "%s: Warning: Host did not "
119				"wait for busy state to end.\n",
120				mmc_hostname(test->card->host));
121		}
122	} while (!(cmd.resp[0] & R1_READY_FOR_DATA));
123
124	return ret;
125}
126
127/*
128 * Transfer a single sector of kernel addressable data
129 */
130static int mmc_test_buffer_transfer(struct mmc_test_card *test,
131	u8 *buffer, unsigned addr, unsigned blksz, int write)
132{
133	int ret;
134
135	struct mmc_request mrq;
136	struct mmc_command cmd;
137	struct mmc_command stop;
138	struct mmc_data data;
139
140	struct scatterlist sg;
141
142	memset(&mrq, 0, sizeof(struct mmc_request));
143	memset(&cmd, 0, sizeof(struct mmc_command));
144	memset(&data, 0, sizeof(struct mmc_data));
145	memset(&stop, 0, sizeof(struct mmc_command));
146
147	mrq.cmd = &cmd;
148	mrq.data = &data;
149	mrq.stop = &stop;
150
151	sg_init_one(&sg, buffer, blksz);
152
153	mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write);
154
155	mmc_wait_for_req(test->card->host, &mrq);
156
157	if (cmd.error)
158		return cmd.error;
159	if (data.error)
160		return data.error;
161
162	ret = mmc_test_wait_busy(test);
163	if (ret)
164		return ret;
165
166	return 0;
167}
168
169/*******************************************************************/
170/*  Test preparation and cleanup                                   */
171/*******************************************************************/
172
173/*
174 * Fill the first couple of sectors of the card with known data
175 * so that bad reads/writes can be detected
176 */
177static int __mmc_test_prepare(struct mmc_test_card *test, int write)
178{
179	int ret, i;
180
181	ret = mmc_test_set_blksize(test, 512);
182	if (ret)
183		return ret;
184
185	if (write)
186		memset(test->buffer, 0xDF, 512);
187	else {
188		for (i = 0;i < 512;i++)
189			test->buffer[i] = i;
190	}
191
192	for (i = 0;i < BUFFER_SIZE / 512;i++) {
193		ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1);
194		if (ret)
195			return ret;
196	}
197
198	return 0;
199}
200
201static int mmc_test_prepare_write(struct mmc_test_card *test)
202{
203	return __mmc_test_prepare(test, 1);
204}
205
206static int mmc_test_prepare_read(struct mmc_test_card *test)
207{
208	return __mmc_test_prepare(test, 0);
209}
210
211static int mmc_test_cleanup(struct mmc_test_card *test)
212{
213	int ret, i;
214
215	ret = mmc_test_set_blksize(test, 512);
216	if (ret)
217		return ret;
218
219	memset(test->buffer, 0, 512);
220
221	for (i = 0;i < BUFFER_SIZE / 512;i++) {
222		ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1);
223		if (ret)
224			return ret;
225	}
226
227	return 0;
228}
229
230/*******************************************************************/
231/*  Test execution helpers                                         */
232/*******************************************************************/
233
234/*
235 * Modifies the mmc_request to perform the "short transfer" tests
236 */
237static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
238	struct mmc_request *mrq, int write)
239{
240	BUG_ON(!mrq || !mrq->cmd || !mrq->data);
241
242	if (mrq->data->blocks > 1) {
243		mrq->cmd->opcode = write ?
244			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
245		mrq->stop = NULL;
246	} else {
247		mrq->cmd->opcode = MMC_SEND_STATUS;
248		mrq->cmd->arg = test->card->rca << 16;
249	}
250}
251
252/*
253 * Checks that a normal transfer didn't have any errors
254 */
255static int mmc_test_check_result(struct mmc_test_card *test,
256	struct mmc_request *mrq)
257{
258	int ret;
259
260	BUG_ON(!mrq || !mrq->cmd || !mrq->data);
261
262	ret = 0;
263
264	if (!ret && mrq->cmd->error)
265		ret = mrq->cmd->error;
266	if (!ret && mrq->data->error)
267		ret = mrq->data->error;
268	if (!ret && mrq->stop && mrq->stop->error)
269		ret = mrq->stop->error;
270	if (!ret && mrq->data->bytes_xfered !=
271		mrq->data->blocks * mrq->data->blksz)
272		ret = RESULT_FAIL;
273
274	if (ret == -EINVAL)
275		ret = RESULT_UNSUP_HOST;
276
277	return ret;
278}
279
280/*
281 * Checks that a "short transfer" behaved as expected
282 */
283static int mmc_test_check_broken_result(struct mmc_test_card *test,
284	struct mmc_request *mrq)
285{
286	int ret;
287
288	BUG_ON(!mrq || !mrq->cmd || !mrq->data);
289
290	ret = 0;
291
292	if (!ret && mrq->cmd->error)
293		ret = mrq->cmd->error;
294	if (!ret && mrq->data->error == 0)
295		ret = RESULT_FAIL;
296	if (!ret && mrq->data->error != -ETIMEDOUT)
297		ret = mrq->data->error;
298	if (!ret && mrq->stop && mrq->stop->error)
299		ret = mrq->stop->error;
300	if (mrq->data->blocks > 1) {
301		if (!ret && mrq->data->bytes_xfered > mrq->data->blksz)
302			ret = RESULT_FAIL;
303	} else {
304		if (!ret && mrq->data->bytes_xfered > 0)
305			ret = RESULT_FAIL;
306	}
307
308	if (ret == -EINVAL)
309		ret = RESULT_UNSUP_HOST;
310
311	return ret;
312}
313
314/*
315 * Tests a basic transfer with certain parameters
316 */
317static int mmc_test_simple_transfer(struct mmc_test_card *test,
318	struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
319	unsigned blocks, unsigned blksz, int write)
320{
321	struct mmc_request mrq;
322	struct mmc_command cmd;
323	struct mmc_command stop;
324	struct mmc_data data;
325
326	memset(&mrq, 0, sizeof(struct mmc_request));
327	memset(&cmd, 0, sizeof(struct mmc_command));
328	memset(&data, 0, sizeof(struct mmc_data));
329	memset(&stop, 0, sizeof(struct mmc_command));
330
331	mrq.cmd = &cmd;
332	mrq.data = &data;
333	mrq.stop = &stop;
334
335	mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr,
336		blocks, blksz, write);
337
338	mmc_wait_for_req(test->card->host, &mrq);
339
340	mmc_test_wait_busy(test);
341
342	return mmc_test_check_result(test, &mrq);
343}
344
345/*
346 * Tests a transfer where the card will fail completely or partly
347 */
348static int mmc_test_broken_transfer(struct mmc_test_card *test,
349	unsigned blocks, unsigned blksz, int write)
350{
351	struct mmc_request mrq;
352	struct mmc_command cmd;
353	struct mmc_command stop;
354	struct mmc_data data;
355
356	struct scatterlist sg;
357
358	memset(&mrq, 0, sizeof(struct mmc_request));
359	memset(&cmd, 0, sizeof(struct mmc_command));
360	memset(&data, 0, sizeof(struct mmc_data));
361	memset(&stop, 0, sizeof(struct mmc_command));
362
363	mrq.cmd = &cmd;
364	mrq.data = &data;
365	mrq.stop = &stop;
366
367	sg_init_one(&sg, test->buffer, blocks * blksz);
368
369	mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write);
370	mmc_test_prepare_broken_mrq(test, &mrq, write);
371
372	mmc_wait_for_req(test->card->host, &mrq);
373
374	mmc_test_wait_busy(test);
375
376	return mmc_test_check_broken_result(test, &mrq);
377}
378
379/*
380 * Does a complete transfer test where data is also validated
381 *
382 * Note: mmc_test_prepare() must have been done before this call
383 */
384static int mmc_test_transfer(struct mmc_test_card *test,
385	struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
386	unsigned blocks, unsigned blksz, int write)
387{
388	int ret, i;
389	unsigned long flags;
390
391	if (write) {
392		for (i = 0;i < blocks * blksz;i++)
393			test->scratch[i] = i;
394	} else {
395		memset(test->scratch, 0, BUFFER_SIZE);
396	}
397	local_irq_save(flags);
398	sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
399	local_irq_restore(flags);
400
401	ret = mmc_test_set_blksize(test, blksz);
402	if (ret)
403		return ret;
404
405	ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr,
406		blocks, blksz, write);
407	if (ret)
408		return ret;
409
410	if (write) {
411		int sectors;
412
413		ret = mmc_test_set_blksize(test, 512);
414		if (ret)
415			return ret;
416
417		sectors = (blocks * blksz + 511) / 512;
418		if ((sectors * 512) == (blocks * blksz))
419			sectors++;
420
421		if ((sectors * 512) > BUFFER_SIZE)
422			return -EINVAL;
423
424		memset(test->buffer, 0, sectors * 512);
425
426		for (i = 0;i < sectors;i++) {
427			ret = mmc_test_buffer_transfer(test,
428				test->buffer + i * 512,
429				dev_addr + i * 512, 512, 0);
430			if (ret)
431				return ret;
432		}
433
434		for (i = 0;i < blocks * blksz;i++) {
435			if (test->buffer[i] != (u8)i)
436				return RESULT_FAIL;
437		}
438
439		for (;i < sectors * 512;i++) {
440			if (test->buffer[i] != 0xDF)
441				return RESULT_FAIL;
442		}
443	} else {
444		local_irq_save(flags);
445		sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
446		local_irq_restore(flags);
447		for (i = 0;i < blocks * blksz;i++) {
448			if (test->scratch[i] != (u8)i)
449				return RESULT_FAIL;
450		}
451	}
452
453	return 0;
454}
455
456/*******************************************************************/
457/*  Tests                                                          */
458/*******************************************************************/
459
460struct mmc_test_case {
461	const char *name;
462
463	int (*prepare)(struct mmc_test_card *);
464	int (*run)(struct mmc_test_card *);
465	int (*cleanup)(struct mmc_test_card *);
466};
467
468static int mmc_test_basic_write(struct mmc_test_card *test)
469{
470	int ret;
471	struct scatterlist sg;
472
473	ret = mmc_test_set_blksize(test, 512);
474	if (ret)
475		return ret;
476
477	sg_init_one(&sg, test->buffer, 512);
478
479	ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
480	if (ret)
481		return ret;
482
483	return 0;
484}
485
486static int mmc_test_basic_read(struct mmc_test_card *test)
487{
488	int ret;
489	struct scatterlist sg;
490
491	ret = mmc_test_set_blksize(test, 512);
492	if (ret)
493		return ret;
494
495	sg_init_one(&sg, test->buffer, 512);
496
497	ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
498	if (ret)
499		return ret;
500
501	return 0;
502}
503
504static int mmc_test_verify_write(struct mmc_test_card *test)
505{
506	int ret;
507	struct scatterlist sg;
508
509	sg_init_one(&sg, test->buffer, 512);
510
511	ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
512	if (ret)
513		return ret;
514
515	return 0;
516}
517
518static int mmc_test_verify_read(struct mmc_test_card *test)
519{
520	int ret;
521	struct scatterlist sg;
522
523	sg_init_one(&sg, test->buffer, 512);
524
525	ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
526	if (ret)
527		return ret;
528
529	return 0;
530}
531
532static int mmc_test_multi_write(struct mmc_test_card *test)
533{
534	int ret;
535	unsigned int size;
536	struct scatterlist sg;
537
538	if (test->card->host->max_blk_count == 1)
539		return RESULT_UNSUP_HOST;
540
541	size = PAGE_SIZE * 2;
542	size = min(size, test->card->host->max_req_size);
543	size = min(size, test->card->host->max_seg_size);
544	size = min(size, test->card->host->max_blk_count * 512);
545
546	if (size < 1024)
547		return RESULT_UNSUP_HOST;
548
549	sg_init_one(&sg, test->buffer, size);
550
551	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
552	if (ret)
553		return ret;
554
555	return 0;
556}
557
558static int mmc_test_multi_read(struct mmc_test_card *test)
559{
560	int ret;
561	unsigned int size;
562	struct scatterlist sg;
563
564	if (test->card->host->max_blk_count == 1)
565		return RESULT_UNSUP_HOST;
566
567	size = PAGE_SIZE * 2;
568	size = min(size, test->card->host->max_req_size);
569	size = min(size, test->card->host->max_seg_size);
570	size = min(size, test->card->host->max_blk_count * 512);
571
572	if (size < 1024)
573		return RESULT_UNSUP_HOST;
574
575	sg_init_one(&sg, test->buffer, size);
576
577	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
578	if (ret)
579		return ret;
580
581	return 0;
582}
583
584static int mmc_test_pow2_write(struct mmc_test_card *test)
585{
586	int ret, i;
587	struct scatterlist sg;
588
589	if (!test->card->csd.write_partial)
590		return RESULT_UNSUP_CARD;
591
592	for (i = 1; i < 512;i <<= 1) {
593		sg_init_one(&sg, test->buffer, i);
594		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
595		if (ret)
596			return ret;
597	}
598
599	return 0;
600}
601
602static int mmc_test_pow2_read(struct mmc_test_card *test)
603{
604	int ret, i;
605	struct scatterlist sg;
606
607	if (!test->card->csd.read_partial)
608		return RESULT_UNSUP_CARD;
609
610	for (i = 1; i < 512;i <<= 1) {
611		sg_init_one(&sg, test->buffer, i);
612		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
613		if (ret)
614			return ret;
615	}
616
617	return 0;
618}
619
620static int mmc_test_weird_write(struct mmc_test_card *test)
621{
622	int ret, i;
623	struct scatterlist sg;
624
625	if (!test->card->csd.write_partial)
626		return RESULT_UNSUP_CARD;
627
628	for (i = 3; i < 512;i += 7) {
629		sg_init_one(&sg, test->buffer, i);
630		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
631		if (ret)
632			return ret;
633	}
634
635	return 0;
636}
637
638static int mmc_test_weird_read(struct mmc_test_card *test)
639{
640	int ret, i;
641	struct scatterlist sg;
642
643	if (!test->card->csd.read_partial)
644		return RESULT_UNSUP_CARD;
645
646	for (i = 3; i < 512;i += 7) {
647		sg_init_one(&sg, test->buffer, i);
648		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
649		if (ret)
650			return ret;
651	}
652
653	return 0;
654}
655
656static int mmc_test_align_write(struct mmc_test_card *test)
657{
658	int ret, i;
659	struct scatterlist sg;
660
661	for (i = 1;i < 4;i++) {
662		sg_init_one(&sg, test->buffer + i, 512);
663		ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
664		if (ret)
665			return ret;
666	}
667
668	return 0;
669}
670
671static int mmc_test_align_read(struct mmc_test_card *test)
672{
673	int ret, i;
674	struct scatterlist sg;
675
676	for (i = 1;i < 4;i++) {
677		sg_init_one(&sg, test->buffer + i, 512);
678		ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
679		if (ret)
680			return ret;
681	}
682
683	return 0;
684}
685
686static int mmc_test_align_multi_write(struct mmc_test_card *test)
687{
688	int ret, i;
689	unsigned int size;
690	struct scatterlist sg;
691
692	if (test->card->host->max_blk_count == 1)
693		return RESULT_UNSUP_HOST;
694
695	size = PAGE_SIZE * 2;
696	size = min(size, test->card->host->max_req_size);
697	size = min(size, test->card->host->max_seg_size);
698	size = min(size, test->card->host->max_blk_count * 512);
699
700	if (size < 1024)
701		return RESULT_UNSUP_HOST;
702
703	for (i = 1;i < 4;i++) {
704		sg_init_one(&sg, test->buffer + i, size);
705		ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
706		if (ret)
707			return ret;
708	}
709
710	return 0;
711}
712
713static int mmc_test_align_multi_read(struct mmc_test_card *test)
714{
715	int ret, i;
716	unsigned int size;
717	struct scatterlist sg;
718
719	if (test->card->host->max_blk_count == 1)
720		return RESULT_UNSUP_HOST;
721
722	size = PAGE_SIZE * 2;
723	size = min(size, test->card->host->max_req_size);
724	size = min(size, test->card->host->max_seg_size);
725	size = min(size, test->card->host->max_blk_count * 512);
726
727	if (size < 1024)
728		return RESULT_UNSUP_HOST;
729
730	for (i = 1;i < 4;i++) {
731		sg_init_one(&sg, test->buffer + i, size);
732		ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
733		if (ret)
734			return ret;
735	}
736
737	return 0;
738}
739
740static int mmc_test_xfersize_write(struct mmc_test_card *test)
741{
742	int ret;
743
744	ret = mmc_test_set_blksize(test, 512);
745	if (ret)
746		return ret;
747
748	ret = mmc_test_broken_transfer(test, 1, 512, 1);
749	if (ret)
750		return ret;
751
752	return 0;
753}
754
755static int mmc_test_xfersize_read(struct mmc_test_card *test)
756{
757	int ret;
758
759	ret = mmc_test_set_blksize(test, 512);
760	if (ret)
761		return ret;
762
763	ret = mmc_test_broken_transfer(test, 1, 512, 0);
764	if (ret)
765		return ret;
766
767	return 0;
768}
769
770static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
771{
772	int ret;
773
774	if (test->card->host->max_blk_count == 1)
775		return RESULT_UNSUP_HOST;
776
777	ret = mmc_test_set_blksize(test, 512);
778	if (ret)
779		return ret;
780
781	ret = mmc_test_broken_transfer(test, 2, 512, 1);
782	if (ret)
783		return ret;
784
785	return 0;
786}
787
788static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
789{
790	int ret;
791
792	if (test->card->host->max_blk_count == 1)
793		return RESULT_UNSUP_HOST;
794
795	ret = mmc_test_set_blksize(test, 512);
796	if (ret)
797		return ret;
798
799	ret = mmc_test_broken_transfer(test, 2, 512, 0);
800	if (ret)
801		return ret;
802
803	return 0;
804}
805
806#ifdef CONFIG_HIGHMEM
807
808static int mmc_test_write_high(struct mmc_test_card *test)
809{
810	int ret;
811	struct scatterlist sg;
812
813	sg_init_table(&sg, 1);
814	sg_set_page(&sg, test->highmem, 512, 0);
815
816	ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
817	if (ret)
818		return ret;
819
820	return 0;
821}
822
823static int mmc_test_read_high(struct mmc_test_card *test)
824{
825	int ret;
826	struct scatterlist sg;
827
828	sg_init_table(&sg, 1);
829	sg_set_page(&sg, test->highmem, 512, 0);
830
831	ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
832	if (ret)
833		return ret;
834
835	return 0;
836}
837
838static int mmc_test_multi_write_high(struct mmc_test_card *test)
839{
840	int ret;
841	unsigned int size;
842	struct scatterlist sg;
843
844	if (test->card->host->max_blk_count == 1)
845		return RESULT_UNSUP_HOST;
846
847	size = PAGE_SIZE * 2;
848	size = min(size, test->card->host->max_req_size);
849	size = min(size, test->card->host->max_seg_size);
850	size = min(size, test->card->host->max_blk_count * 512);
851
852	if (size < 1024)
853		return RESULT_UNSUP_HOST;
854
855	sg_init_table(&sg, 1);
856	sg_set_page(&sg, test->highmem, size, 0);
857
858	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
859	if (ret)
860		return ret;
861
862	return 0;
863}
864
865static int mmc_test_multi_read_high(struct mmc_test_card *test)
866{
867	int ret;
868	unsigned int size;
869	struct scatterlist sg;
870
871	if (test->card->host->max_blk_count == 1)
872		return RESULT_UNSUP_HOST;
873
874	size = PAGE_SIZE * 2;
875	size = min(size, test->card->host->max_req_size);
876	size = min(size, test->card->host->max_seg_size);
877	size = min(size, test->card->host->max_blk_count * 512);
878
879	if (size < 1024)
880		return RESULT_UNSUP_HOST;
881
882	sg_init_table(&sg, 1);
883	sg_set_page(&sg, test->highmem, size, 0);
884
885	ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
886	if (ret)
887		return ret;
888
889	return 0;
890}
891
892#endif /* CONFIG_HIGHMEM */
893
894static const struct mmc_test_case mmc_test_cases[] = {
895	{
896		.name = "Basic write (no data verification)",
897		.run = mmc_test_basic_write,
898	},
899
900	{
901		.name = "Basic read (no data verification)",
902		.run = mmc_test_basic_read,
903	},
904
905	{
906		.name = "Basic write (with data verification)",
907		.prepare = mmc_test_prepare_write,
908		.run = mmc_test_verify_write,
909		.cleanup = mmc_test_cleanup,
910	},
911
912	{
913		.name = "Basic read (with data verification)",
914		.prepare = mmc_test_prepare_read,
915		.run = mmc_test_verify_read,
916		.cleanup = mmc_test_cleanup,
917	},
918
919	{
920		.name = "Multi-block write",
921		.prepare = mmc_test_prepare_write,
922		.run = mmc_test_multi_write,
923		.cleanup = mmc_test_cleanup,
924	},
925
926	{
927		.name = "Multi-block read",
928		.prepare = mmc_test_prepare_read,
929		.run = mmc_test_multi_read,
930		.cleanup = mmc_test_cleanup,
931	},
932
933	{
934		.name = "Power of two block writes",
935		.prepare = mmc_test_prepare_write,
936		.run = mmc_test_pow2_write,
937		.cleanup = mmc_test_cleanup,
938	},
939
940	{
941		.name = "Power of two block reads",
942		.prepare = mmc_test_prepare_read,
943		.run = mmc_test_pow2_read,
944		.cleanup = mmc_test_cleanup,
945	},
946
947	{
948		.name = "Weird sized block writes",
949		.prepare = mmc_test_prepare_write,
950		.run = mmc_test_weird_write,
951		.cleanup = mmc_test_cleanup,
952	},
953
954	{
955		.name = "Weird sized block reads",
956		.prepare = mmc_test_prepare_read,
957		.run = mmc_test_weird_read,
958		.cleanup = mmc_test_cleanup,
959	},
960
961	{
962		.name = "Badly aligned write",
963		.prepare = mmc_test_prepare_write,
964		.run = mmc_test_align_write,
965		.cleanup = mmc_test_cleanup,
966	},
967
968	{
969		.name = "Badly aligned read",
970		.prepare = mmc_test_prepare_read,
971		.run = mmc_test_align_read,
972		.cleanup = mmc_test_cleanup,
973	},
974
975	{
976		.name = "Badly aligned multi-block write",
977		.prepare = mmc_test_prepare_write,
978		.run = mmc_test_align_multi_write,
979		.cleanup = mmc_test_cleanup,
980	},
981
982	{
983		.name = "Badly aligned multi-block read",
984		.prepare = mmc_test_prepare_read,
985		.run = mmc_test_align_multi_read,
986		.cleanup = mmc_test_cleanup,
987	},
988
989	{
990		.name = "Correct xfer_size at write (start failure)",
991		.run = mmc_test_xfersize_write,
992	},
993
994	{
995		.name = "Correct xfer_size at read (start failure)",
996		.run = mmc_test_xfersize_read,
997	},
998
999	{
1000		.name = "Correct xfer_size at write (midway failure)",
1001		.run = mmc_test_multi_xfersize_write,
1002	},
1003
1004	{
1005		.name = "Correct xfer_size at read (midway failure)",
1006		.run = mmc_test_multi_xfersize_read,
1007	},
1008
1009#ifdef CONFIG_HIGHMEM
1010
1011	{
1012		.name = "Highmem write",
1013		.prepare = mmc_test_prepare_write,
1014		.run = mmc_test_write_high,
1015		.cleanup = mmc_test_cleanup,
1016	},
1017
1018	{
1019		.name = "Highmem read",
1020		.prepare = mmc_test_prepare_read,
1021		.run = mmc_test_read_high,
1022		.cleanup = mmc_test_cleanup,
1023	},
1024
1025	{
1026		.name = "Multi-block highmem write",
1027		.prepare = mmc_test_prepare_write,
1028		.run = mmc_test_multi_write_high,
1029		.cleanup = mmc_test_cleanup,
1030	},
1031
1032	{
1033		.name = "Multi-block highmem read",
1034		.prepare = mmc_test_prepare_read,
1035		.run = mmc_test_multi_read_high,
1036		.cleanup = mmc_test_cleanup,
1037	},
1038
1039#endif /* CONFIG_HIGHMEM */
1040
1041};
1042
1043static struct mutex mmc_test_lock;
1044
1045static void mmc_test_run(struct mmc_test_card *test, int testcase)
1046{
1047	int i, ret;
1048
1049	printk(KERN_INFO "%s: Starting tests of card %s...\n",
1050		mmc_hostname(test->card->host), mmc_card_id(test->card));
1051
1052	mmc_claim_host(test->card->host);
1053
1054	for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
1055		if (testcase && ((i + 1) != testcase))
1056			continue;
1057
1058		printk(KERN_INFO "%s: Test case %d. %s...\n",
1059			mmc_hostname(test->card->host), i + 1,
1060			mmc_test_cases[i].name);
1061
1062		if (mmc_test_cases[i].prepare) {
1063			ret = mmc_test_cases[i].prepare(test);
1064			if (ret) {
1065				printk(KERN_INFO "%s: Result: Prepare "
1066					"stage failed! (%d)\n",
1067					mmc_hostname(test->card->host),
1068					ret);
1069				continue;
1070			}
1071		}
1072
1073		ret = mmc_test_cases[i].run(test);
1074		switch (ret) {
1075		case RESULT_OK:
1076			printk(KERN_INFO "%s: Result: OK\n",
1077				mmc_hostname(test->card->host));
1078			break;
1079		case RESULT_FAIL:
1080			printk(KERN_INFO "%s: Result: FAILED\n",
1081				mmc_hostname(test->card->host));
1082			break;
1083		case RESULT_UNSUP_HOST:
1084			printk(KERN_INFO "%s: Result: UNSUPPORTED "
1085				"(by host)\n",
1086				mmc_hostname(test->card->host));
1087			break;
1088		case RESULT_UNSUP_CARD:
1089			printk(KERN_INFO "%s: Result: UNSUPPORTED "
1090				"(by card)\n",
1091				mmc_hostname(test->card->host));
1092			break;
1093		default:
1094			printk(KERN_INFO "%s: Result: ERROR (%d)\n",
1095				mmc_hostname(test->card->host), ret);
1096		}
1097
1098		if (mmc_test_cases[i].cleanup) {
1099			ret = mmc_test_cases[i].cleanup(test);
1100			if (ret) {
1101				printk(KERN_INFO "%s: Warning: Cleanup "
1102					"stage failed! (%d)\n",
1103					mmc_hostname(test->card->host),
1104					ret);
1105			}
1106		}
1107	}
1108
1109	mmc_release_host(test->card->host);
1110
1111	printk(KERN_INFO "%s: Tests completed.\n",
1112		mmc_hostname(test->card->host));
1113}
1114
1115static ssize_t mmc_test_show(struct device *dev,
1116	struct device_attribute *attr, char *buf)
1117{
1118	mutex_lock(&mmc_test_lock);
1119	mutex_unlock(&mmc_test_lock);
1120
1121	return 0;
1122}
1123
1124static ssize_t mmc_test_store(struct device *dev,
1125	struct device_attribute *attr, const char *buf, size_t count)
1126{
1127	struct mmc_card *card;
1128	struct mmc_test_card *test;
1129	int testcase;
1130
1131	card = container_of(dev, struct mmc_card, dev);
1132
1133	testcase = simple_strtol(buf, NULL, 10);
1134
1135	test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
1136	if (!test)
1137		return -ENOMEM;
1138
1139	test->card = card;
1140
1141	test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
1142#ifdef CONFIG_HIGHMEM
1143	test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
1144#endif
1145
1146#ifdef CONFIG_HIGHMEM
1147	if (test->buffer && test->highmem) {
1148#else
1149	if (test->buffer) {
1150#endif
1151		mutex_lock(&mmc_test_lock);
1152		mmc_test_run(test, testcase);
1153		mutex_unlock(&mmc_test_lock);
1154	}
1155
1156#ifdef CONFIG_HIGHMEM
1157	__free_pages(test->highmem, BUFFER_ORDER);
1158#endif
1159	kfree(test->buffer);
1160	kfree(test);
1161
1162	return count;
1163}
1164
1165static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store);
1166
1167static int mmc_test_probe(struct mmc_card *card)
1168{
1169	int ret;
1170
1171	if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD))
1172		return -ENODEV;
1173
1174	mutex_init(&mmc_test_lock);
1175
1176	ret = device_create_file(&card->dev, &dev_attr_test);
1177	if (ret)
1178		return ret;
1179
1180	dev_info(&card->dev, "Card claimed for testing.\n");
1181
1182	return 0;
1183}
1184
1185static void mmc_test_remove(struct mmc_card *card)
1186{
1187	device_remove_file(&card->dev, &dev_attr_test);
1188}
1189
1190static struct mmc_driver mmc_driver = {
1191	.drv		= {
1192		.name	= "mmc_test",
1193	},
1194	.probe		= mmc_test_probe,
1195	.remove		= mmc_test_remove,
1196};
1197
1198static int __init mmc_test_init(void)
1199{
1200	return mmc_register_driver(&mmc_driver);
1201}
1202
1203static void __exit mmc_test_exit(void)
1204{
1205	mmc_unregister_driver(&mmc_driver);
1206}
1207
1208module_init(mmc_test_init);
1209module_exit(mmc_test_exit);
1210
1211MODULE_LICENSE("GPL");
1212MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
1213MODULE_AUTHOR("Pierre Ossman");
1214