Blame view

drivers/misc/ibmasm/command.c 4.72 KB
1da177e4c   Linus Torvalds   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   Dmitry Torokhov   IBMASM: whitespac...
21
   * Author: Max Asböck <amax@us.ibm.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
   *
   */
d43c36dc6   Alexey Dobriyan   headers: remove s...
24
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  #include "ibmasm.h"
881876051   Max Asbock   [PATCH] ibmasm dr...
26
  #include "lowlevel.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  
  static void exec_next_command(struct service_processor *sp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

881876051   Max Asbock   [PATCH] ibmasm dr...
30
  static atomic_t command_count = ATOMIC_INIT(0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

881876051   Max Asbock   [PATCH] ibmasm dr...
32
  struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
  {
  	struct command *cmd;
  
  	if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE)
  		return NULL;
dd00cc486   Yoann Padioleau   some kmalloc/mems...
38
  	cmd = kzalloc(sizeof(struct command), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
  	if (cmd == NULL)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41

dd00cc486   Yoann Padioleau   some kmalloc/mems...
42
  	cmd->buffer = kzalloc(buffer_size, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
  	if (cmd->buffer == NULL) {
  		kfree(cmd);
  		return NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  	cmd->buffer_size = buffer_size;
a045171f8   Greg Kroah-Hartman   kobject: convert ...
48
  	kref_init(&cmd->kref);
881876051   Max Asbock   [PATCH] ibmasm dr...
49
  	cmd->lock = &sp->lock;
1da177e4c   Linus Torvalds   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   Max Asbock   [PATCH] ibmasm dr...
54
55
56
  	atomic_inc(&command_count);
  	dbg("command count: %d
  ", atomic_read(&command_count));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
  	return cmd;
  }
a045171f8   Greg Kroah-Hartman   kobject: convert ...
59
  void ibmasm_free_command(struct kref *kref)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  {
a045171f8   Greg Kroah-Hartman   kobject: convert ...
61
  	struct command *cmd = to_command(kref);
3110dc7a8   Dmitry Torokhov   IBMASM: whitespac...
62

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  	list_del(&cmd->queue_node);
881876051   Max Asbock   [PATCH] ibmasm dr...
64
65
66
  	atomic_dec(&command_count);
  	dbg("command count: %d
  ", atomic_read(&command_count));
1da177e4c   Linus Torvalds   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   Max Asbock   [PATCH] ibmasm dr...
93
  	char tsbuf[32];
6e574195b   Harvey Harrison   drivers/misc: rep...
94
95
  	dbg("%s:%d at %s
  ", __func__, __LINE__, get_timestamp(tsbuf));
881876051   Max Asbock   [PATCH] ibmasm dr...
96

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
  	if (ibmasm_send_i2o_message(sp)) {
  		sp->current_command->status = IBMASM_CMD_FAILED;
881876051   Max Asbock   [PATCH] ibmasm dr...
99
100
  		wake_up(&sp->current_command->wait);
  		command_put(sp->current_command);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
  		exec_next_command(sp);
  	}
  }
3110dc7a8   Dmitry Torokhov   IBMASM: whitespac...
104

1da177e4c   Linus Torvalds   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   Dmitry Torokhov   IBMASM: whitespac...
111
   * the current commands buffer,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
   */
  void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
  {
  	unsigned long flags;
881876051   Max Asbock   [PATCH] ibmasm dr...
116
  	char tsbuf[32];
6e574195b   Harvey Harrison   drivers/misc: rep...
117
118
  	dbg("%s:%d at %s
  ", __func__, __LINE__, get_timestamp(tsbuf));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
122
  
  	spin_lock_irqsave(&sp->lock, flags);
  
  	if (!sp->current_command) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  		sp->current_command = cmd;
881876051   Max Asbock   [PATCH] ibmasm dr...
124
  		command_get(sp->current_command);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  		spin_unlock_irqrestore(&sp->lock, flags);
1da177e4c   Linus Torvalds   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   Max Asbock   [PATCH] ibmasm dr...
136
  	char tsbuf[32];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137

6e574195b   Harvey Harrison   drivers/misc: rep...
138
139
  	dbg("%s:%d at %s
  ", __func__, __LINE__, get_timestamp(tsbuf));
1da177e4c   Linus Torvalds   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   Dmitry Torokhov   IBMASM: whitespac...
151
  /**
1da177e4c   Linus Torvalds   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   Dmitry Torokhov   IBMASM: whitespac...
172
173
  	if (!sp->current_command)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

881876051   Max Asbock   [PATCH] ibmasm dr...
175
  	memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  	cmd->status = IBMASM_CMD_COMPLETE;
881876051   Max Asbock   [PATCH] ibmasm dr...
177
178
  	wake_up(&sp->current_command->wait);
  	command_put(sp->current_command);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
180
  	exec_next_command(sp);
  }