aboutsummaryrefslogtreecommitdiff
path: root/tests/mtd-tests/flash_speed.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/mtd-tests/flash_speed.c')
-rw-r--r--tests/mtd-tests/flash_speed.c117
1 files changed, 59 insertions, 58 deletions
diff --git a/tests/mtd-tests/flash_speed.c b/tests/mtd-tests/flash_speed.c
index 3489233..3319452 100644
--- a/tests/mtd-tests/flash_speed.c
+++ b/tests/mtd-tests/flash_speed.c
@@ -23,6 +23,7 @@
* Author: Adrian Hunter <adrian.hunter@nokia.com>
*/
#define DESTRUCTIVE 0x01
+#define CONTINOUS 0x02
#define PROGRAM_NAME "flash_speed"
@@ -47,7 +48,9 @@ static const char *mtddev;
static libmtd_t mtd_desc;
static int fd;
+static int npages = 1;
static int peb=-1, count=-1, skip=-1, flags=0, speb=-1;
+static bool continuous = false;
static struct timespec start, finish;
static int pgsize, pgcnt;
static int goodebcnt;
@@ -59,6 +62,7 @@ static const struct option options[] = {
{ "count", required_argument, NULL, 'c' },
{ "skip", required_argument, NULL, 's' },
{ "sec-peb", required_argument, NULL, 'k' },
+ { "continuous", no_argument, NULL, 'C' },
{ NULL, 0, NULL, 0 },
};
@@ -72,7 +76,8 @@ static NORETURN void usage(int status)
" -c, --count <num> Number of erase blocks to use (default: all)\n"
" -s, --skip <num> Number of blocks to skip\n"
" -d, --destructive Run destructive (erase and write speed) tests\n"
- " -k, --sec-peb <num> Start of secondary block to measure RWW latency (requires -d)\n",
+ " -k, --sec-peb <num> Start of secondary block to measure RWW latency (requires -d)\n"
+ " -C, --continuous Increase the number of consecutive pages gradually\n",
status==EXIT_SUCCESS ? stdout : stderr);
exit(status);
}
@@ -96,7 +101,7 @@ static void process_options(int argc, char **argv)
int c;
while (1) {
- c = getopt_long(argc, argv, "hb:c:s:dk:", options, NULL);
+ c = getopt_long(argc, argv, "hb:c:s:dk:C", options, NULL);
if (c == -1)
break;
@@ -136,6 +141,9 @@ static void process_options(int argc, char **argv)
if (speb < 0)
goto failarg;
break;
+ case 'C':
+ continuous = true;
+ break;
default:
exit(EXIT_FAILURE);
}
@@ -182,7 +190,7 @@ static int read_eraseblock(int ebnum)
{
int err = mtd_read(&mtd, fd, ebnum, 0, iobuf, mtd.eb_size);
if (err)
- fprintf(stderr, "Error writing block %d!\n", ebnum);
+ fprintf(stderr, "Error reading block %d!\n", ebnum);
return err;
}
@@ -232,46 +240,21 @@ static int write_eraseblock_by_2pages(int ebnum)
return err;
}
-static int read_eraseblock_by_page(int ebnum)
+static int read_eraseblock_by_npages(int ebnum)
{
- void *buf = iobuf;
- int i, err = 0;
-
- for (i = 0; i < pgcnt; ++i) {
- err = mtd_read(&mtd, fd, ebnum, i * pgsize, iobuf, pgsize);
- if (err) {
- fprintf(stderr, "Error reading block %d, page %d!\n",
- ebnum, i);
- break;
- }
- buf += pgsize;
- }
-
- return err;
-}
-
-static int read_eraseblock_by_2pages(int ebnum)
-{
- int i, n = pgcnt / 2, err = 0;
- size_t sz = pgsize * 2;
+ int i, n = pgcnt / npages, err = 0;
+ size_t sz = pgsize * npages;
void *buf = iobuf;
for (i = 0; i < n; ++i) {
err = mtd_read(&mtd, fd, ebnum, i * sz, iobuf, sz);
if (err) {
- fprintf(stderr, "Error reading block %d, page %d + %d!\n",
- ebnum, i*2, i*2+1);
+ fprintf(stderr, "Error reading block %d, page [%d-%d]!\n",
+ ebnum, i*npages, (i*npages) + npages- 1);
return err;
}
buf += sz;
}
- if (pgcnt % 2) {
- err = mtd_read(&mtd, fd, ebnum, i * sz, iobuf, pgsize);
- if (err) {
- fprintf(stderr, "Error reading block %d, page %d!\n",
- ebnum, i*2);
- }
- }
return err;
}
@@ -296,14 +279,17 @@ static long calc_duration(struct timespec *start, struct timespec *finish)
return ms;
}
-static long calc_speed(struct timespec *start, struct timespec *finish)
+static long calc_speed(struct timespec *start, struct timespec *finish,
+ int pages_per_set)
{
long ms = calc_duration(start, finish);
+ int sets_in_eb = pgcnt / pages_per_set;
+ size_t sz = pgsize * pages_per_set * sets_in_eb;
if (ms <= 0)
return 0;
- return ((long)goodebcnt * (mtd.eb_size / 1024L) * 1000L) / ms;
+ return ((long)goodebcnt * (sz / 1024L) * 1000L) / ms;
}
static void scan_for_bad_eraseblocks(unsigned int eb, int ebcnt, int ebskip)
@@ -364,7 +350,7 @@ static void *op_thread(void *ptr)
return (void *)err;
}
-#define TIME_OP_PER_PEB( op )\
+#define TIME_OP_PER_PEB( op, npages ) \
start_timing(&start);\
for (i = 0; i < count; ++i) {\
if (bbt[i])\
@@ -374,7 +360,7 @@ static void *op_thread(void *ptr)
goto out;\
}\
stop_timing(&finish);\
- speed = calc_speed(&start, &finish)
+ speed = calc_speed(&start, &finish, npages)
int main(int argc, char **argv)
{
@@ -435,13 +421,13 @@ int main(int argc, char **argv)
goto out;
puts("testing eraseblock write speed");
- TIME_OP_PER_PEB(write_eraseblock);
+ TIME_OP_PER_PEB(write_eraseblock, 1);
printf("eraseblock write speed is %ld KiB/s\n", speed);
}
/* Read all eraseblocks, 1 eraseblock at a time */
puts("testing eraseblock read speed");
- TIME_OP_PER_PEB(read_eraseblock);
+ TIME_OP_PER_PEB(read_eraseblock, 1);
printf("eraseblock read speed is %ld KiB/s\n", speed);
/* Write all eraseblocks, 1 page at a time */
@@ -451,30 +437,45 @@ int main(int argc, char **argv)
goto out;
puts("testing page write speed");
- TIME_OP_PER_PEB(write_eraseblock_by_page);
+ TIME_OP_PER_PEB(write_eraseblock_by_page, 1);
printf("page write speed is %ld KiB/s\n", speed);
}
/* Read all eraseblocks, 1 page at a time */
puts("testing page read speed");
- TIME_OP_PER_PEB(read_eraseblock_by_page);
+ npages = 1;
+ TIME_OP_PER_PEB(read_eraseblock_by_npages, npages);
printf("page read speed is %ld KiB/s\n", speed);
- /* Write all eraseblocks, 2 pages at a time */
- if (flags & DESTRUCTIVE) {
- err = erase_good_eraseblocks(peb, count, skip);
- if (err)
- goto out;
+ if (continuous) {
+ /* Write all eraseblocks, 2 pages at a time */
+ if (flags & DESTRUCTIVE) {
+ err = erase_good_eraseblocks(peb, count, skip);
+ if (err)
+ goto out;
- puts("testing 2 page write speed");
- TIME_OP_PER_PEB(write_eraseblock_by_2pages);
- printf("2 page write speed is %ld KiB/s\n", speed);
- }
+ puts("testing 2 page write speed");
+ TIME_OP_PER_PEB(write_eraseblock_by_2pages, 2);
+ printf("2 page write speed is %ld KiB/s\n", speed);
+ }
- /* Read all eraseblocks, 2 pages at a time */
- puts("testing 2 page read speed");
- TIME_OP_PER_PEB(read_eraseblock_by_2pages);
- printf("2 page read speed is %ld KiB/s\n", speed);
+ /* Read all eraseblocks, N pages at a time */
+ puts("testing multiple pages read speed");
+ for (npages = 2; npages <= 16 && npages <= pgcnt; npages++) {
+ TIME_OP_PER_PEB(read_eraseblock_by_npages, npages);
+ printf("%d page read speed is %ld KiB/s\n", npages, speed);
+ }
+ if (pgcnt >= 32) {
+ npages = 32;
+ TIME_OP_PER_PEB(read_eraseblock_by_npages, npages);
+ printf("%d page read speed is %ld KiB/s\n", npages, speed);
+ }
+ if (pgcnt >= 64) {
+ npages = 64;
+ TIME_OP_PER_PEB(read_eraseblock_by_npages, npages);
+ printf("%d page read speed is %ld KiB/s\n", npages, speed);
+ }
+ }
/* Erase all eraseblocks */
if (flags & DESTRUCTIVE) {
@@ -484,12 +485,12 @@ int main(int argc, char **argv)
if (err)
goto out;
stop_timing(&finish);
- speed = calc_speed(&start, &finish);
+ speed = calc_speed(&start, &finish, 1);
printf("erase speed is %ld KiB/s\n", speed);
}
/* Multi-block erase all eraseblocks */
- if (!skip) {
+ if (flags & DESTRUCTIVE && !skip) {
for (k = 1; k < 7; ++k) {
blocks = 1 << k;
printf("Testing %dx multi-block erase speed\n", blocks);
@@ -508,7 +509,7 @@ int main(int argc, char **argv)
i += j;
}
stop_timing(&finish);
- speed = calc_speed(&start, &finish);
+ speed = calc_speed(&start, &finish, 1);
printf("%dx multi-block erase speed is %ld KiB/s\n",
blocks, speed);
}
@@ -517,7 +518,7 @@ int main(int argc, char **argv)
/* Write a page and immediately after try to read another page. Report
* the latency difference when performed on different banks (NOR only).
*/
- if (speb >= 0 && mtd.subpage_size == 1) {
+ if (flags & DESTRUCTIVE && speb >= 0 && mtd.subpage_size == 1) {
long rww_duration_w, rww_latency_end;
long rww_duration_rnw, rww_duration_r_end;
bool rww_r_end_first;