^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);