From: Daniel Vetter <daniel@ffwll.ch>
To: "Noralf Trønnes" <noralf@tronnes.org>
Cc: daniel.vetter@ffwll.ch, intel-gfx@lists.freedesktop.org,
dri-devel@lists.freedesktop.org,
laurent.pinchart@ideasonboard.com
Subject: Re: [RFC v2 1/8] drm: provide management functions for drm_file
Date: Tue, 9 Jan 2018 11:20:17 +0100 [thread overview]
Message-ID: <20180109102017.GP26573@phenom.ffwll.local> (raw)
In-Reply-To: <20180103222110.45855-2-noralf@tronnes.org>
On Wed, Jan 03, 2018 at 11:21:03PM +0100, Noralf Trønnes wrote:
> From: David Herrmann <dh.herrmann@gmail.com>
>
> Rather than doing drm_file allocation/destruction right in the fops, lets
> provide separate helpers. This decouples drm_file management from the
> still-mandatory drm-fops. It prepares for use of drm_file without the
> fops, both by possible separate fops implementations and APIs (not that I
> am aware of any such plans), and more importantly from in-kernel use where
> no real file is available.
>
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> [rebased]
> Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
> ---
> drivers/gpu/drm/drm_file.c | 309 +++++++++++++++++++++++------------------
> drivers/gpu/drm/drm_internal.h | 2 +
> 2 files changed, 179 insertions(+), 132 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
> index b3c6e997ccdb..d208faade27e 100644
> --- a/drivers/gpu/drm/drm_file.c
> +++ b/drivers/gpu/drm/drm_file.c
> @@ -101,6 +101,179 @@ DEFINE_MUTEX(drm_global_mutex);
>
> static int drm_open_helper(struct file *filp, struct drm_minor *minor);
>
> +/**
> + * drm_file_alloc - allocate file context
> + * @minor: minor to allocate on
> + *
> + * This allocates a new DRM file context. It is not linked into any context and
> + * can be used by the caller freely. Note that the context keeps a pointer to
> + * @minor, so it must be freed before @minor is.
> + *
> + * The legacy paths might require the drm_global_mutex to be held.
I'd remove this line, since it's only relevant to close the driver load
vs. file open race for drivers still using the deprecated ->load callback.
This only confuses and doesn't help anyone writing a new/modern driver.
> + *
> + * RETURNS:
> + * Pointer to newly allocated context, ERR_PTR on failure.
> + */
> +struct drm_file *drm_file_alloc(struct drm_minor *minor)
> +{
> + struct drm_device *dev = minor->dev;
> + struct drm_file *file;
> + int ret;
> +
> + file = kzalloc(sizeof(*file), GFP_KERNEL);
> + if (!file)
> + return ERR_PTR(-ENOMEM);
> +
> + file->pid = get_pid(task_pid(current));
> + file->minor = minor;
> +
> + /* for compatibility root is always authenticated */
> + file->authenticated = capable(CAP_SYS_ADMIN);
> + file->lock_count = 0;
> +
> + INIT_LIST_HEAD(&file->lhead);
> + INIT_LIST_HEAD(&file->fbs);
> + mutex_init(&file->fbs_lock);
> + INIT_LIST_HEAD(&file->blobs);
> + INIT_LIST_HEAD(&file->pending_event_list);
> + INIT_LIST_HEAD(&file->event_list);
> + init_waitqueue_head(&file->event_wait);
> + file->event_space = 4096; /* set aside 4k for event buffer */
> +
> + mutex_init(&file->event_read_lock);
> +
> + if (drm_core_check_feature(dev, DRIVER_GEM))
> + drm_gem_open(dev, file);
> +
> + if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> + drm_syncobj_open(file);
> +
> + if (drm_core_check_feature(dev, DRIVER_PRIME))
> + drm_prime_init_file_private(&file->prime);
> +
> + if (dev->driver->open) {
> + ret = dev->driver->open(dev, file);
> + if (ret < 0)
> + goto out_prime_destroy;
> + }
> +
> + if (drm_is_primary_client(file)) {
> + ret = drm_master_open(file);
> + if (ret)
> + goto out_close;
> + }
> +
> + return file;
> +
> +out_close:
> + if (dev->driver->postclose)
> + dev->driver->postclose(dev, file);
> +out_prime_destroy:
> + if (drm_core_check_feature(dev, DRIVER_PRIME))
> + drm_prime_destroy_file_private(&file->prime);
> + if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> + drm_syncobj_release(file);
> + if (drm_core_check_feature(dev, DRIVER_GEM))
> + drm_gem_release(dev, file);
> + put_pid(file->pid);
> + kfree(file);
> +
> + return ERR_PTR(ret);
> +}
> +
> +static void drm_events_release(struct drm_file *file_priv)
> +{
> + struct drm_device *dev = file_priv->minor->dev;
> + struct drm_pending_event *e, *et;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dev->event_lock, flags);
> +
> + /* Unlink pending events */
> + list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
> + pending_link) {
> + list_del(&e->pending_link);
> + e->file_priv = NULL;
> + }
> +
> + /* Remove unconsumed events */
> + list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
> + list_del(&e->link);
> + kfree(e);
> + }
> +
> + spin_unlock_irqrestore(&dev->event_lock, flags);
> +}
> +
> +/**
> + * drm_file_free - free file context
> + * @file: context to free, or NULL
> + *
> + * This destroys and deallocates a DRM file context previously allocated via
> + * drm_file_alloc(). The caller must make sure to unlink it from any contexts
> + * before calling this.
> + *
> + * The legacy paths might require the drm_global_mutex to be held.
Same here.
With the bikesheds address and maybe the EXPORT_SYMBOL for these from
patch 3 moved to here:
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> + *
> + * If NULL is passed, this is a no-op.
> + *
> + * RETURNS:
> + * 0 on success, or error code on failure.
> + */
> +void drm_file_free(struct drm_file *file)
> +{
> + struct drm_device *dev;
> +
> + if (!file)
> + return;
> +
> + dev = file->minor->dev;
> +
> + DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
> + task_pid_nr(current),
> + (long)old_encode_dev(file->minor->kdev->devt),
> + dev->open_count);
> +
> + if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
> + dev->driver->preclose)
> + dev->driver->preclose(dev, file);
> +
> + if (drm_core_check_feature(dev, DRIVER_LEGACY))
> + drm_legacy_lock_release(dev, file->filp);
> +
> + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
> + drm_legacy_reclaim_buffers(dev, file);
> +
> + drm_events_release(file);
> +
> + if (drm_core_check_feature(dev, DRIVER_MODESET)) {
> + drm_fb_release(file);
> + drm_property_destroy_user_blobs(dev, file);
> + }
> +
> + if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> + drm_syncobj_release(file);
> +
> + if (drm_core_check_feature(dev, DRIVER_GEM))
> + drm_gem_release(dev, file);
> +
> + drm_legacy_ctxbitmap_flush(dev, file);
> +
> + if (drm_is_primary_client(file))
> + drm_master_release(file);
> +
> + if (dev->driver->postclose)
> + dev->driver->postclose(dev, file);
> +
> + if (drm_core_check_feature(dev, DRIVER_PRIME))
> + drm_prime_destroy_file_private(&file->prime);
> +
> + WARN_ON(!list_empty(&file->event_list));
> +
> + put_pid(file->pid);
> + kfree(file);
> +}
> +
> static int drm_setup(struct drm_device * dev)
> {
> int ret;
> @@ -196,7 +369,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
> {
> struct drm_device *dev = minor->dev;
> struct drm_file *priv;
> - int ret;
>
> if (filp->f_flags & O_EXCL)
> return -EBUSY; /* No exclusive opens */
> @@ -207,50 +379,12 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
>
> DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
>
> - priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> - if (!priv)
> - return -ENOMEM;
> + priv = drm_file_alloc(minor);
> + if (IS_ERR(priv))
> + return PTR_ERR(priv);
>
> filp->private_data = priv;
> priv->filp = filp;
> - priv->pid = get_pid(task_pid(current));
> - priv->minor = minor;
> -
> - /* for compatibility root is always authenticated */
> - priv->authenticated = capable(CAP_SYS_ADMIN);
> - priv->lock_count = 0;
> -
> - INIT_LIST_HEAD(&priv->lhead);
> - INIT_LIST_HEAD(&priv->fbs);
> - mutex_init(&priv->fbs_lock);
> - INIT_LIST_HEAD(&priv->blobs);
> - INIT_LIST_HEAD(&priv->pending_event_list);
> - INIT_LIST_HEAD(&priv->event_list);
> - init_waitqueue_head(&priv->event_wait);
> - priv->event_space = 4096; /* set aside 4k for event buffer */
> -
> - mutex_init(&priv->event_read_lock);
> -
> - if (drm_core_check_feature(dev, DRIVER_GEM))
> - drm_gem_open(dev, priv);
> -
> - if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> - drm_syncobj_open(priv);
> -
> - if (drm_core_check_feature(dev, DRIVER_PRIME))
> - drm_prime_init_file_private(&priv->prime);
> -
> - if (dev->driver->open) {
> - ret = dev->driver->open(dev, priv);
> - if (ret < 0)
> - goto out_prime_destroy;
> - }
> -
> - if (drm_is_primary_client(priv)) {
> - ret = drm_master_open(priv);
> - if (ret)
> - goto out_close;
> - }
>
> mutex_lock(&dev->filelist_mutex);
> list_add(&priv->lhead, &dev->filelist);
> @@ -277,45 +411,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
> #endif
>
> return 0;
> -
> -out_close:
> - if (dev->driver->postclose)
> - dev->driver->postclose(dev, priv);
> -out_prime_destroy:
> - if (drm_core_check_feature(dev, DRIVER_PRIME))
> - drm_prime_destroy_file_private(&priv->prime);
> - if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> - drm_syncobj_release(priv);
> - if (drm_core_check_feature(dev, DRIVER_GEM))
> - drm_gem_release(dev, priv);
> - put_pid(priv->pid);
> - kfree(priv);
> - filp->private_data = NULL;
> - return ret;
> -}
> -
> -static void drm_events_release(struct drm_file *file_priv)
> -{
> - struct drm_device *dev = file_priv->minor->dev;
> - struct drm_pending_event *e, *et;
> - unsigned long flags;
> -
> - spin_lock_irqsave(&dev->event_lock, flags);
> -
> - /* Unlink pending events */
> - list_for_each_entry_safe(e, et, &file_priv->pending_event_list,
> - pending_link) {
> - list_del(&e->pending_link);
> - e->file_priv = NULL;
> - }
> -
> - /* Remove unconsumed events */
> - list_for_each_entry_safe(e, et, &file_priv->event_list, link) {
> - list_del(&e->link);
> - kfree(e);
> - }
> -
> - spin_unlock_irqrestore(&dev->event_lock, flags);
> }
>
> static void drm_legacy_dev_reinit(struct drm_device *dev)
> @@ -382,57 +477,7 @@ int drm_release(struct inode *inode, struct file *filp)
> list_del(&file_priv->lhead);
> mutex_unlock(&dev->filelist_mutex);
>
> - if (drm_core_check_feature(dev, DRIVER_LEGACY) &&
> - dev->driver->preclose)
> - dev->driver->preclose(dev, file_priv);
> -
> - /* ========================================================
> - * Begin inline drm_release
> - */
> -
> - DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
> - task_pid_nr(current),
> - (long)old_encode_dev(file_priv->minor->kdev->devt),
> - dev->open_count);
> -
> - if (drm_core_check_feature(dev, DRIVER_LEGACY))
> - drm_legacy_lock_release(dev, filp);
> -
> - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
> - drm_legacy_reclaim_buffers(dev, file_priv);
> -
> - drm_events_release(file_priv);
> -
> - if (drm_core_check_feature(dev, DRIVER_MODESET)) {
> - drm_fb_release(file_priv);
> - drm_property_destroy_user_blobs(dev, file_priv);
> - }
> -
> - if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
> - drm_syncobj_release(file_priv);
> -
> - if (drm_core_check_feature(dev, DRIVER_GEM))
> - drm_gem_release(dev, file_priv);
> -
> - drm_legacy_ctxbitmap_flush(dev, file_priv);
> -
> - if (drm_is_primary_client(file_priv))
> - drm_master_release(file_priv);
> -
> - if (dev->driver->postclose)
> - dev->driver->postclose(dev, file_priv);
> -
> - if (drm_core_check_feature(dev, DRIVER_PRIME))
> - drm_prime_destroy_file_private(&file_priv->prime);
> -
> - WARN_ON(!list_empty(&file_priv->event_list));
> -
> - put_pid(file_priv->pid);
> - kfree(file_priv);
> -
> - /* ========================================================
> - * End inline drm_release
> - */
> + drm_file_free(file_priv);
>
> if (!--dev->open_count) {
> drm_lastclose(dev);
> diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
> index b72242e93ea4..40179c5fc6b8 100644
> --- a/drivers/gpu/drm/drm_internal.h
> +++ b/drivers/gpu/drm/drm_internal.h
> @@ -26,6 +26,8 @@
>
> /* drm_file.c */
> extern struct mutex drm_global_mutex;
> +struct drm_file *drm_file_alloc(struct drm_minor *minor);
> +void drm_file_free(struct drm_file *file);
> void drm_lastclose(struct drm_device *dev);
>
> /* drm_pci.c */
> --
> 2.14.2
>
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2018-01-09 10:20 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-03 22:21 [RFC v2 0/8] drm: Add generic fbdev emulation Noralf Trønnes
2018-01-03 22:21 ` [RFC v2 1/8] drm: provide management functions for drm_file Noralf Trønnes
2018-01-09 10:20 ` Daniel Vetter [this message]
2018-01-09 10:32 ` David Herrmann
2018-01-03 22:21 ` [RFC v2 2/8] drm/ioctl: Remove trailing whitespace Noralf Trønnes
2018-01-09 10:18 ` Daniel Vetter
2018-01-09 14:49 ` Laurent Pinchart
2018-01-03 22:21 ` [RFC v2 3/8] drm: Export some ioctl functions Noralf Trønnes
2018-01-09 10:16 ` Daniel Vetter
2018-01-09 10:31 ` David Herrmann
2018-01-09 14:48 ` Laurent Pinchart
2018-01-03 22:21 ` [RFC v2 4/8] drm/fb-helper: Ensure driver module is pinned in fb_open() Noralf Trønnes
2018-01-09 10:18 ` Daniel Vetter
2018-01-09 10:22 ` Daniel Vetter
2018-01-03 22:21 ` [RFC v2 5/8] drm/fb-helper: Don't restore if fbdev is not in use Noralf Trønnes
2018-01-09 10:28 ` Daniel Vetter
2018-01-03 22:21 ` [RFC v2 6/8] drm: Handle fbdev emulation in core Noralf Trønnes
2018-01-09 10:38 ` Daniel Vetter
2018-01-10 17:02 ` Noralf Trønnes
2018-01-11 7:45 ` Daniel Vetter
2018-01-11 14:09 ` Noralf Trønnes
2018-01-18 21:36 ` Daniel Vetter
2018-01-03 22:21 ` [RFC v2 7/8] drm/fb-helper: Add generic fbdev emulation Noralf Trønnes
2018-01-09 10:46 ` Daniel Vetter
2018-01-03 22:21 ` [RFC v2 8/8] drm/vc4: Test " Noralf Trønnes
2018-01-03 22:42 ` ✓ Fi.CI.BAT: success for drm: Add generic fbdev emulation (rev2) Patchwork
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=20180109102017.GP26573@phenom.ffwll.local \
--to=daniel@ffwll.ch \
--cc=daniel.vetter@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=noralf@tronnes.org \
/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.