1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot * Copyright 2008 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc.
4926deccbSFrançois Tigeot * Copyright 2009 Jerome Glisse.
5926deccbSFrançois Tigeot *
6926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
7926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"),
8926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation
9926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the
11926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions:
12926deccbSFrançois Tigeot *
13926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in
14926deccbSFrançois Tigeot * all copies or substantial portions of the Software.
15926deccbSFrançois Tigeot *
16926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE.
23926deccbSFrançois Tigeot *
24926deccbSFrançois Tigeot * Authors: Dave Airlie
25926deccbSFrançois Tigeot * Alex Deucher
26926deccbSFrançois Tigeot * Jerome Glisse
27926deccbSFrançois Tigeot */
28926deccbSFrançois Tigeot #include <drm/drmP.h>
2983b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h>
30*a85cb24fSFrançois Tigeot #ifdef CONFIG_X86
31*a85cb24fSFrançois Tigeot #include <asm/set_memory.h>
32*a85cb24fSFrançois Tigeot #endif
33926deccbSFrançois Tigeot #include "radeon.h"
34926deccbSFrançois Tigeot
35926deccbSFrançois Tigeot /*
36926deccbSFrançois Tigeot * GART
37926deccbSFrançois Tigeot * The GART (Graphics Aperture Remapping Table) is an aperture
38926deccbSFrançois Tigeot * in the GPU's address space. System pages can be mapped into
39926deccbSFrançois Tigeot * the aperture and look like contiguous pages from the GPU's
40926deccbSFrançois Tigeot * perspective. A page table maps the pages in the aperture
41926deccbSFrançois Tigeot * to the actual backing pages in system memory.
42926deccbSFrançois Tigeot *
43926deccbSFrançois Tigeot * Radeon GPUs support both an internal GART, as described above,
44926deccbSFrançois Tigeot * and AGP. AGP works similarly, but the GART table is configured
45926deccbSFrançois Tigeot * and maintained by the northbridge rather than the driver.
46926deccbSFrançois Tigeot * Radeon hw has a separate AGP aperture that is programmed to
47926deccbSFrançois Tigeot * point to the AGP aperture provided by the northbridge and the
48926deccbSFrançois Tigeot * requests are passed through to the northbridge aperture.
49926deccbSFrançois Tigeot * Both AGP and internal GART can be used at the same time, however
50926deccbSFrançois Tigeot * that is not currently supported by the driver.
51926deccbSFrançois Tigeot *
52926deccbSFrançois Tigeot * This file handles the common internal GART management.
53926deccbSFrançois Tigeot */
54926deccbSFrançois Tigeot
55926deccbSFrançois Tigeot /*
56926deccbSFrançois Tigeot * Common GART table functions.
57926deccbSFrançois Tigeot */
58926deccbSFrançois Tigeot /**
59926deccbSFrançois Tigeot * radeon_gart_table_ram_alloc - allocate system ram for gart page table
60926deccbSFrançois Tigeot *
61926deccbSFrançois Tigeot * @rdev: radeon_device pointer
62926deccbSFrançois Tigeot *
63926deccbSFrançois Tigeot * Allocate system memory for GART page table
64926deccbSFrançois Tigeot * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the
65926deccbSFrançois Tigeot * gart table to be in system memory.
66926deccbSFrançois Tigeot * Returns 0 for success, -ENOMEM for failure.
67926deccbSFrançois Tigeot */
radeon_gart_table_ram_alloc(struct radeon_device * rdev)68926deccbSFrançois Tigeot int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
69926deccbSFrançois Tigeot {
70f3ac4187SFrançois Tigeot void *ptr;
71926deccbSFrançois Tigeot
72f3ac4187SFrançois Tigeot ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size,
73f3ac4187SFrançois Tigeot &rdev->gart.table_addr);
74f3ac4187SFrançois Tigeot if (ptr == NULL) {
75926deccbSFrançois Tigeot return -ENOMEM;
76926deccbSFrançois Tigeot }
77f3ac4187SFrançois Tigeot #ifdef CONFIG_X86
78926deccbSFrançois Tigeot if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
79926deccbSFrançois Tigeot rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
80f3ac4187SFrançois Tigeot set_memory_uc((unsigned long)ptr,
81f3ac4187SFrançois Tigeot rdev->gart.table_size >> PAGE_SHIFT);
82926deccbSFrançois Tigeot }
83926deccbSFrançois Tigeot #endif
84f3ac4187SFrançois Tigeot rdev->gart.ptr = ptr;
85926deccbSFrançois Tigeot memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size);
86926deccbSFrançois Tigeot return 0;
87926deccbSFrançois Tigeot }
88926deccbSFrançois Tigeot
89926deccbSFrançois Tigeot /**
90926deccbSFrançois Tigeot * radeon_gart_table_ram_free - free system ram for gart page table
91926deccbSFrançois Tigeot *
92926deccbSFrançois Tigeot * @rdev: radeon_device pointer
93926deccbSFrançois Tigeot *
94926deccbSFrançois Tigeot * Free system memory for GART page table
95926deccbSFrançois Tigeot * (r1xx-r3xx, non-pcie r4xx, rs400). These asics require the
96926deccbSFrançois Tigeot * gart table to be in system memory.
97926deccbSFrançois Tigeot */
radeon_gart_table_ram_free(struct radeon_device * rdev)98926deccbSFrançois Tigeot void radeon_gart_table_ram_free(struct radeon_device *rdev)
99926deccbSFrançois Tigeot {
100926deccbSFrançois Tigeot if (rdev->gart.ptr == NULL) {
101926deccbSFrançois Tigeot return;
102926deccbSFrançois Tigeot }
103*a85cb24fSFrançois Tigeot #ifdef CONFIG_X86
104926deccbSFrançois Tigeot if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
105926deccbSFrançois Tigeot rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
106*a85cb24fSFrançois Tigeot set_memory_wb((unsigned long)rdev->gart.ptr,
107*a85cb24fSFrançois Tigeot rdev->gart.table_size >> PAGE_SHIFT);
108926deccbSFrançois Tigeot }
109926deccbSFrançois Tigeot #endif
110*a85cb24fSFrançois Tigeot pci_free_consistent(rdev->pdev, rdev->gart.table_size,
111*a85cb24fSFrançois Tigeot (void *)rdev->gart.ptr,
112*a85cb24fSFrançois Tigeot rdev->gart.table_addr);
113926deccbSFrançois Tigeot rdev->gart.ptr = NULL;
114926deccbSFrançois Tigeot rdev->gart.table_addr = 0;
115926deccbSFrançois Tigeot }
116926deccbSFrançois Tigeot
117926deccbSFrançois Tigeot /**
118926deccbSFrançois Tigeot * radeon_gart_table_vram_alloc - allocate vram for gart page table
119926deccbSFrançois Tigeot *
120926deccbSFrançois Tigeot * @rdev: radeon_device pointer
121926deccbSFrançois Tigeot *
122926deccbSFrançois Tigeot * Allocate video memory for GART page table
123926deccbSFrançois Tigeot * (pcie r4xx, r5xx+). These asics require the
124926deccbSFrançois Tigeot * gart table to be in video memory.
125926deccbSFrançois Tigeot * Returns 0 for success, error for failure.
126926deccbSFrançois Tigeot */
radeon_gart_table_vram_alloc(struct radeon_device * rdev)127926deccbSFrançois Tigeot int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
128926deccbSFrançois Tigeot {
129926deccbSFrançois Tigeot int r;
130926deccbSFrançois Tigeot
131926deccbSFrançois Tigeot if (rdev->gart.robj == NULL) {
132926deccbSFrançois Tigeot r = radeon_bo_create(rdev, rdev->gart.table_size,
133926deccbSFrançois Tigeot PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
1347dcf36dcSFrançois Tigeot 0, NULL, NULL, &rdev->gart.robj);
135926deccbSFrançois Tigeot if (r) {
136926deccbSFrançois Tigeot return r;
137926deccbSFrançois Tigeot }
138926deccbSFrançois Tigeot }
139926deccbSFrançois Tigeot return 0;
140926deccbSFrançois Tigeot }
141926deccbSFrançois Tigeot
142926deccbSFrançois Tigeot /**
143926deccbSFrançois Tigeot * radeon_gart_table_vram_pin - pin gart page table in vram
144926deccbSFrançois Tigeot *
145926deccbSFrançois Tigeot * @rdev: radeon_device pointer
146926deccbSFrançois Tigeot *
147926deccbSFrançois Tigeot * Pin the GART page table in vram so it will not be moved
148926deccbSFrançois Tigeot * by the memory manager (pcie r4xx, r5xx+). These asics require the
149926deccbSFrançois Tigeot * gart table to be in video memory.
150926deccbSFrançois Tigeot * Returns 0 for success, error for failure.
151926deccbSFrançois Tigeot */
radeon_gart_table_vram_pin(struct radeon_device * rdev)152926deccbSFrançois Tigeot int radeon_gart_table_vram_pin(struct radeon_device *rdev)
153926deccbSFrançois Tigeot {
154ee479021SImre Vadász u64 gpu_addr;
155926deccbSFrançois Tigeot int r;
156926deccbSFrançois Tigeot
157926deccbSFrançois Tigeot r = radeon_bo_reserve(rdev->gart.robj, false);
158926deccbSFrançois Tigeot if (unlikely(r != 0))
159926deccbSFrançois Tigeot return r;
160926deccbSFrançois Tigeot r = radeon_bo_pin(rdev->gart.robj,
161ee479021SImre Vadász RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
162926deccbSFrançois Tigeot if (r) {
163926deccbSFrançois Tigeot radeon_bo_unreserve(rdev->gart.robj);
164926deccbSFrançois Tigeot return r;
165926deccbSFrançois Tigeot }
166926deccbSFrançois Tigeot r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr);
167926deccbSFrançois Tigeot if (r)
168926deccbSFrançois Tigeot radeon_bo_unpin(rdev->gart.robj);
169926deccbSFrançois Tigeot radeon_bo_unreserve(rdev->gart.robj);
170926deccbSFrançois Tigeot rdev->gart.table_addr = gpu_addr;
1717dcf36dcSFrançois Tigeot
1727dcf36dcSFrançois Tigeot if (!r) {
1737dcf36dcSFrançois Tigeot int i;
1747dcf36dcSFrançois Tigeot
1757dcf36dcSFrançois Tigeot /* We might have dropped some GART table updates while it wasn't
1767dcf36dcSFrançois Tigeot * mapped, restore all entries
1777dcf36dcSFrançois Tigeot */
1787dcf36dcSFrançois Tigeot for (i = 0; i < rdev->gart.num_gpu_pages; i++)
1797dcf36dcSFrançois Tigeot radeon_gart_set_page(rdev, i, rdev->gart.pages_entry[i]);
1807dcf36dcSFrançois Tigeot mb();
1817dcf36dcSFrançois Tigeot radeon_gart_tlb_flush(rdev);
1827dcf36dcSFrançois Tigeot }
1837dcf36dcSFrançois Tigeot
184926deccbSFrançois Tigeot return r;
185926deccbSFrançois Tigeot }
186926deccbSFrançois Tigeot
187926deccbSFrançois Tigeot /**
188926deccbSFrançois Tigeot * radeon_gart_table_vram_unpin - unpin gart page table in vram
189926deccbSFrançois Tigeot *
190926deccbSFrançois Tigeot * @rdev: radeon_device pointer
191926deccbSFrançois Tigeot *
192926deccbSFrançois Tigeot * Unpin the GART page table in vram (pcie r4xx, r5xx+).
193926deccbSFrançois Tigeot * These asics require the gart table to be in video memory.
194926deccbSFrançois Tigeot */
radeon_gart_table_vram_unpin(struct radeon_device * rdev)195926deccbSFrançois Tigeot void radeon_gart_table_vram_unpin(struct radeon_device *rdev)
196926deccbSFrançois Tigeot {
197926deccbSFrançois Tigeot int r;
198926deccbSFrançois Tigeot
199926deccbSFrançois Tigeot if (rdev->gart.robj == NULL) {
200926deccbSFrançois Tigeot return;
201926deccbSFrançois Tigeot }
202926deccbSFrançois Tigeot r = radeon_bo_reserve(rdev->gart.robj, false);
203926deccbSFrançois Tigeot if (likely(r == 0)) {
204926deccbSFrançois Tigeot radeon_bo_kunmap(rdev->gart.robj);
205926deccbSFrançois Tigeot radeon_bo_unpin(rdev->gart.robj);
206926deccbSFrançois Tigeot radeon_bo_unreserve(rdev->gart.robj);
207926deccbSFrançois Tigeot rdev->gart.ptr = NULL;
208926deccbSFrançois Tigeot }
209926deccbSFrançois Tigeot }
210926deccbSFrançois Tigeot
211926deccbSFrançois Tigeot /**
212926deccbSFrançois Tigeot * radeon_gart_table_vram_free - free gart page table vram
213926deccbSFrançois Tigeot *
214926deccbSFrançois Tigeot * @rdev: radeon_device pointer
215926deccbSFrançois Tigeot *
216926deccbSFrançois Tigeot * Free the video memory used for the GART page table
217926deccbSFrançois Tigeot * (pcie r4xx, r5xx+). These asics require the gart table to
218926deccbSFrançois Tigeot * be in video memory.
219926deccbSFrançois Tigeot */
radeon_gart_table_vram_free(struct radeon_device * rdev)220926deccbSFrançois Tigeot void radeon_gart_table_vram_free(struct radeon_device *rdev)
221926deccbSFrançois Tigeot {
222926deccbSFrançois Tigeot if (rdev->gart.robj == NULL) {
223926deccbSFrançois Tigeot return;
224926deccbSFrançois Tigeot }
225926deccbSFrançois Tigeot radeon_bo_unref(&rdev->gart.robj);
226926deccbSFrançois Tigeot }
227926deccbSFrançois Tigeot
228926deccbSFrançois Tigeot /*
229926deccbSFrançois Tigeot * Common gart functions.
230926deccbSFrançois Tigeot */
231926deccbSFrançois Tigeot /**
232926deccbSFrançois Tigeot * radeon_gart_unbind - unbind pages from the gart page table
233926deccbSFrançois Tigeot *
234926deccbSFrançois Tigeot * @rdev: radeon_device pointer
235926deccbSFrançois Tigeot * @offset: offset into the GPU's gart aperture
236926deccbSFrançois Tigeot * @pages: number of pages to unbind
237926deccbSFrançois Tigeot *
238926deccbSFrançois Tigeot * Unbinds the requested pages from the gart page table and
239926deccbSFrançois Tigeot * replaces them with the dummy page (all asics).
240926deccbSFrançois Tigeot */
radeon_gart_unbind(struct radeon_device * rdev,unsigned offset,int pages)241926deccbSFrançois Tigeot void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
242926deccbSFrançois Tigeot int pages)
243926deccbSFrançois Tigeot {
244926deccbSFrançois Tigeot unsigned t;
245926deccbSFrançois Tigeot unsigned p;
246926deccbSFrançois Tigeot int i, j;
247926deccbSFrançois Tigeot
248926deccbSFrançois Tigeot if (!rdev->gart.ready) {
249c4ef309bSzrj WARN(1, "trying to unbind memory from uninitialized GART !\n");
250926deccbSFrançois Tigeot return;
251926deccbSFrançois Tigeot }
252926deccbSFrançois Tigeot t = offset / RADEON_GPU_PAGE_SIZE;
253926deccbSFrançois Tigeot p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
254926deccbSFrançois Tigeot for (i = 0; i < pages; i++, p++) {
255926deccbSFrançois Tigeot if (rdev->gart.pages[p]) {
256926deccbSFrançois Tigeot rdev->gart.pages[p] = NULL;
257926deccbSFrançois Tigeot for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
2587dcf36dcSFrançois Tigeot rdev->gart.pages_entry[t] = rdev->dummy_page.entry;
259926deccbSFrançois Tigeot if (rdev->gart.ptr) {
2607dcf36dcSFrançois Tigeot radeon_gart_set_page(rdev, t,
2617dcf36dcSFrançois Tigeot rdev->dummy_page.entry);
262ee479021SImre Vadász }
263926deccbSFrançois Tigeot }
264926deccbSFrançois Tigeot }
265926deccbSFrançois Tigeot }
266c59a5c48SFrançois Tigeot if (rdev->gart.ptr) {
267c4ef309bSzrj mb();
268926deccbSFrançois Tigeot radeon_gart_tlb_flush(rdev);
269926deccbSFrançois Tigeot }
270c59a5c48SFrançois Tigeot }
271926deccbSFrançois Tigeot
272926deccbSFrançois Tigeot /**
273926deccbSFrançois Tigeot * radeon_gart_bind - bind pages into the gart page table
274926deccbSFrançois Tigeot *
275926deccbSFrançois Tigeot * @rdev: radeon_device pointer
276926deccbSFrançois Tigeot * @offset: offset into the GPU's gart aperture
277926deccbSFrançois Tigeot * @pages: number of pages to bind
278926deccbSFrançois Tigeot * @pagelist: pages to bind
279926deccbSFrançois Tigeot * @dma_addr: DMA addresses of pages
280c6f73aabSFrançois Tigeot * @flags: RADEON_GART_PAGE_* flags
281926deccbSFrançois Tigeot *
282926deccbSFrançois Tigeot * Binds the requested pages to the gart page table
283926deccbSFrançois Tigeot * (all asics).
284926deccbSFrançois Tigeot * Returns 0 for success, -EINVAL for failure.
285926deccbSFrançois Tigeot */
radeon_gart_bind(struct radeon_device * rdev,unsigned offset,int pages,struct page ** pagelist,dma_addr_t * dma_addr,uint32_t flags)286926deccbSFrançois Tigeot int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
287f0bba3d1SFrançois Tigeot int pages, struct page **pagelist, dma_addr_t *dma_addr,
288c6f73aabSFrançois Tigeot uint32_t flags)
289926deccbSFrançois Tigeot {
290926deccbSFrançois Tigeot unsigned t;
291926deccbSFrançois Tigeot unsigned p;
2927dcf36dcSFrançois Tigeot uint64_t page_base, page_entry;
293926deccbSFrançois Tigeot int i, j;
294926deccbSFrançois Tigeot
295926deccbSFrançois Tigeot if (!rdev->gart.ready) {
296c4ef309bSzrj WARN(1, "trying to bind memory to uninitialized GART !\n");
297926deccbSFrançois Tigeot return -EINVAL;
298926deccbSFrançois Tigeot }
299926deccbSFrançois Tigeot t = offset / RADEON_GPU_PAGE_SIZE;
300926deccbSFrançois Tigeot p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
301926deccbSFrançois Tigeot
302926deccbSFrançois Tigeot for (i = 0; i < pages; i++, p++) {
303926deccbSFrançois Tigeot rdev->gart.pages[p] = pagelist[i];
3047dcf36dcSFrançois Tigeot page_base = dma_addr[i];
305ee479021SImre Vadász for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
3067dcf36dcSFrançois Tigeot page_entry = radeon_gart_get_page_entry(page_base, flags);
3077dcf36dcSFrançois Tigeot rdev->gart.pages_entry[t] = page_entry;
3087dcf36dcSFrançois Tigeot if (rdev->gart.ptr) {
3097dcf36dcSFrançois Tigeot radeon_gart_set_page(rdev, t, page_entry);
310926deccbSFrançois Tigeot }
3117dcf36dcSFrançois Tigeot page_base += RADEON_GPU_PAGE_SIZE;
312926deccbSFrançois Tigeot }
313ee479021SImre Vadász }
314c59a5c48SFrançois Tigeot if (rdev->gart.ptr) {
315c4ef309bSzrj mb();
316926deccbSFrançois Tigeot radeon_gart_tlb_flush(rdev);
317c59a5c48SFrançois Tigeot }
318926deccbSFrançois Tigeot return 0;
319926deccbSFrançois Tigeot }
320926deccbSFrançois Tigeot
321926deccbSFrançois Tigeot /**
322926deccbSFrançois Tigeot * radeon_gart_init - init the driver info for managing the gart
323926deccbSFrançois Tigeot *
324926deccbSFrançois Tigeot * @rdev: radeon_device pointer
325926deccbSFrançois Tigeot *
326926deccbSFrançois Tigeot * Allocate the dummy page and init the gart driver info (all asics).
327926deccbSFrançois Tigeot * Returns 0 for success, error for failure.
328926deccbSFrançois Tigeot */
radeon_gart_init(struct radeon_device * rdev)329926deccbSFrançois Tigeot int radeon_gart_init(struct radeon_device *rdev)
330926deccbSFrançois Tigeot {
331926deccbSFrançois Tigeot int r, i;
332926deccbSFrançois Tigeot
333926deccbSFrançois Tigeot if (rdev->gart.pages) {
334926deccbSFrançois Tigeot return 0;
335926deccbSFrançois Tigeot }
336926deccbSFrançois Tigeot /* We need PAGE_SIZE >= RADEON_GPU_PAGE_SIZE */
337926deccbSFrançois Tigeot if (PAGE_SIZE < RADEON_GPU_PAGE_SIZE) {
338926deccbSFrançois Tigeot DRM_ERROR("Page size is smaller than GPU page size!\n");
339926deccbSFrançois Tigeot return -EINVAL;
340926deccbSFrançois Tigeot }
341926deccbSFrançois Tigeot r = radeon_dummy_page_init(rdev);
342926deccbSFrançois Tigeot if (r)
343926deccbSFrançois Tigeot return r;
344926deccbSFrançois Tigeot /* Compute table size */
345926deccbSFrançois Tigeot rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE;
346926deccbSFrançois Tigeot rdev->gart.num_gpu_pages = rdev->mc.gtt_size / RADEON_GPU_PAGE_SIZE;
347926deccbSFrançois Tigeot DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
348926deccbSFrançois Tigeot rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
349926deccbSFrançois Tigeot /* Allocate pages table */
3507dcf36dcSFrançois Tigeot rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);
351926deccbSFrançois Tigeot if (rdev->gart.pages == NULL) {
352926deccbSFrançois Tigeot radeon_gart_fini(rdev);
353926deccbSFrançois Tigeot return -ENOMEM;
354926deccbSFrançois Tigeot }
3557dcf36dcSFrançois Tigeot rdev->gart.pages_entry = vmalloc(sizeof(uint64_t) *
3567dcf36dcSFrançois Tigeot rdev->gart.num_gpu_pages);
3577dcf36dcSFrançois Tigeot if (rdev->gart.pages_entry == NULL) {
358926deccbSFrançois Tigeot radeon_gart_fini(rdev);
359926deccbSFrançois Tigeot return -ENOMEM;
360926deccbSFrançois Tigeot }
361926deccbSFrançois Tigeot /* set GART entry to point to the dummy page by default */
3627dcf36dcSFrançois Tigeot for (i = 0; i < rdev->gart.num_gpu_pages; i++)
3637dcf36dcSFrançois Tigeot rdev->gart.pages_entry[i] = rdev->dummy_page.entry;
364926deccbSFrançois Tigeot return 0;
365926deccbSFrançois Tigeot }
366926deccbSFrançois Tigeot
367926deccbSFrançois Tigeot /**
368926deccbSFrançois Tigeot * radeon_gart_fini - tear down the driver info for managing the gart
369926deccbSFrançois Tigeot *
370926deccbSFrançois Tigeot * @rdev: radeon_device pointer
371926deccbSFrançois Tigeot *
372926deccbSFrançois Tigeot * Tear down the gart driver info and free the dummy page (all asics).
373926deccbSFrançois Tigeot */
radeon_gart_fini(struct radeon_device * rdev)374926deccbSFrançois Tigeot void radeon_gart_fini(struct radeon_device *rdev)
375926deccbSFrançois Tigeot {
3767dcf36dcSFrançois Tigeot if (rdev->gart.ready) {
377926deccbSFrançois Tigeot /* unbind pages */
378926deccbSFrançois Tigeot radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
379926deccbSFrançois Tigeot }
380926deccbSFrançois Tigeot rdev->gart.ready = false;
3817dcf36dcSFrançois Tigeot vfree(rdev->gart.pages);
3827dcf36dcSFrançois Tigeot vfree(rdev->gart.pages_entry);
383926deccbSFrançois Tigeot rdev->gart.pages = NULL;
3847dcf36dcSFrançois Tigeot rdev->gart.pages_entry = NULL;
385926deccbSFrançois Tigeot
386926deccbSFrançois Tigeot radeon_dummy_page_fini(rdev);
387926deccbSFrançois Tigeot }
388