All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm: Handle atomic state properly in kms getfoo ioctl
@ 2014-11-25 22:50 Daniel Vetter
  2014-11-26 13:00 ` [PATCH] drm: Handle atomic state properly in kms getfoo shuang.he
  2014-11-26 15:52 ` [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Sean Paul
  0 siblings, 2 replies; 4+ messages in thread
From: Daniel Vetter @ 2014-11-25 22:50 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Intel Graphics Development, Daniel Vetter

So the problem with async commit (especially async modeset commit) is
that the legacy pointers only get updated after the point of no
return, in the async part of the modeset sequence. At least as
implemented by the current helper functions. This is done in the
set_routing_links function in drm_atomic_helper.c.

Which also means that access isn't protected by locks but only
coordinated by synchronizing with async workers. No problem thus far,
until we lock at the getconnector/encoder ioctls.

So fix this up by adding special cases for atomic drivers: For those
we need to look at state objects. Unfortunately digging out the
correct encoder->crtc link is a bit of work, so wrap this up in a
helper function.

Moving the assignments of connector->encoder and encoder->crtc earlier
isn't a good idea because the point of the atomic helpers is that we
stage the state updates. That way the disable functions can still
inspect the links and rely upon them.

v2: Extract full encoder->crtc lookup into helper (Rob).

v3: Extract drm_connector_get_encoder too since - we need to always
return state->best_encoder when there is a state otherwise we might
return stale data if there's a pending async disable (and chase
unlocked pointers, too). Same issue with encoder_get_crtc but there
it's a bit more tricky to handle.

Cc: Rob Clark <robdclark@gmail.com>
Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc.c | 49 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 589a921d4313..d51b1c1f6726 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1955,6 +1955,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
 	return true;
 }
 
+static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
+{
+	/* For atomic drivers only state objects are synchronously updated and
+	 * protected by modeset locks, so check those first. */
+	if (connector->state)
+		return connector->state->best_encoder;
+	return connector->encoder;
+}
+
 /**
  * drm_mode_getconnector - get connector configuration
  * @dev: drm device for the ioctl
@@ -1973,6 +1982,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 {
 	struct drm_mode_get_connector *out_resp = data;
 	struct drm_connector *connector;
+	struct drm_encoder *encoder;
 	struct drm_display_mode *mode;
 	int mode_count = 0;
 	int props_count = 0;
@@ -2028,8 +2038,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	out_resp->subpixel = connector->display_info.subpixel_order;
 	out_resp->connection = connector->status;
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	if (connector->encoder)
-		out_resp->encoder_id = connector->encoder->base.id;
+
+	encoder = drm_connector_get_encoder(connector);
+	if (encoder)
+		out_resp->encoder_id = encoder->base.id;
 	else
 		out_resp->encoder_id = 0;
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
@@ -2099,6 +2111,33 @@ out:
 	return ret;
 }
 
+static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
+{
+	struct drm_connector *connector;
+	struct drm_device *dev = encoder->dev;
+	bool uses_atomic = false;
+
+	/* For atomic drivers only state objects are synchronously updated and
+	 * protected by modeset locks, so check those first. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->state)
+			continue;
+
+		uses_atomic = true;
+
+		if (connector->state->best_encoder != encoder)
+			continue;
+
+		return connector->state->crtc;
+	}
+
+	/* Don't return stale data (e.g. pending async disable). */
+	if (uses_atomic)
+		return NULL;
+
+	return encoder->crtc;
+}
+
 /**
  * drm_mode_getencoder - get encoder configuration
  * @dev: drm device for the ioctl
@@ -2117,6 +2156,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
 {
 	struct drm_mode_get_encoder *enc_resp = data;
 	struct drm_encoder *encoder;
+	struct drm_crtc *crtc;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -2126,7 +2166,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
 		return -ENOENT;
 
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	if (encoder->crtc)
+	crtc = drm_encoder_get_crtc(encoder);
+	if (crtc)
+		enc_resp->crtc_id = crtc->base.id;
+	else if (encoder->crtc)
 		enc_resp->crtc_id = encoder->crtc->base.id;
 	else
 		enc_resp->crtc_id = 0;
-- 
2.1.1

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

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

* Re: [PATCH] drm: Handle atomic state properly in kms getfoo
  2014-11-25 22:50 [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Daniel Vetter
@ 2014-11-26 13:00 ` shuang.he
  2014-11-26 15:52 ` [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Sean Paul
  1 sibling, 0 replies; 4+ messages in thread
From: shuang.he @ 2014-11-26 13:00 UTC (permalink / raw)
  To: shuang.he, intel-gfx, daniel.vetter

Tested-By: PRC QA PRTS (Patch Regression Test System Contact: shuang.he@intel.com)
-------------------------------------Summary-------------------------------------
Platform          Delta          drm-intel-nightly          Series Applied
PNV                                  366/366              366/366
ILK                 -13              371/371              358/371
SNB                                  450/450              450/450
IVB                                  498/498              498/498
BYT                                  289/289              289/289
HSW                                  564/564              564/564
BDW                                  417/417              417/417
-------------------------------------Detailed-------------------------------------
Platform  Test                                drm-intel-nightly          Series Applied
 ILK  igt_gem_reset_stats_close-pending-fork-render      TIMEOUT(21, M37M26)PASS(1, M26)      TIMEOUT(1, M26)
 ILK  igt_kms_flip_nonexisting-fb      DMESG_WARN(3, M26)PASS(5, M37M26)      DMESG_WARN(1, M26)
*ILK  igt_kms_pipe_crc_basic_bad-nb-words-1      PASS(3, M37M26)      DMESG_WARN(1, M26)
*ILK  igt_kms_pipe_crc_basic_bad-pipe      PASS(4, M37M26)      DMESG_WARN(1, M26)
*ILK  igt_kms_pipe_crc_basic_bad-source      PASS(2, M37M26)      DMESG_WARN(1, M26)
 ILK  igt_kms_setmode_invalid-clone-exclusive-crtc      DMESG_WARN(1, M26)PASS(4, M37M26)      DMESG_WARN(1, M26)
 ILK  igt_kms_flip_rcs-wf_vblank-vs-modeset      DMESG_WARN(2, M26)PASS(4, M37M26)      DMESG_WARN(1, M26)
 ILK  igt_kms_flip_blocking-absolute-wf_vblank-interruptible      DMESG_WARN(2, M26)PASS(3, M37M26)      DMESG_WARN(1, M26)
 ILK  igt_kms_flip_flip-vs-wf_vblank-interruptible      DMESG_WARN(1, M26)PASS(2, M37M26)      DMESG_WARN(1, M26)
*ILK  igt_kms_flip_plain-flip-ts-check-interruptible      PASS(2, M37M26)      DMESG_WARN(1, M26)
 ILK  igt_kms_flip_rcs-flip-vs-modeset      DMESG_WARN(2, M26)PASS(3, M37M26)      DMESG_WARN(1, M26)
 ILK  igt_kms_flip_vblank-vs-hang      TIMEOUT(20, M37M26)PASS(1, M26)      TIMEOUT(1, M26)
*ILK  igt_kms_flip_wf_vblank-vs-modeset-interruptible      PASS(4, M37M26)      DMESG_WARN(1, M26)
Note: You need to pay more attention to line start with '*'
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm: Handle atomic state properly in kms getfoo ioctl
  2014-11-25 22:50 [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Daniel Vetter
  2014-11-26 13:00 ` [PATCH] drm: Handle atomic state properly in kms getfoo shuang.he
@ 2014-11-26 15:52 ` Sean Paul
  2014-11-26 17:21   ` Daniel Vetter
  1 sibling, 1 reply; 4+ messages in thread
From: Sean Paul @ 2014-11-26 15:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, Intel Graphics Development, DRI Development

On Tue, Nov 25, 2014 at 5:50 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> So the problem with async commit (especially async modeset commit) is
> that the legacy pointers only get updated after the point of no
> return, in the async part of the modeset sequence. At least as
> implemented by the current helper functions. This is done in the
> set_routing_links function in drm_atomic_helper.c.
>
> Which also means that access isn't protected by locks but only
> coordinated by synchronizing with async workers. No problem thus far,
> until we lock at the getconnector/encoder ioctls.
>
> So fix this up by adding special cases for atomic drivers: For those
> we need to look at state objects. Unfortunately digging out the
> correct encoder->crtc link is a bit of work, so wrap this up in a
> helper function.
>
> Moving the assignments of connector->encoder and encoder->crtc earlier
> isn't a good idea because the point of the atomic helpers is that we
> stage the state updates. That way the disable functions can still
> inspect the links and rely upon them.
>
> v2: Extract full encoder->crtc lookup into helper (Rob).
>
> v3: Extract drm_connector_get_encoder too since - we need to always
> return state->best_encoder when there is a state otherwise we might
> return stale data if there's a pending async disable (and chase
> unlocked pointers, too). Same issue with encoder_get_crtc but there
> it's a bit more tricky to handle.
>
> Cc: Rob Clark <robdclark@gmail.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>


My canary is still alive.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Lightly-Tested-by: Sean Paul <seanpaul@chromium.org>


> ---
>  drivers/gpu/drm/drm_crtc.c | 49 +++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 46 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 589a921d4313..d51b1c1f6726 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1955,6 +1955,15 @@ static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
>         return true;
>  }
>
> +static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
> +{
> +       /* For atomic drivers only state objects are synchronously updated and
> +        * protected by modeset locks, so check those first. */
> +       if (connector->state)
> +               return connector->state->best_encoder;
> +       return connector->encoder;
> +}
> +
>  /**
>   * drm_mode_getconnector - get connector configuration
>   * @dev: drm device for the ioctl
> @@ -1973,6 +1982,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
>  {
>         struct drm_mode_get_connector *out_resp = data;
>         struct drm_connector *connector;
> +       struct drm_encoder *encoder;
>         struct drm_display_mode *mode;
>         int mode_count = 0;
>         int props_count = 0;
> @@ -2028,8 +2038,10 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
>         out_resp->subpixel = connector->display_info.subpixel_order;
>         out_resp->connection = connector->status;
>         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -       if (connector->encoder)
> -               out_resp->encoder_id = connector->encoder->base.id;
> +
> +       encoder = drm_connector_get_encoder(connector);
> +       if (encoder)
> +               out_resp->encoder_id = encoder->base.id;
>         else
>                 out_resp->encoder_id = 0;
>         drm_modeset_unlock(&dev->mode_config.connection_mutex);
> @@ -2099,6 +2111,33 @@ out:
>         return ret;
>  }
>
> +static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
> +{
> +       struct drm_connector *connector;
> +       struct drm_device *dev = encoder->dev;
> +       bool uses_atomic = false;
> +
> +       /* For atomic drivers only state objects are synchronously updated and
> +        * protected by modeset locks, so check those first. */
> +       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +               if (!connector->state)
> +                       continue;
> +
> +               uses_atomic = true;
> +
> +               if (connector->state->best_encoder != encoder)
> +                       continue;
> +
> +               return connector->state->crtc;
> +       }
> +
> +       /* Don't return stale data (e.g. pending async disable). */
> +       if (uses_atomic)
> +               return NULL;
> +
> +       return encoder->crtc;
> +}
> +
>  /**
>   * drm_mode_getencoder - get encoder configuration
>   * @dev: drm device for the ioctl
> @@ -2117,6 +2156,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
>  {
>         struct drm_mode_get_encoder *enc_resp = data;
>         struct drm_encoder *encoder;
> +       struct drm_crtc *crtc;
>
>         if (!drm_core_check_feature(dev, DRIVER_MODESET))
>                 return -EINVAL;
> @@ -2126,7 +2166,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
>                 return -ENOENT;
>
>         drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -       if (encoder->crtc)
> +       crtc = drm_encoder_get_crtc(encoder);
> +       if (crtc)
> +               enc_resp->crtc_id = crtc->base.id;
> +       else if (encoder->crtc)
>                 enc_resp->crtc_id = encoder->crtc->base.id;
>         else
>                 enc_resp->crtc_id = 0;
> --
> 2.1.1
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH] drm: Handle atomic state properly in kms getfoo ioctl
  2014-11-26 15:52 ` [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Sean Paul
@ 2014-11-26 17:21   ` Daniel Vetter
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Vetter @ 2014-11-26 17:21 UTC (permalink / raw)
  To: Sean Paul
  Cc: Daniel Vetter, Intel Graphics Development, DRI Development,
	Daniel Vetter

On Wed, Nov 26, 2014 at 10:52:24AM -0500, Sean Paul wrote:
> On Tue, Nov 25, 2014 at 5:50 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > So the problem with async commit (especially async modeset commit) is
> > that the legacy pointers only get updated after the point of no
> > return, in the async part of the modeset sequence. At least as
> > implemented by the current helper functions. This is done in the
> > set_routing_links function in drm_atomic_helper.c.
> >
> > Which also means that access isn't protected by locks but only
> > coordinated by synchronizing with async workers. No problem thus far,
> > until we lock at the getconnector/encoder ioctls.
> >
> > So fix this up by adding special cases for atomic drivers: For those
> > we need to look at state objects. Unfortunately digging out the
> > correct encoder->crtc link is a bit of work, so wrap this up in a
> > helper function.
> >
> > Moving the assignments of connector->encoder and encoder->crtc earlier
> > isn't a good idea because the point of the atomic helpers is that we
> > stage the state updates. That way the disable functions can still
> > inspect the links and rely upon them.
> >
> > v2: Extract full encoder->crtc lookup into helper (Rob).
> >
> > v3: Extract drm_connector_get_encoder too since - we need to always
> > return state->best_encoder when there is a state otherwise we might
> > return stale data if there's a pending async disable (and chase
> > unlocked pointers, too). Same issue with encoder_get_crtc but there
> > it's a bit more tricky to handle.
> >
> > Cc: Rob Clark <robdclark@gmail.com>
> > Cc: Sean Paul <seanpaul@chromium.org>
> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> 
> 
> My canary is still alive.
> 
> Reviewed-by: Sean Paul <seanpaul@chromium.org>
> Lightly-Tested-by: Sean Paul <seanpaul@chromium.org>

Put onto my atomic fixes pile, thanks for review&testing.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2014-11-26 17:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-25 22:50 [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Daniel Vetter
2014-11-26 13:00 ` [PATCH] drm: Handle atomic state properly in kms getfoo shuang.he
2014-11-26 15:52 ` [PATCH] drm: Handle atomic state properly in kms getfoo ioctl Sean Paul
2014-11-26 17:21   ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.