diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_bt_sm.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_bt_sm.c | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index 64c9afa50c13..33862670e285 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
@@ -161,7 +161,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
161 | { | 161 | { |
162 | unsigned int i; | 162 | unsigned int i; |
163 | 163 | ||
164 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) return -1; | 164 | if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH)) |
165 | return -1; | ||
165 | 166 | ||
166 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) | 167 | if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED)) |
167 | return -2; | 168 | return -2; |
@@ -169,7 +170,8 @@ static int bt_start_transaction(struct si_sm_data *bt, | |||
169 | if (bt_debug & BT_DEBUG_MSG) { | 170 | if (bt_debug & BT_DEBUG_MSG) { |
170 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); | 171 | printk(KERN_WARNING "+++++++++++++++++++++++++++++++++++++\n"); |
171 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); | 172 | printk(KERN_WARNING "BT: write seq=0x%02X:", bt->seq); |
172 | for (i = 0; i < size; i ++) printk (" %02x", data[i]); | 173 | for (i = 0; i < size; i ++) |
174 | printk (" %02x", data[i]); | ||
173 | printk("\n"); | 175 | printk("\n"); |
174 | } | 176 | } |
175 | bt->write_data[0] = size + 1; /* all data plus seq byte */ | 177 | bt->write_data[0] = size + 1; /* all data plus seq byte */ |
@@ -208,15 +210,18 @@ static int bt_get_result(struct si_sm_data *bt, | |||
208 | } else { | 210 | } else { |
209 | data[0] = bt->read_data[1]; | 211 | data[0] = bt->read_data[1]; |
210 | data[1] = bt->read_data[3]; | 212 | data[1] = bt->read_data[3]; |
211 | if (length < msg_len) bt->truncated = 1; | 213 | if (length < msg_len) |
214 | bt->truncated = 1; | ||
212 | if (bt->truncated) { /* can be set in read_all_bytes() */ | 215 | if (bt->truncated) { /* can be set in read_all_bytes() */ |
213 | data[2] = IPMI_ERR_MSG_TRUNCATED; | 216 | data[2] = IPMI_ERR_MSG_TRUNCATED; |
214 | msg_len = 3; | 217 | msg_len = 3; |
215 | } else memcpy(data + 2, bt->read_data + 4, msg_len - 2); | 218 | } else |
219 | memcpy(data + 2, bt->read_data + 4, msg_len - 2); | ||
216 | 220 | ||
217 | if (bt_debug & BT_DEBUG_MSG) { | 221 | if (bt_debug & BT_DEBUG_MSG) { |
218 | printk (KERN_WARNING "BT: res (raw)"); | 222 | printk (KERN_WARNING "BT: res (raw)"); |
219 | for (i = 0; i < msg_len; i++) printk(" %02x", data[i]); | 223 | for (i = 0; i < msg_len; i++) |
224 | printk(" %02x", data[i]); | ||
220 | printk ("\n"); | 225 | printk ("\n"); |
221 | } | 226 | } |
222 | } | 227 | } |
@@ -229,8 +234,10 @@ static int bt_get_result(struct si_sm_data *bt, | |||
229 | 234 | ||
230 | static void reset_flags(struct si_sm_data *bt) | 235 | static void reset_flags(struct si_sm_data *bt) |
231 | { | 236 | { |
232 | if (BT_STATUS & BT_H_BUSY) BT_CONTROL(BT_H_BUSY); | 237 | if (BT_STATUS & BT_H_BUSY) |
233 | 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); | ||
234 | BT_CONTROL(BT_CLR_WR_PTR); | 241 | BT_CONTROL(BT_CLR_WR_PTR); |
235 | BT_CONTROL(BT_SMS_ATN); | 242 | BT_CONTROL(BT_SMS_ATN); |
236 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION | 243 | #ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION |
@@ -239,7 +246,8 @@ static void reset_flags(struct si_sm_data *bt) | |||
239 | BT_CONTROL(BT_H_BUSY); | 246 | BT_CONTROL(BT_H_BUSY); |
240 | BT_CONTROL(BT_B2H_ATN); | 247 | BT_CONTROL(BT_B2H_ATN); |
241 | BT_CONTROL(BT_CLR_RD_PTR); | 248 | BT_CONTROL(BT_CLR_RD_PTR); |
242 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) BMC2HOST; | 249 | for (i = 0; i < IPMI_MAX_MSG_LENGTH + 2; i++) |
250 | BMC2HOST; | ||
243 | BT_CONTROL(BT_H_BUSY); | 251 | BT_CONTROL(BT_H_BUSY); |
244 | } | 252 | } |
245 | #endif | 253 | #endif |
@@ -256,7 +264,8 @@ static inline void write_all_bytes(struct si_sm_data *bt) | |||
256 | printk (" %02x", bt->write_data[i]); | 264 | printk (" %02x", bt->write_data[i]); |
257 | printk ("\n"); | 265 | printk ("\n"); |
258 | } | 266 | } |
259 | 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]); | ||
260 | } | 269 | } |
261 | 270 | ||
262 | static inline int read_all_bytes(struct si_sm_data *bt) | 271 | static inline int read_all_bytes(struct si_sm_data *bt) |
@@ -276,7 +285,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
276 | bt->truncated = 1; | 285 | bt->truncated = 1; |
277 | return 1; /* let next XACTION START clean it up */ | 286 | return 1; /* let next XACTION START clean it up */ |
278 | } | 287 | } |
279 | 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; | ||
280 | bt->read_count++; /* account for the length byte */ | 290 | bt->read_count++; /* account for the length byte */ |
281 | 291 | ||
282 | if (bt_debug & BT_DEBUG_MSG) { | 292 | if (bt_debug & BT_DEBUG_MSG) { |
@@ -293,7 +303,8 @@ static inline int read_all_bytes(struct si_sm_data *bt) | |||
293 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) | 303 | ((bt->read_data[1] & 0xF8) == (bt->write_data[1] & 0xF8))) |
294 | return 1; | 304 | return 1; |
295 | 305 | ||
296 | 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: " | ||
297 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", | 308 | "want 0x(%02X, %02X, %02X) got (%02X, %02X, %02X)\n", |
298 | 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], |
299 | 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]); |
@@ -357,7 +368,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
357 | time); | 368 | time); |
358 | bt->last_state = bt->state; | 369 | bt->last_state = bt->state; |
359 | 370 | ||
360 | if (bt->state == BT_STATE_HOSED) return SI_SM_HOSED; | 371 | if (bt->state == BT_STATE_HOSED) |
372 | return SI_SM_HOSED; | ||
361 | 373 | ||
362 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ | 374 | if (bt->state != BT_STATE_IDLE) { /* do timeout test */ |
363 | 375 | ||
@@ -369,7 +381,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
369 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT | 381 | /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT |
370 | (noticed in ipmi_smic_sm.c January 2004) */ | 382 | (noticed in ipmi_smic_sm.c January 2004) */ |
371 | 383 | ||
372 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) time = 100; | 384 | if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT)) |
385 | time = 100; | ||
373 | bt->timeout -= time; | 386 | bt->timeout -= time; |
374 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { | 387 | if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) { |
375 | error_recovery(bt, "timed out"); | 388 | error_recovery(bt, "timed out"); |
@@ -391,12 +404,14 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
391 | BT_CONTROL(BT_H_BUSY); | 404 | BT_CONTROL(BT_H_BUSY); |
392 | break; | 405 | break; |
393 | } | 406 | } |
394 | if (status & BT_B2H_ATN) break; | 407 | if (status & BT_B2H_ATN) |
408 | break; | ||
395 | bt->state = BT_STATE_WRITE_BYTES; | 409 | bt->state = BT_STATE_WRITE_BYTES; |
396 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 410 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
397 | 411 | ||
398 | case BT_STATE_WRITE_BYTES: | 412 | case BT_STATE_WRITE_BYTES: |
399 | if (status & (BT_B_BUSY | BT_H2B_ATN)) break; | 413 | if (status & (BT_B_BUSY | BT_H2B_ATN)) |
414 | break; | ||
400 | BT_CONTROL(BT_CLR_WR_PTR); | 415 | BT_CONTROL(BT_CLR_WR_PTR); |
401 | write_all_bytes(bt); | 416 | write_all_bytes(bt); |
402 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ | 417 | BT_CONTROL(BT_H2B_ATN); /* clears too fast to catch? */ |
@@ -404,7 +419,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
404 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ | 419 | return SI_SM_CALL_WITHOUT_DELAY; /* it MIGHT sail through */ |
405 | 420 | ||
406 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ | 421 | case BT_STATE_WRITE_CONSUME: /* BMCs usually blow right thru here */ |
407 | if (status & (BT_H2B_ATN | BT_B_BUSY)) break; | 422 | if (status & (BT_H2B_ATN | BT_B_BUSY)) |
423 | break; | ||
408 | bt->state = BT_STATE_B2H_WAIT; | 424 | bt->state = BT_STATE_B2H_WAIT; |
409 | /* fall through with status */ | 425 | /* fall through with status */ |
410 | 426 | ||
@@ -413,15 +429,18 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
413 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ | 429 | generation of B2H_ATN so ALWAYS return CALL_WITH_DELAY. */ |
414 | 430 | ||
415 | case BT_STATE_B2H_WAIT: | 431 | case BT_STATE_B2H_WAIT: |
416 | if (!(status & BT_B2H_ATN)) break; | 432 | if (!(status & BT_B2H_ATN)) |
433 | break; | ||
417 | 434 | ||
418 | /* Assume ordered, uncached writes: no need to wait */ | 435 | /* Assume ordered, uncached writes: no need to wait */ |
419 | if (!(status & BT_H_BUSY)) BT_CONTROL(BT_H_BUSY); /* set */ | 436 | if (!(status & BT_H_BUSY)) |
437 | BT_CONTROL(BT_H_BUSY); /* set */ | ||
420 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ | 438 | BT_CONTROL(BT_B2H_ATN); /* clear it, ACK to the BMC */ |
421 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ | 439 | BT_CONTROL(BT_CLR_RD_PTR); /* reset the queue */ |
422 | i = read_all_bytes(bt); | 440 | i = read_all_bytes(bt); |
423 | BT_CONTROL(BT_H_BUSY); /* clear */ | 441 | BT_CONTROL(BT_H_BUSY); /* clear */ |
424 | if (!i) break; /* Try this state again */ | 442 | if (!i) /* Try this state again */ |
443 | break; | ||
425 | bt->state = BT_STATE_READ_END; | 444 | bt->state = BT_STATE_READ_END; |
426 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ | 445 | return SI_SM_CALL_WITHOUT_DELAY; /* for logging */ |
427 | 446 | ||
@@ -434,7 +453,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
434 | 453 | ||
435 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY | 454 | #ifdef MAKE_THIS_TRUE_IF_NECESSARY |
436 | 455 | ||
437 | if (status & BT_H_BUSY) break; | 456 | if (status & BT_H_BUSY) |
457 | break; | ||
438 | #endif | 458 | #endif |
439 | bt->seq++; | 459 | bt->seq++; |
440 | bt->state = BT_STATE_IDLE; | 460 | bt->state = BT_STATE_IDLE; |
@@ -457,7 +477,8 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
457 | break; | 477 | break; |
458 | 478 | ||
459 | case BT_STATE_RESET3: | 479 | case BT_STATE_RESET3: |
460 | if (bt->timeout > 0) return SI_SM_CALL_WITH_DELAY; | 480 | if (bt->timeout > 0) |
481 | return SI_SM_CALL_WITH_DELAY; | ||
461 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ | 482 | bt->state = BT_STATE_RESTART; /* printk in debug modes */ |
462 | break; | 483 | break; |
463 | 484 | ||
@@ -483,7 +504,8 @@ static int bt_detect(struct si_sm_data *bt) | |||
483 | 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 |
484 | test that first. The calling routine uses negative logic. */ | 505 | test that first. The calling routine uses negative logic. */ |
485 | 506 | ||
486 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) return 1; | 507 | if ((BT_STATUS == 0xFF) && (BT_INTMASK_R == 0xFF)) |
508 | return 1; | ||
487 | reset_flags(bt); | 509 | reset_flags(bt); |
488 | return 0; | 510 | return 0; |
489 | } | 511 | } |