blob: 7e24bb3376808b7667a61f7a77fd00e9b42ac6fb [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Abstracted interface for fences.
*
* Copyright (C) 2023 Google LLC
*/
#ifndef __GXP_FENCE_H__
#define __GXP_FENCE_H__
#include <linux/kref.h>
#include <gcip/iif/iif-fence.h>
#include "gxp-internal.h"
#include "gxp.h"
struct gxp_fence;
struct gxp_fence_ops;
struct gxp_fence_all_signaler_submitted_cb;
/* The callback which will be called when all signalers have been submitted to @fence. */
typedef void (*gxp_fence_all_signaler_submitted_cb_t)(
struct gxp_fence *fence, struct gxp_fence_all_signaler_submitted_cb *cb);
enum gxp_fence_type {
GXP_INTER_IP_FENCE,
GXP_IN_KERNEL_FENCE,
};
/* Abstracted fence structure. */
struct gxp_fence {
union {
struct iif_fence *iif;
struct dma_fence *ikf;
} fence;
/* The type of fence. */
enum gxp_fence_type type;
/* Reference count. */
struct kref kref;
};
/* Abstracted all signaler submitted callback structure. */
struct gxp_fence_all_signaler_submitted_cb {
/* IIF callback instance. */
struct iif_fence_all_signaler_submitted_cb iif_cb;
/* The actual callback function. */
gxp_fence_all_signaler_submitted_cb_t func;
/* Fence object. */
struct gxp_fence *fence;
};
/*
* Creates an IIF fence and bind a file descriptor to it.
*
* Returns the fd of the fence on success. Otherwise, returns a negative errno.
*/
int gxp_fence_create_iif(struct gxp_dev *gxp, enum gxp_iif_ip_type signaler_ip,
unsigned int total_signalers);
/*
* Gets a fence from @fd and increments its reference count.
*
* Returns the fence pointer on success. Otherwise, returns an error pointer.
*/
struct gxp_fence *gxp_fence_fdget(int fd);
/* Increments the reference count of @fence. */
struct gxp_fence *gxp_fence_get(struct gxp_fence *fence);
/* Puts the fence and decrements its reference count. */
void gxp_fence_put(struct gxp_fence *fence);
/*
* Submits a signaler.
*
* This function is only meaningful when the fence type is GXP_INTER_IP_FENCE.
*
* Returns 0 if the submission succeeds. Otherwise, returns a negative errno.
*/
int gxp_fence_submit_signaler(struct gxp_fence *fence);
/*
* Submits a waiter.
* Note that the waiter submission will not be done when not all signalers have been submitted.
*
* This function is only meaningful when the fence type is GXP_INTER_IP_FENCE.
*
* Returns the number of remaining signalers to be submitted. (i.e., the submission actually
* has been succeeded when the function returns 0.) Otherwise, returns a negative errno if it fails
* with other reasons.
*/
int gxp_fence_submit_waiter(struct gxp_fence *fence);
/*
* Signals @fence. If all signalers have signaled the fence, it will notify polling FDs.
*
* If @fence is going to signaled with an error, one can pass @errno to let @fence notice it.
*/
void gxp_fence_signal(struct gxp_fence *fence, int errno);
/*
* Notifies @fence that a command which waited the fence has finished their work.
*
* This function is only meaningful when the fence type is GXP_INTER_IP_FENCE.
*/
void gxp_fence_waited(struct gxp_fence *fence);
/*
* Registers a callback which will be called when all signalers are submitted for @fence and
* returns the number of remaining signalers to be submitted to @cb->remaining_signalers. Once the
* callback is called, it will be automatically unregistered from @fence.
*
* This function is only meaningful when the fence type is GXP_INTER_IP_FENCE.
*
* Returns 0 if succeeded. If all signalers are already submitted, returns -EPERM.
*/
int gxp_fence_add_all_signaler_submitted_cb(struct gxp_fence *fence,
struct gxp_fence_all_signaler_submitted_cb *cb,
gxp_fence_all_signaler_submitted_cb_t func);
/*
* Unregisters the callback which is registered by the callback above. Calling this function with
* @cb which has never been added will cause unexpected action.
*
* This function is only meaningful when the fence type is GXP_INTER_IP_FENCE.
*
* Returns true if the callback is removed before its being called.
*/
bool gxp_fence_remove_all_signaler_submitted_cb(struct gxp_fence *fence,
struct gxp_fence_all_signaler_submitted_cb *cb);
/* Returns the ID of @fence if @fence is IIF. Otherwise, returns -EINVAL. */
int gxp_fence_get_iif_id(struct gxp_fence *fence);
/*
* Waits on @fences to complete the signaler submission. If at least one of @fences have remaining
* signalers to be submitted, it will register @eventfd and will trigger it once all fences have
* finishes the submission. Also, the number of remaining signalers of each fence will be returned
* to @remaining_signalers in the same order with @fences.
*
* If @eventfd is `GXP_FENCE_REMAINING_SIGNALERS_NO_REGISTER_EVENTFD`, this function won't wait on
* @fences to finish signaler submission and will simply return the number of remaining signalers of
* each fence.
*
* This function is only meaningful when fences are IIF.
*
* Returns 0 on success. Otherwise, returns a negative errno.
*/
int gxp_fence_wait_signaler_submission(struct gxp_fence **fences, int num_fences,
unsigned int eventfd, int *remaining_signalers);
/*
* Returns the signal completion status of @fence.
*
* Returns 0 if the fence has not yet been signaled, 1 if the fence has been signaled without an
* error condition, or a negative error code if the fence has been completed in err.
*/
int gxp_fence_get_status(struct gxp_fence *fence);
#endif /* __GXP_FENCE_H__ */