From patchwork Fri May 18 15:17:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liviu Dudau X-Patchwork-Id: 136322 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1371763lji; Fri, 18 May 2018 08:18:12 -0700 (PDT) X-Google-Smtp-Source: AB8JxZoXz2o9mB82D1s5sYXFlt2/ECx01CV9zs8W2WrL3qVwwPNEVpeydn5K78krWpohakIsXHF5 X-Received: by 2002:a62:a65c:: with SMTP id t89-v6mr9848395pfe.27.1526656692797; Fri, 18 May 2018 08:18:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526656692; cv=none; d=google.com; s=arc-20160816; b=R2ILrNoiYG6TEchPiIgOR3P1Ye8p80K/pkXI3Q5N4TsJn7lOdox5RVs74pLGRa9UMO glDGd54HxcLU4baD/Z6+IpncvzIDVvTvgfXkGFNch5MJh3ZASuoAm+q9kE31WcAfldoi 81j8oeyleuz/JUpXWWzYKaAMB2B7NU7jK4RPZKDSQlS4QZnxVJhcaPu59o/XesrlygMh RlYLRtn3rS5i72NgUiJq/y2q1ZVOyhK0xPQlSSUpPV2A0nQqeuVdf6UGLNOj3rMjQsvD GJX4J2mjNHtYNx5XV2Qnh06ld5aJnQBLXHzUcgnGkDAha221orXUWEA/1UF4A3xYQwOR mMTg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=KMzE6Wz0WO12Ydf38d5qAAl7e3vzQM3SRa4yYeTmsvE=; b=MWWUWCHk3PANgKzN8z6egooatuT+2oujkdEyFSwbqihrhjNY9xeGbnM5kOKu5NpGRh YJhLKoc9LMyX0UJJ+vi/QvLYho3yf8+NDqT0ZXyRyuEARlpdPy8JB8dk22xsppnyeAtl ordPnJajSeM+cZY22fHQ9tgOP4AmNkH1PnlvFvK5gJAdxtX2Z5GXiRA0JGrkF3nQFeaG 98Vf9ayk3qeyZM5p/e8zH8ltqP0YQHSw7VDGViEEVSdqSeQkHoCvd+mD3iRFwdcWMAXh xvuNdL3IU6DuNUIbjeV0pmfggJKiESN7W/pyI6py0URyTpfskEuzWHrTkd+c+/ZpoSq2 f0fQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r1-v6si7552661plo.414.2018.05.18.08.18.12; Fri, 18 May 2018 08:18:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752188AbeERPSK (ORCPT + 29 others); Fri, 18 May 2018 11:18:10 -0400 Received: from fw-tnat.cambridge.arm.com ([217.140.96.140]:22000 "EHLO cam-smtp0.cambridge.arm.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752163AbeERPSF (ORCPT ); Fri, 18 May 2018 11:18:05 -0400 Received: from e110455-lin.cambridge.arm.com (e110455-lin.cambridge.arm.com [10.2.131.15]) by cam-smtp0.cambridge.arm.com (8.13.8/8.13.8) with ESMTP id w4IFHhrJ024053; Fri, 18 May 2018 16:17:45 +0100 From: Liviu Dudau To: Gustavo Padovan Cc: Maarten Lankhorst , Sean Paul , Jonathan Corbet , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, David Airlie , Brian Starkey , Alexandru-Cosmin Gheorghe , Eric Anholt , Boris Brezillon , Maxime Ripard , Daniel Stone , Mihail Atanassov , Liviu Dudau Subject: [PATCH v8 2/3] drm: writeback: Add out-fences for writeback connectors Date: Fri, 18 May 2018 16:17:42 +0100 Message-Id: <20180518151743.29937-3-Liviu.Dudau@arm.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180518151743.29937-1-Liviu.Dudau@arm.com> References: <20180518151743.29937-1-Liviu.Dudau@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Brian Starkey Add the WRITEBACK_OUT_FENCE_PTR property to writeback connectors, to enable userspace to get a fence which will signal once the writeback is complete. It is not allowed to request an out-fence without a framebuffer attached to the connector. A timeline is added to drm_writeback_connector for use by the writeback out-fences. In the case of a commit failure or DRM_MODE_ATOMIC_TEST_ONLY, the fence is set to -1. Changes from v2: - Rebase onto Gustavo Padovan's v9 explicit sync series - Change out_fence_ptr type to s32 __user * - Set *out_fence_ptr to -1 in drm_atomic_connector_set_property - Store fence in drm_writeback_job Gustavo Padovan: - Move out_fence_ptr out of connector_state - Signal fence from drm_writeback_signal_completion instead of in driver directly Changes from v3: - Rebase onto commit 7e9081c5aac7 ("drm/fence: fix memory overwrite when setting out_fence fd") (change out_fence_ptr to s32 __user *, for real this time.) - Update documentation around WRITEBACK_OUT_FENCE_PTR Signed-off-by: Brian Starkey [rebased and fixed conflicts] Signed-off-by: Mihail Atanassov Signed-off-by: Liviu Dudau --- drivers/gpu/drm/drm_atomic.c | 99 ++++++++++++++++++++++++++--- drivers/gpu/drm/drm_writeback.c | 109 +++++++++++++++++++++++++++++++- include/drm/drm_atomic.h | 8 +++ include/drm/drm_connector.h | 8 +-- include/drm/drm_mode_config.h | 8 +++ include/drm/drm_writeback.h | 43 ++++++++++++- 6 files changed, 259 insertions(+), 16 deletions(-) -- 2.17.0 diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3f1e4b894803b..cc2f86c68b293 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -318,6 +318,35 @@ static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, return fence_ptr; } +static int set_out_fence_for_connector(struct drm_atomic_state *state, + struct drm_connector *connector, + s32 __user *fence_ptr) +{ + unsigned int index = drm_connector_index(connector); + + if (!fence_ptr) + return 0; + + if (put_user(-1, fence_ptr)) + return -EFAULT; + + state->connectors[index].out_fence_ptr = fence_ptr; + + return 0; +} + +static s32 __user *get_out_fence_for_connector(struct drm_atomic_state *state, + struct drm_connector *connector) +{ + unsigned int index = drm_connector_index(connector); + s32 __user *fence_ptr; + + fence_ptr = state->connectors[index].out_fence_ptr; + state->connectors[index].out_fence_ptr = NULL; + + return fence_ptr; +} + /** * drm_atomic_set_mode_for_crtc - set mode for CRTC * @state: the CRTC whose incoming state to update @@ -705,6 +734,12 @@ static int drm_atomic_connector_check(struct drm_connector *connector, return -EINVAL; } + if (writeback_job->out_fence && !writeback_job->fb) { + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] requesting out-fence without framebuffer\n", + connector->base.id, connector->name); + return -EINVAL; + } + return 0; } @@ -1320,6 +1355,11 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, if (fb) drm_framebuffer_unreference(fb); return ret; + } else if (property == config->writeback_out_fence_ptr_property) { + s32 __user *fence_ptr = u64_to_user_ptr(val); + + return set_out_fence_for_connector(state->state, connector, + fence_ptr); } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -1404,6 +1444,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, } else if (property == config->writeback_fb_id_property) { /* Writeback framebuffer is one-shot, write and forget */ *val = 0; + } else if (property == config->writeback_out_fence_ptr_property) { + *val = 0; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); @@ -2263,7 +2305,7 @@ static int setup_out_fence(struct drm_out_fence_state *fence_state, return 0; } -static int prepare_crtc_signaling(struct drm_device *dev, +static int prepare_signaling(struct drm_device *dev, struct drm_atomic_state *state, struct drm_mode_atomic *arg, struct drm_file *file_priv, @@ -2272,6 +2314,8 @@ static int prepare_crtc_signaling(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; + struct drm_connector *conn; + struct drm_connector_state *conn_state; int i, c = 0, ret; if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) @@ -2337,6 +2381,43 @@ static int prepare_crtc_signaling(struct drm_device *dev, c++; } + for_each_new_connector_in_state(state, conn, conn_state, i) { + struct drm_writeback_job *job; + struct drm_out_fence_state *f; + struct dma_fence *fence; + s32 __user *fence_ptr; + + fence_ptr = get_out_fence_for_connector(state, conn); + if (!fence_ptr) + continue; + + job = drm_atomic_get_writeback_job(conn_state); + if (!job) + return -ENOMEM; + + f = krealloc(*fence_state, sizeof(**fence_state) * + (*num_fences + 1), GFP_KERNEL); + if (!f) + return -ENOMEM; + + memset(&f[*num_fences], 0, sizeof(*f)); + + f[*num_fences].out_fence_ptr = fence_ptr; + *fence_state = f; + + fence = drm_writeback_get_out_fence((struct drm_writeback_connector *)conn); + if (!fence) + return -ENOMEM; + + ret = setup_out_fence(&f[(*num_fences)++], fence); + if (ret) { + dma_fence_put(fence); + return ret; + } + + job->out_fence = fence; + } + /* * Having this flag means user mode pends on event which will never * reach due to lack of at least one CRTC for signaling @@ -2347,11 +2428,11 @@ static int prepare_crtc_signaling(struct drm_device *dev, return 0; } -static void complete_crtc_signaling(struct drm_device *dev, - struct drm_atomic_state *state, - struct drm_out_fence_state *fence_state, - unsigned int num_fences, - bool install_fds) +static void complete_signaling(struct drm_device *dev, + struct drm_atomic_state *state, + struct drm_out_fence_state *fence_state, + unsigned int num_fences, + bool install_fds) { struct drm_crtc *crtc; struct drm_crtc_state *crtc_state; @@ -2530,8 +2611,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, drm_mode_object_put(obj); } - ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state, - &num_fences); + ret = prepare_signaling(dev, state, arg, file_priv, &fence_state, + &num_fences); if (ret) goto out; @@ -2549,7 +2630,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, out: drm_atomic_clean_old_fb(dev, plane_mask, ret); - complete_crtc_signaling(dev, state, fence_state, num_fences, !ret); + complete_signaling(dev, state, fence_state, num_fences, !ret); if (ret == -EDEADLK) { drm_atomic_state_clear(state); diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index 1141325b004ab..46a93a883344f 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -13,6 +13,7 @@ #include #include #include +#include /** * DOC: overview @@ -30,6 +31,16 @@ * framebuffer applies only to a single commit (see below). A framebuffer may * not be attached while the CRTC is off. * + * Unlike with planes, when a writeback framebuffer is removed by userspace DRM + * makes no attempt to remove it from active use by the connector. This is + * because no method is provided to abort a writeback operation, and in any + * case making a new commit whilst a writeback is ongoing is undefined (see + * WRITEBACK_OUT_FENCE_PTR below). As soon as the current writeback is finished, + * the framebuffer will automatically no longer be in active use. As it will + * also have already been removed from the framebuffer list, there will be no + * way for any userspace application to retrieve a reference to it in the + * intervening period. + * * Writeback connectors have some additional properties, which userspace * can use to query and control them: * @@ -46,8 +57,54 @@ * data is an array of u32 DRM_FORMAT_* fourcc values. * Userspace can use this blob to find out what pixel formats are supported * by the connector's writeback engine. + * + * "WRITEBACK_OUT_FENCE_PTR": + * Userspace can use this property to provide a pointer for the kernel to + * fill with a sync_file file descriptor, which will signal once the + * writeback is finished. The value should be the address of a 32-bit + * signed integer, cast to a u64. + * Userspace should wait for this fence to signal before making another + * commit affecting any of the same CRTCs, Planes or Connectors. + * **Failure to do so will result in undefined behaviour.** + * For this reason it is strongly recommended that all userspace + * applications making use of writeback connectors *always* retrieve an + * out-fence for the commit and use it appropriately. + * From userspace, this property will always read as zero. */ +#define fence_to_wb_connector(x) container_of(x->lock, \ + struct drm_writeback_connector, \ + fence_lock) + +static const char *drm_writeback_fence_get_driver_name(struct dma_fence *fence) +{ + struct drm_writeback_connector *wb_connector = + fence_to_wb_connector(fence); + + return wb_connector->base.dev->driver->name; +} + +static const char * +drm_writeback_fence_get_timeline_name(struct dma_fence *fence) +{ + struct drm_writeback_connector *wb_connector = + fence_to_wb_connector(fence); + + return wb_connector->timeline_name; +} + +static bool drm_writeback_fence_enable_signaling(struct dma_fence *fence) +{ + return true; +} + +static const struct dma_fence_ops drm_writeback_fence_ops = { + .get_driver_name = drm_writeback_fence_get_driver_name, + .get_timeline_name = drm_writeback_fence_get_timeline_name, + .enable_signaling = drm_writeback_fence_enable_signaling, + .wait = dma_fence_default_wait, +}; + static int create_writeback_properties(struct drm_device *dev) { struct drm_property *prop; @@ -71,6 +128,15 @@ static int create_writeback_properties(struct drm_device *dev) dev->mode_config.writeback_pixel_formats_property = prop; } + if (!dev->mode_config.writeback_out_fence_ptr_property) { + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, + "WRITEBACK_OUT_FENCE_PTR", 0, + U64_MAX); + if (!prop) + return -ENOMEM; + dev->mode_config.writeback_out_fence_ptr_property = prop; + } + return 0; } @@ -140,6 +206,15 @@ int drm_writeback_connector_init(struct drm_device *dev, INIT_LIST_HEAD(&wb_connector->job_queue); spin_lock_init(&wb_connector->job_lock); + wb_connector->fence_context = dma_fence_context_alloc(1); + spin_lock_init(&wb_connector->fence_lock); + snprintf(wb_connector->timeline_name, + sizeof(wb_connector->timeline_name), + "CONNECTOR:%d-%s", connector->base.id, connector->name); + + drm_object_attach_property(&connector->base, + config->writeback_out_fence_ptr_property, 0); + drm_object_attach_property(&connector->base, config->writeback_fb_id_property, 0); @@ -199,6 +274,7 @@ void drm_writeback_cleanup_job(struct drm_writeback_job *job) { if (job->fb) drm_framebuffer_unreference(job->fb); + dma_fence_put(job->out_fence); } EXPORT_SYMBOL(drm_writeback_cleanup_job); @@ -220,6 +296,7 @@ static void cleanup_work(struct work_struct *work) /** * drm_writeback_signal_completion - Signal the completion of a writeback job * @wb_connector: The writeback connector whose job is complete + * @status: Status code to set in the writeback out_fence (0 for success) * * Drivers should call this to signal the completion of a previously queued * writeback job. It should be called as soon as possible after the hardware @@ -233,7 +310,8 @@ static void cleanup_work(struct work_struct *work) * See also: drm_writeback_queue_job() */ void -drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector) +drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector, + int status) { unsigned long flags; struct drm_writeback_job *job; @@ -242,8 +320,14 @@ drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector) job = list_first_entry_or_null(&wb_connector->job_queue, struct drm_writeback_job, list_entry); - if (job) + if (job) { list_del(&job->list_entry); + if (job->out_fence) { + if (status) + dma_fence_set_error(job->out_fence, status); + dma_fence_signal(job->out_fence); + } + } spin_unlock_irqrestore(&wb_connector->job_lock, flags); if (WARN_ON(!job)) @@ -253,3 +337,24 @@ drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector) queue_work(system_long_wq, &job->cleanup_work); } EXPORT_SYMBOL(drm_writeback_signal_completion); + +struct dma_fence * +drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector) +{ + struct dma_fence *fence; + + if (WARN_ON(wb_connector->base.connector_type != + DRM_MODE_CONNECTOR_WRITEBACK)) + return NULL; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return NULL; + + dma_fence_init(fence, &drm_writeback_fence_ops, + &wb_connector->fence_lock, wb_connector->fence_context, + ++wb_connector->fence_seqno); + + return fence; +} +EXPORT_SYMBOL(drm_writeback_get_out_fence); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index a5e904105db3a..7c77a1916182a 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -160,6 +160,14 @@ struct __drm_crtcs_state { struct __drm_connnectors_state { struct drm_connector *ptr; struct drm_connector_state *state, *old_state, *new_state; + /** + * @out_fence_ptr: + * + * User-provided pointer which the kernel uses to return a sync_file + * file descriptor. Used by writeback connectors to signal completion of + * the writeback. + */ + s32 __user *out_fence_ptr; }; struct drm_private_obj; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 60c0ffb947d5e..b0d2ed13d625b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -433,10 +433,10 @@ struct drm_connector_state { /** * @writeback_job: Writeback job for writeback connectors * - * Holds the framebuffer for a writeback connector. As the writeback - * completion may be asynchronous to the normal commit cycle, the - * writeback job lifetime is managed separately from the normal atomic - * state by this object. + * Holds the framebuffer and out-fence for a writeback connector. As + * the writeback completion may be asynchronous to the normal commit + * cycle, the writeback job lifetime is managed separately from the + * normal atomic state by this object. * * See also: drm_writeback_queue_job() and * drm_writeback_signal_completion() diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index de8881324f734..74fe26aaf5444 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -793,6 +793,14 @@ struct drm_mode_config { * See also: drm_writeback_connector_init() */ struct drm_property *writeback_pixel_formats_property; + /** + * @writeback_out_fence_ptr_property: Property for writeback connectors, + * fd pointer representing the outgoing fences for a writeback + * connector. Userspace should provide a pointer to a value of type s32, + * and then cast that pointer to u64. + * See also: drm_writeback_connector_init() + */ + struct drm_property *writeback_out_fence_ptr_property; /* dumb ioctl parameters */ uint32_t preferred_depth, prefer_shadow; diff --git a/include/drm/drm_writeback.h b/include/drm/drm_writeback.h index cf3a28676006a..6a7462c1821ad 100644 --- a/include/drm/drm_writeback.h +++ b/include/drm/drm_writeback.h @@ -49,6 +49,32 @@ struct drm_writeback_connector { * drm_writeback_signal_completion() */ struct list_head job_queue; + + /** + * @fence_context: + * + * timeline context used for fence operations. + */ + unsigned int fence_context; + /** + * @fence_lock: + * + * spinlock to protect the fences in the fence_context. + */ + spinlock_t fence_lock; + /** + * @fence_seqno: + * + * Seqno variable used as monotonic counter for the fences + * created on the connector's timeline. + */ + unsigned long fence_seqno; + /** + * @timeline_name: + * + * The name of the connector's fence timeline. + */ + char timeline_name[32]; }; struct drm_writeback_job { @@ -59,12 +85,14 @@ struct drm_writeback_job { * framebuffer reference to a workqueue. */ struct work_struct cleanup_work; + /** * @list_entry: * * List item for the connector's @job_queue */ struct list_head list_entry; + /** * @fb: * @@ -72,6 +100,13 @@ struct drm_writeback_job { * directly, use drm_atomic_set_writeback_fb_for_connector() */ struct drm_framebuffer *fb; + + /** + * @out_fence: + * + * Fence which will signal once the writeback has completed + */ + struct dma_fence *out_fence; }; int drm_writeback_connector_init(struct drm_device *dev, @@ -84,5 +119,11 @@ void drm_writeback_queue_job(struct drm_writeback_connector *wb_connector, struct drm_writeback_job *job); void drm_writeback_cleanup_job(struct drm_writeback_job *job); -void drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector); + +void +drm_writeback_signal_completion(struct drm_writeback_connector *wb_connector, + int status); + +struct dma_fence * +drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector); #endif From patchwork Fri May 18 15:17:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liviu Dudau X-Patchwork-Id: 136323 Delivered-To: patch@linaro.org Received: by 2002:a2e:9706:0:0:0:0:0 with SMTP id r6-v6csp1371961lji; Fri, 18 May 2018 08:18:24 -0700 (PDT) X-Google-Smtp-Source: AB8JxZq383fJzOFe5PM+2j8BCNzfHkOtwJCubmDy3n/aVbTImJJpaXSoiD3KEkKDRJzmTt9gNRFA X-Received: by 2002:a17:902:b946:: with SMTP id h6-v6mr10231323pls.3.1526656704165; Fri, 18 May 2018 08:18:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526656704; cv=none; d=google.com; s=arc-20160816; b=VYuyMQCXSxlT9obCNjFRQB5KaCPBIvXjH9waXKthFiUlyDVbhKikad7CcMNtxVUW0t nkCwpdXta52vP++lBr3oJBzIkPgLXspttimIulO7INwXxE1byY6haaIrKH8Cz13wVYgD pCdKNQiavesihhPTGJ9psLY5GIewpp79ba6C7mpC579AOSClvKONUN2anNGySK2GPrI+ f023/rKZ/H7AEOkv2VQtub3VwDCKNjM7lAesA1VwXXg51+B23WWwFoNf6pWKfyuNjB1S wdNmMlXUxCZk3UDYbZeZvkw5aAK9w8uPkD2jooWTut+0Rsg908kwvanSYP4QBHxv3Nob ooEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=d3/B3lFLsT0N3ZNP0HeYtBC8qyaacV1GnXP7ZnS8RHg=; b=obeThzWdPJxdTv8NU8bWkFEJqeV/5ELohSQPky078+K45/xsZoRl26Xhb1qYK9Zd4I l5HMvSP/9Rb0d1EkBOviI+098iZzaizdMr2o1E+gjBxJuLcbtvTFW4SwQ+PD2W+xEQmh sgBEXV4Wfa2W+q8g2pKni17WqMsPH5DiM0ThOwyKATjA6l1FidvUxg2dBHI6ftvSUW27 wvuxTSvV6DhoIsKt/LyP/2/FDbfkooyykPWGMXRzwA6i3Y8yrj4a+bPx49Kzoqbivk1R ud2MiCfLAiG9SN/hl+ifWfzN8ypHQH3rg6lAGY44NYLDUMfUQ3jAVwMnade8LZxh707W TIRA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 67-v6si7811107pfm.167.2018.05.18.08.18.23; Fri, 18 May 2018 08:18:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752213AbeERPSI (ORCPT + 29 others); Fri, 18 May 2018 11:18:08 -0400 Received: from fw-tnat.cambridge.arm.com ([217.140.96.140]:54889 "EHLO cam-smtp0.cambridge.arm.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751117AbeERPSB (ORCPT ); Fri, 18 May 2018 11:18:01 -0400 Received: from e110455-lin.cambridge.arm.com (e110455-lin.cambridge.arm.com [10.2.131.15]) by cam-smtp0.cambridge.arm.com (8.13.8/8.13.8) with ESMTP id w4IFHhrK024053; Fri, 18 May 2018 16:17:45 +0100 From: Liviu Dudau To: Gustavo Padovan Cc: Maarten Lankhorst , Sean Paul , Jonathan Corbet , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, David Airlie , Brian Starkey , Alexandru-Cosmin Gheorghe , Eric Anholt , Boris Brezillon , Maxime Ripard , Daniel Stone , Liviu Dudau Subject: [PATCH v8 3/3] drm: writeback: Add client capability for exposing writeback connectors Date: Fri, 18 May 2018 16:17:43 +0100 Message-Id: <20180518151743.29937-4-Liviu.Dudau@arm.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180518151743.29937-1-Liviu.Dudau@arm.com> References: <20180518151743.29937-1-Liviu.Dudau@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Due to the fact that writeback connectors behave in a special way in DRM (they always report being disconnected) we might confuse some userspace. Add a client capability for writeback connectors that will filter them out for clients that don't understand the capability. Re-requested-by: Sean Paul Cc: Brian Starkey Signed-off-by: Liviu Dudau --- drivers/gpu/drm/drm_ioctl.c | 7 +++++++ drivers/gpu/drm/drm_mode_config.c | 5 +++++ include/drm/drm_file.h | 7 +++++++ include/uapi/drm/drm.h | 9 +++++++++ 4 files changed, 28 insertions(+) -- 2.17.0 diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index af782911c505d..59951ff3e3630 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -325,6 +325,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) file_priv->atomic = req->value; file_priv->universal_planes = req->value; break; + case DRM_CLIENT_CAP_WRITEBACK_CONNECTORS: + if (!file_priv->atomic || !drm_core_check_feature(dev, DRIVER_ATOMIC)) + return -EINVAL; + if (req->value > 1) + return -EINVAL; + file_priv->writeback_connectors = req->value; + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index e5c653357024d..21e353bd3948e 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -145,6 +145,11 @@ int drm_mode_getresources(struct drm_device *dev, void *data, count = 0; connector_id = u64_to_user_ptr(card_res->connector_id_ptr); drm_for_each_connector_iter(connector, &conn_iter) { + /* only expose writeback connectors if userspace understands them */ + if (!file_priv->writeback_connectors && + (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)) + continue; + if (drm_lease_held(file_priv, connector->base.id)) { if (count < card_res->count_connectors && put_user(connector->base.id, connector_id + count)) { diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 5176c3797680c..2a09b3c8965c6 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -181,6 +181,13 @@ struct drm_file { /** @atomic: True if client understands atomic properties. */ unsigned atomic:1; + /** + * @writeback_connectors: + * + * True if client understands writeback connectors + */ + unsigned writeback_connectors:1; + /** * @is_master: * diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 6fdff5945c8a0..59f27ea928b42 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -680,6 +680,15 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_ATOMIC 3 +/** + * DRM_CLIENT_CAP_WRITEBACK_CONNECTORS + * + * If set to 1, the DRM core will expose special connectors to be used for + * writing back to memory the scene setup in the commit. Depends on client + * also supporting DRM_CLIENT_CAP_ATOMIC + */ +#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 4 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability;