diff options
Diffstat (limited to 'drivers/edgetpu/edgetpu-dmabuf.c')
-rw-r--r-- | drivers/edgetpu/edgetpu-dmabuf.c | 95 |
1 files changed, 77 insertions, 18 deletions
diff --git a/drivers/edgetpu/edgetpu-dmabuf.c b/drivers/edgetpu/edgetpu-dmabuf.c index 657ae75..72072f6 100644 --- a/drivers/edgetpu/edgetpu-dmabuf.c +++ b/drivers/edgetpu/edgetpu-dmabuf.c @@ -72,6 +72,9 @@ struct edgetpu_dmabuf_map { * @fence: the base DMA fence * @lock: spinlock protecting updates to @fence * @timeline_name: name of the timeline associated with the fence + * @group: owning device group + * @etfence_list: global list of all edgetpu DMA fences + * @group_list: list of DMA fences owned by the same group * * It is likely timelines will become a separate object in the future, * but for now there's a unique named timeline associated with each fence. @@ -80,7 +83,9 @@ struct edgetpu_dma_fence { struct dma_fence fence; spinlock_t lock; char timeline_name[EDGETPU_SYNC_TIMELINE_NAME_LEN]; + struct edgetpu_device_group *group; struct list_head etfence_list; + struct list_head group_list; }; /* List of all edgetpu fence objects for debugging. */ @@ -873,6 +878,7 @@ static const char *edgetpu_dma_fence_get_timeline_name(struct dma_fence *fence) static void edgetpu_dma_fence_release(struct dma_fence *fence) { struct edgetpu_dma_fence *etfence = to_etfence(fence); + struct edgetpu_device_group *group; unsigned long flags; if (!etfence) @@ -881,6 +887,17 @@ static void edgetpu_dma_fence_release(struct dma_fence *fence) spin_lock_irqsave(&etfence_list_lock, flags); list_del(&etfence->etfence_list); spin_unlock_irqrestore(&etfence_list_lock, flags); + + /* TODO(b/258868303): Don't remove this check when group required, might not yet be set. */ + group = etfence->group; + if (group) { + mutex_lock(&group->lock); + list_del(&etfence->group_list); + mutex_unlock(&group->lock); + /* Release this fence's reference on the owning group. */ + edgetpu_device_group_put(group); + } + kfree(etfence); } @@ -904,7 +921,8 @@ static const struct dma_fence_ops edgetpu_dma_fence_ops = { #define SEQ_FMT "%llu" #endif -int edgetpu_sync_fence_create(struct edgetpu_create_sync_fence_data *datap) +int edgetpu_sync_fence_create(struct edgetpu_device_group *group, + struct edgetpu_create_sync_fence_data *datap) { int fd = get_unused_fd_flags(O_CLOEXEC); int ret; @@ -926,6 +944,7 @@ int edgetpu_sync_fence_create(struct edgetpu_create_sync_fence_data *datap) * list_head is needed for list_del(). */ INIT_LIST_HEAD(&etfence->etfence_list); + INIT_LIST_HEAD(&etfence->group_list); memcpy(&etfence->timeline_name, &datap->timeline_name, EDGETPU_SYNC_TIMELINE_NAME_LEN - 1); @@ -945,6 +964,14 @@ int edgetpu_sync_fence_create(struct edgetpu_create_sync_fence_data *datap) list_add_tail(&etfence->etfence_list, &etfence_list_head); spin_unlock_irqrestore(&etfence_list_lock, flags); + /* TODO(b/258868303): Make group required, disallow creating fence we can't track. */ + if (group) { + etfence->group = edgetpu_device_group_get(group); + mutex_lock(&group->lock); + list_add_tail(&etfence->group_list, &group->dma_fence_list); + mutex_unlock(&group->lock); + } + fd_install(fd, sync_file->file); datap->fence = fd; return 0; @@ -954,26 +981,14 @@ err_put_fd: return ret; } -int edgetpu_sync_fence_signal(struct edgetpu_signal_sync_fence_data *datap) +static int _edgetpu_sync_fence_signal(struct dma_fence *fence, int errno, bool ignore_signaled) { - struct dma_fence *fence; - int errno; int ret; - errno = datap->error; - if (errno > 0) - errno = -errno; - if (errno < -MAX_ERRNO) - return -EINVAL; - - fence = sync_file_get_fence(datap->fence); - if (!fence) - return -EINVAL; - spin_lock_irq(fence->lock); /* don't signal fence twice */ if (unlikely(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))) { - ret = -EINVAL; + ret = ignore_signaled ? 0 : -EINVAL; goto out_unlock; } pr_debug("%s: %s-%s%llu-" SEQ_FMT " errno=%d\n", __func__, @@ -986,10 +1001,51 @@ int edgetpu_sync_fence_signal(struct edgetpu_signal_sync_fence_data *datap) out_unlock: spin_unlock_irq(fence->lock); + return ret; +} + +int edgetpu_sync_fence_signal(struct edgetpu_signal_sync_fence_data *datap) +{ + struct dma_fence *fence; + int errno; + int ret; + + errno = datap->error; + if (errno > 0) + errno = -errno; + if (errno < -MAX_ERRNO) + return -EINVAL; + + fence = sync_file_get_fence(datap->fence); + if (!fence) + return -EINVAL; + + ret = _edgetpu_sync_fence_signal(fence, errno, false); dma_fence_put(fence); return ret; } +/* Caller holds group lock. */ +void edgetpu_sync_fence_group_shutdown(struct edgetpu_device_group *group) +{ + struct list_head *pos; + int ret; + + lockdep_assert_held(&group->lock); + list_for_each(pos, &group->dma_fence_list) { + struct edgetpu_dma_fence *etfence = + container_of(pos, struct edgetpu_dma_fence, group_list); + struct dma_fence *fence = &etfence->fence; + + ret = _edgetpu_sync_fence_signal(fence, -EPIPE, true); + if (ret) + etdev_warn(group->etdev, "error %d signaling fence %s-%s %llu-" SEQ_FMT, + ret, fence->ops->get_driver_name(fence), + fence->ops->get_timeline_name(fence), + fence->context, fence->seqno); + } +} + int edgetpu_sync_fence_status(struct edgetpu_sync_fence_status *datap) { struct dma_fence *fence; @@ -1027,8 +1083,9 @@ int edgetpu_sync_fence_debugfs_show(struct seq_file *s, void *unused) spin_lock_irq(&etfence->lock); seq_printf(s, "%s-%s %llu-" SEQ_FMT " %s", - edgetpu_dma_fence_get_driver_name(fence), - etfence->timeline_name, fence->context, fence->seqno, + fence->ops->get_driver_name(fence), + fence->ops->get_timeline_name(fence), + fence->context, fence->seqno, sync_status_str(dma_fence_get_status_locked(fence))); if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) { @@ -1041,7 +1098,9 @@ int edgetpu_sync_fence_debugfs_show(struct seq_file *s, void *unused) if (fence->error) seq_printf(s, " err=%d", fence->error); - + /* TODO(b/258868303): Remove check when group is required. */ + if (etfence->group) + seq_printf(s, " group=%u", etfence->group->workload_id); seq_putc(s, '\n'); spin_unlock_irq(&etfence->lock); } |