All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rob Clark <robdclark@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: Sean Paul <seanpaul@chromium.org>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Rob Clark <robdclark@chromium.org>,
	Maxime Ripard <mripard@kernel.org>, Sean Paul <sean@poorly.run>,
	David Airlie <airlied@linux.ie>, Daniel Vetter <daniel@ffwll.ch>,
	linux-kernel@vger.kernel.org (open list)
Subject: [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference
Date: Fri,  1 Nov 2019 11:07:12 -0700	[thread overview]
Message-ID: <20191101180713.5470-1-robdclark@gmail.com> (raw)

From: Rob Clark <robdclark@chromium.org>

drm_self_refresh_helper_update_avg_times() was incorrectly accessing the
new incoming state after drm_atomic_helper_commit_hw_done().  But this
state might have already been superceeded by an !nonblock atomic update
resulting in dereferencing an already free'd crtc_state.

Fixes: d4da4e33341c ("drm: Measure Self Refresh Entry/Exit times to avoid thrashing")
Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
---
TODO I *think* this will more or less do the right thing.. althought I'm
not 100% sure if, for example, we enter psr in a nonblock commit, and
then leave psr in a !nonblock commit that overtakes the completion of
the nonblock commit.  Not sure if this sort of scenario can happen in
practice.  But not crashing is better than crashing, so I guess we
should either take this patch or rever the self-refresh helpers until
Sean can figure out a better solution.

 drivers/gpu/drm/drm_atomic_helper.c       |  2 ++
 drivers/gpu/drm/drm_self_refresh_helper.c | 11 ++++++-----
 include/drm/drm_atomic.h                  |  8 ++++++++
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 3ef2ac52ce94..732bd0ce9241 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2240,6 +2240,8 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
 	int i;
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
+		old_state->crtcs[i].new_self_refresh_active = new_crtc_state->self_refresh_active;
+
 		commit = new_crtc_state->commit;
 		if (!commit)
 			continue;
diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c
index 68f4765a5896..77b9079fa578 100644
--- a/drivers/gpu/drm/drm_self_refresh_helper.c
+++ b/drivers/gpu/drm/drm_self_refresh_helper.c
@@ -143,19 +143,20 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
 					      unsigned int commit_time_ms)
 {
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+	struct drm_crtc_state *old_crtc_state;
 	int i;
 
-	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
-				      new_crtc_state, i) {
+	for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
+		bool new_self_refresh_active =
+				state->crtcs[i].new_self_refresh_active;
 		struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
 		struct ewma_psr_time *time;
 
 		if (old_crtc_state->self_refresh_active ==
-		    new_crtc_state->self_refresh_active)
+		    new_self_refresh_active)
 			continue;
 
-		if (new_crtc_state->self_refresh_active)
+		if (new_self_refresh_active)
 			time = &sr_data->entry_avg_ms;
 		else
 			time = &sr_data->exit_avg_ms;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 927e1205d7aa..86baf2b38bb3 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -155,6 +155,14 @@ struct __drm_crtcs_state {
 	struct drm_crtc *ptr;
 	struct drm_crtc_state *state, *old_state, *new_state;
 
+	/**
+	 * @new_self_refresh_active:
+	 *
+	 * drm_atomic_helper_commit_hw_done() stashes new_crtc_state->self_refresh_active
+	 * so that it can be accessed late in drm_self_refresh_helper_update_avg_times().
+	 */
+	bool new_self_refresh_active;
+
 	/**
 	 * @commit:
 	 *
-- 
2.21.0


WARNING: multiple messages have this Message-ID (diff)
From: Rob Clark <robdclark@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: Sean Paul <seanpaul@chromium.org>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Rob Clark <robdclark@chromium.org>,
	Maxime Ripard <mripard@kernel.org>, Sean Paul <sean@poorly.run>,
	David Airlie <airlied@linux.ie>, Daniel Vetter <daniel@ffwll.ch>,
	open list <linux-kernel@vger.kernel.org>
Subject: [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference
Date: Fri,  1 Nov 2019 11:07:12 -0700	[thread overview]
Message-ID: <20191101180713.5470-1-robdclark@gmail.com> (raw)

From: Rob Clark <robdclark@chromium.org>

drm_self_refresh_helper_update_avg_times() was incorrectly accessing the
new incoming state after drm_atomic_helper_commit_hw_done().  But this
state might have already been superceeded by an !nonblock atomic update
resulting in dereferencing an already free'd crtc_state.

Fixes: d4da4e33341c ("drm: Measure Self Refresh Entry/Exit times to avoid thrashing")
Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
---
TODO I *think* this will more or less do the right thing.. althought I'm
not 100% sure if, for example, we enter psr in a nonblock commit, and
then leave psr in a !nonblock commit that overtakes the completion of
the nonblock commit.  Not sure if this sort of scenario can happen in
practice.  But not crashing is better than crashing, so I guess we
should either take this patch or rever the self-refresh helpers until
Sean can figure out a better solution.

 drivers/gpu/drm/drm_atomic_helper.c       |  2 ++
 drivers/gpu/drm/drm_self_refresh_helper.c | 11 ++++++-----
 include/drm/drm_atomic.h                  |  8 ++++++++
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 3ef2ac52ce94..732bd0ce9241 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2240,6 +2240,8 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
 	int i;
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
+		old_state->crtcs[i].new_self_refresh_active = new_crtc_state->self_refresh_active;
+
 		commit = new_crtc_state->commit;
 		if (!commit)
 			continue;
diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c
index 68f4765a5896..77b9079fa578 100644
--- a/drivers/gpu/drm/drm_self_refresh_helper.c
+++ b/drivers/gpu/drm/drm_self_refresh_helper.c
@@ -143,19 +143,20 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
 					      unsigned int commit_time_ms)
 {
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+	struct drm_crtc_state *old_crtc_state;
 	int i;
 
-	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
-				      new_crtc_state, i) {
+	for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
+		bool new_self_refresh_active =
+				state->crtcs[i].new_self_refresh_active;
 		struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
 		struct ewma_psr_time *time;
 
 		if (old_crtc_state->self_refresh_active ==
-		    new_crtc_state->self_refresh_active)
+		    new_self_refresh_active)
 			continue;
 
-		if (new_crtc_state->self_refresh_active)
+		if (new_self_refresh_active)
 			time = &sr_data->entry_avg_ms;
 		else
 			time = &sr_data->exit_avg_ms;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 927e1205d7aa..86baf2b38bb3 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -155,6 +155,14 @@ struct __drm_crtcs_state {
 	struct drm_crtc *ptr;
 	struct drm_crtc_state *state, *old_state, *new_state;
 
+	/**
+	 * @new_self_refresh_active:
+	 *
+	 * drm_atomic_helper_commit_hw_done() stashes new_crtc_state->self_refresh_active
+	 * so that it can be accessed late in drm_self_refresh_helper_update_avg_times().
+	 */
+	bool new_self_refresh_active;
+
 	/**
 	 * @commit:
 	 *
-- 
2.21.0

WARNING: multiple messages have this Message-ID (diff)
From: Rob Clark <robdclark@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: Rob Clark <robdclark@chromium.org>,
	David Airlie <airlied@linux.ie>,
	open list <linux-kernel@vger.kernel.org>,
	Sean Paul <seanpaul@chromium.org>, Sean Paul <sean@poorly.run>
Subject: [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference
Date: Fri,  1 Nov 2019 11:07:12 -0700	[thread overview]
Message-ID: <20191101180713.5470-1-robdclark@gmail.com> (raw)
Message-ID: <20191101180712.55MZS5zcT2rtyIytF227U0eoRvPklZ4QxaJ8avE0bQI@z> (raw)

From: Rob Clark <robdclark@chromium.org>

drm_self_refresh_helper_update_avg_times() was incorrectly accessing the
new incoming state after drm_atomic_helper_commit_hw_done().  But this
state might have already been superceeded by an !nonblock atomic update
resulting in dereferencing an already free'd crtc_state.

Fixes: d4da4e33341c ("drm: Measure Self Refresh Entry/Exit times to avoid thrashing")
Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
---
TODO I *think* this will more or less do the right thing.. althought I'm
not 100% sure if, for example, we enter psr in a nonblock commit, and
then leave psr in a !nonblock commit that overtakes the completion of
the nonblock commit.  Not sure if this sort of scenario can happen in
practice.  But not crashing is better than crashing, so I guess we
should either take this patch or rever the self-refresh helpers until
Sean can figure out a better solution.

 drivers/gpu/drm/drm_atomic_helper.c       |  2 ++
 drivers/gpu/drm/drm_self_refresh_helper.c | 11 ++++++-----
 include/drm/drm_atomic.h                  |  8 ++++++++
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 3ef2ac52ce94..732bd0ce9241 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2240,6 +2240,8 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
 	int i;
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
+		old_state->crtcs[i].new_self_refresh_active = new_crtc_state->self_refresh_active;
+
 		commit = new_crtc_state->commit;
 		if (!commit)
 			continue;
diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c
index 68f4765a5896..77b9079fa578 100644
--- a/drivers/gpu/drm/drm_self_refresh_helper.c
+++ b/drivers/gpu/drm/drm_self_refresh_helper.c
@@ -143,19 +143,20 @@ void drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
 					      unsigned int commit_time_ms)
 {
 	struct drm_crtc *crtc;
-	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+	struct drm_crtc_state *old_crtc_state;
 	int i;
 
-	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
-				      new_crtc_state, i) {
+	for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
+		bool new_self_refresh_active =
+				state->crtcs[i].new_self_refresh_active;
 		struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
 		struct ewma_psr_time *time;
 
 		if (old_crtc_state->self_refresh_active ==
-		    new_crtc_state->self_refresh_active)
+		    new_self_refresh_active)
 			continue;
 
-		if (new_crtc_state->self_refresh_active)
+		if (new_self_refresh_active)
 			time = &sr_data->entry_avg_ms;
 		else
 			time = &sr_data->exit_avg_ms;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 927e1205d7aa..86baf2b38bb3 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -155,6 +155,14 @@ struct __drm_crtcs_state {
 	struct drm_crtc *ptr;
 	struct drm_crtc_state *state, *old_state, *new_state;
 
+	/**
+	 * @new_self_refresh_active:
+	 *
+	 * drm_atomic_helper_commit_hw_done() stashes new_crtc_state->self_refresh_active
+	 * so that it can be accessed late in drm_self_refresh_helper_update_avg_times().
+	 */
+	bool new_self_refresh_active;
+
 	/**
 	 * @commit:
 	 *
-- 
2.21.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

             reply	other threads:[~2019-11-01 18:09 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-01 18:07 Rob Clark [this message]
2019-11-01 18:07 ` [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference Rob Clark
2019-11-01 18:07 ` Rob Clark
2019-11-01 18:07 ` [PATCH 2/2] drm/atomic: clear new_state pointers at hw_done Rob Clark
2019-11-01 18:07   ` Rob Clark
2019-11-01 18:07   ` Rob Clark
2019-11-01 18:33   ` Maarten Lankhorst
2019-11-01 18:33     ` Maarten Lankhorst
2019-11-01 19:44     ` Rob Clark
2019-11-01 19:44       ` Rob Clark
2019-11-01 19:24   ` Ville Syrjälä
2019-11-01 19:24     ` Ville Syrjälä
2019-11-01 19:49     ` Rob Clark
2019-11-01 19:49       ` Rob Clark
2019-11-01 21:44       ` Ville Syrjälä
2019-11-01 21:44         ` Ville Syrjälä
2019-11-01 22:14         ` Rob Clark
2019-11-01 22:14           ` Rob Clark
2019-11-04 18:41           ` Ville Syrjälä
2019-11-04 18:41             ` Ville Syrjälä
2019-11-04 19:13             ` Rob Clark
2019-11-04 19:13               ` Rob Clark
2019-11-04 20:50               ` Ville Syrjälä
2019-11-04 20:50                 ` Ville Syrjälä
2019-11-04 21:11                 ` Rob Clark
2019-11-04 21:11                   ` Rob Clark
2019-11-06  2:58   ` [drm/atomic] 554231a5c5: BUG:kernel_NULL_pointer_dereference,address kernel test robot
2019-11-06  2:58     ` [drm/atomic] 554231a5c5: BUG:kernel_NULL_pointer_dereference, address kernel test robot
2019-11-06  2:58     ` [drm/atomic] 554231a5c5: BUG:kernel_NULL_pointer_dereference,address kernel test robot
2019-11-01 20:06 ` [PATCH 1/2] drm/atomic: fix self-refresh helpers crtc state dereference Sean Paul
2019-11-01 20:06   ` Sean Paul
2019-11-04  9:29   ` Maarten Lankhorst
2019-11-04  9:29     ` Maarten Lankhorst

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191101180713.5470-1-robdclark@gmail.com \
    --to=robdclark@gmail.com \
    --cc=airlied@linux.ie \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=robdclark@chromium.org \
    --cc=sean@poorly.run \
    --cc=seanpaul@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.