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] " 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox