Re: Initial 915 superioctl patch.

2007-10-09 Thread Thomas Hellström
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.

2007-10-09 Thread Dave Airlie


[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.

2007-10-08 Thread Jesse Barnes
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.

2007-10-08 Thread Keith Whitwell
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.

2007-10-08 Thread Dave Airlie

 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.

2007-10-08 Thread Jesse Barnes
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.

2007-10-08 Thread Keith Whitwell
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.

2007-10-05 Thread Jesse Barnes
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.

2007-10-04 Thread Dave Airlie


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;
+