diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e0389ad1477d..1449b452cc63 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1072,6 +1072,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1072 | case -EAGAIN: | 1072 | case -EAGAIN: |
1073 | return VM_FAULT_OOM; | 1073 | return VM_FAULT_OOM; |
1074 | case -EFAULT: | 1074 | case -EFAULT: |
1075 | case -EINVAL: | ||
1075 | return VM_FAULT_SIGBUS; | 1076 | return VM_FAULT_SIGBUS; |
1076 | default: | 1077 | default: |
1077 | return VM_FAULT_NOPAGE; | 1078 | return VM_FAULT_NOPAGE; |
@@ -1324,8 +1325,10 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno) | |||
1324 | obj_priv->active = 1; | 1325 | obj_priv->active = 1; |
1325 | } | 1326 | } |
1326 | /* Move from whatever list we were on to the tail of execution. */ | 1327 | /* Move from whatever list we were on to the tail of execution. */ |
1328 | spin_lock(&dev_priv->mm.active_list_lock); | ||
1327 | list_move_tail(&obj_priv->list, | 1329 | list_move_tail(&obj_priv->list, |
1328 | &dev_priv->mm.active_list); | 1330 | &dev_priv->mm.active_list); |
1331 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1329 | obj_priv->last_rendering_seqno = seqno; | 1332 | obj_priv->last_rendering_seqno = seqno; |
1330 | } | 1333 | } |
1331 | 1334 | ||
@@ -1467,6 +1470,7 @@ i915_gem_retire_request(struct drm_device *dev, | |||
1467 | /* Move any buffers on the active list that are no longer referenced | 1470 | /* Move any buffers on the active list that are no longer referenced |
1468 | * by the ringbuffer to the flushing/inactive lists as appropriate. | 1471 | * by the ringbuffer to the flushing/inactive lists as appropriate. |
1469 | */ | 1472 | */ |
1473 | spin_lock(&dev_priv->mm.active_list_lock); | ||
1470 | while (!list_empty(&dev_priv->mm.active_list)) { | 1474 | while (!list_empty(&dev_priv->mm.active_list)) { |
1471 | struct drm_gem_object *obj; | 1475 | struct drm_gem_object *obj; |
1472 | struct drm_i915_gem_object *obj_priv; | 1476 | struct drm_i915_gem_object *obj_priv; |
@@ -1481,7 +1485,7 @@ i915_gem_retire_request(struct drm_device *dev, | |||
1481 | * this seqno. | 1485 | * this seqno. |
1482 | */ | 1486 | */ |
1483 | if (obj_priv->last_rendering_seqno != request->seqno) | 1487 | if (obj_priv->last_rendering_seqno != request->seqno) |
1484 | return; | 1488 | goto out; |
1485 | 1489 | ||
1486 | #if WATCH_LRU | 1490 | #if WATCH_LRU |
1487 | DRM_INFO("%s: retire %d moves to inactive list %p\n", | 1491 | DRM_INFO("%s: retire %d moves to inactive list %p\n", |
@@ -1493,6 +1497,8 @@ i915_gem_retire_request(struct drm_device *dev, | |||
1493 | else | 1497 | else |
1494 | i915_gem_object_move_to_inactive(obj); | 1498 | i915_gem_object_move_to_inactive(obj); |
1495 | } | 1499 | } |
1500 | out: | ||
1501 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1496 | } | 1502 | } |
1497 | 1503 | ||
1498 | /** | 1504 | /** |
@@ -1990,20 +1996,23 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1990 | int regnum = obj_priv->fence_reg; | 1996 | int regnum = obj_priv->fence_reg; |
1991 | uint32_t val; | 1997 | uint32_t val; |
1992 | uint32_t pitch_val; | 1998 | uint32_t pitch_val; |
1999 | uint32_t fence_size_bits; | ||
1993 | 2000 | ||
1994 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 2001 | if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) || |
1995 | (obj_priv->gtt_offset & (obj->size - 1))) { | 2002 | (obj_priv->gtt_offset & (obj->size - 1))) { |
1996 | WARN(1, "%s: object 0x%08x not 1M or size aligned\n", | 2003 | WARN(1, "%s: object 0x%08x not 512K or size aligned\n", |
1997 | __func__, obj_priv->gtt_offset); | 2004 | __func__, obj_priv->gtt_offset); |
1998 | return; | 2005 | return; |
1999 | } | 2006 | } |
2000 | 2007 | ||
2001 | pitch_val = (obj_priv->stride / 128) - 1; | 2008 | pitch_val = (obj_priv->stride / 128) - 1; |
2002 | 2009 | WARN_ON(pitch_val & ~0x0000000f); | |
2003 | val = obj_priv->gtt_offset; | 2010 | val = obj_priv->gtt_offset; |
2004 | if (obj_priv->tiling_mode == I915_TILING_Y) | 2011 | if (obj_priv->tiling_mode == I915_TILING_Y) |
2005 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; | 2012 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; |
2006 | val |= I830_FENCE_SIZE_BITS(obj->size); | 2013 | fence_size_bits = I830_FENCE_SIZE_BITS(obj->size); |
2014 | WARN_ON(fence_size_bits & ~0x00000f00); | ||
2015 | val |= fence_size_bits; | ||
2007 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; | 2016 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; |
2008 | val |= I830_FENCE_REG_VALID; | 2017 | val |= I830_FENCE_REG_VALID; |
2009 | 2018 | ||
@@ -2194,7 +2203,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2194 | return -EBUSY; | 2203 | return -EBUSY; |
2195 | if (alignment == 0) | 2204 | if (alignment == 0) |
2196 | alignment = i915_gem_get_gtt_alignment(obj); | 2205 | alignment = i915_gem_get_gtt_alignment(obj); |
2197 | if (alignment & (PAGE_SIZE - 1)) { | 2206 | if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) { |
2198 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); | 2207 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); |
2199 | return -EINVAL; | 2208 | return -EINVAL; |
2200 | } | 2209 | } |
@@ -2211,15 +2220,20 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2211 | } | 2220 | } |
2212 | } | 2221 | } |
2213 | if (obj_priv->gtt_space == NULL) { | 2222 | if (obj_priv->gtt_space == NULL) { |
2223 | bool lists_empty; | ||
2224 | |||
2214 | /* If the gtt is empty and we're still having trouble | 2225 | /* If the gtt is empty and we're still having trouble |
2215 | * fitting our object in, we're out of memory. | 2226 | * fitting our object in, we're out of memory. |
2216 | */ | 2227 | */ |
2217 | #if WATCH_LRU | 2228 | #if WATCH_LRU |
2218 | DRM_INFO("%s: GTT full, evicting something\n", __func__); | 2229 | DRM_INFO("%s: GTT full, evicting something\n", __func__); |
2219 | #endif | 2230 | #endif |
2220 | if (list_empty(&dev_priv->mm.inactive_list) && | 2231 | spin_lock(&dev_priv->mm.active_list_lock); |
2221 | list_empty(&dev_priv->mm.flushing_list) && | 2232 | lists_empty = (list_empty(&dev_priv->mm.inactive_list) && |
2222 | list_empty(&dev_priv->mm.active_list)) { | 2233 | list_empty(&dev_priv->mm.flushing_list) && |
2234 | list_empty(&dev_priv->mm.active_list)); | ||
2235 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
2236 | if (lists_empty) { | ||
2223 | DRM_ERROR("GTT full, but LRU list empty\n"); | 2237 | DRM_ERROR("GTT full, but LRU list empty\n"); |
2224 | return -ENOMEM; | 2238 | return -ENOMEM; |
2225 | } | 2239 | } |
@@ -3675,6 +3689,7 @@ i915_gem_idle(struct drm_device *dev) | |||
3675 | 3689 | ||
3676 | i915_gem_retire_requests(dev); | 3690 | i915_gem_retire_requests(dev); |
3677 | 3691 | ||
3692 | spin_lock(&dev_priv->mm.active_list_lock); | ||
3678 | if (!dev_priv->mm.wedged) { | 3693 | if (!dev_priv->mm.wedged) { |
3679 | /* Active and flushing should now be empty as we've | 3694 | /* Active and flushing should now be empty as we've |
3680 | * waited for a sequence higher than any pending execbuffer | 3695 | * waited for a sequence higher than any pending execbuffer |
@@ -3701,6 +3716,7 @@ i915_gem_idle(struct drm_device *dev) | |||
3701 | obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; | 3716 | obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; |
3702 | i915_gem_object_move_to_inactive(obj_priv->obj); | 3717 | i915_gem_object_move_to_inactive(obj_priv->obj); |
3703 | } | 3718 | } |
3719 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
3704 | 3720 | ||
3705 | while (!list_empty(&dev_priv->mm.flushing_list)) { | 3721 | while (!list_empty(&dev_priv->mm.flushing_list)) { |
3706 | struct drm_i915_gem_object *obj_priv; | 3722 | struct drm_i915_gem_object *obj_priv; |
@@ -3949,7 +3965,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
3949 | if (ret != 0) | 3965 | if (ret != 0) |
3950 | return ret; | 3966 | return ret; |
3951 | 3967 | ||
3968 | spin_lock(&dev_priv->mm.active_list_lock); | ||
3952 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); | 3969 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); |
3970 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
3971 | |||
3953 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); | 3972 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); |
3954 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); | 3973 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); |
3955 | BUG_ON(!list_empty(&dev_priv->mm.request_list)); | 3974 | BUG_ON(!list_empty(&dev_priv->mm.request_list)); |
@@ -3993,6 +4012,7 @@ i915_gem_load(struct drm_device *dev) | |||
3993 | { | 4012 | { |
3994 | drm_i915_private_t *dev_priv = dev->dev_private; | 4013 | drm_i915_private_t *dev_priv = dev->dev_private; |
3995 | 4014 | ||
4015 | spin_lock_init(&dev_priv->mm.active_list_lock); | ||
3996 | INIT_LIST_HEAD(&dev_priv->mm.active_list); | 4016 | INIT_LIST_HEAD(&dev_priv->mm.active_list); |
3997 | INIT_LIST_HEAD(&dev_priv->mm.flushing_list); | 4017 | INIT_LIST_HEAD(&dev_priv->mm.flushing_list); |
3998 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); | 4018 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); |