[PATCH v4 11/38] drm/i915: Added scheduler hook when closing DRM file handles

John.C.Harrison
2016-01-11T18:43:21Z

The scheduler decouples the submission of batch buffers to the driver
with submission of batch buffers to the hardware. Thus it is possible
for an application to close its DRM file handle while there is still
work outstanding. That means the scheduler needs to know about file
close events so it can remove the file pointer from such orphaned
batch buffers and not attempt to dereference it later.

v3: Updated to not wait for outstanding work to complete but merely
remove the file handle reference. The wait was getting excessively
complicated with inter-ring dependencies, pre-emption, and other such
issues.

v4: Changed some white space to keep the style checker happy.

For: VIZ-1587
Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
---
drivers/gpu/drm/i915/i915_dma.c | 3 +++
drivers/gpu/drm/i915/i915_scheduler.c | 35 +++++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/i915_scheduler.h | 2 ++
3 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 731cf31..c2f9c03 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -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);
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index fc48955..26cd088 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -802,3 +802,38 @@ 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 intel_engine_cs *ring;
+ int i;
+ unsigned long flags;
+
+ if (!scheduler)
+ return 0;
+
+ 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;
+
+ if (!I915_SQS_IS_COMPLETE(node))
+ DRM_DEBUG_DRIVER("Closing file handle with outstanding work: %d:%d/%d on %s\n",
+ node->params.request->uniq,
+ node->params.request->seqno,
+ node->status,
+ ring->name);
+
+ node->params.file = NULL;
+ }
+ }
+
+ spin_unlock_irqrestore(&scheduler->lock, flags);
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h b/drivers/gpu/drm/i915/i915_scheduler.h
index 2d50d83..02ac6f2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -86,6 +86,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);