Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/syncobj: add timeline signal ioctl for syncobj v5

v2: individually allocate chain array, since chain node is free independently.
v3: all existing points must be already signaled before cpu perform signal operation,
so add check condition for that.
v4: remove v3 change and add checking to prevent out-of-order
v5: unify binary and timeline

Signed-off-by: Chunming Zhou <david1.zhou@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Cc: Tobias Hector <Tobias.Hector@amd.com>
Cc: Jason Ekstrand <jason@jlekstrand.net>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Link: https://patchwork.freedesktop.org/patch/295792/?series=58813&rev=1

authored by

Chunming Zhou and committed by
Christian König
50d1ebef ea569910

+78
+2
drivers/gpu/drm/drm_internal.h
··· 190 190 struct drm_file *file_private); 191 191 int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, 192 192 struct drm_file *file_private); 193 + int drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, 194 + struct drm_file *file_private); 193 195 int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, 194 196 struct drm_file *file_private); 195 197
+2
drivers/gpu/drm/drm_ioctl.c
··· 696 696 DRM_UNLOCKED|DRM_RENDER_ALLOW), 697 697 DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl, 698 698 DRM_UNLOCKED|DRM_RENDER_ALLOW), 699 + DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, drm_syncobj_timeline_signal_ioctl, 700 + DRM_UNLOCKED|DRM_RENDER_ALLOW), 699 701 DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_QUERY, drm_syncobj_query_ioctl, 700 702 DRM_UNLOCKED|DRM_RENDER_ALLOW), 701 703 DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, DRM_UNLOCKED),
+73
drivers/gpu/drm/drm_syncobj.c
··· 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 {
+1
include/uapi/drm/drm.h
··· 943 943 #define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) 944 944 #define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array) 945 945 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) 946 + #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array) 946 947 947 948 /** 948 949 * Device specific ioctls should only be in their respective headers