/*
 * PowerNV OPAL asynchronous completion interfaces
 *
 * Copyright 2013 IBM Corp.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#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/opal.h>

#define N_ASYNC_COMPLETIONS	64

static DECLARE_BITMAP(opal_async_complete_map, N_ASYNC_COMPLETIONS) = {~0UL};
static DECLARE_BITMAP(opal_async_token_map, N_ASYNC_COMPLETIONS);
static DECLARE_WAIT_QUEUE_HEAD(opal_async_wait);
static DEFINE_SPINLOCK(opal_async_comp_lock);
static struct semaphore opal_async_sem;
static struct opal_msg *opal_async_responses;
static unsigned int opal_max_async_tokens;

int __opal_async_get_token(void)
{
	unsigned long flags;
	int token;

	spin_lock_irqsave(&opal_async_comp_lock, flags);
	token = find_first_bit(opal_async_complete_map, opal_max_async_tokens);
	if (token >= opal_max_async_tokens) {
		token = -EBUSY;
		goto out;
	}

	if (__test_and_set_bit(token, opal_async_token_map)) {
		token = -EBUSY;
		goto out;
	}

	__clear_bit(token, opal_async_complete_map);

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

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;
}

int __opal_async_release_token(int token)
{
	unsigned long flags;

	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);
	__set_bit(token, opal_async_complete_map);
	__clear_bit(token, opal_async_token_map);
	spin_unlock_irqrestore(&opal_async_comp_lock, flags);

	return 0;
}

int opal_async_release_token(int token)
{
	int ret;

	ret = __opal_async_release_token(token);
	if (ret)
		return ret;

	up(&opal_async_sem);

	return 0;
}

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;
	}

	wait_event(opal_async_wait, test_bit(token, opal_async_complete_map));
	memcpy(msg, &opal_async_responses[token], sizeof(*msg));

	return 0;
}

static int opal_async_comp_event(struct notifier_block *nb,
		unsigned long msg_type, void *msg)
{
	struct opal_msg *comp_msg = msg;
	unsigned long flags;
	uint64_t token;

	if (msg_type != OPAL_MSG_ASYNC_COMP)
		return 0;

	token = be64_to_cpu(comp_msg->params[0]);
	memcpy(&opal_async_responses[token], comp_msg, sizeof(*comp_msg));
	spin_lock_irqsave(&opal_async_comp_lock, flags);
	__set_bit(token, opal_async_complete_map);
	spin_unlock_irqrestore(&opal_async_comp_lock, flags);

	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,
};

static 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: %s has no opal-msg-async-num\n",
				__func__, opal_node->full_name);
		err = -ENOENT;
		goto out_opal_node;
	}

	opal_max_async_tokens = be32_to_cpup(async);
	if (opal_max_async_tokens > N_ASYNC_COMPLETIONS)
		opal_max_async_tokens = N_ASYNC_COMPLETIONS;

	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);
		goto out_opal_node;
	}

	opal_async_responses = kzalloc(
			sizeof(*opal_async_responses) * opal_max_async_tokens,
			GFP_KERNEL);
	if (!opal_async_responses) {
		pr_err("%s: Out of memory, failed to do asynchronous "
				"completion init\n", __func__);
		err = -ENOMEM;
		goto out_opal_node;
	}

	/* Initialize to 1 less than the maximum tokens available, as we may
	 * require to pop one during emergency through synchronous call to
	 * __opal_async_get_token()
	 */
	sema_init(&opal_async_sem, opal_max_async_tokens - 1);

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