--- /dev/null
+From 2e07fb229396f99fc173d8612f0f83ea9de0341b Mon Sep 17 00:00:00 2001
+From: YoungJun Cho <yj44.cho@samsung.com>
+Date: Thu, 27 Jun 2013 08:58:33 +0900
+Subject: drm/gem: fix not to assign error value to gem name
+
+From: YoungJun Cho <yj44.cho@samsung.com>
+
+commit 2e07fb229396f99fc173d8612f0f83ea9de0341b upstream.
+
+If idr_alloc() is failed, obj->name can be error value. Also
+it cleans up duplicated flink processing code.
+
+This regression has been introduced in
+
+commit 2e928815c1886fe628ed54623aa98d0889cf5509
+Author: Tejun Heo <tj@kernel.org>
+Date: Wed Feb 27 17:04:08 2013 -0800
+
+ drm: convert to idr_alloc()
+
+Signed-off-by: YoungJun Cho <yj44.cho@samsung.com>
+Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
+Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/drm_gem.c | 18 +++++++-----------
+ 1 file changed, 7 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/drm_gem.c
++++ b/drivers/gpu/drm/drm_gem.c
+@@ -453,25 +453,21 @@ drm_gem_flink_ioctl(struct drm_device *d
+ spin_lock(&dev->object_name_lock);
+ if (!obj->name) {
+ ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT);
+- obj->name = ret;
+- args->name = (uint64_t) obj->name;
+- spin_unlock(&dev->object_name_lock);
+- idr_preload_end();
+-
+ if (ret < 0)
+ goto err;
+- ret = 0;
++
++ obj->name = ret;
+
+ /* Allocate a reference for the name table. */
+ drm_gem_object_reference(obj);
+- } else {
+- args->name = (uint64_t) obj->name;
+- spin_unlock(&dev->object_name_lock);
+- idr_preload_end();
+- ret = 0;
+ }
+
++ args->name = (uint64_t) obj->name;
++ ret = 0;
++
+ err:
++ spin_unlock(&dev->object_name_lock);
++ idr_preload_end();
+ drm_gem_object_unreference_unlocked(obj);
+ return ret;
+ }
--- /dev/null
+From abbee6238775c6633a3779962e9e5b5cb9823749 Mon Sep 17 00:00:00 2001
+From: Julia Lemire <jlemire@matrox.com>
+Date: Thu, 27 Jun 2013 13:38:59 -0400
+Subject: drm/mgag200: Added resolution and bandwidth limits for various G200e products.
+
+From: Julia Lemire <jlemire@matrox.com>
+
+commit abbee6238775c6633a3779962e9e5b5cb9823749 upstream.
+
+At the larger resolutions, the g200e series sometimes struggles with
+maintaining a proper output. Problems like flickering or black bands appearing
+on screen can occur. In order to avoid this, limitations regarding resolutions
+and bandwidth have been added for the different variations of the g200e series.
+This code was ported from the old xorg mga driver.
+
+Signed-off-by: Julia Lemire <jlemire@matrox.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/mgag200/mgag200_drv.h | 3 -
+ drivers/gpu/drm/mgag200/mgag200_main.c | 2
+ drivers/gpu/drm/mgag200/mgag200_mode.c | 70 +++++++++++++++++++++++++++++++--
+ 3 files changed, 70 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
++++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
+@@ -198,7 +198,8 @@ struct mga_device {
+ struct ttm_bo_device bdev;
+ } ttm;
+
+- u32 reg_1e24; /* SE model number */
++ /* SE model number stored in reg 0x1e24 */
++ u32 unique_rev_id;
+ };
+
+
+--- a/drivers/gpu/drm/mgag200/mgag200_main.c
++++ b/drivers/gpu/drm/mgag200/mgag200_main.c
+@@ -176,7 +176,7 @@ static int mgag200_device_init(struct dr
+
+ /* stash G200 SE model number for later use */
+ if (IS_G200_SE(mdev))
+- mdev->reg_1e24 = RREG32(0x1e24);
++ mdev->unique_rev_id = RREG32(0x1e24);
+
+ ret = mga_vram_init(mdev);
+ if (ret)
+--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
++++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
+@@ -1008,7 +1008,7 @@ static int mga_crtc_mode_set(struct drm_
+
+
+ if (IS_G200_SE(mdev)) {
+- if (mdev->reg_1e24 >= 0x02) {
++ if (mdev->unique_rev_id >= 0x02) {
+ u8 hi_pri_lvl;
+ u32 bpp;
+ u32 mb;
+@@ -1038,7 +1038,7 @@ static int mga_crtc_mode_set(struct drm_
+ WREG8(MGAREG_CRTCEXT_DATA, hi_pri_lvl);
+ } else {
+ WREG8(MGAREG_CRTCEXT_INDEX, 0x06);
+- if (mdev->reg_1e24 >= 0x01)
++ if (mdev->unique_rev_id >= 0x01)
+ WREG8(MGAREG_CRTCEXT_DATA, 0x03);
+ else
+ WREG8(MGAREG_CRTCEXT_DATA, 0x04);
+@@ -1410,6 +1410,32 @@ static int mga_vga_get_modes(struct drm_
+ return ret;
+ }
+
++static uint32_t mga_vga_calculate_mode_bandwidth(struct drm_display_mode *mode,
++ int bits_per_pixel)
++{
++ uint32_t total_area, divisor;
++ int64_t active_area, pixels_per_second, bandwidth;
++ uint64_t bytes_per_pixel = (bits_per_pixel + 7) / 8;
++
++ divisor = 1024;
++
++ if (!mode->htotal || !mode->vtotal || !mode->clock)
++ return 0;
++
++ active_area = mode->hdisplay * mode->vdisplay;
++ total_area = mode->htotal * mode->vtotal;
++
++ pixels_per_second = active_area * mode->clock * 1000;
++ do_div(pixels_per_second, total_area);
++
++ bandwidth = pixels_per_second * bytes_per_pixel * 100;
++ do_div(bandwidth, divisor);
++
++ return (uint32_t)(bandwidth);
++}
++
++#define MODE_BANDWIDTH MODE_BAD
++
+ static int mga_vga_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+ {
+@@ -1421,7 +1447,45 @@ static int mga_vga_mode_valid(struct drm
+ int bpp = 32;
+ int i = 0;
+
+- /* FIXME: Add bandwidth and g200se limitations */
++ if (IS_G200_SE(mdev)) {
++ if (mdev->unique_rev_id == 0x01) {
++ if (mode->hdisplay > 1600)
++ return MODE_VIRTUAL_X;
++ if (mode->vdisplay > 1200)
++ return MODE_VIRTUAL_Y;
++ if (mga_vga_calculate_mode_bandwidth(mode, bpp)
++ > (24400 * 1024))
++ return MODE_BANDWIDTH;
++ } else if (mdev->unique_rev_id >= 0x02) {
++ if (mode->hdisplay > 1920)
++ return MODE_VIRTUAL_X;
++ if (mode->vdisplay > 1200)
++ return MODE_VIRTUAL_Y;
++ if (mga_vga_calculate_mode_bandwidth(mode, bpp)
++ > (30100 * 1024))
++ return MODE_BANDWIDTH;
++ }
++ } else if (mdev->type == G200_WB) {
++ if (mode->hdisplay > 1280)
++ return MODE_VIRTUAL_X;
++ if (mode->vdisplay > 1024)
++ return MODE_VIRTUAL_Y;
++ if (mga_vga_calculate_mode_bandwidth(mode,
++ bpp > (31877 * 1024)))
++ return MODE_BANDWIDTH;
++ } else if (mdev->type == G200_EV &&
++ (mga_vga_calculate_mode_bandwidth(mode, bpp)
++ > (32700 * 1024))) {
++ return MODE_BANDWIDTH;
++ } else if (mode->type == G200_EH &&
++ (mga_vga_calculate_mode_bandwidth(mode, bpp)
++ > (37500 * 1024))) {
++ return MODE_BANDWIDTH;
++ } else if (mode->type == G200_ER &&
++ (mga_vga_calculate_mode_bandwidth(mode,
++ bpp) > (55000 * 1024))) {
++ return MODE_BANDWIDTH;
++ }
+
+ if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
+ mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||
--- /dev/null
+From d005f51eb93d71cd40ebd11dd377453fa8c8a42a Mon Sep 17 00:00:00 2001
+From: Marcin Slusarz <marcin.slusarz@gmail.com>
+Date: Tue, 11 Jun 2013 10:50:30 +0200
+Subject: drm/nouveau: use vmalloc for pgt allocation
+
+From: Marcin Slusarz <marcin.slusarz@gmail.com>
+
+commit d005f51eb93d71cd40ebd11dd377453fa8c8a42a upstream.
+
+Page tables on nv50 take 48kB, which can be hard to allocate in one piece.
+Let's use vmalloc.
+
+Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com>
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/core/subdev/vm/base.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
++++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
+@@ -362,7 +362,7 @@ nouveau_vm_create(struct nouveau_vmmgr *
+ vm->fpde = offset >> (vmm->pgt_bits + 12);
+ vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12);
+
+- vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL);
++ vm->pgt = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt));
+ if (!vm->pgt) {
+ kfree(vm);
+ return -ENOMEM;
+@@ -371,7 +371,7 @@ nouveau_vm_create(struct nouveau_vmmgr *
+ ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12,
+ block >> 12);
+ if (ret) {
+- kfree(vm->pgt);
++ vfree(vm->pgt);
+ kfree(vm);
+ return ret;
+ }
+@@ -446,7 +446,7 @@ nouveau_vm_del(struct nouveau_vm *vm)
+ }
+
+ nouveau_mm_fini(&vm->mm);
+- kfree(vm->pgt);
++ vfree(vm->pgt);
+ kfree(vm);
+ }
+
--- /dev/null
+From 378f2bcdf7c971453d11580936dc0ffe845f5880 Mon Sep 17 00:00:00 2001
+From: Emil Velikov <emil.l.velikov@gmail.com>
+Date: Tue, 2 Jul 2013 14:44:12 +0100
+Subject: drm/nv50-/disp: Use output specific mask in interrupt
+
+From: Emil Velikov <emil.l.velikov@gmail.com>
+
+commit 378f2bcdf7c971453d11580936dc0ffe845f5880 upstream.
+
+The commit
+
+ commit 476e84e126171d809f9c0b5d97137f5055f95ca8
+ Author: Ben Skeggs <bskeggs@redhat.com>
+ Date: Mon Feb 11 09:24:23 2013 +1000
+
+ drm/nv50-/disp: initial supervisor support for off-chip encoders
+
+changed the write mask in one of the interrupt functions for on-chip encoders,
+causing a regression in certain VGA dual-head setups. This commit reintroduces
+the mask thus resolving the regression
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66129
+Reported-and-Tested-by: Yves-Alexis <corsac@debian.org>
+CC: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+@@ -1107,6 +1107,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_
+ u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff;
+ u32 hval, hreg = 0x614200 + (head * 0x800);
+ u32 oval, oreg;
++ u32 mask;
+ u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp);
+ if (conf != ~0) {
+ if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) {
+@@ -1133,6 +1134,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_
+ oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800;
+ oval = 0x00000000;
+ hval = 0x00000000;
++ mask = 0xffffffff;
+ } else
+ if (!outp.location) {
+ if (outp.type == DCB_OUTPUT_DP)
+@@ -1140,14 +1142,16 @@ nv50_disp_intr_unk20_2(struct nv50_disp_
+ oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800;
+ oval = (conf & 0x0100) ? 0x00000101 : 0x00000000;
+ hval = 0x00000000;
++ mask = 0x00000707;
+ } else {
+ oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800;
+ oval = 0x00000001;
+ hval = 0x00000001;
++ mask = 0x00000707;
+ }
+
+ nv_mask(priv, hreg, 0x0000000f, hval);
+- nv_mask(priv, oreg, 0x00000707, oval);
++ nv_mask(priv, oreg, mask, oval);
+ }
+ }
+
--- /dev/null
+From bf03d1b293cc556df53545e318110505014d805e Mon Sep 17 00:00:00 2001
+From: Ilia Mirkin <imirkin@alum.mit.edu>
+Date: Wed, 3 Jul 2013 03:06:02 -0400
+Subject: drm/nva3/disp: Fix HDMI audio regression
+
+From: Ilia Mirkin <imirkin@alum.mit.edu>
+
+commit bf03d1b293cc556df53545e318110505014d805e upstream.
+
+This is the nva3 counterpart to commit beba44b17 (drm/nv84/disp: Fix
+HDMI audio regression). The regression happened as a result of
+refactoring in commit 8e9e3d2de (drm/nv84/disp: move hdmi control into
+core).
+
+Reported-and-tested-by: Max Baldwin <archerseven@gmail.com>
+Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
+Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
++++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdminva3.c
+@@ -55,6 +55,10 @@ nva3_hdmi_ctrl(struct nv50_disp_priv *pr
+ nv_wr32(priv, 0x61c510 + soff, 0x00000000);
+ nv_mask(priv, 0x61c500 + soff, 0x00000001, 0x00000001);
+
++ nv_mask(priv, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
++ nv_mask(priv, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
++ nv_mask(priv, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
++
+ /* ??? */
+ nv_mask(priv, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
+ nv_mask(priv, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
--- /dev/null
+From 80101790670385a85aca35ecae4b89e3f2fceecc Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Mon, 10 Jun 2013 09:57:07 -0400
+Subject: drm/radeon: add backlight quirk for hybrid mac
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 80101790670385a85aca35ecae4b89e3f2fceecc upstream.
+
+Mac laptops with multiple GPUs apparently use the gmux
+driver for backlight control. Don't register a radeon
+backlight interface. We may need to add other pci ids
+for other hybrid mac laptops.
+
+Fixes:
+https://bugs.freedesktop.org/show_bug.cgi?id=65377
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/atombios_encoders.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/radeon/atombios_encoders.c
++++ b/drivers/gpu/drm/radeon/atombios_encoders.c
+@@ -186,6 +186,13 @@ void radeon_atom_backlight_init(struct r
+ u8 backlight_level;
+ char bl_name[16];
+
++ /* Mac laptops with multiple GPUs use the gmux driver for backlight
++ * so don't register a backlight device
++ */
++ if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
++ (rdev->pdev->device == 0x6741))
++ return;
++
+ if (!radeon_encoder->enc_priv)
+ return;
+
--- /dev/null
+From f100380ecd8287b0909d3c5694784adc46e78a4a Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 7 Jun 2013 10:41:03 -0400
+Subject: drm/radeon: fix AVI infoframe generation
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit f100380ecd8287b0909d3c5694784adc46e78a4a upstream.
+
+- remove adding 2 to checksum, this is incorrect.
+
+This was incorrectly introduced in:
+92db7f6c860b8190571a9dc1fcbc16d003422fe8
+http://lists.freedesktop.org/archives/dri-devel/2011-December/017717.html
+However, the off by 2 was due to adding the version twice.
+From the examples in the URL above:
+
+[Rafał Miłecki][RV620] fglrx:
+0x7454: 00 A8 5E 79 R600_HDMI_VIDEOINFOFRAME_0
+0x7458: 00 28 00 10 R600_HDMI_VIDEOINFOFRAME_1
+0x745C: 00 48 00 28 R600_HDMI_VIDEOINFOFRAME_2
+0x7460: 02 00 00 48 R600_HDMI_VIDEOINFOFRAME_3
+===================
+(0x82 + 0x2 + 0xD) + 0x1F8 = 0x289
+-0x289 = 0x77
+
+However, the payload sum is not 0x1f8, it's 0x1f6.
+00 + A8 + 5E + 00 +
+00 + 28 + 00 + 10 +
+00 + 48 + 00 + 28 +
+00 + 48 =
+0x1f6
+
+Bits 25:24 of HDMI_VIDEOINFOFRAME_3 are the packet version, not part
+of the payload. So the total would be:
+(0x82 + 0x2 + 0xD) + 0x1f6 = 0x287
+-0x287 = 0x79
+
+- properly emit the AVI infoframe version. This was not being
+emitted previous which is probably what caused the issue above.
+
+This should fix blank screen when HDMI audio is enabled on
+certain monitors.
+
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: Rafał Miłecki <zajec5@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/radeon/evergreen_hdmi.c | 11 ++---------
+ drivers/gpu/drm/radeon/r600_hdmi.c | 11 ++---------
+ 2 files changed, 4 insertions(+), 18 deletions(-)
+
+--- a/drivers/gpu/drm/radeon/evergreen_hdmi.c
++++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c
+@@ -128,14 +128,7 @@ static void evergreen_hdmi_update_avi_in
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+ uint32_t offset = dig->afmt->offset;
+ uint8_t *frame = buffer + 3;
+-
+- /* Our header values (type, version, length) should be alright, Intel
+- * is using the same. Checksum function also seems to be OK, it works
+- * fine for audio infoframe. However calculated value is always lower
+- * by 2 in comparison to fglrx. It breaks displaying anything in case
+- * of TVs that strictly check the checksum. Hack it manually here to
+- * workaround this issue. */
+- frame[0x0] += 2;
++ uint8_t *header = buffer;
+
+ WREG32(AFMT_AVI_INFO0 + offset,
+ frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
+@@ -144,7 +137,7 @@ static void evergreen_hdmi_update_avi_in
+ WREG32(AFMT_AVI_INFO2 + offset,
+ frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
+ WREG32(AFMT_AVI_INFO3 + offset,
+- frame[0xC] | (frame[0xD] << 8));
++ frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
+ }
+
+ static void evergreen_audio_set_dto(struct drm_encoder *encoder, u32 clock)
+--- a/drivers/gpu/drm/radeon/r600_hdmi.c
++++ b/drivers/gpu/drm/radeon/r600_hdmi.c
+@@ -133,14 +133,7 @@ static void r600_hdmi_update_avi_infofra
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+ uint32_t offset = dig->afmt->offset;
+ uint8_t *frame = buffer + 3;
+-
+- /* Our header values (type, version, length) should be alright, Intel
+- * is using the same. Checksum function also seems to be OK, it works
+- * fine for audio infoframe. However calculated value is always lower
+- * by 2 in comparison to fglrx. It breaks displaying anything in case
+- * of TVs that strictly check the checksum. Hack it manually here to
+- * workaround this issue. */
+- frame[0x0] += 2;
++ uint8_t *header = buffer;
+
+ WREG32(HDMI0_AVI_INFO0 + offset,
+ frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
+@@ -149,7 +142,7 @@ static void r600_hdmi_update_avi_infofra
+ WREG32(HDMI0_AVI_INFO2 + offset,
+ frame[0x8] | (frame[0x9] << 8) | (frame[0xA] << 16) | (frame[0xB] << 24));
+ WREG32(HDMI0_AVI_INFO3 + offset,
+- frame[0xC] | (frame[0xD] << 8));
++ frame[0xC] | (frame[0xD] << 8) | (header[1] << 24));
+ }
+
+ /*
--- /dev/null
+From 60d0ca3cfd199b6612bbbbf4999a3470dad38bb1 Mon Sep 17 00:00:00 2001
+From: Alex Williamson <alex.williamson@redhat.com>
+Date: Fri, 21 Jun 2013 14:33:19 -0600
+Subject: iommu/amd: Only unmap large pages from the first pte
+
+From: Alex Williamson <alex.williamson@redhat.com>
+
+commit 60d0ca3cfd199b6612bbbbf4999a3470dad38bb1 upstream.
+
+If we use a large mapping, the expectation is that only unmaps from
+the first pte in the superpage are supported. Unmaps from offsets
+into the superpage should fail (ie. return zero sized unmap). In the
+current code, unmapping from an offset clears the size of the full
+mapping starting from an offset. For instance, if we map a 16k
+physically contiguous range at IOVA 0x0 with a large page, then
+attempt to unmap 4k at offset 12k, 4 ptes are cleared (12k - 28k) and
+the unmap returns 16k unmapped. This potentially incorrectly clears
+valid mappings and confuses drivers like VFIO that use the unmap size
+to release pinned pages.
+
+Fix by refusing to unmap from offsets into the page.
+
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Joerg Roedel <joro@8bytes.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/amd_iommu.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -1484,6 +1484,10 @@ static unsigned long iommu_unmap_page(st
+
+ /* Large PTE found which maps this address */
+ unmap_size = PTE_PAGE_SIZE(*pte);
++
++ /* Only unmap from the first pte in the page */
++ if ((unmap_size - 1) & bus_addr)
++ break;
+ count = PAGE_SIZE_PTE_COUNT(unmap_size);
+ for (i = 0; i < count; i++)
+ pte[i] = 0ULL;
+@@ -1493,7 +1497,7 @@ static unsigned long iommu_unmap_page(st
+ unmapped += unmap_size;
+ }
+
+- BUG_ON(!is_power_of_2(unmapped));
++ BUG_ON(unmapped && !is_power_of_2(unmapped));
+
+ return unmapped;
+ }
drm-i915-fix-up-sdvo-hpd-pins-for-i965g-gm.patch
drm-i915-fix-context-sizes-on-hsw.patch
drm-i915-only-clear-write-domains-after-a-successful-wait-seqno.patch
+drm-gem-fix-not-to-assign-error-value-to-gem-name.patch
+drm-mgag200-added-resolution-and-bandwidth-limits-for-various-g200e-products.patch
+drm-nouveau-use-vmalloc-for-pgt-allocation.patch
+drm-radeon-fix-avi-infoframe-generation.patch
+drm-radeon-add-backlight-quirk-for-hybrid-mac.patch
+drm-nva3-disp-fix-hdmi-audio-regression.patch
+drm-nv50-disp-use-output-specific-mask-in-interrupt.patch
+iommu-amd-only-unmap-large-pages-from-the-first-pte.patch