From: Gustavo Padovan <gustavo@padovan.org>
To: Brian Starkey <brian.starkey@arm.com>
Cc: dri-devel@lists.freedesktop.org, marcheu@google.com,
Daniel Stone <daniels@collabora.com>,
seanpaul@google.com, Daniel Vetter <daniel.vetter@ffwll.ch>,
linux-kernel@vger.kernel.org, laurent.pinchart@ideasonboard.com,
Gustavo Padovan <gustavo.padovan@collabora.co.uk>,
John Harrison <John.C.Harrison@Intel.com>,
m.chehab@samsung.com
Subject: Re: [PATCH v5 4/4] drm/fence: add out-fences support
Date: Thu, 20 Oct 2016 18:30:17 -0200 [thread overview]
Message-ID: <20161020203017.GC2734@joana> (raw)
In-Reply-To: <20161020174810.GB7165@e106950-lin.cambridge.arm.com>
Hi Brian,
2016-10-20 Brian Starkey <brian.starkey@arm.com>:
> Hi Gustavo,
>
> I notice your branch has the sync_file refcount change in, but this
> doesn't seem to take account for that. Will you be dropping that
> change to match the semantics of fence_array?
I will drop the fence_get() in the out-fence patch because we already
hold the ref when we create the fence. The sync_file refcount patch will
remain.
>
> Couple more comments below.
>
> On Thu, Oct 20, 2016 at 12:50:05PM -0200, Gustavo Padovan wrote:
> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >
> > Support DRM out-fences by creating a sync_file with a fence for each CRTC
> > that sets the OUT_FENCE_PTR property.
> >
> > We use the out_fence pointer received in the OUT_FENCE_PTR prop to send
> > the sync_file fd back to userspace.
> >
> > The sync_file and fd are allocated/created before commit, but the
> > fd_install operation only happens after we know that commit succeed.
> >
> > In case of error userspace should receive a fd number of -1.
> >
> > v2: Comment by Rob Clark:
> > - Squash commit that adds DRM_MODE_ATOMIC_OUT_FENCE flag here.
> >
> > Comment by Daniel Vetter:
> > - Add clean up code for out_fences
> >
> > v3: Comments by Daniel Vetter:
> > - create DRM_MODE_ATOMIC_EVENT_MASK
> > - userspace should fill out_fences_ptr with the crtc_ids for which
> > it wants fences back.
> >
> > v4: Create OUT_FENCE_PTR properties and remove old approach.
> >
> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> > ---
> > drivers/gpu/drm/drm_atomic.c | 116 ++++++++++++++++++++++++++++++++++---------
> > drivers/gpu/drm/drm_crtc.c | 8 +++
> > include/drm/drm_crtc.h | 19 +++++++
> > 3 files changed, 119 insertions(+), 24 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> > index b3284b2..07775fc 100644
> > --- a/drivers/gpu/drm/drm_atomic.c
> > +++ b/drivers/gpu/drm/drm_atomic.c
> > @@ -490,6 +490,8 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
> > &replaced);
> > state->color_mgmt_changed |= replaced;
> > return ret;
> > + } else if (property == config->prop_out_fence_ptr) {
> > + state->out_fence_ptr = u64_to_user_ptr(val);
> > } else if (crtc->funcs->atomic_set_property)
> > return crtc->funcs->atomic_set_property(crtc, state, property, val);
> > else
> > @@ -532,6 +534,8 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
> > *val = (state->ctm) ? state->ctm->base.id : 0;
> > else if (property == config->gamma_lut_property)
> > *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
> > + else if (property == config->prop_out_fence_ptr)
> > + *val = 0;
> > else if (crtc->funcs->atomic_get_property)
> > return crtc->funcs->atomic_get_property(crtc, state, property, val);
> > else
> > @@ -1474,11 +1478,9 @@ EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
> > */
> >
> > static struct drm_pending_vblank_event *create_vblank_event(
> > - struct drm_device *dev, struct drm_file *file_priv,
> > - struct fence *fence, uint64_t user_data)
> > + struct drm_device *dev, uint64_t user_data)
> > {
> > struct drm_pending_vblank_event *e = NULL;
> > - int ret;
> >
> > e = kzalloc(sizeof *e, GFP_KERNEL);
> > if (!e)
> > @@ -1488,17 +1490,6 @@ static struct drm_pending_vblank_event *create_vblank_event(
> > e->event.base.length = sizeof(e->event);
> > e->event.user_data = user_data;
> >
> > - if (file_priv) {
> > - ret = drm_event_reserve_init(dev, file_priv, &e->base,
> > - &e->event.base);
> > - if (ret) {
> > - kfree(e);
> > - return NULL;
> > - }
> > - }
> > -
> > - e->base.fence = fence;
> > -
> > return e;
> > }
> >
> > @@ -1603,6 +1594,40 @@ void drm_atomic_clean_old_fb(struct drm_device *dev,
> > }
> > EXPORT_SYMBOL(drm_atomic_clean_old_fb);
> >
> > +static int crtc_setup_out_fence(struct drm_crtc *crtc,
> > + struct drm_crtc_state *crtc_state,
> > + struct drm_out_fence_state *fence_state)
> > +{
> > + struct fence *fence;
> > +
> > + fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
> > + if (fence_state->fd < 0) {
> > + return fence_state->fd;
> > + }
> > +
> > + fence_state->out_fence_ptr = crtc_state->out_fence_ptr;
> > + crtc_state->out_fence_ptr = NULL;
> > +
> > + if (put_user(fence_state->fd, fence_state->out_fence_ptr))
> > + return -EFAULT;
> > +
> > + fence = kzalloc(sizeof(*fence), GFP_KERNEL);
> > + if (!fence)
> > + return -ENOMEM;
> > +
> > + fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
> > + crtc->fence_context, ++crtc->fence_seqno);
> > +
> > + fence_state->sync_file = sync_file_create(fence);
> > + if(!fence_state->sync_file) {
> > + fence_put(fence);
> > + return -ENOMEM;
> > + }
> > +
> > + crtc_state->event->base.fence = fence_get(fence);
> > + return 0;
> > +}
> > +
> > int drm_mode_atomic_ioctl(struct drm_device *dev,
> > void *data, struct drm_file *file_priv)
> > {
> > @@ -1617,9 +1642,10 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
> > struct drm_plane *plane;
> > struct drm_crtc *crtc;
> > struct drm_crtc_state *crtc_state;
> > + struct drm_out_fence_state *fence_state;
> > unsigned plane_mask;
> > int ret = 0;
> > - unsigned int i, j;
> > + unsigned int i, j, fence_idx = 0;
> >
> > /* disallow for drivers not supporting atomic: */
> > if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
> > @@ -1734,12 +1760,19 @@ retry:
> > drm_mode_object_unreference(obj);
> > }
> >
> > - if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> > - for_each_crtc_in_state(state, crtc, crtc_state, i) {
> > + fence_state = kcalloc(dev->mode_config.num_crtc, sizeof(*fence_state),
> > + GFP_KERNEL);
> > + if (!fence_state) {
> > + ret = -ENOMEM;
> > + goto out;
> > + }
> > +
> > + for_each_crtc_in_state(state, crtc, crtc_state, i) {
> > + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT ||
> > + crtc_state->out_fence_ptr) {
> > struct drm_pending_vblank_event *e;
> >
> > - e = create_vblank_event(dev, file_priv, NULL,
> > - arg->user_data);
> > + e = create_vblank_event(dev, arg->user_data);
> > if (!e) {
> > ret = -ENOMEM;
> > goto out;
> > @@ -1747,6 +1780,28 @@ retry:
> >
> > crtc_state->event = e;
> > }
> > +
> > + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> > + struct drm_pending_vblank_event *e = crtc_state->event;
> > +
> > + if (!file_priv)
> > + continue;
> > +
> > + ret = drm_event_reserve_init(dev, file_priv, &e->base,
> > + &e->event.base);
> > + if (ret) {
> > + kfree(e);
> > + crtc_state->event = NULL;
> > + goto out;
> > + }
> > + }
> > +
> > + if (crtc_state->out_fence_ptr) {
> > + ret = crtc_setup_out_fence(crtc, crtc_state,
> > + &fence_state[fence_idx++]);
> > + if (ret)
> > + goto out;
> > + }
> > }
> >
> > if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
> > @@ -1761,24 +1816,37 @@ retry:
> > ret = drm_atomic_commit(state);
> > }
> >
> > + for (i = 0; i < fence_idx; i++)
> > + fd_install(fence_state[i].fd, fence_state[i].sync_file->file);
> > +
> > out:
> > drm_atomic_clean_old_fb(dev, plane_mask, ret);
> >
> > - if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
> > + for_each_crtc_in_state(state, crtc, crtc_state, i) {
>
> I think a check on ret is still needed before you iterate the CRTCs.
> If the commit is successful then state has already been freed by this
> point, and I get a splat.
Yes, I believe I only tested with non-blocking requests.
>
> > /*
> > * TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
> > * if they weren't, this code should be called on success
> > * for TEST_ONLY too.
> > */
> > + if (ret && crtc_state->event)
> > + drm_event_cancel_free(dev, &crtc_state->event->base);
> > + }
> >
> > - for_each_crtc_in_state(state, crtc, crtc_state, i) {
> > - if (!crtc_state->event)
> > - continue;
> > + if (ret && fence_state) {
> > + for (i = 0; i < fence_idx; i++) {
> > + if (fence_state[i].fd >= 0)
> > + put_unused_fd(fence_state[i].fd);
> > + if (fence_state[i].sync_file)
> > + fput(fence_state[i].sync_file->file);
> >
> > - drm_event_cancel_free(dev, &crtc_state->event->base);
> > + /* If this fails, there's not much we can do about it */
> > + if (put_user(-1, fence_state->out_fence_ptr))
> > + DRM_ERROR("Couldn't clear out_fence_ptr\n");
> > }
> > }
> >
> > + kfree(fence_state);
> > +
> > if (ret == -EDEADLK) {
> > drm_atomic_state_clear(state);
> > drm_modeset_backoff(&ctx);
> > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > index b99090f..40bce97 100644
> > --- a/drivers/gpu/drm/drm_crtc.c
> > +++ b/drivers/gpu/drm/drm_crtc.c
> > @@ -274,6 +274,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
> > if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
> > drm_object_attach_property(&crtc->base, config->prop_active, 0);
> > drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
> > + drm_object_attach_property(&crtc->base,
> > + config->prop_out_fence_ptr, 0);
> > }
> >
> > return 0;
> > @@ -434,6 +436,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
> > return -ENOMEM;
> > dev->mode_config.prop_in_fence_fd = prop;
> >
> > + prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
> > + "OUT_FENCE_PTR", 0, U64_MAX);
> > + if (!prop)
> > + return -ENOMEM;
> > + dev->mode_config.prop_out_fence_ptr = prop;
> > +
> > prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
> > "CRTC_ID", DRM_MODE_OBJECT_CRTC);
> > if (!prop)
> > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> > index 657a33a..b898604 100644
> > --- a/include/drm/drm_crtc.h
> > +++ b/include/drm/drm_crtc.h
> > @@ -165,6 +165,8 @@ struct drm_crtc_state {
> > struct drm_property_blob *ctm;
> > struct drm_property_blob *gamma_lut;
> >
> > + u64 __user *out_fence_ptr;
> > +
>
> I'm somewhat not convinced about stashing a __user pointer in the
> CRTC atomic state. I know it gets cleared before the driver sees it,
> but if anything I think that hints that this isn't the right place to
> store it.
>
> I've been trying to think of other ways to get from a property to
> something drm_mode_atomic_ioctl can use - maybe we can store some
> stuff in drm_atomic_state which only lives for the length of the ioctl
> call and put this pointer in there.
The drm_atomic_state is still visible by the drivers. Between there and
crtc_state, I would keep in the crtc_state for now.
Gustavo
next prev parent reply other threads:[~2016-10-20 20:30 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-10-20 14:50 [PATCH v5 0/4] drm: add explicit fencing Gustavo Padovan
2016-10-20 14:50 ` [PATCH v5 1/4] drm/fence: add in-fences support Gustavo Padovan
2016-10-21 12:51 ` Daniel Vetter
2016-10-21 12:51 ` Daniel Vetter
2016-10-20 14:50 ` [PATCH v5 2/4] drm/fence: release fence reference when canceling event Gustavo Padovan
2016-10-21 12:52 ` Daniel Vetter
2016-10-21 12:52 ` Daniel Vetter
2016-10-20 14:50 ` [PATCH v5 3/4] drm/fence: add fence timeline to drm_crtc Gustavo Padovan
2016-10-20 17:20 ` Brian Starkey
2016-10-20 20:12 ` Gustavo Padovan
2016-10-21 12:54 ` Daniel Vetter
2016-10-21 12:54 ` Daniel Vetter
2016-10-20 14:50 ` [PATCH v5 4/4] drm/fence: add out-fences support Gustavo Padovan
2016-10-20 15:35 ` Ville Syrjälä
2016-10-20 15:55 ` Gustavo Padovan
2016-10-20 16:34 ` Ville Syrjälä
2016-10-20 19:15 ` Ville Syrjälä
2016-10-21 12:57 ` Daniel Vetter
2016-10-21 12:57 ` Daniel Vetter
2016-10-21 13:07 ` Gustavo Padovan
2016-10-21 13:07 ` Gustavo Padovan
2016-10-20 17:48 ` Brian Starkey
2016-10-20 17:48 ` Brian Starkey
2016-10-20 20:30 ` Gustavo Padovan [this message]
2016-10-21 10:55 ` Brian Starkey
2016-10-21 13:00 ` Daniel Vetter
2016-10-21 13:00 ` Daniel Vetter
2016-10-21 15:44 ` Brian Starkey
2016-10-21 13:04 ` [PATCH v5 0/4] drm: add explicit fencing Daniel Vetter
2016-10-21 13:04 ` Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20161020203017.GC2734@joana \
--to=gustavo@padovan.org \
--cc=John.C.Harrison@Intel.com \
--cc=brian.starkey@arm.com \
--cc=daniel.vetter@ffwll.ch \
--cc=daniels@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gustavo.padovan@collabora.co.uk \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=m.chehab@samsung.com \
--cc=marcheu@google.com \
--cc=seanpaul@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.