diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-20 18:14:52 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-23 08:42:08 -0400 |
commit | 48b5352ea1891455eb8e824cf7d92f66931a090f (patch) | |
tree | 5068eb9fb3d16e0f1353a662b48c370fdabfcd7e /drivers/mmc | |
parent | 2661081f5ab9cb25359d27f88707a018cf4e68e9 (diff) |
mmc_test: test oversized sg lists
Add tests that make sure the driver properly checks the blocks and
blksz fields and doesn't assume the sg list has a size that perfectly
matches the current request.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers/mmc')
-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 | { |