162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2008-2010 Cisco Systems, Inc. All rights reserved. 462306a36Sopenharmony_ci * Copyright 2007 Nuova Systems, Inc. All rights reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/kernel.h> 862306a36Sopenharmony_ci#include <linux/errno.h> 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/pci.h> 1162306a36Sopenharmony_ci#include <linux/netdevice.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "wq_enet_desc.h" 1462306a36Sopenharmony_ci#include "rq_enet_desc.h" 1562306a36Sopenharmony_ci#include "cq_enet_desc.h" 1662306a36Sopenharmony_ci#include "vnic_resource.h" 1762306a36Sopenharmony_ci#include "vnic_enet.h" 1862306a36Sopenharmony_ci#include "vnic_dev.h" 1962306a36Sopenharmony_ci#include "vnic_wq.h" 2062306a36Sopenharmony_ci#include "vnic_rq.h" 2162306a36Sopenharmony_ci#include "vnic_cq.h" 2262306a36Sopenharmony_ci#include "vnic_intr.h" 2362306a36Sopenharmony_ci#include "vnic_stats.h" 2462306a36Sopenharmony_ci#include "vnic_nic.h" 2562306a36Sopenharmony_ci#include "vnic_rss.h" 2662306a36Sopenharmony_ci#include "enic_res.h" 2762306a36Sopenharmony_ci#include "enic.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciint enic_get_vnic_config(struct enic *enic) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci struct vnic_enet_config *c = &enic->config; 3262306a36Sopenharmony_ci int err; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr); 3562306a36Sopenharmony_ci if (err) { 3662306a36Sopenharmony_ci dev_err(enic_get_dev(enic), 3762306a36Sopenharmony_ci "Error getting MAC addr, %d\n", err); 3862306a36Sopenharmony_ci return err; 3962306a36Sopenharmony_ci } 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define GET_CONFIG(m) \ 4262306a36Sopenharmony_ci do { \ 4362306a36Sopenharmony_ci err = vnic_dev_spec(enic->vdev, \ 4462306a36Sopenharmony_ci offsetof(struct vnic_enet_config, m), \ 4562306a36Sopenharmony_ci sizeof(c->m), &c->m); \ 4662306a36Sopenharmony_ci if (err) { \ 4762306a36Sopenharmony_ci dev_err(enic_get_dev(enic), \ 4862306a36Sopenharmony_ci "Error getting %s, %d\n", #m, err); \ 4962306a36Sopenharmony_ci return err; \ 5062306a36Sopenharmony_ci } \ 5162306a36Sopenharmony_ci } while (0) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci GET_CONFIG(flags); 5462306a36Sopenharmony_ci GET_CONFIG(wq_desc_count); 5562306a36Sopenharmony_ci GET_CONFIG(rq_desc_count); 5662306a36Sopenharmony_ci GET_CONFIG(mtu); 5762306a36Sopenharmony_ci GET_CONFIG(intr_timer_type); 5862306a36Sopenharmony_ci GET_CONFIG(intr_mode); 5962306a36Sopenharmony_ci GET_CONFIG(intr_timer_usec); 6062306a36Sopenharmony_ci GET_CONFIG(loop_tag); 6162306a36Sopenharmony_ci GET_CONFIG(num_arfs); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci c->wq_desc_count = 6462306a36Sopenharmony_ci min_t(u32, ENIC_MAX_WQ_DESCS, 6562306a36Sopenharmony_ci max_t(u32, ENIC_MIN_WQ_DESCS, 6662306a36Sopenharmony_ci c->wq_desc_count)); 6762306a36Sopenharmony_ci c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci c->rq_desc_count = 7062306a36Sopenharmony_ci min_t(u32, ENIC_MAX_RQ_DESCS, 7162306a36Sopenharmony_ci max_t(u32, ENIC_MIN_RQ_DESCS, 7262306a36Sopenharmony_ci c->rq_desc_count)); 7362306a36Sopenharmony_ci c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */ 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (c->mtu == 0) 7662306a36Sopenharmony_ci c->mtu = 1500; 7762306a36Sopenharmony_ci c->mtu = min_t(u16, ENIC_MAX_MTU, 7862306a36Sopenharmony_ci max_t(u16, ENIC_MIN_MTU, 7962306a36Sopenharmony_ci c->mtu)); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci c->intr_timer_usec = min_t(u32, c->intr_timer_usec, 8262306a36Sopenharmony_ci vnic_dev_get_intr_coal_timer_max(enic->vdev)); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci dev_info(enic_get_dev(enic), 8562306a36Sopenharmony_ci "vNIC MAC addr %pM wq/rq %d/%d mtu %d\n", 8662306a36Sopenharmony_ci enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s " 8962306a36Sopenharmony_ci "tso/lro %s/%s rss %s intr mode %s type %s timer %d usec " 9062306a36Sopenharmony_ci "loopback tag 0x%04x\n", 9162306a36Sopenharmony_ci ENIC_SETTING(enic, TXCSUM) ? "yes" : "no", 9262306a36Sopenharmony_ci ENIC_SETTING(enic, RXCSUM) ? "yes" : "no", 9362306a36Sopenharmony_ci ENIC_SETTING(enic, TSO) ? "yes" : "no", 9462306a36Sopenharmony_ci ENIC_SETTING(enic, LRO) ? "yes" : "no", 9562306a36Sopenharmony_ci ENIC_SETTING(enic, RSS) ? "yes" : "no", 9662306a36Sopenharmony_ci c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" : 9762306a36Sopenharmony_ci c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" : 9862306a36Sopenharmony_ci c->intr_mode == VENET_INTR_MODE_ANY ? "any" : 9962306a36Sopenharmony_ci "unknown", 10062306a36Sopenharmony_ci c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" : 10162306a36Sopenharmony_ci c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" : 10262306a36Sopenharmony_ci "unknown", 10362306a36Sopenharmony_ci c->intr_timer_usec, 10462306a36Sopenharmony_ci c->loop_tag); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return 0; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciint enic_add_vlan(struct enic *enic, u16 vlanid) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci u64 a0 = vlanid, a1 = 0; 11262306a36Sopenharmony_ci int wait = 1000; 11362306a36Sopenharmony_ci int err; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait); 11662306a36Sopenharmony_ci if (err) 11762306a36Sopenharmony_ci dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return err; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciint enic_del_vlan(struct enic *enic, u16 vlanid) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci u64 a0 = vlanid, a1 = 0; 12562306a36Sopenharmony_ci int wait = 1000; 12662306a36Sopenharmony_ci int err; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait); 12962306a36Sopenharmony_ci if (err) 13062306a36Sopenharmony_ci dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return err; 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciint enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type, 13662306a36Sopenharmony_ci u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en, 13762306a36Sopenharmony_ci u8 ig_vlan_strip_en) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci enum vnic_devcmd_cmd cmd = CMD_NIC_CFG; 14062306a36Sopenharmony_ci u64 a0, a1; 14162306a36Sopenharmony_ci u32 nic_cfg; 14262306a36Sopenharmony_ci int wait = 1000; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci vnic_set_nic_cfg(&nic_cfg, rss_default_cpu, 14562306a36Sopenharmony_ci rss_hash_type, rss_hash_bits, rss_base_cpu, 14662306a36Sopenharmony_ci rss_enable, tso_ipid_split_en, ig_vlan_strip_en); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci a0 = nic_cfg; 14962306a36Sopenharmony_ci a1 = 0; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (rss_hash_type & (NIC_CFG_RSS_HASH_TYPE_UDP_IPV4 | 15262306a36Sopenharmony_ci NIC_CFG_RSS_HASH_TYPE_UDP_IPV6)) 15362306a36Sopenharmony_ci cmd = CMD_NIC_CFG_CHK; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci return vnic_dev_cmd(enic->vdev, cmd, &a0, &a1, wait); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ciint enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci u64 a0 = (u64)key_pa, a1 = len; 16162306a36Sopenharmony_ci int wait = 1000; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciint enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci u64 a0 = (u64)cpu_pa, a1 = len; 16962306a36Sopenharmony_ci int wait = 1000; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_civoid enic_free_vnic_resources(struct enic *enic) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci unsigned int i; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci for (i = 0; i < enic->wq_count; i++) 17962306a36Sopenharmony_ci vnic_wq_free(&enic->wq[i]); 18062306a36Sopenharmony_ci for (i = 0; i < enic->rq_count; i++) 18162306a36Sopenharmony_ci vnic_rq_free(&enic->rq[i]); 18262306a36Sopenharmony_ci for (i = 0; i < enic->cq_count; i++) 18362306a36Sopenharmony_ci vnic_cq_free(&enic->cq[i]); 18462306a36Sopenharmony_ci for (i = 0; i < enic->intr_count; i++) 18562306a36Sopenharmony_ci vnic_intr_free(&enic->intr[i]); 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_civoid enic_get_res_counts(struct enic *enic) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ); 19162306a36Sopenharmony_ci enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ); 19262306a36Sopenharmony_ci enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ); 19362306a36Sopenharmony_ci enic->intr_count = vnic_dev_get_res_count(enic->vdev, 19462306a36Sopenharmony_ci RES_TYPE_INTR_CTRL); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci dev_info(enic_get_dev(enic), 19762306a36Sopenharmony_ci "vNIC resources avail: wq %d rq %d cq %d intr %d\n", 19862306a36Sopenharmony_ci enic->wq_count, enic->rq_count, 19962306a36Sopenharmony_ci enic->cq_count, enic->intr_count); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_civoid enic_init_vnic_resources(struct enic *enic) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci enum vnic_dev_intr_mode intr_mode; 20562306a36Sopenharmony_ci unsigned int mask_on_assertion; 20662306a36Sopenharmony_ci unsigned int interrupt_offset; 20762306a36Sopenharmony_ci unsigned int error_interrupt_enable; 20862306a36Sopenharmony_ci unsigned int error_interrupt_offset; 20962306a36Sopenharmony_ci unsigned int cq_index; 21062306a36Sopenharmony_ci unsigned int i; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci intr_mode = vnic_dev_get_intr_mode(enic->vdev); 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* Init RQ/WQ resources. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * RQ[0 - n-1] point to CQ[0 - n-1] 21762306a36Sopenharmony_ci * WQ[0 - m-1] point to CQ[n - n+m-1] 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * Error interrupt is not enabled for MSI. 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci switch (intr_mode) { 22362306a36Sopenharmony_ci case VNIC_DEV_INTR_MODE_INTX: 22462306a36Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSIX: 22562306a36Sopenharmony_ci error_interrupt_enable = 1; 22662306a36Sopenharmony_ci error_interrupt_offset = enic->intr_count - 2; 22762306a36Sopenharmony_ci break; 22862306a36Sopenharmony_ci default: 22962306a36Sopenharmony_ci error_interrupt_enable = 0; 23062306a36Sopenharmony_ci error_interrupt_offset = 0; 23162306a36Sopenharmony_ci break; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci for (i = 0; i < enic->rq_count; i++) { 23562306a36Sopenharmony_ci cq_index = i; 23662306a36Sopenharmony_ci vnic_rq_init(&enic->rq[i], 23762306a36Sopenharmony_ci cq_index, 23862306a36Sopenharmony_ci error_interrupt_enable, 23962306a36Sopenharmony_ci error_interrupt_offset); 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci for (i = 0; i < enic->wq_count; i++) { 24362306a36Sopenharmony_ci cq_index = enic->rq_count + i; 24462306a36Sopenharmony_ci vnic_wq_init(&enic->wq[i], 24562306a36Sopenharmony_ci cq_index, 24662306a36Sopenharmony_ci error_interrupt_enable, 24762306a36Sopenharmony_ci error_interrupt_offset); 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Init CQ resources 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * CQ[0 - n+m-1] point to INTR[0] for INTx, MSI 25362306a36Sopenharmony_ci * CQ[0 - n+m-1] point to INTR[0 - n+m-1] for MSI-X 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci for (i = 0; i < enic->cq_count; i++) { 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci switch (intr_mode) { 25962306a36Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSIX: 26062306a36Sopenharmony_ci interrupt_offset = i; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci default: 26362306a36Sopenharmony_ci interrupt_offset = 0; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci vnic_cq_init(&enic->cq[i], 26862306a36Sopenharmony_ci 0 /* flow_control_enable */, 26962306a36Sopenharmony_ci 1 /* color_enable */, 27062306a36Sopenharmony_ci 0 /* cq_head */, 27162306a36Sopenharmony_ci 0 /* cq_tail */, 27262306a36Sopenharmony_ci 1 /* cq_tail_color */, 27362306a36Sopenharmony_ci 1 /* interrupt_enable */, 27462306a36Sopenharmony_ci 1 /* cq_entry_enable */, 27562306a36Sopenharmony_ci 0 /* cq_message_enable */, 27662306a36Sopenharmony_ci interrupt_offset, 27762306a36Sopenharmony_ci 0 /* cq_message_addr */); 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* Init INTR resources 28162306a36Sopenharmony_ci * 28262306a36Sopenharmony_ci * mask_on_assertion is not used for INTx due to the level- 28362306a36Sopenharmony_ci * triggered nature of INTx 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci switch (intr_mode) { 28762306a36Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSI: 28862306a36Sopenharmony_ci case VNIC_DEV_INTR_MODE_MSIX: 28962306a36Sopenharmony_ci mask_on_assertion = 1; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci default: 29262306a36Sopenharmony_ci mask_on_assertion = 0; 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci for (i = 0; i < enic->intr_count; i++) { 29762306a36Sopenharmony_ci vnic_intr_init(&enic->intr[i], 29862306a36Sopenharmony_ci enic->config.intr_timer_usec, 29962306a36Sopenharmony_ci enic->config.intr_timer_type, 30062306a36Sopenharmony_ci mask_on_assertion); 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ciint enic_alloc_vnic_resources(struct enic *enic) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci enum vnic_dev_intr_mode intr_mode; 30762306a36Sopenharmony_ci unsigned int i; 30862306a36Sopenharmony_ci int err; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci intr_mode = vnic_dev_get_intr_mode(enic->vdev); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci dev_info(enic_get_dev(enic), "vNIC resources used: " 31362306a36Sopenharmony_ci "wq %d rq %d cq %d intr %d intr mode %s\n", 31462306a36Sopenharmony_ci enic->wq_count, enic->rq_count, 31562306a36Sopenharmony_ci enic->cq_count, enic->intr_count, 31662306a36Sopenharmony_ci intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" : 31762306a36Sopenharmony_ci intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" : 31862306a36Sopenharmony_ci intr_mode == VNIC_DEV_INTR_MODE_MSIX ? "MSI-X" : 31962306a36Sopenharmony_ci "unknown"); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci /* Allocate queue resources 32262306a36Sopenharmony_ci */ 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci for (i = 0; i < enic->wq_count; i++) { 32562306a36Sopenharmony_ci err = vnic_wq_alloc(enic->vdev, &enic->wq[i], i, 32662306a36Sopenharmony_ci enic->config.wq_desc_count, 32762306a36Sopenharmony_ci sizeof(struct wq_enet_desc)); 32862306a36Sopenharmony_ci if (err) 32962306a36Sopenharmony_ci goto err_out_cleanup; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci for (i = 0; i < enic->rq_count; i++) { 33362306a36Sopenharmony_ci err = vnic_rq_alloc(enic->vdev, &enic->rq[i], i, 33462306a36Sopenharmony_ci enic->config.rq_desc_count, 33562306a36Sopenharmony_ci sizeof(struct rq_enet_desc)); 33662306a36Sopenharmony_ci if (err) 33762306a36Sopenharmony_ci goto err_out_cleanup; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci for (i = 0; i < enic->cq_count; i++) { 34162306a36Sopenharmony_ci if (i < enic->rq_count) 34262306a36Sopenharmony_ci err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i, 34362306a36Sopenharmony_ci enic->config.rq_desc_count, 34462306a36Sopenharmony_ci sizeof(struct cq_enet_rq_desc)); 34562306a36Sopenharmony_ci else 34662306a36Sopenharmony_ci err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i, 34762306a36Sopenharmony_ci enic->config.wq_desc_count, 34862306a36Sopenharmony_ci sizeof(struct cq_enet_wq_desc)); 34962306a36Sopenharmony_ci if (err) 35062306a36Sopenharmony_ci goto err_out_cleanup; 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci for (i = 0; i < enic->intr_count; i++) { 35462306a36Sopenharmony_ci err = vnic_intr_alloc(enic->vdev, &enic->intr[i], i); 35562306a36Sopenharmony_ci if (err) 35662306a36Sopenharmony_ci goto err_out_cleanup; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci /* Hook remaining resource 36062306a36Sopenharmony_ci */ 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci enic->legacy_pba = vnic_dev_get_res(enic->vdev, 36362306a36Sopenharmony_ci RES_TYPE_INTR_PBA_LEGACY, 0); 36462306a36Sopenharmony_ci if (!enic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) { 36562306a36Sopenharmony_ci dev_err(enic_get_dev(enic), 36662306a36Sopenharmony_ci "Failed to hook legacy pba resource\n"); 36762306a36Sopenharmony_ci err = -ENODEV; 36862306a36Sopenharmony_ci goto err_out_cleanup; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci return 0; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cierr_out_cleanup: 37462306a36Sopenharmony_ci enic_free_vnic_resources(enic); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci return err; 37762306a36Sopenharmony_ci} 378