/*
 * Copyright (c) 2005 Ammasso, Inc. All rights reserved.
 * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the
 * OpenIB.org BSD license below:
 *
 *     Redistribution and use in source and binary forms, with or
 *     without modification, are permitted provided that the following
 *     conditions are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the following
 *        disclaimer in the documentation and/or other materials
 *        provided with the distribution.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include <linux/slab.h>
#include <linux/spinlock.h>

#include "c2_vq.h"
#include "c2_provider.h"

/*
 * Verbs Request Objects:
 *
 * VQ Request Objects are allocated by the kernel verbs handlers.
 * They contain a wait object, a refcnt, an atomic bool indicating that the
 * adapter has replied, and a copy of the verb reply work request.
 * A pointer to the VQ Request Object is passed down in the context
 * field of the work request message, and reflected back by the adapter
 * in the verbs reply message.  The function handle_vq() in the interrupt
 * path will use this pointer to:
 * 	1) append a copy of the verbs reply message
 * 	2) mark that the reply is ready
 * 	3) wake up the kernel verbs handler blocked awaiting the reply.
 *
 *
 * The kernel verbs handlers do a "get" to put a 2nd reference on the
 * VQ Request object.  If the kernel verbs handler exits before the adapter
 * can respond, this extra reference will keep the VQ Request object around
 * until the adapter's reply can be processed.  The reason we need this is
 * because a pointer to this object is stuffed into the context field of
 * the verbs work request message, and reflected back in the reply message.
 * It is used in the interrupt handler (handle_vq()) to wake up the appropriate
 * kernel verb handler that is blocked awaiting the verb reply.
 * So handle_vq() will do a "put" on the object when it's done accessing it.
 * NOTE:  If we guarantee that the kernel verb handler will never bail before
 *        getting the reply, then we don't need these refcnts.
 *
 *
 * VQ Request objects are freed by the kernel verbs handlers only
 * after the verb has been processed, or when the adapter fails and
 * does not reply.
 *
 *
 * Verbs Reply Buffers:
 *
 * VQ Reply bufs are local host memory copies of a
 * outstanding Verb Request reply
 * message.  The are always allocated by the kernel verbs handlers, and _may_ be
 * freed by either the kernel verbs handler -or- the interrupt handler.  The
 * kernel verbs handler _must_ free the repbuf, then free the vq request object
 * in that order.
 */

int vq_init(struct c2_dev *c2dev)
{
	sprintf(c2dev->vq_cache_name, "c2-vq:dev%c",
		(char) ('0' + c2dev->devnum));
	c2dev->host_msg_cache =
	    kmem_cache_create(c2dev->vq_cache_name, c2dev->rep_vq.msg_size, 0,
			      SLAB_HWCACHE_ALIGN, NULL);
	if (c2dev->host_msg_cache == NULL) {
		return -ENOMEM;
	}
	return 0;
}

void vq_term(struct c2_dev *c2dev)
{
	kmem_cache_destroy(c2dev->host_msg_cache);
}

/* vq_req_alloc - allocate a VQ Request Object and initialize it.
 * The refcnt is set to 1.
 */
struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev)
{
	struct c2_vq_req *r;

	r = kmalloc(sizeof(struct c2_vq_req), GFP_KERNEL);
	if (r) {
		init_waitqueue_head(&r->wait_object);
		r->reply_msg = (u64) NULL;
		r->event = 0;
		r->cm_id = NULL;
		r->qp = NULL;
		atomic_set(&r->refcnt, 1);
		atomic_set(&r->reply_ready, 0);
	}
	return r;
}


/* vq_req_free - free the VQ Request Object.  It is assumed the verbs handler
 * has already free the VQ Reply Buffer if it existed.
 */
void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *r)
{
	r->reply_msg = (u64) NULL;
	if (atomic_dec_and_test(&r->refcnt)) {
		kfree(r);
	}
}

/* vq_req_get - reference a VQ Request Object.  Done
 * only in the kernel verbs handlers.
 */
void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *r)
{
	atomic_inc(&r->refcnt);
}


/* vq_req_put - dereference and potentially free a VQ Request Object.
 *
 * This is only called by handle_vq() on the
 * interrupt when it is done processing
 * a verb reply message.  If the associated
 * kernel verbs handler has already bailed,
 * then this put will actually free the VQ
 * Request object _and_ the VQ Reply Buffer
 * if it exists.
 */
void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r)
{
	if (atomic_dec_and_test(&r->refcnt)) {
		if (r->reply_msg != (u64) NULL)
			vq_repbuf_free(c2dev,
				       (void *) (unsigned long) r->reply_msg);
		kfree(r);
	}
}


/*
 * vq_repbuf_alloc - allocate a VQ Reply Buffer.
 */
void *vq_repbuf_alloc(struct c2_dev *c2dev)
{
	return kmem_cache_alloc(c2dev->host_msg_cache, GFP_ATOMIC);
}

/*
 * vq_send_wr - post a verbs request message to the Verbs Request Queue.
 * If a message is not available in the MQ, then block until one is available.
 * NOTE: handle_mq() on the interrupt context will wake up threads blocked here.
 * When the adapter drains the Verbs Request Queue,
 * it inserts MQ index 0 in to the
 * adapter->host activity fifo and interrupts the host.
 */
int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr)
{
	void *msg;
	wait_queue_t __wait;

	/*
	 * grab adapter vq lock
	 */
	spin_lock(&c2dev->vqlock);

	/*
	 * allocate msg
	 */
	msg = c2_mq_alloc(&c2dev->req_vq);

	/*
	 * If we cannot get a msg, then we'll wait
	 * When a messages are available, the int handler will wake_up()
	 * any waiters.
	 */
	while (msg == NULL) {
		pr_debug("%s:%d no available msg in VQ, waiting...\n",
		       __func__, __LINE__);
		init_waitqueue_entry(&__wait, current);
		add_wait_queue(&c2dev->req_vq_wo, &__wait);
		spin_unlock(&c2dev->vqlock);
		for (;;) {
			set_current_state(TASK_INTERRUPTIBLE);
			if (!c2_mq_full(&c2dev->req_vq)) {
				break;
			}
			if (!signal_pending(current)) {
				schedule_timeout(1 * HZ);	/* 1 second... */
				continue;
			}
			set_current_state(TASK_RUNNING);
			remove_wait_queue(&c2dev->req_vq_wo, &__wait);
			return -EINTR;
		}
		set_current_state(TASK_RUNNING);
		remove_wait_queue(&c2dev->req_vq_wo, &__wait);
		spin_lock(&c2dev->vqlock);
		msg = c2_mq_alloc(&c2dev->req_vq);
	}

	/*
	 * copy wr into adapter msg
	 */
	memcpy(msg, wr, c2dev->req_vq.msg_size);

	/*
	 * post msg
	 */
	c2_mq_produce(&c2dev->req_vq);

	/*
	 * release adapter vq lock
	 */
	spin_unlock(&c2dev->vqlock);
	return 0;
}


/*
 * vq_wait_for_reply - block until the adapter posts a Verb Reply Message.
 */
int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req)
{
	if (!wait_event_timeout(req->wait_object,
				atomic_read(&req->reply_ready),
				60*HZ))
		return -ETIMEDOUT;

	return 0;
}

/*
 * vq_repbuf_free - Free a Verbs Reply Buffer.
 */
void vq_repbuf_free(struct c2_dev *c2dev, void *reply)
{
	kmem_cache_free(c2dev->host_msg_cache, reply);
}
