[PATCH 4/6] drm: provide management functions for drm_file

2016-09-19 Thread Daniel Vetter
On Thu, Sep 01, 2016 at 02:48:35PM +0200, David Herrmann wrote:
> 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 
> ---
>  drivers/gpu/drm/drm_drv.c  | 135 
> +
>  drivers/gpu/drm/drm_fops.c | 132 +++-
>  drivers/gpu/drm/drm_internal.h |   4 ++
>  3 files changed, 147 insertions(+), 124 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index 57ce973..9ab0016 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -95,6 +95,141 @@ void drm_ut_debug_printk(const char *function_name, const 
> char *format, ...)
>  }
>  EXPORT_SYMBOL(drm_ut_debug_printk);
>  
> +/**
> + * 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.
> + *
> + * RETURNS:
> + * Pointer to newly allocated context, ERR_PTR on failure.
> + */


Hm, in drm core we only type kerneldoc for exported stuff, not internal
interfaces. The idea being that the target audience for those docs is
(mostly) driver authors.

And since you're touching this, drm_file.[hc] would look pretty I think,
with kerneldoc for the structures ...
-Daniel


> +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;
> + file->authenticated = capable(CAP_SYS_ADMIN); /* legacy compat */
> + INIT_LIST_HEAD(>lhead);
> + INIT_LIST_HEAD(>fbs);
> + mutex_init(>fbs_lock);
> + INIT_LIST_HEAD(>blobs);
> + INIT_LIST_HEAD(>pending_event_list);
> + INIT_LIST_HEAD(>event_list);
> + init_waitqueue_head(>event_wait);
> + file->event_space = 4096; /* set aside 4k for event buffer */
> + mutex_init(>event_read_lock);
> +
> + if (drm_core_check_feature(dev, DRIVER_GEM))
> + drm_gem_open(dev, file);
> + if (drm_core_check_feature(dev, DRIVER_PRIME))
> + drm_prime_init_file_private(>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(>prime);
> + if (drm_core_check_feature(dev, DRIVER_GEM))
> + drm_gem_release(dev, file);
> + put_pid(file->pid);
> + kfree(file);
> + return ERR_PTR(ret);
> +}
> +
> +/**
> + * 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.
> + *
> + * 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_pending_event *e;
> + struct drm_device *dev;
> +
> + if (!file)
> + return;
> +
> + dev = file->minor->dev;
> +
> + if (dev->driver->preclose)
> + dev->driver->preclose(dev, file);
> + if (!drm_core_check_feature(dev, DRIVER_MODESET))
> + drm_legacy_lock_release(dev, file->legacy_filp);
> + if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
> + drm_legacy_reclaim_buffers(dev, file);
> +
> + spin_lock_irq(>event_lock);
> + while ((e = list_first_entry_or_null(>pending_event_list,
> +  struct drm_pending_event,
> +  pending_link))) {
> + list_del(>pending_link);
> + e->file_priv = NULL;
> + }
> + while ((e = 

[PATCH 4/6] drm: provide management functions for drm_file

2016-09-01 Thread David Herrmann
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 
---
 drivers/gpu/drm/drm_drv.c  | 135 +
 drivers/gpu/drm/drm_fops.c | 132 +++-
 drivers/gpu/drm/drm_internal.h |   4 ++
 3 files changed, 147 insertions(+), 124 deletions(-)

diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 57ce973..9ab0016 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -95,6 +95,141 @@ void drm_ut_debug_printk(const char *function_name, const 
char *format, ...)
 }
 EXPORT_SYMBOL(drm_ut_debug_printk);

+/**
+ * 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.
+ *
+ * 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;
+   file->authenticated = capable(CAP_SYS_ADMIN); /* legacy compat */
+   INIT_LIST_HEAD(>lhead);
+   INIT_LIST_HEAD(>fbs);
+   mutex_init(>fbs_lock);
+   INIT_LIST_HEAD(>blobs);
+   INIT_LIST_HEAD(>pending_event_list);
+   INIT_LIST_HEAD(>event_list);
+   init_waitqueue_head(>event_wait);
+   file->event_space = 4096; /* set aside 4k for event buffer */
+   mutex_init(>event_read_lock);
+
+   if (drm_core_check_feature(dev, DRIVER_GEM))
+   drm_gem_open(dev, file);
+   if (drm_core_check_feature(dev, DRIVER_PRIME))
+   drm_prime_init_file_private(>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(>prime);
+   if (drm_core_check_feature(dev, DRIVER_GEM))
+   drm_gem_release(dev, file);
+   put_pid(file->pid);
+   kfree(file);
+   return ERR_PTR(ret);
+}
+
+/**
+ * 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.
+ *
+ * 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_pending_event *e;
+   struct drm_device *dev;
+
+   if (!file)
+   return;
+
+   dev = file->minor->dev;
+
+   if (dev->driver->preclose)
+   dev->driver->preclose(dev, file);
+   if (!drm_core_check_feature(dev, DRIVER_MODESET))
+   drm_legacy_lock_release(dev, file->legacy_filp);
+   if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+   drm_legacy_reclaim_buffers(dev, file);
+
+   spin_lock_irq(>event_lock);
+   while ((e = list_first_entry_or_null(>pending_event_list,
+struct drm_pending_event,
+pending_link))) {
+   list_del(>pending_link);
+   e->file_priv = NULL;
+   }
+   while ((e = list_first_entry_or_null(>event_list,
+struct drm_pending_event, link))) {
+   list_del(>link);
+   kfree(e);
+   }
+   spin_unlock_irq(>event_lock);
+
+   drm_legacy_ctxbitmap_flush(dev, 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_GEM))
+