blob: 2e7cda08b079699c21fd8433cd7da947745ceda1 [file] [log] [blame]
Corey Minyard243ac212018-02-20 07:30:22 -06001// SPDX-License-Identifier: GPL-2.0+
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * ipmi_kcs_sm.c
4 *
5 * State machine for handling IPMI KCS interfaces.
6 *
7 * Author: MontaVista Software, Inc.
8 * Corey Minyard <minyard@mvista.com>
9 * source@mvista.com
10 *
11 * Copyright 2002 MontaVista Software Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 */
13
14/*
15 * This state machine is taken from the state machine in the IPMI spec,
16 * pretty much verbatim. If you have questions about the states, see
17 * that document.
18 */
19
20#include <linux/kernel.h> /* For printk. */
Corey Minyardc4edff12005-11-07 00:59:56 -080021#include <linux/module.h>
22#include <linux/moduleparam.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/string.h>
Corey Minyardc3e7e792005-11-07 01:00:02 -080024#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/ipmi_msgdefs.h> /* for completion codes */
26#include "ipmi_si_sm.h"
27
Corey Minyardc4edff12005-11-07 00:59:56 -080028/* kcs_debug is a bit-field
29 * KCS_DEBUG_ENABLE - turned on for now
30 * KCS_DEBUG_MSG - commands and their responses
31 * KCS_DEBUG_STATES - state machine
32 */
33#define KCS_DEBUG_STATES 4
34#define KCS_DEBUG_MSG 2
35#define KCS_DEBUG_ENABLE 1
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
Corey Minyardc4edff12005-11-07 00:59:56 -080037static int kcs_debug;
38module_param(kcs_debug, int, 0644);
39MODULE_PARM_DESC(kcs_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41/* The states the KCS driver may be in. */
42enum kcs_states {
Corey Minyardc305e3d2008-04-29 01:01:10 -070043 /* The KCS interface is currently doing nothing. */
44 KCS_IDLE,
45
46 /*
47 * We are starting an operation. The data is in the output
48 * buffer, but nothing has been done to the interface yet. This
49 * was added to the state machine in the spec to wait for the
50 * initial IBF.
51 */
52 KCS_START_OP,
53
54 /* We have written a write cmd to the interface. */
55 KCS_WAIT_WRITE_START,
56
57 /* We are writing bytes to the interface. */
58 KCS_WAIT_WRITE,
59
60 /*
61 * We have written the write end cmd to the interface, and
62 * still need to write the last byte.
63 */
64 KCS_WAIT_WRITE_END,
65
66 /* We are waiting to read data from the interface. */
67 KCS_WAIT_READ,
68
69 /*
70 * State to transition to the error handler, this was added to
71 * the state machine in the spec to be sure IBF was there.
72 */
73 KCS_ERROR0,
74
75 /*
76 * First stage error handler, wait for the interface to
77 * respond.
78 */
79 KCS_ERROR1,
80
81 /*
82 * The abort cmd has been written, wait for the interface to
83 * respond.
84 */
85 KCS_ERROR2,
86
87 /*
88 * We wrote some data to the interface, wait for it to switch
89 * to read mode.
90 */
91 KCS_ERROR3,
92
93 /* The hardware failed to follow the state machine. */
94 KCS_HOSED
Linus Torvalds1da177e2005-04-16 15:20:36 -070095};
96
Corey Minyard5a1099b2006-12-06 20:41:16 -080097#define MAX_KCS_READ_SIZE IPMI_MAX_MSG_LENGTH
98#define MAX_KCS_WRITE_SIZE IPMI_MAX_MSG_LENGTH
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100/* Timeouts in microseconds. */
Xie XiuQiccb33682014-01-24 14:00:51 -0600101#define IBF_RETRY_TIMEOUT (5*USEC_PER_SEC)
102#define OBF_RETRY_TIMEOUT (5*USEC_PER_SEC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103#define MAX_ERROR_RETRIES 10
Corey Minyardc3e7e792005-11-07 01:00:02 -0800104#define ERROR0_OBF_WAIT_JIFFIES (2*HZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
Corey Minyardc305e3d2008-04-29 01:01:10 -0700106struct si_sm_data {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 enum kcs_states state;
108 struct si_sm_io *io;
109 unsigned char write_data[MAX_KCS_WRITE_SIZE];
110 int write_pos;
111 int write_count;
112 int orig_write_count;
113 unsigned char read_data[MAX_KCS_READ_SIZE];
114 int read_pos;
115 int truncated;
116
117 unsigned int error_retries;
118 long ibf_timeout;
119 long obf_timeout;
Corey Minyardc3e7e792005-11-07 01:00:02 -0800120 unsigned long error0_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121};
122
123static unsigned int init_kcs_data(struct si_sm_data *kcs,
124 struct si_sm_io *io)
125{
126 kcs->state = KCS_IDLE;
127 kcs->io = io;
128 kcs->write_pos = 0;
129 kcs->write_count = 0;
130 kcs->orig_write_count = 0;
131 kcs->read_pos = 0;
132 kcs->error_retries = 0;
133 kcs->truncated = 0;
134 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
135 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
136
137 /* Reserve 2 I/O bytes. */
138 return 2;
139}
140
141static inline unsigned char read_status(struct si_sm_data *kcs)
142{
143 return kcs->io->inputb(kcs->io, 1);
144}
145
146static inline unsigned char read_data(struct si_sm_data *kcs)
147{
148 return kcs->io->inputb(kcs->io, 0);
149}
150
151static inline void write_cmd(struct si_sm_data *kcs, unsigned char data)
152{
153 kcs->io->outputb(kcs->io, 1, data);
154}
155
156static inline void write_data(struct si_sm_data *kcs, unsigned char data)
157{
158 kcs->io->outputb(kcs->io, 0, data);
159}
160
161/* Control codes. */
162#define KCS_GET_STATUS_ABORT 0x60
163#define KCS_WRITE_START 0x61
164#define KCS_WRITE_END 0x62
165#define KCS_READ_BYTE 0x68
166
167/* Status bits. */
168#define GET_STATUS_STATE(status) (((status) >> 6) & 0x03)
169#define KCS_IDLE_STATE 0
170#define KCS_READ_STATE 1
171#define KCS_WRITE_STATE 2
172#define KCS_ERROR_STATE 3
173#define GET_STATUS_ATN(status) ((status) & 0x04)
174#define GET_STATUS_IBF(status) ((status) & 0x02)
175#define GET_STATUS_OBF(status) ((status) & 0x01)
176
177
178static inline void write_next_byte(struct si_sm_data *kcs)
179{
180 write_data(kcs, kcs->write_data[kcs->write_pos]);
181 (kcs->write_pos)++;
182 (kcs->write_count)--;
183}
184
185static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
186{
187 (kcs->error_retries)++;
188 if (kcs->error_retries > MAX_ERROR_RETRIES) {
Corey Minyardc4edff12005-11-07 00:59:56 -0800189 if (kcs_debug & KCS_DEBUG_ENABLE)
Corey Minyardc305e3d2008-04-29 01:01:10 -0700190 printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n",
191 reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 kcs->state = KCS_HOSED;
193 } else {
Corey Minyardc3e7e792005-11-07 01:00:02 -0800194 kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 kcs->state = KCS_ERROR0;
196 }
197}
198
199static inline void read_next_byte(struct si_sm_data *kcs)
200{
201 if (kcs->read_pos >= MAX_KCS_READ_SIZE) {
202 /* Throw the data away and mark it truncated. */
203 read_data(kcs);
204 kcs->truncated = 1;
205 } else {
206 kcs->read_data[kcs->read_pos] = read_data(kcs);
207 (kcs->read_pos)++;
208 }
209 write_data(kcs, KCS_READ_BYTE);
210}
211
212static inline int check_ibf(struct si_sm_data *kcs, unsigned char status,
213 long time)
214{
215 if (GET_STATUS_IBF(status)) {
216 kcs->ibf_timeout -= time;
217 if (kcs->ibf_timeout < 0) {
218 start_error_recovery(kcs, "IBF not ready in time");
219 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
220 return 1;
221 }
222 return 0;
223 }
224 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
225 return 1;
226}
227
228static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
229 long time)
230{
Corey Minyard8a3628d2006-03-31 02:30:40 -0800231 if (!GET_STATUS_OBF(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 kcs->obf_timeout -= time;
233 if (kcs->obf_timeout < 0) {
Corey Minyardeb6d78e2014-04-14 09:46:52 -0500234 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
235 start_error_recovery(kcs, "OBF not ready in time");
236 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 }
238 return 0;
239 }
240 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
241 return 1;
242}
243
244static void clear_obf(struct si_sm_data *kcs, unsigned char status)
245{
246 if (GET_STATUS_OBF(status))
247 read_data(kcs);
248}
249
250static void restart_kcs_transaction(struct si_sm_data *kcs)
251{
252 kcs->write_count = kcs->orig_write_count;
253 kcs->write_pos = 0;
254 kcs->read_pos = 0;
255 kcs->state = KCS_WAIT_WRITE_START;
256 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
257 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
258 write_cmd(kcs, KCS_WRITE_START);
259}
260
261static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
262 unsigned int size)
263{
Corey Minyardc4edff12005-11-07 00:59:56 -0800264 unsigned int i;
265
Corey Minyard4d7cbac2006-12-06 20:41:14 -0800266 if (size < 2)
267 return IPMI_REQ_LEN_INVALID_ERR;
268 if (size > MAX_KCS_WRITE_SIZE)
269 return IPMI_REQ_LEN_EXCEEDED_ERR;
270
271 if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED))
272 return IPMI_NOT_IN_MY_STATE_ERR;
273
Corey Minyardc4edff12005-11-07 00:59:56 -0800274 if (kcs_debug & KCS_DEBUG_MSG) {
275 printk(KERN_DEBUG "start_kcs_transaction -");
Corey Minyardc305e3d2008-04-29 01:01:10 -0700276 for (i = 0; i < size; i++)
Joe Perchesf993cdd2018-05-09 08:15:49 -0700277 pr_cont(" %02x", data[i]);
278 pr_cont("\n");
Corey Minyardc4edff12005-11-07 00:59:56 -0800279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 kcs->error_retries = 0;
281 memcpy(kcs->write_data, data, size);
282 kcs->write_count = size;
283 kcs->orig_write_count = size;
284 kcs->write_pos = 0;
285 kcs->read_pos = 0;
286 kcs->state = KCS_START_OP;
287 kcs->ibf_timeout = IBF_RETRY_TIMEOUT;
288 kcs->obf_timeout = OBF_RETRY_TIMEOUT;
289 return 0;
290}
291
292static int get_kcs_result(struct si_sm_data *kcs, unsigned char *data,
293 unsigned int length)
294{
295 if (length < kcs->read_pos) {
296 kcs->read_pos = length;
297 kcs->truncated = 1;
298 }
299
300 memcpy(data, kcs->read_data, kcs->read_pos);
301
302 if ((length >= 3) && (kcs->read_pos < 3)) {
303 /* Guarantee that we return at least 3 bytes, with an
304 error in the third byte if it is too short. */
305 data[2] = IPMI_ERR_UNSPECIFIED;
306 kcs->read_pos = 3;
307 }
308 if (kcs->truncated) {
Corey Minyardc305e3d2008-04-29 01:01:10 -0700309 /*
310 * Report a truncated error. We might overwrite
311 * another error, but that's too bad, the user needs
312 * to know it was truncated.
313 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 data[2] = IPMI_ERR_MSG_TRUNCATED;
315 kcs->truncated = 0;
316 }
317
318 return kcs->read_pos;
319}
320
Corey Minyardc305e3d2008-04-29 01:01:10 -0700321/*
322 * This implements the state machine defined in the IPMI manual, see
323 * that for details on how this works. Divide that flowchart into
324 * sections delimited by "Wait for IBF" and this will become clear.
325 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
327{
328 unsigned char status;
329 unsigned char state;
330
331 status = read_status(kcs);
332
Corey Minyardc4edff12005-11-07 00:59:56 -0800333 if (kcs_debug & KCS_DEBUG_STATES)
334 printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status);
335
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 /* All states wait for ibf, so just do it here. */
337 if (!check_ibf(kcs, status, time))
338 return SI_SM_CALL_WITH_DELAY;
339
340 /* Just about everything looks at the KCS state, so grab that, too. */
341 state = GET_STATUS_STATE(status);
342
343 switch (kcs->state) {
344 case KCS_IDLE:
345 /* If there's and interrupt source, turn it off. */
346 clear_obf(kcs, status);
347
348 if (GET_STATUS_ATN(status))
349 return SI_SM_ATTN;
350 else
351 return SI_SM_IDLE;
352
353 case KCS_START_OP:
Julia Lawalld1da96a2009-12-15 16:47:37 -0800354 if (state != KCS_IDLE_STATE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 start_error_recovery(kcs,
356 "State machine not idle at start");
357 break;
358 }
359
360 clear_obf(kcs, status);
361 write_cmd(kcs, KCS_WRITE_START);
362 kcs->state = KCS_WAIT_WRITE_START;
363 break;
364
365 case KCS_WAIT_WRITE_START:
366 if (state != KCS_WRITE_STATE) {
367 start_error_recovery(
368 kcs,
369 "Not in write state at write start");
370 break;
371 }
372 read_data(kcs);
373 if (kcs->write_count == 1) {
374 write_cmd(kcs, KCS_WRITE_END);
375 kcs->state = KCS_WAIT_WRITE_END;
376 } else {
377 write_next_byte(kcs);
378 kcs->state = KCS_WAIT_WRITE;
379 }
380 break;
381
382 case KCS_WAIT_WRITE:
383 if (state != KCS_WRITE_STATE) {
384 start_error_recovery(kcs,
385 "Not in write state for write");
386 break;
387 }
388 clear_obf(kcs, status);
389 if (kcs->write_count == 1) {
390 write_cmd(kcs, KCS_WRITE_END);
391 kcs->state = KCS_WAIT_WRITE_END;
392 } else {
393 write_next_byte(kcs);
394 }
395 break;
Corey Minyardc305e3d2008-04-29 01:01:10 -0700396
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 case KCS_WAIT_WRITE_END:
398 if (state != KCS_WRITE_STATE) {
399 start_error_recovery(kcs,
Corey Minyardc305e3d2008-04-29 01:01:10 -0700400 "Not in write state"
401 " for write end");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 break;
403 }
404 clear_obf(kcs, status);
405 write_next_byte(kcs);
406 kcs->state = KCS_WAIT_READ;
407 break;
408
409 case KCS_WAIT_READ:
410 if ((state != KCS_READ_STATE) && (state != KCS_IDLE_STATE)) {
411 start_error_recovery(
412 kcs,
413 "Not in read or idle in read state");
414 break;
415 }
416
417 if (state == KCS_READ_STATE) {
Corey Minyard8a3628d2006-03-31 02:30:40 -0800418 if (!check_obf(kcs, status, time))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 return SI_SM_CALL_WITH_DELAY;
420 read_next_byte(kcs);
421 } else {
Corey Minyardc305e3d2008-04-29 01:01:10 -0700422 /*
423 * We don't implement this exactly like the state
424 * machine in the spec. Some broken hardware
425 * does not write the final dummy byte to the
426 * read register. Thus obf will never go high
427 * here. We just go straight to idle, and we
428 * handle clearing out obf in idle state if it
429 * happens to come in.
430 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 clear_obf(kcs, status);
432 kcs->orig_write_count = 0;
433 kcs->state = KCS_IDLE;
434 return SI_SM_TRANSACTION_COMPLETE;
435 }
436 break;
437
438 case KCS_ERROR0:
439 clear_obf(kcs, status);
Corey Minyardc3e7e792005-11-07 01:00:02 -0800440 status = read_status(kcs);
Corey Minyardc305e3d2008-04-29 01:01:10 -0700441 if (GET_STATUS_OBF(status))
442 /* controller isn't responding */
Corey Minyardc3e7e792005-11-07 01:00:02 -0800443 if (time_before(jiffies, kcs->error0_timeout))
444 return SI_SM_CALL_WITH_TICK_DELAY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 write_cmd(kcs, KCS_GET_STATUS_ABORT);
446 kcs->state = KCS_ERROR1;
447 break;
448
449 case KCS_ERROR1:
450 clear_obf(kcs, status);
451 write_data(kcs, 0);
452 kcs->state = KCS_ERROR2;
453 break;
Corey Minyardc305e3d2008-04-29 01:01:10 -0700454
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 case KCS_ERROR2:
456 if (state != KCS_READ_STATE) {
457 start_error_recovery(kcs,
458 "Not in read state for error2");
459 break;
460 }
Corey Minyard8a3628d2006-03-31 02:30:40 -0800461 if (!check_obf(kcs, status, time))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 return SI_SM_CALL_WITH_DELAY;
463
464 clear_obf(kcs, status);
465 write_data(kcs, KCS_READ_BYTE);
466 kcs->state = KCS_ERROR3;
467 break;
Corey Minyardc305e3d2008-04-29 01:01:10 -0700468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 case KCS_ERROR3:
470 if (state != KCS_IDLE_STATE) {
471 start_error_recovery(kcs,
472 "Not in idle state for error3");
473 break;
474 }
475
Corey Minyard8a3628d2006-03-31 02:30:40 -0800476 if (!check_obf(kcs, status, time))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 return SI_SM_CALL_WITH_DELAY;
478
479 clear_obf(kcs, status);
480 if (kcs->orig_write_count) {
481 restart_kcs_transaction(kcs);
482 } else {
483 kcs->state = KCS_IDLE;
484 return SI_SM_TRANSACTION_COMPLETE;
485 }
486 break;
Corey Minyardc305e3d2008-04-29 01:01:10 -0700487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 case KCS_HOSED:
489 break;
490 }
491
492 if (kcs->state == KCS_HOSED) {
493 init_kcs_data(kcs, kcs->io);
494 return SI_SM_HOSED;
495 }
496
497 return SI_SM_CALL_WITHOUT_DELAY;
498}
499
500static int kcs_size(void)
501{
502 return sizeof(struct si_sm_data);
503}
504
505static int kcs_detect(struct si_sm_data *kcs)
506{
Corey Minyardc305e3d2008-04-29 01:01:10 -0700507 /*
508 * It's impossible for the KCS status register to be all 1's,
509 * (assuming a properly functioning, self-initialized BMC)
510 * but that's what you get from reading a bogus address, so we
511 * test that first.
512 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 if (read_status(kcs) == 0xff)
514 return 1;
515
516 return 0;
517}
518
519static void kcs_cleanup(struct si_sm_data *kcs)
520{
521}
522
Corey Minyard81d02b72015-06-13 10:34:25 -0500523const struct si_sm_handlers kcs_smi_handlers = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 .init_data = init_kcs_data,
525 .start_transaction = start_kcs_transaction,
526 .get_result = get_kcs_result,
527 .event = kcs_event,
528 .detect = kcs_detect,
529 .cleanup = kcs_cleanup,
530 .size = kcs_size,
531};