Re: [PATCH 1/7] drm: base prime support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 22, 2012 at 2:29 PM, Ben Widawsky <ben@xxxxxxxxxxxx> wrote:
> From: Dave Airlie <airlied@xxxxxxxxxx>
>
> ---
>  drivers/gpu/drm/Makefile    |    2 +-
>  drivers/gpu/drm/drm_drv.c   |    3 +
>  drivers/gpu/drm/drm_gem.c   |    3 +-
>  drivers/gpu/drm/drm_prime.c |  126 +++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm.h           |   10 +++-
>  include/drm/drmP.h          |   35 ++++++++++++
>  6 files changed, 176 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_prime.c
>
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 0cde1b8..202f650 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -12,7 +12,7 @@ drm-y       :=        drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
>                drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
>                drm_crtc.o drm_modes.o drm_edid.o \
>                drm_info.o drm_debugfs.o drm_encoder_slave.o \
> -               drm_trace_points.o drm_global.o drm_usb.o
> +               drm_trace_points.o drm_global.o drm_usb.o drm_prime.o
>
>  drm-$(CONFIG_COMPAT) += drm_ioc32.o
>
> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> index ebf7d3f..786b134 100644
> --- a/drivers/gpu/drm/drm_drv.c
> +++ b/drivers/gpu/drm/drm_drv.c
> @@ -135,6 +135,9 @@ static struct drm_ioctl_desc drm_ioctls[] = {
>        DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
>        DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
>
> +       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +       DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED),
> +
>        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
>        DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index f8625e2..e19a958 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -145,6 +145,7 @@ int drm_gem_object_init(struct drm_device *dev,
>        kref_init(&obj->refcount);
>        atomic_set(&obj->handle_count, 0);
>        obj->size = size;
> +       obj->prime_fd = -1;
>
>        return 0;
>  }
> @@ -166,7 +167,7 @@ int drm_gem_private_object_init(struct drm_device *dev,
>        kref_init(&obj->refcount);
>        atomic_set(&obj->handle_count, 0);
>        obj->size = size;
> -
> +       obj->prime_fd = -1;
>        return 0;
>  }
>  EXPORT_SYMBOL(drm_gem_private_object_init);
> diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
> new file mode 100644
> index 0000000..11f142f
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_prime.c
> @@ -0,0 +1,126 @@
> +#include <linux/export.h>
> +#include <linux/dma-buf.h>
> +#include "drmP.h"
> +
> +struct drm_prime_member {
> +       struct list_head entry;
> +       struct dma_buf *dma_buf;
> +       uint32_t handle;
> +};
> +
> +int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
> +                                struct drm_file *file_priv)
> +{
> +       struct drm_prime_handle *args = data;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_PRIME))
> +               return -EINVAL;
> +
> +       return dev->driver->prime_handle_to_fd(dev, file_priv, args->handle, &args->fd);

We need a way to pass flags to this so we can pass DRM_PRIME_CLOEXEC
(or whatever, but not O_CLOEXEC) to create the fd in close-on-exec
mode, and it needs to be available in the libdrm API.  See man
epoll_create1 for an example where we had to add a new brown-bag
syscall to allow this.

> +}
> +
> +int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
> +                                struct drm_file *file_priv)
> +{
> +       struct drm_prime_handle *args = data;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_PRIME))
> +               return -EINVAL;
> +
> +       return dev->driver->prime_fd_to_handle(dev, file_priv, args->fd, &args->handle);
> +}
> +
> +struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
> +{
> +       struct sg_table *sg = NULL;
> +       struct scatterlist *iter;
> +       int i;
> +       int ret;
> +
> +       sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
> +       if (!sg)
> +               goto out;
> +
> +       ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL);
> +       if (ret)
> +               goto out;
> +
> +       for_each_sg(sg->sgl, iter, nr_pages, i)
> +               sg_set_page(iter, pages[i], PAGE_SIZE, 0);
> +
> +       return sg;
> +out:
> +       kfree(sg);
> +       return NULL;
> +}
> +EXPORT_SYMBOL(drm_prime_pages_to_sg);
> +
> +/* helper function to cleanup a GEM/prime object */
> +void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
> +{
> +       struct dma_buf_attachment *attach;
> +
> +       attach = obj->import_attach;
> +       if (sg)
> +               dma_buf_unmap_attachment(attach, sg);
> +       dma_buf_detach(attach->dmabuf, attach);
> +}
> +EXPORT_SYMBOL(drm_prime_gem_destroy);
> +
> +void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
> +{
> +       INIT_LIST_HEAD(&prime_fpriv->head);
> +}
> +EXPORT_SYMBOL(drm_prime_init_file_private);
> +
> +void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
> +{
> +       struct drm_prime_member *member, *safe;
> +       list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
> +               list_del(&member->entry);
> +               kfree(member);
> +       }
> +}
> +EXPORT_SYMBOL(drm_prime_destroy_file_private);
> +
> +int drm_prime_insert_fd_handle_mapping(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
> +{
> +       struct drm_prime_member *member;
> +
> +       member = kmalloc(sizeof(*member), GFP_KERNEL);
> +       if (!member)
> +               return -ENOMEM;
> +
> +       member->dma_buf = dma_buf;
> +       member->handle = handle;
> +       list_add(&member->entry, &prime_fpriv->head);
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_prime_insert_fd_handle_mapping);
> +
> +int drm_prime_lookup_fd_handle_mapping(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
> +{
> +       struct drm_prime_member *member;
> +
> +       list_for_each_entry(member, &prime_fpriv->head, entry) {
> +               if (member->dma_buf == dma_buf) {
> +                       *handle = member->handle;
> +                       return 0;
> +               }
> +       }
> +       return -ENOENT;
> +}
> +EXPORT_SYMBOL(drm_prime_lookup_fd_handle_mapping);
> +
> +void drm_prime_remove_fd_handle_mapping(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
> +{
> +       struct drm_prime_member *member, *safe;
> +
> +       list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
> +               if (member->dma_buf == dma_buf) {
> +                       list_del(&member->entry);
> +                       kfree(member);
> +               }
> +       }
> +}
> +EXPORT_SYMBOL(drm_prime_remove_fd_handle_mapping);
> diff --git a/include/drm/drm.h b/include/drm/drm.h
> index 49d94ed..3dcae79 100644
> --- a/include/drm/drm.h
> +++ b/include/drm/drm.h
> @@ -617,6 +617,13 @@ struct drm_get_cap {
>        __u64 value;
>  };
>
> +struct drm_prime_handle {
> +       __u32 handle;
> +
> +       /* returned fd for prime */
> +       __s32 fd;

__u32 flags;

> +};
> +
>  #include "drm_mode.h"
>
>  #define DRM_IOCTL_BASE                 'd'
> @@ -673,7 +680,8 @@ struct drm_get_cap {
>  #define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, struct drm_lock)
>  #define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, struct drm_lock)
>
> -#define DRM_IOCTL_GEM_PRIME_OPEN        DRM_IOWR(0x2e, struct drm_gem_open)
> +#define DRM_IOCTL_PRIME_HANDLE_TO_FD    DRM_IOWR(0x2d, struct drm_prime_handle)
> +#define DRM_IOCTL_PRIME_FD_TO_HANDLE    DRM_IOWR(0x2e, struct drm_prime_handle)
>

#define DRM_PRIME_CLOEXEC 0x01

>  #define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
>  #define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 92f0981..9558111 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -150,6 +150,7 @@ int drm_err(const char *func, const char *format, ...);
>  #define DRIVER_IRQ_VBL2    0x800
>  #define DRIVER_GEM         0x1000
>  #define DRIVER_MODESET     0x2000
> +#define DRIVER_PRIME       0x4000
>
>  #define DRIVER_BUS_PCI 0x1
>  #define DRIVER_BUS_PLATFORM 0x2
> @@ -652,6 +653,19 @@ struct drm_gem_object {
>        uint32_t pending_write_domain;
>
>        void *driver_private;
> +
> +       /* prime fd exporting this object, -1 for no fd */
> +       int prime_fd;
> +       /* dma buf exported from this GEM object */
> +       struct dma_buf *export_dma_buf;
> +
> +       /* dma buf attachment backing this object */
> +       struct dma_buf_attachment *import_attach;
> +};
> +
> +/* initial implementaton using a linked list - todo hashtab */
> +struct drm_prime_file_private {
> +       struct list_head head;
>  };
>
>  #include "drm_crtc.h"
> @@ -890,6 +904,13 @@ struct drm_driver {
>        int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
>        void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
>
> +       /* prime */
> +       int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
> +                                 uint32_t handle, int *prime_fd);
> +
> +       int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
> +                                 int prime_fd, uint32_t *handle);
> +
>        /* vga arb irq handler */
>        void (*vgaarb_irq)(struct drm_device *dev, bool state);
>
> @@ -1502,6 +1523,20 @@ extern int drm_vblank_info(struct seq_file *m, void *data);
>  extern int drm_clients_info(struct seq_file *m, void* data);
>  extern int drm_gem_name_info(struct seq_file *m, void *data);
>
> +extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
> +                                       struct drm_file *file_priv);
> +extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
> +                                       struct drm_file *file_priv);
> +
> +extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages);
> +extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
> +
> +void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
> +void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
> +int drm_prime_insert_fd_handle_mapping(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
> +int drm_prime_lookup_fd_handle_mapping(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
> +void drm_prime_remove_fd_handle_mapping(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
> +
>  #if DRM_DEBUG_CODE
>  extern int drm_vma_info(struct seq_file *m, void *data);
>  #endif
> --
> 1.7.9.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@xxxxxxxxxxxxxxxxxxxxx
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux