path: root/drivers/char/ipmi/ipmi_kcs_sm.c
diff options
authorCorey Minyard <>2005-11-07 01:00:02 -0800
committerLinus Torvalds <>2005-11-07 07:53:44 -0800
commitc3e7e7916ec61cf58c88af12f4db17f28cffd83a (patch)
tree4d5be7158f79a9a2b1572e60af5c3645afa333c2 /drivers/char/ipmi/ipmi_kcs_sm.c
parent21dcd300b15f87ce10df8773d029708f27499aa7 (diff)
[PATCH] ipmi: kcs error0 delay
BMCs can get into ERROR0 state while flashing new firmware, particularly while the BMC is erasing the next flash block, which may take a just under 2 seconds on a Dell PowerEdge 2800 (1.75 seconds typical), during which time the single-threaded firmware may not be able to process new commands. In particular, clearing OBF may not take effect immediately. We want it to delay in ERROR0 after clearing OBF a bit waiting for OBF to actually be clear before proceeding. This introduces a new return value from the LLDD's event loop, SI_SM_CALL_WITH_TICK_DELAY. This means the calling thread/timer should schedule_timeout() at least 1 tick, rather than busy-wait. This is a longer delay than SI_SM_CALL_WITH_DELAY, which is typically a 250us busy-wait. Signed-off-by: Matt Domsch <> Signed-off-by: Corey Minyard <> Signed-off-by: Andrew Morton <> Signed-off-by: Linus Torvalds <>
Diffstat (limited to 'drivers/char/ipmi/ipmi_kcs_sm.c')
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index dc83365ede4a..da1554194d3d 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -41,6 +41,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
@@ -99,6 +100,7 @@ enum kcs_states {
#define IBF_RETRY_TIMEOUT 1000000
#define OBF_RETRY_TIMEOUT 1000000
struct si_sm_data
@@ -115,6 +117,7 @@ struct si_sm_data
unsigned int error_retries;
long ibf_timeout;
long obf_timeout;
+ unsigned long error0_timeout;
static unsigned int init_kcs_data(struct si_sm_data *kcs,
@@ -187,6 +190,7 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason);
kcs->state = KCS_HOSED;
} else {
+ kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES;
kcs->state = KCS_ERROR0;
@@ -423,6 +427,10 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
case KCS_ERROR0:
clear_obf(kcs, status);
+ status = read_status(kcs);
+ if (GET_STATUS_OBF(status)) /* controller isn't responding */
+ if (time_before(jiffies, kcs->error0_timeout))
write_cmd(kcs, KCS_GET_STATUS_ABORT);
kcs->state = KCS_ERROR1;