Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
[sfrench/cifs-2.6.git] / arch / sh / kernel / machine_kexec.c
index 0e90c7f9564f9c568cf4962d2942e6f292156935..5a559e666eb352ec2da5418a5fcbd969babbf6a1 100644 (file)
@@ -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;
+}