firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_drivers-dma-buf-sync_fil...

144 lines
4.2 KiB
Diff

--- linux-4.9.37/drivers/dma-buf/sync_file.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/sync_file.c 2021-06-07 13:01:33.000000000 +0300
@@ -67,9 +67,10 @@
* sync_file_create() - creates a sync file
* @fence: fence to add to the sync_fence
*
- * Creates a sync_file containg @fence. Once this is called, the sync_file
- * takes ownership of @fence. The sync_file can be released with
- * fput(sync_file->file). Returns the sync_file or NULL in case of error.
+ * Creates a sync_file containg @fence. This function acquires and additional
+ * reference of @fence for the newly-created &sync_file, if it succeeds. The
+ * sync_file can be released with fput(sync_file->file). Returns the
+ * sync_file or NULL in case of error.
*/
struct sync_file *sync_file_create(struct fence *fence)
{
@@ -79,7 +80,7 @@
if (!sync_file)
return NULL;
- sync_file->fence = fence;
+ sync_file->fence = fence_get(fence);
snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
fence->ops->get_driver_name(fence),
@@ -90,14 +91,7 @@
}
EXPORT_SYMBOL(sync_file_create);
-/**
- * sync_file_fdget() - get a sync_file from an fd
- * @fd: fd referencing a fence
- *
- * Ensures @fd references a valid sync_file, increments the refcount of the
- * backing file. Returns the sync_file or NULL in case of error.
- */
-static struct sync_file *sync_file_fdget(int fd)
+struct sync_file *sync_file_fdget(int fd)
{
struct file *file = fget(fd);
@@ -114,6 +108,8 @@
return NULL;
}
+EXPORT_SYMBOL(sync_file_fdget);
+
/**
* sync_file_get_fence - get the fence related to the sync_file fd
* @fd: sync_file fd to get the fence from
@@ -305,10 +301,9 @@
poll_wait(file, &sync_file->wq, wait);
- if (!poll_does_not_wait(wait) &&
- !test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
+ if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
if (fence_add_callback(sync_file->fence, &sync_file->cb,
- fence_check_cb_func) < 0)
+ fence_check_cb_func) < 0)
wake_up_all(&sync_file->wq);
}
@@ -370,7 +365,7 @@
return err;
}
-static void sync_fill_fence_info(struct fence *fence,
+static int sync_fill_fence_info(struct fence *fence,
struct sync_fence_info *info)
{
strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
@@ -382,6 +377,8 @@
else
info->status = 0;
info->timestamp_ns = ktime_to_ns(fence->timestamp);
+
+ return info->status;
}
static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
@@ -407,8 +404,12 @@
* sync_fence_info and return the actual number of fences on
* info->num_fences.
*/
- if (!info.num_fences)
+ if (!info.num_fences) {
+ info.status = fence_is_signaled(sync_file->fence);
goto no_fences;
+ } else {
+ info.status = 1;
+ }
if (info.num_fences < num_fences)
return -EINVAL;
@@ -418,8 +419,10 @@
if (!fence_info)
return -ENOMEM;
- for (i = 0; i < num_fences; i++)
- sync_fill_fence_info(fences[i], &fence_info[i]);
+ for (i = 0; i < num_fences; i++) {
+ int status = sync_fill_fence_info(fences[i], &fence_info[i]);
+ info.status = info.status <= 0 ? info.status : status;
+ }
if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
size)) {
@@ -429,7 +432,6 @@
no_fences:
strlcpy(info.name, sync_file->name, sizeof(info.name));
- info.status = fence_is_signaled(sync_file->fence);
info.num_fences = num_fences;
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
@@ -443,12 +445,26 @@
return ret;
}
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+static long sync_fence_ioctl_wait(struct sync_file *sync_file, unsigned long arg)
+{
+ __s32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+ if(value <= 0)
+ value = MAX_SCHEDULE_TIMEOUT;
+ return fence_wait_timeout(sync_file->fence, true, value);
+}
+
static long sync_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct sync_file *sync_file = file->private_data;
switch (cmd) {
+ case SYNC_IOC_WAIT:
+ return sync_fence_ioctl_wait(sync_file, arg);
case SYNC_IOC_MERGE:
return sync_file_ioctl_merge(sync_file, arg);