145d3d428SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 245d3d428SAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 345d3d428SAnirudh Venkataramanan 445d3d428SAnirudh Venkataramanan #include "ice.h" 545d3d428SAnirudh Venkataramanan #include "ice_lib.h" 67b9ffc76SAnirudh Venkataramanan #include "ice_dcb_lib.h" 745d3d428SAnirudh Venkataramanan 845d3d428SAnirudh Venkataramanan /** 972adf242SAnirudh Venkataramanan * ice_setup_rx_ctx - Configure a receive ring context 1072adf242SAnirudh Venkataramanan * @ring: The Rx ring to configure 1172adf242SAnirudh Venkataramanan * 1272adf242SAnirudh Venkataramanan * Configure the Rx descriptor ring in RLAN context. 1372adf242SAnirudh Venkataramanan */ 1472adf242SAnirudh Venkataramanan static int ice_setup_rx_ctx(struct ice_ring *ring) 1572adf242SAnirudh Venkataramanan { 1672adf242SAnirudh Venkataramanan struct ice_vsi *vsi = ring->vsi; 1772adf242SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1872adf242SAnirudh Venkataramanan u32 rxdid = ICE_RXDID_FLEX_NIC; 1972adf242SAnirudh Venkataramanan struct ice_rlan_ctx rlan_ctx; 2072adf242SAnirudh Venkataramanan u32 regval; 2172adf242SAnirudh Venkataramanan u16 pf_q; 2272adf242SAnirudh Venkataramanan int err; 2372adf242SAnirudh Venkataramanan 24d337f2afSAnirudh Venkataramanan /* what is Rx queue number in global space of 2K Rx queues */ 2572adf242SAnirudh Venkataramanan pf_q = vsi->rxq_map[ring->q_index]; 2672adf242SAnirudh Venkataramanan 2772adf242SAnirudh Venkataramanan /* clear the context structure first */ 2872adf242SAnirudh Venkataramanan memset(&rlan_ctx, 0, sizeof(rlan_ctx)); 2972adf242SAnirudh Venkataramanan 3072adf242SAnirudh Venkataramanan rlan_ctx.base = ring->dma >> 7; 3172adf242SAnirudh Venkataramanan 3272adf242SAnirudh Venkataramanan rlan_ctx.qlen = ring->count; 3372adf242SAnirudh Venkataramanan 3472adf242SAnirudh Venkataramanan /* Receive Packet Data Buffer Size. 3572adf242SAnirudh Venkataramanan * The Packet Data Buffer Size is defined in 128 byte units. 3672adf242SAnirudh Venkataramanan */ 3772adf242SAnirudh Venkataramanan rlan_ctx.dbuf = vsi->rx_buf_len >> ICE_RLAN_CTX_DBUF_S; 3872adf242SAnirudh Venkataramanan 3972adf242SAnirudh Venkataramanan /* use 32 byte descriptors */ 4072adf242SAnirudh Venkataramanan rlan_ctx.dsize = 1; 4172adf242SAnirudh Venkataramanan 4272adf242SAnirudh Venkataramanan /* Strip the Ethernet CRC bytes before the packet is posted to host 4372adf242SAnirudh Venkataramanan * memory. 4472adf242SAnirudh Venkataramanan */ 4572adf242SAnirudh Venkataramanan rlan_ctx.crcstrip = 1; 4672adf242SAnirudh Venkataramanan 4772adf242SAnirudh Venkataramanan /* L2TSEL flag defines the reported L2 Tags in the receive descriptor */ 4872adf242SAnirudh Venkataramanan rlan_ctx.l2tsel = 1; 4972adf242SAnirudh Venkataramanan 5072adf242SAnirudh Venkataramanan rlan_ctx.dtype = ICE_RX_DTYPE_NO_SPLIT; 5172adf242SAnirudh Venkataramanan rlan_ctx.hsplit_0 = ICE_RLAN_RX_HSPLIT_0_NO_SPLIT; 5272adf242SAnirudh Venkataramanan rlan_ctx.hsplit_1 = ICE_RLAN_RX_HSPLIT_1_NO_SPLIT; 5372adf242SAnirudh Venkataramanan 5472adf242SAnirudh Venkataramanan /* This controls whether VLAN is stripped from inner headers 5572adf242SAnirudh Venkataramanan * The VLAN in the inner L2 header is stripped to the receive 5672adf242SAnirudh Venkataramanan * descriptor if enabled by this flag. 5772adf242SAnirudh Venkataramanan */ 5872adf242SAnirudh Venkataramanan rlan_ctx.showiv = 0; 5972adf242SAnirudh Venkataramanan 6072adf242SAnirudh Venkataramanan /* Max packet size for this queue - must not be set to a larger value 6172adf242SAnirudh Venkataramanan * than 5 x DBUF 6272adf242SAnirudh Venkataramanan */ 6372adf242SAnirudh Venkataramanan rlan_ctx.rxmax = min_t(u16, vsi->max_frame, 6472adf242SAnirudh Venkataramanan ICE_MAX_CHAINED_RX_BUFS * vsi->rx_buf_len); 6572adf242SAnirudh Venkataramanan 6672adf242SAnirudh Venkataramanan /* Rx queue threshold in units of 64 */ 6772adf242SAnirudh Venkataramanan rlan_ctx.lrxqthresh = 1; 6872adf242SAnirudh Venkataramanan 6972adf242SAnirudh Venkataramanan /* Enable Flexible Descriptors in the queue context which 7072adf242SAnirudh Venkataramanan * allows this driver to select a specific receive descriptor format 7172adf242SAnirudh Venkataramanan */ 728ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 7372adf242SAnirudh Venkataramanan regval = rd32(hw, QRXFLXP_CNTXT(pf_q)); 7472adf242SAnirudh Venkataramanan regval |= (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) & 7572adf242SAnirudh Venkataramanan QRXFLXP_CNTXT_RXDID_IDX_M; 7672adf242SAnirudh Venkataramanan 77f9867df6SAnirudh Venkataramanan /* increasing context priority to pick up profile ID; 7872adf242SAnirudh Venkataramanan * default is 0x01; setting to 0x03 to ensure profile 7972adf242SAnirudh Venkataramanan * is programming if prev context is of same priority 8072adf242SAnirudh Venkataramanan */ 8172adf242SAnirudh Venkataramanan regval |= (0x03 << QRXFLXP_CNTXT_RXDID_PRIO_S) & 8272adf242SAnirudh Venkataramanan QRXFLXP_CNTXT_RXDID_PRIO_M; 8372adf242SAnirudh Venkataramanan 8472adf242SAnirudh Venkataramanan wr32(hw, QRXFLXP_CNTXT(pf_q), regval); 858ede0178SAnirudh Venkataramanan } 8672adf242SAnirudh Venkataramanan 8772adf242SAnirudh Venkataramanan /* Absolute queue number out of 2K needs to be passed */ 8872adf242SAnirudh Venkataramanan err = ice_write_rxq_ctx(hw, &rlan_ctx, pf_q); 8972adf242SAnirudh Venkataramanan if (err) { 9072adf242SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, 9172adf242SAnirudh Venkataramanan "Failed to set LAN Rx queue context for absolute Rx queue %d error: %d\n", 9272adf242SAnirudh Venkataramanan pf_q, err); 9372adf242SAnirudh Venkataramanan return -EIO; 9472adf242SAnirudh Venkataramanan } 9572adf242SAnirudh Venkataramanan 968ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 978ede0178SAnirudh Venkataramanan return 0; 988ede0178SAnirudh Venkataramanan 9972adf242SAnirudh Venkataramanan /* init queue specific tail register */ 10072adf242SAnirudh Venkataramanan ring->tail = hw->hw_addr + QRX_TAIL(pf_q); 10172adf242SAnirudh Venkataramanan writel(0, ring->tail); 10272adf242SAnirudh Venkataramanan ice_alloc_rx_bufs(ring, ICE_DESC_UNUSED(ring)); 10372adf242SAnirudh Venkataramanan 10472adf242SAnirudh Venkataramanan return 0; 10572adf242SAnirudh Venkataramanan } 10672adf242SAnirudh Venkataramanan 10772adf242SAnirudh Venkataramanan /** 10872adf242SAnirudh Venkataramanan * ice_setup_tx_ctx - setup a struct ice_tlan_ctx instance 10972adf242SAnirudh Venkataramanan * @ring: The Tx ring to configure 11072adf242SAnirudh Venkataramanan * @tlan_ctx: Pointer to the Tx LAN queue context structure to be initialized 11172adf242SAnirudh Venkataramanan * @pf_q: queue index in the PF space 11272adf242SAnirudh Venkataramanan * 11372adf242SAnirudh Venkataramanan * Configure the Tx descriptor ring in TLAN context. 11472adf242SAnirudh Venkataramanan */ 11572adf242SAnirudh Venkataramanan static void 11672adf242SAnirudh Venkataramanan ice_setup_tx_ctx(struct ice_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q) 11772adf242SAnirudh Venkataramanan { 11872adf242SAnirudh Venkataramanan struct ice_vsi *vsi = ring->vsi; 11972adf242SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 12072adf242SAnirudh Venkataramanan 12172adf242SAnirudh Venkataramanan tlan_ctx->base = ring->dma >> ICE_TLAN_CTX_BASE_S; 12272adf242SAnirudh Venkataramanan 12372adf242SAnirudh Venkataramanan tlan_ctx->port_num = vsi->port_info->lport; 12472adf242SAnirudh Venkataramanan 12572adf242SAnirudh Venkataramanan /* Transmit Queue Length */ 12672adf242SAnirudh Venkataramanan tlan_ctx->qlen = ring->count; 12772adf242SAnirudh Venkataramanan 128a629cf0aSAnirudh Venkataramanan ice_set_cgd_num(tlan_ctx, ring); 129a629cf0aSAnirudh Venkataramanan 13072adf242SAnirudh Venkataramanan /* PF number */ 13172adf242SAnirudh Venkataramanan tlan_ctx->pf_num = hw->pf_id; 13272adf242SAnirudh Venkataramanan 13372adf242SAnirudh Venkataramanan /* queue belongs to a specific VSI type 13472adf242SAnirudh Venkataramanan * VF / VM index should be programmed per vmvf_type setting: 13572adf242SAnirudh Venkataramanan * for vmvf_type = VF, it is VF number between 0-256 13672adf242SAnirudh Venkataramanan * for vmvf_type = VM, it is VM number between 0-767 13772adf242SAnirudh Venkataramanan * for PF or EMP this field should be set to zero 13872adf242SAnirudh Venkataramanan */ 13972adf242SAnirudh Venkataramanan switch (vsi->type) { 14072adf242SAnirudh Venkataramanan case ICE_VSI_PF: 14172adf242SAnirudh Venkataramanan tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_PF; 14272adf242SAnirudh Venkataramanan break; 1438ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 144f9867df6SAnirudh Venkataramanan /* Firmware expects vmvf_num to be absolute VF ID */ 1458ede0178SAnirudh Venkataramanan tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf_id; 1468ede0178SAnirudh Venkataramanan tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF; 1478ede0178SAnirudh Venkataramanan break; 14872adf242SAnirudh Venkataramanan default: 14972adf242SAnirudh Venkataramanan return; 15072adf242SAnirudh Venkataramanan } 15172adf242SAnirudh Venkataramanan 15272adf242SAnirudh Venkataramanan /* make sure the context is associated with the right VSI */ 1534fb33f31SAnirudh Venkataramanan tlan_ctx->src_vsi = ice_get_hw_vsi_num(hw, vsi->idx); 15472adf242SAnirudh Venkataramanan 15572adf242SAnirudh Venkataramanan tlan_ctx->tso_ena = ICE_TX_LEGACY; 15672adf242SAnirudh Venkataramanan tlan_ctx->tso_qnum = pf_q; 15772adf242SAnirudh Venkataramanan 15872adf242SAnirudh Venkataramanan /* Legacy or Advanced Host Interface: 15972adf242SAnirudh Venkataramanan * 0: Advanced Host Interface 16072adf242SAnirudh Venkataramanan * 1: Legacy Host Interface 16172adf242SAnirudh Venkataramanan */ 16272adf242SAnirudh Venkataramanan tlan_ctx->legacy_int = ICE_TX_LEGACY; 16372adf242SAnirudh Venkataramanan } 16472adf242SAnirudh Venkataramanan 16572adf242SAnirudh Venkataramanan /** 16672adf242SAnirudh Venkataramanan * ice_pf_rxq_wait - Wait for a PF's Rx queue to be enabled or disabled 16772adf242SAnirudh Venkataramanan * @pf: the PF being configured 16872adf242SAnirudh Venkataramanan * @pf_q: the PF queue 16972adf242SAnirudh Venkataramanan * @ena: enable or disable state of the queue 17072adf242SAnirudh Venkataramanan * 17172adf242SAnirudh Venkataramanan * This routine will wait for the given Rx queue of the PF to reach the 17272adf242SAnirudh Venkataramanan * enabled or disabled state. 17372adf242SAnirudh Venkataramanan * Returns -ETIMEDOUT in case of failing to reach the requested state after 17472adf242SAnirudh Venkataramanan * multiple retries; else will return 0 in case of success. 17572adf242SAnirudh Venkataramanan */ 17672adf242SAnirudh Venkataramanan static int ice_pf_rxq_wait(struct ice_pf *pf, int pf_q, bool ena) 17772adf242SAnirudh Venkataramanan { 17872adf242SAnirudh Venkataramanan int i; 17972adf242SAnirudh Venkataramanan 1807b8ff0f9SPiotr Raczynski for (i = 0; i < ICE_Q_WAIT_MAX_RETRY; i++) { 18116c3301bSBrett Creeley if (ena == !!(rd32(&pf->hw, QRX_CTRL(pf_q)) & 18216c3301bSBrett Creeley QRX_CTRL_QENA_STAT_M)) 18316c3301bSBrett Creeley return 0; 18472adf242SAnirudh Venkataramanan 1857b8ff0f9SPiotr Raczynski usleep_range(20, 40); 18672adf242SAnirudh Venkataramanan } 18772adf242SAnirudh Venkataramanan 18816c3301bSBrett Creeley return -ETIMEDOUT; 18972adf242SAnirudh Venkataramanan } 19072adf242SAnirudh Venkataramanan 19172adf242SAnirudh Venkataramanan /** 19272adf242SAnirudh Venkataramanan * ice_vsi_ctrl_rx_rings - Start or stop a VSI's Rx rings 19372adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 19472adf242SAnirudh Venkataramanan * @ena: start or stop the Rx rings 19572adf242SAnirudh Venkataramanan */ 19672adf242SAnirudh Venkataramanan static int ice_vsi_ctrl_rx_rings(struct ice_vsi *vsi, bool ena) 19772adf242SAnirudh Venkataramanan { 19872adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 19972adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 200acd1751aSBrett Creeley int i, ret = 0; 20172adf242SAnirudh Venkataramanan 20272adf242SAnirudh Venkataramanan for (i = 0; i < vsi->num_rxq; i++) { 20372adf242SAnirudh Venkataramanan int pf_q = vsi->rxq_map[i]; 20472adf242SAnirudh Venkataramanan u32 rx_reg; 20572adf242SAnirudh Venkataramanan 20672adf242SAnirudh Venkataramanan rx_reg = rd32(hw, QRX_CTRL(pf_q)); 20772adf242SAnirudh Venkataramanan 20872adf242SAnirudh Venkataramanan /* Skip if the queue is already in the requested state */ 20972adf242SAnirudh Venkataramanan if (ena == !!(rx_reg & QRX_CTRL_QENA_STAT_M)) 21072adf242SAnirudh Venkataramanan continue; 21172adf242SAnirudh Venkataramanan 21272adf242SAnirudh Venkataramanan /* turn on/off the queue */ 21372adf242SAnirudh Venkataramanan if (ena) 21472adf242SAnirudh Venkataramanan rx_reg |= QRX_CTRL_QENA_REQ_M; 21572adf242SAnirudh Venkataramanan else 21672adf242SAnirudh Venkataramanan rx_reg &= ~QRX_CTRL_QENA_REQ_M; 21772adf242SAnirudh Venkataramanan wr32(hw, QRX_CTRL(pf_q), rx_reg); 21872adf242SAnirudh Venkataramanan 21972adf242SAnirudh Venkataramanan /* wait for the change to finish */ 22072adf242SAnirudh Venkataramanan ret = ice_pf_rxq_wait(pf, pf_q, ena); 22172adf242SAnirudh Venkataramanan if (ret) { 22272adf242SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 22372adf242SAnirudh Venkataramanan "VSI idx %d Rx ring %d %sable timeout\n", 22472adf242SAnirudh Venkataramanan vsi->idx, pf_q, (ena ? "en" : "dis")); 22572adf242SAnirudh Venkataramanan break; 22672adf242SAnirudh Venkataramanan } 22772adf242SAnirudh Venkataramanan } 22872adf242SAnirudh Venkataramanan 22972adf242SAnirudh Venkataramanan return ret; 23072adf242SAnirudh Venkataramanan } 23172adf242SAnirudh Venkataramanan 23272adf242SAnirudh Venkataramanan /** 23328c2a645SAnirudh Venkataramanan * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI 23428c2a645SAnirudh Venkataramanan * @vsi: VSI pointer 23528c2a645SAnirudh Venkataramanan * 23628c2a645SAnirudh Venkataramanan * On error: returns error code (negative) 23728c2a645SAnirudh Venkataramanan * On success: returns 0 23828c2a645SAnirudh Venkataramanan */ 239a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) 24028c2a645SAnirudh Venkataramanan { 24128c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 24228c2a645SAnirudh Venkataramanan 24328c2a645SAnirudh Venkataramanan /* allocate memory for both Tx and Rx ring pointers */ 24428c2a645SAnirudh Venkataramanan vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 245c6dfd690SBruce Allan sizeof(*vsi->tx_rings), GFP_KERNEL); 24628c2a645SAnirudh Venkataramanan if (!vsi->tx_rings) 24728c2a645SAnirudh Venkataramanan goto err_txrings; 24828c2a645SAnirudh Venkataramanan 24928c2a645SAnirudh Venkataramanan vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 250c6dfd690SBruce Allan sizeof(*vsi->rx_rings), GFP_KERNEL); 25128c2a645SAnirudh Venkataramanan if (!vsi->rx_rings) 25228c2a645SAnirudh Venkataramanan goto err_rxrings; 25328c2a645SAnirudh Venkataramanan 25428c2a645SAnirudh Venkataramanan /* allocate memory for q_vector pointers */ 255a85a3847SBrett Creeley vsi->q_vectors = devm_kcalloc(&pf->pdev->dev, vsi->num_q_vectors, 256a85a3847SBrett Creeley sizeof(*vsi->q_vectors), GFP_KERNEL); 25728c2a645SAnirudh Venkataramanan if (!vsi->q_vectors) 25828c2a645SAnirudh Venkataramanan goto err_vectors; 25928c2a645SAnirudh Venkataramanan 26028c2a645SAnirudh Venkataramanan return 0; 26128c2a645SAnirudh Venkataramanan 26228c2a645SAnirudh Venkataramanan err_vectors: 26328c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 26428c2a645SAnirudh Venkataramanan err_rxrings: 26528c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 26628c2a645SAnirudh Venkataramanan err_txrings: 26728c2a645SAnirudh Venkataramanan return -ENOMEM; 26828c2a645SAnirudh Venkataramanan } 26928c2a645SAnirudh Venkataramanan 27028c2a645SAnirudh Venkataramanan /** 271ad71b256SBrett Creeley * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI 272ad71b256SBrett Creeley * @vsi: the VSI being configured 273ad71b256SBrett Creeley */ 274ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi) 275ad71b256SBrett Creeley { 276ad71b256SBrett Creeley switch (vsi->type) { 277ad71b256SBrett Creeley case ICE_VSI_PF: 278ad71b256SBrett Creeley vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC; 279ad71b256SBrett Creeley vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC; 280ad71b256SBrett Creeley break; 281ad71b256SBrett Creeley default: 282ad71b256SBrett Creeley dev_dbg(&vsi->back->pdev->dev, 283ad71b256SBrett Creeley "Not setting number of Tx/Rx descriptors for VSI type %d\n", 284ad71b256SBrett Creeley vsi->type); 285ad71b256SBrett Creeley break; 286ad71b256SBrett Creeley } 287ad71b256SBrett Creeley } 288ad71b256SBrett Creeley 289ad71b256SBrett Creeley /** 290ad71b256SBrett Creeley * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI 29128c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 292f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 29328c2a645SAnirudh Venkataramanan * 29428c2a645SAnirudh Venkataramanan * Return 0 on success and a negative value on error 29528c2a645SAnirudh Venkataramanan */ 2965743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) 29728c2a645SAnirudh Venkataramanan { 29828c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2995743020dSAkeem G Abodunrin struct ice_vf *vf = NULL; 3005743020dSAkeem G Abodunrin 3015743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 3025743020dSAkeem G Abodunrin vsi->vf_id = vf_id; 3035743020dSAkeem G Abodunrin 30428c2a645SAnirudh Venkataramanan switch (vsi->type) { 30528c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 30628c2a645SAnirudh Venkataramanan vsi->alloc_txq = pf->num_lan_tx; 30728c2a645SAnirudh Venkataramanan vsi->alloc_rxq = pf->num_lan_rx; 30828c2a645SAnirudh Venkataramanan vsi->num_q_vectors = max_t(int, pf->num_lan_rx, pf->num_lan_tx); 30928c2a645SAnirudh Venkataramanan break; 3108ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 3115743020dSAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 3125743020dSAkeem G Abodunrin vsi->alloc_txq = vf->num_vf_qs; 3135743020dSAkeem G Abodunrin vsi->alloc_rxq = vf->num_vf_qs; 3148ede0178SAnirudh Venkataramanan /* pf->num_vf_msix includes (VF miscellaneous vector + 3158ede0178SAnirudh Venkataramanan * data queue interrupts). Since vsi->num_q_vectors is number 3168ede0178SAnirudh Venkataramanan * of queues vectors, subtract 1 from the original vector 3178ede0178SAnirudh Venkataramanan * count 3188ede0178SAnirudh Venkataramanan */ 3198ede0178SAnirudh Venkataramanan vsi->num_q_vectors = pf->num_vf_msix - 1; 3208ede0178SAnirudh Venkataramanan break; 32128c2a645SAnirudh Venkataramanan default: 322819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 32328c2a645SAnirudh Venkataramanan break; 32428c2a645SAnirudh Venkataramanan } 325ad71b256SBrett Creeley 326ad71b256SBrett Creeley ice_vsi_set_num_desc(vsi); 32728c2a645SAnirudh Venkataramanan } 32828c2a645SAnirudh Venkataramanan 32928c2a645SAnirudh Venkataramanan /** 33028c2a645SAnirudh Venkataramanan * ice_get_free_slot - get the next non-NULL location index in array 33128c2a645SAnirudh Venkataramanan * @array: array to search 33228c2a645SAnirudh Venkataramanan * @size: size of the array 33328c2a645SAnirudh Venkataramanan * @curr: last known occupied index to be used as a search hint 33428c2a645SAnirudh Venkataramanan * 33528c2a645SAnirudh Venkataramanan * void * is being used to keep the functionality generic. This lets us use this 33628c2a645SAnirudh Venkataramanan * function on any array of pointers. 33728c2a645SAnirudh Venkataramanan */ 33837bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr) 33928c2a645SAnirudh Venkataramanan { 34028c2a645SAnirudh Venkataramanan int **tmp_array = (int **)array; 34128c2a645SAnirudh Venkataramanan int next; 34228c2a645SAnirudh Venkataramanan 34328c2a645SAnirudh Venkataramanan if (curr < (size - 1) && !tmp_array[curr + 1]) { 34428c2a645SAnirudh Venkataramanan next = curr + 1; 34528c2a645SAnirudh Venkataramanan } else { 34628c2a645SAnirudh Venkataramanan int i = 0; 34728c2a645SAnirudh Venkataramanan 34828c2a645SAnirudh Venkataramanan while ((i < size) && (tmp_array[i])) 34928c2a645SAnirudh Venkataramanan i++; 35028c2a645SAnirudh Venkataramanan if (i == size) 35128c2a645SAnirudh Venkataramanan next = ICE_NO_VSI; 35228c2a645SAnirudh Venkataramanan else 35328c2a645SAnirudh Venkataramanan next = i; 35428c2a645SAnirudh Venkataramanan } 35528c2a645SAnirudh Venkataramanan return next; 35628c2a645SAnirudh Venkataramanan } 35728c2a645SAnirudh Venkataramanan 35828c2a645SAnirudh Venkataramanan /** 3595153a18eSAnirudh Venkataramanan * ice_vsi_delete - delete a VSI from the switch 3605153a18eSAnirudh Venkataramanan * @vsi: pointer to VSI being removed 3615153a18eSAnirudh Venkataramanan */ 3625153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi) 3635153a18eSAnirudh Venkataramanan { 3645153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 365198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 3665153a18eSAnirudh Venkataramanan enum ice_status status; 3675153a18eSAnirudh Venkataramanan 368198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 369198a666aSBruce Allan if (!ctxt) 370198a666aSBruce Allan return; 371198a666aSBruce Allan 3728ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 373198a666aSBruce Allan ctxt->vf_num = vsi->vf_id; 374198a666aSBruce Allan ctxt->vsi_num = vsi->vsi_num; 3755153a18eSAnirudh Venkataramanan 376198a666aSBruce Allan memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); 3775153a18eSAnirudh Venkataramanan 378198a666aSBruce Allan status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); 3795153a18eSAnirudh Venkataramanan if (status) 3805153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failed to delete VSI %i in FW\n", 3815153a18eSAnirudh Venkataramanan vsi->vsi_num); 382198a666aSBruce Allan 383198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 3845153a18eSAnirudh Venkataramanan } 3855153a18eSAnirudh Venkataramanan 3865153a18eSAnirudh Venkataramanan /** 387a85a3847SBrett Creeley * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI 38807309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 38907309a0eSAnirudh Venkataramanan */ 390a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi) 39107309a0eSAnirudh Venkataramanan { 39207309a0eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 39307309a0eSAnirudh Venkataramanan 39407309a0eSAnirudh Venkataramanan /* free the ring and vector containers */ 395a85a3847SBrett Creeley if (vsi->q_vectors) { 39607309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->q_vectors); 39707309a0eSAnirudh Venkataramanan vsi->q_vectors = NULL; 39807309a0eSAnirudh Venkataramanan } 39907309a0eSAnirudh Venkataramanan if (vsi->tx_rings) { 40007309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 40107309a0eSAnirudh Venkataramanan vsi->tx_rings = NULL; 40207309a0eSAnirudh Venkataramanan } 40307309a0eSAnirudh Venkataramanan if (vsi->rx_rings) { 40407309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 40507309a0eSAnirudh Venkataramanan vsi->rx_rings = NULL; 40607309a0eSAnirudh Venkataramanan } 40707309a0eSAnirudh Venkataramanan } 40807309a0eSAnirudh Venkataramanan 40907309a0eSAnirudh Venkataramanan /** 41007309a0eSAnirudh Venkataramanan * ice_vsi_clear - clean up and deallocate the provided VSI 41107309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 41207309a0eSAnirudh Venkataramanan * 41307309a0eSAnirudh Venkataramanan * This deallocates the VSI's queue resources, removes it from the PF's 41407309a0eSAnirudh Venkataramanan * VSI array if necessary, and deallocates the VSI 41507309a0eSAnirudh Venkataramanan * 41607309a0eSAnirudh Venkataramanan * Returns 0 on success, negative on failure 41707309a0eSAnirudh Venkataramanan */ 41807309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi) 41907309a0eSAnirudh Venkataramanan { 42007309a0eSAnirudh Venkataramanan struct ice_pf *pf = NULL; 42107309a0eSAnirudh Venkataramanan 42207309a0eSAnirudh Venkataramanan if (!vsi) 42307309a0eSAnirudh Venkataramanan return 0; 42407309a0eSAnirudh Venkataramanan 42507309a0eSAnirudh Venkataramanan if (!vsi->back) 42607309a0eSAnirudh Venkataramanan return -EINVAL; 42707309a0eSAnirudh Venkataramanan 42807309a0eSAnirudh Venkataramanan pf = vsi->back; 42907309a0eSAnirudh Venkataramanan 43007309a0eSAnirudh Venkataramanan if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) { 43107309a0eSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "vsi does not exist at pf->vsi[%d]\n", 43207309a0eSAnirudh Venkataramanan vsi->idx); 43307309a0eSAnirudh Venkataramanan return -EINVAL; 43407309a0eSAnirudh Venkataramanan } 43507309a0eSAnirudh Venkataramanan 43607309a0eSAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 43707309a0eSAnirudh Venkataramanan /* updates the PF for this cleared VSI */ 43807309a0eSAnirudh Venkataramanan 43907309a0eSAnirudh Venkataramanan pf->vsi[vsi->idx] = NULL; 44007309a0eSAnirudh Venkataramanan if (vsi->idx < pf->next_vsi) 44107309a0eSAnirudh Venkataramanan pf->next_vsi = vsi->idx; 44207309a0eSAnirudh Venkataramanan 443a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 44407309a0eSAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 44507309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 44607309a0eSAnirudh Venkataramanan 44707309a0eSAnirudh Venkataramanan return 0; 44807309a0eSAnirudh Venkataramanan } 44907309a0eSAnirudh Venkataramanan 45007309a0eSAnirudh Venkataramanan /** 4515153a18eSAnirudh Venkataramanan * ice_msix_clean_rings - MSIX mode Interrupt Handler 4525153a18eSAnirudh Venkataramanan * @irq: interrupt number 4535153a18eSAnirudh Venkataramanan * @data: pointer to a q_vector 4545153a18eSAnirudh Venkataramanan */ 455f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data) 4565153a18eSAnirudh Venkataramanan { 4575153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 4585153a18eSAnirudh Venkataramanan 4595153a18eSAnirudh Venkataramanan if (!q_vector->tx.ring && !q_vector->rx.ring) 4605153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 4615153a18eSAnirudh Venkataramanan 4625153a18eSAnirudh Venkataramanan napi_schedule(&q_vector->napi); 4635153a18eSAnirudh Venkataramanan 4645153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 4655153a18eSAnirudh Venkataramanan } 4665153a18eSAnirudh Venkataramanan 4675153a18eSAnirudh Venkataramanan /** 46837bb8390SAnirudh Venkataramanan * ice_vsi_alloc - Allocates the next available struct VSI in the PF 46937bb8390SAnirudh Venkataramanan * @pf: board private structure 47037bb8390SAnirudh Venkataramanan * @type: type of VSI 471f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 47237bb8390SAnirudh Venkataramanan * 47337bb8390SAnirudh Venkataramanan * returns a pointer to a VSI on success, NULL on failure. 47437bb8390SAnirudh Venkataramanan */ 4755743020dSAkeem G Abodunrin static struct ice_vsi * 4765743020dSAkeem G Abodunrin ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type, u16 vf_id) 47737bb8390SAnirudh Venkataramanan { 47837bb8390SAnirudh Venkataramanan struct ice_vsi *vsi = NULL; 47937bb8390SAnirudh Venkataramanan 48037bb8390SAnirudh Venkataramanan /* Need to protect the allocation of the VSIs at the PF level */ 48137bb8390SAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 48237bb8390SAnirudh Venkataramanan 48337bb8390SAnirudh Venkataramanan /* If we have already allocated our maximum number of VSIs, 48437bb8390SAnirudh Venkataramanan * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index 48537bb8390SAnirudh Venkataramanan * is available to be populated 48637bb8390SAnirudh Venkataramanan */ 48737bb8390SAnirudh Venkataramanan if (pf->next_vsi == ICE_NO_VSI) { 48837bb8390SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "out of VSI slots!\n"); 48937bb8390SAnirudh Venkataramanan goto unlock_pf; 49037bb8390SAnirudh Venkataramanan } 49137bb8390SAnirudh Venkataramanan 49237bb8390SAnirudh Venkataramanan vsi = devm_kzalloc(&pf->pdev->dev, sizeof(*vsi), GFP_KERNEL); 49337bb8390SAnirudh Venkataramanan if (!vsi) 49437bb8390SAnirudh Venkataramanan goto unlock_pf; 49537bb8390SAnirudh Venkataramanan 49637bb8390SAnirudh Venkataramanan vsi->type = type; 49737bb8390SAnirudh Venkataramanan vsi->back = pf; 49837bb8390SAnirudh Venkataramanan set_bit(__ICE_DOWN, vsi->state); 49937bb8390SAnirudh Venkataramanan vsi->idx = pf->next_vsi; 50037bb8390SAnirudh Venkataramanan vsi->work_lmt = ICE_DFLT_IRQ_WORK; 50137bb8390SAnirudh Venkataramanan 5025743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 5035743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf_id); 5045743020dSAkeem G Abodunrin else 5055743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 50637bb8390SAnirudh Venkataramanan 50737bb8390SAnirudh Venkataramanan switch (vsi->type) { 50837bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 509a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 51037bb8390SAnirudh Venkataramanan goto err_rings; 51137bb8390SAnirudh Venkataramanan 51237bb8390SAnirudh Venkataramanan /* Setup default MSIX irq handler for VSI */ 51337bb8390SAnirudh Venkataramanan vsi->irq_handler = ice_msix_clean_rings; 51437bb8390SAnirudh Venkataramanan break; 5158ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 516a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 5178ede0178SAnirudh Venkataramanan goto err_rings; 5188ede0178SAnirudh Venkataramanan break; 51937bb8390SAnirudh Venkataramanan default: 52037bb8390SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 52137bb8390SAnirudh Venkataramanan goto unlock_pf; 52237bb8390SAnirudh Venkataramanan } 52337bb8390SAnirudh Venkataramanan 52437bb8390SAnirudh Venkataramanan /* fill VSI slot in the PF struct */ 52537bb8390SAnirudh Venkataramanan pf->vsi[pf->next_vsi] = vsi; 52637bb8390SAnirudh Venkataramanan 52737bb8390SAnirudh Venkataramanan /* prepare pf->next_vsi for next use */ 52837bb8390SAnirudh Venkataramanan pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi, 52937bb8390SAnirudh Venkataramanan pf->next_vsi); 53037bb8390SAnirudh Venkataramanan goto unlock_pf; 53137bb8390SAnirudh Venkataramanan 53237bb8390SAnirudh Venkataramanan err_rings: 53337bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 53437bb8390SAnirudh Venkataramanan vsi = NULL; 53537bb8390SAnirudh Venkataramanan unlock_pf: 53637bb8390SAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 53737bb8390SAnirudh Venkataramanan return vsi; 53837bb8390SAnirudh Venkataramanan } 53937bb8390SAnirudh Venkataramanan 54037bb8390SAnirudh Venkataramanan /** 54103f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI 54203f7a986SAnirudh Venkataramanan * @qs_cfg: gathered variables needed for PF->VSI queues assignment 543df0f8479SAnirudh Venkataramanan * 54403f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 545df0f8479SAnirudh Venkataramanan */ 54603f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs_contig(struct ice_qs_cfg *qs_cfg) 547df0f8479SAnirudh Venkataramanan { 54803f7a986SAnirudh Venkataramanan int offset, i; 549df0f8479SAnirudh Venkataramanan 55003f7a986SAnirudh Venkataramanan mutex_lock(qs_cfg->qs_mutex); 55103f7a986SAnirudh Venkataramanan offset = bitmap_find_next_zero_area(qs_cfg->pf_map, qs_cfg->pf_map_size, 55203f7a986SAnirudh Venkataramanan 0, qs_cfg->q_count, 0); 55303f7a986SAnirudh Venkataramanan if (offset >= qs_cfg->pf_map_size) { 55403f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 55503f7a986SAnirudh Venkataramanan return -ENOMEM; 556df0f8479SAnirudh Venkataramanan } 557df0f8479SAnirudh Venkataramanan 55803f7a986SAnirudh Venkataramanan bitmap_set(qs_cfg->pf_map, offset, qs_cfg->q_count); 55903f7a986SAnirudh Venkataramanan for (i = 0; i < qs_cfg->q_count; i++) 56003f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = i + offset; 56103f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 562df0f8479SAnirudh Venkataramanan 56303f7a986SAnirudh Venkataramanan return 0; 564df0f8479SAnirudh Venkataramanan } 565df0f8479SAnirudh Venkataramanan 566df0f8479SAnirudh Venkataramanan /** 56703f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs_sc - Assign a scattered queues from PF to VSI 568819d8998SJesse Brandeburg * @qs_cfg: gathered variables needed for pf->vsi queues assignment 569df0f8479SAnirudh Venkataramanan * 57003f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 571df0f8479SAnirudh Venkataramanan */ 57203f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs_sc(struct ice_qs_cfg *qs_cfg) 573df0f8479SAnirudh Venkataramanan { 574df0f8479SAnirudh Venkataramanan int i, index = 0; 575df0f8479SAnirudh Venkataramanan 57603f7a986SAnirudh Venkataramanan mutex_lock(qs_cfg->qs_mutex); 57703f7a986SAnirudh Venkataramanan for (i = 0; i < qs_cfg->q_count; i++) { 57803f7a986SAnirudh Venkataramanan index = find_next_zero_bit(qs_cfg->pf_map, 57903f7a986SAnirudh Venkataramanan qs_cfg->pf_map_size, index); 58003f7a986SAnirudh Venkataramanan if (index >= qs_cfg->pf_map_size) 58103f7a986SAnirudh Venkataramanan goto err_scatter; 58203f7a986SAnirudh Venkataramanan set_bit(index, qs_cfg->pf_map); 58303f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = index; 58403f7a986SAnirudh Venkataramanan } 58503f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 586df0f8479SAnirudh Venkataramanan 587df0f8479SAnirudh Venkataramanan return 0; 58803f7a986SAnirudh Venkataramanan err_scatter: 589df0f8479SAnirudh Venkataramanan for (index = 0; index < i; index++) { 59003f7a986SAnirudh Venkataramanan clear_bit(qs_cfg->vsi_map[index], qs_cfg->pf_map); 59103f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[index + qs_cfg->vsi_map_offset] = 0; 592df0f8479SAnirudh Venkataramanan } 59303f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 594df0f8479SAnirudh Venkataramanan 595df0f8479SAnirudh Venkataramanan return -ENOMEM; 596df0f8479SAnirudh Venkataramanan } 597df0f8479SAnirudh Venkataramanan 598df0f8479SAnirudh Venkataramanan /** 59903f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs - helper function for assigning queues from PF to VSI 6006c2f997aSAnirudh Venkataramanan * @qs_cfg: gathered variables needed for pf->vsi queues assignment 60103f7a986SAnirudh Venkataramanan * 6026c2f997aSAnirudh Venkataramanan * This function first tries to find contiguous space. If it is not successful, 6036c2f997aSAnirudh Venkataramanan * it tries with the scatter approach. 60403f7a986SAnirudh Venkataramanan * 60503f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 60603f7a986SAnirudh Venkataramanan */ 60703f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs(struct ice_qs_cfg *qs_cfg) 60803f7a986SAnirudh Venkataramanan { 60903f7a986SAnirudh Venkataramanan int ret = 0; 61003f7a986SAnirudh Venkataramanan 61103f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs_contig(qs_cfg); 61203f7a986SAnirudh Venkataramanan if (ret) { 61303f7a986SAnirudh Venkataramanan /* contig failed, so try with scatter approach */ 61403f7a986SAnirudh Venkataramanan qs_cfg->mapping_mode = ICE_VSI_MAP_SCATTER; 61503f7a986SAnirudh Venkataramanan qs_cfg->q_count = min_t(u16, qs_cfg->q_count, 61603f7a986SAnirudh Venkataramanan qs_cfg->scatter_count); 61703f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs_sc(qs_cfg); 61803f7a986SAnirudh Venkataramanan } 61903f7a986SAnirudh Venkataramanan return ret; 62003f7a986SAnirudh Venkataramanan } 62103f7a986SAnirudh Venkataramanan 62203f7a986SAnirudh Venkataramanan /** 623df0f8479SAnirudh Venkataramanan * ice_vsi_get_qs - Assign queues from PF to VSI 624df0f8479SAnirudh Venkataramanan * @vsi: the VSI to assign queues to 625df0f8479SAnirudh Venkataramanan * 626df0f8479SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 627df0f8479SAnirudh Venkataramanan */ 62837bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi) 629df0f8479SAnirudh Venkataramanan { 63003f7a986SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 63103f7a986SAnirudh Venkataramanan struct ice_qs_cfg tx_qs_cfg = { 63203f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 63303f7a986SAnirudh Venkataramanan .pf_map = pf->avail_txqs, 63403f7a986SAnirudh Venkataramanan .pf_map_size = ICE_MAX_TXQS, 63503f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_txq, 63603f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_TXQS, 63703f7a986SAnirudh Venkataramanan .vsi_map = vsi->txq_map, 63803f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 63903f7a986SAnirudh Venkataramanan .mapping_mode = vsi->tx_mapping_mode 64003f7a986SAnirudh Venkataramanan }; 64103f7a986SAnirudh Venkataramanan struct ice_qs_cfg rx_qs_cfg = { 64203f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 64303f7a986SAnirudh Venkataramanan .pf_map = pf->avail_rxqs, 64403f7a986SAnirudh Venkataramanan .pf_map_size = ICE_MAX_RXQS, 64503f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_rxq, 64603f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_RXQS, 64703f7a986SAnirudh Venkataramanan .vsi_map = vsi->rxq_map, 64803f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 64903f7a986SAnirudh Venkataramanan .mapping_mode = vsi->rx_mapping_mode 65003f7a986SAnirudh Venkataramanan }; 651df0f8479SAnirudh Venkataramanan int ret = 0; 652df0f8479SAnirudh Venkataramanan 653df0f8479SAnirudh Venkataramanan vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG; 654df0f8479SAnirudh Venkataramanan vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG; 655df0f8479SAnirudh Venkataramanan 65603f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&tx_qs_cfg); 65703f7a986SAnirudh Venkataramanan if (!ret) 65803f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&rx_qs_cfg); 659df0f8479SAnirudh Venkataramanan 660df0f8479SAnirudh Venkataramanan return ret; 661df0f8479SAnirudh Venkataramanan } 662df0f8479SAnirudh Venkataramanan 663df0f8479SAnirudh Venkataramanan /** 6645153a18eSAnirudh Venkataramanan * ice_vsi_put_qs - Release queues from VSI to PF 6655153a18eSAnirudh Venkataramanan * @vsi: the VSI that is going to release queues 6665153a18eSAnirudh Venkataramanan */ 6675153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi) 6685153a18eSAnirudh Venkataramanan { 6695153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 6705153a18eSAnirudh Venkataramanan int i; 6715153a18eSAnirudh Venkataramanan 6725153a18eSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 6735153a18eSAnirudh Venkataramanan 6745153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 6755153a18eSAnirudh Venkataramanan clear_bit(vsi->txq_map[i], pf->avail_txqs); 6765153a18eSAnirudh Venkataramanan vsi->txq_map[i] = ICE_INVAL_Q_INDEX; 6775153a18eSAnirudh Venkataramanan } 6785153a18eSAnirudh Venkataramanan 6795153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 6805153a18eSAnirudh Venkataramanan clear_bit(vsi->rxq_map[i], pf->avail_rxqs); 6815153a18eSAnirudh Venkataramanan vsi->rxq_map[i] = ICE_INVAL_Q_INDEX; 6825153a18eSAnirudh Venkataramanan } 6835153a18eSAnirudh Venkataramanan 6845153a18eSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 6855153a18eSAnirudh Venkataramanan } 6865153a18eSAnirudh Venkataramanan 6875153a18eSAnirudh Venkataramanan /** 688df0f8479SAnirudh Venkataramanan * ice_rss_clean - Delete RSS related VSI structures that hold user inputs 689df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 690df0f8479SAnirudh Venkataramanan */ 691df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi) 692df0f8479SAnirudh Venkataramanan { 693df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 694df0f8479SAnirudh Venkataramanan 695df0f8479SAnirudh Venkataramanan pf = vsi->back; 696df0f8479SAnirudh Venkataramanan 697df0f8479SAnirudh Venkataramanan if (vsi->rss_hkey_user) 698df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_hkey_user); 699df0f8479SAnirudh Venkataramanan if (vsi->rss_lut_user) 700df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_lut_user); 701df0f8479SAnirudh Venkataramanan } 702df0f8479SAnirudh Venkataramanan 703df0f8479SAnirudh Venkataramanan /** 70428c2a645SAnirudh Venkataramanan * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type 70528c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 70628c2a645SAnirudh Venkataramanan */ 70737bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi) 70828c2a645SAnirudh Venkataramanan { 70928c2a645SAnirudh Venkataramanan struct ice_hw_common_caps *cap; 71028c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 71128c2a645SAnirudh Venkataramanan 71228c2a645SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 71328c2a645SAnirudh Venkataramanan vsi->rss_size = 1; 71428c2a645SAnirudh Venkataramanan return; 71528c2a645SAnirudh Venkataramanan } 71628c2a645SAnirudh Venkataramanan 71728c2a645SAnirudh Venkataramanan cap = &pf->hw.func_caps.common_cap; 71828c2a645SAnirudh Venkataramanan switch (vsi->type) { 71928c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 72028c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 72128c2a645SAnirudh Venkataramanan vsi->rss_table_size = cap->rss_table_size; 72228c2a645SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 72328c2a645SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 72428c2a645SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; 72528c2a645SAnirudh Venkataramanan break; 7268ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 7278ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table 7288ede0178SAnirudh Venkataramanan * For VSI_LUT, LUT size should be set to 64 bytes 7298ede0178SAnirudh Venkataramanan */ 7308ede0178SAnirudh Venkataramanan vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 7318ede0178SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 7328ede0178SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 7338ede0178SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 7348ede0178SAnirudh Venkataramanan break; 73528c2a645SAnirudh Venkataramanan default: 73628c2a645SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", 73728c2a645SAnirudh Venkataramanan vsi->type); 73828c2a645SAnirudh Venkataramanan break; 73928c2a645SAnirudh Venkataramanan } 74028c2a645SAnirudh Venkataramanan } 74128c2a645SAnirudh Venkataramanan 74228c2a645SAnirudh Venkataramanan /** 74328c2a645SAnirudh Venkataramanan * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI 74428c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 74528c2a645SAnirudh Venkataramanan * 74628c2a645SAnirudh Venkataramanan * This initializes a default VSI context for all sections except the Queues. 74728c2a645SAnirudh Venkataramanan */ 74828c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) 74928c2a645SAnirudh Venkataramanan { 75028c2a645SAnirudh Venkataramanan u32 table = 0; 75128c2a645SAnirudh Venkataramanan 75228c2a645SAnirudh Venkataramanan memset(&ctxt->info, 0, sizeof(ctxt->info)); 75328c2a645SAnirudh Venkataramanan /* VSI's should be allocated from shared pool */ 75428c2a645SAnirudh Venkataramanan ctxt->alloc_from_pool = true; 75528c2a645SAnirudh Venkataramanan /* Src pruning enabled by default */ 75628c2a645SAnirudh Venkataramanan ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; 75728c2a645SAnirudh Venkataramanan /* Traffic from VSI can be sent to LAN */ 75828c2a645SAnirudh Venkataramanan ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; 75928c2a645SAnirudh Venkataramanan /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy 76028c2a645SAnirudh Venkataramanan * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all 76128c2a645SAnirudh Venkataramanan * packets untagged/tagged. 76228c2a645SAnirudh Venkataramanan */ 76328c2a645SAnirudh Venkataramanan ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & 76428c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_M) >> 76528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_S); 76628c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for both ingress/egress tables */ 76728c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(0, 0); 76828c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(1, 1); 76928c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(2, 2); 77028c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(3, 3); 77128c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(4, 4); 77228c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(5, 5); 77328c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(6, 6); 77428c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(7, 7); 77528c2a645SAnirudh Venkataramanan ctxt->info.ingress_table = cpu_to_le32(table); 77628c2a645SAnirudh Venkataramanan ctxt->info.egress_table = cpu_to_le32(table); 77728c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for outer to inner UP table */ 77828c2a645SAnirudh Venkataramanan ctxt->info.outer_up_table = cpu_to_le32(table); 77928c2a645SAnirudh Venkataramanan /* No Outer tag support outer_tag_flags remains to zero */ 78028c2a645SAnirudh Venkataramanan } 78128c2a645SAnirudh Venkataramanan 78228c2a645SAnirudh Venkataramanan /** 78328c2a645SAnirudh Venkataramanan * ice_vsi_setup_q_map - Setup a VSI queue map 78428c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 78528c2a645SAnirudh Venkataramanan * @ctxt: VSI context structure 78628c2a645SAnirudh Venkataramanan */ 78728c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 78828c2a645SAnirudh Venkataramanan { 789c5a2a4a3SUsha Ketineni u16 offset = 0, qmap = 0, tx_count = 0; 79028c2a645SAnirudh Venkataramanan u16 qcount_tx = vsi->alloc_txq; 79128c2a645SAnirudh Venkataramanan u16 qcount_rx = vsi->alloc_rxq; 792c5a2a4a3SUsha Ketineni u16 tx_numq_tc, rx_numq_tc; 793c5a2a4a3SUsha Ketineni u16 pow = 0, max_rss = 0; 79428c2a645SAnirudh Venkataramanan bool ena_tc0 = false; 795c5a2a4a3SUsha Ketineni u8 netdev_tc = 0; 79628c2a645SAnirudh Venkataramanan int i; 79728c2a645SAnirudh Venkataramanan 79828c2a645SAnirudh Venkataramanan /* at least TC0 should be enabled by default */ 79928c2a645SAnirudh Venkataramanan if (vsi->tc_cfg.numtc) { 80028c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(0))) 80128c2a645SAnirudh Venkataramanan ena_tc0 = true; 80228c2a645SAnirudh Venkataramanan } else { 80328c2a645SAnirudh Venkataramanan ena_tc0 = true; 80428c2a645SAnirudh Venkataramanan } 80528c2a645SAnirudh Venkataramanan 80628c2a645SAnirudh Venkataramanan if (ena_tc0) { 80728c2a645SAnirudh Venkataramanan vsi->tc_cfg.numtc++; 80828c2a645SAnirudh Venkataramanan vsi->tc_cfg.ena_tc |= 1; 80928c2a645SAnirudh Venkataramanan } 81028c2a645SAnirudh Venkataramanan 811c5a2a4a3SUsha Ketineni rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc; 812c5a2a4a3SUsha Ketineni if (!rx_numq_tc) 813c5a2a4a3SUsha Ketineni rx_numq_tc = 1; 814c5a2a4a3SUsha Ketineni tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc; 815c5a2a4a3SUsha Ketineni if (!tx_numq_tc) 816c5a2a4a3SUsha Ketineni tx_numq_tc = 1; 81728c2a645SAnirudh Venkataramanan 81828c2a645SAnirudh Venkataramanan /* TC mapping is a function of the number of Rx queues assigned to the 81928c2a645SAnirudh Venkataramanan * VSI for each traffic class and the offset of these queues. 82028c2a645SAnirudh Venkataramanan * The first 10 bits are for queue offset for TC0, next 4 bits for no:of 82128c2a645SAnirudh Venkataramanan * queues allocated to TC0. No:of queues is a power-of-2. 82228c2a645SAnirudh Venkataramanan * 82328c2a645SAnirudh Venkataramanan * If TC is not enabled, the queue offset is set to 0, and allocate one 82428c2a645SAnirudh Venkataramanan * queue, this way, traffic for the given TC will be sent to the default 82528c2a645SAnirudh Venkataramanan * queue. 82628c2a645SAnirudh Venkataramanan * 82728c2a645SAnirudh Venkataramanan * Setup number and offset of Rx queues for all TCs for the VSI 82828c2a645SAnirudh Venkataramanan */ 82928c2a645SAnirudh Venkataramanan 830c5a2a4a3SUsha Ketineni qcount_rx = rx_numq_tc; 831c5a2a4a3SUsha Ketineni 83228c2a645SAnirudh Venkataramanan /* qcount will change if RSS is enabled */ 83328c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) { 8348ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) { 83528c2a645SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) 83628c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_LG_RSS_QS; 83728c2a645SAnirudh Venkataramanan else 83828c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_SMALL_RSS_QS; 839c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, rx_numq_tc, max_rss); 840c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, qcount_rx, vsi->rss_size); 8418ede0178SAnirudh Venkataramanan } 84228c2a645SAnirudh Venkataramanan } 84328c2a645SAnirudh Venkataramanan 84428c2a645SAnirudh Venkataramanan /* find the (rounded up) power-of-2 of qcount */ 845c5a2a4a3SUsha Ketineni pow = order_base_2(qcount_rx); 84628c2a645SAnirudh Venkataramanan 8472bdc97beSBruce Allan ice_for_each_traffic_class(i) { 84828c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 84928c2a645SAnirudh Venkataramanan /* TC is not enabled */ 85028c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = 0; 851c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = 1; 852c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = 1; 853c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = 0; 85428c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = 0; 85528c2a645SAnirudh Venkataramanan continue; 85628c2a645SAnirudh Venkataramanan } 85728c2a645SAnirudh Venkataramanan 85828c2a645SAnirudh Venkataramanan /* TC is enabled */ 85928c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = offset; 860c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx; 861c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc; 862c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 86328c2a645SAnirudh Venkataramanan 86428c2a645SAnirudh Venkataramanan qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 86528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_OFFSET_M) | 86628c2a645SAnirudh Venkataramanan ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 86728c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_NUM_M); 868c5a2a4a3SUsha Ketineni offset += qcount_rx; 869c5a2a4a3SUsha Ketineni tx_count += tx_numq_tc; 87028c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); 87128c2a645SAnirudh Venkataramanan } 87260dcc39eSKiran Patil 87360dcc39eSKiran Patil /* if offset is non-zero, means it is calculated correctly based on 87460dcc39eSKiran Patil * enabled TCs for a given VSI otherwise qcount_rx will always 87560dcc39eSKiran Patil * be correct and non-zero because it is based off - VSI's 87660dcc39eSKiran Patil * allocated Rx queues which is at least 1 (hence qcount_tx will be 87760dcc39eSKiran Patil * at least 1) 87860dcc39eSKiran Patil */ 87960dcc39eSKiran Patil if (offset) 88028c2a645SAnirudh Venkataramanan vsi->num_rxq = offset; 88160dcc39eSKiran Patil else 88260dcc39eSKiran Patil vsi->num_rxq = qcount_rx; 88360dcc39eSKiran Patil 884c5a2a4a3SUsha Ketineni vsi->num_txq = tx_count; 88528c2a645SAnirudh Venkataramanan 8868ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) { 8878ede0178SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n"); 8888ede0178SAnirudh Venkataramanan /* since there is a chance that num_rxq could have been changed 8898ede0178SAnirudh Venkataramanan * in the above for loop, make num_txq equal to num_rxq. 8908ede0178SAnirudh Venkataramanan */ 8918ede0178SAnirudh Venkataramanan vsi->num_txq = vsi->num_rxq; 8928ede0178SAnirudh Venkataramanan } 8938ede0178SAnirudh Venkataramanan 89428c2a645SAnirudh Venkataramanan /* Rx queue mapping */ 89528c2a645SAnirudh Venkataramanan ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 89628c2a645SAnirudh Venkataramanan /* q_mapping buffer holds the info for the first queue allocated for 89728c2a645SAnirudh Venkataramanan * this VSI in the PF space and also the number of queues associated 89828c2a645SAnirudh Venkataramanan * with this VSI. 89928c2a645SAnirudh Venkataramanan */ 90028c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 90128c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq); 90228c2a645SAnirudh Venkataramanan } 90328c2a645SAnirudh Venkataramanan 90428c2a645SAnirudh Venkataramanan /** 90528c2a645SAnirudh Venkataramanan * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI 90628c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 90728c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 90828c2a645SAnirudh Venkataramanan */ 90928c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 91028c2a645SAnirudh Venkataramanan { 91128c2a645SAnirudh Venkataramanan u8 lut_type, hash_type; 912819d8998SJesse Brandeburg struct ice_pf *pf; 913819d8998SJesse Brandeburg 914819d8998SJesse Brandeburg pf = vsi->back; 91528c2a645SAnirudh Venkataramanan 91628c2a645SAnirudh Venkataramanan switch (vsi->type) { 91728c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 91828c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 91928c2a645SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; 92028c2a645SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 92128c2a645SAnirudh Venkataramanan break; 9228ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 9238ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table which is a VSI LUT type */ 9248ede0178SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 9258ede0178SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 9268ede0178SAnirudh Venkataramanan break; 92728c2a645SAnirudh Venkataramanan default: 928819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 92928c2a645SAnirudh Venkataramanan return; 93028c2a645SAnirudh Venkataramanan } 93128c2a645SAnirudh Venkataramanan 93228c2a645SAnirudh Venkataramanan ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & 93328c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | 93428c2a645SAnirudh Venkataramanan ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & 93528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_HASH_M); 93628c2a645SAnirudh Venkataramanan } 93728c2a645SAnirudh Venkataramanan 93828c2a645SAnirudh Venkataramanan /** 93928c2a645SAnirudh Venkataramanan * ice_vsi_init - Create and initialize a VSI 94028c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 94128c2a645SAnirudh Venkataramanan * 94228c2a645SAnirudh Venkataramanan * This initializes a VSI context depending on the VSI type to be added and 94328c2a645SAnirudh Venkataramanan * passes it down to the add_vsi aq command to create a new VSI. 94428c2a645SAnirudh Venkataramanan */ 94537bb8390SAnirudh Venkataramanan static int ice_vsi_init(struct ice_vsi *vsi) 94628c2a645SAnirudh Venkataramanan { 94728c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 94828c2a645SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 949198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 95028c2a645SAnirudh Venkataramanan int ret = 0; 95128c2a645SAnirudh Venkataramanan 952198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 953198a666aSBruce Allan if (!ctxt) 954198a666aSBruce Allan return -ENOMEM; 955198a666aSBruce Allan 956cb93a952SAkeem G Abodunrin ctxt->info = vsi->info; 95728c2a645SAnirudh Venkataramanan switch (vsi->type) { 95828c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 959198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_PF; 96028c2a645SAnirudh Venkataramanan break; 9618ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 962198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_VF; 9638ede0178SAnirudh Venkataramanan /* VF number here is the absolute VF number (0-255) */ 964198a666aSBruce Allan ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; 9658ede0178SAnirudh Venkataramanan break; 96628c2a645SAnirudh Venkataramanan default: 96728c2a645SAnirudh Venkataramanan return -ENODEV; 96828c2a645SAnirudh Venkataramanan } 96928c2a645SAnirudh Venkataramanan 970198a666aSBruce Allan ice_set_dflt_vsi_ctx(ctxt); 97128c2a645SAnirudh Venkataramanan /* if the switch is in VEB mode, allow VSI loopback */ 97228c2a645SAnirudh Venkataramanan if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) 973198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 97428c2a645SAnirudh Venkataramanan 97528c2a645SAnirudh Venkataramanan /* Set LUT type and HASH type if RSS is enabled */ 97628c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 977198a666aSBruce Allan ice_set_rss_vsi_ctx(ctxt, vsi); 97828c2a645SAnirudh Venkataramanan 979198a666aSBruce Allan ctxt->info.sw_id = vsi->port_info->sw_id; 980198a666aSBruce Allan ice_vsi_setup_q_map(vsi, ctxt); 98128c2a645SAnirudh Venkataramanan 982cb93a952SAkeem G Abodunrin /* Enable MAC Antispoof with new VSI being initialized or updated */ 983cb93a952SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF && pf->vf[vsi->vf_id].spoofchk) { 984cb93a952SAkeem G Abodunrin ctxt->info.valid_sections |= 985cb93a952SAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 986cb93a952SAkeem G Abodunrin ctxt->info.sec_flags |= 987cb93a952SAkeem G Abodunrin ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; 988cb93a952SAkeem G Abodunrin } 989cb93a952SAkeem G Abodunrin 990198a666aSBruce Allan ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); 99128c2a645SAnirudh Venkataramanan if (ret) { 99228c2a645SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 99328c2a645SAnirudh Venkataramanan "Add VSI failed, err %d\n", ret); 99428c2a645SAnirudh Venkataramanan return -EIO; 99528c2a645SAnirudh Venkataramanan } 99628c2a645SAnirudh Venkataramanan 99728c2a645SAnirudh Venkataramanan /* keep context for update VSI operations */ 998198a666aSBruce Allan vsi->info = ctxt->info; 99928c2a645SAnirudh Venkataramanan 100028c2a645SAnirudh Venkataramanan /* record VSI number returned */ 1001198a666aSBruce Allan vsi->vsi_num = ctxt->vsi_num; 100228c2a645SAnirudh Venkataramanan 1003198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 100428c2a645SAnirudh Venkataramanan return ret; 100528c2a645SAnirudh Venkataramanan } 100628c2a645SAnirudh Venkataramanan 100728c2a645SAnirudh Venkataramanan /** 1008df0f8479SAnirudh Venkataramanan * ice_free_q_vector - Free memory allocated for a specific interrupt vector 1009df0f8479SAnirudh Venkataramanan * @vsi: VSI having the memory freed 1010df0f8479SAnirudh Venkataramanan * @v_idx: index of the vector to be freed 1011df0f8479SAnirudh Venkataramanan */ 1012df0f8479SAnirudh Venkataramanan static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx) 1013df0f8479SAnirudh Venkataramanan { 1014df0f8479SAnirudh Venkataramanan struct ice_q_vector *q_vector; 1015819d8998SJesse Brandeburg struct ice_pf *pf = vsi->back; 1016df0f8479SAnirudh Venkataramanan struct ice_ring *ring; 1017df0f8479SAnirudh Venkataramanan 1018df0f8479SAnirudh Venkataramanan if (!vsi->q_vectors[v_idx]) { 1019819d8998SJesse Brandeburg dev_dbg(&pf->pdev->dev, "Queue vector at index %d not found\n", 1020df0f8479SAnirudh Venkataramanan v_idx); 1021df0f8479SAnirudh Venkataramanan return; 1022df0f8479SAnirudh Venkataramanan } 1023df0f8479SAnirudh Venkataramanan q_vector = vsi->q_vectors[v_idx]; 1024df0f8479SAnirudh Venkataramanan 1025df0f8479SAnirudh Venkataramanan ice_for_each_ring(ring, q_vector->tx) 1026df0f8479SAnirudh Venkataramanan ring->q_vector = NULL; 1027df0f8479SAnirudh Venkataramanan ice_for_each_ring(ring, q_vector->rx) 1028df0f8479SAnirudh Venkataramanan ring->q_vector = NULL; 1029df0f8479SAnirudh Venkataramanan 1030df0f8479SAnirudh Venkataramanan /* only VSI with an associated netdev is set up with NAPI */ 1031df0f8479SAnirudh Venkataramanan if (vsi->netdev) 1032df0f8479SAnirudh Venkataramanan netif_napi_del(&q_vector->napi); 1033df0f8479SAnirudh Venkataramanan 1034819d8998SJesse Brandeburg devm_kfree(&pf->pdev->dev, q_vector); 1035df0f8479SAnirudh Venkataramanan vsi->q_vectors[v_idx] = NULL; 1036df0f8479SAnirudh Venkataramanan } 1037df0f8479SAnirudh Venkataramanan 1038df0f8479SAnirudh Venkataramanan /** 1039df0f8479SAnirudh Venkataramanan * ice_vsi_free_q_vectors - Free memory allocated for interrupt vectors 1040df0f8479SAnirudh Venkataramanan * @vsi: the VSI having memory freed 1041df0f8479SAnirudh Venkataramanan */ 1042df0f8479SAnirudh Venkataramanan void ice_vsi_free_q_vectors(struct ice_vsi *vsi) 1043df0f8479SAnirudh Venkataramanan { 1044df0f8479SAnirudh Venkataramanan int v_idx; 1045df0f8479SAnirudh Venkataramanan 10460c2561c8SBrett Creeley ice_for_each_q_vector(vsi, v_idx) 1047df0f8479SAnirudh Venkataramanan ice_free_q_vector(vsi, v_idx); 1048df0f8479SAnirudh Venkataramanan } 1049df0f8479SAnirudh Venkataramanan 1050df0f8479SAnirudh Venkataramanan /** 1051df0f8479SAnirudh Venkataramanan * ice_vsi_alloc_q_vector - Allocate memory for a single interrupt vector 1052df0f8479SAnirudh Venkataramanan * @vsi: the VSI being configured 1053df0f8479SAnirudh Venkataramanan * @v_idx: index of the vector in the VSI struct 1054df0f8479SAnirudh Venkataramanan * 1055df0f8479SAnirudh Venkataramanan * We allocate one q_vector. If allocation fails we return -ENOMEM. 1056df0f8479SAnirudh Venkataramanan */ 1057df0f8479SAnirudh Venkataramanan static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, int v_idx) 1058df0f8479SAnirudh Venkataramanan { 1059df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1060df0f8479SAnirudh Venkataramanan struct ice_q_vector *q_vector; 1061df0f8479SAnirudh Venkataramanan 1062df0f8479SAnirudh Venkataramanan /* allocate q_vector */ 1063df0f8479SAnirudh Venkataramanan q_vector = devm_kzalloc(&pf->pdev->dev, sizeof(*q_vector), GFP_KERNEL); 1064df0f8479SAnirudh Venkataramanan if (!q_vector) 1065df0f8479SAnirudh Venkataramanan return -ENOMEM; 1066df0f8479SAnirudh Venkataramanan 1067df0f8479SAnirudh Venkataramanan q_vector->vsi = vsi; 1068df0f8479SAnirudh Venkataramanan q_vector->v_idx = v_idx; 10698ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 10708ede0178SAnirudh Venkataramanan goto out; 1071df0f8479SAnirudh Venkataramanan /* only set affinity_mask if the CPU is online */ 1072df0f8479SAnirudh Venkataramanan if (cpu_online(v_idx)) 1073df0f8479SAnirudh Venkataramanan cpumask_set_cpu(v_idx, &q_vector->affinity_mask); 1074df0f8479SAnirudh Venkataramanan 1075df0f8479SAnirudh Venkataramanan /* This will not be called in the driver load path because the netdev 1076df0f8479SAnirudh Venkataramanan * will not be created yet. All other cases with register the NAPI 1077df0f8479SAnirudh Venkataramanan * handler here (i.e. resume, reset/rebuild, etc.) 1078df0f8479SAnirudh Venkataramanan */ 1079df0f8479SAnirudh Venkataramanan if (vsi->netdev) 1080df0f8479SAnirudh Venkataramanan netif_napi_add(vsi->netdev, &q_vector->napi, ice_napi_poll, 1081df0f8479SAnirudh Venkataramanan NAPI_POLL_WEIGHT); 1082df0f8479SAnirudh Venkataramanan 10838ede0178SAnirudh Venkataramanan out: 1084df0f8479SAnirudh Venkataramanan /* tie q_vector and VSI together */ 1085df0f8479SAnirudh Venkataramanan vsi->q_vectors[v_idx] = q_vector; 1086df0f8479SAnirudh Venkataramanan 1087df0f8479SAnirudh Venkataramanan return 0; 1088df0f8479SAnirudh Venkataramanan } 1089df0f8479SAnirudh Venkataramanan 1090df0f8479SAnirudh Venkataramanan /** 1091df0f8479SAnirudh Venkataramanan * ice_vsi_alloc_q_vectors - Allocate memory for interrupt vectors 1092df0f8479SAnirudh Venkataramanan * @vsi: the VSI being configured 1093df0f8479SAnirudh Venkataramanan * 1094df0f8479SAnirudh Venkataramanan * We allocate one q_vector per queue interrupt. If allocation fails we 1095df0f8479SAnirudh Venkataramanan * return -ENOMEM. 1096df0f8479SAnirudh Venkataramanan */ 109737bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_q_vectors(struct ice_vsi *vsi) 1098df0f8479SAnirudh Venkataramanan { 1099df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1100df0f8479SAnirudh Venkataramanan int v_idx = 0, num_q_vectors; 1101df0f8479SAnirudh Venkataramanan int err; 1102df0f8479SAnirudh Venkataramanan 1103df0f8479SAnirudh Venkataramanan if (vsi->q_vectors[0]) { 1104df0f8479SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "VSI %d has existing q_vectors\n", 1105df0f8479SAnirudh Venkataramanan vsi->vsi_num); 1106df0f8479SAnirudh Venkataramanan return -EEXIST; 1107df0f8479SAnirudh Venkataramanan } 1108df0f8479SAnirudh Venkataramanan 1109df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 1110df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1111df0f8479SAnirudh Venkataramanan } else { 1112df0f8479SAnirudh Venkataramanan err = -EINVAL; 1113df0f8479SAnirudh Venkataramanan goto err_out; 1114df0f8479SAnirudh Venkataramanan } 1115df0f8479SAnirudh Venkataramanan 1116df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < num_q_vectors; v_idx++) { 1117df0f8479SAnirudh Venkataramanan err = ice_vsi_alloc_q_vector(vsi, v_idx); 1118df0f8479SAnirudh Venkataramanan if (err) 1119df0f8479SAnirudh Venkataramanan goto err_out; 1120df0f8479SAnirudh Venkataramanan } 1121df0f8479SAnirudh Venkataramanan 1122df0f8479SAnirudh Venkataramanan return 0; 1123df0f8479SAnirudh Venkataramanan 1124df0f8479SAnirudh Venkataramanan err_out: 1125df0f8479SAnirudh Venkataramanan while (v_idx--) 1126df0f8479SAnirudh Venkataramanan ice_free_q_vector(vsi, v_idx); 1127df0f8479SAnirudh Venkataramanan 1128df0f8479SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1129df0f8479SAnirudh Venkataramanan "Failed to allocate %d q_vector for VSI %d, ret=%d\n", 1130df0f8479SAnirudh Venkataramanan vsi->num_q_vectors, vsi->vsi_num, err); 1131df0f8479SAnirudh Venkataramanan vsi->num_q_vectors = 0; 1132df0f8479SAnirudh Venkataramanan return err; 1133df0f8479SAnirudh Venkataramanan } 1134df0f8479SAnirudh Venkataramanan 1135df0f8479SAnirudh Venkataramanan /** 1136df0f8479SAnirudh Venkataramanan * ice_vsi_setup_vector_base - Set up the base vector for the given VSI 1137df0f8479SAnirudh Venkataramanan * @vsi: ptr to the VSI 1138df0f8479SAnirudh Venkataramanan * 1139df0f8479SAnirudh Venkataramanan * This should only be called after ice_vsi_alloc() which allocates the 1140df0f8479SAnirudh Venkataramanan * corresponding SW VSI structure and initializes num_queue_pairs for the 1141df0f8479SAnirudh Venkataramanan * newly allocated VSI. 1142df0f8479SAnirudh Venkataramanan * 1143df0f8479SAnirudh Venkataramanan * Returns 0 on success or negative on failure 1144df0f8479SAnirudh Venkataramanan */ 114537bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) 1146df0f8479SAnirudh Venkataramanan { 1147df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1148df0f8479SAnirudh Venkataramanan int num_q_vectors = 0; 1149df0f8479SAnirudh Venkataramanan 1150eb0208ecSPreethi Banala if (vsi->sw_base_vector || vsi->hw_base_vector) { 1151eb0208ecSPreethi Banala dev_dbg(&pf->pdev->dev, "VSI %d has non-zero HW base vector %d or SW base vector %d\n", 1152eb0208ecSPreethi Banala vsi->vsi_num, vsi->hw_base_vector, vsi->sw_base_vector); 1153df0f8479SAnirudh Venkataramanan return -EEXIST; 1154df0f8479SAnirudh Venkataramanan } 1155df0f8479SAnirudh Venkataramanan 1156df0f8479SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 1157df0f8479SAnirudh Venkataramanan return -ENOENT; 1158df0f8479SAnirudh Venkataramanan 1159df0f8479SAnirudh Venkataramanan switch (vsi->type) { 1160df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 1161df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1162eb0208ecSPreethi Banala /* reserve slots from OS requested IRQs */ 1163eb0208ecSPreethi Banala vsi->sw_base_vector = ice_get_res(pf, pf->sw_irq_tracker, 1164eb0208ecSPreethi Banala num_q_vectors, vsi->idx); 1165eb0208ecSPreethi Banala if (vsi->sw_base_vector < 0) { 1166eb0208ecSPreethi Banala dev_err(&pf->pdev->dev, 1167eb0208ecSPreethi Banala "Failed to get tracking for %d SW vectors for VSI %d, err=%d\n", 1168eb0208ecSPreethi Banala num_q_vectors, vsi->vsi_num, 1169eb0208ecSPreethi Banala vsi->sw_base_vector); 1170eb0208ecSPreethi Banala return -ENOENT; 1171eb0208ecSPreethi Banala } 1172eb0208ecSPreethi Banala pf->num_avail_sw_msix -= num_q_vectors; 1173eb0208ecSPreethi Banala 1174eb0208ecSPreethi Banala /* reserve slots from HW interrupts */ 1175eb0208ecSPreethi Banala vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker, 1176eb0208ecSPreethi Banala num_q_vectors, vsi->idx); 1177df0f8479SAnirudh Venkataramanan break; 11788ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 11798ede0178SAnirudh Venkataramanan /* take VF misc vector and data vectors into account */ 11808ede0178SAnirudh Venkataramanan num_q_vectors = pf->num_vf_msix; 11818ede0178SAnirudh Venkataramanan /* For VF VSI, reserve slots only from HW interrupts */ 11828ede0178SAnirudh Venkataramanan vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker, 11838ede0178SAnirudh Venkataramanan num_q_vectors, vsi->idx); 11848ede0178SAnirudh Venkataramanan break; 1185df0f8479SAnirudh Venkataramanan default: 1186819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 1187df0f8479SAnirudh Venkataramanan break; 1188df0f8479SAnirudh Venkataramanan } 1189df0f8479SAnirudh Venkataramanan 1190eb0208ecSPreethi Banala if (vsi->hw_base_vector < 0) { 1191df0f8479SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1192eb0208ecSPreethi Banala "Failed to get tracking for %d HW vectors for VSI %d, err=%d\n", 1193eb0208ecSPreethi Banala num_q_vectors, vsi->vsi_num, vsi->hw_base_vector); 11948ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 1195819d8998SJesse Brandeburg ice_free_res(pf->sw_irq_tracker, 11968ede0178SAnirudh Venkataramanan vsi->sw_base_vector, vsi->idx); 1197eb0208ecSPreethi Banala pf->num_avail_sw_msix += num_q_vectors; 11988ede0178SAnirudh Venkataramanan } 1199df0f8479SAnirudh Venkataramanan return -ENOENT; 1200df0f8479SAnirudh Venkataramanan } 1201df0f8479SAnirudh Venkataramanan 1202eb0208ecSPreethi Banala pf->num_avail_hw_msix -= num_q_vectors; 1203eb0208ecSPreethi Banala 1204df0f8479SAnirudh Venkataramanan return 0; 1205df0f8479SAnirudh Venkataramanan } 1206df0f8479SAnirudh Venkataramanan 1207df0f8479SAnirudh Venkataramanan /** 120828c2a645SAnirudh Venkataramanan * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI 120928c2a645SAnirudh Venkataramanan * @vsi: the VSI having rings deallocated 121028c2a645SAnirudh Venkataramanan */ 1211df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi) 121228c2a645SAnirudh Venkataramanan { 121328c2a645SAnirudh Venkataramanan int i; 121428c2a645SAnirudh Venkataramanan 121528c2a645SAnirudh Venkataramanan if (vsi->tx_rings) { 121628c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 121728c2a645SAnirudh Venkataramanan if (vsi->tx_rings[i]) { 121828c2a645SAnirudh Venkataramanan kfree_rcu(vsi->tx_rings[i], rcu); 121928c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = NULL; 122028c2a645SAnirudh Venkataramanan } 122128c2a645SAnirudh Venkataramanan } 122228c2a645SAnirudh Venkataramanan } 122328c2a645SAnirudh Venkataramanan if (vsi->rx_rings) { 122428c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 122528c2a645SAnirudh Venkataramanan if (vsi->rx_rings[i]) { 122628c2a645SAnirudh Venkataramanan kfree_rcu(vsi->rx_rings[i], rcu); 122728c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = NULL; 122828c2a645SAnirudh Venkataramanan } 122928c2a645SAnirudh Venkataramanan } 123028c2a645SAnirudh Venkataramanan } 123128c2a645SAnirudh Venkataramanan } 123228c2a645SAnirudh Venkataramanan 123328c2a645SAnirudh Venkataramanan /** 123428c2a645SAnirudh Venkataramanan * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI 123528c2a645SAnirudh Venkataramanan * @vsi: VSI which is having rings allocated 123628c2a645SAnirudh Venkataramanan */ 123737bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi) 123828c2a645SAnirudh Venkataramanan { 123928c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 124028c2a645SAnirudh Venkataramanan int i; 124128c2a645SAnirudh Venkataramanan 1242d337f2afSAnirudh Venkataramanan /* Allocate Tx rings */ 124328c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 124428c2a645SAnirudh Venkataramanan struct ice_ring *ring; 124528c2a645SAnirudh Venkataramanan 124628c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 124728c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 124828c2a645SAnirudh Venkataramanan 124928c2a645SAnirudh Venkataramanan if (!ring) 125028c2a645SAnirudh Venkataramanan goto err_out; 125128c2a645SAnirudh Venkataramanan 125228c2a645SAnirudh Venkataramanan ring->q_index = i; 125328c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->txq_map[i]; 125428c2a645SAnirudh Venkataramanan ring->ring_active = false; 125528c2a645SAnirudh Venkataramanan ring->vsi = vsi; 125628c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 1257ad71b256SBrett Creeley ring->count = vsi->num_tx_desc; 125828c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = ring; 125928c2a645SAnirudh Venkataramanan } 126028c2a645SAnirudh Venkataramanan 1261d337f2afSAnirudh Venkataramanan /* Allocate Rx rings */ 126228c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 126328c2a645SAnirudh Venkataramanan struct ice_ring *ring; 126428c2a645SAnirudh Venkataramanan 126528c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 126628c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 126728c2a645SAnirudh Venkataramanan if (!ring) 126828c2a645SAnirudh Venkataramanan goto err_out; 126928c2a645SAnirudh Venkataramanan 127028c2a645SAnirudh Venkataramanan ring->q_index = i; 127128c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->rxq_map[i]; 127228c2a645SAnirudh Venkataramanan ring->ring_active = false; 127328c2a645SAnirudh Venkataramanan ring->vsi = vsi; 127428c2a645SAnirudh Venkataramanan ring->netdev = vsi->netdev; 127528c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 1276ad71b256SBrett Creeley ring->count = vsi->num_rx_desc; 127728c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = ring; 127828c2a645SAnirudh Venkataramanan } 127928c2a645SAnirudh Venkataramanan 128028c2a645SAnirudh Venkataramanan return 0; 128128c2a645SAnirudh Venkataramanan 128228c2a645SAnirudh Venkataramanan err_out: 128328c2a645SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 128428c2a645SAnirudh Venkataramanan return -ENOMEM; 128528c2a645SAnirudh Venkataramanan } 128628c2a645SAnirudh Venkataramanan 128728c2a645SAnirudh Venkataramanan /** 128807309a0eSAnirudh Venkataramanan * ice_vsi_map_rings_to_vectors - Map VSI rings to interrupt vectors 128907309a0eSAnirudh Venkataramanan * @vsi: the VSI being configured 129007309a0eSAnirudh Venkataramanan * 129107309a0eSAnirudh Venkataramanan * This function maps descriptor rings to the queue-specific vectors allotted 129207309a0eSAnirudh Venkataramanan * through the MSI-X enabling code. On a constrained vector budget, we map Tx 129307309a0eSAnirudh Venkataramanan * and Rx rings to the vector as "efficiently" as possible. 129407309a0eSAnirudh Venkataramanan */ 12957b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 12967b9ffc76SAnirudh Venkataramanan void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi) 12977b9ffc76SAnirudh Venkataramanan #else 129837bb8390SAnirudh Venkataramanan static void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi) 12997b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 130007309a0eSAnirudh Venkataramanan { 130107309a0eSAnirudh Venkataramanan int q_vectors = vsi->num_q_vectors; 130207309a0eSAnirudh Venkataramanan int tx_rings_rem, rx_rings_rem; 130307309a0eSAnirudh Venkataramanan int v_id; 130407309a0eSAnirudh Venkataramanan 130507309a0eSAnirudh Venkataramanan /* initially assigning remaining rings count to VSIs num queue value */ 130607309a0eSAnirudh Venkataramanan tx_rings_rem = vsi->num_txq; 130707309a0eSAnirudh Venkataramanan rx_rings_rem = vsi->num_rxq; 130807309a0eSAnirudh Venkataramanan 130907309a0eSAnirudh Venkataramanan for (v_id = 0; v_id < q_vectors; v_id++) { 131007309a0eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[v_id]; 131107309a0eSAnirudh Venkataramanan int tx_rings_per_v, rx_rings_per_v, q_id, q_base; 131207309a0eSAnirudh Venkataramanan 131307309a0eSAnirudh Venkataramanan /* Tx rings mapping to vector */ 131407309a0eSAnirudh Venkataramanan tx_rings_per_v = DIV_ROUND_UP(tx_rings_rem, q_vectors - v_id); 131507309a0eSAnirudh Venkataramanan q_vector->num_ring_tx = tx_rings_per_v; 131607309a0eSAnirudh Venkataramanan q_vector->tx.ring = NULL; 1317d2b464a7SBrett Creeley q_vector->tx.itr_idx = ICE_TX_ITR; 131807309a0eSAnirudh Venkataramanan q_base = vsi->num_txq - tx_rings_rem; 131907309a0eSAnirudh Venkataramanan 132007309a0eSAnirudh Venkataramanan for (q_id = q_base; q_id < (q_base + tx_rings_per_v); q_id++) { 132107309a0eSAnirudh Venkataramanan struct ice_ring *tx_ring = vsi->tx_rings[q_id]; 132207309a0eSAnirudh Venkataramanan 132307309a0eSAnirudh Venkataramanan tx_ring->q_vector = q_vector; 132407309a0eSAnirudh Venkataramanan tx_ring->next = q_vector->tx.ring; 132507309a0eSAnirudh Venkataramanan q_vector->tx.ring = tx_ring; 132607309a0eSAnirudh Venkataramanan } 132707309a0eSAnirudh Venkataramanan tx_rings_rem -= tx_rings_per_v; 132807309a0eSAnirudh Venkataramanan 132907309a0eSAnirudh Venkataramanan /* Rx rings mapping to vector */ 133007309a0eSAnirudh Venkataramanan rx_rings_per_v = DIV_ROUND_UP(rx_rings_rem, q_vectors - v_id); 133107309a0eSAnirudh Venkataramanan q_vector->num_ring_rx = rx_rings_per_v; 133207309a0eSAnirudh Venkataramanan q_vector->rx.ring = NULL; 1333d2b464a7SBrett Creeley q_vector->rx.itr_idx = ICE_RX_ITR; 133407309a0eSAnirudh Venkataramanan q_base = vsi->num_rxq - rx_rings_rem; 133507309a0eSAnirudh Venkataramanan 133607309a0eSAnirudh Venkataramanan for (q_id = q_base; q_id < (q_base + rx_rings_per_v); q_id++) { 133707309a0eSAnirudh Venkataramanan struct ice_ring *rx_ring = vsi->rx_rings[q_id]; 133807309a0eSAnirudh Venkataramanan 133907309a0eSAnirudh Venkataramanan rx_ring->q_vector = q_vector; 134007309a0eSAnirudh Venkataramanan rx_ring->next = q_vector->rx.ring; 134107309a0eSAnirudh Venkataramanan q_vector->rx.ring = rx_ring; 134207309a0eSAnirudh Venkataramanan } 134307309a0eSAnirudh Venkataramanan rx_rings_rem -= rx_rings_per_v; 134407309a0eSAnirudh Venkataramanan } 134507309a0eSAnirudh Venkataramanan } 134607309a0eSAnirudh Venkataramanan 134707309a0eSAnirudh Venkataramanan /** 1348492af0abSMd Fahad Iqbal Polash * ice_vsi_manage_rss_lut - disable/enable RSS 1349492af0abSMd Fahad Iqbal Polash * @vsi: the VSI being changed 1350492af0abSMd Fahad Iqbal Polash * @ena: boolean value indicating if this is an enable or disable request 1351492af0abSMd Fahad Iqbal Polash * 1352492af0abSMd Fahad Iqbal Polash * In the event of disable request for RSS, this function will zero out RSS 1353492af0abSMd Fahad Iqbal Polash * LUT, while in the event of enable request for RSS, it will reconfigure RSS 1354492af0abSMd Fahad Iqbal Polash * LUT. 1355492af0abSMd Fahad Iqbal Polash */ 1356492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena) 1357492af0abSMd Fahad Iqbal Polash { 1358492af0abSMd Fahad Iqbal Polash int err = 0; 1359492af0abSMd Fahad Iqbal Polash u8 *lut; 1360492af0abSMd Fahad Iqbal Polash 1361492af0abSMd Fahad Iqbal Polash lut = devm_kzalloc(&vsi->back->pdev->dev, vsi->rss_table_size, 1362492af0abSMd Fahad Iqbal Polash GFP_KERNEL); 1363492af0abSMd Fahad Iqbal Polash if (!lut) 1364492af0abSMd Fahad Iqbal Polash return -ENOMEM; 1365492af0abSMd Fahad Iqbal Polash 1366492af0abSMd Fahad Iqbal Polash if (ena) { 1367492af0abSMd Fahad Iqbal Polash if (vsi->rss_lut_user) 1368492af0abSMd Fahad Iqbal Polash memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 1369492af0abSMd Fahad Iqbal Polash else 1370492af0abSMd Fahad Iqbal Polash ice_fill_rss_lut(lut, vsi->rss_table_size, 1371492af0abSMd Fahad Iqbal Polash vsi->rss_size); 1372492af0abSMd Fahad Iqbal Polash } 1373492af0abSMd Fahad Iqbal Polash 1374492af0abSMd Fahad Iqbal Polash err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size); 1375492af0abSMd Fahad Iqbal Polash devm_kfree(&vsi->back->pdev->dev, lut); 1376492af0abSMd Fahad Iqbal Polash return err; 1377492af0abSMd Fahad Iqbal Polash } 1378492af0abSMd Fahad Iqbal Polash 1379492af0abSMd Fahad Iqbal Polash /** 138037bb8390SAnirudh Venkataramanan * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI 138137bb8390SAnirudh Venkataramanan * @vsi: VSI to be configured 138237bb8390SAnirudh Venkataramanan */ 138337bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi) 138437bb8390SAnirudh Venkataramanan { 138537bb8390SAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *key; 138637bb8390SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 138737bb8390SAnirudh Venkataramanan enum ice_status status; 138837bb8390SAnirudh Venkataramanan int err = 0; 138937bb8390SAnirudh Venkataramanan u8 *lut; 139037bb8390SAnirudh Venkataramanan 139137bb8390SAnirudh Venkataramanan vsi->rss_size = min_t(int, vsi->rss_size, vsi->num_rxq); 139237bb8390SAnirudh Venkataramanan 139337bb8390SAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 139437bb8390SAnirudh Venkataramanan if (!lut) 139537bb8390SAnirudh Venkataramanan return -ENOMEM; 139637bb8390SAnirudh Venkataramanan 139737bb8390SAnirudh Venkataramanan if (vsi->rss_lut_user) 139837bb8390SAnirudh Venkataramanan memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 139937bb8390SAnirudh Venkataramanan else 140037bb8390SAnirudh Venkataramanan ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 140137bb8390SAnirudh Venkataramanan 14024fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut, 14034fb33f31SAnirudh Venkataramanan vsi->rss_table_size); 140437bb8390SAnirudh Venkataramanan 140537bb8390SAnirudh Venkataramanan if (status) { 1406819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, 140737bb8390SAnirudh Venkataramanan "set_rss_lut failed, error %d\n", status); 140837bb8390SAnirudh Venkataramanan err = -EIO; 140937bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 141037bb8390SAnirudh Venkataramanan } 141137bb8390SAnirudh Venkataramanan 1412819d8998SJesse Brandeburg key = devm_kzalloc(&pf->pdev->dev, sizeof(*key), GFP_KERNEL); 141337bb8390SAnirudh Venkataramanan if (!key) { 141437bb8390SAnirudh Venkataramanan err = -ENOMEM; 141537bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 141637bb8390SAnirudh Venkataramanan } 141737bb8390SAnirudh Venkataramanan 141837bb8390SAnirudh Venkataramanan if (vsi->rss_hkey_user) 1419b4b418b3SPaul Greenwalt memcpy(key, 1420b4b418b3SPaul Greenwalt (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user, 1421b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 142237bb8390SAnirudh Venkataramanan else 1423b4b418b3SPaul Greenwalt netdev_rss_key_fill((void *)key, 1424b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 142537bb8390SAnirudh Venkataramanan 14264fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key); 142737bb8390SAnirudh Venkataramanan 142837bb8390SAnirudh Venkataramanan if (status) { 1429819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, "set_rss_key failed, error %d\n", 143037bb8390SAnirudh Venkataramanan status); 143137bb8390SAnirudh Venkataramanan err = -EIO; 143237bb8390SAnirudh Venkataramanan } 143337bb8390SAnirudh Venkataramanan 143437bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, key); 143537bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit: 143637bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 143737bb8390SAnirudh Venkataramanan return err; 143837bb8390SAnirudh Venkataramanan } 143937bb8390SAnirudh Venkataramanan 144037bb8390SAnirudh Venkataramanan /** 1441f9867df6SAnirudh Venkataramanan * ice_add_mac_to_list - Add a MAC address filter entry to the list 144245d3d428SAnirudh Venkataramanan * @vsi: the VSI to be forwarded to 144345d3d428SAnirudh Venkataramanan * @add_list: pointer to the list which contains MAC filter entries 144445d3d428SAnirudh Venkataramanan * @macaddr: the MAC address to be added. 144545d3d428SAnirudh Venkataramanan * 1446f9867df6SAnirudh Venkataramanan * Adds MAC address filter entry to the temp list 144745d3d428SAnirudh Venkataramanan * 144845d3d428SAnirudh Venkataramanan * Returns 0 on success or ENOMEM on failure. 144945d3d428SAnirudh Venkataramanan */ 145045d3d428SAnirudh Venkataramanan int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list, 145145d3d428SAnirudh Venkataramanan const u8 *macaddr) 145245d3d428SAnirudh Venkataramanan { 145345d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 145445d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 145545d3d428SAnirudh Venkataramanan 145645d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC); 145745d3d428SAnirudh Venkataramanan if (!tmp) 145845d3d428SAnirudh Venkataramanan return -ENOMEM; 145945d3d428SAnirudh Venkataramanan 146045d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 14615726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 146245d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC; 146345d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 14645726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 146545d3d428SAnirudh Venkataramanan ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr); 146645d3d428SAnirudh Venkataramanan 146745d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 146845d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, add_list); 146945d3d428SAnirudh Venkataramanan 147045d3d428SAnirudh Venkataramanan return 0; 147145d3d428SAnirudh Venkataramanan } 147245d3d428SAnirudh Venkataramanan 147345d3d428SAnirudh Venkataramanan /** 147445d3d428SAnirudh Venkataramanan * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 147545d3d428SAnirudh Venkataramanan * @vsi: the VSI to be updated 147645d3d428SAnirudh Venkataramanan */ 147745d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi) 147845d3d428SAnirudh Venkataramanan { 147945d3d428SAnirudh Venkataramanan struct ice_eth_stats *prev_es, *cur_es; 148045d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 148145d3d428SAnirudh Venkataramanan u16 vsi_num = vsi->vsi_num; /* HW absolute index of a VSI */ 148245d3d428SAnirudh Venkataramanan 148345d3d428SAnirudh Venkataramanan prev_es = &vsi->eth_stats_prev; 148445d3d428SAnirudh Venkataramanan cur_es = &vsi->eth_stats; 148545d3d428SAnirudh Venkataramanan 148645d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_GORCH(vsi_num), GLV_GORCL(vsi_num), 148745d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_bytes, 148845d3d428SAnirudh Venkataramanan &cur_es->rx_bytes); 148945d3d428SAnirudh Venkataramanan 149045d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_UPRCH(vsi_num), GLV_UPRCL(vsi_num), 149145d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_unicast, 149245d3d428SAnirudh Venkataramanan &cur_es->rx_unicast); 149345d3d428SAnirudh Venkataramanan 149445d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_MPRCH(vsi_num), GLV_MPRCL(vsi_num), 149545d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_multicast, 149645d3d428SAnirudh Venkataramanan &cur_es->rx_multicast); 149745d3d428SAnirudh Venkataramanan 149845d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_BPRCH(vsi_num), GLV_BPRCL(vsi_num), 149945d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_broadcast, 150045d3d428SAnirudh Venkataramanan &cur_es->rx_broadcast); 150145d3d428SAnirudh Venkataramanan 150245d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, 150345d3d428SAnirudh Venkataramanan &prev_es->rx_discards, &cur_es->rx_discards); 150445d3d428SAnirudh Venkataramanan 150545d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_GOTCH(vsi_num), GLV_GOTCL(vsi_num), 150645d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_bytes, 150745d3d428SAnirudh Venkataramanan &cur_es->tx_bytes); 150845d3d428SAnirudh Venkataramanan 150945d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_UPTCH(vsi_num), GLV_UPTCL(vsi_num), 151045d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_unicast, 151145d3d428SAnirudh Venkataramanan &cur_es->tx_unicast); 151245d3d428SAnirudh Venkataramanan 151345d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_MPTCH(vsi_num), GLV_MPTCL(vsi_num), 151445d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_multicast, 151545d3d428SAnirudh Venkataramanan &cur_es->tx_multicast); 151645d3d428SAnirudh Venkataramanan 151745d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_BPTCH(vsi_num), GLV_BPTCL(vsi_num), 151845d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_broadcast, 151945d3d428SAnirudh Venkataramanan &cur_es->tx_broadcast); 152045d3d428SAnirudh Venkataramanan 152145d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, 152245d3d428SAnirudh Venkataramanan &prev_es->tx_errors, &cur_es->tx_errors); 152345d3d428SAnirudh Venkataramanan 152445d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded = true; 152545d3d428SAnirudh Venkataramanan } 152645d3d428SAnirudh Venkataramanan 152745d3d428SAnirudh Venkataramanan /** 152845d3d428SAnirudh Venkataramanan * ice_free_fltr_list - free filter lists helper 152945d3d428SAnirudh Venkataramanan * @dev: pointer to the device struct 153045d3d428SAnirudh Venkataramanan * @h: pointer to the list head to be freed 153145d3d428SAnirudh Venkataramanan * 153245d3d428SAnirudh Venkataramanan * Helper function to free filter lists previously created using 153345d3d428SAnirudh Venkataramanan * ice_add_mac_to_list 153445d3d428SAnirudh Venkataramanan */ 153545d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h) 153645d3d428SAnirudh Venkataramanan { 153745d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *e, *tmp; 153845d3d428SAnirudh Venkataramanan 153945d3d428SAnirudh Venkataramanan list_for_each_entry_safe(e, tmp, h, list_entry) { 154045d3d428SAnirudh Venkataramanan list_del(&e->list_entry); 154145d3d428SAnirudh Venkataramanan devm_kfree(dev, e); 154245d3d428SAnirudh Venkataramanan } 154345d3d428SAnirudh Venkataramanan } 154445d3d428SAnirudh Venkataramanan 154545d3d428SAnirudh Venkataramanan /** 154645d3d428SAnirudh Venkataramanan * ice_vsi_add_vlan - Add VSI membership for given VLAN 154745d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1548f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be added 154945d3d428SAnirudh Venkataramanan */ 155045d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid) 155145d3d428SAnirudh Venkataramanan { 155245d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 155345d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 155445d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 155545d3d428SAnirudh Venkataramanan enum ice_status status; 155645d3d428SAnirudh Venkataramanan int err = 0; 155745d3d428SAnirudh Venkataramanan 155845d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_KERNEL); 155945d3d428SAnirudh Venkataramanan if (!tmp) 156045d3d428SAnirudh Venkataramanan return -ENOMEM; 156145d3d428SAnirudh Venkataramanan 156245d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 156345d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 156445d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 15655726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 15665726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 156745d3d428SAnirudh Venkataramanan tmp->fltr_info.l_data.vlan.vlan_id = vid; 156845d3d428SAnirudh Venkataramanan 156945d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 157045d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, &tmp_add_list); 157145d3d428SAnirudh Venkataramanan 157245d3d428SAnirudh Venkataramanan status = ice_add_vlan(&pf->hw, &tmp_add_list); 157345d3d428SAnirudh Venkataramanan if (status) { 157445d3d428SAnirudh Venkataramanan err = -ENODEV; 157545d3d428SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failure Adding VLAN %d on VSI %i\n", 157645d3d428SAnirudh Venkataramanan vid, vsi->vsi_num); 157745d3d428SAnirudh Venkataramanan } 157845d3d428SAnirudh Venkataramanan 157945d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 158045d3d428SAnirudh Venkataramanan return err; 158145d3d428SAnirudh Venkataramanan } 158245d3d428SAnirudh Venkataramanan 158345d3d428SAnirudh Venkataramanan /** 158445d3d428SAnirudh Venkataramanan * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN 158545d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1586f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be removed 158745d3d428SAnirudh Venkataramanan * 158845d3d428SAnirudh Venkataramanan * Returns 0 on success and negative on failure 158945d3d428SAnirudh Venkataramanan */ 159045d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid) 159145d3d428SAnirudh Venkataramanan { 159245d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *list; 159345d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 159445d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 15955079b853SAkeem G Abodunrin enum ice_status status; 15965079b853SAkeem G Abodunrin int err = 0; 159745d3d428SAnirudh Venkataramanan 159845d3d428SAnirudh Venkataramanan list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 159945d3d428SAnirudh Venkataramanan if (!list) 160045d3d428SAnirudh Venkataramanan return -ENOMEM; 160145d3d428SAnirudh Venkataramanan 160245d3d428SAnirudh Venkataramanan list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 16035726ca0eSAnirudh Venkataramanan list->fltr_info.vsi_handle = vsi->idx; 160445d3d428SAnirudh Venkataramanan list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 160545d3d428SAnirudh Venkataramanan list->fltr_info.l_data.vlan.vlan_id = vid; 160645d3d428SAnirudh Venkataramanan list->fltr_info.flag = ICE_FLTR_TX; 16075726ca0eSAnirudh Venkataramanan list->fltr_info.src_id = ICE_SRC_ID_VSI; 160845d3d428SAnirudh Venkataramanan 160945d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&list->list_entry); 161045d3d428SAnirudh Venkataramanan list_add(&list->list_entry, &tmp_add_list); 161145d3d428SAnirudh Venkataramanan 16125079b853SAkeem G Abodunrin status = ice_remove_vlan(&pf->hw, &tmp_add_list); 1613bb877b22SAkeem G Abodunrin if (status == ICE_ERR_DOES_NOT_EXIST) { 1614bb877b22SAkeem G Abodunrin dev_dbg(&pf->pdev->dev, 1615bb877b22SAkeem G Abodunrin "Failed to remove VLAN %d on VSI %i, it does not exist, status: %d\n", 1616bb877b22SAkeem G Abodunrin vid, vsi->vsi_num, status); 1617bb877b22SAkeem G Abodunrin } else if (status) { 16185079b853SAkeem G Abodunrin dev_err(&pf->pdev->dev, 16195079b853SAkeem G Abodunrin "Error removing VLAN %d on vsi %i error: %d\n", 16205079b853SAkeem G Abodunrin vid, vsi->vsi_num, status); 16215079b853SAkeem G Abodunrin err = -EIO; 162245d3d428SAnirudh Venkataramanan } 162345d3d428SAnirudh Venkataramanan 162445d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 16255079b853SAkeem G Abodunrin return err; 162645d3d428SAnirudh Venkataramanan } 162745d3d428SAnirudh Venkataramanan 162845d3d428SAnirudh Venkataramanan /** 162972adf242SAnirudh Venkataramanan * ice_vsi_cfg_rxqs - Configure the VSI for Rx 163072adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 163172adf242SAnirudh Venkataramanan * 163272adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 163372adf242SAnirudh Venkataramanan * Configure the Rx VSI for operation. 163472adf242SAnirudh Venkataramanan */ 163572adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi) 163672adf242SAnirudh Venkataramanan { 163772adf242SAnirudh Venkataramanan u16 i; 163872adf242SAnirudh Venkataramanan 16398ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 16408ede0178SAnirudh Venkataramanan goto setup_rings; 16418ede0178SAnirudh Venkataramanan 164272adf242SAnirudh Venkataramanan if (vsi->netdev && vsi->netdev->mtu > ETH_DATA_LEN) 164372adf242SAnirudh Venkataramanan vsi->max_frame = vsi->netdev->mtu + 164472adf242SAnirudh Venkataramanan ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; 164572adf242SAnirudh Venkataramanan else 164672adf242SAnirudh Venkataramanan vsi->max_frame = ICE_RXBUF_2048; 164772adf242SAnirudh Venkataramanan 164872adf242SAnirudh Venkataramanan vsi->rx_buf_len = ICE_RXBUF_2048; 16498ede0178SAnirudh Venkataramanan setup_rings: 165072adf242SAnirudh Venkataramanan /* set up individual rings */ 16511553f4f7SBrett Creeley for (i = 0; i < vsi->num_rxq; i++) { 16521553f4f7SBrett Creeley int err; 165372adf242SAnirudh Venkataramanan 16541553f4f7SBrett Creeley err = ice_setup_rx_ctx(vsi->rx_rings[i]); 165572adf242SAnirudh Venkataramanan if (err) { 16561553f4f7SBrett Creeley dev_err(&vsi->back->pdev->dev, 16571553f4f7SBrett Creeley "ice_setup_rx_ctx failed for RxQ %d, err %d\n", 16581553f4f7SBrett Creeley i, err); 165972adf242SAnirudh Venkataramanan return err; 166072adf242SAnirudh Venkataramanan } 16611553f4f7SBrett Creeley } 16621553f4f7SBrett Creeley 16631553f4f7SBrett Creeley return 0; 16641553f4f7SBrett Creeley } 166572adf242SAnirudh Venkataramanan 166672adf242SAnirudh Venkataramanan /** 166772adf242SAnirudh Venkataramanan * ice_vsi_cfg_txqs - Configure the VSI for Tx 166872adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 166903f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be configured 167003f7a986SAnirudh Venkataramanan * @offset: offset within vsi->txq_map 167172adf242SAnirudh Venkataramanan * 167272adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 167372adf242SAnirudh Venkataramanan * Configure the Tx VSI for operation. 167472adf242SAnirudh Venkataramanan */ 167503f7a986SAnirudh Venkataramanan static int 167603f7a986SAnirudh Venkataramanan ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, int offset) 167772adf242SAnirudh Venkataramanan { 167872adf242SAnirudh Venkataramanan struct ice_aqc_add_tx_qgrp *qg_buf; 167972adf242SAnirudh Venkataramanan struct ice_aqc_add_txqs_perq *txq; 168072adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1681c5a2a4a3SUsha Ketineni u8 num_q_grps, q_idx = 0; 168272adf242SAnirudh Venkataramanan enum ice_status status; 168372adf242SAnirudh Venkataramanan u16 buf_len, i, pf_q; 168403f7a986SAnirudh Venkataramanan int err = 0, tc; 168572adf242SAnirudh Venkataramanan 1686c6dfd690SBruce Allan buf_len = sizeof(*qg_buf); 168772adf242SAnirudh Venkataramanan qg_buf = devm_kzalloc(&pf->pdev->dev, buf_len, GFP_KERNEL); 168872adf242SAnirudh Venkataramanan if (!qg_buf) 168972adf242SAnirudh Venkataramanan return -ENOMEM; 169072adf242SAnirudh Venkataramanan 169172adf242SAnirudh Venkataramanan qg_buf->num_txqs = 1; 169272adf242SAnirudh Venkataramanan num_q_grps = 1; 169372adf242SAnirudh Venkataramanan 1694c5a2a4a3SUsha Ketineni /* set up and configure the Tx queues for each enabled TC */ 16952bdc97beSBruce Allan ice_for_each_traffic_class(tc) { 1696c5a2a4a3SUsha Ketineni if (!(vsi->tc_cfg.ena_tc & BIT(tc))) 1697c5a2a4a3SUsha Ketineni break; 1698c5a2a4a3SUsha Ketineni 1699c5a2a4a3SUsha Ketineni for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) { 170072adf242SAnirudh Venkataramanan struct ice_tlan_ctx tlan_ctx = { 0 }; 170172adf242SAnirudh Venkataramanan 170203f7a986SAnirudh Venkataramanan pf_q = vsi->txq_map[q_idx + offset]; 170303f7a986SAnirudh Venkataramanan ice_setup_tx_ctx(rings[q_idx], &tlan_ctx, pf_q); 170472adf242SAnirudh Venkataramanan /* copy context contents into the qg_buf */ 170572adf242SAnirudh Venkataramanan qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q); 170672adf242SAnirudh Venkataramanan ice_set_ctx((u8 *)&tlan_ctx, qg_buf->txqs[0].txq_ctx, 170772adf242SAnirudh Venkataramanan ice_tlan_ctx_info); 170872adf242SAnirudh Venkataramanan 1709c5a2a4a3SUsha Ketineni /* init queue specific tail reg. It is referred as 1710c5a2a4a3SUsha Ketineni * transmit comm scheduler queue doorbell. 171172adf242SAnirudh Venkataramanan */ 171203f7a986SAnirudh Venkataramanan rings[q_idx]->tail = 1713c5a2a4a3SUsha Ketineni pf->hw.hw_addr + QTX_COMM_DBELL(pf_q); 17144fb33f31SAnirudh Venkataramanan status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc, 1715bb87ee0eSAnirudh Venkataramanan i, num_q_grps, qg_buf, 1716bb87ee0eSAnirudh Venkataramanan buf_len, NULL); 171772adf242SAnirudh Venkataramanan if (status) { 1718819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, 171972adf242SAnirudh Venkataramanan "Failed to set LAN Tx queue context, error: %d\n", 172072adf242SAnirudh Venkataramanan status); 172172adf242SAnirudh Venkataramanan err = -ENODEV; 172272adf242SAnirudh Venkataramanan goto err_cfg_txqs; 172372adf242SAnirudh Venkataramanan } 172472adf242SAnirudh Venkataramanan 1725c5a2a4a3SUsha Ketineni /* Add Tx Queue TEID into the VSI Tx ring from the 1726c5a2a4a3SUsha Ketineni * response. This will complete configuring and 1727c5a2a4a3SUsha Ketineni * enabling the queue. 172872adf242SAnirudh Venkataramanan */ 172972adf242SAnirudh Venkataramanan txq = &qg_buf->txqs[0]; 173072adf242SAnirudh Venkataramanan if (pf_q == le16_to_cpu(txq->txq_id)) 173103f7a986SAnirudh Venkataramanan rings[q_idx]->txq_teid = 173272adf242SAnirudh Venkataramanan le32_to_cpu(txq->q_teid); 1733c5a2a4a3SUsha Ketineni 1734c5a2a4a3SUsha Ketineni q_idx++; 1735c5a2a4a3SUsha Ketineni } 173672adf242SAnirudh Venkataramanan } 173772adf242SAnirudh Venkataramanan err_cfg_txqs: 173872adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, qg_buf); 173972adf242SAnirudh Venkataramanan return err; 174072adf242SAnirudh Venkataramanan } 174172adf242SAnirudh Venkataramanan 174272adf242SAnirudh Venkataramanan /** 174303f7a986SAnirudh Venkataramanan * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx 174403f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 174503f7a986SAnirudh Venkataramanan * 174603f7a986SAnirudh Venkataramanan * Return 0 on success and a negative value on error 174703f7a986SAnirudh Venkataramanan * Configure the Tx VSI for operation. 174803f7a986SAnirudh Venkataramanan */ 174903f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) 175003f7a986SAnirudh Venkataramanan { 175103f7a986SAnirudh Venkataramanan return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, 0); 175203f7a986SAnirudh Venkataramanan } 175303f7a986SAnirudh Venkataramanan 175403f7a986SAnirudh Venkataramanan /** 17559e4ab4c2SBrett Creeley * ice_intrl_usec_to_reg - convert interrupt rate limit to register value 17569e4ab4c2SBrett Creeley * @intrl: interrupt rate limit in usecs 17579e4ab4c2SBrett Creeley * @gran: interrupt rate limit granularity in usecs 17589e4ab4c2SBrett Creeley * 17599e4ab4c2SBrett Creeley * This function converts a decimal interrupt rate limit in usecs to the format 17609e4ab4c2SBrett Creeley * expected by firmware. 17619e4ab4c2SBrett Creeley */ 1762b9c8bb06SBrett Creeley u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) 17639e4ab4c2SBrett Creeley { 17649e4ab4c2SBrett Creeley u32 val = intrl / gran; 17659e4ab4c2SBrett Creeley 17669e4ab4c2SBrett Creeley if (val) 17679e4ab4c2SBrett Creeley return val | GLINT_RATE_INTRL_ENA_M; 17689e4ab4c2SBrett Creeley return 0; 17699e4ab4c2SBrett Creeley } 17709e4ab4c2SBrett Creeley 17719e4ab4c2SBrett Creeley /** 177270457520SBrett Creeley * ice_cfg_itr_gran - set the ITR granularity to 2 usecs if not already set 177370457520SBrett Creeley * @hw: board specific structure 177470457520SBrett Creeley */ 177570457520SBrett Creeley static void ice_cfg_itr_gran(struct ice_hw *hw) 177670457520SBrett Creeley { 177770457520SBrett Creeley u32 regval = rd32(hw, GLINT_CTL); 177870457520SBrett Creeley 177970457520SBrett Creeley /* no need to update global register if ITR gran is already set */ 178070457520SBrett Creeley if (!(regval & GLINT_CTL_DIS_AUTOMASK_M) && 178170457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_200_M) >> 178270457520SBrett Creeley GLINT_CTL_ITR_GRAN_200_S) == ICE_ITR_GRAN_US) && 178370457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_100_M) >> 178470457520SBrett Creeley GLINT_CTL_ITR_GRAN_100_S) == ICE_ITR_GRAN_US) && 178570457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_50_M) >> 178670457520SBrett Creeley GLINT_CTL_ITR_GRAN_50_S) == ICE_ITR_GRAN_US) && 178770457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_25_M) >> 178870457520SBrett Creeley GLINT_CTL_ITR_GRAN_25_S) == ICE_ITR_GRAN_US)) 178970457520SBrett Creeley return; 179070457520SBrett Creeley 179170457520SBrett Creeley regval = ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_200_S) & 179270457520SBrett Creeley GLINT_CTL_ITR_GRAN_200_M) | 179370457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_100_S) & 179470457520SBrett Creeley GLINT_CTL_ITR_GRAN_100_M) | 179570457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_50_S) & 179670457520SBrett Creeley GLINT_CTL_ITR_GRAN_50_M) | 179770457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_25_S) & 179870457520SBrett Creeley GLINT_CTL_ITR_GRAN_25_M); 179970457520SBrett Creeley wr32(hw, GLINT_CTL, regval); 180070457520SBrett Creeley } 180170457520SBrett Creeley 180270457520SBrett Creeley /** 1803d2b464a7SBrett Creeley * ice_cfg_itr - configure the initial interrupt throttle values 1804d2b464a7SBrett Creeley * @hw: pointer to the HW structure 1805d2b464a7SBrett Creeley * @q_vector: interrupt vector that's being configured 1806d2b464a7SBrett Creeley * 1807d2b464a7SBrett Creeley * Configure interrupt throttling values for the ring containers that are 1808d2b464a7SBrett Creeley * associated with the interrupt vector passed in. 1809d2b464a7SBrett Creeley */ 1810d2b464a7SBrett Creeley static void 1811b07833a0SBrett Creeley ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector) 1812d2b464a7SBrett Creeley { 181370457520SBrett Creeley ice_cfg_itr_gran(hw); 181470457520SBrett Creeley 1815d2b464a7SBrett Creeley if (q_vector->num_ring_rx) { 1816d2b464a7SBrett Creeley struct ice_ring_container *rc = &q_vector->rx; 1817d2b464a7SBrett Creeley 181863f545edSBrett Creeley /* if this value is set then don't overwrite with default */ 181963f545edSBrett Creeley if (!rc->itr_setting) 182063f545edSBrett Creeley rc->itr_setting = ICE_DFLT_RX_ITR; 182163f545edSBrett Creeley 182263f545edSBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 182363f545edSBrett Creeley rc->next_update = jiffies + 1; 182463f545edSBrett Creeley rc->current_itr = rc->target_itr; 1825b07833a0SBrett Creeley wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), 182663f545edSBrett Creeley ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); 1827d2b464a7SBrett Creeley } 1828d2b464a7SBrett Creeley 1829d2b464a7SBrett Creeley if (q_vector->num_ring_tx) { 1830d2b464a7SBrett Creeley struct ice_ring_container *rc = &q_vector->tx; 1831d2b464a7SBrett Creeley 183263f545edSBrett Creeley /* if this value is set then don't overwrite with default */ 183363f545edSBrett Creeley if (!rc->itr_setting) 183463f545edSBrett Creeley rc->itr_setting = ICE_DFLT_TX_ITR; 183563f545edSBrett Creeley 183663f545edSBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 183763f545edSBrett Creeley rc->next_update = jiffies + 1; 183863f545edSBrett Creeley rc->current_itr = rc->target_itr; 1839b07833a0SBrett Creeley wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), 184063f545edSBrett Creeley ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); 1841d2b464a7SBrett Creeley } 1842d2b464a7SBrett Creeley } 1843d2b464a7SBrett Creeley 1844d2b464a7SBrett Creeley /** 184572adf242SAnirudh Venkataramanan * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW 184672adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 184772adf242SAnirudh Venkataramanan */ 184872adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi) 184972adf242SAnirudh Venkataramanan { 185072adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 185172adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 185272adf242SAnirudh Venkataramanan u32 txq = 0, rxq = 0; 1853d2b464a7SBrett Creeley int i, q; 185472adf242SAnirudh Venkataramanan 1855b07833a0SBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 185672adf242SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1857b07833a0SBrett Creeley u16 reg_idx = q_vector->reg_idx; 185872adf242SAnirudh Venkataramanan 18594b6f3ecaSBrett Creeley if (vsi->type != ICE_VSI_VF) 1860b07833a0SBrett Creeley ice_cfg_itr(hw, q_vector); 18619e4ab4c2SBrett Creeley 1862b07833a0SBrett Creeley wr32(hw, GLINT_RATE(reg_idx), 18639e4ab4c2SBrett Creeley ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); 186472adf242SAnirudh Venkataramanan 186572adf242SAnirudh Venkataramanan /* Both Transmit Queue Interrupt Cause Control register 186672adf242SAnirudh Venkataramanan * and Receive Queue Interrupt Cause control register 186772adf242SAnirudh Venkataramanan * expects MSIX_INDX field to be the vector index 186872adf242SAnirudh Venkataramanan * within the function space and not the absolute 186972adf242SAnirudh Venkataramanan * vector index across PF or across device. 187072adf242SAnirudh Venkataramanan * For SR-IOV VF VSIs queue vector index always starts 187172adf242SAnirudh Venkataramanan * with 1 since first vector index(0) is used for OICR 187272adf242SAnirudh Venkataramanan * in VF space. Since VMDq and other PF VSIs are within 187372adf242SAnirudh Venkataramanan * the PF function space, use the vector index that is 187472adf242SAnirudh Venkataramanan * tracked for this PF. 187572adf242SAnirudh Venkataramanan */ 187672adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 1877ba0db585SMichal Swiatkowski int itr_idx = (q_vector->tx.itr_idx << 1878ba0db585SMichal Swiatkowski QINT_TQCTL_ITR_INDX_S) & 1879ba0db585SMichal Swiatkowski QINT_TQCTL_ITR_INDX_M; 188072adf242SAnirudh Venkataramanan u32 val; 188172adf242SAnirudh Venkataramanan 18828ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 1883ba0db585SMichal Swiatkowski val = QINT_TQCTL_CAUSE_ENA_M | itr_idx | 1884ba0db585SMichal Swiatkowski (((i + 1) << QINT_TQCTL_MSIX_INDX_S) & 1885ba0db585SMichal Swiatkowski QINT_TQCTL_MSIX_INDX_M); 18868ede0178SAnirudh Venkataramanan else 1887ba0db585SMichal Swiatkowski val = QINT_TQCTL_CAUSE_ENA_M | itr_idx | 1888ba0db585SMichal Swiatkowski ((reg_idx << QINT_TQCTL_MSIX_INDX_S) & 1889ba0db585SMichal Swiatkowski QINT_TQCTL_MSIX_INDX_M); 189072adf242SAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), val); 189172adf242SAnirudh Venkataramanan txq++; 189272adf242SAnirudh Venkataramanan } 189372adf242SAnirudh Venkataramanan 189472adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 1895ba0db585SMichal Swiatkowski int itr_idx = (q_vector->rx.itr_idx << 1896ba0db585SMichal Swiatkowski QINT_RQCTL_ITR_INDX_S) & 1897ba0db585SMichal Swiatkowski QINT_RQCTL_ITR_INDX_M; 189872adf242SAnirudh Venkataramanan u32 val; 189972adf242SAnirudh Venkataramanan 19008ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 1901ba0db585SMichal Swiatkowski val = QINT_RQCTL_CAUSE_ENA_M | itr_idx | 1902ba0db585SMichal Swiatkowski (((i + 1) << QINT_RQCTL_MSIX_INDX_S) & 1903ba0db585SMichal Swiatkowski QINT_RQCTL_MSIX_INDX_M); 19048ede0178SAnirudh Venkataramanan else 1905ba0db585SMichal Swiatkowski val = QINT_RQCTL_CAUSE_ENA_M | itr_idx | 1906ba0db585SMichal Swiatkowski ((reg_idx << QINT_RQCTL_MSIX_INDX_S) & 1907ba0db585SMichal Swiatkowski QINT_RQCTL_MSIX_INDX_M); 190872adf242SAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), val); 190972adf242SAnirudh Venkataramanan rxq++; 191072adf242SAnirudh Venkataramanan } 191172adf242SAnirudh Venkataramanan } 191272adf242SAnirudh Venkataramanan 191372adf242SAnirudh Venkataramanan ice_flush(hw); 191472adf242SAnirudh Venkataramanan } 191572adf242SAnirudh Venkataramanan 191672adf242SAnirudh Venkataramanan /** 191745d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx 191845d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 191945d3d428SAnirudh Venkataramanan */ 192045d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) 192145d3d428SAnirudh Venkataramanan { 192245d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 192345d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1924198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 192545d3d428SAnirudh Venkataramanan enum ice_status status; 1926198a666aSBruce Allan int ret = 0; 1927198a666aSBruce Allan 1928198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 1929198a666aSBruce Allan if (!ctxt) 1930198a666aSBruce Allan return -ENOMEM; 193145d3d428SAnirudh Venkataramanan 193245d3d428SAnirudh Venkataramanan /* Here we are configuring the VSI to let the driver add VLAN tags by 193345d3d428SAnirudh Venkataramanan * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag 193445d3d428SAnirudh Venkataramanan * insertion happens in the Tx hot path, in ice_tx_map. 193545d3d428SAnirudh Venkataramanan */ 1936198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; 193745d3d428SAnirudh Venkataramanan 1938e80e76dbSTony Nguyen /* Preserve existing VLAN strip setting */ 1939e80e76dbSTony Nguyen ctxt->info.vlan_flags |= (vsi->info.vlan_flags & 1940e80e76dbSTony Nguyen ICE_AQ_VSI_VLAN_EMOD_M); 1941e80e76dbSTony Nguyen 1942198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 194345d3d428SAnirudh Venkataramanan 1944198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 194545d3d428SAnirudh Venkataramanan if (status) { 194645d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n", 194745d3d428SAnirudh Venkataramanan status, hw->adminq.sq_last_status); 1948198a666aSBruce Allan ret = -EIO; 1949198a666aSBruce Allan goto out; 195045d3d428SAnirudh Venkataramanan } 195145d3d428SAnirudh Venkataramanan 1952198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1953198a666aSBruce Allan out: 1954198a666aSBruce Allan devm_kfree(dev, ctxt); 1955198a666aSBruce Allan return ret; 195645d3d428SAnirudh Venkataramanan } 195745d3d428SAnirudh Venkataramanan 195845d3d428SAnirudh Venkataramanan /** 195945d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx 196045d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 196145d3d428SAnirudh Venkataramanan * @ena: boolean value indicating if this is a enable or disable request 196245d3d428SAnirudh Venkataramanan */ 196345d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) 196445d3d428SAnirudh Venkataramanan { 196545d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 196645d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1967198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 196845d3d428SAnirudh Venkataramanan enum ice_status status; 1969198a666aSBruce Allan int ret = 0; 1970198a666aSBruce Allan 1971198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 1972198a666aSBruce Allan if (!ctxt) 1973198a666aSBruce Allan return -ENOMEM; 197445d3d428SAnirudh Venkataramanan 197545d3d428SAnirudh Venkataramanan /* Here we are configuring what the VSI should do with the VLAN tag in 197645d3d428SAnirudh Venkataramanan * the Rx packet. We can either leave the tag in the packet or put it in 197745d3d428SAnirudh Venkataramanan * the Rx descriptor. 197845d3d428SAnirudh Venkataramanan */ 1979198a666aSBruce Allan if (ena) 198045d3d428SAnirudh Venkataramanan /* Strip VLAN tag from Rx packet and put it in the desc */ 1981198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; 1982198a666aSBruce Allan else 198345d3d428SAnirudh Venkataramanan /* Disable stripping. Leave tag in packet */ 1984198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; 198545d3d428SAnirudh Venkataramanan 198645d3d428SAnirudh Venkataramanan /* Allow all packets untagged/tagged */ 1987198a666aSBruce Allan ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; 198845d3d428SAnirudh Venkataramanan 1989198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 199045d3d428SAnirudh Venkataramanan 1991198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 199245d3d428SAnirudh Venkataramanan if (status) { 199345d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n", 199445d3d428SAnirudh Venkataramanan ena, status, hw->adminq.sq_last_status); 1995198a666aSBruce Allan ret = -EIO; 1996198a666aSBruce Allan goto out; 199745d3d428SAnirudh Venkataramanan } 199845d3d428SAnirudh Venkataramanan 1999198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 2000198a666aSBruce Allan out: 2001198a666aSBruce Allan devm_kfree(dev, ctxt); 2002198a666aSBruce Allan return ret; 200345d3d428SAnirudh Venkataramanan } 200472adf242SAnirudh Venkataramanan 200572adf242SAnirudh Venkataramanan /** 200672adf242SAnirudh Venkataramanan * ice_vsi_start_rx_rings - start VSI's Rx rings 200772adf242SAnirudh Venkataramanan * @vsi: the VSI whose rings are to be started 200872adf242SAnirudh Venkataramanan * 200972adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 201072adf242SAnirudh Venkataramanan */ 201172adf242SAnirudh Venkataramanan int ice_vsi_start_rx_rings(struct ice_vsi *vsi) 201272adf242SAnirudh Venkataramanan { 201372adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, true); 201472adf242SAnirudh Venkataramanan } 201572adf242SAnirudh Venkataramanan 201672adf242SAnirudh Venkataramanan /** 201772adf242SAnirudh Venkataramanan * ice_vsi_stop_rx_rings - stop VSI's Rx rings 201872adf242SAnirudh Venkataramanan * @vsi: the VSI 201972adf242SAnirudh Venkataramanan * 202072adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 202172adf242SAnirudh Venkataramanan */ 202272adf242SAnirudh Venkataramanan int ice_vsi_stop_rx_rings(struct ice_vsi *vsi) 202372adf242SAnirudh Venkataramanan { 202472adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, false); 202572adf242SAnirudh Venkataramanan } 202672adf242SAnirudh Venkataramanan 202772adf242SAnirudh Venkataramanan /** 202872adf242SAnirudh Venkataramanan * ice_vsi_stop_tx_rings - Disable Tx rings 202972adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 2030ddf30f7fSAnirudh Venkataramanan * @rst_src: reset source 2031f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 203203f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be stopped 203303f7a986SAnirudh Venkataramanan * @offset: offset within vsi->txq_map 203472adf242SAnirudh Venkataramanan */ 203503f7a986SAnirudh Venkataramanan static int 203603f7a986SAnirudh Venkataramanan ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 203703f7a986SAnirudh Venkataramanan u16 rel_vmvf_num, struct ice_ring **rings, int offset) 203872adf242SAnirudh Venkataramanan { 203972adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 204072adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 2041bb87ee0eSAnirudh Venkataramanan int tc, q_idx = 0, err = 0; 2042bb87ee0eSAnirudh Venkataramanan u16 *q_ids, *q_handles, i; 204372adf242SAnirudh Venkataramanan enum ice_status status; 204472adf242SAnirudh Venkataramanan u32 *q_teids, val; 204572adf242SAnirudh Venkataramanan 204672adf242SAnirudh Venkataramanan if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS) 204772adf242SAnirudh Venkataramanan return -EINVAL; 204872adf242SAnirudh Venkataramanan 204972adf242SAnirudh Venkataramanan q_teids = devm_kcalloc(&pf->pdev->dev, vsi->num_txq, sizeof(*q_teids), 205072adf242SAnirudh Venkataramanan GFP_KERNEL); 205172adf242SAnirudh Venkataramanan if (!q_teids) 205272adf242SAnirudh Venkataramanan return -ENOMEM; 205372adf242SAnirudh Venkataramanan 205472adf242SAnirudh Venkataramanan q_ids = devm_kcalloc(&pf->pdev->dev, vsi->num_txq, sizeof(*q_ids), 205572adf242SAnirudh Venkataramanan GFP_KERNEL); 205672adf242SAnirudh Venkataramanan if (!q_ids) { 205772adf242SAnirudh Venkataramanan err = -ENOMEM; 205872adf242SAnirudh Venkataramanan goto err_alloc_q_ids; 205972adf242SAnirudh Venkataramanan } 206072adf242SAnirudh Venkataramanan 2061bb87ee0eSAnirudh Venkataramanan q_handles = devm_kcalloc(&pf->pdev->dev, vsi->num_txq, 2062bb87ee0eSAnirudh Venkataramanan sizeof(*q_handles), GFP_KERNEL); 2063bb87ee0eSAnirudh Venkataramanan if (!q_handles) { 2064bb87ee0eSAnirudh Venkataramanan err = -ENOMEM; 2065bb87ee0eSAnirudh Venkataramanan goto err_alloc_q_handles; 2066bb87ee0eSAnirudh Venkataramanan } 2067bb87ee0eSAnirudh Venkataramanan 2068bb87ee0eSAnirudh Venkataramanan /* set up the Tx queue list to be disabled for each enabled TC */ 2069bb87ee0eSAnirudh Venkataramanan ice_for_each_traffic_class(tc) { 2070bb87ee0eSAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(tc))) 2071bb87ee0eSAnirudh Venkataramanan break; 2072bb87ee0eSAnirudh Venkataramanan 2073bb87ee0eSAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) { 2074a92e1bb6SMaciej Fijalkowski if (!rings || !rings[q_idx] || 2075a92e1bb6SMaciej Fijalkowski !rings[q_idx]->q_vector) { 207672adf242SAnirudh Venkataramanan err = -EINVAL; 207772adf242SAnirudh Venkataramanan goto err_out; 207872adf242SAnirudh Venkataramanan } 207972adf242SAnirudh Venkataramanan 2080bb87ee0eSAnirudh Venkataramanan q_ids[i] = vsi->txq_map[q_idx + offset]; 2081bb87ee0eSAnirudh Venkataramanan q_teids[i] = rings[q_idx]->txq_teid; 2082bb87ee0eSAnirudh Venkataramanan q_handles[i] = i; 208372adf242SAnirudh Venkataramanan 208472adf242SAnirudh Venkataramanan /* clear cause_ena bit for disabled queues */ 208503f7a986SAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(rings[i]->reg_idx)); 208672adf242SAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 208703f7a986SAnirudh Venkataramanan wr32(hw, QINT_TQCTL(rings[i]->reg_idx), val); 208872adf242SAnirudh Venkataramanan 208972adf242SAnirudh Venkataramanan /* software is expected to wait for 100 ns */ 209072adf242SAnirudh Venkataramanan ndelay(100); 209172adf242SAnirudh Venkataramanan 2092bb87ee0eSAnirudh Venkataramanan /* trigger a software interrupt for the vector 2093bb87ee0eSAnirudh Venkataramanan * associated to the queue to schedule NAPI handler 209472adf242SAnirudh Venkataramanan */ 2095b07833a0SBrett Creeley wr32(hw, GLINT_DYN_CTL(rings[i]->q_vector->reg_idx), 2096bb87ee0eSAnirudh Venkataramanan GLINT_DYN_CTL_SWINT_TRIG_M | 2097bb87ee0eSAnirudh Venkataramanan GLINT_DYN_CTL_INTENA_MSK_M); 2098bb87ee0eSAnirudh Venkataramanan q_idx++; 209972adf242SAnirudh Venkataramanan } 2100bb87ee0eSAnirudh Venkataramanan status = ice_dis_vsi_txq(vsi->port_info, vsi->idx, tc, 2101bb87ee0eSAnirudh Venkataramanan vsi->num_txq, q_handles, q_ids, 2102bb87ee0eSAnirudh Venkataramanan q_teids, rst_src, rel_vmvf_num, NULL); 2103bb87ee0eSAnirudh Venkataramanan 2104bb87ee0eSAnirudh Venkataramanan /* if the disable queue command was exercised during an active 2105bb87ee0eSAnirudh Venkataramanan * reset flow, ICE_ERR_RESET_ONGOING is returned. This is not 2106bb87ee0eSAnirudh Venkataramanan * an error as the reset operation disables queues at the 2107bb87ee0eSAnirudh Venkataramanan * hardware level anyway. 210872adf242SAnirudh Venkataramanan */ 210972adf242SAnirudh Venkataramanan if (status == ICE_ERR_RESET_ONGOING) { 2110bb87ee0eSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 211172adf242SAnirudh Venkataramanan "Reset in progress. LAN Tx queues already disabled\n"); 211272adf242SAnirudh Venkataramanan } else if (status) { 211372adf242SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 211472adf242SAnirudh Venkataramanan "Failed to disable LAN Tx queues, error: %d\n", 211572adf242SAnirudh Venkataramanan status); 211672adf242SAnirudh Venkataramanan err = -ENODEV; 211772adf242SAnirudh Venkataramanan } 2118bb87ee0eSAnirudh Venkataramanan } 211972adf242SAnirudh Venkataramanan 212072adf242SAnirudh Venkataramanan err_out: 2121bb87ee0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, q_handles); 2122bb87ee0eSAnirudh Venkataramanan 2123bb87ee0eSAnirudh Venkataramanan err_alloc_q_handles: 212472adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, q_ids); 212572adf242SAnirudh Venkataramanan 212672adf242SAnirudh Venkataramanan err_alloc_q_ids: 212772adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, q_teids); 212872adf242SAnirudh Venkataramanan 212972adf242SAnirudh Venkataramanan return err; 213072adf242SAnirudh Venkataramanan } 21315153a18eSAnirudh Venkataramanan 21325153a18eSAnirudh Venkataramanan /** 213303f7a986SAnirudh Venkataramanan * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings 213403f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 213503f7a986SAnirudh Venkataramanan * @rst_src: reset source 2136f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 213703f7a986SAnirudh Venkataramanan */ 2138c8b7abddSBruce Allan int 2139c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 2140c8b7abddSBruce Allan u16 rel_vmvf_num) 214103f7a986SAnirudh Venkataramanan { 214203f7a986SAnirudh Venkataramanan return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings, 214303f7a986SAnirudh Venkataramanan 0); 214403f7a986SAnirudh Venkataramanan } 214503f7a986SAnirudh Venkataramanan 214603f7a986SAnirudh Venkataramanan /** 21475153a18eSAnirudh Venkataramanan * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 21485153a18eSAnirudh Venkataramanan * @vsi: VSI to enable or disable VLAN pruning on 21495153a18eSAnirudh Venkataramanan * @ena: set to true to enable VLAN pruning and false to disable it 21505eda8afdSAkeem G Abodunrin * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode 21515153a18eSAnirudh Venkataramanan * 21525153a18eSAnirudh Venkataramanan * returns 0 if VSI is updated, negative otherwise 21535153a18eSAnirudh Venkataramanan */ 21545eda8afdSAkeem G Abodunrin int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc) 21555153a18eSAnirudh Venkataramanan { 21565153a18eSAnirudh Venkataramanan struct ice_vsi_ctx *ctxt; 21575153a18eSAnirudh Venkataramanan struct device *dev; 2158819d8998SJesse Brandeburg struct ice_pf *pf; 21595153a18eSAnirudh Venkataramanan int status; 21605153a18eSAnirudh Venkataramanan 21615153a18eSAnirudh Venkataramanan if (!vsi) 21625153a18eSAnirudh Venkataramanan return -EINVAL; 21635153a18eSAnirudh Venkataramanan 2164819d8998SJesse Brandeburg pf = vsi->back; 2165819d8998SJesse Brandeburg dev = &pf->pdev->dev; 21665153a18eSAnirudh Venkataramanan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 21675153a18eSAnirudh Venkataramanan if (!ctxt) 21685153a18eSAnirudh Venkataramanan return -ENOMEM; 21695153a18eSAnirudh Venkataramanan 21705153a18eSAnirudh Venkataramanan ctxt->info = vsi->info; 21715153a18eSAnirudh Venkataramanan 21725153a18eSAnirudh Venkataramanan if (ena) { 21735153a18eSAnirudh Venkataramanan ctxt->info.sec_flags |= 21745153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 21755153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S; 21765153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 21775153a18eSAnirudh Venkataramanan } else { 21785153a18eSAnirudh Venkataramanan ctxt->info.sec_flags &= 21795153a18eSAnirudh Venkataramanan ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 21805153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 21815153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 21825153a18eSAnirudh Venkataramanan } 21835153a18eSAnirudh Venkataramanan 21845eda8afdSAkeem G Abodunrin if (!vlan_promisc) 21855eda8afdSAkeem G Abodunrin ctxt->info.valid_sections = 21865eda8afdSAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID | 21875153a18eSAnirudh Venkataramanan ICE_AQ_VSI_PROP_SW_VALID); 21885726ca0eSAnirudh Venkataramanan 2189819d8998SJesse Brandeburg status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL); 21905153a18eSAnirudh Venkataramanan if (status) { 21915726ca0eSAnirudh Venkataramanan netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %d\n", 219231082519SAnirudh Venkataramanan ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status, 2193819d8998SJesse Brandeburg pf->hw.adminq.sq_last_status); 21945153a18eSAnirudh Venkataramanan goto err_out; 21955153a18eSAnirudh Venkataramanan } 21965153a18eSAnirudh Venkataramanan 21975153a18eSAnirudh Venkataramanan vsi->info.sec_flags = ctxt->info.sec_flags; 21985153a18eSAnirudh Venkataramanan vsi->info.sw_flags2 = ctxt->info.sw_flags2; 21995153a18eSAnirudh Venkataramanan 22005153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 22015153a18eSAnirudh Venkataramanan return 0; 22025153a18eSAnirudh Venkataramanan 22035153a18eSAnirudh Venkataramanan err_out: 22045153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 22055153a18eSAnirudh Venkataramanan return -EIO; 22065153a18eSAnirudh Venkataramanan } 22075153a18eSAnirudh Venkataramanan 22087b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) 22097b9ffc76SAnirudh Venkataramanan { 22107b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *cfg = &vsi->port_info->local_dcbx_cfg; 22117b9ffc76SAnirudh Venkataramanan 22127b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg); 22137b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg); 22147b9ffc76SAnirudh Venkataramanan } 22157b9ffc76SAnirudh Venkataramanan 22165153a18eSAnirudh Venkataramanan /** 2217b07833a0SBrett Creeley * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors 2218b07833a0SBrett Creeley * @vsi: VSI to set the q_vectors register index on 2219b07833a0SBrett Creeley */ 2220b07833a0SBrett Creeley static int 2221b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi) 2222b07833a0SBrett Creeley { 2223b07833a0SBrett Creeley u16 i; 2224b07833a0SBrett Creeley 2225b07833a0SBrett Creeley if (!vsi || !vsi->q_vectors) 2226b07833a0SBrett Creeley return -EINVAL; 2227b07833a0SBrett Creeley 2228b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 2229b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2230b07833a0SBrett Creeley 2231b07833a0SBrett Creeley if (!q_vector) { 2232b07833a0SBrett Creeley dev_err(&vsi->back->pdev->dev, 2233b07833a0SBrett Creeley "Failed to set reg_idx on q_vector %d VSI %d\n", 2234b07833a0SBrett Creeley i, vsi->vsi_num); 2235b07833a0SBrett Creeley goto clear_reg_idx; 2236b07833a0SBrett Creeley } 2237b07833a0SBrett Creeley 2238b07833a0SBrett Creeley q_vector->reg_idx = q_vector->v_idx + vsi->hw_base_vector; 2239b07833a0SBrett Creeley } 2240b07833a0SBrett Creeley 2241b07833a0SBrett Creeley return 0; 2242b07833a0SBrett Creeley 2243b07833a0SBrett Creeley clear_reg_idx: 2244b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 2245b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2246b07833a0SBrett Creeley 2247b07833a0SBrett Creeley if (q_vector) 2248b07833a0SBrett Creeley q_vector->reg_idx = 0; 2249b07833a0SBrett Creeley } 2250b07833a0SBrett Creeley 2251b07833a0SBrett Creeley return -EINVAL; 2252b07833a0SBrett Creeley } 2253b07833a0SBrett Creeley 2254b07833a0SBrett Creeley /** 2255d95276ceSAkeem G Abodunrin * ice_vsi_add_rem_eth_mac - Program VSI ethertype based filter with rule 2256d95276ceSAkeem G Abodunrin * @vsi: the VSI being configured 2257d95276ceSAkeem G Abodunrin * @add_rule: boolean value to add or remove ethertype filter rule 2258d95276ceSAkeem G Abodunrin */ 2259d95276ceSAkeem G Abodunrin static void 2260d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(struct ice_vsi *vsi, bool add_rule) 2261d95276ceSAkeem G Abodunrin { 2262d95276ceSAkeem G Abodunrin struct ice_fltr_list_entry *list; 2263d95276ceSAkeem G Abodunrin struct ice_pf *pf = vsi->back; 2264d95276ceSAkeem G Abodunrin LIST_HEAD(tmp_add_list); 2265d95276ceSAkeem G Abodunrin enum ice_status status; 2266d95276ceSAkeem G Abodunrin 2267d95276ceSAkeem G Abodunrin list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 2268d95276ceSAkeem G Abodunrin if (!list) 2269d95276ceSAkeem G Abodunrin return; 2270d95276ceSAkeem G Abodunrin 2271d95276ceSAkeem G Abodunrin list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 2272d95276ceSAkeem G Abodunrin list->fltr_info.fltr_act = ICE_DROP_PACKET; 2273d95276ceSAkeem G Abodunrin list->fltr_info.flag = ICE_FLTR_TX; 2274d95276ceSAkeem G Abodunrin list->fltr_info.src_id = ICE_SRC_ID_VSI; 2275d95276ceSAkeem G Abodunrin list->fltr_info.vsi_handle = vsi->idx; 2276d95276ceSAkeem G Abodunrin list->fltr_info.l_data.ethertype_mac.ethertype = vsi->ethtype; 2277d95276ceSAkeem G Abodunrin 2278d95276ceSAkeem G Abodunrin INIT_LIST_HEAD(&list->list_entry); 2279d95276ceSAkeem G Abodunrin list_add(&list->list_entry, &tmp_add_list); 2280d95276ceSAkeem G Abodunrin 2281d95276ceSAkeem G Abodunrin if (add_rule) 2282d95276ceSAkeem G Abodunrin status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 2283d95276ceSAkeem G Abodunrin else 2284d95276ceSAkeem G Abodunrin status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 2285d95276ceSAkeem G Abodunrin 2286d95276ceSAkeem G Abodunrin if (status) 2287d95276ceSAkeem G Abodunrin dev_err(&pf->pdev->dev, 2288d95276ceSAkeem G Abodunrin "Failure Adding or Removing Ethertype on VSI %i error: %d\n", 2289d95276ceSAkeem G Abodunrin vsi->vsi_num, status); 2290d95276ceSAkeem G Abodunrin 2291d95276ceSAkeem G Abodunrin ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 2292d95276ceSAkeem G Abodunrin } 2293d95276ceSAkeem G Abodunrin 2294d95276ceSAkeem G Abodunrin /** 229537bb8390SAnirudh Venkataramanan * ice_vsi_setup - Set up a VSI by a given type 229637bb8390SAnirudh Venkataramanan * @pf: board private structure 229737bb8390SAnirudh Venkataramanan * @pi: pointer to the port_info instance 229837bb8390SAnirudh Venkataramanan * @type: VSI type 2299f9867df6SAnirudh Venkataramanan * @vf_id: defines VF ID to which this VSI connects. This field is meant to be 230037bb8390SAnirudh Venkataramanan * used only for ICE_VSI_VF VSI type. For other VSI types, should 230137bb8390SAnirudh Venkataramanan * fill-in ICE_INVAL_VFID as input. 230237bb8390SAnirudh Venkataramanan * 230337bb8390SAnirudh Venkataramanan * This allocates the sw VSI structure and its queue resources. 230437bb8390SAnirudh Venkataramanan * 230537bb8390SAnirudh Venkataramanan * Returns pointer to the successfully allocated and configured VSI sw struct on 230637bb8390SAnirudh Venkataramanan * success, NULL on failure. 230737bb8390SAnirudh Venkataramanan */ 230837bb8390SAnirudh Venkataramanan struct ice_vsi * 230937bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, 23108ede0178SAnirudh Venkataramanan enum ice_vsi_type type, u16 vf_id) 231137bb8390SAnirudh Venkataramanan { 231237bb8390SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 231337bb8390SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 231437bb8390SAnirudh Venkataramanan struct ice_vsi *vsi; 231537bb8390SAnirudh Venkataramanan int ret, i; 231637bb8390SAnirudh Venkataramanan 23175743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 23185743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, vf_id); 23195743020dSAkeem G Abodunrin else 23205743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, ICE_INVAL_VFID); 23215743020dSAkeem G Abodunrin 232237bb8390SAnirudh Venkataramanan if (!vsi) { 232337bb8390SAnirudh Venkataramanan dev_err(dev, "could not allocate VSI\n"); 232437bb8390SAnirudh Venkataramanan return NULL; 232537bb8390SAnirudh Venkataramanan } 232637bb8390SAnirudh Venkataramanan 232737bb8390SAnirudh Venkataramanan vsi->port_info = pi; 232837bb8390SAnirudh Venkataramanan vsi->vsw = pf->first_sw; 2329d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 2330d95276ceSAkeem G Abodunrin vsi->ethtype = ETH_P_PAUSE; 2331d95276ceSAkeem G Abodunrin 23328ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 23338ede0178SAnirudh Venkataramanan vsi->vf_id = vf_id; 233437bb8390SAnirudh Venkataramanan 233537bb8390SAnirudh Venkataramanan if (ice_vsi_get_qs(vsi)) { 233637bb8390SAnirudh Venkataramanan dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", 233737bb8390SAnirudh Venkataramanan vsi->idx); 233837bb8390SAnirudh Venkataramanan goto unroll_get_qs; 233937bb8390SAnirudh Venkataramanan } 234037bb8390SAnirudh Venkataramanan 234137bb8390SAnirudh Venkataramanan /* set RSS capabilities */ 234237bb8390SAnirudh Venkataramanan ice_vsi_set_rss_params(vsi); 234337bb8390SAnirudh Venkataramanan 2344f9867df6SAnirudh Venkataramanan /* set TC configuration */ 2345c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2346c5a2a4a3SUsha Ketineni 234737bb8390SAnirudh Venkataramanan /* create the VSI */ 234837bb8390SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 234937bb8390SAnirudh Venkataramanan if (ret) 235037bb8390SAnirudh Venkataramanan goto unroll_get_qs; 235137bb8390SAnirudh Venkataramanan 235237bb8390SAnirudh Venkataramanan switch (vsi->type) { 235337bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 235437bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 235537bb8390SAnirudh Venkataramanan if (ret) 235637bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 235737bb8390SAnirudh Venkataramanan 235837bb8390SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 235937bb8390SAnirudh Venkataramanan if (ret) 236037bb8390SAnirudh Venkataramanan goto unroll_alloc_q_vector; 236137bb8390SAnirudh Venkataramanan 2362b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2363b07833a0SBrett Creeley if (ret) 2364b07833a0SBrett Creeley goto unroll_vector_base; 2365b07833a0SBrett Creeley 236637bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 236737bb8390SAnirudh Venkataramanan if (ret) 236837bb8390SAnirudh Venkataramanan goto unroll_vector_base; 236937bb8390SAnirudh Venkataramanan 237037bb8390SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 237137bb8390SAnirudh Venkataramanan 237237bb8390SAnirudh Venkataramanan /* Do not exit if configuring RSS had an issue, at least 237337bb8390SAnirudh Venkataramanan * receive traffic on first queue. Hence no need to capture 237437bb8390SAnirudh Venkataramanan * return value 237537bb8390SAnirudh Venkataramanan */ 237637bb8390SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 237737bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_lut_key(vsi); 237837bb8390SAnirudh Venkataramanan break; 23798ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 23808ede0178SAnirudh Venkataramanan /* VF driver will take care of creating netdev for this type and 23818ede0178SAnirudh Venkataramanan * map queues to vectors through Virtchnl, PF driver only 23828ede0178SAnirudh Venkataramanan * creates a VSI and corresponding structures for bookkeeping 23838ede0178SAnirudh Venkataramanan * purpose 23848ede0178SAnirudh Venkataramanan */ 23858ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 23868ede0178SAnirudh Venkataramanan if (ret) 23878ede0178SAnirudh Venkataramanan goto unroll_vsi_init; 23888ede0178SAnirudh Venkataramanan 23898ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 23908ede0178SAnirudh Venkataramanan if (ret) 23918ede0178SAnirudh Venkataramanan goto unroll_alloc_q_vector; 23928ede0178SAnirudh Venkataramanan 23938ede0178SAnirudh Venkataramanan /* Setup Vector base only during VF init phase or when VF asks 23948ede0178SAnirudh Venkataramanan * for more vectors than assigned number. In all other cases, 23958ede0178SAnirudh Venkataramanan * assign hw_base_vector to the value given earlier. 23968ede0178SAnirudh Venkataramanan */ 23978ede0178SAnirudh Venkataramanan if (test_bit(ICE_VF_STATE_CFG_INTR, pf->vf[vf_id].vf_states)) { 23988ede0178SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 23998ede0178SAnirudh Venkataramanan if (ret) 24008ede0178SAnirudh Venkataramanan goto unroll_vector_base; 24018ede0178SAnirudh Venkataramanan } else { 24028ede0178SAnirudh Venkataramanan vsi->hw_base_vector = pf->vf[vf_id].first_vector_idx; 24038ede0178SAnirudh Venkataramanan } 2404b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2405b07833a0SBrett Creeley if (ret) 2406b07833a0SBrett Creeley goto unroll_vector_base; 2407b07833a0SBrett Creeley 24088ede0178SAnirudh Venkataramanan pf->q_left_tx -= vsi->alloc_txq; 24098ede0178SAnirudh Venkataramanan pf->q_left_rx -= vsi->alloc_rxq; 24108ede0178SAnirudh Venkataramanan break; 241137bb8390SAnirudh Venkataramanan default: 2412df17b7e0SAnirudh Venkataramanan /* clean up the resources and exit */ 241337bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 241437bb8390SAnirudh Venkataramanan } 241537bb8390SAnirudh Venkataramanan 241637bb8390SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 241737bb8390SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2418c5a2a4a3SUsha Ketineni max_txqs[i] = pf->num_lan_tx; 241937bb8390SAnirudh Venkataramanan 24204fb33f31SAnirudh Venkataramanan ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 24214fb33f31SAnirudh Venkataramanan max_txqs); 242237bb8390SAnirudh Venkataramanan if (ret) { 242320ce2a1aSBrett Creeley dev_err(&pf->pdev->dev, 242420ce2a1aSBrett Creeley "VSI %d failed lan queue config, error %d\n", 242520ce2a1aSBrett Creeley vsi->vsi_num, ret); 242637bb8390SAnirudh Venkataramanan goto unroll_vector_base; 242737bb8390SAnirudh Venkataramanan } 242837bb8390SAnirudh Venkataramanan 2429d95276ceSAkeem G Abodunrin /* Add switch rule to drop all Tx Flow Control Frames, of look up 2430d95276ceSAkeem G Abodunrin * type ETHERTYPE from VSIs, and restrict malicious VF from sending 2431d95276ceSAkeem G Abodunrin * out PAUSE or PFC frames. If enabled, FW can still send FC frames. 2432d95276ceSAkeem G Abodunrin * The rule is added once for PF VSI in order to create appropriate 2433d95276ceSAkeem G Abodunrin * recipe, since VSI/VSI list is ignored with drop action... 2434d95276ceSAkeem G Abodunrin */ 2435d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 2436d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, true); 2437d95276ceSAkeem G Abodunrin 243837bb8390SAnirudh Venkataramanan return vsi; 243937bb8390SAnirudh Venkataramanan 244037bb8390SAnirudh Venkataramanan unroll_vector_base: 2441eb0208ecSPreethi Banala /* reclaim SW interrupts back to the common pool */ 2442819d8998SJesse Brandeburg ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); 2443eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 2444eb0208ecSPreethi Banala /* reclaim HW interrupt back to the common pool */ 2445819d8998SJesse Brandeburg ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); 2446eb0208ecSPreethi Banala pf->num_avail_hw_msix += vsi->num_q_vectors; 244737bb8390SAnirudh Venkataramanan unroll_alloc_q_vector: 244837bb8390SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 244937bb8390SAnirudh Venkataramanan unroll_vsi_init: 245037bb8390SAnirudh Venkataramanan ice_vsi_delete(vsi); 245137bb8390SAnirudh Venkataramanan unroll_get_qs: 245237bb8390SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 245337bb8390SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 245437bb8390SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 245537bb8390SAnirudh Venkataramanan ice_vsi_clear(vsi); 245637bb8390SAnirudh Venkataramanan 245737bb8390SAnirudh Venkataramanan return NULL; 245837bb8390SAnirudh Venkataramanan } 245937bb8390SAnirudh Venkataramanan 246037bb8390SAnirudh Venkataramanan /** 24615153a18eSAnirudh Venkataramanan * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW 24625153a18eSAnirudh Venkataramanan * @vsi: the VSI being cleaned up 24635153a18eSAnirudh Venkataramanan */ 24645153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi) 24655153a18eSAnirudh Venkataramanan { 24665153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2467eb0208ecSPreethi Banala u16 vector = vsi->hw_base_vector; 24685153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 24695153a18eSAnirudh Venkataramanan u32 txq = 0; 24705153a18eSAnirudh Venkataramanan u32 rxq = 0; 24715153a18eSAnirudh Venkataramanan int i, q; 24725153a18eSAnirudh Venkataramanan 24735153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++, vector++) { 24745153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 24755153a18eSAnirudh Venkataramanan 2476d2b464a7SBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR0, vector), 0); 2477d2b464a7SBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR1, vector), 0); 24785153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 24795153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); 24805153a18eSAnirudh Venkataramanan txq++; 24815153a18eSAnirudh Venkataramanan } 24825153a18eSAnirudh Venkataramanan 24835153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 24845153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0); 24855153a18eSAnirudh Venkataramanan rxq++; 24865153a18eSAnirudh Venkataramanan } 24875153a18eSAnirudh Venkataramanan } 24885153a18eSAnirudh Venkataramanan 24895153a18eSAnirudh Venkataramanan ice_flush(hw); 24905153a18eSAnirudh Venkataramanan } 24915153a18eSAnirudh Venkataramanan 24925153a18eSAnirudh Venkataramanan /** 24935153a18eSAnirudh Venkataramanan * ice_vsi_free_irq - Free the IRQ association with the OS 24945153a18eSAnirudh Venkataramanan * @vsi: the VSI being configured 24955153a18eSAnirudh Venkataramanan */ 24965153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi) 24975153a18eSAnirudh Venkataramanan { 24985153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2499eb0208ecSPreethi Banala int base = vsi->sw_base_vector; 25005153a18eSAnirudh Venkataramanan 25015153a18eSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 25025153a18eSAnirudh Venkataramanan int i; 25035153a18eSAnirudh Venkataramanan 25045153a18eSAnirudh Venkataramanan if (!vsi->q_vectors || !vsi->irqs_ready) 25055153a18eSAnirudh Venkataramanan return; 25065153a18eSAnirudh Venkataramanan 2507eb0208ecSPreethi Banala ice_vsi_release_msix(vsi); 25088ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 25098ede0178SAnirudh Venkataramanan return; 2510eb0208ecSPreethi Banala 25115153a18eSAnirudh Venkataramanan vsi->irqs_ready = false; 25120c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) { 25135153a18eSAnirudh Venkataramanan u16 vector = i + base; 25145153a18eSAnirudh Venkataramanan int irq_num; 25155153a18eSAnirudh Venkataramanan 25165153a18eSAnirudh Venkataramanan irq_num = pf->msix_entries[vector].vector; 25175153a18eSAnirudh Venkataramanan 25185153a18eSAnirudh Venkataramanan /* free only the irqs that were actually requested */ 25195153a18eSAnirudh Venkataramanan if (!vsi->q_vectors[i] || 25205153a18eSAnirudh Venkataramanan !(vsi->q_vectors[i]->num_ring_tx || 25215153a18eSAnirudh Venkataramanan vsi->q_vectors[i]->num_ring_rx)) 25225153a18eSAnirudh Venkataramanan continue; 25235153a18eSAnirudh Venkataramanan 25245153a18eSAnirudh Venkataramanan /* clear the affinity notifier in the IRQ descriptor */ 25255153a18eSAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 25265153a18eSAnirudh Venkataramanan 25275153a18eSAnirudh Venkataramanan /* clear the affinity_mask in the IRQ descriptor */ 25285153a18eSAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 25295153a18eSAnirudh Venkataramanan synchronize_irq(irq_num); 25305153a18eSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, 25315153a18eSAnirudh Venkataramanan vsi->q_vectors[i]); 25325153a18eSAnirudh Venkataramanan } 25335153a18eSAnirudh Venkataramanan } 25345153a18eSAnirudh Venkataramanan } 25355153a18eSAnirudh Venkataramanan 25365153a18eSAnirudh Venkataramanan /** 25375153a18eSAnirudh Venkataramanan * ice_vsi_free_tx_rings - Free Tx resources for VSI queues 25385153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 25395153a18eSAnirudh Venkataramanan */ 25405153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi) 25415153a18eSAnirudh Venkataramanan { 25425153a18eSAnirudh Venkataramanan int i; 25435153a18eSAnirudh Venkataramanan 25445153a18eSAnirudh Venkataramanan if (!vsi->tx_rings) 25455153a18eSAnirudh Venkataramanan return; 25465153a18eSAnirudh Venkataramanan 25475153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) 25485153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 25495153a18eSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 25505153a18eSAnirudh Venkataramanan } 25515153a18eSAnirudh Venkataramanan 25525153a18eSAnirudh Venkataramanan /** 25535153a18eSAnirudh Venkataramanan * ice_vsi_free_rx_rings - Free Rx resources for VSI queues 25545153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 25555153a18eSAnirudh Venkataramanan */ 25565153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi) 25575153a18eSAnirudh Venkataramanan { 25585153a18eSAnirudh Venkataramanan int i; 25595153a18eSAnirudh Venkataramanan 25605153a18eSAnirudh Venkataramanan if (!vsi->rx_rings) 25615153a18eSAnirudh Venkataramanan return; 25625153a18eSAnirudh Venkataramanan 25635153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 25645153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) 25655153a18eSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 25665153a18eSAnirudh Venkataramanan } 25675153a18eSAnirudh Venkataramanan 25685153a18eSAnirudh Venkataramanan /** 256907309a0eSAnirudh Venkataramanan * ice_vsi_close - Shut down a VSI 257007309a0eSAnirudh Venkataramanan * @vsi: the VSI being shut down 257107309a0eSAnirudh Venkataramanan */ 257207309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi) 257307309a0eSAnirudh Venkataramanan { 257407309a0eSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) 257507309a0eSAnirudh Venkataramanan ice_down(vsi); 257607309a0eSAnirudh Venkataramanan 257707309a0eSAnirudh Venkataramanan ice_vsi_free_irq(vsi); 257807309a0eSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 257907309a0eSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 258007309a0eSAnirudh Venkataramanan } 258107309a0eSAnirudh Venkataramanan 258207309a0eSAnirudh Venkataramanan /** 25835153a18eSAnirudh Venkataramanan * ice_free_res - free a block of resources 25845153a18eSAnirudh Venkataramanan * @res: pointer to the resource 25855153a18eSAnirudh Venkataramanan * @index: starting index previously returned by ice_get_res 25865153a18eSAnirudh Venkataramanan * @id: identifier to track owner 25875153a18eSAnirudh Venkataramanan * 25885153a18eSAnirudh Venkataramanan * Returns number of resources freed 25895153a18eSAnirudh Venkataramanan */ 25905153a18eSAnirudh Venkataramanan int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) 25915153a18eSAnirudh Venkataramanan { 25925153a18eSAnirudh Venkataramanan int count = 0; 25935153a18eSAnirudh Venkataramanan int i; 25945153a18eSAnirudh Venkataramanan 25955153a18eSAnirudh Venkataramanan if (!res || index >= res->num_entries) 25965153a18eSAnirudh Venkataramanan return -EINVAL; 25975153a18eSAnirudh Venkataramanan 25985153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 25995153a18eSAnirudh Venkataramanan for (i = index; i < res->num_entries && res->list[i] == id; i++) { 26005153a18eSAnirudh Venkataramanan res->list[i] = 0; 26015153a18eSAnirudh Venkataramanan count++; 26025153a18eSAnirudh Venkataramanan } 26035153a18eSAnirudh Venkataramanan 26045153a18eSAnirudh Venkataramanan return count; 26055153a18eSAnirudh Venkataramanan } 26065153a18eSAnirudh Venkataramanan 26075153a18eSAnirudh Venkataramanan /** 26085153a18eSAnirudh Venkataramanan * ice_search_res - Search the tracker for a block of resources 26095153a18eSAnirudh Venkataramanan * @res: pointer to the resource 26105153a18eSAnirudh Venkataramanan * @needed: size of the block needed 26115153a18eSAnirudh Venkataramanan * @id: identifier to track owner 26125153a18eSAnirudh Venkataramanan * 26135153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 26145153a18eSAnirudh Venkataramanan */ 26155153a18eSAnirudh Venkataramanan static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) 26165153a18eSAnirudh Venkataramanan { 26175153a18eSAnirudh Venkataramanan int start = res->search_hint; 26185153a18eSAnirudh Venkataramanan int end = start; 26195153a18eSAnirudh Venkataramanan 2620eb0208ecSPreethi Banala if ((start + needed) > res->num_entries) 2621eb0208ecSPreethi Banala return -ENOMEM; 2622eb0208ecSPreethi Banala 26235153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 26245153a18eSAnirudh Venkataramanan 26255153a18eSAnirudh Venkataramanan do { 26265153a18eSAnirudh Venkataramanan /* skip already allocated entries */ 26275153a18eSAnirudh Venkataramanan if (res->list[end++] & ICE_RES_VALID_BIT) { 26285153a18eSAnirudh Venkataramanan start = end; 26295153a18eSAnirudh Venkataramanan if ((start + needed) > res->num_entries) 26305153a18eSAnirudh Venkataramanan break; 26315153a18eSAnirudh Venkataramanan } 26325153a18eSAnirudh Venkataramanan 26335153a18eSAnirudh Venkataramanan if (end == (start + needed)) { 26345153a18eSAnirudh Venkataramanan int i = start; 26355153a18eSAnirudh Venkataramanan 26365153a18eSAnirudh Venkataramanan /* there was enough, so assign it to the requestor */ 26375153a18eSAnirudh Venkataramanan while (i != end) 26385153a18eSAnirudh Venkataramanan res->list[i++] = id; 26395153a18eSAnirudh Venkataramanan 26405153a18eSAnirudh Venkataramanan if (end == res->num_entries) 26415153a18eSAnirudh Venkataramanan end = 0; 26425153a18eSAnirudh Venkataramanan 26435153a18eSAnirudh Venkataramanan res->search_hint = end; 26445153a18eSAnirudh Venkataramanan return start; 26455153a18eSAnirudh Venkataramanan } 26465153a18eSAnirudh Venkataramanan } while (1); 26475153a18eSAnirudh Venkataramanan 26485153a18eSAnirudh Venkataramanan return -ENOMEM; 26495153a18eSAnirudh Venkataramanan } 26505153a18eSAnirudh Venkataramanan 26515153a18eSAnirudh Venkataramanan /** 26525153a18eSAnirudh Venkataramanan * ice_get_res - get a block of resources 26535153a18eSAnirudh Venkataramanan * @pf: board private structure 26545153a18eSAnirudh Venkataramanan * @res: pointer to the resource 26555153a18eSAnirudh Venkataramanan * @needed: size of the block needed 26565153a18eSAnirudh Venkataramanan * @id: identifier to track owner 26575153a18eSAnirudh Venkataramanan * 26585153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 26595153a18eSAnirudh Venkataramanan * The search_hint trick and lack of advanced fit-finding only works 26605153a18eSAnirudh Venkataramanan * because we're highly likely to have all the same sized requests. 26615153a18eSAnirudh Venkataramanan * Linear search time and any fragmentation should be minimal. 26625153a18eSAnirudh Venkataramanan */ 26635153a18eSAnirudh Venkataramanan int 26645153a18eSAnirudh Venkataramanan ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) 26655153a18eSAnirudh Venkataramanan { 26665153a18eSAnirudh Venkataramanan int ret; 26675153a18eSAnirudh Venkataramanan 26685153a18eSAnirudh Venkataramanan if (!res || !pf) 26695153a18eSAnirudh Venkataramanan return -EINVAL; 26705153a18eSAnirudh Venkataramanan 26715153a18eSAnirudh Venkataramanan if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { 26725153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 26735153a18eSAnirudh Venkataramanan "param err: needed=%d, num_entries = %d id=0x%04x\n", 26745153a18eSAnirudh Venkataramanan needed, res->num_entries, id); 26755153a18eSAnirudh Venkataramanan return -EINVAL; 26765153a18eSAnirudh Venkataramanan } 26775153a18eSAnirudh Venkataramanan 26785153a18eSAnirudh Venkataramanan /* search based on search_hint */ 26795153a18eSAnirudh Venkataramanan ret = ice_search_res(res, needed, id); 26805153a18eSAnirudh Venkataramanan 26815153a18eSAnirudh Venkataramanan if (ret < 0) { 26825153a18eSAnirudh Venkataramanan /* previous search failed. Reset search hint and try again */ 26835153a18eSAnirudh Venkataramanan res->search_hint = 0; 26845153a18eSAnirudh Venkataramanan ret = ice_search_res(res, needed, id); 26855153a18eSAnirudh Venkataramanan } 26865153a18eSAnirudh Venkataramanan 26875153a18eSAnirudh Venkataramanan return ret; 26885153a18eSAnirudh Venkataramanan } 26895153a18eSAnirudh Venkataramanan 26905153a18eSAnirudh Venkataramanan /** 26915153a18eSAnirudh Venkataramanan * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI 26925153a18eSAnirudh Venkataramanan * @vsi: the VSI being un-configured 26935153a18eSAnirudh Venkataramanan */ 26945153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi) 26955153a18eSAnirudh Venkataramanan { 2696eb0208ecSPreethi Banala int base = vsi->sw_base_vector; 26975153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 26985153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 26995153a18eSAnirudh Venkataramanan u32 val; 27005153a18eSAnirudh Venkataramanan int i; 27015153a18eSAnirudh Venkataramanan 27025153a18eSAnirudh Venkataramanan /* disable interrupt causation from each queue */ 27035153a18eSAnirudh Venkataramanan if (vsi->tx_rings) { 27045153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 27055153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i]) { 27065153a18eSAnirudh Venkataramanan u16 reg; 27075153a18eSAnirudh Venkataramanan 27085153a18eSAnirudh Venkataramanan reg = vsi->tx_rings[i]->reg_idx; 27095153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(reg)); 27105153a18eSAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 27115153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(reg), val); 27125153a18eSAnirudh Venkataramanan } 27135153a18eSAnirudh Venkataramanan } 27145153a18eSAnirudh Venkataramanan } 27155153a18eSAnirudh Venkataramanan 27165153a18eSAnirudh Venkataramanan if (vsi->rx_rings) { 27175153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 27185153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i]) { 27195153a18eSAnirudh Venkataramanan u16 reg; 27205153a18eSAnirudh Venkataramanan 27215153a18eSAnirudh Venkataramanan reg = vsi->rx_rings[i]->reg_idx; 27225153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_RQCTL(reg)); 27235153a18eSAnirudh Venkataramanan val &= ~QINT_RQCTL_CAUSE_ENA_M; 27245153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(reg), val); 27255153a18eSAnirudh Venkataramanan } 27265153a18eSAnirudh Venkataramanan } 27275153a18eSAnirudh Venkataramanan } 27285153a18eSAnirudh Venkataramanan 27295153a18eSAnirudh Venkataramanan /* disable each interrupt */ 27305153a18eSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 2731b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) 2732b07833a0SBrett Creeley wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); 27335153a18eSAnirudh Venkataramanan 27345153a18eSAnirudh Venkataramanan ice_flush(hw); 2735b07833a0SBrett Creeley 27360c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) 27375153a18eSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[i + base].vector); 27385153a18eSAnirudh Venkataramanan } 27395153a18eSAnirudh Venkataramanan } 27405153a18eSAnirudh Venkataramanan 27415153a18eSAnirudh Venkataramanan /** 2742df0f8479SAnirudh Venkataramanan * ice_vsi_release - Delete a VSI and free its resources 2743df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 2744df0f8479SAnirudh Venkataramanan * 2745df0f8479SAnirudh Venkataramanan * Returns 0 on success or < 0 on error 2746df0f8479SAnirudh Venkataramanan */ 2747df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi) 2748df0f8479SAnirudh Venkataramanan { 2749b751930cSBrett Creeley struct ice_vf *vf = NULL; 2750df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 2751df0f8479SAnirudh Venkataramanan 2752df0f8479SAnirudh Venkataramanan if (!vsi->back) 2753df0f8479SAnirudh Venkataramanan return -ENODEV; 2754df0f8479SAnirudh Venkataramanan pf = vsi->back; 2755b751930cSBrett Creeley 2756b751930cSBrett Creeley if (vsi->type == ICE_VSI_VF) 27578ede0178SAnirudh Venkataramanan vf = &pf->vf[vsi->vf_id]; 2758aa6ccf3fSBrett Creeley /* do not unregister while driver is in the reset recovery pending 2759aa6ccf3fSBrett Creeley * state. Since reset/rebuild happens through PF service task workqueue, 2760aa6ccf3fSBrett Creeley * it's not a good idea to unregister netdev that is associated to the 2761aa6ccf3fSBrett Creeley * PF that is running the work queue items currently. This is done to 2762aa6ccf3fSBrett Creeley * avoid check_flush_dependency() warning on this wq 2763df0f8479SAnirudh Venkataramanan */ 2764aa6ccf3fSBrett Creeley if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) 2765df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2766df0f8479SAnirudh Venkataramanan 2767df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 2768df0f8479SAnirudh Venkataramanan ice_rss_clean(vsi); 2769df0f8479SAnirudh Venkataramanan 2770df0f8479SAnirudh Venkataramanan /* Disable VSI and free resources */ 2771df0f8479SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 2772df0f8479SAnirudh Venkataramanan ice_vsi_close(vsi); 2773df0f8479SAnirudh Venkataramanan 2774df0f8479SAnirudh Venkataramanan /* reclaim interrupt vectors back to PF */ 27758ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 27768ede0178SAnirudh Venkataramanan /* reclaim SW interrupts back to the common pool */ 2777819d8998SJesse Brandeburg ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); 2778eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 27798ede0178SAnirudh Venkataramanan /* reclaim HW interrupts back to the common pool */ 2780819d8998SJesse Brandeburg ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); 2781eb0208ecSPreethi Banala pf->num_avail_hw_msix += vsi->num_q_vectors; 27828ede0178SAnirudh Venkataramanan } else if (test_bit(ICE_VF_STATE_CFG_INTR, vf->vf_states)) { 27838ede0178SAnirudh Venkataramanan /* Reclaim VF resources back only while freeing all VFs or 27848ede0178SAnirudh Venkataramanan * vector reassignment is requested 27858ede0178SAnirudh Venkataramanan */ 2786819d8998SJesse Brandeburg ice_free_res(pf->hw_irq_tracker, vf->first_vector_idx, 27878ede0178SAnirudh Venkataramanan vsi->idx); 27888ede0178SAnirudh Venkataramanan pf->num_avail_hw_msix += pf->num_vf_msix; 27898ede0178SAnirudh Venkataramanan } 2790df0f8479SAnirudh Venkataramanan 2791d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 2792d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, false); 2793d95276ceSAkeem G Abodunrin 27945726ca0eSAnirudh Venkataramanan ice_remove_vsi_fltr(&pf->hw, vsi->idx); 279510e03a22SAnirudh Venkataramanan ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2796df0f8479SAnirudh Venkataramanan ice_vsi_delete(vsi); 2797df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2798aa6ccf3fSBrett Creeley 2799aa6ccf3fSBrett Creeley /* make sure unregister_netdev() was called by checking __ICE_DOWN */ 2800aa6ccf3fSBrett Creeley if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) { 2801aa6ccf3fSBrett Creeley free_netdev(vsi->netdev); 2802aa6ccf3fSBrett Creeley vsi->netdev = NULL; 2803aa6ccf3fSBrett Creeley } 2804aa6ccf3fSBrett Creeley 2805df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2806df0f8479SAnirudh Venkataramanan 2807df0f8479SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2808df0f8479SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 2809df0f8479SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 2810df0f8479SAnirudh Venkataramanan 2811df0f8479SAnirudh Venkataramanan /* retain SW VSI data structure since it is needed to unregister and 2812df0f8479SAnirudh Venkataramanan * free VSI netdev when PF is not in reset recovery pending state,\ 2813df0f8479SAnirudh Venkataramanan * for ex: during rmmod. 2814df0f8479SAnirudh Venkataramanan */ 28155df7e45dSDave Ertman if (!ice_is_reset_in_progress(pf->state)) 2816df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2817df0f8479SAnirudh Venkataramanan 2818df0f8479SAnirudh Venkataramanan return 0; 2819df0f8479SAnirudh Venkataramanan } 2820df0f8479SAnirudh Venkataramanan 2821df0f8479SAnirudh Venkataramanan /** 2822df0f8479SAnirudh Venkataramanan * ice_vsi_rebuild - Rebuild VSI after reset 2823df0f8479SAnirudh Venkataramanan * @vsi: VSI to be rebuild 2824df0f8479SAnirudh Venkataramanan * 2825df0f8479SAnirudh Venkataramanan * Returns 0 on success and negative value on failure 2826df0f8479SAnirudh Venkataramanan */ 2827df0f8479SAnirudh Venkataramanan int ice_vsi_rebuild(struct ice_vsi *vsi) 2828df0f8479SAnirudh Venkataramanan { 2829df0f8479SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 28307eeac889SAkeem G Abodunrin struct ice_vf *vf = NULL; 2831c5a2a4a3SUsha Ketineni struct ice_pf *pf; 2832df0f8479SAnirudh Venkataramanan int ret, i; 2833df0f8479SAnirudh Venkataramanan 2834df0f8479SAnirudh Venkataramanan if (!vsi) 2835df0f8479SAnirudh Venkataramanan return -EINVAL; 2836df0f8479SAnirudh Venkataramanan 2837c5a2a4a3SUsha Ketineni pf = vsi->back; 28387eeac889SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 28397eeac889SAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 28407eeac889SAkeem G Abodunrin 284147e3e53cSHenry Tieman ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2842df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 28437eeac889SAkeem G Abodunrin 28447eeac889SAkeem G Abodunrin if (vsi->type != ICE_VSI_VF) { 28457eeac889SAkeem G Abodunrin /* reclaim SW interrupts back to the common pool */ 28467eeac889SAkeem G Abodunrin ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); 28477eeac889SAkeem G Abodunrin pf->num_avail_sw_msix += vsi->num_q_vectors; 2848eb0208ecSPreethi Banala vsi->sw_base_vector = 0; 28497eeac889SAkeem G Abodunrin /* reclaim HW interrupts back to the common pool */ 28507eeac889SAkeem G Abodunrin ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, 28517eeac889SAkeem G Abodunrin vsi->idx); 28527eeac889SAkeem G Abodunrin pf->num_avail_hw_msix += vsi->num_q_vectors; 28537eeac889SAkeem G Abodunrin } else { 28547eeac889SAkeem G Abodunrin /* Reclaim VF resources back to the common pool for reset and 28557eeac889SAkeem G Abodunrin * and rebuild, with vector reassignment 28567eeac889SAkeem G Abodunrin */ 28577eeac889SAkeem G Abodunrin ice_free_res(pf->hw_irq_tracker, vf->first_vector_idx, 28587eeac889SAkeem G Abodunrin vsi->idx); 28597eeac889SAkeem G Abodunrin pf->num_avail_hw_msix += pf->num_vf_msix; 28607eeac889SAkeem G Abodunrin } 2861eb0208ecSPreethi Banala vsi->hw_base_vector = 0; 28627eeac889SAkeem G Abodunrin 2863df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2864a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 2865819d8998SJesse Brandeburg ice_dev_onetime_setup(&pf->hw); 28665743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 28675743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf->vf_id); 28685743020dSAkeem G Abodunrin else 28695743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 2870c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2871df0f8479SAnirudh Venkataramanan 2872df0f8479SAnirudh Venkataramanan /* Initialize VSI struct elements and create VSI in FW */ 2873df0f8479SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 2874df0f8479SAnirudh Venkataramanan if (ret < 0) 2875df0f8479SAnirudh Venkataramanan goto err_vsi; 2876df0f8479SAnirudh Venkataramanan 2877a85a3847SBrett Creeley ret = ice_vsi_alloc_arrays(vsi); 2878df0f8479SAnirudh Venkataramanan if (ret < 0) 2879df0f8479SAnirudh Venkataramanan goto err_vsi; 2880df0f8479SAnirudh Venkataramanan 2881df0f8479SAnirudh Venkataramanan switch (vsi->type) { 2882df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 2883df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 2884df0f8479SAnirudh Venkataramanan if (ret) 2885df0f8479SAnirudh Venkataramanan goto err_rings; 2886df0f8479SAnirudh Venkataramanan 2887df0f8479SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 2888df0f8479SAnirudh Venkataramanan if (ret) 2889df0f8479SAnirudh Venkataramanan goto err_vectors; 2890df0f8479SAnirudh Venkataramanan 2891b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2892b07833a0SBrett Creeley if (ret) 2893b07833a0SBrett Creeley goto err_vectors; 2894b07833a0SBrett Creeley 2895df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 2896df0f8479SAnirudh Venkataramanan if (ret) 2897df0f8479SAnirudh Venkataramanan goto err_vectors; 2898df0f8479SAnirudh Venkataramanan 2899df0f8479SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 290027a98affSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 290127a98affSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 290227a98affSMd Fahad Iqbal Polash * return value 290327a98affSMd Fahad Iqbal Polash */ 2904819d8998SJesse Brandeburg if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 290527a98affSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 2906df0f8479SAnirudh Venkataramanan break; 29078ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 29088ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 29098ede0178SAnirudh Venkataramanan if (ret) 29108ede0178SAnirudh Venkataramanan goto err_rings; 29118ede0178SAnirudh Venkataramanan 29128ede0178SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 29138ede0178SAnirudh Venkataramanan if (ret) 29148ede0178SAnirudh Venkataramanan goto err_vectors; 29158ede0178SAnirudh Venkataramanan 2916b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2917b07833a0SBrett Creeley if (ret) 2918b07833a0SBrett Creeley goto err_vectors; 2919b07833a0SBrett Creeley 29208ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 29218ede0178SAnirudh Venkataramanan if (ret) 29228ede0178SAnirudh Venkataramanan goto err_vectors; 29238ede0178SAnirudh Venkataramanan 2924819d8998SJesse Brandeburg pf->q_left_tx -= vsi->alloc_txq; 2925819d8998SJesse Brandeburg pf->q_left_rx -= vsi->alloc_rxq; 29268ede0178SAnirudh Venkataramanan break; 2927df0f8479SAnirudh Venkataramanan default: 2928df0f8479SAnirudh Venkataramanan break; 2929df0f8479SAnirudh Venkataramanan } 2930df0f8479SAnirudh Venkataramanan 2931df0f8479SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 2932df0f8479SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2933c5a2a4a3SUsha Ketineni max_txqs[i] = pf->num_lan_tx; 2934df0f8479SAnirudh Venkataramanan 29354fb33f31SAnirudh Venkataramanan ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 29364fb33f31SAnirudh Venkataramanan max_txqs); 2937df0f8479SAnirudh Venkataramanan if (ret) { 293820ce2a1aSBrett Creeley dev_err(&pf->pdev->dev, 293920ce2a1aSBrett Creeley "VSI %d failed lan queue config, error %d\n", 294020ce2a1aSBrett Creeley vsi->vsi_num, ret); 2941df0f8479SAnirudh Venkataramanan goto err_vectors; 2942df0f8479SAnirudh Venkataramanan } 2943df0f8479SAnirudh Venkataramanan return 0; 2944df0f8479SAnirudh Venkataramanan 2945df0f8479SAnirudh Venkataramanan err_vectors: 2946df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2947df0f8479SAnirudh Venkataramanan err_rings: 2948df0f8479SAnirudh Venkataramanan if (vsi->netdev) { 2949df0f8479SAnirudh Venkataramanan vsi->current_netdev_flags = 0; 2950df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2951df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 2952df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 2953df0f8479SAnirudh Venkataramanan } 2954df0f8479SAnirudh Venkataramanan err_vsi: 2955df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2956819d8998SJesse Brandeburg set_bit(__ICE_RESET_FAILED, pf->state); 2957df0f8479SAnirudh Venkataramanan return ret; 2958df0f8479SAnirudh Venkataramanan } 2959df0f8479SAnirudh Venkataramanan 2960df0f8479SAnirudh Venkataramanan /** 29615df7e45dSDave Ertman * ice_is_reset_in_progress - check for a reset in progress 29625153a18eSAnirudh Venkataramanan * @state: pf state field 29635153a18eSAnirudh Venkataramanan */ 29645df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state) 29655153a18eSAnirudh Venkataramanan { 29665df7e45dSDave Ertman return test_bit(__ICE_RESET_OICR_RECV, state) || 29675df7e45dSDave Ertman test_bit(__ICE_PFR_REQ, state) || 29685df7e45dSDave Ertman test_bit(__ICE_CORER_REQ, state) || 29695df7e45dSDave Ertman test_bit(__ICE_GLOBR_REQ, state); 29705153a18eSAnirudh Venkataramanan } 29717b9ffc76SAnirudh Venkataramanan 29727b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 29737b9ffc76SAnirudh Venkataramanan /** 29747b9ffc76SAnirudh Venkataramanan * ice_vsi_update_q_map - update our copy of the VSI info with new queue map 29757b9ffc76SAnirudh Venkataramanan * @vsi: VSI being configured 29767b9ffc76SAnirudh Venkataramanan * @ctx: the context buffer returned from AQ VSI update command 29777b9ffc76SAnirudh Venkataramanan */ 29787b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx) 29797b9ffc76SAnirudh Venkataramanan { 29807b9ffc76SAnirudh Venkataramanan vsi->info.mapping_flags = ctx->info.mapping_flags; 29817b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping, 29827b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.q_mapping)); 29837b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping, 29847b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.tc_mapping)); 29857b9ffc76SAnirudh Venkataramanan } 29867b9ffc76SAnirudh Venkataramanan 29877b9ffc76SAnirudh Venkataramanan /** 29887b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration 29897b9ffc76SAnirudh Venkataramanan * @vsi: the VSI being configured 29907b9ffc76SAnirudh Venkataramanan * @ena_tc: TC map to be enabled 29917b9ffc76SAnirudh Venkataramanan */ 29927b9ffc76SAnirudh Venkataramanan static void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc) 29937b9ffc76SAnirudh Venkataramanan { 29947b9ffc76SAnirudh Venkataramanan struct net_device *netdev = vsi->netdev; 29957b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 29967b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg; 29977b9ffc76SAnirudh Venkataramanan u8 netdev_tc; 29987b9ffc76SAnirudh Venkataramanan int i; 29997b9ffc76SAnirudh Venkataramanan 30007b9ffc76SAnirudh Venkataramanan if (!netdev) 30017b9ffc76SAnirudh Venkataramanan return; 30027b9ffc76SAnirudh Venkataramanan 30037b9ffc76SAnirudh Venkataramanan if (!ena_tc) { 30047b9ffc76SAnirudh Venkataramanan netdev_reset_tc(netdev); 30057b9ffc76SAnirudh Venkataramanan return; 30067b9ffc76SAnirudh Venkataramanan } 30077b9ffc76SAnirudh Venkataramanan 30087b9ffc76SAnirudh Venkataramanan if (netdev_set_num_tc(netdev, vsi->tc_cfg.numtc)) 30097b9ffc76SAnirudh Venkataramanan return; 30107b9ffc76SAnirudh Venkataramanan 30117b9ffc76SAnirudh Venkataramanan dcbcfg = &pf->hw.port_info->local_dcbx_cfg; 30127b9ffc76SAnirudh Venkataramanan 30137b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) 30147b9ffc76SAnirudh Venkataramanan if (vsi->tc_cfg.ena_tc & BIT(i)) 30157b9ffc76SAnirudh Venkataramanan netdev_set_tc_queue(netdev, 30167b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].netdev_tc, 30177b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qcount_tx, 30187b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset); 30197b9ffc76SAnirudh Venkataramanan 30207b9ffc76SAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 30217b9ffc76SAnirudh Venkataramanan u8 ets_tc = dcbcfg->etscfg.prio_table[i]; 30227b9ffc76SAnirudh Venkataramanan 30237b9ffc76SAnirudh Venkataramanan /* Get the mapped netdev TC# for the UP */ 30247b9ffc76SAnirudh Venkataramanan netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc; 30257b9ffc76SAnirudh Venkataramanan netdev_set_prio_tc_map(netdev, i, netdev_tc); 30267b9ffc76SAnirudh Venkataramanan } 30277b9ffc76SAnirudh Venkataramanan } 30287b9ffc76SAnirudh Venkataramanan 30297b9ffc76SAnirudh Venkataramanan /** 30307b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map 30317b9ffc76SAnirudh Venkataramanan * @vsi: VSI to be configured 30327b9ffc76SAnirudh Venkataramanan * @ena_tc: TC bitmap 30337b9ffc76SAnirudh Venkataramanan * 30347b9ffc76SAnirudh Venkataramanan * VSI queues expected to be quiesced before calling this function 30357b9ffc76SAnirudh Venkataramanan */ 30367b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) 30377b9ffc76SAnirudh Venkataramanan { 30387b9ffc76SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 30397b9ffc76SAnirudh Venkataramanan struct ice_vsi_ctx *ctx; 30407b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 30417b9ffc76SAnirudh Venkataramanan enum ice_status status; 30427b9ffc76SAnirudh Venkataramanan int i, ret = 0; 30437b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 30447b9ffc76SAnirudh Venkataramanan 30457b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) { 30467b9ffc76SAnirudh Venkataramanan /* build bitmap of enabled TCs */ 30477b9ffc76SAnirudh Venkataramanan if (ena_tc & BIT(i)) 30487b9ffc76SAnirudh Venkataramanan num_tc++; 30497b9ffc76SAnirudh Venkataramanan /* populate max_txqs per TC */ 30507b9ffc76SAnirudh Venkataramanan max_txqs[i] = pf->num_lan_tx; 30517b9ffc76SAnirudh Venkataramanan } 30527b9ffc76SAnirudh Venkataramanan 30537b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ena_tc; 30547b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = num_tc; 30557b9ffc76SAnirudh Venkataramanan 30567b9ffc76SAnirudh Venkataramanan ctx = devm_kzalloc(&pf->pdev->dev, sizeof(*ctx), GFP_KERNEL); 30577b9ffc76SAnirudh Venkataramanan if (!ctx) 30587b9ffc76SAnirudh Venkataramanan return -ENOMEM; 30597b9ffc76SAnirudh Venkataramanan 30607b9ffc76SAnirudh Venkataramanan ctx->vf_num = 0; 30617b9ffc76SAnirudh Venkataramanan ctx->info = vsi->info; 30627b9ffc76SAnirudh Venkataramanan 30637b9ffc76SAnirudh Venkataramanan ice_vsi_setup_q_map(vsi, ctx); 30647b9ffc76SAnirudh Venkataramanan 30657b9ffc76SAnirudh Venkataramanan /* must to indicate which section of VSI context are being modified */ 30667b9ffc76SAnirudh Venkataramanan ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 30677b9ffc76SAnirudh Venkataramanan status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL); 30687b9ffc76SAnirudh Venkataramanan if (status) { 30697b9ffc76SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "Failed VSI Update\n"); 30707b9ffc76SAnirudh Venkataramanan ret = -EIO; 30717b9ffc76SAnirudh Venkataramanan goto out; 30727b9ffc76SAnirudh Venkataramanan } 30737b9ffc76SAnirudh Venkataramanan 30747b9ffc76SAnirudh Venkataramanan status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 30757b9ffc76SAnirudh Venkataramanan max_txqs); 30767b9ffc76SAnirudh Venkataramanan 30777b9ffc76SAnirudh Venkataramanan if (status) { 30787b9ffc76SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 30797b9ffc76SAnirudh Venkataramanan "VSI %d failed TC config, error %d\n", 30807b9ffc76SAnirudh Venkataramanan vsi->vsi_num, status); 30817b9ffc76SAnirudh Venkataramanan ret = -EIO; 30827b9ffc76SAnirudh Venkataramanan goto out; 30837b9ffc76SAnirudh Venkataramanan } 30847b9ffc76SAnirudh Venkataramanan ice_vsi_update_q_map(vsi, ctx); 30857b9ffc76SAnirudh Venkataramanan vsi->info.valid_sections = 0; 30867b9ffc76SAnirudh Venkataramanan 30877b9ffc76SAnirudh Venkataramanan ice_vsi_cfg_netdev_tc(vsi, ena_tc); 30887b9ffc76SAnirudh Venkataramanan out: 30897b9ffc76SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, ctx); 30907b9ffc76SAnirudh Venkataramanan return ret; 30917b9ffc76SAnirudh Venkataramanan } 30927b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 3093