]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/mm/memtest.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / arch / x86 / mm / memtest.c
index 827f94044cfc30ac7faf78e56b8077fbcfe7cf92..605c8be06217b0da36344abd5f23d06326bcd87a 100644 (file)
@@ -14,18 +14,37 @@ static u64 patterns[] __initdata = {
        0xffffffffffffffffULL,
        0x5555555555555555ULL,
        0xaaaaaaaaaaaaaaaaULL,
+       0x1111111111111111ULL,
+       0x2222222222222222ULL,
+       0x4444444444444444ULL,
+       0x8888888888888888ULL,
+       0x3333333333333333ULL,
+       0x6666666666666666ULL,
+       0x9999999999999999ULL,
+       0xccccccccccccccccULL,
+       0x7777777777777777ULL,
+       0xbbbbbbbbbbbbbbbbULL,
+       0xddddddddddddddddULL,
+       0xeeeeeeeeeeeeeeeeULL,
+       0x7a6c7258554e494cULL, /* yeah ;-) */
 };
 
-static void __init memtest(unsigned long start_phys, unsigned long size,
-                          u64 pattern)
+static void __init reserve_bad_mem(u64 pattern, u64 start_bad, u64 end_bad)
 {
-       unsigned long i;
+       printk(KERN_INFO "  %016llx bad mem addr %010llx - %010llx reserved\n",
+              (unsigned long long) pattern,
+              (unsigned long long) start_bad,
+              (unsigned long long) end_bad);
+       reserve_early(start_bad, end_bad, "BAD RAM");
+}
+
+static void __init memtest(u64 pattern, u64 start_phys, u64 size)
+{
+       u64 i, count;
        u64 *start;
-       unsigned long start_bad;
-       unsigned long last_bad;
-       unsigned long start_phys_aligned;
-       unsigned long count;
-       unsigned long incr;
+       u64 start_bad, last_bad;
+       u64 start_phys_aligned;
+       size_t incr;
 
        incr = sizeof(pattern);
        start_phys_aligned = ALIGN(start_phys, incr);
@@ -37,25 +56,40 @@ static void __init memtest(unsigned long start_phys, unsigned long size,
        for (i = 0; i < count; i++)
                start[i] = pattern;
        for (i = 0; i < count; i++, start++, start_phys_aligned += incr) {
-               if (*start != pattern) {
-                       if (start_phys_aligned == last_bad + incr) {
-                               last_bad += incr;
-                       } else {
-                               if (start_bad) {
-                                       printk(KERN_CONT "\n  %016llx bad mem addr %010lx - %010lx reserved",
-                                              (unsigned long long) pattern,
-                                              start_bad, last_bad + incr);
-                                       reserve_early(start_bad, last_bad + incr, "BAD RAM");
-                               }
-                               start_bad = last_bad = start_phys_aligned;
-                       }
+               if (*start == pattern)
+                       continue;
+               if (start_phys_aligned == last_bad + incr) {
+                       last_bad += incr;
+                       continue;
                }
+               if (start_bad)
+                       reserve_bad_mem(pattern, start_bad, last_bad + incr);
+               start_bad = last_bad = start_phys_aligned;
        }
-       if (start_bad) {
-               printk(KERN_CONT "\n  %016llx bad mem addr %010lx - %010lx reserved",
-                      (unsigned long long) pattern, start_bad,
-                      last_bad + incr);
-               reserve_early(start_bad, last_bad + incr, "BAD RAM");
+       if (start_bad)
+               reserve_bad_mem(pattern, start_bad, last_bad + incr);
+}
+
+static void __init do_one_pass(u64 pattern, u64 start, u64 end)
+{
+       u64 size = 0;
+
+       while (start < end) {
+               start = find_e820_area_size(start, &size, 1);
+
+               /* done ? */
+               if (start >= end)
+                       break;
+               if (start + size > end)
+                       size = end - start;
+
+               printk(KERN_INFO "  %010llx - %010llx pattern %016llx\n",
+                      (unsigned long long) start,
+                      (unsigned long long) start + size,
+                      (unsigned long long) cpu_to_be64(pattern));
+               memtest(pattern, start, size);
+
+               start += size;
        }
 }
 
@@ -66,6 +100,9 @@ static int __init parse_memtest(char *arg)
 {
        if (arg)
                memtest_pattern = simple_strtoul(arg, NULL, 0);
+       else
+               memtest_pattern = ARRAY_SIZE(patterns);
+
        return 0;
 }
 
@@ -73,36 +110,22 @@ early_param("memtest", parse_memtest);
 
 void __init early_memtest(unsigned long start, unsigned long end)
 {
-       u64 t_start, t_size;
        unsigned int i;
-       u64 pattern;
+       unsigned int idx = 0;
 
        if (!memtest_pattern)
                return;
 
-       printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern);
+       printk(KERN_INFO "early_memtest: # of tests: %d\n", memtest_pattern);
        for (i = 0; i < memtest_pattern; i++) {
-               unsigned int idx = i % ARRAY_SIZE(patterns);
-               pattern = patterns[idx];
-               t_start = start;
-               t_size = 0;
-               while (t_start < end) {
-                       t_start = find_e820_area_size(t_start, &t_size, 1);
-
-                       /* done ? */
-                       if (t_start >= end)
-                               break;
-                       if (t_start + t_size > end)
-                               t_size = end - t_start;
-
-                       printk(KERN_CONT "\n  %010llx - %010llx pattern %d",
-                              (unsigned long long)t_start,
-                              (unsigned long long)t_start + t_size, idx);
-
-                       memtest(t_start, t_size, pattern);
-
-                       t_start += t_size;
-               }
+               idx = i % ARRAY_SIZE(patterns);
+               do_one_pass(patterns[idx], start, end);
+       }
+
+       if (idx > 0) {
+               printk(KERN_INFO "early_memtest: wipe out "
+                      "test pattern from memory\n");
+               /* additional test with pattern 0 will do this */
+               do_one_pass(0, start, end);
        }
-       printk(KERN_CONT "\n");
 }