Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel: drm/i915: fix 945 fence register writes for fence 8 and above. drm/i915: Protect active fences on i915 drm/i915: Check to see if we've pinned all available fences drm/i915: Check fence status on every pin. drm/i915: First recheck for an empty fence register. drm/i915: Fix bad \n in MTRR failure notice. drm/i915: Don't restore palettes through VGA registers. i915: add newline to i915_gem_object_pin failure msg drm: Return EINVAL on duplicate objects in execbuffer object list
This commit is contained in:
commit
932088b136
5 changed files with 99 additions and 37 deletions
|
@ -1105,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||||
1024 * 1024,
|
1024 * 1024,
|
||||||
MTRR_TYPE_WRCOMB, 1);
|
MTRR_TYPE_WRCOMB, 1);
|
||||||
if (dev_priv->mm.gtt_mtrr < 0) {
|
if (dev_priv->mm.gtt_mtrr < 0) {
|
||||||
DRM_INFO("MTRR allocation failed\n. Graphics "
|
DRM_INFO("MTRR allocation failed. Graphics "
|
||||||
"performance may suffer.\n");
|
"performance may suffer.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -279,7 +279,6 @@ typedef struct drm_i915_private {
|
||||||
u8 saveAR_INDEX;
|
u8 saveAR_INDEX;
|
||||||
u8 saveAR[21];
|
u8 saveAR[21];
|
||||||
u8 saveDACMASK;
|
u8 saveDACMASK;
|
||||||
u8 saveDACDATA[256*3]; /* 256 3-byte colors */
|
|
||||||
u8 saveCR[37];
|
u8 saveCR[37];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -457,6 +456,12 @@ struct drm_i915_gem_object {
|
||||||
|
|
||||||
/** for phy allocated objects */
|
/** for phy allocated objects */
|
||||||
struct drm_i915_gem_phys_object *phys_obj;
|
struct drm_i915_gem_phys_object *phys_obj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for checking the object doesn't appear more than once
|
||||||
|
* in an execbuffer object list.
|
||||||
|
*/
|
||||||
|
int in_execbuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1476,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||||
int regnum = obj_priv->fence_reg;
|
int regnum = obj_priv->fence_reg;
|
||||||
int tile_width;
|
int tile_width;
|
||||||
uint32_t val;
|
uint32_t fence_reg, val;
|
||||||
uint32_t pitch_val;
|
uint32_t pitch_val;
|
||||||
|
|
||||||
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
|
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
|
||||||
|
@ -1503,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||||
val |= pitch_val << I830_FENCE_PITCH_SHIFT;
|
val |= pitch_val << I830_FENCE_PITCH_SHIFT;
|
||||||
val |= I830_FENCE_REG_VALID;
|
val |= I830_FENCE_REG_VALID;
|
||||||
|
|
||||||
I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
|
if (regnum < 8)
|
||||||
|
fence_reg = FENCE_REG_830_0 + (regnum * 4);
|
||||||
|
else
|
||||||
|
fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
|
||||||
|
I915_WRITE(fence_reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
|
||||||
|
@ -1557,7 +1561,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||||
struct drm_i915_fence_reg *reg = NULL;
|
struct drm_i915_fence_reg *reg = NULL;
|
||||||
int i, ret;
|
struct drm_i915_gem_object *old_obj_priv = NULL;
|
||||||
|
int i, ret, avail;
|
||||||
|
|
||||||
switch (obj_priv->tiling_mode) {
|
switch (obj_priv->tiling_mode) {
|
||||||
case I915_TILING_NONE:
|
case I915_TILING_NONE:
|
||||||
|
@ -1580,25 +1585,46 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First try to find a free reg */
|
/* 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++) {
|
for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
|
||||||
reg = &dev_priv->fence_regs[i];
|
reg = &dev_priv->fence_regs[i];
|
||||||
if (!reg->obj)
|
if (!reg->obj)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
old_obj_priv = reg->obj->driver_private;
|
||||||
|
if (!old_obj_priv->pin_count)
|
||||||
|
avail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* None available, try to steal one or wait for a user to finish */
|
/* None available, try to steal one or wait for a user to finish */
|
||||||
if (i == dev_priv->num_fence_regs) {
|
if (i == dev_priv->num_fence_regs) {
|
||||||
struct drm_i915_gem_object *old_obj_priv = NULL;
|
uint32_t seqno = dev_priv->mm.next_gem_seqno;
|
||||||
loff_t offset;
|
loff_t offset;
|
||||||
|
|
||||||
try_again:
|
if (avail == 0)
|
||||||
/* Could try to use LRU here instead... */
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = dev_priv->fence_reg_start;
|
for (i = dev_priv->fence_reg_start;
|
||||||
i < dev_priv->num_fence_regs; i++) {
|
i < dev_priv->num_fence_regs; i++) {
|
||||||
|
uint32_t this_seqno;
|
||||||
|
|
||||||
reg = &dev_priv->fence_regs[i];
|
reg = &dev_priv->fence_regs[i];
|
||||||
old_obj_priv = reg->obj->driver_private;
|
old_obj_priv = reg->obj->driver_private;
|
||||||
if (!old_obj_priv->pin_count)
|
|
||||||
|
if (old_obj_priv->pin_count)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* i915 uses fences for GPU access to tiled buffers */
|
||||||
|
if (IS_I965G(dev) || !old_obj_priv->active)
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1606,15 +1632,25 @@ try_again:
|
||||||
* objects to finish before trying again.
|
* objects to finish before trying again.
|
||||||
*/
|
*/
|
||||||
if (i == dev_priv->num_fence_regs) {
|
if (i == dev_priv->num_fence_regs) {
|
||||||
ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0);
|
if (seqno == dev_priv->mm.next_gem_seqno) {
|
||||||
if (ret) {
|
i915_gem_flush(dev,
|
||||||
WARN(ret != -ERESTARTSYS,
|
I915_GEM_GPU_DOMAINS,
|
||||||
"switch to GTT domain failed: %d\n", ret);
|
I915_GEM_GPU_DOMAINS);
|
||||||
return ret;
|
seqno = i915_add_request(dev,
|
||||||
|
I915_GEM_GPU_DOMAINS);
|
||||||
|
if (seqno == 0)
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = i915_wait_request(dev, seqno);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
goto try_again;
|
goto try_again;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BUG_ON(old_obj_priv->active ||
|
||||||
|
(reg->obj->write_domain & I915_GEM_GPU_DOMAINS));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Zap this virtual mapping so we can set up a fence again
|
* Zap this virtual mapping so we can set up a fence again
|
||||||
* for this object next time we need it.
|
* for this object next time we need it.
|
||||||
|
@ -1655,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
|
||||||
|
|
||||||
if (IS_I965G(dev))
|
if (IS_I965G(dev))
|
||||||
I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
|
I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
|
||||||
else
|
else {
|
||||||
I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0);
|
uint32_t fence_reg;
|
||||||
|
|
||||||
|
if (obj_priv->fence_reg < 8)
|
||||||
|
fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
|
||||||
|
else
|
||||||
|
fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg -
|
||||||
|
8) * 4;
|
||||||
|
|
||||||
|
I915_WRITE(fence_reg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
|
dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
|
||||||
obj_priv->fence_reg = I915_FENCE_REG_NONE;
|
obj_priv->fence_reg = I915_FENCE_REG_NONE;
|
||||||
|
@ -2469,6 +2514,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||||
struct drm_i915_gem_exec_object *exec_list = NULL;
|
struct drm_i915_gem_exec_object *exec_list = NULL;
|
||||||
struct drm_gem_object **object_list = NULL;
|
struct drm_gem_object **object_list = NULL;
|
||||||
struct drm_gem_object *batch_obj;
|
struct drm_gem_object *batch_obj;
|
||||||
|
struct drm_i915_gem_object *obj_priv;
|
||||||
int ret, i, pinned = 0;
|
int ret, i, pinned = 0;
|
||||||
uint64_t exec_offset;
|
uint64_t exec_offset;
|
||||||
uint32_t seqno, flush_domains;
|
uint32_t seqno, flush_domains;
|
||||||
|
@ -2533,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj_priv = object_list[i]->driver_private;
|
||||||
|
if (obj_priv->in_execbuffer) {
|
||||||
|
DRM_ERROR("Object %p appears more than once in object list\n",
|
||||||
|
object_list[i]);
|
||||||
|
ret = -EBADF;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
obj_priv->in_execbuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pin and relocate */
|
/* Pin and relocate */
|
||||||
|
@ -2674,8 +2729,13 @@ err:
|
||||||
for (i = 0; i < pinned; i++)
|
for (i = 0; i < pinned; i++)
|
||||||
i915_gem_object_unpin(object_list[i]);
|
i915_gem_object_unpin(object_list[i]);
|
||||||
|
|
||||||
for (i = 0; i < args->buffer_count; i++)
|
for (i = 0; i < args->buffer_count; i++) {
|
||||||
|
if (object_list[i]) {
|
||||||
|
obj_priv = object_list[i]->driver_private;
|
||||||
|
obj_priv->in_execbuffer = false;
|
||||||
|
}
|
||||||
drm_gem_object_unreference(object_list[i]);
|
drm_gem_object_unreference(object_list[i]);
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
||||||
|
@ -2712,17 +2772,24 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
|
||||||
ret = i915_gem_object_bind_to_gtt(obj, alignment);
|
ret = i915_gem_object_bind_to_gtt(obj, alignment);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (ret != -EBUSY && ret != -ERESTARTSYS)
|
if (ret != -EBUSY && ret != -ERESTARTSYS)
|
||||||
DRM_ERROR("Failure to bind: %d", ret);
|
DRM_ERROR("Failure to bind: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
ret = i915_gem_object_get_fence_reg(obj, true);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (ret != -EBUSY && ret != -ERESTARTSYS)
|
||||||
|
DRM_ERROR("Failure to install fence: %d\n",
|
||||||
|
ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
i915_gem_object_get_fence_reg(obj, true);
|
|
||||||
}
|
}
|
||||||
obj_priv->pin_count++;
|
obj_priv->pin_count++;
|
||||||
|
|
||||||
|
|
|
@ -184,6 +184,7 @@
|
||||||
* Fence registers
|
* Fence registers
|
||||||
*/
|
*/
|
||||||
#define FENCE_REG_830_0 0x2000
|
#define FENCE_REG_830_0 0x2000
|
||||||
|
#define FENCE_REG_945_8 0x3000
|
||||||
#define I830_FENCE_START_MASK 0x07f80000
|
#define I830_FENCE_START_MASK 0x07f80000
|
||||||
#define I830_FENCE_TILING_Y_SHIFT 12
|
#define I830_FENCE_TILING_Y_SHIFT 12
|
||||||
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
|
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
|
||||||
|
|
|
@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev)
|
||||||
|
|
||||||
/* VGA color palette registers */
|
/* VGA color palette registers */
|
||||||
dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
|
dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
|
||||||
/* DACCRX automatically increments during read */
|
|
||||||
I915_WRITE8(VGA_DACRX, 0);
|
|
||||||
/* Read 3 bytes of color data from each index */
|
|
||||||
for (i = 0; i < 256 * 3; i++)
|
|
||||||
dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
|
|
||||||
|
|
||||||
/* MSR bits */
|
/* MSR bits */
|
||||||
dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
|
dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
|
||||||
|
@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev)
|
||||||
|
|
||||||
/* VGA color palette registers */
|
/* VGA color palette registers */
|
||||||
I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
|
I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
|
||||||
/* DACCRX automatically increments during read */
|
|
||||||
I915_WRITE8(VGA_DACWX, 0);
|
|
||||||
/* Read 3 bytes of color data from each index */
|
|
||||||
for (i = 0; i < 256 * 3; i++)
|
|
||||||
I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int i915_save_state(struct drm_device *dev)
|
int i915_save_state(struct drm_device *dev)
|
||||||
|
|
Loading…
Add table
Reference in a new issue