2 * linux/drivers/mmc/card/mmc_test.c
4 * Copyright 2007 Pierre Ossman
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.
12 #include <linux/mmc/core.h>
13 #include <linux/mmc/card.h>
14 #include <linux/mmc/host.h>
15 #include <linux/mmc/mmc.h>
17 #include <linux/scatterlist.h>
21 #define RESULT_UNSUP_HOST 2
22 #define RESULT_UNSUP_CARD 3
24 #define BUFFER_SIZE (PAGE_SIZE * 4)
26 struct mmc_test_card {
27 struct mmc_card *card;
32 /*******************************************************************/
33 /* Helper functions */
34 /*******************************************************************/
36 static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
38 struct mmc_command cmd;
41 cmd.opcode = MMC_SET_BLOCKLEN;
43 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
44 ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
51 static int __mmc_test_transfer(struct mmc_test_card *test, int write,
52 unsigned broken_xfer, u8 *buffer, unsigned addr,
53 unsigned blocks, unsigned blksz)
57 struct mmc_request mrq;
58 struct mmc_command cmd;
59 struct mmc_command stop;
62 struct scatterlist sg;
64 memset(&mrq, 0, sizeof(struct mmc_request));
69 memset(&cmd, 0, sizeof(struct mmc_command));
74 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
76 cmd.opcode = MMC_SEND_STATUS;
81 MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
84 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
88 if (broken_xfer && blocks == 1)
89 cmd.arg = test->card->rca << 16;
92 cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
94 memset(&stop, 0, sizeof(struct mmc_command));
96 if (!broken_xfer && (blocks > 1)) {
97 stop.opcode = MMC_STOP_TRANSMISSION;
99 stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
104 memset(&data, 0, sizeof(struct mmc_data));
107 data.blocks = blocks;
108 data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
112 sg_init_one(&sg, buffer, blocks * blksz);
114 mmc_set_data_timeout(&data, test->card);
116 mmc_wait_for_req(test->card->host, &mrq);
121 if (!ret && cmd.error)
123 if (!ret && data.error == 0)
125 if (!ret && data.error != -ETIMEDOUT)
127 if (!ret && stop.error)
130 if (!ret && data.bytes_xfered > blksz)
133 if (!ret && data.bytes_xfered > 0)
137 if (!ret && cmd.error)
139 if (!ret && data.error)
141 if (!ret && stop.error)
143 if (!ret && data.bytes_xfered != blocks * blksz)
148 ret = RESULT_UNSUP_HOST;
154 memset(&cmd, 0, sizeof(struct mmc_command));
156 cmd.opcode = MMC_SEND_STATUS;
157 cmd.arg = test->card->rca << 16;
158 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
160 ret2 = mmc_wait_for_cmd(test->card->host, &cmd, 0);
164 if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
166 printk(KERN_INFO "%s: Warning: Host did not "
167 "wait for busy state to end.\n",
168 mmc_hostname(test->card->host));
170 } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
175 static int mmc_test_transfer(struct mmc_test_card *test, int write,
176 u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz)
178 return __mmc_test_transfer(test, write, 0, buffer,
179 addr, blocks, blksz);
182 static int mmc_test_prepare_verify(struct mmc_test_card *test, int write)
186 ret = mmc_test_set_blksize(test, 512);
191 memset(test->buffer, 0xDF, BUFFER_SIZE);
193 for (i = 0;i < BUFFER_SIZE;i++)
197 for (i = 0;i < BUFFER_SIZE / 512;i++) {
198 ret = mmc_test_transfer(test, 1, test->buffer + i * 512,
207 static int mmc_test_prepare_verify_write(struct mmc_test_card *test)
209 return mmc_test_prepare_verify(test, 1);
212 static int mmc_test_prepare_verify_read(struct mmc_test_card *test)
214 return mmc_test_prepare_verify(test, 0);
217 static int mmc_test_verified_transfer(struct mmc_test_card *test, int write,
218 u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz)
223 * It is assumed that the above preparation has been done.
226 memset(test->buffer, 0, BUFFER_SIZE);
229 for (i = 0;i < blocks * blksz;i++)
233 ret = mmc_test_set_blksize(test, blksz);
237 ret = mmc_test_transfer(test, write, buffer, addr, blocks, blksz);
242 ret = mmc_test_set_blksize(test, 512);
246 sectors = (blocks * blksz + 511) / 512;
247 if ((sectors * 512) == (blocks * blksz))
250 if ((sectors * 512) > BUFFER_SIZE)
253 memset(test->buffer, 0, sectors * 512);
255 for (i = 0;i < sectors;i++) {
256 ret = mmc_test_transfer(test, 0,
257 test->buffer + i * 512,
258 addr + i * 512, 1, 512);
263 for (i = 0;i < blocks * blksz;i++) {
264 if (test->buffer[i] != (u8)i)
268 for (;i < sectors * 512;i++) {
269 if (test->buffer[i] != 0xDF)
273 for (i = 0;i < blocks * blksz;i++) {
274 if (buffer[i] != (u8)i)
282 static int mmc_test_cleanup_verify(struct mmc_test_card *test)
286 ret = mmc_test_set_blksize(test, 512);
290 memset(test->buffer, 0, BUFFER_SIZE);
292 for (i = 0;i < BUFFER_SIZE / 512;i++) {
293 ret = mmc_test_transfer(test, 1, test->buffer + i * 512,
302 /*******************************************************************/
304 /*******************************************************************/
306 struct mmc_test_case {
309 int (*prepare)(struct mmc_test_card *);
310 int (*run)(struct mmc_test_card *);
311 int (*cleanup)(struct mmc_test_card *);
314 static int mmc_test_basic_write(struct mmc_test_card *test)
318 ret = mmc_test_set_blksize(test, 512);
322 ret = mmc_test_transfer(test, 1, test->buffer, 0, 1, 512);
329 static int mmc_test_basic_read(struct mmc_test_card *test)
333 ret = mmc_test_set_blksize(test, 512);
337 ret = mmc_test_transfer(test, 0, test->buffer, 0, 1, 512);
344 static int mmc_test_verify_write(struct mmc_test_card *test)
348 ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, 512);
355 static int mmc_test_verify_read(struct mmc_test_card *test)
359 ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, 512);
366 static int mmc_test_multi_write(struct mmc_test_card *test)
371 if (test->card->host->max_blk_count == 1)
372 return RESULT_UNSUP_HOST;
374 size = PAGE_SIZE * 2;
375 size = min(size, test->card->host->max_req_size);
376 size = min(size, test->card->host->max_seg_size);
377 size = min(size, test->card->host->max_blk_count * 512);
380 return RESULT_UNSUP_HOST;
382 ret = mmc_test_verified_transfer(test, 1, test->buffer, 0,
390 static int mmc_test_multi_read(struct mmc_test_card *test)
395 if (test->card->host->max_blk_count == 1)
396 return RESULT_UNSUP_HOST;
398 size = PAGE_SIZE * 2;
399 size = min(size, test->card->host->max_req_size);
400 size = min(size, test->card->host->max_seg_size);
401 size = min(size, test->card->host->max_blk_count * 512);
404 return RESULT_UNSUP_HOST;
406 ret = mmc_test_verified_transfer(test, 0, test->buffer, 0,
414 static int mmc_test_pow2_write(struct mmc_test_card *test)
418 if (!test->card->csd.write_partial)
419 return RESULT_UNSUP_CARD;
421 for (i = 1; i < 512;i <<= 1) {
422 ret = mmc_test_verified_transfer(test, 1,
423 test->buffer, 0, 1, i);
431 static int mmc_test_pow2_read(struct mmc_test_card *test)
435 if (!test->card->csd.read_partial)
436 return RESULT_UNSUP_CARD;
438 for (i = 1; i < 512;i <<= 1) {
439 ret = mmc_test_verified_transfer(test, 0,
440 test->buffer, 0, 1, i);
448 static int mmc_test_weird_write(struct mmc_test_card *test)
452 if (!test->card->csd.write_partial)
453 return RESULT_UNSUP_CARD;
455 for (i = 3; i < 512;i += 7) {
456 ret = mmc_test_verified_transfer(test, 1,
457 test->buffer, 0, 1, i);
465 static int mmc_test_weird_read(struct mmc_test_card *test)
469 if (!test->card->csd.read_partial)
470 return RESULT_UNSUP_CARD;
472 for (i = 3; i < 512;i += 7) {
473 ret = mmc_test_verified_transfer(test, 0,
474 test->buffer, 0, 1, i);
482 static int mmc_test_align_write(struct mmc_test_card *test)
486 for (i = 1;i < 4;i++) {
487 ret = mmc_test_verified_transfer(test, 1, test->buffer + i,
496 static int mmc_test_align_read(struct mmc_test_card *test)
500 for (i = 1;i < 4;i++) {
501 ret = mmc_test_verified_transfer(test, 0, test->buffer + i,
510 static int mmc_test_align_multi_write(struct mmc_test_card *test)
515 if (test->card->host->max_blk_count == 1)
516 return RESULT_UNSUP_HOST;
518 size = PAGE_SIZE * 2;
519 size = min(size, test->card->host->max_req_size);
520 size = min(size, test->card->host->max_seg_size);
521 size = min(size, test->card->host->max_blk_count * 512);
524 return RESULT_UNSUP_HOST;
526 for (i = 1;i < 4;i++) {
527 ret = mmc_test_verified_transfer(test, 1, test->buffer + i,
536 static int mmc_test_align_multi_read(struct mmc_test_card *test)
541 if (test->card->host->max_blk_count == 1)
542 return RESULT_UNSUP_HOST;
544 size = PAGE_SIZE * 2;
545 size = min(size, test->card->host->max_req_size);
546 size = min(size, test->card->host->max_seg_size);
547 size = min(size, test->card->host->max_blk_count * 512);
550 return RESULT_UNSUP_HOST;
552 for (i = 1;i < 4;i++) {
553 ret = mmc_test_verified_transfer(test, 0, test->buffer + i,
562 static int mmc_test_xfersize_write(struct mmc_test_card *test)
566 ret = mmc_test_set_blksize(test, 512);
570 ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 1, 512);
577 static int mmc_test_xfersize_read(struct mmc_test_card *test)
581 ret = mmc_test_set_blksize(test, 512);
585 ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 1, 512);
592 static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
596 if (test->card->host->max_blk_count == 1)
597 return RESULT_UNSUP_HOST;
599 ret = mmc_test_set_blksize(test, 512);
603 ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 2, 512);
610 static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
614 if (test->card->host->max_blk_count == 1)
615 return RESULT_UNSUP_HOST;
617 ret = mmc_test_set_blksize(test, 512);
621 ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 2, 512);
628 static const struct mmc_test_case mmc_test_cases[] = {
630 .name = "Basic write (no data verification)",
631 .run = mmc_test_basic_write,
635 .name = "Basic read (no data verification)",
636 .run = mmc_test_basic_read,
640 .name = "Basic write (with data verification)",
641 .prepare = mmc_test_prepare_verify_write,
642 .run = mmc_test_verify_write,
643 .cleanup = mmc_test_cleanup_verify,
647 .name = "Basic read (with data verification)",
648 .prepare = mmc_test_prepare_verify_read,
649 .run = mmc_test_verify_read,
650 .cleanup = mmc_test_cleanup_verify,
654 .name = "Multi-block write",
655 .prepare = mmc_test_prepare_verify_write,
656 .run = mmc_test_multi_write,
657 .cleanup = mmc_test_cleanup_verify,
661 .name = "Multi-block read",
662 .prepare = mmc_test_prepare_verify_read,
663 .run = mmc_test_multi_read,
664 .cleanup = mmc_test_cleanup_verify,
668 .name = "Power of two block writes",
669 .prepare = mmc_test_prepare_verify_write,
670 .run = mmc_test_pow2_write,
671 .cleanup = mmc_test_cleanup_verify,
675 .name = "Power of two block reads",
676 .prepare = mmc_test_prepare_verify_read,
677 .run = mmc_test_pow2_read,
678 .cleanup = mmc_test_cleanup_verify,
682 .name = "Weird sized block writes",
683 .prepare = mmc_test_prepare_verify_write,
684 .run = mmc_test_weird_write,
685 .cleanup = mmc_test_cleanup_verify,
689 .name = "Weird sized block reads",
690 .prepare = mmc_test_prepare_verify_read,
691 .run = mmc_test_weird_read,
692 .cleanup = mmc_test_cleanup_verify,
696 .name = "Badly aligned write",
697 .prepare = mmc_test_prepare_verify_write,
698 .run = mmc_test_align_write,
699 .cleanup = mmc_test_cleanup_verify,
703 .name = "Badly aligned read",
704 .prepare = mmc_test_prepare_verify_read,
705 .run = mmc_test_align_read,
706 .cleanup = mmc_test_cleanup_verify,
710 .name = "Badly aligned multi-block write",
711 .prepare = mmc_test_prepare_verify_write,
712 .run = mmc_test_align_multi_write,
713 .cleanup = mmc_test_cleanup_verify,
717 .name = "Badly aligned multi-block read",
718 .prepare = mmc_test_prepare_verify_read,
719 .run = mmc_test_align_multi_read,
720 .cleanup = mmc_test_cleanup_verify,
724 .name = "Correct xfer_size at write (start failure)",
725 .run = mmc_test_xfersize_write,
729 .name = "Correct xfer_size at read (start failure)",
730 .run = mmc_test_xfersize_read,
734 .name = "Correct xfer_size at write (midway failure)",
735 .run = mmc_test_multi_xfersize_write,
739 .name = "Correct xfer_size at read (midway failure)",
740 .run = mmc_test_multi_xfersize_read,
744 static struct mutex mmc_test_lock;
746 static void mmc_test_run(struct mmc_test_card *test)
750 printk(KERN_INFO "%s: Starting tests of card %s...\n",
751 mmc_hostname(test->card->host), mmc_card_id(test->card));
753 mmc_claim_host(test->card->host);
755 for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
756 printk(KERN_INFO "%s: Test case %d. %s...\n",
757 mmc_hostname(test->card->host), i + 1,
758 mmc_test_cases[i].name);
760 if (mmc_test_cases[i].prepare) {
761 ret = mmc_test_cases[i].prepare(test);
763 printk(KERN_INFO "%s: Result: Prepare "
764 "stage failed! (%d)\n",
765 mmc_hostname(test->card->host),
771 ret = mmc_test_cases[i].run(test);
774 printk(KERN_INFO "%s: Result: OK\n",
775 mmc_hostname(test->card->host));
778 printk(KERN_INFO "%s: Result: FAILED\n",
779 mmc_hostname(test->card->host));
781 case RESULT_UNSUP_HOST:
782 printk(KERN_INFO "%s: Result: UNSUPPORTED "
784 mmc_hostname(test->card->host));
786 case RESULT_UNSUP_CARD:
787 printk(KERN_INFO "%s: Result: UNSUPPORTED "
789 mmc_hostname(test->card->host));
792 printk(KERN_INFO "%s: Result: ERROR (%d)\n",
793 mmc_hostname(test->card->host), ret);
796 if (mmc_test_cases[i].cleanup) {
797 ret = mmc_test_cases[i].cleanup(test);
799 printk(KERN_INFO "%s: Warning: Cleanup "
800 "stage failed! (%d)\n",
801 mmc_hostname(test->card->host),
807 mmc_release_host(test->card->host);
809 printk(KERN_INFO "%s: Tests completed.\n",
810 mmc_hostname(test->card->host));
813 static ssize_t mmc_test_show(struct device *dev,
814 struct device_attribute *attr, char *buf)
816 mutex_lock(&mmc_test_lock);
817 mutex_unlock(&mmc_test_lock);
822 static ssize_t mmc_test_store(struct device *dev,
823 struct device_attribute *attr, const char *buf, size_t count)
825 struct mmc_card *card;
826 struct mmc_test_card *test;
828 card = container_of(dev, struct mmc_card, dev);
830 test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
836 test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
838 mutex_lock(&mmc_test_lock);
840 mutex_unlock(&mmc_test_lock);
849 static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store);
851 static int mmc_test_probe(struct mmc_card *card)
855 mutex_init(&mmc_test_lock);
857 ret = device_create_file(&card->dev, &dev_attr_test);
864 static void mmc_test_remove(struct mmc_card *card)
866 device_remove_file(&card->dev, &dev_attr_test);
869 static struct mmc_driver mmc_driver = {
873 .probe = mmc_test_probe,
874 .remove = mmc_test_remove,
877 static int __init mmc_test_init(void)
879 return mmc_register_driver(&mmc_driver);
882 static void __exit mmc_test_exit(void)
884 mmc_unregister_driver(&mmc_driver);
887 module_init(mmc_test_init);
888 module_exit(mmc_test_exit);
890 MODULE_LICENSE("GPL");
891 MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
892 MODULE_AUTHOR("Pierre Ossman");