From 12b989a7108a52f16b1b1bb6dd2ea818c235b52c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 4 Oct 2007 09:51:01 +0200 Subject: Revert "Remove the pinned buffer from the LRU when pinning." This reverts 3a0bc518e35c62bb9c64c9105f836584d949653f commit. --- linux-core/Makefile | 1 - linux-core/drm_bo.c | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'linux-core') diff --git a/linux-core/Makefile b/linux-core/Makefile index 6eb5bf5c..7f6b123e 100644 --- a/linux-core/Makefile +++ b/linux-core/Makefile @@ -269,7 +269,6 @@ PAGE_AGP := $(shell cat $(LINUXDIR)/include/asm/agp.h 2>/dev/null | \ ifneq ($(PAGE_AGP),0) EXTRA_CFLAGS += -DHAVE_PAGE_AGP endif -EXTRA_CFLAGS += -g # Start with all modules turned off. CONFIG_DRM_GAMMA := n diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index fb360e7f..099ebe07 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1965,8 +1965,8 @@ drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, return ret; } - /* Validate the buffer into its pinned location, with no - * pending fence. + /* Validate the buffer into its pinned location, with no pending + * fence. */ ret = drm_buffer_object_validate(bo, bo->fence_class, 0, 0); if (ret) { @@ -1974,12 +1974,9 @@ drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, return ret; } - /* Pull the buffer off of the LRU and add it to the pinned - * list - */ + /* Add our buffer to the pinned list */ bo->pinned_mem_type = bo->mem.mem_type; mutex_lock(&dev->struct_mutex); - list_del_init(&bo->lru); list_del_init(&bo->pinned_lru); drm_bo_add_to_pinned_lru(bo); @@ -1989,7 +1986,6 @@ drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, bo->pinned_node = bo->mem.mm_node; } - bo->pinned = pin; mutex_unlock(&dev->struct_mutex); } else { @@ -2001,9 +1997,9 @@ drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, list_del_init(&bo->pinned_lru); bo->pinned_node = NULL; - bo->pinned = pin; mutex_unlock(&dev->struct_mutex); } + bo->pinned = pin; mutex_unlock(&bo->mutex); return 0; } -- cgit v1.2.3 From cd276d9cab0be8eff2d9450e5c95b6eb3cd639af Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 4 Oct 2007 10:01:30 +0200 Subject: Revert "Copy the important parts of object_validate into object_create()." This reverts f9c27aa50b715a7d21858f1ce9e4785120bd0c36 commit. --- linux-core/drm_bo.c | 44 +++++++++----------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 099ebe07..6e1de80b 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1587,7 +1587,6 @@ int drm_buffer_object_create(struct drm_device *dev, { struct drm_buffer_manager *bm = &dev->bm; struct drm_buffer_object *bo; - struct drm_bo_driver *driver = dev->driver->bo_driver; int ret = 0; unsigned long num_pages; @@ -1646,7 +1645,7 @@ int drm_buffer_object_create(struct drm_device *dev, if (ret) goto out_err; } - +#if 0 bo->fence_class = 0; ret = driver->fence_type(bo, &bo->fence_class, &bo->fence_type); if (ret) { @@ -1655,13 +1654,12 @@ int drm_buffer_object_create(struct drm_device *dev, } ret = drm_bo_add_ttm(bo); +#else + ret = drm_buffer_object_validate(bo, 0, 0, hint & DRM_BO_HINT_DONT_BLOCK); +#endif if (ret) goto out_err; - mutex_lock(&dev->struct_mutex); - drm_bo_add_to_lru(bo); - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&bo->mutex); *buf_obj = bo; return 0; @@ -1711,8 +1709,6 @@ int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_pr void __user *curuserarg = NULL; int ret; - DRM_DEBUG("drm_bo_op_ioctl\n"); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -1792,6 +1788,11 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; } +#if 0 + ret = drm_bo_lock_test(dev, file_priv); + if (ret) + goto out; +#endif ret = drm_buffer_object_create(file_priv->head->dev, req->size, drm_bo_type_dc, req->mask, @@ -1821,9 +1822,6 @@ int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_p struct drm_bo_info_req *req = &arg->d.req; struct drm_bo_info_rep *rep = &arg->d.rep; int ret; - - DRM_DEBUG("drm_bo_map_ioctl: buffer %d\n", req->handle); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -1841,9 +1839,6 @@ int drm_bo_unmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file { struct drm_bo_handle_arg *arg = data; int ret; - - DRM_DEBUG("drm_bo_unmap_ioctl: buffer %d\n", arg->handle); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -1862,8 +1857,6 @@ int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm_file * struct drm_user_object *uo; int ret; - DRM_DEBUG("drm_bo_reference_ioctl: buffer %d\n", req->handle); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -1886,8 +1879,6 @@ int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file struct drm_bo_handle_arg *arg = data; int ret = 0; - DRM_DEBUG("drm_bo_unreference_ioctl: buffer %d\n", arg->handle); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -1904,8 +1895,6 @@ int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ struct drm_bo_info_rep *rep = &arg->d.rep; int ret; - DRM_DEBUG("drm_bo_info_ioctl: buffer %d\n", req->handle); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -1924,9 +1913,6 @@ int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file * struct drm_bo_info_req *req = &arg->d.req; struct drm_bo_info_rep *rep = &arg->d.rep; int ret; - - DRM_DEBUG("drm_bo_wait_idle_ioctl: buffer %d\n", req->handle); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -2013,9 +1999,6 @@ int drm_bo_set_pin_ioctl(struct drm_device *dev, void *data, struct drm_buffer_object *bo; int ret; - DRM_DEBUG("drm_bo_set_pin_ioctl: buffer %d, pin %d\n", - req->handle, req->pin); - if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; @@ -2445,9 +2428,6 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ struct drm_bo_driver *driver = dev->driver->bo_driver; int ret; - DRM_DEBUG("drm_mm_init_ioctl: type %d, 0x%08llx offset, %dkb\n", - arg->mem_type, arg->p_offset * PAGE_SIZE, (int)(arg->p_size * 4)); - if (!driver) { DRM_ERROR("Buffer objects are not supported by this driver\n"); return -EINVAL; @@ -2502,8 +2482,6 @@ int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *f struct drm_bo_driver *driver = dev->driver->bo_driver; int ret; - DRM_DEBUG("drm_mm_takedown_ioctl: %d type\n", arg->mem_type); - if (!driver) { DRM_ERROR("Buffer objects are not supported by this driver\n"); return -EINVAL; @@ -2541,8 +2519,6 @@ int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ struct drm_bo_driver *driver = dev->driver->bo_driver; int ret; - DRM_DEBUG("drm_mm_lock_ioctl: %d type\n", arg->mem_type); - if (!driver) { DRM_ERROR("Buffer objects are not supported by this driver\n"); return -EINVAL; @@ -2565,8 +2541,6 @@ int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *fil struct drm_bo_driver *driver = dev->driver->bo_driver; int ret; - DRM_DEBUG("drm_mm_unlock_ioctl\n"); - if (!driver) { DRM_ERROR("Buffer objects are not supported by this driver\n"); return -EINVAL; -- cgit v1.2.3 From 0d1926d36e59ddfc34d8c9c0cdef10b71a49ecf1 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 4 Oct 2007 10:14:41 +0200 Subject: Revert "Replace NO_MOVE/NO_EVICT flags to buffer objects with an ioctl to set pinning." This reverts cf2d569daca6954d11a796f4d110148ae2e0c827 commit. --- linux-core/drm_bo.c | 174 ++++++++++++++--------------------------------- linux-core/drm_drv.c | 1 - linux-core/drm_objects.h | 3 +- 3 files changed, 52 insertions(+), 126 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 6e1de80b..7335d258 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -80,7 +80,8 @@ void drm_bo_add_to_lru(struct drm_buffer_object * bo) DRM_ASSERT_LOCKED(&bo->dev->struct_mutex); - if (!bo->pinned || bo->mem.mem_type != bo->pinned_mem_type) { + if (!(bo->mem.mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT)) + || bo->mem.mem_type != bo->pinned_mem_type) { man = &bo->dev->bm.man[bo->mem.mem_type]; list_add_tail(&bo->lru, &man->lru); } else { @@ -638,8 +639,7 @@ int drm_fence_buffer_objects(struct drm_device *dev, mutex_lock(&entry->mutex); mutex_lock(&dev->struct_mutex); list_del_init(l); - if (entry->priv_flags & _DRM_BO_FLAG_UNFENCED && - entry->fence_class == fence_class) { + if (entry->priv_flags & _DRM_BO_FLAG_UNFENCED) { count++; if (entry->fence) drm_fence_usage_deref_locked(&entry->fence); @@ -761,7 +761,7 @@ static int drm_bo_mem_force_space(struct drm_device * dev, atomic_inc(&entry->usage); mutex_unlock(&dev->struct_mutex); mutex_lock(&entry->mutex); - BUG_ON(entry->pinned); + BUG_ON(entry->mem.flags & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT)); ret = drm_bo_evict(entry, mem_type, no_wait); mutex_unlock(&entry->mutex); @@ -929,6 +929,18 @@ static int drm_bo_new_mask(struct drm_buffer_object * bo, DRM_ERROR("User buffers are not supported yet\n"); return -EINVAL; } + if (bo->type == drm_bo_type_fake && + !(new_mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))) { + DRM_ERROR("Fake buffers must be pinned.\n"); + return -EINVAL; + } + + if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { + DRM_ERROR + ("DRM_BO_FLAG_NO_EVICT is only available to priviliged " + "processes\n"); + return -EPERM; + } new_props = new_mask & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_READ); @@ -1372,12 +1384,6 @@ static int drm_buffer_object_validate(struct drm_buffer_object * bo, return ret; } - if (bo->pinned && bo->pinned_mem_type != bo->mem.mem_type) { - DRM_ERROR("Attempt to validate pinned buffer into different memory " - "type\n"); - return -EINVAL; - } - /* * We're switching command submission mechanism, * or cannot simply rely on the hardware serializing for us. @@ -1418,6 +1424,37 @@ static int drm_buffer_object_validate(struct drm_buffer_object * bo, } } + /* + * Pinned buffers. + */ + + if (bo->mem.mask & (DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE)) { + bo->pinned_mem_type = bo->mem.mem_type; + mutex_lock(&dev->struct_mutex); + list_del_init(&bo->pinned_lru); + drm_bo_add_to_pinned_lru(bo); + + if (bo->pinned_node != bo->mem.mm_node) { + if (bo->pinned_node != NULL) + drm_mm_put_block(bo->pinned_node); + bo->pinned_node = bo->mem.mm_node; + } + + mutex_unlock(&dev->struct_mutex); + + } else if (bo->pinned_node != NULL) { + + mutex_lock(&dev->struct_mutex); + + if (bo->pinned_node != bo->mem.mm_node) + drm_mm_put_block(bo->pinned_node); + + list_del_init(&bo->pinned_lru); + bo->pinned_node = NULL; + mutex_unlock(&dev->struct_mutex); + + } + /* * We might need to add a TTM. */ @@ -1517,10 +1554,6 @@ int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle, } EXPORT_SYMBOL(drm_bo_handle_validate); -/** - * Fills out the generic buffer object ioctl reply with the information for - * the BO with id of handle. - */ static int drm_bo_handle_info(struct drm_file *file_priv, uint32_t handle, struct drm_bo_info_rep *rep) { @@ -1926,112 +1959,6 @@ int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file * return 0; } -/** - * Pins or unpins the given buffer object in the given memory area. - * - * Pinned buffers will not be evicted from or move within their memory area. - * Must be called with the hardware lock held for pinning. - */ -static int -drm_bo_set_pin(struct drm_device *dev, struct drm_buffer_object *bo, - int pin) -{ - int ret = 0; - - mutex_lock(&bo->mutex); - if (bo->pinned == pin) { - mutex_unlock(&bo->mutex); - return 0; - } - - if (pin) { - ret = drm_bo_wait_unfenced(bo, 0, 0); - if (ret) { - mutex_unlock(&bo->mutex); - return ret; - } - - /* Validate the buffer into its pinned location, with no pending - * fence. - */ - ret = drm_buffer_object_validate(bo, bo->fence_class, 0, 0); - if (ret) { - mutex_unlock(&bo->mutex); - return ret; - } - - /* Add our buffer to the pinned list */ - bo->pinned_mem_type = bo->mem.mem_type; - mutex_lock(&dev->struct_mutex); - list_del_init(&bo->pinned_lru); - drm_bo_add_to_pinned_lru(bo); - - if (bo->pinned_node != bo->mem.mm_node) { - if (bo->pinned_node != NULL) - drm_mm_put_block(bo->pinned_node); - bo->pinned_node = bo->mem.mm_node; - } - - mutex_unlock(&dev->struct_mutex); - - } else { - mutex_lock(&dev->struct_mutex); - - /* Remove our buffer from the pinned list */ - if (bo->pinned_node != bo->mem.mm_node) - drm_mm_put_block(bo->pinned_node); - - list_del_init(&bo->pinned_lru); - bo->pinned_node = NULL; - mutex_unlock(&dev->struct_mutex); - } - bo->pinned = pin; - mutex_unlock(&bo->mutex); - return 0; -} - -int drm_bo_set_pin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_bo_set_pin_arg *arg = data; - struct drm_bo_set_pin_req *req = &arg->d.req; - struct drm_bo_info_rep *rep = &arg->d.rep; - struct drm_buffer_object *bo; - int ret; - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - if (req->pin < 0 || req->pin > 1) { - DRM_ERROR("Bad arguments to set_pin\n"); - return -EINVAL; - } - - if (req->pin) - LOCK_TEST_WITH_RETURN(dev, file_priv); - - mutex_lock(&dev->struct_mutex); - bo = drm_lookup_buffer_object(file_priv, req->handle, 1); - mutex_unlock(&dev->struct_mutex); - if (!bo) { - return -EINVAL; - } - - ret = drm_bo_set_pin(dev, bo, req->pin); - if (ret) { - drm_bo_usage_deref_unlocked(&bo); - return ret; - } - - drm_bo_fill_rep_arg(bo, rep); - drm_bo_usage_deref_unlocked(&bo); - - return 0; -} - - /** *Clean the unfenced list and put on regular LRU. *This is part of the memory manager cleanup and should only be @@ -2112,10 +2039,11 @@ static int drm_bo_leave_list(struct drm_buffer_object * bo, mutex_unlock(&dev->struct_mutex); } - if (bo->pinned) { - DRM_ERROR("A pinned buffer was present at " + if (bo->mem.flags & DRM_BO_FLAG_NO_EVICT) { + DRM_ERROR("A DRM_BO_NO_EVICT buffer present at " "cleanup. Removing flag and evicting.\n"); - bo->pinned = 0; + bo->mem.flags &= ~DRM_BO_FLAG_NO_EVICT; + bo->mem.mask &= ~DRM_BO_FLAG_NO_EVICT; } if (bo->mem.mem_type == mem_type) diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 0fca3a27..80e56938 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -145,7 +145,6 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_BO_OP, drm_bo_op_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_SET_PIN, drm_bo_set_pin_ioctl, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 726ccbe2..91378b8a 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -377,7 +377,6 @@ struct drm_buffer_object { unsigned long num_pages; /* For pinned buffers */ - int pinned; struct drm_mm_node *pinned_node; uint32_t pinned_mem_type; struct list_head pinned_lru; @@ -472,7 +471,7 @@ extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct d extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -int drm_bo_set_pin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); + extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -- cgit v1.2.3 From 086c058a417317491320129d2cbeb68d1cfcfefe Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 17 Oct 2007 10:55:21 +0200 Subject: Remove the op ioctl, and replace it with a setuser ioctl. Remove need for lock for now. May create races when we clean memory areas or on takedown. Needs to be fixed. Really do a validate on buffer creation in order to avoid problems with fixed memory buffers. --- linux-core/drm_bo.c | 146 +++++++++++++---------------------------------- linux-core/drm_drv.c | 2 +- linux-core/drm_objects.h | 4 +- 3 files changed, 41 insertions(+), 111 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 7335d258..bdeefec2 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -929,11 +929,6 @@ static int drm_bo_new_mask(struct drm_buffer_object * bo, DRM_ERROR("User buffers are not supported yet\n"); return -EINVAL; } - if (bo->type == drm_bo_type_fake && - !(new_mask & (DRM_BO_FLAG_NO_MOVE | DRM_BO_FLAG_NO_EVICT))) { - DRM_ERROR("Fake buffers must be pinned.\n"); - return -EINVAL; - } if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { DRM_ERROR @@ -942,6 +937,12 @@ static int drm_bo_new_mask(struct drm_buffer_object * bo, return -EPERM; } + if ((new_mask & DRM_BO_FLAG_NO_MOVE)) { + DRM_ERROR + ("DRM_BO_FLAG_NO_MOVE is not properly implemented yet.\n"); + return -EPERM; + } + new_props = new_mask & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_READ); @@ -1160,11 +1161,9 @@ static int drm_buffer_object_map(struct drm_file *file_priv, uint32_t handle, return -EINVAL; mutex_lock(&bo->mutex); - if (!(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) { - ret = drm_bo_wait_unfenced(bo, no_wait, 0); - if (ret) - goto out; - } + ret = drm_bo_wait_unfenced(bo, no_wait, 0); + if (ret) + goto out; /* * If this returns true, we are currently unmapped. @@ -1542,6 +1541,7 @@ int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle, return -EINVAL; } + ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, no_wait, rep); @@ -1663,8 +1663,10 @@ int drm_buffer_object_create(struct drm_device *dev, bo->mem.page_alignment = page_alignment; bo->buffer_start = buffer_start; bo->priv_flags = 0; - bo->mem.flags = 0ULL; - bo->mem.mask = 0ULL; + bo->mem.flags = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | + DRM_BO_FLAG_MAPPABLE; + bo->mem.mask = DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | + DRM_BO_FLAG_MAPPABLE; atomic_inc(&bm->count); ret = drm_bo_new_mask(bo, mask, hint); @@ -1678,18 +1680,8 @@ int drm_buffer_object_create(struct drm_device *dev, if (ret) goto out_err; } -#if 0 - bo->fence_class = 0; - ret = driver->fence_type(bo, &bo->fence_class, &bo->fence_type); - if (ret) { - DRM_ERROR("Driver did not support given buffer permissions\n"); - goto out_err; - } - ret = drm_bo_add_ttm(bo); -#else ret = drm_buffer_object_validate(bo, 0, 0, hint & DRM_BO_HINT_DONT_BLOCK); -#endif if (ret) goto out_err; @@ -1705,6 +1697,7 @@ int drm_buffer_object_create(struct drm_device *dev, } EXPORT_SYMBOL(drm_buffer_object_create); + static int drm_bo_add_user_object(struct drm_file *file_priv, struct drm_buffer_object *bo, int shareable) { @@ -1726,86 +1719,6 @@ static int drm_bo_add_user_object(struct drm_file *file_priv, return ret; } -static int drm_bo_lock_test(struct drm_device * dev, struct drm_file *file_priv) -{ - LOCK_TEST_WITH_RETURN(dev, file_priv); - return 0; -} - -int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_bo_op_arg curarg; - struct drm_bo_op_arg *arg = data; - struct drm_bo_op_req *req = &arg->d.req; - struct drm_bo_info_rep rep; - unsigned long next = 0; - void __user *curuserarg = NULL; - int ret; - - if (!dev->bm.initialized) { - DRM_ERROR("Buffer object manager is not initialized.\n"); - return -EINVAL; - } - - do { - if (next != 0) { - curuserarg = (void __user *)next; - if (copy_from_user(&curarg, curuserarg, - sizeof(curarg)) != 0) - return -EFAULT; - arg = &curarg; - } - - if (arg->handled) { - next = arg->next; - continue; - } - req = &arg->d.req; - ret = 0; - switch (req->op) { - case drm_bo_validate: - ret = drm_bo_lock_test(dev, file_priv); - if (ret) - break; - ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.fence_class, - req->bo_req.flags, - req->bo_req.mask, - req->bo_req.hint, - &rep, NULL); - break; - case drm_bo_fence: - ret = -EINVAL; - DRM_ERROR("Function is not implemented yet.\n"); - break; - case drm_bo_ref_fence: - ret = -EINVAL; - DRM_ERROR("Function is not implemented yet.\n"); - break; - default: - ret = -EINVAL; - } - next = arg->next; - - /* - * A signal interrupted us. Make sure the ioctl is restartable. - */ - - if (ret == -EAGAIN) - return -EAGAIN; - - arg->handled = 1; - arg->d.rep.ret = ret; - arg->d.rep.bo_info = rep; - if (arg != data) { - if (copy_to_user(curuserarg, &curarg, - sizeof(curarg)) != 0) - return -EFAULT; - } - } while (next != 0); - return 0; -} - int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_bo_create_arg *arg = data; @@ -1821,11 +1734,6 @@ int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *fil DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; } -#if 0 - ret = drm_bo_lock_test(dev, file_priv); - if (ret) - goto out; -#endif ret = drm_buffer_object_create(file_priv->head->dev, req->size, drm_bo_type_dc, req->mask, @@ -1849,6 +1757,30 @@ out: return ret; } +int drm_bo_setstatus_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_bo_map_wait_idle_arg *arg = data; + struct drm_bo_info_req *req = &arg->d.req; + struct drm_bo_info_rep *rep = &arg->d.rep; + int ret; + if (!dev->bm.initialized) { + DRM_ERROR("Buffer object manager is not initialized.\n"); + return -EINVAL; + } + + ret = drm_bo_handle_validate(file_priv, req->handle, req->fence_class, + req->flags, + req->mask, + req->hint | DRM_BO_HINT_DONT_FENCE, + rep, NULL); + + if (ret) + return ret; + + return 0; +} + int drm_bo_map_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_bo_map_wait_idle_arg *arg = data; diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 80e56938..9c867f1b 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -142,7 +142,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_BO_UNMAP, drm_bo_unmap_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_REFERENCE, drm_bo_reference_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_UNREFERENCE, drm_bo_unreference_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_BO_OP, drm_bo_op_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), }; diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 91378b8a..4d1ec993 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -470,9 +470,7 @@ extern int drm_bo_reference_ioctl(struct drm_device *dev, void *data, struct drm extern int drm_bo_unreference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int drm_bo_op_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); - - +extern int drm_bo_setstatus_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -- cgit v1.2.3 From bb29ba7fa77659be284c365ebfb2f740491e8506 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 17 Oct 2007 10:57:12 +0200 Subject: Only allow creator to change shared buffer mask. --- linux-core/drm_bo.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index bdeefec2..d40be07f 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1540,8 +1540,16 @@ int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle, if (!bo) { return -EINVAL; } - + /* + * Only allow creator to change shared buffer mask. + */ + + if (bo->base.owner != file_priv) { + flags = 0x0; + mask = 0x0; + } + ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, no_wait, rep); -- cgit v1.2.3 From cf2d1bba5513ae38d8efbaf50251fc136ed1d414 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 19 Oct 2007 16:24:36 +0200 Subject: Remove the clean_unfenced function. Change the restriction that non-creators can't change the buffer flags to non-creators can't change EVICT and NO_MOVE flags. --- linux-core/drm_bo.c | 65 ++++------------------------------------------------- 1 file changed, 4 insertions(+), 61 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index d40be07f..89c014e3 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1545,10 +1545,9 @@ int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle, * Only allow creator to change shared buffer mask. */ - if (bo->base.owner != file_priv) { - flags = 0x0; - mask = 0x0; - } + if (bo->base.owner != file_priv) + mask &= ~(DRM_BO_FLAG_NO_EVICT | DRM_BO_FLAG_NO_MOVE); + ret = drm_bo_do_validate(bo, flags, mask, hint, fence_class, no_wait, rep); @@ -1899,60 +1898,6 @@ int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file * return 0; } -/** - *Clean the unfenced list and put on regular LRU. - *This is part of the memory manager cleanup and should only be - *called with the DRI lock held. - *Call dev->struct_sem locked. - */ - -static void drm_bo_clean_unfenced(struct drm_device *dev) -{ - struct drm_buffer_manager *bm = &dev->bm; - struct list_head *head, *list; - struct drm_buffer_object *entry; - struct drm_fence_object *fence; - - head = &bm->unfenced; - - if (list_empty(head)) - return; - - DRM_ERROR("Clean unfenced\n"); - - if (drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence)) { - - /* - * Fixme: Should really wait here. - */ - } - - if (fence) - drm_fence_usage_deref_locked(&fence); - - if (list_empty(head)) - return; - - DRM_ERROR("Really clean unfenced\n"); - - list = head->next; - while(list != head) { - prefetch(list->next); - entry = list_entry(list, struct drm_buffer_object, lru); - - atomic_inc(&entry->usage); - mutex_unlock(&dev->struct_mutex); - mutex_lock(&entry->mutex); - mutex_lock(&dev->struct_mutex); - - list_del(&entry->lru); - DRM_FLAG_MASKED(entry->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); - drm_bo_add_to_lru(entry); - mutex_unlock(&entry->mutex); - list = head->next; - } -} - static int drm_bo_leave_list(struct drm_buffer_object * bo, uint32_t mem_type, int free_pinned, int allow_errors) @@ -2103,8 +2048,7 @@ int drm_bo_clean_mm(struct drm_device * dev, unsigned mem_type) ret = 0; if (mem_type > 0) { - - drm_bo_clean_unfenced(dev); + BUG_ON(!list_empty(&bm->unfenced)); drm_bo_force_list_clean(dev, &man->lru, mem_type, 1, 0, 0); drm_bo_force_list_clean(dev, &man->pinned, mem_type, 1, 0, 1); @@ -2142,7 +2086,6 @@ static int drm_bo_lock_mm(struct drm_device * dev, unsigned mem_type) return 0; } - drm_bo_clean_unfenced(dev); ret = drm_bo_force_list_clean(dev, &man->lru, mem_type, 0, 1, 0); if (ret) return ret; -- cgit v1.2.3 From 733ff568346e8fe40e9790f21f8b7efc659d5d12 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 19 Oct 2007 16:28:47 +0200 Subject: No fence_class argument on drmBOSetStatus since it's not associated with a particular command submission. --- linux-core/drm_bo.c | 13 +++++++++---- linux-core/drm_objects.h | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 89c014e3..cc4743dc 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1524,7 +1524,9 @@ EXPORT_SYMBOL(drm_bo_do_validate); 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, + uint64_t flags, uint64_t mask, + uint32_t hint, + int use_old_fence_class, struct drm_bo_info_rep * rep, struct drm_buffer_object **bo_rep) { @@ -1537,10 +1539,12 @@ int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle, bo = drm_lookup_buffer_object(file_priv, handle, 1); mutex_unlock(&dev->struct_mutex); - if (!bo) { + if (!bo) return -EINVAL; - } - + + if (use_old_fence_class) + fence_class = bo->fence_class; + /* * Only allow creator to change shared buffer mask. */ @@ -1780,6 +1784,7 @@ int drm_bo_setstatus_ioctl(struct drm_device *dev, req->flags, req->mask, req->hint | DRM_BO_HINT_DONT_FENCE, + 1, rep, NULL); if (ret) diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 4d1ec993..f153b84a 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -510,6 +510,7 @@ extern int drm_bo_init_mm(struct drm_device * dev, unsigned type, 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, 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 c0e3537e77f1765001f665f93e5349ccd0f1d092 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 19 Oct 2007 16:44:12 +0200 Subject: Some comment updates pending removal of the init mutex. --- linux-core/drm_bo.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index cc4743dc..35ac8a0a 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1072,13 +1072,6 @@ static int drm_bo_check_unfenced(struct drm_buffer_object * bo) /* * Wait until a buffer, scheduled to be fenced moves off the unfenced list. * Until then, we cannot really do anything with it except delete it. - * The unfenced list is a PITA, and the operations - * 1) validating - * 2) submitting commands - * 3) fencing - * Should really be an atomic operation. - * We now "solve" this problem by keeping - * the buffer "unfenced" after validating, but before fencing. */ static int drm_bo_wait_unfenced(struct drm_buffer_object * bo, int no_wait, @@ -2144,8 +2137,10 @@ int drm_bo_init_mm(struct drm_device * dev, EXPORT_SYMBOL(drm_bo_init_mm); /* - * This is called from lastclose, so we don't need to bother about - * any clients still running when we set the initialized flag to zero. + * This function is intended to be called on drm driver unload. + * If you decide to call it from lastclose, you must protect the call + * from a potentially racing drm_bo_driver_init in firstopen. + * (This may happen on X server restart). */ int drm_bo_driver_finish(struct drm_device * dev) @@ -2199,6 +2194,13 @@ int drm_bo_driver_finish(struct drm_device * dev) return ret; } +/* + * This function is intended to be called on drm driver load. + * If you decide to call it from firstopen, you must protect the call + * from a potentially racing drm_bo_driver_finish in lastclose. + * (This may happen on X server restart). + */ + int drm_bo_driver_init(struct drm_device * dev) { struct drm_bo_driver *driver = dev->driver->bo_driver; -- cgit v1.2.3 From 48b5eaf303b60077faed09db77785d7a544ac335 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sat, 20 Oct 2007 16:49:43 +0200 Subject: Simple replacement for hardware lock in some cases. Fix i915 since last commit. --- linux-core/Makefile.kernel | 2 +- linux-core/drm_bo.c | 65 ++++++++++++++++++------------ linux-core/drm_bo_lock2.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ linux-core/drm_objects.h | 27 ++++++++++++- linux-core/drm_stub.c | 1 - 5 files changed, 165 insertions(+), 29 deletions(-) create mode 100644 linux-core/drm_bo_lock2.c (limited to 'linux-core') diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 715454bc..86b225f3 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -13,7 +13,7 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \ drm_memory_debug.o ati_pcigart.o drm_sman.o \ drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \ - drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o + drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock2.o tdfx-objs := tdfx_drv.o r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 35ac8a0a..a2a0291d 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1768,11 +1768,16 @@ int drm_bo_setstatus_ioctl(struct drm_device *dev, struct drm_bo_info_req *req = &arg->d.req; struct drm_bo_info_rep *rep = &arg->d.rep; int ret; + if (!dev->bm.initialized) { DRM_ERROR("Buffer object manager is not initialized.\n"); return -EINVAL; } + ret = drm_bo_read_lock(&dev->bm.bm_lock); + if (ret) + return ret; + ret = drm_bo_handle_validate(file_priv, req->handle, req->fence_class, req->flags, req->mask, @@ -1780,6 +1785,7 @@ int drm_bo_setstatus_ioctl(struct drm_device *dev, 1, rep, NULL); + (void) drm_bo_read_unlock(&dev->bm.bm_lock); if (ret) return ret; @@ -1898,7 +1904,8 @@ int drm_bo_wait_idle_ioctl(struct drm_device *dev, void *data, struct drm_file * static int drm_bo_leave_list(struct drm_buffer_object * bo, uint32_t mem_type, - int free_pinned, int allow_errors) + int free_pinned, + int allow_errors) { struct drm_device *dev = bo->dev; int ret = 0; @@ -2150,7 +2157,6 @@ int drm_bo_driver_finish(struct drm_device * dev) unsigned i = DRM_BO_MEM_TYPES; struct drm_mem_type_manager *man; - mutex_lock(&dev->bm.init_mutex); mutex_lock(&dev->struct_mutex); if (!bm->initialized) @@ -2190,7 +2196,6 @@ int drm_bo_driver_finish(struct drm_device * dev) } out: mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->bm.init_mutex); return ret; } @@ -2207,7 +2212,7 @@ int drm_bo_driver_init(struct drm_device * dev) struct drm_buffer_manager *bm = &dev->bm; int ret = -EINVAL; - mutex_lock(&dev->bm.init_mutex); + drm_bo_init_lock(&bm->bm_lock); mutex_lock(&dev->struct_mutex); if (!driver) goto out_unlock; @@ -2233,7 +2238,6 @@ int drm_bo_driver_init(struct drm_device * dev) INIT_LIST_HEAD(&bm->ddestroy); out_unlock: mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->bm.init_mutex); return ret; } @@ -2252,6 +2256,10 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ } ret = -EINVAL; + ret = drm_bo_write_lock(&bm->bm_lock, file_priv); + if (ret) + return ret; + if (arg->magic != DRM_BO_INIT_MAGIC) { DRM_ERROR("You are using an old libdrm that is not compatible with\n" "\tthe kernel DRM module. Please upgrade your libdrm.\n"); @@ -2271,7 +2279,6 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ return -EINVAL; } - mutex_lock(&dev->bm.init_mutex); mutex_lock(&dev->struct_mutex); if (!bm->initialized) { DRM_ERROR("DRM memory manager was not initialized.\n"); @@ -2286,7 +2293,8 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ out: mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->bm.init_mutex); + (void) drm_bo_write_unlock(&bm->bm_lock, file_priv); + if (ret) return ret; @@ -2305,8 +2313,10 @@ int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *f return -EINVAL; } - LOCK_TEST_WITH_RETURN(dev, file_priv); - mutex_lock(&dev->bm.init_mutex); + ret = drm_bo_write_lock(&bm->bm_lock, file_priv); + if (ret) + return ret; + mutex_lock(&dev->struct_mutex); ret = -EINVAL; if (!bm->initialized) { @@ -2324,7 +2334,8 @@ int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *f } out: mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->bm.init_mutex); + (void) drm_bo_write_unlock(&bm->bm_lock, file_priv); + if (ret) return ret; @@ -2342,20 +2353,28 @@ int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ return -EINVAL; } - LOCK_TEST_WITH_RETURN(dev, file_priv); - mutex_lock(&dev->bm.init_mutex); + if (arg->lock_unlock_bm) { + ret = drm_bo_write_lock(&dev->bm.bm_lock, file_priv); + if (ret) + return ret; + } + mutex_lock(&dev->struct_mutex); ret = drm_bo_lock_mm(dev, arg->mem_type); mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->bm.init_mutex); - if (ret) + if (ret) { + (void) drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); return ret; + } return 0; } -int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_mm_unlock_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file_priv) { + struct drm_mm_type_arg *arg = data; struct drm_bo_driver *driver = dev->driver->bo_driver; int ret; @@ -2364,16 +2383,12 @@ int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *fil return -EINVAL; } - LOCK_TEST_WITH_RETURN(dev, file_priv); - mutex_lock(&dev->bm.init_mutex); - mutex_lock(&dev->struct_mutex); - ret = 0; - - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->bm.init_mutex); - if (ret) - return ret; - + if (arg->lock_unlock_bm) { + ret = drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); + if (ret) + return ret; + } + return 0; } diff --git a/linux-core/drm_bo_lock2.c b/linux-core/drm_bo_lock2.c new file mode 100644 index 00000000..73e58bc0 --- /dev/null +++ b/linux-core/drm_bo_lock2.c @@ -0,0 +1,99 @@ +#include "drmP.h" + +void drm_bo_init_lock(struct drm_bo_lock *lock) +{ + DRM_INIT_WAITQUEUE(&lock->queue); + atomic_set(&lock->write_lock_pending, 0); + atomic_set(&lock->readers, 0); + +} + +void drm_bo_read_unlock(struct drm_bo_lock *lock) +{ + if (unlikely(atomic_add_negative(-1, &lock->readers) == 0)) + BUG(); + if (atomic_read(&lock->readers) == 0) + wake_up_interruptible(&lock->queue); +} + +int drm_bo_read_lock(struct drm_bo_lock *lock) +{ + while( unlikely(atomic_read(&lock->write_lock_pending) != 0)) { + int ret; + ret = wait_event_interruptible + (lock->queue, + atomic_read(&lock->write_lock_pending) == 0); + if (ret) + return -EAGAIN; + } + + while( unlikely (!atomic_add_unless(&lock->readers, 1, -1))) { + int ret; + ret = wait_event_interruptible + (lock->queue, + atomic_add_unless(&lock->readers, 1, -1)); + if (ret) + return -EAGAIN; + } + return 0; +} + +static int __drm_bo_write_unlock(struct drm_bo_lock *lock) +{ + if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1)) + return -EINVAL; + if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 1, 0) != 1)) + return -EINVAL; + wake_up_interruptible(&lock->queue); + return 0; +} + +static void drm_bo_write_lock_remove(struct drm_file *file_priv, + struct drm_user_object *item) +{ + struct drm_bo_lock *lock = + container_of(item, struct drm_bo_lock, base); + int ret; + + ret = __drm_bo_write_unlock(lock); + BUG_ON(ret); +} + +int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv) +{ + int ret = 0; + struct drm_device *dev; + + if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 0, 1) != 0)) + return -EINVAL; + + while(unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) { + ret = wait_event_interruptible + (lock->queue, + atomic_cmpxchg(&lock->readers, 0, -1) == 0); + + if (ret) { + atomic_set(&lock->write_lock_pending, 0); + wake_up_interruptible(&lock->queue); + return -EAGAIN; + } + } + + dev = file_priv->head->dev; + mutex_lock(&dev->struct_mutex); + ret = drm_add_user_object(file_priv, &lock->base, 0); + lock->base.remove = &drm_bo_write_lock_remove; + lock->base.type = drm_lock_type; + if (ret) + (void) __drm_bo_write_unlock(lock); + mutex_unlock(&dev->struct_mutex); + + return ret; +} + + +int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv) +{ + return drm_user_object_unref(file_priv, lock->base.hash.key, + drm_lock_type); +} diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index f153b84a..0b937dc0 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -43,6 +43,7 @@ struct drm_bo_mem_reg; enum drm_object_type { drm_fence_type, drm_buffer_type, + drm_lock_type, /* * Add other user space object types here. */ @@ -414,6 +415,13 @@ struct drm_mem_type_manager { void *io_addr; }; +struct drm_bo_lock { + struct drm_user_object base; + wait_queue_head_t queue; + atomic_t write_lock_pending; + atomic_t readers; +}; + #define _DRM_FLAG_MEMTYPE_FIXED 0x00000001 /* Fixed (on-card) PCI memory */ #define _DRM_FLAG_MEMTYPE_MAPPABLE 0x00000002 /* Memory mappable */ #define _DRM_FLAG_MEMTYPE_CACHED 0x00000004 /* Cached binding */ @@ -423,8 +431,8 @@ struct drm_mem_type_manager { #define _DRM_FLAG_MEMTYPE_CSELECT 0x00000020 /* Select caching */ struct drm_buffer_manager { - struct mutex init_mutex; - struct mutex evict_mutex; + struct drm_bo_lock bm_lock; + struct mutex evict_mutex; int nice_mode; int initialized; struct drm_file *last_to_validate; @@ -603,6 +611,21 @@ extern void drm_regs_init(struct drm_reg_manager *manager, const void *), void (*reg_destroy)(struct drm_reg *)); +/* + * drm_bo_lock.c + * Simple replacement for the hardware lock on buffer manager init and clean. + */ + + +extern void drm_bo_init_lock(struct drm_bo_lock *lock); +extern void drm_bo_read_unlock(struct drm_bo_lock *lock); +extern int drm_bo_read_lock(struct drm_bo_lock *lock); +extern int drm_bo_write_lock(struct drm_bo_lock *lock, + struct drm_file *file_priv); + +extern int drm_bo_write_unlock(struct drm_bo_lock *lock, + struct drm_file *file_priv); + #ifdef CONFIG_DEBUG_MUTEXES #define DRM_ASSERT_LOCKED(_mutex) \ BUG_ON(!mutex_is_locked(_mutex) || \ diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c index 07ea91e0..9e140ac2 100644 --- a/linux-core/drm_stub.c +++ b/linux-core/drm_stub.c @@ -72,7 +72,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); - mutex_init(&dev->bm.init_mutex); mutex_init(&dev->bm.evict_mutex); idr_init(&dev->drw_idr); -- cgit v1.2.3 From 3b19b50cb5cd31e60eb03e99dd1109b6d0f5b8a3 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 21 Oct 2007 12:20:56 +0200 Subject: Remove the need for the hardware lock in the buffer manager. Add interface entry cleaning a memory type without touching NO_EVICT buffers. --- linux-core/Makefile.kernel | 2 +- linux-core/drm_bo.c | 11 ++- linux-core/drm_bo_lock.c | 178 +++++++++++++++++++++++++++++++++++++++++++++ linux-core/drm_compat.c | 3 + linux-core/drm_vm.c | 11 ++- 5 files changed, 199 insertions(+), 6 deletions(-) create mode 100644 linux-core/drm_bo_lock.c (limited to 'linux-core') diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel index 86b225f3..79136431 100644 --- a/linux-core/Makefile.kernel +++ b/linux-core/Makefile.kernel @@ -13,7 +13,7 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \ drm_memory_debug.o ati_pcigart.o drm_sman.o \ drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \ - drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock2.o + drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o tdfx-objs := tdfx_drv.o r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index a2a0291d..e6eb6320 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -2255,11 +2255,11 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ return -EINVAL; } - ret = -EINVAL; ret = drm_bo_write_lock(&bm->bm_lock, file_priv); if (ret) return ret; + ret = -EINVAL; if (arg->magic != DRM_BO_INIT_MAGIC) { DRM_ERROR("You are using an old libdrm that is not compatible with\n" "\tthe kernel DRM module. Please upgrade your libdrm.\n"); @@ -2353,7 +2353,12 @@ int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ return -EINVAL; } - if (arg->lock_unlock_bm) { + if (arg->lock_flags & DRM_BO_LOCK_IGNORE_NO_EVICT) { + DRM_ERROR("Lock flag DRM_BO_LOCK_IGNORE_NO_EVICT not supported yet.\n"); + return -EINVAL; + } + + if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) { ret = drm_bo_write_lock(&dev->bm.bm_lock, file_priv); if (ret) return ret; @@ -2383,7 +2388,7 @@ int drm_mm_unlock_ioctl(struct drm_device *dev, return -EINVAL; } - if (arg->lock_unlock_bm) { + if (arg->lock_flags & DRM_BO_LOCK_UNLOCK_BM) { ret = drm_bo_write_unlock(&dev->bm.bm_lock, file_priv); if (ret) return ret; diff --git a/linux-core/drm_bo_lock.c b/linux-core/drm_bo_lock.c new file mode 100644 index 00000000..e5a86826 --- /dev/null +++ b/linux-core/drm_bo_lock.c @@ -0,0 +1,178 @@ +/************************************************************************** + * + * Copyright (c) 2007 Tungsten Graphics, Inc., Cedar Park, TX., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Thomas Hellström + */ + +/* + * This file implements a simple replacement for the buffer manager use + * of the heavyweight hardware lock. + * The lock is a read-write lock. Taking it in read mode is fast, and + * intended for in-kernel use only. + * Taking it in write mode is slow. + * + * The write mode is used only when there is a need to block all + * user-space processes from allocating a + * new memory area. + * Typical use in write mode is X server VT switching, and it's allowed + * to leave kernel space with the write lock held. If a user-space process + * dies while having the write-lock, it will be released during the file + * descriptor release. + * + * The read lock is typically placed at the start of an IOCTL- or + * user-space callable function that may end up allocating a memory area. + * This includes setstatus, super-ioctls and no_pfn; the latter may move + * unmappable regions to mappable. It's a bug to leave kernel space with the + * read lock held. + * + * Both read- and write lock taking is interruptible for low signal-delivery + * latency. The locking functions will return -EAGAIN if interrupted by a + * signal. + * + * Locking order: The lock should be taken BEFORE any kernel mutexes + * or spinlocks. + */ + +#include "drmP.h" + +void drm_bo_init_lock(struct drm_bo_lock *lock) +{ + DRM_INIT_WAITQUEUE(&lock->queue); + atomic_set(&lock->write_lock_pending, 0); + atomic_set(&lock->readers, 0); +} + +void drm_bo_read_unlock(struct drm_bo_lock *lock) +{ + if (unlikely(atomic_add_negative(-1, &lock->readers))) + BUG(); + if (atomic_read(&lock->readers) == 0) + wake_up_interruptible(&lock->queue); +} + +EXPORT_SYMBOL(drm_bo_read_unlock); + +int drm_bo_read_lock(struct drm_bo_lock *lock) +{ + while (unlikely(atomic_read(&lock->write_lock_pending) != 0)) { + int ret; + ret = wait_event_interruptible + (lock->queue, atomic_read(&lock->write_lock_pending) == 0); + if (ret) + return -EAGAIN; + } + + while (unlikely(!atomic_add_unless(&lock->readers, 1, -1))) { + int ret; + ret = wait_event_interruptible + (lock->queue, atomic_add_unless(&lock->readers, 1, -1)); + if (ret) + return -EAGAIN; + } + return 0; +} + +EXPORT_SYMBOL(drm_bo_read_lock); + +static int __drm_bo_write_unlock(struct drm_bo_lock *lock) +{ + if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1)) + return -EINVAL; + if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 1, 0) != 1)) + return -EINVAL; + wake_up_interruptible(&lock->queue); + return 0; +} + +static void drm_bo_write_lock_remove(struct drm_file *file_priv, + struct drm_user_object *item) +{ + struct drm_bo_lock *lock = container_of(item, struct drm_bo_lock, base); + int ret; + + ret = __drm_bo_write_unlock(lock); + BUG_ON(ret); +} + +int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv) +{ + int ret = 0; + struct drm_device *dev; + + if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 0, 1) != 0)) { + return -EINVAL; + } + + while (unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) { + ret = wait_event_interruptible + (lock->queue, atomic_cmpxchg(&lock->readers, 0, -1) == 0); + + if (ret) { + atomic_set(&lock->write_lock_pending, 0); + wake_up_interruptible(&lock->queue); + return -EAGAIN; + } + } + + /* + * Add a dummy user-object, the destructor of which will + * make sure the lock is released if the client dies + * while holding it. + */ + + dev = file_priv->head->dev; + mutex_lock(&dev->struct_mutex); + ret = drm_add_user_object(file_priv, &lock->base, 0); + lock->base.remove = &drm_bo_write_lock_remove; + lock->base.type = drm_lock_type; + if (ret) { + (void)__drm_bo_write_unlock(lock); + } + mutex_unlock(&dev->struct_mutex); + + return ret; +} + +int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv) +{ + struct drm_device *dev = file_priv->head->dev; + struct drm_ref_object *ro; + + mutex_lock(&dev->struct_mutex); + + if (lock->base.owner != file_priv) { + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + ro = drm_lookup_ref_object(file_priv, &lock->base, _DRM_REF_USE); + BUG_ON(!ro); + drm_remove_ref_object(file_priv, ro); + lock->base.owner = NULL; + + mutex_unlock(&dev->struct_mutex); + return 0; +} diff --git a/linux-core/drm_compat.c b/linux-core/drm_compat.c index e51aedb7..ae44e500 100644 --- a/linux-core/drm_compat.c +++ b/linux-core/drm_compat.c @@ -212,6 +212,8 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma, unsigned long bus_offset; unsigned long bus_size; + dev = bo->dev; + while(drm_bo_read_lock(&dev->bm.bm_lock)); mutex_lock(&bo->mutex); @@ -289,6 +291,7 @@ static struct page *drm_bo_vm_fault(struct vm_area_struct *vma, data->type = VM_FAULT_OOM; out_unlock: mutex_unlock(&bo->mutex); + drm_bo_read_unlock(&dev->bm.bm_lock); return NULL; } diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c index c4e790ef..d2554f31 100644 --- a/linux-core/drm_vm.c +++ b/linux-core/drm_vm.c @@ -728,10 +728,17 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, if (address > vma->vm_end) return NOPFN_SIGBUS; - err = mutex_lock_interruptible(&bo->mutex); + dev = bo->dev; + err = drm_bo_read_lock(&dev->bm.bm_lock); if (err) return NOPFN_REFAULT; + err = mutex_lock_interruptible(&bo->mutex); + if (err) { + drm_bo_read_unlock(&dev->bm.bm_lock); + return NOPFN_REFAULT; + } + err = drm_bo_wait(bo, 0, 0, 0); if (err) { ret = (err != -EAGAIN) ? NOPFN_SIGBUS : NOPFN_REFAULT; @@ -754,7 +761,6 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, } } - dev = bo->dev; err = drm_bo_pci_offset(dev, &bo->mem, &bus_base, &bus_offset, &bus_size); @@ -792,6 +798,7 @@ static unsigned long drm_bo_vm_nopfn(struct vm_area_struct *vma, } out_unlock: mutex_unlock(&bo->mutex); + drm_bo_read_unlock(&dev->bm.bm_lock); return ret; } #endif -- cgit v1.2.3 From 4ebe7471cbfdd6afa33485ea9ec55812da38445f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 21 Oct 2007 12:31:00 +0200 Subject: Disable i915 accelerated blit copy moves for now until we can guarantee that it doesn't clash with the X server. --- linux-core/i915_buffer.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'linux-core') diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index f3ba7ce5..f81def8f 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -121,6 +121,8 @@ uint32_t i915_evict_mask(struct drm_buffer_object *bo) } } +#if 0 /* See comment below */ + static void i915_emit_copy_blit(struct drm_device * dev, uint32_t src_offset, uint32_t dst_offset, @@ -221,6 +223,16 @@ out_cleanup: return ret; } +#endif + +/* + * Disable i915_move_flip for now, since we can't guarantee that the hardware lock + * is held here. To re-enable we need to make sure either + * a) The X server is using DRM to submit commands to the ring, or + * b) DRM can use the HP ring for these blits. This means i915 needs to implement + * a new ring submission mechanism and fence class. + */ + int i915_move(struct drm_buffer_object * bo, int evict, int no_wait, struct drm_bo_mem_reg * new_mem) { @@ -229,10 +241,10 @@ int i915_move(struct drm_buffer_object * bo, if (old_mem->mem_type == DRM_BO_MEM_LOCAL) { return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) { - if (i915_move_flip(bo, evict, no_wait, new_mem)) + if (0 /*i915_move_flip(bo, evict, no_wait, new_mem)*/) return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } else { - if (i915_move_blit(bo, evict, no_wait, new_mem)) + if (0 /*i915_move_blit(bo, evict, no_wait, new_mem)*/) return drm_bo_move_memcpy(bo, evict, no_wait, new_mem); } return 0; -- cgit v1.2.3 From 824330d0e652e0bab1851437f120c7e76feee832 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 22 Oct 2007 19:09:36 +0200 Subject: Don't clobber the unfenced list with DONT_FENCE operations. --- linux-core/drm_bo.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index e6eb6320..9598e353 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1299,10 +1299,7 @@ int drm_bo_move_buffer(struct drm_buffer_object * bo, uint32_t new_mem_flags, mutex_lock(&bm->evict_mutex); mutex_lock(&dev->struct_mutex); - list_del(&bo->lru); - list_add_tail(&bo->lru, &bm->unfenced); - DRM_FLAG_MASKED(bo->priv_flags, _DRM_BO_FLAG_UNFENCED, - _DRM_BO_FLAG_UNFENCED); + list_del_init(&bo->lru); mutex_unlock(&dev->struct_mutex); /* @@ -1322,10 +1319,6 @@ int drm_bo_move_buffer(struct drm_buffer_object * bo, uint32_t new_mem_flags, drm_mm_put_block(mem.mm_node); mem.mm_node = NULL; } - DRM_FLAG_MASKED(bo->priv_flags, 0, _DRM_BO_FLAG_UNFENCED); - DRM_WAKEUP(&bo->event_queue); - list_del(&bo->lru); - drm_bo_add_to_lru(bo); mutex_unlock(&dev->struct_mutex); } -- cgit v1.2.3 From 3d4b32e91647f61712d54a46f0a173deff46e6b4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 22 Oct 2007 19:16:39 +0200 Subject: Remove duplicate file. --- linux-core/drm_bo_lock2.c | 99 ----------------------------------------------- 1 file changed, 99 deletions(-) delete mode 100644 linux-core/drm_bo_lock2.c (limited to 'linux-core') diff --git a/linux-core/drm_bo_lock2.c b/linux-core/drm_bo_lock2.c deleted file mode 100644 index 73e58bc0..00000000 --- a/linux-core/drm_bo_lock2.c +++ /dev/null @@ -1,99 +0,0 @@ -#include "drmP.h" - -void drm_bo_init_lock(struct drm_bo_lock *lock) -{ - DRM_INIT_WAITQUEUE(&lock->queue); - atomic_set(&lock->write_lock_pending, 0); - atomic_set(&lock->readers, 0); - -} - -void drm_bo_read_unlock(struct drm_bo_lock *lock) -{ - if (unlikely(atomic_add_negative(-1, &lock->readers) == 0)) - BUG(); - if (atomic_read(&lock->readers) == 0) - wake_up_interruptible(&lock->queue); -} - -int drm_bo_read_lock(struct drm_bo_lock *lock) -{ - while( unlikely(atomic_read(&lock->write_lock_pending) != 0)) { - int ret; - ret = wait_event_interruptible - (lock->queue, - atomic_read(&lock->write_lock_pending) == 0); - if (ret) - return -EAGAIN; - } - - while( unlikely (!atomic_add_unless(&lock->readers, 1, -1))) { - int ret; - ret = wait_event_interruptible - (lock->queue, - atomic_add_unless(&lock->readers, 1, -1)); - if (ret) - return -EAGAIN; - } - return 0; -} - -static int __drm_bo_write_unlock(struct drm_bo_lock *lock) -{ - if (unlikely(atomic_cmpxchg(&lock->readers, -1, 0) != -1)) - return -EINVAL; - if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 1, 0) != 1)) - return -EINVAL; - wake_up_interruptible(&lock->queue); - return 0; -} - -static void drm_bo_write_lock_remove(struct drm_file *file_priv, - struct drm_user_object *item) -{ - struct drm_bo_lock *lock = - container_of(item, struct drm_bo_lock, base); - int ret; - - ret = __drm_bo_write_unlock(lock); - BUG_ON(ret); -} - -int drm_bo_write_lock(struct drm_bo_lock *lock, struct drm_file *file_priv) -{ - int ret = 0; - struct drm_device *dev; - - if (unlikely(atomic_cmpxchg(&lock->write_lock_pending, 0, 1) != 0)) - return -EINVAL; - - while(unlikely(atomic_cmpxchg(&lock->readers, 0, -1) != 0)) { - ret = wait_event_interruptible - (lock->queue, - atomic_cmpxchg(&lock->readers, 0, -1) == 0); - - if (ret) { - atomic_set(&lock->write_lock_pending, 0); - wake_up_interruptible(&lock->queue); - return -EAGAIN; - } - } - - dev = file_priv->head->dev; - mutex_lock(&dev->struct_mutex); - ret = drm_add_user_object(file_priv, &lock->base, 0); - lock->base.remove = &drm_bo_write_lock_remove; - lock->base.type = drm_lock_type; - if (ret) - (void) __drm_bo_write_unlock(lock); - mutex_unlock(&dev->struct_mutex); - - return ret; -} - - -int drm_bo_write_unlock(struct drm_bo_lock *lock, struct drm_file *file_priv) -{ - return drm_user_object_unref(file_priv, lock->base.hash.key, - drm_lock_type); -} -- cgit v1.2.3 From 07abc3384e24356d1302459e2e5c4699ed7b0072 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Thu, 25 Oct 2007 10:24:55 +1000 Subject: missing mutex unlock bug --- linux-core/sis_mm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core') diff --git a/linux-core/sis_mm.c b/linux-core/sis_mm.c index 7e162a8e..9222b08d 100644 --- a/linux-core/sis_mm.c +++ b/linux-core/sis_mm.c @@ -133,6 +133,7 @@ static int sis_drm_alloc(struct drm_device * dev, struct drm_file *file_priv, dev_priv->agp_initialized)) { DRM_ERROR ("Attempt to allocate from uninitialized memory manager.\n"); + mutex_unlock(&dev->struct_mutex); return -EINVAL; } -- cgit v1.2.3 From b5cad27e05ad3666be8ccdf71e10d743efa5849e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 25 Oct 2007 09:49:33 +0200 Subject: Fix buffer object flag / mask checking. --- linux-core/drm_bo.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 9598e353..039873ca 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -921,37 +921,37 @@ int drm_bo_mem_space(struct drm_buffer_object * bo, EXPORT_SYMBOL(drm_bo_mem_space); static int drm_bo_new_mask(struct drm_buffer_object * bo, - uint64_t new_mask, uint32_t hint) + uint64_t new_flags, uint64_t used_mask) { uint32_t new_props; if (bo->type == drm_bo_type_user) { - DRM_ERROR("User buffers are not supported yet\n"); + DRM_ERROR("User buffers are not supported yet.\n"); return -EINVAL; } - if ((new_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { + if ((used_mask & DRM_BO_FLAG_NO_EVICT) && !DRM_SUSER(DRM_CURPROC)) { DRM_ERROR ("DRM_BO_FLAG_NO_EVICT is only available to priviliged " - "processes\n"); + "processes.\n"); return -EPERM; } - if ((new_mask & DRM_BO_FLAG_NO_MOVE)) { + if ((new_flags & DRM_BO_FLAG_NO_MOVE)) { DRM_ERROR ("DRM_BO_FLAG_NO_MOVE is not properly implemented yet.\n"); return -EPERM; } - new_props = new_mask & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE | - DRM_BO_FLAG_READ); + new_props = new_flags & (DRM_BO_FLAG_EXE | DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_READ); if (!new_props) { DRM_ERROR("Invalid buffer object rwx properties\n"); return -EINVAL; } - bo->mem.mask = new_mask; + bo->mem.mask = new_flags; return 0; } @@ -1490,7 +1490,7 @@ int drm_bo_do_validate(struct drm_buffer_object *bo, DRM_FLAG_MASKED(flags, bo->mem.mask, ~mask); - ret = drm_bo_new_mask(bo, flags, hint); + ret = drm_bo_new_mask(bo, flags, mask); if (ret) goto out; -- cgit v1.2.3 From 11f3e5e53f8fc4de90d1c289e0ba218ddfca23dc Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 25 Oct 2007 10:12:21 +0200 Subject: Buffer manager: Implement a version check IOCTL for drivers that don't use drmMMInit from user-space. Remove the minor check from the kernel code. That's really up to the driver. Bump major. --- linux-core/drm_bo.c | 21 +++++++++++++-------- linux-core/drm_drv.c | 1 + linux-core/drm_objects.h | 1 + 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 039873ca..8d1e2f56 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -2260,17 +2260,10 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ } if (arg->major != DRM_BO_INIT_MAJOR) { DRM_ERROR("libdrm and kernel DRM buffer object interface major\n" - "\tversion don't match. Got %d, expected %d,\n", + "\tversion don't match. Got %d, expected %d.\n", arg->major, DRM_BO_INIT_MAJOR); return -EINVAL; } - if (arg->minor > DRM_BO_INIT_MINOR) { - DRM_ERROR("libdrm expects a newer DRM buffer object interface.\n" - "\tlibdrm buffer object interface version is %d.%d.\n" - "\tkernel DRM buffer object interface version is %d.%d\n", - arg->major, arg->minor, DRM_BO_INIT_MAJOR, DRM_BO_INIT_MINOR); - return -EINVAL; - } mutex_lock(&dev->struct_mutex); if (!bm->initialized) { @@ -2535,3 +2528,15 @@ static int drm_bo_setup_vm_locked(struct drm_buffer_object * bo) return 0; } + +int drm_bo_version_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_bo_version_arg *arg = (struct drm_bo_version_arg *)data; + + arg->major = DRM_BO_INIT_MAJOR; + arg->minor = DRM_BO_INIT_MINOR; + arg->patchlevel = DRM_BO_INIT_PATCH; + + return 0; +} diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 9c867f1b..330566bb 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -145,6 +145,7 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_BO_SETSTATUS, drm_bo_setstatus_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_INFO, drm_bo_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_BO_WAIT_IDLE, drm_bo_wait_idle_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_BO_VERSION, drm_bo_version_ioctl, 0), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/linux-core/drm_objects.h b/linux-core/drm_objects.h index 0b937dc0..702ece56 100644 --- a/linux-core/drm_objects.h +++ b/linux-core/drm_objects.h @@ -483,6 +483,7 @@ extern int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file extern int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_lock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_mm_unlock_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_bo_version_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int drm_bo_driver_finish(struct drm_device *dev); extern int drm_bo_driver_init(struct drm_device *dev); extern int drm_bo_pci_offset(struct drm_device *dev, -- cgit v1.2.3 From b9d9c30474238ac8ba4899a19fe4a97e9376f6c4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 25 Oct 2007 10:29:15 +0200 Subject: Tighten permissions on some buffer manager ioctls. Set bo init minor to 0. Add the version function to header. --- linux-core/drm_drv.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'linux-core') diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index 330566bb..fe2b1200 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -123,10 +123,14 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MM_TAKEDOWN, drm_mm_takedown_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MM_LOCK, drm_mm_lock_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MM_UNLOCK, drm_mm_unlock_ioctl, + DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_FENCE_CREATE, drm_fence_create_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_IOCTL_FENCE_REFERENCE, drm_fence_reference_ioctl, DRM_AUTH), -- cgit v1.2.3