From: Dave Airlie <airl...@redhat.com>

---
 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);
+}
+
+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;
+};
+
 #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_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@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to