linux/drivers/dma-buf/sync_file.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * drivers/dma-buf/sync_file.c
   4 *
   5 * Copyright (C) 2012 Google, Inc.
   6 */
   7
   8#include <linux/dma-fence-unwrap.h>
   9#include <linux/export.h>
  10#include <linux/file.h>
  11#include <linux/fs.h>
  12#include <linux/kernel.h>
  13#include <linux/poll.h>
  14#include <linux/sched.h>
  15#include <linux/slab.h>
  16#include <linux/uaccess.h>
  17#include <linux/anon_inodes.h>
  18#include <linux/sync_file.h>
  19#include <uapi/linux/sync_file.h>
  20
  21static const struct file_operations sync_file_fops;
  22
  23static struct sync_file *sync_file_alloc(void)
  24{
  25        struct sync_file *sync_file;
  26
  27        sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL);
  28        if (!sync_file)
  29                return NULL;
  30
  31        sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
  32                                             sync_file, 0);
  33        if (IS_ERR(sync_file->file))
  34                goto err;
  35
  36        init_waitqueue_head(&sync_file->wq);
  37
  38        INIT_LIST_HEAD(&sync_file->cb.node);
  39
  40        return sync_file;
  41
  42err:
  43        kfree(sync_file);
  44        return NULL;
  45}
  46
  47static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
  48{
  49        struct sync_file *sync_file;
  50
  51        sync_file = container_of(cb, struct sync_file, cb);
  52
  53        wake_up_all(&sync_file->wq);
  54}
  55
  56/**
  57 * sync_file_create() - creates a sync file
  58 * @fence:      fence to add to the sync_fence
  59 *
  60 * Creates a sync_file containg @fence. This function acquires and additional
  61 * reference of @fence for the newly-created &sync_file, if it succeeds. The
  62 * sync_file can be released with fput(sync_file->file). Returns the
  63 * sync_file or NULL in case of error.
  64 */
  65struct sync_file *sync_file_create(struct dma_fence *fence)
  66{
  67        struct sync_file *sync_file;
  68
  69        sync_file = sync_file_alloc();
  70        if (!sync_file)
  71                return NULL;
  72
  73        sync_file->fence = dma_fence_get(fence);
  74
  75        return sync_file;
  76}
  77EXPORT_SYMBOL(sync_file_create);
  78
  79static struct sync_file *sync_file_fdget(int fd)
  80{
  81        struct file *file = fget(fd);
  82
  83        if (!file)
  84                return NULL;
  85
  86        if (file->f_op != &sync_file_fops)
  87                goto err;
  88
  89        return file->private_data;
  90
  91err:
  92        fput(file);
  93        return NULL;
  94}
  95
  96/**
  97 * sync_file_get_fence - get the fence related to the sync_file fd
  98 * @fd:         sync_file fd to get the fence from
  99 *
 100 * Ensures @fd references a valid sync_file and returns a fence that
 101 * represents all fence in the sync_file. On error NULL is returned.
 102 */
 103struct dma_fence *sync_file_get_fence(int fd)
 104{
 105        struct sync_file *sync_file;
 106        struct dma_fence *fence;
 107
 108        sync_file = sync_file_fdget(fd);
 109        if (!sync_file)
 110                return NULL;
 111
 112        fence = dma_fence_get(sync_file->fence);
 113        fput(sync_file->file);
 114
 115        return fence;
 116}
 117EXPORT_SYMBOL(sync_file_get_fence);
 118
 119/**
 120 * sync_file_get_name - get the name of the sync_file
 121 * @sync_file:          sync_file to get the fence from
 122 * @buf:                destination buffer to copy sync_file name into
 123 * @len:                available size of destination buffer.
 124 *
 125 * Each sync_file may have a name assigned either by the user (when merging
 126 * sync_files together) or created from the fence it contains. In the latter
 127 * case construction of the name is deferred until use, and so requires
 128 * sync_file_get_name().
 129 *
 130 * Returns: a string representing the name.
 131 */
 132char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
 133{
 134        if (sync_file->user_name[0]) {
 135                strlcpy(buf, sync_file->user_name, len);
 136        } else {
 137                struct dma_fence *fence = sync_file->fence;
 138
 139                snprintf(buf, len, "%s-%s%llu-%lld",
 140                         fence->ops->get_driver_name(fence),
 141                         fence->ops->get_timeline_name(fence),
 142                         fence->context,
 143                         fence->seqno);
 144        }
 145
 146        return buf;
 147}
 148
 149static int sync_file_set_fence(struct sync_file *sync_file,
 150                               struct dma_fence **fences, int num_fences)
 151{
 152        struct dma_fence_array *array;
 153
 154        /*
 155         * The reference for the fences in the new sync_file and held
 156         * in add_fence() during the merge procedure, so for num_fences == 1
 157         * we already own a new reference to the fence. For num_fence > 1
 158         * we own the reference of the dma_fence_array creation.
 159         */
 160        if (num_fences == 1) {
 161                sync_file->fence = fences[0];
 162                kfree(fences);
 163        } else {
 164                array = dma_fence_array_create(num_fences, fences,
 165                                               dma_fence_context_alloc(1),
 166                                               1, false);
 167                if (!array)
 168                        return -ENOMEM;
 169
 170                sync_file->fence = &array->base;
 171        }
 172
 173        return 0;
 174}
 175
 176static void add_fence(struct dma_fence **fences,
 177                      int *i, struct dma_fence *fence)
 178{
 179        fences[*i] = fence;
 180
 181        if (!dma_fence_is_signaled(fence)) {
 182                dma_fence_get(fence);
 183                (*i)++;
 184        }
 185}
 186
 187/**
 188 * sync_file_merge() - merge two sync_files
 189 * @name:       name of new fence
 190 * @a:          sync_file a
 191 * @b:          sync_file b
 192 *
 193 * Creates a new sync_file which contains copies of all the fences in both
 194 * @a and @b.  @a and @b remain valid, independent sync_file. Returns the
 195 * new merged sync_file or NULL in case of error.
 196 */
 197static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
 198                                         struct sync_file *b)
 199{
 200        struct dma_fence *a_fence, *b_fence, **fences;
 201        struct dma_fence_unwrap a_iter, b_iter;
 202        unsigned int index, num_fences;
 203        struct sync_file *sync_file;
 204
 205        sync_file = sync_file_alloc();
 206        if (!sync_file)
 207                return NULL;
 208
 209        num_fences = 0;
 210        dma_fence_unwrap_for_each(a_fence, &a_iter, a->fence)
 211                ++num_fences;
 212        dma_fence_unwrap_for_each(b_fence, &b_iter, b->fence)
 213                ++num_fences;
 214
 215        if (num_fences > INT_MAX)
 216                goto err_free_sync_file;
 217
 218        fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
 219        if (!fences)
 220                goto err_free_sync_file;
 221
 222        /*
 223         * We can't guarantee that fences in both a and b are ordered, but it is
 224         * still quite likely.
 225         *
 226         * So attempt to order the fences as we pass over them and merge fences
 227         * with the same context.
 228         */
 229
 230        index = 0;
 231        for (a_fence = dma_fence_unwrap_first(a->fence, &a_iter),
 232             b_fence = dma_fence_unwrap_first(b->fence, &b_iter);
 233             a_fence || b_fence; ) {
 234
 235                if (!b_fence) {
 236                        add_fence(fences, &index, a_fence);
 237                        a_fence = dma_fence_unwrap_next(&a_iter);
 238
 239                } else if (!a_fence) {
 240                        add_fence(fences, &index, b_fence);
 241                        b_fence = dma_fence_unwrap_next(&b_iter);
 242
 243                } else if (a_fence->context < b_fence->context) {
 244                        add_fence(fences, &index, a_fence);
 245                        a_fence = dma_fence_unwrap_next(&a_iter);
 246
 247                } else if (b_fence->context < a_fence->context) {
 248                        add_fence(fences, &index, b_fence);
 249                        b_fence = dma_fence_unwrap_next(&b_iter);
 250
 251                } else if (__dma_fence_is_later(a_fence->seqno, b_fence->seqno,
 252                                                a_fence->ops)) {
 253                        add_fence(fences, &index, a_fence);
 254                        a_fence = dma_fence_unwrap_next(&a_iter);
 255                        b_fence = dma_fence_unwrap_next(&b_iter);
 256
 257                } else {
 258                        add_fence(fences, &index, b_fence);
 259                        a_fence = dma_fence_unwrap_next(&a_iter);
 260                        b_fence = dma_fence_unwrap_next(&b_iter);
 261                }
 262        }
 263
 264        if (index == 0)
 265                fences[index++] = dma_fence_get_stub();
 266
 267        if (num_fences > index) {
 268                struct dma_fence **tmp;
 269
 270                /* Keep going even when reducing the size failed */
 271                tmp = krealloc_array(fences, index, sizeof(*fences),
 272                                     GFP_KERNEL);
 273                if (tmp)
 274                        fences = tmp;
 275        }
 276
 277        if (sync_file_set_fence(sync_file, fences, index) < 0)
 278                goto err_put_fences;
 279
 280        strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
 281        return sync_file;
 282
 283err_put_fences:
 284        while (index)
 285                dma_fence_put(fences[--index]);
 286        kfree(fences);
 287
 288err_free_sync_file:
 289        fput(sync_file->file);
 290        return NULL;
 291}
 292
 293static int sync_file_release(struct inode *inode, struct file *file)
 294{
 295        struct sync_file *sync_file = file->private_data;
 296
 297        if (test_bit(POLL_ENABLED, &sync_file->flags))
 298                dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
 299        dma_fence_put(sync_file->fence);
 300        kfree(sync_file);
 301
 302        return 0;
 303}
 304
 305static __poll_t sync_file_poll(struct file *file, poll_table *wait)
 306{
 307        struct sync_file *sync_file = file->private_data;
 308
 309        poll_wait(file, &sync_file->wq, wait);
 310
 311        if (list_empty(&sync_file->cb.node) &&
 312            !test_and_set_bit(POLL_ENABLED, &sync_file->flags)) {
 313                if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
 314                                           fence_check_cb_func) < 0)
 315                        wake_up_all(&sync_file->wq);
 316        }
 317
 318        return dma_fence_is_signaled(sync_file->fence) ? EPOLLIN : 0;
 319}
 320
 321static long sync_file_ioctl_merge(struct sync_file *sync_file,
 322                                  unsigned long arg)
 323{
 324        int fd = get_unused_fd_flags(O_CLOEXEC);
 325        int err;
 326        struct sync_file *fence2, *fence3;
 327        struct sync_merge_data data;
 328
 329        if (fd < 0)
 330                return fd;
 331
 332        if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
 333                err = -EFAULT;
 334                goto err_put_fd;
 335        }
 336
 337        if (data.flags || data.pad) {
 338                err = -EINVAL;
 339                goto err_put_fd;
 340        }
 341
 342        fence2 = sync_file_fdget(data.fd2);
 343        if (!fence2) {
 344                err = -ENOENT;
 345                goto err_put_fd;
 346        }
 347
 348        data.name[sizeof(data.name) - 1] = '\0';
 349        fence3 = sync_file_merge(data.name, sync_file, fence2);
 350        if (!fence3) {
 351                err = -ENOMEM;
 352                goto err_put_fence2;
 353        }
 354
 355        data.fence = fd;
 356        if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
 357                err = -EFAULT;
 358                goto err_put_fence3;
 359        }
 360
 361        fd_install(fd, fence3->file);
 362        fput(fence2->file);
 363        return 0;
 364
 365err_put_fence3:
 366        fput(fence3->file);
 367
 368err_put_fence2:
 369        fput(fence2->file);
 370
 371err_put_fd:
 372        put_unused_fd(fd);
 373        return err;
 374}
 375
 376static int sync_fill_fence_info(struct dma_fence *fence,
 377                                 struct sync_fence_info *info)
 378{
 379        strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
 380                sizeof(info->obj_name));
 381        strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
 382                sizeof(info->driver_name));
 383
 384        info->status = dma_fence_get_status(fence);
 385        while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
 386               !test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags))
 387                cpu_relax();
 388        info->timestamp_ns =
 389                test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ?
 390                ktime_to_ns(fence->timestamp) :
 391                ktime_set(0, 0);
 392
 393        return info->status;
 394}
 395
 396static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
 397                                       unsigned long arg)
 398{
 399        struct sync_fence_info *fence_info = NULL;
 400        struct dma_fence_unwrap iter;
 401        struct sync_file_info info;
 402        unsigned int num_fences;
 403        struct dma_fence *fence;
 404        int ret;
 405        __u32 size;
 406
 407        if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
 408                return -EFAULT;
 409
 410        if (info.flags || info.pad)
 411                return -EINVAL;
 412
 413        num_fences = 0;
 414        dma_fence_unwrap_for_each(fence, &iter, sync_file->fence)
 415                ++num_fences;
 416
 417        /*
 418         * Passing num_fences = 0 means that userspace doesn't want to
 419         * retrieve any sync_fence_info. If num_fences = 0 we skip filling
 420         * sync_fence_info and return the actual number of fences on
 421         * info->num_fences.
 422         */
 423        if (!info.num_fences) {
 424                info.status = dma_fence_get_status(sync_file->fence);
 425                goto no_fences;
 426        } else {
 427                info.status = 1;
 428        }
 429
 430        if (info.num_fences < num_fences)
 431                return -EINVAL;
 432
 433        size = num_fences * sizeof(*fence_info);
 434        fence_info = kzalloc(size, GFP_KERNEL);
 435        if (!fence_info)
 436                return -ENOMEM;
 437
 438        num_fences = 0;
 439        dma_fence_unwrap_for_each(fence, &iter, sync_file->fence) {
 440                int status;
 441
 442                status = sync_fill_fence_info(fence, &fence_info[num_fences++]);
 443                info.status = info.status <= 0 ? info.status : status;
 444        }
 445
 446        if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
 447                         size)) {
 448                ret = -EFAULT;
 449                goto out;
 450        }
 451
 452no_fences:
 453        sync_file_get_name(sync_file, info.name, sizeof(info.name));
 454        info.num_fences = num_fences;
 455
 456        if (copy_to_user((void __user *)arg, &info, sizeof(info)))
 457                ret = -EFAULT;
 458        else
 459                ret = 0;
 460
 461out:
 462        kfree(fence_info);
 463
 464        return ret;
 465}
 466
 467static long sync_file_ioctl(struct file *file, unsigned int cmd,
 468                            unsigned long arg)
 469{
 470        struct sync_file *sync_file = file->private_data;
 471
 472        switch (cmd) {
 473        case SYNC_IOC_MERGE:
 474                return sync_file_ioctl_merge(sync_file, arg);
 475
 476        case SYNC_IOC_FILE_INFO:
 477                return sync_file_ioctl_fence_info(sync_file, arg);
 478
 479        default:
 480                return -ENOTTY;
 481        }
 482}
 483
 484static const struct file_operations sync_file_fops = {
 485        .release = sync_file_release,
 486        .poll = sync_file_poll,
 487        .unlocked_ioctl = sync_file_ioctl,
 488        .compat_ioctl = compat_ptr_ioctl,
 489};
 490