Loading drivers/mmc/card/mmc_test.c +364 −190 Original line number Diff line number Diff line Loading @@ -26,13 +26,17 @@ struct mmc_test_card { struct mmc_card *card; u8 scratch[BUFFER_SIZE]; u8 *buffer; }; /*******************************************************************/ /* Helper functions */ /* General helper functions */ /*******************************************************************/ /* * Configure correct block size in card */ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) { struct mmc_command cmd; Loading @@ -48,117 +52,61 @@ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) return 0; } static int __mmc_test_transfer(struct mmc_test_card *test, int write, unsigned broken_xfer, u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz) /* * Fill in the mmc_request structure given a set of transfer parameters. */ static void mmc_test_prepare_mrq(struct mmc_test_card *test, struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write) { int ret, busy; struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; struct scatterlist sg; BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop); memset(&mrq, 0, sizeof(struct mmc_request)); mrq.cmd = &cmd; mrq.data = &data; memset(&cmd, 0, sizeof(struct mmc_command)); if (broken_xfer) { if (blocks > 1) { cmd.opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; } else { cmd.opcode = MMC_SEND_STATUS; } } else { if (blocks > 1) { cmd.opcode = write ? mrq->cmd->opcode = write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK; } else { cmd.opcode = write ? mrq->cmd->opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; } } if (broken_xfer && blocks == 1) cmd.arg = test->card->rca << 16; else cmd.arg = addr; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; mrq->cmd->arg = dev_addr; mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; memset(&stop, 0, sizeof(struct mmc_command)); if (!broken_xfer && (blocks > 1)) { stop.opcode = MMC_STOP_TRANSMISSION; stop.arg = 0; stop.flags = MMC_RSP_R1B | MMC_CMD_AC; mrq.stop = &stop; if (blocks == 1) mrq->stop = NULL; else { mrq->stop->opcode = MMC_STOP_TRANSMISSION; mrq->stop->arg = 0; mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC; } memset(&data, 0, sizeof(struct mmc_data)); data.blksz = blksz; data.blocks = blocks; data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; data.sg = &sg; data.sg_len = 1; sg_init_one(&sg, buffer, blocks * blksz); mrq->data->blksz = blksz; mrq->data->blocks = blocks; mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; mrq->data->sg = sg; mrq->data->sg_len = sg_len; mmc_set_data_timeout(&data, test->card); mmc_wait_for_req(test->card->host, &mrq); ret = 0; if (broken_xfer) { if (!ret && cmd.error) ret = cmd.error; if (!ret && data.error == 0) ret = RESULT_FAIL; if (!ret && data.error != -ETIMEDOUT) ret = data.error; if (!ret && stop.error) ret = stop.error; if (blocks > 1) { if (!ret && data.bytes_xfered > blksz) ret = RESULT_FAIL; } else { if (!ret && data.bytes_xfered > 0) ret = RESULT_FAIL; } } else { if (!ret && cmd.error) ret = cmd.error; if (!ret && data.error) ret = data.error; if (!ret && stop.error) ret = stop.error; if (!ret && data.bytes_xfered != blocks * blksz) ret = RESULT_FAIL; mmc_set_data_timeout(mrq->data, test->card); } if (ret == -EINVAL) ret = RESULT_UNSUP_HOST; /* * Wait for the card to finish the busy state */ static int mmc_test_wait_busy(struct mmc_test_card *test) { int ret, busy; struct mmc_command cmd; busy = 0; do { int ret2; memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = MMC_SEND_STATUS; cmd.arg = test->card->rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; ret2 = mmc_wait_for_cmd(test->card->host, &cmd, 0); if (ret2) ret = mmc_wait_for_cmd(test->card->host, &cmd, 0); if (ret) break; if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { Loading @@ -172,14 +120,57 @@ static int __mmc_test_transfer(struct mmc_test_card *test, int write, return ret; } static int mmc_test_transfer(struct mmc_test_card *test, int write, u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz) /* * Transfer a single sector of kernel addressable data */ static int mmc_test_buffer_transfer(struct mmc_test_card *test, u8 *buffer, unsigned addr, unsigned blksz, int write) { return __mmc_test_transfer(test, write, 0, buffer, addr, blocks, blksz); int ret; struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; struct scatterlist sg; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; sg_init_one(&sg, buffer, blksz); mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write); mmc_wait_for_req(test->card->host, &mrq); if (cmd.error) return cmd.error; if (data.error) return data.error; ret = mmc_test_wait_busy(test); if (ret) return ret; return 0; } static int mmc_test_prepare_verify(struct mmc_test_card *test, int write) /*******************************************************************/ /* Test preparation and cleanup */ /*******************************************************************/ /* * Fill the first couple of sectors of the card with known data * so that bad reads/writes can be detected */ static int __mmc_test_prepare(struct mmc_test_card *test, int write) { int ret, i; Loading @@ -188,15 +179,14 @@ static int mmc_test_prepare_verify(struct mmc_test_card *test, int write) return ret; if (write) memset(test->buffer, 0xDF, BUFFER_SIZE); memset(test->buffer, 0xDF, 512); else { for (i = 0;i < BUFFER_SIZE;i++) for (i = 0;i < 512;i++) test->buffer[i] = i; } for (i = 0;i < BUFFER_SIZE / 512;i++) { ret = mmc_test_transfer(test, 1, test->buffer + i * 512, i * 512, 1, 512); ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); if (ret) return ret; } Loading @@ -204,41 +194,218 @@ static int mmc_test_prepare_verify(struct mmc_test_card *test, int write) return 0; } static int mmc_test_prepare_verify_write(struct mmc_test_card *test) static int mmc_test_prepare_write(struct mmc_test_card *test) { return mmc_test_prepare_verify(test, 1); return __mmc_test_prepare(test, 1); } static int mmc_test_prepare_verify_read(struct mmc_test_card *test) static int mmc_test_prepare_read(struct mmc_test_card *test) { return mmc_test_prepare_verify(test, 0); return __mmc_test_prepare(test, 0); } static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz) static int mmc_test_cleanup(struct mmc_test_card *test) { int ret, i, sectors; int ret, i; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; memset(test->buffer, 0, 512); for (i = 0;i < BUFFER_SIZE / 512;i++) { ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); if (ret) return ret; } return 0; } /*******************************************************************/ /* Test execution helpers */ /*******************************************************************/ /* * It is assumed that the above preparation has been done. * Modifies the mmc_request to perform the "short transfer" tests */ static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test, struct mmc_request *mrq, int write) { BUG_ON(!mrq || !mrq->cmd || !mrq->data); if (mrq->data->blocks > 1) { mrq->cmd->opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; mrq->stop = NULL; } else { mrq->cmd->opcode = MMC_SEND_STATUS; mrq->cmd->arg = test->card->rca << 16; } } memset(test->buffer, 0, BUFFER_SIZE); /* * Checks that a normal transfer didn't have any errors */ static int mmc_test_check_result(struct mmc_test_card *test, struct mmc_request *mrq) { int ret; BUG_ON(!mrq || !mrq->cmd || !mrq->data); ret = 0; if (!ret && mrq->cmd->error) ret = mrq->cmd->error; if (!ret && mrq->data->error) ret = mrq->data->error; if (!ret && mrq->stop && mrq->stop->error) ret = mrq->stop->error; if (!ret && mrq->data->bytes_xfered != mrq->data->blocks * mrq->data->blksz) ret = RESULT_FAIL; if (ret == -EINVAL) ret = RESULT_UNSUP_HOST; return ret; } /* * Checks that a "short transfer" behaved as expected */ static int mmc_test_check_broken_result(struct mmc_test_card *test, struct mmc_request *mrq) { int ret; BUG_ON(!mrq || !mrq->cmd || !mrq->data); ret = 0; if (!ret && mrq->cmd->error) ret = mrq->cmd->error; if (!ret && mrq->data->error == 0) ret = RESULT_FAIL; if (!ret && mrq->data->error != -ETIMEDOUT) ret = mrq->data->error; if (!ret && mrq->stop && mrq->stop->error) ret = mrq->stop->error; if (mrq->data->blocks > 1) { if (!ret && mrq->data->bytes_xfered > mrq->data->blksz) ret = RESULT_FAIL; } else { if (!ret && mrq->data->bytes_xfered > 0) ret = RESULT_FAIL; } if (ret == -EINVAL) ret = RESULT_UNSUP_HOST; return ret; } /* * Tests a basic transfer with certain parameters */ static int mmc_test_simple_transfer(struct mmc_test_card *test, struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write) { struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr, blocks, blksz, write); mmc_wait_for_req(test->card->host, &mrq); mmc_test_wait_busy(test); return mmc_test_check_result(test, &mrq); } /* * Tests a transfer where the card will fail completely or partly */ static int mmc_test_broken_transfer(struct mmc_test_card *test, unsigned blocks, unsigned blksz, int write) { struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; struct scatterlist sg; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; sg_init_one(&sg, test->buffer, blocks * blksz); mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write); mmc_test_prepare_broken_mrq(test, &mrq, write); mmc_wait_for_req(test->card->host, &mrq); mmc_test_wait_busy(test); return mmc_test_check_broken_result(test, &mrq); } /* * Does a complete transfer test where data is also validated * * Note: mmc_test_prepare() must have been done before this call */ static int mmc_test_transfer(struct mmc_test_card *test, struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write) { int ret, i; unsigned long flags; if (write) { for (i = 0;i < blocks * blksz;i++) buffer[i] = i; test->scratch[i] = i; } else { memset(test->scratch, 0, BUFFER_SIZE); } local_irq_save(flags); sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); local_irq_restore(flags); ret = mmc_test_set_blksize(test, blksz); if (ret) return ret; ret = mmc_test_transfer(test, write, buffer, addr, blocks, blksz); ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr, blocks, blksz, write); if (ret) return ret; if (write) { int sectors; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; Loading @@ -253,9 +420,9 @@ static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, memset(test->buffer, 0, sectors * 512); for (i = 0;i < sectors;i++) { ret = mmc_test_transfer(test, 0, ret = mmc_test_buffer_transfer(test, test->buffer + i * 512, addr + i * 512, 1, 512); dev_addr + i * 512, 512, 0); if (ret) return ret; } Loading @@ -270,8 +437,11 @@ static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, return RESULT_FAIL; } } else { local_irq_save(flags); sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); local_irq_restore(flags); for (i = 0;i < blocks * blksz;i++) { if (buffer[i] != (u8)i) if (test->scratch[i] != (u8)i) return RESULT_FAIL; } } Loading @@ -279,26 +449,6 @@ static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, return 0; } static int mmc_test_cleanup_verify(struct mmc_test_card *test) { int ret, i; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; memset(test->buffer, 0, BUFFER_SIZE); for (i = 0;i < BUFFER_SIZE / 512;i++) { ret = mmc_test_transfer(test, 1, test->buffer + i * 512, i * 512, 1, 512); if (ret) return ret; } return 0; } /*******************************************************************/ /* Tests */ /*******************************************************************/ Loading @@ -314,12 +464,15 @@ struct mmc_test_case { static int mmc_test_basic_write(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; ret = mmc_test_transfer(test, 1, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; Loading @@ -329,12 +482,15 @@ static int mmc_test_basic_write(struct mmc_test_card *test) static int mmc_test_basic_read(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; ret = mmc_test_transfer(test, 0, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; Loading @@ -344,8 +500,11 @@ static int mmc_test_basic_read(struct mmc_test_card *test) static int mmc_test_verify_write(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; Loading @@ -355,8 +514,11 @@ static int mmc_test_verify_write(struct mmc_test_card *test) static int mmc_test_verify_read(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); if (ret) return ret; Loading @@ -367,6 +529,7 @@ static int mmc_test_multi_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; Loading @@ -379,8 +542,9 @@ static int mmc_test_multi_write(struct mmc_test_card *test) if (size < 1024) return RESULT_UNSUP_HOST; ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, size / 512, 512); sg_init_one(&sg, test->buffer, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); if (ret) return ret; Loading @@ -391,6 +555,7 @@ static int mmc_test_multi_read(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; Loading @@ -403,8 +568,9 @@ static int mmc_test_multi_read(struct mmc_test_card *test) if (size < 1024) return RESULT_UNSUP_HOST; ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, size / 512, 512); sg_init_one(&sg, test->buffer, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); if (ret) return ret; Loading @@ -414,13 +580,14 @@ static int mmc_test_multi_read(struct mmc_test_card *test) static int mmc_test_pow2_write(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.write_partial) return RESULT_UNSUP_CARD; for (i = 1; i < 512;i <<= 1) { ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1); if (ret) return ret; } Loading @@ -431,13 +598,14 @@ static int mmc_test_pow2_write(struct mmc_test_card *test) static int mmc_test_pow2_read(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.read_partial) return RESULT_UNSUP_CARD; for (i = 1; i < 512;i <<= 1) { ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0); if (ret) return ret; } Loading @@ -448,13 +616,14 @@ static int mmc_test_pow2_read(struct mmc_test_card *test) static int mmc_test_weird_write(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.write_partial) return RESULT_UNSUP_CARD; for (i = 3; i < 512;i += 7) { ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1); if (ret) return ret; } Loading @@ -465,13 +634,14 @@ static int mmc_test_weird_write(struct mmc_test_card *test) static int mmc_test_weird_read(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.read_partial) return RESULT_UNSUP_CARD; for (i = 3; i < 512;i += 7) { ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0); if (ret) return ret; } Loading @@ -482,10 +652,11 @@ static int mmc_test_weird_read(struct mmc_test_card *test) static int mmc_test_align_write(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 1, test->buffer + i, 0, 1, 512); sg_init_one(&sg, test->buffer + i, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; } Loading @@ -496,10 +667,11 @@ static int mmc_test_align_write(struct mmc_test_card *test) static int mmc_test_align_read(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 0, test->buffer + i, 0, 1, 512); sg_init_one(&sg, test->buffer + i, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); if (ret) return ret; } Loading @@ -511,6 +683,7 @@ static int mmc_test_align_multi_write(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; Loading @@ -524,8 +697,8 @@ static int mmc_test_align_multi_write(struct mmc_test_card *test) return RESULT_UNSUP_HOST; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 1, test->buffer + i, 0, size / 512, 512); sg_init_one(&sg, test->buffer + i, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); if (ret) return ret; } Loading @@ -537,6 +710,7 @@ static int mmc_test_align_multi_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; Loading @@ -550,8 +724,8 @@ static int mmc_test_align_multi_read(struct mmc_test_card *test) return RESULT_UNSUP_HOST; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 0, test->buffer + i, 0, size / 512, 512); sg_init_one(&sg, test->buffer + i, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); if (ret) return ret; } Loading @@ -567,7 +741,7 @@ static int mmc_test_xfersize_write(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 1, 512); ret = mmc_test_broken_transfer(test, 1, 512, 1); if (ret) return ret; Loading @@ -582,7 +756,7 @@ static int mmc_test_xfersize_read(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 1, 512); ret = mmc_test_broken_transfer(test, 1, 512, 0); if (ret) return ret; Loading @@ -600,7 +774,7 @@ static int mmc_test_multi_xfersize_write(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 2, 512); ret = mmc_test_broken_transfer(test, 2, 512, 1); if (ret) return ret; Loading @@ -618,7 +792,7 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 2, 512); ret = mmc_test_broken_transfer(test, 2, 512, 0); if (ret) return ret; Loading @@ -638,86 +812,86 @@ static const struct mmc_test_case mmc_test_cases[] = { { .name = "Basic write (with data verification)", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_verify_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Basic read (with data verification)", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_verify_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Multi-block write", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_multi_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Multi-block read", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_multi_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Power of two block writes", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_pow2_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Power of two block reads", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_pow2_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Weird sized block writes", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_weird_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Weird sized block reads", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_weird_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned write", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_align_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned read", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_align_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned multi-block write", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_align_multi_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned multi-block read", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_align_multi_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { Loading Loading
drivers/mmc/card/mmc_test.c +364 −190 Original line number Diff line number Diff line Loading @@ -26,13 +26,17 @@ struct mmc_test_card { struct mmc_card *card; u8 scratch[BUFFER_SIZE]; u8 *buffer; }; /*******************************************************************/ /* Helper functions */ /* General helper functions */ /*******************************************************************/ /* * Configure correct block size in card */ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) { struct mmc_command cmd; Loading @@ -48,117 +52,61 @@ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) return 0; } static int __mmc_test_transfer(struct mmc_test_card *test, int write, unsigned broken_xfer, u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz) /* * Fill in the mmc_request structure given a set of transfer parameters. */ static void mmc_test_prepare_mrq(struct mmc_test_card *test, struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write) { int ret, busy; struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; struct scatterlist sg; BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop); memset(&mrq, 0, sizeof(struct mmc_request)); mrq.cmd = &cmd; mrq.data = &data; memset(&cmd, 0, sizeof(struct mmc_command)); if (broken_xfer) { if (blocks > 1) { cmd.opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; } else { cmd.opcode = MMC_SEND_STATUS; } } else { if (blocks > 1) { cmd.opcode = write ? mrq->cmd->opcode = write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK; } else { cmd.opcode = write ? mrq->cmd->opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; } } if (broken_xfer && blocks == 1) cmd.arg = test->card->rca << 16; else cmd.arg = addr; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; mrq->cmd->arg = dev_addr; mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC; memset(&stop, 0, sizeof(struct mmc_command)); if (!broken_xfer && (blocks > 1)) { stop.opcode = MMC_STOP_TRANSMISSION; stop.arg = 0; stop.flags = MMC_RSP_R1B | MMC_CMD_AC; mrq.stop = &stop; if (blocks == 1) mrq->stop = NULL; else { mrq->stop->opcode = MMC_STOP_TRANSMISSION; mrq->stop->arg = 0; mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC; } memset(&data, 0, sizeof(struct mmc_data)); data.blksz = blksz; data.blocks = blocks; data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; data.sg = &sg; data.sg_len = 1; sg_init_one(&sg, buffer, blocks * blksz); mrq->data->blksz = blksz; mrq->data->blocks = blocks; mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; mrq->data->sg = sg; mrq->data->sg_len = sg_len; mmc_set_data_timeout(&data, test->card); mmc_wait_for_req(test->card->host, &mrq); ret = 0; if (broken_xfer) { if (!ret && cmd.error) ret = cmd.error; if (!ret && data.error == 0) ret = RESULT_FAIL; if (!ret && data.error != -ETIMEDOUT) ret = data.error; if (!ret && stop.error) ret = stop.error; if (blocks > 1) { if (!ret && data.bytes_xfered > blksz) ret = RESULT_FAIL; } else { if (!ret && data.bytes_xfered > 0) ret = RESULT_FAIL; } } else { if (!ret && cmd.error) ret = cmd.error; if (!ret && data.error) ret = data.error; if (!ret && stop.error) ret = stop.error; if (!ret && data.bytes_xfered != blocks * blksz) ret = RESULT_FAIL; mmc_set_data_timeout(mrq->data, test->card); } if (ret == -EINVAL) ret = RESULT_UNSUP_HOST; /* * Wait for the card to finish the busy state */ static int mmc_test_wait_busy(struct mmc_test_card *test) { int ret, busy; struct mmc_command cmd; busy = 0; do { int ret2; memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = MMC_SEND_STATUS; cmd.arg = test->card->rca << 16; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; ret2 = mmc_wait_for_cmd(test->card->host, &cmd, 0); if (ret2) ret = mmc_wait_for_cmd(test->card->host, &cmd, 0); if (ret) break; if (!busy && !(cmd.resp[0] & R1_READY_FOR_DATA)) { Loading @@ -172,14 +120,57 @@ static int __mmc_test_transfer(struct mmc_test_card *test, int write, return ret; } static int mmc_test_transfer(struct mmc_test_card *test, int write, u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz) /* * Transfer a single sector of kernel addressable data */ static int mmc_test_buffer_transfer(struct mmc_test_card *test, u8 *buffer, unsigned addr, unsigned blksz, int write) { return __mmc_test_transfer(test, write, 0, buffer, addr, blocks, blksz); int ret; struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; struct scatterlist sg; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; sg_init_one(&sg, buffer, blksz); mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write); mmc_wait_for_req(test->card->host, &mrq); if (cmd.error) return cmd.error; if (data.error) return data.error; ret = mmc_test_wait_busy(test); if (ret) return ret; return 0; } static int mmc_test_prepare_verify(struct mmc_test_card *test, int write) /*******************************************************************/ /* Test preparation and cleanup */ /*******************************************************************/ /* * Fill the first couple of sectors of the card with known data * so that bad reads/writes can be detected */ static int __mmc_test_prepare(struct mmc_test_card *test, int write) { int ret, i; Loading @@ -188,15 +179,14 @@ static int mmc_test_prepare_verify(struct mmc_test_card *test, int write) return ret; if (write) memset(test->buffer, 0xDF, BUFFER_SIZE); memset(test->buffer, 0xDF, 512); else { for (i = 0;i < BUFFER_SIZE;i++) for (i = 0;i < 512;i++) test->buffer[i] = i; } for (i = 0;i < BUFFER_SIZE / 512;i++) { ret = mmc_test_transfer(test, 1, test->buffer + i * 512, i * 512, 1, 512); ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); if (ret) return ret; } Loading @@ -204,41 +194,218 @@ static int mmc_test_prepare_verify(struct mmc_test_card *test, int write) return 0; } static int mmc_test_prepare_verify_write(struct mmc_test_card *test) static int mmc_test_prepare_write(struct mmc_test_card *test) { return mmc_test_prepare_verify(test, 1); return __mmc_test_prepare(test, 1); } static int mmc_test_prepare_verify_read(struct mmc_test_card *test) static int mmc_test_prepare_read(struct mmc_test_card *test) { return mmc_test_prepare_verify(test, 0); return __mmc_test_prepare(test, 0); } static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, u8 *buffer, unsigned addr, unsigned blocks, unsigned blksz) static int mmc_test_cleanup(struct mmc_test_card *test) { int ret, i, sectors; int ret, i; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; memset(test->buffer, 0, 512); for (i = 0;i < BUFFER_SIZE / 512;i++) { ret = mmc_test_buffer_transfer(test, test->buffer, i * 512, 512, 1); if (ret) return ret; } return 0; } /*******************************************************************/ /* Test execution helpers */ /*******************************************************************/ /* * It is assumed that the above preparation has been done. * Modifies the mmc_request to perform the "short transfer" tests */ static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test, struct mmc_request *mrq, int write) { BUG_ON(!mrq || !mrq->cmd || !mrq->data); if (mrq->data->blocks > 1) { mrq->cmd->opcode = write ? MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK; mrq->stop = NULL; } else { mrq->cmd->opcode = MMC_SEND_STATUS; mrq->cmd->arg = test->card->rca << 16; } } memset(test->buffer, 0, BUFFER_SIZE); /* * Checks that a normal transfer didn't have any errors */ static int mmc_test_check_result(struct mmc_test_card *test, struct mmc_request *mrq) { int ret; BUG_ON(!mrq || !mrq->cmd || !mrq->data); ret = 0; if (!ret && mrq->cmd->error) ret = mrq->cmd->error; if (!ret && mrq->data->error) ret = mrq->data->error; if (!ret && mrq->stop && mrq->stop->error) ret = mrq->stop->error; if (!ret && mrq->data->bytes_xfered != mrq->data->blocks * mrq->data->blksz) ret = RESULT_FAIL; if (ret == -EINVAL) ret = RESULT_UNSUP_HOST; return ret; } /* * Checks that a "short transfer" behaved as expected */ static int mmc_test_check_broken_result(struct mmc_test_card *test, struct mmc_request *mrq) { int ret; BUG_ON(!mrq || !mrq->cmd || !mrq->data); ret = 0; if (!ret && mrq->cmd->error) ret = mrq->cmd->error; if (!ret && mrq->data->error == 0) ret = RESULT_FAIL; if (!ret && mrq->data->error != -ETIMEDOUT) ret = mrq->data->error; if (!ret && mrq->stop && mrq->stop->error) ret = mrq->stop->error; if (mrq->data->blocks > 1) { if (!ret && mrq->data->bytes_xfered > mrq->data->blksz) ret = RESULT_FAIL; } else { if (!ret && mrq->data->bytes_xfered > 0) ret = RESULT_FAIL; } if (ret == -EINVAL) ret = RESULT_UNSUP_HOST; return ret; } /* * Tests a basic transfer with certain parameters */ static int mmc_test_simple_transfer(struct mmc_test_card *test, struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write) { struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr, blocks, blksz, write); mmc_wait_for_req(test->card->host, &mrq); mmc_test_wait_busy(test); return mmc_test_check_result(test, &mrq); } /* * Tests a transfer where the card will fail completely or partly */ static int mmc_test_broken_transfer(struct mmc_test_card *test, unsigned blocks, unsigned blksz, int write) { struct mmc_request mrq; struct mmc_command cmd; struct mmc_command stop; struct mmc_data data; struct scatterlist sg; memset(&mrq, 0, sizeof(struct mmc_request)); memset(&cmd, 0, sizeof(struct mmc_command)); memset(&data, 0, sizeof(struct mmc_data)); memset(&stop, 0, sizeof(struct mmc_command)); mrq.cmd = &cmd; mrq.data = &data; mrq.stop = &stop; sg_init_one(&sg, test->buffer, blocks * blksz); mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write); mmc_test_prepare_broken_mrq(test, &mrq, write); mmc_wait_for_req(test->card->host, &mrq); mmc_test_wait_busy(test); return mmc_test_check_broken_result(test, &mrq); } /* * Does a complete transfer test where data is also validated * * Note: mmc_test_prepare() must have been done before this call */ static int mmc_test_transfer(struct mmc_test_card *test, struct scatterlist *sg, unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write) { int ret, i; unsigned long flags; if (write) { for (i = 0;i < blocks * blksz;i++) buffer[i] = i; test->scratch[i] = i; } else { memset(test->scratch, 0, BUFFER_SIZE); } local_irq_save(flags); sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); local_irq_restore(flags); ret = mmc_test_set_blksize(test, blksz); if (ret) return ret; ret = mmc_test_transfer(test, write, buffer, addr, blocks, blksz); ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr, blocks, blksz, write); if (ret) return ret; if (write) { int sectors; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; Loading @@ -253,9 +420,9 @@ static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, memset(test->buffer, 0, sectors * 512); for (i = 0;i < sectors;i++) { ret = mmc_test_transfer(test, 0, ret = mmc_test_buffer_transfer(test, test->buffer + i * 512, addr + i * 512, 1, 512); dev_addr + i * 512, 512, 0); if (ret) return ret; } Loading @@ -270,8 +437,11 @@ static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, return RESULT_FAIL; } } else { local_irq_save(flags); sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); local_irq_restore(flags); for (i = 0;i < blocks * blksz;i++) { if (buffer[i] != (u8)i) if (test->scratch[i] != (u8)i) return RESULT_FAIL; } } Loading @@ -279,26 +449,6 @@ static int mmc_test_verified_transfer(struct mmc_test_card *test, int write, return 0; } static int mmc_test_cleanup_verify(struct mmc_test_card *test) { int ret, i; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; memset(test->buffer, 0, BUFFER_SIZE); for (i = 0;i < BUFFER_SIZE / 512;i++) { ret = mmc_test_transfer(test, 1, test->buffer + i * 512, i * 512, 1, 512); if (ret) return ret; } return 0; } /*******************************************************************/ /* Tests */ /*******************************************************************/ Loading @@ -314,12 +464,15 @@ struct mmc_test_case { static int mmc_test_basic_write(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; ret = mmc_test_transfer(test, 1, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; Loading @@ -329,12 +482,15 @@ static int mmc_test_basic_write(struct mmc_test_card *test) static int mmc_test_basic_read(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_set_blksize(test, 512); if (ret) return ret; ret = mmc_test_transfer(test, 0, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; Loading @@ -344,8 +500,11 @@ static int mmc_test_basic_read(struct mmc_test_card *test) static int mmc_test_verify_write(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; Loading @@ -355,8 +514,11 @@ static int mmc_test_verify_write(struct mmc_test_card *test) static int mmc_test_verify_read(struct mmc_test_card *test) { int ret; struct scatterlist sg; ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, 512); sg_init_one(&sg, test->buffer, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); if (ret) return ret; Loading @@ -367,6 +529,7 @@ static int mmc_test_multi_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; Loading @@ -379,8 +542,9 @@ static int mmc_test_multi_write(struct mmc_test_card *test) if (size < 1024) return RESULT_UNSUP_HOST; ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, size / 512, 512); sg_init_one(&sg, test->buffer, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); if (ret) return ret; Loading @@ -391,6 +555,7 @@ static int mmc_test_multi_read(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; Loading @@ -403,8 +568,9 @@ static int mmc_test_multi_read(struct mmc_test_card *test) if (size < 1024) return RESULT_UNSUP_HOST; ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, size / 512, 512); sg_init_one(&sg, test->buffer, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); if (ret) return ret; Loading @@ -414,13 +580,14 @@ static int mmc_test_multi_read(struct mmc_test_card *test) static int mmc_test_pow2_write(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.write_partial) return RESULT_UNSUP_CARD; for (i = 1; i < 512;i <<= 1) { ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1); if (ret) return ret; } Loading @@ -431,13 +598,14 @@ static int mmc_test_pow2_write(struct mmc_test_card *test) static int mmc_test_pow2_read(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.read_partial) return RESULT_UNSUP_CARD; for (i = 1; i < 512;i <<= 1) { ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0); if (ret) return ret; } Loading @@ -448,13 +616,14 @@ static int mmc_test_pow2_read(struct mmc_test_card *test) static int mmc_test_weird_write(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.write_partial) return RESULT_UNSUP_CARD; for (i = 3; i < 512;i += 7) { ret = mmc_test_verified_transfer(test, 1, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1); if (ret) return ret; } Loading @@ -465,13 +634,14 @@ static int mmc_test_weird_write(struct mmc_test_card *test) static int mmc_test_weird_read(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; if (!test->card->csd.read_partial) return RESULT_UNSUP_CARD; for (i = 3; i < 512;i += 7) { ret = mmc_test_verified_transfer(test, 0, test->buffer, 0, 1, i); sg_init_one(&sg, test->buffer, i); ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0); if (ret) return ret; } Loading @@ -482,10 +652,11 @@ static int mmc_test_weird_read(struct mmc_test_card *test) static int mmc_test_align_write(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 1, test->buffer + i, 0, 1, 512); sg_init_one(&sg, test->buffer + i, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1); if (ret) return ret; } Loading @@ -496,10 +667,11 @@ static int mmc_test_align_write(struct mmc_test_card *test) static int mmc_test_align_read(struct mmc_test_card *test) { int ret, i; struct scatterlist sg; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 0, test->buffer + i, 0, 1, 512); sg_init_one(&sg, test->buffer + i, 512); ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0); if (ret) return ret; } Loading @@ -511,6 +683,7 @@ static int mmc_test_align_multi_write(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; Loading @@ -524,8 +697,8 @@ static int mmc_test_align_multi_write(struct mmc_test_card *test) return RESULT_UNSUP_HOST; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 1, test->buffer + i, 0, size / 512, 512); sg_init_one(&sg, test->buffer + i, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); if (ret) return ret; } Loading @@ -537,6 +710,7 @@ static int mmc_test_align_multi_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; Loading @@ -550,8 +724,8 @@ static int mmc_test_align_multi_read(struct mmc_test_card *test) return RESULT_UNSUP_HOST; for (i = 1;i < 4;i++) { ret = mmc_test_verified_transfer(test, 0, test->buffer + i, 0, size / 512, 512); sg_init_one(&sg, test->buffer + i, size); ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); if (ret) return ret; } Loading @@ -567,7 +741,7 @@ static int mmc_test_xfersize_write(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 1, 512); ret = mmc_test_broken_transfer(test, 1, 512, 1); if (ret) return ret; Loading @@ -582,7 +756,7 @@ static int mmc_test_xfersize_read(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 1, 512); ret = mmc_test_broken_transfer(test, 1, 512, 0); if (ret) return ret; Loading @@ -600,7 +774,7 @@ static int mmc_test_multi_xfersize_write(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 1, 1, test->buffer, 0, 2, 512); ret = mmc_test_broken_transfer(test, 2, 512, 1); if (ret) return ret; Loading @@ -618,7 +792,7 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test) if (ret) return ret; ret = __mmc_test_transfer(test, 0, 1, test->buffer, 0, 2, 512); ret = mmc_test_broken_transfer(test, 2, 512, 0); if (ret) return ret; Loading @@ -638,86 +812,86 @@ static const struct mmc_test_case mmc_test_cases[] = { { .name = "Basic write (with data verification)", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_verify_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Basic read (with data verification)", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_verify_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Multi-block write", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_multi_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Multi-block read", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_multi_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Power of two block writes", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_pow2_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Power of two block reads", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_pow2_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Weird sized block writes", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_weird_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Weird sized block reads", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_weird_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned write", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_align_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned read", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_align_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned multi-block write", .prepare = mmc_test_prepare_verify_write, .prepare = mmc_test_prepare_write, .run = mmc_test_align_multi_write, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { .name = "Badly aligned multi-block read", .prepare = mmc_test_prepare_verify_read, .prepare = mmc_test_prepare_read, .run = mmc_test_align_multi_read, .cleanup = mmc_test_cleanup_verify, .cleanup = mmc_test_cleanup, }, { Loading