From b0fee67a305cf37cf2a71d6c3753fba825400b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 22 Feb 2008 00:12:39 -0500 Subject: i915: Remove leading underscore from struct tags. This matches the changes in mesa to use the system drm includes for the definitions of the drm ioctl structs. --- shared-core/i915_drm.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 3dcb6278..b93df670 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -69,7 +69,7 @@ typedef struct _drm_i915_init { unsigned int sarea_handle; } drm_i915_init_t; -typedef struct _drm_i915_sarea { +typedef struct drm_i915_sarea { struct drm_tex_region texList[I915_NR_TEX_REGIONS + 1]; int last_upload; /* last time texture was uploaded */ int last_enqueue; /* last time a buffer was enqueued */ @@ -211,7 +211,7 @@ typedef struct drm_i915_flip { /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. */ -typedef struct _drm_i915_batchbuffer { +typedef struct drm_i915_batchbuffer { int start; /* agp offset */ int used; /* nr bytes in use */ int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ @@ -375,7 +375,7 @@ struct drm_i915_op_arg { struct drm_i915_execbuffer { uint64_t ops_list; uint32_t num_buffers; - struct _drm_i915_batchbuffer batch; + struct drm_i915_batchbuffer batch; drm_context_t context; /* for lockless use in the future */ struct drm_fence_arg fence_arg; }; -- cgit v1.2.3 From b7086e6ae5632ad3c0f7c54ffd641519959d84a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 22 Feb 2008 11:22:52 -0500 Subject: Fix one last occurance of struct _drm_i915_batchbuffer. Thanks to Todd Merrill for pointing it out. --- shared-core/i915_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3874ed58..7da8d55c 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1121,7 +1121,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; struct drm_i915_execbuffer *exec_buf = data; - struct _drm_i915_batchbuffer *batch = &exec_buf->batch; + struct drm_i915_batchbuffer *batch = &exec_buf->batch; struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; int num_buffers; int ret; -- cgit v1.2.3 From 7e5f9c8bd33c503fef9bea20b955a5a48e255621 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 22 Feb 2008 13:35:13 +0100 Subject: nouveau: A single define of dma skips is more than enough. --- shared-core/nouveau_dma.c | 29 +++++++++++------------------ shared-core/nouveau_drm.h | 6 ++++++ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/shared-core/nouveau_dma.c b/shared-core/nouveau_dma.c index dff786d4..e519dc4e 100644 --- a/shared-core/nouveau_dma.c +++ b/shared-core/nouveau_dma.c @@ -29,11 +29,6 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" -/* FIXME : should go into a nouveau_drm.h define ? - * (it's shared between DRI & DDX & DRM) - */ -#define SKIPS 8 - int nouveau_dma_channel_init(struct drm_device *dev) { @@ -76,10 +71,10 @@ nouveau_dma_channel_init(struct drm_device *dev) dchan->cur = dchan->put; dchan->free = dchan->max - dchan->cur; - /* Insert NOPS for SKIPS */ - dchan->free -= SKIPS; - dchan->push_free = SKIPS; - for (i=0; ifree -= NOUVEAU_DMA_SKIPS; + dchan->push_free = NOUVEAU_DMA_SKIPS; + for (i=0; i < NOUVEAU_DMA_SKIPS; i++) OUT_RING(0); /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier */ @@ -131,8 +126,6 @@ nouveau_dma_channel_takedown(struct drm_device *dev) } } -#define RING_SKIPS 8 - #define READ_GET() ((NV_READ(dchan->chan->get) - \ dchan->chan->pushbuf_base) >> 2) #define WRITE_PUT(val) do { \ @@ -156,19 +149,19 @@ nouveau_dma_wait(struct drm_device *dev, int size) if (dchan->free < size) { dchan->push_free = 1; OUT_RING(0x20000000|dchan->chan->pushbuf_base); - if (get <= RING_SKIPS) { + if (get <= NOUVEAU_DMA_SKIPS) { /*corner case - will be idle*/ - if (dchan->put <= RING_SKIPS) - WRITE_PUT(RING_SKIPS + 1); + if (dchan->put <= NOUVEAU_DMA_SKIPS) + WRITE_PUT(NOUVEAU_DMA_SKIPS + 1); do { get = READ_GET(); - } while (get <= RING_SKIPS); + } while (get <= NOUVEAU_DMA_SKIPS); } - WRITE_PUT(RING_SKIPS); - dchan->cur = dchan->put = RING_SKIPS; - dchan->free = get - (RING_SKIPS + 1); + WRITE_PUT(NOUVEAU_DMA_SKIPS); + dchan->cur = dchan->put = NOUVEAU_DMA_SKIPS; + dchan->free = get - (NOUVEAU_DMA_SKIPS + 1); } } else { dchan->free = get - dchan->cur - 1; diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 3bf40089..5f07fcbc 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -70,6 +70,12 @@ struct drm_nouveau_gpuobj_free { uint32_t handle; }; +/* This is needed to avoid a race condition. + * Otherwise you may be writing in the fetch area. + * Is this large enough, as it's only 32 bytes, and the maximum fetch size is 256 bytes? + */ +#define NOUVEAU_DMA_SKIPS 8 + #define NOUVEAU_MEM_FB 0x00000001 #define NOUVEAU_MEM_AGP 0x00000002 #define NOUVEAU_MEM_FB_ACCEPTABLE 0x00000004 -- cgit v1.2.3 From 0d32015974f019e8d2ea1eb48acd9e082389d9c5 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 22 Feb 2008 13:41:05 +0100 Subject: nouveau: Remove some random (french) comment. --- shared-core/nouveau_fifo.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 0daf9ac4..056cb6d0 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -45,11 +45,6 @@ int nouveau_fifo_ctx_size(struct drm_device *dev) * functions doing the actual work ***********************************/ -/* voir nv_xaa.c : NVResetGraphics - * mémoire mappée par nv_driver.c : NVMapMem - * voir nv_driver.c : NVPreInit - */ - static int nouveau_fifo_instmem_configure(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; -- cgit v1.2.3 From 20d0e539160fcbdd65ecbe188ac1ce2800af1b5c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 22 Feb 2008 13:57:38 -0800 Subject: i915: put ARX back into index mode before doing restore Fixes resume from hibernate in some configurations. --- linux-core/i915_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c index cfcb62ed..e18bc8d0 100644 --- a/linux-core/i915_drv.c +++ b/linux-core/i915_drv.c @@ -247,6 +247,7 @@ static void i915_restore_vga(struct drm_device *dev) dev_priv->saveGR[0x18]); /* Attribute controller registers */ + inb(st01); /* switch back to index mode */ for (i = 0; i < 20; i++) i915_write_ar(st01, i, dev_priv->saveAR[i], 0); inb(st01); /* switch back to index mode */ -- cgit v1.2.3 From d6098db1409e8ee45052920d3acdd3b6f2cb80aa Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Sat, 23 Feb 2008 11:01:36 +0100 Subject: fix texture uploads with large 3d textures (bug 13980) Texture uploads could hit the blitter coordinate limit, adjust the texture offset when uploading the pieces. Make sure to check the end address of the upload too. --- shared-core/radeon_state.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 6f2e05b3..70651d7f 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -1662,7 +1662,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, u32 height; int i; u32 texpitch, microtile; - u32 offset; + u32 offset, byte_offset; RING_LOCALS; if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { @@ -1727,6 +1727,13 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } else microtile = 0; + /* this might fail for zero-sized uploads - are those illegal? */ + if (!radeon_check_offset(dev_priv, tex->offset + image->height * + blit_width - 1)) { + DRM_ERROR("Invalid final destination offset\n"); + return -EINVAL; + } + DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width); do { @@ -1840,6 +1847,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } #undef RADEON_COPY_MT + byte_offset = (image->y & ~2047) * blit_width; buf->file_priv = file_priv; buf->used = size; offset = dev_priv->gart_buffers_offset + buf->offset; @@ -1854,9 +1862,9 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); OUT_RING((spitch << 22) | (offset >> 10)); - OUT_RING((texpitch << 22) | (tex->offset >> 10)); + OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10))); OUT_RING(0); - OUT_RING((image->x << 16) | image->y); + OUT_RING((image->x << 16) | (image->y % 2048)); OUT_RING((image->width << 16) | height); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); -- cgit v1.2.3 From 56bb29cf37c27b283efcd1a32d3583393e5208ea Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 26 Feb 2008 00:01:09 +0100 Subject: Make the execbuffer code reasonably safe against errors. In particular -EAGAINs, which should be common during Xserver operation. Also handle the fence creation failure case. --- shared-core/i915_dma.c | 244 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 180 insertions(+), 64 deletions(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 7da8d55c..4f41a688 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -809,7 +809,10 @@ struct i915_relocatee_info { struct drm_i915_validate_buffer { struct drm_buffer_object *buffer; + struct drm_bo_info_rep rep; int presumed_offset_correct; + void __user *data; + int ret; }; static void i915_dereference_buffers_locked(struct drm_i915_validate_buffer *buffers, @@ -1012,6 +1015,40 @@ out_err: 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 */ @@ -1022,13 +1059,11 @@ int i915_validate_buffer_list(struct drm_file *file_priv, { struct drm_i915_op_arg arg; struct drm_bo_op_req *req = &arg.d.req; - struct drm_bo_arg_rep rep; - unsigned long next = 0; int ret = 0; unsigned buf_count = 0; - struct drm_device *dev = file_priv->head->dev; uint32_t buf_handle; uint32_t __user *reloc_user_ptr; + struct drm_i915_validate_buffer *item = buffers; do { if (buf_count >= *num_buffers) { @@ -1036,31 +1071,26 @@ int i915_validate_buffer_list(struct drm_file *file_priv, ret = -EINVAL; goto out_err; } + item = buffers + buf_count; + item->buffer = NULL; + item->presumed_offset_correct = 0; buffers[buf_count].buffer = NULL; - buffers[buf_count].presumed_offset_correct = 0; if (copy_from_user(&arg, (void __user *)(unsigned long)data, sizeof(arg))) { ret = -EFAULT; goto out_err; } - if (arg.handled) { - data = arg.next; - mutex_lock(&dev->struct_mutex); - buffers[buf_count].buffer = drm_lookup_buffer_object(file_priv, req->arg_handle, 1); - mutex_unlock(&dev->struct_mutex); - buf_count++; - continue; - } - - rep.ret = 0; + ret = 0; if (req->op != drm_bo_validate) { DRM_ERROR ("Buffer object operation wasn't \"validate\".\n"); - rep.ret = -EINVAL; + 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; @@ -1072,48 +1102,149 @@ int i915_validate_buffer_list(struct drm_file *file_priv, DRM_MEMORYBARRIER(); } - rep.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, 0, - &rep.bo_info, - &buffers[buf_count].buffer); + 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, 0, + &item->rep, + &item->buffer); + + if (ret) { + DRM_ERROR("error on handle validate %d\n", ret); + goto out_err; + } + + buf_count++; - if (rep.ret) { - DRM_ERROR("error on handle validate %d\n", rep.ret); + 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; + + 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; + arg.d.rep.bo_info = buffers->rep; + 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->head->dev; + int ret; + struct drm_fence_object *fence; + + ret = drm_fence_buffer_objects(dev, NULL, fence_flags, + NULL, &fence); + + if (ret) { + /* - * If the user provided a presumed offset hint, check whether - * the buffer is in the same place, if so, relocations relative to - * this buffer need not be performed + * Fence creation failed. + * Fall back to synchronous operation and idle the engine. */ - if ((req->bo_req.hint & DRM_BO_HINT_PRESUMED_OFFSET) && - buffers[buf_count].buffer->offset == req->bo_req.presumed_offset) { - buffers[buf_count].presumed_offset_correct = 1; - } - next = arg.next; - arg.handled = 1; - arg.d.rep = rep; + (void) i915_quiescent(dev); - if (copy_to_user((void __user *)(unsigned long)data, &arg, sizeof(arg))) - return -EFAULT; + /* + * FIXME: Might need a sync flush here. + */ - data = next; - buf_count++; + if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { - } while (next != 0); - *num_buffers = buf_count; - return 0; -out_err: - mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(buffers, buf_count); - mutex_unlock(&dev->struct_mutex); - *num_buffers = 0; - return (ret) ? ret : rep.ret; + /* + * 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); } + static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1126,7 +1257,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data, int num_buffers; int ret; struct drm_i915_validate_buffer *buffers; - struct drm_fence_object *fence; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); @@ -1171,7 +1301,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, buffers, &num_buffers); if (ret) - goto out_free; + goto out_err0; /* make sure all previous memory operations have passed */ DRM_MEMORYBARRIER(); @@ -1190,30 +1320,16 @@ static int i915_execbuffer(struct drm_device *dev, void *data, if (sarea_priv) sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - /* fence */ - ret = drm_fence_buffer_objects(dev, NULL, fence_arg->flags, - NULL, &fence); - if (ret) - goto out_err0; + i915_fence_or_sync(file_priv, fence_arg->flags, fence_arg, NULL); - if (!(fence_arg->flags & DRM_FENCE_FLAG_NO_USER)) { - ret = drm_fence_add_user_object(file_priv, fence, fence_arg->flags & DRM_FENCE_FLAG_SHAREABLE); - if (!ret) { - fence_arg->handle = fence->base.hash.key; - fence_arg->fence_class = fence->fence_class; - fence_arg->type = fence->type; - fence_arg->signaled = fence->signaled_types; - } - } - drm_fence_usage_deref_unlocked(&fence); out_err0: /* handle errors */ + ret = i915_handle_copyback(dev, buffers, num_buffers, ret); mutex_lock(&dev->struct_mutex); i915_dereference_buffers_locked(buffers, num_buffers); mutex_unlock(&dev->struct_mutex); -out_free: drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER); mutex_unlock(&dev_priv->cmdbuf_mutex); -- cgit v1.2.3 From e87cec19687089f9f268ec0eb81b57e6fb8de6a9 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 26 Feb 2008 10:47:05 +0100 Subject: [i915] Relocation fixes. --- shared-core/i915_dma.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 4f41a688..b916441d 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -833,6 +833,10 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, 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) @@ -854,21 +858,14 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, if (!relocatee->data_page || !drm_bo_same_page(relocatee->offset, new_cmd_offset)) { drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; relocatee->offset = new_cmd_offset; - mutex_lock (&relocatee->buf->mutex); - ret = drm_bo_wait (relocatee->buf, 0, 0, FALSE); - mutex_unlock (&relocatee->buf->mutex); - if (ret) { - DRM_ERROR("Could not wait for buffer to apply relocs\n %08lx", new_cmd_offset); - return ret; - } 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); @@ -887,7 +884,11 @@ int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, reloc[0], reloc[1], buf_index, relocatee->data_page[index], val); } } - relocatee->data_page[index] = val; + + if (relocatee->is_iomem) + iowrite32(val, relocatee->data_page + index); + else + relocatee->data_page[index] = val; return 0; } @@ -955,11 +956,13 @@ int i915_process_relocs(struct drm_file *file_priv, } out: - if (reloc_buf) kfree(reloc_buf); - drm_bo_kunmap(&relocatee->kmap); - relocatee->data_page = NULL; + + if (relocatee->data_page) { + drm_bo_kunmap(&relocatee->kmap); + relocatee->data_page = NULL; + } return ret; } @@ -999,18 +1002,22 @@ static int i915_exec_reloc(struct drm_file *file_priv, drm_handle_t buf_handle, goto out_err; } + mutex_lock (&relocatee.buf->mutex); + ret = drm_bo_wait (relocatee.buf, 0, 0, FALSE); + if (ret) + goto out_err1; + 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"); - break; + goto out_err1; } } - mutex_lock(&dev->struct_mutex); - drm_bo_usage_deref_locked(&relocatee.buf); - mutex_unlock(&dev->struct_mutex); - +out_err1: + mutex_unlock (&relocatee.buf->mutex); + drm_bo_usage_deref_unlocked(&relocatee.buf); out_err: return ret; } @@ -1190,12 +1197,9 @@ void i915_fence_or_sync(struct drm_file *file_priv, * Fall back to synchronous operation and idle the engine. */ + (void) i915_emit_mi_flush(dev, MI_READ_FLUSH); (void) i915_quiescent(dev); - /* - * FIXME: Might need a sync flush here. - */ - if (!(fence_flags & DRM_FENCE_FLAG_NO_USER)) { /* -- cgit v1.2.3