]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Sep 2012 22:55:23 +0000 (15:55 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Sep 2012 22:55:23 +0000 (15:55 -0700)
added patches:
drivers-misc-sgi-xp-xpc_uv.c-sgi-xpc-fails-to-load-when-cpu-0-is-out-of-irq-resources.patch
drivers-rtc-rtc-rs5c348.c-fix-hour-decoding-in-12-hour-mode.patch
drm-radeon-avoid-turning-off-spread-spectrum-for-used-pll.patch
drm-radeon-ss-use-num_crtc-rather-than-hardcoded-6.patch
fbcon-fix-race-condition-between-console-lock-and-cursor-timer-v1.1.patch
mutex-place-lock-in-contended-state-after-fastpath_lock-failure.patch
pm-runtime-clear-power.deferred_resume-on-success-in-rpm_suspend.patch
pm-runtime-fix-rpm_resume-return-value-for-power.no_callbacks-set.patch
tty-serial-imx-console-write-routing-is-unsafe-on-smp.patch

queue-3.4/drivers-misc-sgi-xp-xpc_uv.c-sgi-xpc-fails-to-load-when-cpu-0-is-out-of-irq-resources.patch [new file with mode: 0644]
queue-3.4/drivers-rtc-rtc-rs5c348.c-fix-hour-decoding-in-12-hour-mode.patch [new file with mode: 0644]
queue-3.4/drm-radeon-avoid-turning-off-spread-spectrum-for-used-pll.patch [new file with mode: 0644]
queue-3.4/drm-radeon-ss-use-num_crtc-rather-than-hardcoded-6.patch [new file with mode: 0644]
queue-3.4/fbcon-fix-race-condition-between-console-lock-and-cursor-timer-v1.1.patch [new file with mode: 0644]
queue-3.4/mutex-place-lock-in-contended-state-after-fastpath_lock-failure.patch [new file with mode: 0644]
queue-3.4/pm-runtime-clear-power.deferred_resume-on-success-in-rpm_suspend.patch [new file with mode: 0644]
queue-3.4/pm-runtime-fix-rpm_resume-return-value-for-power.no_callbacks-set.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/tty-serial-imx-console-write-routing-is-unsafe-on-smp.patch [new file with mode: 0644]

diff --git a/queue-3.4/drivers-misc-sgi-xp-xpc_uv.c-sgi-xpc-fails-to-load-when-cpu-0-is-out-of-irq-resources.patch b/queue-3.4/drivers-misc-sgi-xp-xpc_uv.c-sgi-xpc-fails-to-load-when-cpu-0-is-out-of-irq-resources.patch
new file mode 100644 (file)
index 0000000..7094819
--- /dev/null
@@ -0,0 +1,167 @@
+From 7838f994b4fceff24c343f4e26a6cf4393869579 Mon Sep 17 00:00:00 2001
+From: Robin Holt <holt@sgi.com>
+Date: Tue, 21 Aug 2012 16:16:02 -0700
+Subject: drivers/misc/sgi-xp/xpc_uv.c: SGI XPC fails to load when cpu 0 is out of IRQ resources
+
+From: Robin Holt <holt@sgi.com>
+
+commit 7838f994b4fceff24c343f4e26a6cf4393869579 upstream.
+
+On many of our larger systems, CPU 0 has had all of its IRQ resources
+consumed before XPC loads.  Worst cases on machines with multiple 10
+GigE cards and multiple IB cards have depleted the entire first socket
+of IRQs.
+
+This patch makes selecting the node upon which IRQs are allocated (as
+well as all the other GRU Message Queue structures) specifiable as a
+module load param and has a default behavior of searching all nodes/cpus
+for an available resources.
+
+[akpm@linux-foundation.org: fix build: include cpu.h and module.h]
+Signed-off-by: Robin Holt <holt@sgi.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/misc/sgi-xp/xpc_uv.c |   84 +++++++++++++++++++++++++++++++++----------
+ 1 file changed, 65 insertions(+), 19 deletions(-)
+
+--- a/drivers/misc/sgi-xp/xpc_uv.c
++++ b/drivers/misc/sgi-xp/xpc_uv.c
+@@ -18,6 +18,8 @@
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
++#include <linux/cpu.h>
++#include <linux/module.h>
+ #include <linux/err.h>
+ #include <linux/slab.h>
+ #include <asm/uv/uv_hub.h>
+@@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_hear
+                                        XPC_NOTIFY_MSG_SIZE_UV)
+ #define XPC_NOTIFY_IRQ_NAME           "xpc_notify"
++static int xpc_mq_node = -1;
++
+ static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
+ static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
+@@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_
+ #if defined CONFIG_X86_64
+       mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
+                       UV_AFFINITY_CPU);
+-      if (mq->irq < 0) {
+-              dev_err(xpc_part, "uv_setup_irq() returned error=%d\n",
+-                      -mq->irq);
++      if (mq->irq < 0)
+               return mq->irq;
+-      }
+       mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
+@@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_siz
+       mq->mmr_blade = uv_cpu_to_blade_id(cpu);
+       nid = cpu_to_node(cpu);
+-      page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
+-                              pg_order);
++      page = alloc_pages_exact_node(nid,
++                                    GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
++                                    pg_order);
+       if (page == NULL) {
+               dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
+                       "bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
+@@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_ar
+       .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
+ };
++static int
++xpc_init_mq_node(int nid)
++{
++      int cpu;
++
++      get_online_cpus();
++
++      for_each_cpu(cpu, cpumask_of_node(nid)) {
++              xpc_activate_mq_uv =
++                      xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid,
++                                           XPC_ACTIVATE_IRQ_NAME,
++                                           xpc_handle_activate_IRQ_uv);
++              if (!IS_ERR(xpc_activate_mq_uv))
++                      break;
++      }
++      if (IS_ERR(xpc_activate_mq_uv)) {
++              put_online_cpus();
++              return PTR_ERR(xpc_activate_mq_uv);
++      }
++
++      for_each_cpu(cpu, cpumask_of_node(nid)) {
++              xpc_notify_mq_uv =
++                      xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid,
++                                           XPC_NOTIFY_IRQ_NAME,
++                                           xpc_handle_notify_IRQ_uv);
++              if (!IS_ERR(xpc_notify_mq_uv))
++                      break;
++      }
++      if (IS_ERR(xpc_notify_mq_uv)) {
++              xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
++              put_online_cpus();
++              return PTR_ERR(xpc_notify_mq_uv);
++      }
++
++      put_online_cpus();
++      return 0;
++}
++
+ int
+ xpc_init_uv(void)
+ {
++      int nid;
++      int ret = 0;
++
+       xpc_arch_ops = xpc_arch_ops_uv;
+       if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
+@@ -1742,21 +1785,21 @@ xpc_init_uv(void)
+               return -E2BIG;
+       }
+-      xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0,
+-                                                XPC_ACTIVATE_IRQ_NAME,
+-                                                xpc_handle_activate_IRQ_uv);
+-      if (IS_ERR(xpc_activate_mq_uv))
+-              return PTR_ERR(xpc_activate_mq_uv);
++      if (xpc_mq_node < 0)
++              for_each_online_node(nid) {
++                      ret = xpc_init_mq_node(nid);
+-      xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0,
+-                                              XPC_NOTIFY_IRQ_NAME,
+-                                              xpc_handle_notify_IRQ_uv);
+-      if (IS_ERR(xpc_notify_mq_uv)) {
+-              xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
+-              return PTR_ERR(xpc_notify_mq_uv);
+-      }
++                      if (!ret)
++                              break;
++              }
++      else
++              ret = xpc_init_mq_node(xpc_mq_node);
+-      return 0;
++      if (ret < 0)
++              dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n",
++                      -ret);
++
++      return ret;
+ }
+ void
+@@ -1765,3 +1808,6 @@ xpc_exit_uv(void)
+       xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
+       xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
+ }
++
++module_param(xpc_mq_node, int, 0);
++MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues.");
diff --git a/queue-3.4/drivers-rtc-rtc-rs5c348.c-fix-hour-decoding-in-12-hour-mode.patch b/queue-3.4/drivers-rtc-rtc-rs5c348.c-fix-hour-decoding-in-12-hour-mode.patch
new file mode 100644 (file)
index 0000000..9c29ce5
--- /dev/null
@@ -0,0 +1,53 @@
+From 7dbfb315b2aaef0a115765946bf3026d074c33a7 Mon Sep 17 00:00:00 2001
+From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+Date: Tue, 21 Aug 2012 16:16:10 -0700
+Subject: drivers/rtc/rtc-rs5c348.c: fix hour decoding in 12-hour mode
+
+From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+
+commit 7dbfb315b2aaef0a115765946bf3026d074c33a7 upstream.
+
+Correct the offset by subtracting 20 from tm_hour before taking the
+modulo 12.
+
+[ "Why 20?" I hear you ask. Or at least I did.
+
+  Here's the reason why: RS5C348_BIT_PM is 32, and is - stupidly -
+  included in the RS5C348_HOURS_MASK define.  So it's really subtracting
+  out that bit to get "hour+12".  But then because it does things modulo
+  12, it needs to add the 12 in again afterwards anyway.
+
+  This code is confused.  It would be much clearer if RS5C348_HOURS_MASK
+  just didn't include the RS5C348_BIT_PM bit at all, then it wouldn't
+  need to do the silly subtract either.
+
+  Whatever. It's all just math, the end result is the same.   - Linus ]
+
+Reported-by: James Nute <newten82@gmail.com>
+Tested-by: James Nute <newten82@gmail.com>
+Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/rtc/rtc-rs5c348.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/rtc/rtc-rs5c348.c
++++ b/drivers/rtc/rtc-rs5c348.c
+@@ -122,9 +122,12 @@ rs5c348_rtc_read_time(struct device *dev
+       tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
+       tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
+       if (!pdata->rtc_24h) {
+-              tm->tm_hour %= 12;
+-              if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM)
++              if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) {
++                      tm->tm_hour -= 20;
++                      tm->tm_hour %= 12;
+                       tm->tm_hour += 12;
++              } else
++                      tm->tm_hour %= 12;
+       }
+       tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
+       tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
diff --git a/queue-3.4/drm-radeon-avoid-turning-off-spread-spectrum-for-used-pll.patch b/queue-3.4/drm-radeon-avoid-turning-off-spread-spectrum-for-used-pll.patch
new file mode 100644 (file)
index 0000000..71f49ea
--- /dev/null
@@ -0,0 +1,85 @@
+From 5efcc76c13a745f98e7b6604d6aca49761be1970 Mon Sep 17 00:00:00 2001
+From: Jerome Glisse <jglisse@redhat.com>
+Date: Fri, 17 Aug 2012 14:40:04 -0400
+Subject: drm/radeon: avoid turning off spread spectrum for used pll
+
+From: Jerome Glisse <jglisse@redhat.com>
+
+commit 5efcc76c13a745f98e7b6604d6aca49761be1970 upstream.
+
+If spread spectrum is enabled and in use for a given pll we
+should not turn it off as it will lead to turning off display
+for crtc that use the pll (this behavior was observed on chelsea
+edp).
+
+Signed-off-by: Jerome Glisse <jglisse@redhat.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/atombios_crtc.c |   25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -444,11 +444,28 @@ union atom_enable_ss {
+ static void atombios_crtc_program_ss(struct radeon_device *rdev,
+                                    int enable,
+                                    int pll_id,
++                                   int crtc_id,
+                                    struct radeon_atom_ss *ss)
+ {
++      unsigned i;
+       int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
+       union atom_enable_ss args;
++      if (!enable) {
++              for (i = 0; i < 6; i++) {
++                      if (rdev->mode_info.crtcs[i] &&
++                          rdev->mode_info.crtcs[i]->enabled &&
++                          i != crtc_id &&
++                          pll_id == rdev->mode_info.crtcs[i]->pll_id) {
++                              /* one other crtc is using this pll don't turn
++                               * off spread spectrum as it might turn off
++                               * display on active crtc
++                               */
++                              return;
++                      }
++              }
++      }
++
+       memset(&args, 0, sizeof(args));
+       if (ASIC_IS_DCE5(rdev)) {
+@@ -1039,7 +1056,7 @@ static void atombios_crtc_set_pll(struct
+               radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
+                                         &ref_div, &post_div);
+-      atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
++      atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);
+       atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
+                                 encoder_mode, radeon_encoder->encoder_id, mode->clock,
+@@ -1062,7 +1079,7 @@ static void atombios_crtc_set_pll(struct
+                       ss.step = step_size;
+               }
+-              atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
++              atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);
+       }
+ }
+@@ -1571,11 +1588,11 @@ void radeon_atom_disp_eng_pll_init(struc
+                                                                  ASIC_INTERNAL_SS_ON_DCPLL,
+                                                                  rdev->clock.default_dispclk);
+               if (ss_enabled)
+-                      atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss);
++                      atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss);
+               /* XXX: DCE5, make sure voltage, dispclk is high enough */
+               atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);
+               if (ss_enabled)
+-                      atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss);
++                      atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss);
+       }
+ }
diff --git a/queue-3.4/drm-radeon-ss-use-num_crtc-rather-than-hardcoded-6.patch b/queue-3.4/drm-radeon-ss-use-num_crtc-rather-than-hardcoded-6.patch
new file mode 100644 (file)
index 0000000..187dd9b
--- /dev/null
@@ -0,0 +1,29 @@
+From 5317670692f61675394db2eb6713484b67383750 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 21 Aug 2012 18:52:56 -0400
+Subject: drm/radeon/ss: use num_crtc rather than hardcoded 6
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 5317670692f61675394db2eb6713484b67383750 upstream.
+
+When checking if a pll is in use.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/atombios_crtc.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -452,7 +452,7 @@ static void atombios_crtc_program_ss(str
+       union atom_enable_ss args;
+       if (!enable) {
+-              for (i = 0; i < 6; i++) {
++              for (i = 0; i < rdev->num_crtc; i++) {
+                       if (rdev->mode_info.crtcs[i] &&
+                           rdev->mode_info.crtcs[i]->enabled &&
+                           i != crtc_id &&
diff --git a/queue-3.4/fbcon-fix-race-condition-between-console-lock-and-cursor-timer-v1.1.patch b/queue-3.4/fbcon-fix-race-condition-between-console-lock-and-cursor-timer-v1.1.patch
new file mode 100644 (file)
index 0000000..f82e147
--- /dev/null
@@ -0,0 +1,72 @@
+From d8636a2717bb3da2a7ce2154bf08de90bb8c87b0 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@redhat.com>
+Date: Tue, 21 Aug 2012 16:29:47 +1000
+Subject: fbcon: fix race condition between console lock and cursor timer (v1.1)
+
+From: Dave Airlie <airlied@redhat.com>
+
+commit d8636a2717bb3da2a7ce2154bf08de90bb8c87b0 upstream.
+
+So we've had a fair few reports of fbcon handover breakage between
+efi/vesafb and i915 surface recently, so I dedicated a couple of
+days to finding the problem.
+
+Essentially the last thing we saw was the conflicting framebuffer
+message and that was all.
+
+So after much tracing with direct netconsole writes (printks
+under console_lock not so useful), I think I found the race.
+
+Thread A (driver load)    Thread B (timer thread)
+  unbind_con_driver ->              |
+  bind_con_driver ->                |
+  vc->vc_sw->con_deinit ->          |
+  fbcon_deinit ->                   |
+  console_lock()                    |
+      |                             |
+      |                       fbcon_flashcursor timer fires
+      |                       console_lock() <- blocked for A
+      |
+      |
+fbcon_del_cursor_timer ->
+  del_timer_sync
+  (BOOM)
+
+Of course because all of this is under the console lock,
+we never see anything, also since we also just unbound the active
+console guess what we never see anything.
+
+Hopefully this fixes the problem for anyone seeing vesafb->kms
+driver handoff.
+
+v1.1: add comment suggestion from Alan.
+
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Acked-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Tested-by: Josh Boyer <jwboyer@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/video/console/fbcon.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/console/fbcon.c
++++ b/drivers/video/console/fbcon.c
+@@ -372,8 +372,15 @@ static void fb_flashcursor(struct work_s
+       struct vc_data *vc = NULL;
+       int c;
+       int mode;
++      int ret;
++
++      /* FIXME: we should sort out the unbind locking instead */
++      /* instead we just fail to flash the cursor if we can't get
++       * the lock instead of blocking fbcon deinit */
++      ret = console_trylock();
++      if (ret == 0)
++              return;
+-      console_lock();
+       if (ops && ops->currcon != -1)
+               vc = vc_cons[ops->currcon].d;
diff --git a/queue-3.4/mutex-place-lock-in-contended-state-after-fastpath_lock-failure.patch b/queue-3.4/mutex-place-lock-in-contended-state-after-fastpath_lock-failure.patch
new file mode 100644 (file)
index 0000000..32c45c9
--- /dev/null
@@ -0,0 +1,82 @@
+From 0bce9c46bf3b15f485d82d7e81dabed6ebcc24b1 Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Fri, 10 Aug 2012 15:22:09 +0100
+Subject: mutex: Place lock in contended state after fastpath_lock failure
+
+From: Will Deacon <will.deacon@arm.com>
+
+commit 0bce9c46bf3b15f485d82d7e81dabed6ebcc24b1 upstream.
+
+ARM recently moved to asm-generic/mutex-xchg.h for its mutex
+implementation after the previous implementation was found to be missing
+some crucial memory barriers. However, this has revealed some problems
+running hackbench on SMP platforms due to the way in which the
+MUTEX_SPIN_ON_OWNER code operates.
+
+The symptoms are that a bunch of hackbench tasks are left waiting on an
+unlocked mutex and therefore never get woken up to claim it. This boils
+down to the following sequence of events:
+
+        Task A        Task B        Task C        Lock value
+0                                                     1
+1       lock()                                        0
+2                     lock()                          0
+3                     spin(A)                         0
+4       unlock()                                      1
+5                                   lock()            0
+6                     cmpxchg(1,0)                    0
+7                     contended()                    -1
+8       lock()                                        0
+9       spin(C)                                       0
+10                                  unlock()          1
+11      cmpxchg(1,0)                                  0
+12      unlock()                                      1
+
+At this point, the lock is unlocked, but Task B is in an uninterruptible
+sleep with nobody to wake it up.
+
+This patch fixes the problem by ensuring we put the lock into the
+contended state if we fail to acquire it on the fastpath, ensuring that
+any blocked waiters are woken up when the mutex is released.
+
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Chris Mason <chris.mason@fusionio.com>
+Cc: Ingo Molnar <mingo@elte.hu>
+Reviewed-by: Nicolas Pitre <nico@linaro.org>
+Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Link: http://lkml.kernel.org/n/tip-6e9lrw2avczr0617fzl5vqb8@git.kernel.org
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/asm-generic/mutex-xchg.h |   11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/include/asm-generic/mutex-xchg.h
++++ b/include/asm-generic/mutex-xchg.h
+@@ -26,7 +26,13 @@ static inline void
+ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
+ {
+       if (unlikely(atomic_xchg(count, 0) != 1))
+-              fail_fn(count);
++              /*
++               * We failed to acquire the lock, so mark it contended
++               * to ensure that any waiting tasks are woken up by the
++               * unlock slow path.
++               */
++              if (likely(atomic_xchg(count, -1) != 1))
++                      fail_fn(count);
+ }
+ /**
+@@ -43,7 +49,8 @@ static inline int
+ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+ {
+       if (unlikely(atomic_xchg(count, 0) != 1))
+-              return fail_fn(count);
++              if (likely(atomic_xchg(count, -1) != 1))
++                      return fail_fn(count);
+       return 0;
+ }
diff --git a/queue-3.4/pm-runtime-clear-power.deferred_resume-on-success-in-rpm_suspend.patch b/queue-3.4/pm-runtime-clear-power.deferred_resume-on-success-in-rpm_suspend.patch
new file mode 100644 (file)
index 0000000..d5455d8
--- /dev/null
@@ -0,0 +1,49 @@
+From 58a34de7b1a920d287d17d2ca08bc9aaf7e6d35b Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 15 Aug 2012 21:31:55 +0200
+Subject: PM / Runtime: Clear power.deferred_resume on success in rpm_suspend()
+
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+
+commit 58a34de7b1a920d287d17d2ca08bc9aaf7e6d35b upstream.
+
+The power.deferred_resume can only be set if the runtime PM status
+of device is RPM_SUSPENDING and it should be cleared after its
+status has been changed, regardless of whether or not the runtime
+suspend has been successful.  However, it only is cleared on
+suspend failure, while it may remain set on successful suspend and
+is happily leaked to rpm_resume() executed in that case.
+
+That shouldn't happen, so if power.deferred_resume is set in
+rpm_suspend() after the status has been changed to RPM_SUSPENDED,
+clear it before calling rpm_resume().  Then, it doesn't need to be
+cleared before changing the status to RPM_SUSPENDING any more,
+because it's always cleared after the status has been changed to
+either RPM_SUSPENDED (on success) or RPM_ACTIVE (on failure).
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/power/runtime.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -430,7 +430,6 @@ static int rpm_suspend(struct device *de
+               goto repeat;
+       }
+-      dev->power.deferred_resume = false;
+       if (dev->power.no_callbacks)
+               goto no_callback;       /* Assume success. */
+@@ -506,6 +505,7 @@ static int rpm_suspend(struct device *de
+       wake_up_all(&dev->power.wait_queue);
+       if (dev->power.deferred_resume) {
++              dev->power.deferred_resume = false;
+               rpm_resume(dev, 0);
+               retval = -EAGAIN;
+               goto out;
diff --git a/queue-3.4/pm-runtime-fix-rpm_resume-return-value-for-power.no_callbacks-set.patch b/queue-3.4/pm-runtime-fix-rpm_resume-return-value-for-power.no_callbacks-set.patch
new file mode 100644 (file)
index 0000000..23216ca
--- /dev/null
@@ -0,0 +1,46 @@
+From 7f321c26c04807834fef4c524d2b21573423fc74 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+Date: Wed, 15 Aug 2012 21:31:45 +0200
+Subject: PM / Runtime: Fix rpm_resume() return value for power.no_callbacks set
+
+From: "Rafael J. Wysocki" <rjw@sisk.pl>
+
+commit 7f321c26c04807834fef4c524d2b21573423fc74 upstream.
+
+For devices whose power.no_callbacks flag is set, rpm_resume()
+should return 1 if the device's parent is already active, so that
+the callers of pm_runtime_get() don't think that they have to wait
+for the device to resume (asynchronously) in that case (the core
+won't queue up an asynchronous resume in that case, so there's
+nothing to wait for anyway).
+
+Modify the code accordingly (and make sure that an idle notification
+will be queued up on success, even if 1 is to be returned).
+
+Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/power/runtime.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -652,6 +652,7 @@ static int rpm_resume(struct device *dev
+                   || dev->parent->power.runtime_status == RPM_ACTIVE) {
+                       atomic_inc(&dev->parent->power.child_count);
+                       spin_unlock(&dev->parent->power.lock);
++                      retval = 1;
+                       goto no_callback;       /* Assume success. */
+               }
+               spin_unlock(&dev->parent->power.lock);
+@@ -735,7 +736,7 @@ static int rpm_resume(struct device *dev
+       }
+       wake_up_all(&dev->power.wait_queue);
+-      if (!retval)
++      if (retval >= 0)
+               rpm_idle(dev, RPM_ASYNC);
+  out:
index 88b682ff59f4d5de270ae70d2e74b73dbf5d3354..0927ab8bb48c77a9e23010a71f68b1ab111de39d 100644 (file)
@@ -136,3 +136,12 @@ xhci-fix-a-logical-vs-bitwise-and-bug.patch
 xhci-make-handover-code-more-robust.patch
 xhci-recognize-usb-3.0-devices-as-superspeed-at-powerup.patch
 usb-host-xhci-fix-compilation-error-for-non-pci-based-stacks.patch
+tty-serial-imx-console-write-routing-is-unsafe-on-smp.patch
+mutex-place-lock-in-contended-state-after-fastpath_lock-failure.patch
+drivers-rtc-rtc-rs5c348.c-fix-hour-decoding-in-12-hour-mode.patch
+pm-runtime-fix-rpm_resume-return-value-for-power.no_callbacks-set.patch
+pm-runtime-clear-power.deferred_resume-on-success-in-rpm_suspend.patch
+drivers-misc-sgi-xp-xpc_uv.c-sgi-xpc-fails-to-load-when-cpu-0-is-out-of-irq-resources.patch
+fbcon-fix-race-condition-between-console-lock-and-cursor-timer-v1.1.patch
+drm-radeon-avoid-turning-off-spread-spectrum-for-used-pll.patch
+drm-radeon-ss-use-num_crtc-rather-than-hardcoded-6.patch
diff --git a/queue-3.4/tty-serial-imx-console-write-routing-is-unsafe-on-smp.patch b/queue-3.4/tty-serial-imx-console-write-routing-is-unsafe-on-smp.patch
new file mode 100644 (file)
index 0000000..c3fc019
--- /dev/null
@@ -0,0 +1,102 @@
+From 9ec1882df244c4ee1baa692676fef5e8b0f5487d Mon Sep 17 00:00:00 2001
+From: Xinyu Chen <xinyu.chen@freescale.com>
+Date: Mon, 27 Aug 2012 09:36:51 +0200
+Subject: tty: serial: imx: console write routing is unsafe on SMP
+
+From: Xinyu Chen <xinyu.chen@freescale.com>
+
+commit 9ec1882df244c4ee1baa692676fef5e8b0f5487d upstream.
+
+The console feature's write routing is unsafe on SMP with
+the startup/shutdown call.
+
+There could be several consumers of the console
+* the kernel printk
+* the init process using /dev/kmsg to call printk to show log
+* shell, which open /dev/console and write with sys_write()
+
+The shell goes into the normal uart open/write routing,
+but the other two go into the console operations.
+The open routing calls imx serial startup, which will write USR1/2
+register without any lock and critical with imx_console_write call.
+
+Add a spin_lock for startup/shutdown/console_write routing.
+
+This patch is a port from Freescale's Android kernel.
+
+Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
+Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
+CC: Sascha Hauer <s.hauer@pengutronix.de>
+Acked-by: Shawn Guo <shawn.guo@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/imx.c |   12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/imx.c
++++ b/drivers/tty/serial/imx.c
+@@ -756,6 +756,7 @@ static int imx_startup(struct uart_port
+               }
+       }
++      spin_lock_irqsave(&sport->port.lock, flags);
+       /*
+        * Finally, clear and enable interrupts
+        */
+@@ -809,7 +810,6 @@ static int imx_startup(struct uart_port
+       /*
+        * Enable modem status interrupts
+        */
+-      spin_lock_irqsave(&sport->port.lock,flags);
+       imx_enable_ms(&sport->port);
+       spin_unlock_irqrestore(&sport->port.lock,flags);
+@@ -839,10 +839,13 @@ static void imx_shutdown(struct uart_por
+ {
+       struct imx_port *sport = (struct imx_port *)port;
+       unsigned long temp;
++      unsigned long flags;
++      spin_lock_irqsave(&sport->port.lock, flags);
+       temp = readl(sport->port.membase + UCR2);
+       temp &= ~(UCR2_TXEN);
+       writel(temp, sport->port.membase + UCR2);
++      spin_unlock_irqrestore(&sport->port.lock, flags);
+       if (USE_IRDA(sport)) {
+               struct imxuart_platform_data *pdata;
+@@ -871,12 +874,14 @@ static void imx_shutdown(struct uart_por
+        * Disable all interrupts, port and break condition.
+        */
++      spin_lock_irqsave(&sport->port.lock, flags);
+       temp = readl(sport->port.membase + UCR1);
+       temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
+       if (USE_IRDA(sport))
+               temp &= ~(UCR1_IREN);
+       writel(temp, sport->port.membase + UCR1);
++      spin_unlock_irqrestore(&sport->port.lock, flags);
+ }
+ static void
+@@ -1219,6 +1224,9 @@ imx_console_write(struct console *co, co
+       struct imx_port *sport = imx_ports[co->index];
+       struct imx_port_ucrs old_ucr;
+       unsigned int ucr1;
++      unsigned long flags;
++
++      spin_lock_irqsave(&sport->port.lock, flags);
+       /*
+        *      First, save UCR1/2/3 and then disable interrupts
+@@ -1244,6 +1252,8 @@ imx_console_write(struct console *co, co
+       while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
+       imx_port_ucrs_restore(&sport->port, &old_ucr);
++
++      spin_unlock_irqrestore(&sport->port.lock, flags);
+ }
+ /*