diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 113 |
1 files changed, 90 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 42ff97d667d2..1d5d613eb6be 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -318,6 +318,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, | |||
| 318 | * TLB invalidate requires a post-sync write. | 318 | * TLB invalidate requires a post-sync write. |
| 319 | */ | 319 | */ |
| 320 | flags |= PIPE_CONTROL_QW_WRITE; | 320 | flags |= PIPE_CONTROL_QW_WRITE; |
| 321 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; | ||
| 321 | 322 | ||
| 322 | /* Workaround: we must issue a pipe_control with CS-stall bit | 323 | /* Workaround: we must issue a pipe_control with CS-stall bit |
| 323 | * set before a pipe_control command that has the state cache | 324 | * set before a pipe_control command that has the state cache |
| @@ -331,7 +332,7 @@ gen7_render_ring_flush(struct intel_ring_buffer *ring, | |||
| 331 | 332 | ||
| 332 | intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); | 333 | intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); |
| 333 | intel_ring_emit(ring, flags); | 334 | intel_ring_emit(ring, flags); |
| 334 | intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); | 335 | intel_ring_emit(ring, scratch_addr); |
| 335 | intel_ring_emit(ring, 0); | 336 | intel_ring_emit(ring, 0); |
| 336 | intel_ring_advance(ring); | 337 | intel_ring_advance(ring); |
| 337 | 338 | ||
| @@ -467,6 +468,9 @@ init_pipe_control(struct intel_ring_buffer *ring) | |||
| 467 | if (pc->cpu_page == NULL) | 468 | if (pc->cpu_page == NULL) |
| 468 | goto err_unpin; | 469 | goto err_unpin; |
| 469 | 470 | ||
| 471 | DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", | ||
| 472 | ring->name, pc->gtt_offset); | ||
| 473 | |||
| 470 | pc->obj = obj; | 474 | pc->obj = obj; |
| 471 | ring->private = pc; | 475 | ring->private = pc; |
| 472 | return 0; | 476 | return 0; |
| @@ -613,6 +617,13 @@ gen6_add_request(struct intel_ring_buffer *ring) | |||
| 613 | return 0; | 617 | return 0; |
| 614 | } | 618 | } |
| 615 | 619 | ||
| 620 | static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, | ||
| 621 | u32 seqno) | ||
| 622 | { | ||
| 623 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 624 | return dev_priv->last_seqno < seqno; | ||
| 625 | } | ||
| 626 | |||
| 616 | /** | 627 | /** |
| 617 | * intel_ring_sync - sync the waiter to the signaller on seqno | 628 | * intel_ring_sync - sync the waiter to the signaller on seqno |
| 618 | * | 629 | * |
| @@ -643,11 +654,20 @@ gen6_ring_sync(struct intel_ring_buffer *waiter, | |||
| 643 | if (ret) | 654 | if (ret) |
| 644 | return ret; | 655 | return ret; |
| 645 | 656 | ||
| 646 | intel_ring_emit(waiter, | 657 | /* If seqno wrap happened, omit the wait with no-ops */ |
| 647 | dw1 | signaller->semaphore_register[waiter->id]); | 658 | if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { |
| 648 | intel_ring_emit(waiter, seqno); | 659 | intel_ring_emit(waiter, |
| 649 | intel_ring_emit(waiter, 0); | 660 | dw1 | |
| 650 | intel_ring_emit(waiter, MI_NOOP); | 661 | signaller->semaphore_register[waiter->id]); |
| 662 | intel_ring_emit(waiter, seqno); | ||
| 663 | intel_ring_emit(waiter, 0); | ||
| 664 | intel_ring_emit(waiter, MI_NOOP); | ||
| 665 | } else { | ||
| 666 | intel_ring_emit(waiter, MI_NOOP); | ||
| 667 | intel_ring_emit(waiter, MI_NOOP); | ||
| 668 | intel_ring_emit(waiter, MI_NOOP); | ||
| 669 | intel_ring_emit(waiter, MI_NOOP); | ||
| 670 | } | ||
| 651 | intel_ring_advance(waiter); | 671 | intel_ring_advance(waiter); |
| 652 | 672 | ||
| 653 | return 0; | 673 | return 0; |
| @@ -728,6 +748,12 @@ ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) | |||
| 728 | return intel_read_status_page(ring, I915_GEM_HWS_INDEX); | 748 | return intel_read_status_page(ring, I915_GEM_HWS_INDEX); |
| 729 | } | 749 | } |
| 730 | 750 | ||
| 751 | static void | ||
| 752 | ring_set_seqno(struct intel_ring_buffer *ring, u32 seqno) | ||
| 753 | { | ||
| 754 | intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); | ||
| 755 | } | ||
| 756 | |||
| 731 | static u32 | 757 | static u32 |
| 732 | pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) | 758 | pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) |
| 733 | { | 759 | { |
| @@ -735,6 +761,13 @@ pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency) | |||
| 735 | return pc->cpu_page[0]; | 761 | return pc->cpu_page[0]; |
| 736 | } | 762 | } |
| 737 | 763 | ||
| 764 | static void | ||
| 765 | pc_render_set_seqno(struct intel_ring_buffer *ring, u32 seqno) | ||
| 766 | { | ||
| 767 | struct pipe_control *pc = ring->private; | ||
| 768 | pc->cpu_page[0] = seqno; | ||
| 769 | } | ||
| 770 | |||
| 738 | static bool | 771 | static bool |
| 739 | gen5_ring_get_irq(struct intel_ring_buffer *ring) | 772 | gen5_ring_get_irq(struct intel_ring_buffer *ring) |
| 740 | { | 773 | { |
| @@ -1164,7 +1197,11 @@ static int intel_init_ring_buffer(struct drm_device *dev, | |||
| 1164 | return ret; | 1197 | return ret; |
| 1165 | } | 1198 | } |
| 1166 | 1199 | ||
| 1167 | obj = i915_gem_alloc_object(dev, ring->size); | 1200 | obj = NULL; |
| 1201 | if (!HAS_LLC(dev)) | ||
| 1202 | obj = i915_gem_object_create_stolen(dev, ring->size); | ||
| 1203 | if (obj == NULL) | ||
| 1204 | obj = i915_gem_alloc_object(dev, ring->size); | ||
| 1168 | if (obj == NULL) { | 1205 | if (obj == NULL) { |
| 1169 | DRM_ERROR("Failed to allocate ringbuffer\n"); | 1206 | DRM_ERROR("Failed to allocate ringbuffer\n"); |
| 1170 | ret = -ENOMEM; | 1207 | ret = -ENOMEM; |
| @@ -1182,7 +1219,7 @@ static int intel_init_ring_buffer(struct drm_device *dev, | |||
| 1182 | goto err_unpin; | 1219 | goto err_unpin; |
| 1183 | 1220 | ||
| 1184 | ring->virtual_start = | 1221 | ring->virtual_start = |
| 1185 | ioremap_wc(dev_priv->mm.gtt->gma_bus_addr + obj->gtt_offset, | 1222 | ioremap_wc(dev_priv->gtt.mappable_base + obj->gtt_offset, |
| 1186 | ring->size); | 1223 | ring->size); |
| 1187 | if (ring->virtual_start == NULL) { | 1224 | if (ring->virtual_start == NULL) { |
| 1188 | DRM_ERROR("Failed to map ringbuffer.\n"); | 1225 | DRM_ERROR("Failed to map ringbuffer.\n"); |
| @@ -1348,7 +1385,8 @@ static int ring_wait_for_space(struct intel_ring_buffer *ring, int n) | |||
| 1348 | 1385 | ||
| 1349 | msleep(1); | 1386 | msleep(1); |
| 1350 | 1387 | ||
| 1351 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); | 1388 | ret = i915_gem_check_wedge(&dev_priv->gpu_error, |
| 1389 | dev_priv->mm.interruptible); | ||
| 1352 | if (ret) | 1390 | if (ret) |
| 1353 | return ret; | 1391 | return ret; |
| 1354 | } while (!time_after(jiffies, end)); | 1392 | } while (!time_after(jiffies, end)); |
| @@ -1410,14 +1448,35 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring) | |||
| 1410 | return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); | 1448 | return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request); |
| 1411 | } | 1449 | } |
| 1412 | 1450 | ||
| 1451 | static int __intel_ring_begin(struct intel_ring_buffer *ring, | ||
| 1452 | int bytes) | ||
| 1453 | { | ||
| 1454 | int ret; | ||
| 1455 | |||
| 1456 | if (unlikely(ring->tail + bytes > ring->effective_size)) { | ||
| 1457 | ret = intel_wrap_ring_buffer(ring); | ||
| 1458 | if (unlikely(ret)) | ||
| 1459 | return ret; | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | if (unlikely(ring->space < bytes)) { | ||
| 1463 | ret = ring_wait_for_space(ring, bytes); | ||
| 1464 | if (unlikely(ret)) | ||
| 1465 | return ret; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | ring->space -= bytes; | ||
| 1469 | return 0; | ||
| 1470 | } | ||
| 1471 | |||
| 1413 | int intel_ring_begin(struct intel_ring_buffer *ring, | 1472 | int intel_ring_begin(struct intel_ring_buffer *ring, |
| 1414 | int num_dwords) | 1473 | int num_dwords) |
| 1415 | { | 1474 | { |
| 1416 | drm_i915_private_t *dev_priv = ring->dev->dev_private; | 1475 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
| 1417 | int n = 4*num_dwords; | ||
| 1418 | int ret; | 1476 | int ret; |
| 1419 | 1477 | ||
| 1420 | ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); | 1478 | ret = i915_gem_check_wedge(&dev_priv->gpu_error, |
| 1479 | dev_priv->mm.interruptible); | ||
| 1421 | if (ret) | 1480 | if (ret) |
| 1422 | return ret; | 1481 | return ret; |
| 1423 | 1482 | ||
| @@ -1426,20 +1485,21 @@ int intel_ring_begin(struct intel_ring_buffer *ring, | |||
| 1426 | if (ret) | 1485 | if (ret) |
| 1427 | return ret; | 1486 | return ret; |
| 1428 | 1487 | ||
| 1429 | if (unlikely(ring->tail + n > ring->effective_size)) { | 1488 | return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t)); |
| 1430 | ret = intel_wrap_ring_buffer(ring); | 1489 | } |
| 1431 | if (unlikely(ret)) | ||
| 1432 | return ret; | ||
| 1433 | } | ||
| 1434 | 1490 | ||
| 1435 | if (unlikely(ring->space < n)) { | 1491 | void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) |
| 1436 | ret = ring_wait_for_space(ring, n); | 1492 | { |
| 1437 | if (unlikely(ret)) | 1493 | struct drm_i915_private *dev_priv = ring->dev->dev_private; |
| 1438 | return ret; | 1494 | |
| 1495 | BUG_ON(ring->outstanding_lazy_request); | ||
| 1496 | |||
| 1497 | if (INTEL_INFO(ring->dev)->gen >= 6) { | ||
| 1498 | I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); | ||
| 1499 | I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); | ||
| 1439 | } | 1500 | } |
| 1440 | 1501 | ||
| 1441 | ring->space -= n; | 1502 | ring->set_seqno(ring, seqno); |
| 1442 | return 0; | ||
| 1443 | } | 1503 | } |
| 1444 | 1504 | ||
| 1445 | void intel_ring_advance(struct intel_ring_buffer *ring) | 1505 | void intel_ring_advance(struct intel_ring_buffer *ring) |
| @@ -1447,7 +1507,7 @@ void intel_ring_advance(struct intel_ring_buffer *ring) | |||
| 1447 | struct drm_i915_private *dev_priv = ring->dev->dev_private; | 1507 | struct drm_i915_private *dev_priv = ring->dev->dev_private; |
| 1448 | 1508 | ||
| 1449 | ring->tail &= ring->size - 1; | 1509 | ring->tail &= ring->size - 1; |
| 1450 | if (dev_priv->stop_rings & intel_ring_flag(ring)) | 1510 | if (dev_priv->gpu_error.stop_rings & intel_ring_flag(ring)) |
| 1451 | return; | 1511 | return; |
| 1452 | ring->write_tail(ring, ring->tail); | 1512 | ring->write_tail(ring, ring->tail); |
| 1453 | } | 1513 | } |
| @@ -1604,6 +1664,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) | |||
| 1604 | ring->irq_put = gen6_ring_put_irq; | 1664 | ring->irq_put = gen6_ring_put_irq; |
| 1605 | ring->irq_enable_mask = GT_USER_INTERRUPT; | 1665 | ring->irq_enable_mask = GT_USER_INTERRUPT; |
| 1606 | ring->get_seqno = gen6_ring_get_seqno; | 1666 | ring->get_seqno = gen6_ring_get_seqno; |
| 1667 | ring->set_seqno = ring_set_seqno; | ||
| 1607 | ring->sync_to = gen6_ring_sync; | 1668 | ring->sync_to = gen6_ring_sync; |
| 1608 | ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID; | 1669 | ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID; |
| 1609 | ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; | 1670 | ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; |
| @@ -1614,6 +1675,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) | |||
| 1614 | ring->add_request = pc_render_add_request; | 1675 | ring->add_request = pc_render_add_request; |
| 1615 | ring->flush = gen4_render_ring_flush; | 1676 | ring->flush = gen4_render_ring_flush; |
| 1616 | ring->get_seqno = pc_render_get_seqno; | 1677 | ring->get_seqno = pc_render_get_seqno; |
| 1678 | ring->set_seqno = pc_render_set_seqno; | ||
| 1617 | ring->irq_get = gen5_ring_get_irq; | 1679 | ring->irq_get = gen5_ring_get_irq; |
| 1618 | ring->irq_put = gen5_ring_put_irq; | 1680 | ring->irq_put = gen5_ring_put_irq; |
| 1619 | ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; | 1681 | ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; |
| @@ -1624,6 +1686,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) | |||
| 1624 | else | 1686 | else |
| 1625 | ring->flush = gen4_render_ring_flush; | 1687 | ring->flush = gen4_render_ring_flush; |
| 1626 | ring->get_seqno = ring_get_seqno; | 1688 | ring->get_seqno = ring_get_seqno; |
| 1689 | ring->set_seqno = ring_set_seqno; | ||
| 1627 | if (IS_GEN2(dev)) { | 1690 | if (IS_GEN2(dev)) { |
| 1628 | ring->irq_get = i8xx_ring_get_irq; | 1691 | ring->irq_get = i8xx_ring_get_irq; |
| 1629 | ring->irq_put = i8xx_ring_put_irq; | 1692 | ring->irq_put = i8xx_ring_put_irq; |
| @@ -1695,6 +1758,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) | |||
| 1695 | else | 1758 | else |
| 1696 | ring->flush = gen4_render_ring_flush; | 1759 | ring->flush = gen4_render_ring_flush; |
| 1697 | ring->get_seqno = ring_get_seqno; | 1760 | ring->get_seqno = ring_get_seqno; |
| 1761 | ring->set_seqno = ring_set_seqno; | ||
| 1698 | if (IS_GEN2(dev)) { | 1762 | if (IS_GEN2(dev)) { |
| 1699 | ring->irq_get = i8xx_ring_get_irq; | 1763 | ring->irq_get = i8xx_ring_get_irq; |
| 1700 | ring->irq_put = i8xx_ring_put_irq; | 1764 | ring->irq_put = i8xx_ring_put_irq; |
| @@ -1755,6 +1819,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) | |||
| 1755 | ring->flush = gen6_ring_flush; | 1819 | ring->flush = gen6_ring_flush; |
| 1756 | ring->add_request = gen6_add_request; | 1820 | ring->add_request = gen6_add_request; |
| 1757 | ring->get_seqno = gen6_ring_get_seqno; | 1821 | ring->get_seqno = gen6_ring_get_seqno; |
| 1822 | ring->set_seqno = ring_set_seqno; | ||
| 1758 | ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT; | 1823 | ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT; |
| 1759 | ring->irq_get = gen6_ring_get_irq; | 1824 | ring->irq_get = gen6_ring_get_irq; |
| 1760 | ring->irq_put = gen6_ring_put_irq; | 1825 | ring->irq_put = gen6_ring_put_irq; |
| @@ -1770,6 +1835,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) | |||
| 1770 | ring->flush = bsd_ring_flush; | 1835 | ring->flush = bsd_ring_flush; |
| 1771 | ring->add_request = i9xx_add_request; | 1836 | ring->add_request = i9xx_add_request; |
| 1772 | ring->get_seqno = ring_get_seqno; | 1837 | ring->get_seqno = ring_get_seqno; |
| 1838 | ring->set_seqno = ring_set_seqno; | ||
| 1773 | if (IS_GEN5(dev)) { | 1839 | if (IS_GEN5(dev)) { |
| 1774 | ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; | 1840 | ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; |
| 1775 | ring->irq_get = gen5_ring_get_irq; | 1841 | ring->irq_get = gen5_ring_get_irq; |
| @@ -1799,6 +1865,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) | |||
| 1799 | ring->flush = blt_ring_flush; | 1865 | ring->flush = blt_ring_flush; |
| 1800 | ring->add_request = gen6_add_request; | 1866 | ring->add_request = gen6_add_request; |
| 1801 | ring->get_seqno = gen6_ring_get_seqno; | 1867 | ring->get_seqno = gen6_ring_get_seqno; |
| 1868 | ring->set_seqno = ring_set_seqno; | ||
| 1802 | ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT; | 1869 | ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT; |
| 1803 | ring->irq_get = gen6_ring_get_irq; | 1870 | ring->irq_get = gen6_ring_get_irq; |
| 1804 | ring->irq_put = gen6_ring_put_irq; | 1871 | ring->irq_put = gen6_ring_put_irq; |
