diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_bt_sm.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_bt_sm.c | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 5ce9c6269033..33862670e285 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 31 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
32 | #include "ipmi_si_sm.h" | 32 | #include "ipmi_si_sm.h" |
33 | 33 | ||
34 | #define IPMI_BT_VERSION "v33" | ||
35 | |||
36 | static int bt_debug = 0x00; /* Production value 0, see following flags */ | 34 | static int bt_debug = 0x00; /* Production value 0, see following flags */ |
37 | 35 | ||
38 | #define BT_DEBUG_ENABLE 1 | 36 | #define BT_DEBUG_ENABLE 1 |
@@ -163,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
163 | { | 161 | { |
164 | unsigned int i; | 162 | unsigned int i; |
165 | 163 | ||
166 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1; | 164 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) |
165 | return -1; | ||
167 | 166 | ||
168 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) | 167 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) |
169 | return -2; | 168 | return -2; |
@@ -171,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
171 | if (bt_debug & BT_DEBUG_MSG) { | 170 | if (bt_debug & BT_DEBUG_MSG) { |
172 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); | 171 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); |
173 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); | 172 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); |
174 | for (i = 0; i < size; i ++) printk (" %02x", data[i]); | 173 | for (i = 0; i < size; i ++) |
174 | printk (" %02x", data[i]); | ||
175 | printk("\n"); | 175 | printk("\n"); |
176 | } | 176 | } |
177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ | 177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ |
@@ -210,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt, | |||
210 | } else { | 210 | } else { |
211 | data[0] = bt->read_data[1]; | 211 | data[0] = bt->read_data[1]; |
212 | data[1] = bt->read_data[3]; | 212 | data[1] = bt->read_data[3]; |
213 | if (length < msg_len) bt->truncated = 1; | 213 | if (length < msg_len) |
214 | bt->truncated = 1; | ||
214 | if (bt->truncated) { /* can be set in read_all_bytes() */ | 215 | if (bt->truncated) { /* can be set in read_all_bytes() */ |
215 | data[2] = IPMI_ERR_MSG_TRUNCATED; | 216 | data[2] = IPMI_ERR_MSG_TRUNCATED; |
216 | msg_len = 3; | 217 | msg_len = 3; |
217 | } else memcpy(data + 2, bt->read_data + 4, msg_len - 2); | 218 | } else |
219 | memcpy(data + 2, bt->read_data + 4, msg_len - 2); | ||
218 | 220 | ||
219 | if (bt_debug & BT_DEBUG_MSG) { | 221 | if (bt_debug & BT_DEBUG_MSG) { |
220 | printk (KERN_WARNING "BT: res (raw)"); | 222 | printk (KERN_WARNING "BT: res (raw)"); |
221 | for (i = 0; i < msg_len; i++) printk(" %02x", data[i]); | 223 | for (i = 0; i < msg_len; i++) |
224 | printk(" %02x", data[i]); | ||
222 | printk ("\n"); | 225 | printk ("\n"); |
223 | } | 226 | } |
224 | } | 227 | } |
@@ -231,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt, | |||
231 | 234 | ||
232 | static void reset_flags(struct si_sm_data *bt) | 235 | static void reset_flags(struct si_sm_data *bt) |
233 | { | 236 | { |
234 | if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY); | 237 | if (BT_STATUS & BT_H_BUSY) |
235 | if (BT_STATUS & BT_B_BUSY) BT_CONTROL(BT_B_BUSY); | 238 | BT_CONTROL(BT_H_BUSY); |
239 | if (BT_STATUS & BT_B_BUSY) | ||
240 | BT_CONTROL(BT_B_BUSY); | ||
236 | BT_CONTROL(BT_CLR_WR_PTR); | 241 | BT_CONTROL(BT_CLR_WR_PTR); |
237 | BT_CONTROL(BT_SMS_ATN); | 242 | BT_CONTROL(BT_SMS_ATN); |
238 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION | 243 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION |
@@ -241,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt) | |||
241 | BT_CONTROL(BT_H_BUSY); | 246 | BT_CONTROL(BT_H_BUSY); |
242 | BT_CONTROL(BT_B2H_ATN); | 247 | BT_CONTROL(BT_B2H_ATN); |
243 | BT_CONTROL(BT_CLR_RD_PTR); | 248 | BT_CONTROL(BT_CLR_RD_PTR); |
244 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST; | 249 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) |
250 | BMC2HOST; | ||
245 | BT_CONTROL(BT_H_BUSY); | 251 | BT_CONTROL(BT_H_BUSY); |
246 | } | 252 | } |
247 | #endif | 253 | #endif |
@@ -258,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt) | |||
258 | printk (" %02x", bt->write_data[i]); | 264 | printk (" %02x", bt->write_data[i]); |
259 | printk ("\n"); | 265 | printk ("\n"); |
260 | } | 266 | } |
261 | for (i = 0; i < bt->write_count; i++) HOST2BMC(bt->write_data[i]); | 267 | for (i = 0; i < bt->write_count; i++) |
268 | HOST2BMC(bt->write_data[i]); | ||
262 | } | 269 | } |
263 | 270 | ||
264 | static inline int read_all_bytes(struct si_sm_data *bt) | 271 | static inline int read_all_bytes(struct si_sm_data *bt) |
@@ -278,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
278 | bt->truncated = 1; | 285 | bt->truncated = 1; |
279 | return 1; /* let next XACTION START clean it up */ | 286 | return 1; /* let next XACTION START clean it up */ |
280 | } | 287 | } |
281 | for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST; | 288 | for (i = 1; i <= bt->read_count; i++) |
289 | bt->read_data[i] = BMC2HOST; | ||
282 | bt->read_count++; /* account for the length byte */ | 290 | bt->read_count++; /* account for the length byte */ |
283 | 291 | ||
284 | if (bt_debug & BT_DEBUG_MSG) { | 292 | if (bt_debug & BT_DEBUG_MSG) { |
@@ -295,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
295 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) | 303 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) |
296 | return 1; | 304 | return 1; |
297 | 305 | ||
298 | if (bt_debug & BT_DEBUG_MSG) printk(KERN_WARNING "BT: bad packet: " | 306 | if (bt_debug & BT_DEBUG_MSG) |
307 | printk(KERN_WARNING "BT: bad packet: " | ||
299 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", | 308 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", |
300 | bt->write_data[1], bt->write_data[2], bt->write_data[3], | 309 | bt->write_data[1], bt->write_data[2], bt->write_data[3], |
301 | bt->read_data[1], bt->read_data[2], bt->read_data[3]); | 310 | bt->read_data[1], bt->read_data[2], bt->read_data[3]); |
@@ -359,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
359 | time); | 368 | time); |
360 | bt->last_state = bt->state; | 369 | bt->last_state = bt->state; |
361 | 370 | ||
362 | if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED; | 371 | if (bt->state == BT_STATE_HOSED) |
372 | return SI_SM_HOSED; | ||
363 | 373 | ||
364 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ | 374 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ |
365 | 375 | ||
@@ -371,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
371 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT | 381 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT |
372 | (noticed in ipmi_smic_sm.c January 2004) */ | 382 | (noticed in ipmi_smic_sm.c January 2004) */ |
373 | 383 | ||
374 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100; | 384 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) |
385 | time = 100; | ||
375 | bt->timeout -= time; | 386 | bt->timeout -= time; |
376 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { | 387 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { |
377 | error_recovery(bt, "timed out"); | 388 | error_recovery(bt, "timed out"); |
@@ -393,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
393 | BT_CONTROL(BT_H_BUSY); | 404 | BT_CONTROL(BT_H_BUSY); |
394 | break; | 405 | break; |
395 | } | 406 | } |
396 | if (status & BT_B2H_ATN) break; | 407 | if (status & BT_B2H_ATN) |
408 | break; | ||
397 | bt->state = BT_STATE_WRITE_BYTES; | 409 | bt->state = BT_STATE_WRITE_BYTES; |
398 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 410 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
399 | 411 | ||
400 | case BT_STATE_WRITE_BYTES: | 412 | case BT_STATE_WRITE_BYTES: |
401 | if (status & (BT_B_BUSY | BT_H2B_ATN)) break; | 413 | if (status & (BT_B_BUSY | BT_H2B_ATN)) |
414 | break; | ||
402 | BT_CONTROL(BT_CLR_WR_PTR); | 415 | BT_CONTROL(BT_CLR_WR_PTR); |
403 | write_all_bytes(bt); | 416 | write_all_bytes(bt); |
404 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ | 417 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ |
@@ -406,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
406 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ | 419 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ |
407 | 420 | ||
408 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ | 421 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ |
409 | if (status & (BT_H2B_ATN | BT_B_BUSY)) break; | 422 | if (status & (BT_H2B_ATN | BT_B_BUSY)) |
423 | break; | ||
410 | bt->state = BT_STATE_B2H_WAIT; | 424 | bt->state = BT_STATE_B2H_WAIT; |
411 | /* fall through with status */ | 425 | /* fall through with status */ |
412 | 426 | ||
@@ -415,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
415 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ | 429 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ |
416 | 430 | ||
417 | case BT_STATE_B2H_WAIT: | 431 | case BT_STATE_B2H_WAIT: |
418 | if (!(status & BT_B2H_ATN)) break; | 432 | if (!(status & BT_B2H_ATN)) |
433 | break; | ||
419 | 434 | ||
420 | /* Assume ordered, uncached writes: no need to wait */ | 435 | /* Assume ordered, uncached writes: no need to wait */ |
421 | if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */ | 436 | if (!(status & BT_H_BUSY)) |
437 | BT_CONTROL(BT_H_BUSY); /* set */ | ||
422 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ | 438 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ |
423 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ | 439 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ |
424 | i = read_all_bytes(bt); | 440 | i = read_all_bytes(bt); |
425 | BT_CONTROL(BT_H_BUSY); /* clear */ | 441 | BT_CONTROL(BT_H_BUSY); /* clear */ |
426 | if (!i) break; /* Try this state again */ | 442 | if (!i) /* Try this state again */ |
443 | break; | ||
427 | bt->state = BT_STATE_READ_END; | 444 | bt->state = BT_STATE_READ_END; |
428 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 445 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
429 | 446 | ||
@@ -436,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
436 | 453 | ||
437 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY | 454 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY |
438 | 455 | ||
439 | if (status & BT_H_BUSY) break; | 456 | if (status & BT_H_BUSY) |
457 | break; | ||
440 | #endif | 458 | #endif |
441 | bt->seq++; | 459 | bt->seq++; |
442 | bt->state = BT_STATE_IDLE; | 460 | bt->state = BT_STATE_IDLE; |
@@ -459,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
459 | break; | 477 | break; |
460 | 478 | ||
461 | case BT_STATE_RESET3: | 479 | case BT_STATE_RESET3: |
462 | if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY; | 480 | if (bt->timeout > 0) |
481 | return SI_SM_CALL_WITH_DELAY; | ||
463 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ | 482 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ |
464 | break; | 483 | break; |
465 | 484 | ||
@@ -485,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt) | |||
485 | but that's what you get from reading a bogus address, so we | 504 | but that's what you get from reading a bogus address, so we |
486 | test that first. The calling routine uses negative logic. */ | 505 | test that first. The calling routine uses negative logic. */ |
487 | 506 | ||
488 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1; | 507 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) |
508 | return 1; | ||
489 | reset_flags(bt); | 509 | reset_flags(bt); |
490 | return 0; | 510 | return 0; |
491 | } | 511 | } |
@@ -501,7 +521,6 @@ static int bt_size(void) | |||
501 | 521 | ||
502 | struct si_sm_handlers bt_smi_handlers = | 522 | struct si_sm_handlers bt_smi_handlers = |
503 | { | 523 | { |
504 | .version = IPMI_BT_VERSION, | ||
505 | .init_data = bt_init_data, | 524 | .init_data = bt_init_data, |
506 | .start_transaction = bt_start_transaction, | 525 | .start_transaction = bt_start_transaction, |
507 | .get_result = bt_get_result, | 526 | .get_result = bt_get_result, |