// SPDX-License-Identifier: GPL-2.0-only
/*
 * The interface for waiting on multiple inter-IP fences to complete the signaler submission.
 *
 * Copyright (C) 2023 Google LLC
 */

#include <linux/eventfd.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

#include <gcip/iif/iif-fence.h>
#include <gcip/iif/iif-signaler-submission-watier.h>

static struct iif_signaler_submission_waiter *
iif_signaler_submission_waiter_alloc(unsigned int eventfd, int pending_fences)
{
	struct iif_signaler_submission_waiter *waiter;
	struct eventfd_ctx *ctx;

	waiter = kzalloc(sizeof(*waiter), GFP_KERNEL);
	if (!waiter)
		return ERR_PTR(-ENOMEM);

	ctx = eventfd_ctx_fdget((int)eventfd);
	if (IS_ERR(ctx)) {
		kfree(waiter);
		return ERR_CAST(ctx);
	}

	waiter->ctx = ctx;
	waiter->pending_fences = pending_fences;

	INIT_LIST_HEAD(&waiter->cb_list);
	kref_init(&waiter->kref);
	spin_lock_init(&waiter->lock);

	return waiter;
}

static void iif_all_signaler_submission_waiter_free(struct kref *kref)
{
	struct iif_signaler_submission_waiter *waiter =
		container_of(kref, struct iif_signaler_submission_waiter, kref);

	eventfd_ctx_put(waiter->ctx);
	kfree(waiter);
}

struct iif_signaler_submission_waiter *
iif_all_signaler_submission_waiter_get(struct iif_signaler_submission_waiter *waiter)
{
	kref_get(&waiter->kref);
	return waiter;
}

void iif_all_signaler_submission_waiter_put(struct iif_signaler_submission_waiter *waiter)
{
	kref_put(&waiter->kref, iif_all_signaler_submission_waiter_free);
}

static void all_signaler_submitted(struct iif_fence *fence,
				   struct iif_fence_all_signaler_submitted_cb *fence_cb)
{
	struct iif_signaler_submission_waiter_cb *cb =
		container_of(fence_cb, struct iif_signaler_submission_waiter_cb, fence_cb);
	struct iif_signaler_submission_waiter *waiter = cb->waiter;
	unsigned long flags;

	spin_lock_irqsave(&waiter->lock, flags);

	/*
	 * The `iif_all_signaler_submission_waiter_cancel` function will delete @cb from
	 * @watier->cb_list, decrement the refcount of @waiter and release @cb instead.
	 */
	if (waiter->cancel) {
		spin_unlock_irqrestore(&waiter->lock, flags);
		return;
	}

	list_del(&cb->node);

	/*
	 * - The callback will be executed asynchronously even while `iif_wait_signaler_submission`
	 *   function is still registering callbacks for each fence. In this case, even though
	 *   @waiter->cb_list is empty, we must not trigger the eventfd since not all callbacks are
	 *   registered yet (waiter->pending_fences is non-zero).
	 *
	 * - If waiter->pending_fences is 0, it means that we have finished registering callbacks
	 *   for all fences and the waiter should wait on @waiter->cb_list to be empty.
	 *
	 * - If there is no more fence to register the callback and all fences have finished the
	 *   signaler submission, we can signal the eventfd.
	 *
	 * Note that this callback will be called even when @fence is going to be destroyed before
	 * all signalers have been submitted to clean up the callback data, @cb. We can distinguish
	 * the case by checking whether @fence->all_signaler_submitted_error is zero or not and we
	 * should not notify the eventfd if that is non-zero.
	 */
	if (!waiter->pending_fences && list_empty(&waiter->cb_list) &&
	    !fence->all_signaler_submitted_error)
		eventfd_signal(waiter->ctx, 1);

	spin_unlock_irqrestore(&waiter->lock, flags);

	iif_all_signaler_submission_waiter_put(waiter);
	kfree(cb);
}

static int iif_all_signaler_submission_waiter_wait(struct iif_signaler_submission_waiter *waiter,
						   struct iif_fence *fence,
						   int *remaining_signalers)
{
	struct iif_signaler_submission_waiter_cb *cb;
	int ret;

	cb = kzalloc(sizeof(*cb), GFP_KERNEL);
	if (!cb)
		return -ENOMEM;

	cb->waiter = iif_all_signaler_submission_waiter_get(waiter);
	/*
	 * Don't call `iif_fence_get` to prevent @fence from being not released forever if the
	 * runtime never submits signalers somehow.
	 */
	cb->fence = fence;

	spin_lock(&waiter->lock);
	list_add_tail(&cb->node, &waiter->cb_list);
	spin_unlock(&waiter->lock);

	ret = iif_fence_add_all_signaler_submitted_callback(fence, &cb->fence_cb,
							    all_signaler_submitted);

	spin_lock(&waiter->lock);

	if (ret && ret != -EPERM)
		goto out_list_del;

	/*
	 * @fence has been successfully registered the callback or already finished the
	 * signaler submission.
	 */
	waiter->pending_fences--;

	/* (ret = -EPERM) Already all signalers are submitted and the callback is not registered. */
	if (ret) {
		*remaining_signalers = 0;
		ret = 0;
		goto out_list_del;
	}

	/* (ret = 0) The callback is registered and there are remaining signalers. */
	*remaining_signalers = cb->fence_cb.remaining_signalers;

	spin_unlock(&waiter->lock);

	return 0;

out_list_del:
	list_del(&cb->node);
	spin_unlock(&waiter->lock);

	iif_all_signaler_submission_waiter_put(waiter);
	kfree(cb);

	return ret;
}

static void iif_all_signaler_submission_waiter_cancel(struct iif_signaler_submission_waiter *waiter)
{
	struct iif_signaler_submission_waiter_cb *cur, *tmp;

	spin_lock(&waiter->lock);
	waiter->cancel = true;
	spin_unlock(&waiter->lock);

	/* From now on, @waiter->cb_list won't be changed. */

	list_for_each_entry_safe(cur, tmp, &waiter->cb_list, node) {
		iif_fence_remove_all_signaler_submitted_callback(cur->fence, &cur->fence_cb);
		list_del(&cur->node);
		iif_all_signaler_submission_waiter_put(waiter);
		kfree(cur);
	}
}

int iif_wait_signaler_submission(struct iif_fence **fences, int num_fences, unsigned int eventfd,
				 int *remaining_signalers)
{
	struct iif_signaler_submission_waiter *waiter;
	int i, ret = 0;

	if (eventfd == IIF_NO_REGISTER_EVENTFD) {
		for (i = 0; i < num_fences; i++)
			remaining_signalers[i] = iif_fence_unsubmitted_signalers(fences[i]);
		return 0;
	}

	waiter = iif_signaler_submission_waiter_alloc(eventfd, num_fences);
	if (IS_ERR(waiter))
		return PTR_ERR(waiter);

	for (i = 0; i < num_fences; i++) {
		ret = iif_all_signaler_submission_waiter_wait(waiter, fences[i],
							      &remaining_signalers[i]);
		if (ret) {
			iif_all_signaler_submission_waiter_cancel(waiter);
			break;
		}
	}

	iif_all_signaler_submission_waiter_put(waiter);

	return ret;
}
