Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 157174
b: refs/heads/master
c: a09ba7f
h: refs/heads/master
v: v3
  • Loading branch information
Eric Anholt committed Aug 30, 2009
1 parent be08341 commit ab79e5a
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f8aed700c6ec46ddade6570004ce25332283b306
refs/heads/master: a09ba7faf75fa4b21980d81de8e5f3d5c0785ccf
6 changes: 6 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ typedef struct drm_i915_private {
*/
struct list_head inactive_list;

/** LRU list of objects with fence regs on them. */
struct list_head fence_list;

/**
* List of breadcrumbs associated with GPU requests currently
* outstanding.
Expand Down Expand Up @@ -451,6 +454,9 @@ struct drm_i915_gem_object {
/** This object's place on the active/flushing/inactive lists */
struct list_head list;

/** This object's place on the fenced object LRU */
struct list_head fence_list;

/**
* This is set if the object is on the active or flushing lists
* (has pending rendering), and is not set if it's on inactive (ready
Expand Down
86 changes: 48 additions & 38 deletions trunk/drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,7 @@ int
i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_set_domain *args = data;
struct drm_gem_object *obj;
uint32_t read_domains = args->read_domains;
Expand Down Expand Up @@ -1010,8 +1011,18 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
obj, obj->size, read_domains, write_domain);
#endif
if (read_domains & I915_GEM_DOMAIN_GTT) {
struct drm_i915_gem_object *obj_priv = obj->driver_private;

ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);

/* Update the LRU on the fence for the CPU access that's
* about to occur.
*/
if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
list_move_tail(&obj_priv->fence_list,
&dev_priv->mm.fence_list);
}

/* Silently promote "you're not bound, there was nothing to do"
* to success, since the client was just asking us to
* make sure everything was done.
Expand Down Expand Up @@ -1155,8 +1166,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}

/* Need a new fence register? */
if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE) {
if (obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret) {
mutex_unlock(&dev->struct_mutex);
Expand Down Expand Up @@ -2208,6 +2218,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
struct drm_i915_gem_object *old_obj_priv = NULL;
int i, ret, avail;

/* Just update our place in the LRU if our fence is getting used. */
if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
return 0;
}

switch (obj_priv->tiling_mode) {
case I915_TILING_NONE:
WARN(1, "allocating a fence for non-tiled object?\n");
Expand All @@ -2229,7 +2245,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
}

/* First try to find a free reg */
try_again:
avail = 0;
for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
reg = &dev_priv->fence_regs[i];
Expand All @@ -2243,63 +2258,57 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)

/* None available, try to steal one or wait for a user to finish */
if (i == dev_priv->num_fence_regs) {
uint32_t seqno = dev_priv->mm.next_gem_seqno;
struct drm_gem_object *old_obj = NULL;

if (avail == 0)
return -ENOSPC;

for (i = dev_priv->fence_reg_start;
i < dev_priv->num_fence_regs; i++) {
uint32_t this_seqno;
list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
fence_list) {
old_obj = old_obj_priv->obj;

reg = &dev_priv->fence_regs[i];
old_obj_priv = reg->obj->driver_private;
reg = &dev_priv->fence_regs[old_obj_priv->fence_reg];

if (old_obj_priv->pin_count)
continue;

/* Take a reference, as otherwise the wait_rendering
* below may cause the object to get freed out from
* under us.
*/
drm_gem_object_reference(old_obj);

/* i915 uses fences for GPU access to tiled buffers */
if (IS_I965G(dev) || !old_obj_priv->active)
break;

/* find the seqno of the first available fence */
this_seqno = old_obj_priv->last_rendering_seqno;
if (this_seqno != 0 &&
reg->obj->write_domain == 0 &&
i915_seqno_passed(seqno, this_seqno))
seqno = this_seqno;
}

/*
* Now things get ugly... we have to wait for one of the
* objects to finish before trying again.
*/
if (i == dev_priv->num_fence_regs) {
if (seqno == dev_priv->mm.next_gem_seqno) {
i915_gem_flush(dev,
I915_GEM_GPU_DOMAINS,
I915_GEM_GPU_DOMAINS);
seqno = i915_add_request(dev, NULL,
I915_GEM_GPU_DOMAINS);
if (seqno == 0)
return -ENOMEM;
}

ret = i915_wait_request(dev, seqno);
if (ret)
/* This brings the object to the head of the LRU if it
* had been written to. The only way this should
* result in us waiting longer than the expected
* optimal amount of time is if there was a
* fence-using buffer later that was read-only.
*/
i915_gem_object_flush_gpu_write_domain(old_obj);
ret = i915_gem_object_wait_rendering(old_obj);
if (ret != 0)
return ret;
goto try_again;
break;
}

/*
* Zap this virtual mapping so we can set up a fence again
* for this object next time we need it.
*/
i915_gem_release_mmap(reg->obj);
i = old_obj_priv->fence_reg;
old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
list_del_init(&old_obj_priv->fence_list);
drm_gem_object_unreference(old_obj);
}

obj_priv->fence_reg = i;
list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);

reg->obj = obj;

if (IS_I965G(dev))
Expand Down Expand Up @@ -2342,6 +2351,7 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)

dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
obj_priv->fence_reg = I915_FENCE_REG_NONE;
list_del_init(&obj_priv->fence_list);
}

/**
Expand Down Expand Up @@ -3595,9 +3605,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
* Pre-965 chips need a fence register set up in order to
* properly handle tiled surfaces.
*/
if (!IS_I965G(dev) &&
obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE) {
if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj);
if (ret != 0) {
if (ret != -EBUSY && ret != -ERESTARTSYS)
Expand Down Expand Up @@ -3806,6 +3814,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
obj_priv->obj = obj;
obj_priv->fence_reg = I915_FENCE_REG_NONE;
INIT_LIST_HEAD(&obj_priv->list);
INIT_LIST_HEAD(&obj_priv->fence_list);

return 0;
}
Expand Down Expand Up @@ -4253,6 +4262,7 @@ i915_gem_load(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
INIT_LIST_HEAD(&dev_priv->mm.request_list);
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler);
dev_priv->mm.next_gem_seqno = 1;
Expand Down

0 comments on commit ab79e5a

Please sign in to comment.