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