From 3248877ea1796915419fba7c89315fdbf00cb56a Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 25 Nov 2011 15:21:02 +0000 Subject: drm: base prime/dma-buf support (v5) This adds the basic drm dma-buf interface layer, called PRIME. This commit doesn't add any driver support, it is simply and agreed upon starting point so we can work towards merging driver support for the next merge window. Current drivers with work done are nouveau, i915, udl, exynos and omap. The main APIs exposed to userspace allow translating a 32-bit object handle to a file descriptor, and a file descriptor to a 32-bit object handle. The flags value is currently limited to O_CLOEXEC. Acknowledgements: Daniel Vetter: lots of review Rob Clark: cleaned up lots of the internals and did lifetime review. v2: rename some functions after Chris preferred a green shed fix IS_ERR_OR_NULL -> IS_ERR v3: Fix Ville pointed out using buffer + kmalloc v4: add locking as per ickle review v5: allow re-exporting the original dma-buf (Daniel) Reviewed-by: Daniel Vetter Reviewed-by: Rob Clark Reviewed-by: Sumit Semwal Reviewed-by: Inki Dae Acked-by: Ben Widawsky Signed-off-by: Dave Airlie --- include/drm/drm.h | 14 +++++++++++- include/drm/drmP.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm.h b/include/drm/drm.h index 34a7b89fd006..64ff02d5b730 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -617,6 +617,17 @@ struct drm_get_cap { __u64 value; }; +#define DRM_CLOEXEC O_CLOEXEC +struct drm_prime_handle { + __u32 handle; + + /** Flags.. only applicable for handle->fd */ + __u32 flags; + + /** Returned dmabuf file descriptor */ + __s32 fd; +}; + #include "drm_mode.h" #define DRM_IOCTL_BASE 'd' @@ -673,7 +684,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 574bd1c81ebd..dd731043fecd 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -91,6 +91,7 @@ struct drm_device; #define DRM_UT_CORE 0x01 #define DRM_UT_DRIVER 0x02 #define DRM_UT_KMS 0x04 +#define DRM_UT_PRIME 0x08 /* * Three debug levels are defined. * drm_core, drm_driver, drm_kms @@ -150,6 +151,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 @@ -215,6 +217,11 @@ int drm_err(const char *func, const char *format, ...); drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, \ __func__, fmt, ##args); \ } while (0) +#define DRM_DEBUG_PRIME(fmt, args...) \ + do { \ + drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME, \ + __func__, fmt, ##args); \ + } while (0) #define DRM_LOG(fmt, args...) \ do { \ drm_ut_debug_printk(DRM_UT_CORE, NULL, \ @@ -238,6 +245,7 @@ int drm_err(const char *func, const char *format, ...); #else #define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0) #define DRM_DEBUG_KMS(fmt, args...) do { } while (0) +#define DRM_DEBUG_PRIME(fmt, args...) do { } while (0) #define DRM_DEBUG(fmt, arg...) do { } while (0) #define DRM_LOG(fmt, arg...) do { } while (0) #define DRM_LOG_KMS(fmt, args...) do { } while (0) @@ -410,6 +418,12 @@ struct drm_pending_event { void (*destroy)(struct drm_pending_event *event); }; +/* initial implementaton using a linked list - todo hashtab */ +struct drm_prime_file_private { + struct list_head head; + struct mutex lock; +}; + /** File private data */ struct drm_file { int authenticated; @@ -437,6 +451,8 @@ struct drm_file { wait_queue_head_t event_wait; struct list_head event_list; int event_space; + + struct drm_prime_file_private prime; }; /** Wait queue */ @@ -652,6 +668,12 @@ struct drm_gem_object { uint32_t pending_write_domain; void *driver_private; + + /* 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; }; #include "drm_crtc.h" @@ -890,6 +912,20 @@ 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: */ + /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */ + int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd); + /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */ + int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, + int prime_fd, uint32_t *handle); + /* export GEM -> dmabuf */ + struct dma_buf * (*gem_prime_export)(struct drm_device *dev, + struct drm_gem_object *obj, int flags); + /* import dmabuf -> GEM */ + struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, + struct dma_buf *dma_buf); + /* vga arb irq handler */ void (*vgaarb_irq)(struct drm_device *dev, bool state); @@ -1509,6 +1545,32 @@ 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_gem_prime_handle_to_fd(struct drm_device *dev, + struct drm_file *file_priv, uint32_t handle, uint32_t flags, + int *prime_fd); +extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, uint32_t *handle); + +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_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle); +int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle); +void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf); + +int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj); +int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf, + struct drm_gem_object **obj); + #if DRM_DEBUG_CODE extern int drm_vma_info(struct seq_file *m, void *data); #endif -- cgit v1.2.3 From 650dc07ec3b0eba8ff21da706d2b1876ada59fc3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Apr 2012 10:08:35 +0200 Subject: drm/i915: disable ppgtt on snb when dmar is enabled Totally unexpected that this regressed. Luckily it sounds like we just need to have dmar disable on the igfx, not the entire system. At least that's what a few days of testing between Tony Vroon and me indicates. Reported-by: Tony Vroon Cc: Tony Vroon Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43024 Acked-by: Chris Wilson Signed-Off-by: Daniel Vetter --- include/drm/intel-gtt.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include/drm') diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 0a0001b9dc78..923afb5dcf0c 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -44,4 +44,8 @@ void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, /* flag for GFDT type */ #define AGP_USER_CACHED_MEMORY_GFDT (1 << 3) +#ifdef CONFIG_INTEL_IOMMU +extern int intel_iommu_gfx_mapped; +#endif + #endif -- cgit v1.2.3 From dcf9af822803bcc2cd9e8009648547e6060b59a0 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Tue, 3 Apr 2012 21:27:58 +0900 Subject: drm/exynos: fixed page align and code clean. 1M section, 64k page count also should be rounded up so this patch rounds up them and caculates page count of them properly and also checks memory flags from user. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- include/drm/exynos_drm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 3963116083ae..1bb2d4719201 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -96,7 +96,8 @@ struct drm_exynos_plane_set_zpos { /* memory type definitions. */ enum e_drm_exynos_gem_mem_type { /* Physically Non-Continuous memory. */ - EXYNOS_BO_NONCONTIG = 1 << 0 + EXYNOS_BO_NONCONTIG = 1 << 0, + EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG }; #define DRM_EXYNOS_GEM_CREATE 0x00 -- cgit v1.2.3 From 490aa60ee7e884febf4818234d5c97669665db9a Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Thu, 12 Apr 2012 16:42:54 +0900 Subject: drm/exynos: fixed exynos broken ioctl this patch removes the pointer of uint64_t *edid. it should be just a uint64_t. Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- include/drm/exynos_drm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h index 1bb2d4719201..e478de4e5d56 100644 --- a/include/drm/exynos_drm.h +++ b/include/drm/exynos_drm.h @@ -85,7 +85,7 @@ struct drm_exynos_gem_mmap { struct drm_exynos_vidi_connection { unsigned int connection; unsigned int extensions; - uint64_t *edid; + uint64_t edid; }; struct drm_exynos_plane_set_zpos { -- cgit v1.2.3