// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * PowerNV OPAL asynchronous completion interfaces
 *
 * Copyright 2013-2017 IBM Corp.
 */

#undef DEBUG

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/gfp.h>
#include <linux/of.h>
#include <asm/machdep.h>
#include <asm/opal.h>

enum opal_async_token_state {
	ASYNC_TOKEN_UNALLOCATED = 0,
	ASYNC_TOKEN_ALLOCATED,
	ASYNC_TOKEN_DISPATCHED,
	ASYNC_TOKEN_ABANDONED,
	ASYNC_TOKEN_COMPLETED
};

struct opal_async_token {
	enum opal_async_token_state state;
	struct opal_msg response;
};

static DECLARE_WAIT_QUEUE_HEAD(opal_async_wait);
static DEFINE_SPINLOCK(opal_async_comp_lock);
static struct semaphore opal_async_sem;
static unsigned int opal_max_async_tokens;
static struct opal_async_token *opal_async_tokens;

static int __opal_async_get_token(void)
{
	unsigned long flags;
	int i, token = -EBUSY;

	spin_lock_irqsave(&opal_async_comp_lock, flags);

	for (i = 0; i < opal_max_async_tokens; i++) {
		if (opal_async_tokens[i].state == ASYNC_TOKEN_UNALLOCATED) {
			opal_async_tokens[i].state = ASYNC_TOKEN_ALLOCATED;
			token = i;
			break;
		}
	}

	spin_unlock_irqrestore(&opal_async_comp_lock, flags);
	return token;
}

/*
 * Note: If the returned token is used in an opal call and opal returns
 * OPAL_ASYNC_COMPLETION you MUST call one of opal_async_wait_response() or
 * opal_async_wait_response_interruptible() at least once before calling another
 * opal_async_* function
 */
int opal_async_get_token_interruptible(void)
{
	int token;

	/* Wait until a token is available */
	if (down_interruptible(&opal_async_sem))
		return -ERESTARTSYS;

	token = __opal_async_get_token();
	if (token < 0)
		up(&opal_async_sem);

	return token;
}
EXPORT_SYMBOL_GPL(opal_async_get_token_interruptible);

static int __opal_async_release_token(int token)
{
	unsigned long flags;
	int rc;

	if (token < 0 || token >= opal_max_async_tokens) {
		pr_err("%s: Passed token is out of range, token %d\n",
				__func__, token);
		return -EINVAL;
	}

	spin_lock_irqsave(&opal_async_comp_lock, flags);
	switch (opal_async_tokens[token].state) {
	case ASYNC_TOKEN_COMPLETED:
	case ASYNC_TOKEN_ALLOCATED:
		opal_async_tokens[token].state = ASYNC_TOKEN_UNALLOCATED;
		rc = 0;
		break;
	/*
	 * DISPATCHED and ABANDONED tokens must wait for OPAL to respond.
	 * Mark a DISPATCHED token as ABANDONED so that the response handling
	 * code knows no one cares and that it can free it then.
	 */
	case ASYNC_TOKEN_DISPATCHED:
		opal_async_tokens[token].state = ASYNC_TOKEN_ABANDONED;
		fallthrough;
	default:
		rc = 1;
	}
	spin_unlock_irqrestore(&opal_async_comp_lock, flags);

	return rc;
}

int opal_async_release_token(int token)
{
	int ret;

	ret = __opal_async_release_token(token);
	if (!ret)
		up(&opal_async_sem);

	return ret;
}
EXPORT_SYMBOL_GPL(opal_async_release_token);

int opal_async_wait_response(uint64_t token, struct opal_msg *msg)
{
	if (token >= opal_max_async_tokens) {
		pr_err("%s: Invalid token passed\n", __func__);
		return -EINVAL;
	}

	if (!msg) {
		pr_err("%s: Invalid message pointer passed\n", __func__);
		return -EINVAL;
	}

	/*
	 * There is no need to mark the token as dispatched, wait_event()
	 * will block until the token completes.
	 *
	 * Wakeup the poller before we wait for events to speed things
	 * up on platforms or simulators where the interrupts aren't
	 * functional.
	 */
	opal_wake_poller();
	wait_event(opal_async_wait, opal_async_tokens[token].state
			== ASYNC_TOKEN_COMPLETED);
	memcpy(msg, &opal_async_tokens[token].response, sizeof(*msg));

	return 0;
}
EXPORT_SYMBOL_GPL(opal_async_wait_response);

int opal_async_wait_response_interruptible(uint64_t token, struct opal_msg *msg)
{
	unsigned long flags;
	int ret;

	if (token >= opal_max_async_tokens) {
		pr_err("%s: Invalid token passed\n", __func__);
		return -EINVAL;
	}

	if (!msg) {
		pr_err("%s: Invalid message pointer passed\n", __func__);
		return -EINVAL;
	}

	/*
	 * The first time this gets called we mark the token as DISPATCHED
	 * so that if wait_event_interruptible() returns not zero and the
	 * caller frees the token, we know not to actually free the token
	 * until the response comes.
	 *
	 * Only change if the token is ALLOCATED - it may have been
	 * completed even before the caller gets around to calling this
	 * the first time.
	 *
	 * There is also a dirty great comment at the token allocation
	 * function that if the opal call returns OPAL_ASYNC_COMPLETION to
	 * the caller then the caller *must* call this or the not
	 * interruptible version before doing anything else with the
	 * token.
	 */
	if (opal_async_tokens[token].state == ASYNC_TOKEN_ALLOCATED) {
		spin_lock_irqsave(&opal_async_comp_lock, flags);
		if (opal_async_tokens[token].state == ASYNC_TOKEN_ALLOCATED)
			opal_async_tokens[token].state = ASYNC_TOKEN_DISPATCHED;
		spin_unlock_irqrestore(&opal_async_comp_lock, flags);
	}

	/*
	 * Wakeup the poller before we wait for events to speed things
	 * up on platforms or simulators where the interrupts aren't
	 * functional.
	 */
	opal_wake_poller();
	ret = wait_event_interruptible(opal_async_wait,
			opal_async_tokens[token].state ==
			ASYNC_TOKEN_COMPLETED);
	if (!ret)
		memcpy(msg, &opal_async_tokens[token].response, sizeof(*msg));

	return ret;
}
EXPORT_SYMBOL_GPL(opal_async_wait_response_interruptible);

/* Called from interrupt context */
static int opal_async_comp_event(struct notifier_block *nb,
		unsigned long msg_type, void *msg)
{
	struct opal_msg *comp_msg = msg;
	enum opal_async_token_state state;
	unsigned long flags;
	uint64_t token;

	if (msg_type != OPAL_MSG_ASYNC_COMP)
		return 0;

	token = be64_to_cpu(comp_msg->params[0]);
	spin_lock_irqsave(&opal_async_comp_lock, flags);
	state = opal_async_tokens[token].state;
	opal_async_tokens[token].state = ASYNC_TOKEN_COMPLETED;
	spin_unlock_irqrestore(&opal_async_comp_lock, flags);

	if (state == ASYNC_TOKEN_ABANDONED) {
		/* Free the token, no one else will */
		opal_async_release_token(token);
		return 0;
	}
	memcpy(&opal_async_tokens[token].response, comp_msg, sizeof(*comp_msg));
	wake_up(&opal_async_wait);

	return 0;
}

static struct notifier_block opal_async_comp_nb = {
		.notifier_call	= opal_async_comp_event,
		.next		= NULL,
		.priority	= 0,
};

int __init opal_async_comp_init(void)
{
	struct device_node *opal_node;
	const __be32 *async;
	int err;

	opal_node = of_find_node_by_path("/ibm,opal");
	if (!opal_node) {
		pr_err("%s: Opal node not found\n", __func__);
		err = -ENOENT;
		goto out;
	}

	async = of_get_property(opal_node, "opal-msg-async-num", NULL);
	if (!async) {
		pr_err("%s: %pOF has no opal-msg-async-num\n",
				__func__, opal_node);
		err = -ENOENT;
		goto out_opal_node;
	}

	opal_max_async_tokens = be32_to_cpup(async);
	opal_async_tokens = kcalloc(opal_max_async_tokens,
			sizeof(*opal_async_tokens), GFP_KERNEL);
	if (!opal_async_tokens) {
		err = -ENOMEM;
		goto out_opal_node;
	}

	err = opal_message_notifier_register(OPAL_MSG_ASYNC_COMP,
			&opal_async_comp_nb);
	if (err) {
		pr_err("%s: Can't register OPAL event notifier (%d)\n",
				__func__, err);
		kfree(opal_async_tokens);
		goto out_opal_node;
	}

	sema_init(&opal_async_sem, opal_max_async_tokens);

out_opal_node:
	of_node_put(opal_node);
out:
	return err;
}
