]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Jun 2014 00:34:47 +0000 (17:34 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Jun 2014 00:34:47 +0000 (17:34 -0700)
added patches:
ipmi-fix-a-race-restarting-the-timer.patch
ipmi-reset-the-kcs-timeout-when-starting-error-recovery.patch
timer-prevent-overflow-in-apply_slack.patch

queue-3.4/ipmi-fix-a-race-restarting-the-timer.patch [new file with mode: 0644]
queue-3.4/ipmi-reset-the-kcs-timeout-when-starting-error-recovery.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/timer-prevent-overflow-in-apply_slack.patch [new file with mode: 0644]

diff --git a/queue-3.4/ipmi-fix-a-race-restarting-the-timer.patch b/queue-3.4/ipmi-fix-a-race-restarting-the-timer.patch
new file mode 100644 (file)
index 0000000..e13922c
--- /dev/null
@@ -0,0 +1,138 @@
+From 48e8ac2979920ffa39117e2d725afa3a749bfe8d Mon Sep 17 00:00:00 2001
+From: Bodo Stroesser <bstroesser@ts.fujitsu.com>
+Date: Mon, 14 Apr 2014 09:46:51 -0500
+Subject: ipmi: Fix a race restarting the timer
+
+From: Bodo Stroesser <bstroesser@ts.fujitsu.com>
+
+commit 48e8ac2979920ffa39117e2d725afa3a749bfe8d upstream.
+
+With recent changes it is possible for the timer handler to detect an
+idle interface and not start the timer, but the thread to start an
+operation at the same time.  The thread will not start the timer in that
+instance, resulting in the timer not running.
+
+Instead, move all timer operations under the lock and start the timer in
+the thread if it detect non-idle and the timer is not already running.
+Moving under locks allows the last timeout to be set in both the thread
+and the timer.  'Timer is not running' means that the timer is not
+pending and smi_timeout() is not running.  So we need a flag to detect
+this correctly.
+
+Also fix a few other timeout bugs: setting the last timeout when the
+interrupt has to be disabled and the timer started, and setting the last
+timeout in check_start_timer_thread possibly racing with the timer
+
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Bodo Stroesser <bstroesser@ts.fujitsu.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_si_intf.c |   46 +++++++++++++++++++++++----------------
+ 1 file changed, 28 insertions(+), 18 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -244,6 +244,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;
+@@ -427,6 +430,13 @@ static void start_clear_flags(struct smi
+       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
+@@ -439,8 +449,7 @@ static inline void disable_si_irq(struct
+               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);
+       }
+ }
+@@ -896,15 +905,7 @@ static void sender(void                *
+               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);
+@@ -993,6 +994,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);
+@@ -1062,10 +1074,6 @@ static void smi_timeout(unsigned long da
+                    * 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;
+@@ -1087,7 +1095,10 @@ static void smi_timeout(unsigned long da
+  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)
+@@ -1135,8 +1146,7 @@ static int smi_start_processing(void
+       /* 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.
diff --git a/queue-3.4/ipmi-reset-the-kcs-timeout-when-starting-error-recovery.patch b/queue-3.4/ipmi-reset-the-kcs-timeout-when-starting-error-recovery.patch
new file mode 100644 (file)
index 0000000..85429b8
--- /dev/null
@@ -0,0 +1,35 @@
+From eb6d78ec213e6938559b801421d64714dafcf4b2 Mon Sep 17 00:00:00 2001
+From: Corey Minyard <cminyard@mvista.com>
+Date: Mon, 14 Apr 2014 09:46:52 -0500
+Subject: ipmi: Reset the KCS timeout when starting error recovery
+
+From: Corey Minyard <cminyard@mvista.com>
+
+commit eb6d78ec213e6938559b801421d64714dafcf4b2 upstream.
+
+The OBF timer in KCS was not reset in one situation when error recovery
+was started, resulting in an immediate timeout.
+
+Reported-by: Bodo Stroesser <bstroesser@ts.fujitsu.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_kcs_sm.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_kcs_sm.c
++++ b/drivers/char/ipmi/ipmi_kcs_sm.c
+@@ -251,8 +251,9 @@ static inline int check_obf(struct si_sm
+       if (!GET_STATUS_OBF(status)) {
+               kcs->obf_timeout -= time;
+               if (kcs->obf_timeout < 0) {
+-                  start_error_recovery(kcs, "OBF not ready in time");
+-                  return 1;
++                      kcs->obf_timeout = OBF_RETRY_TIMEOUT;
++                      start_error_recovery(kcs, "OBF not ready in time");
++                      return 1;
+               }
+               return 0;
+       }
index 4e9171191caaaec173442bf992ac5d2f000689e8..41b14f7fade70b382222d878fdeb78a11c0a5599 100644 (file)
@@ -36,3 +36,6 @@ futex-prevent-attaching-to-kernel-threads.patch
 ftrace-module-hardcode-ftrace_module_init-call-into-load_module.patch
 pata_at91-fix-ata_host_activate-failure-handling.patch
 mm-make-fixup_user_fault-check-the-vma-access-rights-too.patch
+timer-prevent-overflow-in-apply_slack.patch
+ipmi-fix-a-race-restarting-the-timer.patch
+ipmi-reset-the-kcs-timeout-when-starting-error-recovery.patch
diff --git a/queue-3.4/timer-prevent-overflow-in-apply_slack.patch b/queue-3.4/timer-prevent-overflow-in-apply_slack.patch
new file mode 100644 (file)
index 0000000..78a7169
--- /dev/null
@@ -0,0 +1,45 @@
+From 98a01e779f3c66b0b11cd7e64d531c0e41c95762 Mon Sep 17 00:00:00 2001
+From: Jiri Bohac <jbohac@suse.cz>
+Date: Fri, 18 Apr 2014 17:23:11 +0200
+Subject: timer: Prevent overflow in apply_slack
+
+From: Jiri Bohac <jbohac@suse.cz>
+
+commit 98a01e779f3c66b0b11cd7e64d531c0e41c95762 upstream.
+
+On architectures with sizeof(int) < sizeof (long), the
+computation of mask inside apply_slack() can be undefined if the
+computed bit is > 32.
+
+E.g. with: expires = 0xffffe6f5 and slack = 25, we get:
+
+expires_limit = 0x20000000e
+bit = 33
+mask = (1 << 33) - 1  /* undefined */
+
+On x86, mask becomes 1 and and the slack is not applied properly.
+On s390, mask is -1, expires is set to 0 and the timer fires immediately.
+
+Use 1UL << bit to solve that issue.
+
+Suggested-by: Deborah Townsend <dstownse@us.ibm.com>
+Signed-off-by: Jiri Bohac <jbohac@suse.cz>
+Link: http://lkml.kernel.org/r/20140418152310.GA13654@midget.suse.cz
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/timer.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -815,7 +815,7 @@ unsigned long apply_slack(struct timer_l
+       bit = find_last_bit(&mask, BITS_PER_LONG);
+-      mask = (1 << bit) - 1;
++      mask = (1UL << bit) - 1;
+       expires_limit = expires_limit & ~(mask);