linux/arch/sparc/kernel/sstate.c
<<
>>
Prefs
   1/* sstate.c: System soft state support.
   2 *
   3 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
   4 */
   5
   6#include <linux/kernel.h>
   7#include <linux/notifier.h>
   8#include <linux/reboot.h>
   9#include <linux/init.h>
  10
  11#include <asm/hypervisor.h>
  12#include <asm/spitfire.h>
  13#include <asm/oplib.h>
  14#include <asm/head.h>
  15#include <asm/io.h>
  16
  17static int hv_supports_soft_state;
  18
  19static unsigned long kimage_addr_to_ra(const char *p)
  20{
  21        unsigned long val = (unsigned long) p;
  22
  23        return kern_base + (val - KERNBASE);
  24}
  25
  26static void do_set_sstate(unsigned long state, const char *msg)
  27{
  28        unsigned long err;
  29
  30        if (!hv_supports_soft_state)
  31                return;
  32
  33        err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg));
  34        if (err) {
  35                printk(KERN_WARNING "SSTATE: Failed to set soft-state to "
  36                       "state[%lx] msg[%s], err=%lu\n",
  37                       state, msg, err);
  38        }
  39}
  40
  41static const char booting_msg[32] __attribute__((aligned(32))) =
  42        "Linux booting";
  43static const char running_msg[32] __attribute__((aligned(32))) =
  44        "Linux running";
  45static const char halting_msg[32] __attribute__((aligned(32))) =
  46        "Linux halting";
  47static const char poweroff_msg[32] __attribute__((aligned(32))) =
  48        "Linux powering off";
  49static const char rebooting_msg[32] __attribute__((aligned(32))) =
  50        "Linux rebooting";
  51static const char panicing_msg[32] __attribute__((aligned(32))) =
  52        "Linux panicing";
  53
  54static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused)
  55{
  56        const char *msg;
  57
  58        switch (type) {
  59        case SYS_DOWN:
  60        default:
  61                msg = rebooting_msg;
  62                break;
  63
  64        case SYS_HALT:
  65                msg = halting_msg;
  66                break;
  67
  68        case SYS_POWER_OFF:
  69                msg = poweroff_msg;
  70                break;
  71        }
  72
  73        do_set_sstate(HV_SOFT_STATE_TRANSITION, msg);
  74
  75        return NOTIFY_OK;
  76}
  77
  78static struct notifier_block sstate_reboot_notifier = {
  79        .notifier_call = sstate_reboot_call,
  80};
  81
  82static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
  83{
  84        do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
  85
  86        return NOTIFY_DONE;
  87}
  88
  89static struct notifier_block sstate_panic_block = {
  90        .notifier_call  =       sstate_panic_event,
  91        .priority       =       INT_MAX,
  92};
  93
  94static int __init sstate_init(void)
  95{
  96        unsigned long major, minor;
  97
  98        if (tlb_type != hypervisor)
  99                return 0;
 100
 101        major = 1;
 102        minor = 0;
 103        if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor))
 104                return 0;
 105
 106        hv_supports_soft_state = 1;
 107
 108        prom_sun4v_guest_soft_state();
 109
 110        do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg);
 111
 112        atomic_notifier_chain_register(&panic_notifier_list,
 113                                       &sstate_panic_block);
 114        register_reboot_notifier(&sstate_reboot_notifier);
 115
 116        return 0;
 117}
 118
 119core_initcall(sstate_init);
 120
 121static int __init sstate_running(void)
 122{
 123        do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg);
 124        return 0;
 125}
 126
 127late_initcall(sstate_running);
 128
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.