summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-05-18 18:01:05 -0700
committerEric Anholt <eric@anholt.net>2009-05-19 10:09:41 -0700
commit09beee378cecd1079e7a9fa6eee8f084d680d37e (patch)
tree079c53d1e96e60e89f496bd98871145dbfb84e8f /src
parent34660fd2df5d61b77ed7041d32ac29053fc94f5a (diff)
Don't do GTT maps on objects bigger than half the available aperture size.
The basic problem is that software fallbacks will do single instructions that copy from one GTT-mapped BO into another GTT-mapped BO. If we can't get both of them bound simultanously, we fault one in, retry the instruction, fault the other in (kicking out #1), retry the instruction, fault #1 back in (kicking out #2), etc. Note that we'll still get into a nasty spot if you do a composite operation with a mask where all 3 are big-but-less-than-half-available-aperture, where you'll thrash. It at least means you'll make progress, though, since each instruction will only be operating on two BOs at at time, and the situation seems unlikely. Bug #20152 (3/3)
Diffstat (limited to 'src')
-rw-r--r--src/drmmode_display.c2
-rw-r--r--src/i830.h2
-rw-r--r--src/i830_exa.c20
-rw-r--r--src/i830_memory.c26
4 files changed, 46 insertions, 4 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 7df7b6fb..24e0e269 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -232,6 +232,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_output_dpms(output, DPMSModeOn);
}
+ i830_set_max_gtt_map_size(pScrn);
+
done:
if (!ret) {
crtc->x = saved_x;
diff --git a/src/i830.h b/src/i830.h
index 0969c485..7c260dec 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -437,6 +437,7 @@ typedef struct _I830Rec {
int accel_pixmap_offset_alignment;
int accel_max_x;
int accel_max_y;
+ int max_gtt_map_size;
I830WriteIndexedByteFunc writeControl;
I830ReadIndexedByteFunc readControl;
@@ -748,6 +749,7 @@ Bool i830_bind_all_memory(ScrnInfoPtr pScrn);
Bool i830_unbind_all_memory(ScrnInfoPtr pScrn);
unsigned long i830_get_fence_size(I830Ptr pI830, unsigned long size);
unsigned long i830_get_fence_pitch(I830Ptr pI830, unsigned long pitch, int format);
+void i830_set_max_gtt_map_size(ScrnInfoPtr pScrn);
Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 824f032b..3ca79334 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -506,9 +506,18 @@ i830_uxa_prepare_access (PixmapPtr pixmap, uxa_access_t access)
/* Kernel manages fences at GTT map/fault time */
if (i830->kernel_exec_fencing) {
- if (drm_intel_gem_bo_map_gtt(bo)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map failed\n",
- __FUNCTION__);
+ if (bo->size < i830->max_gtt_map_size) {
+ if (drm_intel_gem_bo_map_gtt(bo)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: bo map failed\n",
+ __FUNCTION__);
+ return FALSE;
+ }
+ } else {
+ if (dri_bo_map(bo, access == UXA_ACCESS_RW) != 0)
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: bo map failed\n",
+ __FUNCTION__);
return FALSE;
}
pixmap->devPrivate.ptr = bo->virtual;
@@ -542,7 +551,10 @@ i830_uxa_finish_access (PixmapPtr pixmap)
}
if (i830->kernel_exec_fencing)
- drm_intel_gem_bo_unmap_gtt(bo);
+ if (bo->size < i830->max_gtt_map_size)
+ drm_intel_gem_bo_unmap_gtt(bo);
+ else
+ dri_bo_unmap(bo);
else
drm_intel_bo_unpin(bo);
pixmap->devPrivate.ptr = NULL;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2a697a7d..99b9fc85 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1128,6 +1128,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn)
if (!pI830->use_drm_mode && pI830->FbBase && front_buffer->bound)
memset (pI830->FbBase + front_buffer->offset, 0, size);
+ i830_set_max_gtt_map_size(pScrn);
+
return front_buffer;
}
@@ -1588,6 +1590,7 @@ i830_bind_all_memory(ScrnInfoPtr pScrn)
}
if (!pI830->use_drm_mode)
i830_update_cursor_offsets(pScrn);
+ i830_set_max_gtt_map_size(pScrn);
return TRUE;
}
@@ -1672,3 +1675,26 @@ Bool i830_allocate_xvmc_buffer(ScrnInfoPtr pScrn, const char *name,
return TRUE;
}
#endif
+
+void
+i830_set_max_gtt_map_size(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ struct drm_i915_gem_get_aperture aperture;
+ int ret;
+
+ /* Default low value in case it gets used during server init. */
+ pI830->max_gtt_map_size = 16 * 1024 * 1024;
+
+ if (!pI830->have_gem)
+ return;
+
+ ret = ioctl(pI830->drmSubFD, DRM_IOCTL_I915_GEM_GET_APERTURE, &aperture);
+ if (ret == 0) {
+ /* Let objects up get bound up to the size where only 2 would fit in
+ * the aperture, but then leave slop to account for alignment like
+ * libdrm does.
+ */
+ pI830->max_gtt_map_size = aperture.aper_available_size * 3 / 4 / 2;
+ }
+}