mmc_test: test oversized sg lists
authorPierre Ossman <drzeus@drzeus.cx>
Sun, 20 Jul 2008 22:14:52 +0000 (00:14 +0200)
committerPierre Ossman <drzeus@drzeus.cx>
Wed, 23 Jul 2008 12:42:08 +0000 (14:42 +0200)
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>
drivers/mmc/card/mmc_test.c

index 6fc13d4..2529601 100644 (file)
@@ -388,14 +388,16 @@ static int mmc_test_transfer(struct mmc_test_card *test,
        int ret, i;
        unsigned long flags;
 
+       BUG_ON(blocks * blksz > BUFFER_SIZE);
+
        if (write) {
                for (i = 0;i < blocks * blksz;i++)
                        test->scratch[i] = i;
        } else {
-               memset(test->scratch, 0, BUFFER_SIZE);
+               memset(test->scratch, 0, blocks * blksz);
        }
        local_irq_save(flags);
-       sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+       sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz);
        local_irq_restore(flags);
 
        ret = mmc_test_set_blksize(test, blksz);
@@ -442,7 +444,7 @@ static int mmc_test_transfer(struct mmc_test_card *test,
                }
        } else {
                local_irq_save(flags);
-               sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+               sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz);
                local_irq_restore(flags);
                for (i = 0;i < blocks * blksz;i++) {
                        if (test->scratch[i] != (u8)i)
@@ -803,6 +805,69 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
        return 0;
 }
 
+static int mmc_test_bigsg_write(struct mmc_test_card *test)
+{
+       int ret;
+       unsigned int size;
+       struct scatterlist sg;
+
+       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);
+
+       memset(test->buffer, 0, BUFFER_SIZE);
+
+       if (size < 1024)
+               return RESULT_UNSUP_HOST;
+
+       sg_init_table(&sg, 1);
+       sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+
+       ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int mmc_test_bigsg_read(struct mmc_test_card *test)
+{
+       int ret, i;
+       unsigned int size;
+       struct scatterlist sg;
+
+       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);
+
+       if (size < 1024)
+               return RESULT_UNSUP_HOST;
+
+       memset(test->buffer, 0xCD, BUFFER_SIZE);
+
+       sg_init_table(&sg, 1);
+       sg_init_one(&sg, test->buffer, BUFFER_SIZE);
+       ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+       if (ret)
+               return ret;
+
+       /* mmc_test_transfer() doesn't check for read overflows */
+       for (i = size;i < BUFFER_SIZE;i++) {
+               if (test->buffer[i] != 0xCD)
+                       return RESULT_FAIL;
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_HIGHMEM
 
 static int mmc_test_write_high(struct mmc_test_card *test)
@@ -1006,6 +1071,20 @@ static const struct mmc_test_case mmc_test_cases[] = {
                .run = mmc_test_multi_xfersize_read,
        },
 
+       {
+               .name = "Over-sized SG list write",
+               .prepare = mmc_test_prepare_write,
+               .run = mmc_test_bigsg_write,
+               .cleanup = mmc_test_cleanup,
+       },
+
+       {
+               .name = "Over-sized SG list read",
+               .prepare = mmc_test_prepare_read,
+               .run = mmc_test_bigsg_read,
+               .cleanup = mmc_test_cleanup,
+       },
+
 #ifdef CONFIG_HIGHMEM
 
        {