/*
  This file is provided under a dual BSD/GPLv2 license.  When using or
  redistributing this file, you may do so under either license.

  GPL LICENSE SUMMARY
  Copyright(c) 2015 Intel Corporation.
  This program is free software; you can redistribute it and/or modify
  it under the terms of version 2 of the GNU General Public License as
  published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  Contact Information:
  qat-linux@intel.com

  BSD LICENSE
  Copyright(c) 2015 Intel Corporation.
  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.
    * Neither the name of Intel Corporation nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

  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 <linux/delay.h>
#include "adf_accel_devices.h"
#include "adf_common_drv.h"
#include "adf_pf2vf_msg.h"

#define ADF_DH895XCC_EP_OFFSET	0x3A000
#define ADF_DH895XCC_ERRMSK3	(ADF_DH895XCC_EP_OFFSET + 0x1C)
#define ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask) ((vf_mask & 0xFFFF) << 9)
#define ADF_DH895XCC_ERRMSK5	(ADF_DH895XCC_EP_OFFSET + 0xDC)
#define ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask) (vf_mask >> 16)

void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev)
{
	struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	void __iomem *pmisc_bar_addr =
		pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;

	ADF_CSR_WR(pmisc_bar_addr, hw_data->get_vintmsk_offset(0), 0x0);
}

void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev)
{
	struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	void __iomem *pmisc_bar_addr =
		pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;

	ADF_CSR_WR(pmisc_bar_addr, hw_data->get_vintmsk_offset(0), 0x2);
}

void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
				 u32 vf_mask)
{
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	struct adf_bar *pmisc =
			&GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
	void __iomem *pmisc_addr = pmisc->virt_addr;
	u32 reg;

	/* Enable VF2PF Messaging Ints - VFs 1 through 16 per vf_mask[15:0] */
	if (vf_mask & 0xFFFF) {
		reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3);
		reg &= ~ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask);
		ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK3, reg);
	}

	/* Enable VF2PF Messaging Ints - VFs 17 through 32 per vf_mask[31:16] */
	if (vf_mask >> 16) {
		reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK5);
		reg &= ~ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask);
		ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK5, reg);
	}
}

void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev, u32 vf_mask)
{
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	struct adf_bar *pmisc =
			&GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
	void __iomem *pmisc_addr = pmisc->virt_addr;
	u32 reg;

	/* Disable VF2PF interrupts for VFs 1 through 16 per vf_mask[15:0] */
	if (vf_mask & 0xFFFF) {
		reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK3) |
			ADF_DH895XCC_ERRMSK3_VF2PF_L_MASK(vf_mask);
		ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK3, reg);
	}

	/* Disable VF2PF interrupts for VFs 17 through 32 per vf_mask[31:16] */
	if (vf_mask >> 16) {
		reg = ADF_CSR_RD(pmisc_addr, ADF_DH895XCC_ERRMSK5) |
			ADF_DH895XCC_ERRMSK5_VF2PF_U_MASK(vf_mask);
		ADF_CSR_WR(pmisc_addr, ADF_DH895XCC_ERRMSK5, reg);
	}
}

static int __adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr)
{
	struct adf_accel_pci *pci_info = &accel_dev->accel_pci_dev;
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	void __iomem *pmisc_bar_addr =
		pci_info->pci_bars[hw_data->get_misc_bar_id(hw_data)].virt_addr;
	u32 val, pf2vf_offset, count = 0;
	u32 local_in_use_mask, local_in_use_pattern;
	u32 remote_in_use_mask, remote_in_use_pattern;
	struct mutex *lock;	/* lock preventing concurrent acces of CSR */
	u32 int_bit;
	int ret = 0;

	if (accel_dev->is_vf) {
		pf2vf_offset = hw_data->get_pf2vf_offset(0);
		lock = &accel_dev->vf.vf2pf_lock;
		local_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
		local_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
		remote_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
		remote_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
		int_bit = ADF_VF2PF_INT;
	} else {
		pf2vf_offset = hw_data->get_pf2vf_offset(vf_nr);
		lock = &accel_dev->pf.vf_info[vf_nr].pf2vf_lock;
		local_in_use_mask = ADF_PF2VF_IN_USE_BY_PF_MASK;
		local_in_use_pattern = ADF_PF2VF_IN_USE_BY_PF;
		remote_in_use_mask = ADF_VF2PF_IN_USE_BY_VF_MASK;
		remote_in_use_pattern = ADF_VF2PF_IN_USE_BY_VF;
		int_bit = ADF_PF2VF_INT;
	}

	mutex_lock(lock);

	/* Check if PF2VF CSR is in use by remote function */
	val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
	if ((val & remote_in_use_mask) == remote_in_use_pattern) {
		dev_dbg(&GET_DEV(accel_dev),
			"PF2VF CSR in use by remote function\n");
		ret = -EBUSY;
		goto out;
	}

	/* Attempt to get ownership of PF2VF CSR */
	msg &= ~local_in_use_mask;
	msg |= local_in_use_pattern;
	ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg);

	/* Wait in case remote func also attempting to get ownership */
	msleep(ADF_IOV_MSG_COLLISION_DETECT_DELAY);

	val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
	if ((val & local_in_use_mask) != local_in_use_pattern) {
		dev_dbg(&GET_DEV(accel_dev),
			"PF2VF CSR in use by remote - collision detected\n");
		ret = -EBUSY;
		goto out;
	}

	/*
	 * This function now owns the PV2VF CSR.  The IN_USE_BY pattern must
	 * remain in the PF2VF CSR for all writes including ACK from remote
	 * until this local function relinquishes the CSR.  Send the message
	 * by interrupting the remote.
	 */
	ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, msg | int_bit);

	/* Wait for confirmation from remote func it received the message */
	do {
		msleep(ADF_IOV_MSG_ACK_DELAY);
		val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
	} while ((val & int_bit) && (count++ < ADF_IOV_MSG_ACK_MAX_RETRY));

	if (val & int_bit) {
		dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");
		val &= ~int_bit;
		ret = -EIO;
	}

	/* Finished with PF2VF CSR; relinquish it and leave msg in CSR */
	ADF_CSR_WR(pmisc_bar_addr, pf2vf_offset, val & ~local_in_use_mask);
out:
	mutex_unlock(lock);
	return ret;
}

/**
 * adf_iov_putmsg() - send PF2VF message
 * @accel_dev:  Pointer to acceleration device.
 * @msg:	Message to send
 * @vf_nr:	VF number to which the message will be sent
 *
 * Function sends a messge from the PF to a VF
 *
 * Return: 0 on success, error code otherwise.
 */
int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr)
{
	u32 count = 0;
	int ret;

	do {
		ret = __adf_iov_putmsg(accel_dev, msg, vf_nr);
		if (ret)
			msleep(ADF_IOV_MSG_RETRY_DELAY);
	} while (ret && (count++ < ADF_IOV_MSG_MAX_RETRIES));

	return ret;
}
EXPORT_SYMBOL_GPL(adf_iov_putmsg);

void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info)
{
	struct adf_accel_dev *accel_dev = vf_info->accel_dev;
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	int bar_id = hw_data->get_misc_bar_id(hw_data);
	struct adf_bar *pmisc = &GET_BARS(accel_dev)[bar_id];
	void __iomem *pmisc_addr = pmisc->virt_addr;
	u32 msg, resp = 0, vf_nr = vf_info->vf_nr;

	/* Read message from the VF */
	msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr));

	/* To ACK, clear the VF2PFINT bit */
	msg &= ~ADF_VF2PF_INT;
	ADF_CSR_WR(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr), msg);

	if (!(msg & ADF_VF2PF_MSGORIGIN_SYSTEM))
		/* Ignore legacy non-system (non-kernel) VF2PF messages */
		goto err;

	switch ((msg & ADF_VF2PF_MSGTYPE_MASK) >> ADF_VF2PF_MSGTYPE_SHIFT) {
	case ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ:
		{
		u8 vf_compat_ver = msg >> ADF_VF2PF_COMPAT_VER_REQ_SHIFT;

		resp = (ADF_PF2VF_MSGORIGIN_SYSTEM |
			 (ADF_PF2VF_MSGTYPE_VERSION_RESP <<
			  ADF_PF2VF_MSGTYPE_SHIFT) |
			 (ADF_PFVF_COMPATIBILITY_VERSION <<
			  ADF_PF2VF_VERSION_RESP_VERS_SHIFT));

		dev_dbg(&GET_DEV(accel_dev),
			"Compatibility Version Request from VF%d vers=%u\n",
			vf_nr + 1, vf_compat_ver);

		if (vf_compat_ver < hw_data->min_iov_compat_ver) {
			dev_err(&GET_DEV(accel_dev),
				"VF (vers %d) incompatible with PF (vers %d)\n",
				vf_compat_ver, ADF_PFVF_COMPATIBILITY_VERSION);
			resp |= ADF_PF2VF_VF_INCOMPATIBLE <<
				ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
		} else if (vf_compat_ver > ADF_PFVF_COMPATIBILITY_VERSION) {
			dev_err(&GET_DEV(accel_dev),
				"VF (vers %d) compat with PF (vers %d) unkn.\n",
				vf_compat_ver, ADF_PFVF_COMPATIBILITY_VERSION);
			resp |= ADF_PF2VF_VF_COMPAT_UNKNOWN <<
				ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
		} else {
			dev_dbg(&GET_DEV(accel_dev),
				"VF (vers %d) compatible with PF (vers %d)\n",
				vf_compat_ver, ADF_PFVF_COMPATIBILITY_VERSION);
			resp |= ADF_PF2VF_VF_COMPATIBLE <<
				ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
		}
		}
		break;
	case ADF_VF2PF_MSGTYPE_VERSION_REQ:
		dev_dbg(&GET_DEV(accel_dev),
			"Legacy VersionRequest received from VF%d 0x%x\n",
			vf_nr + 1, msg);
		resp = (ADF_PF2VF_MSGORIGIN_SYSTEM |
			 (ADF_PF2VF_MSGTYPE_VERSION_RESP <<
			  ADF_PF2VF_MSGTYPE_SHIFT) |
			 (ADF_PFVF_COMPATIBILITY_VERSION <<
			  ADF_PF2VF_VERSION_RESP_VERS_SHIFT));
		resp |= ADF_PF2VF_VF_COMPATIBLE <<
			ADF_PF2VF_VERSION_RESP_RESULT_SHIFT;
		/* Set legacy major and minor version num */
		resp |= 1 << ADF_PF2VF_MAJORVERSION_SHIFT |
			1 << ADF_PF2VF_MINORVERSION_SHIFT;
		break;
	case ADF_VF2PF_MSGTYPE_INIT:
		{
		dev_dbg(&GET_DEV(accel_dev),
			"Init message received from VF%d 0x%x\n",
			vf_nr + 1, msg);
		vf_info->init = true;
		}
		break;
	case ADF_VF2PF_MSGTYPE_SHUTDOWN:
		{
		dev_dbg(&GET_DEV(accel_dev),
			"Shutdown message received from VF%d 0x%x\n",
			vf_nr + 1, msg);
		vf_info->init = false;
		}
		break;
	default:
		goto err;
	}

	if (resp && adf_iov_putmsg(accel_dev, resp, vf_nr))
		dev_err(&GET_DEV(accel_dev), "Failed to send response to VF\n");

	/* re-enable interrupt on PF from this VF */
	adf_enable_vf2pf_interrupts(accel_dev, (1 << vf_nr));
	return;
err:
	dev_dbg(&GET_DEV(accel_dev), "Unknown message from VF%d (0x%x);\n",
		vf_nr + 1, msg);
}

void adf_pf2vf_notify_restarting(struct adf_accel_dev *accel_dev)
{
	struct adf_accel_vf_info *vf;
	u32 msg = (ADF_PF2VF_MSGORIGIN_SYSTEM |
		(ADF_PF2VF_MSGTYPE_RESTARTING << ADF_PF2VF_MSGTYPE_SHIFT));
	int i, num_vfs = pci_num_vf(accel_to_pci_dev(accel_dev));

	for (i = 0, vf = accel_dev->pf.vf_info; i < num_vfs; i++, vf++) {
		if (vf->init && adf_iov_putmsg(accel_dev, msg, i))
			dev_err(&GET_DEV(accel_dev),
				"Failed to send restarting msg to VF%d\n", i);
	}
}

static int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev)
{
	unsigned long timeout = msecs_to_jiffies(ADF_IOV_MSG_RESP_TIMEOUT);
	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
	u32 msg = 0;
	int ret;

	msg = ADF_VF2PF_MSGORIGIN_SYSTEM;
	msg |= ADF_VF2PF_MSGTYPE_COMPAT_VER_REQ << ADF_VF2PF_MSGTYPE_SHIFT;
	msg |= ADF_PFVF_COMPATIBILITY_VERSION << ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
	BUILD_BUG_ON(ADF_PFVF_COMPATIBILITY_VERSION > 255);

	/* Send request from VF to PF */
	ret = adf_iov_putmsg(accel_dev, msg, 0);
	if (ret) {
		dev_err(&GET_DEV(accel_dev),
			"Failed to send Compatibility Version Request.\n");
		return ret;
	}

	/* Wait for response */
	if (!wait_for_completion_timeout(&accel_dev->vf.iov_msg_completion,
					 timeout)) {
		dev_err(&GET_DEV(accel_dev),
			"IOV request/response message timeout expired\n");
		return -EIO;
	}

	/* Response from PF received, check compatibility */
	switch (accel_dev->vf.compatible) {
	case ADF_PF2VF_VF_COMPATIBLE:
		break;
	case ADF_PF2VF_VF_COMPAT_UNKNOWN:
		/* VF is newer than PF and decides whether it is compatible */
		if (accel_dev->vf.pf_version >= hw_data->min_iov_compat_ver)
			break;
		/* fall through */
	case ADF_PF2VF_VF_INCOMPATIBLE:
		dev_err(&GET_DEV(accel_dev),
			"PF (vers %d) and VF (vers %d) are not compatible\n",
			accel_dev->vf.pf_version,
			ADF_PFVF_COMPATIBILITY_VERSION);
		return -EINVAL;
	default:
		dev_err(&GET_DEV(accel_dev),
			"Invalid response from PF; assume not compatible\n");
		return -EINVAL;
	}
	return ret;
}

/**
 * adf_enable_vf2pf_comms() - Function enables communication from vf to pf
 *
 * @accel_dev: Pointer to acceleration device virtual function.
 *
 * Return: 0 on success, error code otherwise.
 */
int adf_enable_vf2pf_comms(struct adf_accel_dev *accel_dev)
{
	adf_enable_pf2vf_interrupts(accel_dev);
	return adf_vf2pf_request_version(accel_dev);
}
EXPORT_SYMBOL_GPL(adf_enable_vf2pf_comms);
