|
5 | 5 | #include <linux/anon_inodes.h> |
6 | 6 | #include <linux/device.h> |
7 | 7 | #include <linux/dma-buf.h> |
| 8 | +#include <linux/dma-mapping.h> |
| 9 | +#include <linux/highmem.h> |
8 | 10 | #include <linux/idr.h> |
9 | 11 | #include <linux/io.h> |
10 | 12 | #include <linux/mm.h> |
|
13 | 15 | #include <linux/tee_core.h> |
14 | 16 | #include <linux/uaccess.h> |
15 | 17 | #include <linux/uio.h> |
16 | | -#include <linux/highmem.h> |
17 | 18 | #include "tee_private.h" |
18 | 19 |
|
| 20 | +struct tee_shm_dma_mem { |
| 21 | + struct tee_shm shm; |
| 22 | + dma_addr_t dma_addr; |
| 23 | + struct page *page; |
| 24 | +}; |
| 25 | + |
19 | 26 | static void shm_put_kernel_pages(struct page **pages, size_t page_count) |
20 | 27 | { |
21 | 28 | size_t n; |
@@ -48,7 +55,16 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) |
48 | 55 | { |
49 | 56 | void *p = shm; |
50 | 57 |
|
51 | | - if (shm->flags & TEE_SHM_DMA_BUF) { |
| 58 | + if (shm->flags & TEE_SHM_DMA_MEM) { |
| 59 | +#if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) |
| 60 | + struct tee_shm_dma_mem *dma_mem; |
| 61 | + |
| 62 | + dma_mem = container_of(shm, struct tee_shm_dma_mem, shm); |
| 63 | + p = dma_mem; |
| 64 | + dma_free_pages(&teedev->dev, shm->size, dma_mem->page, |
| 65 | + dma_mem->dma_addr, DMA_BIDIRECTIONAL); |
| 66 | +#endif |
| 67 | + } else if (shm->flags & TEE_SHM_DMA_BUF) { |
52 | 68 | struct tee_shm_dmabuf_ref *ref; |
53 | 69 |
|
54 | 70 | ref = container_of(shm, struct tee_shm_dmabuf_ref, shm); |
@@ -268,6 +284,71 @@ struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size) |
268 | 284 | } |
269 | 285 | EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf); |
270 | 286 |
|
| 287 | +#if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS) |
| 288 | +/** |
| 289 | + * tee_shm_alloc_dma_mem() - Allocate DMA memory as shared memory object |
| 290 | + * @ctx: Context that allocates the shared memory |
| 291 | + * @page_count: Number of pages |
| 292 | + * |
| 293 | + * The allocated memory is expected to be lent (made inaccessible to the |
| 294 | + * kernel) to the TEE while it's used and returned (accessible to the |
| 295 | + * kernel again) before it's freed. |
| 296 | + * |
| 297 | + * This function should normally only be used internally in the TEE |
| 298 | + * drivers. |
| 299 | + * |
| 300 | + * @returns a pointer to 'struct tee_shm' |
| 301 | + */ |
| 302 | +struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, |
| 303 | + size_t page_count) |
| 304 | +{ |
| 305 | + struct tee_device *teedev = ctx->teedev; |
| 306 | + struct tee_shm_dma_mem *dma_mem; |
| 307 | + dma_addr_t dma_addr; |
| 308 | + struct page *page; |
| 309 | + |
| 310 | + if (!tee_device_get(teedev)) |
| 311 | + return ERR_PTR(-EINVAL); |
| 312 | + |
| 313 | + page = dma_alloc_pages(&teedev->dev, page_count * PAGE_SIZE, |
| 314 | + &dma_addr, DMA_BIDIRECTIONAL, GFP_KERNEL); |
| 315 | + if (!page) |
| 316 | + goto err_put_teedev; |
| 317 | + |
| 318 | + dma_mem = kzalloc(sizeof(*dma_mem), GFP_KERNEL); |
| 319 | + if (!dma_mem) |
| 320 | + goto err_free_pages; |
| 321 | + |
| 322 | + refcount_set(&dma_mem->shm.refcount, 1); |
| 323 | + dma_mem->shm.ctx = ctx; |
| 324 | + dma_mem->shm.paddr = page_to_phys(page); |
| 325 | + dma_mem->dma_addr = dma_addr; |
| 326 | + dma_mem->page = page; |
| 327 | + dma_mem->shm.size = page_count * PAGE_SIZE; |
| 328 | + dma_mem->shm.flags = TEE_SHM_DMA_MEM; |
| 329 | + |
| 330 | + teedev_ctx_get(ctx); |
| 331 | + |
| 332 | + return &dma_mem->shm; |
| 333 | + |
| 334 | +err_free_pages: |
| 335 | + dma_free_pages(&teedev->dev, page_count * PAGE_SIZE, page, dma_addr, |
| 336 | + DMA_BIDIRECTIONAL); |
| 337 | +err_put_teedev: |
| 338 | + tee_device_put(teedev); |
| 339 | + |
| 340 | + return ERR_PTR(-ENOMEM); |
| 341 | +} |
| 342 | +EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem); |
| 343 | +#else |
| 344 | +struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx, |
| 345 | + size_t page_count) |
| 346 | +{ |
| 347 | + return ERR_PTR(-EINVAL); |
| 348 | +} |
| 349 | +EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem); |
| 350 | +#endif |
| 351 | + |
271 | 352 | int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align, |
272 | 353 | int (*shm_register)(struct tee_context *ctx, |
273 | 354 | struct tee_shm *shm, |
|
0 commit comments