summaryrefslogtreecommitdiff
path: root/drivers/mmc/core/mmc_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/mmc_test.c')
-rw-r--r--drivers/mmc/core/mmc_test.c104
1 files changed, 61 insertions, 43 deletions
diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c
index 156d34b2ed4d..01d1e62c2ce7 100644
--- a/drivers/mmc/core/mmc_test.c
+++ b/drivers/mmc/core/mmc_test.c
@@ -180,20 +180,14 @@ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
return mmc_set_blocklen(test->card, size);
}
-static bool mmc_test_card_cmd23(struct mmc_card *card)
-{
- return mmc_card_mmc(card) ||
- (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT);
-}
-
static void mmc_test_prepare_sbc(struct mmc_test_card *test,
struct mmc_request *mrq, unsigned int blocks)
{
struct mmc_card *card = test->card;
- if (!mrq->sbc || !mmc_host_cmd23(card->host) ||
- !mmc_test_card_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) ||
- (card->quirks & MMC_QUIRK_BLK_NO_CMD23)) {
+ if (!mrq->sbc || !mmc_host_can_cmd23(card->host) ||
+ !mmc_card_can_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) ||
+ mmc_card_blk_no_cmd23(card)) {
mrq->sbc = NULL;
return;
}
@@ -592,14 +586,11 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
rate = mmc_test_rate(tot, &ts);
iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
- pr_info("%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
- "%llu.%09u seconds (%u kB/s, %u KiB/s, "
- "%u.%02u IOPS, sg_len %d)\n",
- mmc_hostname(test->card->host), count, sectors, count,
- sectors >> 1, (sectors & 1 ? ".5" : ""),
- (u64)ts.tv_sec, (u32)ts.tv_nsec,
- rate / 1000, rate / 1024, iops / 100, iops % 100,
- test->area.sg_len);
+ pr_info("%s: Transfer of %u x %u sectors (%u x %u%s KiB) took %ptSp seconds (%u kB/s, %u KiB/s, %u.%02u IOPS, sg_len %d)\n",
+ mmc_hostname(test->card->host), count, sectors, count,
+ sectors >> 1, (sectors & 1 ? ".5" : ""), &ts,
+ rate / 1000, rate / 1024, iops / 100, iops % 100,
+ test->area.sg_len);
mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
}
@@ -1510,7 +1501,7 @@ static int mmc_test_area_erase(struct mmc_test_card *test)
{
struct mmc_test_area *t = &test->area;
- if (!mmc_can_erase(test->card))
+ if (!mmc_card_can_erase(test->card))
return 0;
return mmc_erase(test->card, t->dev_addr, t->max_sz >> 9,
@@ -1746,10 +1737,10 @@ static int mmc_test_profile_trim_perf(struct mmc_test_card *test)
struct timespec64 ts1, ts2;
int ret;
- if (!mmc_can_trim(test->card))
+ if (!mmc_card_can_trim(test->card))
return RESULT_UNSUP_CARD;
- if (!mmc_can_erase(test->card))
+ if (!mmc_card_can_erase(test->card))
return RESULT_UNSUP_HOST;
for (sz = 512; sz < t->max_sz; sz <<= 1) {
@@ -1863,10 +1854,10 @@ static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test)
struct timespec64 ts1, ts2;
int ret;
- if (!mmc_can_trim(test->card))
+ if (!mmc_card_can_trim(test->card))
return RESULT_UNSUP_CARD;
- if (!mmc_can_erase(test->card))
+ if (!mmc_card_can_erase(test->card))
return RESULT_UNSUP_HOST;
for (sz = 512; sz <= t->max_sz; sz <<= 1) {
@@ -1904,7 +1895,7 @@ static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
}
static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
- unsigned long sz)
+ unsigned long sz, int secs, int force_retuning)
{
unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
unsigned int ssz;
@@ -1921,7 +1912,7 @@ static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
for (cnt = 0; cnt < UINT_MAX; cnt++) {
ktime_get_ts64(&ts2);
ts = timespec64_sub(ts2, ts1);
- if (ts.tv_sec >= 10)
+ if (ts.tv_sec >= secs)
break;
ea = mmc_test_rnd_num(range1);
if (ea == last_ea)
@@ -1929,6 +1920,8 @@ static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
last_ea = ea;
dev_addr = rnd_addr + test->card->pref_erase * ea +
ssz * mmc_test_rnd_num(range2);
+ if (force_retuning)
+ mmc_retune_needed(test->card->host);
ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
if (ret)
return ret;
@@ -1953,24 +1946,35 @@ static int mmc_test_random_perf(struct mmc_test_card *test, int write)
*/
if (write) {
next = rnd_next;
- ret = mmc_test_rnd_perf(test, write, 0, sz);
+ ret = mmc_test_rnd_perf(test, write, 0, sz, 10, 0);
if (ret)
return ret;
rnd_next = next;
}
- ret = mmc_test_rnd_perf(test, write, 1, sz);
+ ret = mmc_test_rnd_perf(test, write, 1, sz, 10, 0);
if (ret)
return ret;
}
sz = t->max_tfr;
if (write) {
next = rnd_next;
- ret = mmc_test_rnd_perf(test, write, 0, sz);
+ ret = mmc_test_rnd_perf(test, write, 0, sz, 10, 0);
if (ret)
return ret;
rnd_next = next;
}
- return mmc_test_rnd_perf(test, write, 1, sz);
+ return mmc_test_rnd_perf(test, write, 1, sz, 10, 0);
+}
+
+static int mmc_test_retuning(struct mmc_test_card *test)
+{
+ if (!mmc_can_retune(test->card->host)) {
+ pr_info("%s: No retuning - test skipped\n",
+ mmc_hostname(test->card->host));
+ return RESULT_UNSUP_HOST;
+ }
+
+ return mmc_test_rnd_perf(test, 0, 0, 8192, 30, 1);
}
/*
@@ -2101,7 +2105,7 @@ static int mmc_test_rw_multiple(struct mmc_test_card *test,
return 0;
/* prepare test area */
- if (mmc_can_erase(test->card) &&
+ if (mmc_card_can_erase(test->card) &&
tdata->prepare & MMC_TEST_PREP_ERASE) {
ret = mmc_erase(test->card, dev_addr,
size / 512, test->card->erase_arg);
@@ -2377,7 +2381,7 @@ static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
512, write);
if (use_sbc && t->blocks > 1 && !mrq->sbc) {
- ret = mmc_host_cmd23(host) ?
+ ret = mmc_host_can_cmd23(host) ?
RESULT_UNSUP_CARD :
RESULT_UNSUP_HOST;
goto out_free;
@@ -2921,6 +2925,14 @@ static const struct mmc_test_case mmc_test_cases[] = {
.run = mmc_test_cmds_during_write_cmd23_nonblock,
.cleanup = mmc_test_area_cleanup,
},
+
+ {
+ .name = "Re-tuning reliability",
+ .prepare = mmc_test_area_prepare,
+ .run = mmc_test_retuning,
+ .cleanup = mmc_test_area_cleanup,
+ },
+
};
static DEFINE_MUTEX(mmc_test_lock);
@@ -3045,7 +3057,7 @@ static LIST_HEAD(mmc_test_file_test);
static int mtf_test_show(struct seq_file *sf, void *data)
{
- struct mmc_card *card = (struct mmc_card *)sf->private;
+ struct mmc_card *card = sf->private;
struct mmc_test_general_result *gr;
mutex_lock(&mmc_test_lock);
@@ -3059,10 +3071,9 @@ static int mtf_test_show(struct seq_file *sf, void *data)
seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
list_for_each_entry(tr, &gr->tr_lst, link) {
- seq_printf(sf, "%u %d %llu.%09u %u %u.%02u\n",
- tr->count, tr->sectors,
- (u64)tr->ts.tv_sec, (u32)tr->ts.tv_nsec,
- tr->rate, tr->iops / 100, tr->iops % 100);
+ seq_printf(sf, "%u %d %ptSp %u %u.%02u\n",
+ tr->count, tr->sectors, &tr->ts, tr->rate,
+ tr->iops / 100, tr->iops % 100);
}
}
@@ -3079,8 +3090,8 @@ static int mtf_test_open(struct inode *inode, struct file *file)
static ssize_t mtf_test_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
- struct seq_file *sf = (struct seq_file *)file->private_data;
- struct mmc_card *card = (struct mmc_card *)sf->private;
+ struct seq_file *sf = file->private_data;
+ struct mmc_card *card = sf->private;
struct mmc_test_card *test;
long testcase;
int ret;
@@ -3104,13 +3115,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
#ifdef CONFIG_HIGHMEM
test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
+ if (!test->highmem) {
+ count = -ENOMEM;
+ goto free_test_buffer;
+ }
#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);
@@ -3118,6 +3129,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
#ifdef CONFIG_HIGHMEM
__free_pages(test->highmem, BUFFER_ORDER);
+free_test_buffer:
#endif
kfree(test->buffer);
kfree(test);
@@ -3196,12 +3208,12 @@ static int mmc_test_register_dbgfs_file(struct mmc_card *card)
mutex_lock(&mmc_test_lock);
- ret = __mmc_test_register_dbgfs_file(card, "test", S_IWUSR | S_IRUGO,
+ ret = __mmc_test_register_dbgfs_file(card, "test", 0644,
&mmc_test_fops_test);
if (ret)
goto err;
- ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO,
+ ret = __mmc_test_register_dbgfs_file(card, "testlist", 0444,
&mtf_testlist_fops);
if (ret)
goto err;
@@ -3219,6 +3231,12 @@ static int mmc_test_probe(struct mmc_card *card)
if (!mmc_card_mmc(card) && !mmc_card_sd(card))
return -ENODEV;
+ if (mmc_card_ult_capacity(card)) {
+ pr_info("%s: mmc-test currently UNSUPPORTED for SDUC\n",
+ mmc_hostname(card->host));
+ return -EOPNOTSUPP;
+ }
+
ret = mmc_test_register_dbgfs_file(card);
if (ret)
return ret;