brintos

brintos / linux-shallow public Read only

0
0
Text · 15.6 KiB · bfea500 Raw
586 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * ipmi_smic_sm.c4 *5 * The state-machine driver for an IPMI SMIC driver6 *7 * It started as a copy of Corey Minyard's driver for the KSC interface8 * and the kernel patch "mmcdev-patch-245" by HP9 *10 * modified by:	Hannes Schulz <schulz@schwaar.com>11 *		ipmi@schwaar.com12 *13 *14 * Corey Minyard's driver for the KSC interface has the following15 * copyright notice:16 *   Copyright 2002 MontaVista Software Inc.17 *18 * the kernel patch "mmcdev-patch-245" by HP has the following19 * copyright notice:20 * (c) Copyright 2001 Grant Grundler (c) Copyright21 * 2001 Hewlett-Packard Company22 */23 24#define DEBUG /* So dev_dbg() is always available. */25 26#include <linux/kernel.h> /* For printk. */27#include <linux/string.h>28#include <linux/module.h>29#include <linux/moduleparam.h>30#include <linux/ipmi_msgdefs.h>		/* for completion codes */31#include "ipmi_si_sm.h"32 33/* smic_debug is a bit-field34 *	SMIC_DEBUG_ENABLE -	turned on for now35 *	SMIC_DEBUG_MSG -	commands and their responses36 *	SMIC_DEBUG_STATES -	state machine37*/38#define SMIC_DEBUG_STATES	439#define SMIC_DEBUG_MSG		240#define	SMIC_DEBUG_ENABLE	141 42static int smic_debug = 1;43module_param(smic_debug, int, 0644);44MODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states");45 46enum smic_states {47	SMIC_IDLE,48	SMIC_START_OP,49	SMIC_OP_OK,50	SMIC_WRITE_START,51	SMIC_WRITE_NEXT,52	SMIC_WRITE_END,53	SMIC_WRITE2READ,54	SMIC_READ_START,55	SMIC_READ_NEXT,56	SMIC_READ_END,57	SMIC_HOSED58};59 60#define MAX_SMIC_READ_SIZE 8061#define MAX_SMIC_WRITE_SIZE 8062#define SMIC_MAX_ERROR_RETRIES 363 64/* Timeouts in microseconds. */65#define SMIC_RETRY_TIMEOUT (2*USEC_PER_SEC)66 67/* SMIC Flags Register Bits */68#define SMIC_RX_DATA_READY	0x8069#define SMIC_TX_DATA_READY	0x4070 71/*72 * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by73 * a few systems, and then only by Systems Management74 * Interrupts, not by the OS.  Always ignore these bits.75 *76 */77#define SMIC_SMI		0x1078#define SMIC_EVM_DATA_AVAIL	0x0879#define SMIC_SMS_DATA_AVAIL	0x0480#define SMIC_FLAG_BSY		0x0181 82/* SMIC Error Codes */83#define	EC_NO_ERROR		0x0084#define	EC_ABORTED		0x0185#define	EC_ILLEGAL_CONTROL	0x0286#define	EC_NO_RESPONSE		0x0387#define	EC_ILLEGAL_COMMAND	0x0488#define	EC_BUFFER_FULL		0x0589 90struct si_sm_data {91	enum smic_states state;92	struct si_sm_io *io;93	unsigned char	 write_data[MAX_SMIC_WRITE_SIZE];94	int		 write_pos;95	int		 write_count;96	int		 orig_write_count;97	unsigned char	 read_data[MAX_SMIC_READ_SIZE];98	int		 read_pos;99	int		 truncated;100	unsigned int	 error_retries;101	long		 smic_timeout;102};103 104static unsigned int init_smic_data(struct si_sm_data *smic,105				   struct si_sm_io *io)106{107	smic->state = SMIC_IDLE;108	smic->io = io;109	smic->write_pos = 0;110	smic->write_count = 0;111	smic->orig_write_count = 0;112	smic->read_pos = 0;113	smic->error_retries = 0;114	smic->truncated = 0;115	smic->smic_timeout = SMIC_RETRY_TIMEOUT;116 117	/* We use 3 bytes of I/O. */118	return 3;119}120 121static int start_smic_transaction(struct si_sm_data *smic,122				  unsigned char *data, unsigned int size)123{124	unsigned int i;125 126	if (size < 2)127		return IPMI_REQ_LEN_INVALID_ERR;128	if (size > MAX_SMIC_WRITE_SIZE)129		return IPMI_REQ_LEN_EXCEEDED_ERR;130 131	if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) {132		dev_warn(smic->io->dev,133			 "SMIC in invalid state %d\n", smic->state);134		return IPMI_NOT_IN_MY_STATE_ERR;135	}136 137	if (smic_debug & SMIC_DEBUG_MSG) {138		dev_dbg(smic->io->dev, "%s -", __func__);139		for (i = 0; i < size; i++)140			pr_cont(" %02x", data[i]);141		pr_cont("\n");142	}143	smic->error_retries = 0;144	memcpy(smic->write_data, data, size);145	smic->write_count = size;146	smic->orig_write_count = size;147	smic->write_pos = 0;148	smic->read_pos = 0;149	smic->state = SMIC_START_OP;150	smic->smic_timeout = SMIC_RETRY_TIMEOUT;151	return 0;152}153 154static int smic_get_result(struct si_sm_data *smic,155			   unsigned char *data, unsigned int length)156{157	int i;158 159	if (smic_debug & SMIC_DEBUG_MSG) {160		dev_dbg(smic->io->dev, "smic_get result -");161		for (i = 0; i < smic->read_pos; i++)162			pr_cont(" %02x", smic->read_data[i]);163		pr_cont("\n");164	}165	if (length < smic->read_pos) {166		smic->read_pos = length;167		smic->truncated = 1;168	}169	memcpy(data, smic->read_data, smic->read_pos);170 171	if ((length >= 3) && (smic->read_pos < 3)) {172		data[2] = IPMI_ERR_UNSPECIFIED;173		smic->read_pos = 3;174	}175	if (smic->truncated) {176		data[2] = IPMI_ERR_MSG_TRUNCATED;177		smic->truncated = 0;178	}179	return smic->read_pos;180}181 182static inline unsigned char read_smic_flags(struct si_sm_data *smic)183{184	return smic->io->inputb(smic->io, 2);185}186 187static inline unsigned char read_smic_status(struct si_sm_data *smic)188{189	return smic->io->inputb(smic->io, 1);190}191 192static inline unsigned char read_smic_data(struct si_sm_data *smic)193{194	return smic->io->inputb(smic->io, 0);195}196 197static inline void write_smic_flags(struct si_sm_data *smic,198				    unsigned char   flags)199{200	smic->io->outputb(smic->io, 2, flags);201}202 203static inline void write_smic_control(struct si_sm_data *smic,204				      unsigned char   control)205{206	smic->io->outputb(smic->io, 1, control);207}208 209static inline void write_si_sm_data(struct si_sm_data *smic,210				    unsigned char   data)211{212	smic->io->outputb(smic->io, 0, data);213}214 215static inline void start_error_recovery(struct si_sm_data *smic, char *reason)216{217	(smic->error_retries)++;218	if (smic->error_retries > SMIC_MAX_ERROR_RETRIES) {219		if (smic_debug & SMIC_DEBUG_ENABLE)220			pr_warn("ipmi_smic_drv: smic hosed: %s\n", reason);221		smic->state = SMIC_HOSED;222	} else {223		smic->write_count = smic->orig_write_count;224		smic->write_pos = 0;225		smic->read_pos = 0;226		smic->state = SMIC_START_OP;227		smic->smic_timeout = SMIC_RETRY_TIMEOUT;228	}229}230 231static inline void write_next_byte(struct si_sm_data *smic)232{233	write_si_sm_data(smic, smic->write_data[smic->write_pos]);234	(smic->write_pos)++;235	(smic->write_count)--;236}237 238static inline void read_next_byte(struct si_sm_data *smic)239{240	if (smic->read_pos >= MAX_SMIC_READ_SIZE) {241		read_smic_data(smic);242		smic->truncated = 1;243	} else {244		smic->read_data[smic->read_pos] = read_smic_data(smic);245		smic->read_pos++;246	}247}248 249/*  SMIC Control/Status Code Components */250#define	SMIC_GET_STATUS		0x00	/* Control form's name */251#define	SMIC_READY		0x00	/* Status  form's name */252#define	SMIC_WR_START		0x01	/* Unified Control/Status names... */253#define	SMIC_WR_NEXT		0x02254#define	SMIC_WR_END		0x03255#define	SMIC_RD_START		0x04256#define	SMIC_RD_NEXT		0x05257#define	SMIC_RD_END		0x06258#define	SMIC_CODE_MASK		0x0f259 260#define	SMIC_CONTROL		0x00261#define	SMIC_STATUS		0x80262#define	SMIC_CS_MASK		0x80263 264#define	SMIC_SMS		0x40265#define	SMIC_SMM		0x60266#define	SMIC_STREAM_MASK	0x60267 268/*  SMIC Control Codes */269#define	SMIC_CC_SMS_GET_STATUS	(SMIC_CONTROL|SMIC_SMS|SMIC_GET_STATUS)270#define	SMIC_CC_SMS_WR_START	(SMIC_CONTROL|SMIC_SMS|SMIC_WR_START)271#define	SMIC_CC_SMS_WR_NEXT	(SMIC_CONTROL|SMIC_SMS|SMIC_WR_NEXT)272#define	SMIC_CC_SMS_WR_END	(SMIC_CONTROL|SMIC_SMS|SMIC_WR_END)273#define	SMIC_CC_SMS_RD_START	(SMIC_CONTROL|SMIC_SMS|SMIC_RD_START)274#define	SMIC_CC_SMS_RD_NEXT	(SMIC_CONTROL|SMIC_SMS|SMIC_RD_NEXT)275#define	SMIC_CC_SMS_RD_END	(SMIC_CONTROL|SMIC_SMS|SMIC_RD_END)276 277#define	SMIC_CC_SMM_GET_STATUS	(SMIC_CONTROL|SMIC_SMM|SMIC_GET_STATUS)278#define	SMIC_CC_SMM_WR_START	(SMIC_CONTROL|SMIC_SMM|SMIC_WR_START)279#define	SMIC_CC_SMM_WR_NEXT	(SMIC_CONTROL|SMIC_SMM|SMIC_WR_NEXT)280#define	SMIC_CC_SMM_WR_END	(SMIC_CONTROL|SMIC_SMM|SMIC_WR_END)281#define	SMIC_CC_SMM_RD_START	(SMIC_CONTROL|SMIC_SMM|SMIC_RD_START)282#define	SMIC_CC_SMM_RD_NEXT	(SMIC_CONTROL|SMIC_SMM|SMIC_RD_NEXT)283#define	SMIC_CC_SMM_RD_END	(SMIC_CONTROL|SMIC_SMM|SMIC_RD_END)284 285/*  SMIC Status Codes */286#define	SMIC_SC_SMS_READY	(SMIC_STATUS|SMIC_SMS|SMIC_READY)287#define	SMIC_SC_SMS_WR_START	(SMIC_STATUS|SMIC_SMS|SMIC_WR_START)288#define	SMIC_SC_SMS_WR_NEXT	(SMIC_STATUS|SMIC_SMS|SMIC_WR_NEXT)289#define	SMIC_SC_SMS_WR_END	(SMIC_STATUS|SMIC_SMS|SMIC_WR_END)290#define	SMIC_SC_SMS_RD_START	(SMIC_STATUS|SMIC_SMS|SMIC_RD_START)291#define	SMIC_SC_SMS_RD_NEXT	(SMIC_STATUS|SMIC_SMS|SMIC_RD_NEXT)292#define	SMIC_SC_SMS_RD_END	(SMIC_STATUS|SMIC_SMS|SMIC_RD_END)293 294#define	SMIC_SC_SMM_READY	(SMIC_STATUS|SMIC_SMM|SMIC_READY)295#define	SMIC_SC_SMM_WR_START	(SMIC_STATUS|SMIC_SMM|SMIC_WR_START)296#define	SMIC_SC_SMM_WR_NEXT	(SMIC_STATUS|SMIC_SMM|SMIC_WR_NEXT)297#define	SMIC_SC_SMM_WR_END	(SMIC_STATUS|SMIC_SMM|SMIC_WR_END)298#define	SMIC_SC_SMM_RD_START	(SMIC_STATUS|SMIC_SMM|SMIC_RD_START)299#define	SMIC_SC_SMM_RD_NEXT	(SMIC_STATUS|SMIC_SMM|SMIC_RD_NEXT)300#define	SMIC_SC_SMM_RD_END	(SMIC_STATUS|SMIC_SMM|SMIC_RD_END)301 302/* these are the control/status codes we actually use303	SMIC_CC_SMS_GET_STATUS	0x40304	SMIC_CC_SMS_WR_START	0x41305	SMIC_CC_SMS_WR_NEXT	0x42306	SMIC_CC_SMS_WR_END	0x43307	SMIC_CC_SMS_RD_START	0x44308	SMIC_CC_SMS_RD_NEXT	0x45309	SMIC_CC_SMS_RD_END	0x46310 311	SMIC_SC_SMS_READY	0xC0312	SMIC_SC_SMS_WR_START	0xC1313	SMIC_SC_SMS_WR_NEXT	0xC2314	SMIC_SC_SMS_WR_END	0xC3315	SMIC_SC_SMS_RD_START	0xC4316	SMIC_SC_SMS_RD_NEXT	0xC5317	SMIC_SC_SMS_RD_END	0xC6318*/319 320static enum si_sm_result smic_event(struct si_sm_data *smic, long time)321{322	unsigned char status;323	unsigned char flags;324	unsigned char data;325 326	if (smic->state == SMIC_HOSED) {327		init_smic_data(smic, smic->io);328		return SI_SM_HOSED;329	}330	if (smic->state != SMIC_IDLE) {331		if (smic_debug & SMIC_DEBUG_STATES)332			dev_dbg(smic->io->dev,333				"%s - smic->smic_timeout = %ld, time = %ld\n",334				__func__, smic->smic_timeout, time);335		/*336		 * FIXME: smic_event is sometimes called with time >337		 * SMIC_RETRY_TIMEOUT338		 */339		if (time < SMIC_RETRY_TIMEOUT) {340			smic->smic_timeout -= time;341			if (smic->smic_timeout < 0) {342				start_error_recovery(smic, "smic timed out.");343				return SI_SM_CALL_WITH_DELAY;344			}345		}346	}347	flags = read_smic_flags(smic);348	if (flags & SMIC_FLAG_BSY)349		return SI_SM_CALL_WITH_DELAY;350 351	status = read_smic_status(smic);352	if (smic_debug & SMIC_DEBUG_STATES)353		dev_dbg(smic->io->dev,354			"%s - state = %d, flags = 0x%02x, status = 0x%02x\n",355			__func__, smic->state, flags, status);356 357	switch (smic->state) {358	case SMIC_IDLE:359		/* in IDLE we check for available messages */360		if (flags & SMIC_SMS_DATA_AVAIL)361			return SI_SM_ATTN;362		return SI_SM_IDLE;363 364	case SMIC_START_OP:365		/* sanity check whether smic is really idle */366		write_smic_control(smic, SMIC_CC_SMS_GET_STATUS);367		write_smic_flags(smic, flags | SMIC_FLAG_BSY);368		smic->state = SMIC_OP_OK;369		break;370 371	case SMIC_OP_OK:372		if (status != SMIC_SC_SMS_READY) {373			/* this should not happen */374			start_error_recovery(smic,375					     "state = SMIC_OP_OK,"376					     " status != SMIC_SC_SMS_READY");377			return SI_SM_CALL_WITH_DELAY;378		}379		/* OK so far; smic is idle let us start ... */380		write_smic_control(smic, SMIC_CC_SMS_WR_START);381		write_next_byte(smic);382		write_smic_flags(smic, flags | SMIC_FLAG_BSY);383		smic->state = SMIC_WRITE_START;384		break;385 386	case SMIC_WRITE_START:387		if (status != SMIC_SC_SMS_WR_START) {388			start_error_recovery(smic,389					     "state = SMIC_WRITE_START, "390					     "status != SMIC_SC_SMS_WR_START");391			return SI_SM_CALL_WITH_DELAY;392		}393		/*394		 * we must not issue WR_(NEXT|END) unless395		 * TX_DATA_READY is set396		 * */397		if (flags & SMIC_TX_DATA_READY) {398			if (smic->write_count == 1) {399				/* last byte */400				write_smic_control(smic, SMIC_CC_SMS_WR_END);401				smic->state = SMIC_WRITE_END;402			} else {403				write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);404				smic->state = SMIC_WRITE_NEXT;405			}406			write_next_byte(smic);407			write_smic_flags(smic, flags | SMIC_FLAG_BSY);408		} else409			return SI_SM_CALL_WITH_DELAY;410		break;411 412	case SMIC_WRITE_NEXT:413		if (status != SMIC_SC_SMS_WR_NEXT) {414			start_error_recovery(smic,415					     "state = SMIC_WRITE_NEXT, "416					     "status != SMIC_SC_SMS_WR_NEXT");417			return SI_SM_CALL_WITH_DELAY;418		}419		/* this is the same code as in SMIC_WRITE_START */420		if (flags & SMIC_TX_DATA_READY) {421			if (smic->write_count == 1) {422				write_smic_control(smic, SMIC_CC_SMS_WR_END);423				smic->state = SMIC_WRITE_END;424			} else {425				write_smic_control(smic, SMIC_CC_SMS_WR_NEXT);426				smic->state = SMIC_WRITE_NEXT;427			}428			write_next_byte(smic);429			write_smic_flags(smic, flags | SMIC_FLAG_BSY);430		} else431			return SI_SM_CALL_WITH_DELAY;432		break;433 434	case SMIC_WRITE_END:435		if (status != SMIC_SC_SMS_WR_END) {436			start_error_recovery(smic,437					     "state = SMIC_WRITE_END, "438					     "status != SMIC_SC_SMS_WR_END");439			return SI_SM_CALL_WITH_DELAY;440		}441		/* data register holds an error code */442		data = read_smic_data(smic);443		if (data != 0) {444			if (smic_debug & SMIC_DEBUG_ENABLE)445				dev_dbg(smic->io->dev,446					"SMIC_WRITE_END: data = %02x\n",447					data);448			start_error_recovery(smic,449					     "state = SMIC_WRITE_END, "450					     "data != SUCCESS");451			return SI_SM_CALL_WITH_DELAY;452		} else453			smic->state = SMIC_WRITE2READ;454		break;455 456	case SMIC_WRITE2READ:457		/*458		 * we must wait for RX_DATA_READY to be set before we459		 * can continue460		 */461		if (flags & SMIC_RX_DATA_READY) {462			write_smic_control(smic, SMIC_CC_SMS_RD_START);463			write_smic_flags(smic, flags | SMIC_FLAG_BSY);464			smic->state = SMIC_READ_START;465		} else466			return SI_SM_CALL_WITH_DELAY;467		break;468 469	case SMIC_READ_START:470		if (status != SMIC_SC_SMS_RD_START) {471			start_error_recovery(smic,472					     "state = SMIC_READ_START, "473					     "status != SMIC_SC_SMS_RD_START");474			return SI_SM_CALL_WITH_DELAY;475		}476		if (flags & SMIC_RX_DATA_READY) {477			read_next_byte(smic);478			write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);479			write_smic_flags(smic, flags | SMIC_FLAG_BSY);480			smic->state = SMIC_READ_NEXT;481		} else482			return SI_SM_CALL_WITH_DELAY;483		break;484 485	case SMIC_READ_NEXT:486		switch (status) {487		/*488		 * smic tells us that this is the last byte to be read489		 * --> clean up490		 */491		case SMIC_SC_SMS_RD_END:492			read_next_byte(smic);493			write_smic_control(smic, SMIC_CC_SMS_RD_END);494			write_smic_flags(smic, flags | SMIC_FLAG_BSY);495			smic->state = SMIC_READ_END;496			break;497		case SMIC_SC_SMS_RD_NEXT:498			if (flags & SMIC_RX_DATA_READY) {499				read_next_byte(smic);500				write_smic_control(smic, SMIC_CC_SMS_RD_NEXT);501				write_smic_flags(smic, flags | SMIC_FLAG_BSY);502				smic->state = SMIC_READ_NEXT;503			} else504				return SI_SM_CALL_WITH_DELAY;505			break;506		default:507			start_error_recovery(508				smic,509				"state = SMIC_READ_NEXT, "510				"status != SMIC_SC_SMS_RD_(NEXT|END)");511			return SI_SM_CALL_WITH_DELAY;512		}513		break;514 515	case SMIC_READ_END:516		if (status != SMIC_SC_SMS_READY) {517			start_error_recovery(smic,518					     "state = SMIC_READ_END, "519					     "status != SMIC_SC_SMS_READY");520			return SI_SM_CALL_WITH_DELAY;521		}522		data = read_smic_data(smic);523		/* data register holds an error code */524		if (data != 0) {525			if (smic_debug & SMIC_DEBUG_ENABLE)526				dev_dbg(smic->io->dev,527					"SMIC_READ_END: data = %02x\n",528					data);529			start_error_recovery(smic,530					     "state = SMIC_READ_END, "531					     "data != SUCCESS");532			return SI_SM_CALL_WITH_DELAY;533		} else {534			smic->state = SMIC_IDLE;535			return SI_SM_TRANSACTION_COMPLETE;536		}537 538	case SMIC_HOSED:539		init_smic_data(smic, smic->io);540		return SI_SM_HOSED;541 542	default:543		if (smic_debug & SMIC_DEBUG_ENABLE) {544			dev_dbg(smic->io->dev,545				"smic->state = %d\n", smic->state);546			start_error_recovery(smic, "state = UNKNOWN");547			return SI_SM_CALL_WITH_DELAY;548		}549	}550	smic->smic_timeout = SMIC_RETRY_TIMEOUT;551	return SI_SM_CALL_WITHOUT_DELAY;552}553 554static int smic_detect(struct si_sm_data *smic)555{556	/*557	 * It's impossible for the SMIC fnags register to be all 1's,558	 * (assuming a properly functioning, self-initialized BMC)559	 * but that's what you get from reading a bogus address, so we560	 * test that first.561	 */562	if (read_smic_flags(smic) == 0xff)563		return 1;564 565	return 0;566}567 568static void smic_cleanup(struct si_sm_data *kcs)569{570}571 572static int smic_size(void)573{574	return sizeof(struct si_sm_data);575}576 577const struct si_sm_handlers smic_smi_handlers = {578	.init_data         = init_smic_data,579	.start_transaction = start_smic_transaction,580	.get_result        = smic_get_result,581	.event             = smic_event,582	.detect            = smic_detect,583	.cleanup           = smic_cleanup,584	.size              = smic_size,585};586