we need to import/export timeline point. v2: unify to one transfer ioctl
Unified · Split
| @@ -180,6 +180,8 @@ int drm_syncobj_handle_to_fd_ioctl(struct drm_device *dev, void *data, · 179 unmodified lines | ||
| 180 | 180 | struct drm_file *file_private); |
| 181 | 181 | int drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, |
| 182 | 182 | struct drm_file *file_private); |
| 183 | +int drm_syncobj_transfer_ioctl(struct drm_device *dev, void *data, | |
| 184 | + struct drm_file *file_private); | |
| 183 | 185 | int drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, |
| 184 | 186 | struct drm_file *file_private); |
| 185 | 187 | int drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, |
| @@ -686,6 +686,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { · 685 unmodified lines | ||
| 686 | 686 | DRM_UNLOCKED|DRM_RENDER_ALLOW), |
| 687 | 687 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl, |
| 688 | 688 | DRM_UNLOCKED|DRM_RENDER_ALLOW), |
| 689 | + DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TRANSFER, drm_syncobj_transfer_ioctl, | |
| 690 | + DRM_UNLOCKED|DRM_RENDER_ALLOW), | |
| 689 | 691 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl, |
| 690 | 692 | DRM_UNLOCKED|DRM_RENDER_ALLOW), |
| 691 | 693 | DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, drm_syncobj_timeline_wait_ioctl, |
| @@ -680,6 +680,80 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, · 679 unmodified lines | ||
| 680 | 680 | &args->handle); |
| 681 | 681 | } |
| 682 | 682 | |
| 683 | +static int drm_syncobj_transfer_to_timeline(struct drm_file *file_private, | |
| 684 | + struct drm_syncobj_transfer *args) | |
| 685 | +{ | |
| 686 | + struct drm_syncobj *timeline_syncobj = NULL; | |
| 687 | + struct dma_fence *fence; | |
| 688 | + struct dma_fence_chain *chain; | |
| 689 | + int ret; | |
| 690 | + | |
| 691 | + timeline_syncobj = drm_syncobj_find(file_private, args->dst_handle); | |
| 692 | + if (!timeline_syncobj) { | |
| 693 | + return -ENOENT; | |
| 694 | + } | |
| 695 | + ret = drm_syncobj_find_fence(file_private, args->src_handle, | |
| 696 | + args->src_point, args->flags, | |
| 697 | + &fence); | |
| 698 | + if (ret) | |
| 699 | + goto err; | |
| 700 | + chain = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL); | |
| 701 | + if (!chain) { | |
| 702 | + ret = -ENOMEM; | |
| 703 | + goto err1; | |
| 704 | + } | |
| 705 | + drm_syncobj_add_point(timeline_syncobj, chain, fence, args->dst_point); | |
| 706 | +err1: | |
| 707 | + dma_fence_put(fence); | |
| 708 | +err: | |
| 709 | + drm_syncobj_put(timeline_syncobj); | |
| 710 | + | |
| 711 | + return ret; | |
| 712 | +} | |
| 713 | + | |
| 714 | +static int | |
| 715 | +drm_syncobj_transfer_to_binary(struct drm_file *file_private, | |
| 716 | + struct drm_syncobj_transfer *args) | |
| 717 | +{ | |
| 718 | + struct drm_syncobj *binary_syncobj = NULL; | |
| 719 | + struct dma_fence *fence; | |
| 720 | + int ret; | |
| 721 | + | |
| 722 | + binary_syncobj = drm_syncobj_find(file_private, args->dst_handle); | |
| 723 | + if (!binary_syncobj) | |
| 724 | + return -ENOENT; | |
| 725 | + ret = drm_syncobj_find_fence(file_private, args->src_handle, | |
| 726 | + args->src_point, args->flags, &fence); | |
| 727 | + if (ret) | |
| 728 | + goto err; | |
| 729 | + drm_syncobj_replace_fence(binary_syncobj, fence); | |
| 730 | + dma_fence_put(fence); | |
| 731 | +err: | |
| 732 | + drm_syncobj_put(binary_syncobj); | |
| 733 | + | |
| 734 | + return ret; | |
| 735 | +} | |
| 736 | +int | |
| 737 | +drm_syncobj_transfer_ioctl(struct drm_device *dev, void *data, | |
| 738 | + struct drm_file *file_private) | |
| 739 | +{ | |
| 740 | + struct drm_syncobj_transfer *args = data; | |
| 741 | + int ret; | |
| 742 | + | |
| 743 | + if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) | |
| 744 | + return -ENODEV; | |
| 745 | + | |
| 746 | + if (args->pad) | |
| 747 | + return -EINVAL; | |
| 748 | + | |
| 749 | + if (args->dst_point) | |
| 750 | + ret = drm_syncobj_transfer_to_timeline(file_private, args); | |
| 751 | + else | |
| 752 | + ret = drm_syncobj_transfer_to_binary(file_private, args); | |
| 753 | + | |
| 754 | + return ret; | |
| 755 | +} | |
| 756 | + | |
| 683 | 757 | static void syncobj_wait_fence_func(struct dma_fence *fence, |
| 684 | 758 | struct dma_fence_cb *cb) |
| 685 | 759 | { |
| @@ -735,6 +735,15 @@ struct drm_syncobj_handle { · 734 unmodified lines | ||
| 735 | 735 | __u32 pad; |
| 736 | 736 | }; |
| 737 | 737 | |
| 738 | +struct drm_syncobj_transfer { | |
| 739 | + __u32 src_handle; | |
| 740 | + __u32 dst_handle; | |
| 741 | + __u64 src_point; | |
| 742 | + __u64 dst_point; | |
| 743 | + __u32 flags; | |
| 744 | + __u32 pad; | |
| 745 | +}; | |
| 746 | + | |
| 738 | 747 | #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) |
| 739 | 748 | #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) |
| 740 | 749 | #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ |
| @@ -933,6 +942,7 @@ extern "C" { · 192 unmodified lines | ||
| 933 | 942 | |
| 934 | 943 | #define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) |
| 935 | 944 | #define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array) |
| 945 | +#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer) | |
| 936 | 946 | |
| 937 | 947 | /** |
| 938 | 948 | * Device specific ioctls should only be in their respective headers |