PageRenderTime 57ms CodeModel.GetById 18ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/char/ipmi/ipmi_bt_sm.c

https://bitbucket.org/evzijst/gittest
C | 513 lines | 368 code | 74 blank | 71 comment | 78 complexity | 519456206bcdaab8e7f61eaf333a8067 MD5 | raw file
  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
 34#define IPMI_BT_VERSION "v33"
 35
 36static int bt_debug = 0x00;	/* Production value 0, see following flags */
 37
 38#define	BT_DEBUG_ENABLE	1
 39#define BT_DEBUG_MSG	2
 40#define BT_DEBUG_STATES	4
 41
 42/* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
 43   and 64 byte buffers.  However, one HP implementation wants 255 bytes of
 44   buffer (with a documented message of 160 bytes) so go for the max.
 45   Since the Open IPMI architecture is single-message oriented at this
 46   stage, the queue depth of BT is of no concern. */
 47
 48#define BT_NORMAL_TIMEOUT	2000000	/* seconds in microseconds */
 49#define BT_RETRY_LIMIT		2
 50#define BT_RESET_DELAY		6000000	/* 6 seconds after warm reset */
 51
 52enum bt_states {
 53	BT_STATE_IDLE,
 54	BT_STATE_XACTION_START,
 55	BT_STATE_WRITE_BYTES,
 56	BT_STATE_WRITE_END,
 57	BT_STATE_WRITE_CONSUME,
 58	BT_STATE_B2H_WAIT,
 59	BT_STATE_READ_END,
 60	BT_STATE_RESET1,		/* These must come last */
 61	BT_STATE_RESET2,
 62	BT_STATE_RESET3,
 63	BT_STATE_RESTART,
 64	BT_STATE_HOSED
 65};
 66
 67struct si_sm_data {
 68	enum bt_states	state;
 69	enum bt_states	last_state;	/* assist printing and resets */
 70	unsigned char	seq;		/* BT sequence number */
 71	struct si_sm_io	*io;
 72        unsigned char	write_data[IPMI_MAX_MSG_LENGTH];
 73        int		write_count;
 74        unsigned char	read_data[IPMI_MAX_MSG_LENGTH];
 75        int		read_count;
 76        int		truncated;
 77        long		timeout;
 78        unsigned int	error_retries;	/* end of "common" fields */
 79	int		nonzero_status;	/* hung BMCs stay all 0 */
 80};
 81
 82#define BT_CLR_WR_PTR	0x01	/* See IPMI 1.5 table 11.6.4 */
 83#define BT_CLR_RD_PTR	0x02
 84#define BT_H2B_ATN	0x04
 85#define BT_B2H_ATN	0x08
 86#define BT_SMS_ATN	0x10
 87#define BT_OEM0		0x20
 88#define BT_H_BUSY	0x40
 89#define BT_B_BUSY	0x80
 90
 91/* Some bits are toggled on each write: write once to set it, once
 92   more to clear it; writing a zero does nothing.  To absolutely
 93   clear it, check its state and write if set.  This avoids the "get
 94   current then use as mask" scheme to modify one bit.  Note that the
 95   variable "bt" is hardcoded into these macros. */
 96
 97#define BT_STATUS	bt->io->inputb(bt->io, 0)
 98#define BT_CONTROL(x)	bt->io->outputb(bt->io, 0, x)
 99
100#define BMC2HOST	bt->io->inputb(bt->io, 1)
101#define HOST2BMC(x)	bt->io->outputb(bt->io, 1, x)
102
103#define BT_INTMASK_R	bt->io->inputb(bt->io, 2)
104#define BT_INTMASK_W(x)	bt->io->outputb(bt->io, 2, x)
105
106/* Convenience routines for debugging.  These are not multi-open safe!
107   Note the macros have hardcoded variables in them. */
108
109static char *state2txt(unsigned char state)
110{
111	switch (state) {
112		case BT_STATE_IDLE:		return("IDLE");
113		case BT_STATE_XACTION_START:	return("XACTION");
114		case BT_STATE_WRITE_BYTES:	return("WR_BYTES");
115		case BT_STATE_WRITE_END:	return("WR_END");
116		case BT_STATE_WRITE_CONSUME:	return("WR_CONSUME");
117		case BT_STATE_B2H_WAIT:		return("B2H_WAIT");
118		case BT_STATE_READ_END:		return("RD_END");
119		case BT_STATE_RESET1:		return("RESET1");
120		case BT_STATE_RESET2:		return("RESET2");
121		case BT_STATE_RESET3:		return("RESET3");
122		case BT_STATE_RESTART:		return("RESTART");
123		case BT_STATE_HOSED:		return("HOSED");
124	}
125	return("BAD STATE");
126}
127#define STATE2TXT state2txt(bt->state)
128
129static char *status2txt(unsigned char status, char *buf)
130{
131	strcpy(buf, "[ ");
132	if (status & BT_B_BUSY) strcat(buf, "B_BUSY ");
133	if (status & BT_H_BUSY) strcat(buf, "H_BUSY ");
134	if (status & BT_OEM0) strcat(buf, "OEM0 ");
135	if (status & BT_SMS_ATN) strcat(buf, "SMS ");
136	if (status & BT_B2H_ATN) strcat(buf, "B2H ");
137	if (status & BT_H2B_ATN) strcat(buf, "H2B ");
138	strcat(buf, "]");
139	return buf;
140}
141#define STATUS2TXT(buf) status2txt(status, buf)
142
143/* This will be called from within this module on a hosed condition */
144#define FIRST_SEQ	0
145static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io)
146{
147	bt->state = BT_STATE_IDLE;
148	bt->last_state = BT_STATE_IDLE;
149	bt->seq = FIRST_SEQ;
150	bt->io = io;
151	bt->write_count = 0;
152	bt->read_count = 0;
153	bt->error_retries = 0;
154	bt->nonzero_status = 0;
155	bt->truncated = 0;
156	bt->timeout = BT_NORMAL_TIMEOUT;
157	return 3; /* We claim 3 bytes of space; ought to check SPMI table */
158}
159
160static int bt_start_transaction(struct si_sm_data *bt,
161				unsigned char *data,
162				unsigned int size)
163{
164	unsigned int i;
165
166	if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1;
167
168	if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
169		return -2;
170
171	if (bt_debug & BT_DEBUG_MSG) {
172    		printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n");
173		printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq);
174		for (i = 0; i < size; i ++) printk (" %02x", data[i]);
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];
213		if (length < msg_len) bt->truncated = 1;
214		if (bt->truncated) {	/* can be set in read_all_bytes() */
215			data[2] = IPMI_ERR_MSG_TRUNCATED;
216			msg_len = 3;
217		} else memcpy(data + 2, bt->read_data + 4, msg_len - 2);
218
219		if (bt_debug & BT_DEBUG_MSG) {
220			printk (KERN_WARNING "BT: res (raw)");
221			for (i = 0; i < msg_len; i++) printk(" %02x", data[i]);
222			printk ("\n");
223		}
224	}
225	bt->read_count = 0;	/* paranoia */
226	return msg_len;
227}
228
229/* This bit's functionality is optional */
230#define BT_BMC_HWRST	0x80
231
232static void reset_flags(struct si_sm_data *bt)
233{
234	if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY);
235	if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY);
236	BT_CONTROL(BT_CLR_WR_PTR);
237	BT_CONTROL(BT_SMS_ATN);
238	BT_INTMASK_W(BT_BMC_HWRST);
239#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
240	if (BT_STATUS & BT_B2H_ATN) {
241		int i;
242		BT_CONTROL(BT_H_BUSY);
243		BT_CONTROL(BT_B2H_ATN);
244		BT_CONTROL(BT_CLR_RD_PTR);
245		for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST;
246		BT_CONTROL(BT_H_BUSY);
247	}
248#endif
249}
250
251static inline void write_all_bytes(struct si_sm_data *bt)
252{
253	int i;
254
255	if (bt_debug & BT_DEBUG_MSG) {
256    		printk(KERN_WARNING "BT: write %d bytes seq=0x%02X",
257			bt->write_count, bt->seq);
258		for (i = 0; i < bt->write_count; i++)
259			printk (" %02x", bt->write_data[i]);
260		printk ("\n");
261	}
262	for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]);
263}
264
265static inline int read_all_bytes(struct si_sm_data *bt)
266{
267	unsigned char i;
268
269	bt->read_data[0] = BMC2HOST;
270	bt->read_count = bt->read_data[0];
271	if (bt_debug & BT_DEBUG_MSG)
272    		printk(KERN_WARNING "BT: read %d bytes:", bt->read_count);
273
274	/* minimum: length, NetFn, Seq, Cmd, cCode == 5 total, or 4 more
275	   following the length byte. */
276	if (bt->read_count < 4 || bt->read_count >= IPMI_MAX_MSG_LENGTH) {
277		if (bt_debug & BT_DEBUG_MSG)
278			printk("bad length %d\n", bt->read_count);
279		bt->truncated = 1;
280		return 1;	/* let next XACTION START clean it up */
281	}
282	for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST;
283	bt->read_count++;	/* account for the length byte */
284
285	if (bt_debug & BT_DEBUG_MSG) {
286	    	for (i = 0; i < bt->read_count; i++)
287			printk (" %02x", bt->read_data[i]);
288	    	printk ("\n");
289	}
290	if (bt->seq != bt->write_data[2])	/* idiot check */
291		printk(KERN_WARNING "BT: internal error: sequence mismatch\n");
292
293	/* per the spec, the (NetFn, Seq, Cmd) tuples should match */
294	if ((bt->read_data[3] == bt->write_data[3]) &&		/* Cmd */
295        	(bt->read_data[2] == bt->write_data[2]) &&	/* Sequence */
296        	((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8)))
297			return 1;
298
299	if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: "
300		"want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n",
301		bt->write_data[1], bt->write_data[2], bt->write_data[3],
302		bt->read_data[1],  bt->read_data[2],  bt->read_data[3]);
303	return 0;
304}
305
306/* Modifies bt->state appropriately, need to get into the bt_event() switch */
307
308static void error_recovery(struct si_sm_data *bt, char *reason)
309{
310	unsigned char status;
311	char buf[40]; /* For getting status */
312
313	bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */
314
315	status = BT_STATUS;
316	printk(KERN_WARNING "BT: %s in %s %s ", reason, STATE2TXT,
317	       STATUS2TXT(buf));
318
319	(bt->error_retries)++;
320	if (bt->error_retries > BT_RETRY_LIMIT) {
321		printk("retry limit (%d) exceeded\n", BT_RETRY_LIMIT);
322		bt->state = BT_STATE_HOSED;
323		if (!bt->nonzero_status)
324			printk(KERN_ERR "IPMI: BT stuck, try power cycle\n");
325		else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) {
326			/* most likely during insmod */
327			printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n");
328        		bt->state = BT_STATE_RESET1;
329		}
330	return;
331	}
332
333	/* Sometimes the BMC queues get in an "off-by-one" state...*/
334	if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) {
335    		printk("retry B2H_WAIT\n");
336		return;
337	}
338
339	printk("restart command\n");
340	bt->state = BT_STATE_RESTART;
341}
342
343/* Check the status and (possibly) advance the BT state machine.  The
344   default return is SI_SM_CALL_WITH_DELAY. */
345
346static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
347{
348	unsigned char status;
349	char buf[40]; /* For getting status */
350	int i;
351
352	status = BT_STATUS;
353	bt->nonzero_status |= status;
354
355	if ((bt_debug & BT_DEBUG_STATES) && (bt->state != bt->last_state))
356		printk(KERN_WARNING "BT: %s %s TO=%ld - %ld \n",
357			STATE2TXT,
358			STATUS2TXT(buf),
359			bt->timeout,
360			time);
361	bt->last_state = bt->state;
362
363	if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED;
364
365	if (bt->state != BT_STATE_IDLE) {	/* do timeout test */
366
367		/* Certain states, on error conditions, can lock up a CPU
368		   because they are effectively in an infinite loop with
369		   CALL_WITHOUT_DELAY (right back here with time == 0).
370		   Prevent infinite lockup by ALWAYS decrementing timeout. */
371
372    	/* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
373              (noticed in ipmi_smic_sm.c January 2004) */
374
375		if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100;
376		bt->timeout -= time;
377		if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
378			error_recovery(bt, "timed out");
379			return SI_SM_CALL_WITHOUT_DELAY;
380		}
381	}
382
383	switch (bt->state) {
384
385    	case BT_STATE_IDLE:	/* check for asynchronous messages */
386		if (status & BT_SMS_ATN) {
387			BT_CONTROL(BT_SMS_ATN);	/* clear it */
388			return SI_SM_ATTN;
389		}
390		return SI_SM_IDLE;
391
392	case BT_STATE_XACTION_START:
393		if (status & BT_H_BUSY) {
394			BT_CONTROL(BT_H_BUSY);
395			break;
396		}
397    		if (status & BT_B2H_ATN) break;
398		bt->state = BT_STATE_WRITE_BYTES;
399		return SI_SM_CALL_WITHOUT_DELAY;	/* for logging */
400
401	case BT_STATE_WRITE_BYTES:
402		if (status & (BT_B_BUSY | BT_H2B_ATN)) break;
403		BT_CONTROL(BT_CLR_WR_PTR);
404		write_all_bytes(bt);
405		BT_CONTROL(BT_H2B_ATN);	/* clears too fast to catch? */
406		bt->state = BT_STATE_WRITE_CONSUME;
407		return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */
408
409	case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */
410        	if (status & (BT_H2B_ATN | BT_B_BUSY)) break;
411		bt->state = BT_STATE_B2H_WAIT;
412		/* fall through with status */
413
414	/* Stay in BT_STATE_B2H_WAIT until a packet matches.  However, spinning
415	   hard here, constantly reading status, seems to hold off the
416	   generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */
417
418	case BT_STATE_B2H_WAIT:
419    		if (!(status & BT_B2H_ATN)) break;
420
421		/* Assume ordered, uncached writes: no need to wait */
422		if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */
423		BT_CONTROL(BT_B2H_ATN);		/* clear it, ACK to the BMC */
424		BT_CONTROL(BT_CLR_RD_PTR);	/* reset the queue */
425		i = read_all_bytes(bt);
426		BT_CONTROL(BT_H_BUSY);		/* clear */
427		if (!i) break;			/* Try this state again */
428		bt->state = BT_STATE_READ_END;
429		return SI_SM_CALL_WITHOUT_DELAY;	/* for logging */
430
431    	case BT_STATE_READ_END:
432
433		/* I could wait on BT_H_BUSY to go clear for a truly clean
434		   exit.  However, this is already done in XACTION_START
435		   and the (possible) extra loop/status/possible wait affects
436		   performance.  So, as long as it works, just ignore H_BUSY */
437
438#ifdef MAKE_THIS_TRUE_IF_NECESSARY
439
440		if (status & BT_H_BUSY) break;
441#endif
442		bt->seq++;
443		bt->state = BT_STATE_IDLE;
444		return SI_SM_TRANSACTION_COMPLETE;
445
446	case BT_STATE_RESET1:
447    		reset_flags(bt);
448    		bt->timeout = BT_RESET_DELAY;
449		bt->state = BT_STATE_RESET2;
450		break;
451
452	case BT_STATE_RESET2:		/* Send a soft reset */
453		BT_CONTROL(BT_CLR_WR_PTR);
454		HOST2BMC(3);		/* number of bytes following */
455		HOST2BMC(0x18);		/* NetFn/LUN == Application, LUN 0 */
456		HOST2BMC(42);		/* Sequence number */
457		HOST2BMC(3);		/* Cmd == Soft reset */
458		BT_CONTROL(BT_H2B_ATN);
459		bt->state = BT_STATE_RESET3;
460		break;
461
462	case BT_STATE_RESET3:
463		if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY;
464		bt->state = BT_STATE_RESTART;	/* printk in debug modes */
465		break;
466
467	case BT_STATE_RESTART:		/* don't reset retries! */
468		bt->write_data[2] = ++bt->seq;
469		bt->read_count = 0;
470		bt->nonzero_status = 0;
471		bt->timeout = BT_NORMAL_TIMEOUT;
472		bt->state = BT_STATE_XACTION_START;
473		break;
474
475	default:	/* HOSED is supposed to be caught much earlier */
476		error_recovery(bt, "internal logic error");
477		break;
478  	}
479  	return SI_SM_CALL_WITH_DELAY;
480}
481
482static int bt_detect(struct si_sm_data *bt)
483{
484	/* It's impossible for the BT status and interrupt registers to be
485	   all 1's, (assuming a properly functioning, self-initialized BMC)
486	   but that's what you get from reading a bogus address, so we
487	   test that first.  The calling routine uses negative logic. */
488
489	if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1;
490	reset_flags(bt);
491	return 0;
492}
493
494static void bt_cleanup(struct si_sm_data *bt)
495{
496}
497
498static int bt_size(void)
499{
500	return sizeof(struct si_sm_data);
501}
502
503struct si_sm_handlers bt_smi_handlers =
504{
505	.version           = IPMI_BT_VERSION,
506	.init_data         = bt_init_data,
507	.start_transaction = bt_start_transaction,
508	.get_result        = bt_get_result,
509	.event             = bt_event,
510	.detect            = bt_detect,
511	.cleanup           = bt_cleanup,
512	.size              = bt_size,
513};