diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-05-13 17:48:05 +0900 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-05-13 17:48:05 +0900 |
commit | ef4ed97d6bd91aa41907181e80a7feaf2721719a (patch) | |
tree | adc44e858c150c41ebf1dd7c6ee2f6bcbac75502 /arch/sh/kernel/machine_kexec.c | |
parent | c5eb5b372e7ea18a5eeb6b5192a6369967cb1afe (diff) | |
parent | 21823259a70b7a2a21eea1d48c25a6f38896dd11 (diff) |
Merge branch 'sh/lmb'
Conflicts:
arch/sh/kernel/setup.c
Diffstat (limited to 'arch/sh/kernel/machine_kexec.c')
-rw-r--r-- | arch/sh/kernel/machine_kexec.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 0e90c7f9564..5a559e666eb 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -8,7 +8,6 @@ * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ - #include <linux/mm.h> #include <linux/kexec.h> #include <linux/delay.h> @@ -16,6 +15,7 @@ #include <linux/numa.h> #include <linux/ftrace.h> #include <linux/suspend.h> +#include <linux/lmb.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/mmu_context.h> @@ -151,3 +151,60 @@ void arch_crash_save_vmcoreinfo(void) VMCOREINFO_CONFIG(X2TLB); #endif } + +void __init reserve_crashkernel(void) +{ + unsigned long long crash_size, crash_base; + int ret; + + /* this is necessary because of lmb_phys_mem_size() */ + lmb_analyze(); + + ret = parse_crashkernel(boot_command_line, lmb_phys_mem_size(), + &crash_size, &crash_base); + if (ret == 0 && crash_size > 0) { + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size - 1; + } + + if (crashk_res.end == crashk_res.start) + goto disable; + + crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1); + if (!crashk_res.start) { + unsigned long max = lmb_end_of_DRAM() - memory_limit; + crashk_res.start = __lmb_alloc_base(crash_size, PAGE_SIZE, max); + if (!crashk_res.start) { + pr_err("crashkernel allocation failed\n"); + goto disable; + } + } else { + ret = lmb_reserve(crashk_res.start, crash_size); + if (unlikely(ret < 0)) { + pr_err("crashkernel reservation failed - " + "memory is in use\n"); + goto disable; + } + } + + crashk_res.end = crashk_res.start + crash_size - 1; + + /* + * Crash kernel trumps memory limit + */ + if ((lmb_end_of_DRAM() - memory_limit) <= crashk_res.end) { + memory_limit = 0; + pr_info("Disabled memory limit for crashkernel\n"); + } + + pr_info("Reserving %ldMB of memory at 0x%08lx " + "for crashkernel (System RAM: %ldMB)\n", + (unsigned long)(crash_size >> 20), + (unsigned long)(crashk_res.start), + (unsigned long)(lmb_phys_mem_size() >> 20)); + + return; + +disable: + crashk_res.start = crashk_res.end = 0; +} |