Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  PS3 System Manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 2007 Sony Computer Entertainment Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  Copyright 2007 Sony Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <asm/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <asm/lv1call.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/ps3.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "vuart.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * ps3_sys_manager - PS3 system manager driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * The system manager provides an asynchronous system event notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * mechanism for reporting events like thermal alert and button presses to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * guests.  It also provides support to control system shutdown and startup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * The actual system manager is implemented as an application running in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * system policy module in lpar_1.  Guests communicate with the system manager
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * through port 2 of the vuart using a simple packet message protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * Messages are comprised of a fixed field header followed by a message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * specific payload.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * struct ps3_sys_manager_header - System manager message header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * @version: Header version, currently 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * @size: Header size in bytes, currently 16.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  * @payload_size: Message payload size in bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  * @service_id: Message type, one of enum ps3_sys_manager_service_id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * @request_tag: Unique number to identify reply.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) struct ps3_sys_manager_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	/* version 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	u8 size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	u16 reserved_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	u32 payload_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	u16 service_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	u16 reserved_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	u32 request_tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) static void __maybe_unused _dump_sm_header(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	const struct ps3_sys_manager_header *h, const char *func, int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	pr_debug("%s:%d: version:      %xh\n", func, line, h->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	pr_debug("%s:%d: size:         %xh\n", func, line, h->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	pr_debug("%s:%d: service_id:   %xh\n", func, line, h->service_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	pr_debug("%s:%d: request_tag:  %xh\n", func, line, h->request_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * Currently all messages received from the system manager are either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * + 16 bytes payload = 32 bytes).  This knowledge is used to simplify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * the logic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	PS3_SM_RX_MSG_LEN_MIN = 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	PS3_SM_RX_MSG_LEN_MAX = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * enum ps3_sys_manager_service_id - Message header service_id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * @PS3_SM_SERVICE_ID_REQUEST:       guest --> sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * @PS3_SM_SERVICE_ID_COMMAND:       guest <-- sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * @PS3_SM_SERVICE_ID_RESPONSE:      guest --> sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * @PS3_SM_SERVICE_ID_SET_ATTR:      guest --> sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * @PS3_SM_SERVICE_ID_EXTERN_EVENT:  guest <-- sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  * @PS3_SM_SERVICE_ID_SET_NEXT_OP:   guest --> sys_manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * a PS3_SM_SERVICE_ID_REQUEST message.  It also seems to be returned when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * a REQUEST message is sent at the wrong time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) enum ps3_sys_manager_service_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	/* version 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	PS3_SM_SERVICE_ID_REQUEST = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	PS3_SM_SERVICE_ID_RESPONSE = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	PS3_SM_SERVICE_ID_COMMAND = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	PS3_SM_SERVICE_ID_EXTERN_EVENT = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	PS3_SM_SERVICE_ID_SET_NEXT_OP = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	PS3_SM_SERVICE_ID_REQUEST_ERROR = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	PS3_SM_SERVICE_ID_SET_ATTR = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  * enum ps3_sys_manager_attr - Notification attribute (bit position mask).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)  * @PS3_SM_ATTR_POWER: Power button.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)  * @PS3_SM_ATTR_RESET: Reset button, not available on retail console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)  * @PS3_SM_ATTR_THERMAL: System thermal alert.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)  * @PS3_SM_ATTR_CONTROLLER: Remote controller event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)  * @PS3_SM_ATTR_ALL: Logical OR of all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  * The guest tells the system manager which events it is interested in receiving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)  * notice of by sending the system manager a logical OR of notification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)  * attributes via the ps3_sys_manager_send_attr() routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) enum ps3_sys_manager_attr {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	/* version 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	PS3_SM_ATTR_POWER = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	PS3_SM_ATTR_RESET = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	PS3_SM_ATTR_THERMAL = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	PS3_SM_ATTR_CONTROLLER = 8, /* bogus? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	PS3_SM_ATTR_ALL = 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  * enum ps3_sys_manager_event - External event type, reported by system manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  * @PS3_SM_EVENT_POWER_PRESSED: payload.value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)  *  enum ps3_sys_manager_button_event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)  * @PS3_SM_EVENT_POWER_RELEASED: payload.value = time pressed in millisec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)  * @PS3_SM_EVENT_RESET_PRESSED: payload.value =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)  *  enum ps3_sys_manager_button_event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)  * @PS3_SM_EVENT_RESET_RELEASED: payload.value = time pressed in millisec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)  * @PS3_SM_EVENT_THERMAL_ALERT: payload.value = thermal zone id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)  * @PS3_SM_EVENT_THERMAL_CLEARED: payload.value = thermal zone id.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) enum ps3_sys_manager_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	/* version 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	PS3_SM_EVENT_POWER_PRESSED = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	PS3_SM_EVENT_POWER_RELEASED = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	PS3_SM_EVENT_RESET_PRESSED = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	PS3_SM_EVENT_RESET_RELEASED = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	PS3_SM_EVENT_THERMAL_ALERT = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	PS3_SM_EVENT_THERMAL_CLEARED = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	/* no info on controller events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  * enum ps3_sys_manager_button_event - Button event payload values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * @PS3_SM_BUTTON_EVENT_HARD: Hardware generated event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * @PS3_SM_BUTTON_EVENT_SOFT: Software generated event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) enum ps3_sys_manager_button_event {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	PS3_SM_BUTTON_EVENT_HARD = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	PS3_SM_BUTTON_EVENT_SOFT = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  * enum ps3_sys_manager_next_op - Operation to perform after lpar is destroyed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) enum ps3_sys_manager_next_op {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/* version 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	PS3_SM_NEXT_OP_SYS_SHUTDOWN = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	PS3_SM_NEXT_OP_SYS_REBOOT = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	PS3_SM_NEXT_OP_LPAR_REBOOT = 0x82,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)  * enum ps3_sys_manager_wake_source - Next-op wakeup source (bit position mask).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * @PS3_SM_WAKE_DEFAULT: Disk insert, power button, eject button.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * @PS3_SM_WAKE_W_O_L: Ether or wireless LAN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * @PS3_SM_WAKE_P_O_R: Power on reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * Additional wakeup sources when specifying PS3_SM_NEXT_OP_SYS_SHUTDOWN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * The system will always wake from the PS3_SM_WAKE_DEFAULT sources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * Sources listed here are the only ones available to guests in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * other-os lpar.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) enum ps3_sys_manager_wake_source {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	/* version 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	PS3_SM_WAKE_DEFAULT   = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	PS3_SM_WAKE_W_O_L     = 0x00000400,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	PS3_SM_WAKE_P_O_R     = 0x80000000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)  * user_wake_sources - User specified wakeup sources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * Logical OR of enum ps3_sys_manager_wake_source types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static u32 user_wake_sources = PS3_SM_WAKE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  * enum ps3_sys_manager_cmd - Command from system manager to guest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * The guest completes the actions needed, then acks or naks the command via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * ps3_sys_manager_send_response().  In the case of @PS3_SM_CMD_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  * the guest must be fully prepared for a system poweroff prior to acking the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  * command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) enum ps3_sys_manager_cmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	/* version 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	PS3_SM_CMD_SHUTDOWN = 1, /* shutdown guest OS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  * ps3_sm_force_power_off - Poweroff helper.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * A global variable used to force a poweroff when the power button has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  * been pressed irrespective of how init handles the ctrl_alt_del signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static unsigned int ps3_sm_force_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  * ps3_sys_manager_write - Helper to write a two part message to the vuart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static int ps3_sys_manager_write(struct ps3_system_bus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	const struct ps3_sys_manager_header *header, const void *payload)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	BUG_ON(header->version != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	BUG_ON(header->size != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	BUG_ON(header->payload_size != 8 && header->payload_size != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	BUG_ON(header->service_id > 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	result = ps3_vuart_write(dev, header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		sizeof(struct ps3_sys_manager_header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (!result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		result = ps3_vuart_write(dev, payload, header->payload_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  * ps3_sys_manager_send_attr - Send a 'set attribute' to the system manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	enum ps3_sys_manager_attr attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	struct ps3_sys_manager_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		u8 reserved_1[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		u32 attribute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	} payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	BUILD_BUG_ON(sizeof(payload) != 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	memset(&header, 0, sizeof(header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	header.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	header.size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	header.payload_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	header.service_id = PS3_SM_SERVICE_ID_SET_ATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	memset(&payload, 0, sizeof(payload));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	payload.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	payload.attribute = attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	return ps3_sys_manager_write(dev, &header, &payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)  * ps3_sys_manager_send_next_op - Send a 'set next op' to the system manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)  * Tell the system manager what to do after this lpar is destroyed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	enum ps3_sys_manager_next_op op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	enum ps3_sys_manager_wake_source wake_source)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct ps3_sys_manager_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		u8 gos_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		u8 reserved_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		u32 wake_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		u8 reserved_2[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	} payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	BUILD_BUG_ON(sizeof(payload) != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	memset(&header, 0, sizeof(header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	header.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	header.size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	header.payload_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	memset(&payload, 0, sizeof(payload));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	payload.version = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	payload.type = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	payload.gos_id = 3; /* other os */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	payload.wake_source = wake_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	return ps3_sys_manager_write(dev, &header, &payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * ps3_sys_manager_send_request_shutdown - Send 'request' to the system manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)  * The guest sends this message to request an operation or action of the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)  * manager.  The reply is a command message from the system manager.  In the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)  * command handler the guest performs the requested operation.  The result of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)  * the command is then communicated back to the system manager with a response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)  * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  * Currently, the only supported request is the 'shutdown self' request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static int ps3_sys_manager_send_request_shutdown(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	struct ps3_sys_manager_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		u8 gos_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		u8 reserved_1[13];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	} payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	BUILD_BUG_ON(sizeof(payload) != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	memset(&header, 0, sizeof(header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	header.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	header.size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	header.payload_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	header.service_id = PS3_SM_SERVICE_ID_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	memset(&payload, 0, sizeof(payload));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	payload.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	payload.type = 1; /* shutdown */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	payload.gos_id = 0; /* self */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	return ps3_sys_manager_write(dev, &header, &payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)  * ps3_sys_manager_send_response - Send a 'response' to the system manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)  * @status: zero = success, others fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)  * The guest sends this message to the system manager to acnowledge success or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)  * failure of a command sent by the system manager.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	u64 status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	struct ps3_sys_manager_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		u8 reserved_1[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		u8 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 		u8 reserved_2[11];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	} payload;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	BUILD_BUG_ON(sizeof(payload) != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		(status ? "nak" : "ack"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	memset(&header, 0, sizeof(header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	header.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	header.size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	header.payload_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	header.service_id = PS3_SM_SERVICE_ID_RESPONSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	memset(&payload, 0, sizeof(payload));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	payload.version = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	payload.status = status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	return ps3_sys_manager_write(dev, &header, &payload);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)  * ps3_sys_manager_handle_event - Second stage event msg handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		u8 reserved_1[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 		u8 reserved_2[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	} event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	BUILD_BUG_ON(sizeof(event) != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	result = ps3_vuart_read(dev, &event, sizeof(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	BUG_ON(result && "need to retry here");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	if (event.version != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			__func__, __LINE__, event.version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	switch (event.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	case PS3_SM_EVENT_POWER_PRESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		dev_dbg(&dev->core, "%s:%d: POWER_PRESSED (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 			__func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 			(event.value == PS3_SM_BUTTON_EVENT_SOFT ? "soft"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 			: "hard"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		ps3_sm_force_power_off = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		 * A memory barrier is use here to sync memory since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		 * ps3_sys_manager_final_restart() could be called on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		 * another cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 		wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	case PS3_SM_EVENT_POWER_RELEASED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 			__func__, __LINE__, event.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	case PS3_SM_EVENT_RESET_PRESSED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		dev_dbg(&dev->core, "%s:%d: RESET_PRESSED (%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			__func__, __LINE__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 			(event.value == PS3_SM_BUTTON_EVENT_SOFT ? "soft"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			: "hard"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		ps3_sm_force_power_off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		 * A memory barrier is use here to sync memory since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		 * ps3_sys_manager_final_restart() could be called on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		 * another cpu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 		wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	case PS3_SM_EVENT_RESET_RELEASED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 		dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 			__func__, __LINE__, event.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	case PS3_SM_EVENT_THERMAL_ALERT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 			__func__, __LINE__, event.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 		pr_info("PS3 Thermal Alert Zone %u\n", event.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	case PS3_SM_EVENT_THERMAL_CLEARED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		dev_dbg(&dev->core, "%s:%d: THERMAL_CLEARED (zone %u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 			__func__, __LINE__, event.value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		dev_dbg(&dev->core, "%s:%d: unknown event (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 			__func__, __LINE__, event.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)  * ps3_sys_manager_handle_cmd - Second stage command msg handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)  * The system manager sends this in reply to a 'request' message from the guest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		u8 reserved_1[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	} cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	BUILD_BUG_ON(sizeof(cmd) != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 	result = ps3_vuart_read(dev, &cmd, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	BUG_ON(result && "need to retry here");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	if (cmd.version != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		dev_dbg(&dev->core, "%s:%d: unsupported cmd version (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			__func__, __LINE__, cmd.version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	if (cmd.type != PS3_SM_CMD_SHUTDOWN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		dev_dbg(&dev->core, "%s:%d: unknown cmd (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 			__func__, __LINE__, cmd.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	ps3_sys_manager_send_response(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)  * ps3_sys_manager_handle_msg - First stage msg handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)  * Can be called directly to manually poll vuart and pump message handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	struct ps3_sys_manager_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	result = ps3_vuart_read(dev, &header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		sizeof(struct ps3_sys_manager_header));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	if (header.version != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 			__func__, __LINE__, header.version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		dump_sm_header(&header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 		goto fail_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	BUILD_BUG_ON(sizeof(header) != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	if (header.size != 16 || (header.payload_size != 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		&& header.payload_size != 16)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		dump_sm_header(&header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	switch (header.service_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	case PS3_SM_SERVICE_ID_EXTERN_EVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		dev_dbg(&dev->core, "%s:%d: EVENT\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		return ps3_sys_manager_handle_event(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	case PS3_SM_SERVICE_ID_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		return ps3_sys_manager_handle_cmd(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	case PS3_SM_SERVICE_ID_REQUEST_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 			__LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 		dump_sm_header(&header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 			__func__, __LINE__, header.service_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	goto fail_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) fail_header:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	ps3_vuart_clear_rx_bytes(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) fail_id:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	ps3_vuart_clear_rx_bytes(dev, header.payload_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static void ps3_sys_manager_fin(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	ps3_sys_manager_send_request_shutdown(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	pr_emerg("System Halted, OK to turn off power\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	while (ps3_sys_manager_handle_msg(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		/* pause until next DEC interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		lv1_pause(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		/* pause, ignoring DEC interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		lv1_pause(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)  * ps3_sys_manager_final_power_off - The final platform machine_power_off routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)  * This routine never returns.  The routine disables asynchronous vuart reads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)  * the shutdown command sent from the system manager.  Soon after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)  * should only be called from ps3_power_off() through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)  * ps3_sys_manager_ops.power_off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	BUG_ON(!dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	ps3_vuart_cancel_async(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		user_wake_sources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	ps3_sys_manager_fin(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)  * ps3_sys_manager_final_restart - The final platform machine_restart routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)  * This routine never returns.  The routine disables asynchronous vuart reads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)  * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)  * the shutdown command sent from the system manager.  Soon after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)  * acknowledgement is sent the lpar is destroyed by the HV.  This routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)  * should only be called from ps3_restart() through ps3_sys_manager_ops.restart.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	BUG_ON(!dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	/* Check if we got here via a power button event. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	if (ps3_sm_force_power_off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 		dev_dbg(&dev->core, "%s:%d: forcing poweroff\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			__func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		ps3_sys_manager_final_power_off(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	ps3_vuart_cancel_async(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	ps3_sys_manager_send_attr(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_REBOOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 		user_wake_sources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	ps3_sys_manager_fin(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)  * ps3_sys_manager_get_wol - Get wake-on-lan setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) int ps3_sys_manager_get_wol(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	pr_debug("%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	return (user_wake_sources & PS3_SM_WAKE_W_O_L) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) EXPORT_SYMBOL_GPL(ps3_sys_manager_get_wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)  * ps3_sys_manager_set_wol - Set wake-on-lan setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) void ps3_sys_manager_set_wol(int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	static DEFINE_MUTEX(mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	mutex_lock(&mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	pr_debug("%s:%d: %d\n", __func__, __LINE__, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		user_wake_sources |= PS3_SM_WAKE_W_O_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		user_wake_sources &= ~PS3_SM_WAKE_W_O_L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	mutex_unlock(&mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) EXPORT_SYMBOL_GPL(ps3_sys_manager_set_wol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)  * ps3_sys_manager_work - Asynchronous read handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)  * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static void ps3_sys_manager_work(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	ps3_sys_manager_handle_msg(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	struct ps3_sys_manager_ops ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	ops.power_off = ps3_sys_manager_final_power_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	ops.restart = ps3_sys_manager_final_restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	ops.dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	/* ps3_sys_manager_register_ops copies ops. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	ps3_sys_manager_register_ops(&ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	BUG_ON(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	BUG_ON(result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static struct ps3_vuart_port_driver ps3_sys_manager = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	.core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	.core.core.name = "ps3_sys_manager",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	.probe = ps3_sys_manager_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	.remove = ps3_sys_manager_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	.shutdown = ps3_sys_manager_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	.work = ps3_sys_manager_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int __init ps3_sys_manager_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	return ps3_vuart_port_driver_register(&ps3_sys_manager);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) module_init(ps3_sys_manager_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* Module remove not supported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) MODULE_AUTHOR("Sony Corporation");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) MODULE_DESCRIPTION("PS3 System Manager");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER);