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)
This commit is contained in:
parent
34660fd2df
commit
09beee378c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue