Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3030 → Rev 3031

/drivers/video/drm/i915/intel_ringbuffer.c
29,10 → 29,9
#define iowrite32(v, addr) writel((v), (addr))
#define ioread32(addr) readl(addr)
 
#include "drmP.h"
#include "drm.h"
#include <drm/drmP.h>
#include "i915_drv.h"
#include "i915_drm.h"
#include <drm/i915_drm.h>
#include "i915_trace.h"
#include "intel_drv.h"
 
54,22 → 53,34
return space;
}
 
static u32 i915_gem_get_seqno(struct drm_device *dev)
static int
gen2_render_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate_domains,
u32 flush_domains)
{
drm_i915_private_t *dev_priv = dev->dev_private;
u32 seqno;
u32 cmd;
int ret;
 
seqno = dev_priv->next_seqno;
cmd = MI_FLUSH;
if (((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER) == 0)
cmd |= MI_NO_WRITE_FLUSH;
 
/* reserve 0 for non-seqno */
if (++dev_priv->next_seqno == 0)
dev_priv->next_seqno = 1;
if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
cmd |= MI_READ_FLUSH;
 
return seqno;
ret = intel_ring_begin(ring, 2);
if (ret)
return ret;
 
intel_ring_emit(ring, cmd);
intel_ring_emit(ring, MI_NOOP);
intel_ring_advance(ring);
 
return 0;
}
 
static int
render_ring_flush(struct intel_ring_buffer *ring,
gen4_render_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate_domains,
u32 flush_domains)
{
106,17 → 117,8
*/
 
cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
if ((invalidate_domains|flush_domains) &
I915_GEM_DOMAIN_RENDER)
if ((invalidate_domains|flush_domains) & I915_GEM_DOMAIN_RENDER)
cmd &= ~MI_NO_WRITE_FLUSH;
if (INTEL_INFO(dev)->gen < 4) {
/*
* On the 965, the sampler cache always gets flushed
* and this bit is reserved.
*/
if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
cmd |= MI_READ_FLUSH;
}
if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
cmd |= MI_EXE_FLUSH;
 
218,30 → 220,121
int ret;
 
/* Force SNB workarounds for PIPE_CONTROL flushes */
intel_emit_post_sync_nonzero_flush(ring);
ret = intel_emit_post_sync_nonzero_flush(ring);
if (ret)
return ret;
 
/* Just flush everything. Experiments have shown that reducing the
* number of bits based on the write domains has little performance
* impact.
*/
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
/*
* Ensure that any following seqno writes only happen
* when the render cache is indeed flushed.
*/
flags |= PIPE_CONTROL_CS_STALL;
}
if (invalidate_domains) {
flags |= PIPE_CONTROL_TLB_INVALIDATE;
flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
/*
* TLB invalidate requires a post-sync write.
*/
flags |= PIPE_CONTROL_QW_WRITE;
}
 
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
 
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
intel_ring_emit(ring, flags);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, 0);
intel_ring_advance(ring);
 
return 0;
}
 
static int
gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring)
{
int ret;
 
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
 
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
PIPE_CONTROL_STALL_AT_SCOREBOARD);
intel_ring_emit(ring, 0);
intel_ring_emit(ring, 0);
intel_ring_advance(ring);
 
return 0;
}
 
static int
gen7_render_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate_domains, u32 flush_domains)
{
u32 flags = 0;
struct pipe_control *pc = ring->private;
u32 scratch_addr = pc->gtt_offset + 128;
int ret;
 
/*
* Ensure that any following seqno writes only happen when the render
* cache is indeed flushed.
*
* Workaround: 4th PIPE_CONTROL command (except the ones with only
* read-cache invalidate bits set) must have the CS_STALL bit set. We
* don't try to be clever and just set it unconditionally.
*/
flags |= PIPE_CONTROL_CS_STALL;
 
/* Just flush everything. Experiments have shown that reducing the
* number of bits based on the write domains has little performance
* impact.
*/
if (flush_domains) {
flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
}
if (invalidate_domains) {
flags |= PIPE_CONTROL_TLB_INVALIDATE;
flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
/*
* TLB invalidate requires a post-sync write.
*/
flags |= PIPE_CONTROL_QW_WRITE;
 
ret = intel_ring_begin(ring, 6);
/* Workaround: we must issue a pipe_control with CS-stall bit
* set before a pipe_control command that has the state cache
* invalidate bit set. */
gen7_render_ring_cs_stall_wa(ring);
}
 
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
 
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
intel_ring_emit(ring, flags);
intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
intel_ring_emit(ring, 0); /* lower dword */
intel_ring_emit(ring, 0); /* uppwer dword */
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, 0);
intel_ring_advance(ring);
 
return 0;
265,17 → 358,20
 
static int init_ring_common(struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = ring->dev->dev_private;
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = ring->obj;
int ret = 0;
u32 head;
 
if (HAS_FORCE_WAKE(dev))
gen6_gt_force_wake_get(dev_priv);
 
/* Stop the ring if it's running. */
I915_WRITE_CTL(ring, 0);
I915_WRITE_HEAD(ring, 0);
ring->write_tail(ring, 0);
 
/* Initialize the ring. */
I915_WRITE_START(ring, obj->gtt_offset);
head = I915_READ_HEAD(ring) & HEAD_ADDR;
 
/* G45 ring initialization fails to reset head to zero */
301,14 → 397,19
}
}
 
/* Initialize the ring. This must happen _after_ we've cleared the ring
* registers with the above sequence (the readback of the HEAD registers
* also enforces ordering), otherwise the hw might lose the new ring
* register values. */
I915_WRITE_START(ring, obj->gtt_offset);
I915_WRITE_CTL(ring,
((ring->size - PAGE_SIZE) & RING_NR_PAGES)
| RING_REPORT_64K | RING_VALID);
| RING_VALID);
 
/* If the head is still not zero, the ring is dead */
if ((I915_READ_CTL(ring) & RING_VALID) == 0 ||
I915_READ_START(ring) != obj->gtt_offset ||
(I915_READ_HEAD(ring) & HEAD_ADDR) != 0) {
if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
I915_READ_START(ring) == obj->gtt_offset &&
(I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
DRM_ERROR("%s initialization failed "
"ctl %08x head %08x tail %08x start %08x\n",
ring->name,
316,15 → 417,20
I915_READ_HEAD(ring),
I915_READ_TAIL(ring),
I915_READ_START(ring));
return -EIO;
ret = -EIO;
goto out;
}
 
ring->head = I915_READ_HEAD(ring);
ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
ring->space = ring_space(ring);
ring->last_retired_head = -1;
 
out:
if (HAS_FORCE_WAKE(dev))
gen6_gt_force_wake_put(dev_priv);
 
return 0;
return ret;
}
 
static int
350,12 → 456,12
 
i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
ret = i915_gem_object_pin(obj, 4096, true);
ret = i915_gem_object_pin(obj, 4096, true, false);
if (ret)
goto err_unref;
 
pc->gtt_offset = obj->gtt_offset;
pc->cpu_page = (void*)MapIoMem((addr_t)obj->pages[0], 4096, PG_SW);
pc->cpu_page = (void*)MapIoMem((addr_t)obj->pages.page[0], 4096, PG_SW);
if (pc->cpu_page == NULL)
goto err_unpin;
 
397,14 → 503,11
int ret = init_ring_common(ring);
 
if (INTEL_INFO(dev)->gen > 3) {
int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH;
if (IS_GEN6(dev) || IS_GEN7(dev))
mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE;
I915_WRITE(MI_MODE, mode);
I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
if (IS_GEN7(dev))
I915_WRITE(GFX_MODE_GEN7,
GFX_MODE_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
GFX_MODE_ENABLE(GFX_REPLAY_MODE));
_MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
_MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
}
 
if (INTEL_INFO(dev)->gen >= 5) {
413,11 → 516,29
return ret;
}
 
if (INTEL_INFO(dev)->gen >= 6) {
I915_WRITE(INSTPM,
INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
if (IS_GEN6(dev)) {
/* From the Sandybridge PRM, volume 1 part 3, page 24:
* "If this bit is set, STCunit will have LRA as replacement
* policy. [...] This bit must be reset. LRA replacement
* policy is not supported."
*/
I915_WRITE(CACHE_MODE_0,
_MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
 
/* This is not explicitly set for GEN6, so read the register.
* see intel_ring_mi_set_context() for why we care.
* TODO: consider explicitly setting the bit for GEN5
*/
ring->itlb_before_ctx_switch =
!!(I915_READ(GFX_MODE) & GFX_TLB_INVALIDATE_ALWAYS);
}
 
if (INTEL_INFO(dev)->gen >= 6)
I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
if (HAS_L3_GPU_CACHE(dev))
I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
 
return ret;
}
 
466,7 → 587,7
mbox1_reg = ring->signal_mbox[0];
mbox2_reg = ring->signal_mbox[1];
 
*seqno = i915_gem_get_seqno(ring->dev);
*seqno = i915_gem_next_request_seqno(ring);
 
update_mboxes(ring, *seqno, mbox1_reg);
update_mboxes(ring, *seqno, mbox2_reg);
487,9 → 608,8
* @seqno - seqno which the waiter will block on
*/
static int
intel_ring_sync(struct intel_ring_buffer *waiter,
gen6_ring_sync(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
int ring,
u32 seqno)
{
int ret;
497,11 → 617,21
MI_SEMAPHORE_COMPARE |
MI_SEMAPHORE_REGISTER;
 
/* Throughout all of the GEM code, seqno passed implies our current
* seqno is >= the last seqno executed. However for hardware the
* comparison is strictly greater than.
*/
seqno -= 1;
 
WARN_ON(signaller->semaphore_register[waiter->id] ==
MI_SEMAPHORE_SYNC_INVALID);
 
ret = intel_ring_begin(waiter, 4);
if (ret)
return ret;
 
intel_ring_emit(waiter, dw1 | signaller->semaphore_register[ring]);
intel_ring_emit(waiter,
dw1 | signaller->semaphore_register[waiter->id]);
intel_ring_emit(waiter, seqno);
intel_ring_emit(waiter, 0);
intel_ring_emit(waiter, MI_NOOP);
510,47 → 640,6
return 0;
}
 
/* VCS->RCS (RVSYNC) or BCS->RCS (RBSYNC) */
int
render_ring_sync_to(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
u32 seqno)
{
WARN_ON(signaller->semaphore_register[RCS] == MI_SEMAPHORE_SYNC_INVALID);
return intel_ring_sync(waiter,
signaller,
RCS,
seqno);
}
 
/* RCS->VCS (VRSYNC) or BCS->VCS (VBSYNC) */
int
gen6_bsd_ring_sync_to(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
u32 seqno)
{
WARN_ON(signaller->semaphore_register[VCS] == MI_SEMAPHORE_SYNC_INVALID);
return intel_ring_sync(waiter,
signaller,
VCS,
seqno);
}
 
/* RCS->BCS (BRSYNC) or VCS->BCS (BVSYNC) */
int
gen6_blt_ring_sync_to(struct intel_ring_buffer *waiter,
struct intel_ring_buffer *signaller,
u32 seqno)
{
WARN_ON(signaller->semaphore_register[BCS] == MI_SEMAPHORE_SYNC_INVALID);
return intel_ring_sync(waiter,
signaller,
BCS,
seqno);
}
 
 
 
#define PIPE_CONTROL_FLUSH(ring__, addr__) \
do { \
intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | \
564,8 → 653,7
pc_render_add_request(struct intel_ring_buffer *ring,
u32 *result)
{
struct drm_device *dev = ring->dev;
u32 seqno = i915_gem_get_seqno(dev);
u32 seqno = i915_gem_next_request_seqno(ring);
struct pipe_control *pc = ring->private;
u32 scratch_addr = pc->gtt_offset + 128;
int ret;
599,6 → 687,7
PIPE_CONTROL_FLUSH(ring, scratch_addr);
scratch_addr += 128;
PIPE_CONTROL_FLUSH(ring, scratch_addr);
 
intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
PIPE_CONTROL_WRITE_FLUSH |
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
612,124 → 701,139
return 0;
}
 
static int
render_ring_add_request(struct intel_ring_buffer *ring,
u32 *result)
{
struct drm_device *dev = ring->dev;
u32 seqno = i915_gem_get_seqno(dev);
int ret;
 
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
 
intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
intel_ring_emit(ring, seqno);
intel_ring_emit(ring, MI_USER_INTERRUPT);
intel_ring_advance(ring);
 
*result = seqno;
return 0;
}
 
static u32
gen6_ring_get_seqno(struct intel_ring_buffer *ring)
gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
{
struct drm_device *dev = ring->dev;
 
/* Workaround to force correct ordering between irq and seqno writes on
* ivb (and maybe also on snb) by reading from a CS register (like
* ACTHD) before reading the status page. */
if (IS_GEN7(dev))
if (!lazy_coherency)
intel_ring_get_active_head(ring);
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
}
 
static u32
ring_get_seqno(struct intel_ring_buffer *ring)
ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
{
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
}
 
static u32
pc_render_get_seqno(struct intel_ring_buffer *ring)
pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
{
struct pipe_control *pc = ring->private;
return pc->cpu_page[0];
}
 
static void
ironlake_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
static bool
gen5_ring_get_irq(struct intel_ring_buffer *ring)
{
dev_priv->gt_irq_mask &= ~mask;
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
if (!dev->irq_enabled)
return false;
 
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0) {
dev_priv->gt_irq_mask &= ~ring->irq_enable_mask;
I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
POSTING_READ(GTIMR);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
return true;
}
 
static void
ironlake_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
gen5_ring_put_irq(struct intel_ring_buffer *ring)
{
dev_priv->gt_irq_mask |= mask;
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0) {
dev_priv->gt_irq_mask |= ring->irq_enable_mask;
I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
POSTING_READ(GTIMR);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
}
 
static void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
static bool
i9xx_ring_get_irq(struct intel_ring_buffer *ring)
{
dev_priv->irq_mask &= ~mask;
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
if (!dev->irq_enabled)
return false;
 
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0) {
dev_priv->irq_mask &= ~ring->irq_enable_mask;
I915_WRITE(IMR, dev_priv->irq_mask);
POSTING_READ(IMR);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
return true;
}
 
static void
i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
i9xx_ring_put_irq(struct intel_ring_buffer *ring)
{
dev_priv->irq_mask |= mask;
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0) {
dev_priv->irq_mask |= ring->irq_enable_mask;
I915_WRITE(IMR, dev_priv->irq_mask);
POSTING_READ(IMR);
}
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
}
 
static bool
render_ring_get_irq(struct intel_ring_buffer *ring)
i8xx_ring_get_irq(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
if (!dev->irq_enabled)
return false;
 
spin_lock(&ring->irq_lock);
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0) {
if (HAS_PCH_SPLIT(dev))
ironlake_enable_irq(dev_priv,
GT_PIPE_NOTIFY | GT_USER_INTERRUPT);
else
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
dev_priv->irq_mask &= ~ring->irq_enable_mask;
I915_WRITE16(IMR, dev_priv->irq_mask);
POSTING_READ16(IMR);
}
spin_unlock(&ring->irq_lock);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
return true;
}
 
static void
render_ring_put_irq(struct intel_ring_buffer *ring)
i8xx_ring_put_irq(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
spin_lock(&ring->irq_lock);
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0) {
if (HAS_PCH_SPLIT(dev))
ironlake_disable_irq(dev_priv,
GT_USER_INTERRUPT |
GT_PIPE_NOTIFY);
else
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
dev_priv->irq_mask |= ring->irq_enable_mask;
I915_WRITE16(IMR, dev_priv->irq_mask);
POSTING_READ16(IMR);
}
spin_unlock(&ring->irq_lock);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
}
 
void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
743,13 → 847,13
*/
if (IS_GEN7(dev)) {
switch (ring->id) {
case RING_RENDER:
case RCS:
mmio = RENDER_HWS_PGA_GEN7;
break;
case RING_BLT:
case BCS:
mmio = BLT_HWS_PGA_GEN7;
break;
case RING_BSD:
case VCS:
mmio = BSD_HWS_PGA_GEN7;
break;
}
781,7 → 885,7
}
 
static int
ring_add_request(struct intel_ring_buffer *ring,
i9xx_add_request(struct intel_ring_buffer *ring,
u32 *result)
{
u32 seqno;
791,7 → 895,7
if (ret)
return ret;
 
seqno = i915_gem_get_seqno(ring->dev);
seqno = i915_gem_next_request_seqno(ring);
 
intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
804,10 → 908,11
}
 
static bool
gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
gen6_ring_get_irq(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
if (!dev->irq_enabled)
return false;
815,76 → 920,48
/* It looks like we need to prevent the gt from suspending while waiting
* for an notifiy irq, otherwise irqs seem to get lost on at least the
* blt/bsd rings on ivb. */
if (IS_GEN7(dev))
gen6_gt_force_wake_get(dev_priv);
 
spin_lock(&ring->irq_lock);
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (ring->irq_refcount++ == 0) {
ring->irq_mask &= ~rflag;
I915_WRITE_IMR(ring, ring->irq_mask);
ironlake_enable_irq(dev_priv, gflag);
if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
I915_WRITE_IMR(ring, ~(ring->irq_enable_mask |
GEN6_RENDER_L3_PARITY_ERROR));
else
I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
dev_priv->gt_irq_mask &= ~ring->irq_enable_mask;
I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
POSTING_READ(GTIMR);
}
spin_unlock(&ring->irq_lock);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
return true;
}
 
static void
gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
gen6_ring_put_irq(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
unsigned long flags;
 
spin_lock(&ring->irq_lock);
spin_lock_irqsave(&dev_priv->irq_lock, flags);
if (--ring->irq_refcount == 0) {
ring->irq_mask |= rflag;
I915_WRITE_IMR(ring, ring->irq_mask);
ironlake_disable_irq(dev_priv, gflag);
if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
else
I915_WRITE_IMR(ring, ~0);
dev_priv->gt_irq_mask |= ring->irq_enable_mask;
I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
POSTING_READ(GTIMR);
}
spin_unlock(&ring->irq_lock);
spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
if (IS_GEN7(dev))
gen6_gt_force_wake_put(dev_priv);
}
 
static bool
bsd_ring_get_irq(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
 
if (!dev->irq_enabled)
return false;
 
spin_lock(&ring->irq_lock);
if (ring->irq_refcount++ == 0) {
if (IS_G4X(dev))
i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
else
ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
}
spin_unlock(&ring->irq_lock);
 
return true;
}
static void
bsd_ring_put_irq(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
 
spin_lock(&ring->irq_lock);
if (--ring->irq_refcount == 0) {
if (IS_G4X(dev))
i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
else
ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
}
spin_unlock(&ring->irq_lock);
}
 
static int
ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
i965_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length)
{
int ret;
 
893,7 → 970,8
return ret;
 
intel_ring_emit(ring,
MI_BATCH_BUFFER_START | (2 << 6) |
MI_BATCH_BUFFER_START |
MI_BATCH_GTT |
MI_BATCH_NON_SECURE_I965);
intel_ring_emit(ring, offset);
intel_ring_advance(ring);
902,13 → 980,11
}
 
static int
render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
i830_dispatch_execbuffer(struct intel_ring_buffer *ring,
u32 offset, u32 len)
{
struct drm_device *dev = ring->dev;
int ret;
 
if (IS_I830(dev) || IS_845G(dev)) {
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
917,22 → 993,23
intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
intel_ring_emit(ring, offset + len - 8);
intel_ring_emit(ring, 0);
} else {
intel_ring_advance(ring);
 
return 0;
}
 
static int
i915_dispatch_execbuffer(struct intel_ring_buffer *ring,
u32 offset, u32 len)
{
int ret;
 
ret = intel_ring_begin(ring, 2);
if (ret)
return ret;
 
if (INTEL_INFO(dev)->gen >= 4) {
intel_ring_emit(ring,
MI_BATCH_BUFFER_START | (2 << 6) |
MI_BATCH_NON_SECURE_I965);
intel_ring_emit(ring, offset);
} else {
intel_ring_emit(ring,
MI_BATCH_BUFFER_START | (2 << 6));
intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE);
}
}
intel_ring_advance(ring);
 
return 0;
940,7 → 1017,6
 
static void cleanup_status_page(struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = ring->dev->dev_private;
struct drm_i915_gem_object *obj;
 
obj = ring->status_page.obj;
947,18 → 1023,15
if (obj == NULL)
return;
 
kunmap(obj->pages[0]);
// kunmap(sg_page(obj->pages->sgl));
i915_gem_object_unpin(obj);
drm_gem_object_unreference(&obj->base);
ring->status_page.obj = NULL;
 
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
}
 
static int init_status_page(struct intel_ring_buffer *ring)
{
struct drm_device *dev = ring->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
int ret;
 
971,15 → 1044,15
 
i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
ret = i915_gem_object_pin(obj, 4096, true);
ret = i915_gem_object_pin(obj, 4096, true, false);
if (ret != 0) {
goto err_unref;
}
 
ring->status_page.gfx_addr = obj->gtt_offset;
ring->status_page.page_addr = (void*)MapIoMem((addr_t)obj->pages[0], 4096, PG_SW);
ring->status_page.page_addr = (void*)MapIoMem(obj->pages.page[0],4096,PG_SW);
if (ring->status_page.page_addr == NULL) {
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
ret = -ENOMEM;
goto err_unpin;
}
ring->status_page.obj = obj;
999,20 → 1072,19
return ret;
}
 
int intel_init_ring_buffer(struct drm_device *dev,
static int intel_init_ring_buffer(struct drm_device *dev,
struct intel_ring_buffer *ring)
{
struct drm_i915_gem_object *obj;
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
 
ring->dev = dev;
INIT_LIST_HEAD(&ring->active_list);
INIT_LIST_HEAD(&ring->request_list);
INIT_LIST_HEAD(&ring->gpu_write_list);
ring->size = 32 * PAGE_SIZE;
 
init_waitqueue_head(&ring->irq_queue);
spin_lock_init(&ring->irq_lock);
ring->irq_mask = ~0;
 
if (I915_NEED_GFX_HWS(dev)) {
ret = init_status_page(ring);
1029,27 → 1101,23
 
ring->obj = obj;
 
ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
ret = i915_gem_object_pin(obj, PAGE_SIZE, true, false);
if (ret)
goto err_unref;
 
ring->map.size = ring->size;
ring->map.offset = get_bus_addr() + obj->gtt_offset;
ring->map.type = 0;
ring->map.flags = 0;
ring->map.mtrr = 0;
ret = i915_gem_object_set_to_gtt_domain(obj, true);
if (ret)
goto err_unpin;
 
// drm_core_ioremap_wc(&ring->map, dev);
 
ring->map.handle = ioremap(ring->map.offset, ring->map.size);
 
if (ring->map.handle == NULL) {
ring->virtual_start =
ioremap(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset,
ring->size);
if (ring->virtual_start == NULL) {
DRM_ERROR("Failed to map ringbuffer.\n");
ret = -EINVAL;
goto err_unpin;
}
 
ring->virtual_start = ring->map.handle;
ret = ring->init(ring);
if (ret)
goto err_unmap;
1059,7 → 1127,7
* of the buffer.
*/
ring->effective_size = ring->size;
if (IS_I830(ring->dev))
if (IS_I830(ring->dev) || IS_845G(ring->dev))
ring->effective_size -= 128;
 
return 0;
1107,7 → 1175,7
 
static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
{
unsigned int *virt;
uint32_t __iomem *virt;
int rem = ring->size - ring->tail;
 
ENTER();
1118,12 → 1186,10
return ret;
}
 
virt = (unsigned int *)(ring->virtual_start + ring->tail);
rem /= 8;
while (rem--) {
*virt++ = MI_NOOP;
*virt++ = MI_NOOP;
}
virt = ring->virtual_start + ring->tail;
rem /= 4;
while (rem--)
iowrite32(MI_NOOP, virt++);
 
ring->tail = 0;
ring->space = ring_space(ring);
1132,26 → 1198,93
return 0;
}
 
int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
static int intel_ring_wait_seqno(struct intel_ring_buffer *ring, u32 seqno)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long end;
u32 head;
int ret;
 
/* If the reported head position has wrapped or hasn't advanced,
* fallback to the slow and accurate path.
*/
head = intel_read_status_page(ring, 4);
if (head > ring->head) {
ring->head = head;
ret = i915_wait_seqno(ring, seqno);
if (!ret)
i915_gem_retire_requests_ring(ring);
 
return ret;
}
 
static int intel_ring_wait_request(struct intel_ring_buffer *ring, int n)
{
struct drm_i915_gem_request *request;
u32 seqno = 0;
int ret;
 
i915_gem_retire_requests_ring(ring);
 
if (ring->last_retired_head != -1) {
ring->head = ring->last_retired_head;
ring->last_retired_head = -1;
ring->space = ring_space(ring);
if (ring->space >= n)
return 0;
}
 
list_for_each_entry(request, &ring->request_list, list) {
int space;
 
end = jiffies + 3 * HZ;
if (request->tail == -1)
continue;
 
space = request->tail - (ring->tail + 8);
if (space < 0)
space += ring->size;
if (space >= n) {
seqno = request->seqno;
break;
}
 
/* Consume this request in case we need more space than
* is available and so need to prevent a race between
* updating last_retired_head and direct reads of
* I915_RING_HEAD. It also provides a nice sanity check.
*/
request->tail = -1;
}
 
if (seqno == 0)
return -ENOSPC;
 
ret = intel_ring_wait_seqno(ring, seqno);
if (ret)
return ret;
 
if (WARN_ON(ring->last_retired_head == -1))
return -ENOSPC;
 
ring->head = ring->last_retired_head;
ring->last_retired_head = -1;
ring->space = ring_space(ring);
if (WARN_ON(ring->space < n))
return -ENOSPC;
 
return 0;
}
 
int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
{
struct drm_device *dev = ring->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long end;
int ret;
 
ret = intel_ring_wait_request(ring, n);
if (ret != -ENOSPC)
return ret;
 
 
/* With GEM the hangcheck timer should kick us out of the loop,
* leaving it early runs the risk of corrupting GEM state (due
* to running on almost untested codepaths). But on resume
* timers don't work yet, so prevent a complete hang in that
* case by choosing an insanely large timeout. */
end = GetTimerTicks() + 60 * HZ;
 
do {
ring->head = I915_READ_HEAD(ring);
ring->space = ring_space(ring);
1161,9 → 1294,11
}
 
msleep(1);
if (atomic_read(&dev_priv->mm.wedged))
return -EAGAIN;
} while (!time_after(jiffies, end));
 
ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible);
if (ret)
return ret;
} while (!time_after(GetTimerTicks(), end));
trace_i915_ring_wait_end(ring);
return -EBUSY;
}
1171,12 → 1306,13
int intel_ring_begin(struct intel_ring_buffer *ring,
int num_dwords)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
drm_i915_private_t *dev_priv = ring->dev->dev_private;
int n = 4*num_dwords;
int ret;
 
if (unlikely(atomic_read(&dev_priv->mm.wedged)))
return -EIO;
ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible);
if (ret)
return ret;
 
if (unlikely(ring->tail + n > ring->effective_size)) {
ret = intel_wrap_ring_buffer(ring);
1196,49 → 1332,15
 
void intel_ring_advance(struct intel_ring_buffer *ring)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
 
ring->tail &= ring->size - 1;
if (dev_priv->stop_rings & intel_ring_flag(ring))
return;
ring->write_tail(ring, ring->tail);
}
 
static const struct intel_ring_buffer render_ring = {
.name = "render ring",
.id = RING_RENDER,
.mmio_base = RENDER_RING_BASE,
.size = 32 * PAGE_SIZE,
.init = init_render_ring,
.write_tail = ring_write_tail,
.flush = render_ring_flush,
.add_request = render_ring_add_request,
.get_seqno = ring_get_seqno,
.irq_get = render_ring_get_irq,
.irq_put = render_ring_put_irq,
.dispatch_execbuffer = render_ring_dispatch_execbuffer,
// .cleanup = render_ring_cleanup,
.sync_to = render_ring_sync_to,
.semaphore_register = {MI_SEMAPHORE_SYNC_INVALID,
MI_SEMAPHORE_SYNC_RV,
MI_SEMAPHORE_SYNC_RB},
.signal_mbox = {GEN6_VRSYNC, GEN6_BRSYNC},
};
 
/* ring buffer for bit-stream decoder */
 
static const struct intel_ring_buffer bsd_ring = {
.name = "bsd ring",
.id = RING_BSD,
.mmio_base = BSD_RING_BASE,
.size = 32 * PAGE_SIZE,
.init = init_ring_common,
.write_tail = ring_write_tail,
.flush = bsd_ring_flush,
.add_request = ring_add_request,
.get_seqno = ring_get_seqno,
.irq_get = bsd_ring_get_irq,
.irq_put = bsd_ring_put_irq,
.dispatch_execbuffer = ring_dispatch_execbuffer,
};
 
 
static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring,
u32 value)
{
1245,20 → 1347,31
drm_i915_private_t *dev_priv = ring->dev->dev_private;
 
/* Every tail move must follow the sequence below */
 
/* Disable notification that the ring is IDLE. The GT
* will then assume that it is busy and bring it out of rc6.
*/
I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
I915_WRITE(GEN6_BSD_RNCID, 0x0);
_MASKED_BIT_ENABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
 
/* Clear the context id. Here be magic! */
I915_WRITE64(GEN6_BSD_RNCID, 0x0);
 
/* Wait for the ring not to be idle, i.e. for it to wake up. */
if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
GEN6_BSD_SLEEP_INDICATOR) == 0,
50))
DRM_ERROR("timed out waiting for IDLE Indicator\n");
DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
 
/* Now that the ring is fully powered up, update the tail */
I915_WRITE_TAIL(ring, value);
POSTING_READ(RING_TAIL(ring->mmio_base));
 
/* Let the ring send IDLE messages to the GT again,
* and so let it sleep to conserve power when idle.
*/
I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
_MASKED_BIT_DISABLE(GEN6_BSD_SLEEP_MSG_DISABLE));
}
 
static int gen6_ring_flush(struct intel_ring_buffer *ring,
1300,148 → 1413,8
return 0;
}
 
static bool
gen6_render_ring_get_irq(struct intel_ring_buffer *ring)
{
return gen6_ring_get_irq(ring,
GT_USER_INTERRUPT,
GEN6_RENDER_USER_INTERRUPT);
}
 
static void
gen6_render_ring_put_irq(struct intel_ring_buffer *ring)
{
return gen6_ring_put_irq(ring,
GT_USER_INTERRUPT,
GEN6_RENDER_USER_INTERRUPT);
}
 
static bool
gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring)
{
return gen6_ring_get_irq(ring,
GT_GEN6_BSD_USER_INTERRUPT,
GEN6_BSD_USER_INTERRUPT);
}
 
static void
gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring)
{
return gen6_ring_put_irq(ring,
GT_GEN6_BSD_USER_INTERRUPT,
GEN6_BSD_USER_INTERRUPT);
}
 
/* ring buffer for Video Codec for Gen6+ */
static const struct intel_ring_buffer gen6_bsd_ring = {
.name = "gen6 bsd ring",
.id = RING_BSD,
.mmio_base = GEN6_BSD_RING_BASE,
.size = 32 * PAGE_SIZE,
.init = init_ring_common,
.write_tail = gen6_bsd_ring_write_tail,
.flush = gen6_ring_flush,
.add_request = gen6_add_request,
.get_seqno = gen6_ring_get_seqno,
.irq_get = gen6_bsd_ring_get_irq,
.irq_put = gen6_bsd_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
.sync_to = gen6_bsd_ring_sync_to,
.semaphore_register = {MI_SEMAPHORE_SYNC_VR,
MI_SEMAPHORE_SYNC_INVALID,
MI_SEMAPHORE_SYNC_VB},
.signal_mbox = {GEN6_RVSYNC, GEN6_BVSYNC},
};
 
/* Blitter support (SandyBridge+) */
 
static bool
blt_ring_get_irq(struct intel_ring_buffer *ring)
{
return gen6_ring_get_irq(ring,
GT_BLT_USER_INTERRUPT,
GEN6_BLITTER_USER_INTERRUPT);
}
 
static void
blt_ring_put_irq(struct intel_ring_buffer *ring)
{
gen6_ring_put_irq(ring,
GT_BLT_USER_INTERRUPT,
GEN6_BLITTER_USER_INTERRUPT);
}
 
 
/* Workaround for some stepping of SNB,
* each time when BLT engine ring tail moved,
* the first command in the ring to be parsed
* should be MI_BATCH_BUFFER_START
*/
#define NEED_BLT_WORKAROUND(dev) \
(IS_GEN6(dev) && (dev->pdev->revision < 8))
 
static inline struct drm_i915_gem_object *
to_blt_workaround(struct intel_ring_buffer *ring)
{
return ring->private;
}
 
static int blt_ring_init(struct intel_ring_buffer *ring)
{
if (NEED_BLT_WORKAROUND(ring->dev)) {
struct drm_i915_gem_object *obj;
u32 *ptr;
int ret;
 
obj = i915_gem_alloc_object(ring->dev, 4096);
if (obj == NULL)
return -ENOMEM;
 
ret = i915_gem_object_pin(obj, 4096, true);
if (ret) {
drm_gem_object_unreference(&obj->base);
return ret;
}
 
ptr = (void*)MapIoMem((addr_t)obj->pages[0], 4096, PG_SW);
obj->mapped = ptr;
 
*ptr++ = MI_BATCH_BUFFER_END;
*ptr++ = MI_NOOP;
 
ret = i915_gem_object_set_to_gtt_domain(obj, false);
if (ret) {
i915_gem_object_unpin(obj);
drm_gem_object_unreference(&obj->base);
FreeKernelSpace(ptr);
obj->mapped = NULL;
return ret;
}
FreeKernelSpace(ptr);
obj->mapped = NULL;
 
ring->private = obj;
}
 
return init_ring_common(ring);
}
 
static int blt_ring_begin(struct intel_ring_buffer *ring,
int num_dwords)
{
if (ring->private) {
int ret = intel_ring_begin(ring, num_dwords+2);
if (ret)
return ret;
 
intel_ring_emit(ring, MI_BATCH_BUFFER_START);
intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset);
 
return 0;
} else
return intel_ring_begin(ring, 4);
}
 
static int blt_ring_flush(struct intel_ring_buffer *ring,
u32 invalidate, u32 flush)
{
1448,7 → 1421,7
uint32_t cmd;
int ret;
 
ret = blt_ring_begin(ring, 4);
ret = intel_ring_begin(ring, 4);
if (ret)
return ret;
 
1463,54 → 1436,66
return 0;
}
 
static void blt_ring_cleanup(struct intel_ring_buffer *ring)
{
if (!ring->private)
return;
 
i915_gem_object_unpin(ring->private);
drm_gem_object_unreference(ring->private);
ring->private = NULL;
}
 
static const struct intel_ring_buffer gen6_blt_ring = {
.name = "blt ring",
.id = RING_BLT,
.mmio_base = BLT_RING_BASE,
.size = 32 * PAGE_SIZE,
.init = blt_ring_init,
.write_tail = ring_write_tail,
.flush = blt_ring_flush,
.add_request = gen6_add_request,
.get_seqno = gen6_ring_get_seqno,
.irq_get = blt_ring_get_irq,
.irq_put = blt_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
// .cleanup = blt_ring_cleanup,
.sync_to = gen6_blt_ring_sync_to,
.semaphore_register = {MI_SEMAPHORE_SYNC_BR,
MI_SEMAPHORE_SYNC_BV,
MI_SEMAPHORE_SYNC_INVALID},
.signal_mbox = {GEN6_RBSYNC, GEN6_VBSYNC},
};
 
int intel_init_render_ring_buffer(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
 
*ring = render_ring;
ring->name = "render ring";
ring->id = RCS;
ring->mmio_base = RENDER_RING_BASE;
 
if (INTEL_INFO(dev)->gen >= 6) {
ring->add_request = gen6_add_request;
ring->flush = gen7_render_ring_flush;
if (INTEL_INFO(dev)->gen == 6)
ring->flush = gen6_render_ring_flush;
ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq;
ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq;
ring->irq_enable_mask = GT_USER_INTERRUPT;
ring->get_seqno = gen6_ring_get_seqno;
ring->sync_to = gen6_ring_sync;
ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID;
ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV;
ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_RB;
ring->signal_mbox[0] = GEN6_VRSYNC;
ring->signal_mbox[1] = GEN6_BRSYNC;
} else if (IS_GEN5(dev)) {
ring->add_request = pc_render_add_request;
ring->flush = gen4_render_ring_flush;
ring->get_seqno = pc_render_get_seqno;
ring->irq_get = gen5_ring_get_irq;
ring->irq_put = gen5_ring_put_irq;
ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY;
} else {
ring->add_request = i9xx_add_request;
if (INTEL_INFO(dev)->gen < 4)
ring->flush = gen2_render_ring_flush;
else
ring->flush = gen4_render_ring_flush;
ring->get_seqno = ring_get_seqno;
if (IS_GEN2(dev)) {
ring->irq_get = i8xx_ring_get_irq;
ring->irq_put = i8xx_ring_put_irq;
} else {
ring->irq_get = i9xx_ring_get_irq;
ring->irq_put = i9xx_ring_put_irq;
}
ring->irq_enable_mask = I915_USER_INTERRUPT;
}
ring->write_tail = ring_write_tail;
if (INTEL_INFO(dev)->gen >= 6)
ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
else if (INTEL_INFO(dev)->gen >= 4)
ring->dispatch_execbuffer = i965_dispatch_execbuffer;
else if (IS_I830(dev) || IS_845G(dev))
ring->dispatch_execbuffer = i830_dispatch_execbuffer;
else
ring->dispatch_execbuffer = i915_dispatch_execbuffer;
ring->init = init_render_ring;
ring->cleanup = render_ring_cleanup;
 
 
if (!I915_NEED_GFX_HWS(dev)) {
ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
memset(ring->status_page.page_addr, 0, PAGE_SIZE);
1525,11 → 1510,47
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = &dev_priv->ring[VCS];
 
if (IS_GEN6(dev) || IS_GEN7(dev))
*ring = gen6_bsd_ring;
else
*ring = bsd_ring;
ring->name = "bsd ring";
ring->id = VCS;
 
ring->write_tail = ring_write_tail;
if (IS_GEN6(dev) || IS_GEN7(dev)) {
ring->mmio_base = GEN6_BSD_RING_BASE;
/* gen6 bsd needs a special wa for tail updates */
if (IS_GEN6(dev))
ring->write_tail = gen6_bsd_ring_write_tail;
ring->flush = gen6_ring_flush;
ring->add_request = gen6_add_request;
ring->get_seqno = gen6_ring_get_seqno;
ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT;
ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq;
ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
ring->sync_to = gen6_ring_sync;
ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_VR;
ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_INVALID;
ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_VB;
ring->signal_mbox[0] = GEN6_RVSYNC;
ring->signal_mbox[1] = GEN6_BVSYNC;
} else {
ring->mmio_base = BSD_RING_BASE;
ring->flush = bsd_ring_flush;
ring->add_request = i9xx_add_request;
ring->get_seqno = ring_get_seqno;
if (IS_GEN5(dev)) {
ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
ring->irq_get = gen5_ring_get_irq;
ring->irq_put = gen5_ring_put_irq;
} else {
ring->irq_enable_mask = I915_BSD_USER_INTERRUPT;
ring->irq_get = i9xx_ring_get_irq;
ring->irq_put = i9xx_ring_put_irq;
}
ring->dispatch_execbuffer = i965_dispatch_execbuffer;
}
ring->init = init_ring_common;
 
 
return intel_init_ring_buffer(dev, ring);
}
 
1538,7 → 1559,63
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_ring_buffer *ring = &dev_priv->ring[BCS];
 
*ring = gen6_blt_ring;
ring->name = "blitter ring";
ring->id = BCS;
 
ring->mmio_base = BLT_RING_BASE;
ring->write_tail = ring_write_tail;
ring->flush = blt_ring_flush;
ring->add_request = gen6_add_request;
ring->get_seqno = gen6_ring_get_seqno;
ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT;
ring->irq_get = gen6_ring_get_irq;
ring->irq_put = gen6_ring_put_irq;
ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
ring->sync_to = gen6_ring_sync;
ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_BR;
ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_BV;
ring->semaphore_register[2] = MI_SEMAPHORE_SYNC_INVALID;
ring->signal_mbox[0] = GEN6_RBSYNC;
ring->signal_mbox[1] = GEN6_VBSYNC;
ring->init = init_ring_common;
 
return intel_init_ring_buffer(dev, ring);
}
 
int
intel_ring_flush_all_caches(struct intel_ring_buffer *ring)
{
int ret;
 
if (!ring->gpu_caches_dirty)
return 0;
 
ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS);
if (ret)
return ret;
 
trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS);
 
ring->gpu_caches_dirty = false;
return 0;
}
 
int
intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring)
{
uint32_t flush_domains;
int ret;
 
flush_domains = 0;
if (ring->gpu_caches_dirty)
flush_domains = I915_GEM_GPU_DOMAINS;
 
ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
if (ret)
return ret;
 
trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
 
ring->gpu_caches_dirty = false;
return 0;
}