]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Apr 2016 20:47:31 +0000 (13:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Apr 2016 20:47:31 +0000 (13:47 -0700)
added patches:
drm-amdgpu-gmc-move-vram-type-fetching-into-sw_init.patch
drm-amdgpu-gmc-use-proper-register-for-vram-type-on-fiji.patch
drm-dp-move-hw_mutex-up-the-call-stack.patch
drm-radeon-add-a-dpm-quirk-for-all-r7-370-parts.patch
drm-radeon-add-a-dpm-quirk-for-sapphire-dual-x-r7-370-2g-d5.patch
drm-radeon-add-another-r7-370-quirk.patch
drm-udl-use-unlocked-gem-unreferencing.patch
xen-events-mask-a-moving-irq.patch

queue-4.4/drm-amdgpu-gmc-move-vram-type-fetching-into-sw_init.patch [new file with mode: 0644]
queue-4.4/drm-amdgpu-gmc-use-proper-register-for-vram-type-on-fiji.patch [new file with mode: 0644]
queue-4.4/drm-dp-move-hw_mutex-up-the-call-stack.patch [new file with mode: 0644]
queue-4.4/drm-radeon-add-a-dpm-quirk-for-all-r7-370-parts.patch [new file with mode: 0644]
queue-4.4/drm-radeon-add-a-dpm-quirk-for-sapphire-dual-x-r7-370-2g-d5.patch [new file with mode: 0644]
queue-4.4/drm-radeon-add-another-r7-370-quirk.patch [new file with mode: 0644]
queue-4.4/drm-udl-use-unlocked-gem-unreferencing.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/xen-events-mask-a-moving-irq.patch [new file with mode: 0644]

diff --git a/queue-4.4/drm-amdgpu-gmc-move-vram-type-fetching-into-sw_init.patch b/queue-4.4/drm-amdgpu-gmc-move-vram-type-fetching-into-sw_init.patch
new file mode 100644 (file)
index 0000000..5cba3c7
--- /dev/null
@@ -0,0 +1,85 @@
+From d1518a1db31a25682ea09c4b135fa72d9883be42 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 31 Mar 2016 16:07:38 -0400
+Subject: drm/amdgpu/gmc: move vram type fetching into sw_init
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit d1518a1db31a25682ea09c4b135fa72d9883be42 upstream.
+
+early_init gets called before atom asic init so on non-posted
+cards, the vram type is not initialized.
+
+Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c |   16 ++++++++--------
+ drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c |   16 ++++++++--------
+ 2 files changed, 16 insertions(+), 16 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+@@ -898,14 +898,6 @@ static int gmc_v7_0_early_init(void *han
+       gmc_v7_0_set_gart_funcs(adev);
+       gmc_v7_0_set_irq_funcs(adev);
+-      if (adev->flags & AMD_IS_APU) {
+-              adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
+-      } else {
+-              u32 tmp = RREG32(mmMC_SEQ_MISC0);
+-              tmp &= MC_SEQ_MISC0__MT__MASK;
+-              adev->mc.vram_type = gmc_v7_0_convert_vram_type(tmp);
+-      }
+-
+       return 0;
+ }
+@@ -926,6 +918,14 @@ static int gmc_v7_0_sw_init(void *handle
+       if (r)
+               return r;
++      if (adev->flags & AMD_IS_APU) {
++              adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
++      } else {
++              u32 tmp = RREG32(mmMC_SEQ_MISC0);
++              tmp &= MC_SEQ_MISC0__MT__MASK;
++              adev->mc.vram_type = gmc_v7_0_convert_vram_type(tmp);
++      }
++
+       r = amdgpu_irq_add_id(adev, 146, &adev->mc.vm_fault);
+       if (r)
+               return r;
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+@@ -852,14 +852,6 @@ static int gmc_v8_0_early_init(void *han
+       gmc_v8_0_set_gart_funcs(adev);
+       gmc_v8_0_set_irq_funcs(adev);
+-      if (adev->flags & AMD_IS_APU) {
+-              adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
+-      } else {
+-              u32 tmp = RREG32(mmMC_SEQ_MISC0);
+-              tmp &= MC_SEQ_MISC0__MT__MASK;
+-              adev->mc.vram_type = gmc_v8_0_convert_vram_type(tmp);
+-      }
+-
+       return 0;
+ }
+@@ -880,6 +872,14 @@ static int gmc_v8_0_sw_init(void *handle
+       if (r)
+               return r;
++      if (adev->flags & AMD_IS_APU) {
++              adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
++      } else {
++              u32 tmp = RREG32(mmMC_SEQ_MISC0);
++              tmp &= MC_SEQ_MISC0__MT__MASK;
++              adev->mc.vram_type = gmc_v8_0_convert_vram_type(tmp);
++      }
++
+       r = amdgpu_irq_add_id(adev, 146, &adev->mc.vm_fault);
+       if (r)
+               return r;
diff --git a/queue-4.4/drm-amdgpu-gmc-use-proper-register-for-vram-type-on-fiji.patch b/queue-4.4/drm-amdgpu-gmc-use-proper-register-for-vram-type-on-fiji.patch
new file mode 100644 (file)
index 0000000..cfe07e6
--- /dev/null
@@ -0,0 +1,44 @@
+From b634de4f446c062a0c95ec4d150b4cf7c85e3526 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu, 31 Mar 2016 16:41:32 -0400
+Subject: drm/amdgpu/gmc: use proper register for vram type on Fiji
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit b634de4f446c062a0c95ec4d150b4cf7c85e3526 upstream.
+
+The offset changed on Fiji.
+
+Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c |    9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+@@ -862,6 +862,8 @@ static int gmc_v8_0_late_init(void *hand
+       return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+ }
++#define mmMC_SEQ_MISC0_FIJI 0xA71
++
+ static int gmc_v8_0_sw_init(void *handle)
+ {
+       int r;
+@@ -875,7 +877,12 @@ static int gmc_v8_0_sw_init(void *handle
+       if (adev->flags & AMD_IS_APU) {
+               adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
+       } else {
+-              u32 tmp = RREG32(mmMC_SEQ_MISC0);
++              u32 tmp;
++
++              if (adev->asic_type == CHIP_FIJI)
++                      tmp = RREG32(mmMC_SEQ_MISC0_FIJI);
++              else
++                      tmp = RREG32(mmMC_SEQ_MISC0);
+               tmp &= MC_SEQ_MISC0__MT__MASK;
+               adev->mc.vram_type = gmc_v8_0_convert_vram_type(tmp);
+       }
diff --git a/queue-4.4/drm-dp-move-hw_mutex-up-the-call-stack.patch b/queue-4.4/drm-dp-move-hw_mutex-up-the-call-stack.patch
new file mode 100644 (file)
index 0000000..db03443
--- /dev/null
@@ -0,0 +1,128 @@
+From 7779c5e23c5132c22a219f1f5554ef81dd15ee91 Mon Sep 17 00:00:00 2001
+From: Rob Clark <robdclark@gmail.com>
+Date: Thu, 25 Feb 2016 16:15:05 -0500
+Subject: drm/dp: move hw_mutex up the call stack
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rob Clark <robdclark@gmail.com>
+
+commit 7779c5e23c5132c22a219f1f5554ef81dd15ee91 upstream.
+
+1) don't let other threads trying to bang on aux channel interrupt the
+defer timeout/logic
+2) don't let other threads interrupt the i2c over aux logic
+
+Technically, according to people who actually have the DP spec, this
+should not be required.  In practice, it makes some troublesome Dell
+monitor (and perhaps others) work, so probably a case of "It's compliant
+if it works with windows" on the hw vendor's part..
+
+v2: rebased to come before DPCD/AUX logging patch for easier backport
+to stable branches.
+
+Reported-by: Dave Wysochanski <dwysocha@redhat.com>
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1274157
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_dp_helper.c |   27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpu/drm/drm_dp_helper.c
++++ b/drivers/gpu/drm/drm_dp_helper.c
+@@ -178,7 +178,7 @@ static int drm_dp_dpcd_access(struct drm
+ {
+       struct drm_dp_aux_msg msg;
+       unsigned int retry;
+-      int err;
++      int err = 0;
+       memset(&msg, 0, sizeof(msg));
+       msg.address = offset;
+@@ -186,6 +186,8 @@ static int drm_dp_dpcd_access(struct drm
+       msg.buffer = buffer;
+       msg.size = size;
++      mutex_lock(&aux->hw_mutex);
++
+       /*
+        * The specification doesn't give any recommendation on how often to
+        * retry native transactions. We used to retry 7 times like for
+@@ -194,25 +196,24 @@ static int drm_dp_dpcd_access(struct drm
+        */
+       for (retry = 0; retry < 32; retry++) {
+-              mutex_lock(&aux->hw_mutex);
+               err = aux->transfer(aux, &msg);
+-              mutex_unlock(&aux->hw_mutex);
+               if (err < 0) {
+                       if (err == -EBUSY)
+                               continue;
+-                      return err;
++                      goto unlock;
+               }
+               switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
+               case DP_AUX_NATIVE_REPLY_ACK:
+                       if (err < size)
+-                              return -EPROTO;
+-                      return err;
++                              err = -EPROTO;
++                      goto unlock;
+               case DP_AUX_NATIVE_REPLY_NACK:
+-                      return -EIO;
++                      err = -EIO;
++                      goto unlock;
+               case DP_AUX_NATIVE_REPLY_DEFER:
+                       usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
+@@ -221,7 +222,11 @@ static int drm_dp_dpcd_access(struct drm
+       }
+       DRM_DEBUG_KMS("too many retries, giving up\n");
+-      return -EIO;
++      err = -EIO;
++
++unlock:
++      mutex_unlock(&aux->hw_mutex);
++      return err;
+ }
+ /**
+@@ -543,9 +548,7 @@ static int drm_dp_i2c_do_msg(struct drm_
+       int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz));
+       for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) {
+-              mutex_lock(&aux->hw_mutex);
+               ret = aux->transfer(aux, msg);
+-              mutex_unlock(&aux->hw_mutex);
+               if (ret < 0) {
+                       if (ret == -EBUSY)
+                               continue;
+@@ -684,6 +687,8 @@ static int drm_dp_i2c_xfer(struct i2c_ad
+       memset(&msg, 0, sizeof(msg));
++      mutex_lock(&aux->hw_mutex);
++
+       for (i = 0; i < num; i++) {
+               msg.address = msgs[i].addr;
+               drm_dp_i2c_msg_set_request(&msg, &msgs[i]);
+@@ -738,6 +743,8 @@ static int drm_dp_i2c_xfer(struct i2c_ad
+       msg.size = 0;
+       (void)drm_dp_i2c_do_msg(aux, &msg);
++      mutex_unlock(&aux->hw_mutex);
++
+       return err;
+ }
diff --git a/queue-4.4/drm-radeon-add-a-dpm-quirk-for-all-r7-370-parts.patch b/queue-4.4/drm-radeon-add-a-dpm-quirk-for-all-r7-370-parts.patch
new file mode 100644 (file)
index 0000000..fa0aa02
--- /dev/null
@@ -0,0 +1,32 @@
+From 0e5585dc870af947fab2af96a88c2d8b4270247c Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Mon, 28 Mar 2016 10:21:20 -0400
+Subject: drm/radeon: add a dpm quirk for all R7 370 parts
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 0e5585dc870af947fab2af96a88c2d8b4270247c upstream.
+
+Higher mclk values are not stable due to a bug somewhere.
+Limit them for now.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/si_dpm.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/si_dpm.c
++++ b/drivers/gpu/drm/radeon/si_dpm.c
+@@ -3010,6 +3010,10 @@ static void si_apply_state_adjust_rules(
+               }
+               ++p;
+       }
++      /* limit mclk on all R7 370 parts for stability */
++      if (rdev->pdev->device == 0x6811 &&
++          rdev->pdev->revision == 0x81)
++              max_mclk = 120000;
+       if (rps->vce_active) {
+               rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
diff --git a/queue-4.4/drm-radeon-add-a-dpm-quirk-for-sapphire-dual-x-r7-370-2g-d5.patch b/queue-4.4/drm-radeon-add-a-dpm-quirk-for-sapphire-dual-x-r7-370-2g-d5.patch
new file mode 100644 (file)
index 0000000..0ec8cef
--- /dev/null
@@ -0,0 +1,29 @@
+From f971f2263deaa4a441e377b385c11aee0f3b3f9a Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 25 Mar 2016 10:31:04 -0400
+Subject: drm/radeon: add a dpm quirk for sapphire Dual-X R7 370 2G D5
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit f971f2263deaa4a441e377b385c11aee0f3b3f9a upstream.
+
+bug:
+https://bugs.freedesktop.org/show_bug.cgi?id=94692
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/si_dpm.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/radeon/si_dpm.c
++++ b/drivers/gpu/drm/radeon/si_dpm.c
+@@ -2926,6 +2926,7 @@ static struct si_dpm_quirk si_dpm_quirk_
+       /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */
+       { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
++      { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0x2015, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
diff --git a/queue-4.4/drm-radeon-add-another-r7-370-quirk.patch b/queue-4.4/drm-radeon-add-another-r7-370-quirk.patch
new file mode 100644 (file)
index 0000000..ed3bafc
--- /dev/null
@@ -0,0 +1,29 @@
+From a64663d9870364bd2a2df62bf0d3a9fbe5ea62a8 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Mon, 28 Mar 2016 10:16:40 -0400
+Subject: drm/radeon: add another R7 370 quirk
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit a64663d9870364bd2a2df62bf0d3a9fbe5ea62a8 upstream.
+
+bug:
+https://bugzilla.kernel.org/show_bug.cgi?id=115291
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/si_dpm.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpu/drm/radeon/si_dpm.c
++++ b/drivers/gpu/drm/radeon/si_dpm.c
+@@ -2930,6 +2930,7 @@ static struct si_dpm_quirk si_dpm_quirk_
+       { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
++      { PCI_VENDOR_ID_ATI, 0x6811, 0x148c, 0x2015, 0, 120000 },
+       { 0, 0, 0, 0 },
+ };
diff --git a/queue-4.4/drm-udl-use-unlocked-gem-unreferencing.patch b/queue-4.4/drm-udl-use-unlocked-gem-unreferencing.patch
new file mode 100644 (file)
index 0000000..dba1097
--- /dev/null
@@ -0,0 +1,50 @@
+From 72b9ff0612ad8fc969b910cd00ac16b57a1a9ba4 Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Wed, 30 Mar 2016 11:40:43 +0200
+Subject: drm/udl: Use unlocked gem unreferencing
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 72b9ff0612ad8fc969b910cd00ac16b57a1a9ba4 upstream.
+
+For drm_gem_object_unreference callers are required to hold
+dev->struct_mutex, which these paths don't. Enforcing this requirement
+has become a bit more strict with
+
+commit ef4c6270bf2867e2f8032e9614d1a8cfc6c71663
+Author: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date:   Thu Oct 15 09:36:25 2015 +0200
+
+    drm/gem: Check locking in drm_gem_object_unreference
+
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/udl/udl_fb.c  |    2 +-
+ drivers/gpu/drm/udl/udl_gem.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/udl/udl_fb.c
++++ b/drivers/gpu/drm/udl/udl_fb.c
+@@ -539,7 +539,7 @@ static int udlfb_create(struct drm_fb_he
+ out_destroy_fbi:
+       drm_fb_helper_release_fbi(helper);
+ out_gfree:
+-      drm_gem_object_unreference(&ufbdev->ufb.obj->base);
++      drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base);
+ out:
+       return ret;
+ }
+--- a/drivers/gpu/drm/udl/udl_gem.c
++++ b/drivers/gpu/drm/udl/udl_gem.c
+@@ -52,7 +52,7 @@ udl_gem_create(struct drm_file *file,
+               return ret;
+       }
+-      drm_gem_object_unreference(&obj->base);
++      drm_gem_object_unreference_unlocked(&obj->base);
+       *handle_p = handle;
+       return 0;
+ }
index 92c6e923dd572e2db89f9c567d724f4dd5ec7a40..79c94cf550bac4b5298c428060df210e52e79d57 100644 (file)
@@ -13,3 +13,11 @@ libnvdimm-fix-smart-data-retrieval.patch
 libnvdimm-pfn-fix-uuid-validation.patch
 compiler-gcc-disable-ftracer-for-__noclone-functions.patch
 arm64-opcodes.h-add-arm-big-endian-config-options-before-including-arm-header.patch
+drm-dp-move-hw_mutex-up-the-call-stack.patch
+drm-udl-use-unlocked-gem-unreferencing.patch
+drm-radeon-add-a-dpm-quirk-for-sapphire-dual-x-r7-370-2g-d5.patch
+drm-radeon-add-another-r7-370-quirk.patch
+drm-radeon-add-a-dpm-quirk-for-all-r7-370-parts.patch
+drm-amdgpu-gmc-move-vram-type-fetching-into-sw_init.patch
+drm-amdgpu-gmc-use-proper-register-for-vram-type-on-fiji.patch
+xen-events-mask-a-moving-irq.patch
diff --git a/queue-4.4/xen-events-mask-a-moving-irq.patch b/queue-4.4/xen-events-mask-a-moving-irq.patch
new file mode 100644 (file)
index 0000000..1410c79
--- /dev/null
@@ -0,0 +1,93 @@
+From ff1e22e7a638a0782f54f81a6c9cb139aca2da35 Mon Sep 17 00:00:00 2001
+From: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Date: Fri, 18 Mar 2016 10:11:07 -0400
+Subject: xen/events: Mask a moving irq
+
+From: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+
+commit ff1e22e7a638a0782f54f81a6c9cb139aca2da35 upstream.
+
+Moving an unmasked irq may result in irq handler being invoked on both
+source and target CPUs.
+
+With 2-level this can happen as follows:
+
+On source CPU:
+        evtchn_2l_handle_events() ->
+            generic_handle_irq() ->
+                handle_edge_irq() ->
+                   eoi_pirq():
+                       irq_move_irq(data);
+
+                       /***** WE ARE HERE *****/
+
+                       if (VALID_EVTCHN(evtchn))
+                           clear_evtchn(evtchn);
+
+If at this moment target processor is handling an unrelated event in
+evtchn_2l_handle_events()'s loop it may pick up our event since target's
+cpu_evtchn_mask claims that this event belongs to it *and* the event is
+unmasked and still pending. At the same time, source CPU will continue
+executing its own handle_edge_irq().
+
+With FIFO interrupt the scenario is similar: irq_move_irq() may result
+in a EVTCHNOP_unmask hypercall which, in turn, may make the event
+pending on the target CPU.
+
+We can avoid this situation by moving and clearing the event while
+keeping event masked.
+
+Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Signed-off-by: David Vrabel <david.vrabel@citrix.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/xen/events/events_base.c |   28 ++++++++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 4 deletions(-)
+
+--- a/drivers/xen/events/events_base.c
++++ b/drivers/xen/events/events_base.c
+@@ -484,9 +484,19 @@ static void eoi_pirq(struct irq_data *da
+       struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) };
+       int rc = 0;
+-      irq_move_irq(data);
++      if (!VALID_EVTCHN(evtchn))
++              return;
+-      if (VALID_EVTCHN(evtchn))
++      if (unlikely(irqd_is_setaffinity_pending(data))) {
++              int masked = test_and_set_mask(evtchn);
++
++              clear_evtchn(evtchn);
++
++              irq_move_masked_irq(data);
++
++              if (!masked)
++                      unmask_evtchn(evtchn);
++      } else
+               clear_evtchn(evtchn);
+       if (pirq_needs_eoi(data->irq)) {
+@@ -1357,9 +1367,19 @@ static void ack_dynirq(struct irq_data *
+ {
+       int evtchn = evtchn_from_irq(data->irq);
+-      irq_move_irq(data);
++      if (!VALID_EVTCHN(evtchn))
++              return;
+-      if (VALID_EVTCHN(evtchn))
++      if (unlikely(irqd_is_setaffinity_pending(data))) {
++              int masked = test_and_set_mask(evtchn);
++
++              clear_evtchn(evtchn);
++
++              irq_move_masked_irq(data);
++
++              if (!masked)
++                      unmask_evtchn(evtchn);
++      } else
+               clear_evtchn(evtchn);
+ }