|
@@ -248,6 +248,9 @@ struct smi_info {
|
|
|
/* The timer for this si. */
|
|
|
struct timer_list si_timer;
|
|
|
|
|
|
+ /* This flag is set, if the timer is running (timer_pending() isn't enough) */
|
|
|
+ bool timer_running;
|
|
|
+
|
|
|
/* The time (in jiffies) the last timeout occurred at. */
|
|
|
unsigned long last_timeout_jiffies;
|
|
|
|
|
@@ -434,6 +437,13 @@ static void start_clear_flags(struct smi_info *smi_info)
|
|
|
smi_info->si_state = SI_CLEARING_FLAGS;
|
|
|
}
|
|
|
|
|
|
+static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
|
|
|
+{
|
|
|
+ smi_info->last_timeout_jiffies = jiffies;
|
|
|
+ mod_timer(&smi_info->si_timer, new_val);
|
|
|
+ smi_info->timer_running = true;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* When we have a situtaion where we run out of memory and cannot
|
|
|
* allocate messages, we just leave them in the BMC and run the system
|
|
@@ -446,8 +456,7 @@ static inline void disable_si_irq(struct smi_info *smi_info)
|
|
|
start_disable_irq(smi_info);
|
|
|
smi_info->interrupt_disabled = 1;
|
|
|
if (!atomic_read(&smi_info->stop_operation))
|
|
|
- mod_timer(&smi_info->si_timer,
|
|
|
- jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -907,15 +916,7 @@ static void sender(void *send_info,
|
|
|
list_add_tail(&msg->link, &smi_info->xmit_msgs);
|
|
|
|
|
|
if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) {
|
|
|
- /*
|
|
|
- * last_timeout_jiffies is updated here to avoid
|
|
|
- * smi_timeout() handler passing very large time_diff
|
|
|
- * value to smi_event_handler() that causes
|
|
|
- * the send command to abort.
|
|
|
- */
|
|
|
- smi_info->last_timeout_jiffies = jiffies;
|
|
|
-
|
|
|
- mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
|
|
|
if (smi_info->thread)
|
|
|
wake_up_process(smi_info->thread);
|
|
@@ -1004,6 +1005,17 @@ static int ipmi_thread(void *data)
|
|
|
|
|
|
spin_lock_irqsave(&(smi_info->si_lock), flags);
|
|
|
smi_result = smi_event_handler(smi_info, 0);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the driver is doing something, there is a possible
|
|
|
+ * race with the timer. If the timer handler see idle,
|
|
|
+ * and the thread here sees something else, the timer
|
|
|
+ * handler won't restart the timer even though it is
|
|
|
+ * required. So start it here if necessary.
|
|
|
+ */
|
|
|
+ if (smi_result != SI_SM_IDLE && !smi_info->timer_running)
|
|
|
+ smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
+
|
|
|
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
|
|
|
busy_wait = ipmi_thread_busy_wait(smi_result, smi_info,
|
|
|
&busy_until);
|
|
@@ -1073,10 +1085,6 @@ static void smi_timeout(unsigned long data)
|
|
|
* SI_USEC_PER_JIFFY);
|
|
|
smi_result = smi_event_handler(smi_info, time_diff);
|
|
|
|
|
|
- spin_unlock_irqrestore(&(smi_info->si_lock), flags);
|
|
|
-
|
|
|
- smi_info->last_timeout_jiffies = jiffies_now;
|
|
|
-
|
|
|
if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
|
|
|
/* Running with interrupts, only do long timeouts. */
|
|
|
timeout = jiffies + SI_TIMEOUT_JIFFIES;
|
|
@@ -1098,7 +1106,10 @@ static void smi_timeout(unsigned long data)
|
|
|
|
|
|
do_mod_timer:
|
|
|
if (smi_result != SI_SM_IDLE)
|
|
|
- mod_timer(&(smi_info->si_timer), timeout);
|
|
|
+ smi_mod_timer(smi_info, timeout);
|
|
|
+ else
|
|
|
+ smi_info->timer_running = false;
|
|
|
+ spin_unlock_irqrestore(&(smi_info->si_lock), flags);
|
|
|
}
|
|
|
|
|
|
static irqreturn_t si_irq_handler(int irq, void *data)
|
|
@@ -1146,8 +1157,7 @@ static int smi_start_processing(void *send_info,
|
|
|
|
|
|
/* Set up the timer that drives the interface. */
|
|
|
setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
|
|
|
- new_smi->last_timeout_jiffies = jiffies;
|
|
|
- mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
+ smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
|
|
|
|
|
|
/*
|
|
|
* Check if the user forcefully enabled the daemon.
|