From 6b127d4f189c03f4417f6185de1aeb55b1706f94 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 23 Oct 2015 09:39:15 +0200 Subject: memtest: move request/release regions to common/ Normally code providing a feature should be implemented in common/ which is then called from the command code. Follow this rule and move some more of the memtest code to common/. Signed-off-by: Sascha Hauer --- include/memtest.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/memtest.h b/include/memtest.h index a337be832f..1c67a73e74 100644 --- a/include/memtest.h +++ b/include/memtest.h @@ -8,6 +8,9 @@ struct mem_test_resource { struct list_head list; }; +int mem_test_request_regions(struct list_head *list); +void mem_test_release_regions(struct list_head *list); + int mem_test(resource_size_t _start, resource_size_t _end, int bus_only); -- cgit v1.2.3 From b792124a7dd30f03b9ad0e06589b5b58ed930d3b Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 23 Oct 2015 11:06:56 +0200 Subject: rework remap_range remap_range is for remapping regions with different cache attributes. It is implemented for ARM and PowerPC only, the other architectures only provide stubs. Currently the new cache attributes are passed in an architecture specific way and the attributes have to be retrieved by calls to mmu_get_pte_cached_flags() and mmu_get_pte_uncached_flags(). Make this simpler by providing architecture independent flags which can be directly passed to remap_range() Also provide a MAP_ARCH_DEFAULT flag and a arch_can_remap() function. The MAP_ARCH_DEFAULT defaults to whatever caching type the architecture has as default. the arch_can_remap() function returns true if the architecture can change the cache attributes, false otherwise. This allows the memtest code to better find out what it has to do. Signed-off-by: Sascha Hauer --- arch/arm/cpu/mmu.c | 30 +++++++++++++++------------ arch/arm/include/asm/mmu.h | 23 ++++----------------- arch/blackfin/include/asm/mmu.h | 14 +------------ arch/mips/include/asm/mmu.h | 14 +------------ arch/nios2/include/asm/mmu.h | 14 +------------ arch/openrisc/include/asm/mmu.h | 14 +------------ arch/ppc/cpu-85xx/mmu.c | 26 ++++++++++++++---------- arch/ppc/include/asm/mmu.h | 24 ++++++---------------- arch/sandbox/include/asm/mmu.h | 14 +------------ arch/x86/include/asm/mmu.h | 14 +------------ commands/memtest.c | 45 +++++++++++++++++++++-------------------- common/memtest.c | 5 ++--- drivers/video/imx-ipu-fb.c | 5 ++--- drivers/video/omap.c | 5 ++--- drivers/video/stm.c | 5 ++--- include/mmu.h | 41 +++++++++++++++++++++++++++++++++++++ 16 files changed, 120 insertions(+), 173 deletions(-) create mode 100644 include/mmu.h (limited to 'include') diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 470b448957..81c23947b7 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -81,16 +81,6 @@ static uint32_t pte_flags_uncached; #define PTE_MASK ((1 << 12) - 1) -uint32_t mmu_get_pte_cached_flags() -{ - return pte_flags_cached; -} - -uint32_t mmu_get_pte_uncached_flags() -{ - return pte_flags_uncached; -} - static void arm_mmu_not_initialized_error(void) { /* @@ -173,24 +163,38 @@ static void dma_inv_range(unsigned long start, unsigned long end) __dma_inv_range(start, end); } -void remap_range(void *_start, size_t size, uint32_t flags) +int arch_remap_range(void *_start, size_t size, unsigned flags) { unsigned long start = (unsigned long)_start; u32 *p; int numentries, i; + u32 pte_flags; + + switch (flags) { + case MAP_CACHED: + pte_flags = pte_flags_cached; + break; + case MAP_UNCACHED: + pte_flags = pte_flags_uncached; + break; + default: + return -EINVAL; + } numentries = size >> PAGE_SHIFT; p = find_pte(start); for (i = 0; i < numentries; i++) { p[i] &= ~PTE_MASK; - p[i] |= flags | PTE_TYPE_SMALL; + p[i] |= pte_flags | PTE_TYPE_SMALL; } dma_flush_range((unsigned long)p, (unsigned long)p + numentries * sizeof(u32)); tlb_invalidate(); + + return 0; } void *map_io_sections(unsigned long phys, void *_start, size_t size) diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index 3b19e9ef3c..8de6544657 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -27,32 +27,17 @@ static inline void setup_dma_coherent(unsigned long offset) } #ifdef CONFIG_MMU -void remap_range(void *_start, size_t size, uint32_t flags); +#define ARCH_HAS_REMAP +#define MAP_ARCH_DEFAULT MAP_CACHED +int arch_remap_range(void *_start, size_t size, unsigned flags); void *map_io_sections(unsigned long physaddr, void *start, size_t size); -uint32_t mmu_get_pte_cached_flags(void); -uint32_t mmu_get_pte_uncached_flags(void); - #else - -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - +#define MAP_ARCH_DEFAULT MAP_UNCACHED static inline void *map_io_sections(unsigned long phys, void *start, size_t size) { return (void *)phys; } -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} - #endif #ifdef CONFIG_CACHE_L2X0 diff --git a/arch/blackfin/include/asm/mmu.h b/arch/blackfin/include/asm/mmu.h index bf654206ac..95af871420 100644 --- a/arch/blackfin/include/asm/mmu.h +++ b/arch/blackfin/include/asm/mmu.h @@ -1,18 +1,6 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} +#define MAP_ARCH_DEFAULT MAP_UNCACHED #endif /* __ASM_MMU_H */ diff --git a/arch/mips/include/asm/mmu.h b/arch/mips/include/asm/mmu.h index bf654206ac..95af871420 100644 --- a/arch/mips/include/asm/mmu.h +++ b/arch/mips/include/asm/mmu.h @@ -1,18 +1,6 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} +#define MAP_ARCH_DEFAULT MAP_UNCACHED #endif /* __ASM_MMU_H */ diff --git a/arch/nios2/include/asm/mmu.h b/arch/nios2/include/asm/mmu.h index bf654206ac..95af871420 100644 --- a/arch/nios2/include/asm/mmu.h +++ b/arch/nios2/include/asm/mmu.h @@ -1,18 +1,6 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} +#define MAP_ARCH_DEFAULT MAP_UNCACHED #endif /* __ASM_MMU_H */ diff --git a/arch/openrisc/include/asm/mmu.h b/arch/openrisc/include/asm/mmu.h index bf654206ac..95af871420 100644 --- a/arch/openrisc/include/asm/mmu.h +++ b/arch/openrisc/include/asm/mmu.h @@ -1,18 +1,6 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} +#define MAP_ARCH_DEFAULT MAP_UNCACHED #endif /* __ASM_MMU_H */ diff --git a/arch/ppc/cpu-85xx/mmu.c b/arch/ppc/cpu-85xx/mmu.c index 7e86e6b2b6..6b93c3e8db 100644 --- a/arch/ppc/cpu-85xx/mmu.c +++ b/arch/ppc/cpu-85xx/mmu.c @@ -14,17 +14,29 @@ #include #include +#include #include -void remap_range(void *_start, size_t size, uint32_t flags) +int arch_remap_range(void *_start, size_t size, unsigned flags) { - uint32_t ptr, start, tsize, valid, wimge; + uint32_t ptr, start, tsize, valid, wimge, pte_flags; unsigned long epn; phys_addr_t rpn = 0; int esel = 0; + switch (flags) { + case MAP_UNCACHED: + pte_flags = MAS2_I; + break; + case MAP_CACHED: + pte_flags = 0; + break; + default: + return -EINVAL; + } + ptr = start = (uint32_t)_start; - wimge = flags | MAS2_M; + wimge = pte_flags | MAS2_M; while (ptr < (start + size)) { esel = e500_find_tlb_idx((void *)ptr, 1); @@ -41,14 +53,6 @@ void remap_range(void *_start, size_t size, uint32_t flags) /* convert tsize to bytes to increment address. */ ptr += (1ULL << ((tsize) + 10)); } -} -uint32_t mmu_get_pte_cached_flags(void) -{ return 0; } - -uint32_t mmu_get_pte_uncached_flags(void) -{ - return MAS2_I; -} diff --git a/arch/ppc/include/asm/mmu.h b/arch/ppc/include/asm/mmu.h index 6e15975545..c691de1c77 100644 --- a/arch/ppc/include/asm/mmu.h +++ b/arch/ppc/include/asm/mmu.h @@ -557,25 +557,13 @@ extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower); #ifndef __ASSEMBLY__ +#define MAP_ARCH_DEFAULT MAP_CACHED + #ifdef CONFIG_MMU -void remap_range(void *_start, size_t size, uint32_t flags); -uint32_t mmu_get_pte_cached_flags(void); -uint32_t mmu_get_pte_uncached_flags(void); -#else -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} -#endif /* CONFIG_MMU */ +#define ARCH_HAS_REMAP +int arch_remap_range(void *_start, size_t size, unsigned flags); +#endif + #endif #endif /* _PPC_MMU_H_ */ diff --git a/arch/sandbox/include/asm/mmu.h b/arch/sandbox/include/asm/mmu.h index bf654206ac..95af871420 100644 --- a/arch/sandbox/include/asm/mmu.h +++ b/arch/sandbox/include/asm/mmu.h @@ -1,18 +1,6 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} +#define MAP_ARCH_DEFAULT MAP_UNCACHED #endif /* __ASM_MMU_H */ diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index bf654206ac..95af871420 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -1,18 +1,6 @@ #ifndef __ASM_MMU_H #define __ASM_MMU_H -static inline void remap_range(void *_start, size_t size, uint32_t flags) -{ -} - -static inline uint32_t mmu_get_pte_cached_flags(void) -{ - return 0; -} - -static inline uint32_t mmu_get_pte_uncached_flags(void) -{ - return 0; -} +#define MAP_ARCH_DEFAULT MAP_UNCACHED #endif /* __ASM_MMU_H */ diff --git a/commands/memtest.c b/commands/memtest.c index 531b8e0ea7..db9e3dbb01 100644 --- a/commands/memtest.c +++ b/commands/memtest.c @@ -21,15 +21,15 @@ #include #include -#include #include #include #include #include #include +#include static int __do_memtest(struct list_head *memtest_regions, - int bus_only, uint32_t cache_flag) + int bus_only, unsigned cache_flag) { struct mem_test_resource *r; int ret; @@ -53,7 +53,7 @@ static int __do_memtest(struct list_head *memtest_regions, 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; + uint32_t i, max_i = 1; struct list_head memtest_used_regions; while ((opt = getopt(argc, argv, "i:b")) > 0) { @@ -72,12 +72,6 @@ static int do_memtest(int argc, char *argv[]) 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 = mem_test_request_regions(&memtest_used_regions); @@ -87,24 +81,31 @@ static int do_memtest(int argc, char *argv[]) for (i = 1; (i <= max_i) || !max_i; i++) { if (max_i) printf("Start iteration %u of %u.\n", i, max_i); - /* - * First try a memtest with caching enabled. - */ - if (IS_ENABLED(CONFIG_MMU)) { + + if (arch_can_remap()) { + /* + * First try a memtest with caching enabled. + */ printf("Do memtest with caching enabled.\n"); ret = __do_memtest(&memtest_used_regions, - bus_only, pte_flags_cached); + bus_only, MAP_CACHED); + 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, MAP_UNCACHED); + if (ret < 0) + goto out; + } else { + ret = __do_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: diff --git a/common/memtest.c b/common/memtest.c index fc71e91477..467eea546d 100644 --- a/common/memtest.c +++ b/common/memtest.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include static int alloc_memtest_region(struct list_head *list, resource_size_t start, resource_size_t size) @@ -126,14 +126,13 @@ int mem_test_request_regions(struct list_head *list) void mem_test_release_regions(struct list_head *list) { struct mem_test_resource *r, *r_tmp; - uint32_t pte_flags_cached = mmu_get_pte_cached_flags(); list_for_each_entry_safe(r, r_tmp, list, 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); + r->r->start + 1, MAP_DEFAULT); release_sdram_region(r->r); free(r); diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c index a87e720d96..03d191a331 100644 --- a/drivers/video/imx-ipu-fb.c +++ b/drivers/video/imx-ipu-fb.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -1030,8 +1030,7 @@ static int imxfb_probe(struct device_d *dev) fbi->info.screen_base = pdata->framebuffer; if (fbi->info.screen_base) { remap_range(fbi->info.screen_base, - fbi->info.screen_size, - mmu_get_pte_uncached_flags()); + fbi->info.screen_size, MAP_UNCACHED); } else { fbi->info.screen_base = dma_alloc_coherent(fbi->info.screen_size, DMA_ADDRESS_BROKEN); diff --git a/drivers/video/omap.c b/drivers/video/omap.c index 3603ad2ccb..884365f609 100644 --- a/drivers/video/omap.c +++ b/drivers/video/omap.c @@ -35,7 +35,7 @@ #include #include -#include +#include #include "omap.h" @@ -487,8 +487,7 @@ static int omapfb_probe(struct device_d *dev) (void __iomem *)pdata->screen->start; fbi->prealloc_screen.size = resource_size(pdata->screen); remap_range(fbi->prealloc_screen.addr, - fbi->prealloc_screen.size, - mmu_get_pte_uncached_flags()); + fbi->prealloc_screen.size, MAP_UNCACHED); } rc = omapfb_reset(fbi); diff --git a/drivers/video/stm.c b/drivers/video/stm.c index 1b42a18356..e5c1ef3974 100644 --- a/drivers/video/stm.c +++ b/drivers/video/stm.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -332,8 +332,7 @@ static int stmfb_activate_var(struct fb_info *fb_info) fb_info->screen_base = fbi->fixed_screen; fbi->memory_size = fbi->fixed_screen_size; remap_range(fbi->fixed_screen, - fbi->fixed_screen_size, - mmu_get_pte_uncached_flags()); + fbi->fixed_screen_size, MAP_UNCACHED); } else { fb_info->screen_base = dma_alloc_coherent(size, NULL); if (!fb_info->screen_base) diff --git a/include/mmu.h b/include/mmu.h new file mode 100644 index 0000000000..66b246f6d2 --- /dev/null +++ b/include/mmu.h @@ -0,0 +1,41 @@ +#ifndef __MMU_H +#define __MMU_H + +#define MAP_UNCACHED 0 +#define MAP_CACHED 1 + +/* + * Depending on the architecture the default mapping can be + * cached or uncached. Without ARCH_HAS_REMAP being set this + * is mapping type is the only one supported. + */ +#define MAP_DEFAULT MAP_ARCH_DEFAULT + +#include + +#ifndef ARCH_HAS_REMAP +static inline int arch_remap_range(void *start, size_t size, unsigned flags) +{ + if (flags == MAP_ARCH_DEFAULT) + return 0; + + return -EINVAL; +} + +static inline bool arch_can_remap(void) +{ + return false; +} +#else +static inline bool arch_can_remap(void) +{ + return true; +} +#endif + +static inline int remap_range(void *start, size_t size, unsigned flags) +{ + return arch_remap_range(start, size, flags); +} + +#endif -- cgit v1.2.3 From e96b1713eaef979a9e6fa41b2f63b05fadbabb3c Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 23 Oct 2015 11:29:59 +0200 Subject: memtest: split tests in separate functions The memtest does a bus integrity check and a moving inversions test. Split the tests into two separate functions so that the can be called separately. Signed-off-by: Sascha Hauer --- commands/memtest.c | 9 ++++++++- common/memtest.c | 36 +----------------------------------- include/memtest.h | 4 ++-- 3 files changed, 11 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/commands/memtest.c b/commands/memtest.c index db9e3dbb01..ccccc9c19e 100644 --- a/commands/memtest.c +++ b/commands/memtest.c @@ -41,7 +41,14 @@ static int __do_memtest(struct list_head *memtest_regions, 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); + ret = mem_test_bus_integrity(r->r->start, r->r->end); + if (ret < 0) + 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"); diff --git a/common/memtest.c b/common/memtest.c index 467eea546d..4a84dc3b54 100644 --- a/common/memtest.c +++ b/common/memtest.c @@ -331,8 +331,7 @@ int mem_test_bus_integrity(resource_size_t _start, return 0; } -int mem_test_dram(resource_size_t _start, - resource_size_t _end) +int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end) { volatile resource_size_t *start, num_words, offset, temp, anti_pattern; @@ -438,36 +437,3 @@ int mem_test_dram(resource_size_t _start, return 0; } - -/* - * Perform a memory test. The complete test - * loops until interrupted by ctrl-c. - * - * Prameters: - * start: start address for memory test. - * end: end address of memory test. - * bus_only: skip integrity check and do only a address/data bus - * testing. - * - * Return value can be -EINVAL for invalid parameter or -EINTR - * if memory test was interrupted. - */ -int mem_test(resource_size_t _start, - resource_size_t _end, int bus_only) -{ - int ret; - - ret = mem_test_bus_integrity(_start, _end); - - if (ret < 0) - return ret; - - /* - * We tested only the bus if != 0 - * leaving here - */ - if (!bus_only) - ret = mem_test_dram(_start, _end); - - return ret; -} diff --git a/include/memtest.h b/include/memtest.h index 1c67a73e74..3979d651d6 100644 --- a/include/memtest.h +++ b/include/memtest.h @@ -11,7 +11,7 @@ struct mem_test_resource { int mem_test_request_regions(struct list_head *list); void mem_test_release_regions(struct list_head *list); -int mem_test(resource_size_t _start, - resource_size_t _end, int bus_only); +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); #endif /* __MEMTEST_H */ -- cgit v1.2.3 From 8f2549abb7b4c4b93ee38aba5ed2156e0d4efece Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 23 Oct 2015 14:51:52 +0200 Subject: memtest: By default only test biggest region Often enough the biggest free region spans most free RAM, so it doesn't add much value to test the remaining free regions. This patch changes the default behaviour to only test the biggest free region and adds the -t option to test all regions. Signed-off-by: Sascha Hauer --- commands/memtest.c | 82 ++++++++++++++++++++++++++++++++++++------------------ common/memtest.c | 16 +++++++++++ include/memtest.h | 1 + 3 files changed, 72 insertions(+), 27 deletions(-) (limited to 'include') 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 #include -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); -- cgit v1.2.3