diff options
Diffstat (limited to 'drivers/char/ipmi/ipmi_si_intf.c')
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 25a1436a4291..444ea548dfe3 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -257,6 +257,9 @@ struct smi_info { | |||
257 | /* Used to gracefully stop the timer without race conditions. */ | 257 | /* Used to gracefully stop the timer without race conditions. */ |
258 | atomic_t stop_operation; | 258 | atomic_t stop_operation; |
259 | 259 | ||
260 | /* Are we waiting for the events, pretimeouts, received msgs? */ | ||
261 | atomic_t need_watch; | ||
262 | |||
260 | /* | 263 | /* |
261 | * The driver will disable interrupts when it gets into a | 264 | * The driver will disable interrupts when it gets into a |
262 | * situation where it cannot handle messages due to lack of | 265 | * situation where it cannot handle messages due to lack of |
@@ -862,6 +865,19 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
862 | return si_sm_result; | 865 | return si_sm_result; |
863 | } | 866 | } |
864 | 867 | ||
868 | static void check_start_timer_thread(struct smi_info *smi_info) | ||
869 | { | ||
870 | if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { | ||
871 | smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); | ||
872 | |||
873 | if (smi_info->thread) | ||
874 | wake_up_process(smi_info->thread); | ||
875 | |||
876 | start_next_msg(smi_info); | ||
877 | smi_event_handler(smi_info, 0); | ||
878 | } | ||
879 | } | ||
880 | |||
865 | static void sender(void *send_info, | 881 | static void sender(void *send_info, |
866 | struct ipmi_smi_msg *msg, | 882 | struct ipmi_smi_msg *msg, |
867 | int priority) | 883 | int priority) |
@@ -915,15 +931,7 @@ static void sender(void *send_info, | |||
915 | else | 931 | else |
916 | list_add_tail(&msg->link, &smi_info->xmit_msgs); | 932 | list_add_tail(&msg->link, &smi_info->xmit_msgs); |
917 | 933 | ||
918 | if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { | 934 | check_start_timer_thread(smi_info); |
919 | smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); | ||
920 | |||
921 | if (smi_info->thread) | ||
922 | wake_up_process(smi_info->thread); | ||
923 | |||
924 | start_next_msg(smi_info); | ||
925 | smi_event_handler(smi_info, 0); | ||
926 | } | ||
927 | spin_unlock_irqrestore(&smi_info->si_lock, flags); | 935 | spin_unlock_irqrestore(&smi_info->si_lock, flags); |
928 | } | 936 | } |
929 | 937 | ||
@@ -1023,9 +1031,15 @@ static int ipmi_thread(void *data) | |||
1023 | ; /* do nothing */ | 1031 | ; /* do nothing */ |
1024 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) | 1032 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) |
1025 | schedule(); | 1033 | schedule(); |
1026 | else if (smi_result == SI_SM_IDLE) | 1034 | else if (smi_result == SI_SM_IDLE) { |
1027 | schedule_timeout_interruptible(100); | 1035 | if (atomic_read(&smi_info->need_watch)) { |
1028 | else | 1036 | schedule_timeout_interruptible(100); |
1037 | } else { | ||
1038 | /* Wait to be woken up when we are needed. */ | ||
1039 | __set_current_state(TASK_INTERRUPTIBLE); | ||
1040 | schedule(); | ||
1041 | } | ||
1042 | } else | ||
1029 | schedule_timeout_interruptible(1); | 1043 | schedule_timeout_interruptible(1); |
1030 | } | 1044 | } |
1031 | return 0; | 1045 | return 0; |
@@ -1061,6 +1075,17 @@ static void request_events(void *send_info) | |||
1061 | atomic_set(&smi_info->req_events, 1); | 1075 | atomic_set(&smi_info->req_events, 1); |
1062 | } | 1076 | } |
1063 | 1077 | ||
1078 | static void set_need_watch(void *send_info, int enable) | ||
1079 | { | ||
1080 | struct smi_info *smi_info = send_info; | ||
1081 | unsigned long flags; | ||
1082 | |||
1083 | atomic_set(&smi_info->need_watch, enable); | ||
1084 | spin_lock_irqsave(&smi_info->si_lock, flags); | ||
1085 | check_start_timer_thread(smi_info); | ||
1086 | spin_unlock_irqrestore(&smi_info->si_lock, flags); | ||
1087 | } | ||
1088 | |||
1064 | static int initialized; | 1089 | static int initialized; |
1065 | 1090 | ||
1066 | static void smi_timeout(unsigned long data) | 1091 | static void smi_timeout(unsigned long data) |
@@ -1212,6 +1237,7 @@ static struct ipmi_smi_handlers handlers = { | |||
1212 | .get_smi_info = get_smi_info, | 1237 | .get_smi_info = get_smi_info, |
1213 | .sender = sender, | 1238 | .sender = sender, |
1214 | .request_events = request_events, | 1239 | .request_events = request_events, |
1240 | .set_need_watch = set_need_watch, | ||
1215 | .set_maintenance_mode = set_maintenance_mode, | 1241 | .set_maintenance_mode = set_maintenance_mode, |
1216 | .set_run_to_completion = set_run_to_completion, | 1242 | .set_run_to_completion = set_run_to_completion, |
1217 | .poll = poll, | 1243 | .poll = poll, |
@@ -3352,6 +3378,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3352 | 3378 | ||
3353 | new_smi->interrupt_disabled = 1; | 3379 | new_smi->interrupt_disabled = 1; |
3354 | atomic_set(&new_smi->stop_operation, 0); | 3380 | atomic_set(&new_smi->stop_operation, 0); |
3381 | atomic_set(&new_smi->need_watch, 0); | ||
3355 | new_smi->intf_num = smi_num; | 3382 | new_smi->intf_num = smi_num; |
3356 | smi_num++; | 3383 | smi_num++; |
3357 | 3384 | ||