/*
 *  IBM eServer eHCA Infiniband device driver for Linux on POWER
 *
 *  SQP functions
 *
 *  Authors: Khadija Souissi <souissi@de.ibm.com>
 *           Heiko J Schick <schickhj@de.ibm.com>
 *
 *  Copyright (c) 2005 IBM Corporation
 *
 *  All rights reserved.
 *
 *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
 *  BSD.
 *
 * OpenIB BSD License
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <rdma/ib_mad.h>

#include "ehca_classes.h"
#include "ehca_tools.h"
#include "ehca_iverbs.h"
#include "hcp_if.h"

#define IB_MAD_STATUS_REDIRECT		__constant_htons(0x0002)
#define IB_MAD_STATUS_UNSUP_VERSION	__constant_htons(0x0004)
#define IB_MAD_STATUS_UNSUP_METHOD	__constant_htons(0x0008)

#define IB_PMA_CLASS_PORT_INFO		__constant_htons(0x0001)

/**
 * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue
 * pair is created successfully, the corresponding port gets active.
 *
 * Define Special Queue pair 0 (SMI QP) is still not supported.
 *
 * @qp_init_attr: Queue pair init attributes with port and queue pair type
 */

u64 ehca_define_sqp(struct ehca_shca *shca,
		    struct ehca_qp *ehca_qp,
		    struct ib_qp_init_attr *qp_init_attr)
{
	u32 pma_qp_nr, bma_qp_nr;
	u64 ret;
	u8 port = qp_init_attr->port_num;
	int counter;

	shca->sport[port - 1].port_state = IB_PORT_DOWN;

	switch (qp_init_attr->qp_type) {
	case IB_QPT_SMI:
		/* function not supported yet */
		break;
	case IB_QPT_GSI:
		ret = hipz_h_define_aqp1(shca->ipz_hca_handle,
					 ehca_qp->ipz_qp_handle,
					 ehca_qp->galpas.kernel,
					 (u32) qp_init_attr->port_num,
					 &pma_qp_nr, &bma_qp_nr);

		if (ret != H_SUCCESS) {
			ehca_err(&shca->ib_device,
				 "Can't define AQP1 for port %x. h_ret=%li",
				 port, ret);
			return ret;
		}
		shca->sport[port - 1].pma_qp_nr = pma_qp_nr;
		ehca_dbg(&shca->ib_device, "port=%x pma_qp_nr=%x",
			 port, pma_qp_nr);
		break;
	default:
		ehca_err(&shca->ib_device, "invalid qp_type=%x",
			 qp_init_attr->qp_type);
		return H_PARAMETER;
	}

	if (ehca_nr_ports < 0) /* autodetect mode */
		return H_SUCCESS;

	for (counter = 0;
	     shca->sport[port - 1].port_state != IB_PORT_ACTIVE &&
		     counter < ehca_port_act_time;
	     counter++) {
		ehca_dbg(&shca->ib_device, "... wait until port %x is active",
			 port);
		msleep_interruptible(1000);
	}

	if (counter == ehca_port_act_time) {
		ehca_err(&shca->ib_device, "Port %x is not active.", port);
		return H_HARDWARE;
	}

	return H_SUCCESS;
}

struct ib_perf {
	struct ib_mad_hdr mad_hdr;
	u8 reserved[40];
	u8 data[192];
} __attribute__ ((packed));


static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
			     struct ib_mad *in_mad, struct ib_mad *out_mad)
{
	struct ib_perf *in_perf = (struct ib_perf *)in_mad;
	struct ib_perf *out_perf = (struct ib_perf *)out_mad;
	struct ib_class_port_info *poi =
		(struct ib_class_port_info *)out_perf->data;
	struct ehca_shca *shca =
		container_of(ibdev, struct ehca_shca, ib_device);
	struct ehca_sport *sport = &shca->sport[port_num - 1];

	ehca_dbg(ibdev, "method=%x", in_perf->mad_hdr.method);

	*out_mad = *in_mad;

	if (in_perf->mad_hdr.class_version != 1) {
		ehca_warn(ibdev, "Unsupported class_version=%x",
			  in_perf->mad_hdr.class_version);
		out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_VERSION;
		goto perf_reply;
	}

	switch (in_perf->mad_hdr.method) {
	case IB_MGMT_METHOD_GET:
	case IB_MGMT_METHOD_SET:
		/* set class port info for redirection */
		out_perf->mad_hdr.attr_id = IB_PMA_CLASS_PORT_INFO;
		out_perf->mad_hdr.status = IB_MAD_STATUS_REDIRECT;
		memset(poi, 0, sizeof(*poi));
		poi->base_version = 1;
		poi->class_version = 1;
		poi->resp_time_value = 18;
		poi->redirect_lid = sport->saved_attr.lid;
		poi->redirect_qp = sport->pma_qp_nr;
		poi->redirect_qkey = IB_QP1_QKEY;
		poi->redirect_pkey = IB_DEFAULT_PKEY_FULL;

		ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x",
			 sport->saved_attr.lid, sport->pma_qp_nr);
		break;

	case IB_MGMT_METHOD_GET_RESP:
		return IB_MAD_RESULT_FAILURE;

	default:
		out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_METHOD;
		break;
	}

perf_reply:
	out_perf->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;

	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
}

int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
		     struct ib_wc *in_wc, struct ib_grh *in_grh,
		     struct ib_mad *in_mad,
		     struct ib_mad *out_mad)
{
	int ret;

	if (!port_num || port_num > ibdev->phys_port_cnt)
		return IB_MAD_RESULT_FAILURE;

	/* accept only pma request */
	if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
		return IB_MAD_RESULT_SUCCESS;

	ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp);
	ret = ehca_process_perf(ibdev, port_num, in_mad, out_mad);

	return ret;
}
