/*
 * 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/string.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/interrupt.h>

#include "vnic_dev.h"
#include "vnic_intr.h"
#include "vnic_stats.h"
#include "snic_io.h"
#include "snic.h"


/*
 * snic_isr_msix_wq : MSIx ISR for work queue.
 */

static irqreturn_t
snic_isr_msix_wq(int irq, void *data)
{
	struct snic *snic = data;
	unsigned long wq_work_done = 0;

	snic->s_stats.misc.last_isr_time = jiffies;
	atomic64_inc(&snic->s_stats.misc.isr_cnt);

	wq_work_done = snic_wq_cmpl_handler(snic, -1);
	svnic_intr_return_credits(&snic->intr[SNIC_MSIX_WQ],
				  wq_work_done,
				  1 /* unmask intr */,
				  1 /* reset intr timer */);

	return IRQ_HANDLED;
} /* end of snic_isr_msix_wq */

static irqreturn_t
snic_isr_msix_io_cmpl(int irq, void *data)
{
	struct snic *snic = data;
	unsigned long iocmpl_work_done = 0;

	snic->s_stats.misc.last_isr_time = jiffies;
	atomic64_inc(&snic->s_stats.misc.isr_cnt);

	iocmpl_work_done = snic_fwcq_cmpl_handler(snic, -1);
	svnic_intr_return_credits(&snic->intr[SNIC_MSIX_IO_CMPL],
				  iocmpl_work_done,
				  1 /* unmask intr */,
				  1 /* reset intr timer */);

	return IRQ_HANDLED;
} /* end of snic_isr_msix_io_cmpl */

static irqreturn_t
snic_isr_msix_err_notify(int irq, void *data)
{
	struct snic *snic = data;

	snic->s_stats.misc.last_isr_time = jiffies;
	atomic64_inc(&snic->s_stats.misc.isr_cnt);

	svnic_intr_return_all_credits(&snic->intr[SNIC_MSIX_ERR_NOTIFY]);
	snic_log_q_error(snic);

	/*Handling link events */
	snic_handle_link_event(snic);

	return IRQ_HANDLED;
} /* end of snic_isr_msix_err_notify */


void
snic_free_intr(struct snic *snic)
{
	int i;

	/* ONLY interrupt mode MSIX is supported */
	for (i = 0; i < ARRAY_SIZE(snic->msix); i++) {
		if (snic->msix[i].requested) {
			free_irq(snic->msix_entry[i].vector,
				 snic->msix[i].devid);
		}
	}
} /* end of snic_free_intr */

int
snic_request_intr(struct snic *snic)
{
	int ret = 0, i;
	enum vnic_dev_intr_mode intr_mode;

	intr_mode = svnic_dev_get_intr_mode(snic->vdev);
	SNIC_BUG_ON(intr_mode != VNIC_DEV_INTR_MODE_MSIX);

	/*
	 * Currently HW supports single WQ and CQ. So passing devid as snic.
	 * When hardware supports multiple WQs and CQs, one idea is
	 * to pass devid as corresponding WQ or CQ ptr and retrieve snic
	 * from queue ptr.
	 * Except for err_notify, which is always one.
	 */
	sprintf(snic->msix[SNIC_MSIX_WQ].devname,
		"%.11s-scsi-wq",
		snic->name);
	snic->msix[SNIC_MSIX_WQ].isr = snic_isr_msix_wq;
	snic->msix[SNIC_MSIX_WQ].devid = snic;

	sprintf(snic->msix[SNIC_MSIX_IO_CMPL].devname,
		"%.11s-io-cmpl",
		snic->name);
	snic->msix[SNIC_MSIX_IO_CMPL].isr = snic_isr_msix_io_cmpl;
	snic->msix[SNIC_MSIX_IO_CMPL].devid = snic;

	sprintf(snic->msix[SNIC_MSIX_ERR_NOTIFY].devname,
		"%.11s-err-notify",
		snic->name);
	snic->msix[SNIC_MSIX_ERR_NOTIFY].isr = snic_isr_msix_err_notify;
	snic->msix[SNIC_MSIX_ERR_NOTIFY].devid = snic;

	for (i = 0; i < ARRAY_SIZE(snic->msix); i++) {
		ret = request_irq(snic->msix_entry[i].vector,
				  snic->msix[i].isr,
				  0,
				  snic->msix[i].devname,
				  snic->msix[i].devid);
		if (ret) {
			SNIC_HOST_ERR(snic->shost,
				      "MSI-X: requrest_irq(%d) failed %d\n",
				      i,
				      ret);
			snic_free_intr(snic);
			break;
		}
		snic->msix[i].requested = 1;
	}

	return ret;
} /* end of snic_requrest_intr */

int
snic_set_intr_mode(struct snic *snic)
{
	unsigned int n = ARRAY_SIZE(snic->wq);
	unsigned int m = SNIC_CQ_IO_CMPL_MAX;
	unsigned int i;

	/*
	 * We need n WQs, m CQs, and n+m+1 INTRs
	 * (last INTR is used for WQ/CQ errors and notification area
	 */

	BUILD_BUG_ON((ARRAY_SIZE(snic->wq) + SNIC_CQ_IO_CMPL_MAX) >
			ARRAY_SIZE(snic->intr));
	SNIC_BUG_ON(ARRAY_SIZE(snic->msix_entry) < (n + m + 1));

	for (i = 0; i < (n + m + 1); i++)
		snic->msix_entry[i].entry = i;

	if (snic->wq_count >= n && snic->cq_count >= (n + m)) {
		if (!pci_enable_msix(snic->pdev,
				     snic->msix_entry,
				     (n + m + 1))) {
			snic->wq_count = n;
			snic->cq_count = n + m;
			snic->intr_count = n + m + 1;
			snic->err_intr_offset = SNIC_MSIX_ERR_NOTIFY;

			SNIC_ISR_DBG(snic->shost,
				     "Using MSI-X Interrupts\n");
			svnic_dev_set_intr_mode(snic->vdev,
						VNIC_DEV_INTR_MODE_MSIX);

			return 0;
		}
	}

	svnic_dev_set_intr_mode(snic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);

	return -EINVAL;
} /* end of snic_set_intr_mode */

void
snic_clear_intr_mode(struct snic *snic)
{
	pci_disable_msix(snic->pdev);

	svnic_dev_set_intr_mode(snic->vdev, VNIC_DEV_INTR_MODE_INTX);
}
