From 9b8d71b5eb09857b07409731d3de182751f712a2 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 31 Jul 2008 12:54:48 +1000 Subject: TTM: remove API and userspace objects. This removes all the TTM userspace API and all userspace objects. It also removes the drm_bo_lock.c code --- linux-core/i915_execbuf.c | 921 ---------------------------------------------- 1 file changed, 921 deletions(-) delete mode 100644 linux-core/i915_execbuf.c (limited to 'linux-core/i915_execbuf.c') diff --git a/linux-core/i915_execbuf.c b/linux-core/i915_execbuf.c deleted file mode 100644 index 932882dd..00000000 --- a/linux-core/i915_execbuf.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Copyright 2003-2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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 TUNGSTEN GRAPHICS 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 Hellstrom - * Dave Airlie - * Keith Packard - * ... ? - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -#if DRM_DEBUG_CODE -#define DRM_DEBUG_RELOCATION (drm_debug != 0) -#else -#define DRM_DEBUG_RELOCATION 0 -#endif - -enum i915_buf_idle { - I915_RELOC_UNCHECKED, - I915_RELOC_IDLE, - I915_RELOC_BUSY -}; - -struct i915_relocatee_info { - struct drm_buffer_object *buf; - unsigned long offset; - uint32_t *data_page; - unsigned page_offset; - struct drm_bo_kmap_obj kmap; - int is_iomem; - int dst; - int idle; - int performed_ring_relocs; -#ifdef DRM_KMAP_ATOMIC_PROT_PFN - unsigned long pfn; - pgprot_t pg_prot; -#endif -}; - -struct drm_i915_validate_buffer { - struct drm_buffer_object *buffer; - int presumed_offset_correct; - void __user *data; - int ret; - enum i915_buf_idle idle; -}; - -/* - * I'd like to use MI_STORE_DATA_IMM here, but I can't make - * it work. Seems like GART writes are broken with that - * instruction. Also I'm not sure that MI_FLUSH will - * act as a memory barrier for that instruction. It will - * for this single dword 2D blit. - */ - -static void i915_emit_ring_reloc(struct drm_device *dev, uint32_t offset, - uint32_t value) -{ - struct drm_i915_private *dev_priv = - (struct drm_i915_private *)dev->dev_private; - - RING_LOCALS; - i915_kernel_lost_context(dev); - BEGIN_LP_RING(6); - OUT_RING((0x02 << 29) | (0x40 << 22) | (0x3 << 20) | (0x3)); - OUT_RING((0x3 << 24) | (0xF0 << 16) | (0x40)); - OUT_RING((0x1 << 16) | (0x4)); - OUT_RING(offset); - OUT_RING(value); - OUT_RING(0); - ADVANCE_LP_RING(); -} - -static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer - *buffers, unsigned num_buffers) -{ - while (num_buffers--) - drm_bo_usage_deref_locked(&buffers[num_buffers].buffer); -} - -int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, - struct drm_i915_validate_buffer *buffers, - struct i915_relocatee_info *relocatee, uint32_t * reloc) -{ - unsigned index; - unsigned long new_cmd_offset; - u32 val; - int ret, i; - int buf_index = -1; - - /* - * FIXME: O(relocs * buffers) complexity. - */ - - for (i = 0; i <= num_buffers; i++) - if (buffers[i].buffer) - if (reloc[2] == buffers[i].buffer->base.hash.key) - buf_index = i; - - if (buf_index == -1) { - DRM_ERROR("Illegal relocation buffer %08X\n", reloc[2]); - return -EINVAL; - } - - /* - * Short-circuit relocations that were correctly - * guessed by the client - */ - if (buffers[buf_index].presumed_offset_correct && !DRM_DEBUG_RELOCATION) - return 0; - - new_cmd_offset = reloc[0]; - if (!relocatee->data_page || - !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { - struct drm_bo_mem_reg *mem = &relocatee->buf->mem; - - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - relocatee->offset = new_cmd_offset; - - if (unlikely(relocatee->idle == I915_RELOC_UNCHECKED)) { - ret = drm_bo_wait(relocatee->buf, 0, 1, 0, 0); - if (ret) - return ret; - relocatee->idle = I915_RELOC_IDLE; - } - - if (unlikely((mem->mem_type != DRM_BO_MEM_LOCAL) && - (mem->flags & DRM_BO_FLAG_CACHED_MAPPED))) - drm_bo_evict_cached(relocatee->buf); - - ret = drm_bo_kmap(relocatee->buf, new_cmd_offset >> PAGE_SHIFT, - 1, &relocatee->kmap); - if (ret) { - DRM_ERROR - ("Could not map command buffer to apply relocs\n %08lx", - new_cmd_offset); - return ret; - } - relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, - &relocatee->is_iomem); - relocatee->page_offset = (relocatee->offset & PAGE_MASK); - } - - val = buffers[buf_index].buffer->offset; - index = (reloc[0] - relocatee->page_offset) >> 2; - - /* add in validate */ - val = val + reloc[1]; - - if (DRM_DEBUG_RELOCATION) { - if (buffers[buf_index].presumed_offset_correct && - relocatee->data_page[index] != val) { - DRM_DEBUG - ("Relocation mismatch source %d target %d buffer %d user %08x kernel %08x\n", - reloc[0], reloc[1], buf_index, - relocatee->data_page[index], val); - } - } - - if (relocatee->is_iomem) - iowrite32(val, relocatee->data_page + index); - else - relocatee->data_page[index] = val; - return 0; -} - -int i915_process_relocs(struct drm_file *file_priv, - uint32_t buf_handle, - uint32_t __user ** reloc_user_ptr, - struct i915_relocatee_info *relocatee, - struct drm_i915_validate_buffer *buffers, - uint32_t num_buffers) -{ - int ret, reloc_stride; - uint32_t cur_offset; - uint32_t reloc_count; - uint32_t reloc_type; - uint32_t reloc_buf_size; - uint32_t *reloc_buf = NULL; - int i; - - /* do a copy from user from the user ptr */ - ret = get_user(reloc_count, *reloc_user_ptr); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } - - ret = get_user(reloc_type, (*reloc_user_ptr) + 1); - if (ret) { - DRM_ERROR("Could not map relocation buffer.\n"); - goto out; - } - - if (reloc_type != 0) { - DRM_ERROR("Unsupported relocation type requested\n"); - ret = -EINVAL; - goto out; - } - - reloc_buf_size = - (I915_RELOC_HEADER + - (reloc_count * I915_RELOC0_STRIDE)) * sizeof(uint32_t); - reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); - if (!reloc_buf) { - DRM_ERROR("Out of memory for reloc buffer\n"); - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(reloc_buf, *reloc_user_ptr, reloc_buf_size)) { - ret = -EFAULT; - goto out; - } - - /* get next relocate buffer handle */ - *reloc_user_ptr = (uint32_t *) * (unsigned long *)&reloc_buf[2]; - - reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); /* may be different for other types of relocs */ - - DRM_DEBUG("num relocs is %d, next is %p\n", reloc_count, - *reloc_user_ptr); - - for (i = 0; i < reloc_count; i++) { - cur_offset = I915_RELOC_HEADER + (i * I915_RELOC0_STRIDE); - - ret = i915_apply_reloc(file_priv, num_buffers, buffers, - relocatee, reloc_buf + cur_offset); - if (ret) - goto out; - } - - out: - if (reloc_buf) - kfree(reloc_buf); - - if (relocatee->data_page) { - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - } - - return ret; -} - -static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, - uint32_t __user * reloc_user_ptr, - struct drm_i915_validate_buffer *buffers, - uint32_t buf_count) -{ - struct drm_device *dev = file_priv->minor->dev; - struct i915_relocatee_info relocatee; - int ret = 0; - int b; - - /* - * Short circuit relocations when all previous - * buffers offsets were correctly guessed by - * the client - */ - if (!DRM_DEBUG_RELOCATION) { - for (b = 0; b < buf_count; b++) - if (!buffers[b].presumed_offset_correct) - break; - - if (b == buf_count) - return 0; - } - - memset(&relocatee, 0, sizeof(relocatee)); - relocatee.idle = I915_RELOC_UNCHECKED; - - mutex_lock(&dev->struct_mutex); - relocatee.buf = drm_lookup_buffer_object(file_priv, buf_handle, 1); - mutex_unlock(&dev->struct_mutex); - if (!relocatee.buf) { - DRM_DEBUG("relocatee buffer invalid %08x\n", buf_handle); - ret = -EINVAL; - goto out_err; - } - - mutex_lock(&relocatee.buf->mutex); - while (reloc_user_ptr) { - ret = - i915_process_relocs(file_priv, buf_handle, &reloc_user_ptr, - &relocatee, buffers, buf_count); - if (ret) { - DRM_ERROR("process relocs failed\n"); - goto out_err1; - } - } - - out_err1: - mutex_unlock(&relocatee.buf->mutex); - drm_bo_usage_deref_unlocked(&relocatee.buf); - out_err: - return ret; -} - -static void i915_clear_relocatee(struct i915_relocatee_info *relocatee) -{ - if (relocatee->data_page) { -#ifndef DRM_KMAP_ATOMIC_PROT_PFN - drm_bo_kunmap(&relocatee->kmap); -#else - kunmap_atomic(relocatee->data_page, KM_USER0); -#endif - relocatee->data_page = NULL; - } - relocatee->buf = NULL; - relocatee->dst = ~0; -} - -static int i915_update_relocatee(struct i915_relocatee_info *relocatee, - struct drm_i915_validate_buffer *buffers, - unsigned int dst, unsigned long dst_offset) -{ - int ret; - - if (unlikely(dst != relocatee->dst || NULL == relocatee->buf)) { - i915_clear_relocatee(relocatee); - relocatee->dst = dst; - relocatee->buf = buffers[dst].buffer; - relocatee->idle = buffers[dst].idle; - - /* - * Check for buffer idle. If the buffer is busy, revert to - * ring relocations. - */ - - if (relocatee->idle == I915_RELOC_UNCHECKED) { - preempt_enable(); - mutex_lock(&relocatee->buf->mutex); - - ret = drm_bo_wait(relocatee->buf, 0, 1, 1, 0); - if (ret == 0) - relocatee->idle = I915_RELOC_IDLE; - else { - relocatee->idle = I915_RELOC_BUSY; - relocatee->performed_ring_relocs = 1; - } - mutex_unlock(&relocatee->buf->mutex); - preempt_disable(); - buffers[dst].idle = relocatee->idle; - } - } - - if (relocatee->idle == I915_RELOC_BUSY) - return 0; - - if (unlikely(dst_offset > relocatee->buf->num_pages * PAGE_SIZE)) { - DRM_ERROR("Relocation destination out of bounds.\n"); - return -EINVAL; - } - if (unlikely(!drm_bo_same_page(relocatee->page_offset, dst_offset) || - NULL == relocatee->data_page)) { -#ifdef DRM_KMAP_ATOMIC_PROT_PFN - if (NULL != relocatee->data_page) { - kunmap_atomic(relocatee->data_page, KM_USER0); - relocatee->data_page = NULL; - } - ret = drm_bo_pfn_prot(relocatee->buf, dst_offset, - &relocatee->pfn, &relocatee->pg_prot); - if (ret) { - DRM_ERROR("Can't map relocation destination.\n"); - return -EINVAL; - } - relocatee->data_page = - kmap_atomic_prot_pfn(relocatee->pfn, KM_USER0, - relocatee->pg_prot); -#else - if (NULL != relocatee->data_page) { - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; - } - - ret = drm_bo_kmap(relocatee->buf, dst_offset >> PAGE_SHIFT, - 1, &relocatee->kmap); - if (ret) { - DRM_ERROR("Can't map relocation destination.\n"); - return ret; - } - - relocatee->data_page = drm_bmo_virtual(&relocatee->kmap, - &relocatee->is_iomem); -#endif - relocatee->page_offset = dst_offset & PAGE_MASK; - } - return 0; -} - -static int i915_apply_post_reloc(uint32_t reloc[], - struct drm_i915_validate_buffer *buffers, - uint32_t num_buffers, - struct i915_relocatee_info *relocatee) -{ - uint32_t reloc_buffer = reloc[2]; - uint32_t dst_buffer = reloc[3]; - uint32_t val; - uint32_t index; - int ret; - - if (likely(buffers[reloc_buffer].presumed_offset_correct)) - return 0; - if (unlikely(reloc_buffer >= num_buffers)) { - DRM_ERROR("Invalid reloc buffer index.\n"); - return -EINVAL; - } - if (unlikely(dst_buffer >= num_buffers)) { - DRM_ERROR("Invalid dest buffer index.\n"); - return -EINVAL; - } - - ret = i915_update_relocatee(relocatee, buffers, dst_buffer, reloc[0]); - if (unlikely(ret)) - return ret; - - val = buffers[reloc_buffer].buffer->offset; - index = (reloc[0] - relocatee->page_offset) >> 2; - val = val + reloc[1]; - - if (relocatee->idle == I915_RELOC_BUSY) { - i915_emit_ring_reloc(relocatee->buf->dev, - relocatee->buf->offset + reloc[0], val); - return 0; - } -#ifdef DRM_KMAP_ATOMIC_PROT_PFN - relocatee->data_page[index] = val; -#else - if (likely(relocatee->is_iomem)) - iowrite32(val, relocatee->data_page + index); - else - relocatee->data_page[index] = val; -#endif - - return 0; -} - -static int i915_post_relocs(struct drm_file *file_priv, - uint32_t __user * new_reloc_ptr, - struct drm_i915_validate_buffer *buffers, - unsigned int num_buffers) -{ - uint32_t *reloc; - uint32_t reloc_stride = I915_RELOC0_STRIDE * sizeof(uint32_t); - uint32_t header_size = I915_RELOC_HEADER * sizeof(uint32_t); - struct i915_relocatee_info relocatee; - uint32_t reloc_type; - uint32_t num_relocs; - uint32_t count; - int ret = 0; - int i; - int short_circuit = 1; - uint32_t __user *reloc_ptr; - uint64_t new_reloc_data; - uint32_t reloc_buf_size; - uint32_t *reloc_buf; - - for (i = 0; i < num_buffers; ++i) { - if (unlikely(!buffers[i].presumed_offset_correct)) { - short_circuit = 0; - break; - } - } - - if (likely(short_circuit)) - return 0; - - memset(&relocatee, 0, sizeof(relocatee)); - - while (new_reloc_ptr) { - reloc_ptr = new_reloc_ptr; - - ret = get_user(num_relocs, reloc_ptr); - if (unlikely(ret)) - goto out; - if (unlikely(!access_ok(VERIFY_READ, reloc_ptr, - header_size + - num_relocs * reloc_stride))) - return -EFAULT; - - ret = __get_user(reloc_type, reloc_ptr + 1); - if (unlikely(ret)) - goto out; - - if (unlikely(reloc_type != 1)) { - DRM_ERROR("Unsupported relocation type requested.\n"); - ret = -EINVAL; - goto out; - } - - ret = __get_user(new_reloc_data, reloc_ptr + 2); - new_reloc_ptr = (uint32_t __user *) (unsigned long) - new_reloc_data; - - reloc_ptr += I915_RELOC_HEADER; - - if (num_relocs == 0) - goto out; - - reloc_buf_size = - (num_relocs * I915_RELOC0_STRIDE) * sizeof(uint32_t); - reloc_buf = kmalloc(reloc_buf_size, GFP_KERNEL); - if (!reloc_buf) { - DRM_ERROR("Out of memory for reloc buffer\n"); - ret = -ENOMEM; - goto out; - } - - if (__copy_from_user(reloc_buf, reloc_ptr, reloc_buf_size)) { - ret = -EFAULT; - goto out; - } - reloc = reloc_buf; - preempt_disable(); - for (count = 0; count < num_relocs; ++count) { - ret = i915_apply_post_reloc(reloc, buffers, - num_buffers, &relocatee); - if (unlikely(ret)) { - preempt_enable(); - goto out; - } - reloc += I915_RELOC0_STRIDE; - } - preempt_enable(); - - if (reloc_buf) { - kfree(reloc_buf); - reloc_buf = NULL; - } - i915_clear_relocatee(&relocatee); - } - - out: - /* - * Flush ring relocs so the command parser will pick them up. - */ - - if (relocatee.performed_ring_relocs) - (void)i915_emit_mi_flush(file_priv->minor->dev, 0); - - i915_clear_relocatee(&relocatee); - if (reloc_buf) { - kfree(reloc_buf); - reloc_buf = NULL; - } - - return ret; -} - -static int i915_check_presumed(struct drm_i915_op_arg *arg, - struct drm_buffer_object *bo, - uint32_t __user * data, int *presumed_ok) -{ - struct drm_bo_op_req *req = &arg->d.req; - uint32_t hint_offset; - uint32_t hint = req->bo_req.hint; - - *presumed_ok = 0; - - if (!(hint & DRM_BO_HINT_PRESUMED_OFFSET)) - return 0; - if (bo->offset == req->bo_req.presumed_offset) { - *presumed_ok = 1; - return 0; - } - - /* - * We need to turn off the HINT_PRESUMED_OFFSET for this buffer in - * the user-space IOCTL argument list, since the buffer has moved, - * we're about to apply relocations and we might subsequently - * hit an -EAGAIN. In that case the argument list will be reused by - * user-space, but the presumed offset is no longer valid. - * - * Needless to say, this is a bit ugly. - */ - - hint_offset = (uint32_t *) & req->bo_req.hint - (uint32_t *) arg; - hint &= ~DRM_BO_HINT_PRESUMED_OFFSET; - return __put_user(hint, data + hint_offset); -} - -/* - * Validate, add fence and relocate a block of bos from a userspace list - */ -int i915_validate_buffer_list(struct drm_file *file_priv, - unsigned int fence_class, uint64_t data, - struct drm_i915_validate_buffer *buffers, - uint32_t * num_buffers, - uint32_t __user ** post_relocs) -{ - struct drm_i915_op_arg arg; - struct drm_bo_op_req *req = &arg.d.req; - int ret = 0; - unsigned buf_count = 0; - uint32_t buf_handle; - uint32_t __user *reloc_user_ptr; - struct drm_i915_validate_buffer *item = buffers; - *post_relocs = NULL; - - do { - if (buf_count >= *num_buffers) { - DRM_ERROR("Buffer count exceeded %d\n.", *num_buffers); - ret = -EINVAL; - goto out_err; - } - item = buffers + buf_count; - item->buffer = NULL; - item->presumed_offset_correct = 0; - item->idle = I915_RELOC_UNCHECKED; - - if (copy_from_user - (&arg, (void __user *)(unsigned long)data, sizeof(arg))) { - ret = -EFAULT; - goto out_err; - } - - ret = 0; - if (req->op != drm_bo_validate) { - DRM_ERROR - ("Buffer object operation wasn't \"validate\".\n"); - ret = -EINVAL; - goto out_err; - } - item->ret = 0; - item->data = (void __user *)(unsigned long)data; - - buf_handle = req->bo_req.handle; - reloc_user_ptr = (uint32_t *) (unsigned long)arg.reloc_ptr; - - /* - * Switch mode to post-validation relocations? - */ - - if (unlikely((buf_count == 0) && (*post_relocs == NULL) && - (reloc_user_ptr != NULL))) { - uint32_t reloc_type; - - ret = get_user(reloc_type, reloc_user_ptr + 1); - if (ret) - goto out_err; - - if (reloc_type == 1) - *post_relocs = reloc_user_ptr; - - } - - if ((*post_relocs == NULL) && (reloc_user_ptr != NULL)) { - ret = - i915_exec_reloc(file_priv, buf_handle, - reloc_user_ptr, buffers, buf_count); - if (ret) - goto out_err; - DRM_MEMORYBARRIER(); - } - - ret = drm_bo_handle_validate(file_priv, req->bo_req.handle, - req->bo_req.flags, - req->bo_req.mask, req->bo_req.hint, - req->bo_req.fence_class, - NULL, &item->buffer); - if (ret) { - DRM_ERROR("error on handle validate %d\n", ret); - goto out_err; - } - - buf_count++; - - ret = i915_check_presumed(&arg, item->buffer, - (uint32_t __user *) - (unsigned long)data, - &item->presumed_offset_correct); - if (ret) - goto out_err; - - data = arg.next; - } while (data != 0); - out_err: - *num_buffers = buf_count; - item->ret = (ret != -EAGAIN) ? ret : 0; - return ret; -} - -/* - * Remove all buffers from the unfenced list. - * If the execbuffer operation was aborted, for example due to a signal, - * this also make sure that buffers retain their original state and - * fence pointers. - * Copy back buffer information to user-space unless we were interrupted - * by a signal. In which case the IOCTL must be rerun. - */ - -static int i915_handle_copyback(struct drm_device *dev, - struct drm_i915_validate_buffer *buffers, - unsigned int num_buffers, int ret) -{ - int err = ret; - int i; - struct drm_i915_op_arg arg; - struct drm_buffer_object *bo; - - if (ret) - drm_putback_buffer_objects(dev); - - if (ret != -EAGAIN) { - for (i = 0; i < num_buffers; ++i) { - arg.handled = 1; - arg.d.rep.ret = buffers->ret; - bo = buffers->buffer; - mutex_lock(&bo->mutex); - drm_bo_fill_rep_arg(bo, &arg.d.rep.bo_info); - mutex_unlock(&bo->mutex); - if (__copy_to_user(buffers->data, &arg, sizeof(arg))) - err = -EFAULT; - buffers++; - } - } - - return err; -} - -/* - * Create a fence object, and if that fails, pretend that everything is - * OK and just idle the GPU. - */ - -void i915_fence_or_sync(struct drm_file *file_priv, - uint32_t fence_flags, - struct drm_fence_arg *fence_arg, - struct drm_fence_object **fence_p) -{ - struct drm_device *dev = file_priv->minor->dev; - int ret; - struct drm_fence_object *fence; - - ret = drm_fence_buffer_objects(dev, NULL, fence_flags, NULL, &fence); - - if (ret) { - - /* - * Fence creation failed. - * Fall back to synchronous operation and idle the engine. - */ - - (void)i915_emit_mi_flush(dev, MI_READ_FLUSH); - (void)i915_quiescent(dev); - - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - - /* - * Communicate to user-space that - * fence creation has failed and that - * the engine is idle. - */ - - fence_arg->handle = ~0; - fence_arg->error = ret; - } - drm_putback_buffer_objects(dev); - if (fence_p) - *fence_p = NULL; - return; - } - - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - - ret = drm_fence_add_user_object(file_priv, fence, - fence_flags & - DRM_FENCE_FLAG_SHAREABLE); - if (!ret) - drm_fence_fill_arg(fence, fence_arg); - else { - /* - * Fence user object creation failed. - * We must idle the engine here as well, as user- - * space expects a fence object to wait on. Since we - * have a fence object we wait for it to signal - * to indicate engine "sufficiently" idle. - */ - - (void)drm_fence_object_wait(fence, 0, 1, fence->type); - drm_fence_usage_deref_unlocked(&fence); - fence_arg->handle = ~0; - fence_arg->error = ret; - } - } - - if (fence_p) - *fence_p = fence; - else if (fence) - drm_fence_usage_deref_unlocked(&fence); -} - -int i915_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_i915_private *dev_priv = (struct drm_i915_private *) - dev->dev_private; - struct drm_i915_master_private *master_priv = - (struct drm_i915_master_private *) - dev->primary->master->driver_priv; - struct drm_i915_sarea *sarea_priv = (struct drm_i915_sarea *) - master_priv->sarea_priv; - struct drm_i915_execbuffer *exec_buf = data; - struct drm_i915_batchbuffer *batch = &exec_buf->batch; - struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; - int num_buffers; - int ret; - uint32_t __user *post_relocs; - - if (!dev_priv->allow_batchbuffer) { - DRM_ERROR("Batchbuffer ioctl disabled\n"); - return -EINVAL; - } - - if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, - batch->num_cliprects * - sizeof(struct - drm_clip_rect))) - return -EFAULT; - - if (exec_buf->num_buffers > dev_priv->max_validate_buffers) - return -EINVAL; - - ret = drm_bo_read_lock(&dev->bm.bm_lock, 1); - if (ret) - return ret; - - /* - * The cmdbuf_mutex makes sure the validate-submit-fence - * operation is atomic. - */ - - ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); - if (ret) { - drm_bo_read_unlock(&dev->bm.bm_lock); - return -EAGAIN; - } - - num_buffers = exec_buf->num_buffers; - - if (!dev_priv->val_bufs) { - dev_priv->val_bufs = - vmalloc(sizeof(struct drm_i915_validate_buffer) * - dev_priv->max_validate_buffers); - } - if (!dev_priv->val_bufs) { - drm_bo_read_unlock(&dev->bm.bm_lock); - mutex_unlock(&dev_priv->cmdbuf_mutex); - return -ENOMEM; - } - - /* validate buffer list + fixup relocations */ - ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, - dev_priv->val_bufs, &num_buffers, - &post_relocs); - if (ret) - goto out_err0; - - if (post_relocs) { - ret = i915_post_relocs(file_priv, post_relocs, - dev_priv->val_bufs, num_buffers); - if (ret) - goto out_err0; - } - - /* make sure all previous memory operations have passed */ - DRM_MEMORYBARRIER(); - - if (!post_relocs) { - drm_agp_chipset_flush(dev); - batch->start = - dev_priv->val_bufs[num_buffers - 1].buffer->offset; - } else { - batch->start += dev_priv->val_bufs[0].buffer->offset; - } - - DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", - batch->start, batch->used, batch->num_cliprects); - - ret = i915_dispatch_batchbuffer(dev, batch); - if (ret) - goto out_err0; - if (sarea_priv) - sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); - - out_err0: - ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret); - mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers); - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev_priv->cmdbuf_mutex); - drm_bo_read_unlock(&dev->bm.bm_lock); - return ret; -} -- cgit v1.2.3