[PATCH 1/2] drm/xe: add ref count to xe_file

Moti Haimovski mhaimovski at habana.ai
Tue Feb 6 14:18:19 UTC 2024


Added reference counters (kref) to for managing the xe_file and
exported xe_file open and close routines.

Xe-file is a structure which is a part of the context created when
a user opens the device.
The xef serves as a "database" for all the resources the user allocates
and uses (directly and indirectly). Since this is a per-user resource
then the initial design was for a single user controlling it.
Latest modifications to the driver broke the above the assumption
since user context may now be accessed also by the driver. This lead
to races and subsequent crashes when a user context was closed while
still in use by the driver.
The use of kref added by this commit solves this issue.
i
Exporting the xe_file open and close routines is done for supporting
the creation of internal contexts implemented in another commit.

Signed-off-by: Moti Haimovski <mhaimovski at habana.ai>
---
 drivers/gpu/drm/xe/xe_device.c       | 51 ++++++++++++++++++++++++----
 drivers/gpu/drm/xe/xe_device.h       |  6 ++++
 drivers/gpu/drm/xe/xe_device_types.h |  3 ++
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 5b84d73055202..e75bca060f473 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -51,9 +51,8 @@ struct lockdep_map xe_device_mem_access_lockdep_map = {
 };
 #endif
 
-static int xe_file_open(struct drm_device *dev, struct drm_file *file)
+int xe_file_open(struct xe_device *xe, struct drm_file *file)
 {
-	struct xe_device *xe = to_xe_device(dev);
 	struct xe_drm_client *client;
 	struct xe_file *xef;
 	int ret = -ENOMEM;
@@ -82,17 +81,27 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
 	xe->clients.count++;
 	spin_unlock(&xe->clients.lock);
 
+	kref_init(&xef->refcount);
+
 	file->driver_priv = xef;
 	return 0;
 }
 
+
+static int __xe_file_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+
+	return xe_file_open(xe, file);
+}
+
 static void device_kill_persistent_exec_queues(struct xe_device *xe,
 					       struct xe_file *xef);
 
-static void xe_file_close(struct drm_device *dev, struct drm_file *file)
+static void xe_file_terminate(struct kref *ref)
 {
-	struct xe_device *xe = to_xe_device(dev);
-	struct xe_file *xef = file->driver_priv;
+	struct xe_file *xef = container_of(ref, struct xe_file, refcount);
+	struct xe_device *xe = xef->xe;
 	struct xe_vm *vm;
 	struct xe_exec_queue *q;
 	unsigned long idx;
@@ -122,6 +131,33 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
 	kfree(xef);
 }
 
+struct xe_file *xe_file_get(struct xe_file *xef)
+{
+	if (likely(xef && kref_get_unless_zero(&xef->refcount)))
+		return xef;
+
+	return NULL;
+}
+
+void xe_file_put(struct xe_file *xef)
+{
+	kref_put(&xef->refcount, xe_file_terminate);
+}
+
+void xe_file_close(struct xe_device *xe, struct drm_file *file)
+{
+	struct xe_file *xef = file->driver_priv;
+
+	xe_file_put(xef);
+}
+
+static void __xe_file_close(struct drm_device *dev, struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+
+	xe_file_close(xe, file);
+}
+
 static const struct drm_ioctl_desc xe_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(XE_DEVICE_QUERY, xe_query_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_GEM_CREATE, xe_gem_create_ioctl, DRM_RENDER_ALLOW),
@@ -171,8 +207,9 @@ static struct drm_driver driver = {
 	    DRIVER_GEM |
 	    DRIVER_RENDER | DRIVER_SYNCOBJ |
 	    DRIVER_SYNCOBJ_TIMELINE | DRIVER_GEM_GPUVA,
-	.open = xe_file_open,
-	.postclose = xe_file_close,
+
+	.open = __xe_file_open,
+	.postclose = __xe_file_close,
 
 	.gem_prime_import = xe_gem_prime_import,
 
diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
index 462f59e902b12..fb89b83c3d850 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -48,6 +48,12 @@ void xe_device_remove_persistent_exec_queues(struct xe_device *xe,
 
 void xe_device_wmb(struct xe_device *xe);
 
+int xe_file_open(struct xe_device *xe, struct drm_file *file);
+void xe_file_close(struct xe_device *xe, struct drm_file *file);
+
+struct xe_file *xe_file_get(struct xe_file *xef);
+void xe_file_put(struct xe_file *xef);
+
 static inline struct xe_file *to_xe_file(const struct drm_file *file)
 {
 	return file->driver_priv;
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index eb2b806a1d233..72e6958f15ac2 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -550,6 +550,9 @@ struct xe_file {
 	/** @drm: base DRM file */
 	struct drm_file *drm;
 
+	/** @refcount: xef usage count  */
+	struct kref refcount;
+
 	/** @vm: VM state for file */
 	struct {
 		/** @vm.xe: xarray to store VMs */
-- 
2.34.1



More information about the Intel-xe mailing list