From patchwork Tue Apr 3 22:42:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 10321845 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8688C60467 for ; Tue, 3 Apr 2018 22:42:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B1211260CD for ; Tue, 3 Apr 2018 22:42:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A5BEA27D4A; Tue, 3 Apr 2018 22:42:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 036DB260CD for ; Tue, 3 Apr 2018 22:42:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753658AbeDCWme (ORCPT ); Tue, 3 Apr 2018 18:42:34 -0400 Received: from mail-qk0-f193.google.com ([209.85.220.193]:39151 "EHLO mail-qk0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753398AbeDCWmd (ORCPT ); Tue, 3 Apr 2018 18:42:33 -0400 Received: by mail-qk0-f193.google.com with SMTP id j73so20521159qke.6; Tue, 03 Apr 2018 15:42:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=oqd3gdszyHIn0pFJkmMS8PT9QAuVKffU/GqUrkRurls=; b=thuxdHSKGyhbh9sSVobKzHIVTAAQ036iPIrNw52pu63MZT1sxUjjWlmZ6jfnisCs4C 3oE94ymasGfxnS8JUt6KLrFGV0L4dCUaM4W7UU3J3jCu92Ps6Hmj8aUsZjBvbThQnLU6 118wmULUdLNkhuZg5Y1AHhr1Q8stPkJOAWDOiAnVwHh/rsuBUVE6rCxfq/CT++zg1u+w s5w0tBZcAQsm5o3yT2jZHu5T7FIHz8PhfT3kQAfrAGkeAVTJObn3eCcanVWh61rlCL6M 58g5zUbZl0DYTac9tC5OIu8oWMmA2X8kyJOYOqhQP73NRYY5/EVFyl2NLzFC+CQjos29 0VVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=oqd3gdszyHIn0pFJkmMS8PT9QAuVKffU/GqUrkRurls=; b=Xedsjx09CsLfWDiGYq5piLWusNx1yEJFdA7CzplRq5TFa3IMOK/KBYqw3pHZo9Z4Gw rlLeFdKATwjBONYiJt7k0SK2prDDvC6ByKn7T6D7g3WoYFdMx9AjBCkbywEO58F/XcGN /odnDrwD2+mSBkSwuGrX4F4NTrS0S748qSIngXW+9gx6+Do7flSJ8QLa7dB7G0Ns59f1 R/ncFIk+1psp8tE63mMwVxfOvVu65zVTt4TRSkIErPiIDYOLpHVGtx1qJ/GWkggTYpwT AyZ/To6xePE1zfawy15z4uuz1lnV+kg2RmeeyjadJqimj8X88izQx59VpSop+NDkWU3f TTBw== X-Gm-Message-State: ALQs6tC4vvB99iqfrFu7MqM7OM0KtXPvZhVqbca3ExdaEDgtafB35SRr DuheHpL640A9tuo/4EUpRMA= X-Google-Smtp-Source: AIpwx49btLhbs/IiP43gIaBrKhNDUVf0OGC7Hw1lGtO/dt0p5ksiQxghns6O09YPzN6hF04t5I/W4Q== X-Received: by 10.55.23.11 with SMTP id i11mr21272736qkh.333.1522795352821; Tue, 03 Apr 2018 15:42:32 -0700 (PDT) Received: from localhost ([2601:184:4780:7861:f0f3:2e63:b9c2:ceee]) by smtp.gmail.com with ESMTPSA id 42sm3271679qty.51.2018.04.03.15.42.31 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 03 Apr 2018 15:42:32 -0700 (PDT) From: Rob Clark To: dri-devel@lists.freedesktop.org Cc: freedreno@lists.freedesktop.org, linux-arm-msm@vger.kernel.org, Daniel Vetter , Thomas Hellstrom , =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= , Lukasz Spintzyk , Deepak Singh Rawat , Rob Clark , Gustavo Padovan , Maarten Lankhorst , Sean Paul , David Airlie , linux-kernel@vger.kernel.org Subject: [RFC] drm/atomic+msm: add helper to implement legacy dirtyfb Date: Tue, 3 Apr 2018 18:42:23 -0400 Message-Id: <20180403224225.26776-1-robdclark@gmail.com> X-Mailer: git-send-email 2.14.3 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add an atomic helper to implement dirtyfb support. This is needed to support DSI command-mode panels with x11 userspace (ie. when we can't rely on pageflips to trigger a flush to the panel). To signal to the driver that the async atomic update needs to synchronize with fences, even though the fb didn't change, the drm_atomic_state::dirty flag is added. Signed-off-by: Rob Clark --- Background: there are a number of different folks working on getting upstream kernel working on various different phones/tablets with qcom SoC's.. many of them have command mode panels, so we kind of need a way to support the legacy dirtyfb ioctl for x11 support. I know there is work on a proprer non-legacy atomic property for userspace to communicate dirty-rect(s) to the kernel, so this can be improved from triggering a full-frame flush once that is in place. But we kinda needa a stop-gap solution. I had considered an in-driver solution for this, but things get a bit tricky if userspace ands up combining dirtyfb ioctls with page- flips, because we need to synchronize setting various CTL.FLUSH bits with setting the CTL.START bit. (ie. really all we need to do for cmd mode panels is bang CTL.START, but is this ends up racing with pageflips setting FLUSH bits, then bad things.) The easiest soln is to wrap this up as an atomic commit and rely on the worker to serialize things. Hence adding an atomic dirtyfb helper. I guess at least the helper, with some small addition to translate and pass-thru the dirty rect(s) is useful to the final atomic dirty- rect property solution. Depending on how far off that is, a stop- gap solution could be useful. drivers/gpu/drm/drm_atomic_helper.c | 66 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_atomic.c | 5 ++- drivers/gpu/drm/msm/msm_fb.c | 1 + include/drm/drm_atomic_helper.h | 4 +++ include/drm/drm_plane.h | 9 +++++ 5 files changed, 84 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index c35654591c12..a578dc681b27 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3504,6 +3504,7 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane, if (state->fb) drm_framebuffer_get(state->fb); + state->dirty = false; state->fence = NULL; state->commit = NULL; } @@ -3847,6 +3848,71 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); +/** + * drm_atomic_helper_dirtyfb - helper for dirtyfb + * + * A helper to implement drm_framebuffer_funcs::dirty + */ +int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned flags, + unsigned color, struct drm_clip_rect *clips, + unsigned num_clips) +{ + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_plane *plane; + int ret = 0; + + /* + * When called from ioctl, we are interruptable, but not when + * called internally (ie. defio worker) + */ + drm_modeset_acquire_init(&ctx, + file_priv ? DRM_MODESET_ACQUIRE_INTERRUPTIBLE : 0); + + state = drm_atomic_state_alloc(fb->dev); + if (!state) { + ret = -ENOMEM; + goto out; + } + state->acquire_ctx = &ctx; + +retry: + drm_for_each_plane(plane, fb->dev) { + struct drm_plane_state *plane_state; + + if (plane->state->fb != fb) + continue; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + goto out; + } + + plane_state->dirty = true; + } + + ret = drm_atomic_nonblocking_commit(state); + +out: + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } + + drm_atomic_state_put(state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +} +EXPORT_SYMBOL(drm_atomic_helper_dirtyfb); + /** * __drm_atomic_helper_private_duplicate_state - copy atomic private state * @obj: CRTC object diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index bf5f8c39f34d..bb55a048e98b 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -201,7 +201,10 @@ int msm_atomic_commit(struct drm_device *dev, * Figure out what fence to wait for: */ for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { - if ((new_plane_state->fb != old_plane_state->fb) && new_plane_state->fb) { + bool sync_fb = new_plane_state->fb && + ((new_plane_state->fb != old_plane_state->fb) || + new_plane_state->dirty); + if (sync_fb) { struct drm_gem_object *obj = msm_framebuffer_bo(new_plane_state->fb, 0); struct msm_gem_object *msm_obj = to_msm_bo(obj); struct dma_fence *fence = reservation_object_get_excl_rcu(msm_obj->resv); diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 0e0c87252ab0..a5d882a34a33 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -62,6 +62,7 @@ static void msm_framebuffer_destroy(struct drm_framebuffer *fb) static const struct drm_framebuffer_funcs msm_framebuffer_funcs = { .create_handle = msm_framebuffer_create_handle, .destroy = msm_framebuffer_destroy, + .dirty = drm_atomic_helper_dirtyfb, }; #ifdef CONFIG_DEBUG_FS diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 26aaba58d6ce..9b7a95c2643d 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -183,6 +183,10 @@ int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, uint32_t size, struct drm_modeset_acquire_ctx *ctx); +int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned flags, + unsigned color, struct drm_clip_rect *clips, + unsigned num_clips); void __drm_atomic_helper_private_obj_duplicate_state(struct drm_private_obj *obj, struct drm_private_state *state); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index f7bf4a48b1c3..296fa22bda7a 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -76,6 +76,15 @@ struct drm_plane_state { */ struct drm_framebuffer *fb; + /** + * @dirty: + * + * Flag that indicates the fb contents have changed even though the + * fb has not. This is mostly a stop-gap solution until we have + * atomic dirty-rect(s) property. + */ + bool dirty; + /** * @fence: *