123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
- */
- #include <linux/types.h>
- #include <linux/dma-buf.h>
- #include <linux/dma-fence.h>
- #include <linux/slab.h>
- #include <linux/spinlock.h>
- #include <linux/regmap.h>
- #include <linux/uaccess.h>
- #include <linux/jiffies.h>
- #include "hgsl.h"
- #define HGSL_HSYNC_FINI_RETRY_COUNT 50
- #define HGSL_HSYNC_FINI_RETRY_TIME_SLICE 10
- #define HGSL_TIMELINE_INFINITE_TIMEOUT (~(0ULL))
- static const struct dma_fence_ops hgsl_hsync_fence_ops;
- static const struct dma_fence_ops hgsl_isync_fence_ops;
- int hgsl_hsync_fence_create_fd(struct hgsl_context *context,
- uint32_t ts)
- {
- int fence_fd;
- struct hgsl_hsync_fence *fence;
- fence_fd = get_unused_fd_flags(0);
- if (fence_fd < 0)
- return fence_fd;
- fence = hgsl_hsync_fence_create(context, ts);
- if (fence == NULL) {
- put_unused_fd(fence_fd);
- return -ENOMEM;
- }
- fd_install(fence_fd, fence->sync_file->file);
- return fence_fd;
- }
- struct hgsl_hsync_fence *hgsl_hsync_fence_create(
- struct hgsl_context *context,
- uint32_t ts)
- {
- unsigned long flags;
- struct hgsl_hsync_timeline *timeline = context->timeline;
- struct hgsl_hsync_fence *fence;
- if (timeline == NULL)
- return NULL;
- if (!kref_get_unless_zero(&timeline->kref))
- return NULL;
- fence = kzalloc(sizeof(*fence), GFP_KERNEL);
- if (fence == NULL) {
- hgsl_hsync_timeline_put(timeline);
- return NULL;
- }
- fence->ts = ts;
- dma_fence_init(&fence->fence, &hgsl_hsync_fence_ops,
- &timeline->lock, timeline->fence_context, ts);
- fence->sync_file = sync_file_create(&fence->fence);
- dma_fence_put(&fence->fence);
- if (fence->sync_file == NULL) {
- hgsl_hsync_timeline_put(timeline);
- return NULL;
- }
- fence->timeline = timeline;
- spin_lock_irqsave(&timeline->lock, flags);
- list_add_tail(&fence->child_list, &timeline->fence_list);
- spin_unlock_irqrestore(&timeline->lock, flags);
- return fence;
- }
- void hgsl_hsync_timeline_signal(struct hgsl_hsync_timeline *timeline,
- unsigned int ts)
- {
- struct hgsl_hsync_fence *cur, *next;
- unsigned long flags;
- if (!kref_get_unless_zero(&timeline->kref))
- return;
- if (hgsl_ts32_ge(timeline->last_ts, ts)) {
- hgsl_hsync_timeline_put(timeline);
- return;
- }
- spin_lock_irqsave(&timeline->lock, flags);
- timeline->last_ts = ts;
- list_for_each_entry_safe(cur, next, &timeline->fence_list,
- child_list) {
- if (dma_fence_is_signaled_locked(&cur->fence))
- list_del_init(&cur->child_list);
- }
- spin_unlock_irqrestore(&timeline->lock, flags);
- hgsl_hsync_timeline_put(timeline);
- }
- int hgsl_hsync_timeline_create(struct hgsl_context *context)
- {
- struct hgsl_hsync_timeline *timeline;
- timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
- if (!timeline)
- return -ENOMEM;
- snprintf(timeline->name, HGSL_TIMELINE_NAME_LEN,
- "timeline_%s_%d",
- current->comm, current->pid);
- kref_init(&timeline->kref);
- timeline->fence_context = dma_fence_context_alloc(1);
- INIT_LIST_HEAD(&timeline->fence_list);
- spin_lock_init(&timeline->lock);
- timeline->context = context;
- context->timeline = timeline;
- return 0;
- }
- static void hgsl_hsync_timeline_destroy(struct kref *kref)
- {
- struct hgsl_hsync_timeline *timeline =
- container_of(kref, struct hgsl_hsync_timeline, kref);
- kfree(timeline);
- }
- void hgsl_hsync_timeline_put(struct hgsl_hsync_timeline *timeline)
- {
- if (timeline)
- kref_put(&timeline->kref, hgsl_hsync_timeline_destroy);
- }
- void hgsl_hsync_timeline_fini(struct hgsl_context *context)
- {
- struct hgsl_hsync_timeline *timeline = context->timeline;
- struct hgsl_hsync_fence *fence;
- int retry_count = HGSL_HSYNC_FINI_RETRY_COUNT;
- unsigned int max_ts = 0;
- unsigned long flags;
- if (!kref_get_unless_zero(&timeline->kref))
- return;
- spin_lock_irqsave(&timeline->lock, flags);
- while ((retry_count >= 0) && (!list_empty(&timeline->fence_list))) {
- spin_unlock_irqrestore(&timeline->lock, flags);
- msleep(HGSL_HSYNC_FINI_RETRY_TIME_SLICE);
- retry_count--;
- spin_lock_irqsave(&timeline->lock, flags);
- }
- list_for_each_entry(fence, &timeline->fence_list, child_list)
- if (max_ts < fence->ts)
- max_ts = fence->ts;
- spin_unlock_irqrestore(&timeline->lock, flags);
- hgsl_hsync_timeline_signal(timeline, max_ts);
- context->last_ts = max_ts;
- hgsl_hsync_timeline_put(timeline);
- }
- static const char *hgsl_hsync_get_driver_name(struct dma_fence *base)
- {
- return "hgsl-timeline";
- }
- static const char *hgsl_hsync_get_timeline_name(struct dma_fence *base)
- {
- struct hgsl_hsync_fence *fence =
- container_of(base, struct hgsl_hsync_fence, fence);
- struct hgsl_hsync_timeline *timeline = fence->timeline;
- return (timeline == NULL) ? "null" : timeline->name;
- }
- static bool hgsl_hsync_enable_signaling(struct dma_fence *base)
- {
- return true;
- }
- static bool hgsl_hsync_has_signaled(struct dma_fence *base)
- {
- struct hgsl_hsync_fence *fence =
- container_of(base, struct hgsl_hsync_fence, fence);
- struct hgsl_hsync_timeline *timeline = fence->timeline;
- return hgsl_ts32_ge(timeline->last_ts, fence->ts);
- }
- static void hgsl_hsync_fence_release(struct dma_fence *base)
- {
- struct hgsl_hsync_fence *fence =
- container_of(base, struct hgsl_hsync_fence, fence);
- struct hgsl_hsync_timeline *timeline = fence->timeline;
- if (timeline) {
- spin_lock(&timeline->lock);
- list_del_init(&fence->child_list);
- spin_unlock(&timeline->lock);
- hgsl_hsync_timeline_put(timeline);
- }
- kfree(fence);
- }
- static void hgsl_hsync_fence_value_str(struct dma_fence *base,
- char *str, int size)
- {
- struct hgsl_hsync_fence *fence =
- container_of(base, struct hgsl_hsync_fence, fence);
- snprintf(str, size, "%u", fence->ts);
- }
- static void hgsl_hsync_timeline_value_str(struct dma_fence *base,
- char *str, int size)
- {
- struct hgsl_hsync_fence *fence =
- container_of(base, struct hgsl_hsync_fence, fence);
- struct hgsl_hsync_timeline *timeline = fence->timeline;
- if (!kref_get_unless_zero(&timeline->kref))
- return;
- snprintf(str, size, "Last retired TS:%u", timeline->last_ts);
- hgsl_hsync_timeline_put(timeline);
- }
- static const struct dma_fence_ops hgsl_hsync_fence_ops = {
- .get_driver_name = hgsl_hsync_get_driver_name,
- .get_timeline_name = hgsl_hsync_get_timeline_name,
- .enable_signaling = hgsl_hsync_enable_signaling,
- .signaled = hgsl_hsync_has_signaled,
- .wait = dma_fence_default_wait,
- .release = hgsl_hsync_fence_release,
- .fence_value_str = hgsl_hsync_fence_value_str,
- .timeline_value_str = hgsl_hsync_timeline_value_str,
- };
- static void hgsl_isync_timeline_release(struct kref *kref)
- {
- struct hgsl_isync_timeline *timeline = container_of(kref,
- struct hgsl_isync_timeline,
- kref);
- kfree(timeline);
- }
- static struct hgsl_isync_timeline *
- hgsl_isync_timeline_get(struct hgsl_priv *priv, int id, bool check_owner)
- {
- int ret = 0;
- struct qcom_hgsl *hgsl = priv->dev;
- struct hgsl_isync_timeline *timeline = NULL;
- spin_lock(&hgsl->isync_timeline_lock);
- timeline = idr_find(&hgsl->isync_timeline_idr, id);
- if (timeline) {
- if (check_owner && (timeline->priv != priv)) {
- timeline = NULL;
- } else {
- ret = kref_get_unless_zero(&timeline->kref);
- if (!ret)
- timeline = NULL;
- }
- }
- spin_unlock(&hgsl->isync_timeline_lock);
- return timeline;
- }
- static void hgsl_isync_timeline_put(struct hgsl_isync_timeline *timeline)
- {
- if (timeline)
- kref_put(&timeline->kref, hgsl_isync_timeline_release);
- }
- int hgsl_isync_timeline_create(struct hgsl_priv *priv,
- uint32_t *timeline_id,
- uint32_t flags,
- uint64_t initial_ts)
- {
- struct qcom_hgsl *hgsl = priv->dev;
- struct hgsl_isync_timeline *timeline;
- int ret = -EINVAL;
- uint32_t idr;
- if (timeline_id == NULL)
- return -EINVAL;
- timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
- if (timeline == NULL)
- return -ENOMEM;
- kref_init(&timeline->kref);
- timeline->context = dma_fence_context_alloc(1);
- INIT_LIST_HEAD(&timeline->fence_list);
- spin_lock_init(&timeline->lock);
- timeline->priv = priv;
- snprintf((char *) timeline->name, sizeof(timeline->name),
- "isync-timeline-%d", *timeline_id);
- timeline->flags = flags;
- timeline->last_ts = initial_ts;
- timeline->is64bits = ((flags & HGSL_ISYNC_64BITS_TIMELINE) != 0);
- idr_preload(GFP_KERNEL);
- spin_lock(&hgsl->isync_timeline_lock);
- idr = idr_alloc(&hgsl->isync_timeline_idr, timeline, 1, 0, GFP_NOWAIT);
- if (idr > 0) {
- timeline->id = idr;
- *timeline_id = idr;
- ret = 0;
- }
- spin_unlock(&hgsl->isync_timeline_lock);
- idr_preload_end();
- /* allocate IDR failed */
- if (ret != 0)
- kfree(timeline);
- return ret;
- }
- int hgsl_isync_fence_create(struct hgsl_priv *priv, uint32_t timeline_id,
- uint32_t ts, bool ts_is_valid, int *fence_fd)
- {
- unsigned long flags;
- struct hgsl_isync_timeline *timeline = NULL;
- struct hgsl_isync_fence *fence = NULL;
- struct sync_file *sync_file = NULL;
- int ret = 0;
- if (fence_fd == NULL)
- return -EINVAL;
- timeline = hgsl_isync_timeline_get(priv, timeline_id, true);
- if (timeline == NULL) {
- ret = -EINVAL;
- goto out;
- }
- fence = kzalloc(sizeof(*fence), GFP_KERNEL);
- if (fence == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- /* set a minimal ts if user don't set it */
- if (!ts_is_valid)
- ts = 1;
- fence->ts = ts;
- dma_fence_init(&fence->fence, &hgsl_isync_fence_ops,
- &timeline->lock,
- timeline->context,
- ts);
- sync_file = sync_file_create(&fence->fence);
- if (sync_file == NULL) {
- ret = -ENOMEM;
- goto out_fence;
- }
- *fence_fd = get_unused_fd_flags(0);
- if (*fence_fd < 0) {
- ret = -EBADF;
- goto out_fence;
- }
- fd_install(*fence_fd, sync_file->file);
- fence->timeline = timeline;
- spin_lock_irqsave(&timeline->lock, flags);
- list_add_tail(&fence->child_list, &timeline->fence_list);
- spin_unlock_irqrestore(&timeline->lock, flags);
- out_fence:
- dma_fence_put(&fence->fence);
- out:
- if (ret) {
- if (sync_file)
- fput(sync_file->file);
- if (timeline)
- hgsl_isync_timeline_put(timeline);
- }
- return ret;
- }
- static int hgsl_isync_timeline_destruct(struct hgsl_priv *priv,
- struct hgsl_isync_timeline *timeline)
- {
- unsigned long flags;
- struct hgsl_isync_fence *cur, *next;
- LIST_HEAD(flist);
- if (timeline == NULL)
- return -EINVAL;
- spin_lock_irqsave(&timeline->lock, flags);
- list_for_each_entry_safe(cur, next, &timeline->fence_list,
- child_list) {
- if (dma_fence_get_rcu(&cur->fence)) {
- list_del_init(&cur->child_list);
- list_add(&cur->free_list, &flist);
- }
- }
- spin_unlock_irqrestore(&timeline->lock, flags);
- list_for_each_entry_safe(cur, next, &flist, free_list) {
- list_del(&cur->free_list);
- dma_fence_signal(&cur->fence);
- dma_fence_put(&cur->fence);
- }
- hgsl_isync_timeline_put(timeline);
- return 0;
- }
- int hgsl_isync_timeline_destroy(struct hgsl_priv *priv, uint32_t id)
- {
- struct qcom_hgsl *hgsl = priv->dev;
- struct hgsl_isync_timeline *timeline;
- spin_lock(&hgsl->isync_timeline_lock);
- timeline = idr_find(&hgsl->isync_timeline_idr, id);
- if (timeline) {
- if (timeline->priv == priv) {
- idr_remove(&hgsl->isync_timeline_idr, timeline->id);
- timeline->id = 0;
- } else {
- timeline = NULL;
- }
- }
- spin_unlock(&hgsl->isync_timeline_lock);
- if (timeline == NULL)
- return -EINVAL;
- return hgsl_isync_timeline_destruct(priv, timeline);
- }
- void hgsl_isync_fini(struct hgsl_priv *priv)
- {
- LIST_HEAD(flist);
- struct qcom_hgsl *hgsl = priv->dev;
- struct hgsl_isync_timeline *cur, *t;
- uint32_t idr;
- spin_lock(&hgsl->isync_timeline_lock);
- idr_for_each_entry(&hgsl->isync_timeline_idr,
- cur, idr) {
- if (cur->priv == priv) {
- idr_remove(&hgsl->isync_timeline_idr, idr);
- list_add(&cur->free_list, &flist);
- }
- }
- spin_unlock(&hgsl->isync_timeline_lock);
- list_for_each_entry_safe(cur, t, &flist, free_list) {
- list_del(&cur->free_list);
- hgsl_isync_timeline_destruct(priv, cur);
- }
- }
- static int _isync_timeline_signal(
- struct hgsl_isync_timeline *timeline,
- struct dma_fence *fence)
- {
- unsigned long flags;
- int ret = -EINVAL;
- struct hgsl_isync_fence *cur, *next;
- bool found = false;
- spin_lock_irqsave(&timeline->lock, flags);
- list_for_each_entry_safe(cur, next, &timeline->fence_list,
- child_list) {
- if (fence == &cur->fence) {
- list_del_init(&cur->child_list);
- found = true;
- break;
- }
- }
- spin_unlock_irqrestore(&timeline->lock, flags);
- if (found) {
- dma_fence_signal(fence);
- ret = 0;
- }
- return ret;
- }
- int hgsl_isync_fence_signal(struct hgsl_priv *priv, uint32_t timeline_id,
- int fence_fd)
- {
- struct hgsl_isync_timeline *timeline;
- struct dma_fence *fence = NULL;
- int ret = -EINVAL;
- timeline = hgsl_isync_timeline_get(priv, timeline_id, true);
- if (timeline == NULL) {
- ret = -EINVAL;
- goto out;
- }
- fence = sync_file_get_fence(fence_fd);
- if (fence == NULL) {
- ret = -EBADF;
- goto out;
- }
- ret = _isync_timeline_signal(timeline, fence);
- out:
- if (fence)
- dma_fence_put(fence);
- if (timeline)
- hgsl_isync_timeline_put(timeline);
- return ret;
- }
- int hgsl_isync_forward(struct hgsl_priv *priv, uint32_t timeline_id,
- uint64_t ts, bool check_owner)
- {
- unsigned long flags;
- struct hgsl_isync_timeline *timeline;
- struct hgsl_isync_fence *cur, *next;
- struct dma_fence *base;
- LIST_HEAD(flist);
- timeline = hgsl_isync_timeline_get(priv, timeline_id, check_owner);
- if (timeline == NULL)
- return -EINVAL;
- if (hgsl_ts_ge(timeline->last_ts, ts, timeline->is64bits))
- goto out;
- spin_lock_irqsave(&timeline->lock, flags);
- timeline->last_ts = ts;
- list_for_each_entry_safe(cur, next, &timeline->fence_list,
- child_list) {
- if (hgsl_ts_ge(ts, cur->ts, timeline->is64bits)) {
- base = dma_fence_get_rcu(&cur->fence);
- list_del_init(&cur->child_list);
- /* It *shouldn't* happen. If it does, it's
- * the last thing you'll see
- */
- if (base == NULL)
- pr_warn(" Invalid fence:%p.\n", cur);
- else
- list_add(&cur->free_list, &flist);
- }
- }
- spin_unlock_irqrestore(&timeline->lock, flags);
- list_for_each_entry_safe(cur, next, &flist, free_list) {
- list_del(&cur->free_list);
- dma_fence_signal(&cur->fence);
- dma_fence_put(&cur->fence);
- }
- out:
- if (timeline)
- hgsl_isync_timeline_put(timeline);
- return 0;
- }
- int hgsl_isync_query(struct hgsl_priv *priv, uint32_t timeline_id,
- uint64_t *ts)
- {
- struct hgsl_isync_timeline *timeline;
- timeline = hgsl_isync_timeline_get(priv, timeline_id, false);
- if (timeline == NULL)
- return -EINVAL;
- *ts = timeline->last_ts;
- hgsl_isync_timeline_put(timeline);
- return 0;
- }
- static struct dma_fence *hgsl_timelines_to_fence_array(struct hgsl_priv *priv,
- u64 timelines, u32 count, u64 usize, bool any)
- {
- void __user *uptr = u64_to_user_ptr(timelines);
- struct dma_fence_array *array;
- struct dma_fence **fences;
- struct hgsl_isync_fence *fence = NULL;
- int i, ret = 0;
- if (!count || count > INT_MAX)
- return ERR_PTR(-EINVAL);
- fences = kcalloc(count, sizeof(*fences),
- GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN);
- if (!fences)
- return ERR_PTR(-ENOMEM);
- for (i = 0; i < count; i++) {
- struct hgsl_timeline_val val;
- struct hgsl_isync_timeline *timeline;
- if (copy_struct_from_user(&val, sizeof(val), uptr, usize)) {
- ret = -EFAULT;
- goto err;
- }
- if (val.padding) {
- ret = -EINVAL;
- goto err;
- }
- timeline = hgsl_isync_timeline_get(priv, val.timeline_id, false);
- if (!timeline) {
- ret = -ENOENT;
- goto err;
- }
- fence = kzalloc(sizeof(*fence), GFP_KERNEL);
- if (fence == NULL) {
- hgsl_isync_timeline_put(timeline);
- ret = -ENOMEM;
- goto err;
- }
- fence->timeline = timeline;
- fence->ts = val.timepoint;
- dma_fence_init(&fence->fence, &hgsl_isync_fence_ops,
- &timeline->lock,
- timeline->context,
- fence->ts);
- spin_lock(&timeline->lock);
- list_add_tail(&fence->child_list, &timeline->fence_list);
- spin_unlock(&timeline->lock);
- fences[i] = &fence->fence;
- uptr += usize;
- }
- /* No need for a fence array for only one fence */
- if (count == 1) {
- struct dma_fence *fence = fences[0];
- kfree(fences);
- return fence;
- }
- array = dma_fence_array_create(count, fences,
- dma_fence_context_alloc(1), 0, any);
- if (array)
- return &array->base;
- ret = -ENOMEM;
- err:
- for (i = 0; i < count; i++) {
- if (!IS_ERR_OR_NULL(fences[i]))
- dma_fence_put(fences[i]);
- }
- kfree(fences);
- return ERR_PTR(ret);
- }
- int hgsl_isync_wait_multiple(struct hgsl_priv *priv, struct hgsl_timeline_wait *param)
- {
- struct dma_fence *fence;
- unsigned long timeout;
- signed long ret;
- if (param->flags != HGSL_TIMELINE_WAIT_ANY &&
- param->flags != HGSL_TIMELINE_WAIT_ALL)
- return -EINVAL;
- if (param->padding)
- return -EINVAL;
- fence = hgsl_timelines_to_fence_array(priv, param->timelines,
- param->count, param->timelines_size,
- (param->flags == HGSL_TIMELINE_WAIT_ANY));
- if (IS_ERR(fence))
- return PTR_ERR(fence);
- if (param->timeout_nanosec == HGSL_TIMELINE_INFINITE_TIMEOUT)
- timeout = MAX_SCHEDULE_TIMEOUT;
- else {
- struct timespec64 timespec;
- timespec.tv_sec = param->timeout_nanosec / NSEC_PER_SEC;
- timespec.tv_nsec = param->timeout_nanosec % NSEC_PER_SEC;
- timeout = timespec64_to_jiffies(×pec);
- }
- if (!timeout)
- ret = dma_fence_is_signaled(fence) ? 0 : -EBUSY;
- else {
- ret = dma_fence_wait_timeout(fence, true, timeout);
- if (!ret)
- ret = -ETIMEDOUT;
- else if (ret > 0)
- ret = 0;
- else if (ret == -ERESTARTSYS)
- ret = -EINTR;
- }
- dma_fence_put(fence);
- return ret;
- }
- static const char *hgsl_isync_get_driver_name(struct dma_fence *base)
- {
- return "hgsl";
- }
- static const char *hgsl_isync_get_timeline_name(struct dma_fence *base)
- {
- struct hgsl_isync_fence *fence =
- container_of(base,
- struct hgsl_isync_fence,
- fence);
- struct hgsl_isync_timeline *timeline = fence->timeline;
- return (timeline == NULL) ? "null":timeline->name;
- }
- static bool hgsl_isync_has_signaled(struct dma_fence *base)
- {
- struct hgsl_isync_fence *fence = NULL;
- struct hgsl_isync_timeline *timeline = NULL;
- if (base) {
- fence = container_of(base, struct hgsl_isync_fence, fence);
- timeline = fence->timeline;
- if (timeline)
- return hgsl_ts_ge(timeline->last_ts, fence->ts, timeline->is64bits);
- }
- return false;
- }
- static bool hgsl_isync_enable_signaling(struct dma_fence *base)
- {
- return !hgsl_isync_has_signaled(base);
- }
- static void hgsl_isync_fence_release(struct dma_fence *base)
- {
- unsigned long flags;
- struct hgsl_isync_fence *fence = container_of(base,
- struct hgsl_isync_fence,
- fence);
- struct hgsl_isync_timeline *timeline = fence->timeline;
- if (timeline) {
- spin_lock_irqsave(&timeline->lock, flags);
- list_del_init(&fence->child_list);
- spin_unlock_irqrestore(&timeline->lock, flags);
- dma_fence_signal(base);
- hgsl_isync_timeline_put(fence->timeline);
- }
- kfree(fence);
- }
- static void hgsl_isync_fence_value_str(struct dma_fence *base,
- char *str, int size)
- {
- snprintf(str, size, "%llu", base->context);
- }
- static const struct dma_fence_ops hgsl_isync_fence_ops = {
- .get_driver_name = hgsl_isync_get_driver_name,
- .get_timeline_name = hgsl_isync_get_timeline_name,
- .enable_signaling = hgsl_isync_enable_signaling,
- .signaled = hgsl_isync_has_signaled,
- .wait = dma_fence_default_wait,
- .release = hgsl_isync_fence_release,
- .fence_value_str = hgsl_isync_fence_value_str,
- };
|