The xe driver was using the drm_exec retry pointer directly to
restart the locking loop after out-of-memory errors. This is
relying on undocumented behaviour.

Instead add a drm_exec_retry() macro that can be used in this
situation, and that also warns if the struct drm_exec is
not newly (re-)initialized.

Use that macro in xe.

v2:
- Only allow if the drm_exec context is newly initialized.
  (Christian)

Signed-off-by: Thomas Hellström <[email protected]>
---
 drivers/gpu/drm/drm_exec.c         |  3 ---
 drivers/gpu/drm/xe/xe_validation.h |  2 +-
 include/drm/drm_exec.h             | 19 +++++++++++++++++++
 3 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c
index 746210f3f6c2..7988f5e7d56a 100644
--- a/drivers/gpu/drm/drm_exec.c
+++ b/drivers/gpu/drm/drm_exec.c
@@ -48,9 +48,6 @@
  * See struct dma_exec for more details.
  */
 
-/* Dummy value used to initially enter the retry loop */
-#define DRM_EXEC_DUMMY ((void *)~0)
-
 /* Unlock all objects and drop references */
 static void drm_exec_unlock_all(struct drm_exec *exec)
 {
diff --git a/drivers/gpu/drm/xe/xe_validation.h 
b/drivers/gpu/drm/xe/xe_validation.h
index a30e732c4d51..4cd955ce6cd2 100644
--- a/drivers/gpu/drm/xe/xe_validation.h
+++ b/drivers/gpu/drm/xe/xe_validation.h
@@ -146,7 +146,7 @@ bool xe_validation_should_retry(struct xe_validation_ctx 
*ctx, int *ret);
 #define xe_validation_retry_on_oom(_ctx, _ret)                         \
        do {                                                            \
                if (xe_validation_should_retry(_ctx, _ret))             \
-                       goto *__drm_exec_retry_ptr;                     \
+                       drm_exec_retry((_ctx)->exec);                   \
        } while (0)
 
 /**
diff --git a/include/drm/drm_exec.h b/include/drm/drm_exec.h
index 18f84faabbb9..99c7e1bb3c5b 100644
--- a/include/drm/drm_exec.h
+++ b/include/drm/drm_exec.h
@@ -9,6 +9,12 @@
 #define DRM_EXEC_INTERRUPTIBLE_WAIT    BIT(0)
 #define DRM_EXEC_IGNORE_DUPLICATES     BIT(1)
 
+/*
+ * Dummy value used to initially enter the retry loop.
+ * internal use only.
+ */
+#define DRM_EXEC_DUMMY ((void *)~0)
+
 struct drm_gem_object;
 
 /**
@@ -142,6 +148,19 @@ static inline bool drm_exec_is_contended(struct drm_exec 
*exec)
        return !!exec->contended;
 }
 
+/**
+ * drm_exec_retry() - Unconditionally restart the loop to grab all locks.
+ * @exec: drm_exec object
+ *
+ * Unconditionally retry the loop to lock all objects. For consistency,
+ * the exec object needs to be newly initialized.
+ */
+#define drm_exec_retry(_exec)                                  \
+       do {                                                    \
+               WARN_ON((_exec)->contended != DRM_EXEC_DUMMY);  \
+               goto *__drm_exec_retry_ptr;                     \
+       } while (0)
+
 void drm_exec_init(struct drm_exec *exec, u32 flags, unsigned nr);
 void drm_exec_fini(struct drm_exec *exec);
 bool drm_exec_cleanup(struct drm_exec *exec);
-- 
2.54.0

Reply via email to