aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/card/mmc_test.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@nokia.com>2010-08-11 17:17:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-12 11:43:31 -0400
commitfec4dcce237c7185ff7129e704bc508850b6e3f0 (patch)
tree018b868ff5a1a66ac5dfcbc8704362295987f4f6 /drivers/mmc/card/mmc_test.c
parent64f7120d890b892ed2c82c87bed958902e809075 (diff)
mmc_test: fix large memory allocation
- Fix mmc_test_alloc_mem. - Use nr_free_buffer_pages() instead of sysinfo.totalram to determine total lowmem pages. - Change variables containing memory sizes to unsigned long. - Limit maximum test area size to 128MiB because that is the maximum MMC high capacity erase size (the maxmium SD allocation unit size is just 4MiB) Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mmc/card/mmc_test.c')
-rw-r--r--drivers/mmc/card/mmc_test.c76
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 */
58struct mmc_test_area { 65struct 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 */
243static struct mmc_test_mem *mmc_test_alloc_mem(unsigned int min_sz, 250static 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 */
303static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned int sz, 311static 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 */
346static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem, 354static 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 */
1205static int mmc_test_area_map(struct mmc_test_card *test, unsigned int sz, 1214static 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 */
1236static int mmc_test_area_io(struct mmc_test_card *test, unsigned int sz, 1245static 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)
1308static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill) 1317static 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 */
1431static int mmc_test_profile_read_perf(struct mmc_test_card *test) 1443static 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 */
1449static int mmc_test_profile_write_perf(struct mmc_test_card *test) 1462static 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 */
1473static int mmc_test_profile_trim_perf(struct mmc_test_card *test) 1487static 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 */
1507static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test) 1522static 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 */
1532static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test) 1548static 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 */
1560static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test) 1577static 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