| .. | .. |
|---|
| 3 | 3 | * Copyright (C) 2017-2018 Etnaviv Project |
|---|
| 4 | 4 | */ |
|---|
| 5 | 5 | |
|---|
| 6 | +#include <linux/dma-mapping.h> |
|---|
| 7 | + |
|---|
| 6 | 8 | #include <drm/drm_mm.h> |
|---|
| 7 | 9 | |
|---|
| 8 | 10 | #include "etnaviv_cmdbuf.h" |
|---|
| 11 | +#include "etnaviv_gem.h" |
|---|
| 9 | 12 | #include "etnaviv_gpu.h" |
|---|
| 10 | 13 | #include "etnaviv_mmu.h" |
|---|
| 11 | 14 | #include "etnaviv_perfmon.h" |
|---|
| 12 | 15 | |
|---|
| 13 | | -#define SUBALLOC_SIZE SZ_256K |
|---|
| 16 | +#define SUBALLOC_SIZE SZ_512K |
|---|
| 14 | 17 | #define SUBALLOC_GRANULE SZ_4K |
|---|
| 15 | 18 | #define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE) |
|---|
| 16 | 19 | |
|---|
| 17 | 20 | struct etnaviv_cmdbuf_suballoc { |
|---|
| 18 | 21 | /* suballocated dma buffer properties */ |
|---|
| 19 | | - struct etnaviv_gpu *gpu; |
|---|
| 22 | + struct device *dev; |
|---|
| 20 | 23 | void *vaddr; |
|---|
| 21 | 24 | dma_addr_t paddr; |
|---|
| 22 | | - |
|---|
| 23 | | - /* GPU mapping */ |
|---|
| 24 | | - u32 iova; |
|---|
| 25 | | - struct drm_mm_node vram_node; /* only used on MMUv2 */ |
|---|
| 26 | 25 | |
|---|
| 27 | 26 | /* allocation management */ |
|---|
| 28 | 27 | struct mutex lock; |
|---|
| .. | .. |
|---|
| 32 | 31 | }; |
|---|
| 33 | 32 | |
|---|
| 34 | 33 | struct etnaviv_cmdbuf_suballoc * |
|---|
| 35 | | -etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu) |
|---|
| 34 | +etnaviv_cmdbuf_suballoc_new(struct device *dev) |
|---|
| 36 | 35 | { |
|---|
| 37 | 36 | struct etnaviv_cmdbuf_suballoc *suballoc; |
|---|
| 38 | 37 | int ret; |
|---|
| .. | .. |
|---|
| 41 | 40 | if (!suballoc) |
|---|
| 42 | 41 | return ERR_PTR(-ENOMEM); |
|---|
| 43 | 42 | |
|---|
| 44 | | - suballoc->gpu = gpu; |
|---|
| 43 | + suballoc->dev = dev; |
|---|
| 45 | 44 | mutex_init(&suballoc->lock); |
|---|
| 46 | 45 | init_waitqueue_head(&suballoc->free_event); |
|---|
| 47 | 46 | |
|---|
| 48 | | - suballoc->vaddr = dma_alloc_wc(gpu->dev, SUBALLOC_SIZE, |
|---|
| 47 | + BUILD_BUG_ON(ETNAVIV_SOFTPIN_START_ADDRESS < SUBALLOC_SIZE); |
|---|
| 48 | + suballoc->vaddr = dma_alloc_wc(dev, SUBALLOC_SIZE, |
|---|
| 49 | 49 | &suballoc->paddr, GFP_KERNEL); |
|---|
| 50 | | - if (!suballoc->vaddr) |
|---|
| 50 | + if (!suballoc->vaddr) { |
|---|
| 51 | + ret = -ENOMEM; |
|---|
| 51 | 52 | goto free_suballoc; |
|---|
| 52 | | - |
|---|
| 53 | | - ret = etnaviv_iommu_get_suballoc_va(gpu, suballoc->paddr, |
|---|
| 54 | | - &suballoc->vram_node, SUBALLOC_SIZE, |
|---|
| 55 | | - &suballoc->iova); |
|---|
| 56 | | - if (ret) |
|---|
| 57 | | - goto free_dma; |
|---|
| 53 | + } |
|---|
| 58 | 54 | |
|---|
| 59 | 55 | return suballoc; |
|---|
| 60 | 56 | |
|---|
| 61 | | -free_dma: |
|---|
| 62 | | - dma_free_wc(gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, suballoc->paddr); |
|---|
| 63 | 57 | free_suballoc: |
|---|
| 64 | 58 | kfree(suballoc); |
|---|
| 65 | 59 | |
|---|
| 66 | | - return NULL; |
|---|
| 60 | + return ERR_PTR(ret); |
|---|
| 61 | +} |
|---|
| 62 | + |
|---|
| 63 | +int etnaviv_cmdbuf_suballoc_map(struct etnaviv_cmdbuf_suballoc *suballoc, |
|---|
| 64 | + struct etnaviv_iommu_context *context, |
|---|
| 65 | + struct etnaviv_vram_mapping *mapping, |
|---|
| 66 | + u32 memory_base) |
|---|
| 67 | +{ |
|---|
| 68 | + return etnaviv_iommu_get_suballoc_va(context, mapping, memory_base, |
|---|
| 69 | + suballoc->paddr, SUBALLOC_SIZE); |
|---|
| 70 | +} |
|---|
| 71 | + |
|---|
| 72 | +void etnaviv_cmdbuf_suballoc_unmap(struct etnaviv_iommu_context *context, |
|---|
| 73 | + struct etnaviv_vram_mapping *mapping) |
|---|
| 74 | +{ |
|---|
| 75 | + etnaviv_iommu_put_suballoc_va(context, mapping); |
|---|
| 67 | 76 | } |
|---|
| 68 | 77 | |
|---|
| 69 | 78 | void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc) |
|---|
| 70 | 79 | { |
|---|
| 71 | | - etnaviv_iommu_put_suballoc_va(suballoc->gpu, &suballoc->vram_node, |
|---|
| 72 | | - SUBALLOC_SIZE, suballoc->iova); |
|---|
| 73 | | - dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, |
|---|
| 80 | + dma_free_wc(suballoc->dev, SUBALLOC_SIZE, suballoc->vaddr, |
|---|
| 74 | 81 | suballoc->paddr); |
|---|
| 75 | 82 | kfree(suballoc); |
|---|
| 76 | 83 | } |
|---|
| .. | .. |
|---|
| 95 | 102 | suballoc->free_space, |
|---|
| 96 | 103 | msecs_to_jiffies(10 * 1000)); |
|---|
| 97 | 104 | if (!ret) { |
|---|
| 98 | | - dev_err(suballoc->gpu->dev, |
|---|
| 105 | + dev_err(suballoc->dev, |
|---|
| 99 | 106 | "Timeout waiting for cmdbuf space\n"); |
|---|
| 100 | 107 | return -ETIMEDOUT; |
|---|
| 101 | 108 | } |
|---|
| .. | .. |
|---|
| 123 | 130 | wake_up_all(&suballoc->free_event); |
|---|
| 124 | 131 | } |
|---|
| 125 | 132 | |
|---|
| 126 | | -u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf) |
|---|
| 133 | +u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf, |
|---|
| 134 | + struct etnaviv_vram_mapping *mapping) |
|---|
| 127 | 135 | { |
|---|
| 128 | | - return buf->suballoc->iova + buf->suballoc_offset; |
|---|
| 136 | + return mapping->iova + buf->suballoc_offset; |
|---|
| 129 | 137 | } |
|---|
| 130 | 138 | |
|---|
| 131 | 139 | dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf) |
|---|