// SPDX-License-Identifier: GPL-2.0-only /* * Sync File validation framework * * Copyright (C) 2012 Google, Inc. */ #include <linux/file.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/slab.h> #include <linux/sync_file.h> #include "sync_debug.h" #define CREATE_TRACE_POINTS #include "sync_trace.h" /* * SW SYNC validation framework * * A sync object driver that uses a 32bit counter to coordinate * synchronization. Useful when there is no hardware primitive backing * the synchronization. * * To start the framework just open: * * <debugfs>/sync/sw_sync * * That will create a sync timeline, all fences created under this timeline * file descriptor will belong to the this timeline. * * The 'sw_sync' file can be opened many times as to create different * timelines. * * Fences can be created with SW_SYNC_IOC_CREATE_FENCE ioctl with struct * sw_sync_create_fence_data as parameter. * * To increment the timeline counter, SW_SYNC_IOC_INC ioctl should be used * with the increment as u32. This will update the last signaled value * from the timeline and signal any fence that has a seqno smaller or equal * to it. * * struct sw_sync_create_fence_data * @value: the seqno to initialise the fence with * @name: the name of the new sync point * @fence: return the fd of the new sync_file with the created fence */ struct sw_sync_create_fence_data { … }; /** * struct sw_sync_get_deadline - get the deadline hint of a sw_sync fence * @deadline_ns: absolute time of the deadline * @pad: must be zero * @fence_fd: the sw_sync fence fd (in) * * Return the earliest deadline set on the fence. The timebase for the * deadline is CLOCK_MONOTONIC (same as vblank). If there is no deadline * set on the fence, this ioctl will return -ENOENT. */ struct sw_sync_get_deadline { … }; #define SW_SYNC_IOC_MAGIC … #define SW_SYNC_IOC_CREATE_FENCE … #define SW_SYNC_IOC_INC … #define SW_SYNC_GET_DEADLINE … #define SW_SYNC_HAS_DEADLINE_BIT … static const struct dma_fence_ops timeline_fence_ops; static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence) { … } /** * sync_timeline_create() - creates a sync object * @name: sync_timeline name * * Creates a new sync_timeline. Returns the sync_timeline object or NULL in * case of error. */ static struct sync_timeline *sync_timeline_create(const char *name) { … } static void sync_timeline_free(struct kref *kref) { … } static void sync_timeline_get(struct sync_timeline *obj) { … } static void sync_timeline_put(struct sync_timeline *obj) { … } static const char *timeline_fence_get_driver_name(struct dma_fence *fence) { … } static const char *timeline_fence_get_timeline_name(struct dma_fence *fence) { … } static void timeline_fence_release(struct dma_fence *fence) { … } static bool timeline_fence_signaled(struct dma_fence *fence) { … } static bool timeline_fence_enable_signaling(struct dma_fence *fence) { … } static void timeline_fence_value_str(struct dma_fence *fence, char *str, int size) { … } static void timeline_fence_timeline_value_str(struct dma_fence *fence, char *str, int size) { … } static void timeline_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) { … } static const struct dma_fence_ops timeline_fence_ops = …; /** * sync_timeline_signal() - signal a status change on a sync_timeline * @obj: sync_timeline to signal * @inc: num to increment on timeline->value * * A sync implementation should call this any time one of it's fences * has signaled or has an error condition. */ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) { … } /** * sync_pt_create() - creates a sync pt * @obj: parent sync_timeline * @value: value of the fence * * Creates a new sync_pt (fence) as a child of @parent. @size bytes will be * allocated allowing for implementation specific data to be kept after * the generic sync_timeline struct. Returns the sync_pt object or * NULL in case of error. */ static struct sync_pt *sync_pt_create(struct sync_timeline *obj, unsigned int value) { … } /* * *WARNING* * * improper use of this can result in deadlocking kernel drivers from userspace. */ /* opening sw_sync create a new sync obj */ static int sw_sync_debugfs_open(struct inode *inode, struct file *file) { … } static int sw_sync_debugfs_release(struct inode *inode, struct file *file) { … } static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, unsigned long arg) { … } static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) { … } static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long arg) { … } static long sw_sync_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { … } const struct file_operations sw_sync_debugfs_fops = …;