Unverified Commit 2fe8ea39 authored by Dengcheng Zhu's avatar Dengcheng Zhu Committed by Paul Burton
Browse files

MIPS: kexec: Use prepare method from Generic for UHI platforms



Out-of-tree platforms may not be based on Generic as shown in customer
communication. Share the prepare method with all using UHI boot protocol,
and put into machine_kexec.c.

The benefit is that, when having kexec_args related problems, developers
will naturally look into machine_kexec.c, where "CONFIG_UHI_BOOT" will be
found, prompting them to add "select UHI_BOOT" to the platform Kconfig. It
would otherwise require a lot debugging or online searching to be aware
that the solution is in Generic code.

Tested-by: default avatarRachel Mozes <rachel.mozes@intel.com>
Reported-by: default avatarRachel Mozes <rachel.mozes@intel.com>
Signed-off-by: default avatarDengcheng Zhu <dzhu@wavecomp.com>
Signed-off-by: default avatarPaul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/20569/
Cc: pburton@wavecomp.com
Cc: ralf@linux-mips.org
Cc: linux-mips@linux-mips.org
parent a6da4d6f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ config MIPS_GENERIC
	select USB_UHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
	select USB_UHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
	select USE_OF
	select UHI_BOOT
	help
	  Select this to build a kernel which aims to support multiple boards,
	  generally using a flattened device tree passed from the bootloader
@@ -2899,6 +2900,9 @@ config USE_OF
	select OF_EARLY_FLATTREE
	select IRQ_DOMAIN

config UHI_BOOT
	bool

config BUILTIN_DTB
	bool

+0 −1
Original line number Diff line number Diff line
@@ -15,5 +15,4 @@ obj-y += proc.o
obj-$(CONFIG_YAMON_DT_SHIM)		+= yamon-dt.o
obj-$(CONFIG_LEGACY_BOARD_SEAD3)	+= board-sead3.o
obj-$(CONFIG_LEGACY_BOARD_OCELOT)	+= board-ocelot.o
obj-$(CONFIG_KEXEC)			+= kexec.o
obj-$(CONFIG_VIRT_BOARD_RANCHU)		+= board-ranchu.o

arch/mips/generic/kexec.c

deleted100644 → 0
+0 −44
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 Imagination Technologies
 * Author: Marcin Nowakowski <marcin.nowakowski@mips.com>
 *
 * 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.
 */

#include <linux/kexec.h>
#include <linux/libfdt.h>
#include <linux/uaccess.h>

static int generic_kexec_prepare(struct kimage *image)
{
	int i;

	for (i = 0; i < image->nr_segments; i++) {
		struct fdt_header fdt;

		if (image->segment[i].memsz <= sizeof(fdt))
			continue;

		if (copy_from_user(&fdt, image->segment[i].buf, sizeof(fdt)))
			continue;

		if (fdt_check_header(&fdt))
			continue;

		kexec_args[0] = -2;
		kexec_args[1] = (unsigned long)
			phys_to_virt((unsigned long)image->segment[i].mem);
		break;
	}
	return 0;
}

static int __init register_generic_kexec(void)
{
	_machine_kexec_prepare = generic_kexec_prepare;
	return 0;
}
arch_initcall(register_generic_kexec);
+41 −1
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/kexec.h>
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/libfdt.h>

#include <asm/cacheflush.h>
#include <asm/page.h>
@@ -28,7 +29,6 @@ atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
void (*_crash_smp_send_stop)(void) = NULL;
#endif

int (*_machine_kexec_prepare)(struct kimage *) = NULL;
void (*_machine_kexec_shutdown)(void) = NULL;
void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;

@@ -52,6 +52,46 @@ static void kexec_image_info(const struct kimage *kimage)
	}
}

#ifdef CONFIG_UHI_BOOT

static int uhi_machine_kexec_prepare(struct kimage *kimage)
{
	int i;

	/*
	 * In case DTB file is not passed to the new kernel, a flat device
	 * tree will be created by kexec tool. It holds modified command
	 * line for the new kernel.
	 */
	for (i = 0; i < kimage->nr_segments; i++) {
		struct fdt_header fdt;

		if (kimage->segment[i].memsz <= sizeof(fdt))
			continue;

		if (copy_from_user(&fdt, kimage->segment[i].buf, sizeof(fdt)))
			continue;

		if (fdt_check_header(&fdt))
			continue;

		kexec_args[0] = -2;
		kexec_args[1] = (unsigned long)
			phys_to_virt((unsigned long)kimage->segment[i].mem);
		break;
	}

	return 0;
}

int (*_machine_kexec_prepare)(struct kimage *) = uhi_machine_kexec_prepare;

#else

int (*_machine_kexec_prepare)(struct kimage *) = NULL;

#endif /* CONFIG_UHI_BOOT */

int
machine_kexec_prepare(struct kimage *kimage)
{