Re: Initial 915 superioctl patch.
Dave Airlie wrote: On Monday, October 8, 2007 10:13 am Keith Whitwell wrote: Neither 42 nor 256 are very good - the number needs to be dynamic. Think about situations where an app has eg. one glyph per texture and is doing font rendering... Or any reasonably complex game might use 256 textures in a frame. So maybe the buffer count should be part of the execbuffer request object? Or does it have to be a separate settable parameter? I would think the kernel needs to limit this in some way... as otherwise we are trusting a userspace number and allocating memory according to it... So I'll make it dynamic but I'll have to add a kernel limit.. keithw: btws poulsbo uses 256 I think also.. Hmm, yes. Although that has been bumped recently it could be changed to dynamic, though, but as Dave says, we need to impose some kind of limit to avoid DOS. Poulsbo is still using a buffer list from user-space, and there's an internal kernel array that imposes this limit. What's a bit different, though, is that the number of relocs is fixed (by user space using a fixed-size shared memory buffer for the relocs). This is based on the assumption that user space will know how many relocs a code-block will issue, and if the limit is going to be hit, it can flush its command buffers. While I believe this is OK for Poulsbo (although complicating things), what about i915 zone rendering? Keith? /Thomas Dave. - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: Initial 915 superioctl patch.
[updated patch attached] Hmm, yes. Although that has been bumped recently it could be changed to dynamic, though, but as Dave says, we need to impose some kind of limit to avoid DOS. Poulsbo is still using a buffer list from user-space, and there's an internal kernel array that imposes this limit. Okay the attached patch lets it dynamic up to 4096, and in theory we could make it a module parameter or settable via /sys, and possibly add a getparam for userspace to figure out what the limit is... What's a bit different, though, is that the number of relocs is fixed (by user space using a fixed-size shared memory buffer for the relocs). What I've done for the reloc numbers is allowed for one reloc per 4-dwords in a batchbuffer in my Mesa code, and allocated that side.. granted it may not be that accurate it was just a rough heuristic.. However I have allowed for chaining reloc buffers in the interface if not in the implementation, if you look are relocation buffer header, the first word is the relocation count and type of relocation and the second word is the buffer handle for another buffer of relocations... if this word contains !zero the code will look it another buffer of relocations.. I originally meant this for having different types of relocations but I could see how userspace could abuse this to get what you mentioned.. Dave.diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 4e73577..27bca52 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -1563,7 +1563,6 @@ int drm_bo_handle_validate(struct drm_file * file_priv, uint32_t handle, *bo_rep = bo; else drm_bo_usage_deref_unlocked(bo); - return ret; } EXPORT_SYMBOL(drm_bo_handle_validate); diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 75763e7..f3ba7ce 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -42,7 +42,7 @@ int i915_fence_types(struct drm_buffer_object *bo, uint32_t * fclass, uint32_t * type) { - if (bo-mem.flags (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) + if (bo-mem.mask (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) *type = 3; else *type = 1; diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3a9ecab..eeb6085 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -147,6 +147,10 @@ static int i915_initialize(struct drm_device * dev, return -EINVAL; } +#ifdef I915_HAVE_BUFFER + dev_priv-max_validate_buffers = I915_MAX_VALIDATE_BUFFERS; +#endif + dev_priv-sarea_priv = (drm_i915_sarea_t *) ((u8 *) dev_priv-sarea-handle + init-sarea_priv_offset); @@ -725,6 +729,344 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return 0; } +struct i915_relocatee_info { + struct drm_buffer_object *buf; + unsigned long offset; + u32 *data_page; + unsigned page_offset; + struct drm_bo_kmap_obj kmap; + int is_iomem; +}; + +static void i915_dereference_buffers_locked(struct drm_buffer_object **buffers, + unsigned num_buffers) +{ + while (num_buffers--) + drm_bo_usage_deref_locked(buffers[num_buffers]); +} + +int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, +struct drm_buffer_object **buffers, +struct i915_relocatee_info *relocatee, +uint32_t *reloc) +{ + unsigned index; + unsigned long new_cmd_offset; + u32 val; + int ret; + + if (reloc[2] = num_buffers) { + DRM_ERROR(Illegal relocation buffer %08X\n, reloc[2]); + return -EINVAL; + } + + new_cmd_offset = reloc[0]; + if (!relocatee-data_page || + !drm_bo_same_page(relocatee-offset, new_cmd_offset)) { + drm_bo_kunmap(relocatee-kmap); + relocatee-offset = new_cmd_offset; + 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[reloc[2]]-offset; + index = (reloc[0] - relocatee-page_offset) 2; + + /* add in validate */ + val = val + reloc[1]; + + relocatee-data_page[index] = val; + return 0; +} + +int i915_process_relocs(struct drm_file *file_priv, + uint32_t buf_handle, + uint32_t *reloc_buf_handle, +
Re: Initial 915 superioctl patch.
On Sunday, October 7, 2007 4:26 pm Dave Airlie wrote: At a high level, I'm wondering if something like this could be made more generic... It seems like other GPUs will need similar relocation processing so maybe the DRM should grow some generic reloc processing code? Much of this stuff seems fairly generic, so maybe it wouldn't be that hard, and it would keep us from adding yet another driver specific ioctl... You'd think that, and some parts maybe later could be generalised internally in the kenrel, but the ioctl needs to remain driver specific otherwise we won't be able to optimise use-cases for specific drivers.. Thomas's original code attempted to make parts of this generic in libdrm but once I started experimenting with it I found it limited what I could do.. the i915 has different requirements to the poulsbo which are the only two example superioctls in the wild at the moment.. Ah ok, we don't want to give up on optimizing for specific devices, so if poulsbo and i915 already have different characteristics we'd better keep the ioctls driver specific. + struct drm_buffer_object *reloc_list_object; + int ret; + uint32_t cur_handle = *reloc_buf_handle; + uint32_t num_relocs; + struct drm_bo_kmap_obj reloc_kmap; + uint32_t *reloc_page; + int reloc_is_iomem; + uint32_t reloc_offset, reloc_end, reloc_page_offset, next_offset; + int reloc_stride; + uint32_t cur_offset; gcc probably takes care of this, but it's still nice to order your automatic variables from large to small just to make sure you get good alignment. Damn ia64 hackers... :) Don't forget that unaligned accesses on x86 cost a lot too, you just don't take an interrupt for them... So the first 32 bits of the reloc_page contains the reloc count and type, and the next bits contain the actual info required, right? It might be nice to cast them into reloc_info and reloc_arg structures of some kind. That way if new reloc types were added later things would be a little clearer (and this code would be a little more straightforward I think too). Would that make sense? Yeah I thought about doing that, it's what poulsbo does pretty much, then I also thought for future different relocs type you really just want stride and pointer.. Yeah, up to you. If you don't end up with a separate struct though, it would be good to add a comment describing the layout. + if (!dev_priv-allow_batchbuffer) { + DRM_ERROR(Batchbuffer ioctl disabled\n); + return -EINVAL; + } Why would userspace turn this off? Looks like current code turns the feature on at least... We can probably remove thse later when we do init in-kernel. Cool (my first reaction to anything configurable is oh no, not another config option, so I had to ask :). +#define DRM_IOCTL_I915_EXECBUFFER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_EXECBUFFER, struct drm_i915_execbuffer) I know it's not in keeping with DRM tradition, but a short blurb about how this ioctl works (i.e. data structures and how to submit them) would be nice... :) I'll have userspace example code in my mesa tree.. I can't see there being many users beyond Mesa and the DDX.. Sounds good. + struct _drm_i915_batchbuffer batch; + uint64_t ops_list; + struct drm_fence_arg fence_arg; +}; Why the _ prefixed version here? In my tree there's no _drm_i915_batchbuffer, just drm_i915_batchbuffer... I was starting to dump some typedefs... Yeah, I noticed the massive removal in the DRM tree, looks really nice. I guess there's just some driver specific stuff left... +#ifdef I915_HAVE_BUFFER +#define I915_NUM_VALIDATE_BUFFERS 256 +#endif Why 256? It was larger than 42.. I suppose I could use getparam to report this to userspace so we could change it in theory later.. I don't know if 42 is better than 256... do we have any measurements that would help us pick a good number or that would tell us we need to make it a runtime option? Or maybe just part of the argument structure that's passed in? Jesse - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: Initial 915 superioctl patch.
Neither 42 nor 256 are very good - the number needs to be dynamic. Think about situations where an app has eg. one glyph per texture and is doing font rendering... Or any reasonably complex game might use 256 textures in a frame. Sorry for topposting -- webmail. Keith - Original Message From: Jesse Barnes [EMAIL PROTECTED] To: Dave Airlie [EMAIL PROTECTED] Cc: dri-devel@lists.sourceforge.net Sent: Monday, October 8, 2007 6:04:42 PM Subject: Re: Initial 915 superioctl patch. I don't know if 42 is better than 256... do we have any measurements that would help us pick a good number or that would tell us we need to make it a runtime option? Or maybe just part of the argument structure that's passed in? Jesse - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: Initial 915 superioctl patch.
On Monday, October 8, 2007 10:13 am Keith Whitwell wrote: Neither 42 nor 256 are very good - the number needs to be dynamic. Think about situations where an app has eg. one glyph per texture and is doing font rendering... Or any reasonably complex game might use 256 textures in a frame. So maybe the buffer count should be part of the execbuffer request object? Or does it have to be a separate settable parameter? I would think the kernel needs to limit this in some way... as otherwise we are trusting a userspace number and allocating memory according to it... So I'll make it dynamic but I'll have to add a kernel limit.. keithw: btws poulsbo uses 256 I think also.. Dave. - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: Initial 915 superioctl patch.
On Monday, October 8, 2007 2:14 pm Dave Airlie wrote: On Monday, October 8, 2007 10:13 am Keith Whitwell wrote: Neither 42 nor 256 are very good - the number needs to be dynamic. Think about situations where an app has eg. one glyph per texture and is doing font rendering... Or any reasonably complex game might use 256 textures in a frame. So maybe the buffer count should be part of the execbuffer request object? Or does it have to be a separate settable parameter? I would think the kernel needs to limit this in some way... as otherwise we are trusting a userspace number and allocating memory according to it... So I'll make it dynamic but I'll have to add a kernel limit.. Yeah, definitely need a kernel limit of some kind, settable by the DRM master presumably? Jesse - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: Initial 915 superioctl patch.
Dave Airlie wrote: On Monday, October 8, 2007 10:13 am Keith Whitwell wrote: Neither 42 nor 256 are very good - the number needs to be dynamic. Think about situations where an app has eg. one glyph per texture and is doing font rendering... Or any reasonably complex game might use 256 textures in a frame. So maybe the buffer count should be part of the execbuffer request object? Or does it have to be a separate settable parameter? I would think the kernel needs to limit this in some way... as otherwise we are trusting a userspace number and allocating memory according to it... So I'll make it dynamic but I'll have to add a kernel limit.. keithw: btws poulsbo uses 256 I think also.. Yes but I suspect we'll need to increase or make it dynamic before we're done. As with most hard limits, you can work around it by flushing prematurely, but there is a cost to that, one way or another. Keith - This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now http://get.splunk.com/ -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: Initial 915 superioctl patch.
On Thursday, October 4, 2007 8:55 pm Dave Airlie wrote: Overall, looks nice. At a high level, I'm wondering if something like this could be made more generic... It seems like other GPUs will need similar relocation processing so maybe the DRM should grow some generic reloc processing code? Much of this stuff seems fairly generic, so maybe it wouldn't be that hard, and it would keep us from adding yet another driver specific ioctl... +int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, + struct drm_buffer_object **buffers, + struct i915_relocatee_info *relocatee, + uint32_t *reloc) +{ + unsigned index; + unsigned long new_cmd_offset; + u32 val; + int ret; + + if (reloc[2] = num_buffers) { + DRM_ERROR(Illegal relocation buffer %08X\n, reloc[2]); + return -EINVAL; + } + + new_cmd_offset = reloc[0]; + if (!relocatee-data_page || + !drm_bo_same_page(relocatee-offset, new_cmd_offset)) { + drm_bo_kunmap(relocatee-kmap); + relocatee-offset = new_cmd_offset; + 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 %08x, 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[reloc[2]]-offset; + index = (reloc[0] - relocatee-page_offset) 2; + + /* add in validate */ + val = val + reloc[1]; + + relocatee-data_page[index] = val; + return 0; +} + +#define RELOC_START_OFFSET 2 +#define RELOC_NUM_INTS 3 These seem unused? +int i915_process_relocs(struct drm_file *file_priv, + uint32_t buf_handle, + uint32_t *reloc_buf_handle, + struct i915_relocatee_info *relocatee, + struct drm_buffer_object **buffers, + uint32_t num_buffers) +{ + struct drm_device *dev = file_priv-head-dev; + struct drm_buffer_object *reloc_list_object; + int ret; + uint32_t cur_handle = *reloc_buf_handle; + uint32_t num_relocs; + struct drm_bo_kmap_obj reloc_kmap; + uint32_t *reloc_page; + int reloc_is_iomem; + uint32_t reloc_offset, reloc_end, reloc_page_offset, next_offset; + int reloc_stride; + uint32_t cur_offset; gcc probably takes care of this, but it's still nice to order your automatic variables from large to small just to make sure you get good alignment. + + memset(reloc_kmap, 0, sizeof(reloc_kmap)); + + reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1); + if (!reloc_list_object) + return -EINVAL; + + ret = drm_bo_kmap(reloc_list_object, 0, 1, reloc_kmap); + if (ret) { + DRM_ERROR(Could not map relocation buffer.\n); + goto out; + } + + reloc_page = drm_bmo_virtual(reloc_kmap, reloc_is_iomem); + num_relocs = reloc_page[0] 0x; + + if ((reloc_page[0] 16) 0x) { + DRM_ERROR(Unsupported relocation type requested\n); + goto out; + } + + /* get next relocate buffer handle */ + *reloc_buf_handle = reloc_page[1]; + reloc_stride = 4; /* may be different for other types of relocs */ + + DRM_DEBUG(num relocs is %d, next is %08X\n, num_relocs, reloc_page[1]); + + reloc_page_offset = 0; + reloc_offset = 4 * sizeof(uint32_t); + reloc_end = reloc_offset + (num_relocs * reloc_stride * sizeof(uint32_t)); So the first 32 bits of the reloc_page contains the reloc count and type, and the next bits contain the actual info required, right? It might be nice to cast them into reloc_info and reloc_arg structures of some kind. That way if new reloc types were added later things would be a little clearer (and this code would be a little more straightforward I think too). Would that make sense? +static int i915_execbuffer(struct drm_device *dev, void *data, +struct drm_file *file_priv) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev-dev_private; + 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_fence_arg *fence_arg = exec_buf-fence_arg; + int num_buffers; + int ret; + struct drm_fence_object *fence; Should data be __user? Oh no, I see it's already been copied in drm_ioctl()... + if (!dev_priv-allow_batchbuffer) { +
Initial 915 superioctl patch.
Okay this is my first public efforts at the i915 driver superioctl. Please review and give out about anything I missed, I'm sure the error handling needs some work. But I thought I'd get it out there.. I have a Mesa side to this in my personal mesa tree (i915-superioctl branch) but I just want to review the DRM side first. Regards, Dave. -- David Airlie, Software Engineer http://www.skynet.ie/~airlied / airlied at skynet.ie Linux kernel - DRI, VAX / pam_smb / ILUG diff --git a/linux-core/i915_buffer.c b/linux-core/i915_buffer.c index 75763e7..4ea0478 100644 --- a/linux-core/i915_buffer.c +++ b/linux-core/i915_buffer.c @@ -42,7 +42,7 @@ int i915_fence_types(struct drm_buffer_object *bo, uint32_t * fclass, uint32_t * type) { - if (bo-mem.flags (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) + if ((bo-mem.mask | bo-mem.flags) (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) *type = 3; else *type = 1; diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 3a9ecab..58f6735 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -725,6 +725,338 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return 0; } +struct i915_relocatee_info { + struct drm_buffer_object *buf; + unsigned long offset; + u32 *data_page; + unsigned page_offset; + struct drm_bo_kmap_obj kmap; + int is_iomem; +}; + +static void i915_dereference_buffers_locked(struct drm_buffer_object **buffers, + unsigned num_buffers) +{ + while (num_buffers--) + drm_bo_usage_deref_locked(buffers[num_buffers]); +} + +int i915_apply_reloc(struct drm_file *file_priv, int num_buffers, + struct drm_buffer_object **buffers, + struct i915_relocatee_info *relocatee, + uint32_t *reloc) +{ + unsigned index; + unsigned long new_cmd_offset; + u32 val; + int ret; + + if (reloc[2] = num_buffers) { + DRM_ERROR(Illegal relocation buffer %08X\n, reloc[2]); + return -EINVAL; + } + + new_cmd_offset = reloc[0]; + if (!relocatee-data_page || + !drm_bo_same_page(relocatee-offset, new_cmd_offset)) { + drm_bo_kunmap(relocatee-kmap); + relocatee-offset = new_cmd_offset; + 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 %08x, 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[reloc[2]]-offset; + index = (reloc[0] - relocatee-page_offset) 2; + + /* add in validate */ + val = val + reloc[1]; + + relocatee-data_page[index] = val; + return 0; +} + +#define RELOC_START_OFFSET 2 +#define RELOC_NUM_INTS 3 +int i915_process_relocs(struct drm_file *file_priv, + uint32_t buf_handle, + uint32_t *reloc_buf_handle, + struct i915_relocatee_info *relocatee, + struct drm_buffer_object **buffers, + uint32_t num_buffers) +{ + struct drm_device *dev = file_priv-head-dev; + struct drm_buffer_object *reloc_list_object; + int ret; + uint32_t cur_handle = *reloc_buf_handle; + uint32_t num_relocs; + struct drm_bo_kmap_obj reloc_kmap; + uint32_t *reloc_page; + int reloc_is_iomem; + uint32_t reloc_offset, reloc_end, reloc_page_offset, next_offset; + int reloc_stride; + uint32_t cur_offset; + + memset(reloc_kmap, 0, sizeof(reloc_kmap)); + + reloc_list_object = drm_lookup_buffer_object(file_priv, cur_handle, 1); + if (!reloc_list_object) + return -EINVAL; + + ret = drm_bo_kmap(reloc_list_object, 0, 1, reloc_kmap); + if (ret) { + DRM_ERROR(Could not map relocation buffer.\n); + goto out; + } + + reloc_page = drm_bmo_virtual(reloc_kmap, reloc_is_iomem); + num_relocs = reloc_page[0] 0x; + + if ((reloc_page[0] 16) 0x) { + DRM_ERROR(Unsupported relocation type requested\n); + goto out; + } + + /* get next relocate buffer handle */ + *reloc_buf_handle = reloc_page[1]; + reloc_stride = 4; /* may be different for other types of relocs */ + + DRM_DEBUG(num relocs is %d, next is %08X\n, num_relocs, reloc_page[1]); + + reloc_page_offset = 0; + reloc_offset = 4 * sizeof(uint32_t); + reloc_end = reloc_offset + (num_relocs * reloc_stride * sizeof(uint32_t)); + + do { + next_offset = drm_bo_offset_end(reloc_offset, reloc_end); + + do { + cur_offset = ((reloc_offset + reloc_page_offset) ~PAGE_MASK) / sizeof(uint32_t); + ret = i915_apply_reloc(file_priv, num_buffers, + buffers, relocatee, reloc_page[cur_offset]); + if (ret) +goto out; + + reloc_offset += reloc_stride * sizeof(uint32_t); + } while(reloc_offset next_offset); + + drm_bo_kunmap(reloc_kmap); + + reloc_offset = next_offset; + if (reloc_offset != reloc_end) { + ret = drm_bo_kmap(reloc_list_object, reloc_offset PAGE_SHIFT, 1, reloc_kmap); + if (ret){ +DRM_ERROR(Could not map relocation buffer.\n); +goto out; + } + + reloc_page = drm_bmo_virtual(reloc_kmap, reloc_is_iomem); + reloc_page_offset = reloc_offset ~PAGE_MASK; +