|
25 | 25 | * superpage bit set.
|
26 | 26 | */
|
27 | 27 | #define V3D_PTE_SUPERPAGE BIT(31)
|
| 28 | +#define V3D_PTE_BIGPAGE BIT(30) |
28 | 29 | #define V3D_PTE_WRITEABLE BIT(29)
|
29 | 30 | #define V3D_PTE_VALID BIT(28)
|
30 | 31 |
|
| 32 | +static bool v3d_mmu_is_aligned(u32 page, u32 page_address, size_t alignment) |
| 33 | +{ |
| 34 | + return IS_ALIGNED(page, alignment >> V3D_MMU_PAGE_SHIFT) && |
| 35 | + IS_ALIGNED(page_address, alignment >> V3D_MMU_PAGE_SHIFT); |
| 36 | +} |
| 37 | + |
31 | 38 | int v3d_mmu_flush_all(struct v3d_dev *v3d)
|
32 | 39 | {
|
33 | 40 | int ret;
|
@@ -78,19 +85,40 @@ void v3d_mmu_insert_ptes(struct v3d_bo *bo)
|
78 | 85 | struct drm_gem_shmem_object *shmem_obj = &bo->base;
|
79 | 86 | struct v3d_dev *v3d = to_v3d_dev(shmem_obj->base.dev);
|
80 | 87 | u32 page = bo->node.start;
|
81 |
| - u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID; |
82 |
| - struct sg_dma_page_iter dma_iter; |
83 |
| - |
84 |
| - for_each_sgtable_dma_page(shmem_obj->sgt, &dma_iter, 0) { |
85 |
| - dma_addr_t dma_addr = sg_page_iter_dma_address(&dma_iter); |
86 |
| - u32 page_address = dma_addr >> V3D_MMU_PAGE_SHIFT; |
87 |
| - u32 pte = page_prot | page_address; |
88 |
| - u32 i; |
89 |
| - |
90 |
| - BUG_ON(page_address + (PAGE_SIZE >> V3D_MMU_PAGE_SHIFT) >= |
91 |
| - BIT(24)); |
92 |
| - for (i = 0; i < PAGE_SIZE >> V3D_MMU_PAGE_SHIFT; i++) |
93 |
| - v3d->pt[page++] = pte + i; |
| 88 | + struct scatterlist *sgl; |
| 89 | + unsigned int count; |
| 90 | + |
| 91 | + for_each_sgtable_dma_sg(shmem_obj->sgt, sgl, count) { |
| 92 | + dma_addr_t dma_addr = sg_dma_address(sgl); |
| 93 | + u32 pfn = dma_addr >> V3D_MMU_PAGE_SHIFT; |
| 94 | + unsigned int len = sg_dma_len(sgl); |
| 95 | + |
| 96 | + while (len > 0) { |
| 97 | + u32 page_prot = V3D_PTE_WRITEABLE | V3D_PTE_VALID; |
| 98 | + u32 page_address = page_prot | pfn; |
| 99 | + unsigned int i, page_size; |
| 100 | + |
| 101 | + BUG_ON(pfn + V3D_PAGE_FACTOR >= BIT(24)); |
| 102 | + |
| 103 | + if (len >= SZ_1M && |
| 104 | + v3d_mmu_is_aligned(page, page_address, SZ_1M)) { |
| 105 | + page_size = SZ_1M; |
| 106 | + page_address |= V3D_PTE_SUPERPAGE; |
| 107 | + } else if (len >= SZ_64K && |
| 108 | + v3d_mmu_is_aligned(page, page_address, SZ_64K)) { |
| 109 | + page_size = SZ_64K; |
| 110 | + page_address |= V3D_PTE_BIGPAGE; |
| 111 | + } else { |
| 112 | + page_size = SZ_4K; |
| 113 | + } |
| 114 | + |
| 115 | + for (i = 0; i < page_size >> V3D_MMU_PAGE_SHIFT; i++) { |
| 116 | + v3d->pt[page++] = page_address + i; |
| 117 | + pfn++; |
| 118 | + } |
| 119 | + |
| 120 | + len -= page_size; |
| 121 | + } |
94 | 122 | }
|
95 | 123 |
|
96 | 124 | WARN_ON_ONCE(page - bo->node.start !=
|
|
0 commit comments