aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2011-07-01 12:55:27 -0400
committerChris Ball <cjb@laptop.org>2011-07-20 17:21:12 -0400
commitbf043330362b1ccb0c0611b8fc394e06ba8498b0 (patch)
tree487ce7a117c16e63d6d49cb74df21d7fdf3ce03f /drivers/mmc/card
parent9f9c4180f88d127e2bb83913d80750a8fbdb8f3e (diff)
mmc: mmc_test: test to measure how sg_len affect performance
Add a test that measures how the mmc bandwidth depends on the numbers of sg elements in the sg list. The transfer size if fixed and sg length goes from a few up to 512. The purpose is to measure overhead caused by multiple sg elements. Signed-off-by: Per Forlin <per.forlin@linaro.org> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Venkatraman S <svenkatr@ti.com> Tested-by: Sourav Poddar <sourav.poddar@ti.com> Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/card')
-rw-r--r--drivers/mmc/card/mmc_test.c151
1 files changed, 139 insertions, 12 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 51031a54470..006a5e9f8ab 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -155,6 +155,7 @@ enum mmc_test_prep_media {
155}; 155};
156 156
157struct mmc_test_multiple_rw { 157struct mmc_test_multiple_rw {
158 unsigned int *sg_len;
158 unsigned int *bs; 159 unsigned int *bs;
159 unsigned int len; 160 unsigned int len;
160 unsigned int size; 161 unsigned int size;
@@ -387,21 +388,26 @@ out_free:
387 * Map memory into a scatterlist. Optionally allow the same memory to be 388 * Map memory into a scatterlist. Optionally allow the same memory to be
388 * mapped more than once. 389 * mapped more than once.
389 */ 390 */
390static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, 391static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long size,
391 struct scatterlist *sglist, int repeat, 392 struct scatterlist *sglist, int repeat,
392 unsigned int max_segs, unsigned int max_seg_sz, 393 unsigned int max_segs, unsigned int max_seg_sz,
393 unsigned int *sg_len) 394 unsigned int *sg_len, int min_sg_len)
394{ 395{
395 struct scatterlist *sg = NULL; 396 struct scatterlist *sg = NULL;
396 unsigned int i; 397 unsigned int i;
398 unsigned long sz = size;
397 399
398 sg_init_table(sglist, max_segs); 400 sg_init_table(sglist, max_segs);
401 if (min_sg_len > max_segs)
402 min_sg_len = max_segs;
399 403
400 *sg_len = 0; 404 *sg_len = 0;
401 do { 405 do {
402 for (i = 0; i < mem->cnt; i++) { 406 for (i = 0; i < mem->cnt; i++) {
403 unsigned long len = PAGE_SIZE << mem->arr[i].order; 407 unsigned long len = PAGE_SIZE << mem->arr[i].order;
404 408
409 if (min_sg_len && (size / min_sg_len < len))
410 len = ALIGN(size / min_sg_len, 512);
405 if (len > sz) 411 if (len > sz)
406 len = sz; 412 len = sz;
407 if (len > max_seg_sz) 413 if (len > max_seg_sz)
@@ -574,11 +580,12 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
574 580
575 printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took " 581 printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
576 "%lu.%09lu seconds (%u kB/s, %u KiB/s, " 582 "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
577 "%u.%02u IOPS)\n", 583 "%u.%02u IOPS, sg_len %d)\n",
578 mmc_hostname(test->card->host), count, sectors, count, 584 mmc_hostname(test->card->host), count, sectors, count,
579 sectors >> 1, (sectors & 1 ? ".5" : ""), 585 sectors >> 1, (sectors & 1 ? ".5" : ""),
580 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec, 586 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
581 rate / 1000, rate / 1024, iops / 100, iops % 100); 587 rate / 1000, rate / 1024, iops / 100, iops % 100,
588 test->area.sg_len);
582 589
583 mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops); 590 mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
584} 591}
@@ -1412,7 +1419,7 @@ static int mmc_test_no_highmem(struct mmc_test_card *test)
1412 * Map sz bytes so that it can be transferred. 1419 * Map sz bytes so that it can be transferred.
1413 */ 1420 */
1414static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, 1421static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
1415 int max_scatter) 1422 int max_scatter, int min_sg_len)
1416{ 1423{
1417 struct mmc_test_area *t = &test->area; 1424 struct mmc_test_area *t = &test->area;
1418 int err; 1425 int err;
@@ -1425,7 +1432,7 @@ static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
1425 &t->sg_len); 1432 &t->sg_len);
1426 } else { 1433 } else {
1427 err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs, 1434 err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs,
1428 t->max_seg_sz, &t->sg_len); 1435 t->max_seg_sz, &t->sg_len, min_sg_len);
1429 } 1436 }
1430 if (err) 1437 if (err)
1431 printk(KERN_INFO "%s: Failed to map sg list\n", 1438 printk(KERN_INFO "%s: Failed to map sg list\n",
@@ -1451,7 +1458,7 @@ static int mmc_test_area_transfer(struct mmc_test_card *test,
1451static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz, 1458static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz,
1452 unsigned int dev_addr, int write, 1459 unsigned int dev_addr, int write,
1453 int max_scatter, int timed, int count, 1460 int max_scatter, int timed, int count,
1454 bool nonblock) 1461 bool nonblock, int min_sg_len)
1455{ 1462{
1456 struct timespec ts1, ts2; 1463 struct timespec ts1, ts2;
1457 int ret = 0; 1464 int ret = 0;
@@ -1474,7 +1481,7 @@ static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz,
1474 sz = max_tfr; 1481 sz = max_tfr;
1475 } 1482 }
1476 1483
1477 ret = mmc_test_area_map(test, sz, max_scatter); 1484 ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len);
1478 if (ret) 1485 if (ret)
1479 return ret; 1486 return ret;
1480 1487
@@ -1506,7 +1513,7 @@ static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
1506 int timed) 1513 int timed)
1507{ 1514{
1508 return mmc_test_area_io_seq(test, sz, dev_addr, write, max_scatter, 1515 return mmc_test_area_io_seq(test, sz, dev_addr, write, max_scatter,
1509 timed, 1, false); 1516 timed, 1, false, 0);
1510} 1517}
1511 1518
1512/* 1519/*
@@ -2084,7 +2091,8 @@ static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
2084 2091
2085static int mmc_test_rw_multiple(struct mmc_test_card *test, 2092static int mmc_test_rw_multiple(struct mmc_test_card *test,
2086 struct mmc_test_multiple_rw *tdata, 2093 struct mmc_test_multiple_rw *tdata,
2087 unsigned int reqsize, unsigned int size) 2094 unsigned int reqsize, unsigned int size,
2095 int min_sg_len)
2088{ 2096{
2089 unsigned int dev_addr; 2097 unsigned int dev_addr;
2090 struct mmc_test_area *t = &test->area; 2098 struct mmc_test_area *t = &test->area;
@@ -2121,7 +2129,7 @@ static int mmc_test_rw_multiple(struct mmc_test_card *test,
2121 /* Run test */ 2129 /* Run test */
2122 ret = mmc_test_area_io_seq(test, reqsize, dev_addr, 2130 ret = mmc_test_area_io_seq(test, reqsize, dev_addr,
2123 tdata->do_write, 0, 1, size / reqsize, 2131 tdata->do_write, 0, 1, size / reqsize,
2124 tdata->do_nonblock_req); 2132 tdata->do_nonblock_req, min_sg_len);
2125 if (ret) 2133 if (ret)
2126 goto err; 2134 goto err;
2127 2135
@@ -2146,7 +2154,22 @@ static int mmc_test_rw_multiple_size(struct mmc_test_card *test,
2146 } 2154 }
2147 2155
2148 for (i = 0 ; i < rw->len && ret == 0; i++) { 2156 for (i = 0 ; i < rw->len && ret == 0; i++) {
2149 ret = mmc_test_rw_multiple(test, rw, rw->bs[i], rw->size); 2157 ret = mmc_test_rw_multiple(test, rw, rw->bs[i], rw->size, 0);
2158 if (ret)
2159 break;
2160 }
2161 return ret;
2162}
2163
2164static int mmc_test_rw_multiple_sg_len(struct mmc_test_card *test,
2165 struct mmc_test_multiple_rw *rw)
2166{
2167 int ret = 0;
2168 int i;
2169
2170 for (i = 0 ; i < rw->len && ret == 0; i++) {
2171 ret = mmc_test_rw_multiple(test, rw, 512*1024, rw->size,
2172 rw->sg_len[i]);
2150 if (ret) 2173 if (ret)
2151 break; 2174 break;
2152 } 2175 }
@@ -2229,6 +2252,82 @@ static int mmc_test_profile_mult_read_nonblock_perf(struct mmc_test_card *test)
2229 return mmc_test_rw_multiple_size(test, &test_data); 2252 return mmc_test_rw_multiple_size(test, &test_data);
2230} 2253}
2231 2254
2255/*
2256 * Multiple blocking write 1 to 512 sg elements
2257 */
2258static int mmc_test_profile_sglen_wr_blocking_perf(struct mmc_test_card *test)
2259{
2260 unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
2261 1 << 7, 1 << 8, 1 << 9};
2262 struct mmc_test_multiple_rw test_data = {
2263 .sg_len = sg_len,
2264 .size = TEST_AREA_MAX_SIZE,
2265 .len = ARRAY_SIZE(sg_len),
2266 .do_write = true,
2267 .do_nonblock_req = false,
2268 .prepare = MMC_TEST_PREP_ERASE,
2269 };
2270
2271 return mmc_test_rw_multiple_sg_len(test, &test_data);
2272};
2273
2274/*
2275 * Multiple non-blocking write 1 to 512 sg elements
2276 */
2277static int mmc_test_profile_sglen_wr_nonblock_perf(struct mmc_test_card *test)
2278{
2279 unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
2280 1 << 7, 1 << 8, 1 << 9};
2281 struct mmc_test_multiple_rw test_data = {
2282 .sg_len = sg_len,
2283 .size = TEST_AREA_MAX_SIZE,
2284 .len = ARRAY_SIZE(sg_len),
2285 .do_write = true,
2286 .do_nonblock_req = true,
2287 .prepare = MMC_TEST_PREP_ERASE,
2288 };
2289
2290 return mmc_test_rw_multiple_sg_len(test, &test_data);
2291}
2292
2293/*
2294 * Multiple blocking read 1 to 512 sg elements
2295 */
2296static int mmc_test_profile_sglen_r_blocking_perf(struct mmc_test_card *test)
2297{
2298 unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
2299 1 << 7, 1 << 8, 1 << 9};
2300 struct mmc_test_multiple_rw test_data = {
2301 .sg_len = sg_len,
2302 .size = TEST_AREA_MAX_SIZE,
2303 .len = ARRAY_SIZE(sg_len),
2304 .do_write = false,
2305 .do_nonblock_req = false,
2306 .prepare = MMC_TEST_PREP_NONE,
2307 };
2308
2309 return mmc_test_rw_multiple_sg_len(test, &test_data);
2310}
2311
2312/*
2313 * Multiple non-blocking read 1 to 512 sg elements
2314 */
2315static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
2316{
2317 unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
2318 1 << 7, 1 << 8, 1 << 9};
2319 struct mmc_test_multiple_rw test_data = {
2320 .sg_len = sg_len,
2321 .size = TEST_AREA_MAX_SIZE,
2322 .len = ARRAY_SIZE(sg_len),
2323 .do_write = false,
2324 .do_nonblock_req = true,
2325 .prepare = MMC_TEST_PREP_NONE,
2326 };
2327
2328 return mmc_test_rw_multiple_sg_len(test, &test_data);
2329}
2330
2232static const struct mmc_test_case mmc_test_cases[] = { 2331static const struct mmc_test_case mmc_test_cases[] = {
2233 { 2332 {
2234 .name = "Basic write (no data verification)", 2333 .name = "Basic write (no data verification)",
@@ -2523,6 +2622,34 @@ static const struct mmc_test_case mmc_test_cases[] = {
2523 .run = mmc_test_profile_mult_read_nonblock_perf, 2622 .run = mmc_test_profile_mult_read_nonblock_perf,
2524 .cleanup = mmc_test_area_cleanup, 2623 .cleanup = mmc_test_area_cleanup,
2525 }, 2624 },
2625
2626 {
2627 .name = "Write performance blocking req 1 to 512 sg elems",
2628 .prepare = mmc_test_area_prepare,
2629 .run = mmc_test_profile_sglen_wr_blocking_perf,
2630 .cleanup = mmc_test_area_cleanup,
2631 },
2632
2633 {
2634 .name = "Write performance non-blocking req 1 to 512 sg elems",
2635 .prepare = mmc_test_area_prepare,
2636 .run = mmc_test_profile_sglen_wr_nonblock_perf,
2637 .cleanup = mmc_test_area_cleanup,
2638 },
2639
2640 {
2641 .name = "Read performance blocking req 1 to 512 sg elems",
2642 .prepare = mmc_test_area_prepare,
2643 .run = mmc_test_profile_sglen_r_blocking_perf,
2644 .cleanup = mmc_test_area_cleanup,
2645 },
2646
2647 {
2648 .name = "Read performance non-blocking req 1 to 512 sg elems",
2649 .prepare = mmc_test_area_prepare,
2650 .run = mmc_test_profile_sglen_r_nonblock_perf,
2651 .cleanup = mmc_test_area_cleanup,
2652 },
2526}; 2653};
2527 2654
2528static DEFINE_MUTEX(mmc_test_lock); 2655static DEFINE_MUTEX(mmc_test_lock);