1 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
2 /**************************************************************************
4 * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 * USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
29 * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
32 #define pr_fmt(fmt) "[TTM] " fmt
34 #include <linux/sched.h>
35 #include <linux/pagemap.h>
36 #include <linux/shmem_fs.h>
37 #include <linux/file.h>
38 #include <drm/drm_cache.h>
39 #include <drm/ttm/ttm_bo_driver.h>
42 * Allocates a ttm structure for the given BO.
44 int ttm_tt_create(struct ttm_buffer_object
*bo
, bool zero_alloc
)
46 struct ttm_bo_device
*bdev
= bo
->bdev
;
47 uint32_t page_flags
= 0;
49 dma_resv_assert_held(bo
->base
.resv
);
55 case ttm_bo_type_device
:
57 page_flags
|= TTM_PAGE_FLAG_ZERO_ALLOC
;
59 case ttm_bo_type_kernel
:
62 page_flags
|= TTM_PAGE_FLAG_SG
;
65 pr_err("Illegal buffer object type\n");
69 bo
->ttm
= bdev
->driver
->ttm_tt_create(bo
, page_flags
);
70 if (unlikely(bo
->ttm
== NULL
))
77 * Allocates storage for pointers to the pages that back the ttm.
79 static int ttm_tt_alloc_page_directory(struct ttm_tt
*ttm
)
81 ttm
->pages
= kvmalloc_array(ttm
->num_pages
, sizeof(void*),
82 GFP_KERNEL
| __GFP_ZERO
);
88 static int ttm_dma_tt_alloc_page_directory(struct ttm_tt
*ttm
)
90 ttm
->pages
= kvmalloc_array(ttm
->num_pages
,
92 sizeof(*ttm
->dma_address
),
93 GFP_KERNEL
| __GFP_ZERO
);
97 ttm
->dma_address
= (void *)(ttm
->pages
+ ttm
->num_pages
);
101 static int ttm_sg_tt_alloc_page_directory(struct ttm_tt
*ttm
)
103 ttm
->dma_address
= kvmalloc_array(ttm
->num_pages
,
104 sizeof(*ttm
->dma_address
),
105 GFP_KERNEL
| __GFP_ZERO
);
106 if (!ttm
->dma_address
)
111 void ttm_tt_destroy_common(struct ttm_bo_device
*bdev
, struct ttm_tt
*ttm
)
113 ttm_tt_unpopulate(bdev
, ttm
);
115 if (ttm
->swap_storage
)
116 fput(ttm
->swap_storage
);
118 ttm
->swap_storage
= NULL
;
120 EXPORT_SYMBOL(ttm_tt_destroy_common
);
122 void ttm_tt_destroy(struct ttm_bo_device
*bdev
, struct ttm_tt
*ttm
)
124 bdev
->driver
->ttm_tt_destroy(bdev
, ttm
);
127 static void ttm_tt_init_fields(struct ttm_tt
*ttm
,
128 struct ttm_buffer_object
*bo
,
130 enum ttm_caching caching
)
132 ttm
->num_pages
= bo
->num_pages
;
133 ttm
->caching
= ttm_cached
;
134 ttm
->page_flags
= page_flags
;
135 ttm
->dma_address
= NULL
;
136 ttm
->swap_storage
= NULL
;
138 ttm
->caching
= caching
;
141 int ttm_tt_init(struct ttm_tt
*ttm
, struct ttm_buffer_object
*bo
,
142 uint32_t page_flags
, enum ttm_caching caching
)
144 ttm_tt_init_fields(ttm
, bo
, page_flags
, caching
);
146 if (ttm_tt_alloc_page_directory(ttm
)) {
147 pr_err("Failed allocating page table\n");
152 EXPORT_SYMBOL(ttm_tt_init
);
154 void ttm_tt_fini(struct ttm_tt
*ttm
)
159 kvfree(ttm
->dma_address
);
161 ttm
->dma_address
= NULL
;
163 EXPORT_SYMBOL(ttm_tt_fini
);
165 int ttm_dma_tt_init(struct ttm_tt
*ttm
, struct ttm_buffer_object
*bo
,
166 uint32_t page_flags
, enum ttm_caching caching
)
168 ttm_tt_init_fields(ttm
, bo
, page_flags
, caching
);
170 if (ttm_dma_tt_alloc_page_directory(ttm
)) {
171 pr_err("Failed allocating page table\n");
176 EXPORT_SYMBOL(ttm_dma_tt_init
);
178 int ttm_sg_tt_init(struct ttm_tt
*ttm
, struct ttm_buffer_object
*bo
,
179 uint32_t page_flags
, enum ttm_caching caching
)
183 ttm_tt_init_fields(ttm
, bo
, page_flags
, caching
);
185 if (page_flags
& TTM_PAGE_FLAG_SG
)
186 ret
= ttm_sg_tt_alloc_page_directory(ttm
);
188 ret
= ttm_dma_tt_alloc_page_directory(ttm
);
190 pr_err("Failed allocating page table\n");
195 EXPORT_SYMBOL(ttm_sg_tt_init
);
197 int ttm_tt_swapin(struct ttm_tt
*ttm
)
199 struct address_space
*swap_space
;
200 struct file
*swap_storage
;
201 struct page
*from_page
;
202 struct page
*to_page
;
206 swap_storage
= ttm
->swap_storage
;
207 BUG_ON(swap_storage
== NULL
);
209 swap_space
= swap_storage
->f_mapping
;
210 gfp_mask
= mapping_gfp_mask(swap_space
);
212 for (i
= 0; i
< ttm
->num_pages
; ++i
) {
213 from_page
= shmem_read_mapping_page_gfp(swap_space
, i
,
215 if (IS_ERR(from_page
)) {
216 ret
= PTR_ERR(from_page
);
219 to_page
= ttm
->pages
[i
];
220 if (unlikely(to_page
== NULL
)) {
225 copy_highpage(to_page
, from_page
);
230 ttm
->swap_storage
= NULL
;
231 ttm
->page_flags
&= ~TTM_PAGE_FLAG_SWAPPED
;
239 int ttm_tt_swapout(struct ttm_bo_device
*bdev
, struct ttm_tt
*ttm
)
241 struct address_space
*swap_space
;
242 struct file
*swap_storage
;
243 struct page
*from_page
;
244 struct page
*to_page
;
248 swap_storage
= shmem_file_setup("ttm swap",
249 ttm
->num_pages
<< PAGE_SHIFT
,
251 if (IS_ERR(swap_storage
)) {
252 pr_err("Failed allocating swap storage\n");
253 return PTR_ERR(swap_storage
);
256 swap_space
= swap_storage
->f_mapping
;
257 gfp_mask
= mapping_gfp_mask(swap_space
);
259 for (i
= 0; i
< ttm
->num_pages
; ++i
) {
260 from_page
= ttm
->pages
[i
];
261 if (unlikely(from_page
== NULL
))
264 to_page
= shmem_read_mapping_page_gfp(swap_space
, i
, gfp_mask
);
265 if (IS_ERR(to_page
)) {
266 ret
= PTR_ERR(to_page
);
269 copy_highpage(to_page
, from_page
);
270 set_page_dirty(to_page
);
271 mark_page_accessed(to_page
);
275 ttm_tt_unpopulate(bdev
, ttm
);
276 ttm
->swap_storage
= swap_storage
;
277 ttm
->page_flags
|= TTM_PAGE_FLAG_SWAPPED
;
287 static void ttm_tt_add_mapping(struct ttm_bo_device
*bdev
, struct ttm_tt
*ttm
)
291 if (ttm
->page_flags
& TTM_PAGE_FLAG_SG
)
294 for (i
= 0; i
< ttm
->num_pages
; ++i
)
295 ttm
->pages
[i
]->mapping
= bdev
->dev_mapping
;
298 int ttm_tt_populate(struct ttm_bo_device
*bdev
,
299 struct ttm_tt
*ttm
, struct ttm_operation_ctx
*ctx
)
306 if (ttm_tt_is_populated(ttm
))
309 if (bdev
->driver
->ttm_tt_populate
)
310 ret
= bdev
->driver
->ttm_tt_populate(bdev
, ttm
, ctx
);
312 ret
= ttm_pool_alloc(&bdev
->pool
, ttm
, ctx
);
316 ttm_tt_add_mapping(bdev
, ttm
);
317 ttm
->page_flags
|= TTM_PAGE_FLAG_PRIV_POPULATED
;
318 if (unlikely(ttm
->page_flags
& TTM_PAGE_FLAG_SWAPPED
)) {
319 ret
= ttm_tt_swapin(ttm
);
320 if (unlikely(ret
!= 0)) {
321 ttm_tt_unpopulate(bdev
, ttm
);
328 EXPORT_SYMBOL(ttm_tt_populate
);
330 static void ttm_tt_clear_mapping(struct ttm_tt
*ttm
)
333 struct page
**page
= ttm
->pages
;
335 if (ttm
->page_flags
& TTM_PAGE_FLAG_SG
)
338 for (i
= 0; i
< ttm
->num_pages
; ++i
) {
339 (*page
)->mapping
= NULL
;
340 (*page
++)->index
= 0;
344 void ttm_tt_unpopulate(struct ttm_bo_device
*bdev
,
347 if (!ttm_tt_is_populated(ttm
))
350 ttm_tt_clear_mapping(ttm
);
351 if (bdev
->driver
->ttm_tt_unpopulate
)
352 bdev
->driver
->ttm_tt_unpopulate(bdev
, ttm
);
354 ttm_pool_free(&bdev
->pool
, ttm
);
355 ttm
->page_flags
&= ~TTM_PAGE_FLAG_PRIV_POPULATED
;