diff options
| -rw-r--r-- | drivers/mmc/card/mmc_test.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 6fc13d4c634a..25296011df59 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
| @@ -388,14 +388,16 @@ static int mmc_test_transfer(struct mmc_test_card *test, | |||
| 388 | int ret, i; | 388 | int ret, i; |
| 389 | unsigned long flags; | 389 | unsigned long flags; |
| 390 | 390 | ||
| 391 | BUG_ON(blocks * blksz > BUFFER_SIZE); | ||
| 392 | |||
| 391 | if (write) { | 393 | if (write) { |
| 392 | for (i = 0;i < blocks * blksz;i++) | 394 | for (i = 0;i < blocks * blksz;i++) |
| 393 | test->scratch[i] = i; | 395 | test->scratch[i] = i; |
| 394 | } else { | 396 | } else { |
| 395 | memset(test->scratch, 0, BUFFER_SIZE); | 397 | memset(test->scratch, 0, blocks * blksz); |
| 396 | } | 398 | } |
| 397 | local_irq_save(flags); | 399 | local_irq_save(flags); |
| 398 | sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); | 400 | sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz); |
| 399 | local_irq_restore(flags); | 401 | local_irq_restore(flags); |
| 400 | 402 | ||
| 401 | ret = mmc_test_set_blksize(test, blksz); | 403 | ret = mmc_test_set_blksize(test, blksz); |
| @@ -442,7 +444,7 @@ static int mmc_test_transfer(struct mmc_test_card *test, | |||
| 442 | } | 444 | } |
| 443 | } else { | 445 | } else { |
| 444 | local_irq_save(flags); | 446 | local_irq_save(flags); |
| 445 | sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); | 447 | sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz); |
| 446 | local_irq_restore(flags); | 448 | local_irq_restore(flags); |
| 447 | for (i = 0;i < blocks * blksz;i++) { | 449 | for (i = 0;i < blocks * blksz;i++) { |
| 448 | if (test->scratch[i] != (u8)i) | 450 | if (test->scratch[i] != (u8)i) |
| @@ -803,6 +805,69 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test) | |||
| 803 | return 0; | 805 | return 0; |
| 804 | } | 806 | } |
| 805 | 807 | ||
| 808 | static int mmc_test_bigsg_write(struct mmc_test_card *test) | ||
| 809 | { | ||
| 810 | int ret; | ||
| 811 | unsigned int size; | ||
| 812 | struct scatterlist sg; | ||
| 813 | |||
| 814 | if (test->card->host->max_blk_count == 1) | ||
| 815 | return RESULT_UNSUP_HOST; | ||
| 816 | |||
| 817 | size = PAGE_SIZE * 2; | ||
| 818 | size = min(size, test->card->host->max_req_size); | ||
| 819 | size = min(size, test->card->host->max_seg_size); | ||
| 820 | size = min(size, test->card->host->max_blk_count * 512); | ||
| 821 | |||
| 822 | memset(test->buffer, 0, BUFFER_SIZE); | ||
| 823 | |||
| 824 | if (size < 1024) | ||
| 825 | return RESULT_UNSUP_HOST; | ||
| 826 | |||
| 827 | sg_init_table(&sg, 1); | ||
| 828 | sg_init_one(&sg, test->buffer, BUFFER_SIZE); | ||
| 829 | |||
| 830 | ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); | ||
| 831 | if (ret) | ||
| 832 | return ret; | ||
| 833 | |||
| 834 | return 0; | ||
| 835 | } | ||
| 836 | |||
| 837 | static int mmc_test_bigsg_read(struct mmc_test_card *test) | ||
| 838 | { | ||
| 839 | int ret, i; | ||
| 840 | unsigned int size; | ||
| 841 | struct scatterlist sg; | ||
| 842 | |||
| 843 | if (test->card->host->max_blk_count == 1) | ||
| 844 | return RESULT_UNSUP_HOST; | ||
| 845 | |||
| 846 | size = PAGE_SIZE * 2; | ||
| 847 | size = min(size, test->card->host->max_req_size); | ||
| 848 | size = min(size, test->card->host->max_seg_size); | ||
| 849 | size = min(size, test->card->host->max_blk_count * 512); | ||
| 850 | |||
| 851 | if (size < 1024) | ||
| 852 | return RESULT_UNSUP_HOST; | ||
| 853 | |||
| 854 | memset(test->buffer, 0xCD, BUFFER_SIZE); | ||
| 855 | |||
| 856 | sg_init_table(&sg, 1); | ||
| 857 | sg_init_one(&sg, test->buffer, BUFFER_SIZE); | ||
| 858 | ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); | ||
| 859 | if (ret) | ||
| 860 | return ret; | ||
| 861 | |||
| 862 | /* mmc_test_transfer() doesn't check for read overflows */ | ||
| 863 | for (i = size;i < BUFFER_SIZE;i++) { | ||
| 864 | if (test->buffer[i] != 0xCD) | ||
| 865 | return RESULT_FAIL; | ||
| 866 | } | ||
| 867 | |||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 806 | #ifdef CONFIG_HIGHMEM | 871 | #ifdef CONFIG_HIGHMEM |
| 807 | 872 | ||
| 808 | static int mmc_test_write_high(struct mmc_test_card *test) | 873 | static int mmc_test_write_high(struct mmc_test_card *test) |
| @@ -1006,6 +1071,20 @@ static const struct mmc_test_case mmc_test_cases[] = { | |||
| 1006 | .run = mmc_test_multi_xfersize_read, | 1071 | .run = mmc_test_multi_xfersize_read, |
| 1007 | }, | 1072 | }, |
| 1008 | 1073 | ||
| 1074 | { | ||
| 1075 | .name = "Over-sized SG list write", | ||
| 1076 | .prepare = mmc_test_prepare_write, | ||
| 1077 | .run = mmc_test_bigsg_write, | ||
| 1078 | .cleanup = mmc_test_cleanup, | ||
| 1079 | }, | ||
| 1080 | |||
| 1081 | { | ||
| 1082 | .name = "Over-sized SG list read", | ||
| 1083 | .prepare = mmc_test_prepare_read, | ||
| 1084 | .run = mmc_test_bigsg_read, | ||
| 1085 | .cleanup = mmc_test_cleanup, | ||
| 1086 | }, | ||
| 1087 | |||
| 1009 | #ifdef CONFIG_HIGHMEM | 1088 | #ifdef CONFIG_HIGHMEM |
| 1010 | 1089 | ||
| 1011 | { | 1090 | { |
