Commit 79d24273 authored by Chris Wilson's avatar Chris Wilson Committed by Keith Packard

drm/i915/overlay: Fix unpinning along init error paths

As pointed out by Dan Carpenter, it was seemingly possible to hit an error
whilst mapping the buffer for the regs (except the only likely error
returns should not happen during init) and so leak a pin count on the
bo. To handle this we would need to reacquire the struct mutex, so for
simplicity rearrange for the lock to be held for the entire function.
For extra pedagogy, test that we only call init once.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarKeith Packard <keithp@keithp.com>
Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
parent dc501fbc
...@@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev)
overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
if (!overlay) if (!overlay)
return; return;
mutex_lock(&dev->struct_mutex);
if (WARN_ON(dev_priv->overlay))
goto out_free;
overlay->dev = dev; overlay->dev = dev;
reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
...@@ -1416,8 +1421,6 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1416,8 +1421,6 @@ void intel_setup_overlay(struct drm_device *dev)
goto out_free; goto out_free;
overlay->reg_bo = reg_bo; overlay->reg_bo = reg_bo;
mutex_lock(&dev->struct_mutex);
if (OVERLAY_NEEDS_PHYSICAL(dev)) { if (OVERLAY_NEEDS_PHYSICAL(dev)) {
ret = i915_gem_attach_phys_object(dev, reg_bo, ret = i915_gem_attach_phys_object(dev, reg_bo,
I915_GEM_PHYS_OVERLAY_REGS, I915_GEM_PHYS_OVERLAY_REGS,
...@@ -1442,8 +1445,6 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1442,8 +1445,6 @@ void intel_setup_overlay(struct drm_device *dev)
} }
} }
mutex_unlock(&dev->struct_mutex);
/* init all values */ /* init all values */
overlay->color_key = 0x0101fe; overlay->color_key = 0x0101fe;
overlay->brightness = -19; overlay->brightness = -19;
...@@ -1452,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1452,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev)
regs = intel_overlay_map_regs(overlay); regs = intel_overlay_map_regs(overlay);
if (!regs) if (!regs)
goto out_free_bo; goto out_unpin_bo;
memset(regs, 0, sizeof(struct overlay_registers)); memset(regs, 0, sizeof(struct overlay_registers));
update_polyphase_filter(regs); update_polyphase_filter(regs);
...@@ -1461,15 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev) ...@@ -1461,15 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev)
intel_overlay_unmap_regs(overlay, regs); intel_overlay_unmap_regs(overlay, regs);
dev_priv->overlay = overlay; dev_priv->overlay = overlay;
mutex_unlock(&dev->struct_mutex);
DRM_INFO("initialized overlay support\n"); DRM_INFO("initialized overlay support\n");
return; return;
out_unpin_bo: out_unpin_bo:
i915_gem_object_unpin(reg_bo); if (!OVERLAY_NEEDS_PHYSICAL(dev))
i915_gem_object_unpin(reg_bo);
out_free_bo: out_free_bo:
drm_gem_object_unreference(&reg_bo->base); drm_gem_object_unreference(&reg_bo->base);
mutex_unlock(&dev->struct_mutex);
out_free: out_free:
mutex_unlock(&dev->struct_mutex);
kfree(overlay); kfree(overlay);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment