| @@ -1184,6 +1184,79 @@ drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, · 1183 unmodified lines |
| 1184 | 1184 | return ret; |
| 1185 | 1185 | } |
| 1186 | 1186 | |
| 1187 | +int |
| 1188 | +drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, |
| 1189 | + struct drm_file *file_private) |
| 1190 | +{ |
| 1191 | + struct drm_syncobj_timeline_array *args = data; |
| 1192 | + struct drm_syncobj **syncobjs; |
| 1193 | + struct dma_fence_chain **chains; |
| 1194 | + uint64_t *points; |
| 1195 | + uint32_t i, j; |
| 1196 | + int ret; |
| 1197 | + |
| 1198 | + if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) |
| 1199 | + return -EOPNOTSUPP; |
| 1200 | + |
| 1201 | + if (args->pad != 0) |
| 1202 | + return -EINVAL; |
| 1203 | + |
| 1204 | + if (args->count_handles == 0) |
| 1205 | + return -EINVAL; |
| 1206 | + |
| 1207 | + ret = drm_syncobj_array_find(file_private, |
| 1208 | + u64_to_user_ptr(args->handles), |
| 1209 | + args->count_handles, |
| 1210 | + &syncobjs); |
| 1211 | + if (ret < 0) |
| 1212 | + return ret; |
| 1213 | + |
| 1214 | + points = kmalloc_array(args->count_handles, sizeof(*points), |
| 1215 | + GFP_KERNEL); |
| 1216 | + if (!points) { |
| 1217 | + ret = -ENOMEM; |
| 1218 | + goto out; |
| 1219 | + } |
| 1220 | + if (!u64_to_user_ptr(args->points)) { |
| 1221 | + memset(points, 0, args->count_handles * sizeof(uint64_t)); |
| 1222 | + } else if (copy_from_user(points, u64_to_user_ptr(args->points), |
| 1223 | + sizeof(uint64_t) * args->count_handles)) { |
| 1224 | + ret = -EFAULT; |
| 1225 | + goto err_points; |
| 1226 | + } |
| 1227 | + |
| 1228 | + chains = kmalloc_array(args->count_handles, sizeof(void *), GFP_KERNEL); |
| 1229 | + if (!chains) { |
| 1230 | + ret = -ENOMEM; |
| 1231 | + goto err_points; |
| 1232 | + } |
| 1233 | + for (i = 0; i < args->count_handles; i++) { |
| 1234 | + chains[i] = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL); |
| 1235 | + if (!chains[i]) { |
| 1236 | + for (j = 0; j < i; j++) |
| 1237 | + kfree(chains[j]); |
| 1238 | + ret = -ENOMEM; |
| 1239 | + goto err_chains; |
| 1240 | + } |
| 1241 | + } |
| 1242 | + |
| 1243 | + for (i = 0; i < args->count_handles; i++) { |
| 1244 | + struct dma_fence *fence = dma_fence_get_stub(); |
| 1245 | + |
| 1246 | + drm_syncobj_add_point(syncobjs[i], chains[i], |
| 1247 | + fence, points[i]); |
| 1248 | + dma_fence_put(fence); |
| 1249 | + } |
| 1250 | +err_chains: |
| 1251 | + kfree(chains); |
| 1252 | +err_points: |
| 1253 | + kfree(points); |
| 1254 | +out: |
| 1255 | + drm_syncobj_array_free(syncobjs, args->count_handles); |
| 1256 | + |
| 1257 | + return ret; |
| 1258 | +} |
| 1259 | + |
| 1187 | 1260 | int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, |
| 1188 | 1261 | struct drm_file *file_private) |
| 1189 | 1262 | { |