--- /dev/null
+From e7d841ca03b7ab668620045cd7b428eda9f41601 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Mon, 3 Dec 2012 11:36:30 +0000
+Subject: drm/i915: Close race between processing unpin task and queueing the flip
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit e7d841ca03b7ab668620045cd7b428eda9f41601 upstream.
+
+Before queuing the flip but crucially after attaching the unpin-work to
+the crtc, we continue to setup the unpin-work. However, should the
+hardware fire early, we see the connected unpin-work and queue the task.
+The task then promptly runs and unpins the fb before we finish taking
+the required references or even pinning it... Havoc.
+
+To close the race, we use the flip-pending atomic to indicate when the
+flip is finally setup and enqueued. So during the flip-done processing,
+we can check more accurately whether the flip was expected.
+
+v2: Add the appropriate mb() to ensure that the writes to the page-flip
+worker are complete prior to marking it active and emitting the MI_FLIP.
+On the read side, the mb should be enforced by the spinlocks.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+[danvet: Review the barriers a bit, we need a write barrier both
+before and after updating ->pending. Similarly we need a read barrier
+in the interrupt handler both before and after reading ->pending. With
+well-ordered irqs only one barrier in each place should be required,
+but since this patch explicitly sets out to combat spurious interrupts
+with is staged activation of the unpin work we need to go full-bore on
+the barriers, too. Discussed with Chris Wilson on irc and changes
+acked by him.]
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_debugfs.c | 4 +--
+ drivers/gpu/drm/i915/i915_irq.c | 4 ++-
+ drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++++++++++++++-------
+ drivers/gpu/drm/i915/intel_drv.h | 5 +++-
+ 4 files changed, 41 insertions(+), 11 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_debugfs.c
++++ b/drivers/gpu/drm/i915/i915_debugfs.c
+@@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct
+ seq_printf(m, "No flip due on pipe %c (plane %c)\n",
+ pipe, plane);
+ } else {
+- if (!work->pending) {
++ if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
+ seq_printf(m, "Flip queued on pipe %c (plane %c)\n",
+ pipe, plane);
+ } else {
+@@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct
+ seq_printf(m, "Stall check enabled, ");
+ else
+ seq_printf(m, "Stall check waiting for page flip ioctl, ");
+- seq_printf(m, "%d prepares\n", work->pending);
++ seq_printf(m, "%d prepares\n", atomic_read(&work->pending));
+
+ if (work->old_fb_obj) {
+ struct drm_i915_gem_object *obj = work->old_fb_obj;
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -1464,7 +1464,9 @@ static void i915_pageflip_stall_check(st
+ spin_lock_irqsave(&dev->event_lock, flags);
+ work = intel_crtc->unpin_work;
+
+- if (work == NULL || work->pending || !work->enable_stall_check) {
++ if (work == NULL ||
++ atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE ||
++ !work->enable_stall_check) {
+ /* Either the pending flip IRQ arrived, or we're too early. Don't check */
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ return;
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -6215,11 +6215,18 @@ static void do_intel_finish_page_flip(st
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+ work = intel_crtc->unpin_work;
+- if (work == NULL || !work->pending) {
++
++ /* Ensure we don't miss a work->pending update ... */
++ smp_rmb();
++
++ if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) {
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ return;
+ }
+
++ /* and that the unpin work is consistent wrt ->pending. */
++ smp_rmb();
++
+ intel_crtc->unpin_work = NULL;
+
+ if (work->event) {
+@@ -6272,16 +6279,25 @@ void intel_prepare_page_flip(struct drm_
+ to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]);
+ unsigned long flags;
+
++ /* NB: An MMIO update of the plane base pointer will also
++ * generate a page-flip completion irq, i.e. every modeset
++ * is also accompanied by a spurious intel_prepare_page_flip().
++ */
+ spin_lock_irqsave(&dev->event_lock, flags);
+- if (intel_crtc->unpin_work) {
+- if ((++intel_crtc->unpin_work->pending) > 1)
+- DRM_ERROR("Prepared flip multiple times\n");
+- } else {
+- DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n");
+- }
++ if (intel_crtc->unpin_work)
++ atomic_inc_not_zero(&intel_crtc->unpin_work->pending);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ }
+
++inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc)
++{
++ /* Ensure that the work item is consistent when activating it ... */
++ smp_wmb();
++ atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING);
++ /* and that it is marked active as soon as the irq could fire. */
++ smp_wmb();
++}
++
+ static int intel_gen2_queue_flip(struct drm_device *dev,
+ struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+@@ -6315,6 +6331,8 @@ static int intel_gen2_queue_flip(struct
+ intel_ring_emit(ring, fb->pitches[0]);
+ intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+ intel_ring_emit(ring, 0); /* aux display base address, unused */
++
++ intel_mark_page_flip_active(intel_crtc);
+ intel_ring_advance(ring);
+ return 0;
+
+@@ -6355,6 +6373,7 @@ static int intel_gen3_queue_flip(struct
+ intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+ intel_ring_emit(ring, MI_NOOP);
+
++ intel_mark_page_flip_active(intel_crtc);
+ intel_ring_advance(ring);
+ return 0;
+
+@@ -6401,6 +6420,8 @@ static int intel_gen4_queue_flip(struct
+ pf = 0;
+ pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+ intel_ring_emit(ring, pf | pipesrc);
++
++ intel_mark_page_flip_active(intel_crtc);
+ intel_ring_advance(ring);
+ return 0;
+
+@@ -6443,6 +6464,8 @@ static int intel_gen6_queue_flip(struct
+ pf = 0;
+ pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
+ intel_ring_emit(ring, pf | pipesrc);
++
++ intel_mark_page_flip_active(intel_crtc);
+ intel_ring_advance(ring);
+ return 0;
+
+@@ -6497,6 +6520,8 @@ static int intel_gen7_queue_flip(struct
+ intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
+ intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset);
+ intel_ring_emit(ring, (MI_NOOP));
++
++ intel_mark_page_flip_active(intel_crtc);
+ intel_ring_advance(ring);
+ return 0;
+
+--- a/drivers/gpu/drm/i915/intel_drv.h
++++ b/drivers/gpu/drm/i915/intel_drv.h
+@@ -384,7 +384,10 @@ struct intel_unpin_work {
+ struct drm_i915_gem_object *old_fb_obj;
+ struct drm_i915_gem_object *pending_flip_obj;
+ struct drm_pending_vblank_event *event;
+- int pending;
++ atomic_t pending;
++#define INTEL_FLIP_INACTIVE 0
++#define INTEL_FLIP_PENDING 1
++#define INTEL_FLIP_COMPLETE 2
+ bool enable_stall_check;
+ };
+
--- /dev/null
+From b0a2658acb5bf9ca86b4aab011b7106de3af0add Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Tue, 18 Dec 2012 09:37:54 +0100
+Subject: drm/i915: don't disable disconnected outputs
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit b0a2658acb5bf9ca86b4aab011b7106de3af0add upstream.
+
+This piece of neat lore has been ported painstakingly and bug-for-bug
+compatible from the old crtc helper code.
+
+Imo it's utter nonsense.
+
+If you disconnected a cable and before you reconnect it, userspace (or
+the kernel) does an set_crtc call, this will result in that connector
+getting disabled. Which will result in a nice black screen when
+plugging in the cable again.
+
+There's absolutely no reason the kernel does such policy enforcements
+- if userspace tries to set up a mode on something disconnected we
+might fail loudly (since the dp link training fails), but silently
+adjusting the output configuration behind userspace's back is a recipe
+for disaster. Specifically I think that this could explain some of our
+MI_WAIT hangs around suspend, where userspace issues a scanline wait
+on a disable pipe. This mechanisims here could explain how that pipe
+got disabled without userspace noticing.
+
+Note that this fixes a NULL deref at BIOS takeover when the firmware
+sets up a disconnected output in a clone configuration with a
+connected output on the 2nd pipe: When doing the full modeset we don't
+have a mode for the 2nd pipe and OOPS. On the first pipe this doesn't
+matter, since at boot-up the fbdev helpers will set up the choosen
+configuration on that on first. Since this is now the umptenth bug
+around handling this imo brain-dead semantics correctly, I think it's
+time to kill it and see whether there's any userspace out there which
+relies on this.
+
+It also nicely demonstrates that we have a tiny window where DP
+hotplug can still kill the driver.
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58396
+Tested-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
+Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
+Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_display.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -7298,10 +7298,6 @@ intel_modeset_stage_output_state(struct
+ DRM_DEBUG_KMS("encoder changed, full mode switch\n");
+ config->mode_changed = true;
+ }
+-
+- /* Disable all disconnected encoders. */
+- if (connector->base.status == connector_status_disconnected)
+- connector->new_encoder = NULL;
+ }
+ /* connector->new_encoder is now updated for all connectors. */
+
--- /dev/null
+From 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@redhat.com>
+Date: Thu, 20 Dec 2012 10:51:09 +1000
+Subject: drm/i915: fix flags in dma buf exporting
+
+From: Dave Airlie <airlied@redhat.com>
+
+commit 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 upstream.
+
+As pointed out by Seung-Woo Kim this should have been
+passing flags like nouveau/radeon have.
+
+Signed-off-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/i915/i915_gem_dmabuf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+@@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(st
+ {
+ struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
+
+- return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600);
++ return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags);
+ }
+
+ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
--- /dev/null
+From b4a98e57fc27854b5938fc8b08b68e5e68b91e1f Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Thu, 1 Nov 2012 09:26:26 +0000
+Subject: drm/i915: Flush outstanding unpin tasks before pageflipping
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit b4a98e57fc27854b5938fc8b08b68e5e68b91e1f upstream.
+
+If we accumulate unpin tasks because we are pageflipping faster than the
+system can schedule its workers, we can effectively create a
+pin-leak. The solution taken here is to limit the number of unpin tasks
+we have per-crtc and to flush those outstanding tasks if we accumulate
+too many. This should prevent any jitter in the normal case, and also
+prevent the hang if we should run too fast.
+
+Note: It is important that we switch from the system workqueue to our
+own dev_priv->wq since all work items on that queue are guaranteed to
+only need the dev->struct_mutex and not any modeset resources. For
+otherwise if we have a work item ahead in the queue which needs the
+modeset lock (like the output detect work used by both polling or
+hpd), this work and so the unpin work will never execute since the
+pageflip code already holds that lock. Unfortunately there's no
+lockdep support for this scenario in the workqueue code.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46991
+Reported-and-tested-by: Tvrtko Ursulin <tvrtko.ursulin@onelan.co.uk>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+[danvet: Added note about workqueu deadlock.]
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56337
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Tested-by: Daniel Gnoutcheff <daniel@gnoutcheff.name>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++------
+ drivers/gpu/drm/i915/intel_drv.h | 4 +++-
+ 2 files changed, 19 insertions(+), 7 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_display.c
++++ b/drivers/gpu/drm/i915/intel_display.c
+@@ -6187,14 +6187,19 @@ static void intel_unpin_work_fn(struct w
+ {
+ struct intel_unpin_work *work =
+ container_of(__work, struct intel_unpin_work, work);
++ struct drm_device *dev = work->crtc->dev;
+
+- mutex_lock(&work->dev->struct_mutex);
++ mutex_lock(&dev->struct_mutex);
+ intel_unpin_fb_obj(work->old_fb_obj);
+ drm_gem_object_unreference(&work->pending_flip_obj->base);
+ drm_gem_object_unreference(&work->old_fb_obj->base);
+
+- intel_update_fbc(work->dev);
+- mutex_unlock(&work->dev->struct_mutex);
++ intel_update_fbc(dev);
++ mutex_unlock(&dev->struct_mutex);
++
++ BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0);
++ atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count);
++
+ kfree(work);
+ }
+
+@@ -6249,9 +6254,9 @@ static void do_intel_finish_page_flip(st
+
+ atomic_clear_mask(1 << intel_crtc->plane,
+ &obj->pending_flip.counter);
+-
+ wake_up(&dev_priv->pending_flip_queue);
+- schedule_work(&work->work);
++
++ queue_work(dev_priv->wq, &work->work);
+
+ trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj);
+ }
+@@ -6570,7 +6575,7 @@ static int intel_crtc_page_flip(struct d
+ return -ENOMEM;
+
+ work->event = event;
+- work->dev = crtc->dev;
++ work->crtc = crtc;
+ intel_fb = to_intel_framebuffer(crtc->fb);
+ work->old_fb_obj = intel_fb->obj;
+ INIT_WORK(&work->work, intel_unpin_work_fn);
+@@ -6595,6 +6600,9 @@ static int intel_crtc_page_flip(struct d
+ intel_fb = to_intel_framebuffer(fb);
+ obj = intel_fb->obj;
+
++ if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
++ flush_workqueue(dev_priv->wq);
++
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ goto cleanup;
+@@ -6613,6 +6621,7 @@ static int intel_crtc_page_flip(struct d
+ * the flip occurs and the object is no longer visible.
+ */
+ atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
++ atomic_inc(&intel_crtc->unpin_work_count);
+
+ ret = dev_priv->display.queue_flip(dev, crtc, fb, obj);
+ if (ret)
+@@ -6627,6 +6636,7 @@ static int intel_crtc_page_flip(struct d
+ return 0;
+
+ cleanup_pending:
++ atomic_dec(&intel_crtc->unpin_work_count);
+ atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);
+ drm_gem_object_unreference(&work->old_fb_obj->base);
+ drm_gem_object_unreference(&obj->base);
+--- a/drivers/gpu/drm/i915/intel_drv.h
++++ b/drivers/gpu/drm/i915/intel_drv.h
+@@ -198,6 +198,8 @@ struct intel_crtc {
+ struct intel_unpin_work *unpin_work;
+ int fdi_lanes;
+
++ atomic_t unpin_work_count;
++
+ /* Display surface base address adjustement for pageflips. Note that on
+ * gen4+ this only adjusts up to a tile, offsets within a tile are
+ * handled in the hw itself (with the TILEOFF register). */
+@@ -380,7 +382,7 @@ intel_get_crtc_for_plane(struct drm_devi
+
+ struct intel_unpin_work {
+ struct work_struct work;
+- struct drm_device *dev;
++ struct drm_crtc *crtc;
+ struct drm_i915_gem_object *old_fb_obj;
+ struct drm_i915_gem_object *pending_flip_obj;
+ struct drm_pending_vblank_event *event;
--- /dev/null
+From 93be8788e648817d62fda33e2998eb6ca6ebf3a3 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed, 2 Jan 2013 10:31:22 +0000
+Subject: drm/i915; Only increment the user-pin-count after successfully pinning the bo
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 93be8788e648817d62fda33e2998eb6ca6ebf3a3 upstream.
+
+As along the error path we do not correct the user pin-count for the
+failure, we may end up with userspace believing that it has a pinned
+object at offset 0 (when interrupted by a signal for example).
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_gem.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_gem.c
++++ b/drivers/gpu/drm/i915/i915_gem.c
+@@ -3511,14 +3511,15 @@ i915_gem_pin_ioctl(struct drm_device *de
+ goto out;
+ }
+
+- obj->user_pin_count++;
+- obj->pin_filp = file;
+- if (obj->user_pin_count == 1) {
++ if (obj->user_pin_count == 0) {
+ ret = i915_gem_object_pin(obj, args->alignment, true, false);
+ if (ret)
+ goto out;
+ }
+
++ obj->user_pin_count++;
++ obj->pin_filp = file;
++
+ /* XXX - flush the CPU caches for pinned objects
+ * as the X server doesn't manage domains yet
+ */
--- /dev/null
+From 93927ca52a55c23e0a6a305e7e9082e8411ac9fa Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Thu, 10 Jan 2013 18:03:00 +0100
+Subject: drm/i915: Revert shrinker changes from "Track unbound pages"
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+commit 93927ca52a55c23e0a6a305e7e9082e8411ac9fa upstream.
+
+This partially reverts
+
+commit 6c085a728cf000ac1865d66f8c9b52935558b328
+Author: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Mon Aug 20 11:40:46 2012 +0200
+
+ drm/i915: Track unbound pages
+
+Closer inspection of that patch revealed a bunch of unrelated changes
+in the shrinker:
+- The shrinker count is now in pages instead of objects.
+- For counting the shrinkable objects the old code only looked at the
+ inactive list, the new code looks at all bounds objects (including
+ pinned ones). That is obviously in addition to the new unbound list.
+- The shrinker cound is no longer scaled with
+ sysctl_vfs_cache_pressure. Note though that with the default tuning
+ value of vfs_cache_pressue = 100 this doesn't affect the shrinker
+ behaviour.
+- When actually shrinking objects, the old code first dropped
+ purgeable objects, then normal (inactive) objects. Only then did it,
+ in a last-ditch effort idle the gpu and evict everything. The new
+ code omits the intermediate step of evicting normal inactive
+ objects.
+
+Safe for the first change, which seems benign, and the shrinker count
+scaling, which is a bit a different story, the endresult of all these
+changes is that the shrinker is _much_ more likely to fall back to the
+last-ditch resort of idling the gpu and evicting everything. The old
+code could only do that if something else evicted lots of objects
+meanwhile (since without any other changes the nr_to_scan will be
+smaller than the object count).
+
+Reverting the vfs_cache_pressure behaviour itself is a bit bogus: Only
+dentry/inode object caches should scale their shrinker counts with
+vfs_cache_pressure. Originally I've had that change reverted, too. But
+Chris Wilson insisted that it's too bogus and shouldn't again see the
+light of day.
+
+Hence revert all these other changes and restore the old shrinker
+behaviour, with the minor adjustment that we now first scan the
+unbound list, then the inactive list for each object category
+(purgeable or normal).
+
+A similar patch has been tested by a few people affected by the gen4/5
+hangs which started to appear in 3.7, which some people bisected to
+the "drm/i915: Track unbound pages" commit. But just disabling the
+unbound logic alone didn't change things at all.
+
+Note that this patch doesn't fix the referenced bugs, it only hides
+the underlying bug(s) well enough to restore pre-3.7 behaviour. The
+key to achieve that is to massively reduce the likelyhood of going
+into a full gpu stall and evicting everything.
+
+v2: Reword commit message a bit, taking Chris Wilson's comment into
+account.
+
+v3: On Chris Wilson's insistency, do not reinstate the rather bogus
+vfs_cache_pressure change.
+
+Tested-by: Greg KH <gregkh@linuxfoundation.org>
+Tested-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+References: https://bugs.freedesktop.org/show_bug.cgi?id=55984
+References: https://bugs.freedesktop.org/show_bug.cgi?id=57122
+References: https://bugs.freedesktop.org/show_bug.cgi?id=56916
+References: https://bugs.freedesktop.org/show_bug.cgi?id=57136
+Cc: Chris Wilson <chris@chris-wilson.co.uk>
+Acked-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_gem.c
++++ b/drivers/gpu/drm/i915/i915_gem.c
+@@ -1718,7 +1718,8 @@ i915_gem_object_put_pages(struct drm_i91
+ }
+
+ static long
+-i915_gem_purge(struct drm_i915_private *dev_priv, long target)
++__i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
++ bool purgeable_only)
+ {
+ struct drm_i915_gem_object *obj, *next;
+ long count = 0;
+@@ -1726,7 +1727,7 @@ i915_gem_purge(struct drm_i915_private *
+ list_for_each_entry_safe(obj, next,
+ &dev_priv->mm.unbound_list,
+ gtt_list) {
+- if (i915_gem_object_is_purgeable(obj) &&
++ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
+ i915_gem_object_put_pages(obj) == 0) {
+ count += obj->base.size >> PAGE_SHIFT;
+ if (count >= target)
+@@ -1737,7 +1738,7 @@ i915_gem_purge(struct drm_i915_private *
+ list_for_each_entry_safe(obj, next,
+ &dev_priv->mm.inactive_list,
+ mm_list) {
+- if (i915_gem_object_is_purgeable(obj) &&
++ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
+ i915_gem_object_unbind(obj) == 0 &&
+ i915_gem_object_put_pages(obj) == 0) {
+ count += obj->base.size >> PAGE_SHIFT;
+@@ -1749,6 +1750,12 @@ i915_gem_purge(struct drm_i915_private *
+ return count;
+ }
+
++static long
++i915_gem_purge(struct drm_i915_private *dev_priv, long target)
++{
++ return __i915_gem_shrink(dev_priv, target, true);
++}
++
+ static void
+ i915_gem_shrink_all(struct drm_i915_private *dev_priv)
+ {
+@@ -4426,6 +4433,9 @@ i915_gem_inactive_shrink(struct shrinker
+ if (nr_to_scan) {
+ nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);
+ if (nr_to_scan > 0)
++ nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan,
++ false);
++ if (nr_to_scan > 0)
+ i915_gem_shrink_all(dev_priv);
+ }
+
+@@ -4433,7 +4443,7 @@ i915_gem_inactive_shrink(struct shrinker
+ list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
+ if (obj->pages_pin_count == 0)
+ cnt += obj->base.size >> PAGE_SHIFT;
+- list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
++ list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
+ if (obj->pin_count == 0 && obj->pages_pin_count == 0)
+ cnt += obj->base.size >> PAGE_SHIFT;
+
--- /dev/null
+From 901593f2bf221659a605bdc1dcb11376ea934163 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Wed, 19 Dec 2012 16:51:06 +0000
+Subject: drm: Only evict the blocks required to create the requested hole
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 901593f2bf221659a605bdc1dcb11376ea934163 upstream.
+
+Avoid clobbering adjacent blocks if they happen to expire earlier and
+amalgamate together to form the requested hole.
+
+In passing this fixes a regression from
+commit ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c
+Author: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Fri Feb 18 17:59:12 2011 +0100
+
+ drm: mm: track free areas implicitly
+
+which swaps the end address for size (with a potential overflow) and
+effectively causes the eviction code to clobber almost all earlier
+buffers above the evictee.
+
+v2: Check the original hole not the adjusted as the coloring may confuse
+us when later searching for the overlapping nodes. Also make sure that
+we do apply the range restriction and color adjustment in the same
+order for both scanning, searching and insertion.
+
+v3: Send the version that was actually tested.
+
+Note that this seems to be ducttape of decent quality ot paper over
+some of our unbind related gpu hangs reported since 3.7. It is not
+fully effective though, and certainly doesn't fix the underlying bug.
+
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+[danvet: Added note plus bugzilla link and tested-by.]
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984
+Tested-by: Norbert Preining <preining@logic.at>
+Acked-by: Dave Airlie <airlied@gmail.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 | 45 +++++++++++++++++----------------------------
+ include/drm/drm_mm.h | 2 +-
+ 2 files changed, 18 insertions(+), 29 deletions(-)
+
+--- a/drivers/gpu/drm/drm_mm.c
++++ b/drivers/gpu/drm/drm_mm.c
+@@ -213,11 +213,13 @@ static void drm_mm_insert_helper_range(s
+
+ BUG_ON(!hole_node->hole_follows || node->allocated);
+
+- if (mm->color_adjust)
+- mm->color_adjust(hole_node, color, &adj_start, &adj_end);
+-
+ if (adj_start < start)
+ adj_start = start;
++ if (adj_end > end)
++ adj_end = end;
++
++ if (mm->color_adjust)
++ mm->color_adjust(hole_node, color, &adj_start, &adj_end);
+
+ if (alignment) {
+ unsigned tmp = adj_start % alignment;
+@@ -489,7 +491,7 @@ void drm_mm_init_scan(struct drm_mm *mm,
+ mm->scan_size = size;
+ mm->scanned_blocks = 0;
+ mm->scan_hit_start = 0;
+- mm->scan_hit_size = 0;
++ mm->scan_hit_end = 0;
+ mm->scan_check_range = 0;
+ mm->prev_scanned_node = NULL;
+ }
+@@ -516,7 +518,7 @@ void drm_mm_init_scan_with_range(struct
+ mm->scan_size = size;
+ mm->scanned_blocks = 0;
+ mm->scan_hit_start = 0;
+- mm->scan_hit_size = 0;
++ mm->scan_hit_end = 0;
+ mm->scan_start = start;
+ mm->scan_end = end;
+ mm->scan_check_range = 1;
+@@ -535,8 +537,7 @@ int drm_mm_scan_add_block(struct drm_mm_
+ struct drm_mm *mm = node->mm;
+ struct drm_mm_node *prev_node;
+ unsigned long hole_start, hole_end;
+- unsigned long adj_start;
+- unsigned long adj_end;
++ unsigned long adj_start, adj_end;
+
+ mm->scanned_blocks++;
+
+@@ -553,14 +554,8 @@ int drm_mm_scan_add_block(struct drm_mm_
+ node->node_list.next = &mm->prev_scanned_node->node_list;
+ mm->prev_scanned_node = node;
+
+- hole_start = drm_mm_hole_node_start(prev_node);
+- hole_end = drm_mm_hole_node_end(prev_node);
+-
+- adj_start = hole_start;
+- adj_end = hole_end;
+-
+- if (mm->color_adjust)
+- mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end);
++ adj_start = hole_start = drm_mm_hole_node_start(prev_node);
++ adj_end = hole_end = drm_mm_hole_node_end(prev_node);
+
+ if (mm->scan_check_range) {
+ if (adj_start < mm->scan_start)
+@@ -569,11 +564,14 @@ int drm_mm_scan_add_block(struct drm_mm_
+ adj_end = mm->scan_end;
+ }
+
++ if (mm->color_adjust)
++ mm->color_adjust(prev_node, mm->scan_color,
++ &adj_start, &adj_end);
++
+ if (check_free_hole(adj_start, adj_end,
+ mm->scan_size, mm->scan_alignment)) {
+ mm->scan_hit_start = hole_start;
+- mm->scan_hit_size = hole_end;
+-
++ mm->scan_hit_end = hole_end;
+ return 1;
+ }
+
+@@ -609,19 +607,10 @@ int drm_mm_scan_remove_block(struct drm_
+ node_list);
+
+ prev_node->hole_follows = node->scanned_preceeds_hole;
+- INIT_LIST_HEAD(&node->node_list);
+ list_add(&node->node_list, &prev_node->node_list);
+
+- /* Only need to check for containement because start&size for the
+- * complete resulting free block (not just the desired part) is
+- * stored. */
+- if (node->start >= mm->scan_hit_start &&
+- node->start + node->size
+- <= mm->scan_hit_start + mm->scan_hit_size) {
+- return 1;
+- }
+-
+- return 0;
++ return (drm_mm_hole_node_end(node) > mm->scan_hit_start &&
++ node->start < mm->scan_hit_end);
+ }
+ EXPORT_SYMBOL(drm_mm_scan_remove_block);
+
+--- a/include/drm/drm_mm.h
++++ b/include/drm/drm_mm.h
+@@ -70,7 +70,7 @@ struct drm_mm {
+ unsigned long scan_color;
+ unsigned long scan_size;
+ unsigned long scan_hit_start;
+- unsigned scan_hit_size;
++ unsigned long scan_hit_end;
+ unsigned scanned_blocks;
+ unsigned long scan_start;
+ unsigned long scan_end;
--- /dev/null
+From be8a42ae60addd8b6092535c11b42d099d6470ec Mon Sep 17 00:00:00 2001
+From: Seung-Woo Kim <sw0312.kim@samsung.com>
+Date: Thu, 27 Sep 2012 15:30:06 +0900
+Subject: drm/prime: drop reference on imported dma-buf come from gem
+
+From: Seung-Woo Kim <sw0312.kim@samsung.com>
+
+commit be8a42ae60addd8b6092535c11b42d099d6470ec upstream.
+
+Increasing ref counts of both dma-buf and gem for imported dma-buf come from gem
+makes memory leak. release function of dma-buf cannot be called because f_count
+of dma-buf increased by importing gem and gem ref count cannot be decrease
+because of exported dma-buf.
+
+So I add dma_buf_put() for imported gem come from its own gem into each drivers
+having prime_import and prime_export capabilities. With this, only gem ref
+count is increased if importing gem exported from gem of same driver.
+
+Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
+Signed-off-by: Kyungmin.park <kyungmin.park@samsung.com>
+Cc: Inki Dae <inki.dae@samsung.com>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Rob Clark <rob.clark@linaro.org>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 5 +++++
+ drivers/gpu/drm/i915/i915_gem_dmabuf.c | 5 +++++
+ drivers/gpu/drm/nouveau/nouveau_prime.c | 1 +
+ drivers/gpu/drm/radeon/radeon_prime.c | 1 +
+ drivers/staging/omapdrm/omap_gem_dmabuf.c | 5 +++++
+ 5 files changed, 17 insertions(+)
+
+--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+@@ -210,7 +210,12 @@ struct drm_gem_object *exynos_dmabuf_pri
+
+ /* is it from our device? */
+ if (obj->dev == drm_dev) {
++ /*
++ * Importing dmabuf exported from out own gem increases
++ * refcount on gem itself instead of f_count of dmabuf.
++ */
+ drm_gem_object_reference(obj);
++ dma_buf_put(dma_buf);
+ return obj;
+ }
+ }
+--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+@@ -266,7 +266,12 @@ struct drm_gem_object *i915_gem_prime_im
+ obj = dma_buf->priv;
+ /* is it from our device? */
+ if (obj->base.dev == dev) {
++ /*
++ * Importing dmabuf exported from out own gem increases
++ * refcount on gem itself instead of f_count of dmabuf.
++ */
+ drm_gem_object_reference(&obj->base);
++ dma_buf_put(dma_buf);
+ return &obj->base;
+ }
+ }
+--- a/drivers/gpu/drm/nouveau/nouveau_prime.c
++++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
+@@ -197,6 +197,7 @@ struct drm_gem_object *nouveau_gem_prime
+ if (nvbo->gem) {
+ if (nvbo->gem->dev == dev) {
+ drm_gem_object_reference(nvbo->gem);
++ dma_buf_put(dma_buf);
+ return nvbo->gem;
+ }
+ }
+--- a/drivers/gpu/drm/radeon/radeon_prime.c
++++ b/drivers/gpu/drm/radeon/radeon_prime.c
+@@ -194,6 +194,7 @@ struct drm_gem_object *radeon_gem_prime_
+ bo = dma_buf->priv;
+ if (bo->gem_base.dev == dev) {
+ drm_gem_object_reference(&bo->gem_base);
++ dma_buf_put(dma_buf);
+ return &bo->gem_base;
+ }
+ }
+--- a/drivers/staging/omapdrm/omap_gem_dmabuf.c
++++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c
+@@ -207,7 +207,12 @@ struct drm_gem_object * omap_gem_prime_i
+ obj = buffer->priv;
+ /* is it from our device? */
+ if (obj->dev == dev) {
++ /*
++ * Importing dmabuf exported from out own gem increases
++ * refcount on gem itself instead of f_count of dmabuf.
++ */
+ drm_gem_object_reference(obj);
++ dma_buf_put(buffer);
+ return obj;
+ }
+ }
--- /dev/null
+From 8fb74b9fb2b182d54beee592350d9ea1f325917a Mon Sep 17 00:00:00 2001
+From: Mel Gorman <mgorman@suse.de>
+Date: Fri, 11 Jan 2013 14:32:16 -0800
+Subject: mm: compaction: partially revert capture of suitable high-order page
+
+From: Mel Gorman <mgorman@suse.de>
+
+commit 8fb74b9fb2b182d54beee592350d9ea1f325917a upstream.
+
+Eric Wong reported on 3.7 and 3.8-rc2 that ppoll() got stuck when
+waiting for POLLIN on a local TCP socket. It was easier to trigger if
+there was disk IO and dirty pages at the same time and he bisected it to
+commit 1fb3f8ca0e92 ("mm: compaction: capture a suitable high-order page
+immediately when it is made available").
+
+The intention of that patch was to improve high-order allocations under
+memory pressure after changes made to reclaim in 3.6 drastically hurt
+THP allocations but the approach was flawed. For Eric, the problem was
+that page->pfmemalloc was not being cleared for captured pages leading
+to a poor interaction with swap-over-NFS support causing the packets to
+be dropped. However, I identified a few more problems with the patch
+including the fact that it can increase contention on zone->lock in some
+cases which could result in async direct compaction being aborted early.
+
+In retrospect the capture patch took the wrong approach. What it should
+have done is mark the pageblock being migrated as MIGRATE_ISOLATE if it
+was allocating for THP and avoided races that way. While the patch was
+showing to improve allocation success rates at the time, the benefit is
+marginal given the relative complexity and it should be revisited from
+scratch in the context of the other reclaim-related changes that have
+taken place since the patch was first written and tested. This patch
+partially reverts commit 1fb3f8ca0e92 ("mm: compaction: capture a
+suitable high-order page immediately when it is made available").
+
+Reported-and-tested-by: Eric Wong <normalperson@yhbt.net>
+Tested-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Cc: David Miller <davem@davemloft.net>
+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>
+
+---
+ include/linux/compaction.h | 4 -
+ include/linux/mm.h | 1
+ mm/compaction.c | 92 ++++++---------------------------------------
+ mm/internal.h | 1
+ mm/page_alloc.c | 35 +++--------------
+ 5 files changed, 23 insertions(+), 110 deletions(-)
+
+--- a/include/linux/compaction.h
++++ b/include/linux/compaction.h
+@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct
+ extern int fragmentation_index(struct zone *zone, unsigned int order);
+ extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
+ int order, gfp_t gfp_mask, nodemask_t *mask,
+- bool sync, bool *contended, struct page **page);
++ bool sync, bool *contended);
+ extern int compact_pgdat(pg_data_t *pgdat, int order);
+ extern void reset_isolation_suitable(pg_data_t *pgdat);
+ extern unsigned long compaction_suitable(struct zone *zone, int order);
+@@ -75,7 +75,7 @@ static inline bool compaction_restarting
+ #else
+ static inline unsigned long try_to_compact_pages(struct zonelist *zonelist,
+ int order, gfp_t gfp_mask, nodemask_t *nodemask,
+- bool sync, bool *contended, struct page **page)
++ bool sync, bool *contended)
+ {
+ return COMPACT_CONTINUE;
+ }
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pa
+
+ void split_page(struct page *page, unsigned int order);
+ int split_free_page(struct page *page);
+-int capture_free_page(struct page *page, int alloc_order, int migratetype);
+
+ /*
+ * Compound pages have a destructor function. Provide a
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -214,60 +214,6 @@ static bool suitable_migration_target(st
+ return false;
+ }
+
+-static void compact_capture_page(struct compact_control *cc)
+-{
+- unsigned long flags;
+- int mtype, mtype_low, mtype_high;
+-
+- if (!cc->page || *cc->page)
+- return;
+-
+- /*
+- * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
+- * regardless of the migratetype of the freelist is is captured from.
+- * This is fine because the order for a high-order MIGRATE_MOVABLE
+- * allocation is typically at least a pageblock size and overall
+- * fragmentation is not impaired. Other allocation types must
+- * capture pages from their own migratelist because otherwise they
+- * could pollute other pageblocks like MIGRATE_MOVABLE with
+- * difficult to move pages and making fragmentation worse overall.
+- */
+- if (cc->migratetype == MIGRATE_MOVABLE) {
+- mtype_low = 0;
+- mtype_high = MIGRATE_PCPTYPES;
+- } else {
+- mtype_low = cc->migratetype;
+- mtype_high = cc->migratetype + 1;
+- }
+-
+- /* Speculatively examine the free lists without zone lock */
+- for (mtype = mtype_low; mtype < mtype_high; mtype++) {
+- int order;
+- for (order = cc->order; order < MAX_ORDER; order++) {
+- struct page *page;
+- struct free_area *area;
+- area = &(cc->zone->free_area[order]);
+- if (list_empty(&area->free_list[mtype]))
+- continue;
+-
+- /* Take the lock and attempt capture of the page */
+- if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
+- return;
+- if (!list_empty(&area->free_list[mtype])) {
+- page = list_entry(area->free_list[mtype].next,
+- struct page, lru);
+- if (capture_free_page(page, cc->order, mtype)) {
+- spin_unlock_irqrestore(&cc->zone->lock,
+- flags);
+- *cc->page = page;
+- return;
+- }
+- }
+- spin_unlock_irqrestore(&cc->zone->lock, flags);
+- }
+- }
+-}
+-
+ /*
+ * Isolate free pages onto a private freelist. Caller must hold zone->lock.
+ * If @strict is true, will abort returning 0 on any invalid PFNs or non-free
+@@ -831,6 +777,7 @@ static isolate_migrate_t isolate_migrate
+ static int compact_finished(struct zone *zone,
+ struct compact_control *cc)
+ {
++ unsigned int order;
+ unsigned long watermark;
+
+ if (fatal_signal_pending(current))
+@@ -865,22 +812,16 @@ static int compact_finished(struct zone
+ return COMPACT_CONTINUE;
+
+ /* Direct compactor: Is a suitable page free? */
+- if (cc->page) {
+- /* Was a suitable page captured? */
+- if (*cc->page)
++ for (order = cc->order; order < MAX_ORDER; order++) {
++ struct free_area *area = &zone->free_area[order];
++
++ /* Job done if page is free of the right migratetype */
++ if (!list_empty(&area->free_list[cc->migratetype]))
++ return COMPACT_PARTIAL;
++
++ /* Job done if allocation would set block type */
++ if (cc->order >= pageblock_order && area->nr_free)
+ return COMPACT_PARTIAL;
+- } else {
+- unsigned int order;
+- for (order = cc->order; order < MAX_ORDER; order++) {
+- struct free_area *area = &zone->free_area[cc->order];
+- /* Job done if page is free of the right migratetype */
+- if (!list_empty(&area->free_list[cc->migratetype]))
+- return COMPACT_PARTIAL;
+-
+- /* Job done if allocation would set block type */
+- if (cc->order >= pageblock_order && area->nr_free)
+- return COMPACT_PARTIAL;
+- }
+ }
+
+ return COMPACT_CONTINUE;
+@@ -1018,9 +959,6 @@ static int compact_zone(struct zone *zon
+ goto out;
+ }
+ }
+-
+- /* Capture a page now if it is a suitable size */
+- compact_capture_page(cc);
+ }
+
+ out:
+@@ -1033,8 +971,7 @@ out:
+
+ static unsigned long compact_zone_order(struct zone *zone,
+ int order, gfp_t gfp_mask,
+- bool sync, bool *contended,
+- struct page **page)
++ bool sync, bool *contended)
+ {
+ unsigned long ret;
+ struct compact_control cc = {
+@@ -1044,7 +981,6 @@ static unsigned long compact_zone_order(
+ .migratetype = allocflags_to_migratetype(gfp_mask),
+ .zone = zone,
+ .sync = sync,
+- .page = page,
+ };
+ INIT_LIST_HEAD(&cc.freepages);
+ INIT_LIST_HEAD(&cc.migratepages);
+@@ -1074,7 +1010,7 @@ int sysctl_extfrag_threshold = 500;
+ */
+ unsigned long try_to_compact_pages(struct zonelist *zonelist,
+ int order, gfp_t gfp_mask, nodemask_t *nodemask,
+- bool sync, bool *contended, struct page **page)
++ bool sync, bool *contended)
+ {
+ enum zone_type high_zoneidx = gfp_zone(gfp_mask);
+ int may_enter_fs = gfp_mask & __GFP_FS;
+@@ -1100,7 +1036,7 @@ unsigned long try_to_compact_pages(struc
+ int status;
+
+ status = compact_zone_order(zone, order, gfp_mask, sync,
+- contended, page);
++ contended);
+ rc = max(status, rc);
+
+ /* If a normal allocation would succeed, stop compacting */
+@@ -1156,7 +1092,6 @@ int compact_pgdat(pg_data_t *pgdat, int
+ struct compact_control cc = {
+ .order = order,
+ .sync = false,
+- .page = NULL,
+ };
+
+ return __compact_pgdat(pgdat, &cc);
+@@ -1167,7 +1102,6 @@ static int compact_node(int nid)
+ struct compact_control cc = {
+ .order = -1,
+ .sync = true,
+- .page = NULL,
+ };
+
+ return __compact_pgdat(NODE_DATA(nid), &cc);
+--- a/mm/internal.h
++++ b/mm/internal.h
+@@ -130,7 +130,6 @@ struct compact_control {
+ int migratetype; /* MOVABLE, RECLAIMABLE etc */
+ struct zone *zone;
+ bool contended; /* True if a lock was contended */
+- struct page **page; /* Page captured of requested size */
+ };
+
+ unsigned long
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1376,14 +1376,8 @@ void split_page(struct page *page, unsig
+ set_page_refcounted(page + i);
+ }
+
+-/*
+- * Similar to the split_page family of functions except that the page
+- * required at the given order and being isolated now to prevent races
+- * with parallel allocators
+- */
+-int capture_free_page(struct page *page, int alloc_order, int migratetype)
++static int __isolate_free_page(struct page *page, unsigned int order)
+ {
+- unsigned int order;
+ unsigned long watermark;
+ struct zone *zone;
+ int mt;
+@@ -1391,7 +1385,6 @@ int capture_free_page(struct page *page,
+ BUG_ON(!PageBuddy(page));
+
+ zone = page_zone(page);
+- order = page_order(page);
+
+ /* Obey watermarks as if the page was being allocated */
+ watermark = low_wmark_pages(zone) + (1 << order);
+@@ -1405,13 +1398,9 @@ int capture_free_page(struct page *page,
+
+ mt = get_pageblock_migratetype(page);
+ if (unlikely(mt != MIGRATE_ISOLATE))
+- __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
+-
+- if (alloc_order != order)
+- expand(zone, page, alloc_order, order,
+- &zone->free_area[order], migratetype);
++ __mod_zone_freepage_state(zone, -(1UL << order), mt);
+
+- /* Set the pageblock if the captured page is at least a pageblock */
++ /* Set the pageblock if the isolated page is at least a pageblock */
+ if (order >= pageblock_order - 1) {
+ struct page *endpage = page + (1 << order) - 1;
+ for (; page < endpage; page += pageblock_nr_pages) {
+@@ -1422,7 +1411,7 @@ int capture_free_page(struct page *page,
+ }
+ }
+
+- return 1UL << alloc_order;
++ return 1UL << order;
+ }
+
+ /*
+@@ -1440,10 +1429,9 @@ int split_free_page(struct page *page)
+ unsigned int order;
+ int nr_pages;
+
+- BUG_ON(!PageBuddy(page));
+ order = page_order(page);
+
+- nr_pages = capture_free_page(page, order, 0);
++ nr_pages = __isolate_free_page(page, order);
+ if (!nr_pages)
+ return 0;
+
+@@ -2148,8 +2136,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m
+ bool *contended_compaction, bool *deferred_compaction,
+ unsigned long *did_some_progress)
+ {
+- struct page *page = NULL;
+-
+ if (!order)
+ return NULL;
+
+@@ -2161,16 +2147,12 @@ __alloc_pages_direct_compact(gfp_t gfp_m
+ current->flags |= PF_MEMALLOC;
+ *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask,
+ nodemask, sync_migration,
+- contended_compaction, &page);
++ contended_compaction);
+ current->flags &= ~PF_MEMALLOC;
+
+- /* If compaction captured a page, prep and use it */
+- if (page) {
+- prep_new_page(page, order, gfp_mask);
+- goto got_page;
+- }
+-
+ if (*did_some_progress != COMPACT_SKIPPED) {
++ struct page *page;
++
+ /* Page migration frees to the PCP lists but we want merging */
+ drain_pages(get_cpu());
+ put_cpu();
+@@ -2180,7 +2162,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m
+ alloc_flags & ~ALLOC_NO_WATERMARKS,
+ preferred_zone, migratetype);
+ if (page) {
+-got_page:
+ preferred_zone->compact_blockskip_flush = false;
+ preferred_zone->compact_considered = 0;
+ preferred_zone->compact_defer_shift = 0;
drm-radeon-properly-handle-ddc-probe-for-dp-bridges.patch
drm-nouveau-fix-init-with-agpgart-uninorth.patch
drm-i915-make-the-panel-fitter-work-on-pipes-b-and-c-on-ivb.patch
+mm-compaction-partially-revert-capture-of-suitable-high-order-page.patch
+drm-i915-close-race-between-processing-unpin-task-and-queueing-the-flip.patch
+drm-i915-flush-outstanding-unpin-tasks-before-pageflipping.patch
+drm-i915-don-t-disable-disconnected-outputs.patch
+drm-i915-fix-flags-in-dma-buf-exporting.patch
+drm-prime-drop-reference-on-imported-dma-buf-come-from-gem.patch
+drm-only-evict-the-blocks-required-to-create-the-requested-hole.patch
+drm-i915-only-increment-the-user-pin-count-after-successfully-pinning-the-bo.patch
+drm-i915-revert-shrinker-changes-from-track-unbound-pages.patch