[Intel-gfx] [PATCH 2/8] drm/i915: Handle cursor updating active_planes correctly, v2.
Maarten Lankhorst
maarten.lankhorst at linux.intel.com
Fri Sep 21 09:41:14 UTC 2018
Op 21-09-18 om 01:18 schreef Matt Roper:
> On Thu, Sep 20, 2018 at 12:27:05PM +0200, Maarten Lankhorst wrote:
>> While we may not update new_crtc_state, we may clear active_planes
>> if the new cursor update state will disable the cursor, but we fail
>> after. If this is immediately followed by a modeset disable, we may
>> soon not disable the planes correctly when we start depending on
>> active_planes.
>>
>> Changes since v1:
>> - Clarify why we cannot swap crtc_state. (Matt)
>>
>> Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
>> ---
>> drivers/gpu/drm/i915/intel_display.c | 36 +++++++++++++++++++++-------
>> 1 file changed, 28 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 58c188482c78..078cdcca88e1 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -13515,14 +13515,16 @@ intel_legacy_cursor_update(struct drm_plane *plane,
>> struct drm_plane_state *old_plane_state, *new_plane_state;
>> struct intel_plane *intel_plane = to_intel_plane(plane);
>> struct drm_framebuffer *old_fb;
>> - struct drm_crtc_state *crtc_state = crtc->state;
>> + struct intel_crtc_state *crtc_state =
>> + to_intel_crtc_state(crtc->state);
>> + struct intel_crtc_state *new_crtc_state;
>>
>> /*
>> * When crtc is inactive or there is a modeset pending,
>> * wait for it to complete in the slowpath
>> */
>> - if (!crtc_state->active || needs_modeset(crtc_state) ||
>> - to_intel_crtc_state(crtc_state)->update_pipe)
>> + if (!crtc_state->base.active || needs_modeset(&crtc_state->base) ||
>> + crtc_state->update_pipe)
>> goto slow;
>>
>> old_plane_state = plane->state;
>> @@ -13552,6 +13554,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
>> if (!new_plane_state)
>> return -ENOMEM;
>>
>> + new_crtc_state = to_intel_crtc_state(intel_crtc_duplicate_state(crtc));
>> + if (!new_crtc_state) {
>> + ret = -ENOMEM;
>> + goto out_free;
>> + }
>> +
>> drm_atomic_set_fb_for_plane(new_plane_state, fb);
>>
>> new_plane_state->src_x = src_x;
>> @@ -13563,9 +13571,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
>> new_plane_state->crtc_w = crtc_w;
>> new_plane_state->crtc_h = crtc_h;
>>
>> - ret = intel_plane_atomic_check_with_state(to_intel_crtc_state(crtc->state),
>> - to_intel_crtc_state(crtc->state), /* FIXME need a new crtc state? */
>> - to_intel_plane_state(plane->state),
>> + ret = intel_plane_atomic_check_with_state(crtc_state, new_crtc_state,
>> + to_intel_plane_state(old_plane_state),
>> to_intel_plane_state(new_plane_state));
>> if (ret)
>> goto out_free;
>> @@ -13587,10 +13594,21 @@ intel_legacy_cursor_update(struct drm_plane *plane,
>> /* Swap plane state */
>> plane->state = new_plane_state;
>>
>> + /*
>> + * We cannot swap crtc_state as it may be in use by an atomic commit or
>> + * page flip that's running simultaneously. If we swap crtc_state and
>> + * destroy the old state, we will cause a use-after-free there.
> Just to confirm, the commit running simultaneously would have to have
> already dropped locks (specifically the crtc lock) and returned to
> userspace for us to have this problem, right? So it's either a
> non-blocking commit in the process of doing its programming via
> workqueue, or a blocking commit that's done everything except
> intel_atomic_cleanup_work?
>
> Reviewed-by: Matt Roper <matthew.d.roper at intel.com>
Anything before drm_atomic_helper_commit_hw_done().
Cleanup work is done after, and isn't allowed to look at new state any more. :)
More information about the Intel-gfx
mailing list