18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * SPDX-License-Identifier: MIT
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * i915_sw_fence.h - library routines for N:M synchronisation points
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright (C) 2016 Intel Corporation
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#ifndef _I915_SW_FENCE_H_
108c2ecf20Sopenharmony_ci#define _I915_SW_FENCE_H_
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/dma-fence.h>
138c2ecf20Sopenharmony_ci#include <linux/gfp.h>
148c2ecf20Sopenharmony_ci#include <linux/kref.h>
158c2ecf20Sopenharmony_ci#include <linux/notifier.h> /* for NOTIFY_DONE */
168c2ecf20Sopenharmony_ci#include <linux/wait.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_cistruct completion;
198c2ecf20Sopenharmony_cistruct dma_resv;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct i915_sw_fence {
228c2ecf20Sopenharmony_ci	wait_queue_head_t wait;
238c2ecf20Sopenharmony_ci	unsigned long flags;
248c2ecf20Sopenharmony_ci	atomic_t pending;
258c2ecf20Sopenharmony_ci	int error;
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define I915_SW_FENCE_CHECKED_BIT	0 /* used internally for DAG checking */
298c2ecf20Sopenharmony_ci#define I915_SW_FENCE_PRIVATE_BIT	1 /* available for use by owner */
308c2ecf20Sopenharmony_ci#define I915_SW_FENCE_MASK		(~3)
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cienum i915_sw_fence_notify {
338c2ecf20Sopenharmony_ci	FENCE_COMPLETE,
348c2ecf20Sopenharmony_ci	FENCE_FREE
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_citypedef int (*i915_sw_fence_notify_t)(struct i915_sw_fence *,
388c2ecf20Sopenharmony_ci				      enum i915_sw_fence_notify state);
398c2ecf20Sopenharmony_ci#define __i915_sw_fence_call __aligned(4)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_civoid __i915_sw_fence_init(struct i915_sw_fence *fence,
428c2ecf20Sopenharmony_ci			  i915_sw_fence_notify_t fn,
438c2ecf20Sopenharmony_ci			  const char *name,
448c2ecf20Sopenharmony_ci			  struct lock_class_key *key);
458c2ecf20Sopenharmony_ci#ifdef CONFIG_LOCKDEP
468c2ecf20Sopenharmony_ci#define i915_sw_fence_init(fence, fn)				\
478c2ecf20Sopenharmony_cido {								\
488c2ecf20Sopenharmony_ci	static struct lock_class_key __key;			\
498c2ecf20Sopenharmony_ci								\
508c2ecf20Sopenharmony_ci	__i915_sw_fence_init((fence), (fn), #fence, &__key);	\
518c2ecf20Sopenharmony_ci} while (0)
528c2ecf20Sopenharmony_ci#else
538c2ecf20Sopenharmony_ci#define i915_sw_fence_init(fence, fn)				\
548c2ecf20Sopenharmony_ci	__i915_sw_fence_init((fence), (fn), NULL, NULL)
558c2ecf20Sopenharmony_ci#endif
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_civoid i915_sw_fence_reinit(struct i915_sw_fence *fence);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
608c2ecf20Sopenharmony_civoid i915_sw_fence_fini(struct i915_sw_fence *fence);
618c2ecf20Sopenharmony_ci#else
628c2ecf20Sopenharmony_cistatic inline void i915_sw_fence_fini(struct i915_sw_fence *fence) {}
638c2ecf20Sopenharmony_ci#endif
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_civoid i915_sw_fence_commit(struct i915_sw_fence *fence);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ciint i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
688c2ecf20Sopenharmony_ci				 struct i915_sw_fence *after,
698c2ecf20Sopenharmony_ci				 wait_queue_entry_t *wq);
708c2ecf20Sopenharmony_ciint i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
718c2ecf20Sopenharmony_ci				     struct i915_sw_fence *after,
728c2ecf20Sopenharmony_ci				     gfp_t gfp);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistruct i915_sw_dma_fence_cb {
758c2ecf20Sopenharmony_ci	struct dma_fence_cb base;
768c2ecf20Sopenharmony_ci	struct i915_sw_fence *fence;
778c2ecf20Sopenharmony_ci};
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ciint __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
808c2ecf20Sopenharmony_ci				    struct dma_fence *dma,
818c2ecf20Sopenharmony_ci				    struct i915_sw_dma_fence_cb *cb);
828c2ecf20Sopenharmony_ciint i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
838c2ecf20Sopenharmony_ci				  struct dma_fence *dma,
848c2ecf20Sopenharmony_ci				  unsigned long timeout,
858c2ecf20Sopenharmony_ci				  gfp_t gfp);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciint i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
888c2ecf20Sopenharmony_ci				    struct dma_resv *resv,
898c2ecf20Sopenharmony_ci				    const struct dma_fence_ops *exclude,
908c2ecf20Sopenharmony_ci				    bool write,
918c2ecf20Sopenharmony_ci				    unsigned long timeout,
928c2ecf20Sopenharmony_ci				    gfp_t gfp);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cibool i915_sw_fence_await(struct i915_sw_fence *fence);
958c2ecf20Sopenharmony_civoid i915_sw_fence_complete(struct i915_sw_fence *fence);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	return atomic_read(&fence->pending) <= 0;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic inline bool i915_sw_fence_done(const struct i915_sw_fence *fence)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	return atomic_read(&fence->pending) < 0;
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic inline void i915_sw_fence_wait(struct i915_sw_fence *fence)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	wait_event(fence->wait, i915_sw_fence_done(fence));
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic inline void
1138c2ecf20Sopenharmony_cii915_sw_fence_set_error_once(struct i915_sw_fence *fence, int error)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	if (unlikely(error))
1168c2ecf20Sopenharmony_ci		cmpxchg(&fence->error, 0, error);
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci#endif /* _I915_SW_FENCE_H_ */
120