18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
38c2ecf20Sopenharmony_ci * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This program is free software; you may redistribute it and/or modify
68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by
78c2ecf20Sopenharmony_ci * the Free Software Foundation; version 2 of the License.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
108c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
118c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
128c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
138c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
148c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
158c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
168c2ecf20Sopenharmony_ci * SOFTWARE.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci#include <linux/string.h>
198c2ecf20Sopenharmony_ci#include <linux/errno.h>
208c2ecf20Sopenharmony_ci#include <linux/pci.h>
218c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
228c2ecf20Sopenharmony_ci#include <scsi/libfc.h>
238c2ecf20Sopenharmony_ci#include <scsi/fc_frame.h>
248c2ecf20Sopenharmony_ci#include "vnic_dev.h"
258c2ecf20Sopenharmony_ci#include "vnic_intr.h"
268c2ecf20Sopenharmony_ci#include "vnic_stats.h"
278c2ecf20Sopenharmony_ci#include "fnic_io.h"
288c2ecf20Sopenharmony_ci#include "fnic.h"
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic irqreturn_t fnic_isr_legacy(int irq, void *data)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct fnic *fnic = data;
338c2ecf20Sopenharmony_ci	u32 pba;
348c2ecf20Sopenharmony_ci	unsigned long work_done = 0;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	pba = vnic_intr_legacy_pba(fnic->legacy_pba);
378c2ecf20Sopenharmony_ci	if (!pba)
388c2ecf20Sopenharmony_ci		return IRQ_NONE;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
418c2ecf20Sopenharmony_ci	atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	if (pba & (1 << FNIC_INTX_NOTIFY)) {
448c2ecf20Sopenharmony_ci		vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_NOTIFY]);
458c2ecf20Sopenharmony_ci		fnic_handle_link_event(fnic);
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (pba & (1 << FNIC_INTX_ERR)) {
498c2ecf20Sopenharmony_ci		vnic_intr_return_all_credits(&fnic->intr[FNIC_INTX_ERR]);
508c2ecf20Sopenharmony_ci		fnic_log_q_error(fnic);
518c2ecf20Sopenharmony_ci	}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	if (pba & (1 << FNIC_INTX_WQ_RQ_COPYWQ)) {
548c2ecf20Sopenharmony_ci		work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
558c2ecf20Sopenharmony_ci		work_done += fnic_wq_cmpl_handler(fnic, -1);
568c2ecf20Sopenharmony_ci		work_done += fnic_rq_cmpl_handler(fnic, -1);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci		vnic_intr_return_credits(&fnic->intr[FNIC_INTX_WQ_RQ_COPYWQ],
598c2ecf20Sopenharmony_ci					 work_done,
608c2ecf20Sopenharmony_ci					 1 /* unmask intr */,
618c2ecf20Sopenharmony_ci					 1 /* reset intr timer */);
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic irqreturn_t fnic_isr_msi(int irq, void *data)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct fnic *fnic = data;
708c2ecf20Sopenharmony_ci	unsigned long work_done = 0;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
738c2ecf20Sopenharmony_ci	atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	work_done += fnic_wq_copy_cmpl_handler(fnic, io_completions);
768c2ecf20Sopenharmony_ci	work_done += fnic_wq_cmpl_handler(fnic, -1);
778c2ecf20Sopenharmony_ci	work_done += fnic_rq_cmpl_handler(fnic, -1);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	vnic_intr_return_credits(&fnic->intr[0],
808c2ecf20Sopenharmony_ci				 work_done,
818c2ecf20Sopenharmony_ci				 1 /* unmask intr */,
828c2ecf20Sopenharmony_ci				 1 /* reset intr timer */);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic irqreturn_t fnic_isr_msix_rq(int irq, void *data)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	struct fnic *fnic = data;
908c2ecf20Sopenharmony_ci	unsigned long rq_work_done = 0;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
938c2ecf20Sopenharmony_ci	atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	rq_work_done = fnic_rq_cmpl_handler(fnic, -1);
968c2ecf20Sopenharmony_ci	vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_RQ],
978c2ecf20Sopenharmony_ci				 rq_work_done,
988c2ecf20Sopenharmony_ci				 1 /* unmask intr */,
998c2ecf20Sopenharmony_ci				 1 /* reset intr timer */);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic irqreturn_t fnic_isr_msix_wq(int irq, void *data)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	struct fnic *fnic = data;
1078c2ecf20Sopenharmony_ci	unsigned long wq_work_done = 0;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
1108c2ecf20Sopenharmony_ci	atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	wq_work_done = fnic_wq_cmpl_handler(fnic, -1);
1138c2ecf20Sopenharmony_ci	vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ],
1148c2ecf20Sopenharmony_ci				 wq_work_done,
1158c2ecf20Sopenharmony_ci				 1 /* unmask intr */,
1168c2ecf20Sopenharmony_ci				 1 /* reset intr timer */);
1178c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic irqreturn_t fnic_isr_msix_wq_copy(int irq, void *data)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	struct fnic *fnic = data;
1238c2ecf20Sopenharmony_ci	unsigned long wq_copy_work_done = 0;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
1268c2ecf20Sopenharmony_ci	atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	wq_copy_work_done = fnic_wq_copy_cmpl_handler(fnic, io_completions);
1298c2ecf20Sopenharmony_ci	vnic_intr_return_credits(&fnic->intr[FNIC_MSIX_WQ_COPY],
1308c2ecf20Sopenharmony_ci				 wq_copy_work_done,
1318c2ecf20Sopenharmony_ci				 1 /* unmask intr */,
1328c2ecf20Sopenharmony_ci				 1 /* reset intr timer */);
1338c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic irqreturn_t fnic_isr_msix_err_notify(int irq, void *data)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct fnic *fnic = data;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	fnic->fnic_stats.misc_stats.last_isr_time = jiffies;
1418c2ecf20Sopenharmony_ci	atomic64_inc(&fnic->fnic_stats.misc_stats.isr_count);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	vnic_intr_return_all_credits(&fnic->intr[FNIC_MSIX_ERR_NOTIFY]);
1448c2ecf20Sopenharmony_ci	fnic_log_q_error(fnic);
1458c2ecf20Sopenharmony_ci	fnic_handle_link_event(fnic);
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_civoid fnic_free_intr(struct fnic *fnic)
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci	int i;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	switch (vnic_dev_get_intr_mode(fnic->vdev)) {
1558c2ecf20Sopenharmony_ci	case VNIC_DEV_INTR_MODE_INTX:
1568c2ecf20Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSI:
1578c2ecf20Sopenharmony_ci		free_irq(pci_irq_vector(fnic->pdev, 0), fnic);
1588c2ecf20Sopenharmony_ci		break;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSIX:
1618c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(fnic->msix); i++)
1628c2ecf20Sopenharmony_ci			if (fnic->msix[i].requested)
1638c2ecf20Sopenharmony_ci				free_irq(pci_irq_vector(fnic->pdev, i),
1648c2ecf20Sopenharmony_ci					 fnic->msix[i].devid);
1658c2ecf20Sopenharmony_ci		break;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	default:
1688c2ecf20Sopenharmony_ci		break;
1698c2ecf20Sopenharmony_ci	}
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ciint fnic_request_intr(struct fnic *fnic)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	int err = 0;
1758c2ecf20Sopenharmony_ci	int i;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	switch (vnic_dev_get_intr_mode(fnic->vdev)) {
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	case VNIC_DEV_INTR_MODE_INTX:
1808c2ecf20Sopenharmony_ci		err = request_irq(pci_irq_vector(fnic->pdev, 0),
1818c2ecf20Sopenharmony_ci				&fnic_isr_legacy, IRQF_SHARED, DRV_NAME, fnic);
1828c2ecf20Sopenharmony_ci		break;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSI:
1858c2ecf20Sopenharmony_ci		err = request_irq(pci_irq_vector(fnic->pdev, 0), &fnic_isr_msi,
1868c2ecf20Sopenharmony_ci				  0, fnic->name, fnic);
1878c2ecf20Sopenharmony_ci		break;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSIX:
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		sprintf(fnic->msix[FNIC_MSIX_RQ].devname,
1928c2ecf20Sopenharmony_ci			"%.11s-fcs-rq", fnic->name);
1938c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_RQ].isr = fnic_isr_msix_rq;
1948c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_RQ].devid = fnic;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci		sprintf(fnic->msix[FNIC_MSIX_WQ].devname,
1978c2ecf20Sopenharmony_ci			"%.11s-fcs-wq", fnic->name);
1988c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_WQ].isr = fnic_isr_msix_wq;
1998c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_WQ].devid = fnic;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci		sprintf(fnic->msix[FNIC_MSIX_WQ_COPY].devname,
2028c2ecf20Sopenharmony_ci			"%.11s-scsi-wq", fnic->name);
2038c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_WQ_COPY].isr = fnic_isr_msix_wq_copy;
2048c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_WQ_COPY].devid = fnic;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci		sprintf(fnic->msix[FNIC_MSIX_ERR_NOTIFY].devname,
2078c2ecf20Sopenharmony_ci			"%.11s-err-notify", fnic->name);
2088c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_ERR_NOTIFY].isr =
2098c2ecf20Sopenharmony_ci			fnic_isr_msix_err_notify;
2108c2ecf20Sopenharmony_ci		fnic->msix[FNIC_MSIX_ERR_NOTIFY].devid = fnic;
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(fnic->msix); i++) {
2138c2ecf20Sopenharmony_ci			err = request_irq(pci_irq_vector(fnic->pdev, i),
2148c2ecf20Sopenharmony_ci					  fnic->msix[i].isr, 0,
2158c2ecf20Sopenharmony_ci					  fnic->msix[i].devname,
2168c2ecf20Sopenharmony_ci					  fnic->msix[i].devid);
2178c2ecf20Sopenharmony_ci			if (err) {
2188c2ecf20Sopenharmony_ci				shost_printk(KERN_ERR, fnic->lport->host,
2198c2ecf20Sopenharmony_ci					     "MSIX: request_irq"
2208c2ecf20Sopenharmony_ci					     " failed %d\n", err);
2218c2ecf20Sopenharmony_ci				fnic_free_intr(fnic);
2228c2ecf20Sopenharmony_ci				break;
2238c2ecf20Sopenharmony_ci			}
2248c2ecf20Sopenharmony_ci			fnic->msix[i].requested = 1;
2258c2ecf20Sopenharmony_ci		}
2268c2ecf20Sopenharmony_ci		break;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	default:
2298c2ecf20Sopenharmony_ci		break;
2308c2ecf20Sopenharmony_ci	}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	return err;
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ciint fnic_set_intr_mode(struct fnic *fnic)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	unsigned int n = ARRAY_SIZE(fnic->rq);
2388c2ecf20Sopenharmony_ci	unsigned int m = ARRAY_SIZE(fnic->wq);
2398c2ecf20Sopenharmony_ci	unsigned int o = ARRAY_SIZE(fnic->wq_copy);
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	/*
2428c2ecf20Sopenharmony_ci	 * Set interrupt mode (INTx, MSI, MSI-X) depending
2438c2ecf20Sopenharmony_ci	 * system capabilities.
2448c2ecf20Sopenharmony_ci	 *
2458c2ecf20Sopenharmony_ci	 * Try MSI-X first
2468c2ecf20Sopenharmony_ci	 *
2478c2ecf20Sopenharmony_ci	 * We need n RQs, m WQs, o Copy WQs, n+m+o CQs, and n+m+o+1 INTRs
2488c2ecf20Sopenharmony_ci	 * (last INTR is used for WQ/RQ errors and notification area)
2498c2ecf20Sopenharmony_ci	 */
2508c2ecf20Sopenharmony_ci	if (fnic->rq_count >= n &&
2518c2ecf20Sopenharmony_ci	    fnic->raw_wq_count >= m &&
2528c2ecf20Sopenharmony_ci	    fnic->wq_copy_count >= o &&
2538c2ecf20Sopenharmony_ci	    fnic->cq_count >= n + m + o) {
2548c2ecf20Sopenharmony_ci		int vecs = n + m + o + 1;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci		if (pci_alloc_irq_vectors(fnic->pdev, vecs, vecs,
2578c2ecf20Sopenharmony_ci				PCI_IRQ_MSIX) == vecs) {
2588c2ecf20Sopenharmony_ci			fnic->rq_count = n;
2598c2ecf20Sopenharmony_ci			fnic->raw_wq_count = m;
2608c2ecf20Sopenharmony_ci			fnic->wq_copy_count = o;
2618c2ecf20Sopenharmony_ci			fnic->wq_count = m + o;
2628c2ecf20Sopenharmony_ci			fnic->cq_count = n + m + o;
2638c2ecf20Sopenharmony_ci			fnic->intr_count = vecs;
2648c2ecf20Sopenharmony_ci			fnic->err_intr_offset = FNIC_MSIX_ERR_NOTIFY;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci			FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
2678c2ecf20Sopenharmony_ci				     "Using MSI-X Interrupts\n");
2688c2ecf20Sopenharmony_ci			vnic_dev_set_intr_mode(fnic->vdev,
2698c2ecf20Sopenharmony_ci					       VNIC_DEV_INTR_MODE_MSIX);
2708c2ecf20Sopenharmony_ci			return 0;
2718c2ecf20Sopenharmony_ci		}
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	/*
2758c2ecf20Sopenharmony_ci	 * Next try MSI
2768c2ecf20Sopenharmony_ci	 * We need 1 RQ, 1 WQ, 1 WQ_COPY, 3 CQs, and 1 INTR
2778c2ecf20Sopenharmony_ci	 */
2788c2ecf20Sopenharmony_ci	if (fnic->rq_count >= 1 &&
2798c2ecf20Sopenharmony_ci	    fnic->raw_wq_count >= 1 &&
2808c2ecf20Sopenharmony_ci	    fnic->wq_copy_count >= 1 &&
2818c2ecf20Sopenharmony_ci	    fnic->cq_count >= 3 &&
2828c2ecf20Sopenharmony_ci	    fnic->intr_count >= 1 &&
2838c2ecf20Sopenharmony_ci	    pci_alloc_irq_vectors(fnic->pdev, 1, 1, PCI_IRQ_MSI) == 1) {
2848c2ecf20Sopenharmony_ci		fnic->rq_count = 1;
2858c2ecf20Sopenharmony_ci		fnic->raw_wq_count = 1;
2868c2ecf20Sopenharmony_ci		fnic->wq_copy_count = 1;
2878c2ecf20Sopenharmony_ci		fnic->wq_count = 2;
2888c2ecf20Sopenharmony_ci		fnic->cq_count = 3;
2898c2ecf20Sopenharmony_ci		fnic->intr_count = 1;
2908c2ecf20Sopenharmony_ci		fnic->err_intr_offset = 0;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci		FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
2938c2ecf20Sopenharmony_ci			     "Using MSI Interrupts\n");
2948c2ecf20Sopenharmony_ci		vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_MSI);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci		return 0;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/*
3008c2ecf20Sopenharmony_ci	 * Next try INTx
3018c2ecf20Sopenharmony_ci	 * We need 1 RQ, 1 WQ, 1 WQ_COPY, 3 CQs, and 3 INTRs
3028c2ecf20Sopenharmony_ci	 * 1 INTR is used for all 3 queues, 1 INTR for queue errors
3038c2ecf20Sopenharmony_ci	 * 1 INTR for notification area
3048c2ecf20Sopenharmony_ci	 */
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	if (fnic->rq_count >= 1 &&
3078c2ecf20Sopenharmony_ci	    fnic->raw_wq_count >= 1 &&
3088c2ecf20Sopenharmony_ci	    fnic->wq_copy_count >= 1 &&
3098c2ecf20Sopenharmony_ci	    fnic->cq_count >= 3 &&
3108c2ecf20Sopenharmony_ci	    fnic->intr_count >= 3) {
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci		fnic->rq_count = 1;
3138c2ecf20Sopenharmony_ci		fnic->raw_wq_count = 1;
3148c2ecf20Sopenharmony_ci		fnic->wq_copy_count = 1;
3158c2ecf20Sopenharmony_ci		fnic->cq_count = 3;
3168c2ecf20Sopenharmony_ci		fnic->intr_count = 3;
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		FNIC_ISR_DBG(KERN_DEBUG, fnic->lport->host,
3198c2ecf20Sopenharmony_ci			     "Using Legacy Interrupts\n");
3208c2ecf20Sopenharmony_ci		vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci		return 0;
3238c2ecf20Sopenharmony_ci	}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_UNKNOWN);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	return -EINVAL;
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_civoid fnic_clear_intr_mode(struct fnic *fnic)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	pci_free_irq_vectors(fnic->pdev);
3338c2ecf20Sopenharmony_ci	vnic_dev_set_intr_mode(fnic->vdev, VNIC_DEV_INTR_MODE_INTX);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
336