Re: [Intel-gfx] [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl

2021-09-21 Thread Tvrtko Ursulin



On 21/09/2021 10:41, Christian König wrote:

Am 20.09.21 um 12:33 schrieb Tvrtko Ursulin:

On 20/09/2021 11:13, Christian König wrote:

Am 20.09.21 um 10:45 schrieb Tvrtko Ursulin:


On 17/09/2021 13:35, Christian König wrote:

This makes the function much simpler since the complex
retry logic is now handled else where.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/i915/gem/i915_gem_busy.c | 32 


  1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c 
b/drivers/gpu/drm/i915/gem/i915_gem_busy.c

index 6234e17259c1..b1cb7ba688da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void 
*data,

  {
  struct drm_i915_gem_busy *args = data;
  struct drm_i915_gem_object *obj;
-    struct dma_resv_list *list;
-    unsigned int seq;
+    struct dma_resv_iter cursor;
+    struct dma_fence *fence;
  int err;
    err = -ENOENT;
@@ -109,27 +109,17 @@ i915_gem_busy_ioctl(struct drm_device *dev, 
void *data,
   * to report the overall busyness. This is what the 
wait-ioctl does.

   *
   */
-retry:
-    seq = raw_read_seqcount(>base.resv->seq);
-
-    /* Translate the exclusive fence to the READ *and* WRITE 
engine */
-    args->busy = 
busy_check_writer(dma_resv_excl_fence(obj->base.resv));

-
-    /* Translate shared fences to READ set of engines */
-    list = dma_resv_shared_list(obj->base.resv);
-    if (list) {
-    unsigned int shared_count = list->shared_count, i;
-
-    for (i = 0; i < shared_count; ++i) {
-    struct dma_fence *fence =
-    rcu_dereference(list->shared[i]);
-
+    args->busy = false;
+    dma_resv_iter_begin(, obj->base.resv, true);
+    dma_resv_for_each_fence_unlocked(, fence) {


You did not agree with my suggestion to reset args->busy on restart 
and so preserve current behaviour?


No, I want to keep the restart behavior internally to the dma_resv 
object and as far as I can see it should not make a difference here.


To be clear, on paper difference between old and new implementation is 
if the restart happens while processing the shared fences.


Old implementation unconditionally goes to "args->busy =
>>> busy_check_writer(dma_resv_excl_fence(obj->base.resv));" and so 
overwrites the set of flags returned to userspace.


New implementation can merge new read flags to the old set of flags 
and so return a composition of past and current fences.


Maybe it does not matter hugely in this case, depends if userspace 
typically just restarts until flags are clear. But I am not sure.


On the higher level - what do you mean with wanting to keep the 
restart behaviour internal? Not providing iterators users means of 
detecting it? I think it has to be provided.


Ok I will adjust that for now to get the patch set upstream. But in 
general when somebody outside of the dma_resv code base depends on the 
restart behavior then that's a bug inside the design of that code.


Thanks, no change in behaviour makes for an easy r-b. :)

The callers should only care about what unsignaled fences are inside the 
dma_resv container and it shouldn't matter if those fences are presented 
once or multiple times because of a reset..


When this makes a difference we have a bug in the handling and should 
probably consider taking the dma_resv.lock instead.


I agree, which is why I was mentioning earlier how it would be good to 
completely sort locked from unlocked iterators and avoid situations 
where unlocked one is called from a path where object is locked.


Unfortunately for the display code path I cannot easily help with the 
audit of call paths. And I think there are at least two patches in your 
series which need KMS expertise.


Regards,

Tvrtko


Re: [Intel-gfx] [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl

2021-09-21 Thread Christian König

Am 20.09.21 um 12:33 schrieb Tvrtko Ursulin:

On 20/09/2021 11:13, Christian König wrote:

Am 20.09.21 um 10:45 schrieb Tvrtko Ursulin:


On 17/09/2021 13:35, Christian König wrote:

This makes the function much simpler since the complex
retry logic is now handled else where.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/i915/gem/i915_gem_busy.c | 32 


  1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c 
b/drivers/gpu/drm/i915/gem/i915_gem_busy.c

index 6234e17259c1..b1cb7ba688da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void 
*data,

  {
  struct drm_i915_gem_busy *args = data;
  struct drm_i915_gem_object *obj;
-    struct dma_resv_list *list;
-    unsigned int seq;
+    struct dma_resv_iter cursor;
+    struct dma_fence *fence;
  int err;
    err = -ENOENT;
@@ -109,27 +109,17 @@ i915_gem_busy_ioctl(struct drm_device *dev, 
void *data,
   * to report the overall busyness. This is what the 
wait-ioctl does.

   *
   */
-retry:
-    seq = raw_read_seqcount(>base.resv->seq);
-
-    /* Translate the exclusive fence to the READ *and* WRITE 
engine */
-    args->busy = 
busy_check_writer(dma_resv_excl_fence(obj->base.resv));

-
-    /* Translate shared fences to READ set of engines */
-    list = dma_resv_shared_list(obj->base.resv);
-    if (list) {
-    unsigned int shared_count = list->shared_count, i;
-
-    for (i = 0; i < shared_count; ++i) {
-    struct dma_fence *fence =
-    rcu_dereference(list->shared[i]);
-
+    args->busy = false;
+    dma_resv_iter_begin(, obj->base.resv, true);
+    dma_resv_for_each_fence_unlocked(, fence) {


You did not agree with my suggestion to reset args->busy on restart 
and so preserve current behaviour?


No, I want to keep the restart behavior internally to the dma_resv 
object and as far as I can see it should not make a difference here.


To be clear, on paper difference between old and new implementation is 
if the restart happens while processing the shared fences.


Old implementation unconditionally goes to "args->busy =
>>> busy_check_writer(dma_resv_excl_fence(obj->base.resv));" and so 
overwrites the set of flags returned to userspace.


New implementation can merge new read flags to the old set of flags 
and so return a composition of past and current fences.


Maybe it does not matter hugely in this case, depends if userspace 
typically just restarts until flags are clear. But I am not sure.


On the higher level - what do you mean with wanting to keep the 
restart behaviour internal? Not providing iterators users means of 
detecting it? I think it has to be provided.


Ok I will adjust that for now to get the patch set upstream. But in 
general when somebody outside of the dma_resv code base depends on the 
restart behavior then that's a bug inside the design of that code.


The callers should only care about what unsignaled fences are inside the 
dma_resv container and it shouldn't matter if those fences are presented 
once or multiple times because of a reset..


When this makes a difference we have a bug in the handling and should 
probably consider taking the dma_resv.lock instead.


Regards,
Christian.



Regards,

Tvrtko


Regards,
Christian.



Regards,

Tvrtko


+    if (dma_resv_iter_is_exclusive())
+    /* Translate the exclusive fence to the READ *and* 
WRITE engine */

+    args->busy = busy_check_writer(fence);
+    else
+    /* Translate shared fences to READ set of engines */
  args->busy |= busy_check_reader(fence);
-    }
  }
-
-    if (args->busy && read_seqcount_retry(>base.resv->seq, seq))
-    goto retry;
+    dma_resv_iter_end();
    err = 0;
  out:







Re: [Intel-gfx] [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl

2021-09-20 Thread Tvrtko Ursulin



On 20/09/2021 11:13, Christian König wrote:

Am 20.09.21 um 10:45 schrieb Tvrtko Ursulin:


On 17/09/2021 13:35, Christian König wrote:

This makes the function much simpler since the complex
retry logic is now handled else where.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/i915/gem/i915_gem_busy.c | 32 
  1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c 
b/drivers/gpu/drm/i915/gem/i915_gem_busy.c

index 6234e17259c1..b1cb7ba688da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void 
*data,

  {
  struct drm_i915_gem_busy *args = data;
  struct drm_i915_gem_object *obj;
-    struct dma_resv_list *list;
-    unsigned int seq;
+    struct dma_resv_iter cursor;
+    struct dma_fence *fence;
  int err;
    err = -ENOENT;
@@ -109,27 +109,17 @@ i915_gem_busy_ioctl(struct drm_device *dev, 
void *data,
   * to report the overall busyness. This is what the wait-ioctl 
does.

   *
   */
-retry:
-    seq = raw_read_seqcount(>base.resv->seq);
-
-    /* Translate the exclusive fence to the READ *and* WRITE engine */
-    args->busy = 
busy_check_writer(dma_resv_excl_fence(obj->base.resv));

-
-    /* Translate shared fences to READ set of engines */
-    list = dma_resv_shared_list(obj->base.resv);
-    if (list) {
-    unsigned int shared_count = list->shared_count, i;
-
-    for (i = 0; i < shared_count; ++i) {
-    struct dma_fence *fence =
-    rcu_dereference(list->shared[i]);
-
+    args->busy = false;
+    dma_resv_iter_begin(, obj->base.resv, true);
+    dma_resv_for_each_fence_unlocked(, fence) {


You did not agree with my suggestion to reset args->busy on restart 
and so preserve current behaviour?


No, I want to keep the restart behavior internally to the dma_resv 
object and as far as I can see it should not make a difference here.


To be clear, on paper difference between old and new implementation is 
if the restart happens while processing the shared fences.


Old implementation unconditionally goes to "args->busy =
>>> busy_check_writer(dma_resv_excl_fence(obj->base.resv));" and so 
overwrites the set of flags returned to userspace.


New implementation can merge new read flags to the old set of flags and 
so return a composition of past and current fences.


Maybe it does not matter hugely in this case, depends if userspace 
typically just restarts until flags are clear. But I am not sure.


On the higher level - what do you mean with wanting to keep the restart 
behaviour internal? Not providing iterators users means of detecting it? 
I think it has to be provided.


Regards,

Tvrtko


Regards,
Christian.



Regards,

Tvrtko


+    if (dma_resv_iter_is_exclusive())
+    /* Translate the exclusive fence to the READ *and* WRITE 
engine */

+    args->busy = busy_check_writer(fence);
+    else
+    /* Translate shared fences to READ set of engines */
  args->busy |= busy_check_reader(fence);
-    }
  }
-
-    if (args->busy && read_seqcount_retry(>base.resv->seq, seq))
-    goto retry;
+    dma_resv_iter_end();
    err = 0;
  out:





Re: [Intel-gfx] [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl

2021-09-20 Thread Christian König

Am 20.09.21 um 10:45 schrieb Tvrtko Ursulin:


On 17/09/2021 13:35, Christian König wrote:

This makes the function much simpler since the complex
retry logic is now handled else where.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/i915/gem/i915_gem_busy.c | 32 
  1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c 
b/drivers/gpu/drm/i915/gem/i915_gem_busy.c

index 6234e17259c1..b1cb7ba688da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void 
*data,

  {
  struct drm_i915_gem_busy *args = data;
  struct drm_i915_gem_object *obj;
-    struct dma_resv_list *list;
-    unsigned int seq;
+    struct dma_resv_iter cursor;
+    struct dma_fence *fence;
  int err;
    err = -ENOENT;
@@ -109,27 +109,17 @@ i915_gem_busy_ioctl(struct drm_device *dev, 
void *data,
   * to report the overall busyness. This is what the wait-ioctl 
does.

   *
   */
-retry:
-    seq = raw_read_seqcount(>base.resv->seq);
-
-    /* Translate the exclusive fence to the READ *and* WRITE engine */
-    args->busy = 
busy_check_writer(dma_resv_excl_fence(obj->base.resv));

-
-    /* Translate shared fences to READ set of engines */
-    list = dma_resv_shared_list(obj->base.resv);
-    if (list) {
-    unsigned int shared_count = list->shared_count, i;
-
-    for (i = 0; i < shared_count; ++i) {
-    struct dma_fence *fence =
-    rcu_dereference(list->shared[i]);
-
+    args->busy = false;
+    dma_resv_iter_begin(, obj->base.resv, true);
+    dma_resv_for_each_fence_unlocked(, fence) {


You did not agree with my suggestion to reset args->busy on restart 
and so preserve current behaviour?


No, I want to keep the restart behavior internally to the dma_resv 
object and as far as I can see it should not make a difference here.


Regards,
Christian.



Regards,

Tvrtko


+    if (dma_resv_iter_is_exclusive())
+    /* Translate the exclusive fence to the READ *and* WRITE 
engine */

+    args->busy = busy_check_writer(fence);
+    else
+    /* Translate shared fences to READ set of engines */
  args->busy |= busy_check_reader(fence);
-    }
  }
-
-    if (args->busy && read_seqcount_retry(>base.resv->seq, seq))
-    goto retry;
+    dma_resv_iter_end();
    err = 0;
  out:





Re: [Intel-gfx] [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl

2021-09-20 Thread Tvrtko Ursulin



On 17/09/2021 13:35, Christian König wrote:

This makes the function much simpler since the complex
retry logic is now handled else where.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/i915/gem/i915_gem_busy.c | 32 
  1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c 
b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index 6234e17259c1..b1cb7ba688da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
  {
struct drm_i915_gem_busy *args = data;
struct drm_i915_gem_object *obj;
-   struct dma_resv_list *list;
-   unsigned int seq;
+   struct dma_resv_iter cursor;
+   struct dma_fence *fence;
int err;
  
  	err = -ENOENT;

@@ -109,27 +109,17 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 * to report the overall busyness. This is what the wait-ioctl does.
 *
 */
-retry:
-   seq = raw_read_seqcount(>base.resv->seq);
-
-   /* Translate the exclusive fence to the READ *and* WRITE engine */
-   args->busy = busy_check_writer(dma_resv_excl_fence(obj->base.resv));
-
-   /* Translate shared fences to READ set of engines */
-   list = dma_resv_shared_list(obj->base.resv);
-   if (list) {
-   unsigned int shared_count = list->shared_count, i;
-
-   for (i = 0; i < shared_count; ++i) {
-   struct dma_fence *fence =
-   rcu_dereference(list->shared[i]);
-
+   args->busy = false;
+   dma_resv_iter_begin(, obj->base.resv, true);
+   dma_resv_for_each_fence_unlocked(, fence) {


You did not agree with my suggestion to reset args->busy on restart and 
so preserve current behaviour?


Regards,

Tvrtko


+   if (dma_resv_iter_is_exclusive())
+   /* Translate the exclusive fence to the READ *and* 
WRITE engine */
+   args->busy = busy_check_writer(fence);
+   else
+   /* Translate shared fences to READ set of engines */
args->busy |= busy_check_reader(fence);
-   }
}
-
-   if (args->busy && read_seqcount_retry(>base.resv->seq, seq))
-   goto retry;
+   dma_resv_iter_end();
  
  	err = 0;

  out:



Re: [Intel-gfx] [PATCH 13/26] drm/i915: use the new iterator in i915_gem_busy_ioctl

2021-09-14 Thread Tvrtko Ursulin



On 13/09/2021 14:16, Christian König wrote:

This makes the function much simpler since the complex
retry logic is now handled else where.

Signed-off-by: Christian König 
---
  drivers/gpu/drm/i915/gem/i915_gem_busy.c | 30 +++-
  1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c 
b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
index 6234e17259c1..c6c6d747b33e 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -82,8 +82,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
  {
struct drm_i915_gem_busy *args = data;
struct drm_i915_gem_object *obj;
-   struct dma_resv_list *list;
-   unsigned int seq;
+   struct dma_resv_cursor cursor;
+   struct dma_fence *fence;
int err;
  
  	err = -ENOENT;

@@ -109,28 +109,16 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 * to report the overall busyness. This is what the wait-ioctl does.
 *
 */
-retry:
-   seq = raw_read_seqcount(>base.resv->seq);
-
-   /* Translate the exclusive fence to the READ *and* WRITE engine */
-   args->busy = busy_check_writer(dma_resv_excl_fence(obj->base.resv));
-
-   /* Translate shared fences to READ set of engines */
-   list = dma_resv_shared_list(obj->base.resv);
-   if (list) {
-   unsigned int shared_count = list->shared_count, i;
-
-   for (i = 0; i < shared_count; ++i) {
-   struct dma_fence *fence =
-   rcu_dereference(list->shared[i]);
-
+   args->busy = false;
+   dma_resv_for_each_fence_unlocked(obj->base.resv, , true, fence) {


To preserve strictly identical behaviour, I think add before the below 
if-else:


if (cursor.is_first)
args->busy = 0;

As mentioned elsewhere in the thread I am not convinced it is hugely 
important, all that can happen without it is that stale read activity 
gets reported, and this ioctl is not really that sensitive to that.


Regards,

Tvrtko


+   if (cursor.is_exclusive)
+   /* Translate the exclusive fence to the READ *and* 
WRITE engine */
+   args->busy = busy_check_writer(fence);
+   else
+   /* Translate shared fences to READ set of engines */
args->busy |= busy_check_reader(fence);
-   }
}
  
-	if (args->busy && read_seqcount_retry(>base.resv->seq, seq))

-   goto retry;
-
err = 0;
  out:
rcu_read_unlock();