aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@nokia.com>2011-02-08 06:41:02 -0500
committerChris Ball <cjb@laptop.org>2011-03-15 13:48:42 -0400
commitb6056d12342f936256cbf64c86459af06f11cd5e (patch)
treeab033f6d6d53f29a5f5953cb77de333bf229ea24 /drivers/mmc/card
parent0532ff6358ae00615cfba7212f5075356b437c66 (diff)
mmc: mmc_test: add tests to measure random I/O operations per second
Existing performance tests measure single or sequential I/O speed. Add two random I/O tests: 33. Random read performance by transfer size 34. Random write performance by transfer size Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/mmc_test.c139
1 files changed, 128 insertions, 11 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index ec6060c06ce8..d1aa57a4d058 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -88,6 +88,7 @@ struct mmc_test_area {
88 * @sectors: amount of sectors to check in one group 88 * @sectors: amount of sectors to check in one group
89 * @ts: time values of transfer 89 * @ts: time values of transfer
90 * @rate: calculated transfer rate 90 * @rate: calculated transfer rate
91 * @iops: I/O operations per second (times 100)
91 */ 92 */
92struct mmc_test_transfer_result { 93struct mmc_test_transfer_result {
93 struct list_head link; 94 struct list_head link;
@@ -95,6 +96,7 @@ struct mmc_test_transfer_result {
95 unsigned int sectors; 96 unsigned int sectors;
96 struct timespec ts; 97 struct timespec ts;
97 unsigned int rate; 98 unsigned int rate;
99 unsigned int iops;
98}; 100};
99 101
100/** 102/**
@@ -495,7 +497,7 @@ static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts)
495 */ 497 */
496static void mmc_test_save_transfer_result(struct mmc_test_card *test, 498static void mmc_test_save_transfer_result(struct mmc_test_card *test,
497 unsigned int count, unsigned int sectors, struct timespec ts, 499 unsigned int count, unsigned int sectors, struct timespec ts,
498 unsigned int rate) 500 unsigned int rate, unsigned int iops)
499{ 501{
500 struct mmc_test_transfer_result *tr; 502 struct mmc_test_transfer_result *tr;
501 503
@@ -510,6 +512,7 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test,
510 tr->sectors = sectors; 512 tr->sectors = sectors;
511 tr->ts = ts; 513 tr->ts = ts;
512 tr->rate = rate; 514 tr->rate = rate;
515 tr->iops = iops;
513 516
514 list_add_tail(&tr->link, &test->gr->tr_lst); 517 list_add_tail(&tr->link, &test->gr->tr_lst);
515} 518}
@@ -520,20 +523,22 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test,
520static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes, 523static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
521 struct timespec *ts1, struct timespec *ts2) 524 struct timespec *ts1, struct timespec *ts2)
522{ 525{
523 unsigned int rate, sectors = bytes >> 9; 526 unsigned int rate, iops, sectors = bytes >> 9;
524 struct timespec ts; 527 struct timespec ts;
525 528
526 ts = timespec_sub(*ts2, *ts1); 529 ts = timespec_sub(*ts2, *ts1);
527 530
528 rate = mmc_test_rate(bytes, &ts); 531 rate = mmc_test_rate(bytes, &ts);
532 iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
529 533
530 printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu " 534 printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
531 "seconds (%u kB/s, %u KiB/s)\n", 535 "seconds (%u kB/s, %u KiB/s, %u.%02u IOPS)\n",
532 mmc_hostname(test->card->host), sectors, sectors >> 1, 536 mmc_hostname(test->card->host), sectors, sectors >> 1,
533 (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec, 537 (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec,
534 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024); 538 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024,
539 iops / 100, iops % 100);
535 540
536 mmc_test_save_transfer_result(test, 1, sectors, ts, rate); 541 mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops);
537} 542}
538 543
539/* 544/*
@@ -543,22 +548,24 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
543 unsigned int count, struct timespec *ts1, 548 unsigned int count, struct timespec *ts1,
544 struct timespec *ts2) 549 struct timespec *ts2)
545{ 550{
546 unsigned int rate, sectors = bytes >> 9; 551 unsigned int rate, iops, sectors = bytes >> 9;
547 uint64_t tot = bytes * count; 552 uint64_t tot = bytes * count;
548 struct timespec ts; 553 struct timespec ts;
549 554
550 ts = timespec_sub(*ts2, *ts1); 555 ts = timespec_sub(*ts2, *ts1);
551 556
552 rate = mmc_test_rate(tot, &ts); 557 rate = mmc_test_rate(tot, &ts);
558 iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
553 559
554 printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " 560 printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
555 "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n", 561 "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
562 "%u.%02u IOPS)\n",
556 mmc_hostname(test->card->host), count, sectors, count, 563 mmc_hostname(test->card->host), count, sectors, count,
557 sectors >> 1, (sectors & 1 ? ".5" : ""), 564 sectors >> 1, (sectors & 1 ? ".5" : ""),
558 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, 565 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
559 rate / 1000, rate / 1024); 566 rate / 1000, rate / 1024, iops / 100, iops % 100);
560 567
561 mmc_test_save_transfer_result(test, count, sectors, ts, rate); 568 mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
562} 569}
563 570
564/* 571/*
@@ -1768,6 +1775,102 @@ static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test)
1768 return 0; 1775 return 0;
1769} 1776}
1770 1777
1778static unsigned int rnd_next = 1;
1779
1780static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
1781{
1782 uint64_t r;
1783
1784 rnd_next = rnd_next * 1103515245 + 12345;
1785 r = (rnd_next >> 16) & 0x7fff;
1786 return (r * rnd_cnt) >> 15;
1787}
1788
1789static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
1790 unsigned long sz)
1791{
1792 unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
1793 unsigned int ssz;
1794 struct timespec ts1, ts2, ts;
1795 int ret;
1796
1797 ssz = sz >> 9;
1798
1799 rnd_addr = mmc_test_capacity(test->card) / 4;
1800 range1 = rnd_addr / test->card->pref_erase;
1801 range2 = range1 / ssz;
1802
1803 getnstimeofday(&ts1);
1804 for (cnt = 0; cnt < UINT_MAX; cnt++) {
1805 getnstimeofday(&ts2);
1806 ts = timespec_sub(ts2, ts1);
1807 if (ts.tv_sec >= 10)
1808 break;
1809 ea = mmc_test_rnd_num(range1);
1810 if (ea == last_ea)
1811 ea -= 1;
1812 last_ea = ea;
1813 dev_addr = rnd_addr + test->card->pref_erase * ea +
1814 ssz * mmc_test_rnd_num(range2);
1815 ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
1816 if (ret)
1817 return ret;
1818 }
1819 if (print)
1820 mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
1821 return 0;
1822}
1823
1824static int mmc_test_random_perf(struct mmc_test_card *test, int write)
1825{
1826 unsigned int next;
1827 unsigned long sz;
1828 int ret;
1829
1830 for (sz = 512; sz < test->area.max_tfr; sz <<= 1) {
1831 /*
1832 * When writing, try to get more consistent results by running
1833 * the test twice with exactly the same I/O but outputting the
1834 * results only for the 2nd run.
1835 */
1836 if (write) {
1837 next = rnd_next;
1838 ret = mmc_test_rnd_perf(test, write, 0, sz);
1839 if (ret)
1840 return ret;
1841 rnd_next = next;
1842 }
1843 ret = mmc_test_rnd_perf(test, write, 1, sz);
1844 if (ret)
1845 return ret;
1846 }
1847 sz = test->area.max_tfr;
1848 if (write) {
1849 next = rnd_next;
1850 ret = mmc_test_rnd_perf(test, write, 0, sz);
1851 if (ret)
1852 return ret;
1853 rnd_next = next;
1854 }
1855 return mmc_test_rnd_perf(test, write, 1, sz);
1856}
1857
1858/*
1859 * Random read performance by transfer size.
1860 */
1861static int mmc_test_random_read_perf(struct mmc_test_card *test)
1862{
1863 return mmc_test_random_perf(test, 0);
1864}
1865
1866/*
1867 * Random write performance by transfer size.
1868 */
1869static int mmc_test_random_write_perf(struct mmc_test_card *test)
1870{
1871 return mmc_test_random_perf(test, 1);
1872}
1873
1771static const struct mmc_test_case mmc_test_cases[] = { 1874static const struct mmc_test_case mmc_test_cases[] = {
1772 { 1875 {
1773 .name = "Basic write (no data verification)", 1876 .name = "Basic write (no data verification)",
@@ -2007,6 +2110,20 @@ static const struct mmc_test_case mmc_test_cases[] = {
2007 .cleanup = mmc_test_area_cleanup, 2110 .cleanup = mmc_test_area_cleanup,
2008 }, 2111 },
2009 2112
2113 {
2114 .name = "Random read performance by transfer size",
2115 .prepare = mmc_test_area_prepare,
2116 .run = mmc_test_random_read_perf,
2117 .cleanup = mmc_test_area_cleanup,
2118 },
2119
2120 {
2121 .name = "Random write performance by transfer size",
2122 .prepare = mmc_test_area_prepare,
2123 .run = mmc_test_random_write_perf,
2124 .cleanup = mmc_test_area_cleanup,
2125 },
2126
2010}; 2127};
2011 2128
2012static DEFINE_MUTEX(mmc_test_lock); 2129static DEFINE_MUTEX(mmc_test_lock);
@@ -2150,11 +2267,11 @@ static int mtf_test_show(struct seq_file *sf, void *data)
2150 seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result); 2267 seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
2151 2268
2152 list_for_each_entry(tr, &gr->tr_lst, link) { 2269 list_for_each_entry(tr, &gr->tr_lst, link) {
2153 seq_printf(sf, "%u %d %lu.%09lu %u\n", 2270 seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n",
2154 tr->count, tr->sectors, 2271 tr->count, tr->sectors,
2155 (unsigned long)tr->ts.tv_sec, 2272 (unsigned long)tr->ts.tv_sec,
2156 (unsigned long)tr->ts.tv_nsec, 2273 (unsigned long)tr->ts.tv_nsec,
2157 tr->rate); 2274 tr->rate, tr->iops / 100, tr->iops % 100);
2158 } 2275 }
2159 } 2276 }
2160 2277