]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 2 May 2015 17:46:01 +0000 (19:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 2 May 2015 17:46:01 +0000 (19:46 +0200)
added patches:
drm-i915-cope-with-large-i2c-transfers.patch
drm-radeon-fix-doublescan-modes-v2.patch
ksoftirqd-enable-irqs-and-call-cond_resched-before-poking-rcu.patch
rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch

queue-3.14/drm-i915-cope-with-large-i2c-transfers.patch [new file with mode: 0644]
queue-3.14/drm-radeon-fix-doublescan-modes-v2.patch [new file with mode: 0644]
queue-3.14/ksoftirqd-enable-irqs-and-call-cond_resched-before-poking-rcu.patch [new file with mode: 0644]
queue-3.14/rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch [new file with mode: 0644]
queue-3.14/series

diff --git a/queue-3.14/drm-i915-cope-with-large-i2c-transfers.patch b/queue-3.14/drm-i915-cope-with-large-i2c-transfers.patch
new file mode 100644 (file)
index 0000000..104846f
--- /dev/null
@@ -0,0 +1,145 @@
+From 9535c4757b881e06fae72a857485ad57c422b8d2 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Tue, 21 Apr 2015 09:49:11 -0700
+Subject: drm/i915: cope with large i2c transfers
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 9535c4757b881e06fae72a857485ad57c422b8d2 upstream.
+
+The hardware, according to the specs, is limited to 256 byte transfers,
+and current driver has no protections in case users attempt to do larger
+transfers. The code will just stomp over status register and mayhem
+ensues.
+
+Let's split larger transfers into digestable chunks. Doing this allows
+Atmel MXT driver on Pixel 1 function properly (it hasn't since commit
+9d8dc3e529a19e427fd379118acd132520935c5d "Input: atmel_mxt_ts -
+implement T44 message handling" which tries to consume multiple
+touchscreen/touchpad reports in a single transaction).
+
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_reg.h  |    1 
+ drivers/gpu/drm/i915/intel_i2c.c |   66 +++++++++++++++++++++++++++++++++------
+ 2 files changed, 57 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -1181,6 +1181,7 @@
+ #define   GMBUS_CYCLE_INDEX   (2<<25)
+ #define   GMBUS_CYCLE_STOP    (4<<25)
+ #define   GMBUS_BYTE_COUNT_SHIFT 16
++#define   GMBUS_BYTE_COUNT_MAX   256U
+ #define   GMBUS_SLAVE_INDEX_SHIFT 8
+ #define   GMBUS_SLAVE_ADDR_SHIFT 1
+ #define   GMBUS_SLAVE_READ    (1<<0)
+--- a/drivers/gpu/drm/i915/intel_i2c.c
++++ b/drivers/gpu/drm/i915/intel_i2c.c
+@@ -324,18 +324,17 @@ gmbus_wait_idle(struct drm_i915_private
+ }
+ static int
+-gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
+-              u32 gmbus1_index)
++gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
++                    unsigned short addr, u8 *buf, unsigned int len,
++                    u32 gmbus1_index)
+ {
+       int reg_offset = dev_priv->gpio_mmio_base;
+-      u16 len = msg->len;
+-      u8 *buf = msg->buf;
+       I915_WRITE(GMBUS1 + reg_offset,
+                  gmbus1_index |
+                  GMBUS_CYCLE_WAIT |
+                  (len << GMBUS_BYTE_COUNT_SHIFT) |
+-                 (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
++                 (addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  GMBUS_SLAVE_READ | GMBUS_SW_RDY);
+       while (len) {
+               int ret;
+@@ -357,11 +356,35 @@ gmbus_xfer_read(struct drm_i915_private
+ }
+ static int
+-gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
++gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
++              u32 gmbus1_index)
+ {
+-      int reg_offset = dev_priv->gpio_mmio_base;
+-      u16 len = msg->len;
+       u8 *buf = msg->buf;
++      unsigned int rx_size = msg->len;
++      unsigned int len;
++      int ret;
++
++      do {
++              len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
++
++              ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
++                                          buf, len, gmbus1_index);
++              if (ret)
++                      return ret;
++
++              rx_size -= len;
++              buf += len;
++      } while (rx_size != 0);
++
++      return 0;
++}
++
++static int
++gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
++                     unsigned short addr, u8 *buf, unsigned int len)
++{
++      int reg_offset = dev_priv->gpio_mmio_base;
++      unsigned int chunk_size = len;
+       u32 val, loop;
+       val = loop = 0;
+@@ -373,8 +396,8 @@ gmbus_xfer_write(struct drm_i915_private
+       I915_WRITE(GMBUS3 + reg_offset, val);
+       I915_WRITE(GMBUS1 + reg_offset,
+                  GMBUS_CYCLE_WAIT |
+-                 (msg->len << GMBUS_BYTE_COUNT_SHIFT) |
+-                 (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
++                 (chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
++                 (addr << GMBUS_SLAVE_ADDR_SHIFT) |
+                  GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
+       while (len) {
+               int ret;
+@@ -391,6 +414,29 @@ gmbus_xfer_write(struct drm_i915_private
+               if (ret)
+                       return ret;
+       }
++
++      return 0;
++}
++
++static int
++gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
++{
++      u8 *buf = msg->buf;
++      unsigned int tx_size = msg->len;
++      unsigned int len;
++      int ret;
++
++      do {
++              len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
++
++              ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len);
++              if (ret)
++                      return ret;
++
++              buf += len;
++              tx_size -= len;
++      } while (tx_size != 0);
++
+       return 0;
+ }
diff --git a/queue-3.14/drm-radeon-fix-doublescan-modes-v2.patch b/queue-3.14/drm-radeon-fix-doublescan-modes-v2.patch
new file mode 100644 (file)
index 0000000..baae5e8
--- /dev/null
@@ -0,0 +1,46 @@
+From fd99a0943ffaa0320ea4f69d09ed188f950c0432 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Tue, 24 Feb 2015 11:29:21 -0500
+Subject: drm/radeon: fix doublescan modes (v2)
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit fd99a0943ffaa0320ea4f69d09ed188f950c0432 upstream.
+
+Use the correct flags for atom.
+
+v2: handle DRM_MODE_FLAG_DBLCLK
+
+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 |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -330,8 +330,10 @@ atombios_set_crtc_dtd_timing(struct drm_
+               misc |= ATOM_COMPOSITESYNC;
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               misc |= ATOM_INTERLACE;
+-      if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
++      if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               misc |= ATOM_DOUBLE_CLOCK_MODE;
++      if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
++              misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
+       args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
+       args.ucCRTC = radeon_crtc->crtc_id;
+@@ -374,8 +376,10 @@ static void atombios_crtc_set_timing(str
+               misc |= ATOM_COMPOSITESYNC;
+       if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+               misc |= ATOM_INTERLACE;
+-      if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
++      if (mode->flags & DRM_MODE_FLAG_DBLCLK)
+               misc |= ATOM_DOUBLE_CLOCK_MODE;
++      if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
++              misc |= ATOM_H_REPLICATIONBY2 | ATOM_V_REPLICATIONBY2;
+       args.susModeMiscInfo.usAccess = cpu_to_le16(misc);
+       args.ucCRTC = radeon_crtc->crtc_id;
diff --git a/queue-3.14/ksoftirqd-enable-irqs-and-call-cond_resched-before-poking-rcu.patch b/queue-3.14/ksoftirqd-enable-irqs-and-call-cond_resched-before-poking-rcu.patch
new file mode 100644 (file)
index 0000000..b32ffb8
--- /dev/null
@@ -0,0 +1,51 @@
+From 28423ad283d5348793b0c45cc9b1af058e776fd6 Mon Sep 17 00:00:00 2001
+From: Calvin Owens <calvinowens@fb.com>
+Date: Tue, 13 Jan 2015 13:16:18 -0800
+Subject: ksoftirqd: Enable IRQs and call cond_resched() before poking RCU
+
+From: Calvin Owens <calvinowens@fb.com>
+
+commit 28423ad283d5348793b0c45cc9b1af058e776fd6 upstream.
+
+While debugging an issue with excessive softirq usage, I encountered the
+following note in commit 3e339b5dae24a706 ("softirq: Use hotplug thread
+infrastructure"):
+
+    [ paulmck: Call rcu_note_context_switch() with interrupts enabled. ]
+
+...but despite this note, the patch still calls RCU with IRQs disabled.
+
+This seemingly innocuous change caused a significant regression in softirq
+CPU usage on the sending side of a large TCP transfer (~1 GB/s): when
+introducing 0.01% packet loss, the softirq usage would jump to around 25%,
+spiking as high as 50%. Before the change, the usage would never exceed 5%.
+
+Moving the call to rcu_note_context_switch() after the cond_sched() call,
+as it was originally before the hotplug patch, completely eliminated this
+problem.
+
+Signed-off-by: Calvin Owens <calvinowens@fb.com>
+Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Signed-off-by: Mike Galbraith <mgalbraith@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/softirq.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -657,9 +657,13 @@ static void run_ksoftirqd(unsigned int c
+                * in the task stack here.
+                */
+               __do_softirq();
+-              rcu_note_context_switch(cpu);
+               local_irq_enable();
+               cond_resched();
++
++              preempt_disable();
++              rcu_note_context_switch(cpu);
++              preempt_enable();
++
+               return;
+       }
+       local_irq_enable();
diff --git a/queue-3.14/rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch b/queue-3.14/rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch
new file mode 100644 (file)
index 0000000..0b335f0
--- /dev/null
@@ -0,0 +1,45 @@
+From 3cab989afd8d8d1bc3d99fef0e7ed87c31e7b647 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Fri, 24 Apr 2015 15:47:07 -0400
+Subject: RCU pathwalk breakage when running into a symlink overmounting something
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 3cab989afd8d8d1bc3d99fef0e7ed87c31e7b647 upstream.
+
+Calling unlazy_walk() in walk_component() and do_last() when we find
+a symlink that needs to be followed doesn't acquire a reference to vfsmount.
+That's fine when the symlink is on the same vfsmount as the parent directory
+(which is almost always the case), but it's not always true - one _can_
+manage to bind a symlink on top of something.  And in such cases we end up
+with excessive mntput().
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/namei.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1545,7 +1545,8 @@ static inline int walk_component(struct
+       if (should_follow_link(path->dentry, follow)) {
+               if (nd->flags & LOOKUP_RCU) {
+-                      if (unlikely(unlazy_walk(nd, path->dentry))) {
++                      if (unlikely(nd->path.mnt != path->mnt ||
++                                   unlazy_walk(nd, path->dentry))) {
+                               err = -ECHILD;
+                               goto out_err;
+                       }
+@@ -2992,7 +2993,8 @@ finish_lookup:
+       if (should_follow_link(path->dentry, !symlink_ok)) {
+               if (nd->flags & LOOKUP_RCU) {
+-                      if (unlikely(unlazy_walk(nd, path->dentry))) {
++                      if (unlikely(nd->path.mnt != path->mnt ||
++                                   unlazy_walk(nd, path->dentry))) {
+                               error = -ECHILD;
+                               goto out;
+                       }
index e97ef5834f11a7125dc87c4fd42c99beedbb2839..359dc6e14513be672eadf184fc0154bd333e4157 100644 (file)
@@ -78,3 +78,7 @@ ib-core-disallow-registering-0-sized-memory-region.patch
 ib-core-don-t-disallow-registering-region-starting-at-0x0.patch
 ib-mlx4-fix-wqe-lso-segment-calculation.patch
 i2c-core-export-bus-recovery-functions.patch
+drm-radeon-fix-doublescan-modes-v2.patch
+drm-i915-cope-with-large-i2c-transfers.patch
+rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch
+ksoftirqd-enable-irqs-and-call-cond_resched-before-poking-rcu.patch