162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
462306a36Sopenharmony_ci * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include <linux/errno.h>
762306a36Sopenharmony_ci#include <linux/types.h>
862306a36Sopenharmony_ci#include <linux/pci.h>
962306a36Sopenharmony_ci#include "wq_enet_desc.h"
1062306a36Sopenharmony_ci#include "rq_enet_desc.h"
1162306a36Sopenharmony_ci#include "cq_enet_desc.h"
1262306a36Sopenharmony_ci#include "vnic_resource.h"
1362306a36Sopenharmony_ci#include "vnic_dev.h"
1462306a36Sopenharmony_ci#include "vnic_wq.h"
1562306a36Sopenharmony_ci#include "vnic_rq.h"
1662306a36Sopenharmony_ci#include "vnic_cq.h"
1762306a36Sopenharmony_ci#include "vnic_intr.h"
1862306a36Sopenharmony_ci#include "vnic_stats.h"
1962306a36Sopenharmony_ci#include "vnic_nic.h"
2062306a36Sopenharmony_ci#include "fnic.h"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciint fnic_get_vnic_config(struct fnic *fnic)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	struct vnic_fc_config *c = &fnic->config;
2562306a36Sopenharmony_ci	int err;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#define GET_CONFIG(m) \
2862306a36Sopenharmony_ci	do { \
2962306a36Sopenharmony_ci		err = vnic_dev_spec(fnic->vdev, \
3062306a36Sopenharmony_ci				    offsetof(struct vnic_fc_config, m), \
3162306a36Sopenharmony_ci				    sizeof(c->m), &c->m); \
3262306a36Sopenharmony_ci		if (err) { \
3362306a36Sopenharmony_ci			shost_printk(KERN_ERR, fnic->lport->host, \
3462306a36Sopenharmony_ci				     "Error getting %s, %d\n", #m, \
3562306a36Sopenharmony_ci				     err); \
3662306a36Sopenharmony_ci			return err; \
3762306a36Sopenharmony_ci		} \
3862306a36Sopenharmony_ci	} while (0);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	GET_CONFIG(node_wwn);
4162306a36Sopenharmony_ci	GET_CONFIG(port_wwn);
4262306a36Sopenharmony_ci	GET_CONFIG(wq_enet_desc_count);
4362306a36Sopenharmony_ci	GET_CONFIG(wq_copy_desc_count);
4462306a36Sopenharmony_ci	GET_CONFIG(rq_desc_count);
4562306a36Sopenharmony_ci	GET_CONFIG(maxdatafieldsize);
4662306a36Sopenharmony_ci	GET_CONFIG(ed_tov);
4762306a36Sopenharmony_ci	GET_CONFIG(ra_tov);
4862306a36Sopenharmony_ci	GET_CONFIG(intr_timer);
4962306a36Sopenharmony_ci	GET_CONFIG(intr_timer_type);
5062306a36Sopenharmony_ci	GET_CONFIG(flags);
5162306a36Sopenharmony_ci	GET_CONFIG(flogi_retries);
5262306a36Sopenharmony_ci	GET_CONFIG(flogi_timeout);
5362306a36Sopenharmony_ci	GET_CONFIG(plogi_retries);
5462306a36Sopenharmony_ci	GET_CONFIG(plogi_timeout);
5562306a36Sopenharmony_ci	GET_CONFIG(io_throttle_count);
5662306a36Sopenharmony_ci	GET_CONFIG(link_down_timeout);
5762306a36Sopenharmony_ci	GET_CONFIG(port_down_timeout);
5862306a36Sopenharmony_ci	GET_CONFIG(port_down_io_retries);
5962306a36Sopenharmony_ci	GET_CONFIG(luns_per_tgt);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	c->wq_enet_desc_count =
6262306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_WQ_DESCS_MAX,
6362306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_WQ_DESCS_MIN,
6462306a36Sopenharmony_ci			    c->wq_enet_desc_count));
6562306a36Sopenharmony_ci	c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	c->wq_copy_desc_count =
6862306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MAX,
6962306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MIN,
7062306a36Sopenharmony_ci			    c->wq_copy_desc_count));
7162306a36Sopenharmony_ci	c->wq_copy_desc_count = ALIGN(c->wq_copy_desc_count, 16);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	c->rq_desc_count =
7462306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_RQ_DESCS_MAX,
7562306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_RQ_DESCS_MIN,
7662306a36Sopenharmony_ci			    c->rq_desc_count));
7762306a36Sopenharmony_ci	c->rq_desc_count = ALIGN(c->rq_desc_count, 16);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	c->maxdatafieldsize =
8062306a36Sopenharmony_ci		min_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MAX,
8162306a36Sopenharmony_ci		      max_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MIN,
8262306a36Sopenharmony_ci			    c->maxdatafieldsize));
8362306a36Sopenharmony_ci	c->ed_tov =
8462306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_EDTOV_MAX,
8562306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_EDTOV_MIN,
8662306a36Sopenharmony_ci			    c->ed_tov));
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	c->ra_tov =
8962306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_RATOV_MAX,
9062306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_RATOV_MIN,
9162306a36Sopenharmony_ci			    c->ra_tov));
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	c->flogi_retries =
9462306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_FLOGI_RETRIES_MAX, c->flogi_retries);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	c->flogi_timeout =
9762306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MAX,
9862306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MIN,
9962306a36Sopenharmony_ci			    c->flogi_timeout));
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	c->plogi_retries =
10262306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_PLOGI_RETRIES_MAX, c->plogi_retries);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	c->plogi_timeout =
10562306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MAX,
10662306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MIN,
10762306a36Sopenharmony_ci			    c->plogi_timeout));
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	c->io_throttle_count =
11062306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MAX,
11162306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MIN,
11262306a36Sopenharmony_ci			    c->io_throttle_count));
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	c->link_down_timeout =
11562306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_LINK_DOWN_TIMEOUT_MAX,
11662306a36Sopenharmony_ci		      c->link_down_timeout);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	c->port_down_timeout =
11962306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_PORT_DOWN_TIMEOUT_MAX,
12062306a36Sopenharmony_ci		      c->port_down_timeout);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	c->port_down_io_retries =
12362306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX,
12462306a36Sopenharmony_ci		      c->port_down_io_retries);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	c->luns_per_tgt =
12762306a36Sopenharmony_ci		min_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MAX,
12862306a36Sopenharmony_ci		      max_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MIN,
12962306a36Sopenharmony_ci			    c->luns_per_tgt));
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
13262306a36Sopenharmony_ci	c->intr_timer_type = c->intr_timer_type;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
13562306a36Sopenharmony_ci		     "vNIC MAC addr %pM "
13662306a36Sopenharmony_ci		     "wq/wq_copy/rq %d/%d/%d\n",
13762306a36Sopenharmony_ci		     fnic->ctlr.ctl_src_addr,
13862306a36Sopenharmony_ci		     c->wq_enet_desc_count, c->wq_copy_desc_count,
13962306a36Sopenharmony_ci		     c->rq_desc_count);
14062306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
14162306a36Sopenharmony_ci		     "vNIC node wwn %llx port wwn %llx\n",
14262306a36Sopenharmony_ci		     c->node_wwn, c->port_wwn);
14362306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
14462306a36Sopenharmony_ci		     "vNIC ed_tov %d ra_tov %d\n",
14562306a36Sopenharmony_ci		     c->ed_tov, c->ra_tov);
14662306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
14762306a36Sopenharmony_ci		     "vNIC mtu %d intr timer %d\n",
14862306a36Sopenharmony_ci		     c->maxdatafieldsize, c->intr_timer);
14962306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
15062306a36Sopenharmony_ci		     "vNIC flags 0x%x luns per tgt %d\n",
15162306a36Sopenharmony_ci		     c->flags, c->luns_per_tgt);
15262306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
15362306a36Sopenharmony_ci		     "vNIC flogi_retries %d flogi timeout %d\n",
15462306a36Sopenharmony_ci		     c->flogi_retries, c->flogi_timeout);
15562306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
15662306a36Sopenharmony_ci		     "vNIC plogi retries %d plogi timeout %d\n",
15762306a36Sopenharmony_ci		     c->plogi_retries, c->plogi_timeout);
15862306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
15962306a36Sopenharmony_ci		     "vNIC io throttle count %d link dn timeout %d\n",
16062306a36Sopenharmony_ci		     c->io_throttle_count, c->link_down_timeout);
16162306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host,
16262306a36Sopenharmony_ci		     "vNIC port dn io retries %d port dn timeout %d\n",
16362306a36Sopenharmony_ci		     c->port_down_io_retries, c->port_down_timeout);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	return 0;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ciint fnic_set_nic_config(struct fnic *fnic, u8 rss_default_cpu,
16962306a36Sopenharmony_ci			u8 rss_hash_type,
17062306a36Sopenharmony_ci			u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable,
17162306a36Sopenharmony_ci			u8 tso_ipid_split_en, u8 ig_vlan_strip_en)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	u64 a0, a1;
17462306a36Sopenharmony_ci	u32 nic_cfg;
17562306a36Sopenharmony_ci	int wait = 1000;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
17862306a36Sopenharmony_ci		rss_hash_type, rss_hash_bits, rss_base_cpu,
17962306a36Sopenharmony_ci		rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	a0 = nic_cfg;
18262306a36Sopenharmony_ci	a1 = 0;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	return vnic_dev_cmd(fnic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
18562306a36Sopenharmony_ci}
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_civoid fnic_get_res_counts(struct fnic *fnic)
18862306a36Sopenharmony_ci{
18962306a36Sopenharmony_ci	fnic->wq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_WQ);
19062306a36Sopenharmony_ci	fnic->raw_wq_count = fnic->wq_count - 1;
19162306a36Sopenharmony_ci	fnic->wq_copy_count = fnic->wq_count - fnic->raw_wq_count;
19262306a36Sopenharmony_ci	fnic->rq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_RQ);
19362306a36Sopenharmony_ci	fnic->cq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_CQ);
19462306a36Sopenharmony_ci	fnic->intr_count = vnic_dev_get_res_count(fnic->vdev,
19562306a36Sopenharmony_ci		RES_TYPE_INTR_CTRL);
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_civoid fnic_free_vnic_resources(struct fnic *fnic)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	unsigned int i;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	for (i = 0; i < fnic->raw_wq_count; i++)
20362306a36Sopenharmony_ci		vnic_wq_free(&fnic->wq[i]);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	for (i = 0; i < fnic->wq_copy_count; i++)
20662306a36Sopenharmony_ci		vnic_wq_copy_free(&fnic->wq_copy[i]);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	for (i = 0; i < fnic->rq_count; i++)
20962306a36Sopenharmony_ci		vnic_rq_free(&fnic->rq[i]);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	for (i = 0; i < fnic->cq_count; i++)
21262306a36Sopenharmony_ci		vnic_cq_free(&fnic->cq[i]);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	for (i = 0; i < fnic->intr_count; i++)
21562306a36Sopenharmony_ci		vnic_intr_free(&fnic->intr[i]);
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ciint fnic_alloc_vnic_resources(struct fnic *fnic)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	enum vnic_dev_intr_mode intr_mode;
22162306a36Sopenharmony_ci	unsigned int mask_on_assertion;
22262306a36Sopenharmony_ci	unsigned int interrupt_offset;
22362306a36Sopenharmony_ci	unsigned int error_interrupt_enable;
22462306a36Sopenharmony_ci	unsigned int error_interrupt_offset;
22562306a36Sopenharmony_ci	unsigned int i, cq_index;
22662306a36Sopenharmony_ci	unsigned int wq_copy_cq_desc_count;
22762306a36Sopenharmony_ci	int err;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	intr_mode = vnic_dev_get_intr_mode(fnic->vdev);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host, "vNIC interrupt mode: %s\n",
23262306a36Sopenharmony_ci		     intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :
23362306a36Sopenharmony_ci		     intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :
23462306a36Sopenharmony_ci		     intr_mode == VNIC_DEV_INTR_MODE_MSIX ?
23562306a36Sopenharmony_ci		     "MSI-X" : "unknown");
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	shost_printk(KERN_INFO, fnic->lport->host, "vNIC resources avail: "
23862306a36Sopenharmony_ci		     "wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
23962306a36Sopenharmony_ci		     fnic->wq_count, fnic->wq_copy_count, fnic->raw_wq_count,
24062306a36Sopenharmony_ci		     fnic->rq_count, fnic->cq_count, fnic->intr_count);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	/* Allocate Raw WQ used for FCS frames */
24362306a36Sopenharmony_ci	for (i = 0; i < fnic->raw_wq_count; i++) {
24462306a36Sopenharmony_ci		err = vnic_wq_alloc(fnic->vdev, &fnic->wq[i], i,
24562306a36Sopenharmony_ci			fnic->config.wq_enet_desc_count,
24662306a36Sopenharmony_ci			sizeof(struct wq_enet_desc));
24762306a36Sopenharmony_ci		if (err)
24862306a36Sopenharmony_ci			goto err_out_cleanup;
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	/* Allocate Copy WQs used for SCSI IOs */
25262306a36Sopenharmony_ci	for (i = 0; i < fnic->wq_copy_count; i++) {
25362306a36Sopenharmony_ci		err = vnic_wq_copy_alloc(fnic->vdev, &fnic->wq_copy[i],
25462306a36Sopenharmony_ci			(fnic->raw_wq_count + i),
25562306a36Sopenharmony_ci			fnic->config.wq_copy_desc_count,
25662306a36Sopenharmony_ci			sizeof(struct fcpio_host_req));
25762306a36Sopenharmony_ci		if (err)
25862306a36Sopenharmony_ci			goto err_out_cleanup;
25962306a36Sopenharmony_ci	}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	/* RQ for receiving FCS frames */
26262306a36Sopenharmony_ci	for (i = 0; i < fnic->rq_count; i++) {
26362306a36Sopenharmony_ci		err = vnic_rq_alloc(fnic->vdev, &fnic->rq[i], i,
26462306a36Sopenharmony_ci			fnic->config.rq_desc_count,
26562306a36Sopenharmony_ci			sizeof(struct rq_enet_desc));
26662306a36Sopenharmony_ci		if (err)
26762306a36Sopenharmony_ci			goto err_out_cleanup;
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/* CQ for each RQ */
27162306a36Sopenharmony_ci	for (i = 0; i < fnic->rq_count; i++) {
27262306a36Sopenharmony_ci		cq_index = i;
27362306a36Sopenharmony_ci		err = vnic_cq_alloc(fnic->vdev,
27462306a36Sopenharmony_ci			&fnic->cq[cq_index], cq_index,
27562306a36Sopenharmony_ci			fnic->config.rq_desc_count,
27662306a36Sopenharmony_ci			sizeof(struct cq_enet_rq_desc));
27762306a36Sopenharmony_ci		if (err)
27862306a36Sopenharmony_ci			goto err_out_cleanup;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* CQ for each WQ */
28262306a36Sopenharmony_ci	for (i = 0; i < fnic->raw_wq_count; i++) {
28362306a36Sopenharmony_ci		cq_index = fnic->rq_count + i;
28462306a36Sopenharmony_ci		err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index], cq_index,
28562306a36Sopenharmony_ci			fnic->config.wq_enet_desc_count,
28662306a36Sopenharmony_ci			sizeof(struct cq_enet_wq_desc));
28762306a36Sopenharmony_ci		if (err)
28862306a36Sopenharmony_ci			goto err_out_cleanup;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	/* CQ for each COPY WQ */
29262306a36Sopenharmony_ci	wq_copy_cq_desc_count = (fnic->config.wq_copy_desc_count * 3);
29362306a36Sopenharmony_ci	for (i = 0; i < fnic->wq_copy_count; i++) {
29462306a36Sopenharmony_ci		cq_index = fnic->raw_wq_count + fnic->rq_count + i;
29562306a36Sopenharmony_ci		err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index],
29662306a36Sopenharmony_ci			cq_index,
29762306a36Sopenharmony_ci			wq_copy_cq_desc_count,
29862306a36Sopenharmony_ci			sizeof(struct fcpio_fw_req));
29962306a36Sopenharmony_ci		if (err)
30062306a36Sopenharmony_ci			goto err_out_cleanup;
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	for (i = 0; i < fnic->intr_count; i++) {
30462306a36Sopenharmony_ci		err = vnic_intr_alloc(fnic->vdev, &fnic->intr[i], i);
30562306a36Sopenharmony_ci		if (err)
30662306a36Sopenharmony_ci			goto err_out_cleanup;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	fnic->legacy_pba = vnic_dev_get_res(fnic->vdev,
31062306a36Sopenharmony_ci				RES_TYPE_INTR_PBA_LEGACY, 0);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	if (!fnic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {
31362306a36Sopenharmony_ci		shost_printk(KERN_ERR, fnic->lport->host,
31462306a36Sopenharmony_ci			     "Failed to hook legacy pba resource\n");
31562306a36Sopenharmony_ci		err = -ENODEV;
31662306a36Sopenharmony_ci		goto err_out_cleanup;
31762306a36Sopenharmony_ci	}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/*
32062306a36Sopenharmony_ci	 * Init RQ/WQ resources.
32162306a36Sopenharmony_ci	 *
32262306a36Sopenharmony_ci	 * RQ[0 to n-1] point to CQ[0 to n-1]
32362306a36Sopenharmony_ci	 * WQ[0 to m-1] point to CQ[n to n+m-1]
32462306a36Sopenharmony_ci	 * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1]
32562306a36Sopenharmony_ci	 *
32662306a36Sopenharmony_ci	 * Note for copy wq we always initialize with cq_index = 0
32762306a36Sopenharmony_ci	 *
32862306a36Sopenharmony_ci	 * Error interrupt is not enabled for MSI.
32962306a36Sopenharmony_ci	 */
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	switch (intr_mode) {
33262306a36Sopenharmony_ci	case VNIC_DEV_INTR_MODE_INTX:
33362306a36Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSIX:
33462306a36Sopenharmony_ci		error_interrupt_enable = 1;
33562306a36Sopenharmony_ci		error_interrupt_offset = fnic->err_intr_offset;
33662306a36Sopenharmony_ci		break;
33762306a36Sopenharmony_ci	default:
33862306a36Sopenharmony_ci		error_interrupt_enable = 0;
33962306a36Sopenharmony_ci		error_interrupt_offset = 0;
34062306a36Sopenharmony_ci		break;
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	for (i = 0; i < fnic->rq_count; i++) {
34462306a36Sopenharmony_ci		cq_index = i;
34562306a36Sopenharmony_ci		vnic_rq_init(&fnic->rq[i],
34662306a36Sopenharmony_ci			     cq_index,
34762306a36Sopenharmony_ci			     error_interrupt_enable,
34862306a36Sopenharmony_ci			     error_interrupt_offset);
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	for (i = 0; i < fnic->raw_wq_count; i++) {
35262306a36Sopenharmony_ci		cq_index = i + fnic->rq_count;
35362306a36Sopenharmony_ci		vnic_wq_init(&fnic->wq[i],
35462306a36Sopenharmony_ci			     cq_index,
35562306a36Sopenharmony_ci			     error_interrupt_enable,
35662306a36Sopenharmony_ci			     error_interrupt_offset);
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	for (i = 0; i < fnic->wq_copy_count; i++) {
36062306a36Sopenharmony_ci		vnic_wq_copy_init(&fnic->wq_copy[i],
36162306a36Sopenharmony_ci				  0 /* cq_index 0 - always */,
36262306a36Sopenharmony_ci				  error_interrupt_enable,
36362306a36Sopenharmony_ci				  error_interrupt_offset);
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	for (i = 0; i < fnic->cq_count; i++) {
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci		switch (intr_mode) {
36962306a36Sopenharmony_ci		case VNIC_DEV_INTR_MODE_MSIX:
37062306a36Sopenharmony_ci			interrupt_offset = i;
37162306a36Sopenharmony_ci			break;
37262306a36Sopenharmony_ci		default:
37362306a36Sopenharmony_ci			interrupt_offset = 0;
37462306a36Sopenharmony_ci			break;
37562306a36Sopenharmony_ci		}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci		vnic_cq_init(&fnic->cq[i],
37862306a36Sopenharmony_ci			0 /* flow_control_enable */,
37962306a36Sopenharmony_ci			1 /* color_enable */,
38062306a36Sopenharmony_ci			0 /* cq_head */,
38162306a36Sopenharmony_ci			0 /* cq_tail */,
38262306a36Sopenharmony_ci			1 /* cq_tail_color */,
38362306a36Sopenharmony_ci			1 /* interrupt_enable */,
38462306a36Sopenharmony_ci			1 /* cq_entry_enable */,
38562306a36Sopenharmony_ci			0 /* cq_message_enable */,
38662306a36Sopenharmony_ci			interrupt_offset,
38762306a36Sopenharmony_ci			0 /* cq_message_addr */);
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	/*
39162306a36Sopenharmony_ci	 * Init INTR resources
39262306a36Sopenharmony_ci	 *
39362306a36Sopenharmony_ci	 * mask_on_assertion is not used for INTx due to the level-
39462306a36Sopenharmony_ci	 * triggered nature of INTx
39562306a36Sopenharmony_ci	 */
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	switch (intr_mode) {
39862306a36Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSI:
39962306a36Sopenharmony_ci	case VNIC_DEV_INTR_MODE_MSIX:
40062306a36Sopenharmony_ci		mask_on_assertion = 1;
40162306a36Sopenharmony_ci		break;
40262306a36Sopenharmony_ci	default:
40362306a36Sopenharmony_ci		mask_on_assertion = 0;
40462306a36Sopenharmony_ci		break;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	for (i = 0; i < fnic->intr_count; i++) {
40862306a36Sopenharmony_ci		vnic_intr_init(&fnic->intr[i],
40962306a36Sopenharmony_ci			fnic->config.intr_timer,
41062306a36Sopenharmony_ci			fnic->config.intr_timer_type,
41162306a36Sopenharmony_ci			mask_on_assertion);
41262306a36Sopenharmony_ci	}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	/* init the stats memory by making the first call here */
41562306a36Sopenharmony_ci	err = vnic_dev_stats_dump(fnic->vdev, &fnic->stats);
41662306a36Sopenharmony_ci	if (err) {
41762306a36Sopenharmony_ci		shost_printk(KERN_ERR, fnic->lport->host,
41862306a36Sopenharmony_ci			     "vnic_dev_stats_dump failed - x%x\n", err);
41962306a36Sopenharmony_ci		goto err_out_cleanup;
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	/* Clear LIF stats */
42362306a36Sopenharmony_ci	vnic_dev_stats_clear(fnic->vdev);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	return 0;
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cierr_out_cleanup:
42862306a36Sopenharmony_ci	fnic_free_vnic_resources(fnic);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	return err;
43162306a36Sopenharmony_ci}
432