diff options
author | Corey Minyard <minyard@acm.org> | 2005-11-07 04:00:02 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 10:53:44 -0500 |
commit | c3e7e7916ec61cf58c88af12f4db17f28cffd83a (patch) | |
tree | 4d5be7158f79a9a2b1572e60af5c3645afa333c2 /drivers/char/ipmi/ipmi_kcs_sm.c | |
parent | 21dcd300b15f87ce10df8773d029708f27499aa7 (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 <Matt_Domsch@dell.com>
Signed-off-by: Corey Minyard <minyard@acm.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char/ipmi/ipmi_kcs_sm.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_kcs_sm.c | 8 |
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 @@ | |||
41 | #include <linux/module.h> | 41 | #include <linux/module.h> |
42 | #include <linux/moduleparam.h> | 42 | #include <linux/moduleparam.h> |
43 | #include <linux/string.h> | 43 | #include <linux/string.h> |
44 | #include <linux/jiffies.h> | ||
44 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ | 45 | #include <linux/ipmi_msgdefs.h> /* for completion codes */ |
45 | #include "ipmi_si_sm.h" | 46 | #include "ipmi_si_sm.h" |
46 | 47 | ||
@@ -99,6 +100,7 @@ enum kcs_states { | |||
99 | #define IBF_RETRY_TIMEOUT 1000000 | 100 | #define IBF_RETRY_TIMEOUT 1000000 |
100 | #define OBF_RETRY_TIMEOUT 1000000 | 101 | #define OBF_RETRY_TIMEOUT 1000000 |
101 | #define MAX_ERROR_RETRIES 10 | 102 | #define MAX_ERROR_RETRIES 10 |
103 | #define ERROR0_OBF_WAIT_JIFFIES (2*HZ) | ||
102 | 104 | ||
103 | struct si_sm_data | 105 | struct si_sm_data |
104 | { | 106 | { |
@@ -115,6 +117,7 @@ struct si_sm_data | |||
115 | unsigned int error_retries; | 117 | unsigned int error_retries; |
116 | long ibf_timeout; | 118 | long ibf_timeout; |
117 | long obf_timeout; | 119 | long obf_timeout; |
120 | unsigned long error0_timeout; | ||
118 | }; | 121 | }; |
119 | 122 | ||
120 | static unsigned int init_kcs_data(struct si_sm_data *kcs, | 123 | 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) | |||
187 | printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason); | 190 | printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason); |
188 | kcs->state = KCS_HOSED; | 191 | kcs->state = KCS_HOSED; |
189 | } else { | 192 | } else { |
193 | kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES; | ||
190 | kcs->state = KCS_ERROR0; | 194 | kcs->state = KCS_ERROR0; |
191 | } | 195 | } |
192 | } | 196 | } |
@@ -423,6 +427,10 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time) | |||
423 | 427 | ||
424 | case KCS_ERROR0: | 428 | case KCS_ERROR0: |
425 | clear_obf(kcs, status); | 429 | clear_obf(kcs, status); |
430 | status = read_status(kcs); | ||
431 | if (GET_STATUS_OBF(status)) /* controller isn't responding */ | ||
432 | if (time_before(jiffies, kcs->error0_timeout)) | ||
433 | return SI_SM_CALL_WITH_TICK_DELAY; | ||
426 | write_cmd(kcs, KCS_GET_STATUS_ABORT); | 434 | write_cmd(kcs, KCS_GET_STATUS_ABORT); |
427 | kcs->state = KCS_ERROR1; | 435 | kcs->state = KCS_ERROR1; |
428 | break; | 436 | break; |