aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-12-15 04:56:50 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-12-15 05:15:25 -0500
commitc6df541c00e53a4fdff7a130d4365f848075adcc (patch)
tree20c92d7402399e8060d73d23b9d2e81771d174b5 /drivers
parent1b894b59247728b02d6363d458088cf438f5ec92 (diff)
Revert "drm/i915: Avoid using PIPE_CONTROL on Ironlake"
Restore PIPE_CONTROL once again just for Ironlake, as it appears that MI_USER_INTERRUPT does not have the same coherency guarantees, that is on Ironlake the interrupt following a GPU write is not guaranteed to arrive after the write is coherent from the CPU, as it does on the other generations. Reported-by: Zhenyu Wang <zhenyuw@linux.intel.com> Reported-by: Shuang He <shuang.he@intel.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=32402 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c3
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c162
2 files changed, 162 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2ddb98b5c90..e4a2e2c3dbe 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -349,7 +349,7 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
349 READ_BREADCRUMB(dev_priv); 349 READ_BREADCRUMB(dev_priv);
350 } 350 }
351 351
352 if (gt_iir & GT_USER_INTERRUPT) 352 if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY))
353 notify_ring(dev, &dev_priv->ring[RCS]); 353 notify_ring(dev, &dev_priv->ring[RCS]);
354 if (gt_iir & bsd_usr_interrupt) 354 if (gt_iir & bsd_usr_interrupt)
355 notify_ring(dev, &dev_priv->ring[VCS]); 355 notify_ring(dev, &dev_priv->ring[VCS]);
@@ -1558,6 +1558,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
1558 else 1558 else
1559 render_irqs = 1559 render_irqs =
1560 GT_USER_INTERRUPT | 1560 GT_USER_INTERRUPT |
1561 GT_PIPE_NOTIFY |
1561 GT_BSD_USER_INTERRUPT; 1562 GT_BSD_USER_INTERRUPT;
1562 I915_WRITE(GTIER, render_irqs); 1563 I915_WRITE(GTIER, render_irqs);
1563 POSTING_READ(GTIER); 1564 POSTING_READ(GTIER);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index a3fd993e0de..56bc95c056d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -209,6 +209,78 @@ static int init_ring_common(struct intel_ring_buffer *ring)
209 return 0; 209 return 0;
210} 210}
211 211
212/*
213 * 965+ support PIPE_CONTROL commands, which provide finer grained control
214 * over cache flushing.
215 */
216struct pipe_control {
217 struct drm_i915_gem_object *obj;
218 volatile u32 *cpu_page;
219 u32 gtt_offset;
220};
221
222static int
223init_pipe_control(struct intel_ring_buffer *ring)
224{
225 struct pipe_control *pc;
226 struct drm_i915_gem_object *obj;
227 int ret;
228
229 if (ring->private)
230 return 0;
231
232 pc = kmalloc(sizeof(*pc), GFP_KERNEL);
233 if (!pc)
234 return -ENOMEM;
235
236 obj = i915_gem_alloc_object(ring->dev, 4096);
237 if (obj == NULL) {
238 DRM_ERROR("Failed to allocate seqno page\n");
239 ret = -ENOMEM;
240 goto err;
241 }
242 obj->agp_type = AGP_USER_CACHED_MEMORY;
243
244 ret = i915_gem_object_pin(obj, 4096, true);
245 if (ret)
246 goto err_unref;
247
248 pc->gtt_offset = obj->gtt_offset;
249 pc->cpu_page = kmap(obj->pages[0]);
250 if (pc->cpu_page == NULL)
251 goto err_unpin;
252
253 pc->obj = obj;
254 ring->private = pc;
255 return 0;
256
257err_unpin:
258 i915_gem_object_unpin(obj);
259err_unref:
260 drm_gem_object_unreference(&obj->base);
261err:
262 kfree(pc);
263 return ret;
264}
265
266static void
267cleanup_pipe_control(struct intel_ring_buffer *ring)
268{
269 struct pipe_control *pc = ring->private;
270 struct drm_i915_gem_object *obj;
271
272 if (!ring->private)
273 return;
274
275 obj = pc->obj;
276 kunmap(obj->pages[0]);
277 i915_gem_object_unpin(obj);
278 drm_gem_object_unreference(&obj->base);
279
280 kfree(pc);
281 ring->private = NULL;
282}
283
212static int init_render_ring(struct intel_ring_buffer *ring) 284static int init_render_ring(struct intel_ring_buffer *ring)
213{ 285{
214 struct drm_device *dev = ring->dev; 286 struct drm_device *dev = ring->dev;
@@ -222,9 +294,24 @@ static int init_render_ring(struct intel_ring_buffer *ring)
222 I915_WRITE(MI_MODE, mode); 294 I915_WRITE(MI_MODE, mode);
223 } 295 }
224 296
297 if (INTEL_INFO(dev)->gen >= 6) {
298 } else if (IS_GEN5(dev)) {
299 ret = init_pipe_control(ring);
300 if (ret)
301 return ret;
302 }
303
225 return ret; 304 return ret;
226} 305}
227 306
307static void render_ring_cleanup(struct intel_ring_buffer *ring)
308{
309 if (!ring->private)
310 return;
311
312 cleanup_pipe_control(ring);
313}
314
228static void 315static void
229update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno) 316update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno)
230{ 317{
@@ -299,6 +386,65 @@ intel_ring_sync(struct intel_ring_buffer *ring,
299 return 0; 386 return 0;
300} 387}
301 388
389#define PIPE_CONTROL_FLUSH(ring__, addr__) \
390do { \
391 intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
392 PIPE_CONTROL_DEPTH_STALL | 2); \
393 intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \
394 intel_ring_emit(ring__, 0); \
395 intel_ring_emit(ring__, 0); \
396} while (0)
397
398static int
399pc_render_add_request(struct intel_ring_buffer *ring,
400 u32 *result)
401{
402 struct drm_device *dev = ring->dev;
403 u32 seqno = i915_gem_get_seqno(dev);
404 struct pipe_control *pc = ring->private;
405 u32 scratch_addr = pc->gtt_offset + 128;
406 int ret;
407
408 /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently
409 * incoherent with writes to memory, i.e. completely fubar,
410 * so we need to use PIPE_NOTIFY instead.
411 *
412 * However, we also need to workaround the qword write
413 * incoherence by flushing the 6 PIPE_NOTIFY buffers out to
414 * memory before requesting an interrupt.
415 */
416 ret = intel_ring_begin(ring, 32);
417 if (ret)
418 return ret;
419
420 intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
421 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
422 intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
423 intel_ring_emit(ring, seqno);
424 intel_ring_emit(ring, 0);
425 PIPE_CONTROL_FLUSH(ring, scratch_addr);
426 scratch_addr += 128; /* write to separate cachelines */
427 PIPE_CONTROL_FLUSH(ring, scratch_addr);
428 scratch_addr += 128;
429 PIPE_CONTROL_FLUSH(ring, scratch_addr);
430 scratch_addr += 128;
431 PIPE_CONTROL_FLUSH(ring, scratch_addr);
432 scratch_addr += 128;
433 PIPE_CONTROL_FLUSH(ring, scratch_addr);
434 scratch_addr += 128;
435 PIPE_CONTROL_FLUSH(ring, scratch_addr);
436 intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
437 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
438 PIPE_CONTROL_NOTIFY);
439 intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
440 intel_ring_emit(ring, seqno);
441 intel_ring_emit(ring, 0);
442 intel_ring_advance(ring);
443
444 *result = seqno;
445 return 0;
446}
447
302static int 448static int
303render_ring_add_request(struct intel_ring_buffer *ring, 449render_ring_add_request(struct intel_ring_buffer *ring,
304 u32 *result) 450 u32 *result)
@@ -327,6 +473,13 @@ ring_get_seqno(struct intel_ring_buffer *ring)
327 return intel_read_status_page(ring, I915_GEM_HWS_INDEX); 473 return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
328} 474}
329 475
476static u32
477pc_render_get_seqno(struct intel_ring_buffer *ring)
478{
479 struct pipe_control *pc = ring->private;
480 return pc->cpu_page[0];
481}
482
330static bool 483static bool
331render_ring_get_irq(struct intel_ring_buffer *ring) 484render_ring_get_irq(struct intel_ring_buffer *ring)
332{ 485{
@@ -342,7 +495,7 @@ render_ring_get_irq(struct intel_ring_buffer *ring)
342 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 495 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
343 if (HAS_PCH_SPLIT(dev)) 496 if (HAS_PCH_SPLIT(dev))
344 ironlake_enable_graphics_irq(dev_priv, 497 ironlake_enable_graphics_irq(dev_priv,
345 GT_USER_INTERRUPT); 498 GT_PIPE_NOTIFY | GT_USER_INTERRUPT);
346 else 499 else
347 i915_enable_irq(dev_priv, I915_USER_INTERRUPT); 500 i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
348 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 501 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -363,7 +516,8 @@ render_ring_put_irq(struct intel_ring_buffer *ring)
363 spin_lock_irqsave(&dev_priv->irq_lock, irqflags); 516 spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
364 if (HAS_PCH_SPLIT(dev)) 517 if (HAS_PCH_SPLIT(dev))
365 ironlake_disable_graphics_irq(dev_priv, 518 ironlake_disable_graphics_irq(dev_priv,
366 GT_USER_INTERRUPT); 519 GT_USER_INTERRUPT |
520 GT_PIPE_NOTIFY);
367 else 521 else
368 i915_disable_irq(dev_priv, I915_USER_INTERRUPT); 522 i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
369 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); 523 spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
@@ -776,6 +930,7 @@ static const struct intel_ring_buffer render_ring = {
776 .irq_get = render_ring_get_irq, 930 .irq_get = render_ring_get_irq,
777 .irq_put = render_ring_put_irq, 931 .irq_put = render_ring_put_irq,
778 .dispatch_execbuffer = render_ring_dispatch_execbuffer, 932 .dispatch_execbuffer = render_ring_dispatch_execbuffer,
933 .cleanup = render_ring_cleanup,
779}; 934};
780 935
781/* ring buffer for bit-stream decoder */ 936/* ring buffer for bit-stream decoder */
@@ -1010,6 +1165,9 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
1010 *ring = render_ring; 1165 *ring = render_ring;
1011 if (INTEL_INFO(dev)->gen >= 6) { 1166 if (INTEL_INFO(dev)->gen >= 6) {
1012 ring->add_request = gen6_add_request; 1167 ring->add_request = gen6_add_request;
1168 } else if (IS_GEN5(dev)) {
1169 ring->add_request = pc_render_add_request;
1170 ring->get_seqno = pc_render_get_seqno;
1013 } 1171 }
1014 1172
1015 if (!I915_NEED_GFX_HWS(dev)) { 1173 if (!I915_NEED_GFX_HWS(dev)) {