@@ -46,6 +46,7 @@
#include <linux/vga_switcheroo.h>
#include <linux/slab.h>
#include <acpi/video.h>
+#include "i915_scheduler.h"
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/oom.h>
@@ -1250,6 +1251,8 @@ void i915_driver_lastclose(struct drm_device *dev)
void i915_driver_preclose(struct drm_device *dev, struct drm_file *file)
{
+ i915_scheduler_closefile(dev, file);
+
mutex_lock(&dev->struct_mutex);
i915_gem_context_close(dev, file);
i915_gem_release(dev, file);
@@ -745,3 +745,69 @@ static int i915_scheduler_remove_dependent(struct i915_scheduler *scheduler,
return 0;
}
+
+int i915_scheduler_closefile(struct drm_device *dev, struct drm_file *file)
+{
+ struct i915_scheduler_queue_entry *node;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_scheduler *scheduler = dev_priv->scheduler;
+ struct drm_i915_gem_request *req;
+ struct intel_engine_cs *ring;
+ int i, ret;
+ unsigned long flags;
+ bool found;
+
+ if (!scheduler)
+ return 0;
+
+ for_each_ring(ring, dev_priv, i) {
+ do {
+ spin_lock_irqsave(&scheduler->lock, flags);
+
+ found = false;
+ list_for_each_entry(node, &scheduler->node_queue[ring->id], link) {
+ if (I915_SQS_IS_COMPLETE(node))
+ continue;
+
+ if (node->params.file != file)
+ continue;
+
+ found = true;
+ req = node->params.request;
+ i915_gem_request_reference(req);
+ break;
+ }
+
+ spin_unlock_irqrestore(&scheduler->lock, flags);
+
+ if (found) {
+ do {
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_wait_request(req);
+ mutex_unlock(&dev->struct_mutex);
+ if (ret == -EAGAIN)
+ msleep(20);
+ } while (ret == -EAGAIN);
+
+ mutex_lock(&dev->struct_mutex);
+ i915_gem_request_unreference(req);
+ mutex_unlock(&dev->struct_mutex);
+ }
+ } while (found);
+ }
+
+ spin_lock_irqsave(&scheduler->lock, flags);
+ for_each_ring(ring, dev_priv, i) {
+ list_for_each_entry(node, &scheduler->node_queue[ring->id], link) {
+ if (node->params.file != file)
+ continue;
+
+ WARN_ON(!I915_SQS_IS_COMPLETE(node));
+
+ node->params.file = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&scheduler->lock, flags);
+
+ return 0;
+}
@@ -85,6 +85,8 @@ enum {
bool i915_scheduler_is_enabled(struct drm_device *dev);
int i915_scheduler_init(struct drm_device *dev);
+int i915_scheduler_closefile(struct drm_device *dev,
+ struct drm_file *file);
int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry *qe);
bool i915_scheduler_notify_request(struct drm_i915_gem_request *req);