[Intel-gfx] [PATCH 1/3] drm/i915: introduce a mechanism to extend execbuf2

2020-08-03 Thread Lionel Landwerlin
We're planning to use this for a couple of new feature where we need
to provide additional parameters to execbuf.

v2: Check for invalid flags in execbuffer2 (Lionel)

v3: Rename I915_EXEC_EXT -> I915_EXEC_USE_EXTENSIONS (Chris)

v4: Rebase
Move array fence parsing in i915_gem_do_execbuffer()

Signed-off-by: Lionel Landwerlin 
Reviewed-by: Chris Wilson  (v1)
Reviewed-by: Daniel Vetter 
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 131 +++---
 include/uapi/drm/i915_drm.h   |  26 +++-
 2 files changed, 103 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 07cb2dd0f795..ed8d1c2517f6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -26,6 +26,7 @@
 #include "i915_gem_ioctls.h"
 #include "i915_sw_fence_work.h"
 #include "i915_trace.h"
+#include "i915_user_extensions.h"
 
 struct eb_vma {
struct i915_vma *vma;
@@ -281,6 +282,13 @@ struct i915_execbuffer {
int lut_size;
struct hlist_head *buckets; /** ht for relocation handles */
struct eb_vma_array *array;
+
+   struct i915_eb_fence {
+   struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */
+   } *fences;
+   u32 n_fences;
+
+   u64 extension_flags; /** Available extensions parameters */
 };
 
 static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb)
@@ -1622,7 +1630,8 @@ static int i915_gem_check_execbuffer(struct 
drm_i915_gem_execbuffer2 *exec)
return -EINVAL;
 
/* Kernel clipping was a DRI1 misfeature */
-   if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) {
+   if (!(exec->flags & (I915_EXEC_FENCE_ARRAY |
+I915_EXEC_USE_EXTENSIONS))) {
if (exec->num_cliprects || exec->cliprects_ptr)
return -EINVAL;
}
@@ -2189,41 +2198,41 @@ eb_pin_engine(struct i915_execbuffer *eb,
 }
 
 static void
-__free_fence_array(struct drm_syncobj **fences, unsigned int n)
+__free_fence_array(struct i915_eb_fence *fences, unsigned int n)
 {
while (n--)
-   drm_syncobj_put(ptr_mask_bits(fences[n], 2));
+   drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2));
kvfree(fences);
 }
 
-static struct drm_syncobj **
+static int
 get_fence_array(struct drm_i915_gem_execbuffer2 *args,
-   struct drm_file *file)
+   struct i915_execbuffer *eb)
 {
const unsigned long nfences = args->num_cliprects;
struct drm_i915_gem_exec_fence __user *user;
-   struct drm_syncobj **fences;
+   struct i915_eb_fence *fences;
unsigned long n;
int err;
 
if (!(args->flags & I915_EXEC_FENCE_ARRAY))
-   return NULL;
+   return 0;
 
/* Check multiplication overflow for access_ok() and kvmalloc_array() */
BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long));
if (nfences > min_t(unsigned long,
ULONG_MAX / sizeof(*user),
SIZE_MAX / sizeof(*fences)))
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
 
user = u64_to_user_ptr(args->cliprects_ptr);
if (!access_ok(user, nfences * sizeof(*user)))
-   return ERR_PTR(-EFAULT);
+   return -EFAULT;
 
fences = kvmalloc_array(nfences, sizeof(*fences),
__GFP_NOWARN | GFP_KERNEL);
if (!fences)
-   return ERR_PTR(-ENOMEM);
+   return -ENOMEM;
 
for (n = 0; n < nfences; n++) {
struct drm_i915_gem_exec_fence fence;
@@ -2239,7 +2248,7 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args,
goto err;
}
 
-   syncobj = drm_syncobj_find(file, fence.handle);
+   syncobj = drm_syncobj_find(eb->file, fence.handle);
if (!syncobj) {
DRM_DEBUG("Invalid syncobj handle provided\n");
err = -ENOENT;
@@ -2249,38 +2258,31 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args,
BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) &
 ~__I915_EXEC_FENCE_UNKNOWN_FLAGS);
 
-   fences[n] = ptr_pack_bits(syncobj, fence.flags, 2);
+   fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2);
}
 
-   return fences;
+   eb->fences = fences;
+   eb->n_fences = nfences;
+
+   return 0;
 
 err:
__free_fence_array(fences, n);
-   return ERR_PTR(err);
-}
-
-static void
-put_fence_array(struct drm_i915_gem_execbuffer2 *args,
-   struct drm_syncobj **fences)
-{
-   if (fences)
-   __free_fence_array(fences, args->num_cliprects);
+   return err;
 }
 
 static int
-await_fence_array(struct i915_execbuffer *eb,
-   

[Intel-gfx] [PATCH 1/3] drm/i915: introduce a mechanism to extend execbuf2

2020-08-03 Thread Lionel Landwerlin
We're planning to use this for a couple of new feature where we need
to provide additional parameters to execbuf.

v2: Check for invalid flags in execbuffer2 (Lionel)

v3: Rename I915_EXEC_EXT -> I915_EXEC_USE_EXTENSIONS (Chris)

v4: Rebase
Move array fence parsing in i915_gem_do_execbuffer()

Signed-off-by: Lionel Landwerlin 
Reviewed-by: Chris Wilson  (v1)
Reviewed-by: Daniel Vetter 
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 131 +++---
 include/uapi/drm/i915_drm.h   |  26 +++-
 2 files changed, 103 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 07cb2dd0f795..ed8d1c2517f6 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -26,6 +26,7 @@
 #include "i915_gem_ioctls.h"
 #include "i915_sw_fence_work.h"
 #include "i915_trace.h"
+#include "i915_user_extensions.h"
 
 struct eb_vma {
struct i915_vma *vma;
@@ -281,6 +282,13 @@ struct i915_execbuffer {
int lut_size;
struct hlist_head *buckets; /** ht for relocation handles */
struct eb_vma_array *array;
+
+   struct i915_eb_fence {
+   struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */
+   } *fences;
+   u32 n_fences;
+
+   u64 extension_flags; /** Available extensions parameters */
 };
 
 static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb)
@@ -1622,7 +1630,8 @@ static int i915_gem_check_execbuffer(struct 
drm_i915_gem_execbuffer2 *exec)
return -EINVAL;
 
/* Kernel clipping was a DRI1 misfeature */
-   if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) {
+   if (!(exec->flags & (I915_EXEC_FENCE_ARRAY |
+I915_EXEC_USE_EXTENSIONS))) {
if (exec->num_cliprects || exec->cliprects_ptr)
return -EINVAL;
}
@@ -2189,41 +2198,41 @@ eb_pin_engine(struct i915_execbuffer *eb,
 }
 
 static void
-__free_fence_array(struct drm_syncobj **fences, unsigned int n)
+__free_fence_array(struct i915_eb_fence *fences, unsigned int n)
 {
while (n--)
-   drm_syncobj_put(ptr_mask_bits(fences[n], 2));
+   drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2));
kvfree(fences);
 }
 
-static struct drm_syncobj **
+static int
 get_fence_array(struct drm_i915_gem_execbuffer2 *args,
-   struct drm_file *file)
+   struct i915_execbuffer *eb)
 {
const unsigned long nfences = args->num_cliprects;
struct drm_i915_gem_exec_fence __user *user;
-   struct drm_syncobj **fences;
+   struct i915_eb_fence *fences;
unsigned long n;
int err;
 
if (!(args->flags & I915_EXEC_FENCE_ARRAY))
-   return NULL;
+   return 0;
 
/* Check multiplication overflow for access_ok() and kvmalloc_array() */
BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long));
if (nfences > min_t(unsigned long,
ULONG_MAX / sizeof(*user),
SIZE_MAX / sizeof(*fences)))
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
 
user = u64_to_user_ptr(args->cliprects_ptr);
if (!access_ok(user, nfences * sizeof(*user)))
-   return ERR_PTR(-EFAULT);
+   return -EFAULT;
 
fences = kvmalloc_array(nfences, sizeof(*fences),
__GFP_NOWARN | GFP_KERNEL);
if (!fences)
-   return ERR_PTR(-ENOMEM);
+   return -ENOMEM;
 
for (n = 0; n < nfences; n++) {
struct drm_i915_gem_exec_fence fence;
@@ -2239,7 +2248,7 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args,
goto err;
}
 
-   syncobj = drm_syncobj_find(file, fence.handle);
+   syncobj = drm_syncobj_find(eb->file, fence.handle);
if (!syncobj) {
DRM_DEBUG("Invalid syncobj handle provided\n");
err = -ENOENT;
@@ -2249,38 +2258,31 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args,
BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) &
 ~__I915_EXEC_FENCE_UNKNOWN_FLAGS);
 
-   fences[n] = ptr_pack_bits(syncobj, fence.flags, 2);
+   fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2);
}
 
-   return fences;
+   eb->fences = fences;
+   eb->n_fences = nfences;
+
+   return 0;
 
 err:
__free_fence_array(fences, n);
-   return ERR_PTR(err);
-}
-
-static void
-put_fence_array(struct drm_i915_gem_execbuffer2 *args,
-   struct drm_syncobj **fences)
-{
-   if (fences)
-   __free_fence_array(fences, args->num_cliprects);
+   return err;
 }
 
 static int
-await_fence_array(struct i915_execbuffer *eb,
-   

[Intel-gfx] [PATCH 1/3] drm/i915: introduce a mechanism to extend execbuf2

2020-07-31 Thread Lionel Landwerlin
We're planning to use this for a couple of new feature where we need
to provide additional parameters to execbuf.

v2: Check for invalid flags in execbuffer2 (Lionel)

v3: Rename I915_EXEC_EXT -> I915_EXEC_USE_EXTENSIONS (Chris)

v4: Rebase
Move array fence parsing in i915_gem_do_execbuffer()

Signed-off-by: Lionel Landwerlin 
Reviewed-by: Chris Wilson  (v1)
Reviewed-by: Daniel Vetter 
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 131 +++---
 include/uapi/drm/i915_drm.h   |  26 +++-
 2 files changed, 103 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index b7a86cdec9b5..5aac474c058f 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -26,6 +26,7 @@
 #include "i915_gem_ioctls.h"
 #include "i915_sw_fence_work.h"
 #include "i915_trace.h"
+#include "i915_user_extensions.h"
 
 struct eb_vma {
struct i915_vma *vma;
@@ -281,6 +282,13 @@ struct i915_execbuffer {
int lut_size;
struct hlist_head *buckets; /** ht for relocation handles */
struct eb_vma_array *array;
+
+   struct i915_eb_fence {
+   struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */
+   } *fences;
+   u32 n_fences;
+
+   u64 extension_flags; /** Available extensions parameters */
 };
 
 static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb)
@@ -1622,7 +1630,8 @@ static int i915_gem_check_execbuffer(struct 
drm_i915_gem_execbuffer2 *exec)
return -EINVAL;
 
/* Kernel clipping was a DRI1 misfeature */
-   if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) {
+   if (!(exec->flags & (I915_EXEC_FENCE_ARRAY |
+I915_EXEC_USE_EXTENSIONS))) {
if (exec->num_cliprects || exec->cliprects_ptr)
return -EINVAL;
}
@@ -2189,41 +2198,41 @@ eb_pin_engine(struct i915_execbuffer *eb,
 }
 
 static void
-__free_fence_array(struct drm_syncobj **fences, unsigned int n)
+__free_fence_array(struct i915_eb_fence *fences, unsigned int n)
 {
while (n--)
-   drm_syncobj_put(ptr_mask_bits(fences[n], 2));
+   drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2));
kvfree(fences);
 }
 
-static struct drm_syncobj **
+static int
 get_fence_array(struct drm_i915_gem_execbuffer2 *args,
-   struct drm_file *file)
+   struct i915_execbuffer *eb)
 {
const unsigned long nfences = args->num_cliprects;
struct drm_i915_gem_exec_fence __user *user;
-   struct drm_syncobj **fences;
+   struct i915_eb_fence *fences;
unsigned long n;
int err;
 
if (!(args->flags & I915_EXEC_FENCE_ARRAY))
-   return NULL;
+   return 0;
 
/* Check multiplication overflow for access_ok() and kvmalloc_array() */
BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long));
if (nfences > min_t(unsigned long,
ULONG_MAX / sizeof(*user),
SIZE_MAX / sizeof(*fences)))
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
 
user = u64_to_user_ptr(args->cliprects_ptr);
if (!access_ok(user, nfences * sizeof(*user)))
-   return ERR_PTR(-EFAULT);
+   return -EFAULT;
 
fences = kvmalloc_array(nfences, sizeof(*fences),
__GFP_NOWARN | GFP_KERNEL);
if (!fences)
-   return ERR_PTR(-ENOMEM);
+   return -ENOMEM;
 
for (n = 0; n < nfences; n++) {
struct drm_i915_gem_exec_fence fence;
@@ -2239,7 +2248,7 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args,
goto err;
}
 
-   syncobj = drm_syncobj_find(file, fence.handle);
+   syncobj = drm_syncobj_find(eb->file, fence.handle);
if (!syncobj) {
DRM_DEBUG("Invalid syncobj handle provided\n");
err = -ENOENT;
@@ -2249,38 +2258,31 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args,
BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) &
 ~__I915_EXEC_FENCE_UNKNOWN_FLAGS);
 
-   fences[n] = ptr_pack_bits(syncobj, fence.flags, 2);
+   fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2);
}
 
-   return fences;
+   eb->fences = fences;
+   eb->n_fences = nfences;
+
+   return 0;
 
 err:
__free_fence_array(fences, n);
-   return ERR_PTR(err);
-}
-
-static void
-put_fence_array(struct drm_i915_gem_execbuffer2 *args,
-   struct drm_syncobj **fences)
-{
-   if (fences)
-   __free_fence_array(fences, args->num_cliprects);
+   return err;
 }
 
 static int
-await_fence_array(struct i915_execbuffer *eb,
-   

[Intel-gfx] [PATCH 1/3] drm/i915: introduce a mechanism to extend execbuf2

2020-04-06 Thread Venkata Sandeep Dhanalakota
From: Lionel Landwerlin 

We're planning to use this for a couple of new feature where we need
to provide additional parameters to execbuf.

v2: Check for invalid flags in execbuffer2 (Lionel)

v3: Rename I915_EXEC_EXT -> I915_EXEC_USE_EXTENSIONS (Chris)

Signed-off-by: Lionel Landwerlin 
Reviewed-by: Chris Wilson  (v1)
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 39 ++-
 include/uapi/drm/i915_drm.h   | 26 +++--
 2 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 9d11bad74e9a..16831f715daa 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -26,6 +26,7 @@
 #include "i915_gem_ioctls.h"
 #include "i915_sw_fence_work.h"
 #include "i915_trace.h"
+#include "i915_user_extensions.h"
 
 struct eb_vma {
struct i915_vma *vma;
@@ -288,6 +289,10 @@ struct i915_execbuffer {
int lut_size;
struct hlist_head *buckets; /** ht for relocation handles */
struct eb_vma_array *array;
+
+   struct {
+   u64 flags; /** Available extensions parameters */
+   } extensions;
 };
 
 static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb)
@@ -1698,7 +1703,8 @@ static int i915_gem_check_execbuffer(struct 
drm_i915_gem_execbuffer2 *exec)
return -EINVAL;
 
/* Kernel clipping was a DRI1 misfeature */
-   if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) {
+   if (!(exec->flags & (I915_EXEC_FENCE_ARRAY |
+I915_EXEC_USE_EXTENSIONS))) {
if (exec->num_cliprects || exec->cliprects_ptr)
return -EINVAL;
}
@@ -2431,6 +2437,33 @@ static void eb_request_add(struct i915_execbuffer *eb)
mutex_unlock(>mutex);
 }
 
+static const i915_user_extension_fn execbuf_extensions[] = {
+};
+
+static int
+parse_execbuf2_extensions(struct drm_i915_gem_execbuffer2 *args,
+ struct i915_execbuffer *eb)
+{
+   eb->extensions.flags = 0;
+
+   if (!(args->flags & I915_EXEC_USE_EXTENSIONS))
+   return 0;
+
+   /* The execbuf2 extension mechanism reuses cliprects_ptr. So we cannot
+* have another flag also using it at the same time.
+*/
+   if (eb->args->flags & I915_EXEC_FENCE_ARRAY)
+   return -EINVAL;
+
+   if (args->num_cliprects != 0)
+   return -EINVAL;
+
+   return i915_user_extensions(u64_to_user_ptr(args->cliprects_ptr),
+   execbuf_extensions,
+   ARRAY_SIZE(execbuf_extensions),
+   eb);
+}
+
 static int
 i915_gem_do_execbuffer(struct drm_device *dev,
   struct drm_file *file,
@@ -2484,6 +2517,10 @@ i915_gem_do_execbuffer(struct drm_device *dev,
if (args->flags & I915_EXEC_IS_PINNED)
eb.batch_flags |= I915_DISPATCH_PINNED;
 
+   err = parse_execbuf2_extensions(args, );
+   if (err)
+   return err;
+
if (args->flags & I915_EXEC_FENCE_IN) {
in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2));
if (!in_fence)
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 14b67cd6b54b..7ea38aa6502c 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1046,6 +1046,10 @@ struct drm_i915_gem_exec_fence {
__u32 flags;
 };
 
+enum drm_i915_gem_execbuffer_ext {
+   DRM_I915_GEM_EXECBUFFER_EXT_MAX /* non-ABI */
+};
+
 struct drm_i915_gem_execbuffer2 {
/**
 * List of gem_exec_object2 structs
@@ -1062,8 +1066,15 @@ struct drm_i915_gem_execbuffer2 {
__u32 num_cliprects;
/**
 * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
-* is not set.  If I915_EXEC_FENCE_ARRAY is set, then this is a
-* struct drm_i915_gem_exec_fence *fences.
+* & I915_EXEC_USE_EXTENSIONS are not set.
+*
+* If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array
+* of struct drm_i915_gem_exec_fence and num_cliprects is the length
+* of the array.
+*
+* If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a
+* single struct drm_i915_gem_base_execbuffer_ext and num_cliprects is
+* 0.
 */
__u64 cliprects_ptr;
 #define I915_EXEC_RING_MASK  (0x3f)
@@ -1181,7 +1192,16 @@ struct drm_i915_gem_execbuffer2 {
  */
 #define I915_EXEC_FENCE_SUBMIT (1 << 20)
 
-#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1))
+/*
+ * Setting I915_EXEC_USE_EXTENSIONS implies that
+ * drm_i915_gem_execbuffer2.cliprects_ptr is treated as a pointer to an linked
+ * list of i915_user_extension. Each i915_user_extension node is the base of a
+ * larger structure. The list of