Rev 3039 | Rev 3255 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3039 | Rev 3243 | ||
---|---|---|---|
Line 28... | Line 28... | ||
28 | #include |
28 | #include |
29 | #include |
29 | #include |
30 | #include "i915_drv.h" |
30 | #include "i915_drv.h" |
31 | #include "i915_trace.h" |
31 | #include "i915_trace.h" |
32 | #include "intel_drv.h" |
32 | #include "intel_drv.h" |
33 | //#include |
- | |
34 | #include |
33 | #include |
35 | //#include |
34 | //#include |
36 | #include |
35 | #include |
Line 37... | Line 36... | ||
37 | 36 | ||
Line 51... | Line 50... | ||
51 | 50 | ||
Line 52... | Line 51... | ||
52 | #define MAX_ERRNO 4095 |
51 | #define MAX_ERRNO 4095 |
Line 53... | Line -... | ||
53 | - | ||
54 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) |
- | |
55 | - | ||
56 | static inline long IS_ERR(const void *ptr) |
- | |
57 | { |
- | |
58 | return IS_ERR_VALUE((unsigned long)ptr); |
- | |
59 | } |
- | |
60 | - | ||
61 | static inline void *ERR_PTR(long error) |
- | |
62 | { |
- | |
63 | return (void *) error; |
- | |
64 | } |
- | |
65 | - | ||
66 | static inline long PTR_ERR(const void *ptr) |
- | |
67 | { |
- | |
68 | return (long) ptr; |
52 | |
69 | } |
53 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) |
70 | 54 | ||
71 | void |
55 | void |
72 | drm_gem_object_free(struct kref *kref) |
56 | drm_gem_object_free(struct kref *kref) |
Line 919... | Line 903... | ||
919 | i915_gem_object_truncate(obj); |
903 | i915_gem_object_truncate(obj); |
920 | /* and flush dirty cachelines in case the object isn't in the cpu write |
904 | /* and flush dirty cachelines in case the object isn't in the cpu write |
921 | * domain anymore. */ |
905 | * domain anymore. */ |
922 | if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) { |
906 | if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) { |
923 | i915_gem_clflush_object(obj); |
907 | i915_gem_clflush_object(obj); |
924 | intel_gtt_chipset_flush(); |
908 | i915_gem_chipset_flush(dev); |
925 | } |
909 | } |
926 | } |
910 | } |
Line 927... | Line 911... | ||
927 | 911 | ||
928 | if (needs_clflush_after) |
912 | if (needs_clflush_after) |
Line 929... | Line 913... | ||
929 | intel_gtt_chipset_flush(); |
913 | i915_gem_chipset_flush(dev); |
930 | 914 | ||
Line 931... | Line 915... | ||
931 | return ret; |
915 | return ret; |
Line 1387... | Line 1371... | ||
1387 | } |
1371 | } |
Line 1388... | Line 1372... | ||
1388 | 1372 | ||
1389 | static void |
1373 | static void |
1390 | i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) |
1374 | i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) |
- | 1375 | { |
|
- | 1376 | int page_count = obj->base.size / PAGE_SIZE; |
|
1391 | { |
1377 | struct scatterlist *sg; |
Line 1392... | Line 1378... | ||
1392 | int ret, i; |
1378 | int ret, i; |
Line 1393... | Line 1379... | ||
1393 | 1379 | ||
Line 1404... | Line 1390... | ||
1404 | } |
1390 | } |
Line 1405... | Line 1391... | ||
1405 | 1391 | ||
1406 | if (obj->madv == I915_MADV_DONTNEED) |
1392 | if (obj->madv == I915_MADV_DONTNEED) |
Line 1407... | Line 1393... | ||
1407 | obj->dirty = 0; |
1393 | obj->dirty = 0; |
1408 | 1394 | ||
Line -... | Line 1395... | ||
- | 1395 | for_each_sg(obj->pages->sgl, sg, page_count, i) { |
|
- | 1396 | struct page *page = sg_page(sg); |
|
- | 1397 | ||
- | 1398 | ||
1409 | for (i = 0; i < obj->pages.nents; i++) |
1399 | |
1410 | FreePage(obj->pages.page[i]); |
1400 | page_cache_release(page); |
- | 1401 | } |
|
- | 1402 | //DRM_DEBUG_KMS("%s release %d pages\n", __FUNCTION__, page_count); |
|
1411 | 1403 | obj->dirty = 0; |
|
1412 | DRM_DEBUG_KMS("%s release %d pages\n", __FUNCTION__, obj->pages.nents); |
1404 | |
Line 1413... | Line 1405... | ||
1413 | obj->dirty = 0; |
1405 | sg_free_table(obj->pages); |
1414 | kfree(obj->pages.page); |
1406 | kfree(obj->pages); |
1415 | } |
1407 | } |
1416 | 1408 | ||
Line 1417... | Line -... | ||
1417 | static int |
- | |
1418 | i915_gem_object_put_pages(struct drm_i915_gem_object *obj) |
- | |
1419 | { |
- | |
1420 | const struct drm_i915_gem_object_ops *ops = obj->ops; |
1409 | static int |
1421 | 1410 | i915_gem_object_put_pages(struct drm_i915_gem_object *obj) |
|
Line 1422... | Line 1411... | ||
1422 | // printf("page %x pin count %d\n", |
1411 | { |
Line 1423... | Line 1412... | ||
1423 | // obj->pages.page, obj->pages_pin_count ); |
1412 | const struct drm_i915_gem_object_ops *ops = obj->ops; |
1424 | 1413 | ||
Line -... | Line 1414... | ||
- | 1414 | if (obj->pages == NULL) |
|
- | 1415 | return 0; |
|
- | 1416 | ||
- | 1417 | BUG_ON(obj->gtt_space); |
|
- | 1418 | ||
1425 | if (obj->pages.page == NULL) |
1419 | if (obj->pages_pin_count) |
1426 | return 0; |
1420 | return -EBUSY; |
Line 1427... | Line -... | ||
1427 | - | ||
1428 | BUG_ON(obj->gtt_space); |
1421 | |
1429 | 1422 | /* ->put_pages might need to allocate memory for the bit17 swizzle |
|
Line 1430... | Line 1423... | ||
1430 | if (obj->pages_pin_count) |
1423 | * array, hence protect them from being reaped by removing them from gtt |
1431 | return -EBUSY; |
1424 | * lists early. */ |
Line 1448... | Line 1441... | ||
1448 | 1441 | ||
1449 | 1442 | ||
1450 | static int |
1443 | static int |
1451 | i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) |
- | |
1452 | { |
1444 | i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) |
- | 1445 | { |
|
- | 1446 | int page_count, i; |
|
- | 1447 | struct sg_table *st; |
|
- | 1448 | struct scatterlist *sg; |
|
Line 1453... | Line 1449... | ||
1453 | dma_addr_t page; |
1449 | struct page *page; |
1454 | int page_count, i; |
1450 | gfp_t gfp; |
- | 1451 | ||
1455 | 1452 | /* Assert that the object is not currently in any GPU domain. As it |
|
- | 1453 | * wasn't in the GTT, there shouldn't be any way it could have been in |
|
- | 1454 | * a GPU cache |
|
- | 1455 | */ |
|
- | 1456 | BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); |
|
- | 1457 | BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); |
|
- | 1458 | ||
- | 1459 | st = kmalloc(sizeof(*st), GFP_KERNEL); |
|
1456 | /* Get the list of pages out of our struct file. They'll be pinned |
1460 | if (st == NULL) |
1457 | * at this point until we release them. |
1461 | return -ENOMEM; |
1458 | */ |
1462 | |
1459 | page_count = obj->base.size / PAGE_SIZE; |
1463 | page_count = obj->base.size / PAGE_SIZE; |
1460 | BUG_ON(obj->pages.page != NULL); |
1464 | if (sg_alloc_table(st, page_count, GFP_KERNEL)) { |
- | 1465 | sg_free_table(st); |
|
Line -... | Line 1466... | ||
- | 1466 | kfree(st); |
|
- | 1467 | return -ENOMEM; |
|
- | 1468 | } |
|
- | 1469 | ||
- | 1470 | /* Get the list of pages out of our struct file. They'll be pinned |
|
1461 | obj->pages.page = malloc(page_count * sizeof(dma_addr_t)); |
1471 | * at this point until we release them. |
1462 | if (obj->pages.page == NULL) |
1472 | * |
1463 | return -ENOMEM; |
1473 | * Fail silently without starting the shrinker |
1464 | 1474 | */ |
|
Line 1465... | Line 1475... | ||
1465 | for (i = 0; i < page_count; i++) { |
1475 | for_each_sg(st->sgl, sg, page_count, i) { |
1466 | page = AllocPage(); // oh-oh |
1476 | page = AllocPage(); // oh-oh |
1467 | if ( page == 0 ) |
- | |
1468 | goto err_pages; |
- | |
Line -... | Line 1477... | ||
- | 1477 | if ( page == 0 ) |
|
Line 1469... | Line -... | ||
1469 | - | ||
1470 | obj->pages.page[i] = page; |
1478 | goto err_pages; |
Line 1471... | Line 1479... | ||
1471 | }; |
1479 | |
Line 1472... | Line 1480... | ||
1472 | DRM_DEBUG_KMS("%s alloc %d pages\n", __FUNCTION__, page_count); |
1480 | sg_set_page(sg, page, PAGE_SIZE, 0); |
1473 | obj->pages.nents = page_count; |
- | |
1474 | 1481 | } |
|
1475 | - | ||
1476 | // if (obj->tiling_mode != I915_TILING_NONE) |
1482 | |
1477 | // i915_gem_object_do_bit_17_swizzle(obj); |
1483 | obj->pages = st; |
1478 | 1484 | ||
1479 | return 0; |
- | |
1480 | 1485 | // DRM_DEBUG_KMS("%s alloc %d pages\n", __FUNCTION__, page_count); |
|
1481 | err_pages: |
1486 | |
Line 1482... | Line 1487... | ||
1482 | while (i--) |
1487 | return 0; |
1483 | FreePage(obj->pages.page[i]); |
1488 | |
1484 | 1489 | err_pages: |
|
Line 1501... | Line 1506... | ||
1501 | { |
1506 | { |
1502 | struct drm_i915_private *dev_priv = obj->base.dev->dev_private; |
1507 | struct drm_i915_private *dev_priv = obj->base.dev->dev_private; |
1503 | const struct drm_i915_gem_object_ops *ops = obj->ops; |
1508 | const struct drm_i915_gem_object_ops *ops = obj->ops; |
1504 | int ret; |
1509 | int ret; |
Line 1505... | Line 1510... | ||
1505 | 1510 | ||
1506 | if (obj->pages.page) |
1511 | if (obj->pages) |
Line 1507... | Line 1512... | ||
1507 | return 0; |
1512 | return 0; |
Line 1508... | Line 1513... | ||
1508 | 1513 | ||
Line 1516... | Line 1521... | ||
1516 | return 0; |
1521 | return 0; |
1517 | } |
1522 | } |
Line 1518... | Line 1523... | ||
1518 | 1523 | ||
1519 | void |
1524 | void |
1520 | i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, |
1525 | i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, |
1521 | struct intel_ring_buffer *ring, |
- | |
1522 | u32 seqno) |
1526 | struct intel_ring_buffer *ring) |
1523 | { |
1527 | { |
1524 | struct drm_device *dev = obj->base.dev; |
1528 | struct drm_device *dev = obj->base.dev; |
- | 1529 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
Line 1525... | Line 1530... | ||
1525 | struct drm_i915_private *dev_priv = dev->dev_private; |
1530 | u32 seqno = intel_ring_get_seqno(ring); |
1526 | 1531 | ||
Line 1527... | Line 1532... | ||
1527 | BUG_ON(ring == NULL); |
1532 | BUG_ON(ring == NULL); |
Line 1581... | Line 1586... | ||
1581 | drm_gem_object_unreference(&obj->base); |
1586 | drm_gem_object_unreference(&obj->base); |
Line 1582... | Line 1587... | ||
1582 | 1587 | ||
1583 | WARN_ON(i915_verify_lists(dev)); |
1588 | WARN_ON(i915_verify_lists(dev)); |
Line 1584... | Line 1589... | ||
1584 | } |
1589 | } |
1585 | 1590 | ||
1586 | static u32 |
1591 | static int |
1587 | i915_gem_get_seqno(struct drm_device *dev) |
1592 | i915_gem_handle_seqno_wrap(struct drm_device *dev) |
1588 | { |
1593 | { |
- | 1594 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
Line -... | Line 1595... | ||
- | 1595 | struct intel_ring_buffer *ring; |
|
- | 1596 | int ret, i, j; |
|
1589 | drm_i915_private_t *dev_priv = dev->dev_private; |
1597 | |
- | 1598 | /* The hardware uses various monotonic 32-bit counters, if we |
|
- | 1599 | * detect that they will wraparound we need to idle the GPU |
|
- | 1600 | * and reset those counters. |
|
- | 1601 | */ |
|
1590 | u32 seqno = dev_priv->next_seqno; |
1602 | ret = 0; |
- | 1603 | for_each_ring(ring, dev_priv, i) { |
|
- | 1604 | for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++) |
|
- | 1605 | ret |= ring->sync_seqno[j] != 0; |
|
- | 1606 | } |
|
- | 1607 | if (ret == 0) |
|
- | 1608 | return ret; |
|
- | 1609 | ||
- | 1610 | ret = i915_gpu_idle(dev); |
|
- | 1611 | if (ret) |
|
- | 1612 | return ret; |
|
- | 1613 | ||
1591 | 1614 | i915_gem_retire_requests(dev); |
|
- | 1615 | for_each_ring(ring, dev_priv, i) { |
|
Line 1592... | Line 1616... | ||
1592 | /* reserve 0 for non-seqno */ |
1616 | for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++) |
1593 | if (++dev_priv->next_seqno == 0) |
1617 | ring->sync_seqno[j] = 0; |
Line 1594... | Line 1618... | ||
1594 | dev_priv->next_seqno = 1; |
1618 | } |
1595 | 1619 | ||
1596 | return seqno; |
1620 | return 0; |
- | 1621 | } |
|
- | 1622 | ||
- | 1623 | int |
|
1597 | } |
1624 | i915_gem_get_seqno(struct drm_device *dev, u32 *seqno) |
1598 | 1625 | { |
|
- | 1626 | struct drm_i915_private *dev_priv = dev->dev_private; |
|
- | 1627 | ||
- | 1628 | /* reserve 0 for non-seqno */ |
|
- | 1629 | if (dev_priv->next_seqno == 0) { |
|
- | 1630 | int ret = i915_gem_handle_seqno_wrap(dev); |
|
Line 1599... | Line 1631... | ||
1599 | u32 |
1631 | if (ret) |
- | 1632 | return ret; |
|
1600 | i915_gem_next_request_seqno(struct intel_ring_buffer *ring) |
1633 | |
Line 1601... | Line 1634... | ||
1601 | { |
1634 | dev_priv->next_seqno = 1; |
1602 | if (ring->outstanding_lazy_request == 0) |
1635 | } |
1603 | ring->outstanding_lazy_request = i915_gem_get_seqno(ring->dev); |
1636 | |
1604 | 1637 | *seqno = dev_priv->next_seqno++; |
|
1605 | return ring->outstanding_lazy_request; |
1638 | return 0; |
1606 | } |
1639 | } |
1607 | 1640 | ||
1608 | int |
1641 | int |
1609 | i915_add_request(struct intel_ring_buffer *ring, |
- | |
1610 | struct drm_file *file, |
1642 | i915_add_request(struct intel_ring_buffer *ring, |
1611 | u32 *out_seqno) |
1643 | struct drm_file *file, |
Line 1612... | Line 1644... | ||
1612 | { |
1644 | u32 *out_seqno) |
1613 | drm_i915_private_t *dev_priv = ring->dev->dev_private; |
1645 | { |
Line 1630... | Line 1662... | ||
1630 | 1662 | ||
1631 | request = kmalloc(sizeof(*request), GFP_KERNEL); |
1663 | request = kmalloc(sizeof(*request), GFP_KERNEL); |
1632 | if (request == NULL) |
1664 | if (request == NULL) |
Line 1633... | Line -... | ||
1633 | return -ENOMEM; |
- | |
Line 1634... | Line 1665... | ||
1634 | 1665 | return -ENOMEM; |
|
1635 | seqno = i915_gem_next_request_seqno(ring); |
1666 | |
1636 | 1667 | ||
1637 | /* Record the position of the start of the request so that |
1668 | /* Record the position of the start of the request so that |
1638 | * should we detect the updated seqno part-way through the |
1669 | * should we detect the updated seqno part-way through the |
1639 | * GPU processing the request, we never over-estimate the |
1670 | * GPU processing the request, we never over-estimate the |
Line 1640... | Line 1671... | ||
1640 | * position of the head. |
1671 | * position of the head. |
1641 | */ |
1672 | */ |
1642 | request_ring_position = intel_ring_get_tail(ring); |
1673 | request_ring_position = intel_ring_get_tail(ring); |
1643 | 1674 | ||
1644 | ret = ring->add_request(ring, &seqno); |
1675 | ret = ring->add_request(ring); |
Line 1645... | Line -... | ||
1645 | if (ret) { |
- | |
1646 | kfree(request); |
- | |
1647 | return ret; |
1676 | if (ret) { |
1648 | } |
1677 | kfree(request); |
1649 | 1678 | return ret; |
|
1650 | trace_i915_gem_request_add(ring, seqno); |
1679 | } |
1651 | 1680 | ||
1652 | request->seqno = seqno; |
1681 | request->seqno = intel_ring_get_seqno(ring); |
Line 1672... | Line 1701... | ||
1672 | intel_mark_busy(dev_priv->dev); |
1701 | intel_mark_busy(dev_priv->dev); |
1673 | } |
1702 | } |
1674 | } |
1703 | } |
Line 1675... | Line 1704... | ||
1675 | 1704 | ||
1676 | if (out_seqno) |
1705 | if (out_seqno) |
1677 | *out_seqno = seqno; |
1706 | *out_seqno = request->seqno; |
1678 | return 0; |
1707 | return 0; |
Line 1757... | Line 1786... | ||
1757 | */ |
1786 | */ |
1758 | void |
1787 | void |
1759 | i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) |
1788 | i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) |
1760 | { |
1789 | { |
1761 | uint32_t seqno; |
1790 | uint32_t seqno; |
1762 | int i; |
- | |
Line 1763... | Line 1791... | ||
1763 | 1791 | ||
1764 | if (list_empty(&ring->request_list)) |
1792 | if (list_empty(&ring->request_list)) |
Line 1765... | Line 1793... | ||
1765 | return; |
1793 | return; |
Line 1766... | Line 1794... | ||
1766 | 1794 | ||
Line 1767... | Line -... | ||
1767 | WARN_ON(i915_verify_lists(ring->dev)); |
- | |
1768 | - | ||
1769 | seqno = ring->get_seqno(ring, true); |
- | |
1770 | - | ||
1771 | for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++) |
1795 | WARN_ON(i915_verify_lists(ring->dev)); |
1772 | if (seqno >= ring->sync_seqno[i]) |
1796 | |
Line 1773... | Line 1797... | ||
1773 | ring->sync_seqno[i] = 0; |
1797 | seqno = ring->get_seqno(ring, true); |
1774 | 1798 | ||
Line 1889... | Line 1913... | ||
1889 | } |
1913 | } |
Line 1890... | Line 1914... | ||
1890 | 1914 | ||
1891 | return 0; |
1915 | return 0; |
Line -... | Line 1916... | ||
- | 1916 | } |
|
- | 1917 | ||
- | 1918 | /** |
|
- | 1919 | * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT |
|
- | 1920 | * @DRM_IOCTL_ARGS: standard ioctl arguments |
|
- | 1921 | * |
|
- | 1922 | * Returns 0 if successful, else an error is returned with the remaining time in |
|
- | 1923 | * the timeout parameter. |
|
- | 1924 | * -ETIME: object is still busy after timeout |
|
- | 1925 | * -ERESTARTSYS: signal interrupted the wait |
|
- | 1926 | * -ENONENT: object doesn't exist |
|
- | 1927 | * Also possible, but rare: |
|
- | 1928 | * -EAGAIN: GPU wedged |
|
- | 1929 | * -ENOMEM: damn |
|
- | 1930 | * -ENODEV: Internal IRQ fail |
|
- | 1931 | * -E?: The add request failed |
|
- | 1932 | * |
|
- | 1933 | * The wait ioctl with a timeout of 0 reimplements the busy ioctl. With any |
|
- | 1934 | * non-zero timeout parameter the wait ioctl will wait for the given number of |
|
- | 1935 | * nanoseconds on an object becoming unbusy. Since the wait itself does so |
|
- | 1936 | * without holding struct_mutex the object may become re-busied before this |
|
- | 1937 | * function completes. A similar but shorter * race condition exists in the busy |
|
- | 1938 | * ioctl |
|
- | 1939 | */ |
|
- | 1940 | ||
- | 1941 | ||
- | 1942 | ||
Line 1936... | Line 1987... | ||
1936 | if (ret) |
1987 | if (ret) |
1937 | return ret; |
1988 | return ret; |
Line 1938... | Line 1989... | ||
1938 | 1989 | ||
1939 | ret = to->sync_to(to, from, seqno); |
1990 | ret = to->sync_to(to, from, seqno); |
- | 1991 | if (!ret) |
|
- | 1992 | /* We use last_read_seqno because sync_to() |
|
- | 1993 | * might have just caused seqno wrap under |
|
- | 1994 | * the radar. |
|
1940 | if (!ret) |
1995 | */ |
Line 1941... | Line 1996... | ||
1941 | from->sync_seqno[idx] = seqno; |
1996 | from->sync_seqno[idx] = obj->last_read_seqno; |
1942 | 1997 | ||
Line 1943... | Line 1998... | ||
1943 | return ret; |
1998 | return ret; |
Line 1980... | Line 2035... | ||
1980 | return 0; |
2035 | return 0; |
Line 1981... | Line 2036... | ||
1981 | 2036 | ||
1982 | if (obj->pin_count) |
2037 | if (obj->pin_count) |
Line 1983... | Line 2038... | ||
1983 | return -EBUSY; |
2038 | return -EBUSY; |
Line 1984... | Line 2039... | ||
1984 | 2039 | ||
1985 | BUG_ON(obj->pages.page == NULL); |
2040 | BUG_ON(obj->pages == NULL); |
1986 | 2041 | ||
1987 | ret = i915_gem_object_finish_gpu(obj); |
2042 | ret = i915_gem_object_finish_gpu(obj); |
Line 2019... | Line 2074... | ||
2019 | obj->gtt_offset = 0; |
2074 | obj->gtt_offset = 0; |
Line 2020... | Line 2075... | ||
2020 | 2075 | ||
2021 | return 0; |
2076 | return 0; |
Line 2022... | Line -... | ||
2022 | } |
- | |
2023 | - | ||
2024 | static int i915_ring_idle(struct intel_ring_buffer *ring) |
- | |
2025 | { |
- | |
2026 | if (list_empty(&ring->active_list)) |
- | |
2027 | return 0; |
- | |
2028 | - | ||
2029 | return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring)); |
- | |
2030 | } |
2077 | } |
2031 | 2078 | ||
2032 | int i915_gpu_idle(struct drm_device *dev) |
2079 | int i915_gpu_idle(struct drm_device *dev) |
2033 | { |
2080 | { |
2034 | drm_i915_private_t *dev_priv = dev->dev_private; |
2081 | drm_i915_private_t *dev_priv = dev->dev_private; |
Line 2039... | Line 2086... | ||
2039 | for_each_ring(ring, dev_priv, i) { |
2086 | for_each_ring(ring, dev_priv, i) { |
2040 | ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); |
2087 | ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); |
2041 | if (ret) |
2088 | if (ret) |
2042 | return ret; |
2089 | return ret; |
Line 2043... | Line 2090... | ||
2043 | 2090 | ||
2044 | ret = i915_ring_idle(ring); |
2091 | ret = intel_ring_idle(ring); |
2045 | if (ret) |
2092 | if (ret) |
2046 | return ret; |
2093 | return ret; |
Line 2047... | Line 2094... | ||
2047 | } |
2094 | } |
Line 2429... | Line 2476... | ||
2429 | bool map_and_fenceable, |
2476 | bool map_and_fenceable, |
2430 | bool nonblocking) |
2477 | bool nonblocking) |
2431 | { |
2478 | { |
2432 | struct drm_device *dev = obj->base.dev; |
2479 | struct drm_device *dev = obj->base.dev; |
2433 | drm_i915_private_t *dev_priv = dev->dev_private; |
2480 | drm_i915_private_t *dev_priv = dev->dev_private; |
2434 | struct drm_mm_node *free_space; |
2481 | struct drm_mm_node *node; |
2435 | u32 size, fence_size, fence_alignment, unfenced_alignment; |
2482 | u32 size, fence_size, fence_alignment, unfenced_alignment; |
2436 | bool mappable, fenceable; |
2483 | bool mappable, fenceable; |
2437 | int ret; |
2484 | int ret; |
Line 2438... | Line 2485... | ||
2438 | 2485 | ||
Line 2473... | Line 2520... | ||
2473 | 2520 | ||
2474 | ret = i915_gem_object_get_pages(obj); |
2521 | ret = i915_gem_object_get_pages(obj); |
2475 | if (ret) |
2522 | if (ret) |
Line -... | Line 2523... | ||
- | 2523 | return ret; |
|
- | 2524 | ||
- | 2525 | i915_gem_object_pin_pages(obj); |
|
- | 2526 | ||
- | 2527 | node = kzalloc(sizeof(*node), GFP_KERNEL); |
|
- | 2528 | if (node == NULL) { |
|
- | 2529 | i915_gem_object_unpin_pages(obj); |
|
- | 2530 | return -ENOMEM; |
|
2476 | return ret; |
2531 | } |
2477 | 2532 | ||
2478 | search_free: |
- | |
2479 | if (map_and_fenceable) |
2533 | search_free: |
2480 | free_space = |
2534 | if (map_and_fenceable) |
2481 | drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space, |
2535 | ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node, |
2482 | size, alignment, obj->cache_level, |
- | |
2483 | 0, dev_priv->mm.gtt_mappable_end, |
2536 | size, alignment, obj->cache_level, |
2484 | false); |
2537 | 0, dev_priv->mm.gtt_mappable_end); |
2485 | else |
2538 | else |
2486 | free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space, |
2539 | ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node, |
Line 2487... | Line -... | ||
2487 | size, alignment, obj->cache_level, |
- | |
2488 | false); |
- | |
2489 | - | ||
2490 | if (free_space != NULL) { |
- | |
2491 | if (map_and_fenceable) |
- | |
2492 | obj->gtt_space = |
- | |
2493 | drm_mm_get_block_range_generic(free_space, |
- | |
2494 | size, alignment, obj->cache_level, |
- | |
2495 | 0, dev_priv->mm.gtt_mappable_end, |
- | |
2496 | false); |
2540 | size, alignment, obj->cache_level); |
2497 | else |
- | |
2498 | obj->gtt_space = |
2541 | if (ret) { |
2499 | drm_mm_get_block_generic(free_space, |
- | |
2500 | size, alignment, obj->cache_level, |
- | |
2501 | false); |
- | |
2502 | } |
- | |
2503 | if (obj->gtt_space == NULL) { |
- | |
2504 | ret = 1; //i915_gem_evict_something(dev, size, alignment, |
2542 | |
2505 | // map_and_fenceable); |
- | |
2506 | if (ret) |
- | |
2507 | return ret; |
2543 | i915_gem_object_unpin_pages(obj); |
2508 | 2544 | kfree(node); |
|
2509 | goto search_free; |
- | |
2510 | } |
2545 | return ret; |
2511 | if (WARN_ON(!i915_gem_valid_gtt_space(dev, |
2546 | } |
2512 | obj->gtt_space, |
- | |
2513 | obj->cache_level))) { |
2547 | if (WARN_ON(!i915_gem_valid_gtt_space(dev, node, obj->cache_level))) { |
2514 | drm_mm_put_block(obj->gtt_space); |
2548 | i915_gem_object_unpin_pages(obj); |
Line 2515... | Line -... | ||
2515 | obj->gtt_space = NULL; |
- | |
2516 | return -EINVAL; |
2549 | drm_mm_put_block(node); |
2517 | } |
2550 | return -EINVAL; |
2518 | 2551 | } |
|
2519 | 2552 | ||
2520 | ret = i915_gem_gtt_prepare_object(obj); |
2553 | ret = i915_gem_gtt_prepare_object(obj); |
2521 | if (ret) { |
2554 | if (ret) { |
Line 2522... | Line -... | ||
2522 | drm_mm_put_block(obj->gtt_space); |
- | |
2523 | obj->gtt_space = NULL; |
- | |
2524 | return ret; |
- | |
2525 | } |
2555 | i915_gem_object_unpin_pages(obj); |
2526 | 2556 | drm_mm_put_block(node); |
|
Line -... | Line 2557... | ||
- | 2557 | return ret; |
|
2527 | if (!dev_priv->mm.aliasing_ppgtt) |
2558 | } |
Line 2528... | Line 2559... | ||
2528 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
2559 | |
2529 | 2560 | list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list); |
|
2530 | list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list); |
2561 | list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); |
Line 2531... | Line 2562... | ||
2531 | list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); |
2562 | |
2532 | 2563 | obj->gtt_space = node; |
|
Line 2533... | Line 2564... | ||
2533 | obj->gtt_offset = obj->gtt_space->start; |
2564 | obj->gtt_offset = node->start; |
Line -... | Line 2565... | ||
- | 2565 | ||
2534 | 2566 | fenceable = |
|
2535 | fenceable = |
2567 | node->size == fence_size && |
2536 | obj->gtt_space->size == fence_size && |
2568 | (node->start & (fence_alignment - 1)) == 0; |
2537 | (obj->gtt_space->start & (fence_alignment - 1)) == 0; |
2569 | |
Line 2551... | Line 2583... | ||
2551 | { |
2583 | { |
2552 | /* If we don't have a page list set up, then we're not pinned |
2584 | /* If we don't have a page list set up, then we're not pinned |
2553 | * to GPU, and we can ignore the cache flush because it'll happen |
2585 | * to GPU, and we can ignore the cache flush because it'll happen |
2554 | * again at bind time. |
2586 | * again at bind time. |
2555 | */ |
2587 | */ |
2556 | if (obj->pages.page == NULL) |
2588 | if (obj->pages == NULL) |
2557 | return; |
2589 | return; |
Line 2558... | Line 2590... | ||
2558 | 2590 | ||
2559 | /* If the GPU is snooping the contents of the CPU cache, |
2591 | /* If the GPU is snooping the contents of the CPU cache, |
2560 | * we do not need to manually clear the CPU cache lines. However, |
2592 | * we do not need to manually clear the CPU cache lines. However, |
Line 2564... | Line 2596... | ||
2564 | * snooping behaviour occurs naturally as the result of our domain |
2596 | * snooping behaviour occurs naturally as the result of our domain |
2565 | * tracking. |
2597 | * tracking. |
2566 | */ |
2598 | */ |
2567 | if (obj->cache_level != I915_CACHE_NONE) |
2599 | if (obj->cache_level != I915_CACHE_NONE) |
2568 | return; |
2600 | return; |
2569 | 2601 | #if 0 |
|
2570 | if(obj->mapped != NULL) |
2602 | if(obj->mapped != NULL) |
2571 | { |
2603 | { |
2572 | uint8_t *page_virtual; |
2604 | uint8_t *page_virtual; |
2573 | unsigned int i; |
2605 | unsigned int i; |
Line 2611... | Line 2643... | ||
2611 | "mfence \n" |
2643 | "mfence \n" |
2612 | "wbinvd \n" /* this is really ugly */ |
2644 | "wbinvd \n" /* this is really ugly */ |
2613 | "mfence"); |
2645 | "mfence"); |
2614 | } |
2646 | } |
2615 | } |
2647 | } |
- | 2648 | #endif |
|
- | 2649 | ||
2616 | } |
2650 | } |
Line 2617... | Line 2651... | ||
2617 | 2651 | ||
2618 | /** Flushes the GTT write domain for the object if it's dirty. */ |
2652 | /** Flushes the GTT write domain for the object if it's dirty. */ |
2619 | static void |
2653 | static void |
Line 2650... | Line 2684... | ||
2650 | 2684 | ||
2651 | if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) |
2685 | if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) |
Line 2652... | Line 2686... | ||
2652 | return; |
2686 | return; |
2653 | 2687 | ||
2654 | i915_gem_clflush_object(obj); |
2688 | i915_gem_clflush_object(obj); |
2655 | intel_gtt_chipset_flush(); |
2689 | i915_gem_chipset_flush(obj->base.dev); |
Line 2656... | Line 2690... | ||
2656 | old_write_domain = obj->base.write_domain; |
2690 | old_write_domain = obj->base.write_domain; |
2657 | obj->base.write_domain = 0; |
2691 | obj->base.write_domain = 0; |
Line 2987... | Line 3021... | ||
2987 | } |
3021 | } |
2988 | } |
3022 | } |
2989 | #endif |
3023 | #endif |
Line 2990... | Line 3024... | ||
2990 | 3024 | ||
- | 3025 | if (obj->gtt_space == NULL) { |
|
- | 3026 | struct drm_i915_private *dev_priv = obj->base.dev->dev_private; |
|
2991 | if (obj->gtt_space == NULL) { |
3027 | |
2992 | ret = i915_gem_object_bind_to_gtt(obj, alignment, |
3028 | ret = i915_gem_object_bind_to_gtt(obj, alignment, |
2993 | map_and_fenceable, |
3029 | map_and_fenceable, |
2994 | nonblocking); |
3030 | nonblocking); |
2995 | if (ret) |
3031 | if (ret) |
- | 3032 | return ret; |
|
- | 3033 | ||
- | 3034 | if (!dev_priv->mm.aliasing_ppgtt) |
|
2996 | return ret; |
3035 | i915_gem_gtt_bind_object(obj, obj->cache_level); |
Line 2997... | Line 3036... | ||
2997 | } |
3036 | } |
2998 | 3037 | ||
Line 3045... | Line 3084... | ||
3045 | args->handle); |
3084 | args->handle); |
3046 | ret = -EINVAL; |
3085 | ret = -EINVAL; |
3047 | goto out; |
3086 | goto out; |
3048 | } |
3087 | } |
Line 3049... | Line -... | ||
3049 | - | ||
3050 | obj->user_pin_count++; |
- | |
3051 | obj->pin_filp = file; |
3088 | |
3052 | if (obj->user_pin_count == 1) { |
3089 | if (obj->user_pin_count == 0) { |
3053 | ret = i915_gem_object_pin(obj, args->alignment, true, false); |
3090 | ret = i915_gem_object_pin(obj, args->alignment, true, false); |
3054 | if (ret) |
3091 | if (ret) |
3055 | goto out; |
3092 | goto out; |
Line -... | Line 3093... | ||
- | 3093 | } |
|
- | 3094 | ||
- | 3095 | obj->user_pin_count++; |
|
3056 | } |
3096 | obj->pin_filp = file; |
3057 | 3097 | ||
3058 | /* XXX - flush the CPU caches for pinned objects |
3098 | /* XXX - flush the CPU caches for pinned objects |
3059 | * as the X server doesn't manage domains yet |
3099 | * as the X server doesn't manage domains yet |
3060 | */ |
3100 | */ |
Line 3293... | Line 3333... | ||
3293 | 3333 | ||
3294 | obj->pages_pin_count = 0; |
3334 | obj->pages_pin_count = 0; |
3295 | i915_gem_object_put_pages(obj); |
3335 | i915_gem_object_put_pages(obj); |
Line 3296... | Line 3336... | ||
3296 | // i915_gem_object_free_mmap_offset(obj); |
3336 | // i915_gem_object_free_mmap_offset(obj); |
Line 3297... | Line 3337... | ||
3297 | 3337 | ||
3298 | BUG_ON(obj->pages.page); |
3338 | BUG_ON(obj->pages); |
Line 3299... | Line 3339... | ||
3299 | 3339 | ||
Line 3356... | Line 3396... | ||
3356 | int i; |
3396 | int i; |
Line 3357... | Line 3397... | ||
3357 | 3397 | ||
3358 | if (!IS_IVYBRIDGE(dev)) |
3398 | if (!IS_IVYBRIDGE(dev)) |
Line 3359... | Line 3399... | ||
3359 | return; |
3399 | return; |
3360 | 3400 | ||
Line 3361... | Line 3401... | ||
3361 | if (!dev_priv->mm.l3_remap_info) |
3401 | if (!dev_priv->l3_parity.remap_info) |
3362 | return; |
3402 | return; |
3363 | 3403 | ||
Line 3364... | Line 3404... | ||
3364 | misccpctl = I915_READ(GEN7_MISCCPCTL); |
3404 | misccpctl = I915_READ(GEN7_MISCCPCTL); |
3365 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); |
3405 | I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); |
3366 | POSTING_READ(GEN7_MISCCPCTL); |
3406 | POSTING_READ(GEN7_MISCCPCTL); |
3367 | 3407 | ||
3368 | for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { |
3408 | for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) { |
3369 | u32 remap = I915_READ(GEN7_L3LOG_BASE + i); |
3409 | u32 remap = I915_READ(GEN7_L3LOG_BASE + i); |
3370 | if (remap && remap != dev_priv->mm.l3_remap_info[i/4]) |
3410 | if (remap && remap != dev_priv->l3_parity.remap_info[i/4]) |
3371 | DRM_DEBUG("0x%x was already programmed to %x\n", |
3411 | DRM_DEBUG("0x%x was already programmed to %x\n", |
3372 | GEN7_L3LOG_BASE + i, remap); |
3412 | GEN7_L3LOG_BASE + i, remap); |
Line 3373... | Line 3413... | ||
3373 | if (remap && !dev_priv->mm.l3_remap_info[i/4]) |
3413 | if (remap && !dev_priv->l3_parity.remap_info[i/4]) |
3374 | DRM_DEBUG_DRIVER("Clearing remapped register\n"); |
3414 | DRM_DEBUG_DRIVER("Clearing remapped register\n"); |
Line 3400... | Line 3440... | ||
3400 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); |
3440 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); |
3401 | else |
3441 | else |
3402 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); |
3442 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); |
3403 | } |
3443 | } |
Line 3404... | Line -... | ||
3404 | - | ||
3405 | void i915_gem_init_ppgtt(struct drm_device *dev) |
- | |
3406 | { |
- | |
3407 | drm_i915_private_t *dev_priv = dev->dev_private; |
- | |
3408 | uint32_t pd_offset; |
- | |
3409 | struct intel_ring_buffer *ring; |
- | |
3410 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
- | |
3411 | uint32_t __iomem *pd_addr; |
- | |
3412 | uint32_t pd_entry; |
- | |
3413 | int i; |
- | |
3414 | - | ||
3415 | if (!dev_priv->mm.aliasing_ppgtt) |
- | |
3416 | return; |
- | |
3417 | - | ||
3418 | - | ||
3419 | pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t); |
- | |
3420 | for (i = 0; i < ppgtt->num_pd_entries; i++) { |
- | |
3421 | dma_addr_t pt_addr; |
- | |
3422 | - | ||
3423 | if (dev_priv->mm.gtt->needs_dmar) |
- | |
3424 | pt_addr = ppgtt->pt_dma_addr[i]; |
- | |
3425 | else |
- | |
3426 | pt_addr = ppgtt->pt_pages[i]; |
- | |
3427 | - | ||
3428 | pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr); |
- | |
3429 | pd_entry |= GEN6_PDE_VALID; |
- | |
3430 | - | ||
3431 | writel(pd_entry, pd_addr + i); |
- | |
3432 | } |
- | |
3433 | readl(pd_addr); |
- | |
3434 | - | ||
3435 | pd_offset = ppgtt->pd_offset; |
- | |
3436 | pd_offset /= 64; /* in cachelines, */ |
- | |
3437 | pd_offset <<= 16; |
- | |
3438 | - | ||
3439 | if (INTEL_INFO(dev)->gen == 6) { |
- | |
3440 | uint32_t ecochk, gab_ctl, ecobits; |
- | |
3441 | - | ||
3442 | ecobits = I915_READ(GAC_ECO_BITS); |
- | |
3443 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); |
- | |
3444 | - | ||
3445 | gab_ctl = I915_READ(GAB_CTL); |
- | |
3446 | I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT); |
- | |
3447 | - | ||
3448 | ecochk = I915_READ(GAM_ECOCHK); |
- | |
3449 | I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT | |
- | |
3450 | ECOCHK_PPGTT_CACHE64B); |
- | |
3451 | I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
- | |
3452 | } else if (INTEL_INFO(dev)->gen >= 7) { |
- | |
3453 | I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B); |
- | |
3454 | /* GFX_MODE is per-ring on gen7+ */ |
- | |
3455 | } |
- | |
3456 | - | ||
3457 | for_each_ring(ring, dev_priv, i) { |
- | |
3458 | if (INTEL_INFO(dev)->gen >= 7) |
- | |
3459 | I915_WRITE(RING_MODE_GEN7(ring), |
- | |
3460 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
- | |
3461 | - | ||
3462 | I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); |
- | |
3463 | I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset); |
- | |
3464 | } |
- | |
3465 | } |
- | |
3466 | 3444 | ||
3467 | static bool |
3445 | static bool |
3468 | intel_enable_blt(struct drm_device *dev) |
3446 | intel_enable_blt(struct drm_device *dev) |
3469 | { |
3447 | { |
3470 | if (!HAS_BLT(dev)) |
3448 | if (!HAS_BLT(dev)) |
Line 3484... | Line 3462... | ||
3484 | i915_gem_init_hw(struct drm_device *dev) |
3462 | i915_gem_init_hw(struct drm_device *dev) |
3485 | { |
3463 | { |
3486 | drm_i915_private_t *dev_priv = dev->dev_private; |
3464 | drm_i915_private_t *dev_priv = dev->dev_private; |
3487 | int ret; |
3465 | int ret; |
Line 3488... | Line 3466... | ||
3488 | 3466 | ||
3489 | if (!intel_enable_gtt()) |
3467 | if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) |
Line 3490... | Line 3468... | ||
3490 | return -EIO; |
3468 | return -EIO; |
3491 | 3469 |