#include <linux/dma-buf.h>
 #include <linux/vmalloc.h>
 
+#include "gt/intel_gt_requests.h"
+
 #include "i915_trace.h"
 
 static bool swap_available(void)
        unsigned long count = 0;
        unsigned long scanned = 0;
 
-       /*
-        * When shrinking the active list, we should also consider active
-        * contexts. Active contexts are pinned until they are retired, and
-        * so can not be simply unbound to retire and unpin their pages. To
-        * shrink the contexts, we must wait until the gpu is idle and
-        * completed its switch to the kernel context. In short, we do
-        * not have a good mechanism for idling a specific context.
-        */
-
        trace_i915_gem_shrink(i915, target, shrink);
 
        /*
                        shrink &= ~I915_SHRINK_BOUND;
        }
 
+       /*
+        * When shrinking the active list, we should also consider active
+        * contexts. Active contexts are pinned until they are retired, and
+        * so can not be simply unbound to retire and unpin their pages. To
+        * shrink the contexts, we must wait until the gpu is idle and
+        * completed its switch to the kernel context. In short, we do
+        * not have a good mechanism for idling a specific context, but
+        * what we can do is give them a kick so that we do not keep idle
+        * contexts around longer than is necessary.
+        */
+       if (shrink & I915_SHRINK_ACTIVE)
+               /* Retire requests to unpin all idle contexts */
+               intel_gt_retire_requests(&i915->gt);
+
        /*
         * As we may completely rewrite the (un)bound list whilst unbinding
         * (due to retiring requests) we have to strictly process only
 
        return !list_empty(&engine->kernel_context->timeline->requests);
 }
 
-static bool flush_submission(struct intel_gt *gt)
+static bool flush_submission(struct intel_gt *gt, long timeout)
 {
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
        bool active = false;
 
+       if (!timeout)
+               return false;
+
        if (!intel_gt_pm_is_awake(gt))
                return false;
 
        if (unlikely(timeout < 0))
                timeout = -timeout, interruptible = false;
 
-       flush_submission(gt); /* kick the ksoftirqd tasklets */
+       flush_submission(gt, timeout); /* kick the ksoftirqd tasklets */
        spin_lock(&timelines->lock);
        list_for_each_entry_safe(tl, tn, &timelines->active_list, link) {
                if (!mutex_trylock(&tl->mutex)) {
        list_for_each_entry_safe(tl, tn, &free, link)
                __intel_timeline_free(&tl->kref);
 
-       if (flush_submission(gt)) /* Wait, there's more! */
+       if (flush_submission(gt, timeout)) /* Wait, there's more! */
                active_count++;
 
        return active_count ? timeout : 0;