/*
 * Copyright 2014 Cisco Systems, Inc.  All rights reserved.
 *
 * This program is free software; you may redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * 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/errno.h>
#include <linux/pci.h>
#include <linux/slab.h>

#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/spinlock.h>
#include <linux/mempool.h>
#include <scsi/scsi_tcq.h>
#include <linux/ctype.h>

#include "snic_io.h"
#include "snic.h"
#include "cq_enet_desc.h"
#include "snic_fwint.h"

/*
 * snic_handle_link : Handles link flaps.
 */
void
snic_handle_link(struct work_struct *work)
{
	struct snic *snic = container_of(work, struct snic, link_work);

	if (snic->config.xpt_type == SNIC_DAS)
		return;

	snic->link_status = svnic_dev_link_status(snic->vdev);
	snic->link_down_cnt = svnic_dev_link_down_cnt(snic->vdev);
	SNIC_HOST_INFO(snic->shost, "Link Event: Link %s.\n",
		       ((snic->link_status) ? "Up" : "Down"));

	SNIC_ASSERT_NOT_IMPL(1);
}


/*
 * snic_ver_enc : Encodes version str to int
 * version string is similar to netmask string
 */
static int
snic_ver_enc(const char *s)
{
	int v[4] = {0};
	int  i = 0, x = 0;
	char c;
	const char *p = s;

	/* validate version string */
	if ((strlen(s) > 15) || (strlen(s) < 7))
		goto end;

	while ((c = *p++)) {
		if (c == '.') {
			i++;
			continue;
		}

		if (i > 3 || !isdigit(c))
			goto end;

		v[i] = v[i] * 10 + (c - '0');
	}

	/* validate sub version numbers */
	for (i = 3; i >= 0; i--)
		if (v[i] > 0xff)
			goto end;

	x |= (v[0] << 24) | v[1] << 16 | v[2] << 8 | v[3];

end:
	if (x == 0) {
		SNIC_ERR("Invalid version string [%s].\n", s);

		return -1;
	}

	return x;
} /* end of snic_ver_enc */

/*
 * snic_qeueue_exch_ver_req :
 *
 * Queues Exchange Version Request, to communicate host information
 * in return, it gets firmware version details
 */
int
snic_queue_exch_ver_req(struct snic *snic)
{
	struct snic_req_info *rqi = NULL;
	struct snic_host_req *req = NULL;
	u32 ver = 0;
	int ret = 0;

	SNIC_HOST_INFO(snic->shost, "Exch Ver Req Preparing...\n");

	rqi = snic_req_init(snic, 0);
	if (!rqi) {
		SNIC_HOST_ERR(snic->shost,
			      "Queuing Exch Ver Req failed, err = %d\n",
			      ret);

		ret = -ENOMEM;
		goto error;
	}

	req = rqi_to_req(rqi);

	/* Initialize snic_host_req */
	snic_io_hdr_enc(&req->hdr, SNIC_REQ_EXCH_VER, 0, SCSI_NO_TAG,
			snic->config.hid, 0, (ulong)rqi);
	ver = snic_ver_enc(SNIC_DRV_VERSION);
	req->u.exch_ver.drvr_ver = cpu_to_le32(ver);
	req->u.exch_ver.os_type = cpu_to_le32(SNIC_OS_LINUX);

	snic_handle_untagged_req(snic, rqi);

	ret = snic_queue_wq_desc(snic, req, sizeof(*req));
	if (ret) {
		snic_release_untagged_req(snic, rqi);
		SNIC_HOST_ERR(snic->shost,
			      "Queuing Exch Ver Req failed, err = %d\n",
			      ret);
		goto error;
	}

	SNIC_HOST_INFO(snic->shost, "Exch Ver Req is issued. ret = %d\n", ret);

error:
	return ret;
} /* end of snic_queue_exch_ver_req */

/*
 * snic_io_exch_ver_cmpl_handler
 */
void
snic_io_exch_ver_cmpl_handler(struct snic *snic, struct snic_fw_req *fwreq)
{
	struct snic_req_info *rqi = NULL;
	struct snic_exch_ver_rsp *exv_cmpl = &fwreq->u.exch_ver_cmpl;
	u8 typ, hdr_stat;
	u32 cmnd_id, hid, max_sgs;
	ulong ctx = 0;
	unsigned long flags;

	SNIC_HOST_INFO(snic->shost, "Exch Ver Compl Received.\n");
	snic_io_hdr_dec(&fwreq->hdr, &typ, &hdr_stat, &cmnd_id, &hid, &ctx);
	SNIC_BUG_ON(snic->config.hid != hid);
	rqi = (struct snic_req_info *) ctx;

	if (hdr_stat) {
		SNIC_HOST_ERR(snic->shost,
			      "Exch Ver Completed w/ err status %d\n",
			      hdr_stat);

		goto exch_cmpl_end;
	}

	spin_lock_irqsave(&snic->snic_lock, flags);
	snic->fwinfo.fw_ver = le32_to_cpu(exv_cmpl->version);
	snic->fwinfo.hid = le32_to_cpu(exv_cmpl->hid);
	snic->fwinfo.max_concur_ios = le32_to_cpu(exv_cmpl->max_concur_ios);
	snic->fwinfo.max_sgs_per_cmd = le32_to_cpu(exv_cmpl->max_sgs_per_cmd);
	snic->fwinfo.max_io_sz = le32_to_cpu(exv_cmpl->max_io_sz);
	snic->fwinfo.max_tgts = le32_to_cpu(exv_cmpl->max_tgts);
	snic->fwinfo.io_tmo = le16_to_cpu(exv_cmpl->io_timeout);

	SNIC_HOST_INFO(snic->shost,
		       "vers %u hid %u max_concur_ios %u max_sgs_per_cmd %u max_io_sz %u max_tgts %u fw tmo %u\n",
		       snic->fwinfo.fw_ver,
		       snic->fwinfo.hid,
		       snic->fwinfo.max_concur_ios,
		       snic->fwinfo.max_sgs_per_cmd,
		       snic->fwinfo.max_io_sz,
		       snic->fwinfo.max_tgts,
		       snic->fwinfo.io_tmo);

	SNIC_HOST_INFO(snic->shost,
		       "HBA Capabilities = 0x%x\n",
		       le32_to_cpu(exv_cmpl->hba_cap));

	/* Updating SGList size */
	max_sgs = snic->fwinfo.max_sgs_per_cmd;
	if (max_sgs && max_sgs < SNIC_MAX_SG_DESC_CNT) {
		snic->shost->sg_tablesize = max_sgs;
		SNIC_HOST_INFO(snic->shost, "Max SGs set to %d\n",
			       snic->shost->sg_tablesize);
	} else if (max_sgs > snic->shost->sg_tablesize) {
		SNIC_HOST_INFO(snic->shost,
			       "Target type %d Supports Larger Max SGList %d than driver's Max SG List %d.\n",
			       snic->config.xpt_type, max_sgs,
			       snic->shost->sg_tablesize);
	}

	if (snic->shost->can_queue > snic->fwinfo.max_concur_ios)
		snic->shost->can_queue = snic->fwinfo.max_concur_ios;

	snic->shost->max_sectors = snic->fwinfo.max_io_sz >> 9;
	if (snic->fwinfo.wait)
		complete(snic->fwinfo.wait);

	spin_unlock_irqrestore(&snic->snic_lock, flags);

exch_cmpl_end:
	snic_release_untagged_req(snic, rqi);

	SNIC_HOST_INFO(snic->shost, "Exch_cmpl Done, hdr_stat %d.\n", hdr_stat);
} /* end of snic_io_exch_ver_cmpl_handler */

/*
 * snic_get_conf
 *
 * Synchronous call, and Retrieves snic params.
 */
int
snic_get_conf(struct snic *snic)
{
	DECLARE_COMPLETION_ONSTACK(wait);
	unsigned long flags;
	int ret;
	int nr_retries = 3;

	SNIC_HOST_INFO(snic->shost, "Retrieving snic params.\n");
	spin_lock_irqsave(&snic->snic_lock, flags);
	memset(&snic->fwinfo, 0, sizeof(snic->fwinfo));
	snic->fwinfo.wait = &wait;
	spin_unlock_irqrestore(&snic->snic_lock, flags);

	/* Additional delay to handle HW Resource initialization. */
	msleep(50);

	/*
	 * Exch ver req can be ignored by FW, if HW Resource initialization
	 * is in progress, Hence retry.
	 */
	do {
		ret = snic_queue_exch_ver_req(snic);
		if (ret)
			return ret;

		wait_for_completion_timeout(&wait, msecs_to_jiffies(2000));
		spin_lock_irqsave(&snic->snic_lock, flags);
		ret = (snic->fwinfo.fw_ver != 0) ? 0 : -ETIMEDOUT;
		if (ret)
			SNIC_HOST_ERR(snic->shost,
				      "Failed to retrieve snic params,\n");

		/* Unset fwinfo.wait, on success or on last retry */
		if (ret == 0 || nr_retries == 1)
			snic->fwinfo.wait = NULL;

		spin_unlock_irqrestore(&snic->snic_lock, flags);
	} while (ret && --nr_retries);

	return ret;
} /* end of snic_get_info */
