Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/drzeus/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  sdhci: highmem capable PIO routines
  sg: reimplement sg mapping iterator
  mmc_test: print message when attaching to card
  mmc: Remove Russell as primecell mci maintainer
  mmc_block: bounce buffer highmem support
  sdhci: fix bad warning from commit c8b3e02
  sdhci: add warnings for bad buffers in ADMA path
  mmc_test: test oversized sg lists
  mmc_test: highmem tests
  s3cmci: ensure host stopped on machine shutdown
  au1xmmc: suspend/resume implementation
  s3cmci: fixes for section mismatch warnings
  pxamci: trivial fix of DMA alignment register bit clearing
  • Loading branch information
torvalds committed Jul 23, 2008
2 parents 5554b35 + 7659150 commit 20b7997
Show file tree
Hide file tree
Showing 10 changed files with 573 additions and 248 deletions.
5 changes: 1 addition & 4 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,7 @@ M: [email protected]
S: Maintained

ARM PRIMECELL MMCI PL180/1 DRIVER
P: Russell King
M: [email protected]
L: [email protected] (subscribers-only)
S: Maintained
S: Orphan

ARM/ADI ROADRUNNER MACHINE SUPPORT
P: Lennert Buytenhek
Expand Down
225 changes: 221 additions & 4 deletions 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 @@ -384,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);
Expand Down Expand Up @@ -438,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)
Expand Down Expand Up @@ -799,6 +805,157 @@ 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)
{
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 +1070,53 @@ static const struct mmc_test_case mmc_test_cases[] = {
.name = "Correct xfer_size at read (midway failure)",
.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

{
.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 +1218,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 All @@ -1041,6 +1256,8 @@ static int mmc_test_probe(struct mmc_card *card)
if (ret)
return ret;

dev_info(&card->dev, "Card claimed for testing.\n");

return 0;
}

Expand Down
Loading

0 comments on commit 20b7997

Please sign in to comment.