Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3479 → Rev 3480

/drivers/video/drm/i915/i915_gem.c
118,14 → 118,12
}
 
static int
i915_gem_wait_for_error(struct drm_device *dev)
i915_gem_wait_for_error(struct i915_gpu_error *error)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct completion *x = &dev_priv->error_completion;
unsigned long flags;
int ret;
 
if (!atomic_read(&dev_priv->mm.wedged))
#define EXIT_COND (!i915_reset_in_progress(error))
if (EXIT_COND)
return 0;
#if 0
/*
133,7 → 131,9
* userspace. If it takes that long something really bad is going on and
* we should simply try to bail out and fail as gracefully as possible.
*/
ret = wait_for_completion_interruptible_timeout(x, 10*HZ);
ret = wait_event_interruptible_timeout(error->reset_queue,
EXIT_COND,
10*HZ);
if (ret == 0) {
DRM_ERROR("Timed out waiting for the gpu reset to complete\n");
return -EIO;
141,17 → 141,8
return ret;
}
 
if (atomic_read(&dev_priv->mm.wedged)) {
/* GPU is hung, bump the completion count to account for
* the token we just consumed so that we never hit zero and
* end up waiting upon a subsequent completion event that
* will never happen.
*/
spin_lock_irqsave(&x->wait.lock, flags);
x->done++;
spin_unlock_irqrestore(&x->wait.lock, flags);
}
#endif
#undef EXIT_COND
 
return 0;
}
158,13 → 149,16
 
int i915_mutex_lock_interruptible(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
 
ret = i915_gem_wait_for_error(dev);
ret = i915_gem_wait_for_error(&dev_priv->gpu_error);
if (ret)
return ret;
 
mutex_lock(&dev->struct_mutex);
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
 
WARN_ON(i915_verify_lists(dev));
return 0;
183,6 → 177,7
i915_gem_init_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_init *args = data;
 
if (drm_core_check_feature(dev, DRIVER_MODESET))
197,8 → 192,9
return -ENODEV;
 
mutex_lock(&dev->struct_mutex);
i915_gem_init_global_gtt(dev, args->gtt_start,
args->gtt_end, args->gtt_end);
i915_gem_setup_global_gtt(dev, args->gtt_start, args->gtt_end,
args->gtt_end);
dev_priv->gtt.mappable_end = args->gtt_end;
mutex_unlock(&dev->struct_mutex);
 
return 0;
221,12 → 217,24
pinned += obj->gtt_space->size;
mutex_unlock(&dev->struct_mutex);
 
args->aper_size = dev_priv->mm.gtt_total;
args->aper_size = dev_priv->gtt.total;
args->aper_available_size = args->aper_size - pinned;
 
return 0;
}
 
void *i915_gem_object_alloc(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
return kmalloc(sizeof(struct drm_i915_gem_object), 0);
}
 
void i915_gem_object_free(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
kfree(obj);
}
 
static int
i915_gem_create(struct drm_file *file,
struct drm_device *dev,
297,13 → 305,7
args->size, &args->handle);
}
 
static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
{
drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
 
return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
obj->tiling_mode != I915_TILING_NONE;
}
#if 0
 
static inline int
446,7 → 448,6
loff_t offset;
int shmem_page_offset, page_length, ret = 0;
int obj_do_bit17_swizzling, page_do_bit17_swizzling;
int hit_slowpath = 0;
int prefaulted = 0;
int needs_clflush = 0;
struct scatterlist *sg;
508,7 → 509,6
if (ret == 0)
goto next_page;
 
hit_slowpath = 1;
mutex_unlock(&dev->struct_mutex);
 
if (!prefaulted) {
541,12 → 541,6
out:
i915_gem_object_unpin_pages(obj);
 
if (hit_slowpath) {
/* Fixup: Kill any reinstated backing storage pages */
if (obj->madv == __I915_MADV_PURGED)
i915_gem_object_truncate(obj);
}
 
return ret;
}
 
888,12 → 882,13
i915_gem_object_unpin_pages(obj);
 
if (hit_slowpath) {
/* Fixup: Kill any reinstated backing storage pages */
if (obj->madv == __I915_MADV_PURGED)
i915_gem_object_truncate(obj);
/* and flush dirty cachelines in case the object isn't in the cpu write
* domain anymore. */
if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
/*
* Fixup: Flush cpu caches in case we didn't flush the dirty
* cachelines in-line while writing and the object moved
* out of the cpu write domain while we've dropped the lock.
*/
if (!needs_clflush_after &&
obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
i915_gem_clflush_object(obj);
i915_gem_chipset_flush(dev);
}
918,6 → 913,12
struct drm_i915_gem_object *obj;
int ret;
 
if(args->handle == -2)
{
printf("%s handle %d\n", __FUNCTION__, args->handle);
return 0;
}
 
if (args->size == 0)
return 0;
 
980,26 → 981,17
}
 
int
i915_gem_check_wedge(struct drm_i915_private *dev_priv,
i915_gem_check_wedge(struct i915_gpu_error *error,
bool interruptible)
{
if (atomic_read(&dev_priv->mm.wedged)) {
struct completion *x = &dev_priv->error_completion;
bool recovery_complete;
unsigned long flags;
 
/* Give the error handler a chance to run. */
spin_lock_irqsave(&x->wait.lock, flags);
recovery_complete = x->done > 0;
spin_unlock_irqrestore(&x->wait.lock, flags);
 
if (i915_reset_in_progress(error)) {
/* Non-interruptible callers can't handle -EAGAIN, hence return
* -EIO unconditionally for these. */
if (!interruptible)
return -EIO;
 
/* Recovery complete, but still wedged means reset failure. */
if (recovery_complete)
/* Recovery complete, but the reset failed ... */
if (i915_terminally_wedged(error))
return -EIO;
 
return -EAGAIN;
1030,13 → 1022,22
* __wait_seqno - wait until execution of seqno has finished
* @ring: the ring expected to report seqno
* @seqno: duh!
* @reset_counter: reset sequence associated with the given seqno
* @interruptible: do an interruptible wait (normally yes)
* @timeout: in - how long to wait (NULL forever); out - how much time remaining
*
* Note: It is of utmost importance that the passed in seqno and reset_counter
* values have been read by the caller in an smp safe manner. Where read-side
* locks are involved, it is sufficient to read the reset_counter before
* unlocking the lock that protects the seqno. For lockless tricks, the
* reset_counter _must_ be read before, and an appropriate smp_rmb must be
* inserted.
*
* Returns 0 if the seqno was found within the alloted time. Else returns the
* errno with remaining time filled in timeout argument.
*/
static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
unsigned reset_counter,
bool interruptible, struct timespec *timeout)
{
drm_i915_private_t *dev_priv = ring->dev->dev_private;
1066,7 → 1067,8
 
#define EXIT_COND \
(i915_seqno_passed(ring->get_seqno(ring, false), seqno) || \
atomic_read(&dev_priv->mm.wedged))
i915_reset_in_progress(&dev_priv->gpu_error) || \
reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
do {
if (interruptible)
end = wait_event_interruptible_timeout(ring->irq_queue,
1076,7 → 1078,14
end = wait_event_timeout(ring->irq_queue, EXIT_COND,
timeout_jiffies);
 
ret = i915_gem_check_wedge(dev_priv, interruptible);
/* We need to check whether any gpu reset happened in between
* the caller grabbing the seqno and now ... */
if (reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
end = -EAGAIN;
 
/* ... but upgrade the -EGAIN to an -EIO if the gpu is truely
* gone. */
ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible);
if (ret)
end = ret;
} while (end == 0 && wait_forever);
1122,7 → 1131,7
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
BUG_ON(seqno == 0);
 
ret = i915_gem_check_wedge(dev_priv, interruptible);
ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible);
if (ret)
return ret;
 
1130,7 → 1139,9
if (ret)
return ret;
 
return __wait_seqno(ring, seqno, interruptible, NULL);
return __wait_seqno(ring, seqno,
atomic_read(&dev_priv->gpu_error.reset_counter),
interruptible, NULL);
}
 
/**
1177,6 → 1188,7
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = obj->ring;
unsigned reset_counter;
u32 seqno;
int ret;
 
1187,7 → 1199,7
if (seqno == 0)
return 0;
 
ret = i915_gem_check_wedge(dev_priv, true);
ret = i915_gem_check_wedge(&dev_priv->gpu_error, true);
if (ret)
return ret;
 
1195,8 → 1207,9
if (ret)
return ret;
 
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
mutex_unlock(&dev->struct_mutex);
ret = __wait_seqno(ring, seqno, true, NULL);
ret = __wait_seqno(ring, seqno, reset_counter, true, NULL);
mutex_lock(&dev->struct_mutex);
 
i915_gem_retire_requests_ring(ring);
1227,6 → 1240,13
uint32_t write_domain = args->write_domain;
int ret;
 
 
if(args->handle == -2)
{
printf("%s handle %d\n", __FUNCTION__, args->handle);
return 0;
}
 
/* Only handle setting domains to types used by the CPU. */
if (write_domain & I915_GEM_GPU_DOMAINS)
return -EINVAL;
1298,6 → 1318,12
struct drm_gem_object *obj;
unsigned long addr = 0;
 
if(args->handle == -2)
{
printf("%s handle %d\n", __FUNCTION__, args->handle);
return 0;
}
 
obj = drm_gem_object_lookup(dev, file, args->handle);
if (obj == NULL)
return -ENOENT;
1364,7 → 1390,7
obj->fault_mappable = false;
}
 
static uint32_t
uint32_t
i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
{
uint32_t gtt_size;
1392,16 → 1418,15
* Return the required GTT alignment for an object, taking into account
* potential fence register mapping.
*/
static uint32_t
i915_gem_get_gtt_alignment(struct drm_device *dev,
uint32_t size,
int tiling_mode)
uint32_t
i915_gem_get_gtt_alignment(struct drm_device *dev, uint32_t size,
int tiling_mode, bool fenced)
{
/*
* Minimum alignment is 4k (GTT page size), but might be greater
* if a fence register is needed for the object.
*/
if (INTEL_INFO(dev)->gen >= 4 ||
if (INTEL_INFO(dev)->gen >= 4 || (!fenced && IS_G33(dev)) ||
tiling_mode == I915_TILING_NONE)
return 4096;
 
1441,6 → 1466,104
return i915_gem_get_gtt_size(dev, size, tiling_mode);
}
 
int
i915_gem_mmap_gtt(struct drm_file *file,
struct drm_device *dev,
uint32_t handle,
uint64_t *offset)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
unsigned long pfn;
char *mem, *ptr;
int ret;
 
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
 
obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
if (&obj->base == NULL) {
ret = -ENOENT;
goto unlock;
}
 
if (obj->base.size > dev_priv->gtt.mappable_end) {
ret = -E2BIG;
goto out;
}
 
if (obj->madv != I915_MADV_WILLNEED) {
DRM_ERROR("Attempting to mmap a purgeable buffer\n");
ret = -EINVAL;
goto out;
}
/* Now bind it into the GTT if needed */
ret = i915_gem_object_pin(obj, 0, true, false);
if (ret)
goto out;
 
ret = i915_gem_object_set_to_gtt_domain(obj, 1);
if (ret)
goto unpin;
 
ret = i915_gem_object_get_fence(obj);
if (ret)
goto unpin;
 
obj->fault_mappable = true;
 
pfn = dev_priv->gtt.mappable_base + obj->gtt_offset;
 
/* Finally, remap it using the new GTT offset */
 
mem = UserAlloc(obj->base.size);
if(unlikely(mem == NULL))
{
ret = -ENOMEM;
goto unpin;
}
 
for(ptr = mem; ptr < mem + obj->base.size; ptr+= 4096, pfn+= 4096)
MapPage(ptr, pfn, PG_SHARED|PG_UW);
 
unpin:
i915_gem_object_unpin(obj);
 
 
*offset = (u64)mem;
 
out:
drm_gem_object_unreference(&obj->base);
unlock:
mutex_unlock(&dev->struct_mutex);
return ret;
}
 
/**
* i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
* @dev: DRM device
* @data: GTT mapping ioctl data
* @file: GEM object info
*
* Simply returns the fake offset to userspace so it can mmap it.
* The mmap call will end up in drm_gem_mmap(), which will set things
* up so we can get faults in the handler above.
*
* The fault handler will take care of binding the object into the GTT
* (since it may have been evicted to make room for something), allocating
* a fence register, and mapping the appropriate aperture address into
* userspace.
*/
int
i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_i915_gem_mmap_gtt *args = data;
 
return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
}
 
/* Immediately discard the backing storage */
static void
i915_gem_object_truncate(struct drm_i915_gem_object *obj)
1504,7 → 1627,7
kfree(obj->pages);
}
 
static int
int
i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
{
const struct drm_i915_gem_object_ops *ops = obj->ops;
1669,9 → 1792,6
BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
BUG_ON(!obj->active);
 
if (obj->pin_count) /* are we a framebuffer? */
intel_mark_fb_idle(obj);
 
list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
list_del_init(&obj->ring_list);
1691,30 → 1811,24
}
 
static int
i915_gem_handle_seqno_wrap(struct drm_device *dev)
i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring;
int ret, i, j;
 
/* The hardware uses various monotonic 32-bit counters, if we
* detect that they will wraparound we need to idle the GPU
* and reset those counters.
*/
ret = 0;
/* Carefully retire all requests without writing to the rings */
for_each_ring(ring, dev_priv, i) {
for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)
ret |= ring->sync_seqno[j] != 0;
}
if (ret == 0)
return ret;
 
ret = i915_gpu_idle(dev);
ret = intel_ring_idle(ring);
if (ret)
return ret;
}
i915_gem_retire_requests(dev);
 
i915_gem_retire_requests(dev);
/* Finally reset hw state */
for_each_ring(ring, dev_priv, i) {
intel_ring_init_seqno(ring, seqno);
 
for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)
ring->sync_seqno[j] = 0;
}
1722,6 → 1836,32
return 0;
}
 
int i915_gem_set_seqno(struct drm_device *dev, u32 seqno)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
 
if (seqno == 0)
return -EINVAL;
 
/* HWS page needs to be set less than what we
* will inject to ring
*/
ret = i915_gem_init_seqno(dev, seqno - 1);
if (ret)
return ret;
 
/* Carefully set the last_seqno value so that wrap
* detection still works
*/
dev_priv->next_seqno = seqno;
dev_priv->last_seqno = seqno - 1;
if (dev_priv->last_seqno == 0)
dev_priv->last_seqno--;
 
return 0;
}
 
int
i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
{
1729,7 → 1869,7
 
/* reserve 0 for non-seqno */
if (dev_priv->next_seqno == 0) {
int ret = i915_gem_handle_seqno_wrap(dev);
int ret = i915_gem_init_seqno(dev, 0);
if (ret)
return ret;
 
1736,7 → 1876,7
dev_priv->next_seqno = 1;
}
 
*seqno = dev_priv->next_seqno++;
*seqno = dev_priv->last_seqno = dev_priv->next_seqno++;
return 0;
}
 
2126,9 → 2266,6
{
u32 old_write_domain, old_read_domains;
 
/* Act a barrier for all accesses through the GTT */
mb();
 
/* Force a pagefault for domain tracking on next user access */
// i915_gem_release_mmap(obj);
 
2135,6 → 2272,9
if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
return;
 
/* Wait for any direct GTT access to complete */
mb();
 
old_read_domains = obj->base.read_domains;
old_write_domain = obj->base.write_domain;
 
2153,7 → 2293,7
i915_gem_object_unbind(struct drm_i915_gem_object *obj)
{
drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
int ret = 0;
int ret;
 
if(obj == get_fb_obj())
return 0;
2223,37 → 2363,22
return 0;
}
 
static void sandybridge_write_fence_reg(struct drm_device *dev, int reg,
static void i965_write_fence_reg(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int fence_reg;
int fence_pitch_shift;
uint64_t val;
 
if (obj) {
u32 size = obj->gtt_space->size;
 
val = (uint64_t)((obj->gtt_offset + size - 4096) &
0xfffff000) << 32;
val |= obj->gtt_offset & 0xfffff000;
val |= (uint64_t)((obj->stride / 128) - 1) <<
SANDYBRIDGE_FENCE_PITCH_SHIFT;
 
if (obj->tiling_mode == I915_TILING_Y)
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
val |= I965_FENCE_REG_VALID;
} else
val = 0;
 
I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + reg * 8, val);
POSTING_READ(FENCE_REG_SANDYBRIDGE_0 + reg * 8);
if (INTEL_INFO(dev)->gen >= 6) {
fence_reg = FENCE_REG_SANDYBRIDGE_0;
fence_pitch_shift = SANDYBRIDGE_FENCE_PITCH_SHIFT;
} else {
fence_reg = FENCE_REG_965_0;
fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
}
 
static void i965_write_fence_reg(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
drm_i915_private_t *dev_priv = dev->dev_private;
uint64_t val;
 
if (obj) {
u32 size = obj->gtt_space->size;
 
2260,7 → 2385,7
val = (uint64_t)((obj->gtt_offset + size - 4096) &
0xfffff000) << 32;
val |= obj->gtt_offset & 0xfffff000;
val |= ((obj->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT;
val |= (uint64_t)((obj->stride / 128) - 1) << fence_pitch_shift;
if (obj->tiling_mode == I915_TILING_Y)
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
val |= I965_FENCE_REG_VALID;
2267,8 → 2392,9
} else
val = 0;
 
I915_WRITE64(FENCE_REG_965_0 + reg * 8, val);
POSTING_READ(FENCE_REG_965_0 + reg * 8);
fence_reg += reg * 8;
I915_WRITE64(fence_reg, val);
POSTING_READ(fence_reg);
}
 
static void i915_write_fence_reg(struct drm_device *dev, int reg,
2347,18 → 2473,37
POSTING_READ(FENCE_REG_830_0 + reg * 4);
}
 
inline static bool i915_gem_object_needs_mb(struct drm_i915_gem_object *obj)
{
return obj && obj->base.read_domains & I915_GEM_DOMAIN_GTT;
}
 
static void i915_gem_write_fence(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
struct drm_i915_private *dev_priv = dev->dev_private;
 
/* Ensure that all CPU reads are completed before installing a fence
* and all writes before removing the fence.
*/
if (i915_gem_object_needs_mb(dev_priv->fence_regs[reg].obj))
mb();
 
switch (INTEL_INFO(dev)->gen) {
case 7:
case 6: sandybridge_write_fence_reg(dev, reg, obj); break;
case 6:
case 5:
case 4: i965_write_fence_reg(dev, reg, obj); break;
case 3: i915_write_fence_reg(dev, reg, obj); break;
case 2: i830_write_fence_reg(dev, reg, obj); break;
default: break;
default: BUG();
}
 
/* And similarly be paranoid that no direct access to this region
* is reordered to before the fence is installed.
*/
if (i915_gem_object_needs_mb(obj))
mb();
}
 
static inline int fence_number(struct drm_i915_private *dev_priv,
2388,7 → 2533,7
}
 
static int
i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
i915_gem_object_wait_fence(struct drm_i915_gem_object *obj)
{
if (obj->last_fenced_seqno) {
int ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno);
2398,12 → 2543,6
obj->last_fenced_seqno = 0;
}
 
/* Ensure that all CPU reads are completed before installing a fence
* and all writes before removing the fence.
*/
if (obj->base.read_domains & I915_GEM_DOMAIN_GTT)
mb();
 
obj->fenced_gpu_access = false;
return 0;
}
2414,7 → 2553,7
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
int ret;
 
ret = i915_gem_object_flush_fence(obj);
ret = i915_gem_object_wait_fence(obj);
if (ret)
return ret;
 
2488,7 → 2627,7
* will need to serialise the write to the associated fence register?
*/
if (obj->fence_dirty) {
ret = i915_gem_object_flush_fence(obj);
ret = i915_gem_object_wait_fence(obj);
if (ret)
return ret;
}
2509,7 → 2648,7
if (reg->obj) {
struct drm_i915_gem_object *old = reg->obj;
 
ret = i915_gem_object_flush_fence(old);
ret = i915_gem_object_wait_fence(old);
if (ret)
return ret;
 
2532,7 → 2671,7
 
/* On non-LLC machines we have to be careful when putting differing
* types of snoopable memory together to avoid the prefetcher
* crossing memory domains and dieing.
* crossing memory domains and dying.
*/
if (HAS_LLC(dev))
return true;
2610,21 → 2749,16
bool mappable, fenceable;
int ret;
 
if (obj->madv != I915_MADV_WILLNEED) {
DRM_ERROR("Attempting to bind a purgeable object\n");
return -EINVAL;
}
 
fence_size = i915_gem_get_gtt_size(dev,
obj->base.size,
obj->tiling_mode);
fence_alignment = i915_gem_get_gtt_alignment(dev,
obj->base.size,
obj->tiling_mode);
obj->tiling_mode, true);
unfenced_alignment =
i915_gem_get_unfenced_gtt_alignment(dev,
i915_gem_get_gtt_alignment(dev,
obj->base.size,
obj->tiling_mode);
obj->tiling_mode, false);
 
if (alignment == 0)
alignment = map_and_fenceable ? fence_alignment :
2640,7 → 2774,7
* before evicting everything in a vain attempt to find space.
*/
if (obj->base.size >
(map_and_fenceable ? dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) {
(map_and_fenceable ? dev_priv->gtt.mappable_end : dev_priv->gtt.total)) {
DRM_ERROR("Attempting to bind an object larger than the aperture\n");
return -E2BIG;
}
2661,7 → 2795,7
if (map_and_fenceable)
ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
size, alignment, obj->cache_level,
0, dev_priv->mm.gtt_mappable_end);
0, dev_priv->gtt.mappable_end);
else
ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
size, alignment, obj->cache_level);
2695,7 → 2829,7
(node->start & (fence_alignment - 1)) == 0;
 
mappable =
obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
obj->gtt_offset + obj->base.size <= dev_priv->gtt.mappable_end;
 
obj->map_and_fenceable = mappable && fenceable;
 
2715,6 → 2849,13
if (obj->pages == NULL)
return;
 
/*
* Stolen memory is always coherent with the GPU as it is explicitly
* marked as wc by the system, or the system is cache-coherent.
*/
if (obj->stolen)
return;
 
/* If the GPU is snooping the contents of the CPU cache,
* we do not need to manually clear the CPU cache lines. However,
* the caches are only snooped when the render cache is
2848,6 → 2989,13
 
i915_gem_object_flush_cpu_write_domain(obj);
 
/* Serialise direct access to this object with the barriers for
* coherent writes from the GPU, by effectively invalidating the
* GTT domain upon first access.
*/
if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
mb();
 
old_write_domain = obj->base.write_domain;
old_read_domains = obj->base.read_domains;
 
2955,6 → 3103,12
struct drm_i915_gem_object *obj;
int ret;
 
if(args->handle == -2)
{
printf("%s handle %d\n", __FUNCTION__, args->handle);
return 0;
}
 
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
2981,6 → 3135,12
enum i915_cache_level level;
int ret;
 
if(args->handle == -2)
{
printf("%s handle %d\n", __FUNCTION__, args->handle);
return 0;
}
 
switch (args->caching) {
case I915_CACHING_NONE:
level = I915_CACHE_NONE;
3154,12 → 3314,18
unsigned long recent_enough = GetTimerTicks() - msecs_to_jiffies(20);
struct drm_i915_gem_request *request;
struct intel_ring_buffer *ring = NULL;
unsigned reset_counter;
u32 seqno = 0;
int ret;
 
if (atomic_read(&dev_priv->mm.wedged))
return -EIO;
ret = i915_gem_wait_for_error(&dev_priv->gpu_error);
if (ret)
return ret;
 
ret = i915_gem_check_wedge(&dev_priv->gpu_error, false);
if (ret)
return ret;
 
spin_lock(&file_priv->mm.lock);
list_for_each_entry(request, &file_priv->mm.request_list, client_list) {
if (time_after_eq(request->emitted_jiffies, recent_enough))
3168,12 → 3334,13
ring = request->ring;
seqno = request->seqno;
}
reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
spin_unlock(&file_priv->mm.lock);
 
if (seqno == 0)
return 0;
 
ret = __wait_seqno(ring, seqno, true, NULL);
ret = __wait_seqno(ring, seqno, reset_counter, true, NULL);
if (ret == 0)
queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0);
 
3247,6 → 3414,12
struct drm_i915_gem_object *obj;
int ret;
 
if(args->handle == -2)
{
printf("%s handle %d\n", __FUNCTION__, args->handle);
return 0;
}
 
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
3344,6 → 3517,12
if (ret)
return ret;
 
if(args->handle == -2)
{
obj = get_fb_obj();
drm_gem_object_reference(&obj->base);
}
else
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
if (&obj->base == NULL) {
ret = -ENOENT;
3454,7 → 3633,7
{
struct drm_i915_gem_object *obj;
struct address_space *mapping;
u32 mask;
gfp_t mask;
 
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (obj == NULL)
3565,6 → 3744,10
}
i915_gem_retire_requests(dev);
 
/* Under UMS, be paranoid and evict. */
if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_gem_evict_everything(dev);
 
i915_gem_reset_fences(dev);
 
/* Hack! Don't let anybody do execbuf while we don't control the chip.
3572,7 → 3755,7
* And not confound mm.suspended!
*/
dev_priv->mm.suspended = 1;
del_timer_sync(&dev_priv->hangcheck_timer);
del_timer_sync(&dev_priv->gpu_error.hangcheck_timer);
 
i915_kernel_lost_context(dev);
i915_gem_cleanup_ringbuffer(dev);
3592,7 → 3775,7
u32 misccpctl;
int i;
 
if (!IS_IVYBRIDGE(dev))
if (!HAS_L3_GPU_CACHE(dev))
return;
 
if (!dev_priv->l3_parity.remap_info)
3635,8 → 3818,10
I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
if (IS_GEN6(dev))
I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
else if (IS_GEN7(dev))
I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
else
I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
BUG();
}
 
static bool
3655,22 → 3840,11
return true;
}
 
int
i915_gem_init_hw(struct drm_device *dev)
static int i915_gem_init_rings(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
 
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
 
if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
 
i915_gem_l3_remap(dev);
 
i915_gem_init_swizzling(dev);
 
ret = intel_init_render_ring_buffer(dev);
if (ret)
return ret;
3687,37 → 3861,50
goto cleanup_bsd_ring;
}
 
dev_priv->next_seqno = 1;
ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000));
if (ret)
goto cleanup_blt_ring;
 
/*
* XXX: There was some w/a described somewhere suggesting loading
* contexts before PPGTT.
*/
i915_gem_context_init(dev);
i915_gem_init_ppgtt(dev);
 
return 0;
 
cleanup_blt_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[BCS]);
cleanup_bsd_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[VCS]);
cleanup_render_ring:
intel_cleanup_ring_buffer(&dev_priv->ring[RCS]);
 
return ret;
}
 
static bool
intel_enable_ppgtt(struct drm_device *dev)
int
i915_gem_init_hw(struct drm_device *dev)
{
if (i915_enable_ppgtt >= 0)
return i915_enable_ppgtt;
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;
 
#ifdef CONFIG_INTEL_IOMMU
/* Disable ppgtt on SNB if VT-d is on. */
if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
return false;
#endif
if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
return -EIO;
 
return true;
if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
 
i915_gem_l3_remap(dev);
 
i915_gem_init_swizzling(dev);
 
ret = i915_gem_init_rings(dev);
if (ret)
return ret;
 
/*
* XXX: There was some w/a described somewhere suggesting loading
* contexts before PPGTT.
*/
i915_gem_context_init(dev);
i915_gem_init_ppgtt(dev);
 
return 0;
}
 
#define LFB_SIZE 0xC00000
3725,39 → 3912,10
int i915_gem_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long gtt_size, mappable_size;
int ret;
 
gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
 
mutex_lock(&dev->struct_mutex);
if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
/* PPGTT pdes are stolen from global gtt ptes, so shrink the
* aperture accordingly when using aliasing ppgtt. */
gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
 
i915_gem_init_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size - LFB_SIZE);
 
ret = i915_gem_init_aliasing_ppgtt(dev);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return ret;
}
} else {
/* Let GEM Manage all of the aperture.
*
* However, leave one page at the end still bound to the scratch
* page. There are a number of places where the hardware
* apparently prefetches past the end of the object, and we've
* seen multiple hangs with the GPU head pointer stuck in a
* batchbuffer bound at the last page of the aperture. One page
* should be enough to keep any prefetching inside of the
* aperture.
*/
i915_gem_init_global_gtt(dev, LFB_SIZE, mappable_size, gtt_size - LFB_SIZE);
}
 
i915_gem_init_global_gtt(dev);
ret = i915_gem_init_hw(dev);
mutex_unlock(&dev->struct_mutex);
if (ret) {
3791,9 → 3949,9
if (drm_core_check_feature(dev, DRIVER_MODESET))
return 0;
 
if (atomic_read(&dev_priv->mm.wedged)) {
if (i915_reset_in_progress(&dev_priv->gpu_error)) {
DRM_ERROR("Reenabling wedged hardware, good luck\n");
atomic_set(&dev_priv->mm.wedged, 0);
atomic_set(&dev_priv->gpu_error.reset_counter, 0);
}
 
mutex_lock(&dev->struct_mutex);
3858,8 → 4016,8
void
i915_gem_load(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int i;
drm_i915_private_t *dev_priv = dev->dev_private;
 
INIT_LIST_HEAD(&dev_priv->mm.active_list);
INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
3872,6 → 4030,7
INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
i915_gem_retire_work_handler);
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
 
/* On GEN3 we really need to make sure the ARB C3 LP bit is set */
if (IS_GEN3(dev)) {