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>
This commit is contained in:
parent
907b2cd6db
commit
2661081f5a
1 changed files with 137 additions and 1 deletions
|
@ -21,13 +21,17 @@
|
||||||
#define RESULT_UNSUP_HOST 2
|
#define RESULT_UNSUP_HOST 2
|
||||||
#define RESULT_UNSUP_CARD 3
|
#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_test_card {
|
||||||
struct mmc_card *card;
|
struct mmc_card *card;
|
||||||
|
|
||||||
u8 scratch[BUFFER_SIZE];
|
u8 scratch[BUFFER_SIZE];
|
||||||
u8 *buffer;
|
u8 *buffer;
|
||||||
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
struct page *highmem;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
|
@ -799,6 +803,94 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
|
||||||
return 0;
|
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[] = {
|
static const struct mmc_test_case mmc_test_cases[] = {
|
||||||
{
|
{
|
||||||
.name = "Basic write (no data verification)",
|
.name = "Basic write (no data verification)",
|
||||||
|
@ -913,6 +1005,39 @@ static const struct mmc_test_case mmc_test_cases[] = {
|
||||||
.name = "Correct xfer_size at read (midway failure)",
|
.name = "Correct xfer_size at read (midway failure)",
|
||||||
.run = mmc_test_multi_xfersize_read,
|
.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;
|
static struct mutex mmc_test_lock;
|
||||||
|
@ -1014,12 +1139,23 @@ static ssize_t mmc_test_store(struct device *dev,
|
||||||
test->card = card;
|
test->card = card;
|
||||||
|
|
||||||
test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
|
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) {
|
if (test->buffer) {
|
||||||
|
#endif
|
||||||
mutex_lock(&mmc_test_lock);
|
mutex_lock(&mmc_test_lock);
|
||||||
mmc_test_run(test, testcase);
|
mmc_test_run(test, testcase);
|
||||||
mutex_unlock(&mmc_test_lock);
|
mutex_unlock(&mmc_test_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
__free_pages(test->highmem, BUFFER_ORDER);
|
||||||
|
#endif
|
||||||
kfree(test->buffer);
|
kfree(test->buffer);
|
||||||
kfree(test);
|
kfree(test);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue