diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/si_dma.c')
-rw-r--r-- | drivers/gpu/drm/radeon/si_dma.c | 172 |
1 files changed, 106 insertions, 66 deletions
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index e24c94b6d14d..716505129450 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c | |||
@@ -56,7 +56,41 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * si_dma_vm_set_page - update the page tables using the DMA | 59 | * si_dma_vm_copy_pages - update PTEs by copying them from the GART |
60 | * | ||
61 | * @rdev: radeon_device pointer | ||
62 | * @ib: indirect buffer to fill with commands | ||
63 | * @pe: addr of the page entry | ||
64 | * @src: src addr where to copy from | ||
65 | * @count: number of page entries to update | ||
66 | * | ||
67 | * Update PTEs by copying them from the GART using the DMA (SI). | ||
68 | */ | ||
69 | void si_dma_vm_copy_pages(struct radeon_device *rdev, | ||
70 | struct radeon_ib *ib, | ||
71 | uint64_t pe, uint64_t src, | ||
72 | unsigned count) | ||
73 | { | ||
74 | while (count) { | ||
75 | unsigned bytes = count * 8; | ||
76 | if (bytes > 0xFFFF8) | ||
77 | bytes = 0xFFFF8; | ||
78 | |||
79 | ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY, | ||
80 | 1, 0, 0, bytes); | ||
81 | ib->ptr[ib->length_dw++] = lower_32_bits(pe); | ||
82 | ib->ptr[ib->length_dw++] = lower_32_bits(src); | ||
83 | ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; | ||
84 | ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff; | ||
85 | |||
86 | pe += bytes; | ||
87 | src += bytes; | ||
88 | count -= bytes / 8; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * si_dma_vm_write_pages - update PTEs by writing them manually | ||
60 | * | 94 | * |
61 | * @rdev: radeon_device pointer | 95 | * @rdev: radeon_device pointer |
62 | * @ib: indirect buffer to fill with commands | 96 | * @ib: indirect buffer to fill with commands |
@@ -66,83 +100,89 @@ bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) | |||
66 | * @incr: increase next addr by incr bytes | 100 | * @incr: increase next addr by incr bytes |
67 | * @flags: access flags | 101 | * @flags: access flags |
68 | * | 102 | * |
69 | * Update the page tables using the DMA (SI). | 103 | * Update PTEs by writing them manually using the DMA (SI). |
70 | */ | 104 | */ |
71 | void si_dma_vm_set_page(struct radeon_device *rdev, | 105 | void si_dma_vm_write_pages(struct radeon_device *rdev, |
72 | struct radeon_ib *ib, | 106 | struct radeon_ib *ib, |
73 | uint64_t pe, | 107 | uint64_t pe, |
74 | uint64_t addr, unsigned count, | 108 | uint64_t addr, unsigned count, |
75 | uint32_t incr, uint32_t flags) | 109 | uint32_t incr, uint32_t flags) |
76 | { | 110 | { |
77 | uint64_t value; | 111 | uint64_t value; |
78 | unsigned ndw; | 112 | unsigned ndw; |
79 | 113 | ||
80 | trace_radeon_vm_set_page(pe, addr, count, incr, flags); | 114 | while (count) { |
81 | 115 | ndw = count * 2; | |
82 | if (flags == R600_PTE_GART) { | 116 | if (ndw > 0xFFFFE) |
83 | uint64_t src = rdev->gart.table_addr + (addr >> 12) * 8; | 117 | ndw = 0xFFFFE; |
84 | while (count) { | 118 | |
85 | unsigned bytes = count * 8; | 119 | /* for non-physically contiguous pages (system) */ |
86 | if (bytes > 0xFFFF8) | 120 | ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw); |
87 | bytes = 0xFFFF8; | 121 | ib->ptr[ib->length_dw++] = pe; |
88 | 122 | ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; | |
89 | ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY, | 123 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { |
90 | 1, 0, 0, bytes); | 124 | if (flags & R600_PTE_SYSTEM) { |
91 | ib->ptr[ib->length_dw++] = lower_32_bits(pe); | ||
92 | ib->ptr[ib->length_dw++] = lower_32_bits(src); | ||
93 | ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; | ||
94 | ib->ptr[ib->length_dw++] = upper_32_bits(src) & 0xff; | ||
95 | |||
96 | pe += bytes; | ||
97 | src += bytes; | ||
98 | count -= bytes / 8; | ||
99 | } | ||
100 | } else if (flags & R600_PTE_SYSTEM) { | ||
101 | while (count) { | ||
102 | ndw = count * 2; | ||
103 | if (ndw > 0xFFFFE) | ||
104 | ndw = 0xFFFFE; | ||
105 | |||
106 | /* for non-physically contiguous pages (system) */ | ||
107 | ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_WRITE, 0, 0, 0, ndw); | ||
108 | ib->ptr[ib->length_dw++] = pe; | ||
109 | ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; | ||
110 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { | ||
111 | value = radeon_vm_map_gart(rdev, addr); | 125 | value = radeon_vm_map_gart(rdev, addr); |
112 | value &= 0xFFFFFFFFFFFFF000ULL; | 126 | value &= 0xFFFFFFFFFFFFF000ULL; |
113 | addr += incr; | 127 | } else if (flags & R600_PTE_VALID) { |
114 | value |= flags; | ||
115 | ib->ptr[ib->length_dw++] = value; | ||
116 | ib->ptr[ib->length_dw++] = upper_32_bits(value); | ||
117 | } | ||
118 | } | ||
119 | } else { | ||
120 | while (count) { | ||
121 | ndw = count * 2; | ||
122 | if (ndw > 0xFFFFE) | ||
123 | ndw = 0xFFFFE; | ||
124 | |||
125 | if (flags & R600_PTE_VALID) | ||
126 | value = addr; | 128 | value = addr; |
127 | else | 129 | } else { |
128 | value = 0; | 130 | value = 0; |
129 | /* for physically contiguous pages (vram) */ | 131 | } |
130 | ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw); | 132 | addr += incr; |
131 | ib->ptr[ib->length_dw++] = pe; /* dst addr */ | 133 | value |= flags; |
132 | ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; | 134 | ib->ptr[ib->length_dw++] = value; |
133 | ib->ptr[ib->length_dw++] = flags; /* mask */ | ||
134 | ib->ptr[ib->length_dw++] = 0; | ||
135 | ib->ptr[ib->length_dw++] = value; /* value */ | ||
136 | ib->ptr[ib->length_dw++] = upper_32_bits(value); | 135 | ib->ptr[ib->length_dw++] = upper_32_bits(value); |
137 | ib->ptr[ib->length_dw++] = incr; /* increment size */ | ||
138 | ib->ptr[ib->length_dw++] = 0; | ||
139 | pe += ndw * 4; | ||
140 | addr += (ndw / 2) * incr; | ||
141 | count -= ndw / 2; | ||
142 | } | 136 | } |
143 | } | 137 | } |
144 | while (ib->length_dw & 0x7) | 138 | } |
145 | ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0); | 139 | |
140 | /** | ||
141 | * si_dma_vm_set_pages - update the page tables using the DMA | ||
142 | * | ||
143 | * @rdev: radeon_device pointer | ||
144 | * @ib: indirect buffer to fill with commands | ||
145 | * @pe: addr of the page entry | ||
146 | * @addr: dst addr to write into pe | ||
147 | * @count: number of page entries to update | ||
148 | * @incr: increase next addr by incr bytes | ||
149 | * @flags: access flags | ||
150 | * | ||
151 | * Update the page tables using the DMA (SI). | ||
152 | */ | ||
153 | void si_dma_vm_set_pages(struct radeon_device *rdev, | ||
154 | struct radeon_ib *ib, | ||
155 | uint64_t pe, | ||
156 | uint64_t addr, unsigned count, | ||
157 | uint32_t incr, uint32_t flags) | ||
158 | { | ||
159 | uint64_t value; | ||
160 | unsigned ndw; | ||
161 | |||
162 | while (count) { | ||
163 | ndw = count * 2; | ||
164 | if (ndw > 0xFFFFE) | ||
165 | ndw = 0xFFFFE; | ||
166 | |||
167 | if (flags & R600_PTE_VALID) | ||
168 | value = addr; | ||
169 | else | ||
170 | value = 0; | ||
171 | |||
172 | /* for physically contiguous pages (vram) */ | ||
173 | ib->ptr[ib->length_dw++] = DMA_PTE_PDE_PACKET(ndw); | ||
174 | ib->ptr[ib->length_dw++] = pe; /* dst addr */ | ||
175 | ib->ptr[ib->length_dw++] = upper_32_bits(pe) & 0xff; | ||
176 | ib->ptr[ib->length_dw++] = flags; /* mask */ | ||
177 | ib->ptr[ib->length_dw++] = 0; | ||
178 | ib->ptr[ib->length_dw++] = value; /* value */ | ||
179 | ib->ptr[ib->length_dw++] = upper_32_bits(value); | ||
180 | ib->ptr[ib->length_dw++] = incr; /* increment size */ | ||
181 | ib->ptr[ib->length_dw++] = 0; | ||
182 | pe += ndw * 4; | ||
183 | addr += (ndw / 2) * incr; | ||
184 | count -= ndw / 2; | ||
185 | } | ||
146 | } | 186 | } |
147 | 187 | ||
148 | void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) | 188 | void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm) |