diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-08-12 12:36:12 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-08 10:23:50 +0100 |
commit | 8dc5d14741dc1ee0074a14b360993a10c2c02d24 (patch) | |
tree | 9b4885aa1e74161138caf5f611e5f99d379a817e /drivers/gpu/drm/i915/intel_overlay.c | |
parent | 5cd68c9864d65e49c910c701716e4e94e09f7ce0 (diff) |
drm/i915: Preallocate requests
By allocating the request prior to writing to the ringbuffer, we can
abort the operation without leaving the GPU in an inconsistent state.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_overlay.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_overlay.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 8c660abb0e6..cd0c4bf88b9 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -218,6 +218,7 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay, } static int intel_overlay_do_wait_request(struct intel_overlay *overlay, + struct drm_i915_gem_request *request, bool interruptible, int stage) { @@ -226,7 +227,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, int ret; overlay->last_flip_req = - i915_add_request(dev, NULL, &dev_priv->render_ring); + i915_add_request(dev, NULL, request, &dev_priv->render_ring); if (overlay->last_flip_req == 0) return -ENOMEM; @@ -246,11 +247,15 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, static int intel_overlay_on(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; + struct drm_i915_gem_request *request; BUG_ON(overlay->active); - overlay->active = 1; + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + BEGIN_LP_RING(4); OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); OUT_RING(overlay->flip_addr | OFC_UPDATE); @@ -258,21 +263,26 @@ static int intel_overlay_on(struct intel_overlay *overlay) OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - return intel_overlay_do_wait_request(overlay, true, + return intel_overlay_do_wait_request(overlay, request, true, NEEDS_WAIT_FOR_FLIP); } /* overlay needs to be enabled in OCMD reg */ -static void intel_overlay_continue(struct intel_overlay *overlay, - bool load_polyphase_filter) +static int intel_overlay_continue(struct intel_overlay *overlay, + bool load_polyphase_filter) { struct drm_device *dev = overlay->dev; drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_request *request; u32 flip_addr = overlay->flip_addr; u32 tmp; BUG_ON(!overlay->active); + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + if (load_polyphase_filter) flip_addr |= OFC_UPDATE; @@ -287,17 +297,23 @@ static void intel_overlay_continue(struct intel_overlay *overlay, ADVANCE_LP_RING(); overlay->last_flip_req = - i915_add_request(dev, NULL, &dev_priv->render_ring); + i915_add_request(dev, NULL, request, &dev_priv->render_ring); + return 0; } /* overlay needs to be disabled in OCMD reg */ static int intel_overlay_off(struct intel_overlay *overlay) { - u32 flip_addr = overlay->flip_addr; struct drm_device *dev = overlay->dev; + u32 flip_addr = overlay->flip_addr; + struct drm_i915_gem_request *request; BUG_ON(!overlay->active); + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + /* According to intel docs the overlay hw may hang (when switching * off) without loading the filter coeffs. It is however unclear whether * this applies to the disabling of the overlay or to the switching off @@ -315,7 +331,8 @@ static int intel_overlay_off(struct intel_overlay *overlay) OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); ADVANCE_LP_RING(); - return intel_overlay_do_wait_request(overlay, true, SWITCH_OFF); + return intel_overlay_do_wait_request(overlay, request, true, + SWITCH_OFF); } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) @@ -397,13 +414,19 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) return 0; if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) { + struct drm_i915_gem_request *request; + /* synchronous slowpath */ + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + BEGIN_LP_RING(2); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); OUT_RING(MI_NOOP); ADVANCE_LP_RING(); - ret = intel_overlay_do_wait_request(overlay, true, + ret = intel_overlay_do_wait_request(overlay, request, true, RELEASE_OLD_VID); if (ret) return ret; @@ -755,7 +778,9 @@ int intel_overlay_do_put_image(struct intel_overlay *overlay, intel_overlay_unmap_regs(overlay, regs); - intel_overlay_continue(overlay, scale_changed); + ret = intel_overlay_continue(overlay, scale_changed); + if (ret) + goto out_unpin; overlay->old_vid_bo = overlay->vid_bo; overlay->vid_bo = to_intel_bo(new_bo); |