From b0bc5f1ae559c705565e516ebb289bf072559dec Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Dec 2007 11:42:17 -0800 Subject: Make ttm create/destroy APIs consistent. Pass page_flags in create. Creating a ttm was done with drm_ttm_init while destruction was done with drm_destroy_ttm. Renaming these to drm_ttm_create and drm_ttm_destroy makes their use clearer. Passing page_flags to the create function will allow that to know whether user or kernel pages are needed, with the goal of allowing kernel ttms to be saved for later reuse. --- linux-core/drm_objects.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 1dc61fde..66611f6d 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -297,7 +297,7 @@ struct drm_ttm { }; -extern struct drm_ttm *drm_ttm_init(struct drm_device *dev, unsigned long size); +extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags); extern int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem); extern void drm_ttm_unbind(struct drm_ttm *ttm); extern void drm_ttm_evict(struct drm_ttm *ttm); @@ -318,7 +318,7 @@ extern int drm_ttm_set_user(struct drm_ttm *ttm, * Otherwise it is called when the last vma exits. */ -extern int drm_destroy_ttm(struct drm_ttm *ttm); +extern int drm_ttm_destroy(struct drm_ttm *ttm); #define DRM_FLAG_MASKED(_old, _new, _mask) {\ (_old) ^= (((_old) ^ (_new)) & (_mask)); \ -- cgit v1.2.3 From b5181d2506be332db8b07c02cdf37c6e25545c4d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Dec 2007 12:33:35 -0800 Subject: Document drm_bo_do_validate. Remove spurious 'do_wait' parameter. Add comments about the parameters to drm_bo_do_validate, along with comments for the DRM_BO_HINT options. Remove the 'do_wait' parameter as it is duplicated by DRM_BO_HINT_DONT_BLOCK. --- linux-core/drm_objects.h | 1 - 1 file changed, 1 deletion(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 66611f6d..1c6ca795 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -546,7 +546,6 @@ extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_ extern int drm_bo_do_validate(struct drm_buffer_object *bo, uint64_t flags, uint64_t mask, uint32_t hint, uint32_t fence_class, - int no_wait, struct drm_bo_info_rep *rep); /* -- cgit v1.2.3 From 5f23519b14e54823c94f5db5ad81e6bd5ffd3877 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Dec 2007 12:45:55 -0800 Subject: Document drm_bo_handle_validate. Match drm_bo_do_validate parameter order. Document parameters and usage for drm_bo_handle_validate. Change parameter order to match drm_bo_do_validate (fence_class has been moved to after flags, hint and mask values). Existing users of this function have been changed, but out-of-tree users must be modified separately. --- linux-core/drm_objects.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 1c6ca795..0926b47b 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -535,9 +535,8 @@ extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type); extern int drm_bo_init_mm(struct drm_device *dev, unsigned type, unsigned long p_offset, unsigned long p_size); extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle, - uint32_t fence_class, uint64_t flags, - uint64_t mask, uint32_t hint, - int use_old_fence_class, + uint64_t flags, uint64_t mask, uint32_t hint, + uint32_t fence_class, int use_old_fence_class, struct drm_bo_info_rep *rep, struct drm_buffer_object **bo_rep); extern struct drm_buffer_object *drm_lookup_buffer_object(struct drm_file *file_priv, -- cgit v1.2.3 From 6d44f48002c19d67187adb660ef74dd1870d52c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Dec 2007 00:54:25 -0800 Subject: Clean up and document drm_ttm.c APIs. drm_bind_ttm -> drm_ttm_bind. Aside from changing drm_bind_ttm to drm_ttm_bind, this patch adds only documentation and fixes the functions inside drm_ttm.c to all be prefixed with drm_ttm_. --- linux-core/drm_objects.h | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 0926b47b..fa029d8e 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -298,7 +298,7 @@ struct drm_ttm { }; extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags); -extern int drm_bind_ttm(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem); +extern int drm_ttm_bind(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem); extern void drm_ttm_unbind(struct drm_ttm *ttm); extern void drm_ttm_evict(struct drm_ttm *ttm); extern void drm_ttm_fixup_caching(struct drm_ttm *ttm); @@ -331,14 +331,47 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm); * Page flags. */ +/* + * This ttm should not be cached by the CPU + */ #define DRM_TTM_PAGE_UNCACHED (1 << 0) +/* + * This flat is not used at this time; I don't know what the + * intent was + */ #define DRM_TTM_PAGE_USED (1 << 1) +/* + * This flat is not used at this time; I don't know what the + * intent was + */ #define DRM_TTM_PAGE_BOUND (1 << 2) +/* + * This flat is not used at this time; I don't know what the + * intent was + */ #define DRM_TTM_PAGE_PRESENT (1 << 3) +/* + * The array of page pointers was allocated with vmalloc + * instead of drm_calloc. + */ #define DRM_TTM_PAGE_VMALLOC (1 << 4) +/* + * This ttm is mapped from user space + */ #define DRM_TTM_PAGE_USER (1 << 5) -#define DRM_TTM_PAGE_USER_WRITE (1 << 6) +/* + * This ttm will be written to by the GPU + */ +#define DRM_TTM_PAGE_USER_WRITE (1 << 6) +/* + * This ttm was mapped to the GPU, and so the contents may have + * been modified + */ #define DRM_TTM_PAGE_USER_DIRTY (1 << 7) +/* + * This flag is not used at this time; I don't know what the + * intent was. + */ #define DRM_TTM_PAGE_USER_DMA (1 << 8) /*************************************************** -- cgit v1.2.3 From 881ee70ab7bab5d6f6140dc9bf1e19c7b5844084 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Dec 2007 01:12:07 -0800 Subject: Move dummy_read_page from drm_ttm_set_user to drm_ttm_create. I'm hoping to use the dummy_read_page for kernel allocated buffers to avoid allocating extra pages for read-only buffers (like vertex and batch buffers). This also eliminates the 'write' parameter to drm_ttm_set_user and just has DRM_TTM_PAGE_WRITE passed into drm_ttm_create. --- linux-core/drm_objects.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index fa029d8e..375420dc 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -297,7 +297,9 @@ struct drm_ttm { }; -extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, uint32_t page_flags); +extern struct drm_ttm *drm_ttm_create(struct drm_device *dev, unsigned long size, + uint32_t page_flags, + struct page *dummy_read_page); extern int drm_ttm_bind(struct drm_ttm *ttm, struct drm_bo_mem_reg *bo_mem); extern void drm_ttm_unbind(struct drm_ttm *ttm); extern void drm_ttm_evict(struct drm_ttm *ttm); @@ -307,10 +309,8 @@ extern void drm_ttm_cache_flush(void); extern int drm_ttm_populate(struct drm_ttm *ttm); extern int drm_ttm_set_user(struct drm_ttm *ttm, struct task_struct *tsk, - int write, unsigned long start, - unsigned long num_pages, - struct page *dummy_read_page); + unsigned long num_pages); /* * Destroy a ttm. The user normally calls drmRmMap or a similar IOCTL to do @@ -362,7 +362,7 @@ extern int drm_ttm_destroy(struct drm_ttm *ttm); /* * This ttm will be written to by the GPU */ -#define DRM_TTM_PAGE_USER_WRITE (1 << 6) +#define DRM_TTM_PAGE_WRITE (1 << 6) /* * This ttm was mapped to the GPU, and so the contents may have * been modified -- cgit v1.2.3 From 37fb2ac4071f62bad2c36cc9ca84f9c8feee6bf5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Dec 2007 01:47:51 -0800 Subject: Use dummy_read_page for unpopulated kernel-allocated ttm pages. Previously, dummy_read_page was used only for read-only user allocations; it filled in pages that were not present in the user address map (presumably, these were allocated but never written to pages). This patch allows them to be used for read-only ttms allocated from the kernel, so that applications can over-allocate buffers without forcing every page to be allocated. --- linux-core/drm_objects.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 375420dc..47b6b018 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -263,7 +263,8 @@ struct drm_ttm_backend; struct drm_ttm_backend_func { int (*needs_ub_cache_adjust) (struct drm_ttm_backend *backend); int (*populate) (struct drm_ttm_backend *backend, - unsigned long num_pages, struct page **pages); + unsigned long num_pages, struct page **pages, + struct page *dummy_read_page); void (*clear) (struct drm_ttm_backend *backend); int (*bind) (struct drm_ttm_backend *backend, struct drm_bo_mem_reg *bo_mem); -- cgit v1.2.3 From d1187641d64f442968a3b9ea6a19de6cdd45acd4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Dec 2007 20:16:50 -0800 Subject: Rename inappropriately named 'mask' fields to 'proposed_flags' instead. Flags pending validation were stored in a misleadingly named field, 'mask'. As 'mask' is already used to indicate pieces of a flags field which are changing, it seems better to use a name reflecting the actual purpose of this field. I chose 'proposed_flags' as they may not actually end up in 'flags', and in an case will be modified when they are moved over. This affects the API, but not ABI of the user-mode interface. --- linux-core/drm_objects.h | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 47b6b018..98421e4c 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -385,8 +385,20 @@ struct drm_bo_mem_reg { unsigned long num_pages; uint32_t page_alignment; uint32_t mem_type; + /* + * Current buffer status flags, indicating + * where the buffer is located and which + * access modes are in effect + */ uint64_t flags; - uint64_t mask; + /** + * These are the flags proposed for + * a validate operation. If the + * validate succeeds, they'll get moved + * into the flags field + */ + uint64_t proposed_flags; + uint32_t desired_tile_stride; uint32_t hw_tile_stride; }; @@ -511,9 +523,36 @@ struct drm_bo_driver { int (*invalidate_caches) (struct drm_device *dev, uint64_t flags); int (*init_mem_type) (struct drm_device *dev, uint32_t type, struct drm_mem_type_manager *man); - uint32_t(*evict_mask) (struct drm_buffer_object *bo); + /* + * evict_flags: + * + * @bo: the buffer object to be evicted + * + * Return the bo flags for a buffer which is not mapped to the hardware. + * These will be placed in proposed_flags so that when the move is + * finished, they'll end up in bo->mem.flags + */ + uint64_t(*evict_flags) (struct drm_buffer_object *bo); + /* + * move: + * + * @bo: the buffer to move + * + * @evict: whether this motion is evicting the buffer from + * the graphics address space + * + * @no_wait: whether this should give up and return -EBUSY + * if this move would require sleeping + * + * @new_mem: the new memory region receiving the buffer + * + * Move a buffer between two memory regions. + */ int (*move) (struct drm_buffer_object *bo, int evict, int no_wait, struct drm_bo_mem_reg *new_mem); + /* + * ttm_cache_flush + */ void (*ttm_cache_flush)(struct drm_ttm *ttm); }; @@ -554,7 +593,7 @@ extern int drm_fence_buffer_objects(struct drm_device *dev, struct drm_fence_object **used_fence); extern void drm_bo_add_to_lru(struct drm_buffer_object *bo); extern int drm_buffer_object_create(struct drm_device *dev, unsigned long size, - enum drm_bo_type type, uint64_t mask, + enum drm_bo_type type, uint64_t flags, uint32_t hint, uint32_t page_alignment, unsigned long buffer_start, struct drm_buffer_object **bo); -- cgit v1.2.3 From da3601e43ae75695f3b080904b1e090c8eb1cd8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Dec 2007 22:00:45 -0800 Subject: Change drm_bo_type_dc to drm_bo_type_device and comment usage of this value. I couldn't figure out what drm_bo_type_dc was for; Dave Airlie finally clued me in that it was the 'normal' buffer objects with kernel allocated pages that could be mmapped from the drm device file. I thought that 'drm_bo_type_device' was a more descriptive name. I also added a bunch of comments describing the use of the type enum values and the functions that use them. --- linux-core/drm_objects.h | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_objects.h') diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 98421e4c..a2d10b5d 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -404,9 +404,31 @@ struct drm_bo_mem_reg { }; enum drm_bo_type { - drm_bo_type_dc, + /* + * drm_bo_type_device are 'normal' drm allocations, + * pages are allocated from within the kernel automatically + * and the objects can be mmap'd from the drm device. Each + * drm_bo_type_device object has a unique name which can be + * used by other processes to share access to the underlying + * buffer. + */ + drm_bo_type_device, + /* + * drm_bo_type_user are buffers of pages that already exist + * in the process address space. They are more limited than + * drm_bo_type_device buffers in that they must always + * remain cached (as we assume the user pages are mapped cached), + * and they are not sharable to other processes through DRM + * (although, regular shared memory should still work fine). + */ drm_bo_type_user, - drm_bo_type_kernel, /* for initial kernel allocations */ + /* + * drm_bo_type_kernel are buffers that exist solely for use + * within the kernel. The pages cannot be mapped into the + * process. One obvious use would be for the ring + * buffer where user access would not (ideally) be required. + */ + drm_bo_type_kernel, }; struct drm_buffer_object { -- cgit v1.2.3