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/errno.h> 198c2ecf20Sopenharmony_ci#include <linux/types.h> 208c2ecf20Sopenharmony_ci#include <linux/pci.h> 218c2ecf20Sopenharmony_ci#include "wq_enet_desc.h" 228c2ecf20Sopenharmony_ci#include "rq_enet_desc.h" 238c2ecf20Sopenharmony_ci#include "cq_enet_desc.h" 248c2ecf20Sopenharmony_ci#include "vnic_resource.h" 258c2ecf20Sopenharmony_ci#include "vnic_dev.h" 268c2ecf20Sopenharmony_ci#include "vnic_wq.h" 278c2ecf20Sopenharmony_ci#include "vnic_rq.h" 288c2ecf20Sopenharmony_ci#include "vnic_cq.h" 298c2ecf20Sopenharmony_ci#include "vnic_intr.h" 308c2ecf20Sopenharmony_ci#include "vnic_stats.h" 318c2ecf20Sopenharmony_ci#include "vnic_nic.h" 328c2ecf20Sopenharmony_ci#include "fnic.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciint fnic_get_vnic_config(struct fnic *fnic) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci struct vnic_fc_config *c = &fnic->config; 378c2ecf20Sopenharmony_ci int err; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define GET_CONFIG(m) \ 408c2ecf20Sopenharmony_ci do { \ 418c2ecf20Sopenharmony_ci err = vnic_dev_spec(fnic->vdev, \ 428c2ecf20Sopenharmony_ci offsetof(struct vnic_fc_config, m), \ 438c2ecf20Sopenharmony_ci sizeof(c->m), &c->m); \ 448c2ecf20Sopenharmony_ci if (err) { \ 458c2ecf20Sopenharmony_ci shost_printk(KERN_ERR, fnic->lport->host, \ 468c2ecf20Sopenharmony_ci "Error getting %s, %d\n", #m, \ 478c2ecf20Sopenharmony_ci err); \ 488c2ecf20Sopenharmony_ci return err; \ 498c2ecf20Sopenharmony_ci } \ 508c2ecf20Sopenharmony_ci } while (0); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci GET_CONFIG(node_wwn); 538c2ecf20Sopenharmony_ci GET_CONFIG(port_wwn); 548c2ecf20Sopenharmony_ci GET_CONFIG(wq_enet_desc_count); 558c2ecf20Sopenharmony_ci GET_CONFIG(wq_copy_desc_count); 568c2ecf20Sopenharmony_ci GET_CONFIG(rq_desc_count); 578c2ecf20Sopenharmony_ci GET_CONFIG(maxdatafieldsize); 588c2ecf20Sopenharmony_ci GET_CONFIG(ed_tov); 598c2ecf20Sopenharmony_ci GET_CONFIG(ra_tov); 608c2ecf20Sopenharmony_ci GET_CONFIG(intr_timer); 618c2ecf20Sopenharmony_ci GET_CONFIG(intr_timer_type); 628c2ecf20Sopenharmony_ci GET_CONFIG(flags); 638c2ecf20Sopenharmony_ci GET_CONFIG(flogi_retries); 648c2ecf20Sopenharmony_ci GET_CONFIG(flogi_timeout); 658c2ecf20Sopenharmony_ci GET_CONFIG(plogi_retries); 668c2ecf20Sopenharmony_ci GET_CONFIG(plogi_timeout); 678c2ecf20Sopenharmony_ci GET_CONFIG(io_throttle_count); 688c2ecf20Sopenharmony_ci GET_CONFIG(link_down_timeout); 698c2ecf20Sopenharmony_ci GET_CONFIG(port_down_timeout); 708c2ecf20Sopenharmony_ci GET_CONFIG(port_down_io_retries); 718c2ecf20Sopenharmony_ci GET_CONFIG(luns_per_tgt); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci c->wq_enet_desc_count = 748c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_WQ_DESCS_MAX, 758c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_WQ_DESCS_MIN, 768c2ecf20Sopenharmony_ci c->wq_enet_desc_count)); 778c2ecf20Sopenharmony_ci c->wq_enet_desc_count = ALIGN(c->wq_enet_desc_count, 16); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci c->wq_copy_desc_count = 808c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MAX, 818c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_WQ_COPY_DESCS_MIN, 828c2ecf20Sopenharmony_ci c->wq_copy_desc_count)); 838c2ecf20Sopenharmony_ci c->wq_copy_desc_count = ALIGN(c->wq_copy_desc_count, 16); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci c->rq_desc_count = 868c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_RQ_DESCS_MAX, 878c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_RQ_DESCS_MIN, 888c2ecf20Sopenharmony_ci c->rq_desc_count)); 898c2ecf20Sopenharmony_ci c->rq_desc_count = ALIGN(c->rq_desc_count, 16); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci c->maxdatafieldsize = 928c2ecf20Sopenharmony_ci min_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MAX, 938c2ecf20Sopenharmony_ci max_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MIN, 948c2ecf20Sopenharmony_ci c->maxdatafieldsize)); 958c2ecf20Sopenharmony_ci c->ed_tov = 968c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_EDTOV_MAX, 978c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_EDTOV_MIN, 988c2ecf20Sopenharmony_ci c->ed_tov)); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci c->ra_tov = 1018c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_RATOV_MAX, 1028c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_RATOV_MIN, 1038c2ecf20Sopenharmony_ci c->ra_tov)); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci c->flogi_retries = 1068c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_FLOGI_RETRIES_MAX, c->flogi_retries); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci c->flogi_timeout = 1098c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MAX, 1108c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MIN, 1118c2ecf20Sopenharmony_ci c->flogi_timeout)); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci c->plogi_retries = 1148c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_PLOGI_RETRIES_MAX, c->plogi_retries); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci c->plogi_timeout = 1178c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MAX, 1188c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MIN, 1198c2ecf20Sopenharmony_ci c->plogi_timeout)); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci c->io_throttle_count = 1228c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MAX, 1238c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_IO_THROTTLE_COUNT_MIN, 1248c2ecf20Sopenharmony_ci c->io_throttle_count)); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci c->link_down_timeout = 1278c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_LINK_DOWN_TIMEOUT_MAX, 1288c2ecf20Sopenharmony_ci c->link_down_timeout); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci c->port_down_timeout = 1318c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_PORT_DOWN_TIMEOUT_MAX, 1328c2ecf20Sopenharmony_ci c->port_down_timeout); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci c->port_down_io_retries = 1358c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX, 1368c2ecf20Sopenharmony_ci c->port_down_io_retries); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci c->luns_per_tgt = 1398c2ecf20Sopenharmony_ci min_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MAX, 1408c2ecf20Sopenharmony_ci max_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MIN, 1418c2ecf20Sopenharmony_ci c->luns_per_tgt)); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer); 1448c2ecf20Sopenharmony_ci c->intr_timer_type = c->intr_timer_type; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1478c2ecf20Sopenharmony_ci "vNIC MAC addr %pM " 1488c2ecf20Sopenharmony_ci "wq/wq_copy/rq %d/%d/%d\n", 1498c2ecf20Sopenharmony_ci fnic->ctlr.ctl_src_addr, 1508c2ecf20Sopenharmony_ci c->wq_enet_desc_count, c->wq_copy_desc_count, 1518c2ecf20Sopenharmony_ci c->rq_desc_count); 1528c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1538c2ecf20Sopenharmony_ci "vNIC node wwn %llx port wwn %llx\n", 1548c2ecf20Sopenharmony_ci c->node_wwn, c->port_wwn); 1558c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1568c2ecf20Sopenharmony_ci "vNIC ed_tov %d ra_tov %d\n", 1578c2ecf20Sopenharmony_ci c->ed_tov, c->ra_tov); 1588c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1598c2ecf20Sopenharmony_ci "vNIC mtu %d intr timer %d\n", 1608c2ecf20Sopenharmony_ci c->maxdatafieldsize, c->intr_timer); 1618c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1628c2ecf20Sopenharmony_ci "vNIC flags 0x%x luns per tgt %d\n", 1638c2ecf20Sopenharmony_ci c->flags, c->luns_per_tgt); 1648c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1658c2ecf20Sopenharmony_ci "vNIC flogi_retries %d flogi timeout %d\n", 1668c2ecf20Sopenharmony_ci c->flogi_retries, c->flogi_timeout); 1678c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1688c2ecf20Sopenharmony_ci "vNIC plogi retries %d plogi timeout %d\n", 1698c2ecf20Sopenharmony_ci c->plogi_retries, c->plogi_timeout); 1708c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1718c2ecf20Sopenharmony_ci "vNIC io throttle count %d link dn timeout %d\n", 1728c2ecf20Sopenharmony_ci c->io_throttle_count, c->link_down_timeout); 1738c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, 1748c2ecf20Sopenharmony_ci "vNIC port dn io retries %d port dn timeout %d\n", 1758c2ecf20Sopenharmony_ci c->port_down_io_retries, c->port_down_timeout); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return 0; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ciint fnic_set_nic_config(struct fnic *fnic, u8 rss_default_cpu, 1818c2ecf20Sopenharmony_ci u8 rss_hash_type, 1828c2ecf20Sopenharmony_ci u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, 1838c2ecf20Sopenharmony_ci u8 tso_ipid_split_en, u8 ig_vlan_strip_en) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci u64 a0, a1; 1868c2ecf20Sopenharmony_ci u32 nic_cfg; 1878c2ecf20Sopenharmony_ci int wait = 1000; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci vnic_set_nic_cfg(&nic_cfg, rss_default_cpu, 1908c2ecf20Sopenharmony_ci rss_hash_type, rss_hash_bits, rss_base_cpu, 1918c2ecf20Sopenharmony_ci rss_enable, tso_ipid_split_en, ig_vlan_strip_en); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci a0 = nic_cfg; 1948c2ecf20Sopenharmony_ci a1 = 0; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci return vnic_dev_cmd(fnic->vdev, CMD_NIC_CFG, &a0, &a1, wait); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_civoid fnic_get_res_counts(struct fnic *fnic) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci fnic->wq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_WQ); 2028c2ecf20Sopenharmony_ci fnic->raw_wq_count = fnic->wq_count - 1; 2038c2ecf20Sopenharmony_ci fnic->wq_copy_count = fnic->wq_count - fnic->raw_wq_count; 2048c2ecf20Sopenharmony_ci fnic->rq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_RQ); 2058c2ecf20Sopenharmony_ci fnic->cq_count = vnic_dev_get_res_count(fnic->vdev, RES_TYPE_CQ); 2068c2ecf20Sopenharmony_ci fnic->intr_count = vnic_dev_get_res_count(fnic->vdev, 2078c2ecf20Sopenharmony_ci RES_TYPE_INTR_CTRL); 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_civoid fnic_free_vnic_resources(struct fnic *fnic) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci unsigned int i; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci for (i = 0; i < fnic->raw_wq_count; i++) 2158c2ecf20Sopenharmony_ci vnic_wq_free(&fnic->wq[i]); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci for (i = 0; i < fnic->wq_copy_count; i++) 2188c2ecf20Sopenharmony_ci vnic_wq_copy_free(&fnic->wq_copy[i]); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci for (i = 0; i < fnic->rq_count; i++) 2218c2ecf20Sopenharmony_ci vnic_rq_free(&fnic->rq[i]); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci for (i = 0; i < fnic->cq_count; i++) 2248c2ecf20Sopenharmony_ci vnic_cq_free(&fnic->cq[i]); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci for (i = 0; i < fnic->intr_count; i++) 2278c2ecf20Sopenharmony_ci vnic_intr_free(&fnic->intr[i]); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ciint fnic_alloc_vnic_resources(struct fnic *fnic) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci enum vnic_dev_intr_mode intr_mode; 2338c2ecf20Sopenharmony_ci unsigned int mask_on_assertion; 2348c2ecf20Sopenharmony_ci unsigned int interrupt_offset; 2358c2ecf20Sopenharmony_ci unsigned int error_interrupt_enable; 2368c2ecf20Sopenharmony_ci unsigned int error_interrupt_offset; 2378c2ecf20Sopenharmony_ci unsigned int i, cq_index; 2388c2ecf20Sopenharmony_ci unsigned int wq_copy_cq_desc_count; 2398c2ecf20Sopenharmony_ci int err; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci intr_mode = vnic_dev_get_intr_mode(fnic->vdev); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, "vNIC interrupt mode: %s\n", 2448c2ecf20Sopenharmony_ci intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" : 2458c2ecf20Sopenharmony_ci intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" : 2468c2ecf20Sopenharmony_ci intr_mode == VNIC_DEV_INTR_MODE_MSIX ? 2478c2ecf20Sopenharmony_ci "MSI-X" : "unknown"); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci shost_printk(KERN_INFO, fnic->lport->host, "vNIC resources avail: " 2508c2ecf20Sopenharmony_ci "wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n", 2518c2ecf20Sopenharmony_ci fnic->wq_count, fnic->wq_copy_count, fnic->raw_wq_count, 2528c2ecf20Sopenharmony_ci fnic->rq_count, fnic->cq_count, fnic->intr_count); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* Allocate Raw WQ used for FCS frames */ 2558c2ecf20Sopenharmony_ci for (i = 0; i < fnic->raw_wq_count; i++) { 2568c2ecf20Sopenharmony_ci err = vnic_wq_alloc(fnic->vdev, &fnic->wq[i], i, 2578c2ecf20Sopenharmony_ci fnic->config.wq_enet_desc_count, 2588c2ecf20Sopenharmony_ci sizeof(struct wq_enet_desc)); 2598c2ecf20Sopenharmony_ci if (err) 2608c2ecf20Sopenharmony_ci goto err_out_cleanup; 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* Allocate Copy WQs used for SCSI IOs */ 2648c2ecf20Sopenharmony_ci for (i = 0; i < fnic->wq_copy_count; i++) { 2658c2ecf20Sopenharmony_ci err = vnic_wq_copy_alloc(fnic->vdev, &fnic->wq_copy[i], 2668c2ecf20Sopenharmony_ci (fnic->raw_wq_count + i), 2678c2ecf20Sopenharmony_ci fnic->config.wq_copy_desc_count, 2688c2ecf20Sopenharmony_ci sizeof(struct fcpio_host_req)); 2698c2ecf20Sopenharmony_ci if (err) 2708c2ecf20Sopenharmony_ci goto err_out_cleanup; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* RQ for receiving FCS frames */ 2748c2ecf20Sopenharmony_ci for (i = 0; i < fnic->rq_count; i++) { 2758c2ecf20Sopenharmony_ci err = vnic_rq_alloc(fnic->vdev, &fnic->rq[i], i, 2768c2ecf20Sopenharmony_ci fnic->config.rq_desc_count, 2778c2ecf20Sopenharmony_ci sizeof(struct rq_enet_desc)); 2788c2ecf20Sopenharmony_ci if (err) 2798c2ecf20Sopenharmony_ci goto err_out_cleanup; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* CQ for each RQ */ 2838c2ecf20Sopenharmony_ci for (i = 0; i < fnic->rq_count; i++) { 2848c2ecf20Sopenharmony_ci cq_index = i; 2858c2ecf20Sopenharmony_ci err = vnic_cq_alloc(fnic->vdev, 2868c2ecf20Sopenharmony_ci &fnic->cq[cq_index], cq_index, 2878c2ecf20Sopenharmony_ci fnic->config.rq_desc_count, 2888c2ecf20Sopenharmony_ci sizeof(struct cq_enet_rq_desc)); 2898c2ecf20Sopenharmony_ci if (err) 2908c2ecf20Sopenharmony_ci goto err_out_cleanup; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* CQ for each WQ */ 2948c2ecf20Sopenharmony_ci for (i = 0; i < fnic->raw_wq_count; i++) { 2958c2ecf20Sopenharmony_ci cq_index = fnic->rq_count + i; 2968c2ecf20Sopenharmony_ci err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index], cq_index, 2978c2ecf20Sopenharmony_ci fnic->config.wq_enet_desc_count, 2988c2ecf20Sopenharmony_ci sizeof(struct cq_enet_wq_desc)); 2998c2ecf20Sopenharmony_ci if (err) 3008c2ecf20Sopenharmony_ci goto err_out_cleanup; 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* CQ for each COPY WQ */ 3048c2ecf20Sopenharmony_ci wq_copy_cq_desc_count = (fnic->config.wq_copy_desc_count * 3); 3058c2ecf20Sopenharmony_ci for (i = 0; i < fnic->wq_copy_count; i++) { 3068c2ecf20Sopenharmony_ci cq_index = fnic->raw_wq_count + fnic->rq_count + i; 3078c2ecf20Sopenharmony_ci err = vnic_cq_alloc(fnic->vdev, &fnic->cq[cq_index], 3088c2ecf20Sopenharmony_ci cq_index, 3098c2ecf20Sopenharmony_ci wq_copy_cq_desc_count, 3108c2ecf20Sopenharmony_ci sizeof(struct fcpio_fw_req)); 3118c2ecf20Sopenharmony_ci if (err) 3128c2ecf20Sopenharmony_ci goto err_out_cleanup; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci for (i = 0; i < fnic->intr_count; i++) { 3168c2ecf20Sopenharmony_ci err = vnic_intr_alloc(fnic->vdev, &fnic->intr[i], i); 3178c2ecf20Sopenharmony_ci if (err) 3188c2ecf20Sopenharmony_ci goto err_out_cleanup; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci fnic->legacy_pba = vnic_dev_get_res(fnic->vdev, 3228c2ecf20Sopenharmony_ci RES_TYPE_INTR_PBA_LEGACY, 0); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (!fnic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) { 3258c2ecf20Sopenharmony_ci shost_printk(KERN_ERR, fnic->lport->host, 3268c2ecf20Sopenharmony_ci "Failed to hook legacy pba resource\n"); 3278c2ecf20Sopenharmony_ci err = -ENODEV; 3288c2ecf20Sopenharmony_ci goto err_out_cleanup; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* 3328c2ecf20Sopenharmony_ci * Init RQ/WQ resources. 3338c2ecf20Sopenharmony_ci * 3348c2ecf20Sopenharmony_ci * RQ[0 to n-1] point to CQ[0 to n-1] 3358c2ecf20Sopenharmony_ci * WQ[0 to m-1] point to CQ[n to n+m-1] 3368c2ecf20Sopenharmony_ci * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1] 3378c2ecf20Sopenharmony_ci * 3388c2ecf20Sopenharmony_ci * Note for copy wq we always initialize with cq_index = 0 3398c2ecf20Sopenharmony_ci * 3408c2ecf20Sopenharmony_ci * Error interrupt is not enabled for MSI. 3418c2ecf20Sopenharmony_ci */ 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci switch (intr_mode) { 3448c2ecf20Sopenharmony_ci case VNIC_DEV_INTR_MODE_INTX: 3458c2ecf20Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSIX: 3468c2ecf20Sopenharmony_ci error_interrupt_enable = 1; 3478c2ecf20Sopenharmony_ci error_interrupt_offset = fnic->err_intr_offset; 3488c2ecf20Sopenharmony_ci break; 3498c2ecf20Sopenharmony_ci default: 3508c2ecf20Sopenharmony_ci error_interrupt_enable = 0; 3518c2ecf20Sopenharmony_ci error_interrupt_offset = 0; 3528c2ecf20Sopenharmony_ci break; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci for (i = 0; i < fnic->rq_count; i++) { 3568c2ecf20Sopenharmony_ci cq_index = i; 3578c2ecf20Sopenharmony_ci vnic_rq_init(&fnic->rq[i], 3588c2ecf20Sopenharmony_ci cq_index, 3598c2ecf20Sopenharmony_ci error_interrupt_enable, 3608c2ecf20Sopenharmony_ci error_interrupt_offset); 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci for (i = 0; i < fnic->raw_wq_count; i++) { 3648c2ecf20Sopenharmony_ci cq_index = i + fnic->rq_count; 3658c2ecf20Sopenharmony_ci vnic_wq_init(&fnic->wq[i], 3668c2ecf20Sopenharmony_ci cq_index, 3678c2ecf20Sopenharmony_ci error_interrupt_enable, 3688c2ecf20Sopenharmony_ci error_interrupt_offset); 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci for (i = 0; i < fnic->wq_copy_count; i++) { 3728c2ecf20Sopenharmony_ci vnic_wq_copy_init(&fnic->wq_copy[i], 3738c2ecf20Sopenharmony_ci 0 /* cq_index 0 - always */, 3748c2ecf20Sopenharmony_ci error_interrupt_enable, 3758c2ecf20Sopenharmony_ci error_interrupt_offset); 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci for (i = 0; i < fnic->cq_count; i++) { 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci switch (intr_mode) { 3818c2ecf20Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSIX: 3828c2ecf20Sopenharmony_ci interrupt_offset = i; 3838c2ecf20Sopenharmony_ci break; 3848c2ecf20Sopenharmony_ci default: 3858c2ecf20Sopenharmony_ci interrupt_offset = 0; 3868c2ecf20Sopenharmony_ci break; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci vnic_cq_init(&fnic->cq[i], 3908c2ecf20Sopenharmony_ci 0 /* flow_control_enable */, 3918c2ecf20Sopenharmony_ci 1 /* color_enable */, 3928c2ecf20Sopenharmony_ci 0 /* cq_head */, 3938c2ecf20Sopenharmony_ci 0 /* cq_tail */, 3948c2ecf20Sopenharmony_ci 1 /* cq_tail_color */, 3958c2ecf20Sopenharmony_ci 1 /* interrupt_enable */, 3968c2ecf20Sopenharmony_ci 1 /* cq_entry_enable */, 3978c2ecf20Sopenharmony_ci 0 /* cq_message_enable */, 3988c2ecf20Sopenharmony_ci interrupt_offset, 3998c2ecf20Sopenharmony_ci 0 /* cq_message_addr */); 4008c2ecf20Sopenharmony_ci } 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* 4038c2ecf20Sopenharmony_ci * Init INTR resources 4048c2ecf20Sopenharmony_ci * 4058c2ecf20Sopenharmony_ci * mask_on_assertion is not used for INTx due to the level- 4068c2ecf20Sopenharmony_ci * triggered nature of INTx 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci switch (intr_mode) { 4108c2ecf20Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSI: 4118c2ecf20Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSIX: 4128c2ecf20Sopenharmony_ci mask_on_assertion = 1; 4138c2ecf20Sopenharmony_ci break; 4148c2ecf20Sopenharmony_ci default: 4158c2ecf20Sopenharmony_ci mask_on_assertion = 0; 4168c2ecf20Sopenharmony_ci break; 4178c2ecf20Sopenharmony_ci } 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci for (i = 0; i < fnic->intr_count; i++) { 4208c2ecf20Sopenharmony_ci vnic_intr_init(&fnic->intr[i], 4218c2ecf20Sopenharmony_ci fnic->config.intr_timer, 4228c2ecf20Sopenharmony_ci fnic->config.intr_timer_type, 4238c2ecf20Sopenharmony_ci mask_on_assertion); 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* init the stats memory by making the first call here */ 4278c2ecf20Sopenharmony_ci err = vnic_dev_stats_dump(fnic->vdev, &fnic->stats); 4288c2ecf20Sopenharmony_ci if (err) { 4298c2ecf20Sopenharmony_ci shost_printk(KERN_ERR, fnic->lport->host, 4308c2ecf20Sopenharmony_ci "vnic_dev_stats_dump failed - x%x\n", err); 4318c2ecf20Sopenharmony_ci goto err_out_cleanup; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci /* Clear LIF stats */ 4358c2ecf20Sopenharmony_ci vnic_dev_stats_clear(fnic->vdev); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return 0; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cierr_out_cleanup: 4408c2ecf20Sopenharmony_ci fnic_free_vnic_resources(fnic); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci return err; 4438c2ecf20Sopenharmony_ci} 444