diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 302 |
1 files changed, 210 insertions, 92 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 818576654092..37427e4016cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -34,10 +34,6 @@ | |||
34 | 34 | ||
35 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) | 35 | #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) |
36 | 36 | ||
37 | static void | ||
38 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | ||
39 | uint32_t read_domains, | ||
40 | uint32_t write_domain); | ||
41 | static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); | 37 | static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); |
42 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 38 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
43 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 39 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
@@ -607,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
607 | case -EAGAIN: | 603 | case -EAGAIN: |
608 | return VM_FAULT_OOM; | 604 | return VM_FAULT_OOM; |
609 | case -EFAULT: | 605 | case -EFAULT: |
610 | case -EBUSY: | ||
611 | DRM_ERROR("can't insert pfn?? fault or busy...\n"); | ||
612 | return VM_FAULT_SIGBUS; | 606 | return VM_FAULT_SIGBUS; |
613 | default: | 607 | default: |
614 | return VM_FAULT_NOPAGE; | 608 | return VM_FAULT_NOPAGE; |
@@ -684,6 +678,30 @@ out_free_list: | |||
684 | return ret; | 678 | return ret; |
685 | } | 679 | } |
686 | 680 | ||
681 | static void | ||
682 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) | ||
683 | { | ||
684 | struct drm_device *dev = obj->dev; | ||
685 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
686 | struct drm_gem_mm *mm = dev->mm_private; | ||
687 | struct drm_map_list *list; | ||
688 | |||
689 | list = &obj->map_list; | ||
690 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
691 | |||
692 | if (list->file_offset_node) { | ||
693 | drm_mm_put_block(list->file_offset_node); | ||
694 | list->file_offset_node = NULL; | ||
695 | } | ||
696 | |||
697 | if (list->map) { | ||
698 | drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER); | ||
699 | list->map = NULL; | ||
700 | } | ||
701 | |||
702 | obj_priv->mmap_offset = 0; | ||
703 | } | ||
704 | |||
687 | /** | 705 | /** |
688 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object | 706 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object |
689 | * @obj: object to check | 707 | * @obj: object to check |
@@ -758,8 +776,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
758 | 776 | ||
759 | if (!obj_priv->mmap_offset) { | 777 | if (!obj_priv->mmap_offset) { |
760 | ret = i915_gem_create_mmap_offset(obj); | 778 | ret = i915_gem_create_mmap_offset(obj); |
761 | if (ret) | 779 | if (ret) { |
780 | drm_gem_object_unreference(obj); | ||
781 | mutex_unlock(&dev->struct_mutex); | ||
762 | return ret; | 782 | return ret; |
783 | } | ||
763 | } | 784 | } |
764 | 785 | ||
765 | args->offset = obj_priv->mmap_offset; | 786 | args->offset = obj_priv->mmap_offset; |
@@ -1030,6 +1051,9 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
1030 | drm_i915_private_t *dev_priv = dev->dev_private; | 1051 | drm_i915_private_t *dev_priv = dev->dev_private; |
1031 | uint32_t seqno; | 1052 | uint32_t seqno; |
1032 | 1053 | ||
1054 | if (!dev_priv->hw_status_page) | ||
1055 | return; | ||
1056 | |||
1033 | seqno = i915_get_gem_seqno(dev); | 1057 | seqno = i915_get_gem_seqno(dev); |
1034 | 1058 | ||
1035 | while (!list_empty(&dev_priv->mm.request_list)) { | 1059 | while (!list_empty(&dev_priv->mm.request_list)) { |
@@ -1452,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1452 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1476 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
1453 | int regnum = obj_priv->fence_reg; | 1477 | int regnum = obj_priv->fence_reg; |
1454 | int tile_width; | 1478 | int tile_width; |
1455 | uint32_t val; | 1479 | uint32_t fence_reg, val; |
1456 | uint32_t pitch_val; | 1480 | uint32_t pitch_val; |
1457 | 1481 | ||
1458 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1482 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
@@ -1479,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1479 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; | 1503 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; |
1480 | val |= I830_FENCE_REG_VALID; | 1504 | val |= I830_FENCE_REG_VALID; |
1481 | 1505 | ||
1482 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); | 1506 | if (regnum < 8) |
1507 | fence_reg = FENCE_REG_830_0 + (regnum * 4); | ||
1508 | else | ||
1509 | fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); | ||
1510 | I915_WRITE(fence_reg, val); | ||
1483 | } | 1511 | } |
1484 | 1512 | ||
1485 | static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | 1513 | static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) |
@@ -1533,7 +1561,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) | |||
1533 | struct drm_i915_private *dev_priv = dev->dev_private; | 1561 | struct drm_i915_private *dev_priv = dev->dev_private; |
1534 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1562 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
1535 | struct drm_i915_fence_reg *reg = NULL; | 1563 | struct drm_i915_fence_reg *reg = NULL; |
1536 | int i, ret; | 1564 | struct drm_i915_gem_object *old_obj_priv = NULL; |
1565 | int i, ret, avail; | ||
1537 | 1566 | ||
1538 | switch (obj_priv->tiling_mode) { | 1567 | switch (obj_priv->tiling_mode) { |
1539 | case I915_TILING_NONE: | 1568 | case I915_TILING_NONE: |
@@ -1556,25 +1585,46 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) | |||
1556 | } | 1585 | } |
1557 | 1586 | ||
1558 | /* First try to find a free reg */ | 1587 | /* First try to find a free reg */ |
1588 | try_again: | ||
1589 | avail = 0; | ||
1559 | for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { | 1590 | for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { |
1560 | reg = &dev_priv->fence_regs[i]; | 1591 | reg = &dev_priv->fence_regs[i]; |
1561 | if (!reg->obj) | 1592 | if (!reg->obj) |
1562 | break; | 1593 | break; |
1594 | |||
1595 | old_obj_priv = reg->obj->driver_private; | ||
1596 | if (!old_obj_priv->pin_count) | ||
1597 | avail++; | ||
1563 | } | 1598 | } |
1564 | 1599 | ||
1565 | /* None available, try to steal one or wait for a user to finish */ | 1600 | /* None available, try to steal one or wait for a user to finish */ |
1566 | if (i == dev_priv->num_fence_regs) { | 1601 | if (i == dev_priv->num_fence_regs) { |
1567 | struct drm_i915_gem_object *old_obj_priv = NULL; | 1602 | uint32_t seqno = dev_priv->mm.next_gem_seqno; |
1568 | loff_t offset; | 1603 | loff_t offset; |
1569 | 1604 | ||
1570 | try_again: | 1605 | if (avail == 0) |
1571 | /* Could try to use LRU here instead... */ | 1606 | return -ENOMEM; |
1607 | |||
1572 | for (i = dev_priv->fence_reg_start; | 1608 | for (i = dev_priv->fence_reg_start; |
1573 | i < dev_priv->num_fence_regs; i++) { | 1609 | i < dev_priv->num_fence_regs; i++) { |
1610 | uint32_t this_seqno; | ||
1611 | |||
1574 | reg = &dev_priv->fence_regs[i]; | 1612 | reg = &dev_priv->fence_regs[i]; |
1575 | old_obj_priv = reg->obj->driver_private; | 1613 | old_obj_priv = reg->obj->driver_private; |
1576 | if (!old_obj_priv->pin_count) | 1614 | |
1615 | if (old_obj_priv->pin_count) | ||
1616 | continue; | ||
1617 | |||
1618 | /* i915 uses fences for GPU access to tiled buffers */ | ||
1619 | if (IS_I965G(dev) || !old_obj_priv->active) | ||
1577 | break; | 1620 | break; |
1621 | |||
1622 | /* find the seqno of the first available fence */ | ||
1623 | this_seqno = old_obj_priv->last_rendering_seqno; | ||
1624 | if (this_seqno != 0 && | ||
1625 | reg->obj->write_domain == 0 && | ||
1626 | i915_seqno_passed(seqno, this_seqno)) | ||
1627 | seqno = this_seqno; | ||
1578 | } | 1628 | } |
1579 | 1629 | ||
1580 | /* | 1630 | /* |
@@ -1582,15 +1632,25 @@ try_again: | |||
1582 | * objects to finish before trying again. | 1632 | * objects to finish before trying again. |
1583 | */ | 1633 | */ |
1584 | if (i == dev_priv->num_fence_regs) { | 1634 | if (i == dev_priv->num_fence_regs) { |
1585 | ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); | 1635 | if (seqno == dev_priv->mm.next_gem_seqno) { |
1586 | if (ret) { | 1636 | i915_gem_flush(dev, |
1587 | WARN(ret != -ERESTARTSYS, | 1637 | I915_GEM_GPU_DOMAINS, |
1588 | "switch to GTT domain failed: %d\n", ret); | 1638 | I915_GEM_GPU_DOMAINS); |
1589 | return ret; | 1639 | seqno = i915_add_request(dev, |
1640 | I915_GEM_GPU_DOMAINS); | ||
1641 | if (seqno == 0) | ||
1642 | return -ENOMEM; | ||
1590 | } | 1643 | } |
1644 | |||
1645 | ret = i915_wait_request(dev, seqno); | ||
1646 | if (ret) | ||
1647 | return ret; | ||
1591 | goto try_again; | 1648 | goto try_again; |
1592 | } | 1649 | } |
1593 | 1650 | ||
1651 | BUG_ON(old_obj_priv->active || | ||
1652 | (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); | ||
1653 | |||
1594 | /* | 1654 | /* |
1595 | * Zap this virtual mapping so we can set up a fence again | 1655 | * Zap this virtual mapping so we can set up a fence again |
1596 | * for this object next time we need it. | 1656 | * for this object next time we need it. |
@@ -1631,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) | |||
1631 | 1691 | ||
1632 | if (IS_I965G(dev)) | 1692 | if (IS_I965G(dev)) |
1633 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); | 1693 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); |
1634 | else | 1694 | else { |
1635 | I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); | 1695 | uint32_t fence_reg; |
1696 | |||
1697 | if (obj_priv->fence_reg < 8) | ||
1698 | fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; | ||
1699 | else | ||
1700 | fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - | ||
1701 | 8) * 4; | ||
1702 | |||
1703 | I915_WRITE(fence_reg, 0); | ||
1704 | } | ||
1636 | 1705 | ||
1637 | dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; | 1706 | dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; |
1638 | obj_priv->fence_reg = I915_FENCE_REG_NONE; | 1707 | obj_priv->fence_reg = I915_FENCE_REG_NONE; |
@@ -1996,30 +2065,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
1996 | * drm_agp_chipset_flush | 2065 | * drm_agp_chipset_flush |
1997 | */ | 2066 | */ |
1998 | static void | 2067 | static void |
1999 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | 2068 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) |
2000 | uint32_t read_domains, | ||
2001 | uint32_t write_domain) | ||
2002 | { | 2069 | { |
2003 | struct drm_device *dev = obj->dev; | 2070 | struct drm_device *dev = obj->dev; |
2004 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2071 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
2005 | uint32_t invalidate_domains = 0; | 2072 | uint32_t invalidate_domains = 0; |
2006 | uint32_t flush_domains = 0; | 2073 | uint32_t flush_domains = 0; |
2007 | 2074 | ||
2008 | BUG_ON(read_domains & I915_GEM_DOMAIN_CPU); | 2075 | BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); |
2009 | BUG_ON(write_domain == I915_GEM_DOMAIN_CPU); | 2076 | BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); |
2010 | 2077 | ||
2011 | #if WATCH_BUF | 2078 | #if WATCH_BUF |
2012 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", | 2079 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", |
2013 | __func__, obj, | 2080 | __func__, obj, |
2014 | obj->read_domains, read_domains, | 2081 | obj->read_domains, obj->pending_read_domains, |
2015 | obj->write_domain, write_domain); | 2082 | obj->write_domain, obj->pending_write_domain); |
2016 | #endif | 2083 | #endif |
2017 | /* | 2084 | /* |
2018 | * If the object isn't moving to a new write domain, | 2085 | * If the object isn't moving to a new write domain, |
2019 | * let the object stay in multiple read domains | 2086 | * let the object stay in multiple read domains |
2020 | */ | 2087 | */ |
2021 | if (write_domain == 0) | 2088 | if (obj->pending_write_domain == 0) |
2022 | read_domains |= obj->read_domains; | 2089 | obj->pending_read_domains |= obj->read_domains; |
2023 | else | 2090 | else |
2024 | obj_priv->dirty = 1; | 2091 | obj_priv->dirty = 1; |
2025 | 2092 | ||
@@ -2029,15 +2096,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
2029 | * any read domains which differ from the old | 2096 | * any read domains which differ from the old |
2030 | * write domain | 2097 | * write domain |
2031 | */ | 2098 | */ |
2032 | if (obj->write_domain && obj->write_domain != read_domains) { | 2099 | if (obj->write_domain && |
2100 | obj->write_domain != obj->pending_read_domains) { | ||
2033 | flush_domains |= obj->write_domain; | 2101 | flush_domains |= obj->write_domain; |
2034 | invalidate_domains |= read_domains & ~obj->write_domain; | 2102 | invalidate_domains |= |
2103 | obj->pending_read_domains & ~obj->write_domain; | ||
2035 | } | 2104 | } |
2036 | /* | 2105 | /* |
2037 | * Invalidate any read caches which may have | 2106 | * Invalidate any read caches which may have |
2038 | * stale data. That is, any new read domains. | 2107 | * stale data. That is, any new read domains. |
2039 | */ | 2108 | */ |
2040 | invalidate_domains |= read_domains & ~obj->read_domains; | 2109 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; |
2041 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { | 2110 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { |
2042 | #if WATCH_BUF | 2111 | #if WATCH_BUF |
2043 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", | 2112 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", |
@@ -2046,9 +2115,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, | |||
2046 | i915_gem_clflush_object(obj); | 2115 | i915_gem_clflush_object(obj); |
2047 | } | 2116 | } |
2048 | 2117 | ||
2049 | if ((write_domain | flush_domains) != 0) | 2118 | /* The actual obj->write_domain will be updated with |
2050 | obj->write_domain = write_domain; | 2119 | * pending_write_domain after we emit the accumulated flush for all |
2051 | obj->read_domains = read_domains; | 2120 | * of our domain changes in execbuffers (which clears objects' |
2121 | * write_domains). So if we have a current write domain that we | ||
2122 | * aren't changing, set pending_write_domain to that. | ||
2123 | */ | ||
2124 | if (flush_domains == 0 && obj->pending_write_domain == 0) | ||
2125 | obj->pending_write_domain = obj->write_domain; | ||
2126 | obj->read_domains = obj->pending_read_domains; | ||
2052 | 2127 | ||
2053 | dev->invalidate_domains |= invalidate_domains; | 2128 | dev->invalidate_domains |= invalidate_domains; |
2054 | dev->flush_domains |= flush_domains; | 2129 | dev->flush_domains |= flush_domains; |
@@ -2251,6 +2326,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
2251 | (int) reloc.offset, | 2326 | (int) reloc.offset, |
2252 | reloc.read_domains, | 2327 | reloc.read_domains, |
2253 | reloc.write_domain); | 2328 | reloc.write_domain); |
2329 | drm_gem_object_unreference(target_obj); | ||
2330 | i915_gem_object_unpin(obj); | ||
2254 | return -EINVAL; | 2331 | return -EINVAL; |
2255 | } | 2332 | } |
2256 | 2333 | ||
@@ -2437,6 +2514,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2437 | struct drm_i915_gem_exec_object *exec_list = NULL; | 2514 | struct drm_i915_gem_exec_object *exec_list = NULL; |
2438 | struct drm_gem_object **object_list = NULL; | 2515 | struct drm_gem_object **object_list = NULL; |
2439 | struct drm_gem_object *batch_obj; | 2516 | struct drm_gem_object *batch_obj; |
2517 | struct drm_i915_gem_object *obj_priv; | ||
2440 | int ret, i, pinned = 0; | 2518 | int ret, i, pinned = 0; |
2441 | uint64_t exec_offset; | 2519 | uint64_t exec_offset; |
2442 | uint32_t seqno, flush_domains; | 2520 | uint32_t seqno, flush_domains; |
@@ -2480,13 +2558,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2480 | if (dev_priv->mm.wedged) { | 2558 | if (dev_priv->mm.wedged) { |
2481 | DRM_ERROR("Execbuf while wedged\n"); | 2559 | DRM_ERROR("Execbuf while wedged\n"); |
2482 | mutex_unlock(&dev->struct_mutex); | 2560 | mutex_unlock(&dev->struct_mutex); |
2483 | return -EIO; | 2561 | ret = -EIO; |
2562 | goto pre_mutex_err; | ||
2484 | } | 2563 | } |
2485 | 2564 | ||
2486 | if (dev_priv->mm.suspended) { | 2565 | if (dev_priv->mm.suspended) { |
2487 | DRM_ERROR("Execbuf while VT-switched.\n"); | 2566 | DRM_ERROR("Execbuf while VT-switched.\n"); |
2488 | mutex_unlock(&dev->struct_mutex); | 2567 | mutex_unlock(&dev->struct_mutex); |
2489 | return -EBUSY; | 2568 | ret = -EBUSY; |
2569 | goto pre_mutex_err; | ||
2490 | } | 2570 | } |
2491 | 2571 | ||
2492 | /* Look up object handles */ | 2572 | /* Look up object handles */ |
@@ -2499,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2499 | ret = -EBADF; | 2579 | ret = -EBADF; |
2500 | goto err; | 2580 | goto err; |
2501 | } | 2581 | } |
2582 | |||
2583 | obj_priv = object_list[i]->driver_private; | ||
2584 | if (obj_priv->in_execbuffer) { | ||
2585 | DRM_ERROR("Object %p appears more than once in object list\n", | ||
2586 | object_list[i]); | ||
2587 | ret = -EBADF; | ||
2588 | goto err; | ||
2589 | } | ||
2590 | obj_priv->in_execbuffer = true; | ||
2502 | } | 2591 | } |
2503 | 2592 | ||
2504 | /* Pin and relocate */ | 2593 | /* Pin and relocate */ |
@@ -2554,9 +2643,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2554 | struct drm_gem_object *obj = object_list[i]; | 2643 | struct drm_gem_object *obj = object_list[i]; |
2555 | 2644 | ||
2556 | /* Compute new gpu domains and update invalidate/flush */ | 2645 | /* Compute new gpu domains and update invalidate/flush */ |
2557 | i915_gem_object_set_to_gpu_domain(obj, | 2646 | i915_gem_object_set_to_gpu_domain(obj); |
2558 | obj->pending_read_domains, | ||
2559 | obj->pending_write_domain); | ||
2560 | } | 2647 | } |
2561 | 2648 | ||
2562 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2649 | i915_verify_inactive(dev, __FILE__, __LINE__); |
@@ -2575,6 +2662,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2575 | (void)i915_add_request(dev, dev->flush_domains); | 2662 | (void)i915_add_request(dev, dev->flush_domains); |
2576 | } | 2663 | } |
2577 | 2664 | ||
2665 | for (i = 0; i < args->buffer_count; i++) { | ||
2666 | struct drm_gem_object *obj = object_list[i]; | ||
2667 | |||
2668 | obj->write_domain = obj->pending_write_domain; | ||
2669 | } | ||
2670 | |||
2578 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2671 | i915_verify_inactive(dev, __FILE__, __LINE__); |
2579 | 2672 | ||
2580 | #if WATCH_COHERENCY | 2673 | #if WATCH_COHERENCY |
@@ -2632,24 +2725,32 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2632 | 2725 | ||
2633 | i915_verify_inactive(dev, __FILE__, __LINE__); | 2726 | i915_verify_inactive(dev, __FILE__, __LINE__); |
2634 | 2727 | ||
2635 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
2636 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
2637 | (uintptr_t) args->buffers_ptr, | ||
2638 | exec_list, | ||
2639 | sizeof(*exec_list) * args->buffer_count); | ||
2640 | if (ret) | ||
2641 | DRM_ERROR("failed to copy %d exec entries " | ||
2642 | "back to user (%d)\n", | ||
2643 | args->buffer_count, ret); | ||
2644 | err: | 2728 | err: |
2645 | for (i = 0; i < pinned; i++) | 2729 | for (i = 0; i < pinned; i++) |
2646 | i915_gem_object_unpin(object_list[i]); | 2730 | i915_gem_object_unpin(object_list[i]); |
2647 | 2731 | ||
2648 | for (i = 0; i < args->buffer_count; i++) | 2732 | for (i = 0; i < args->buffer_count; i++) { |
2733 | if (object_list[i]) { | ||
2734 | obj_priv = object_list[i]->driver_private; | ||
2735 | obj_priv->in_execbuffer = false; | ||
2736 | } | ||
2649 | drm_gem_object_unreference(object_list[i]); | 2737 | drm_gem_object_unreference(object_list[i]); |
2738 | } | ||
2650 | 2739 | ||
2651 | mutex_unlock(&dev->struct_mutex); | 2740 | mutex_unlock(&dev->struct_mutex); |
2652 | 2741 | ||
2742 | if (!ret) { | ||
2743 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
2744 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
2745 | (uintptr_t) args->buffers_ptr, | ||
2746 | exec_list, | ||
2747 | sizeof(*exec_list) * args->buffer_count); | ||
2748 | if (ret) | ||
2749 | DRM_ERROR("failed to copy %d exec entries " | ||
2750 | "back to user (%d)\n", | ||
2751 | args->buffer_count, ret); | ||
2752 | } | ||
2753 | |||
2653 | pre_mutex_err: | 2754 | pre_mutex_err: |
2654 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, | 2755 | drm_free(object_list, sizeof(*object_list) * args->buffer_count, |
2655 | DRM_MEM_DRIVER); | 2756 | DRM_MEM_DRIVER); |
@@ -2671,17 +2772,24 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
2671 | ret = i915_gem_object_bind_to_gtt(obj, alignment); | 2772 | ret = i915_gem_object_bind_to_gtt(obj, alignment); |
2672 | if (ret != 0) { | 2773 | if (ret != 0) { |
2673 | if (ret != -EBUSY && ret != -ERESTARTSYS) | 2774 | if (ret != -EBUSY && ret != -ERESTARTSYS) |
2674 | DRM_ERROR("Failure to bind: %d", ret); | 2775 | DRM_ERROR("Failure to bind: %d\n", ret); |
2776 | return ret; | ||
2777 | } | ||
2778 | } | ||
2779 | /* | ||
2780 | * Pre-965 chips need a fence register set up in order to | ||
2781 | * properly handle tiled surfaces. | ||
2782 | */ | ||
2783 | if (!IS_I965G(dev) && | ||
2784 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
2785 | obj_priv->tiling_mode != I915_TILING_NONE) { | ||
2786 | ret = i915_gem_object_get_fence_reg(obj, true); | ||
2787 | if (ret != 0) { | ||
2788 | if (ret != -EBUSY && ret != -ERESTARTSYS) | ||
2789 | DRM_ERROR("Failure to install fence: %d\n", | ||
2790 | ret); | ||
2675 | return ret; | 2791 | return ret; |
2676 | } | 2792 | } |
2677 | /* | ||
2678 | * Pre-965 chips need a fence register set up in order to | ||
2679 | * properly handle tiled surfaces. | ||
2680 | */ | ||
2681 | if (!IS_I965G(dev) && | ||
2682 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
2683 | obj_priv->tiling_mode != I915_TILING_NONE) | ||
2684 | i915_gem_object_get_fence_reg(obj, true); | ||
2685 | } | 2793 | } |
2686 | obj_priv->pin_count++; | 2794 | obj_priv->pin_count++; |
2687 | 2795 | ||
@@ -2753,6 +2861,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
2753 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { | 2861 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { |
2754 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", | 2862 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", |
2755 | args->handle); | 2863 | args->handle); |
2864 | drm_gem_object_unreference(obj); | ||
2756 | mutex_unlock(&dev->struct_mutex); | 2865 | mutex_unlock(&dev->struct_mutex); |
2757 | return -EINVAL; | 2866 | return -EINVAL; |
2758 | } | 2867 | } |
@@ -2833,6 +2942,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
2833 | return -EBADF; | 2942 | return -EBADF; |
2834 | } | 2943 | } |
2835 | 2944 | ||
2945 | /* Update the active list for the hardware's current position. | ||
2946 | * Otherwise this only updates on a delayed timer or when irqs are | ||
2947 | * actually unmasked, and our working set ends up being larger than | ||
2948 | * required. | ||
2949 | */ | ||
2950 | i915_gem_retire_requests(dev); | ||
2951 | |||
2836 | obj_priv = obj->driver_private; | 2952 | obj_priv = obj->driver_private; |
2837 | /* Don't count being on the flushing list against the object being | 2953 | /* Don't count being on the flushing list against the object being |
2838 | * done. Otherwise, a buffer left on the flushing list but not getting | 2954 | * done. Otherwise, a buffer left on the flushing list but not getting |
@@ -2885,9 +3001,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) | |||
2885 | void i915_gem_free_object(struct drm_gem_object *obj) | 3001 | void i915_gem_free_object(struct drm_gem_object *obj) |
2886 | { | 3002 | { |
2887 | struct drm_device *dev = obj->dev; | 3003 | struct drm_device *dev = obj->dev; |
2888 | struct drm_gem_mm *mm = dev->mm_private; | ||
2889 | struct drm_map_list *list; | ||
2890 | struct drm_map *map; | ||
2891 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 3004 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
2892 | 3005 | ||
2893 | while (obj_priv->pin_count > 0) | 3006 | while (obj_priv->pin_count > 0) |
@@ -2898,19 +3011,7 @@ void i915_gem_free_object(struct drm_gem_object *obj) | |||
2898 | 3011 | ||
2899 | i915_gem_object_unbind(obj); | 3012 | i915_gem_object_unbind(obj); |
2900 | 3013 | ||
2901 | list = &obj->map_list; | 3014 | i915_gem_free_mmap_offset(obj); |
2902 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
2903 | |||
2904 | if (list->file_offset_node) { | ||
2905 | drm_mm_put_block(list->file_offset_node); | ||
2906 | list->file_offset_node = NULL; | ||
2907 | } | ||
2908 | |||
2909 | map = list->map; | ||
2910 | if (map) { | ||
2911 | drm_free(map, sizeof(*map), DRM_MEM_DRIVER); | ||
2912 | list->map = NULL; | ||
2913 | } | ||
2914 | 3015 | ||
2915 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); | 3016 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); |
2916 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); | 3017 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); |
@@ -2949,7 +3050,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head) | |||
2949 | return 0; | 3050 | return 0; |
2950 | } | 3051 | } |
2951 | 3052 | ||
2952 | static int | 3053 | int |
2953 | i915_gem_idle(struct drm_device *dev) | 3054 | i915_gem_idle(struct drm_device *dev) |
2954 | { | 3055 | { |
2955 | drm_i915_private_t *dev_priv = dev->dev_private; | 3056 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -3095,6 +3196,7 @@ i915_gem_init_hws(struct drm_device *dev) | |||
3095 | if (dev_priv->hw_status_page == NULL) { | 3196 | if (dev_priv->hw_status_page == NULL) { |
3096 | DRM_ERROR("Failed to map status page.\n"); | 3197 | DRM_ERROR("Failed to map status page.\n"); |
3097 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | 3198 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); |
3199 | i915_gem_object_unpin(obj); | ||
3098 | drm_gem_object_unreference(obj); | 3200 | drm_gem_object_unreference(obj); |
3099 | return -EINVAL; | 3201 | return -EINVAL; |
3100 | } | 3202 | } |
@@ -3107,6 +3209,31 @@ i915_gem_init_hws(struct drm_device *dev) | |||
3107 | return 0; | 3209 | return 0; |
3108 | } | 3210 | } |
3109 | 3211 | ||
3212 | static void | ||
3213 | i915_gem_cleanup_hws(struct drm_device *dev) | ||
3214 | { | ||
3215 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
3216 | struct drm_gem_object *obj; | ||
3217 | struct drm_i915_gem_object *obj_priv; | ||
3218 | |||
3219 | if (dev_priv->hws_obj == NULL) | ||
3220 | return; | ||
3221 | |||
3222 | obj = dev_priv->hws_obj; | ||
3223 | obj_priv = obj->driver_private; | ||
3224 | |||
3225 | kunmap(obj_priv->page_list[0]); | ||
3226 | i915_gem_object_unpin(obj); | ||
3227 | drm_gem_object_unreference(obj); | ||
3228 | dev_priv->hws_obj = NULL; | ||
3229 | |||
3230 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | ||
3231 | dev_priv->hw_status_page = NULL; | ||
3232 | |||
3233 | /* Write high address into HWS_PGA when disabling. */ | ||
3234 | I915_WRITE(HWS_PGA, 0x1ffff000); | ||
3235 | } | ||
3236 | |||
3110 | int | 3237 | int |
3111 | i915_gem_init_ringbuffer(struct drm_device *dev) | 3238 | i915_gem_init_ringbuffer(struct drm_device *dev) |
3112 | { | 3239 | { |
@@ -3124,6 +3251,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
3124 | obj = drm_gem_object_alloc(dev, 128 * 1024); | 3251 | obj = drm_gem_object_alloc(dev, 128 * 1024); |
3125 | if (obj == NULL) { | 3252 | if (obj == NULL) { |
3126 | DRM_ERROR("Failed to allocate ringbuffer\n"); | 3253 | DRM_ERROR("Failed to allocate ringbuffer\n"); |
3254 | i915_gem_cleanup_hws(dev); | ||
3127 | return -ENOMEM; | 3255 | return -ENOMEM; |
3128 | } | 3256 | } |
3129 | obj_priv = obj->driver_private; | 3257 | obj_priv = obj->driver_private; |
@@ -3131,6 +3259,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
3131 | ret = i915_gem_object_pin(obj, 4096); | 3259 | ret = i915_gem_object_pin(obj, 4096); |
3132 | if (ret != 0) { | 3260 | if (ret != 0) { |
3133 | drm_gem_object_unreference(obj); | 3261 | drm_gem_object_unreference(obj); |
3262 | i915_gem_cleanup_hws(dev); | ||
3134 | return ret; | 3263 | return ret; |
3135 | } | 3264 | } |
3136 | 3265 | ||
@@ -3148,7 +3277,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
3148 | if (ring->map.handle == NULL) { | 3277 | if (ring->map.handle == NULL) { |
3149 | DRM_ERROR("Failed to map ringbuffer.\n"); | 3278 | DRM_ERROR("Failed to map ringbuffer.\n"); |
3150 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); | 3279 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); |
3280 | i915_gem_object_unpin(obj); | ||
3151 | drm_gem_object_unreference(obj); | 3281 | drm_gem_object_unreference(obj); |
3282 | i915_gem_cleanup_hws(dev); | ||
3152 | return -EINVAL; | 3283 | return -EINVAL; |
3153 | } | 3284 | } |
3154 | ring->ring_obj = obj; | 3285 | ring->ring_obj = obj; |
@@ -3228,20 +3359,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) | |||
3228 | dev_priv->ring.ring_obj = NULL; | 3359 | dev_priv->ring.ring_obj = NULL; |
3229 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); | 3360 | memset(&dev_priv->ring, 0, sizeof(dev_priv->ring)); |
3230 | 3361 | ||
3231 | if (dev_priv->hws_obj != NULL) { | 3362 | i915_gem_cleanup_hws(dev); |
3232 | struct drm_gem_object *obj = dev_priv->hws_obj; | ||
3233 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
3234 | |||
3235 | kunmap(obj_priv->page_list[0]); | ||
3236 | i915_gem_object_unpin(obj); | ||
3237 | drm_gem_object_unreference(obj); | ||
3238 | dev_priv->hws_obj = NULL; | ||
3239 | memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); | ||
3240 | dev_priv->hw_status_page = NULL; | ||
3241 | |||
3242 | /* Write high address into HWS_PGA when disabling. */ | ||
3243 | I915_WRITE(HWS_PGA, 0x1ffff000); | ||
3244 | } | ||
3245 | } | 3363 | } |
3246 | 3364 | ||
3247 | int | 3365 | int |
@@ -3497,7 +3615,7 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
3497 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 3615 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
3498 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; | 3616 | obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset; |
3499 | 3617 | ||
3500 | DRM_ERROR("obj_addr %p, %lld\n", obj_addr, args->size); | 3618 | DRM_DEBUG("obj_addr %p, %lld\n", obj_addr, args->size); |
3501 | ret = copy_from_user(obj_addr, user_data, args->size); | 3619 | ret = copy_from_user(obj_addr, user_data, args->size); |
3502 | if (ret) | 3620 | if (ret) |
3503 | return -EFAULT; | 3621 | return -EFAULT; |