summaryrefslogtreecommitdiff
path: root/drivers/edgetpu/edgetpu-dmabuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edgetpu/edgetpu-dmabuf.c')
-rw-r--r--drivers/edgetpu/edgetpu-dmabuf.c95
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);
}