Skip to content

Commit

Permalink
mmc_test: highmem tests
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pierre Ossman committed Jul 23, 2008
1 parent 907b2cd commit 2661081
Showing 1 changed file with 137 additions and 1 deletion.
138 changes: 137 additions & 1 deletion drivers/mmc/card/mmc_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
#define RESULT_UNSUP_HOST 2
#define RESULT_UNSUP_CARD 3

#define BUFFER_SIZE (PAGE_SIZE * 4)
#define BUFFER_ORDER 2
#define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER)

struct mmc_test_card {
struct mmc_card *card;

u8 scratch[BUFFER_SIZE];
u8 *buffer;
#ifdef CONFIG_HIGHMEM
struct page *highmem;
#endif
};

/*******************************************************************/
Expand Down Expand Up @@ -799,6 +803,94 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
return 0;
}

#ifdef CONFIG_HIGHMEM

static int mmc_test_write_high(struct mmc_test_card *test)
{
int ret;
struct scatterlist sg;

sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, 512, 0);

ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
if (ret)
return ret;

return 0;
}

static int mmc_test_read_high(struct mmc_test_card *test)
{
int ret;
struct scatterlist sg;

sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, 512, 0);

ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
if (ret)
return ret;

return 0;
}

static int mmc_test_multi_write_high(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);

if (size < 1024)
return RESULT_UNSUP_HOST;

sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, size, 0);

ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
if (ret)
return ret;

return 0;
}

static int mmc_test_multi_read_high(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);

if (size < 1024)
return RESULT_UNSUP_HOST;

sg_init_table(&sg, 1);
sg_set_page(&sg, test->highmem, size, 0);

ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
if (ret)
return ret;

return 0;
}

#endif /* CONFIG_HIGHMEM */

static const struct mmc_test_case mmc_test_cases[] = {
{
.name = "Basic write (no data verification)",
Expand Down Expand Up @@ -913,6 +1005,39 @@ static const struct mmc_test_case mmc_test_cases[] = {
.name = "Correct xfer_size at read (midway failure)",
.run = mmc_test_multi_xfersize_read,
},

#ifdef CONFIG_HIGHMEM

{
.name = "Highmem write",
.prepare = mmc_test_prepare_write,
.run = mmc_test_write_high,
.cleanup = mmc_test_cleanup,
},

{
.name = "Highmem read",
.prepare = mmc_test_prepare_read,
.run = mmc_test_read_high,
.cleanup = mmc_test_cleanup,
},

{
.name = "Multi-block highmem write",
.prepare = mmc_test_prepare_write,
.run = mmc_test_multi_write_high,
.cleanup = mmc_test_cleanup,
},

{
.name = "Multi-block highmem read",
.prepare = mmc_test_prepare_read,
.run = mmc_test_multi_read_high,
.cleanup = mmc_test_cleanup,
},

#endif /* CONFIG_HIGHMEM */

};

static struct mutex mmc_test_lock;
Expand Down Expand Up @@ -1014,12 +1139,23 @@ static ssize_t mmc_test_store(struct device *dev,
test->card = card;

test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
#ifdef CONFIG_HIGHMEM
test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
#endif

#ifdef CONFIG_HIGHMEM
if (test->buffer && test->highmem) {
#else
if (test->buffer) {
#endif
mutex_lock(&mmc_test_lock);
mmc_test_run(test, testcase);
mutex_unlock(&mmc_test_lock);
}

#ifdef CONFIG_HIGHMEM
__free_pages(test->highmem, BUFFER_ORDER);
#endif
kfree(test->buffer);
kfree(test);

Expand Down

0 comments on commit 2661081

Please sign in to comment.