Skip to content

Commit

Permalink
dma-buf/sw_sync: Add fence deadline support
Browse files Browse the repository at this point in the history
This consists of simply storing the most recent deadline, and adding an
ioctl to retrieve the deadline.  This can be used in conjunction with
the SET_DEADLINE ioctl on a fence fd for testing.  Ie. create various
sw_sync fences, merge them into a fence-array, set deadline on the
fence-array and confirm that it is propagated properly to each fence.

v2: Switch UABI to express deadline as u64
v3: More verbose UAPI docs, show how to convert from timespec
v4: Better comments, track the soonest deadline, as a normal fence
    implementation would, return an error if no deadline set.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Christian König <christian.koenig@amd.com>
Acked-by: Pekka Paalanen <pekka.paalanen@collabora.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230823215458.203366-4-robdclark@gmail.com
  • Loading branch information
Rob Clark authored and Dmitry Baryshkov committed Dec 1, 2023
1 parent 63ee445 commit 70e67aa
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
82 changes: 82 additions & 0 deletions drivers/dma-buf/sw_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,33 @@ struct sw_sync_create_fence_data {
__s32 fence; /* fd of new fence */
};

/**
* 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 {
__u64 deadline_ns;
__u32 pad;
__s32 fence_fd;
};

#define SW_SYNC_IOC_MAGIC 'W'

#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
struct sw_sync_create_fence_data)

#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
#define SW_SYNC_GET_DEADLINE _IOWR(SW_SYNC_IOC_MAGIC, 2, \
struct sw_sync_get_deadline)


#define SW_SYNC_HAS_DEADLINE_BIT DMA_FENCE_FLAG_USER_BITS

static const struct dma_fence_ops timeline_fence_ops;

Expand Down Expand Up @@ -171,6 +192,22 @@ static void timeline_fence_timeline_value_str(struct dma_fence *fence,
snprintf(str, size, "%d", parent->value);
}

static void timeline_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
{
struct sync_pt *pt = dma_fence_to_sync_pt(fence);
unsigned long flags;

spin_lock_irqsave(fence->lock, flags);
if (test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) {
if (ktime_before(deadline, pt->deadline))
pt->deadline = deadline;
} else {
pt->deadline = deadline;
__set_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags);
}
spin_unlock_irqrestore(fence->lock, flags);
}

static const struct dma_fence_ops timeline_fence_ops = {
.get_driver_name = timeline_fence_get_driver_name,
.get_timeline_name = timeline_fence_get_timeline_name,
Expand All @@ -179,6 +216,7 @@ static const struct dma_fence_ops timeline_fence_ops = {
.release = timeline_fence_release,
.fence_value_str = timeline_fence_value_str,
.timeline_value_str = timeline_fence_timeline_value_str,
.set_deadline = timeline_fence_set_deadline,
};

/**
Expand Down Expand Up @@ -387,6 +425,47 @@ static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg)
return 0;
}

static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long arg)
{
struct sw_sync_get_deadline data;
struct dma_fence *fence;
unsigned long flags;
struct sync_pt *pt;
int ret = 0;

if (copy_from_user(&data, (void __user *)arg, sizeof(data)))
return -EFAULT;

if (data.deadline_ns || data.pad)
return -EINVAL;

fence = sync_file_get_fence(data.fence_fd);
if (!fence)
return -EINVAL;

pt = dma_fence_to_sync_pt(fence);
if (!pt)
return -EINVAL;

spin_lock_irqsave(fence->lock, flags);
if (test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) {
data.deadline_ns = ktime_to_ns(pt->deadline);
} else {
ret = -ENOENT;
}
spin_unlock_irqrestore(fence->lock, flags);

dma_fence_put(fence);

if (ret)
return ret;

if (copy_to_user((void __user *)arg, &data, sizeof(data)))
return -EFAULT;

return 0;
}

static long sw_sync_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
Expand All @@ -399,6 +478,9 @@ static long sw_sync_ioctl(struct file *file, unsigned int cmd,
case SW_SYNC_IOC_INC:
return sw_sync_ioctl_inc(obj, arg);

case SW_SYNC_GET_DEADLINE:
return sw_sync_ioctl_get_deadline(obj, arg);

default:
return -ENOTTY;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/dma-buf/sync_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence)
* @base: base fence object
* @link: link on the sync timeline's list
* @node: node in the sync timeline's tree
* @deadline: the earliest fence deadline hint
*/
struct sync_pt {
struct dma_fence base;
struct list_head link;
struct rb_node node;
ktime_t deadline;
};

extern const struct file_operations sw_sync_debugfs_fops;
Expand Down

0 comments on commit 70e67aa

Please sign in to comment.