2012년 2월 23일 오전 4:29, Ben Widawsky ben@bwidawsk.net님의 말:
From: Dave Airlie airlied@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
Tested-by: Inki Dae inki.dae@samsung.com
for this, you can refer to following link: http://git.infradead.org/users/kmpark/linux-samsung/shortlog/refs/heads/exyn...
Thanks.