aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-28 06:27:47 -0400
committerKeith Packard <keithp@keithp.com>2011-06-29 22:09:13 -0400
commit79d2427338e8da362678de32a1c8af1dc8a9810a (patch)
tree5f1018e11a501c24ce9a5bc978a6df49d5adc4dc /drivers/gpu
parentdc501fbc4389f6c15a8da14684b5926e0d9553da (diff)
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: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_overlay.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 56a8e2aea19c..9e2959bc91cd 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev)
1409 overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); 1409 overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);
1410 if (!overlay) 1410 if (!overlay)
1411 return; 1411 return;
1412
1413 mutex_lock(&dev->struct_mutex);
1414 if (WARN_ON(dev_priv->overlay))
1415 goto out_free;
1416
1412 overlay->dev = dev; 1417 overlay->dev = dev;
1413 1418
1414 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); 1419 reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE);
@@ -1416,8 +1421,6 @@ void intel_setup_overlay(struct drm_device *dev)
1416 goto out_free; 1421 goto out_free;
1417 overlay->reg_bo = reg_bo; 1422 overlay->reg_bo = reg_bo;
1418 1423
1419 mutex_lock(&dev->struct_mutex);
1420
1421 if (OVERLAY_NEEDS_PHYSICAL(dev)) { 1424 if (OVERLAY_NEEDS_PHYSICAL(dev)) {
1422 ret = i915_gem_attach_phys_object(dev, reg_bo, 1425 ret = i915_gem_attach_phys_object(dev, reg_bo,
1423 I915_GEM_PHYS_OVERLAY_REGS, 1426 I915_GEM_PHYS_OVERLAY_REGS,
@@ -1442,8 +1445,6 @@ void intel_setup_overlay(struct drm_device *dev)
1442 } 1445 }
1443 } 1446 }
1444 1447
1445 mutex_unlock(&dev->struct_mutex);
1446
1447 /* init all values */ 1448 /* init all values */
1448 overlay->color_key = 0x0101fe; 1449 overlay->color_key = 0x0101fe;
1449 overlay->brightness = -19; 1450 overlay->brightness = -19;
@@ -1452,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev)
1452 1453
1453 regs = intel_overlay_map_regs(overlay); 1454 regs = intel_overlay_map_regs(overlay);
1454 if (!regs) 1455 if (!regs)
1455 goto out_free_bo; 1456 goto out_unpin_bo;
1456 1457
1457 memset(regs, 0, sizeof(struct overlay_registers)); 1458 memset(regs, 0, sizeof(struct overlay_registers));
1458 update_polyphase_filter(regs); 1459 update_polyphase_filter(regs);
@@ -1461,15 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev)
1461 intel_overlay_unmap_regs(overlay, regs); 1462 intel_overlay_unmap_regs(overlay, regs);
1462 1463
1463 dev_priv->overlay = overlay; 1464 dev_priv->overlay = overlay;
1465 mutex_unlock(&dev->struct_mutex);
1464 DRM_INFO("initialized overlay support\n"); 1466 DRM_INFO("initialized overlay support\n");
1465 return; 1467 return;
1466 1468
1467out_unpin_bo: 1469out_unpin_bo:
1468 i915_gem_object_unpin(reg_bo); 1470 if (!OVERLAY_NEEDS_PHYSICAL(dev))
1471 i915_gem_object_unpin(reg_bo);
1469out_free_bo: 1472out_free_bo:
1470 drm_gem_object_unreference(&reg_bo->base); 1473 drm_gem_object_unreference(&reg_bo->base);
1471 mutex_unlock(&dev->struct_mutex);
1472out_free: 1474out_free:
1475 mutex_unlock(&dev->struct_mutex);
1473 kfree(overlay); 1476 kfree(overlay);
1474 return; 1477 return;
1475} 1478}