From 8824cdd4e414fbd49edb83a9805784e994645b0c Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Fri, 14 Oct 2011 13:54:36 +0200 Subject: mmc: mmc_test: add 4 byte alignment tests Add test cases to verify alignment with 4 bytes and 32 bytes for sg element lengths and memory addresses. These tests were added to investigate DMA constraints when transferring buffers that are not aligned with 32 bytes. ST-Ericsson ID: 363565 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I6363a018647f22e5d69920af2cb30dfe2b2a699e Signed-off-by: Per Forlin Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34362 Reviewed-by: QATOOLS Reviewed-by: Ulf HANSSON --- drivers/mmc/card/mmc_test.c | 180 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 759714ed6be..6622f2e6e05 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -1253,6 +1253,130 @@ static int mmc_test_align_multi_read(struct mmc_test_card *test) return 0; } + +/* helper function for various address alignment and sg length alignment */ +static int mmc_test_align_multi(struct mmc_test_card *test, bool do_write, + struct scatterlist *sg, + u32 *sizes, int sg_len, int offset) +{ + int ret, i; + unsigned int size; + u32 buf_off; + u32 sg_size; + + if (test->card->host->max_blk_count == 1) + return RESULT_UNSUP_HOST; + + size = PAGE_SIZE * 2; + size = min(size, test->card->host->max_req_size); + size = min(size, test->card->host->max_seg_size); + size = min(size, test->card->host->max_blk_count * 512); + size -= offset; + size -= size % 512; + + if (size < 1024) + return RESULT_UNSUP_HOST; + + for (i = 0, sg_size = 0; + i < sg_len && sg_size + sizes[i] < size; i++) + sg_size += sizes[i]; + + if (sg_size < size) + sizes[i-1] += size - sg_size; + sg_len = i; + + sg_init_table(sg, sg_len); + for (i = 0, buf_off = offset; i < sg_len; i++) { + sg_set_buf(&sg[i], test->buffer + buf_off, sizes[i]); + buf_off += sizes[i]; + } + + ret = mmc_test_transfer(test, sg, sg_len, 0, size/512, 512, do_write); + if (ret) + return ret; + + return 0; +} + +static int mmc_test_align_length_32(struct mmc_test_card *test, bool do_write) +{ + u32 sizes[] = {512, 32*1, 32*2, 32*3, 32*4, 32*5, 32*6, 32*7, + 32*8, 32*9, 32*10, 32*11, 32*12, 32*13, 2048}; + struct scatterlist sg[ARRAY_SIZE(sizes)]; + + return mmc_test_align_multi(test, do_write, sg, sizes, + ARRAY_SIZE(sg), 0); +} + +static int mmc_test_align_length_4(struct mmc_test_card *test, bool do_write) +{ + u32 sizes[] = {512, 4*1, 4*2, 4*3, 4*4, 4*5, 4*6, 4*7, + 4*8, 4*9, 520, 1040, 2080}; + struct scatterlist sg[ARRAY_SIZE(sizes)]; + + return mmc_test_align_multi(test, do_write, sg, sizes, + ARRAY_SIZE(sg), 0); +} + +static int mmc_test_align_length_4_write(struct mmc_test_card *test) +{ + bool do_write = true; + return mmc_test_align_length_4(test, do_write); +} + +static int mmc_test_align_length_4_read(struct mmc_test_card *test) +{ + bool do_write = false; + return mmc_test_align_length_4(test, do_write); +} + +static int mmc_test_align_length_32_write(struct mmc_test_card *test) +{ + bool do_write = true; + return mmc_test_align_length_32(test, do_write); +} + +static int mmc_test_align_length_32_read(struct mmc_test_card *test) +{ + bool do_write = false; + return mmc_test_align_length_32(test, do_write); +} + +/* helper function for testing address alignment */ +static int mmc_test_align_address(struct mmc_test_card *test, bool do_write, + u32 offset) +{ + u32 sizes[] = {512, 512, 1024, 1024, 2048}; + struct scatterlist sg[ARRAY_SIZE(sizes)]; + + return mmc_test_align_multi(test, do_write, sg, + sizes, ARRAY_SIZE(sg), offset); +} + +static int mmc_test_align_address_4_write(struct mmc_test_card *test) +{ + bool do_write = true; + return mmc_test_align_address(test, do_write, 4); +} + +static int mmc_test_align_address_4_read(struct mmc_test_card *test) +{ + bool do_write = false; + return mmc_test_align_address(test, do_write, 4); +} + +static int mmc_test_align_address_32_write(struct mmc_test_card *test) +{ + bool do_write = true; + return mmc_test_align_address(test, do_write, 32); +} + +static int mmc_test_align_address_32_read(struct mmc_test_card *test) +{ + bool do_write = false; + return mmc_test_align_address(test, do_write, 32); +} + static int mmc_test_xfersize_write(struct mmc_test_card *test) { int ret; @@ -2450,6 +2574,62 @@ static const struct mmc_test_case mmc_test_cases[] = { .cleanup = mmc_test_cleanup, }, + { + .name = "4 bytes aligned sg-element length write", + .prepare = mmc_test_prepare_write, + .run = mmc_test_align_length_4_write, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "4 bytes aligned sg-element length read", + .prepare = mmc_test_prepare_read, + .run = mmc_test_align_length_4_read, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "32 bytes aligned sg-element length write", + .prepare = mmc_test_prepare_write, + .run = mmc_test_align_length_32_write, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "32 bytes aligned sg-element length read", + .prepare = mmc_test_prepare_read, + .run = mmc_test_align_length_32_read, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "4 bytes aligned sg-element address write", + .prepare = mmc_test_prepare_write, + .run = mmc_test_align_address_4_write, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "4 bytes aligned sg-element address read", + .prepare = mmc_test_prepare_read, + .run = mmc_test_align_address_4_read, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "32 bytes aligned sg-element address write", + .prepare = mmc_test_prepare_write, + .run = mmc_test_align_address_32_write, + .cleanup = mmc_test_cleanup, + }, + + { + .name = "32 bytes aligned sg-element address read", + .prepare = mmc_test_prepare_read, + .run = mmc_test_align_address_32_read, + .cleanup = mmc_test_cleanup, + }, + { .name = "Correct xfer_size at write (start failure)", .run = mmc_test_xfersize_write, -- cgit v1.2.3