From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Alexander Aring <alex.aring@gmail.com>
Cc: barebox@lists.infradead.org
Subject: Re: [PATCH 6/6] commands: add new memtest command
Date: Thu, 07 Feb 2013 11:56:07 +0100 [thread overview]
Message-ID: <51138847.8080100@pengutronix.de> (raw)
In-Reply-To: <1360233900-26486-7-git-send-email-alex.aring@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 11397 bytes --]
On 02/07/2013 11:45 AM, Alexander Aring wrote:
> Add new memtest command which can enable or disable caching
> on non allocted barebox regions(test area).
>
> This command simply parse and check parameters then call
> the mem_test routine.
>
> If no address parameters are given then mem_test will call
> for each memory bank.
>
> Signed-off-by: Alexander Aring <alex.aring@gmail.com>
A howto-get-rid-of-ifdef nitpick inline
> ---
> commands/Kconfig | 10 ++
> commands/Makefile | 1 +
> commands/memtest.c | 362 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 373 insertions(+)
> create mode 100644 commands/memtest.c
>
> diff --git a/commands/Kconfig b/commands/Kconfig
> index 7cc759c..d158c3f 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -516,6 +516,16 @@ config CMD_NANDTEST
> select PARTITION_NEED_MTD
> prompt "nandtest"
>
> +config CMD_MEMTEST
> + tristate
> + select MEMTEST
> + prompt "memtest"
> + help
> + This command enables a memtest to test installed memory.
> + During this test allocated iomem regions will be skipped.
> + If tested architecture has MMU with PTE flags support,
> + caching can be set enabled or disabled.
> +
> endmenu
>
> menu "video command"
> diff --git a/commands/Makefile b/commands/Makefile
> index 393ba51..b39b489 100644
> --- a/commands/Makefile
> +++ b/commands/Makefile
> @@ -7,6 +7,7 @@ obj-$(CONFIG_CMD_LOADY) += loadxy.o
> obj-$(CONFIG_CMD_LOADS) += loads.o
> obj-$(CONFIG_CMD_ECHO) += echo.o
> obj-$(CONFIG_CMD_MEMORY) += mem.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
> new file mode 100644
> index 0000000..22e8006
> --- /dev/null
> +++ b/commands/memtest.c
> @@ -0,0 +1,362 @@
> +/*
> + * memtest - Perform a memory test
> + *
> + * (C) Copyright 2013
> + * Alexander Aring <aar@pengutronix.de>, Pengutronix
> + *
> + * (C) Copyright 2000
> + * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <command.h>
> +#include <getopt.h>
> +#include <asm/mmu.h>
> +
> +#include <memory_test.h>
> +
> +/*
> + * In CONFIG_MMU we have a special c flag.
> + */
> +#ifdef CONFIG_MMU
> +static char optstr[] = "s:e:i:cb";
const?
> +
> +/*
> + * PTE flags variables to set cached and
> + * uncached regions.
> + */
> +static uint32_t pte_flags_cached;
> +static uint32_t pte_flags_uncached;
> +#else
> +static char optstr[] = "s:e:i:b";
const?
> +#endif
> +
> +#ifdef CONFIG_MMU
Can
> +static void print_region(vu_long start, vu_long size, uint32_t flags)
> +{
> + if (!size)
> + return;
> +
> + printf("\t0x%08lx - "
> + "0x%08lx (size 0x%08lx)\n",
> + start, start + size - 1, size);
> +}
> +
> +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;
> +
> + if (flags == pte_flags_uncached)
> + printf("Set non caching regions:\n");
> + else if (flags == pte_flags_cached)
> + printf("Set caching regions:\n");
> + else
> + BUG();
> +
> + /*
> + * We assume that the regions are sorted in this list
> + */
> + list_for_each_entry(r, &bank->res->children, sibling) {
> + /*
> + * Do on head element for bank boundary
> + */
> + if (r->sibling.prev == &bank->res->children) {
> + /*
> + * remember last used element
> + */
> + r_prev = r;
> +
> + start = PAGE_ALIGN(bank->start);
> + end = PAGE_ALIGN_DOWN(r->start) - 1;
> + if (start >= end)
> + continue;
> + size = end - start + 1;
> +
> + print_region(start, size, flags);
> + remap_range((void *)start, size, flags);
> +
> + continue;
> + }
> + /*
> + * Between used regions
> + */
> + start = PAGE_ALIGN(r_prev->end);
> + end = PAGE_ALIGN_DOWN(r->start) - 1;
> + if (start < end) {
> + size = end - start + 1;
> + print_region(start, size, flags);
> + remap_range((void *)start, size, flags);
> + }
> +
> + r_prev = r;
> + /*
> + * Do on head element for bank boundary
> + */
> + if (list_is_last(&r->sibling, &bank->res->children)) {
> + start = PAGE_ALIGN(r->end);
> + end = PAGE_ALIGN_DOWN(bank->start + bank->size) - 1;
> + if (start >= end)
> + continue;
> + size = end - start + 1;
> +
> + print_region(start, size, flags);
> + remap_range((void *)start, size, flags);
> + }
> + }
> +}
> +#endif
> +
> +static int do_mem_memtest(int argc, char *argv[])
> +{
> + /*
> + * Set start address to 0xffffffff which
> + * can't be.
> + */
> + vu_long start = 0xffffffff;
> + vu_long end = 0;
> +
> + uint i;
> + uint max_i = 1;
> +
> +#ifdef CONFIG_MMU
> + int cache = 0;
> +#endif
> + 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, optstr)) > 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;
> +#ifdef CONFIG_MMU
> + case 'c':
> + cache = 1;
> + break;
> +#endif
> + case 'b':
> + bus_only = 1;
> + break;
> + default:
> + return COMMAND_ERROR_USAGE;
> + }
> + }
> +
> + if (optind > argc)
> + return COMMAND_ERROR_USAGE;
> +
> + /*
> + * Error if no end address
> + */
> + if (start != 0xffffffff && !end) {
> + printf("Please add an end address.\n");
> + return 1;
> + }
> +
> + /*
> + * Error if no start address
> + */
> + if (end && start == 0xffffffff) {
> + printf("Please add a start address.\n");
> + return 1;
> + }
> +
> + /*
> + * Check parameters
> + */
> + if (start != 0xffffffff && end) {
> + if (end <= start) {
> + printf("End address less than or"
> + " equal start address.\n");
> + return 1;
> + }
> +
> + /*
> + * Check if given start and end address are in any banks
> + */
> + for_each_memory_bank(bank) {
> + if (ADDRESS_IN_REGIONS(start, bank->start,
> + bank->start + bank->size))
> + cnt++;
> +
> + if (ADDRESS_IN_REGIONS(end, bank->start,
> + bank->start + bank->size))
> + cnt++;
> + }
> +
> + if (cnt != 2) {
> + printf("Start or end addresses are"
> + " not in any ram bank.\n");
> + return 1;
> + }
> + }
> +
> +#ifdef CONFIG_MMU
> + /*
> + * Get pte flags. Which are configured at
> + * runtime at booting.
> + */
> + pte_flags_cached = mmu_get_pte_cached_flags();
> + pte_flags_uncached = mmu_get_pte_uncached_flags();
> +#endif
> +
> + printf("Skipping regions:\n");
> + for_each_memory_bank(bank) {
> + list_for_each_entry(r, &bank->res->children, sibling)
> + printf("\t0x%08x - "
> + "0x%08x (size 0x%08x) %s\n",
> + r->start, r->end,
> + r->end - r->start + 1, r->name);
> +#ifdef CONFIG_MMU
Use if (IS_ENABLED(CONFIG_MMU) and you can get rid of most ifdefs
Marc
> + /*
> + * Disable or enable caching
> + */
> + if (cache)
> + do_remap_range(bank, pte_flags_cached);
> + else
> + do_remap_range(bank, pte_flags_uncached);
> +#endif
> + }
> +
> + /*
> + * Do test if we set a start or end address
> + */
> + if (start != 0xffffffff && end) {
> + printf("Testing address range:\n\t0x%08lx - 0x%08lx"
> + " (size 0x%08lx)\n",
> + start, end, end - start + 1);
> +
> + 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 == -EINTR) {
> + printf("Test interrupted.\n");
> + goto err;
> + }
> +
> + if (err < 0) {
> + printf("Test failed.\n");
> + goto err;
> + }
> + printf("Tested %u iteration(s) without errors.\n", i);
> + }
> +#ifdef CONFIG_MMU
> + /*
> + * Renable caching
> + */
> + if (!cache)
> + for_each_memory_bank(bank)
> + do_remap_range(bank, pte_flags_cached);
> +#endif
> + printf("Memtest done.\n");
> +
> + return 0;
> + }
> +
> + /*
> + * If we set no start or end address
> + * we do the test on all ram banks
> + */
> + for (i = 1; (i <= max_i) || !max_i; i++) {
> + for_each_memory_bank(bank) {
> + start = bank->start;
> + end = bank->start + bank->size - 1;
> +
> + printf("Iteration: %u\n", i);
> +
> + printf("Testing address range:\n\t0x%08lx - "
> + "0x%08lx (size 0x%08lx) on bank /dev/%s\n",
> + start, end, bank->size,
> + bank->res->name);
> +
> + err = mem_test(start, end, bus_only);
> + if (err == -EINTR) {
> + printf("Test interrupted.\n");
> + goto err;
> + }
> +
> + if (err < 0) {
> + printf("Test on bank /dev/%s failed.\n",
> + bank->res->name);
> + goto err;
> + }
> + printf("Tested %u iteration(s) without errors.\n", i);
> + }
> + }
> +#ifdef CONFIG_MMU
> + /*
> + * Renable caching
> + */
> + if (!cache)
> + for_each_memory_bank(bank)
> + do_remap_range(bank, pte_flags_cached);
> +#endif
> + printf("Memtest done.\n");
> +
> + return 0;
> +
> +err:
> +#ifdef CONFIG_MMU
> + /*
> + * Enable caching
> + */
> + for_each_memory_bank(bank)
> + do_remap_range(bank, pte_flags_cached);
> +#endif
> +
> + return 1;
> +}
> +
> +static const __maybe_unused char cmd_memtest_help[] =
> +"Usage: memtest [OPTION]...\n"
> +"memtest related commands\n"
> +" -s <start> start address to begin memtest.\n"
> +" -e <end> end address to stop memtest.\n"
> +" -i <iterations> iterations [default=1, endless=0].\n"
> +#ifdef CONFIG_MMU
> +" -c run test with enable cache.\n"
> +#endif
> +" -b only test bus datalines.";
> +
> +BAREBOX_CMD_START(memtest)
> + .cmd = do_mem_memtest,
> + .usage = "Memory Test",
> + BAREBOX_CMD_HELP(cmd_memtest_help)
> +BAREBOX_CMD_END
>
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]
[-- Attachment #2: Type: text/plain, Size: 149 bytes --]
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2013-02-07 10:56 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-07 10:44 [PATCH v3 0/6] add new memtest command Alexander Aring
2013-02-07 10:44 ` [PATCH 1/6] common: fix codestyle in ALIGN macros Alexander Aring
2013-02-07 10:44 ` [PATCH 2/6] common: add ALIGN_DOWN macro Alexander Aring
2013-02-07 10:44 ` [PATCH 3/6] memory: add function address_in_sdram_regions Alexander Aring
2013-02-07 10:44 ` [PATCH 4/6] memtest: remove memtest command Alexander Aring
2013-02-07 10:44 ` [PATCH 5/6] common: add mem_test routine Alexander Aring
2013-02-07 10:52 ` Marc Kleine-Budde
2013-02-07 11:16 ` Alexander Aring
2013-02-07 11:00 ` Sascha Hauer
2013-02-07 11:40 ` Alexander Aring
2013-02-07 11:54 ` Sascha Hauer
2013-02-07 15:41 ` Alexander Aring
2013-02-07 10:45 ` [PATCH 6/6] commands: add new memtest command Alexander Aring
2013-02-07 10:56 ` Marc Kleine-Budde [this message]
2013-02-07 11:20 ` Alexander Aring
2013-02-07 12:01 ` Sascha Hauer
2013-02-07 15:42 ` Alexander Aring
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51138847.8080100@pengutronix.de \
--to=mkl@pengutronix.de \
--cc=alex.aring@gmail.com \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.