aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2008-07-04 12:17:13 -0400
committerPierre Ossman <drzeus@drzeus.cx>2008-07-23 08:42:08 -0400
commit2661081f5ab9cb25359d27f88707a018cf4e68e9 (patch)
tree5bbdd138b1432a76de4328bbd718aa6253c76928 /drivers/mmc
parent907b2cd6dbbdfd6a4be7908f57b1498dfabc880e (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>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/card/mmc_test.c138
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
26struct mmc_test_card { 27struct 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
808static 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
823static 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
838static 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
865static 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
802static const struct mmc_test_case mmc_test_cases[] = { 894static 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
918static struct mutex mmc_test_lock; 1043static 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