/*
 * 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 "c2.h"
#include <rdma/iw_cm.h>
#include "c2_vq.h"

static void handle_mq(struct c2_dev *c2dev, u32 index);
static void handle_vq(struct c2_dev *c2dev, u32 mq_index);

/*
 * Handle RNIC interrupts
 */
void c2_rnic_interrupt(struct c2_dev *c2dev)
{
	unsigned int mq_index;

	while (c2dev->hints_read != be16_to_cpu(*c2dev->hint_count)) {
		mq_index = readl(c2dev->regs + PCI_BAR0_HOST_HINT);
		if (mq_index & 0x80000000) {
			break;
		}

		c2dev->hints_read++;
		handle_mq(c2dev, mq_index);
	}

}

/*
 * Top level MQ handler
 */
static void handle_mq(struct c2_dev *c2dev, u32 mq_index)
{
	if (c2dev->qptr_array[mq_index] == NULL) {
		pr_debug(KERN_INFO "handle_mq: stray activity for mq_index=%d\n",
			mq_index);
		return;
	}

	switch (mq_index) {
	case (0):
		/*
		 * An index of 0 in the activity queue
		 * indicates the req vq now has messages
		 * available...
		 *
		 * Wake up any waiters waiting on req VQ
		 * message availability.
		 */
		wake_up(&c2dev->req_vq_wo);
		break;
	case (1):
		handle_vq(c2dev, mq_index);
		break;
	case (2):
		/* We have to purge the VQ in case there are pending
		 * accept reply requests that would result in the
		 * generation of an ESTABLISHED event. If we don't
		 * generate these first, a CLOSE event could end up
		 * being delivered before the ESTABLISHED event.
		 */
		handle_vq(c2dev, 1);

		c2_ae_event(c2dev, mq_index);
		break;
	default:
		/* There is no event synchronization between CQ events
		 * and AE or CM events. In fact, CQE could be
		 * delivered for all of the I/O up to and including the
		 * FLUSH for a peer disconenct prior to the ESTABLISHED
		 * event being delivered to the app. The reason for this
		 * is that CM events are delivered on a thread, while AE
		 * and CM events are delivered on interrupt context.
		 */
		c2_cq_event(c2dev, mq_index);
		break;
	}

	return;
}

/*
 * Handles verbs WR replies.
 */
static void handle_vq(struct c2_dev *c2dev, u32 mq_index)
{
	void *adapter_msg, *reply_msg;
	struct c2wr_hdr *host_msg;
	struct c2wr_hdr tmp;
	struct c2_mq *reply_vq;
	struct c2_vq_req *req;
	struct iw_cm_event cm_event;
	int err;

	reply_vq = (struct c2_mq *) c2dev->qptr_array[mq_index];

	/*
	 * get next msg from mq_index into adapter_msg.
	 * don't free it yet.
	 */
	adapter_msg = c2_mq_consume(reply_vq);
	if (adapter_msg == NULL) {
		return;
	}

	host_msg = vq_repbuf_alloc(c2dev);

	/*
	 * If we can't get a host buffer, then we'll still
	 * wakeup the waiter, we just won't give him the msg.
	 * It is assumed the waiter will deal with this...
	 */
	if (!host_msg) {
		pr_debug("handle_vq: no repbufs!\n");

		/*
		 * just copy the WR header into a local variable.
		 * this allows us to still demux on the context
		 */
		host_msg = &tmp;
		memcpy(host_msg, adapter_msg, sizeof(tmp));
		reply_msg = NULL;
	} else {
		memcpy(host_msg, adapter_msg, reply_vq->msg_size);
		reply_msg = host_msg;
	}

	/*
	 * consume the msg from the MQ
	 */
	c2_mq_free(reply_vq);

	/*
	 * wakeup the waiter.
	 */
	req = (struct c2_vq_req *) (unsigned long) host_msg->context;
	if (req == NULL) {
		/*
		 * We should never get here, as the adapter should
		 * never send us a reply that we're not expecting.
		 */
		vq_repbuf_free(c2dev, host_msg);
		pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n");
		return;
	}

	err = c2_errno(reply_msg);
	if (!err) switch (req->event) {
	case IW_CM_EVENT_ESTABLISHED:
		c2_set_qp_state(req->qp,
				C2_QP_STATE_RTS);
	case IW_CM_EVENT_CLOSE:

		/*
		 * Move the QP to RTS if this is
		 * the established event
		 */
		cm_event.event = req->event;
		cm_event.status = 0;
		cm_event.local_addr = req->cm_id->local_addr;
		cm_event.remote_addr = req->cm_id->remote_addr;
		cm_event.private_data = NULL;
		cm_event.private_data_len = 0;
		req->cm_id->event_handler(req->cm_id, &cm_event);
		break;
	default:
		break;
	}

	req->reply_msg = (u64) (unsigned long) (reply_msg);
	atomic_set(&req->reply_ready, 1);
	wake_up(&req->wait_object);

	/*
	 * If the request was cancelled, then this put will
	 * free the vq_req memory...and reply_msg!!!
	 */
	vq_req_put(c2dev, req);
}
