Commit ea5e7447 authored by David S. Miller's avatar David S. Miller
Browse files

sparc: Set reboot-cmd using reboot data hypervisor call if available.

parent e2eb9f81
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2927,6 +2927,13 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
#define HV_FAST_FIRE_GET_PERFREG	0x120
#define HV_FAST_FIRE_SET_PERFREG	0x121

#define HV_FAST_REBOOT_DATA_SET		0x172

#ifndef __ASSEMBLY__
extern unsigned long sun4v_reboot_data_set(unsigned long ra,
					   unsigned long len);
#endif

/* Function numbers for HV_CORE_TRAP.  */
#define HV_CORE_SET_VER			0x00
#define HV_CORE_PUTCHAR			0x01
+28 −2
Original line number Diff line number Diff line
@@ -15,12 +15,15 @@
#include <linux/reboot.h>
#include <linux/cpu.h>

#include <asm/hypervisor.h>
#include <asm/ldc.h>
#include <asm/vio.h>
#include <asm/mdesc.h>
#include <asm/head.h>
#include <asm/irq.h>

#include "kernel.h"

#define DRV_MODULE_NAME		"ds"
#define PFX DRV_MODULE_NAME	": "
#define DRV_MODULE_VERSION	"1.0"
@@ -828,19 +831,33 @@ void ldom_set_var(const char *var, const char *value)
	}
}

static char full_boot_str[256] __attribute__((aligned(32)));
static int reboot_data_supported;

void ldom_reboot(const char *boot_command)
{
	/* Don't bother with any of this if the boot_command
	 * is empty.
	 */
	if (boot_command && strlen(boot_command)) {
		char full_boot_str[256];
		unsigned long len;

		strcpy(full_boot_str, "boot ");
		strcpy(full_boot_str + strlen("boot "), boot_command);
		len = strlen(full_boot_str);

		if (reboot_data_supported) {
			unsigned long ra = kimage_addr_to_ra(full_boot_str);
			unsigned long hv_ret;

			hv_ret = sun4v_reboot_data_set(ra, len);
			if (hv_ret != HV_EOK)
				pr_err("SUN4V: Unable to set reboot data "
				       "hv_ret=%lu\n", hv_ret);
		} else {
			ldom_set_var("reboot-command", full_boot_str);
		}
	}
	sun4v_mach_sir();
}

@@ -1237,6 +1254,15 @@ static struct vio_driver ds_driver = {

static int __init ds_init(void)
{
	unsigned long hv_ret, major, minor;

	hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
	if (hv_ret == HV_EOK) {
		pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
			major, minor);
		reboot_data_supported = 1;
	}

	kthread_run(ds_thread, NULL, "kldomd");

	return vio_register_driver(&ds_driver);
+7 −0
Original line number Diff line number Diff line
@@ -798,3 +798,10 @@ ENTRY(sun4v_niagara2_setperf)
	retl
	 nop
ENDPROC(sun4v_niagara2_setperf)

ENTRY(sun4v_reboot_data_set)
	mov	HV_FAST_REBOOT_DATA_SET, %o5
	ta	HV_FAST_TRAP
	retl
	 nop
ENDPROC(sun4v_reboot_data_set)
+9 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@
#include <linux/interrupt.h>

#include <asm/traps.h>
#include <asm/head.h>
#include <asm/io.h>

/* cpu.c */
extern const char *sparc_pmu_type;
@@ -14,6 +16,13 @@ extern int ncpus_probed;
/* setup_64.c */
struct seq_file;
extern void cpucap_info(struct seq_file *);

static inline unsigned long kimage_addr_to_ra(const char *p)
{
	unsigned long val = (unsigned long) p;

	return kern_base + (val - KERNBASE);
}
#endif

#ifdef CONFIG_SPARC32
+2 −7
Original line number Diff line number Diff line
@@ -14,14 +14,9 @@
#include <asm/head.h>
#include <asm/io.h>

static int hv_supports_soft_state;

static unsigned long kimage_addr_to_ra(const char *p)
{
	unsigned long val = (unsigned long) p;
#include "kernel.h"

	return kern_base + (val - KERNBASE);
}
static int hv_supports_soft_state;

static void do_set_sstate(unsigned long state, const char *msg)
{