summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2008-05-06 11:18:47 -0700
committerEric Anholt <eric@anholt.net>2008-05-06 11:18:57 -0700
commit8551bfc6dba03dcd9d182b2099a0906153ecfa01 (patch)
tree98128927001e368695e23ae63fa2f6b999707287 /linux-core
parent91cba3ae17eb34d1836164f86c13a2a8e08c2a29 (diff)
GEM: Save the last ioremapped page for relocations in case we need it again.
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/i915_gem.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c
index 4dcfd2b1..e795ee77 100644
--- a/linux-core/i915_gem.c
+++ b/linux-core/i915_gem.c
@@ -233,6 +233,8 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
struct drm_i915_gem_relocation_entry __user *relocs;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
int i;
+ uint32_t last_reloc_offset = -1;
+ void *reloc_page = NULL;
/* Choose the GTT offset for our buffer and put it there. */
if (obj_priv->gtt_space == NULL) {
@@ -249,7 +251,6 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
for (i = 0; i < entry->relocation_count; i++) {
struct drm_gem_object *target_obj;
struct drm_i915_gem_object *target_obj_priv;
- void *reloc_page;
uint32_t reloc_val, reloc_offset, *reloc_entry;
int ret;
@@ -288,13 +289,20 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
* perform.
*/
reloc_offset = obj_priv->gtt_offset + reloc.offset;
- reloc_page = ioremap(dev->agp->base +
- (reloc_offset & ~(PAGE_SIZE - 1)),
- PAGE_SIZE);
- if (reloc_page == NULL)
- {
- drm_gem_object_unreference (target_obj);
- return -ENOMEM;
+ if (reloc_page == NULL ||
+ (last_reloc_offset & ~(PAGE_SIZE - 1)) !=
+ (reloc_offset & ~(PAGE_SIZE - 1))) {
+ if (reloc_page != NULL)
+ iounmap(reloc_page);
+
+ reloc_page = ioremap(dev->agp->base +
+ (reloc_offset & ~(PAGE_SIZE - 1)),
+ PAGE_SIZE);
+ last_reloc_offset = reloc_offset;
+ if (reloc_page == NULL) {
+ drm_gem_object_unreference (target_obj);
+ return -ENOMEM;
+ }
}
reloc_entry = (uint32_t *)((char *)reloc_page +
@@ -308,10 +316,12 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj,
#endif
writel (reloc_val, reloc_entry);
- iounmap(reloc_page);
drm_gem_object_unreference (target_obj);
}
+ if (reloc_page != NULL)
+ iounmap(reloc_page);
+
#if WATCH_BUF
i915_gem_dump_object (obj, 128, __FUNCTION__, ~0);
#endif