]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/char/ipmi/ipmi_kcs_sm.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[mv-sheeva.git] / drivers / char / ipmi / ipmi_kcs_sm.c
index dc83365ede4abbf3e25f9055182235eb2e51186e..2062675f9e998d1e8f3420f6a1b7af747624f283 100644 (file)
@@ -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
 #define MAX_ERROR_RETRIES 10
+#define ERROR0_OBF_WAIT_JIFFIES (2*HZ)
 
 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;
        }
 }
@@ -223,7 +227,7 @@ static inline int check_ibf(struct si_sm_data *kcs, unsigned char status,
 static inline int check_obf(struct si_sm_data *kcs, unsigned char status,
                            long time)
 {
-       if (! GET_STATUS_OBF(status)) {
+       if (!GET_STATUS_OBF(status)) {
                kcs->obf_timeout -= time;
                if (kcs->obf_timeout < 0) {
                    start_error_recovery(kcs, "OBF not ready in time");
@@ -403,7 +407,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                }
 
                if (state == KCS_READ_STATE) {
-                       if (! check_obf(kcs, status, time))
+                       if (!check_obf(kcs, status, time))
                                return SI_SM_CALL_WITH_DELAY;
                        read_next_byte(kcs);
                } else {
@@ -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))
+                               return SI_SM_CALL_WITH_TICK_DELAY;
                write_cmd(kcs, KCS_GET_STATUS_ABORT);
                kcs->state = KCS_ERROR1;
                break;
@@ -439,7 +447,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                                             "Not in read state for error2");
                        break;
                }
-               if (! check_obf(kcs, status, time))
+               if (!check_obf(kcs, status, time))
                        return SI_SM_CALL_WITH_DELAY;
 
                clear_obf(kcs, status);
@@ -454,7 +462,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
                        break;
                }
 
-               if (! check_obf(kcs, status, time))
+               if (!check_obf(kcs, status, time))
                        return SI_SM_CALL_WITH_DELAY;
 
                clear_obf(kcs, status);