command.c (4178B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2 3/* 4 * IBM ASM Service Processor Device Driver 5 * 6 * Copyright (C) IBM Corporation, 2004 7 * 8 * Author: Max Asböck <amax@us.ibm.com> 9 */ 10 11#include <linux/sched.h> 12#include <linux/slab.h> 13#include "ibmasm.h" 14#include "lowlevel.h" 15 16static void exec_next_command(struct service_processor *sp); 17 18static atomic_t command_count = ATOMIC_INIT(0); 19 20struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size) 21{ 22 struct command *cmd; 23 24 if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE) 25 return NULL; 26 27 cmd = kzalloc(sizeof(struct command), GFP_KERNEL); 28 if (cmd == NULL) 29 return NULL; 30 31 32 cmd->buffer = kzalloc(buffer_size, GFP_KERNEL); 33 if (cmd->buffer == NULL) { 34 kfree(cmd); 35 return NULL; 36 } 37 cmd->buffer_size = buffer_size; 38 39 kref_init(&cmd->kref); 40 cmd->lock = &sp->lock; 41 42 cmd->status = IBMASM_CMD_PENDING; 43 init_waitqueue_head(&cmd->wait); 44 INIT_LIST_HEAD(&cmd->queue_node); 45 46 atomic_inc(&command_count); 47 dbg("command count: %d\n", atomic_read(&command_count)); 48 49 return cmd; 50} 51 52void ibmasm_free_command(struct kref *kref) 53{ 54 struct command *cmd = to_command(kref); 55 56 list_del(&cmd->queue_node); 57 atomic_dec(&command_count); 58 dbg("command count: %d\n", atomic_read(&command_count)); 59 kfree(cmd->buffer); 60 kfree(cmd); 61} 62 63static void enqueue_command(struct service_processor *sp, struct command *cmd) 64{ 65 list_add_tail(&cmd->queue_node, &sp->command_queue); 66} 67 68static struct command *dequeue_command(struct service_processor *sp) 69{ 70 struct command *cmd; 71 struct list_head *next; 72 73 if (list_empty(&sp->command_queue)) 74 return NULL; 75 76 next = sp->command_queue.next; 77 list_del_init(next); 78 cmd = list_entry(next, struct command, queue_node); 79 80 return cmd; 81} 82 83static inline void do_exec_command(struct service_processor *sp) 84{ 85 char tsbuf[32]; 86 87 dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf)); 88 89 if (ibmasm_send_i2o_message(sp)) { 90 sp->current_command->status = IBMASM_CMD_FAILED; 91 wake_up(&sp->current_command->wait); 92 command_put(sp->current_command); 93 exec_next_command(sp); 94 } 95} 96 97/* 98 * exec_command 99 * send a command to a service processor 100 * Commands are executed sequentially. One command (sp->current_command) 101 * is sent to the service processor. Once the interrupt handler gets a 102 * message of type command_response, the message is copied into 103 * the current commands buffer, 104 */ 105void ibmasm_exec_command(struct service_processor *sp, struct command *cmd) 106{ 107 unsigned long flags; 108 char tsbuf[32]; 109 110 dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf)); 111 112 spin_lock_irqsave(&sp->lock, flags); 113 114 if (!sp->current_command) { 115 sp->current_command = cmd; 116 command_get(sp->current_command); 117 spin_unlock_irqrestore(&sp->lock, flags); 118 do_exec_command(sp); 119 } else { 120 enqueue_command(sp, cmd); 121 spin_unlock_irqrestore(&sp->lock, flags); 122 } 123} 124 125static void exec_next_command(struct service_processor *sp) 126{ 127 unsigned long flags; 128 char tsbuf[32]; 129 130 dbg("%s:%d at %s\n", __func__, __LINE__, get_timestamp(tsbuf)); 131 132 spin_lock_irqsave(&sp->lock, flags); 133 sp->current_command = dequeue_command(sp); 134 if (sp->current_command) { 135 command_get(sp->current_command); 136 spin_unlock_irqrestore(&sp->lock, flags); 137 do_exec_command(sp); 138 } else { 139 spin_unlock_irqrestore(&sp->lock, flags); 140 } 141} 142 143/* 144 * Sleep until a command has failed or a response has been received 145 * and the command status been updated by the interrupt handler. 146 * (see receive_response). 147 */ 148void ibmasm_wait_for_response(struct command *cmd, int timeout) 149{ 150 wait_event_interruptible_timeout(cmd->wait, 151 cmd->status == IBMASM_CMD_COMPLETE || 152 cmd->status == IBMASM_CMD_FAILED, 153 timeout * HZ); 154} 155 156/* 157 * receive_command_response 158 * called by the interrupt handler when a dot command of type command_response 159 * was received. 160 */ 161void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size) 162{ 163 struct command *cmd = sp->current_command; 164 165 if (!sp->current_command) 166 return; 167 168 memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size)); 169 cmd->status = IBMASM_CMD_COMPLETE; 170 wake_up(&sp->current_command->wait); 171 command_put(sp->current_command); 172 exec_next_command(sp); 173}