command.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2
1 2/* 3 * IBM ASM Service Processor Device Driver 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * 19 * Copyright (C) IBM Corporation, 2004 20 * 21 * Author: Max Asb�ck <amax@us.ibm.com> 22 * 23 */ 24 25#include "ibmasm.h" 26 27static void exec_next_command(struct service_processor *sp); 28static void free_command(struct kobject *kobj); 29 30static struct kobj_type ibmasm_cmd_kobj_type = { 31 .release = free_command, 32}; 33 34 35struct command *ibmasm_new_command(size_t buffer_size) 36{ 37 struct command *cmd; 38 39 if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE) 40 return NULL; 41 42 cmd = kmalloc(sizeof(struct command), GFP_KERNEL); 43 if (cmd == NULL) 44 return NULL; 45 46 memset(cmd, 0, sizeof(*cmd)); 47 48 cmd->buffer = kmalloc(buffer_size, GFP_KERNEL); 49 if (cmd->buffer == NULL) { 50 kfree(cmd); 51 return NULL; 52 } 53 memset(cmd->buffer, 0, buffer_size); 54 cmd->buffer_size = buffer_size; 55 56 kobject_init(&cmd->kobj); 57 cmd->kobj.ktype = &ibmasm_cmd_kobj_type; 58 59 cmd->status = IBMASM_CMD_PENDING; 60 init_waitqueue_head(&cmd->wait); 61 INIT_LIST_HEAD(&cmd->queue_node); 62 63 return cmd; 64} 65 66static void free_command(struct kobject *kobj) 67{ 68 struct command *cmd = to_command(kobj); 69 70 list_del(&cmd->queue_node); 71 kfree(cmd->buffer); 72 kfree(cmd); 73} 74 75static void enqueue_command(struct service_processor *sp, struct command *cmd) 76{ 77 list_add_tail(&cmd->queue_node, &sp->command_queue); 78} 79 80static struct command *dequeue_command(struct service_processor *sp) 81{ 82 struct command *cmd; 83 struct list_head *next; 84 85 if (list_empty(&sp->command_queue)) 86 return NULL; 87 88 next = sp->command_queue.next; 89 list_del_init(next); 90 cmd = list_entry(next, struct command, queue_node); 91 92 return cmd; 93} 94 95static inline void do_exec_command(struct service_processor *sp) 96{ 97 if (ibmasm_send_i2o_message(sp)) { 98 sp->current_command->status = IBMASM_CMD_FAILED; 99 exec_next_command(sp); 100 } 101} 102 103/** 104 * exec_command 105 * send a command to a service processor 106 * Commands are executed sequentially. One command (sp->current_command) 107 * is sent to the service processor. Once the interrupt handler gets a 108 * message of type command_response, the message is copied into 109 * the current commands buffer, 110 */ 111void ibmasm_exec_command(struct service_processor *sp, struct command *cmd) 112{ 113 unsigned long flags; 114 115 spin_lock_irqsave(&sp->lock, flags); 116 117 if (!sp->current_command) { 118 command_get(cmd); 119 sp->current_command = cmd; 120 spin_unlock_irqrestore(&sp->lock, flags); 121 122 do_exec_command(sp); 123 } else { 124 enqueue_command(sp, cmd); 125 spin_unlock_irqrestore(&sp->lock, flags); 126 } 127} 128 129static void exec_next_command(struct service_processor *sp) 130{ 131 unsigned long flags; 132 133 wake_up(&sp->current_command->wait); 134 command_put(sp->current_command); 135 136 spin_lock_irqsave(&sp->lock, flags); 137 sp->current_command = dequeue_command(sp); 138 if (sp->current_command) { 139 command_get(sp->current_command); 140 spin_unlock_irqrestore(&sp->lock, flags); 141 do_exec_command(sp); 142 } else { 143 spin_unlock_irqrestore(&sp->lock, flags); 144 } 145} 146 147/** 148 * Sleep until a command has failed or a response has been received 149 * and the command status been updated by the interrupt handler. 150 * (see receive_response). 151 */ 152void ibmasm_wait_for_response(struct command *cmd, int timeout) 153{ 154 wait_event_interruptible_timeout(cmd->wait, 155 cmd->status == IBMASM_CMD_COMPLETE || 156 cmd->status == IBMASM_CMD_FAILED, 157 timeout * HZ); 158} 159 160/** 161 * receive_command_response 162 * called by the interrupt handler when a dot command of type command_response 163 * was received. 164 */ 165void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size) 166{ 167 struct command *cmd = sp->current_command; 168 169 if (!sp->current_command) 170 return; 171 172 memcpy(cmd->buffer, response, min(size, cmd->buffer_size)); 173 cmd->status = IBMASM_CMD_COMPLETE; 174 exec_next_command(sp); 175} 176