diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_bt_sm.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_bt_sm.c | 153 |
1 files changed, 94 insertions, 59 deletions
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index e736119b6497..7b98c067190a 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -37,26 +37,32 @@ | |||
37 | #define BT_DEBUG_ENABLE 1 /* Generic messages */ | 37 | #define BT_DEBUG_ENABLE 1 /* Generic messages */ |
38 | #define BT_DEBUG_MSG 2 /* Prints all request/response buffers */ | 38 | #define BT_DEBUG_MSG 2 /* Prints all request/response buffers */ |
39 | #define BT_DEBUG_STATES 4 /* Verbose look at state changes */ | 39 | #define BT_DEBUG_STATES 4 /* Verbose look at state changes */ |
40 | /* BT_DEBUG_OFF must be zero to correspond to the default uninitialized | 40 | /* |
41 | value */ | 41 | * BT_DEBUG_OFF must be zero to correspond to the default uninitialized |
42 | * value | ||
43 | */ | ||
42 | 44 | ||
43 | static int bt_debug; /* 0 == BT_DEBUG_OFF */ | 45 | static int bt_debug; /* 0 == BT_DEBUG_OFF */ |
44 | 46 | ||
45 | module_param(bt_debug, int, 0644); | 47 | module_param(bt_debug, int, 0644); |
46 | MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); | 48 | MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states"); |
47 | 49 | ||
48 | /* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds, | 50 | /* |
49 | and 64 byte buffers. However, one HP implementation wants 255 bytes of | 51 | * Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds, |
50 | buffer (with a documented message of 160 bytes) so go for the max. | 52 | * and 64 byte buffers. However, one HP implementation wants 255 bytes of |
51 | Since the Open IPMI architecture is single-message oriented at this | 53 | * buffer (with a documented message of 160 bytes) so go for the max. |
52 | stage, the queue depth of BT is of no concern. */ | 54 | * Since the Open IPMI architecture is single-message oriented at this |
55 | * stage, the queue depth of BT is of no concern. | ||
56 | */ | ||
53 | 57 | ||
54 | #define BT_NORMAL_TIMEOUT 5 /* seconds */ | 58 | #define BT_NORMAL_TIMEOUT 5 /* seconds */ |
55 | #define BT_NORMAL_RETRY_LIMIT 2 | 59 | #define BT_NORMAL_RETRY_LIMIT 2 |
56 | #define BT_RESET_DELAY 6 /* seconds after warm reset */ | 60 | #define BT_RESET_DELAY 6 /* seconds after warm reset */ |
57 | 61 | ||
58 | /* States are written in chronological order and usually cover | 62 | /* |
59 | multiple rows of the state table discussion in the IPMI spec. */ | 63 | * States are written in chronological order and usually cover |
64 | * multiple rows of the state table discussion in the IPMI spec. | ||
65 | */ | ||
60 | 66 | ||
61 | enum bt_states { | 67 | enum bt_states { |
62 | BT_STATE_IDLE = 0, /* Order is critical in this list */ | 68 | BT_STATE_IDLE = 0, /* Order is critical in this list */ |
@@ -76,10 +82,12 @@ enum bt_states { | |||
76 | BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */ | 82 | BT_STATE_LONG_BUSY /* BT doesn't get hosed :-) */ |
77 | }; | 83 | }; |
78 | 84 | ||
79 | /* Macros seen at the end of state "case" blocks. They help with legibility | 85 | /* |
80 | and debugging. */ | 86 | * Macros seen at the end of state "case" blocks. They help with legibility |
87 | * and debugging. | ||
88 | */ | ||
81 | 89 | ||
82 | #define BT_STATE_CHANGE(X,Y) { bt->state = X; return Y; } | 90 | #define BT_STATE_CHANGE(X, Y) { bt->state = X; return Y; } |
83 | 91 | ||
84 | #define BT_SI_SM_RETURN(Y) { last_printed = BT_STATE_PRINTME; return Y; } | 92 | #define BT_SI_SM_RETURN(Y) { last_printed = BT_STATE_PRINTME; return Y; } |
85 | 93 | ||
@@ -110,11 +118,13 @@ struct si_sm_data { | |||
110 | #define BT_H_BUSY 0x40 | 118 | #define BT_H_BUSY 0x40 |
111 | #define BT_B_BUSY 0x80 | 119 | #define BT_B_BUSY 0x80 |
112 | 120 | ||
113 | /* Some bits are toggled on each write: write once to set it, once | 121 | /* |
114 | more to clear it; writing a zero does nothing. To absolutely | 122 | * Some bits are toggled on each write: write once to set it, once |
115 | clear it, check its state and write if set. This avoids the "get | 123 | * more to clear it; writing a zero does nothing. To absolutely |
116 | current then use as mask" scheme to modify one bit. Note that the | 124 | * clear it, check its state and write if set. This avoids the "get |
117 | variable "bt" is hardcoded into these macros. */ | 125 | * current then use as mask" scheme to modify one bit. Note that the |
126 | * variable "bt" is hardcoded into these macros. | ||
127 | */ | ||
118 | 128 | ||
119 | #define BT_STATUS bt->io->inputb(bt->io, 0) | 129 | #define BT_STATUS bt->io->inputb(bt->io, 0) |
120 | #define BT_CONTROL(x) bt->io->outputb(bt->io, 0, x) | 130 | #define BT_CONTROL(x) bt->io->outputb(bt->io, 0, x) |
@@ -125,8 +135,10 @@ struct si_sm_data { | |||
125 | #define BT_INTMASK_R bt->io->inputb(bt->io, 2) | 135 | #define BT_INTMASK_R bt->io->inputb(bt->io, 2) |
126 | #define BT_INTMASK_W(x) bt->io->outputb(bt->io, 2, x) | 136 | #define BT_INTMASK_W(x) bt->io->outputb(bt->io, 2, x) |
127 | 137 | ||
128 | /* Convenience routines for debugging. These are not multi-open safe! | 138 | /* |
129 | Note the macros have hardcoded variables in them. */ | 139 | * Convenience routines for debugging. These are not multi-open safe! |
140 | * Note the macros have hardcoded variables in them. | ||
141 | */ | ||
130 | 142 | ||
131 | static char *state2txt(unsigned char state) | 143 | static char *state2txt(unsigned char state) |
132 | { | 144 | { |
@@ -182,7 +194,8 @@ static char *status2txt(unsigned char status) | |||
182 | static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io) | 194 | static unsigned int bt_init_data(struct si_sm_data *bt, struct si_sm_io *io) |
183 | { | 195 | { |
184 | memset(bt, 0, sizeof(struct si_sm_data)); | 196 | memset(bt, 0, sizeof(struct si_sm_data)); |
185 | if (bt->io != io) { /* external: one-time only things */ | 197 | if (bt->io != io) { |
198 | /* external: one-time only things */ | ||
186 | bt->io = io; | 199 | bt->io = io; |
187 | bt->seq = 0; | 200 | bt->seq = 0; |
188 | } | 201 | } |
@@ -229,7 +242,7 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
229 | printk(KERN_WARNING "BT: +++++++++++++++++ New command\n"); | 242 | printk(KERN_WARNING "BT: +++++++++++++++++ New command\n"); |
230 | printk(KERN_WARNING "BT: NetFn/LUN CMD [%d data]:", size - 2); | 243 | printk(KERN_WARNING "BT: NetFn/LUN CMD [%d data]:", size - 2); |
231 | for (i = 0; i < size; i ++) | 244 | for (i = 0; i < size; i ++) |
232 | printk (" %02x", data[i]); | 245 | printk(" %02x", data[i]); |
233 | printk("\n"); | 246 | printk("\n"); |
234 | } | 247 | } |
235 | bt->write_data[0] = size + 1; /* all data plus seq byte */ | 248 | bt->write_data[0] = size + 1; /* all data plus seq byte */ |
@@ -246,8 +259,10 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
246 | return 0; | 259 | return 0; |
247 | } | 260 | } |
248 | 261 | ||
249 | /* After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE | 262 | /* |
250 | it calls this. Strip out the length and seq bytes. */ | 263 | * After the upper state machine has been told SI_SM_TRANSACTION_COMPLETE |
264 | * it calls this. Strip out the length and seq bytes. | ||
265 | */ | ||
251 | 266 | ||
252 | static int bt_get_result(struct si_sm_data *bt, | 267 | static int bt_get_result(struct si_sm_data *bt, |
253 | unsigned char *data, | 268 | unsigned char *data, |
@@ -269,10 +284,10 @@ static int bt_get_result(struct si_sm_data *bt, | |||
269 | memcpy(data + 2, bt->read_data + 4, msg_len - 2); | 284 | memcpy(data + 2, bt->read_data + 4, msg_len - 2); |
270 | 285 | ||
271 | if (bt_debug & BT_DEBUG_MSG) { | 286 | if (bt_debug & BT_DEBUG_MSG) { |
272 | printk (KERN_WARNING "BT: result %d bytes:", msg_len); | 287 | printk(KERN_WARNING "BT: result %d bytes:", msg_len); |
273 | for (i = 0; i < msg_len; i++) | 288 | for (i = 0; i < msg_len; i++) |
274 | printk(" %02x", data[i]); | 289 | printk(" %02x", data[i]); |
275 | printk ("\n"); | 290 | printk("\n"); |
276 | } | 291 | } |
277 | return msg_len; | 292 | return msg_len; |
278 | } | 293 | } |
@@ -292,8 +307,10 @@ static void reset_flags(struct si_sm_data *bt) | |||
292 | BT_INTMASK_W(BT_BMC_HWRST); | 307 | BT_INTMASK_W(BT_BMC_HWRST); |
293 | } | 308 | } |
294 | 309 | ||
295 | /* Get rid of an unwanted/stale response. This should only be needed for | 310 | /* |
296 | BMCs that support multiple outstanding requests. */ | 311 | * Get rid of an unwanted/stale response. This should only be needed for |
312 | * BMCs that support multiple outstanding requests. | ||
313 | */ | ||
297 | 314 | ||
298 | static void drain_BMC2HOST(struct si_sm_data *bt) | 315 | static void drain_BMC2HOST(struct si_sm_data *bt) |
299 | { | 316 | { |
@@ -326,8 +343,8 @@ static inline void write_all_bytes(struct si_sm_data *bt) | |||
326 | printk(KERN_WARNING "BT: write %d bytes seq=0x%02X", | 343 | printk(KERN_WARNING "BT: write %d bytes seq=0x%02X", |
327 | bt->write_count, bt->seq); | 344 | bt->write_count, bt->seq); |
328 | for (i = 0; i < bt->write_count; i++) | 345 | for (i = 0; i < bt->write_count; i++) |
329 | printk (" %02x", bt->write_data[i]); | 346 | printk(" %02x", bt->write_data[i]); |
330 | printk ("\n"); | 347 | printk("\n"); |
331 | } | 348 | } |
332 | for (i = 0; i < bt->write_count; i++) | 349 | for (i = 0; i < bt->write_count; i++) |
333 | HOST2BMC(bt->write_data[i]); | 350 | HOST2BMC(bt->write_data[i]); |
@@ -337,8 +354,10 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
337 | { | 354 | { |
338 | unsigned char i; | 355 | unsigned char i; |
339 | 356 | ||
340 | /* length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. | 357 | /* |
341 | Keep layout of first four bytes aligned with write_data[] */ | 358 | * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. |
359 | * Keep layout of first four bytes aligned with write_data[] | ||
360 | */ | ||
342 | 361 | ||
343 | bt->read_data[0] = BMC2HOST; | 362 | bt->read_data[0] = BMC2HOST; |
344 | bt->read_count = bt->read_data[0]; | 363 | bt->read_count = bt->read_data[0]; |
@@ -362,8 +381,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
362 | if (max > 16) | 381 | if (max > 16) |
363 | max = 16; | 382 | max = 16; |
364 | for (i = 0; i < max; i++) | 383 | for (i = 0; i < max; i++) |
365 | printk (" %02x", bt->read_data[i]); | 384 | printk(KERN_CONT " %02x", bt->read_data[i]); |
366 | printk ("%s\n", bt->read_count == max ? "" : " ..."); | 385 | printk(KERN_CONT "%s\n", bt->read_count == max ? "" : " ..."); |
367 | } | 386 | } |
368 | 387 | ||
369 | /* per the spec, the (NetFn[1], Seq[2], Cmd[3]) tuples must match */ | 388 | /* per the spec, the (NetFn[1], Seq[2], Cmd[3]) tuples must match */ |
@@ -402,8 +421,10 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt, | |||
402 | printk(KERN_WARNING "IPMI BT: %s in %s %s ", /* open-ended line */ | 421 | printk(KERN_WARNING "IPMI BT: %s in %s %s ", /* open-ended line */ |
403 | reason, STATE2TXT, STATUS2TXT); | 422 | reason, STATE2TXT, STATUS2TXT); |
404 | 423 | ||
405 | /* Per the IPMI spec, retries are based on the sequence number | 424 | /* |
406 | known only to this module, so manage a restart here. */ | 425 | * Per the IPMI spec, retries are based on the sequence number |
426 | * known only to this module, so manage a restart here. | ||
427 | */ | ||
407 | (bt->error_retries)++; | 428 | (bt->error_retries)++; |
408 | if (bt->error_retries < bt->BT_CAP_retries) { | 429 | if (bt->error_retries < bt->BT_CAP_retries) { |
409 | printk("%d retries left\n", | 430 | printk("%d retries left\n", |
@@ -412,8 +433,8 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt, | |||
412 | return SI_SM_CALL_WITHOUT_DELAY; | 433 | return SI_SM_CALL_WITHOUT_DELAY; |
413 | } | 434 | } |
414 | 435 | ||
415 | printk("failed %d retries, sending error response\n", | 436 | printk(KERN_WARNING "failed %d retries, sending error response\n", |
416 | bt->BT_CAP_retries); | 437 | bt->BT_CAP_retries); |
417 | if (!bt->nonzero_status) | 438 | if (!bt->nonzero_status) |
418 | printk(KERN_ERR "IPMI BT: stuck, try power cycle\n"); | 439 | printk(KERN_ERR "IPMI BT: stuck, try power cycle\n"); |
419 | 440 | ||
@@ -424,8 +445,10 @@ static enum si_sm_result error_recovery(struct si_sm_data *bt, | |||
424 | return SI_SM_CALL_WITHOUT_DELAY; | 445 | return SI_SM_CALL_WITHOUT_DELAY; |
425 | } | 446 | } |
426 | 447 | ||
427 | /* Concoct a useful error message, set up the next state, and | 448 | /* |
428 | be done with this sequence. */ | 449 | * Concoct a useful error message, set up the next state, and |
450 | * be done with this sequence. | ||
451 | */ | ||
429 | 452 | ||
430 | bt->state = BT_STATE_IDLE; | 453 | bt->state = BT_STATE_IDLE; |
431 | switch (cCode) { | 454 | switch (cCode) { |
@@ -461,10 +484,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
461 | last_printed = bt->state; | 484 | last_printed = bt->state; |
462 | } | 485 | } |
463 | 486 | ||
464 | /* Commands that time out may still (eventually) provide a response. | 487 | /* |
465 | This stale response will get in the way of a new response so remove | 488 | * Commands that time out may still (eventually) provide a response. |
466 | it if possible (hopefully during IDLE). Even if it comes up later | 489 | * This stale response will get in the way of a new response so remove |
467 | it will be rejected by its (now-forgotten) seq number. */ | 490 | * it if possible (hopefully during IDLE). Even if it comes up later |
491 | * it will be rejected by its (now-forgotten) seq number. | ||
492 | */ | ||
468 | 493 | ||
469 | if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) { | 494 | if ((bt->state < BT_STATE_WRITE_BYTES) && (status & BT_B2H_ATN)) { |
470 | drain_BMC2HOST(bt); | 495 | drain_BMC2HOST(bt); |
@@ -472,7 +497,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
472 | } | 497 | } |
473 | 498 | ||
474 | if ((bt->state != BT_STATE_IDLE) && | 499 | if ((bt->state != BT_STATE_IDLE) && |
475 | (bt->state < BT_STATE_PRINTME)) { /* check timeout */ | 500 | (bt->state < BT_STATE_PRINTME)) { |
501 | /* check timeout */ | ||
476 | bt->timeout -= time; | 502 | bt->timeout -= time; |
477 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) | 503 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) |
478 | return error_recovery(bt, | 504 | return error_recovery(bt, |
@@ -482,8 +508,10 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
482 | 508 | ||
483 | switch (bt->state) { | 509 | switch (bt->state) { |
484 | 510 | ||
485 | /* Idle state first checks for asynchronous messages from another | 511 | /* |
486 | channel, then does some opportunistic housekeeping. */ | 512 | * Idle state first checks for asynchronous messages from another |
513 | * channel, then does some opportunistic housekeeping. | ||
514 | */ | ||
487 | 515 | ||
488 | case BT_STATE_IDLE: | 516 | case BT_STATE_IDLE: |
489 | if (status & BT_SMS_ATN) { | 517 | if (status & BT_SMS_ATN) { |
@@ -531,16 +559,19 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
531 | BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); | 559 | BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); |
532 | BT_CONTROL(BT_H_BUSY); /* set */ | 560 | BT_CONTROL(BT_H_BUSY); /* set */ |
533 | 561 | ||
534 | /* Uncached, ordered writes should just proceeed serially but | 562 | /* |
535 | some BMCs don't clear B2H_ATN with one hit. Fast-path a | 563 | * Uncached, ordered writes should just proceeed serially but |
536 | workaround without too much penalty to the general case. */ | 564 | * some BMCs don't clear B2H_ATN with one hit. Fast-path a |
565 | * workaround without too much penalty to the general case. | ||
566 | */ | ||
537 | 567 | ||
538 | BT_CONTROL(BT_B2H_ATN); /* clear it to ACK the BMC */ | 568 | BT_CONTROL(BT_B2H_ATN); /* clear it to ACK the BMC */ |
539 | BT_STATE_CHANGE(BT_STATE_CLEAR_B2H, | 569 | BT_STATE_CHANGE(BT_STATE_CLEAR_B2H, |
540 | SI_SM_CALL_WITHOUT_DELAY); | 570 | SI_SM_CALL_WITHOUT_DELAY); |
541 | 571 | ||
542 | case BT_STATE_CLEAR_B2H: | 572 | case BT_STATE_CLEAR_B2H: |
543 | if (status & BT_B2H_ATN) { /* keep hitting it */ | 573 | if (status & BT_B2H_ATN) { |
574 | /* keep hitting it */ | ||
544 | BT_CONTROL(BT_B2H_ATN); | 575 | BT_CONTROL(BT_B2H_ATN); |
545 | BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); | 576 | BT_SI_SM_RETURN(SI_SM_CALL_WITH_DELAY); |
546 | } | 577 | } |
@@ -548,7 +579,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
548 | SI_SM_CALL_WITHOUT_DELAY); | 579 | SI_SM_CALL_WITHOUT_DELAY); |
549 | 580 | ||
550 | case BT_STATE_READ_BYTES: | 581 | case BT_STATE_READ_BYTES: |
551 | if (!(status & BT_H_BUSY)) /* check in case of retry */ | 582 | if (!(status & BT_H_BUSY)) |
583 | /* check in case of retry */ | ||
552 | BT_CONTROL(BT_H_BUSY); | 584 | BT_CONTROL(BT_H_BUSY); |
553 | BT_CONTROL(BT_CLR_RD_PTR); /* start of BMC2HOST buffer */ | 585 | BT_CONTROL(BT_CLR_RD_PTR); /* start of BMC2HOST buffer */ |
554 | i = read_all_bytes(bt); /* true == packet seq match */ | 586 | i = read_all_bytes(bt); /* true == packet seq match */ |
@@ -599,8 +631,10 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
599 | BT_STATE_CHANGE(BT_STATE_XACTION_START, | 631 | BT_STATE_CHANGE(BT_STATE_XACTION_START, |
600 | SI_SM_CALL_WITH_DELAY); | 632 | SI_SM_CALL_WITH_DELAY); |
601 | 633 | ||
602 | /* Get BT Capabilities, using timing of upper level state machine. | 634 | /* |
603 | Set outreqs to prevent infinite loop on timeout. */ | 635 | * Get BT Capabilities, using timing of upper level state machine. |
636 | * Set outreqs to prevent infinite loop on timeout. | ||
637 | */ | ||
604 | case BT_STATE_CAPABILITIES_BEGIN: | 638 | case BT_STATE_CAPABILITIES_BEGIN: |
605 | bt->BT_CAP_outreqs = 1; | 639 | bt->BT_CAP_outreqs = 1; |
606 | { | 640 | { |
@@ -638,10 +672,12 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
638 | 672 | ||
639 | static int bt_detect(struct si_sm_data *bt) | 673 | static int bt_detect(struct si_sm_data *bt) |
640 | { | 674 | { |
641 | /* It's impossible for the BT status and interrupt registers to be | 675 | /* |
642 | all 1's, (assuming a properly functioning, self-initialized BMC) | 676 | * It's impossible for the BT status and interrupt registers to be |
643 | but that's what you get from reading a bogus address, so we | 677 | * all 1's, (assuming a properly functioning, self-initialized BMC) |
644 | test that first. The calling routine uses negative logic. */ | 678 | * but that's what you get from reading a bogus address, so we |
679 | * test that first. The calling routine uses negative logic. | ||
680 | */ | ||
645 | 681 | ||
646 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) | 682 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) |
647 | return 1; | 683 | return 1; |
@@ -658,8 +694,7 @@ static int bt_size(void) | |||
658 | return sizeof(struct si_sm_data); | 694 | return sizeof(struct si_sm_data); |
659 | } | 695 | } |
660 | 696 | ||
661 | struct si_sm_handlers bt_smi_handlers = | 697 | struct si_sm_handlers bt_smi_handlers = { |
662 | { | ||
663 | .init_data = bt_init_data, | 698 | .init_data = bt_init_data, |
664 | .start_transaction = bt_start_transaction, | 699 | .start_transaction = bt_start_transaction, |
665 | .get_result = bt_get_result, | 700 | .get_result = bt_get_result, |