diff options
| -rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_dotclock.c | 12 | ||||
| -rw-r--r-- | include/drm/drm_atomic.h | 11 |
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); | |||
| 1408 | void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, | 1408 | void 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 { | |||
| 153 | struct __drm_crtcs_state { | 153 | struct __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 | }; |
