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