diff options
Diffstat (limited to 'commands/memtest.c')
-rw-r--r-- | commands/memtest.c | 204 |
1 files changed, 76 insertions, 128 deletions
diff --git a/commands/memtest.c b/commands/memtest.c index b88290c227..d784a5c0e2 100644 --- a/commands/memtest.c +++ b/commands/memtest.c @@ -21,137 +21,78 @@ #include <command.h> #include <getopt.h> -#include <asm/mmu.h> #include <memory.h> #include <malloc.h> #include <common.h> #include <errno.h> - #include <memtest.h> +#include <mmu.h> -static int alloc_memtest_region(struct list_head *list, - resource_size_t start, resource_size_t size) -{ - struct resource *r_new; - struct mem_test_resource *r; - - r = xzalloc(sizeof(struct mem_test_resource)); - r_new = request_sdram_region("memtest", start, size); - if (!r_new) - return -EINVAL; - - r->r = r_new; - list_add_tail(&r->list, list); - - return 0; -} - -static int request_memtest_regions(struct list_head *list) +static int do_test_one_area(struct mem_test_resource *r, int bus_only, + unsigned cache_flag) { int ret; - struct memory_bank *bank; - struct resource *r, *r_prev = NULL; - resource_size_t start, end, size; - for_each_memory_bank(bank) { - /* - * If we don't have any allocated region on bank, - * we use the whole bank boundary - */ - if (list_empty(&bank->res->children)) { - start = PAGE_ALIGN(bank->res->start); - size = PAGE_ALIGN_DOWN(bank->res->end - start + 1); + printf("Testing memory space: " + "0x%08x -> 0x%08x:\n", + r->r->start, r->r->end); - if (size) { - ret = alloc_memtest_region(list, start, size); - if (ret < 0) - return ret; - } + remap_range((void *)r->r->start, r->r->end - + r->r->start + 1, cache_flag); - continue; - } + ret = mem_test_bus_integrity(r->r->start, r->r->end); + if (ret < 0) + return ret; - r = list_first_entry(&bank->res->children, - struct resource, sibling); - start = PAGE_ALIGN(bank->res->start); - end = PAGE_ALIGN_DOWN(r->start); - r_prev = r; - if (start != end) { - size = end - start; - ret = alloc_memtest_region(list, start, size); - if (ret < 0) - return ret; - } - /* - * We assume that the regions are sorted in this list - * So the first element has start boundary on bank->res->start - * and the last element hast end boundary on bank->res->end. - * - * Between used regions. Start from second entry. - */ - list_for_each_entry_from(r, &bank->res->children, sibling) { - start = PAGE_ALIGN(r_prev->end + 1); - end = r->start - 1; - r_prev = r; - if (start >= end) - continue; - - size = PAGE_ALIGN_DOWN(end - start + 1); - if (size == 0) - continue; - ret = alloc_memtest_region(list, start, size); - if (ret < 0) - return ret; - } + if (bus_only) + return 0; - /* - * Do on head element for bank boundary. - */ - r = list_last_entry(&bank->res->children, - struct resource, sibling); - start = PAGE_ALIGN(r->end); - end = bank->res->end; - size = PAGE_ALIGN_DOWN(end - start + 1); - if (size && start < end && start > r->end) { - ret = alloc_memtest_region(list, start, size); - if (ret < 0) - return ret; - } - } + 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(struct list_head *memtest_regions, - int bus_only, uint32_t cache_flag) +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(r->r->start, r->r->end, bus_only); - if (ret < 0) + ret = do_test_one_area(r, bus_only, cache_flag); + if (ret) 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, pte_flags_cached, pte_flags_uncached; - struct mem_test_resource *r, *r_tmp; + uint32_t i, max_i = 1; struct list_head memtest_used_regions; + int (*memtest)(struct list_head *, int, unsigned); + int cached = 0, uncached = 0; + + memtest = do_memtest_biggest; - while ((opt = getopt(argc, argv, "i:b")) > 0) { + while ((opt = getopt(argc, argv, "i:btcu")) > 0) { switch (opt) { case 'i': max_i = simple_strtoul(optarg, NULL, 0); @@ -159,23 +100,31 @@ static int do_memtest(int argc, char *argv[]) case 'b': bus_only = 1; break; + case 't': + memtest = do_memtest_thorough; + break; + case 'c': + cached = 1; + break; + case 'u': + uncached = 1; + break; default: return COMMAND_ERROR_USAGE; } } + if (!arch_can_remap() && (cached || uncached)) { + printf("Cannot map cached or uncached\n"); + return -EINVAL; + } + if (optind > argc) return COMMAND_ERROR_USAGE; - /* - * Get pte flags for enable and disable cache support on page. - */ - pte_flags_cached = mmu_get_pte_cached_flags(); - pte_flags_uncached = mmu_get_pte_uncached_flags(); - INIT_LIST_HEAD(&memtest_used_regions); - ret = request_memtest_regions(&memtest_used_regions); + ret = mem_test_request_regions(&memtest_used_regions); if (ret < 0) goto out; @@ -186,36 +135,32 @@ static int do_memtest(int argc, char *argv[]) else putchar('\n'); - /* - * First try a memtest with caching enabled. - */ - if (IS_ENABLED(CONFIG_MMU)) { + if (cached) { printf("Do memtest with caching enabled.\n"); - ret = __do_memtest(&memtest_used_regions, - bus_only, pte_flags_cached); + ret = memtest(&memtest_used_regions, + bus_only, MAP_CACHED); + if (ret < 0) + goto out; + } + + if (uncached) { + printf("Do memtest with caching disabled.\n"); + ret = memtest(&memtest_used_regions, + bus_only, MAP_UNCACHED); + if (ret < 0) + goto out; + } + + if (!cached && !uncached) { + ret = memtest(&memtest_used_regions, + bus_only, MAP_DEFAULT); if (ret < 0) goto out; } - /* - * Second try a memtest with caching disabled. - */ - printf("Do memtest with caching disabled.\n"); - ret = __do_memtest(&memtest_used_regions, - bus_only, pte_flags_uncached); - if (ret < 0) - goto out; } out: - list_for_each_entry_safe(r, r_tmp, &memtest_used_regions, list) { - /* - * Ensure to leave with a cached on non used sdram regions. - */ - remap_range((void *)r->r->start, r->r->end - - r->r->start + 1, pte_flags_cached); - release_sdram_region(r->r); - free(r); - } + mem_test_release_regions(&memtest_used_regions); if (ret < 0) { /* @@ -238,6 +183,9 @@ 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("-c", "cached. Test using cached memory") +BAREBOX_CMD_HELP_OPT("-u", "uncached. Test using uncached memory") +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) |