]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 May 2013 21:48:58 +0000 (17:48 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 May 2013 21:48:58 +0000 (17:48 -0400)
added patches:
ath9k-fix-key-allocation-error-handling-for-powersave-keys.patch
drm-don-t-check-modeset-locks-in-panic-handler.patch
drm-mm-fix-dump-table-bug.patch
ext4-limit-group-search-loop-for-non-extent-files.patch
mwifiex-clear-is_suspended-flag-when-interrupt-is-received-early.patch
mwifiex-fix-setting-of-multicast-filter.patch
powerpc-kexec-fix-kexec-when-using-vmx-optimised-memcpy.patch
tick-cleanup-nohz-per-cpu-data-on-cpu-down.patch
timer-don-t-reinitialize-the-cpu-base-lock-during-cpu_up_prepare.patch

queue-3.0/ath9k-fix-key-allocation-error-handling-for-powersave-keys.patch [new file with mode: 0644]
queue-3.0/drm-don-t-check-modeset-locks-in-panic-handler.patch [new file with mode: 0644]
queue-3.0/drm-mm-fix-dump-table-bug.patch [new file with mode: 0644]
queue-3.0/ext4-limit-group-search-loop-for-non-extent-files.patch [new file with mode: 0644]
queue-3.0/mwifiex-clear-is_suspended-flag-when-interrupt-is-received-early.patch [new file with mode: 0644]
queue-3.0/mwifiex-fix-setting-of-multicast-filter.patch [new file with mode: 0644]
queue-3.0/powerpc-kexec-fix-kexec-when-using-vmx-optimised-memcpy.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/tick-cleanup-nohz-per-cpu-data-on-cpu-down.patch [new file with mode: 0644]
queue-3.0/timer-don-t-reinitialize-the-cpu-base-lock-during-cpu_up_prepare.patch [new file with mode: 0644]

diff --git a/queue-3.0/ath9k-fix-key-allocation-error-handling-for-powersave-keys.patch b/queue-3.0/ath9k-fix-key-allocation-error-handling-for-powersave-keys.patch
new file mode 100644 (file)
index 0000000..6e1d320
--- /dev/null
@@ -0,0 +1,52 @@
+From 4ef69d0394cba8caa9f75d3f2e53429bfb8b3045 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sat, 27 Apr 2013 11:47:01 +0200
+Subject: ath9k: fix key allocation error handling for powersave keys
+
+From: Felix Fietkau <nbd@openwrt.org>
+
+commit 4ef69d0394cba8caa9f75d3f2e53429bfb8b3045 upstream.
+
+If no keycache slots are available, ath_key_config can return -ENOSPC.
+If the key index is not checked for errors, it can lead to logspam that
+looks like this: "ath: wiphy0: keyreset: keycache entry 228 out of range"
+This can cause follow-up errors if the invalid keycache index gets
+used for tx.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/ath/ath9k/main.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1791,6 +1791,7 @@ static int ath9k_sta_add(struct ieee8021
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_node *an = (struct ath_node *) sta->drv_priv;
+       struct ieee80211_key_conf ps_key = { };
++      int key;
+       ath_node_attach(sc, sta);
+@@ -1798,7 +1799,9 @@ static int ath9k_sta_add(struct ieee8021
+           vif->type != NL80211_IFTYPE_AP_VLAN)
+               return 0;
+-      an->ps_key = ath_key_config(common, vif, sta, &ps_key);
++      key = ath_key_config(common, vif, sta, &ps_key);
++      if (key > 0)
++              an->ps_key = key;
+       return 0;
+ }
+@@ -1815,6 +1818,7 @@ static void ath9k_del_ps_key(struct ath_
+           return;
+       ath_key_delete(common, &ps_key);
++      an->ps_key = 0;
+ }
+ static int ath9k_sta_remove(struct ieee80211_hw *hw,
diff --git a/queue-3.0/drm-don-t-check-modeset-locks-in-panic-handler.patch b/queue-3.0/drm-don-t-check-modeset-locks-in-panic-handler.patch
new file mode 100644 (file)
index 0000000..e9fce03
--- /dev/null
@@ -0,0 +1,36 @@
+From a9b054e8ab06504c2afa0e307ee78d3778993a1d Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Thu, 2 May 2013 09:43:05 +0200
+Subject: drm: don't check modeset locks in panic handler
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit a9b054e8ab06504c2afa0e307ee78d3778993a1d upstream.
+
+Since we know that locking is broken in that case and it's more
+important to not flood the dmesg with random gunk.
+
+References: http://lkml.kernel.org/r/20130502000206.GH15623@pd.tnic
+Cc: Dave Airlie <airlied@gmail.com>
+Cc: Borislav Petkov <bp@alien8.de>
+Reported-and-tested-by: Borislav Petkov <bp@suse.de>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_crtc.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/drm_crtc.c
++++ b/drivers/gpu/drm/drm_crtc.c
+@@ -907,6 +907,10 @@ int drm_mode_group_init_legacy_group(str
+       if ((ret = drm_mode_group_init(dev, group)))
+               return ret;
++      /* Locking is currently fubar in the panic handler. */
++      if (oops_in_progress)
++              return;
++
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+               group->id_list[group->num_crtcs++] = crtc->base.id;
diff --git a/queue-3.0/drm-mm-fix-dump-table-bug.patch b/queue-3.0/drm-mm-fix-dump-table-bug.patch
new file mode 100644 (file)
index 0000000..16693e5
--- /dev/null
@@ -0,0 +1,92 @@
+From 3a359f0b21ab218c1bf7a6a1b638b6fd143d0b99 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Sat, 20 Apr 2013 12:08:11 +0200
+Subject: drm/mm: fix dump table BUG
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 3a359f0b21ab218c1bf7a6a1b638b6fd143d0b99 upstream.
+
+In
+
+commit 9e8944ab564f2e3dde90a518cd32048c58918608
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date:   Thu Nov 15 11:32:17 2012 +0000
+
+    drm: Introduce an iterator over holes in the drm_mm range manager
+
+helpers and iterators for hole handling have been introduced with some
+debug BUG_ONs sprinkled over. Unfortunately this broke the mm dumper
+which unconditionally tried to compute the size of the very first
+hole.
+
+While at it unify the code a bit with the hole dumping in the loop.
+
+v2: Extract a hole dump helper.
+
+Reported-by: Christopher Harvey <charvey@matrox.com>
+Cc: Christopher Harvey <charvey@matrox.com>
+Cc: Dave Airlie <airlied@redhat.com>
+Cc: Chris Wilson <chris@chris-wilson.co.uk>
+Acked-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_mm.c |   34 ++++++++++++++++++----------------
+ 1 file changed, 18 insertions(+), 16 deletions(-)
+
+--- a/drivers/gpu/drm/drm_mm.c
++++ b/drivers/gpu/drm/drm_mm.c
+@@ -679,33 +679,35 @@ void drm_mm_debug_table(struct drm_mm *m
+ EXPORT_SYMBOL(drm_mm_debug_table);
+ #if defined(CONFIG_DEBUG_FS)
+-int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
++static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
+ {
+-      struct drm_mm_node *entry;
+-      unsigned long total_used = 0, total_free = 0, total = 0;
+       unsigned long hole_start, hole_end, hole_size;
+-      hole_start = drm_mm_hole_node_start(&mm->head_node);
+-      hole_end = drm_mm_hole_node_end(&mm->head_node);
+-      hole_size = hole_end - hole_start;
+-      if (hole_size)
++      if (entry->hole_follows) {
++              hole_start = drm_mm_hole_node_start(entry);
++              hole_end = drm_mm_hole_node_end(entry);
++              hole_size = hole_end - hole_start;
+               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
+                               hole_start, hole_end, hole_size);
+-      total_free += hole_size;
++              return hole_size;
++      }
++
++      return 0;
++}
++
++int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
++{
++      struct drm_mm_node *entry;
++      unsigned long total_used = 0, total_free = 0, total = 0;
++
++      total_free += drm_mm_dump_hole(m, &mm->head_node);
+       drm_mm_for_each_node(entry, mm) {
+               seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
+                               entry->start, entry->start + entry->size,
+                               entry->size);
+               total_used += entry->size;
+-              if (entry->hole_follows) {
+-                      hole_start = drm_mm_hole_node_start(entry);
+-                      hole_end = drm_mm_hole_node_end(entry);
+-                      hole_size = hole_end - hole_start;
+-                      seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
+-                                      hole_start, hole_end, hole_size);
+-                      total_free += hole_size;
+-              }
++              total_free += drm_mm_dump_hole(m, entry);
+       }
+       total = total_free + total_used;
diff --git a/queue-3.0/ext4-limit-group-search-loop-for-non-extent-files.patch b/queue-3.0/ext4-limit-group-search-loop-for-non-extent-files.patch
new file mode 100644 (file)
index 0000000..c139e50
--- /dev/null
@@ -0,0 +1,55 @@
+From e6155736ad76b2070652745f9e54cdea3f0d8567 Mon Sep 17 00:00:00 2001
+From: Lachlan McIlroy <lmcilroy@redhat.com>
+Date: Sun, 5 May 2013 23:10:00 -0400
+Subject: ext4: limit group search loop for non-extent files
+
+From: Lachlan McIlroy <lmcilroy@redhat.com>
+
+commit e6155736ad76b2070652745f9e54cdea3f0d8567 upstream.
+
+In the case where we are allocating for a non-extent file,
+we must limit the groups we allocate from to those below
+2^32 blocks, and ext4_mb_regular_allocator() attempts to
+do this initially by putting a cap on ngroups for the
+subsequent search loop.
+
+However, the initial target group comes in from the
+allocation context (ac), and it may already be beyond
+the artificially limited ngroups.  In this case,
+the limit
+
+       if (group == ngroups)
+               group = 0;
+
+at the top of the loop is never true, and the loop will
+run away.
+
+Catch this case inside the loop and reset the search to
+start at group 0.
+
+[sandeen@redhat.com: add commit msg & comments]
+
+Signed-off-by: Lachlan McIlroy <lmcilroy@redhat.com>
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/mballoc.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2026,7 +2026,11 @@ repeat:
+               group = ac->ac_g_ex.fe_group;
+               for (i = 0; i < ngroups; group++, i++) {
+-                      if (group == ngroups)
++                      /*
++                       * Artificially restricted ngroups for non-extent
++                       * files makes group > ngroups possible on first loop.
++                       */
++                      if (group >= ngroups)
+                               group = 0;
+                       /* This now checks without needing the buddy page */
diff --git a/queue-3.0/mwifiex-clear-is_suspended-flag-when-interrupt-is-received-early.patch b/queue-3.0/mwifiex-clear-is_suspended-flag-when-interrupt-is-received-early.patch
new file mode 100644 (file)
index 0000000..d92cba8
--- /dev/null
@@ -0,0 +1,60 @@
+From 48795424acff7215d5eac0b52793a2c1eb3a6283 Mon Sep 17 00:00:00 2001
+From: Bing Zhao <bzhao@marvell.com>
+Date: Mon, 6 May 2013 19:46:53 -0700
+Subject: mwifiex: clear is_suspended flag when interrupt is received early
+
+From: Bing Zhao <bzhao@marvell.com>
+
+commit 48795424acff7215d5eac0b52793a2c1eb3a6283 upstream.
+
+When the XO-4 with 8787 wireless is woken up due to wake-on-WLAN
+mwifiex is often flooded with "not allowed while suspended" messages
+and the interface is unusable.
+
+[  202.171609] int: sdio_ireg = 0x1
+[  202.180700] info: mwifiex_process_hs_config: auto cancelling host
+               sleep since there is interrupt from the firmware
+[  202.201880] event: wakeup device...
+[  202.211452] event: hs_deactivated
+[  202.514638] info: --- Rx: Data packet ---
+[  202.514753] data: 4294957544 BSS(0-0): Data <= kernel
+[  202.514825] PREP_CMD: device in suspended state
+[  202.514839] data: dequeuing the packet ec7248c0 ec4869c0
+[  202.514886] mwifiex_write_data_sync: not allowed while suspended
+[  202.514886] host_to_card, write iomem (1) failed: -1
+[  202.514917] mwifiex_write_data_sync: not allowed while suspended
+[  202.514936] host_to_card, write iomem (2) failed: -1
+[  202.514949] mwifiex_write_data_sync: not allowed while suspended
+[  202.514965] host_to_card, write iomem (3) failed: -1
+[  202.514976] mwifiex_write_data_async failed: 0xFFFFFFFF
+
+This can be readily reproduced when putting the XO-4 in a loop where
+it goes to sleep due to inactivity, but then wakes up due to an
+incoming ping. The error is hit within an hour or two.
+
+This issue happens when an interrupt comes in early while host sleep
+is still activated. Driver handles this case by auto cancelling host
+sleep. However is_suspended flag is still set which prevents any cmd
+or data from being sent to firmware. Fix it by clearing is_suspended
+flag in this path.
+
+Reported-by: Daniel Drake <dsd@laptop.org>
+Tested-by: Daniel Drake <dsd@laptop.org>
+Signed-off-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/cmdevt.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/mwifiex/cmdevt.c
++++ b/drivers/net/wireless/mwifiex/cmdevt.c
+@@ -1081,6 +1081,7 @@ mwifiex_process_hs_config(struct mwifiex
+       adapter->if_ops.wakeup(adapter);
+       adapter->hs_activated = false;
+       adapter->is_hs_configured = false;
++      adapter->is_suspended = false;
+       mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
+                                  MWIFIEX_BSS_ROLE_ANY), false);
+ }
diff --git a/queue-3.0/mwifiex-fix-setting-of-multicast-filter.patch b/queue-3.0/mwifiex-fix-setting-of-multicast-filter.patch
new file mode 100644 (file)
index 0000000..9717dae
--- /dev/null
@@ -0,0 +1,66 @@
+From ccd384b10420ac81ba3fb9b0a7d18272c7173552 Mon Sep 17 00:00:00 2001
+From: Daniel Drake <dsd@laptop.org>
+Date: Wed, 8 May 2013 15:37:19 -0400
+Subject: mwifiex: fix setting of multicast filter
+
+From: Daniel Drake <dsd@laptop.org>
+
+commit ccd384b10420ac81ba3fb9b0a7d18272c7173552 upstream.
+
+A small bug in this code was causing the ALLMULTI filter to be set
+when in fact we were just wanting to program a selective multicast list
+to the hardware.
+
+Fix that bug and remove a redundant if condition in the code that
+follows.
+
+This fixes wakeup behaviour when multicast WOL is enabled. Previously,
+all multicast packets would wake up the system. Now, only those that the
+host intended to receive trigger wakeups.
+
+Signed-off-by: Daniel Drake <dsd@laptop.org>
+Acked-by: Bing Zhao <bzhao@marvell.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mwifiex/sta_ioctl.c |   21 ++++++---------------
+ 1 file changed, 6 insertions(+), 15 deletions(-)
+
+--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
+@@ -100,7 +100,7 @@ int mwifiex_request_set_multicast_list(s
+       } else {
+               /* Multicast */
+               priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+-              if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) {
++              if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
+                       dev_dbg(priv->adapter->dev,
+                               "info: Enabling All Multicast!\n");
+                       priv->curr_pkt_filter |=
+@@ -112,20 +112,11 @@ int mwifiex_request_set_multicast_list(s
+                               dev_dbg(priv->adapter->dev,
+                                       "info: Set multicast list=%d\n",
+                                      mcast_list->num_multicast_addr);
+-                              /* Set multicast addresses to firmware */
+-                              if (old_pkt_filter == priv->curr_pkt_filter) {
+-                                      /* Send request to firmware */
+-                                      ret = mwifiex_send_cmd_async(priv,
+-                                              HostCmd_CMD_MAC_MULTICAST_ADR,
+-                                              HostCmd_ACT_GEN_SET, 0,
+-                                              mcast_list);
+-                              } else {
+-                                      /* Send request to firmware */
+-                                      ret = mwifiex_send_cmd_async(priv,
+-                                              HostCmd_CMD_MAC_MULTICAST_ADR,
+-                                              HostCmd_ACT_GEN_SET, 0,
+-                                              mcast_list);
+-                              }
++                              /* Send multicast addresses to firmware */
++                              ret = mwifiex_send_cmd_async(priv,
++                                      HostCmd_CMD_MAC_MULTICAST_ADR,
++                                      HostCmd_ACT_GEN_SET, 0,
++                                      mcast_list);
+                       }
+               }
+       }
diff --git a/queue-3.0/powerpc-kexec-fix-kexec-when-using-vmx-optimised-memcpy.patch b/queue-3.0/powerpc-kexec-fix-kexec-when-using-vmx-optimised-memcpy.patch
new file mode 100644 (file)
index 0000000..24cf839
--- /dev/null
@@ -0,0 +1,54 @@
+From 79c66ce8f6448a3295a32efeac88c9debd7f7094 Mon Sep 17 00:00:00 2001
+From: Anton Blanchard <anton@au1.ibm.com>
+Date: Sun, 12 May 2013 15:04:53 +0000
+Subject: powerpc/kexec: Fix kexec when using VMX optimised memcpy
+
+From: Anton Blanchard <anton@au1.ibm.com>
+
+commit 79c66ce8f6448a3295a32efeac88c9debd7f7094 upstream.
+
+commit b3f271e86e5a (powerpc: POWER7 optimised memcpy using VMX and
+enhanced prefetch) uses VMX when it is safe to do so (ie not in
+interrupt). It also looks at the task struct to decide if we have to
+save the current tasks' VMX state.
+
+kexec calls memcpy() at a point where the task struct may have been
+overwritten by the new kexec segments. If it has been overwritten
+then when memcpy -> enable_altivec looks up current->thread.regs->msr
+we get a cryptic oops or lockup.
+
+I also notice we aren't initialising thread_info->cpu, which means
+smp_processor_id is broken. Fix that too.
+
+Signed-off-by: Anton Blanchard <anton@samba.org>
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kernel/machine_kexec_64.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/powerpc/kernel/machine_kexec_64.c
++++ b/arch/powerpc/kernel/machine_kexec_64.c
+@@ -17,6 +17,7 @@
+ #include <linux/errno.h>
+ #include <linux/kernel.h>
+ #include <linux/cpu.h>
++#include <linux/hardirq.h>
+ #include <asm/page.h>
+ #include <asm/current.h>
+@@ -336,10 +337,13 @@ void default_machine_kexec(struct kimage
+       pr_debug("kexec: Starting switchover sequence.\n");
+       /* switch to a staticly allocated stack.  Based on irq stack code.
++       * We setup preempt_count to avoid using VMX in memcpy.
+        * XXX: the task struct will likely be invalid once we do the copy!
+        */
+       kexec_stack.thread_info.task = current_thread_info()->task;
+       kexec_stack.thread_info.flags = 0;
++      kexec_stack.thread_info.preempt_count = HARDIRQ_OFFSET;
++      kexec_stack.thread_info.cpu = current_thread_info()->cpu;
+       /* We need a static PACA, too; copy this CPU's PACA over and switch to
+        * it.  Also poison per_cpu_offset to catch anyone using non-static
index 5dc89dc80de1214aae46a69336b02ef0a19fc547..2d9b1d4703ae687dea419a9e5ae6b1e2ff9b732b 100644 (file)
@@ -5,3 +5,12 @@ acpica-fix-possible-buffer-overflow-during-a-field-unit-read-operation.patch
 dm-snapshot-fix-error-return-code-in-snapshot_ctr.patch
 xen-vcpu-pvhvm-fix-vcpu-hotplugging-hanging.patch
 scsi-sd-fix-array-cache-flushing-bug-causing-performance-problems.patch
+timer-don-t-reinitialize-the-cpu-base-lock-during-cpu_up_prepare.patch
+tick-cleanup-nohz-per-cpu-data-on-cpu-down.patch
+ext4-limit-group-search-loop-for-non-extent-files.patch
+powerpc-kexec-fix-kexec-when-using-vmx-optimised-memcpy.patch
+ath9k-fix-key-allocation-error-handling-for-powersave-keys.patch
+mwifiex-clear-is_suspended-flag-when-interrupt-is-received-early.patch
+mwifiex-fix-setting-of-multicast-filter.patch
+drm-mm-fix-dump-table-bug.patch
+drm-don-t-check-modeset-locks-in-panic-handler.patch
diff --git a/queue-3.0/tick-cleanup-nohz-per-cpu-data-on-cpu-down.patch b/queue-3.0/tick-cleanup-nohz-per-cpu-data-on-cpu-down.patch
new file mode 100644 (file)
index 0000000..93ea9fb
--- /dev/null
@@ -0,0 +1,38 @@
+From 4b0c0f294f60abcdd20994a8341a95c8ac5eeb96 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 3 May 2013 15:02:50 +0200
+Subject: tick: Cleanup NOHZ per cpu data on cpu down
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 4b0c0f294f60abcdd20994a8341a95c8ac5eeb96 upstream.
+
+Prarit reported a crash on CPU offline/online. The reason is that on
+CPU down the NOHZ related per cpu data of the dead cpu is not cleaned
+up. If at cpu online an interrupt happens before the per cpu tick
+device is registered the irq_enter() check potentially sees stale data
+and dereferences a NULL pointer.
+
+Cleanup the data after the cpu is dead.
+
+Reported-by: Prarit Bhargava <prarit@redhat.com>
+Cc: Mike Galbraith <bitbucket@online.de>
+Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1305031451561.2886@ionos
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/time/tick-sched.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -811,7 +811,7 @@ void tick_cancel_sched_timer(int cpu)
+               hrtimer_cancel(&ts->sched_timer);
+ # endif
+-      ts->nohz_mode = NOHZ_MODE_INACTIVE;
++      memset(ts, 0, sizeof(*ts));
+ }
+ #endif
diff --git a/queue-3.0/timer-don-t-reinitialize-the-cpu-base-lock-during-cpu_up_prepare.patch b/queue-3.0/timer-don-t-reinitialize-the-cpu-base-lock-during-cpu_up_prepare.patch
new file mode 100644 (file)
index 0000000..778421f
--- /dev/null
@@ -0,0 +1,85 @@
+From 42a5cf46cd56f46267d2a9fcf2655f4078cd3042 Mon Sep 17 00:00:00 2001
+From: Tirupathi Reddy <tirupath@codeaurora.org>
+Date: Tue, 14 May 2013 13:59:02 +0530
+Subject: timer: Don't reinitialize the cpu base lock during CPU_UP_PREPARE
+
+From: Tirupathi Reddy <tirupath@codeaurora.org>
+
+commit 42a5cf46cd56f46267d2a9fcf2655f4078cd3042 upstream.
+
+An inactive timer's base can refer to a offline cpu's base.
+
+In the current code, cpu_base's lock is blindly reinitialized each
+time a CPU is brought up. If a CPU is brought online during the period
+that another thread is trying to modify an inactive timer on that CPU
+with holding its timer base lock, then the lock will be reinitialized
+under its feet. This leads to following SPIN_BUG().
+
+<0> BUG: spinlock already unlocked on CPU#3, kworker/u:3/1466
+<0> lock: 0xe3ebe000, .magic: dead4ead, .owner: kworker/u:3/1466, .owner_cpu: 1
+<4> [<c0013dc4>] (unwind_backtrace+0x0/0x11c) from [<c026e794>] (do_raw_spin_unlock+0x40/0xcc)
+<4> [<c026e794>] (do_raw_spin_unlock+0x40/0xcc) from [<c076c160>] (_raw_spin_unlock+0x8/0x30)
+<4> [<c076c160>] (_raw_spin_unlock+0x8/0x30) from [<c009b858>] (mod_timer+0x294/0x310)
+<4> [<c009b858>] (mod_timer+0x294/0x310) from [<c00a5e04>] (queue_delayed_work_on+0x104/0x120)
+<4> [<c00a5e04>] (queue_delayed_work_on+0x104/0x120) from [<c04eae00>] (sdhci_msm_bus_voting+0x88/0x9c)
+<4> [<c04eae00>] (sdhci_msm_bus_voting+0x88/0x9c) from [<c04d8780>] (sdhci_disable+0x40/0x48)
+<4> [<c04d8780>] (sdhci_disable+0x40/0x48) from [<c04bf300>] (mmc_release_host+0x4c/0xb0)
+<4> [<c04bf300>] (mmc_release_host+0x4c/0xb0) from [<c04c7aac>] (mmc_sd_detect+0x90/0xfc)
+<4> [<c04c7aac>] (mmc_sd_detect+0x90/0xfc) from [<c04c2504>] (mmc_rescan+0x7c/0x2c4)
+<4> [<c04c2504>] (mmc_rescan+0x7c/0x2c4) from [<c00a6a7c>] (process_one_work+0x27c/0x484)
+<4> [<c00a6a7c>] (process_one_work+0x27c/0x484) from [<c00a6e94>] (worker_thread+0x210/0x3b0)
+<4> [<c00a6e94>] (worker_thread+0x210/0x3b0) from [<c00aad9c>] (kthread+0x80/0x8c)
+<4> [<c00aad9c>] (kthread+0x80/0x8c) from [<c000ea80>] (kernel_thread_exit+0x0/0x8)
+
+As an example, this particular crash occurred when CPU #3 is executing
+mod_timer() on an inactive timer whose base is refered to offlined CPU
+#2.  The code locked the timer_base corresponding to CPU #2. Before it
+could proceed, CPU #2 came online and reinitialized the spinlock
+corresponding to its base. Thus now CPU #3 held a lock which was
+reinitialized. When CPU #3 finally ended up unlocking the old cpu_base
+corresponding to CPU #2, we hit the above SPIN_BUG().
+
+CPU #0         CPU #3                                 CPU #2
+------         -------                                -------
+.....           ......                               <Offline>
+               mod_timer()
+                lock_timer_base
+                  spin_lock_irqsave(&base->lock)
+
+cpu_up(2)       .....                                  ......
+                                                       init_timers_cpu()
+....            .....                                  spin_lock_init(&base->lock)
+.....             spin_unlock_irqrestore(&base->lock)  ......
+                  <spin_bug>
+
+Allocation of per_cpu timer vector bases is done only once under
+"tvec_base_done[]" check. In the current code, spinlock_initialization
+of base->lock isn't under this check. When a CPU is up each time the
+base lock is reinitialized. Move base spinlock initialization under
+the check.
+
+Signed-off-by: Tirupathi Reddy <tirupath@codeaurora.org>
+Link: http://lkml.kernel.org/r/1368520142-4136-1-git-send-email-tirupath@codeaurora.org
+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
+@@ -1630,12 +1630,12 @@ static int __cpuinit init_timers_cpu(int
+                       boot_done = 1;
+                       base = &boot_tvec_bases;
+               }
++              spin_lock_init(&base->lock);
+               tvec_base_done[cpu] = 1;
+       } else {
+               base = per_cpu(tvec_bases, cpu);
+       }
+-      spin_lock_init(&base->lock);
+       for (j = 0; j < TVN_SIZE; j++) {
+               INIT_LIST_HEAD(base->tv5.vec + j);