diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/ni.c')
-rw-r--r-- | drivers/gpu/drm/radeon/ni.c | 160 |
1 files changed, 156 insertions, 4 deletions
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index d89b2ebd5bbb..321137295400 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -934,7 +934,7 @@ void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev) | |||
934 | 934 | ||
935 | int cayman_pcie_gart_enable(struct radeon_device *rdev) | 935 | int cayman_pcie_gart_enable(struct radeon_device *rdev) |
936 | { | 936 | { |
937 | int r; | 937 | int i, r; |
938 | 938 | ||
939 | if (rdev->gart.robj == NULL) { | 939 | if (rdev->gart.robj == NULL) { |
940 | dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); | 940 | dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); |
@@ -945,9 +945,12 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev) | |||
945 | return r; | 945 | return r; |
946 | radeon_gart_restore(rdev); | 946 | radeon_gart_restore(rdev); |
947 | /* Setup TLB control */ | 947 | /* Setup TLB control */ |
948 | WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB | | 948 | WREG32(MC_VM_MX_L1_TLB_CNTL, |
949 | (0xA << 7) | | ||
950 | ENABLE_L1_TLB | | ||
949 | ENABLE_L1_FRAGMENT_PROCESSING | | 951 | ENABLE_L1_FRAGMENT_PROCESSING | |
950 | SYSTEM_ACCESS_MODE_NOT_IN_SYS | | 952 | SYSTEM_ACCESS_MODE_NOT_IN_SYS | |
953 | ENABLE_ADVANCED_DRIVER_MODEL | | ||
951 | SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); | 954 | SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU); |
952 | /* Setup L2 cache */ | 955 | /* Setup L2 cache */ |
953 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | | 956 | WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | |
@@ -967,9 +970,26 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev) | |||
967 | WREG32(VM_CONTEXT0_CNTL2, 0); | 970 | WREG32(VM_CONTEXT0_CNTL2, 0); |
968 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | | 971 | WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | |
969 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); | 972 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); |
970 | /* disable context1-7 */ | 973 | |
974 | WREG32(0x15D4, 0); | ||
975 | WREG32(0x15D8, 0); | ||
976 | WREG32(0x15DC, 0); | ||
977 | |||
978 | /* empty context1-7 */ | ||
979 | for (i = 1; i < 8; i++) { | ||
980 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0); | ||
981 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0); | ||
982 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), | ||
983 | rdev->gart.table_addr >> 12); | ||
984 | } | ||
985 | |||
986 | /* enable context1-7 */ | ||
987 | WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, | ||
988 | (u32)(rdev->dummy_page.addr >> 12)); | ||
971 | WREG32(VM_CONTEXT1_CNTL2, 0); | 989 | WREG32(VM_CONTEXT1_CNTL2, 0); |
972 | WREG32(VM_CONTEXT1_CNTL, 0); | 990 | WREG32(VM_CONTEXT1_CNTL, 0); |
991 | WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | | ||
992 | RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); | ||
973 | 993 | ||
974 | cayman_pcie_gart_tlb_flush(rdev); | 994 | cayman_pcie_gart_tlb_flush(rdev); |
975 | DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", | 995 | DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", |
@@ -1024,7 +1044,10 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, | |||
1024 | struct radeon_ring *ring = &rdev->ring[fence->ring]; | 1044 | struct radeon_ring *ring = &rdev->ring[fence->ring]; |
1025 | u64 addr = rdev->fence_drv[fence->ring].gpu_addr; | 1045 | u64 addr = rdev->fence_drv[fence->ring].gpu_addr; |
1026 | 1046 | ||
1027 | /* flush read cache over gart */ | 1047 | /* flush read cache over gart for this vmid */ |
1048 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
1049 | radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); | ||
1050 | radeon_ring_write(ring, 0); | ||
1028 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); | 1051 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); |
1029 | radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); | 1052 | radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); |
1030 | radeon_ring_write(ring, 0xFFFFFFFF); | 1053 | radeon_ring_write(ring, 0xFFFFFFFF); |
@@ -1039,6 +1062,33 @@ void cayman_fence_ring_emit(struct radeon_device *rdev, | |||
1039 | radeon_ring_write(ring, 0); | 1062 | radeon_ring_write(ring, 0); |
1040 | } | 1063 | } |
1041 | 1064 | ||
1065 | void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) | ||
1066 | { | ||
1067 | struct radeon_ring *ring = &rdev->ring[ib->fence->ring]; | ||
1068 | |||
1069 | /* set to DX10/11 mode */ | ||
1070 | radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); | ||
1071 | radeon_ring_write(ring, 1); | ||
1072 | radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | ||
1073 | radeon_ring_write(ring, | ||
1074 | #ifdef __BIG_ENDIAN | ||
1075 | (2 << 0) | | ||
1076 | #endif | ||
1077 | (ib->gpu_addr & 0xFFFFFFFC)); | ||
1078 | radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); | ||
1079 | radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); | ||
1080 | |||
1081 | /* flush read cache over gart for this vmid */ | ||
1082 | radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
1083 | radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); | ||
1084 | radeon_ring_write(ring, ib->vm_id); | ||
1085 | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); | ||
1086 | radeon_ring_write(ring, PACKET3_TC_ACTION_ENA | PACKET3_SH_ACTION_ENA); | ||
1087 | radeon_ring_write(ring, 0xFFFFFFFF); | ||
1088 | radeon_ring_write(ring, 0); | ||
1089 | radeon_ring_write(ring, 10); /* poll interval */ | ||
1090 | } | ||
1091 | |||
1042 | static void cayman_cp_enable(struct radeon_device *rdev, bool enable) | 1092 | static void cayman_cp_enable(struct radeon_device *rdev, bool enable) |
1043 | { | 1093 | { |
1044 | if (enable) | 1094 | if (enable) |
@@ -1324,6 +1374,15 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) | |||
1324 | RREG32(GRBM_STATUS_SE1)); | 1374 | RREG32(GRBM_STATUS_SE1)); |
1325 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", | 1375 | dev_info(rdev->dev, " SRBM_STATUS=0x%08X\n", |
1326 | RREG32(SRBM_STATUS)); | 1376 | RREG32(SRBM_STATUS)); |
1377 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_ADDR 0x%08X\n", | ||
1378 | RREG32(0x14F8)); | ||
1379 | dev_info(rdev->dev, " VM_CONTEXT0_PROTECTION_FAULT_STATUS 0x%08X\n", | ||
1380 | RREG32(0x14D8)); | ||
1381 | dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", | ||
1382 | RREG32(0x14FC)); | ||
1383 | dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", | ||
1384 | RREG32(0x14DC)); | ||
1385 | |||
1327 | evergreen_mc_stop(rdev, &save); | 1386 | evergreen_mc_stop(rdev, &save); |
1328 | if (evergreen_mc_wait_for_idle(rdev)) { | 1387 | if (evergreen_mc_wait_for_idle(rdev)) { |
1329 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); | 1388 | dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); |
@@ -1354,6 +1413,7 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev) | |||
1354 | (void)RREG32(GRBM_SOFT_RESET); | 1413 | (void)RREG32(GRBM_SOFT_RESET); |
1355 | /* Wait a little for things to settle down */ | 1414 | /* Wait a little for things to settle down */ |
1356 | udelay(50); | 1415 | udelay(50); |
1416 | |||
1357 | dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", | 1417 | dev_info(rdev->dev, " GRBM_STATUS=0x%08X\n", |
1358 | RREG32(GRBM_STATUS)); | 1418 | RREG32(GRBM_STATUS)); |
1359 | dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", | 1419 | dev_info(rdev->dev, " GRBM_STATUS_SE0=0x%08X\n", |
@@ -1464,6 +1524,10 @@ static int cayman_startup(struct radeon_device *rdev) | |||
1464 | return r; | 1524 | return r; |
1465 | } | 1525 | } |
1466 | 1526 | ||
1527 | r = radeon_vm_manager_start(rdev); | ||
1528 | if (r) | ||
1529 | return r; | ||
1530 | |||
1467 | return 0; | 1531 | return 0; |
1468 | } | 1532 | } |
1469 | 1533 | ||
@@ -1491,6 +1555,7 @@ int cayman_suspend(struct radeon_device *rdev) | |||
1491 | { | 1555 | { |
1492 | /* FIXME: we should wait for ring to be empty */ | 1556 | /* FIXME: we should wait for ring to be empty */ |
1493 | radeon_ib_pool_suspend(rdev); | 1557 | radeon_ib_pool_suspend(rdev); |
1558 | radeon_vm_manager_suspend(rdev); | ||
1494 | r600_blit_suspend(rdev); | 1559 | r600_blit_suspend(rdev); |
1495 | cayman_cp_enable(rdev, false); | 1560 | cayman_cp_enable(rdev, false); |
1496 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; | 1561 | rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; |
@@ -1577,6 +1642,10 @@ int cayman_init(struct radeon_device *rdev) | |||
1577 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); | 1642 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
1578 | rdev->accel_working = false; | 1643 | rdev->accel_working = false; |
1579 | } | 1644 | } |
1645 | r = radeon_vm_manager_init(rdev); | ||
1646 | if (r) { | ||
1647 | dev_err(rdev->dev, "vm manager initialization failed (%d).\n", r); | ||
1648 | } | ||
1580 | 1649 | ||
1581 | r = cayman_startup(rdev); | 1650 | r = cayman_startup(rdev); |
1582 | if (r) { | 1651 | if (r) { |
@@ -1585,6 +1654,7 @@ int cayman_init(struct radeon_device *rdev) | |||
1585 | r600_irq_fini(rdev); | 1654 | r600_irq_fini(rdev); |
1586 | radeon_wb_fini(rdev); | 1655 | radeon_wb_fini(rdev); |
1587 | r100_ib_fini(rdev); | 1656 | r100_ib_fini(rdev); |
1657 | radeon_vm_manager_fini(rdev); | ||
1588 | radeon_irq_kms_fini(rdev); | 1658 | radeon_irq_kms_fini(rdev); |
1589 | cayman_pcie_gart_fini(rdev); | 1659 | cayman_pcie_gart_fini(rdev); |
1590 | rdev->accel_working = false; | 1660 | rdev->accel_working = false; |
@@ -1608,6 +1678,7 @@ void cayman_fini(struct radeon_device *rdev) | |||
1608 | cayman_cp_fini(rdev); | 1678 | cayman_cp_fini(rdev); |
1609 | r600_irq_fini(rdev); | 1679 | r600_irq_fini(rdev); |
1610 | radeon_wb_fini(rdev); | 1680 | radeon_wb_fini(rdev); |
1681 | radeon_vm_manager_fini(rdev); | ||
1611 | r100_ib_fini(rdev); | 1682 | r100_ib_fini(rdev); |
1612 | radeon_irq_kms_fini(rdev); | 1683 | radeon_irq_kms_fini(rdev); |
1613 | cayman_pcie_gart_fini(rdev); | 1684 | cayman_pcie_gart_fini(rdev); |
@@ -1621,3 +1692,84 @@ void cayman_fini(struct radeon_device *rdev) | |||
1621 | rdev->bios = NULL; | 1692 | rdev->bios = NULL; |
1622 | } | 1693 | } |
1623 | 1694 | ||
1695 | /* | ||
1696 | * vm | ||
1697 | */ | ||
1698 | int cayman_vm_init(struct radeon_device *rdev) | ||
1699 | { | ||
1700 | /* number of VMs */ | ||
1701 | rdev->vm_manager.nvm = 8; | ||
1702 | /* base offset of vram pages */ | ||
1703 | rdev->vm_manager.vram_base_offset = 0; | ||
1704 | return 0; | ||
1705 | } | ||
1706 | |||
1707 | void cayman_vm_fini(struct radeon_device *rdev) | ||
1708 | { | ||
1709 | } | ||
1710 | |||
1711 | int cayman_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id) | ||
1712 | { | ||
1713 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (id << 2), 0); | ||
1714 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (id << 2), vm->last_pfn); | ||
1715 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (id << 2), vm->pt_gpu_addr >> 12); | ||
1716 | /* flush hdp cache */ | ||
1717 | WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); | ||
1718 | /* bits 0-7 are the VM contexts0-7 */ | ||
1719 | WREG32(VM_INVALIDATE_REQUEST, 1 << id); | ||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1723 | void cayman_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm) | ||
1724 | { | ||
1725 | WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (vm->id << 2), 0); | ||
1726 | WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0); | ||
1727 | WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0); | ||
1728 | /* flush hdp cache */ | ||
1729 | WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); | ||
1730 | /* bits 0-7 are the VM contexts0-7 */ | ||
1731 | WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); | ||
1732 | } | ||
1733 | |||
1734 | void cayman_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm) | ||
1735 | { | ||
1736 | if (vm->id == -1) | ||
1737 | return; | ||
1738 | |||
1739 | /* flush hdp cache */ | ||
1740 | WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); | ||
1741 | /* bits 0-7 are the VM contexts0-7 */ | ||
1742 | WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); | ||
1743 | } | ||
1744 | |||
1745 | #define R600_PTE_VALID (1 << 0) | ||
1746 | #define R600_PTE_SYSTEM (1 << 1) | ||
1747 | #define R600_PTE_SNOOPED (1 << 2) | ||
1748 | #define R600_PTE_READABLE (1 << 5) | ||
1749 | #define R600_PTE_WRITEABLE (1 << 6) | ||
1750 | |||
1751 | uint32_t cayman_vm_page_flags(struct radeon_device *rdev, | ||
1752 | struct radeon_vm *vm, | ||
1753 | uint32_t flags) | ||
1754 | { | ||
1755 | uint32_t r600_flags = 0; | ||
1756 | |||
1757 | r600_flags |= (flags & RADEON_VM_PAGE_VALID) ? R600_PTE_VALID : 0; | ||
1758 | r600_flags |= (flags & RADEON_VM_PAGE_READABLE) ? R600_PTE_READABLE : 0; | ||
1759 | r600_flags |= (flags & RADEON_VM_PAGE_WRITEABLE) ? R600_PTE_WRITEABLE : 0; | ||
1760 | if (flags & RADEON_VM_PAGE_SYSTEM) { | ||
1761 | r600_flags |= R600_PTE_SYSTEM; | ||
1762 | r600_flags |= (flags & RADEON_VM_PAGE_SNOOPED) ? R600_PTE_SNOOPED : 0; | ||
1763 | } | ||
1764 | return r600_flags; | ||
1765 | } | ||
1766 | |||
1767 | void cayman_vm_set_page(struct radeon_device *rdev, struct radeon_vm *vm, | ||
1768 | unsigned pfn, uint64_t addr, uint32_t flags) | ||
1769 | { | ||
1770 | void __iomem *ptr = (void *)vm->pt; | ||
1771 | |||
1772 | addr = addr & 0xFFFFFFFFFFFFF000ULL; | ||
1773 | addr |= flags; | ||
1774 | writeq(addr, ptr + (pfn * 8)); | ||
1775 | } | ||