summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/memtest.c82
-rw-r--r--common/memtest.c16
-rw-r--r--include/memtest.h1
3 files changed, 72 insertions, 27 deletions
diff --git a/commands/memtest.c b/commands/memtest.c
index ccccc9c19e..957095ff0c 100644
--- a/commands/memtest.c
+++ b/commands/memtest.c
@@ -28,42 +28,70 @@
#include <memtest.h>
#include <mmu.h>
-static int __do_memtest(struct list_head *memtest_regions,
+static int do_test_one_area(struct mem_test_resource *r, int bus_only,
+ unsigned cache_flag)
+{
+ int ret;
+
+ printf("Testing memory space: "
+ "0x%08x -> 0x%08x:\n",
+ r->r->start, r->r->end);
+
+ remap_range((void *)r->r->start, r->r->end -
+ r->r->start + 1, cache_flag);
+
+ ret = mem_test_bus_integrity(r->r->start, r->r->end);
+ if (ret < 0)
+ return ret;
+
+ if (bus_only)
+ return 0;
+
+ ret = mem_test_moving_inversions(r->r->start, r->r->end);
+ if (ret < 0)
+ return ret;
+ printf("done.\n\n");
+
+ return 0;
+}
+
+static int do_memtest_thorough(struct list_head *memtest_regions,
int bus_only, unsigned cache_flag)
{
struct mem_test_resource *r;
int ret;
list_for_each_entry(r, memtest_regions, list) {
- printf("Testing memory space: "
- "0x%08x -> 0x%08x:\n",
- r->r->start, r->r->end);
- remap_range((void *)r->r->start, r->r->end -
- r->r->start + 1, cache_flag);
-
- ret = mem_test_bus_integrity(r->r->start, r->r->end);
- if (ret < 0)
+ ret = do_test_one_area(r, bus_only, cache_flag);
+ if (ret)
return ret;
-
- if (bus_only)
- continue;
-
- ret = mem_test_moving_inversions(r->r->start, r->r->end);
- if (ret < 0)
- return ret;
- printf("done.\n\n");
}
return 0;
}
+static int do_memtest_biggest(struct list_head *memtest_regions,
+ int bus_only, unsigned cache_flag)
+{
+ struct mem_test_resource *r;
+
+ r = mem_test_biggest_region(memtest_regions);
+ if (!r)
+ return -EINVAL;
+
+ return do_test_one_area(r, bus_only, cache_flag);
+}
+
static int do_memtest(int argc, char *argv[])
{
int bus_only = 0, ret, opt;
uint32_t i, max_i = 1;
struct list_head memtest_used_regions;
+ int (*memtest)(struct list_head *, int, unsigned);
+
+ memtest = do_memtest_biggest;
- while ((opt = getopt(argc, argv, "i:b")) > 0) {
+ while ((opt = getopt(argc, argv, "i:bt")) > 0) {
switch (opt) {
case 'i':
max_i = simple_strtoul(optarg, NULL, 0);
@@ -71,6 +99,9 @@ static int do_memtest(int argc, char *argv[])
case 'b':
bus_only = 1;
break;
+ case 't':
+ memtest = do_memtest_thorough;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -90,25 +121,21 @@ static int do_memtest(int argc, char *argv[])
printf("Start iteration %u of %u.\n", i, max_i);
if (arch_can_remap()) {
- /*
- * First try a memtest with caching enabled.
- */
+ /* First do a memtest with caching enabled. */
printf("Do memtest with caching enabled.\n");
- ret = __do_memtest(&memtest_used_regions,
+ ret = memtest(&memtest_used_regions,
bus_only, MAP_CACHED);
if (ret < 0)
goto out;
- /*
- * Second try a memtest with caching disabled.
- */
+ /* Second do a memtest with caching disabled. */
printf("Do memtest with caching disabled.\n");
- ret = __do_memtest(&memtest_used_regions,
+ ret = memtest(&memtest_used_regions,
bus_only, MAP_UNCACHED);
if (ret < 0)
goto out;
} else {
- ret = __do_memtest(&memtest_used_regions,
+ ret = memtest(&memtest_used_regions,
bus_only, MAP_DEFAULT);
if (ret < 0)
goto out;
@@ -139,6 +166,7 @@ BAREBOX_CMD_HELP_START(memtest)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-i ITERATIONS", "perform number of iterations (default 1, 0 is endless)")
BAREBOX_CMD_HELP_OPT("-b", "perform only a test on bus lines")
+BAREBOX_CMD_HELP_OPT("-t", "thorough. test all free areas. If unset, only test biggest free area")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(memtest)
diff --git a/common/memtest.c b/common/memtest.c
index 026fd0d48d..401b902c78 100644
--- a/common/memtest.c
+++ b/common/memtest.c
@@ -139,6 +139,22 @@ void mem_test_release_regions(struct list_head *list)
}
}
+struct mem_test_resource *mem_test_biggest_region(struct list_head *list)
+{
+ struct mem_test_resource *r, *best = NULL;
+ resource_size_t size = 0;
+
+ list_for_each_entry(r, list, list) {
+ resource_size_t now = resource_size(r->r);
+ if (now > size) {
+ size = now;
+ best = r;
+ }
+ }
+
+ return best;
+}
+
static void mem_test_report_failure(const char *failure_description,
resource_size_t expected_value,
resource_size_t actual_value,
diff --git a/include/memtest.h b/include/memtest.h
index 3979d651d6..0100a6c58c 100644
--- a/include/memtest.h
+++ b/include/memtest.h
@@ -10,6 +10,7 @@ struct mem_test_resource {
int mem_test_request_regions(struct list_head *list);
void mem_test_release_regions(struct list_head *list);
+struct mem_test_resource *mem_test_biggest_region(struct list_head *list);
int mem_test_bus_integrity(resource_size_t _start, resource_size_t _end);
int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end);