[PATCH/RFC 4/4] memtest: rewrite memtest commands
Sascha Hauer
s.hauer at pengutronix.de
Tue Mar 6 04:05:58 EST 2012
Hi Alexander,
On Fri, Mar 02, 2012 at 04:04:07PM +0100, Alexander Aring wrote:
> Rewrite memtest command:
> Skip barebox sdram regions.
> Disable cache while testing.
> Add iteration parameter.
> Check start and end addresses.
> Testing all banks if no start and end
> address are given.
>
> Signed-off-by: Alexander Aring <a.aring at phytec.de>
Since this is a complete rewrite, can you please send a patch removing
the old memtest command completely and then another one adding it again?
This would help reviewing it.
> ---
> commands/Kconfig | 9 +-
> commands/Makefile | 2 +-
> commands/memtest.c | 826 ++++++++++++++++++++++++++++++++++------------------
> 3 files changed, 553 insertions(+), 284 deletions(-)
>
> diff --git a/commands/Kconfig b/commands/Kconfig
> index e332a85..9f59d05 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -279,14 +279,9 @@ config CMD_SHA224SUM
> select SHA224
> prompt "sha224sum"
>
> -config CMD_MTEST
> +config CMD_MEMTEST
> tristate
> - prompt "mtest"
> -
> -config CMD_MTEST_ALTERNATIVE
> - bool
> - depends on CMD_MTEST
> - prompt "alternative mtest implementation"
> + prompt "memtest"
>
> endmenu
>
> diff --git a/commands/Makefile b/commands/Makefile
> index 31442b5..80ad8a3 100644
> --- a/commands/Makefile
> +++ b/commands/Makefile
> @@ -6,7 +6,7 @@ obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o
> obj-$(CONFIG_CMD_LOADS) += loads.o
> obj-$(CONFIG_CMD_ECHO) += echo.o
> obj-$(CONFIG_CMD_MEMORY) += mem.o
> -obj-$(CONFIG_CMD_MTEST) += memtest.o
> +obj-$(CONFIG_CMD_MEMTEST) += memtest.o
> obj-$(CONFIG_CMD_EDIT) += edit.o
> obj-$(CONFIG_CMD_EXEC) += exec.o
> obj-$(CONFIG_CMD_SLEEP) += sleep.o
> diff --git a/commands/memtest.c b/commands/memtest.c
> index d9c8b3d..04ad418 100644
> --- a/commands/memtest.c
> +++ b/commands/memtest.c
> @@ -1,5 +1,8 @@
> /*
> - * mtest - Perform a memory test
> + * memtest - Perform a memory test
> + *
> + * (C) Copyright 2012
> + * Alexander Aring <a.aring at phytec.de>
> *
> * (C) Copyright 2000
> * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> @@ -26,330 +29,601 @@
> #include <common.h>
> #include <command.h>
> #include <types.h>
> +#include <getopt.h>
> +#include <memory.h>
> +#include <asm/mmu.h>
> +
> +static const vu_long bitpattern[] = {
> + 0x00000001, /* single bit */
> + 0x00000003, /* two adjacent bits */
> + 0x00000007, /* three adjacent bits */
> + 0x0000000F, /* four adjacent bits */
> + 0x00000005, /* two non-adjacent bits */
> + 0x00000015, /* three non-adjacent bits */
> + 0x00000055, /* four non-adjacent bits */
> + 0xAAAAAAAA, /* alternating 1/0 */
> +};
>
> /*
> - * Perform a memory test. A more complete alternative test can be
> - * configured using CONFIG_CMD_MTEST_ALTERNATIVE. The complete test
> - * loops until interrupted by ctrl-c or by a failure of one of the
> - * sub-tests.
> + * Perform a memory test. The complete test
> + * loops until interrupted by ctrl-c.
> */
> -#ifdef CONFIG_CMD_MTEST_ALTERNATIVE
> -static int mem_test(ulong _start, ulong _end, ulong pattern_unused)
> +static int mem_test(vu_long _start, vu_long _end,
> + int bus_only)
> {
> vu_long *start = (vu_long *)_start;
> - vu_long *end = (vu_long *)_end;
> - vu_long *addr;
> - ulong val;
> - ulong readback;
> - vu_long addr_mask;
> - vu_long offset;
> - vu_long test_offset;
> - vu_long pattern;
> - vu_long temp;
> - vu_long anti_pattern;
> - vu_long num_words;
> -#ifdef CFG_MEMTEST_SCRATCH
> - vu_long *dummy = (vu_long*)CFG_MEMTEST_SCRATCH;
> -#else
> - vu_long *dummy = start;
> -#endif
> - int j;
> - int iterations = 1;
> -
> - static const ulong bitpattern[] = {
> - 0x00000001, /* single bit */
> - 0x00000003, /* two adjacent bits */
> - 0x00000007, /* three adjacent bits */
> - 0x0000000F, /* four adjacent bits */
> - 0x00000005, /* two non-adjacent bits */
> - 0x00000015, /* three non-adjacent bits */
> - 0x00000055, /* four non-adjacent bits */
> - 0xaaaaaaaa, /* alternating 1/0 */
> - };
> -
> - /* XXX: enforce alignment of start and end? */
> - for (;;) {
> - if (ctrlc()) {
> - putchar ('\n');
> - return 1;
> + /* Point the dummy to start[1] */
> + vu_long *dummy = start+1;
<nitpick> Please add space on both sides of '+' </nitpick>
> +
> + vu_long val;
> + vu_long readback;
> + vu_long offset;
> + vu_long pattern;
> + vu_long test_offset;
> + vu_long temp;
> + vu_long anti_pattern;
> + vu_long num_words;
> +
> + int i;
> + int ret;
> +
> + num_words = (_end - _start)/sizeof(vu_long);
ditto here.
> +
> + /* Exit if ctrl-c is pressed */
> + if (ctrlc()) {
> + printf("Memtest interrupted.\n");
> + return -1;
> + }
> +
> + printf("Starting data line test.\n");
> +
> + /*
> + * Data line test: write a pattern to the first
> + * location, write the 1's complement to a 'parking'
> + * address (changes the state of the data bus so a
> + * floating bus doen't give a false OK), and then
> + * read the value back. Note that we read it back
> + * into a variable because the next time we read it,
> + * it might be right (been there, tough to explain to
> + * the quality guys why it prints a failure when the
> + * "is" and "should be" are obviously the same in the
> + * error message).
> + *
> + * Rather than exhaustively testing, we test some
> + * patterns by shifting '1' bits through a field of
> + * '0's and '0' bits through a field of '1's (i.e.
> + * pattern and ~pattern).
> + */
> + for (i = 0; i < sizeof(bitpattern)/
> + sizeof(bitpattern[0]); i++) {
> + ret = address_in_sdram_regions((vu_long)start);
> + if (ret) {
> + printf("WARNING (data line): "
> + "address 0x%08lx is in sdram regions.\n",
> + (vu_long)start);
> + break;
> + }
> +
> + ret = address_in_sdram_regions((vu_long)dummy);
> + if (ret) {
> + printf("WARNING (data line): "
> + "address 0x%08lx is in sdram regions.\n",
> + (vu_long)dummy);
> + break;
> }
>
> - printf("Iteration: %6d\r", iterations);
> - iterations++;
> -
> - /*
> - * Data line test: write a pattern to the first
> - * location, write the 1's complement to a 'parking'
> - * address (changes the state of the data bus so a
> - * floating bus doen't give a false OK), and then
> - * read the value back. Note that we read it back
> - * into a variable because the next time we read it,
> - * it might be right (been there, tough to explain to
> - * the quality guys why it prints a failure when the
> - * "is" and "should be" are obviously the same in the
> - * error message).
> - *
> - * Rather than exhaustively testing, we test some
> - * patterns by shifting '1' bits through a field of
> - * '0's and '0' bits through a field of '1's (i.e.
> - * pattern and ~pattern).
> - */
> - addr = start;
> - /* XXX */
> - if (addr == dummy) ++addr;
> - for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
> - val = bitpattern[j];
> - for(; val != 0; val <<= 1) {
> - *addr = val;
> - *dummy = ~val; /* clear the test data off of the bus */
> - readback = *addr;
> - if(readback != val) {
> - printf ("FAILURE (data line): "
> - "expected 0x%08lx, actual 0x%08lx at address 0x%p\n",
> - val, readback, addr);
> + val = bitpattern[i];
> +
> + for (; val != 0; val <<= 1) {
> + *start = val;
> + /* clear the test data off of the bus */
> + *dummy = ~val;
> + readback = *start;
> +
> + if (readback != val) {
> + printf("FAILURE (data line): "
> + "expected 0x%08lx, actual 0x%08lx at address 0x%08lx.\n",
> + val, readback, (vu_long)start);
> + return -1;
> }
> - *addr = ~val;
> - *dummy = val;
> - readback = *addr;
> - if(readback != ~val) {
> - printf ("FAILURE (data line): "
> - "Is 0x%08lx, should be 0x%08lx at address 0x%p\n",
> - readback, ~val, addr);
> +
> + *start = ~val;
> + *dummy = val;
> + readback = *start;
> + if (readback != ~val) {
> + printf("FAILURE (data line): "
> + "Is 0x%08lx, should be 0x%08lx at address 0x%08lx.\n",
> + readback,
> + ~val, (vu_long)start);
> + return -1;
> }
> - }
> }
> + }
> +
>
> - /*
> - * Based on code whose Original Author and Copyright
> - * information follows: Copyright (c) 1998 by Michael
> - * Barr. This software is placed into the public
> - * domain and may be used for any purpose. However,
> - * this notice must not be changed or removed and no
> - * warranty is either expressed or implied by its
> - * publication or distribution.
> - */
> -
> - /*
> - * Address line test
> - *
> - * Description: Test the address bus wiring in a
> - * memory region by performing a walking
> - * 1's test on the relevant bits of the
> - * address and checking for aliasing.
> - * This test will find single-bit
> - * address failures such as stuck -high,
> - * stuck-low, and shorted pins. The base
> - * address and size of the region are
> - * selected by the caller.
> - *
> - * Notes: For best results, the selected base
> - * address should have enough LSB 0's to
> - * guarantee single address bit changes.
> - * For example, to test a 64-Kbyte
> - * region, select a base address on a
> - * 64-Kbyte boundary. Also, select the
> - * region size as a power-of-two if at
> - * all possible.
> - *
> - * Returns: 0 if the test succeeds, 1 if the test fails.
> - *
> - * ## NOTE ## Be sure to specify start and end
> - * addresses such that addr_mask has
> - * lots of bits set. For example an
> - * address range of 01000000 02000000 is
> - * bad while a range of 01000000
> - * 01ffffff is perfect.
> - */
> - addr_mask = ((ulong)end - (ulong)start)/sizeof(vu_long);
> - pattern = (vu_long) 0xaaaaaaaa;
> - anti_pattern = (vu_long) 0x55555555;
> -
> - debug("%s:%d: addr mask = 0x%.8lx\n",
> - __FUNCTION__, __LINE__,
> - addr_mask);
> - /*
> - * Write the default pattern at each of the
> - * power-of-two offsets.
> - */
> - for (offset = 1; (offset & addr_mask) != 0; offset <<= 1)
> - start[offset] = pattern;
> -
> - /*
> - * Check for address bits stuck high.
> - */
> - test_offset = 0;
> + /*
> + * Based on code whose Original Author and Copyright
> + * information follows: Copyright (c) 1998 by Michael
> + * Barr. This software is placed into the public
> + * domain and may be used for any purpose. However,
> + * this notice must not be changed or removed and no
> + * warranty is either expressed or implied by its
> + * publication or distribution.
> + */
> +
> + /*
> + * Address line test
> + *
> + * Description: Test the address bus wiring in a
> + * memory region by performing a walking
> + * 1's test on the relevant bits of the
> + * address and checking for aliasing.
> + * This test will find single-bit
> + * address failures such as stuck -high,
> + * stuck-low, and shorted pins. The base
> + * address and size of the region are
> + * selected by the caller.
> + *
> + * Notes: For best results, the selected base
> + * address should have enough LSB 0's to
> + * guarantee single address bit changes.
> + * For example, to test a 64-Kbyte
> + * region, select a base address on a
> + * 64-Kbyte boundary. Also, select the
> + * region size as a power-of-two if at
> + * all possible.
> + *
> + * ## NOTE ## Be sure to specify start and end
> + * addresses such that num_words has
> + * lots of bits set. For example an
> + * address range of 01000000 02000000 is
> + * bad while a range of 01000000
> + * 01ffffff is perfect.
> + */
> +
> + pattern = 0xAAAAAAAA;
> + anti_pattern = 0x55555555;
> +
> + /*
> + * Write the default pattern at each of the
> + * power-of-two offsets.
> + */
> + for (offset = 1; (offset & num_words) != 0; offset <<= 1) {
> + ret = address_in_sdram_regions((vu_long)&start[offset]);
> + if (ret) {
> + printf("WARNING (stuck high): "
> + "address 0x%08lx is in sdram regions.\n",
> + (vu_long)&start[offset]);
> + continue;
> + }
> +
> + start[offset] = pattern;
> + }
> +
> + printf("Check for address bits stuck high.\n");
> +
> + /*
> + * Check for address bits stuck high.
> + */
> + test_offset = 0;
> +
> + ret = address_in_sdram_regions((vu_long)&start[test_offset]);
> + if (ret)
> + printf("WARNING (stuck high): "
> + "address 0x%08lx is in sdram regions.\n",
> + (vu_long)&start[test_offset]);
> + else
> start[test_offset] = anti_pattern;
>
> - for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
> - temp = start[offset];
> - if (temp != pattern) {
> - printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
> - " expected 0x%.8lx, actual 0x%.8lx\n",
> - (ulong)&start[offset], pattern, temp);
> - return 1;
> - }
> + for (offset = 1; (offset & num_words) != 0; offset <<= 1) {
> + ret = address_in_sdram_regions((vu_long)&start[offset]);
> + if (ret) {
> + printf("WARNING (stuck high): "
> + "address 0x%08lx is in sdram regions.\n",
> + (vu_long)&start[offset]);
> + continue;
> + }
> +
> + temp = start[offset];
> +
> + if (temp != pattern) {
> + printf("FAILURE: Address bit "
> + "stuck high @ 0x%08lx:"
> + " expected 0x%08lx, actual 0x%08lx.\n",
> + (vu_long)&start[offset],
> + pattern, temp);
> + return -1;
> }
> + }
> +
> + ret = address_in_sdram_regions((vu_long)&start[test_offset]);
> + if (ret)
> + printf("WARNING (stuck high): "
> + "address 0x%08lx is in sdram regions.\n",
> + (vu_long)&start[test_offset]);
> + else
> start[test_offset] = pattern;
>
> - /*
> - * Check for addr bits stuck low or shorted.
> - */
> - for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
> - start[test_offset] = anti_pattern;
> + printf("Check for address bits stuck "
> + "low or shorted.\n");
> +
> + /*
> + * Check for address bits stuck low or shorted.
> + */
> + for (test_offset = 1;
> + (test_offset & num_words) != 0;
> + test_offset <<= 1) {
> + ret = address_in_sdram_regions(
> + (vu_long)&start[test_offset]);
> + if (ret) {
> + printf("WARNING (low high): "
> + "address 0x%08lx is in barebox regions.\n",
> + (vu_long)&start[test_offset]);
> + continue;
> + }
> +
> + start[test_offset] = anti_pattern;
> +
> + for (offset = 1; (offset & num_words) != 0; offset <<= 1) {
> + ret = address_in_sdram_regions(
> + (vu_long)&start[offset]);
> + if (ret) {
> + printf("WARNING (low high): "
> + "address 0x%08lx is in barebox regions.\n",
> + (vu_long)&start[test_offset]);
> + continue;
> + }
>
> - for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
> temp = start[offset];
> - if ((temp != pattern) && (offset != test_offset)) {
> - printf ("\nFAILURE: Address bit stuck low or shorted @"
> - " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
> - (ulong)&start[offset], pattern, temp);
> - return 1;
> +
> + if ((temp != pattern) &&
> + (offset != test_offset)) {
> + printf("FAILURE: Address bit stuck"
> + " low or shorted @"
> + " 0x%08lx: expected 0x%08lx, actual 0x%08lx.\n",
> + (vu_long)&start[offset],
> + pattern, temp);
> + return -1;
> }
> - }
> - start[test_offset] = pattern;
> }
> + start[test_offset] = pattern;
> + }
> +
> + /* We tested only the bus if != 0
> + * leaving here */
> + if (bus_only)
> + return 0;
> +
> + printf("Starting integrity check of physicaly ram.\n"
> + "Filling ram with patterns...\n");
> +
> + /*
> + * Description: Test the integrity of a physical
> + * memory device by performing an
> + * increment/decrement test over the
> + * entire region. In the process every
> + * storage bit in the device is tested
> + * as a zero and a one. The base address
> + * and the size of the region are
> + * selected by the caller.
> + */
> +
> + /*
> + * Fill memory with a known pattern.
> + */
> + for (offset = 0; offset < (num_words); offset++) {
> + ret = address_in_sdram_regions((vu_long)&start[offset]);
> + if (ret)
> + continue;
> +
> + start[offset] = offset+1;
> + }
>
> - /*
> - * Description: Test the integrity of a physical
> - * memory device by performing an
> - * increment/decrement test over the
> - * entire region. In the process every
> - * storage bit in the device is tested
> - * as a zero and a one. The base address
> - * and the size of the region are
> - * selected by the caller.
> - *
> - * Returns: 0 if the test succeeds, 1 if the test fails.
> - */
> - num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
> -
> - /*
> - * Fill memory with a known pattern.
> - */
> - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
> - start[offset] = pattern;
> + printf("Compare written patterns...\n");
> +
> + /*
> + * Check each location and invert it for the second pass.
> + */
> + for (offset = 0; offset < num_words; offset++) {
> + ret = address_in_sdram_regions((vu_long)&start[offset]);
> + if (ret)
> + continue;
> +
> + temp = start[offset];
> + if (temp != (offset+1)) {
> + printf("FAILURE (read/write) @ 0x%08lx:"
> + " expected 0x%08lx, actual 0x%08lx.\n",
> + (vu_long)&start[offset],
> + (offset+1), temp);
> + return -1;
> }
>
> - /*
> - * Check each location and invert it for the second pass.
> - */
> - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
> - temp = start[offset];
> - if (temp != pattern) {
> - printf ("\nFAILURE (read/write) @ 0x%.8lx:"
> - " expected 0x%.8lx, actual 0x%.8lx)\n",
> - (ulong)&start[offset], pattern, temp);
> - return 1;
> - }
> + anti_pattern = ~(offset+1);
> + start[offset] = anti_pattern;
> + }
>
> - anti_pattern = ~pattern;
> - start[offset] = anti_pattern;
> + printf("Filling ram with inverted pattern and compare it...\n");
> +
> + /*
> + * Check each location for the inverted pattern and zero it.
> + */
> + for (offset = 0; offset < num_words; offset++) {
> + ret = address_in_sdram_regions((vu_long)&start[offset]);
> + /* Step over barebox mem usage */
> + if (ret)
> + continue;
> +
> + anti_pattern = ~(offset+1);
> + temp = start[offset];
> +
> + if (temp != anti_pattern) {
> + printf("FAILURE (read/write): @ 0x%08lx:"
> + " expected 0x%08lx, actual 0x%08lx.\n",
> + (vu_long)&start[offset],
> + anti_pattern, temp);
> + return -1;
> }
>
> - /*
> - * Check each location for the inverted pattern and zero it.
> - */
> - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
> - anti_pattern = ~pattern;
> - temp = start[offset];
> - if (temp != anti_pattern) {
> - printf ("\nFAILURE (read/write): @ 0x%.8lx:"
> - " expected 0x%.8lx, actual 0x%.8lx)\n",
> - (ulong)&start[offset], anti_pattern, temp);
> - return 1;
> - }
> - start[offset] = 0;
> - }
> + start[offset] = 0;
> }
>
> + return 0;
> }
> -#else
> -static int mem_test(ulong _start, ulong _end, ulong pattern)
> +
> +#ifdef CONFIG_MMU
> +static void print_region(vu_long start, vu_long size, uint32_t flags)
> {
> - vu_long *addr;
> - vu_long *start = (vu_long *)_start;
> - vu_long *end = (vu_long *)_end;
> - ulong val;
> - ulong readback;
> - ulong incr;
> - int rcode;
> -
> - incr = 1;
> - for (;;) {
> - if (ctrlc()) {
> - putchar('\n');
> - return 1;
> + if (!size)
> + return;
> +
> + switch (flags) {
> + case PTE_FLAGS_UNCACHED:
> + printf("Set non caching region at 0x%08lx until"
> + " 0x%08lx size 0x%08lx.\n", start,
> + start + size, size);
> + break;
> + case PTE_FLAGS_CACHED:
> + printf("Set caching region at 0x%08lx until"
> + " 0x%08lx size 0x%08lx.\n", start,
> + start + size, size);
> + break;
> + default:
> + /* This should never happen. */
> + BUG();
> + break;
> + }
> +}
> +
> +static void do_remap_range(struct memory_bank *bank, uint32_t flags)
> +{
> + struct resource *r = NULL;
> + struct resource *r_prev = NULL;
> +
> + vu_long size;
> + vu_long start;
> + vu_long end;
> +
> + list_for_each_entry(r, &bank->res->children, sibling) {
> + /* Do on head element for bank boundary */
> + if (r->sibling.prev == &bank->res->children) {
> + start = bank->start;
> + end = r->start;
> + size = end - start;
> +
> + size = PAGE_ALIGN(size);
> + start = PAGE_ALIGN(start);
> +
> + print_region(start, size, flags);
> + remap_range((void *)start, size, flags);
> +
> + /* remember last used element */
> + r_prev = r;
> + continue;
> }
> + /* Between used regions */
> + start = r_prev->start + r_prev->size;
> + end = r->start;
> + size = end - start;
> +
> +
> + size = PAGE_ALIGN(size);
> + start = PAGE_ALIGN(start);
>
> - printf ("\rPattern 0x%08lX Writing..."
> - "%12s"
> - "\b\b\b\b\b\b\b\b\b\b",
> - pattern, "");
> + print_region(start, size, flags);
> + remap_range((void *)start, size, flags);
>
> - for (addr=start,val=pattern; addr<end; addr++) {
> - *addr = val;
> - val += incr;
> + r_prev = r;
> + /* Do on head element for bank boundary */
> + if (list_is_last(&r->sibling, &bank->res->children)) {
> + start = r->start + r->size;
> + end = bank->start + bank->size;
> + size = end - start;
> +
> + size = PAGE_ALIGN(size);
> + start = PAGE_ALIGN(start);
> +
> + print_region(start, size, flags);
> + remap_range((void *)start, size, flags);
> }
> + }
> +}
> +#endif
>
> - puts ("Reading...");
> +static int do_mem_memtest(struct command *cmdtp, int argc, char *argv[])
> +{
> + vu_long start = 0;
> + vu_long end = 0;
> +
> + uint i;
> + uint max_i = 1;
> +
> + int bus_only = 0;
> + int err = 0;
> + int cnt = 0;
> + int opt;
> +
> + struct memory_bank *bank = NULL;
> + struct resource *r = NULL;
> +
> + while ((opt = getopt(argc, argv, "s:e:i:b")) > 0) {
> + switch (opt) {
> + case 's':
> + start = simple_strtoul(optarg, NULL, 0);
> + break;
> + case 'e':
> + end = simple_strtoul(optarg, NULL, 0);
> + break;
> + case 'i':
> + max_i = simple_strtoul(optarg, NULL, 0);
> + break;
> + case 'b':
> + bus_only = 1;
> + break;
> + default:
> + return COMMAND_ERROR_USAGE;
> + }
> + }
>
> - for (addr=start,val=pattern; addr<end; addr++) {
> - readback = *addr;
> - if (readback != val) {
> - printf ("\nMem error @ 0x%08X: "
> - "found 0x%08lX, expected 0x%08lX\n",
> - (uint)addr, readback, val);
> - rcode = 1;
> + if (optind > argc)
> + return COMMAND_ERROR_USAGE;
> +
> + /* Error if no end address */
> + if (start && !end) {
> + printf("Please add a end address.\n");
> + return 1;
> + }
> +
> + /* Error if no start address */
> + if (end && !start) {
> + printf("Please add a start address.\n");
> + return 1;
> + }
> +
> + /* Check parameters */
> + if (end && start) {
> + /* We need a even number to start, so we clear the first bit */
> + start &= ~0x1;
> +
> + if (end <= start) {
> + printf("End address less than or"
> + " equal start address.\n");
> + return 1;
> + }
> +
> + for_each_memory_bank(bank) {
> + if (ADDRESS_IN_REGIONS(start, bank->start,
> + bank->start + bank->size + 1)) {
> + cnt++;
> + }
> +
> + if (ADDRESS_IN_REGIONS(end, bank->start,
> + bank->start + bank->size + 1)) {
> + cnt++;
> }
> - val += incr;
> }
>
> - /*
> - * Flip the pattern each time to make lots of zeros and
> - * then, the next time, lots of ones. We decrement
> - * the "negative" patterns and increment the "positive"
> - * patterns to preserve this feature.
> - */
> - if(pattern & 0x80000000) {
> - pattern = -pattern; /* complement & increment */
> + if (cnt != 2) {
> + printf("Start or end addresses are"
> + " not in any ram bank.\n");
> + return 1;
> }
> - else {
> - pattern = ~pattern;
> + }
> +
> +
> + for_each_memory_bank(bank) {
> + list_for_each_entry(r, &bank->res->children, sibling) {
> + printf("Will skipping region at 0x%08x"
> + " until 0x%08x size 0x%08x name %s.\n",
> + r->start, r->size + r->start,
> + r->size, r->name);
> }
> - incr = -incr;
> +
> +#ifdef CONFIG_MMU
> + /* Disable caching */
> + do_remap_range(bank, PTE_FLAGS_UNCACHED);
> +#endif
> }
> - return rcode;
> -}
> +
> + /* Do test if we set a start or end address */
> + if (start && end) {
> + printf("Testing address range: 0x%08lx until "
> + "0x%08lx.\n",
> + start, end);
> +
> + for (i = 1; (i <= max_i) || !max_i; i++) {
> + printf("Iteration: %u\n", i);
> +
> + /* Do the memtest */
> + err = mem_test(start, end, bus_only);
> +
> + if (err < 0) {
> + printf("Test failed.\n");
> + goto err;
> + }
> + }
> + printf("Tested %u iteration(s) without errors.\n", i-1);
> +#ifdef CONFIG_MMU
> + /* Enable caching */
> + for_each_memory_bank(bank)
> + do_remap_range(bank, PTE_FLAGS_CACHED);
> #endif
You can't do this as this will remap everything we alloced with
dma_alloc_coherent cached again. You have to do this the same way
you remap it uncached. It's probably best to add a seperate function for
this and pass PTE_FLAGS_* as parameter.
I'll have a closer look at the patch again when you resend it. It's a
bit hard to see the end result when a whole file is rewritten and sent
as a patch.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the barebox
mailing list