]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/char/ipmi/ipmi_bt_sm.c
[PATCH] ipmi: style cleanups
[net-next-2.6.git] / drivers / char / ipmi / ipmi_bt_sm.c
CommitLineData
1da177e4
LT
1/*
2 * ipmi_bt_sm.c
3 *
4 * The state machine for an Open IPMI BT sub-driver under ipmi_si.c, part
5 * of the driver architecture at http://sourceforge.net/project/openipmi
6 *
7 * Author: Rocky Craig <first.last@hp.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
20 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
22 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 675 Mass Ave, Cambridge, MA 02139, USA. */
28
29#include <linux/kernel.h> /* For printk. */
30#include <linux/string.h>
31#include <linux/ipmi_msgdefs.h> /* for completion codes */
32#include "ipmi_si_sm.h"
33
1da177e4
LT
34static int bt_debug = 0x00; /* Production value 0, see following flags */
35
36#define BT_DEBUG_ENABLE 1
37#define BT_DEBUG_MSG 2
38#define BT_DEBUG_STATES 4
39
40/* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
41 and 64 byte buffers. However, one HP implementation wants 255 bytes of
42 buffer (with a documented message of 160 bytes) so go for the max.
43 Since the Open IPMI architecture is single-message oriented at this
44 stage, the queue depth of BT is of no concern. */
45
46#define BT_NORMAL_TIMEOUT 2000000 /* seconds in microseconds */
47#define BT_RETRY_LIMIT 2
48#define BT_RESET_DELAY 6000000 /* 6 seconds after warm reset */
49
50enum bt_states {
51 BT_STATE_IDLE,
52 BT_STATE_XACTION_START,
53 BT_STATE_WRITE_BYTES,
54 BT_STATE_WRITE_END,
55 BT_STATE_WRITE_CONSUME,
56 BT_STATE_B2H_WAIT,
57 BT_STATE_READ_END,
58 BT_STATE_RESET1, /* These must come last */
59 BT_STATE_RESET2,
60 BT_STATE_RESET3,
61 BT_STATE_RESTART,
62 BT_STATE_HOSED
63};
64
65struct si_sm_data {
66 enum bt_states state;
67 enum bt_states last_state; /* assist printing and resets */
68 unsigned char seq; /* BT sequence number */
69 struct si_sm_io *io;
70 unsigned char write_data[IPMI_MAX_MSG_LENGTH];
71 int write_count;
72 unsigned char read_data[IPMI_MAX_MSG_LENGTH];
73 int read_count;
74 int truncated;
75 long timeout;
76 unsigned int error_retries; /* end of "common" fields */
77 int nonzero_status; /* hung BMCs stay all 0 */
78};
79
80#define BT_CLR_WR_PTR 0x01 /* See IPMI 1.5 table 11.6.4 */
81#define BT_CLR_RD_PTR 0x02
82#define BT_H2B_ATN 0x04
83#define BT_B2H_ATN 0x08
84#define BT_SMS_ATN 0x10
85#define BT_OEM0 0x20
86#define BT_H_BUSY 0x40
87#define BT_B_BUSY 0x80
88
89/* Some bits are toggled on each write: write once to set it, once
90 more to clear it; writing a zero does nothing. To absolutely
91 clear it, check its state and write if set. This avoids the "get
92 current then use as mask" scheme to modify one bit. Note that the
93 variable "bt" is hardcoded into these macros. */
94
95#define BT_STATUS bt->io->inputb(bt->io, 0)
96#define BT_CONTROL(x) bt->io->outputb(bt->io, 0, x)
97
98#define BMC2HOST bt->io->inputb(bt->io, 1)
99#define HOST2BMC(x) bt->io->outputb(bt->io, 1, x)
100
101#define BT_INTMASK_R bt->io->inputb(bt->io, 2)
102#define BT_INTMASK_W(x) bt->io->outputb(bt->io, 2, x)
103
104/* Convenience routines for debugging. These are not multi-open safe!
105 Note the macros have hardcoded variables in them. */
106
107static char *state2txt(unsigned char state)
108{
109 switch (state) {
110 case BT_STATE_IDLE: return("IDLE");
111 case BT_STATE_XACTION_START: return("XACTION");
112 case BT_STATE_WRITE_BYTES: return("WR_BYTES");
113 case BT_STATE_WRITE_END: return("WR_END");
114 case BT_STATE_WRITE_CONSUME: return("WR_CONSUME");
115 case BT_STATE_B2H_WAIT: return("B2H_WAIT");
116 case BT_STATE_READ_END: return("RD_END");
117 case BT_STATE_RESET1: return("RESET1");
118 case BT_STATE_RESET2: return("RESET2");
119 case BT_STATE_RESET3: return("RESET3");
120 case BT_STATE_RESTART: return("RESTART");
121 case BT_STATE_HOSED: return("HOSED");
122 }
123 return("BAD STATE");
124}
125#define STATE2TXT state2txt(bt->state)
126
127static char *status2txt(unsigned char status, char *buf)
128{
129 strcpy(buf, "[ ");
130 if (status & BT_B_BUSY) strcat(buf, "B_BUSY ");
131 if (status & BT_H_BUSY) strcat(buf, "H_BUSY ");
132 if (status & BT_OEM0) strcat(buf, "OEM0 ");
133 if (status & BT_SMS_ATN) strcat(buf, "SMS ");
134 if (status & BT_B2H_ATN) strcat(buf, "B2H ");
135 if (status & BT_H2B_ATN) strcat(buf, "H2B ");
136 strcat(buf, "]");
137 return buf;
138}
139#define STATUS2TXT(buf) status2txt(status, buf)
140
141/* This will be called from within this module on a hosed condition */
142#define FIRST_SEQ 0
143static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io)
144{
145 bt->state = BT_STATE_IDLE;
146 bt->last_state = BT_STATE_IDLE;
147 bt->seq = FIRST_SEQ;
148 bt->io = io;
149 bt->write_count = 0;
150 bt->read_count = 0;
151 bt->error_retries = 0;
152 bt->nonzero_status = 0;
153 bt->truncated = 0;
154 bt->timeout = BT_NORMAL_TIMEOUT;
155 return 3; /* We claim 3 bytes of space; ought to check SPMI table */
156}
157
158static int bt_start_transaction(struct si_sm_data *bt,
159 unsigned char *data,
160 unsigned int size)
161{
162 unsigned int i;
163
e8b33617
CM
164 if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
165 return -1;
1da177e4
LT
166
167 if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
168 return -2;
169
170 if (bt_debug & BT_DEBUG_MSG) {
171 printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n");
172 printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq);
e8b33617
CM
173 for (i = 0; i < size; i ++)
174 printk (" %02x", data[i]);
1da177e4
LT
175 printk("\n");
176 }
177 bt->write_data[0] = size + 1; /* all data plus seq byte */
178 bt->write_data[1] = *data; /* NetFn/LUN */
179 bt->write_data[2] = bt->seq;
180 memcpy(bt->write_data + 3, data + 1, size - 1);
181 bt->write_count = size + 2;
182
183 bt->error_retries = 0;
184 bt->nonzero_status = 0;
185 bt->read_count = 0;
186 bt->truncated = 0;
187 bt->state = BT_STATE_XACTION_START;
188 bt->last_state = BT_STATE_IDLE;
189 bt->timeout = BT_NORMAL_TIMEOUT;
190 return 0;
191}
192
193/* After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE
194 it calls this. Strip out the length and seq bytes. */
195
196static int bt_get_result(struct si_sm_data *bt,
197 unsigned char *data,
198 unsigned int length)
199{
200 int i, msg_len;
201
202 msg_len = bt->read_count - 2; /* account for length & seq */
203 /* Always NetFn, Cmd, cCode */
204 if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) {
205 printk(KERN_WARNING "BT results: bad msg_len = %d\n", msg_len);
206 data[0] = bt->write_data[1] | 0x4; /* Kludge a response */
207 data[1] = bt->write_data[3];
208 data[2] = IPMI_ERR_UNSPECIFIED;
209 msg_len = 3;
210 } else {
211 data[0] = bt->read_data[1];
212 data[1] = bt->read_data[3];
e8b33617
CM
213 if (length < msg_len)
214 bt->truncated = 1;
1da177e4
LT
215 if (bt->truncated) { /* can be set in read_all_bytes() */
216 data[2] = IPMI_ERR_MSG_TRUNCATED;
217 msg_len = 3;
e8b33617
CM
218 } else
219 memcpy(data + 2, bt->read_data + 4, msg_len - 2);
1da177e4
LT
220
221 if (bt_debug & BT_DEBUG_MSG) {
222 printk (KERN_WARNING "BT: res (raw)");
e8b33617
CM
223 for (i = 0; i < msg_len; i++)
224 printk(" %02x", data[i]);
1da177e4
LT
225 printk ("\n");
226 }
227 }
228 bt->read_count = 0; /* paranoia */
229 return msg_len;
230}
231
232/* This bit's functionality is optional */
233#define BT_BMC_HWRST 0x80
234
235static void reset_flags(struct si_sm_data *bt)
236{
e8b33617
CM
237 if (BT_STATUS & BT_H_BUSY)
238 BT_CONTROL(BT_H_BUSY);
239 if (BT_STATUS & BT_B_BUSY)
240 BT_CONTROL(BT_B_BUSY);
1da177e4
LT
241 BT_CONTROL(BT_CLR_WR_PTR);
242 BT_CONTROL(BT_SMS_ATN);
1da177e4
LT
243#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
244 if (BT_STATUS & BT_B2H_ATN) {
245 int i;
246 BT_CONTROL(BT_H_BUSY);
247 BT_CONTROL(BT_B2H_ATN);
248 BT_CONTROL(BT_CLR_RD_PTR);
e8b33617
CM
249 for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++)
250 BMC2HOST;
1da177e4
LT
251 BT_CONTROL(BT_H_BUSY);
252 }
253#endif
254}
255
256static inline void write_all_bytes(struct si_sm_data *bt)
257{
258 int i;
259
260 if (bt_debug & BT_DEBUG_MSG) {
261 printk(KERN_WARNING "BT: write %d bytes seq=0x%02X",
262 bt->write_count, bt->seq);
263 for (i = 0; i < bt->write_count; i++)
264 printk (" %02x", bt->write_data[i]);
265 printk ("\n");
266 }
e8b33617
CM
267 for (i = 0; i < bt->write_count; i++)
268 HOST2BMC(bt->write_data[i]);
1da177e4
LT
269}
270
271static inline int read_all_bytes(struct si_sm_data *bt)
272{
273 unsigned char i;
274
275 bt->read_data[0] = BMC2HOST;
276 bt->read_count = bt->read_data[0];
277 if (bt_debug & BT_DEBUG_MSG)
278 printk(KERN_WARNING "BT: read %d bytes:", bt->read_count);
279
280 /* minimum: length, NetFn, Seq, Cmd, cCode == 5 total, or 4 more
281 following the length byte. */
282 if (bt->read_count < 4 || bt->read_count >= IPMI_MAX_MSG_LENGTH) {
283 if (bt_debug & BT_DEBUG_MSG)
284 printk("bad length %d\n", bt->read_count);
285 bt->truncated = 1;
286 return 1; /* let next XACTION START clean it up */
287 }
e8b33617
CM
288 for (i = 1; i <= bt->read_count; i++)
289 bt->read_data[i] = BMC2HOST;
1da177e4
LT
290 bt->read_count++; /* account for the length byte */
291
292 if (bt_debug & BT_DEBUG_MSG) {
293 for (i = 0; i < bt->read_count; i++)
294 printk (" %02x", bt->read_data[i]);
295 printk ("\n");
296 }
297 if (bt->seq != bt->write_data[2]) /* idiot check */
298 printk(KERN_WARNING "BT: internal error: sequence mismatch\n");
299
300 /* per the spec, the (NetFn, Seq, Cmd) tuples should match */
301 if ((bt->read_data[3] == bt->write_data[3]) && /* Cmd */
302 (bt->read_data[2] == bt->write_data[2]) && /* Sequence */
303 ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
304 return 1;
305
e8b33617
CM
306 if (bt_debug & BT_DEBUG_MSG)
307 printk(KERN_WARNING "BT: bad packet: "
1da177e4
LT
308 "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n",
309 bt->write_data[1], bt->write_data[2], bt->write_data[3],
310 bt->read_data[1], bt->read_data[2], bt->read_data[3]);
311 return 0;
312}
313
314/* Modifies bt->state appropriately, need to get into the bt_event() switch */
315
316static void error_recovery(struct si_sm_data *bt, char *reason)
317{
318 unsigned char status;
319 char buf[40]; /* For getting status */
320
321 bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */
322
323 status = BT_STATUS;
324 printk(KERN_WARNING "BT: %s in %s %s ", reason, STATE2TXT,
325 STATUS2TXT(buf));
326
327 (bt->error_retries)++;
328 if (bt->error_retries > BT_RETRY_LIMIT) {
329 printk("retry limit (%d) exceeded\n", BT_RETRY_LIMIT);
330 bt->state = BT_STATE_HOSED;
331 if (!bt->nonzero_status)
332 printk(KERN_ERR "IPMI: BT stuck, try power cycle\n");
333 else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) {
334 /* most likely during insmod */
335 printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n");
336 bt->state = BT_STATE_RESET1;
337 }
338 return;
339 }
340
341 /* Sometimes the BMC queues get in an "off-by-one" state...*/
342 if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) {
343 printk("retry B2H_WAIT\n");
344 return;
345 }
346
347 printk("restart command\n");
348 bt->state = BT_STATE_RESTART;
349}
350
351/* Check the status and (possibly) advance the BT state machine. The
352 default return is SI_SM_CALL_WITH_DELAY. */
353
354static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
355{
356 unsigned char status;
357 char buf[40]; /* For getting status */
358 int i;
359
360 status = BT_STATUS;
361 bt->nonzero_status |= status;
362
363 if ((bt_debug & BT_DEBUG_STATES) && (bt->state != bt->last_state))
364 printk(KERN_WARNING "BT: %s %s TO=%ld - %ld \n",
365 STATE2TXT,
366 STATUS2TXT(buf),
367 bt->timeout,
368 time);
369 bt->last_state = bt->state;
370
e8b33617
CM
371 if (bt->state == BT_STATE_HOSED)
372 return SI_SM_HOSED;
1da177e4
LT
373
374 if (bt->state != BT_STATE_IDLE) { /* do timeout test */
375
376 /* Certain states, on error conditions, can lock up a CPU
377 because they are effectively in an infinite loop with
378 CALL_WITHOUT_DELAY (right back here with time == 0).
379 Prevent infinite lockup by ALWAYS decrementing timeout. */
380
381 /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
382 (noticed in ipmi_smic_sm.c January 2004) */
383
e8b33617
CM
384 if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))
385 time = 100;
1da177e4
LT
386 bt->timeout -= time;
387 if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
388 error_recovery(bt, "timed out");
389 return SI_SM_CALL_WITHOUT_DELAY;
390 }
391 }
392
393 switch (bt->state) {
394
395 case BT_STATE_IDLE: /* check for asynchronous messages */
396 if (status & BT_SMS_ATN) {
397 BT_CONTROL(BT_SMS_ATN); /* clear it */
398 return SI_SM_ATTN;
399 }
400 return SI_SM_IDLE;
401
402 case BT_STATE_XACTION_START:
403 if (status & BT_H_BUSY) {
404 BT_CONTROL(BT_H_BUSY);
405 break;
406 }
e8b33617
CM
407 if (status & BT_B2H_ATN)
408 break;
1da177e4
LT
409 bt->state = BT_STATE_WRITE_BYTES;
410 return SI_SM_CALL_WITHOUT_DELAY; /* for logging */
411
412 case BT_STATE_WRITE_BYTES:
e8b33617
CM
413 if (status & (BT_B_BUSY | BT_H2B_ATN))
414 break;
1da177e4
LT
415 BT_CONTROL(BT_CLR_WR_PTR);
416 write_all_bytes(bt);
417 BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */
418 bt->state = BT_STATE_WRITE_CONSUME;
419 return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */
420
421 case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */
e8b33617
CM
422 if (status & (BT_H2B_ATN | BT_B_BUSY))
423 break;
1da177e4
LT
424 bt->state = BT_STATE_B2H_WAIT;
425 /* fall through with status */
426
427 /* Stay in BT_STATE_B2H_WAIT until a packet matches. However, spinning
428 hard here, constantly reading status, seems to hold off the
429 generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */
430
431 case BT_STATE_B2H_WAIT:
e8b33617
CM
432 if (!(status & BT_B2H_ATN))
433 break;
1da177e4
LT
434
435 /* Assume ordered, uncached writes: no need to wait */
e8b33617
CM
436 if (!(status & BT_H_BUSY))
437 BT_CONTROL(BT_H_BUSY); /* set */
1da177e4
LT
438 BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */
439 BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */
440 i = read_all_bytes(bt);
441 BT_CONTROL(BT_H_BUSY); /* clear */
e8b33617
CM
442 if (!i) /* Try this state again */
443 break;
1da177e4
LT
444 bt->state = BT_STATE_READ_END;
445 return SI_SM_CALL_WITHOUT_DELAY; /* for logging */
446
447 case BT_STATE_READ_END:
448
449 /* I could wait on BT_H_BUSY to go clear for a truly clean
450 exit. However, this is already done in XACTION_START
451 and the (possible) extra loop/status/possible wait affects
452 performance. So, as long as it works, just ignore H_BUSY */
453
454#ifdef MAKE_THIS_TRUE_IF_NECESSARY
455
e8b33617
CM
456 if (status & BT_H_BUSY)
457 break;
1da177e4
LT
458#endif
459 bt->seq++;
460 bt->state = BT_STATE_IDLE;
461 return SI_SM_TRANSACTION_COMPLETE;
462
463 case BT_STATE_RESET1:
464 reset_flags(bt);
465 bt->timeout = BT_RESET_DELAY;
466 bt->state = BT_STATE_RESET2;
467 break;
468
469 case BT_STATE_RESET2: /* Send a soft reset */
470 BT_CONTROL(BT_CLR_WR_PTR);
471 HOST2BMC(3); /* number of bytes following */
472 HOST2BMC(0x18); /* NetFn/LUN == Application, LUN 0 */
473 HOST2BMC(42); /* Sequence number */
474 HOST2BMC(3); /* Cmd == Soft reset */
475 BT_CONTROL(BT_H2B_ATN);
476 bt->state = BT_STATE_RESET3;
477 break;
478
479 case BT_STATE_RESET3:
e8b33617
CM
480 if (bt->timeout > 0)
481 return SI_SM_CALL_WITH_DELAY;
1da177e4
LT
482 bt->state = BT_STATE_RESTART; /* printk in debug modes */
483 break;
484
485 case BT_STATE_RESTART: /* don't reset retries! */
486 bt->write_data[2] = ++bt->seq;
487 bt->read_count = 0;
488 bt->nonzero_status = 0;
489 bt->timeout = BT_NORMAL_TIMEOUT;
490 bt->state = BT_STATE_XACTION_START;
491 break;
492
493 default: /* HOSED is supposed to be caught much earlier */
494 error_recovery(bt, "internal logic error");
495 break;
496 }
497 return SI_SM_CALL_WITH_DELAY;
498}
499
500static int bt_detect(struct si_sm_data *bt)
501{
502 /* It's impossible for the BT status and interrupt registers to be
503 all 1's, (assuming a properly functioning, self-initialized BMC)
504 but that's what you get from reading a bogus address, so we
505 test that first. The calling routine uses negative logic. */
506
e8b33617
CM
507 if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF))
508 return 1;
1da177e4
LT
509 reset_flags(bt);
510 return 0;
511}
512
513static void bt_cleanup(struct si_sm_data *bt)
514{
515}
516
517static int bt_size(void)
518{
519 return sizeof(struct si_sm_data);
520}
521
522struct si_sm_handlers bt_smi_handlers =
523{
1da177e4
LT
524 .init_data = bt_init_data,
525 .start_transaction = bt_start_transaction,
526 .get_result = bt_get_result,
527 .event = bt_event,
528 .detect = bt_detect,
529 .cleanup = bt_cleanup,
530 .size = bt_size,
531};