diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-04 12:17:13 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-23 08:42:08 -0400 |
commit | 2661081f5ab9cb25359d27f88707a018cf4e68e9 (patch) | |
tree | 5bbdd138b1432a76de4328bbd718aa6253c76928 | |
parent | 907b2cd6dbbdfd6a4be7908f57b1498dfabc880e (diff) |
mmc_test: highmem tests
Add a couple of tests to make sure the host driver handles highmem
memory pages properly. Unfortunately there is no way to guarantee an
allocation below 4 GB in i386, so it might give you addresses that
are out of reach for the hardware (OTOH, so will any other highmem
allocation in the kernel).
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
-rw-r--r-- | drivers/mmc/card/mmc_test.c | 138 |
1 files changed, 137 insertions, 1 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index d6b9b486417c..6fc13d4c634a 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -21,13 +21,17 @@ | |||
21 | #define RESULT_UNSUP_HOST 2 | 21 | #define RESULT_UNSUP_HOST 2 |
22 | #define RESULT_UNSUP_CARD 3 | 22 | #define RESULT_UNSUP_CARD 3 |
23 | 23 | ||
24 | #define BUFFER_SIZE (PAGE_SIZE * 4) | 24 | #define BUFFER_ORDER 2 |
25 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) | ||
25 | 26 | ||
26 | struct mmc_test_card { | 27 | struct mmc_test_card { |
27 | struct mmc_card *card; | 28 | struct mmc_card *card; |
28 | 29 | ||
29 | u8 scratch[BUFFER_SIZE]; | 30 | u8 scratch[BUFFER_SIZE]; |
30 | u8 *buffer; | 31 | u8 *buffer; |
32 | #ifdef CONFIG_HIGHMEM | ||
33 | struct page *highmem; | ||
34 | #endif | ||
31 | }; | 35 | }; |
32 | 36 | ||
33 | /*******************************************************************/ | 37 | /*******************************************************************/ |
@@ -799,6 +803,94 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test) | |||
799 | return 0; | 803 | return 0; |
800 | } | 804 | } |
801 | 805 | ||
806 | #ifdef CONFIG_HIGHMEM | ||
807 | |||
808 | static 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 | |||
823 | static 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 | |||
838 | static 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 | |||
865 | static 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 | |||
802 | static const struct mmc_test_case mmc_test_cases[] = { | 894 | static const struct mmc_test_case mmc_test_cases[] = { |
803 | { | 895 | { |
804 | .name = "Basic write (no data verification)", | 896 | .name = "Basic write (no data verification)", |
@@ -913,6 +1005,39 @@ static const struct mmc_test_case mmc_test_cases[] = { | |||
913 | .name = "Correct xfer_size at read (midway failure)", | 1005 | .name = "Correct xfer_size at read (midway failure)", |
914 | .run = mmc_test_multi_xfersize_read, | 1006 | .run = mmc_test_multi_xfersize_read, |
915 | }, | 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 | |||
916 | }; | 1041 | }; |
917 | 1042 | ||
918 | static struct mutex mmc_test_lock; | 1043 | static struct mutex mmc_test_lock; |
@@ -1014,12 +1139,23 @@ static ssize_t mmc_test_store(struct device *dev, | |||
1014 | test->card = card; | 1139 | test->card = card; |
1015 | 1140 | ||
1016 | test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL); | 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 | ||
1017 | if (test->buffer) { | 1149 | if (test->buffer) { |
1150 | #endif | ||
1018 | mutex_lock(&mmc_test_lock); | 1151 | mutex_lock(&mmc_test_lock); |
1019 | mmc_test_run(test, testcase); | 1152 | mmc_test_run(test, testcase); |
1020 | mutex_unlock(&mmc_test_lock); | 1153 | mutex_unlock(&mmc_test_lock); |
1021 | } | 1154 | } |
1022 | 1155 | ||
1156 | #ifdef CONFIG_HIGHMEM | ||
1157 | __free_pages(test->highmem, BUFFER_ORDER); | ||
1158 | #endif | ||
1023 | kfree(test->buffer); | 1159 | kfree(test->buffer); |
1024 | kfree(test); | 1160 | kfree(test); |
1025 | 1161 | ||