aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2010-02-19 05:51:58 -0500
committerEric Anholt <eric@anholt.net>2010-02-26 16:23:21 -0500
commitae3db24aab398fb5f985696c12362eb12ef65812 (patch)
tree6c8c552805855cc42ec9d18773dc026424a0fa9f /drivers
parent4a87b8ca2185199c5d1b37b570efffd2e46fe813 (diff)
drm/i915: extract fence stealing code
The spaghetti logic in there tripped up my brain's code parser for a few secs. Prevent this from happening again by extracting the fence stealing code into a seperate functions. IMHO this slightly clears up the code flow. v2: Beautified according to ickle's comments. v3: ickle forgot to flush his comment queue ... Now there's also a we-are-paranoid BUG_ON in there. v4: I've forgotten to switch on my brain when doing v3. Now the BUG_ON actually checks something useful. v5: Clean up a stale comment as noted by Eric Anholt. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c107
1 files changed, 60 insertions, 47 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e6b85cdbc60f..ce1c0262bc63 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2382,6 +2382,58 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
2382 I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); 2382 I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
2383} 2383}
2384 2384
2385static int i915_find_fence_reg(struct drm_device *dev)
2386{
2387 struct drm_i915_fence_reg *reg = NULL;
2388 struct drm_i915_gem_object *obj_priv = NULL;
2389 struct drm_i915_private *dev_priv = dev->dev_private;
2390 struct drm_gem_object *obj = NULL;
2391 int i, avail, ret;
2392
2393 /* First try to find a free reg */
2394 avail = 0;
2395 for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
2396 reg = &dev_priv->fence_regs[i];
2397 if (!reg->obj)
2398 return i;
2399
2400 obj_priv = reg->obj->driver_private;
2401 if (!obj_priv->pin_count)
2402 avail++;
2403 }
2404
2405 if (avail == 0)
2406 return -ENOSPC;
2407
2408 /* None available, try to steal one or wait for a user to finish */
2409 i = I915_FENCE_REG_NONE;
2410 list_for_each_entry(obj_priv, &dev_priv->mm.fence_list,
2411 fence_list) {
2412 obj = obj_priv->obj;
2413
2414 if (obj_priv->pin_count)
2415 continue;
2416
2417 /* found one! */
2418 i = obj_priv->fence_reg;
2419 break;
2420 }
2421
2422 BUG_ON(i == I915_FENCE_REG_NONE);
2423
2424 /* We only have a reference on obj from the active list. put_fence_reg
2425 * might drop that one, causing a use-after-free in it. So hold a
2426 * private reference to obj like the other callers of put_fence_reg
2427 * (set_tiling ioctl) do. */
2428 drm_gem_object_reference(obj);
2429 ret = i915_gem_object_put_fence_reg(obj);
2430 drm_gem_object_unreference(obj);
2431 if (ret != 0)
2432 return ret;
2433
2434 return i;
2435}
2436
2385/** 2437/**
2386 * i915_gem_object_get_fence_reg - set up a fence reg for an object 2438 * i915_gem_object_get_fence_reg - set up a fence reg for an object
2387 * @obj: object to map through a fence reg 2439 * @obj: object to map through a fence reg
@@ -2402,8 +2454,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
2402 struct drm_i915_private *dev_priv = dev->dev_private; 2454 struct drm_i915_private *dev_priv = dev->dev_private;
2403 struct drm_i915_gem_object *obj_priv = obj->driver_private; 2455 struct drm_i915_gem_object *obj_priv = obj->driver_private;
2404 struct drm_i915_fence_reg *reg = NULL; 2456 struct drm_i915_fence_reg *reg = NULL;
2405 struct drm_i915_gem_object *old_obj_priv = NULL; 2457 int ret;
2406 int i, ret, avail;
2407 2458
2408 /* Just update our place in the LRU if our fence is getting used. */ 2459 /* Just update our place in the LRU if our fence is getting used. */
2409 if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { 2460 if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
@@ -2431,51 +2482,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
2431 break; 2482 break;
2432 } 2483 }
2433 2484
2434 /* First try to find a free reg */ 2485 ret = i915_find_fence_reg(dev);
2435 avail = 0; 2486 if (ret < 0)
2436 for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { 2487 return ret;
2437 reg = &dev_priv->fence_regs[i];
2438 if (!reg->obj)
2439 break;
2440
2441 old_obj_priv = reg->obj->driver_private;
2442 if (!old_obj_priv->pin_count)
2443 avail++;
2444 }
2445
2446 /* None available, try to steal one or wait for a user to finish */
2447 if (i == dev_priv->num_fence_regs) {
2448 struct drm_gem_object *old_obj = NULL;
2449
2450 if (avail == 0)
2451 return -ENOSPC;
2452
2453 list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
2454 fence_list) {
2455 old_obj = old_obj_priv->obj;
2456
2457 if (old_obj_priv->pin_count)
2458 continue;
2459
2460 /* Take a reference, as otherwise the wait_rendering
2461 * below may cause the object to get freed out from
2462 * under us.
2463 */
2464 drm_gem_object_reference(old_obj);
2465
2466 break;
2467 }
2468
2469 i = old_obj_priv->fence_reg;
2470 reg = &dev_priv->fence_regs[i];
2471
2472 ret = i915_gem_object_put_fence_reg(old_obj);
2473 drm_gem_object_unreference(old_obj);
2474 if (ret != 0)
2475 return ret;
2476 }
2477 2488
2478 obj_priv->fence_reg = i; 2489 obj_priv->fence_reg = ret;
2490 reg = &dev_priv->fence_regs[obj_priv->fence_reg];
2479 list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list); 2491 list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
2480 2492
2481 reg->obj = obj; 2493 reg->obj = obj;
@@ -2489,7 +2501,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
2489 else 2501 else
2490 i830_write_fence_reg(reg); 2502 i830_write_fence_reg(reg);
2491 2503
2492 trace_i915_gem_object_get_fence(obj, i, obj_priv->tiling_mode); 2504 trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
2505 obj_priv->tiling_mode);
2493 2506
2494 return 0; 2507 return 0;
2495} 2508}