33,14 → 33,24 |
#include "i915_trace.h" |
#include "intel_drv.h" |
|
/* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill, |
* but keeps the logic simple. Indeed, the whole purpose of this macro is just |
* to give some inclination as to some of the magic values used in the various |
* workarounds! |
*/ |
#define CACHELINE_BYTES 64 |
bool |
intel_ring_initialized(struct intel_engine_cs *ring) |
{ |
struct drm_device *dev = ring->dev; |
|
static inline int __ring_space(int head, int tail, int size) |
if (!dev) |
return false; |
|
if (i915.enable_execlists) { |
struct intel_context *dctx = ring->default_context; |
struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf; |
|
return ringbuf->obj; |
} else |
return ring->buffer && ring->buffer->obj; |
} |
|
int __intel_ring_space(int head, int tail, int size) |
{ |
int space = head - (tail + I915_RING_FREE_SPACE); |
if (space < 0) |
48,12 → 58,13 |
return space; |
} |
|
static inline int ring_space(struct intel_ringbuffer *ringbuf) |
int intel_ring_space(struct intel_ringbuffer *ringbuf) |
{ |
return __ring_space(ringbuf->head & HEAD_ADDR, ringbuf->tail, ringbuf->size); |
return __intel_ring_space(ringbuf->head & HEAD_ADDR, |
ringbuf->tail, ringbuf->size); |
} |
|
static bool intel_ring_stopped(struct intel_engine_cs *ring) |
bool intel_ring_stopped(struct intel_engine_cs *ring) |
{ |
struct drm_i915_private *dev_priv = ring->dev->dev_private; |
return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring); |
351,6 → 362,7 |
flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; |
flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; |
flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; |
flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; |
/* |
* TLB invalidate requires a post-sync write. |
*/ |
357,6 → 369,8 |
flags |= PIPE_CONTROL_QW_WRITE; |
flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; |
|
flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; |
|
/* 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. */ |
433,7 → 447,14 |
return ret; |
} |
|
return gen8_emit_pipe_control(ring, flags, scratch_addr); |
ret = gen8_emit_pipe_control(ring, flags, scratch_addr); |
if (ret) |
return ret; |
|
if (!invalidate_domains && flush_domains) |
return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); |
|
return 0; |
} |
|
static void ring_write_tail(struct intel_engine_cs *ring, |
476,8 → 497,13 |
|
if (!IS_GEN2(ring->dev)) { |
I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); |
if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { |
if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { |
DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); |
/* Sometimes we observe that the idle flag is not |
* set even though the ring is empty. So double |
* check before giving up. |
*/ |
if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring)) |
return false; |
} |
} |
540,6 → 566,14 |
* also enforces ordering), otherwise the hw might lose the new ring |
* register values. */ |
I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); |
|
/* WaClearRingBufHeadRegAtInit:ctg,elk */ |
if (I915_READ_HEAD(ring)) |
DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", |
ring->name, I915_READ_HEAD(ring)); |
I915_WRITE_HEAD(ring, 0); |
(void)I915_READ_HEAD(ring); |
|
I915_WRITE_CTL(ring, |
((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) |
| RING_VALID); |
558,10 → 592,9 |
goto out; |
} |
|
|
ringbuf->head = I915_READ_HEAD(ring); |
ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; |
ringbuf->space = ring_space(ringbuf); |
ringbuf->space = intel_ring_space(ringbuf); |
ringbuf->last_retired_head = -1; |
|
memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); |
572,9 → 605,26 |
return ret; |
} |
|
static int |
init_pipe_control(struct intel_engine_cs *ring) |
void |
intel_fini_pipe_control(struct intel_engine_cs *ring) |
{ |
struct drm_device *dev = ring->dev; |
|
if (ring->scratch.obj == NULL) |
return; |
|
if (INTEL_INFO(dev)->gen >= 5) { |
kunmap(sg_page(ring->scratch.obj->pages->sgl)); |
i915_gem_object_ggtt_unpin(ring->scratch.obj); |
} |
|
drm_gem_object_unreference(&ring->scratch.obj->base); |
ring->scratch.obj = NULL; |
} |
|
int |
intel_init_pipe_control(struct intel_engine_cs *ring) |
{ |
int ret; |
|
if (ring->scratch.obj) |
596,7 → 646,7 |
goto err_unref; |
|
ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); |
ring->scratch.cpu_page = (void*)MapIoMem((addr_t)sg_page(ring->scratch.obj->pages->sgl),4096, PG_SW|0x100); |
ring->scratch.cpu_page = kmap(sg_page(ring->scratch.obj->pages->sgl)); |
if (ring->scratch.cpu_page == NULL) { |
ret = -ENOMEM; |
goto err_unpin; |
614,6 → 664,170 |
return ret; |
} |
|
static int intel_ring_workarounds_emit(struct intel_engine_cs *ring, |
struct intel_context *ctx) |
{ |
int ret, i; |
struct drm_device *dev = ring->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct i915_workarounds *w = &dev_priv->workarounds; |
|
if (WARN_ON(w->count == 0)) |
return 0; |
|
ring->gpu_caches_dirty = true; |
ret = intel_ring_flush_all_caches(ring); |
if (ret) |
return ret; |
|
ret = intel_ring_begin(ring, (w->count * 2 + 2)); |
if (ret) |
return ret; |
|
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); |
for (i = 0; i < w->count; i++) { |
intel_ring_emit(ring, w->reg[i].addr); |
intel_ring_emit(ring, w->reg[i].value); |
} |
intel_ring_emit(ring, MI_NOOP); |
|
intel_ring_advance(ring); |
|
ring->gpu_caches_dirty = true; |
ret = intel_ring_flush_all_caches(ring); |
if (ret) |
return ret; |
|
DRM_DEBUG_DRIVER("Number of Workarounds emitted: %d\n", w->count); |
|
return 0; |
} |
|
static int wa_add(struct drm_i915_private *dev_priv, |
const u32 addr, const u32 mask, const u32 val) |
{ |
const u32 idx = dev_priv->workarounds.count; |
|
if (WARN_ON(idx >= I915_MAX_WA_REGS)) |
return -ENOSPC; |
|
dev_priv->workarounds.reg[idx].addr = addr; |
dev_priv->workarounds.reg[idx].value = val; |
dev_priv->workarounds.reg[idx].mask = mask; |
|
dev_priv->workarounds.count++; |
|
return 0; |
} |
|
#define WA_REG(addr, mask, val) { \ |
const int r = wa_add(dev_priv, (addr), (mask), (val)); \ |
if (r) \ |
return r; \ |
} |
|
#define WA_SET_BIT_MASKED(addr, mask) \ |
WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) |
|
#define WA_CLR_BIT_MASKED(addr, mask) \ |
WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) |
|
#define WA_SET_FIELD_MASKED(addr, mask, value) \ |
WA_REG(addr, mask, _MASKED_FIELD(mask, value)) |
|
#define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) |
#define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) |
|
#define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) |
|
static int bdw_init_workarounds(struct intel_engine_cs *ring) |
{ |
struct drm_device *dev = ring->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
/* WaDisablePartialInstShootdown:bdw */ |
/* WaDisableThreadStallDopClockGating:bdw (pre-production) */ |
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, |
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | |
STALL_DOP_GATING_DISABLE); |
|
/* WaDisableDopClockGating:bdw */ |
WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, |
DOP_CLOCK_GATING_DISABLE); |
|
WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, |
GEN8_SAMPLER_POWER_BYPASS_DIS); |
|
/* Use Force Non-Coherent whenever executing a 3D context. This is a |
* workaround for for a possible hang in the unlikely event a TLB |
* invalidation occurs during a PSD flush. |
*/ |
/* WaDisableFenceDestinationToSLM:bdw (GT3 pre-production) */ |
WA_SET_BIT_MASKED(HDC_CHICKEN0, |
HDC_FORCE_NON_COHERENT | |
(IS_BDW_GT3(dev) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); |
|
/* Wa4x4STCOptimizationDisable:bdw */ |
WA_SET_BIT_MASKED(CACHE_MODE_1, |
GEN8_4x4_STC_OPTIMIZATION_DISABLE); |
|
/* |
* BSpec recommends 8x4 when MSAA is used, |
* however in practice 16x4 seems fastest. |
* |
* Note that PS/WM thread counts depend on the WIZ hashing |
* disable bit, which we don't touch here, but it's good |
* to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). |
*/ |
WA_SET_FIELD_MASKED(GEN7_GT_MODE, |
GEN6_WIZ_HASHING_MASK, |
GEN6_WIZ_HASHING_16x4); |
|
return 0; |
} |
|
static int chv_init_workarounds(struct intel_engine_cs *ring) |
{ |
struct drm_device *dev = ring->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
/* WaDisablePartialInstShootdown:chv */ |
/* WaDisableThreadStallDopClockGating:chv */ |
WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, |
PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE | |
STALL_DOP_GATING_DISABLE); |
|
/* Use Force Non-Coherent whenever executing a 3D context. This is a |
* workaround for a possible hang in the unlikely event a TLB |
* invalidation occurs during a PSD flush. |
*/ |
/* WaForceEnableNonCoherent:chv */ |
/* WaHdcDisableFetchWhenMasked:chv */ |
WA_SET_BIT_MASKED(HDC_CHICKEN0, |
HDC_FORCE_NON_COHERENT | |
HDC_DONOT_FETCH_MEM_WHEN_MASKED); |
|
return 0; |
} |
|
int init_workarounds_ring(struct intel_engine_cs *ring) |
{ |
struct drm_device *dev = ring->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
|
WARN_ON(ring->id != RCS); |
|
dev_priv->workarounds.count = 0; |
|
if (IS_BROADWELL(dev)) |
return bdw_init_workarounds(ring); |
|
if (IS_CHERRYVIEW(dev)) |
return chv_init_workarounds(ring); |
|
return 0; |
} |
|
static int init_render_ring(struct intel_engine_cs *ring) |
{ |
struct drm_device *dev = ring->dev; |
632,7 → 846,7 |
* |
* WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv |
*/ |
if (INTEL_INFO(dev)->gen >= 6) |
if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 9) |
I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); |
|
/* Required for the hardware to program scanline values for waiting */ |
648,7 → 862,7 |
_MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); |
|
if (INTEL_INFO(dev)->gen >= 5) { |
ret = init_pipe_control(ring); |
ret = intel_init_pipe_control(ring); |
if (ret) |
return ret; |
} |
669,7 → 883,7 |
if (HAS_L3_DPF(dev)) |
I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); |
|
return ret; |
return init_workarounds_ring(ring); |
} |
|
static void render_ring_cleanup(struct intel_engine_cs *ring) |
683,18 → 897,9 |
dev_priv->semaphore_obj = NULL; |
} |
|
if (ring->scratch.obj == NULL) |
return; |
|
if (INTEL_INFO(dev)->gen >= 5) { |
// kunmap(sg_page(ring->scratch.obj->pages->sgl)); |
i915_gem_object_ggtt_unpin(ring->scratch.obj); |
intel_fini_pipe_control(ring); |
} |
|
drm_gem_object_unreference(&ring->scratch.obj->base); |
ring->scratch.obj = NULL; |
} |
|
static int gen8_rcs_signal(struct intel_engine_cs *signaller, |
unsigned int num_dwords) |
{ |
1015,7 → 1220,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
if (WARN_ON(!intel_irqs_enabled(dev_priv))) |
return false; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1046,7 → 1251,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
if (!intel_irqs_enabled(dev_priv)) |
return false; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1083,7 → 1288,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
if (!intel_irqs_enabled(dev_priv)) |
return false; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1217,7 → 1422,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
if (WARN_ON(!intel_irqs_enabled(dev_priv))) |
return false; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1260,7 → 1465,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
if (WARN_ON(!intel_irqs_enabled(dev_priv))) |
return false; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1280,9 → 1485,6 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
return; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
if (--ring->irq_refcount == 0) { |
I915_WRITE_IMR(ring, ~0); |
1298,7 → 1500,7 |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
if (!dev->irq_enabled) |
if (WARN_ON(!intel_irqs_enabled(dev_priv))) |
return false; |
|
spin_lock_irqsave(&dev_priv->irq_lock, flags); |
1449,7 → 1651,7 |
if (obj == NULL) |
return; |
|
// kunmap(sg_page(obj->pages->sgl)); |
kunmap(sg_page(obj->pages->sgl)); |
i915_gem_object_ggtt_unpin(obj); |
drm_gem_object_unreference(&obj->base); |
ring->status_page.obj = NULL; |
1497,7 → 1699,7 |
} |
|
ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); |
ring->status_page.page_addr = (void*)MapIoMem((addr_t)sg_page(obj->pages->sgl),4096,PG_SW|0x100); |
ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); |
memset(ring->status_page.page_addr, 0, PAGE_SIZE); |
|
DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", |
1523,27 → 1725,51 |
return 0; |
} |
|
static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) |
void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf) |
{ |
if (!ringbuf->obj) |
return; |
|
iounmap(ringbuf->virtual_start); |
ringbuf->virtual_start = NULL; |
i915_gem_object_ggtt_unpin(ringbuf->obj); |
drm_gem_object_unreference(&ringbuf->obj->base); |
ringbuf->obj = NULL; |
} |
|
static int intel_alloc_ringbuffer_obj(struct drm_device *dev, |
int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, |
struct intel_ringbuffer *ringbuf) |
{ |
struct drm_i915_private *dev_priv = to_i915(dev); |
struct drm_i915_gem_object *obj; |
struct drm_i915_gem_object *obj = ringbuf->obj; |
int ret; |
|
if (ringbuf->obj) |
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); |
if (ret) |
return ret; |
|
ret = i915_gem_object_set_to_gtt_domain(obj, true); |
if (ret) { |
i915_gem_object_ggtt_unpin(obj); |
return ret; |
} |
|
ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + |
i915_gem_obj_ggtt_offset(obj), ringbuf->size); |
if (ringbuf->virtual_start == NULL) { |
i915_gem_object_ggtt_unpin(obj); |
return -EINVAL; |
} |
|
return 0; |
} |
|
void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) |
{ |
drm_gem_object_unreference(&ringbuf->obj->base); |
ringbuf->obj = NULL; |
} |
|
int intel_alloc_ringbuffer_obj(struct drm_device *dev, |
struct intel_ringbuffer *ringbuf) |
{ |
struct drm_i915_gem_object *obj; |
|
obj = NULL; |
if (!HAS_LLC(dev)) |
obj = i915_gem_object_create_stolen(dev, ringbuf->size); |
1555,30 → 1781,9 |
/* mark ring buffers as read-only from GPU side by default */ |
obj->gt_ro = 1; |
|
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE); |
if (ret) |
goto err_unref; |
ringbuf->obj = obj; |
|
ret = i915_gem_object_set_to_gtt_domain(obj, true); |
if (ret) |
goto err_unpin; |
|
ringbuf->virtual_start = |
ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj), |
ringbuf->size); |
if (ringbuf->virtual_start == NULL) { |
ret = -EINVAL; |
goto err_unpin; |
} |
|
ringbuf->obj = obj; |
return 0; |
|
err_unpin: |
i915_gem_object_ggtt_unpin(obj); |
err_unref: |
drm_gem_object_unreference(&obj->base); |
return ret; |
} |
|
static int intel_init_ring_buffer(struct drm_device *dev, |
1597,7 → 1802,9 |
ring->dev = dev; |
INIT_LIST_HEAD(&ring->active_list); |
INIT_LIST_HEAD(&ring->request_list); |
INIT_LIST_HEAD(&ring->execlist_queue); |
ringbuf->size = 32 * PAGE_SIZE; |
ringbuf->ring = ring; |
memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); |
|
init_waitqueue_head(&ring->irq_queue); |
1613,12 → 1820,23 |
goto error; |
} |
|
if (ringbuf->obj == NULL) { |
ret = intel_alloc_ringbuffer_obj(dev, ringbuf); |
if (ret) { |
DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret); |
DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", |
ring->name, ret); |
goto error; |
} |
|
ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); |
if (ret) { |
DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n", |
ring->name, ret); |
intel_destroy_ringbuffer_obj(ringbuf); |
goto error; |
} |
} |
|
/* Workaround an erratum on the i830 which causes a hang if |
* the TAIL pointer points to within the last 2 cachelines |
* of the buffer. |
1645,15 → 1863,19 |
|
void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) |
{ |
struct drm_i915_private *dev_priv = to_i915(ring->dev); |
struct intel_ringbuffer *ringbuf = ring->buffer; |
struct drm_i915_private *dev_priv; |
struct intel_ringbuffer *ringbuf; |
|
if (!intel_ring_initialized(ring)) |
return; |
|
dev_priv = to_i915(ring->dev); |
ringbuf = ring->buffer; |
|
intel_stop_ring_buffer(ring); |
WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); |
|
intel_unpin_ringbuffer_obj(ringbuf); |
intel_destroy_ringbuffer_obj(ringbuf); |
ring->preallocated_lazy_request = NULL; |
ring->outstanding_lazy_seqno = 0; |
1680,13 → 1902,14 |
ringbuf->head = ringbuf->last_retired_head; |
ringbuf->last_retired_head = -1; |
|
ringbuf->space = ring_space(ringbuf); |
ringbuf->space = intel_ring_space(ringbuf); |
if (ringbuf->space >= n) |
return 0; |
} |
|
list_for_each_entry(request, &ring->request_list, list) { |
if (__ring_space(request->tail, ringbuf->tail, ringbuf->size) >= n) { |
if (__intel_ring_space(request->tail, ringbuf->tail, |
ringbuf->size) >= n) { |
seqno = request->seqno; |
break; |
} |
1703,7 → 1926,7 |
ringbuf->head = ringbuf->last_retired_head; |
ringbuf->last_retired_head = -1; |
|
ringbuf->space = ring_space(ringbuf); |
ringbuf->space = intel_ring_space(ringbuf); |
return 0; |
} |
|
1732,13 → 1955,12 |
trace_i915_ring_wait_begin(ring); |
do { |
ringbuf->head = I915_READ_HEAD(ring); |
ringbuf->space = ring_space(ringbuf); |
ringbuf->space = intel_ring_space(ringbuf); |
if (ringbuf->space >= n) { |
ret = 0; |
break; |
} |
|
|
msleep(1); |
|
ret = i915_gem_check_wedge(&dev_priv->gpu_error, |
1773,7 → 1995,7 |
iowrite32(MI_NOOP, virt++); |
|
ringbuf->tail = 0; |
ringbuf->space = ring_space(ringbuf); |
ringbuf->space = intel_ring_space(ringbuf); |
|
return 0; |
} |
1978,9 → 2200,7 |
u64 offset, u32 len, |
unsigned flags) |
{ |
struct drm_i915_private *dev_priv = ring->dev->dev_private; |
bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL && |
!(flags & I915_DISPATCH_SECURE); |
bool ppgtt = USES_PPGTT(ring->dev) && !(flags & I915_DISPATCH_SECURE); |
int ret; |
|
ret = intel_ring_begin(ring, 4); |
2009,8 → 2229,9 |
return ret; |
|
intel_ring_emit(ring, |
MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW | |
(flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_HSW)); |
MI_BATCH_BUFFER_START | |
(flags & I915_DISPATCH_SECURE ? |
0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW)); |
/* bit0-7 is the length on GEN6+ */ |
intel_ring_emit(ring, offset); |
intel_ring_advance(ring); |
2045,6 → 2266,7 |
u32 invalidate, u32 flush) |
{ |
struct drm_device *dev = ring->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
uint32_t cmd; |
int ret; |
|
2075,8 → 2297,12 |
} |
intel_ring_advance(ring); |
|
if (IS_GEN7(dev) && !invalidate && flush) |
if (!invalidate && flush) { |
if (IS_GEN7(dev)) |
return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); |
else if (IS_BROADWELL(dev)) |
dev_priv->fbc.need_sw_cache_clean = true; |
} |
|
return 0; |
} |
2109,6 → 2335,8 |
dev_priv->semaphore_obj = obj; |
} |
} |
|
ring->init_context = intel_ring_workarounds_emit; |
ring->add_request = gen6_add_request; |
ring->flush = gen8_render_ring_flush; |
ring->irq_get = gen8_ring_get_irq; |
2218,93 → 2446,6 |
return intel_init_ring_buffer(dev, ring); |
} |
|
#if 0 |
int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_engine_cs *ring = &dev_priv->ring[RCS]; |
struct intel_ringbuffer *ringbuf = ring->buffer; |
int ret; |
|
if (ringbuf == NULL) { |
ringbuf = kzalloc(sizeof(*ringbuf), GFP_KERNEL); |
if (!ringbuf) |
return -ENOMEM; |
ring->buffer = ringbuf; |
} |
|
ring->name = "render ring"; |
ring->id = RCS; |
ring->mmio_base = RENDER_RING_BASE; |
|
if (INTEL_INFO(dev)->gen >= 6) { |
/* non-kms not supported on gen6+ */ |
ret = -ENODEV; |
goto err_ringbuf; |
} |
|
/* Note: gem is not supported on gen5/ilk without kms (the corresponding |
* gem_init ioctl returns with -ENODEV). Hence we do not need to set up |
* the special gen5 functions. */ |
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; |
ring->set_seqno = ring_set_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 >= 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; |
|
ring->dev = dev; |
INIT_LIST_HEAD(&ring->active_list); |
INIT_LIST_HEAD(&ring->request_list); |
|
ringbuf->size = size; |
ringbuf->effective_size = ringbuf->size; |
if (IS_I830(ring->dev) || IS_845G(ring->dev)) |
ringbuf->effective_size -= 2 * CACHELINE_BYTES; |
|
ringbuf->virtual_start = ioremap_wc(start, size); |
if (ringbuf->virtual_start == NULL) { |
DRM_ERROR("can not ioremap virtual address for" |
" ring buffer\n"); |
ret = -ENOMEM; |
goto err_ringbuf; |
} |
|
if (!I915_NEED_GFX_HWS(dev)) { |
ret = init_phys_status_page(ring); |
if (ret) |
goto err_vstart; |
} |
|
return 0; |
|
err_vstart: |
iounmap(ringbuf->virtual_start); |
err_ringbuf: |
kfree(ringbuf); |
ring->buffer = NULL; |
return ret; |
} |
#endif |
|
int intel_init_bsd_ring_buffer(struct drm_device *dev) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |