1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* Copyright (C) 2020 Google, Inc */ 3 4 #include "drm/drm_drv.h" 5 6 #include "msm_drv.h" 7 #include "msm_syncobj.h" 8 9 struct drm_syncobj ** 10 msm_syncobj_parse_deps(struct drm_device *dev, 11 struct drm_sched_job *job, 12 struct drm_file *file, 13 uint64_t in_syncobjs_addr, 14 uint32_t nr_in_syncobjs, 15 size_t syncobj_stride) 16 { 17 struct drm_syncobj **syncobjs = NULL; 18 struct drm_msm_syncobj syncobj_desc = {0}; 19 int ret = 0; 20 uint32_t i, j; 21 22 syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs), 23 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); 24 if (!syncobjs) 25 return ERR_PTR(-ENOMEM); 26 27 for (i = 0; i < nr_in_syncobjs; ++i) { 28 uint64_t address = in_syncobjs_addr + i * syncobj_stride; 29 30 if (copy_from_user(&syncobj_desc, 31 u64_to_user_ptr(address), 32 min(syncobj_stride, sizeof(syncobj_desc)))) { 33 ret = -EFAULT; 34 break; 35 } 36 37 if (syncobj_desc.point && 38 !drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) { 39 ret = UERR(EOPNOTSUPP, dev, "syncobj timeline unsupported"); 40 break; 41 } 42 43 if (syncobj_desc.flags & ~MSM_SYNCOBJ_FLAGS) { 44 ret = UERR(EINVAL, dev, "invalid syncobj flags: %x", syncobj_desc.flags); 45 break; 46 } 47 48 ret = drm_sched_job_add_syncobj_dependency(job, file, 49 syncobj_desc.handle, 50 syncobj_desc.point); 51 if (ret) 52 break; 53 54 if (syncobj_desc.flags & MSM_SYNCOBJ_RESET) { 55 syncobjs[i] = drm_syncobj_find(file, syncobj_desc.handle); 56 if (!syncobjs[i]) { 57 ret = UERR(EINVAL, dev, "invalid syncobj handle: %u", i); 58 break; 59 } 60 } 61 } 62 63 if (ret) { 64 for (j = 0; j <= i; ++j) { 65 if (syncobjs[j]) 66 drm_syncobj_put(syncobjs[j]); 67 } 68 kfree(syncobjs); 69 return ERR_PTR(ret); 70 } 71 return syncobjs; 72 } 73 74 void 75 msm_syncobj_reset(struct drm_syncobj **syncobjs, uint32_t nr_syncobjs) 76 { 77 uint32_t i; 78 79 for (i = 0; syncobjs && i < nr_syncobjs; ++i) { 80 if (syncobjs[i]) 81 drm_syncobj_replace_fence(syncobjs[i], NULL); 82 } 83 } 84 85 struct msm_syncobj_post_dep * 86 msm_syncobj_parse_post_deps(struct drm_device *dev, 87 struct drm_file *file, 88 uint64_t syncobjs_addr, 89 uint32_t nr_syncobjs, 90 size_t syncobj_stride) 91 { 92 struct msm_syncobj_post_dep *post_deps; 93 struct drm_msm_syncobj syncobj_desc = {0}; 94 int ret = 0; 95 uint32_t i, j; 96 97 post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps), 98 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY); 99 if (!post_deps) 100 return ERR_PTR(-ENOMEM); 101 102 for (i = 0; i < nr_syncobjs; ++i) { 103 uint64_t address = syncobjs_addr + i * syncobj_stride; 104 105 if (copy_from_user(&syncobj_desc, 106 u64_to_user_ptr(address), 107 min(syncobj_stride, sizeof(syncobj_desc)))) { 108 ret = -EFAULT; 109 break; 110 } 111 112 post_deps[i].point = syncobj_desc.point; 113 114 if (syncobj_desc.flags) { 115 ret = UERR(EINVAL, dev, "invalid syncobj flags"); 116 break; 117 } 118 119 if (syncobj_desc.point) { 120 if (!drm_core_check_feature(dev, 121 DRIVER_SYNCOBJ_TIMELINE)) { 122 ret = UERR(EOPNOTSUPP, dev, "syncobj timeline unsupported"); 123 break; 124 } 125 126 post_deps[i].chain = dma_fence_chain_alloc(); 127 if (!post_deps[i].chain) { 128 ret = -ENOMEM; 129 break; 130 } 131 } 132 133 post_deps[i].syncobj = 134 drm_syncobj_find(file, syncobj_desc.handle); 135 if (!post_deps[i].syncobj) { 136 ret = UERR(EINVAL, dev, "invalid syncobj handle"); 137 break; 138 } 139 } 140 141 if (ret) { 142 for (j = 0; j <= i; ++j) { 143 dma_fence_chain_free(post_deps[j].chain); 144 if (post_deps[j].syncobj) 145 drm_syncobj_put(post_deps[j].syncobj); 146 } 147 148 kfree(post_deps); 149 return ERR_PTR(ret); 150 } 151 152 return post_deps; 153 } 154 155 void 156 msm_syncobj_process_post_deps(struct msm_syncobj_post_dep *post_deps, 157 uint32_t count, struct dma_fence *fence) 158 { 159 uint32_t i; 160 161 for (i = 0; post_deps && i < count; ++i) { 162 if (post_deps[i].chain) { 163 drm_syncobj_add_point(post_deps[i].syncobj, 164 post_deps[i].chain, 165 fence, post_deps[i].point); 166 post_deps[i].chain = NULL; 167 } else { 168 drm_syncobj_replace_fence(post_deps[i].syncobj, 169 fence); 170 } 171 } 172 } 173