blob: 5c0417a912a6d4d5e8d0ea0e5c0d5cd54f3745e4 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Abstracted interface for fences.
*
* Copyright (C) 2023 Google LLC
*/
#ifndef __GCIP_FENCE_H__
#define __GCIP_FENCE_H__
#include <linux/dma-fence.h>
#include <linux/kref.h>
#include <gcip/iif/iif-fence.h>
#include <gcip/iif/iif-manager.h>
#include <gcip/iif/iif.h>
#define GCIP_FENCE_REMAINING_SIGNALERS_NO_REGISTER_EVENTFD (~0u)
struct gcip_fence;
struct gcip_fence_ops;
struct gcip_fence_all_signaler_submitted_cb;
/* The callback which will be called when all signalers have been submitted to @fence. */
typedef void (*gcip_fence_all_signaler_submitted_cb_t)(
struct gcip_fence *fence, struct gcip_fence_all_signaler_submitted_cb *cb);
enum gcip_fence_type {
GCIP_INTER_IP_FENCE,
GCIP_IN_KERNEL_FENCE,
};
/* Abstracted fence structure. */
struct gcip_fence {
union {
struct iif_fence *iif;
struct dma_fence *ikf;
} fence;
/* The type of fence. */
enum gcip_fence_type type;
/* Reference count. */
struct kref kref;
};
/* Abstracted all signaler submitted callback structure. */
struct gcip_fence_all_signaler_submitted_cb {
/* IIF callback instance. */
struct iif_fence_all_signaler_submitted_cb iif_cb;
/* The actual callback function. */
gcip_fence_all_signaler_submitted_cb_t func;
/* Fence object. */
struct gcip_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 gcip_fence_create_iif(struct iif_manager *mgr, enum 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 gcip_fence *gcip_fence_fdget(int fd);
/* Increments the reference count of @fence. */
struct gcip_fence *gcip_fence_get(struct gcip_fence *fence);
/* Puts the fence and decrements its reference count. */
void gcip_fence_put(struct gcip_fence *fence);
/*
* Submits a signaler.
*
* This function is only meaningful when the fence type is GCIP_INTER_IP_FENCE and can be called in
* the IRQ context.
*
* Returns 0 if the submission succeeds. Otherwise, returns a negative errno.
*/
int gcip_fence_submit_signaler(struct gcip_fence *fence);
/*
* Its functionality is the same with the `gcip_fence_submit_signaler` function, but the caller
* is holding the submitted_signalers lock. (See `gcip_fence_submitted_signalers_lock`)
*/
int gcip_fence_submit_signaler_locked(struct gcip_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 GCIP_INTER_IP_FENCE and can be called in
* the IRQ context.
*
* 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 gcip_fence_submit_waiter(struct gcip_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 gcip_fence_signal(struct gcip_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 GCIP_INTER_IP_FENCE.
*/
void gcip_fence_waited(struct gcip_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 GCIP_INTER_IP_FENCE.
*
* Returns 0 if succeeded. If all signalers are already submitted, returns -EPERM.
*/
int gcip_fence_add_all_signaler_submitted_cb(struct gcip_fence *fence,
struct gcip_fence_all_signaler_submitted_cb *cb,
gcip_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 GCIP_INTER_IP_FENCE.
*
* Returns true if the callback is removed before its being called.
*/
bool gcip_fence_remove_all_signaler_submitted_cb(struct gcip_fence *fence,
struct gcip_fence_all_signaler_submitted_cb *cb);
/* Returns the ID of @fence if @fence is IIF. Otherwise, returns -EINVAL. */
int gcip_fence_get_iif_id(struct gcip_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 `GCIP_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 gcip_fence_wait_signaler_submission(struct gcip_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 gcip_fence_get_status(struct gcip_fence *fence);
/*
* Returns true if a waiter or a signaler is submittable to @fence.
*
* These functions are only meaningful when the fence type is GCIP_INTER_IP_FENCE. For other type of
* fences, they will always return true.
*
* The caller must hold the submitted_signalers lock. (See `gcip_fence_submitted_signalers_lock`)
*/
bool gcip_fence_is_waiter_submittable_locked(struct gcip_fence *fence);
bool gcip_fence_is_signaler_submittable_locked(struct gcip_fence *fence);
/*
* Holds/releases the lock protecting the number of submitted signalers of @fence.
*
* These functions are only meaningful when the fence type is GCIP_INTER_IP_FENCE.
*/
void gcip_fence_submitted_signalers_lock(struct gcip_fence *fence);
void gcip_fence_submitted_signalers_unlock(struct gcip_fence *fence);
#endif /* __GCIP_FENCE_H__ */