mmc: card: Add eMMC4.5 write packed commands unit-tests
Expose the following packed commands tests: - Test the write packed commands list preparation - Simulate a returned error code - Send an invalid packed command to the card Change-Id: I23a15f94571da3ff9553a342dc37e1a8de6827c6 Signed-off-by: Lee Susman <lsusman@codeaurora.org> Signed-off-by: Maya Erez <merez@codeaurora.org> Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
This commit is contained in:
parent
8a0840d289
commit
fececf257d
5 changed files with 1607 additions and 11 deletions
|
@ -68,13 +68,3 @@ config MMC_TEST
|
|||
|
||||
This driver is only of interest to those developing or
|
||||
testing a host driver. Most people should say N here.
|
||||
|
||||
config MMC_BLOCK_TEST
|
||||
tristate "MMC block test"
|
||||
depends on MMC_BLOCK && IOSCHED_TEST
|
||||
help
|
||||
MMC block test can be used with test iosched to test the MMC block
|
||||
device.
|
||||
Currently used to test eMMC 4.5 features (packed commands, sanitize,
|
||||
BKOPs).
|
||||
|
||||
|
|
|
@ -8,3 +8,4 @@ obj-$(CONFIG_MMC_TEST) += mmc_test.o
|
|||
|
||||
obj-$(CONFIG_SDIO_UART) += sdio_uart.o
|
||||
|
||||
obj-$(CONFIG_MMC_BLOCK_TEST) += mmc_block_test.o
|
||||
|
|
|
@ -1742,6 +1742,64 @@ void mmc_blk_init_packed_statistics(struct mmc_card *card)
|
|||
}
|
||||
EXPORT_SYMBOL(mmc_blk_init_packed_statistics);
|
||||
|
||||
void print_mmc_packing_stats(struct mmc_card *card)
|
||||
{
|
||||
int i;
|
||||
int max_num_of_packed_reqs = 0;
|
||||
|
||||
if ((!card) || (!card->wr_pack_stats.packing_events))
|
||||
return;
|
||||
|
||||
max_num_of_packed_reqs = card->ext_csd.max_packed_writes;
|
||||
|
||||
spin_lock(&card->wr_pack_stats.lock);
|
||||
|
||||
pr_info("%s: write packing statistics:\n",
|
||||
mmc_hostname(card->host));
|
||||
|
||||
for (i = 1 ; i <= max_num_of_packed_reqs ; ++i) {
|
||||
if (card->wr_pack_stats.packing_events[i] != 0)
|
||||
pr_info("%s: Packed %d reqs - %d times\n",
|
||||
mmc_hostname(card->host), i,
|
||||
card->wr_pack_stats.packing_events[i]);
|
||||
}
|
||||
|
||||
pr_info("%s: stopped packing due to the following reasons:\n",
|
||||
mmc_hostname(card->host));
|
||||
|
||||
if (card->wr_pack_stats.pack_stop_reason[EXCEEDS_SEGMENTS])
|
||||
pr_info("%s: %d times: exceedmax num of segments\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[EXCEEDS_SEGMENTS]);
|
||||
if (card->wr_pack_stats.pack_stop_reason[EXCEEDS_SECTORS])
|
||||
pr_info("%s: %d times: exceeding the max num of sectors\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[EXCEEDS_SECTORS]);
|
||||
if (card->wr_pack_stats.pack_stop_reason[WRONG_DATA_DIR])
|
||||
pr_info("%s: %d times: wrong data direction\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[WRONG_DATA_DIR]);
|
||||
if (card->wr_pack_stats.pack_stop_reason[FLUSH_OR_DISCARD])
|
||||
pr_info("%s: %d times: flush or discard\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[FLUSH_OR_DISCARD]);
|
||||
if (card->wr_pack_stats.pack_stop_reason[EMPTY_QUEUE])
|
||||
pr_info("%s: %d times: empty queue\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[EMPTY_QUEUE]);
|
||||
if (card->wr_pack_stats.pack_stop_reason[REL_WRITE])
|
||||
pr_info("%s: %d times: rel write\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[REL_WRITE]);
|
||||
if (card->wr_pack_stats.pack_stop_reason[THRESHOLD])
|
||||
pr_info("%s: %d times: Threshold\n",
|
||||
mmc_hostname(card->host),
|
||||
card->wr_pack_stats.pack_stop_reason[THRESHOLD]);
|
||||
|
||||
spin_unlock(&card->wr_pack_stats.lock);
|
||||
}
|
||||
EXPORT_SYMBOL(print_mmc_packing_stats);
|
||||
|
||||
static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
|
||||
{
|
||||
struct request_queue *q = mq->queue;
|
||||
|
@ -1960,7 +2018,18 @@ static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,
|
|||
brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
|
||||
|
||||
mqrq->mmc_active.mrq = &brq->mrq;
|
||||
mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
|
||||
|
||||
/*
|
||||
* This is intended for packed commands tests usage - in case these
|
||||
* functions are not in use the respective pointers are NULL
|
||||
*/
|
||||
if (mq->err_check_fn)
|
||||
mqrq->mmc_active.err_check = mq->err_check_fn;
|
||||
else
|
||||
mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
|
||||
|
||||
if (mq->packed_test_fn)
|
||||
mq->packed_test_fn(mq->queue, mqrq);
|
||||
|
||||
mmc_queue_bounce_pre(mqrq);
|
||||
}
|
||||
|
|
1532
drivers/mmc/card/mmc_block_test.c
Normal file
1532
drivers/mmc/card/mmc_block_test.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -61,6 +61,8 @@ struct mmc_queue {
|
|||
bool wr_packing_enabled;
|
||||
int num_of_potential_packed_wr_reqs;
|
||||
int num_wr_reqs_to_start_packing;
|
||||
int (*err_check_fn) (struct mmc_card *, struct mmc_async_req *);
|
||||
void (*packed_test_fn) (struct request_queue *, struct mmc_queue_req *);
|
||||
};
|
||||
|
||||
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
|
||||
|
@ -79,4 +81,6 @@ extern void mmc_packed_clean(struct mmc_queue *);
|
|||
|
||||
extern int mmc_access_rpmb(struct mmc_queue *);
|
||||
|
||||
extern void print_mmc_packing_stats(struct mmc_card *card);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue