aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_atomic.c5
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c12
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_dotclock.c12
-rw-r--r--include/drm/drm_atomic.h11
4 files changed, 35 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 018fcdb353d2..281cf9cbb44c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -174,6 +174,11 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
174 state->crtcs[i].state = NULL; 174 state->crtcs[i].state = NULL;
175 state->crtcs[i].old_state = NULL; 175 state->crtcs[i].old_state = NULL;
176 state->crtcs[i].new_state = NULL; 176 state->crtcs[i].new_state = NULL;
177
178 if (state->crtcs[i].commit) {
179 drm_crtc_commit_put(state->crtcs[i].commit);
180 state->crtcs[i].commit = NULL;
181 }
177 } 182 }
178 183
179 for (i = 0; i < config->num_total_plane; i++) { 184 for (i = 0; i < config->num_total_plane; i++) {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 80be74df7ba6..1bb4c318bdd4 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1408,15 +1408,16 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
1408void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, 1408void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
1409 struct drm_atomic_state *old_state) 1409 struct drm_atomic_state *old_state)
1410{ 1410{
1411 struct drm_crtc_state *new_crtc_state;
1412 struct drm_crtc *crtc; 1411 struct drm_crtc *crtc;
1413 int i; 1412 int i;
1414 1413
1415 for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) { 1414 for (i = 0; i < dev->mode_config.num_crtc; i++) {
1416 struct drm_crtc_commit *commit = new_crtc_state->commit; 1415 struct drm_crtc_commit *commit = old_state->crtcs[i].commit;
1417 int ret; 1416 int ret;
1418 1417
1419 if (!commit) 1418 crtc = old_state->crtcs[i].ptr;
1419
1420 if (!crtc || !commit)
1420 continue; 1421 continue;
1421 1422
1422 ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ); 1423 ret = wait_for_completion_timeout(&commit->flip_done, 10 * HZ);
@@ -1934,6 +1935,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
1934 drm_crtc_commit_get(commit); 1935 drm_crtc_commit_get(commit);
1935 1936
1936 commit->abort_completion = true; 1937 commit->abort_completion = true;
1938
1939 state->crtcs[i].commit = commit;
1940 drm_crtc_commit_get(commit);
1937 } 1941 }
1938 1942
1939 for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) { 1943 for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) {
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
index e36004fbe453..2a15f2f9271e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c
+++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c
@@ -81,9 +81,19 @@ static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
81 int i; 81 int i;
82 82
83 for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) { 83 for (i = tcon->dclk_min_div; i <= tcon->dclk_max_div; i++) {
84 unsigned long ideal = rate * i; 84 u64 ideal = (u64)rate * i;
85 unsigned long rounded; 85 unsigned long rounded;
86 86
87 /*
88 * ideal has overflowed the max value that can be stored in an
89 * unsigned long, and every clk operation we might do on a
90 * truncated u64 value will give us incorrect results.
91 * Let's just stop there since bigger dividers will result in
92 * the same overflow issue.
93 */
94 if (ideal > ULONG_MAX)
95 goto out;
96
87 rounded = clk_hw_round_rate(clk_hw_get_parent(hw), 97 rounded = clk_hw_round_rate(clk_hw_get_parent(hw),
88 ideal); 98 ideal);
89 99
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index da9d95a19580..1e713154f00e 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -153,6 +153,17 @@ struct __drm_planes_state {
153struct __drm_crtcs_state { 153struct __drm_crtcs_state {
154 struct drm_crtc *ptr; 154 struct drm_crtc *ptr;
155 struct drm_crtc_state *state, *old_state, *new_state; 155 struct drm_crtc_state *state, *old_state, *new_state;
156
157 /**
158 * @commit:
159 *
160 * A reference to the CRTC commit object that is kept for use by
161 * drm_atomic_helper_wait_for_flip_done() after
162 * drm_atomic_helper_commit_hw_done() is called. This ensures that a
163 * concurrent commit won't free a commit object that is still in use.
164 */
165 struct drm_crtc_commit *commit;
166
156 s32 __user *out_fence_ptr; 167 s32 __user *out_fence_ptr;
157 u64 last_vblank_count; 168 u64 last_vblank_count;
158}; 169};