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