diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2010-02-19 05:51:58 -0500 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-02-26 16:23:21 -0500 |
commit | ae3db24aab398fb5f985696c12362eb12ef65812 (patch) | |
tree | 6c8c552805855cc42ec9d18773dc026424a0fa9f /drivers | |
parent | 4a87b8ca2185199c5d1b37b570efffd2e46fe813 (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.c | 107 |
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 | ||
2385 | static 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 | } |