diff options
Diffstat (limited to 'drivers/mmc/card/mmc_test.c')
-rw-r--r-- | drivers/mmc/card/mmc_test.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 197f3877b017..5dd8576b5c18 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | 17 | ||
18 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
19 | #include <linux/swap.h> /* For nr_free_buffer_pages() */ | ||
19 | 20 | ||
20 | #define RESULT_OK 0 | 21 | #define RESULT_OK 0 |
21 | #define RESULT_FAIL 1 | 22 | #define RESULT_FAIL 1 |
@@ -25,6 +26,12 @@ | |||
25 | #define BUFFER_ORDER 2 | 26 | #define BUFFER_ORDER 2 |
26 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) | 27 | #define BUFFER_SIZE (PAGE_SIZE << BUFFER_ORDER) |
27 | 28 | ||
29 | /* | ||
30 | * Limit the test area size to the maximum MMC HC erase group size. Note that | ||
31 | * the maximum SD allocation unit size is just 4MiB. | ||
32 | */ | ||
33 | #define TEST_AREA_MAX_SIZE (128 * 1024 * 1024) | ||
34 | |||
28 | /** | 35 | /** |
29 | * struct mmc_test_pages - pages allocated by 'alloc_pages()'. | 36 | * struct mmc_test_pages - pages allocated by 'alloc_pages()'. |
30 | * @page: first page in the allocation | 37 | * @page: first page in the allocation |
@@ -47,8 +54,8 @@ struct mmc_test_mem { | |||
47 | 54 | ||
48 | /** | 55 | /** |
49 | * struct mmc_test_area - information for performance tests. | 56 | * struct mmc_test_area - information for performance tests. |
50 | * @dev_addr: address on card at which to do performance tests | ||
51 | * @max_sz: test area size (in bytes) | 57 | * @max_sz: test area size (in bytes) |
58 | * @dev_addr: address on card at which to do performance tests | ||
52 | * @max_segs: maximum segments in scatterlist @sg | 59 | * @max_segs: maximum segments in scatterlist @sg |
53 | * @blocks: number of (512 byte) blocks currently mapped by @sg | 60 | * @blocks: number of (512 byte) blocks currently mapped by @sg |
54 | * @sg_len: length of currently mapped scatterlist @sg | 61 | * @sg_len: length of currently mapped scatterlist @sg |
@@ -56,8 +63,8 @@ struct mmc_test_mem { | |||
56 | * @sg: scatterlist | 63 | * @sg: scatterlist |
57 | */ | 64 | */ |
58 | struct mmc_test_area { | 65 | struct mmc_test_area { |
66 | unsigned long max_sz; | ||
59 | unsigned int dev_addr; | 67 | unsigned int dev_addr; |
60 | unsigned int max_sz; | ||
61 | unsigned int max_segs; | 68 | unsigned int max_segs; |
62 | unsigned int blocks; | 69 | unsigned int blocks; |
63 | unsigned int sg_len; | 70 | unsigned int sg_len; |
@@ -238,20 +245,19 @@ static void mmc_test_free_mem(struct mmc_test_mem *mem) | |||
238 | 245 | ||
239 | /* | 246 | /* |
240 | * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case | 247 | * Allocate a lot of memory, preferrably max_sz but at least min_sz. In case |
241 | * there isn't much memory do not exceed 1/16th total RAM. | 248 | * there isn't much memory do not exceed 1/16th total lowmem pages. |
242 | */ | 249 | */ |
243 | static struct mmc_test_mem *mmc_test_alloc_mem(unsigned int min_sz, | 250 | static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz, |
244 | unsigned int max_sz) | 251 | unsigned long max_sz) |
245 | { | 252 | { |
246 | unsigned int max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE); | 253 | unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE); |
247 | unsigned int min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE); | 254 | unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE); |
248 | unsigned int page_cnt = 0; | 255 | unsigned long page_cnt = 0; |
256 | unsigned long limit = nr_free_buffer_pages() >> 4; | ||
249 | struct mmc_test_mem *mem; | 257 | struct mmc_test_mem *mem; |
250 | struct sysinfo si; | ||
251 | 258 | ||
252 | si_meminfo(&si); | 259 | if (max_page_cnt > limit) |
253 | if (max_page_cnt > si.totalram >> 4) | 260 | max_page_cnt = limit; |
254 | max_page_cnt = si.totalram >> 4; | ||
255 | if (max_page_cnt < min_page_cnt) | 261 | if (max_page_cnt < min_page_cnt) |
256 | max_page_cnt = min_page_cnt; | 262 | max_page_cnt = min_page_cnt; |
257 | 263 | ||
@@ -270,7 +276,7 @@ static struct mmc_test_mem *mmc_test_alloc_mem(unsigned int min_sz, | |||
270 | gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN | | 276 | gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN | |
271 | __GFP_NORETRY; | 277 | __GFP_NORETRY; |
272 | 278 | ||
273 | order = get_order(page_cnt << PAGE_SHIFT); | 279 | order = get_order(max_page_cnt << PAGE_SHIFT); |
274 | while (1) { | 280 | while (1) { |
275 | page = alloc_pages(flags, order); | 281 | page = alloc_pages(flags, order); |
276 | if (page || !order) | 282 | if (page || !order) |
@@ -285,8 +291,10 @@ static struct mmc_test_mem *mmc_test_alloc_mem(unsigned int min_sz, | |||
285 | mem->arr[mem->cnt].page = page; | 291 | mem->arr[mem->cnt].page = page; |
286 | mem->arr[mem->cnt].order = order; | 292 | mem->arr[mem->cnt].order = order; |
287 | mem->cnt += 1; | 293 | mem->cnt += 1; |
288 | max_page_cnt -= 1 << order; | 294 | if (max_page_cnt <= (1UL << order)) |
289 | page_cnt += 1 << order; | 295 | break; |
296 | max_page_cnt -= 1UL << order; | ||
297 | page_cnt += 1UL << order; | ||
290 | } | 298 | } |
291 | 299 | ||
292 | return mem; | 300 | return mem; |
@@ -300,7 +308,7 @@ out_free: | |||
300 | * Map memory into a scatterlist. Optionally allow the same memory to be | 308 | * Map memory into a scatterlist. Optionally allow the same memory to be |
301 | * mapped more than once. | 309 | * mapped more than once. |
302 | */ | 310 | */ |
303 | static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned int sz, | 311 | static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long sz, |
304 | struct scatterlist *sglist, int repeat, | 312 | struct scatterlist *sglist, int repeat, |
305 | unsigned int max_segs, unsigned int *sg_len) | 313 | unsigned int max_segs, unsigned int *sg_len) |
306 | { | 314 | { |
@@ -312,7 +320,7 @@ static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned int sz, | |||
312 | *sg_len = 0; | 320 | *sg_len = 0; |
313 | do { | 321 | do { |
314 | for (i = 0; i < mem->cnt; i++) { | 322 | for (i = 0; i < mem->cnt; i++) { |
315 | unsigned int len = PAGE_SIZE << mem->arr[i].order; | 323 | unsigned long len = PAGE_SIZE << mem->arr[i].order; |
316 | 324 | ||
317 | if (sz < len) | 325 | if (sz < len) |
318 | len = sz; | 326 | len = sz; |
@@ -344,13 +352,14 @@ static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned int sz, | |||
344 | * same memory to be mapped more than once. | 352 | * same memory to be mapped more than once. |
345 | */ | 353 | */ |
346 | static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, | 354 | static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, |
347 | unsigned int sz, | 355 | unsigned long sz, |
348 | struct scatterlist *sglist, | 356 | struct scatterlist *sglist, |
349 | unsigned int max_segs, | 357 | unsigned int max_segs, |
350 | unsigned int *sg_len) | 358 | unsigned int *sg_len) |
351 | { | 359 | { |
352 | struct scatterlist *sg = NULL; | 360 | struct scatterlist *sg = NULL; |
353 | unsigned int i = mem->cnt, cnt, len; | 361 | unsigned int i = mem->cnt, cnt; |
362 | unsigned long len; | ||
354 | void *base, *addr, *last_addr = NULL; | 363 | void *base, *addr, *last_addr = NULL; |
355 | 364 | ||
356 | sg_init_table(sglist, max_segs); | 365 | sg_init_table(sglist, max_segs); |
@@ -1202,7 +1211,7 @@ static int mmc_test_no_highmem(struct mmc_test_card *test) | |||
1202 | /* | 1211 | /* |
1203 | * Map sz bytes so that it can be transferred. | 1212 | * Map sz bytes so that it can be transferred. |
1204 | */ | 1213 | */ |
1205 | static int mmc_test_area_map(struct mmc_test_card *test, unsigned int sz, | 1214 | static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz, |
1206 | int max_scatter) | 1215 | int max_scatter) |
1207 | { | 1216 | { |
1208 | struct mmc_test_area *t = &test->area; | 1217 | struct mmc_test_area *t = &test->area; |
@@ -1233,7 +1242,7 @@ static int mmc_test_area_transfer(struct mmc_test_card *test, | |||
1233 | /* | 1242 | /* |
1234 | * Map and transfer bytes. | 1243 | * Map and transfer bytes. |
1235 | */ | 1244 | */ |
1236 | static int mmc_test_area_io(struct mmc_test_card *test, unsigned int sz, | 1245 | static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz, |
1237 | unsigned int dev_addr, int write, int max_scatter, | 1246 | unsigned int dev_addr, int write, int max_scatter, |
1238 | int timed) | 1247 | int timed) |
1239 | { | 1248 | { |
@@ -1308,19 +1317,22 @@ static int mmc_test_area_cleanup(struct mmc_test_card *test) | |||
1308 | static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) | 1317 | static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) |
1309 | { | 1318 | { |
1310 | struct mmc_test_area *t = &test->area; | 1319 | struct mmc_test_area *t = &test->area; |
1311 | unsigned int min_sz = 64 * 1024; | 1320 | unsigned long min_sz = 64 * 1024; |
1312 | int ret; | 1321 | int ret; |
1313 | 1322 | ||
1314 | ret = mmc_test_set_blksize(test, 512); | 1323 | ret = mmc_test_set_blksize(test, 512); |
1315 | if (ret) | 1324 | if (ret) |
1316 | return ret; | 1325 | return ret; |
1317 | 1326 | ||
1327 | if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9) | ||
1328 | t->max_sz = TEST_AREA_MAX_SIZE; | ||
1329 | else | ||
1330 | t->max_sz = (unsigned long)test->card->pref_erase << 9; | ||
1318 | /* | 1331 | /* |
1319 | * Try to allocate enough memory for the whole area. Less is OK | 1332 | * Try to allocate enough memory for the whole area. Less is OK |
1320 | * because the same memory can be mapped into the scatterlist more than | 1333 | * because the same memory can be mapped into the scatterlist more than |
1321 | * once. | 1334 | * once. |
1322 | */ | 1335 | */ |
1323 | t->max_sz = test->card->pref_erase << 9; | ||
1324 | t->mem = mmc_test_alloc_mem(min_sz, t->max_sz); | 1336 | t->mem = mmc_test_alloc_mem(min_sz, t->max_sz); |
1325 | if (!t->mem) | 1337 | if (!t->mem) |
1326 | return -ENOMEM; | 1338 | return -ENOMEM; |
@@ -1430,7 +1442,8 @@ static int mmc_test_best_write_perf_max_scatter(struct mmc_test_card *test) | |||
1430 | */ | 1442 | */ |
1431 | static int mmc_test_profile_read_perf(struct mmc_test_card *test) | 1443 | static int mmc_test_profile_read_perf(struct mmc_test_card *test) |
1432 | { | 1444 | { |
1433 | unsigned int sz, dev_addr; | 1445 | unsigned long sz; |
1446 | unsigned int dev_addr; | ||
1434 | int ret; | 1447 | int ret; |
1435 | 1448 | ||
1436 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { | 1449 | for (sz = 512; sz < test->area.max_sz; sz <<= 1) { |
@@ -1448,7 +1461,8 @@ static int mmc_test_profile_read_perf(struct mmc_test_card *test) | |||
1448 | */ | 1461 | */ |
1449 | static int mmc_test_profile_write_perf(struct mmc_test_card *test) | 1462 | static int mmc_test_profile_write_perf(struct mmc_test_card *test) |
1450 | { | 1463 | { |
1451 | unsigned int sz, dev_addr; | 1464 | unsigned long sz; |
1465 | unsigned int dev_addr; | ||
1452 | int ret; | 1466 | int ret; |
1453 | 1467 | ||
1454 | ret = mmc_test_area_erase(test); | 1468 | ret = mmc_test_area_erase(test); |
@@ -1472,7 +1486,8 @@ static int mmc_test_profile_write_perf(struct mmc_test_card *test) | |||
1472 | */ | 1486 | */ |
1473 | static int mmc_test_profile_trim_perf(struct mmc_test_card *test) | 1487 | static int mmc_test_profile_trim_perf(struct mmc_test_card *test) |
1474 | { | 1488 | { |
1475 | unsigned int sz, dev_addr; | 1489 | unsigned long sz; |
1490 | unsigned int dev_addr; | ||
1476 | struct timespec ts1, ts2; | 1491 | struct timespec ts1, ts2; |
1477 | int ret; | 1492 | int ret; |
1478 | 1493 | ||
@@ -1506,7 +1521,8 @@ static int mmc_test_profile_trim_perf(struct mmc_test_card *test) | |||
1506 | */ | 1521 | */ |
1507 | static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) | 1522 | static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) |
1508 | { | 1523 | { |
1509 | unsigned int sz, dev_addr, i, cnt; | 1524 | unsigned long sz; |
1525 | unsigned int dev_addr, i, cnt; | ||
1510 | struct timespec ts1, ts2; | 1526 | struct timespec ts1, ts2; |
1511 | int ret; | 1527 | int ret; |
1512 | 1528 | ||
@@ -1531,7 +1547,8 @@ static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) | |||
1531 | */ | 1547 | */ |
1532 | static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) | 1548 | static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) |
1533 | { | 1549 | { |
1534 | unsigned int sz, dev_addr, i, cnt; | 1550 | unsigned long sz; |
1551 | unsigned int dev_addr, i, cnt; | ||
1535 | struct timespec ts1, ts2; | 1552 | struct timespec ts1, ts2; |
1536 | int ret; | 1553 | int ret; |
1537 | 1554 | ||
@@ -1559,7 +1576,8 @@ static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) | |||
1559 | */ | 1576 | */ |
1560 | static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) | 1577 | static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) |
1561 | { | 1578 | { |
1562 | unsigned int sz, dev_addr, i, cnt; | 1579 | unsigned long sz; |
1580 | unsigned int dev_addr, i, cnt; | ||
1563 | struct timespec ts1, ts2; | 1581 | struct timespec ts1, ts2; |
1564 | int ret; | 1582 | int ret; |
1565 | 1583 | ||