1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * IBM ASM Service Processor Device Driver 4 * 5 * Copyright (C) IBM Corporation, 2004 6 * 7 * Author: Max Asböck <amax@us.ibm.com> 8 */ 9 10 #include "ibmasm.h" 11 #include "dot_command.h" 12 13 /** 14 * Dispatch an incoming message to the specific handler for the message. 15 * Called from interrupt context. 16 */ 17 void ibmasm_receive_message(struct service_processor *sp, void *message, int message_size) 18 { 19 u32 size; 20 struct dot_command_header *header = (struct dot_command_header *)message; 21 22 if (message_size == 0) 23 return; 24 25 size = get_dot_command_size(message); 26 if (size == 0) 27 return; 28 29 if (size > message_size) 30 size = message_size; 31 32 switch (header->type) { 33 case sp_event: 34 ibmasm_receive_event(sp, message, size); 35 break; 36 case sp_command_response: 37 ibmasm_receive_command_response(sp, message, size); 38 break; 39 case sp_heartbeat: 40 ibmasm_receive_heartbeat(sp, message, size); 41 break; 42 default: 43 dev_err(sp->dev, "Received unknown message from service processor\n"); 44 } 45 } 46 47 48 #define INIT_BUFFER_SIZE 32 49 50 51 /** 52 * send the 4.3.5.10 dot command (driver VPD) to the service processor 53 */ 54 int ibmasm_send_driver_vpd(struct service_processor *sp) 55 { 56 struct command *command; 57 struct dot_command_header *header; 58 u8 *vpd_command; 59 u8 *vpd_data; 60 int result = 0; 61 62 command = ibmasm_new_command(sp, INIT_BUFFER_SIZE); 63 if (command == NULL) 64 return -ENOMEM; 65 66 header = (struct dot_command_header *)command->buffer; 67 header->type = sp_write; 68 header->command_size = 4; 69 header->data_size = 16; 70 header->status = 0; 71 header->reserved = 0; 72 73 vpd_command = command->buffer + sizeof(struct dot_command_header); 74 vpd_command[0] = 0x4; 75 vpd_command[1] = 0x3; 76 vpd_command[2] = 0x5; 77 vpd_command[3] = 0xa; 78 79 vpd_data = vpd_command + header->command_size; 80 vpd_data[0] = 0; 81 strcat(vpd_data, IBMASM_DRIVER_VPD); 82 vpd_data[10] = 0; 83 vpd_data[15] = 0; 84 85 ibmasm_exec_command(sp, command); 86 ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL); 87 88 if (command->status != IBMASM_CMD_COMPLETE) 89 result = -ENODEV; 90 91 command_put(command); 92 93 return result; 94 } 95 96 struct os_state_command { 97 struct dot_command_header header; 98 unsigned char command[3]; 99 unsigned char data; 100 }; 101 102 /** 103 * send the 4.3.6 dot command (os state) to the service processor 104 * During driver init this function is called with os state "up". 105 * This causes the service processor to start sending heartbeats the 106 * driver. 107 * During driver exit the function is called with os state "down", 108 * causing the service processor to stop the heartbeats. 109 */ 110 int ibmasm_send_os_state(struct service_processor *sp, int os_state) 111 { 112 struct command *cmd; 113 struct os_state_command *os_state_cmd; 114 int result = 0; 115 116 cmd = ibmasm_new_command(sp, sizeof(struct os_state_command)); 117 if (cmd == NULL) 118 return -ENOMEM; 119 120 os_state_cmd = (struct os_state_command *)cmd->buffer; 121 os_state_cmd->header.type = sp_write; 122 os_state_cmd->header.command_size = 3; 123 os_state_cmd->header.data_size = 1; 124 os_state_cmd->header.status = 0; 125 os_state_cmd->command[0] = 4; 126 os_state_cmd->command[1] = 3; 127 os_state_cmd->command[2] = 6; 128 os_state_cmd->data = os_state; 129 130 ibmasm_exec_command(sp, cmd); 131 ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL); 132 133 if (cmd->status != IBMASM_CMD_COMPLETE) 134 result = -ENODEV; 135 136 command_put(cmd); 137 return result; 138 } 139