2 * linux/drivers/mmc/card/mmc_test.c
4 * Copyright 2007-2008 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_ORDER 2
25 #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER)
27 struct mmc_test_card {
28 struct mmc_card *card;
30 u8 scratch[BUFFER_SIZE];
37 /*******************************************************************/
38 /* General helper functions */
39 /*******************************************************************/
42 * Configure correct block size in card
44 static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
46 struct mmc_command cmd;
49 cmd.opcode = MMC_SET_BLOCKLEN;
51 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
52 ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
60 * Fill in the mmc_request structure given a set of transfer parameters.
62 static 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)
66 BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop);
69 mrq->cmd->opcode = write ?
70 MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
72 mrq->cmd->opcode = write ?
73 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
76 mrq->cmd->arg = dev_addr;
77 if (!mmc_card_blockaddr(test->card))
80 mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
85 mrq->stop->opcode = MMC_STOP_TRANSMISSION;
87 mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
90 mrq->data->blksz = blksz;
91 mrq->data->blocks = blocks;
92 mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
94 mrq->data->sg_len = sg_len;
96 mmc_set_data_timeout(mrq->data, test->card);
100 * Wait for the card to finish the busy state
102 static int mmc_test_wait_busy(struct mmc_test_card *test)
105 struct mmc_command cmd;
109 memset(&cmd, 0, sizeof(struct mmc_command));
111 cmd.opcode = MMC_SEND_STATUS;
112 cmd.arg = test->card->rca << 16;
113 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
115 ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
119 if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) {
121 printk(KERN_INFO "%s: Warning: Host did not "
122 "wait for busy state to end.\n",
123 mmc_hostname(test->card->host));
125 } while (!(cmd.resp[0] & R1_READY_FOR_DATA));
131 * Transfer a single sector of kernel addressable data
133 static int mmc_test_buffer_transfer(struct mmc_test_card *test,
134 u8 *buffer, unsigned addr, unsigned blksz, int write)
138 struct mmc_request mrq;
139 struct mmc_command cmd;
140 struct mmc_command stop;
141 struct mmc_data data;
143 struct scatterlist sg;
145 memset(&mrq, 0, sizeof(struct mmc_request));
146 memset(&cmd, 0, sizeof(struct mmc_command));
147 memset(&data, 0, sizeof(struct mmc_data));
148 memset(&stop, 0, sizeof(struct mmc_command));
154 sg_init_one(&sg, buffer, blksz);
156 mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write);
158 mmc_wait_for_req(test->card->host, &mrq);
165 ret = mmc_test_wait_busy(test);
172 /*******************************************************************/
173 /* Test preparation and cleanup */
174 /*******************************************************************/
177 * Fill the first couple of sectors of the card with known data
178 * so that bad reads/writes can be detected
180 static int __mmc_test_prepare(struct mmc_test_card *test, int write)
184 ret = mmc_test_set_blksize(test, 512);
189 memset(test->buffer, 0xDF, 512);
191 for (i = 0;i < 512;i++)
195 for (i = 0;i < BUFFER_SIZE / 512;i++) {
196 ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1);
204 static int mmc_test_prepare_write(struct mmc_test_card *test)
206 return __mmc_test_prepare(test, 1);
209 static int mmc_test_prepare_read(struct mmc_test_card *test)
211 return __mmc_test_prepare(test, 0);
214 static int mmc_test_cleanup(struct mmc_test_card *test)
218 ret = mmc_test_set_blksize(test, 512);
222 memset(test->buffer, 0, 512);
224 for (i = 0;i < BUFFER_SIZE / 512;i++) {
225 ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1);
233 /*******************************************************************/
234 /* Test execution helpers */
235 /*******************************************************************/
238 * Modifies the mmc_request to perform the "short transfer" tests
240 static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
241 struct mmc_request *mrq, int write)
243 BUG_ON(!mrq || !mrq->cmd || !mrq->data);
245 if (mrq->data->blocks > 1) {
246 mrq->cmd->opcode = write ?
247 MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
250 mrq->cmd->opcode = MMC_SEND_STATUS;
251 mrq->cmd->arg = test->card->rca << 16;
256 * Checks that a normal transfer didn't have any errors
258 static int mmc_test_check_result(struct mmc_test_card *test,
259 struct mmc_request *mrq)
263 BUG_ON(!mrq || !mrq->cmd || !mrq->data);
267 if (!ret && mrq->cmd->error)
268 ret = mrq->cmd->error;
269 if (!ret && mrq->data->error)
270 ret = mrq->data->error;
271 if (!ret && mrq->stop && mrq->stop->error)
272 ret = mrq->stop->error;
273 if (!ret && mrq->data->bytes_xfered !=
274 mrq->data->blocks * mrq->data->blksz)
278 ret = RESULT_UNSUP_HOST;
284 * Checks that a "short transfer" behaved as expected
286 static int mmc_test_check_broken_result(struct mmc_test_card *test,
287 struct mmc_request *mrq)
291 BUG_ON(!mrq || !mrq->cmd || !mrq->data);
295 if (!ret && mrq->cmd->error)
296 ret = mrq->cmd->error;
297 if (!ret && mrq->data->error == 0)
299 if (!ret && mrq->data->error != -ETIMEDOUT)
300 ret = mrq->data->error;
301 if (!ret && mrq->stop && mrq->stop->error)
302 ret = mrq->stop->error;
303 if (mrq->data->blocks > 1) {
304 if (!ret && mrq->data->bytes_xfered > mrq->data->blksz)
307 if (!ret && mrq->data->bytes_xfered > 0)
312 ret = RESULT_UNSUP_HOST;
318 * Tests a basic transfer with certain parameters
320 static int mmc_test_simple_transfer(struct mmc_test_card *test,
321 struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
322 unsigned blocks, unsigned blksz, int write)
324 struct mmc_request mrq;
325 struct mmc_command cmd;
326 struct mmc_command stop;
327 struct mmc_data data;
329 memset(&mrq, 0, sizeof(struct mmc_request));
330 memset(&cmd, 0, sizeof(struct mmc_command));
331 memset(&data, 0, sizeof(struct mmc_data));
332 memset(&stop, 0, sizeof(struct mmc_command));
338 mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr,
339 blocks, blksz, write);
341 mmc_wait_for_req(test->card->host, &mrq);
343 mmc_test_wait_busy(test);
345 return mmc_test_check_result(test, &mrq);
349 * Tests a transfer where the card will fail completely or partly
351 static int mmc_test_broken_transfer(struct mmc_test_card *test,
352 unsigned blocks, unsigned blksz, int write)
354 struct mmc_request mrq;
355 struct mmc_command cmd;
356 struct mmc_command stop;
357 struct mmc_data data;
359 struct scatterlist sg;
361 memset(&mrq, 0, sizeof(struct mmc_request));
362 memset(&cmd, 0, sizeof(struct mmc_command));
363 memset(&data, 0, sizeof(struct mmc_data));
364 memset(&stop, 0, sizeof(struct mmc_command));
370 sg_init_one(&sg, test->buffer, blocks * blksz);
372 mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write);
373 mmc_test_prepare_broken_mrq(test, &mrq, write);
375 mmc_wait_for_req(test->card->host, &mrq);
377 mmc_test_wait_busy(test);
379 return mmc_test_check_broken_result(test, &mrq);
383 * Does a complete transfer test where data is also validated
385 * Note: mmc_test_prepare() must have been done before this call
387 static int mmc_test_transfer(struct mmc_test_card *test,
388 struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
389 unsigned blocks, unsigned blksz, int write)
395 for (i = 0;i < blocks * blksz;i++)
396 test->scratch[i] = i;
398 memset(test->scratch, 0, BUFFER_SIZE);
400 local_irq_save(flags);
401 sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
402 local_irq_restore(flags);
404 ret = mmc_test_set_blksize(test, blksz);
408 ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr,
409 blocks, blksz, write);
416 ret = mmc_test_set_blksize(test, 512);
420 sectors = (blocks * blksz + 511) / 512;
421 if ((sectors * 512) == (blocks * blksz))
424 if ((sectors * 512) > BUFFER_SIZE)
427 memset(test->buffer, 0, sectors * 512);
429 for (i = 0;i < sectors;i++) {
430 ret = mmc_test_buffer_transfer(test,
431 test->buffer + i * 512,
432 dev_addr + i, 512, 0);
437 for (i = 0;i < blocks * blksz;i++) {
438 if (test->buffer[i] != (u8)i)
442 for (;i < sectors * 512;i++) {
443 if (test->buffer[i] != 0xDF)
447 local_irq_save(flags);
448 sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
449 local_irq_restore(flags);
450 for (i = 0;i < blocks * blksz;i++) {
451 if (test->scratch[i] != (u8)i)
459 /*******************************************************************/
461 /*******************************************************************/
463 struct mmc_test_case {
466 int (*prepare)(struct mmc_test_card *);
467 int (*run)(struct mmc_test_card *);
468 int (*cleanup)(struct mmc_test_card *);
471 static int mmc_test_basic_write(struct mmc_test_card *test)
474 struct scatterlist sg;
476 ret = mmc_test_set_blksize(test, 512);
480 sg_init_one(&sg, test->buffer, 512);
482 ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
489 static int mmc_test_basic_read(struct mmc_test_card *test)
492 struct scatterlist sg;
494 ret = mmc_test_set_blksize(test, 512);
498 sg_init_one(&sg, test->buffer, 512);
500 ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
507 static int mmc_test_verify_write(struct mmc_test_card *test)
510 struct scatterlist sg;
512 sg_init_one(&sg, test->buffer, 512);
514 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
521 static int mmc_test_verify_read(struct mmc_test_card *test)
524 struct scatterlist sg;
526 sg_init_one(&sg, test->buffer, 512);
528 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
535 static int mmc_test_multi_write(struct mmc_test_card *test)
539 struct scatterlist sg;
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 sg_init_one(&sg, test->buffer, size);
554 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
561 static int mmc_test_multi_read(struct mmc_test_card *test)
565 struct scatterlist sg;
567 if (test->card->host->max_blk_count == 1)
568 return RESULT_UNSUP_HOST;
570 size = PAGE_SIZE * 2;
571 size = min(size, test->card->host->max_req_size);
572 size = min(size, test->card->host->max_seg_size);
573 size = min(size, test->card->host->max_blk_count * 512);
576 return RESULT_UNSUP_HOST;
578 sg_init_one(&sg, test->buffer, size);
580 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
587 static int mmc_test_pow2_write(struct mmc_test_card *test)
590 struct scatterlist sg;
592 if (!test->card->csd.write_partial)
593 return RESULT_UNSUP_CARD;
595 for (i = 1; i < 512;i <<= 1) {
596 sg_init_one(&sg, test->buffer, i);
597 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
605 static int mmc_test_pow2_read(struct mmc_test_card *test)
608 struct scatterlist sg;
610 if (!test->card->csd.read_partial)
611 return RESULT_UNSUP_CARD;
613 for (i = 1; i < 512;i <<= 1) {
614 sg_init_one(&sg, test->buffer, i);
615 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
623 static int mmc_test_weird_write(struct mmc_test_card *test)
626 struct scatterlist sg;
628 if (!test->card->csd.write_partial)
629 return RESULT_UNSUP_CARD;
631 for (i = 3; i < 512;i += 7) {
632 sg_init_one(&sg, test->buffer, i);
633 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
641 static int mmc_test_weird_read(struct mmc_test_card *test)
644 struct scatterlist sg;
646 if (!test->card->csd.read_partial)
647 return RESULT_UNSUP_CARD;
649 for (i = 3; i < 512;i += 7) {
650 sg_init_one(&sg, test->buffer, i);
651 ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
659 static int mmc_test_align_write(struct mmc_test_card *test)
662 struct scatterlist sg;
664 for (i = 1;i < 4;i++) {
665 sg_init_one(&sg, test->buffer + i, 512);
666 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
674 static int mmc_test_align_read(struct mmc_test_card *test)
677 struct scatterlist sg;
679 for (i = 1;i < 4;i++) {
680 sg_init_one(&sg, test->buffer + i, 512);
681 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
689 static int mmc_test_align_multi_write(struct mmc_test_card *test)
693 struct scatterlist sg;
695 if (test->card->host->max_blk_count == 1)
696 return RESULT_UNSUP_HOST;
698 size = PAGE_SIZE * 2;
699 size = min(size, test->card->host->max_req_size);
700 size = min(size, test->card->host->max_seg_size);
701 size = min(size, test->card->host->max_blk_count * 512);
704 return RESULT_UNSUP_HOST;
706 for (i = 1;i < 4;i++) {
707 sg_init_one(&sg, test->buffer + i, size);
708 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
716 static int mmc_test_align_multi_read(struct mmc_test_card *test)
720 struct scatterlist sg;
722 if (test->card->host->max_blk_count == 1)
723 return RESULT_UNSUP_HOST;
725 size = PAGE_SIZE * 2;
726 size = min(size, test->card->host->max_req_size);
727 size = min(size, test->card->host->max_seg_size);
728 size = min(size, test->card->host->max_blk_count * 512);
731 return RESULT_UNSUP_HOST;
733 for (i = 1;i < 4;i++) {
734 sg_init_one(&sg, test->buffer + i, size);
735 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
743 static int mmc_test_xfersize_write(struct mmc_test_card *test)
747 ret = mmc_test_set_blksize(test, 512);
751 ret = mmc_test_broken_transfer(test, 1, 512, 1);
758 static int mmc_test_xfersize_read(struct mmc_test_card *test)
762 ret = mmc_test_set_blksize(test, 512);
766 ret = mmc_test_broken_transfer(test, 1, 512, 0);
773 static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
777 if (test->card->host->max_blk_count == 1)
778 return RESULT_UNSUP_HOST;
780 ret = mmc_test_set_blksize(test, 512);
784 ret = mmc_test_broken_transfer(test, 2, 512, 1);
791 static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
795 if (test->card->host->max_blk_count == 1)
796 return RESULT_UNSUP_HOST;
798 ret = mmc_test_set_blksize(test, 512);
802 ret = mmc_test_broken_transfer(test, 2, 512, 0);
809 #ifdef CONFIG_HIGHMEM
811 static int mmc_test_write_high(struct mmc_test_card *test)
814 struct scatterlist sg;
816 sg_init_table(&sg, 1);
817 sg_set_page(&sg, test->highmem, 512, 0);
819 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
826 static int mmc_test_read_high(struct mmc_test_card *test)
829 struct scatterlist sg;
831 sg_init_table(&sg, 1);
832 sg_set_page(&sg, test->highmem, 512, 0);
834 ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
841 static int mmc_test_multi_write_high(struct mmc_test_card *test)
845 struct scatterlist sg;
847 if (test->card->host->max_blk_count == 1)
848 return RESULT_UNSUP_HOST;
850 size = PAGE_SIZE * 2;
851 size = min(size, test->card->host->max_req_size);
852 size = min(size, test->card->host->max_seg_size);
853 size = min(size, test->card->host->max_blk_count * 512);
856 return RESULT_UNSUP_HOST;
858 sg_init_table(&sg, 1);
859 sg_set_page(&sg, test->highmem, size, 0);
861 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
868 static int mmc_test_multi_read_high(struct mmc_test_card *test)
872 struct scatterlist sg;
874 if (test->card->host->max_blk_count == 1)
875 return RESULT_UNSUP_HOST;
877 size = PAGE_SIZE * 2;
878 size = min(size, test->card->host->max_req_size);
879 size = min(size, test->card->host->max_seg_size);
880 size = min(size, test->card->host->max_blk_count * 512);
883 return RESULT_UNSUP_HOST;
885 sg_init_table(&sg, 1);
886 sg_set_page(&sg, test->highmem, size, 0);
888 ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
895 #endif /* CONFIG_HIGHMEM */
897 static const struct mmc_test_case mmc_test_cases[] = {
899 .name = "Basic write (no data verification)",
900 .run = mmc_test_basic_write,
904 .name = "Basic read (no data verification)",
905 .run = mmc_test_basic_read,
909 .name = "Basic write (with data verification)",
910 .prepare = mmc_test_prepare_write,
911 .run = mmc_test_verify_write,
912 .cleanup = mmc_test_cleanup,
916 .name = "Basic read (with data verification)",
917 .prepare = mmc_test_prepare_read,
918 .run = mmc_test_verify_read,
919 .cleanup = mmc_test_cleanup,
923 .name = "Multi-block write",
924 .prepare = mmc_test_prepare_write,
925 .run = mmc_test_multi_write,
926 .cleanup = mmc_test_cleanup,
930 .name = "Multi-block read",
931 .prepare = mmc_test_prepare_read,
932 .run = mmc_test_multi_read,
933 .cleanup = mmc_test_cleanup,
937 .name = "Power of two block writes",
938 .prepare = mmc_test_prepare_write,
939 .run = mmc_test_pow2_write,
940 .cleanup = mmc_test_cleanup,
944 .name = "Power of two block reads",
945 .prepare = mmc_test_prepare_read,
946 .run = mmc_test_pow2_read,
947 .cleanup = mmc_test_cleanup,
951 .name = "Weird sized block writes",
952 .prepare = mmc_test_prepare_write,
953 .run = mmc_test_weird_write,
954 .cleanup = mmc_test_cleanup,
958 .name = "Weird sized block reads",
959 .prepare = mmc_test_prepare_read,
960 .run = mmc_test_weird_read,
961 .cleanup = mmc_test_cleanup,
965 .name = "Badly aligned write",
966 .prepare = mmc_test_prepare_write,
967 .run = mmc_test_align_write,
968 .cleanup = mmc_test_cleanup,
972 .name = "Badly aligned read",
973 .prepare = mmc_test_prepare_read,
974 .run = mmc_test_align_read,
975 .cleanup = mmc_test_cleanup,
979 .name = "Badly aligned multi-block write",
980 .prepare = mmc_test_prepare_write,
981 .run = mmc_test_align_multi_write,
982 .cleanup = mmc_test_cleanup,
986 .name = "Badly aligned multi-block read",
987 .prepare = mmc_test_prepare_read,
988 .run = mmc_test_align_multi_read,
989 .cleanup = mmc_test_cleanup,
993 .name = "Correct xfer_size at write (start failure)",
994 .run = mmc_test_xfersize_write,
998 .name = "Correct xfer_size at read (start failure)",
999 .run = mmc_test_xfersize_read,
1003 .name = "Correct xfer_size at write (midway failure)",
1004 .run = mmc_test_multi_xfersize_write,
1008 .name = "Correct xfer_size at read (midway failure)",
1009 .run = mmc_test_multi_xfersize_read,
1012 #ifdef CONFIG_HIGHMEM
1015 .name = "Highmem write",
1016 .prepare = mmc_test_prepare_write,
1017 .run = mmc_test_write_high,
1018 .cleanup = mmc_test_cleanup,
1022 .name = "Highmem read",
1023 .prepare = mmc_test_prepare_read,
1024 .run = mmc_test_read_high,
1025 .cleanup = mmc_test_cleanup,
1029 .name = "Multi-block highmem write",
1030 .prepare = mmc_test_prepare_write,
1031 .run = mmc_test_multi_write_high,
1032 .cleanup = mmc_test_cleanup,
1036 .name = "Multi-block highmem read",
1037 .prepare = mmc_test_prepare_read,
1038 .run = mmc_test_multi_read_high,
1039 .cleanup = mmc_test_cleanup,
1042 #endif /* CONFIG_HIGHMEM */
1046 static DEFINE_MUTEX(mmc_test_lock);
1048 static void mmc_test_run(struct mmc_test_card *test, int testcase)
1052 printk(KERN_INFO "%s: Starting tests of card %s...\n",
1053 mmc_hostname(test->card->host), mmc_card_id(test->card));
1055 mmc_claim_host(test->card->host);
1057 for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
1058 if (testcase && ((i + 1) != testcase))
1061 printk(KERN_INFO "%s: Test case %d. %s...\n",
1062 mmc_hostname(test->card->host), i + 1,
1063 mmc_test_cases[i].name);
1065 if (mmc_test_cases[i].prepare) {
1066 ret = mmc_test_cases[i].prepare(test);
1068 printk(KERN_INFO "%s: Result: Prepare "
1069 "stage failed! (%d)\n",
1070 mmc_hostname(test->card->host),
1076 ret = mmc_test_cases[i].run(test);
1079 printk(KERN_INFO "%s: Result: OK\n",
1080 mmc_hostname(test->card->host));
1083 printk(KERN_INFO "%s: Result: FAILED\n",
1084 mmc_hostname(test->card->host));
1086 case RESULT_UNSUP_HOST:
1087 printk(KERN_INFO "%s: Result: UNSUPPORTED "
1089 mmc_hostname(test->card->host));
1091 case RESULT_UNSUP_CARD:
1092 printk(KERN_INFO "%s: Result: UNSUPPORTED "
1094 mmc_hostname(test->card->host));
1097 printk(KERN_INFO "%s: Result: ERROR (%d)\n",
1098 mmc_hostname(test->card->host), ret);
1101 if (mmc_test_cases[i].cleanup) {
1102 ret = mmc_test_cases[i].cleanup(test);
1104 printk(KERN_INFO "%s: Warning: Cleanup "
1105 "stage failed! (%d)\n",
1106 mmc_hostname(test->card->host),
1112 mmc_release_host(test->card->host);
1114 printk(KERN_INFO "%s: Tests completed.\n",
1115 mmc_hostname(test->card->host));
1118 static ssize_t mmc_test_show(struct device *dev,
1119 struct device_attribute *attr, char *buf)
1121 mutex_lock(&mmc_test_lock);
1122 mutex_unlock(&mmc_test_lock);
1127 static ssize_t mmc_test_store(struct device *dev,
1128 struct device_attribute *attr, const char *buf, size_t count)
1130 struct mmc_card *card;
1131 struct mmc_test_card *test;
1134 card = container_of(dev, struct mmc_card, dev);
1136 testcase = simple_strtol(buf, NULL, 10);
1138 test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
1144 test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
1145 #ifdef CONFIG_HIGHMEM
1146 test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
1149 #ifdef CONFIG_HIGHMEM
1150 if (test->buffer && test->highmem) {
1154 mutex_lock(&mmc_test_lock);
1155 mmc_test_run(test, testcase);
1156 mutex_unlock(&mmc_test_lock);
1159 #ifdef CONFIG_HIGHMEM
1160 __free_pages(test->highmem, BUFFER_ORDER);
1162 kfree(test->buffer);
1168 static DEVICE_ATTR(test, S_IWUSR | S_IRUGO, mmc_test_show, mmc_test_store);
1170 static int mmc_test_probe(struct mmc_card *card)
1174 if ((card->type != MMC_TYPE_MMC) && (card->type != MMC_TYPE_SD))
1177 ret = device_create_file(&card->dev, &dev_attr_test);
1181 dev_info(&card->dev, "Card claimed for testing.\n");
1186 static void mmc_test_remove(struct mmc_card *card)
1188 device_remove_file(&card->dev, &dev_attr_test);
1191 static struct mmc_driver mmc_driver = {
1195 .probe = mmc_test_probe,
1196 .remove = mmc_test_remove,
1199 static int __init mmc_test_init(void)
1201 return mmc_register_driver(&mmc_driver);
1204 static void __exit mmc_test_exit(void)
1206 mmc_unregister_driver(&mmc_driver);
1209 module_init(mmc_test_init);
1210 module_exit(mmc_test_exit);
1212 MODULE_LICENSE("GPL");
1213 MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
1214 MODULE_AUTHOR("Pierre Ossman");