dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/crc: Handle opening and closing crc better
@ 2017-06-21 11:00 Maarten Lankhorst
  2017-07-06 11:09 ` Tomeu Vizoso
  0 siblings, 1 reply; 5+ messages in thread
From: Maarten Lankhorst @ 2017-06-21 11:00 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

When I was doing a grep . -r /sys/kernel/debug/dri/0 I noticed a WARN
appearing when I aborted the grep with ^C.

After investigating I've also noticed that the error handling was
lacking and there are race conditions involving multiple calls to
open/close simultaneously.

Fix this by setting the opened flag first and using crc->entries to
decide when crc can be collected.

Also call unset crc source before cleaning up, this way there is
no race with a future open().

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
---
 drivers/gpu/drm/drm_debugfs_crc.c | 46 ++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index 1722d8f21449..d0ea4627a093 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -136,21 +136,38 @@ static int crtc_crc_data_count(struct drm_crtc_crc *crc)
 	return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR);
 }
 
+static void crtc_crc_cleanup(struct drm_crtc_crc *crc)
+{
+	kfree(crc->entries);
+	crc->entries = NULL;
+	crc->head = 0;
+	crc->tail = 0;
+	crc->values_cnt = 0;
+	crc->opened = false;
+}
+
 static int crtc_crc_open(struct inode *inode, struct file *filep)
 {
 	struct drm_crtc *crtc = inode->i_private;
 	struct drm_crtc_crc *crc = &crtc->crc;
 	struct drm_crtc_crc_entry *entries = NULL;
 	size_t values_cnt;
-	int ret;
+	int ret = 0;
 
-	if (crc->opened)
-		return -EBUSY;
+	spin_lock_irq(&crc->lock);
+	if (!crc->opened)
+		crc->opened = true;
+	else
+		ret = -EBUSY;
+	spin_unlock_irq(&crc->lock);
 
-	ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
 	if (ret)
 		return ret;
 
+	ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
+	if (ret)
+		goto err;
+
 	if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) {
 		ret = -EINVAL;
 		goto err_disable;
@@ -170,7 +187,6 @@ static int crtc_crc_open(struct inode *inode, struct file *filep)
 	spin_lock_irq(&crc->lock);
 	crc->entries = entries;
 	crc->values_cnt = values_cnt;
-	crc->opened = true;
 
 	/*
 	 * Only return once we got a first frame, so userspace doesn't have to
@@ -182,12 +198,17 @@ static int crtc_crc_open(struct inode *inode, struct file *filep)
 						crc->lock);
 	spin_unlock_irq(&crc->lock);
 
-	WARN_ON(ret);
+	if (ret)
+		goto err_disable;
 
 	return 0;
 
 err_disable:
 	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
+err:
+	spin_lock_irq(&crc->lock);
+	crtc_crc_cleanup(crc);
+	spin_unlock_irq(&crc->lock);
 	return ret;
 }
 
@@ -197,17 +218,12 @@ static int crtc_crc_release(struct inode *inode, struct file *filep)
 	struct drm_crtc_crc *crc = &crtc->crc;
 	size_t values_cnt;
 
+	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
+
 	spin_lock_irq(&crc->lock);
-	kfree(crc->entries);
-	crc->entries = NULL;
-	crc->head = 0;
-	crc->tail = 0;
-	crc->values_cnt = 0;
-	crc->opened = false;
+	crtc_crc_cleanup(crc);
 	spin_unlock_irq(&crc->lock);
 
-	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
-
 	return 0;
 }
 
@@ -334,7 +350,7 @@ int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
 	spin_lock(&crc->lock);
 
 	/* Caller may not have noticed yet that userspace has stopped reading */
-	if (!crc->opened) {
+	if (!crc->entries) {
 		spin_unlock(&crc->lock);
 		return -EINVAL;
 	}
-- 
2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm/crc: Handle opening and closing crc better
  2017-06-21 11:00 [PATCH] drm/crc: Handle opening and closing crc better Maarten Lankhorst
@ 2017-07-06 11:09 ` Tomeu Vizoso
  2017-07-06 13:03   ` [PATCH] drm/crc: Only open CRC on atomic drivers when the CRTC is active Maarten Lankhorst
  0 siblings, 1 reply; 5+ messages in thread
From: Tomeu Vizoso @ 2017-07-06 11:09 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Intel Graphics Development, dri-devel@lists.freedesktop.org

Looks good to me:

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

I guess you have tested this with IGT? In any case, I think it would
be good to mention how a patch has been tested in the changelog. That
can be very useful to others if things go wrong at some point.

Thanks,

Tomeu




On 21 June 2017 at 13:00, Maarten Lankhorst
<maarten.lankhorst@linux.intel.com> wrote:
> When I was doing a grep . -r /sys/kernel/debug/dri/0 I noticed a WARN
> appearing when I aborted the grep with ^C.
>
> After investigating I've also noticed that the error handling was
> lacking and there are race conditions involving multiple calls to
> open/close simultaneously.
>
> Fix this by setting the opened flag first and using crc->entries to
> decide when crc can be collected.
>
> Also call unset crc source before cleaning up, this way there is
> no race with a future open().
>
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_debugfs_crc.c | 46 ++++++++++++++++++++++++++-------------
>  1 file changed, 31 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
> index 1722d8f21449..d0ea4627a093 100644
> --- a/drivers/gpu/drm/drm_debugfs_crc.c
> +++ b/drivers/gpu/drm/drm_debugfs_crc.c
> @@ -136,21 +136,38 @@ static int crtc_crc_data_count(struct drm_crtc_crc *crc)
>         return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR);
>  }
>
> +static void crtc_crc_cleanup(struct drm_crtc_crc *crc)
> +{
> +       kfree(crc->entries);
> +       crc->entries = NULL;
> +       crc->head = 0;
> +       crc->tail = 0;
> +       crc->values_cnt = 0;
> +       crc->opened = false;
> +}
> +
>  static int crtc_crc_open(struct inode *inode, struct file *filep)
>  {
>         struct drm_crtc *crtc = inode->i_private;
>         struct drm_crtc_crc *crc = &crtc->crc;
>         struct drm_crtc_crc_entry *entries = NULL;
>         size_t values_cnt;
> -       int ret;
> +       int ret = 0;
>
> -       if (crc->opened)
> -               return -EBUSY;
> +       spin_lock_irq(&crc->lock);
> +       if (!crc->opened)
> +               crc->opened = true;
> +       else
> +               ret = -EBUSY;
> +       spin_unlock_irq(&crc->lock);
>
> -       ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
>         if (ret)
>                 return ret;
>
> +       ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
> +       if (ret)
> +               goto err;
> +
>         if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) {
>                 ret = -EINVAL;
>                 goto err_disable;
> @@ -170,7 +187,6 @@ static int crtc_crc_open(struct inode *inode, struct file *filep)
>         spin_lock_irq(&crc->lock);
>         crc->entries = entries;
>         crc->values_cnt = values_cnt;
> -       crc->opened = true;
>
>         /*
>          * Only return once we got a first frame, so userspace doesn't have to
> @@ -182,12 +198,17 @@ static int crtc_crc_open(struct inode *inode, struct file *filep)
>                                                 crc->lock);
>         spin_unlock_irq(&crc->lock);
>
> -       WARN_ON(ret);
> +       if (ret)
> +               goto err_disable;
>
>         return 0;
>
>  err_disable:
>         crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
> +err:
> +       spin_lock_irq(&crc->lock);
> +       crtc_crc_cleanup(crc);
> +       spin_unlock_irq(&crc->lock);
>         return ret;
>  }
>
> @@ -197,17 +218,12 @@ static int crtc_crc_release(struct inode *inode, struct file *filep)
>         struct drm_crtc_crc *crc = &crtc->crc;
>         size_t values_cnt;
>
> +       crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
> +
>         spin_lock_irq(&crc->lock);
> -       kfree(crc->entries);
> -       crc->entries = NULL;
> -       crc->head = 0;
> -       crc->tail = 0;
> -       crc->values_cnt = 0;
> -       crc->opened = false;
> +       crtc_crc_cleanup(crc);
>         spin_unlock_irq(&crc->lock);
>
> -       crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
> -
>         return 0;
>  }
>
> @@ -334,7 +350,7 @@ int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
>         spin_lock(&crc->lock);
>
>         /* Caller may not have noticed yet that userspace has stopped reading */
> -       if (!crc->opened) {
> +       if (!crc->entries) {
>                 spin_unlock(&crc->lock);
>                 return -EINVAL;
>         }
> --
> 2.11.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] drm/crc: Only open CRC on atomic drivers when the CRTC is active.
  2017-07-06 11:09 ` Tomeu Vizoso
@ 2017-07-06 13:03   ` Maarten Lankhorst
  2017-07-07 11:01     ` [Intel-gfx] " Daniel Vetter
  0 siblings, 1 reply; 5+ messages in thread
From: Maarten Lankhorst @ 2017-07-06 13:03 UTC (permalink / raw)
  To: Tomeu Vizoso; +Cc: Intel Graphics Development, dri-devel@lists.freedesktop.org

Op 06-07-17 om 13:09 schreef Tomeu Vizoso:
> Looks good to me:
>
> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> I guess you have tested this with IGT? In any case, I think it would
> be good to mention how a patch has been tested in the changelog. That
> can be very useful to others if things go wrong at some point.
Testcase: debugfs_test.read_all_entries

But I hit it by doing a recursive grep, which I guess is the same thing here. :)

One further improvement I wanted to do was reject opening the CRC with -EIO
when the crtc is not active, that way the above test will not hang.
Does the below patch also look good to you?

----8<-----
Commit e8fa5671183c ("drm: crc: Wait for a frame before returning
from open()") adds a wait for CRC frame, but with the CRTC off
this will never be generated. For atomic drivers we know if a CRTC
is active through crtc_state->active, so when inactive reject the
open with -EIO.

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: e8fa5671183c ("drm: crc: Wait for a frame before returning from open()")
Testcase: debugfs_test.read_all_entries
---
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index d0ea4627a093..f9e26dda56d6 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -154,6 +154,19 @@ static int crtc_crc_open(struct inode *inode, struct file *filep)
 	size_t values_cnt;
 	int ret = 0;
 
+	if (drm_drv_uses_atomic_modeset(crtc->dev)) {
+		ret = drm_modeset_lock_interruptible(&crtc->mutex, NULL);
+		if (ret)
+			return ret;
+
+		if (!crtc->state->active)
+			ret = -EIO;
+		drm_modeset_unlock(&crtc->mutex);
+
+		if (ret)
+			return ret;
+	}
+
 	spin_lock_irq(&crc->lock);
 	if (!crc->opened)
 		crc->opened = true;

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Intel-gfx] [PATCH] drm/crc: Only open CRC on atomic drivers when the CRTC is active.
  2017-07-06 13:03   ` [PATCH] drm/crc: Only open CRC on atomic drivers when the CRTC is active Maarten Lankhorst
@ 2017-07-07 11:01     ` Daniel Vetter
  2017-07-10  7:57       ` Maarten Lankhorst
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel Vetter @ 2017-07-07 11:01 UTC (permalink / raw)
  To: Maarten Lankhorst
  Cc: Intel Graphics Development, dri-devel@lists.freedesktop.org

On Thu, Jul 06, 2017 at 03:03:15PM +0200, Maarten Lankhorst wrote:
> Op 06-07-17 om 13:09 schreef Tomeu Vizoso:
> > Looks good to me:
> >
> > Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > I guess you have tested this with IGT? In any case, I think it would
> > be good to mention how a patch has been tested in the changelog. That
> > can be very useful to others if things go wrong at some point.
> Testcase: debugfs_test.read_all_entries
> 
> But I hit it by doing a recursive grep, which I guess is the same thing here. :)
> 
> One further improvement I wanted to do was reject opening the CRC with -EIO
> when the crtc is not active, that way the above test will not hang.
> Does the below patch also look good to you?
> 
> ----8<-----
> Commit e8fa5671183c ("drm: crc: Wait for a frame before returning
> from open()") adds a wait for CRC frame, but with the CRTC off
> this will never be generated. For atomic drivers we know if a CRTC
> is active through crtc_state->active, so when inactive reject the
> open with -EIO.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> Fixes: e8fa5671183c ("drm: crc: Wait for a frame before returning from open()")
> Testcase: debugfs_test.read_all_entries

At least for the semantics I think this makes sense. Opening the CRC file
when the crtc is off is undefined.

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

But pls get Tomeu's ack too.

Thanks, Daniel


> ---
> diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
> index d0ea4627a093..f9e26dda56d6 100644
> --- a/drivers/gpu/drm/drm_debugfs_crc.c
> +++ b/drivers/gpu/drm/drm_debugfs_crc.c
> @@ -154,6 +154,19 @@ static int crtc_crc_open(struct inode *inode, struct file *filep)
>  	size_t values_cnt;
>  	int ret = 0;
>  
> +	if (drm_drv_uses_atomic_modeset(crtc->dev)) {
> +		ret = drm_modeset_lock_interruptible(&crtc->mutex, NULL);
> +		if (ret)
> +			return ret;
> +
> +		if (!crtc->state->active)
> +			ret = -EIO;
> +		drm_modeset_unlock(&crtc->mutex);
> +
> +		if (ret)
> +			return ret;
> +	}
> +
>  	spin_lock_irq(&crc->lock);
>  	if (!crc->opened)
>  		crc->opened = true;
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm/crc: Only open CRC on atomic drivers when the CRTC is active.
  2017-07-07 11:01     ` [Intel-gfx] " Daniel Vetter
@ 2017-07-10  7:57       ` Maarten Lankhorst
  0 siblings, 0 replies; 5+ messages in thread
From: Maarten Lankhorst @ 2017-07-10  7:57 UTC (permalink / raw)
  To: Tomeu Vizoso; +Cc: Intel Graphics Development, dri-devel@lists.freedesktop.org

Op 07-07-17 om 13:01 schreef Daniel Vetter:
> On Thu, Jul 06, 2017 at 03:03:15PM +0200, Maarten Lankhorst wrote:
>> Op 06-07-17 om 13:09 schreef Tomeu Vizoso:
>>> Looks good to me:
>>>
>>> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>>>
>>> I guess you have tested this with IGT? In any case, I think it would
>>> be good to mention how a patch has been tested in the changelog. That
>>> can be very useful to others if things go wrong at some point.
>> Testcase: debugfs_test.read_all_entries
>>
>> But I hit it by doing a recursive grep, which I guess is the same thing here. :)
>>
>> One further improvement I wanted to do was reject opening the CRC with -EIO
>> when the crtc is not active, that way the above test will not hang.
>> Does the below patch also look good to you?
>>
>> ----8<-----
>> Commit e8fa5671183c ("drm: crc: Wait for a frame before returning
>> from open()") adds a wait for CRC frame, but with the CRTC off
>> this will never be generated. For atomic drivers we know if a CRTC
>> is active through crtc_state->active, so when inactive reject the
>> open with -EIO.
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> Fixes: e8fa5671183c ("drm: crc: Wait for a frame before returning from open()")
>> Testcase: debugfs_test.read_all_entries
> At least for the semantics I think this makes sense. Opening the CRC file
> when the crtc is off is undefined.
>
> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>
> But pls get Tomeu's ack too.
Tomeu, can you ack? :)

I did some testing on IGT with both patches applied on all tests with
CRC in their name, no problems with opening CRC as far as I can see,
and all tests except kms_ccs and kms_mmap_write_crc succeed. The
former needs render compression, the latter fails on a crc failure,
so it can't have been caused by this patch.

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-07-10  7:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-21 11:00 [PATCH] drm/crc: Handle opening and closing crc better Maarten Lankhorst
2017-07-06 11:09 ` Tomeu Vizoso
2017-07-06 13:03   ` [PATCH] drm/crc: Only open CRC on atomic drivers when the CRTC is active Maarten Lankhorst
2017-07-07 11:01     ` [Intel-gfx] " Daniel Vetter
2017-07-10  7:57       ` Maarten Lankhorst

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox