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) { 1400e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 1410e674aebSAnirudh Venkataramanan /* fall through */ 14272adf242SAnirudh Venkataramanan case ICE_VSI_PF: 14372adf242SAnirudh Venkataramanan tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_PF; 14472adf242SAnirudh Venkataramanan break; 1458ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 146f9867df6SAnirudh Venkataramanan /* Firmware expects vmvf_num to be absolute VF ID */ 1478ede0178SAnirudh Venkataramanan tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf_id; 1488ede0178SAnirudh Venkataramanan tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF; 1498ede0178SAnirudh Venkataramanan break; 15072adf242SAnirudh Venkataramanan default: 15172adf242SAnirudh Venkataramanan return; 15272adf242SAnirudh Venkataramanan } 15372adf242SAnirudh Venkataramanan 15472adf242SAnirudh Venkataramanan /* make sure the context is associated with the right VSI */ 1554fb33f31SAnirudh Venkataramanan tlan_ctx->src_vsi = ice_get_hw_vsi_num(hw, vsi->idx); 15672adf242SAnirudh Venkataramanan 15772adf242SAnirudh Venkataramanan tlan_ctx->tso_ena = ICE_TX_LEGACY; 15872adf242SAnirudh Venkataramanan tlan_ctx->tso_qnum = pf_q; 15972adf242SAnirudh Venkataramanan 16072adf242SAnirudh Venkataramanan /* Legacy or Advanced Host Interface: 16172adf242SAnirudh Venkataramanan * 0: Advanced Host Interface 16272adf242SAnirudh Venkataramanan * 1: Legacy Host Interface 16372adf242SAnirudh Venkataramanan */ 16472adf242SAnirudh Venkataramanan tlan_ctx->legacy_int = ICE_TX_LEGACY; 16572adf242SAnirudh Venkataramanan } 16672adf242SAnirudh Venkataramanan 16772adf242SAnirudh Venkataramanan /** 16872adf242SAnirudh Venkataramanan * ice_pf_rxq_wait - Wait for a PF's Rx queue to be enabled or disabled 16972adf242SAnirudh Venkataramanan * @pf: the PF being configured 17072adf242SAnirudh Venkataramanan * @pf_q: the PF queue 17172adf242SAnirudh Venkataramanan * @ena: enable or disable state of the queue 17272adf242SAnirudh Venkataramanan * 17372adf242SAnirudh Venkataramanan * This routine will wait for the given Rx queue of the PF to reach the 17472adf242SAnirudh Venkataramanan * enabled or disabled state. 17572adf242SAnirudh Venkataramanan * Returns -ETIMEDOUT in case of failing to reach the requested state after 17672adf242SAnirudh Venkataramanan * multiple retries; else will return 0 in case of success. 17772adf242SAnirudh Venkataramanan */ 17872adf242SAnirudh Venkataramanan static int ice_pf_rxq_wait(struct ice_pf *pf, int pf_q, bool ena) 17972adf242SAnirudh Venkataramanan { 18072adf242SAnirudh Venkataramanan int i; 18172adf242SAnirudh Venkataramanan 1827b8ff0f9SPiotr Raczynski for (i = 0; i < ICE_Q_WAIT_MAX_RETRY; i++) { 18316c3301bSBrett Creeley if (ena == !!(rd32(&pf->hw, QRX_CTRL(pf_q)) & 18416c3301bSBrett Creeley QRX_CTRL_QENA_STAT_M)) 18516c3301bSBrett Creeley return 0; 18672adf242SAnirudh Venkataramanan 1877b8ff0f9SPiotr Raczynski usleep_range(20, 40); 18872adf242SAnirudh Venkataramanan } 18972adf242SAnirudh Venkataramanan 19016c3301bSBrett Creeley return -ETIMEDOUT; 19172adf242SAnirudh Venkataramanan } 19272adf242SAnirudh Venkataramanan 19372adf242SAnirudh Venkataramanan /** 194d02f734cSMaciej Fijalkowski * ice_vsi_ctrl_rx_ring - Start or stop a VSI's Rx ring 19572adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 19672adf242SAnirudh Venkataramanan * @ena: start or stop the Rx rings 197d02f734cSMaciej Fijalkowski * @rxq_idx: Rx queue index 19872adf242SAnirudh Venkataramanan */ 19977ca27c4SPaul Greenwalt #ifndef CONFIG_PCI_IOV 20077ca27c4SPaul Greenwalt static 20177ca27c4SPaul Greenwalt #endif /* !CONFIG_PCI_IOV */ 20277ca27c4SPaul Greenwalt int ice_vsi_ctrl_rx_ring(struct ice_vsi *vsi, bool ena, u16 rxq_idx) 20372adf242SAnirudh Venkataramanan { 204d02f734cSMaciej Fijalkowski int pf_q = vsi->rxq_map[rxq_idx]; 20572adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 20672adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 207d02f734cSMaciej Fijalkowski int ret = 0; 20872adf242SAnirudh Venkataramanan u32 rx_reg; 20972adf242SAnirudh Venkataramanan 21072adf242SAnirudh Venkataramanan rx_reg = rd32(hw, QRX_CTRL(pf_q)); 21172adf242SAnirudh Venkataramanan 21272adf242SAnirudh Venkataramanan /* Skip if the queue is already in the requested state */ 21372adf242SAnirudh Venkataramanan if (ena == !!(rx_reg & QRX_CTRL_QENA_STAT_M)) 214d02f734cSMaciej Fijalkowski return 0; 21572adf242SAnirudh Venkataramanan 21672adf242SAnirudh Venkataramanan /* turn on/off the queue */ 21772adf242SAnirudh Venkataramanan if (ena) 21872adf242SAnirudh Venkataramanan rx_reg |= QRX_CTRL_QENA_REQ_M; 21972adf242SAnirudh Venkataramanan else 22072adf242SAnirudh Venkataramanan rx_reg &= ~QRX_CTRL_QENA_REQ_M; 22172adf242SAnirudh Venkataramanan wr32(hw, QRX_CTRL(pf_q), rx_reg); 22272adf242SAnirudh Venkataramanan 22372adf242SAnirudh Venkataramanan /* wait for the change to finish */ 22472adf242SAnirudh Venkataramanan ret = ice_pf_rxq_wait(pf, pf_q, ena); 225d02f734cSMaciej Fijalkowski if (ret) 22672adf242SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 22772adf242SAnirudh Venkataramanan "VSI idx %d Rx ring %d %sable timeout\n", 22872adf242SAnirudh Venkataramanan vsi->idx, pf_q, (ena ? "en" : "dis")); 229d02f734cSMaciej Fijalkowski 230d02f734cSMaciej Fijalkowski return ret; 23172adf242SAnirudh Venkataramanan } 232d02f734cSMaciej Fijalkowski 233d02f734cSMaciej Fijalkowski /** 234d02f734cSMaciej Fijalkowski * ice_vsi_ctrl_rx_rings - Start or stop a VSI's Rx rings 235d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 236d02f734cSMaciej Fijalkowski * @ena: start or stop the Rx rings 237d02f734cSMaciej Fijalkowski */ 238d02f734cSMaciej Fijalkowski static int ice_vsi_ctrl_rx_rings(struct ice_vsi *vsi, bool ena) 239d02f734cSMaciej Fijalkowski { 240d02f734cSMaciej Fijalkowski int i, ret = 0; 241d02f734cSMaciej Fijalkowski 242d02f734cSMaciej Fijalkowski for (i = 0; i < vsi->num_rxq; i++) { 243d02f734cSMaciej Fijalkowski ret = ice_vsi_ctrl_rx_ring(vsi, ena, i); 244d02f734cSMaciej Fijalkowski if (ret) 245d02f734cSMaciej Fijalkowski break; 24672adf242SAnirudh Venkataramanan } 24772adf242SAnirudh Venkataramanan 24872adf242SAnirudh Venkataramanan return ret; 24972adf242SAnirudh Venkataramanan } 25072adf242SAnirudh Venkataramanan 25172adf242SAnirudh Venkataramanan /** 25228c2a645SAnirudh Venkataramanan * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI 25328c2a645SAnirudh Venkataramanan * @vsi: VSI pointer 25428c2a645SAnirudh Venkataramanan * 25528c2a645SAnirudh Venkataramanan * On error: returns error code (negative) 25628c2a645SAnirudh Venkataramanan * On success: returns 0 25728c2a645SAnirudh Venkataramanan */ 258a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) 25928c2a645SAnirudh Venkataramanan { 26028c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 26128c2a645SAnirudh Venkataramanan 26228c2a645SAnirudh Venkataramanan /* allocate memory for both Tx and Rx ring pointers */ 26328c2a645SAnirudh Venkataramanan vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 264c6dfd690SBruce Allan sizeof(*vsi->tx_rings), GFP_KERNEL); 26528c2a645SAnirudh Venkataramanan if (!vsi->tx_rings) 26678b5713aSAnirudh Venkataramanan return -ENOMEM; 26728c2a645SAnirudh Venkataramanan 26828c2a645SAnirudh Venkataramanan vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 269c6dfd690SBruce Allan sizeof(*vsi->rx_rings), GFP_KERNEL); 27028c2a645SAnirudh Venkataramanan if (!vsi->rx_rings) 27178b5713aSAnirudh Venkataramanan goto err_rings; 27278b5713aSAnirudh Venkataramanan 27378b5713aSAnirudh Venkataramanan vsi->txq_map = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 27478b5713aSAnirudh Venkataramanan sizeof(*vsi->txq_map), GFP_KERNEL); 27578b5713aSAnirudh Venkataramanan 27678b5713aSAnirudh Venkataramanan if (!vsi->txq_map) 27778b5713aSAnirudh Venkataramanan goto err_txq_map; 27878b5713aSAnirudh Venkataramanan 27978b5713aSAnirudh Venkataramanan vsi->rxq_map = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 28078b5713aSAnirudh Venkataramanan sizeof(*vsi->rxq_map), GFP_KERNEL); 28178b5713aSAnirudh Venkataramanan if (!vsi->rxq_map) 28278b5713aSAnirudh Venkataramanan goto err_rxq_map; 28378b5713aSAnirudh Venkataramanan 28428c2a645SAnirudh Venkataramanan 2850e674aebSAnirudh Venkataramanan /* There is no need to allocate q_vectors for a loopback VSI. */ 2860e674aebSAnirudh Venkataramanan if (vsi->type == ICE_VSI_LB) 2870e674aebSAnirudh Venkataramanan return 0; 2880e674aebSAnirudh Venkataramanan 28928c2a645SAnirudh Venkataramanan /* allocate memory for q_vector pointers */ 290a85a3847SBrett Creeley vsi->q_vectors = devm_kcalloc(&pf->pdev->dev, vsi->num_q_vectors, 291a85a3847SBrett Creeley sizeof(*vsi->q_vectors), GFP_KERNEL); 29228c2a645SAnirudh Venkataramanan if (!vsi->q_vectors) 29328c2a645SAnirudh Venkataramanan goto err_vectors; 29428c2a645SAnirudh Venkataramanan 29528c2a645SAnirudh Venkataramanan return 0; 29628c2a645SAnirudh Venkataramanan 29728c2a645SAnirudh Venkataramanan err_vectors: 29878b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rxq_map); 29978b5713aSAnirudh Venkataramanan err_rxq_map: 30078b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->txq_map); 30178b5713aSAnirudh Venkataramanan err_txq_map: 30228c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 30378b5713aSAnirudh Venkataramanan err_rings: 30428c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 30528c2a645SAnirudh Venkataramanan return -ENOMEM; 30628c2a645SAnirudh Venkataramanan } 30728c2a645SAnirudh Venkataramanan 30828c2a645SAnirudh Venkataramanan /** 309ad71b256SBrett Creeley * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI 310ad71b256SBrett Creeley * @vsi: the VSI being configured 311ad71b256SBrett Creeley */ 312ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi) 313ad71b256SBrett Creeley { 314ad71b256SBrett Creeley switch (vsi->type) { 315ad71b256SBrett Creeley case ICE_VSI_PF: 3160e674aebSAnirudh Venkataramanan /* fall through */ 3170e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 318ad71b256SBrett Creeley vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC; 319ad71b256SBrett Creeley vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC; 320ad71b256SBrett Creeley break; 321ad71b256SBrett Creeley default: 322ad71b256SBrett Creeley dev_dbg(&vsi->back->pdev->dev, 323ad71b256SBrett Creeley "Not setting number of Tx/Rx descriptors for VSI type %d\n", 324ad71b256SBrett Creeley vsi->type); 325ad71b256SBrett Creeley break; 326ad71b256SBrett Creeley } 327ad71b256SBrett Creeley } 328ad71b256SBrett Creeley 329ad71b256SBrett Creeley /** 330ad71b256SBrett Creeley * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI 33128c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 332f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 33328c2a645SAnirudh Venkataramanan * 33428c2a645SAnirudh Venkataramanan * Return 0 on success and a negative value on error 33528c2a645SAnirudh Venkataramanan */ 3365743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) 33728c2a645SAnirudh Venkataramanan { 33828c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3395743020dSAkeem G Abodunrin struct ice_vf *vf = NULL; 3405743020dSAkeem G Abodunrin 3415743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 3425743020dSAkeem G Abodunrin vsi->vf_id = vf_id; 3435743020dSAkeem G Abodunrin 34428c2a645SAnirudh Venkataramanan switch (vsi->type) { 34528c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 34628c2a645SAnirudh Venkataramanan vsi->alloc_txq = pf->num_lan_tx; 34728c2a645SAnirudh Venkataramanan vsi->alloc_rxq = pf->num_lan_rx; 34828c2a645SAnirudh Venkataramanan vsi->num_q_vectors = max_t(int, pf->num_lan_rx, pf->num_lan_tx); 34928c2a645SAnirudh Venkataramanan break; 3508ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 3515743020dSAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 3525743020dSAkeem G Abodunrin vsi->alloc_txq = vf->num_vf_qs; 3535743020dSAkeem G Abodunrin vsi->alloc_rxq = vf->num_vf_qs; 3548ede0178SAnirudh Venkataramanan /* pf->num_vf_msix includes (VF miscellaneous vector + 3558ede0178SAnirudh Venkataramanan * data queue interrupts). Since vsi->num_q_vectors is number 356047e52c0SAnirudh Venkataramanan * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the 357047e52c0SAnirudh Venkataramanan * original vector count 3588ede0178SAnirudh Venkataramanan */ 359047e52c0SAnirudh Venkataramanan vsi->num_q_vectors = pf->num_vf_msix - ICE_NONQ_VECS_VF; 3608ede0178SAnirudh Venkataramanan break; 3610e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 3620e674aebSAnirudh Venkataramanan vsi->alloc_txq = 1; 3630e674aebSAnirudh Venkataramanan vsi->alloc_rxq = 1; 3640e674aebSAnirudh Venkataramanan break; 36528c2a645SAnirudh Venkataramanan default: 366819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 36728c2a645SAnirudh Venkataramanan break; 36828c2a645SAnirudh Venkataramanan } 369ad71b256SBrett Creeley 370ad71b256SBrett Creeley ice_vsi_set_num_desc(vsi); 37128c2a645SAnirudh Venkataramanan } 37228c2a645SAnirudh Venkataramanan 37328c2a645SAnirudh Venkataramanan /** 37428c2a645SAnirudh Venkataramanan * ice_get_free_slot - get the next non-NULL location index in array 37528c2a645SAnirudh Venkataramanan * @array: array to search 37628c2a645SAnirudh Venkataramanan * @size: size of the array 37728c2a645SAnirudh Venkataramanan * @curr: last known occupied index to be used as a search hint 37828c2a645SAnirudh Venkataramanan * 37928c2a645SAnirudh Venkataramanan * void * is being used to keep the functionality generic. This lets us use this 38028c2a645SAnirudh Venkataramanan * function on any array of pointers. 38128c2a645SAnirudh Venkataramanan */ 38237bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr) 38328c2a645SAnirudh Venkataramanan { 38428c2a645SAnirudh Venkataramanan int **tmp_array = (int **)array; 38528c2a645SAnirudh Venkataramanan int next; 38628c2a645SAnirudh Venkataramanan 38728c2a645SAnirudh Venkataramanan if (curr < (size - 1) && !tmp_array[curr + 1]) { 38828c2a645SAnirudh Venkataramanan next = curr + 1; 38928c2a645SAnirudh Venkataramanan } else { 39028c2a645SAnirudh Venkataramanan int i = 0; 39128c2a645SAnirudh Venkataramanan 39228c2a645SAnirudh Venkataramanan while ((i < size) && (tmp_array[i])) 39328c2a645SAnirudh Venkataramanan i++; 39428c2a645SAnirudh Venkataramanan if (i == size) 39528c2a645SAnirudh Venkataramanan next = ICE_NO_VSI; 39628c2a645SAnirudh Venkataramanan else 39728c2a645SAnirudh Venkataramanan next = i; 39828c2a645SAnirudh Venkataramanan } 39928c2a645SAnirudh Venkataramanan return next; 40028c2a645SAnirudh Venkataramanan } 40128c2a645SAnirudh Venkataramanan 40228c2a645SAnirudh Venkataramanan /** 4035153a18eSAnirudh Venkataramanan * ice_vsi_delete - delete a VSI from the switch 4045153a18eSAnirudh Venkataramanan * @vsi: pointer to VSI being removed 4055153a18eSAnirudh Venkataramanan */ 4065153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi) 4075153a18eSAnirudh Venkataramanan { 4085153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 409198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 4105153a18eSAnirudh Venkataramanan enum ice_status status; 4115153a18eSAnirudh Venkataramanan 412198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 413198a666aSBruce Allan if (!ctxt) 414198a666aSBruce Allan return; 415198a666aSBruce Allan 4168ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 417198a666aSBruce Allan ctxt->vf_num = vsi->vf_id; 418198a666aSBruce Allan ctxt->vsi_num = vsi->vsi_num; 4195153a18eSAnirudh Venkataramanan 420198a666aSBruce Allan memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); 4215153a18eSAnirudh Venkataramanan 422198a666aSBruce Allan status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); 4235153a18eSAnirudh Venkataramanan if (status) 4245153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failed to delete VSI %i in FW\n", 4255153a18eSAnirudh Venkataramanan vsi->vsi_num); 426198a666aSBruce Allan 427198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 4285153a18eSAnirudh Venkataramanan } 4295153a18eSAnirudh Venkataramanan 4305153a18eSAnirudh Venkataramanan /** 431a85a3847SBrett Creeley * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI 43207309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 43307309a0eSAnirudh Venkataramanan */ 434a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi) 43507309a0eSAnirudh Venkataramanan { 43607309a0eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 43707309a0eSAnirudh Venkataramanan 43807309a0eSAnirudh Venkataramanan /* free the ring and vector containers */ 439a85a3847SBrett Creeley if (vsi->q_vectors) { 44007309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->q_vectors); 44107309a0eSAnirudh Venkataramanan vsi->q_vectors = NULL; 44207309a0eSAnirudh Venkataramanan } 44307309a0eSAnirudh Venkataramanan if (vsi->tx_rings) { 44407309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 44507309a0eSAnirudh Venkataramanan vsi->tx_rings = NULL; 44607309a0eSAnirudh Venkataramanan } 44707309a0eSAnirudh Venkataramanan if (vsi->rx_rings) { 44807309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 44907309a0eSAnirudh Venkataramanan vsi->rx_rings = NULL; 45007309a0eSAnirudh Venkataramanan } 45178b5713aSAnirudh Venkataramanan if (vsi->txq_map) { 45278b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->txq_map); 45378b5713aSAnirudh Venkataramanan vsi->txq_map = NULL; 45478b5713aSAnirudh Venkataramanan } 45578b5713aSAnirudh Venkataramanan if (vsi->rxq_map) { 45678b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rxq_map); 45778b5713aSAnirudh Venkataramanan vsi->rxq_map = NULL; 45878b5713aSAnirudh Venkataramanan } 45907309a0eSAnirudh Venkataramanan } 46007309a0eSAnirudh Venkataramanan 46107309a0eSAnirudh Venkataramanan /** 46207309a0eSAnirudh Venkataramanan * ice_vsi_clear - clean up and deallocate the provided VSI 46307309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 46407309a0eSAnirudh Venkataramanan * 46507309a0eSAnirudh Venkataramanan * This deallocates the VSI's queue resources, removes it from the PF's 46607309a0eSAnirudh Venkataramanan * VSI array if necessary, and deallocates the VSI 46707309a0eSAnirudh Venkataramanan * 46807309a0eSAnirudh Venkataramanan * Returns 0 on success, negative on failure 46907309a0eSAnirudh Venkataramanan */ 47007309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi) 47107309a0eSAnirudh Venkataramanan { 47207309a0eSAnirudh Venkataramanan struct ice_pf *pf = NULL; 47307309a0eSAnirudh Venkataramanan 47407309a0eSAnirudh Venkataramanan if (!vsi) 47507309a0eSAnirudh Venkataramanan return 0; 47607309a0eSAnirudh Venkataramanan 47707309a0eSAnirudh Venkataramanan if (!vsi->back) 47807309a0eSAnirudh Venkataramanan return -EINVAL; 47907309a0eSAnirudh Venkataramanan 48007309a0eSAnirudh Venkataramanan pf = vsi->back; 48107309a0eSAnirudh Venkataramanan 48207309a0eSAnirudh Venkataramanan if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) { 48307309a0eSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "vsi does not exist at pf->vsi[%d]\n", 48407309a0eSAnirudh Venkataramanan vsi->idx); 48507309a0eSAnirudh Venkataramanan return -EINVAL; 48607309a0eSAnirudh Venkataramanan } 48707309a0eSAnirudh Venkataramanan 48807309a0eSAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 48907309a0eSAnirudh Venkataramanan /* updates the PF for this cleared VSI */ 49007309a0eSAnirudh Venkataramanan 49107309a0eSAnirudh Venkataramanan pf->vsi[vsi->idx] = NULL; 49207309a0eSAnirudh Venkataramanan if (vsi->idx < pf->next_vsi) 49307309a0eSAnirudh Venkataramanan pf->next_vsi = vsi->idx; 49407309a0eSAnirudh Venkataramanan 495a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 49607309a0eSAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 49707309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 49807309a0eSAnirudh Venkataramanan 49907309a0eSAnirudh Venkataramanan return 0; 50007309a0eSAnirudh Venkataramanan } 50107309a0eSAnirudh Venkataramanan 50207309a0eSAnirudh Venkataramanan /** 5035153a18eSAnirudh Venkataramanan * ice_msix_clean_rings - MSIX mode Interrupt Handler 5045153a18eSAnirudh Venkataramanan * @irq: interrupt number 5055153a18eSAnirudh Venkataramanan * @data: pointer to a q_vector 5065153a18eSAnirudh Venkataramanan */ 507f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data) 5085153a18eSAnirudh Venkataramanan { 5095153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 5105153a18eSAnirudh Venkataramanan 5115153a18eSAnirudh Venkataramanan if (!q_vector->tx.ring && !q_vector->rx.ring) 5125153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 5135153a18eSAnirudh Venkataramanan 5145153a18eSAnirudh Venkataramanan napi_schedule(&q_vector->napi); 5155153a18eSAnirudh Venkataramanan 5165153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 5175153a18eSAnirudh Venkataramanan } 5185153a18eSAnirudh Venkataramanan 5195153a18eSAnirudh Venkataramanan /** 52037bb8390SAnirudh Venkataramanan * ice_vsi_alloc - Allocates the next available struct VSI in the PF 52137bb8390SAnirudh Venkataramanan * @pf: board private structure 52237bb8390SAnirudh Venkataramanan * @type: type of VSI 523f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 52437bb8390SAnirudh Venkataramanan * 52537bb8390SAnirudh Venkataramanan * returns a pointer to a VSI on success, NULL on failure. 52637bb8390SAnirudh Venkataramanan */ 5275743020dSAkeem G Abodunrin static struct ice_vsi * 5285743020dSAkeem G Abodunrin ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type, u16 vf_id) 52937bb8390SAnirudh Venkataramanan { 53037bb8390SAnirudh Venkataramanan struct ice_vsi *vsi = NULL; 53137bb8390SAnirudh Venkataramanan 53237bb8390SAnirudh Venkataramanan /* Need to protect the allocation of the VSIs at the PF level */ 53337bb8390SAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 53437bb8390SAnirudh Venkataramanan 53537bb8390SAnirudh Venkataramanan /* If we have already allocated our maximum number of VSIs, 53637bb8390SAnirudh Venkataramanan * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index 53737bb8390SAnirudh Venkataramanan * is available to be populated 53837bb8390SAnirudh Venkataramanan */ 53937bb8390SAnirudh Venkataramanan if (pf->next_vsi == ICE_NO_VSI) { 54037bb8390SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "out of VSI slots!\n"); 54137bb8390SAnirudh Venkataramanan goto unlock_pf; 54237bb8390SAnirudh Venkataramanan } 54337bb8390SAnirudh Venkataramanan 54437bb8390SAnirudh Venkataramanan vsi = devm_kzalloc(&pf->pdev->dev, sizeof(*vsi), GFP_KERNEL); 54537bb8390SAnirudh Venkataramanan if (!vsi) 54637bb8390SAnirudh Venkataramanan goto unlock_pf; 54737bb8390SAnirudh Venkataramanan 54837bb8390SAnirudh Venkataramanan vsi->type = type; 54937bb8390SAnirudh Venkataramanan vsi->back = pf; 55037bb8390SAnirudh Venkataramanan set_bit(__ICE_DOWN, vsi->state); 55137bb8390SAnirudh Venkataramanan vsi->idx = pf->next_vsi; 55237bb8390SAnirudh Venkataramanan vsi->work_lmt = ICE_DFLT_IRQ_WORK; 55337bb8390SAnirudh Venkataramanan 5545743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 5555743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf_id); 5565743020dSAkeem G Abodunrin else 5575743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 55837bb8390SAnirudh Venkataramanan 55937bb8390SAnirudh Venkataramanan switch (vsi->type) { 56037bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 561a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 56237bb8390SAnirudh Venkataramanan goto err_rings; 56337bb8390SAnirudh Venkataramanan 56437bb8390SAnirudh Venkataramanan /* Setup default MSIX irq handler for VSI */ 56537bb8390SAnirudh Venkataramanan vsi->irq_handler = ice_msix_clean_rings; 56637bb8390SAnirudh Venkataramanan break; 5678ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 568a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 5698ede0178SAnirudh Venkataramanan goto err_rings; 5708ede0178SAnirudh Venkataramanan break; 5710e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 5720e674aebSAnirudh Venkataramanan if (ice_vsi_alloc_arrays(vsi)) 5730e674aebSAnirudh Venkataramanan goto err_rings; 5740e674aebSAnirudh Venkataramanan break; 57537bb8390SAnirudh Venkataramanan default: 57637bb8390SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 57737bb8390SAnirudh Venkataramanan goto unlock_pf; 57837bb8390SAnirudh Venkataramanan } 57937bb8390SAnirudh Venkataramanan 58037bb8390SAnirudh Venkataramanan /* fill VSI slot in the PF struct */ 58137bb8390SAnirudh Venkataramanan pf->vsi[pf->next_vsi] = vsi; 58237bb8390SAnirudh Venkataramanan 58337bb8390SAnirudh Venkataramanan /* prepare pf->next_vsi for next use */ 58437bb8390SAnirudh Venkataramanan pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi, 58537bb8390SAnirudh Venkataramanan pf->next_vsi); 58637bb8390SAnirudh Venkataramanan goto unlock_pf; 58737bb8390SAnirudh Venkataramanan 58837bb8390SAnirudh Venkataramanan err_rings: 58937bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 59037bb8390SAnirudh Venkataramanan vsi = NULL; 59137bb8390SAnirudh Venkataramanan unlock_pf: 59237bb8390SAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 59337bb8390SAnirudh Venkataramanan return vsi; 59437bb8390SAnirudh Venkataramanan } 59537bb8390SAnirudh Venkataramanan 59637bb8390SAnirudh Venkataramanan /** 59703f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI 59803f7a986SAnirudh Venkataramanan * @qs_cfg: gathered variables needed for PF->VSI queues assignment 599df0f8479SAnirudh Venkataramanan * 60003f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 601df0f8479SAnirudh Venkataramanan */ 60203f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs_contig(struct ice_qs_cfg *qs_cfg) 603df0f8479SAnirudh Venkataramanan { 60403f7a986SAnirudh Venkataramanan int offset, i; 605df0f8479SAnirudh Venkataramanan 60603f7a986SAnirudh Venkataramanan mutex_lock(qs_cfg->qs_mutex); 60703f7a986SAnirudh Venkataramanan offset = bitmap_find_next_zero_area(qs_cfg->pf_map, qs_cfg->pf_map_size, 60803f7a986SAnirudh Venkataramanan 0, qs_cfg->q_count, 0); 60903f7a986SAnirudh Venkataramanan if (offset >= qs_cfg->pf_map_size) { 61003f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 61103f7a986SAnirudh Venkataramanan return -ENOMEM; 612df0f8479SAnirudh Venkataramanan } 613df0f8479SAnirudh Venkataramanan 61403f7a986SAnirudh Venkataramanan bitmap_set(qs_cfg->pf_map, offset, qs_cfg->q_count); 61503f7a986SAnirudh Venkataramanan for (i = 0; i < qs_cfg->q_count; i++) 61603f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = i + offset; 61703f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 618df0f8479SAnirudh Venkataramanan 61903f7a986SAnirudh Venkataramanan return 0; 620df0f8479SAnirudh Venkataramanan } 621df0f8479SAnirudh Venkataramanan 622df0f8479SAnirudh Venkataramanan /** 62303f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs_sc - Assign a scattered queues from PF to VSI 624819d8998SJesse Brandeburg * @qs_cfg: gathered variables needed for pf->vsi queues assignment 625df0f8479SAnirudh Venkataramanan * 62603f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 627df0f8479SAnirudh Venkataramanan */ 62803f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs_sc(struct ice_qs_cfg *qs_cfg) 629df0f8479SAnirudh Venkataramanan { 630df0f8479SAnirudh Venkataramanan int i, index = 0; 631df0f8479SAnirudh Venkataramanan 63203f7a986SAnirudh Venkataramanan mutex_lock(qs_cfg->qs_mutex); 63303f7a986SAnirudh Venkataramanan for (i = 0; i < qs_cfg->q_count; i++) { 63403f7a986SAnirudh Venkataramanan index = find_next_zero_bit(qs_cfg->pf_map, 63503f7a986SAnirudh Venkataramanan qs_cfg->pf_map_size, index); 63603f7a986SAnirudh Venkataramanan if (index >= qs_cfg->pf_map_size) 63703f7a986SAnirudh Venkataramanan goto err_scatter; 63803f7a986SAnirudh Venkataramanan set_bit(index, qs_cfg->pf_map); 63903f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = index; 64003f7a986SAnirudh Venkataramanan } 64103f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 642df0f8479SAnirudh Venkataramanan 643df0f8479SAnirudh Venkataramanan return 0; 64403f7a986SAnirudh Venkataramanan err_scatter: 645df0f8479SAnirudh Venkataramanan for (index = 0; index < i; index++) { 64603f7a986SAnirudh Venkataramanan clear_bit(qs_cfg->vsi_map[index], qs_cfg->pf_map); 64703f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[index + qs_cfg->vsi_map_offset] = 0; 648df0f8479SAnirudh Venkataramanan } 64903f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 650df0f8479SAnirudh Venkataramanan 651df0f8479SAnirudh Venkataramanan return -ENOMEM; 652df0f8479SAnirudh Venkataramanan } 653df0f8479SAnirudh Venkataramanan 654df0f8479SAnirudh Venkataramanan /** 65503f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs - helper function for assigning queues from PF to VSI 6566c2f997aSAnirudh Venkataramanan * @qs_cfg: gathered variables needed for pf->vsi queues assignment 65703f7a986SAnirudh Venkataramanan * 6586c2f997aSAnirudh Venkataramanan * This function first tries to find contiguous space. If it is not successful, 6596c2f997aSAnirudh Venkataramanan * it tries with the scatter approach. 66003f7a986SAnirudh Venkataramanan * 66103f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 66203f7a986SAnirudh Venkataramanan */ 66303f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs(struct ice_qs_cfg *qs_cfg) 66403f7a986SAnirudh Venkataramanan { 66503f7a986SAnirudh Venkataramanan int ret = 0; 66603f7a986SAnirudh Venkataramanan 66703f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs_contig(qs_cfg); 66803f7a986SAnirudh Venkataramanan if (ret) { 66903f7a986SAnirudh Venkataramanan /* contig failed, so try with scatter approach */ 67003f7a986SAnirudh Venkataramanan qs_cfg->mapping_mode = ICE_VSI_MAP_SCATTER; 67103f7a986SAnirudh Venkataramanan qs_cfg->q_count = min_t(u16, qs_cfg->q_count, 67203f7a986SAnirudh Venkataramanan qs_cfg->scatter_count); 67303f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs_sc(qs_cfg); 67403f7a986SAnirudh Venkataramanan } 67503f7a986SAnirudh Venkataramanan return ret; 67603f7a986SAnirudh Venkataramanan } 67703f7a986SAnirudh Venkataramanan 67803f7a986SAnirudh Venkataramanan /** 679df0f8479SAnirudh Venkataramanan * ice_vsi_get_qs - Assign queues from PF to VSI 680df0f8479SAnirudh Venkataramanan * @vsi: the VSI to assign queues to 681df0f8479SAnirudh Venkataramanan * 682df0f8479SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 683df0f8479SAnirudh Venkataramanan */ 68437bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi) 685df0f8479SAnirudh Venkataramanan { 68603f7a986SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 68703f7a986SAnirudh Venkataramanan struct ice_qs_cfg tx_qs_cfg = { 68803f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 68903f7a986SAnirudh Venkataramanan .pf_map = pf->avail_txqs, 69078b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_txqs, 69103f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_txq, 69203f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_TXQS, 69303f7a986SAnirudh Venkataramanan .vsi_map = vsi->txq_map, 69403f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 69503f7a986SAnirudh Venkataramanan .mapping_mode = vsi->tx_mapping_mode 69603f7a986SAnirudh Venkataramanan }; 69703f7a986SAnirudh Venkataramanan struct ice_qs_cfg rx_qs_cfg = { 69803f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 69903f7a986SAnirudh Venkataramanan .pf_map = pf->avail_rxqs, 70078b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_rxqs, 70103f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_rxq, 70203f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_RXQS, 70303f7a986SAnirudh Venkataramanan .vsi_map = vsi->rxq_map, 70403f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 70503f7a986SAnirudh Venkataramanan .mapping_mode = vsi->rx_mapping_mode 70603f7a986SAnirudh Venkataramanan }; 707df0f8479SAnirudh Venkataramanan int ret = 0; 708df0f8479SAnirudh Venkataramanan 709df0f8479SAnirudh Venkataramanan vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG; 710df0f8479SAnirudh Venkataramanan vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG; 711df0f8479SAnirudh Venkataramanan 71203f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&tx_qs_cfg); 71303f7a986SAnirudh Venkataramanan if (!ret) 71403f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&rx_qs_cfg); 715df0f8479SAnirudh Venkataramanan 716df0f8479SAnirudh Venkataramanan return ret; 717df0f8479SAnirudh Venkataramanan } 718df0f8479SAnirudh Venkataramanan 719df0f8479SAnirudh Venkataramanan /** 7205153a18eSAnirudh Venkataramanan * ice_vsi_put_qs - Release queues from VSI to PF 7215153a18eSAnirudh Venkataramanan * @vsi: the VSI that is going to release queues 7225153a18eSAnirudh Venkataramanan */ 7235153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi) 7245153a18eSAnirudh Venkataramanan { 7255153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 7265153a18eSAnirudh Venkataramanan int i; 7275153a18eSAnirudh Venkataramanan 7285153a18eSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 7295153a18eSAnirudh Venkataramanan 7305153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 7315153a18eSAnirudh Venkataramanan clear_bit(vsi->txq_map[i], pf->avail_txqs); 7325153a18eSAnirudh Venkataramanan vsi->txq_map[i] = ICE_INVAL_Q_INDEX; 7335153a18eSAnirudh Venkataramanan } 7345153a18eSAnirudh Venkataramanan 7355153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 7365153a18eSAnirudh Venkataramanan clear_bit(vsi->rxq_map[i], pf->avail_rxqs); 7375153a18eSAnirudh Venkataramanan vsi->rxq_map[i] = ICE_INVAL_Q_INDEX; 7385153a18eSAnirudh Venkataramanan } 7395153a18eSAnirudh Venkataramanan 7405153a18eSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 7415153a18eSAnirudh Venkataramanan } 7425153a18eSAnirudh Venkataramanan 7435153a18eSAnirudh Venkataramanan /** 744df0f8479SAnirudh Venkataramanan * ice_rss_clean - Delete RSS related VSI structures that hold user inputs 745df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 746df0f8479SAnirudh Venkataramanan */ 747df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi) 748df0f8479SAnirudh Venkataramanan { 749df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 750df0f8479SAnirudh Venkataramanan 751df0f8479SAnirudh Venkataramanan pf = vsi->back; 752df0f8479SAnirudh Venkataramanan 753df0f8479SAnirudh Venkataramanan if (vsi->rss_hkey_user) 754df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_hkey_user); 755df0f8479SAnirudh Venkataramanan if (vsi->rss_lut_user) 756df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_lut_user); 757df0f8479SAnirudh Venkataramanan } 758df0f8479SAnirudh Venkataramanan 759df0f8479SAnirudh Venkataramanan /** 76028c2a645SAnirudh Venkataramanan * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type 76128c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 76228c2a645SAnirudh Venkataramanan */ 76337bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi) 76428c2a645SAnirudh Venkataramanan { 76528c2a645SAnirudh Venkataramanan struct ice_hw_common_caps *cap; 76628c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 76728c2a645SAnirudh Venkataramanan 76828c2a645SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 76928c2a645SAnirudh Venkataramanan vsi->rss_size = 1; 77028c2a645SAnirudh Venkataramanan return; 77128c2a645SAnirudh Venkataramanan } 77228c2a645SAnirudh Venkataramanan 77328c2a645SAnirudh Venkataramanan cap = &pf->hw.func_caps.common_cap; 77428c2a645SAnirudh Venkataramanan switch (vsi->type) { 77528c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 77628c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 77728c2a645SAnirudh Venkataramanan vsi->rss_table_size = cap->rss_table_size; 77828c2a645SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 77928c2a645SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 78028c2a645SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; 78128c2a645SAnirudh Venkataramanan break; 7828ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 7838ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table 7848ede0178SAnirudh Venkataramanan * For VSI_LUT, LUT size should be set to 64 bytes 7858ede0178SAnirudh Venkataramanan */ 7868ede0178SAnirudh Venkataramanan vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 7878ede0178SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 7888ede0178SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 7898ede0178SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 7908ede0178SAnirudh Venkataramanan break; 7910e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 7920e674aebSAnirudh Venkataramanan break; 79328c2a645SAnirudh Venkataramanan default: 79428c2a645SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", 79528c2a645SAnirudh Venkataramanan vsi->type); 79628c2a645SAnirudh Venkataramanan break; 79728c2a645SAnirudh Venkataramanan } 79828c2a645SAnirudh Venkataramanan } 79928c2a645SAnirudh Venkataramanan 80028c2a645SAnirudh Venkataramanan /** 80128c2a645SAnirudh Venkataramanan * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI 80228c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 80328c2a645SAnirudh Venkataramanan * 80428c2a645SAnirudh Venkataramanan * This initializes a default VSI context for all sections except the Queues. 80528c2a645SAnirudh Venkataramanan */ 80628c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) 80728c2a645SAnirudh Venkataramanan { 80828c2a645SAnirudh Venkataramanan u32 table = 0; 80928c2a645SAnirudh Venkataramanan 81028c2a645SAnirudh Venkataramanan memset(&ctxt->info, 0, sizeof(ctxt->info)); 81128c2a645SAnirudh Venkataramanan /* VSI's should be allocated from shared pool */ 81228c2a645SAnirudh Venkataramanan ctxt->alloc_from_pool = true; 81328c2a645SAnirudh Venkataramanan /* Src pruning enabled by default */ 81428c2a645SAnirudh Venkataramanan ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; 81528c2a645SAnirudh Venkataramanan /* Traffic from VSI can be sent to LAN */ 81628c2a645SAnirudh Venkataramanan ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; 81728c2a645SAnirudh Venkataramanan /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy 81828c2a645SAnirudh Venkataramanan * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all 81928c2a645SAnirudh Venkataramanan * packets untagged/tagged. 82028c2a645SAnirudh Venkataramanan */ 82128c2a645SAnirudh Venkataramanan ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & 82228c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_M) >> 82328c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_S); 82428c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for both ingress/egress tables */ 82528c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(0, 0); 82628c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(1, 1); 82728c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(2, 2); 82828c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(3, 3); 82928c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(4, 4); 83028c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(5, 5); 83128c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(6, 6); 83228c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(7, 7); 83328c2a645SAnirudh Venkataramanan ctxt->info.ingress_table = cpu_to_le32(table); 83428c2a645SAnirudh Venkataramanan ctxt->info.egress_table = cpu_to_le32(table); 83528c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for outer to inner UP table */ 83628c2a645SAnirudh Venkataramanan ctxt->info.outer_up_table = cpu_to_le32(table); 83728c2a645SAnirudh Venkataramanan /* No Outer tag support outer_tag_flags remains to zero */ 83828c2a645SAnirudh Venkataramanan } 83928c2a645SAnirudh Venkataramanan 84028c2a645SAnirudh Venkataramanan /** 84128c2a645SAnirudh Venkataramanan * ice_vsi_setup_q_map - Setup a VSI queue map 84228c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 84328c2a645SAnirudh Venkataramanan * @ctxt: VSI context structure 84428c2a645SAnirudh Venkataramanan */ 84528c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 84628c2a645SAnirudh Venkataramanan { 847c5a2a4a3SUsha Ketineni u16 offset = 0, qmap = 0, tx_count = 0; 84828c2a645SAnirudh Venkataramanan u16 qcount_tx = vsi->alloc_txq; 84928c2a645SAnirudh Venkataramanan u16 qcount_rx = vsi->alloc_rxq; 850c5a2a4a3SUsha Ketineni u16 tx_numq_tc, rx_numq_tc; 851c5a2a4a3SUsha Ketineni u16 pow = 0, max_rss = 0; 85228c2a645SAnirudh Venkataramanan bool ena_tc0 = false; 853c5a2a4a3SUsha Ketineni u8 netdev_tc = 0; 85428c2a645SAnirudh Venkataramanan int i; 85528c2a645SAnirudh Venkataramanan 85628c2a645SAnirudh Venkataramanan /* at least TC0 should be enabled by default */ 85728c2a645SAnirudh Venkataramanan if (vsi->tc_cfg.numtc) { 85828c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(0))) 85928c2a645SAnirudh Venkataramanan ena_tc0 = true; 86028c2a645SAnirudh Venkataramanan } else { 86128c2a645SAnirudh Venkataramanan ena_tc0 = true; 86228c2a645SAnirudh Venkataramanan } 86328c2a645SAnirudh Venkataramanan 86428c2a645SAnirudh Venkataramanan if (ena_tc0) { 86528c2a645SAnirudh Venkataramanan vsi->tc_cfg.numtc++; 86628c2a645SAnirudh Venkataramanan vsi->tc_cfg.ena_tc |= 1; 86728c2a645SAnirudh Venkataramanan } 86828c2a645SAnirudh Venkataramanan 869c5a2a4a3SUsha Ketineni rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc; 870c5a2a4a3SUsha Ketineni if (!rx_numq_tc) 871c5a2a4a3SUsha Ketineni rx_numq_tc = 1; 872c5a2a4a3SUsha Ketineni tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc; 873c5a2a4a3SUsha Ketineni if (!tx_numq_tc) 874c5a2a4a3SUsha Ketineni tx_numq_tc = 1; 87528c2a645SAnirudh Venkataramanan 87628c2a645SAnirudh Venkataramanan /* TC mapping is a function of the number of Rx queues assigned to the 87728c2a645SAnirudh Venkataramanan * VSI for each traffic class and the offset of these queues. 87828c2a645SAnirudh Venkataramanan * The first 10 bits are for queue offset for TC0, next 4 bits for no:of 87928c2a645SAnirudh Venkataramanan * queues allocated to TC0. No:of queues is a power-of-2. 88028c2a645SAnirudh Venkataramanan * 88128c2a645SAnirudh Venkataramanan * If TC is not enabled, the queue offset is set to 0, and allocate one 88228c2a645SAnirudh Venkataramanan * queue, this way, traffic for the given TC will be sent to the default 88328c2a645SAnirudh Venkataramanan * queue. 88428c2a645SAnirudh Venkataramanan * 88528c2a645SAnirudh Venkataramanan * Setup number and offset of Rx queues for all TCs for the VSI 88628c2a645SAnirudh Venkataramanan */ 88728c2a645SAnirudh Venkataramanan 888c5a2a4a3SUsha Ketineni qcount_rx = rx_numq_tc; 889c5a2a4a3SUsha Ketineni 89028c2a645SAnirudh Venkataramanan /* qcount will change if RSS is enabled */ 89128c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) { 8928ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) { 89328c2a645SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) 89428c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_LG_RSS_QS; 89528c2a645SAnirudh Venkataramanan else 89628c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_SMALL_RSS_QS; 897c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, rx_numq_tc, max_rss); 898c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, qcount_rx, vsi->rss_size); 8998ede0178SAnirudh Venkataramanan } 90028c2a645SAnirudh Venkataramanan } 90128c2a645SAnirudh Venkataramanan 90228c2a645SAnirudh Venkataramanan /* find the (rounded up) power-of-2 of qcount */ 903c5a2a4a3SUsha Ketineni pow = order_base_2(qcount_rx); 90428c2a645SAnirudh Venkataramanan 9052bdc97beSBruce Allan ice_for_each_traffic_class(i) { 90628c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 90728c2a645SAnirudh Venkataramanan /* TC is not enabled */ 90828c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = 0; 909c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = 1; 910c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = 1; 911c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = 0; 91228c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = 0; 91328c2a645SAnirudh Venkataramanan continue; 91428c2a645SAnirudh Venkataramanan } 91528c2a645SAnirudh Venkataramanan 91628c2a645SAnirudh Venkataramanan /* TC is enabled */ 91728c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = offset; 918c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx; 919c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc; 920c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 92128c2a645SAnirudh Venkataramanan 92228c2a645SAnirudh Venkataramanan qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 92328c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_OFFSET_M) | 92428c2a645SAnirudh Venkataramanan ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 92528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_NUM_M); 926c5a2a4a3SUsha Ketineni offset += qcount_rx; 927c5a2a4a3SUsha Ketineni tx_count += tx_numq_tc; 92828c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); 92928c2a645SAnirudh Venkataramanan } 93060dcc39eSKiran Patil 93160dcc39eSKiran Patil /* if offset is non-zero, means it is calculated correctly based on 93260dcc39eSKiran Patil * enabled TCs for a given VSI otherwise qcount_rx will always 93360dcc39eSKiran Patil * be correct and non-zero because it is based off - VSI's 93460dcc39eSKiran Patil * allocated Rx queues which is at least 1 (hence qcount_tx will be 93560dcc39eSKiran Patil * at least 1) 93660dcc39eSKiran Patil */ 93760dcc39eSKiran Patil if (offset) 93828c2a645SAnirudh Venkataramanan vsi->num_rxq = offset; 93960dcc39eSKiran Patil else 94060dcc39eSKiran Patil vsi->num_rxq = qcount_rx; 94160dcc39eSKiran Patil 942c5a2a4a3SUsha Ketineni vsi->num_txq = tx_count; 94328c2a645SAnirudh Venkataramanan 9448ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) { 9458ede0178SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n"); 9468ede0178SAnirudh Venkataramanan /* since there is a chance that num_rxq could have been changed 9478ede0178SAnirudh Venkataramanan * in the above for loop, make num_txq equal to num_rxq. 9488ede0178SAnirudh Venkataramanan */ 9498ede0178SAnirudh Venkataramanan vsi->num_txq = vsi->num_rxq; 9508ede0178SAnirudh Venkataramanan } 9518ede0178SAnirudh Venkataramanan 95228c2a645SAnirudh Venkataramanan /* Rx queue mapping */ 95328c2a645SAnirudh Venkataramanan ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 95428c2a645SAnirudh Venkataramanan /* q_mapping buffer holds the info for the first queue allocated for 95528c2a645SAnirudh Venkataramanan * this VSI in the PF space and also the number of queues associated 95628c2a645SAnirudh Venkataramanan * with this VSI. 95728c2a645SAnirudh Venkataramanan */ 95828c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 95928c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq); 96028c2a645SAnirudh Venkataramanan } 96128c2a645SAnirudh Venkataramanan 96228c2a645SAnirudh Venkataramanan /** 96328c2a645SAnirudh Venkataramanan * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI 96428c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 96528c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 96628c2a645SAnirudh Venkataramanan */ 96728c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 96828c2a645SAnirudh Venkataramanan { 96928c2a645SAnirudh Venkataramanan u8 lut_type, hash_type; 970819d8998SJesse Brandeburg struct ice_pf *pf; 971819d8998SJesse Brandeburg 972819d8998SJesse Brandeburg pf = vsi->back; 97328c2a645SAnirudh Venkataramanan 97428c2a645SAnirudh Venkataramanan switch (vsi->type) { 97528c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 97628c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 97728c2a645SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; 97828c2a645SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 97928c2a645SAnirudh Venkataramanan break; 9808ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 9818ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table which is a VSI LUT type */ 9828ede0178SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 9838ede0178SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 9848ede0178SAnirudh Venkataramanan break; 9850e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 9860e674aebSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "Unsupported VSI type %d\n", vsi->type); 9870e674aebSAnirudh Venkataramanan return; 98828c2a645SAnirudh Venkataramanan default: 989819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 99028c2a645SAnirudh Venkataramanan return; 99128c2a645SAnirudh Venkataramanan } 99228c2a645SAnirudh Venkataramanan 99328c2a645SAnirudh Venkataramanan ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & 99428c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | 99528c2a645SAnirudh Venkataramanan ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & 99628c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_HASH_M); 99728c2a645SAnirudh Venkataramanan } 99828c2a645SAnirudh Venkataramanan 99928c2a645SAnirudh Venkataramanan /** 100028c2a645SAnirudh Venkataramanan * ice_vsi_init - Create and initialize a VSI 100128c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 100228c2a645SAnirudh Venkataramanan * 100328c2a645SAnirudh Venkataramanan * This initializes a VSI context depending on the VSI type to be added and 100428c2a645SAnirudh Venkataramanan * passes it down to the add_vsi aq command to create a new VSI. 100528c2a645SAnirudh Venkataramanan */ 100637bb8390SAnirudh Venkataramanan static int ice_vsi_init(struct ice_vsi *vsi) 100728c2a645SAnirudh Venkataramanan { 100828c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 100928c2a645SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1010198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 101128c2a645SAnirudh Venkataramanan int ret = 0; 101228c2a645SAnirudh Venkataramanan 1013198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 1014198a666aSBruce Allan if (!ctxt) 1015198a666aSBruce Allan return -ENOMEM; 1016198a666aSBruce Allan 1017cb93a952SAkeem G Abodunrin ctxt->info = vsi->info; 101828c2a645SAnirudh Venkataramanan switch (vsi->type) { 10190e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 10200e674aebSAnirudh Venkataramanan /* fall through */ 102128c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 1022198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_PF; 102328c2a645SAnirudh Venkataramanan break; 10248ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 1025198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_VF; 10268ede0178SAnirudh Venkataramanan /* VF number here is the absolute VF number (0-255) */ 1027198a666aSBruce Allan ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; 10288ede0178SAnirudh Venkataramanan break; 102928c2a645SAnirudh Venkataramanan default: 103028c2a645SAnirudh Venkataramanan return -ENODEV; 103128c2a645SAnirudh Venkataramanan } 103228c2a645SAnirudh Venkataramanan 1033198a666aSBruce Allan ice_set_dflt_vsi_ctx(ctxt); 103428c2a645SAnirudh Venkataramanan /* if the switch is in VEB mode, allow VSI loopback */ 103528c2a645SAnirudh Venkataramanan if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) 1036198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 103728c2a645SAnirudh Venkataramanan 103828c2a645SAnirudh Venkataramanan /* Set LUT type and HASH type if RSS is enabled */ 103928c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 1040198a666aSBruce Allan ice_set_rss_vsi_ctx(ctxt, vsi); 104128c2a645SAnirudh Venkataramanan 1042198a666aSBruce Allan ctxt->info.sw_id = vsi->port_info->sw_id; 1043198a666aSBruce Allan ice_vsi_setup_q_map(vsi, ctxt); 104428c2a645SAnirudh Venkataramanan 1045cb93a952SAkeem G Abodunrin /* Enable MAC Antispoof with new VSI being initialized or updated */ 1046cb93a952SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF && pf->vf[vsi->vf_id].spoofchk) { 1047cb93a952SAkeem G Abodunrin ctxt->info.valid_sections |= 1048cb93a952SAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 1049cb93a952SAkeem G Abodunrin ctxt->info.sec_flags |= 1050cb93a952SAkeem G Abodunrin ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; 1051cb93a952SAkeem G Abodunrin } 1052cb93a952SAkeem G Abodunrin 10530c3a6101SDave Ertman /* Allow control frames out of main VSI */ 10540c3a6101SDave Ertman if (vsi->type == ICE_VSI_PF) { 10550c3a6101SDave Ertman ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; 10560c3a6101SDave Ertman ctxt->info.valid_sections |= 10570c3a6101SDave Ertman cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 10580c3a6101SDave Ertman } 10590c3a6101SDave Ertman 1060198a666aSBruce Allan ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); 106128c2a645SAnirudh Venkataramanan if (ret) { 106228c2a645SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 106328c2a645SAnirudh Venkataramanan "Add VSI failed, err %d\n", ret); 106428c2a645SAnirudh Venkataramanan return -EIO; 106528c2a645SAnirudh Venkataramanan } 106628c2a645SAnirudh Venkataramanan 106728c2a645SAnirudh Venkataramanan /* keep context for update VSI operations */ 1068198a666aSBruce Allan vsi->info = ctxt->info; 106928c2a645SAnirudh Venkataramanan 107028c2a645SAnirudh Venkataramanan /* record VSI number returned */ 1071198a666aSBruce Allan vsi->vsi_num = ctxt->vsi_num; 107228c2a645SAnirudh Venkataramanan 1073198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 107428c2a645SAnirudh Venkataramanan return ret; 107528c2a645SAnirudh Venkataramanan } 107628c2a645SAnirudh Venkataramanan 107728c2a645SAnirudh Venkataramanan /** 1078df0f8479SAnirudh Venkataramanan * ice_free_q_vector - Free memory allocated for a specific interrupt vector 1079df0f8479SAnirudh Venkataramanan * @vsi: VSI having the memory freed 1080df0f8479SAnirudh Venkataramanan * @v_idx: index of the vector to be freed 1081df0f8479SAnirudh Venkataramanan */ 1082df0f8479SAnirudh Venkataramanan static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx) 1083df0f8479SAnirudh Venkataramanan { 1084df0f8479SAnirudh Venkataramanan struct ice_q_vector *q_vector; 1085819d8998SJesse Brandeburg struct ice_pf *pf = vsi->back; 1086df0f8479SAnirudh Venkataramanan struct ice_ring *ring; 1087df0f8479SAnirudh Venkataramanan 1088df0f8479SAnirudh Venkataramanan if (!vsi->q_vectors[v_idx]) { 1089819d8998SJesse Brandeburg dev_dbg(&pf->pdev->dev, "Queue vector at index %d not found\n", 1090df0f8479SAnirudh Venkataramanan v_idx); 1091df0f8479SAnirudh Venkataramanan return; 1092df0f8479SAnirudh Venkataramanan } 1093df0f8479SAnirudh Venkataramanan q_vector = vsi->q_vectors[v_idx]; 1094df0f8479SAnirudh Venkataramanan 1095df0f8479SAnirudh Venkataramanan ice_for_each_ring(ring, q_vector->tx) 1096df0f8479SAnirudh Venkataramanan ring->q_vector = NULL; 1097df0f8479SAnirudh Venkataramanan ice_for_each_ring(ring, q_vector->rx) 1098df0f8479SAnirudh Venkataramanan ring->q_vector = NULL; 1099df0f8479SAnirudh Venkataramanan 1100df0f8479SAnirudh Venkataramanan /* only VSI with an associated netdev is set up with NAPI */ 1101df0f8479SAnirudh Venkataramanan if (vsi->netdev) 1102df0f8479SAnirudh Venkataramanan netif_napi_del(&q_vector->napi); 1103df0f8479SAnirudh Venkataramanan 1104819d8998SJesse Brandeburg devm_kfree(&pf->pdev->dev, q_vector); 1105df0f8479SAnirudh Venkataramanan vsi->q_vectors[v_idx] = NULL; 1106df0f8479SAnirudh Venkataramanan } 1107df0f8479SAnirudh Venkataramanan 1108df0f8479SAnirudh Venkataramanan /** 1109df0f8479SAnirudh Venkataramanan * ice_vsi_free_q_vectors - Free memory allocated for interrupt vectors 1110df0f8479SAnirudh Venkataramanan * @vsi: the VSI having memory freed 1111df0f8479SAnirudh Venkataramanan */ 1112df0f8479SAnirudh Venkataramanan void ice_vsi_free_q_vectors(struct ice_vsi *vsi) 1113df0f8479SAnirudh Venkataramanan { 1114df0f8479SAnirudh Venkataramanan int v_idx; 1115df0f8479SAnirudh Venkataramanan 11160c2561c8SBrett Creeley ice_for_each_q_vector(vsi, v_idx) 1117df0f8479SAnirudh Venkataramanan ice_free_q_vector(vsi, v_idx); 1118df0f8479SAnirudh Venkataramanan } 1119df0f8479SAnirudh Venkataramanan 1120df0f8479SAnirudh Venkataramanan /** 1121df0f8479SAnirudh Venkataramanan * ice_vsi_alloc_q_vector - Allocate memory for a single interrupt vector 1122df0f8479SAnirudh Venkataramanan * @vsi: the VSI being configured 1123df0f8479SAnirudh Venkataramanan * @v_idx: index of the vector in the VSI struct 1124df0f8479SAnirudh Venkataramanan * 1125df0f8479SAnirudh Venkataramanan * We allocate one q_vector. If allocation fails we return -ENOMEM. 1126df0f8479SAnirudh Venkataramanan */ 1127df0f8479SAnirudh Venkataramanan static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, int v_idx) 1128df0f8479SAnirudh Venkataramanan { 1129df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1130df0f8479SAnirudh Venkataramanan struct ice_q_vector *q_vector; 1131df0f8479SAnirudh Venkataramanan 1132df0f8479SAnirudh Venkataramanan /* allocate q_vector */ 1133df0f8479SAnirudh Venkataramanan q_vector = devm_kzalloc(&pf->pdev->dev, sizeof(*q_vector), GFP_KERNEL); 1134df0f8479SAnirudh Venkataramanan if (!q_vector) 1135df0f8479SAnirudh Venkataramanan return -ENOMEM; 1136df0f8479SAnirudh Venkataramanan 1137df0f8479SAnirudh Venkataramanan q_vector->vsi = vsi; 1138df0f8479SAnirudh Venkataramanan q_vector->v_idx = v_idx; 11398ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 11408ede0178SAnirudh Venkataramanan goto out; 1141df0f8479SAnirudh Venkataramanan /* only set affinity_mask if the CPU is online */ 1142df0f8479SAnirudh Venkataramanan if (cpu_online(v_idx)) 1143df0f8479SAnirudh Venkataramanan cpumask_set_cpu(v_idx, &q_vector->affinity_mask); 1144df0f8479SAnirudh Venkataramanan 1145df0f8479SAnirudh Venkataramanan /* This will not be called in the driver load path because the netdev 1146df0f8479SAnirudh Venkataramanan * will not be created yet. All other cases with register the NAPI 1147df0f8479SAnirudh Venkataramanan * handler here (i.e. resume, reset/rebuild, etc.) 1148df0f8479SAnirudh Venkataramanan */ 1149df0f8479SAnirudh Venkataramanan if (vsi->netdev) 1150df0f8479SAnirudh Venkataramanan netif_napi_add(vsi->netdev, &q_vector->napi, ice_napi_poll, 1151df0f8479SAnirudh Venkataramanan NAPI_POLL_WEIGHT); 1152df0f8479SAnirudh Venkataramanan 11538ede0178SAnirudh Venkataramanan out: 1154df0f8479SAnirudh Venkataramanan /* tie q_vector and VSI together */ 1155df0f8479SAnirudh Venkataramanan vsi->q_vectors[v_idx] = q_vector; 1156df0f8479SAnirudh Venkataramanan 1157df0f8479SAnirudh Venkataramanan return 0; 1158df0f8479SAnirudh Venkataramanan } 1159df0f8479SAnirudh Venkataramanan 1160df0f8479SAnirudh Venkataramanan /** 1161df0f8479SAnirudh Venkataramanan * ice_vsi_alloc_q_vectors - Allocate memory for interrupt vectors 1162df0f8479SAnirudh Venkataramanan * @vsi: the VSI being configured 1163df0f8479SAnirudh Venkataramanan * 1164df0f8479SAnirudh Venkataramanan * We allocate one q_vector per queue interrupt. If allocation fails we 1165df0f8479SAnirudh Venkataramanan * return -ENOMEM. 1166df0f8479SAnirudh Venkataramanan */ 116737bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_q_vectors(struct ice_vsi *vsi) 1168df0f8479SAnirudh Venkataramanan { 1169df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1170df0f8479SAnirudh Venkataramanan int v_idx = 0, num_q_vectors; 1171df0f8479SAnirudh Venkataramanan int err; 1172df0f8479SAnirudh Venkataramanan 1173df0f8479SAnirudh Venkataramanan if (vsi->q_vectors[0]) { 1174df0f8479SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "VSI %d has existing q_vectors\n", 1175df0f8479SAnirudh Venkataramanan vsi->vsi_num); 1176df0f8479SAnirudh Venkataramanan return -EEXIST; 1177df0f8479SAnirudh Venkataramanan } 1178df0f8479SAnirudh Venkataramanan 1179df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1180df0f8479SAnirudh Venkataramanan 1181df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < num_q_vectors; v_idx++) { 1182df0f8479SAnirudh Venkataramanan err = ice_vsi_alloc_q_vector(vsi, v_idx); 1183df0f8479SAnirudh Venkataramanan if (err) 1184df0f8479SAnirudh Venkataramanan goto err_out; 1185df0f8479SAnirudh Venkataramanan } 1186df0f8479SAnirudh Venkataramanan 1187df0f8479SAnirudh Venkataramanan return 0; 1188df0f8479SAnirudh Venkataramanan 1189df0f8479SAnirudh Venkataramanan err_out: 1190df0f8479SAnirudh Venkataramanan while (v_idx--) 1191df0f8479SAnirudh Venkataramanan ice_free_q_vector(vsi, v_idx); 1192df0f8479SAnirudh Venkataramanan 1193df0f8479SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1194df0f8479SAnirudh Venkataramanan "Failed to allocate %d q_vector for VSI %d, ret=%d\n", 1195df0f8479SAnirudh Venkataramanan vsi->num_q_vectors, vsi->vsi_num, err); 1196df0f8479SAnirudh Venkataramanan vsi->num_q_vectors = 0; 1197df0f8479SAnirudh Venkataramanan return err; 1198df0f8479SAnirudh Venkataramanan } 1199df0f8479SAnirudh Venkataramanan 1200df0f8479SAnirudh Venkataramanan /** 1201df0f8479SAnirudh Venkataramanan * ice_vsi_setup_vector_base - Set up the base vector for the given VSI 1202df0f8479SAnirudh Venkataramanan * @vsi: ptr to the VSI 1203df0f8479SAnirudh Venkataramanan * 1204df0f8479SAnirudh Venkataramanan * This should only be called after ice_vsi_alloc() which allocates the 1205df0f8479SAnirudh Venkataramanan * corresponding SW VSI structure and initializes num_queue_pairs for the 1206df0f8479SAnirudh Venkataramanan * newly allocated VSI. 1207df0f8479SAnirudh Venkataramanan * 1208df0f8479SAnirudh Venkataramanan * Returns 0 on success or negative on failure 1209df0f8479SAnirudh Venkataramanan */ 121037bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) 1211df0f8479SAnirudh Venkataramanan { 1212df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1213cbe66bfeSBrett Creeley u16 num_q_vectors; 1214df0f8479SAnirudh Venkataramanan 1215cbe66bfeSBrett Creeley /* SRIOV doesn't grab irq_tracker entries for each VSI */ 1216cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) 1217cbe66bfeSBrett Creeley return 0; 1218cbe66bfeSBrett Creeley 1219cbe66bfeSBrett Creeley if (vsi->base_vector) { 1220cbe66bfeSBrett Creeley dev_dbg(&pf->pdev->dev, "VSI %d has non-zero base vector %d\n", 1221cbe66bfeSBrett Creeley vsi->vsi_num, vsi->base_vector); 1222df0f8479SAnirudh Venkataramanan return -EEXIST; 1223df0f8479SAnirudh Venkataramanan } 1224df0f8479SAnirudh Venkataramanan 1225df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1226eb0208ecSPreethi Banala /* reserve slots from OS requested IRQs */ 1227cbe66bfeSBrett Creeley vsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors, 1228cbe66bfeSBrett Creeley vsi->idx); 1229cbe66bfeSBrett Creeley if (vsi->base_vector < 0) { 1230eb0208ecSPreethi Banala dev_err(&pf->pdev->dev, 1231cbe66bfeSBrett Creeley "Failed to get tracking for %d vectors for VSI %d, err=%d\n", 1232cbe66bfeSBrett Creeley num_q_vectors, vsi->vsi_num, vsi->base_vector); 1233eb0208ecSPreethi Banala return -ENOENT; 1234eb0208ecSPreethi Banala } 1235eb0208ecSPreethi Banala pf->num_avail_sw_msix -= num_q_vectors; 1236eb0208ecSPreethi Banala 1237df0f8479SAnirudh Venkataramanan return 0; 1238df0f8479SAnirudh Venkataramanan } 1239df0f8479SAnirudh Venkataramanan 1240df0f8479SAnirudh Venkataramanan /** 124128c2a645SAnirudh Venkataramanan * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI 124228c2a645SAnirudh Venkataramanan * @vsi: the VSI having rings deallocated 124328c2a645SAnirudh Venkataramanan */ 1244df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi) 124528c2a645SAnirudh Venkataramanan { 124628c2a645SAnirudh Venkataramanan int i; 124728c2a645SAnirudh Venkataramanan 124828c2a645SAnirudh Venkataramanan if (vsi->tx_rings) { 124928c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 125028c2a645SAnirudh Venkataramanan if (vsi->tx_rings[i]) { 125128c2a645SAnirudh Venkataramanan kfree_rcu(vsi->tx_rings[i], rcu); 125228c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = NULL; 125328c2a645SAnirudh Venkataramanan } 125428c2a645SAnirudh Venkataramanan } 125528c2a645SAnirudh Venkataramanan } 125628c2a645SAnirudh Venkataramanan if (vsi->rx_rings) { 125728c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 125828c2a645SAnirudh Venkataramanan if (vsi->rx_rings[i]) { 125928c2a645SAnirudh Venkataramanan kfree_rcu(vsi->rx_rings[i], rcu); 126028c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = NULL; 126128c2a645SAnirudh Venkataramanan } 126228c2a645SAnirudh Venkataramanan } 126328c2a645SAnirudh Venkataramanan } 126428c2a645SAnirudh Venkataramanan } 126528c2a645SAnirudh Venkataramanan 126628c2a645SAnirudh Venkataramanan /** 126728c2a645SAnirudh Venkataramanan * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI 126828c2a645SAnirudh Venkataramanan * @vsi: VSI which is having rings allocated 126928c2a645SAnirudh Venkataramanan */ 127037bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi) 127128c2a645SAnirudh Venkataramanan { 127228c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 127328c2a645SAnirudh Venkataramanan int i; 127428c2a645SAnirudh Venkataramanan 1275d337f2afSAnirudh Venkataramanan /* Allocate Tx rings */ 127628c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 127728c2a645SAnirudh Venkataramanan struct ice_ring *ring; 127828c2a645SAnirudh Venkataramanan 127928c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 128028c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 128128c2a645SAnirudh Venkataramanan 128228c2a645SAnirudh Venkataramanan if (!ring) 128328c2a645SAnirudh Venkataramanan goto err_out; 128428c2a645SAnirudh Venkataramanan 128528c2a645SAnirudh Venkataramanan ring->q_index = i; 128628c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->txq_map[i]; 128728c2a645SAnirudh Venkataramanan ring->ring_active = false; 128828c2a645SAnirudh Venkataramanan ring->vsi = vsi; 128928c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 1290ad71b256SBrett Creeley ring->count = vsi->num_tx_desc; 129128c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = ring; 129228c2a645SAnirudh Venkataramanan } 129328c2a645SAnirudh Venkataramanan 1294d337f2afSAnirudh Venkataramanan /* Allocate Rx rings */ 129528c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 129628c2a645SAnirudh Venkataramanan struct ice_ring *ring; 129728c2a645SAnirudh Venkataramanan 129828c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 129928c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 130028c2a645SAnirudh Venkataramanan if (!ring) 130128c2a645SAnirudh Venkataramanan goto err_out; 130228c2a645SAnirudh Venkataramanan 130328c2a645SAnirudh Venkataramanan ring->q_index = i; 130428c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->rxq_map[i]; 130528c2a645SAnirudh Venkataramanan ring->ring_active = false; 130628c2a645SAnirudh Venkataramanan ring->vsi = vsi; 130728c2a645SAnirudh Venkataramanan ring->netdev = vsi->netdev; 130828c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 1309ad71b256SBrett Creeley ring->count = vsi->num_rx_desc; 131028c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = ring; 131128c2a645SAnirudh Venkataramanan } 131228c2a645SAnirudh Venkataramanan 131328c2a645SAnirudh Venkataramanan return 0; 131428c2a645SAnirudh Venkataramanan 131528c2a645SAnirudh Venkataramanan err_out: 131628c2a645SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 131728c2a645SAnirudh Venkataramanan return -ENOMEM; 131828c2a645SAnirudh Venkataramanan } 131928c2a645SAnirudh Venkataramanan 132028c2a645SAnirudh Venkataramanan /** 132107309a0eSAnirudh Venkataramanan * ice_vsi_map_rings_to_vectors - Map VSI rings to interrupt vectors 132207309a0eSAnirudh Venkataramanan * @vsi: the VSI being configured 132307309a0eSAnirudh Venkataramanan * 132407309a0eSAnirudh Venkataramanan * This function maps descriptor rings to the queue-specific vectors allotted 132507309a0eSAnirudh Venkataramanan * through the MSI-X enabling code. On a constrained vector budget, we map Tx 132607309a0eSAnirudh Venkataramanan * and Rx rings to the vector as "efficiently" as possible. 132707309a0eSAnirudh Venkataramanan */ 13287b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 13297b9ffc76SAnirudh Venkataramanan void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi) 13307b9ffc76SAnirudh Venkataramanan #else 133137bb8390SAnirudh Venkataramanan static void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi) 13327b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 133307309a0eSAnirudh Venkataramanan { 133407309a0eSAnirudh Venkataramanan int q_vectors = vsi->num_q_vectors; 133507309a0eSAnirudh Venkataramanan int tx_rings_rem, rx_rings_rem; 133607309a0eSAnirudh Venkataramanan int v_id; 133707309a0eSAnirudh Venkataramanan 133807309a0eSAnirudh Venkataramanan /* initially assigning remaining rings count to VSIs num queue value */ 133907309a0eSAnirudh Venkataramanan tx_rings_rem = vsi->num_txq; 134007309a0eSAnirudh Venkataramanan rx_rings_rem = vsi->num_rxq; 134107309a0eSAnirudh Venkataramanan 134207309a0eSAnirudh Venkataramanan for (v_id = 0; v_id < q_vectors; v_id++) { 134307309a0eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[v_id]; 134407309a0eSAnirudh Venkataramanan int tx_rings_per_v, rx_rings_per_v, q_id, q_base; 134507309a0eSAnirudh Venkataramanan 134607309a0eSAnirudh Venkataramanan /* Tx rings mapping to vector */ 134707309a0eSAnirudh Venkataramanan tx_rings_per_v = DIV_ROUND_UP(tx_rings_rem, q_vectors - v_id); 134807309a0eSAnirudh Venkataramanan q_vector->num_ring_tx = tx_rings_per_v; 134907309a0eSAnirudh Venkataramanan q_vector->tx.ring = NULL; 1350d2b464a7SBrett Creeley q_vector->tx.itr_idx = ICE_TX_ITR; 135107309a0eSAnirudh Venkataramanan q_base = vsi->num_txq - tx_rings_rem; 135207309a0eSAnirudh Venkataramanan 135307309a0eSAnirudh Venkataramanan for (q_id = q_base; q_id < (q_base + tx_rings_per_v); q_id++) { 135407309a0eSAnirudh Venkataramanan struct ice_ring *tx_ring = vsi->tx_rings[q_id]; 135507309a0eSAnirudh Venkataramanan 135607309a0eSAnirudh Venkataramanan tx_ring->q_vector = q_vector; 135707309a0eSAnirudh Venkataramanan tx_ring->next = q_vector->tx.ring; 135807309a0eSAnirudh Venkataramanan q_vector->tx.ring = tx_ring; 135907309a0eSAnirudh Venkataramanan } 136007309a0eSAnirudh Venkataramanan tx_rings_rem -= tx_rings_per_v; 136107309a0eSAnirudh Venkataramanan 136207309a0eSAnirudh Venkataramanan /* Rx rings mapping to vector */ 136307309a0eSAnirudh Venkataramanan rx_rings_per_v = DIV_ROUND_UP(rx_rings_rem, q_vectors - v_id); 136407309a0eSAnirudh Venkataramanan q_vector->num_ring_rx = rx_rings_per_v; 136507309a0eSAnirudh Venkataramanan q_vector->rx.ring = NULL; 1366d2b464a7SBrett Creeley q_vector->rx.itr_idx = ICE_RX_ITR; 136707309a0eSAnirudh Venkataramanan q_base = vsi->num_rxq - rx_rings_rem; 136807309a0eSAnirudh Venkataramanan 136907309a0eSAnirudh Venkataramanan for (q_id = q_base; q_id < (q_base + rx_rings_per_v); q_id++) { 137007309a0eSAnirudh Venkataramanan struct ice_ring *rx_ring = vsi->rx_rings[q_id]; 137107309a0eSAnirudh Venkataramanan 137207309a0eSAnirudh Venkataramanan rx_ring->q_vector = q_vector; 137307309a0eSAnirudh Venkataramanan rx_ring->next = q_vector->rx.ring; 137407309a0eSAnirudh Venkataramanan q_vector->rx.ring = rx_ring; 137507309a0eSAnirudh Venkataramanan } 137607309a0eSAnirudh Venkataramanan rx_rings_rem -= rx_rings_per_v; 137707309a0eSAnirudh Venkataramanan } 137807309a0eSAnirudh Venkataramanan } 137907309a0eSAnirudh Venkataramanan 138007309a0eSAnirudh Venkataramanan /** 1381492af0abSMd Fahad Iqbal Polash * ice_vsi_manage_rss_lut - disable/enable RSS 1382492af0abSMd Fahad Iqbal Polash * @vsi: the VSI being changed 1383492af0abSMd Fahad Iqbal Polash * @ena: boolean value indicating if this is an enable or disable request 1384492af0abSMd Fahad Iqbal Polash * 1385492af0abSMd Fahad Iqbal Polash * In the event of disable request for RSS, this function will zero out RSS 1386492af0abSMd Fahad Iqbal Polash * LUT, while in the event of enable request for RSS, it will reconfigure RSS 1387492af0abSMd Fahad Iqbal Polash * LUT. 1388492af0abSMd Fahad Iqbal Polash */ 1389492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena) 1390492af0abSMd Fahad Iqbal Polash { 1391492af0abSMd Fahad Iqbal Polash int err = 0; 1392492af0abSMd Fahad Iqbal Polash u8 *lut; 1393492af0abSMd Fahad Iqbal Polash 1394492af0abSMd Fahad Iqbal Polash lut = devm_kzalloc(&vsi->back->pdev->dev, vsi->rss_table_size, 1395492af0abSMd Fahad Iqbal Polash GFP_KERNEL); 1396492af0abSMd Fahad Iqbal Polash if (!lut) 1397492af0abSMd Fahad Iqbal Polash return -ENOMEM; 1398492af0abSMd Fahad Iqbal Polash 1399492af0abSMd Fahad Iqbal Polash if (ena) { 1400492af0abSMd Fahad Iqbal Polash if (vsi->rss_lut_user) 1401492af0abSMd Fahad Iqbal Polash memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 1402492af0abSMd Fahad Iqbal Polash else 1403492af0abSMd Fahad Iqbal Polash ice_fill_rss_lut(lut, vsi->rss_table_size, 1404492af0abSMd Fahad Iqbal Polash vsi->rss_size); 1405492af0abSMd Fahad Iqbal Polash } 1406492af0abSMd Fahad Iqbal Polash 1407492af0abSMd Fahad Iqbal Polash err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size); 1408492af0abSMd Fahad Iqbal Polash devm_kfree(&vsi->back->pdev->dev, lut); 1409492af0abSMd Fahad Iqbal Polash return err; 1410492af0abSMd Fahad Iqbal Polash } 1411492af0abSMd Fahad Iqbal Polash 1412492af0abSMd Fahad Iqbal Polash /** 141337bb8390SAnirudh Venkataramanan * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI 141437bb8390SAnirudh Venkataramanan * @vsi: VSI to be configured 141537bb8390SAnirudh Venkataramanan */ 141637bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi) 141737bb8390SAnirudh Venkataramanan { 141837bb8390SAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *key; 141937bb8390SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 142037bb8390SAnirudh Venkataramanan enum ice_status status; 142137bb8390SAnirudh Venkataramanan int err = 0; 142237bb8390SAnirudh Venkataramanan u8 *lut; 142337bb8390SAnirudh Venkataramanan 142437bb8390SAnirudh Venkataramanan vsi->rss_size = min_t(int, vsi->rss_size, vsi->num_rxq); 142537bb8390SAnirudh Venkataramanan 142637bb8390SAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 142737bb8390SAnirudh Venkataramanan if (!lut) 142837bb8390SAnirudh Venkataramanan return -ENOMEM; 142937bb8390SAnirudh Venkataramanan 143037bb8390SAnirudh Venkataramanan if (vsi->rss_lut_user) 143137bb8390SAnirudh Venkataramanan memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 143237bb8390SAnirudh Venkataramanan else 143337bb8390SAnirudh Venkataramanan ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 143437bb8390SAnirudh Venkataramanan 14354fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut, 14364fb33f31SAnirudh Venkataramanan vsi->rss_table_size); 143737bb8390SAnirudh Venkataramanan 143837bb8390SAnirudh Venkataramanan if (status) { 1439819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, 144037bb8390SAnirudh Venkataramanan "set_rss_lut failed, error %d\n", status); 144137bb8390SAnirudh Venkataramanan err = -EIO; 144237bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 144337bb8390SAnirudh Venkataramanan } 144437bb8390SAnirudh Venkataramanan 1445819d8998SJesse Brandeburg key = devm_kzalloc(&pf->pdev->dev, sizeof(*key), GFP_KERNEL); 144637bb8390SAnirudh Venkataramanan if (!key) { 144737bb8390SAnirudh Venkataramanan err = -ENOMEM; 144837bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 144937bb8390SAnirudh Venkataramanan } 145037bb8390SAnirudh Venkataramanan 145137bb8390SAnirudh Venkataramanan if (vsi->rss_hkey_user) 1452b4b418b3SPaul Greenwalt memcpy(key, 1453b4b418b3SPaul Greenwalt (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user, 1454b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 145537bb8390SAnirudh Venkataramanan else 1456b4b418b3SPaul Greenwalt netdev_rss_key_fill((void *)key, 1457b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 145837bb8390SAnirudh Venkataramanan 14594fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key); 146037bb8390SAnirudh Venkataramanan 146137bb8390SAnirudh Venkataramanan if (status) { 1462819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, "set_rss_key failed, error %d\n", 146337bb8390SAnirudh Venkataramanan status); 146437bb8390SAnirudh Venkataramanan err = -EIO; 146537bb8390SAnirudh Venkataramanan } 146637bb8390SAnirudh Venkataramanan 146737bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, key); 146837bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit: 146937bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 147037bb8390SAnirudh Venkataramanan return err; 147137bb8390SAnirudh Venkataramanan } 147237bb8390SAnirudh Venkataramanan 147337bb8390SAnirudh Venkataramanan /** 1474f9867df6SAnirudh Venkataramanan * ice_add_mac_to_list - Add a MAC address filter entry to the list 147545d3d428SAnirudh Venkataramanan * @vsi: the VSI to be forwarded to 147645d3d428SAnirudh Venkataramanan * @add_list: pointer to the list which contains MAC filter entries 147745d3d428SAnirudh Venkataramanan * @macaddr: the MAC address to be added. 147845d3d428SAnirudh Venkataramanan * 1479f9867df6SAnirudh Venkataramanan * Adds MAC address filter entry to the temp list 148045d3d428SAnirudh Venkataramanan * 148145d3d428SAnirudh Venkataramanan * Returns 0 on success or ENOMEM on failure. 148245d3d428SAnirudh Venkataramanan */ 148345d3d428SAnirudh Venkataramanan int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list, 148445d3d428SAnirudh Venkataramanan const u8 *macaddr) 148545d3d428SAnirudh Venkataramanan { 148645d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 148745d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 148845d3d428SAnirudh Venkataramanan 148945d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC); 149045d3d428SAnirudh Venkataramanan if (!tmp) 149145d3d428SAnirudh Venkataramanan return -ENOMEM; 149245d3d428SAnirudh Venkataramanan 149345d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 14945726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 149545d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC; 149645d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 14975726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 149845d3d428SAnirudh Venkataramanan ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr); 149945d3d428SAnirudh Venkataramanan 150045d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 150145d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, add_list); 150245d3d428SAnirudh Venkataramanan 150345d3d428SAnirudh Venkataramanan return 0; 150445d3d428SAnirudh Venkataramanan } 150545d3d428SAnirudh Venkataramanan 150645d3d428SAnirudh Venkataramanan /** 150745d3d428SAnirudh Venkataramanan * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 150845d3d428SAnirudh Venkataramanan * @vsi: the VSI to be updated 150945d3d428SAnirudh Venkataramanan */ 151045d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi) 151145d3d428SAnirudh Venkataramanan { 151245d3d428SAnirudh Venkataramanan struct ice_eth_stats *prev_es, *cur_es; 151345d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 151445d3d428SAnirudh Venkataramanan u16 vsi_num = vsi->vsi_num; /* HW absolute index of a VSI */ 151545d3d428SAnirudh Venkataramanan 151645d3d428SAnirudh Venkataramanan prev_es = &vsi->eth_stats_prev; 151745d3d428SAnirudh Venkataramanan cur_es = &vsi->eth_stats; 151845d3d428SAnirudh Venkataramanan 151936517fd3SJacob Keller ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded, 152036517fd3SJacob Keller &prev_es->rx_bytes, &cur_es->rx_bytes); 152145d3d428SAnirudh Venkataramanan 152236517fd3SJacob Keller ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded, 152336517fd3SJacob Keller &prev_es->rx_unicast, &cur_es->rx_unicast); 152445d3d428SAnirudh Venkataramanan 152536517fd3SJacob Keller ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded, 152636517fd3SJacob Keller &prev_es->rx_multicast, &cur_es->rx_multicast); 152745d3d428SAnirudh Venkataramanan 152836517fd3SJacob Keller ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded, 152936517fd3SJacob Keller &prev_es->rx_broadcast, &cur_es->rx_broadcast); 153045d3d428SAnirudh Venkataramanan 153145d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, 153245d3d428SAnirudh Venkataramanan &prev_es->rx_discards, &cur_es->rx_discards); 153345d3d428SAnirudh Venkataramanan 153436517fd3SJacob Keller ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded, 153536517fd3SJacob Keller &prev_es->tx_bytes, &cur_es->tx_bytes); 153645d3d428SAnirudh Venkataramanan 153736517fd3SJacob Keller ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded, 153836517fd3SJacob Keller &prev_es->tx_unicast, &cur_es->tx_unicast); 153945d3d428SAnirudh Venkataramanan 154036517fd3SJacob Keller ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded, 154136517fd3SJacob Keller &prev_es->tx_multicast, &cur_es->tx_multicast); 154245d3d428SAnirudh Venkataramanan 154336517fd3SJacob Keller ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded, 154436517fd3SJacob Keller &prev_es->tx_broadcast, &cur_es->tx_broadcast); 154545d3d428SAnirudh Venkataramanan 154645d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, 154745d3d428SAnirudh Venkataramanan &prev_es->tx_errors, &cur_es->tx_errors); 154845d3d428SAnirudh Venkataramanan 154945d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded = true; 155045d3d428SAnirudh Venkataramanan } 155145d3d428SAnirudh Venkataramanan 155245d3d428SAnirudh Venkataramanan /** 155345d3d428SAnirudh Venkataramanan * ice_free_fltr_list - free filter lists helper 155445d3d428SAnirudh Venkataramanan * @dev: pointer to the device struct 155545d3d428SAnirudh Venkataramanan * @h: pointer to the list head to be freed 155645d3d428SAnirudh Venkataramanan * 155745d3d428SAnirudh Venkataramanan * Helper function to free filter lists previously created using 155845d3d428SAnirudh Venkataramanan * ice_add_mac_to_list 155945d3d428SAnirudh Venkataramanan */ 156045d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h) 156145d3d428SAnirudh Venkataramanan { 156245d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *e, *tmp; 156345d3d428SAnirudh Venkataramanan 156445d3d428SAnirudh Venkataramanan list_for_each_entry_safe(e, tmp, h, list_entry) { 156545d3d428SAnirudh Venkataramanan list_del(&e->list_entry); 156645d3d428SAnirudh Venkataramanan devm_kfree(dev, e); 156745d3d428SAnirudh Venkataramanan } 156845d3d428SAnirudh Venkataramanan } 156945d3d428SAnirudh Venkataramanan 157045d3d428SAnirudh Venkataramanan /** 157145d3d428SAnirudh Venkataramanan * ice_vsi_add_vlan - Add VSI membership for given VLAN 157245d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1573f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be added 157445d3d428SAnirudh Venkataramanan */ 157545d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid) 157645d3d428SAnirudh Venkataramanan { 157745d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 157845d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 157945d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 158045d3d428SAnirudh Venkataramanan enum ice_status status; 158145d3d428SAnirudh Venkataramanan int err = 0; 158245d3d428SAnirudh Venkataramanan 158345d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_KERNEL); 158445d3d428SAnirudh Venkataramanan if (!tmp) 158545d3d428SAnirudh Venkataramanan return -ENOMEM; 158645d3d428SAnirudh Venkataramanan 158745d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 158845d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 158945d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 15905726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 15915726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 159245d3d428SAnirudh Venkataramanan tmp->fltr_info.l_data.vlan.vlan_id = vid; 159345d3d428SAnirudh Venkataramanan 159445d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 159545d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, &tmp_add_list); 159645d3d428SAnirudh Venkataramanan 159745d3d428SAnirudh Venkataramanan status = ice_add_vlan(&pf->hw, &tmp_add_list); 159845d3d428SAnirudh Venkataramanan if (status) { 159945d3d428SAnirudh Venkataramanan err = -ENODEV; 160045d3d428SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failure Adding VLAN %d on VSI %i\n", 160145d3d428SAnirudh Venkataramanan vid, vsi->vsi_num); 160245d3d428SAnirudh Venkataramanan } 160345d3d428SAnirudh Venkataramanan 160445d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 160545d3d428SAnirudh Venkataramanan return err; 160645d3d428SAnirudh Venkataramanan } 160745d3d428SAnirudh Venkataramanan 160845d3d428SAnirudh Venkataramanan /** 160945d3d428SAnirudh Venkataramanan * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN 161045d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1611f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be removed 161245d3d428SAnirudh Venkataramanan * 161345d3d428SAnirudh Venkataramanan * Returns 0 on success and negative on failure 161445d3d428SAnirudh Venkataramanan */ 161545d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid) 161645d3d428SAnirudh Venkataramanan { 161745d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *list; 161845d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 161945d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 16205079b853SAkeem G Abodunrin enum ice_status status; 16215079b853SAkeem G Abodunrin int err = 0; 162245d3d428SAnirudh Venkataramanan 162345d3d428SAnirudh Venkataramanan list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 162445d3d428SAnirudh Venkataramanan if (!list) 162545d3d428SAnirudh Venkataramanan return -ENOMEM; 162645d3d428SAnirudh Venkataramanan 162745d3d428SAnirudh Venkataramanan list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 16285726ca0eSAnirudh Venkataramanan list->fltr_info.vsi_handle = vsi->idx; 162945d3d428SAnirudh Venkataramanan list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 163045d3d428SAnirudh Venkataramanan list->fltr_info.l_data.vlan.vlan_id = vid; 163145d3d428SAnirudh Venkataramanan list->fltr_info.flag = ICE_FLTR_TX; 16325726ca0eSAnirudh Venkataramanan list->fltr_info.src_id = ICE_SRC_ID_VSI; 163345d3d428SAnirudh Venkataramanan 163445d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&list->list_entry); 163545d3d428SAnirudh Venkataramanan list_add(&list->list_entry, &tmp_add_list); 163645d3d428SAnirudh Venkataramanan 16375079b853SAkeem G Abodunrin status = ice_remove_vlan(&pf->hw, &tmp_add_list); 1638bb877b22SAkeem G Abodunrin if (status == ICE_ERR_DOES_NOT_EXIST) { 1639bb877b22SAkeem G Abodunrin dev_dbg(&pf->pdev->dev, 1640bb877b22SAkeem G Abodunrin "Failed to remove VLAN %d on VSI %i, it does not exist, status: %d\n", 1641bb877b22SAkeem G Abodunrin vid, vsi->vsi_num, status); 1642bb877b22SAkeem G Abodunrin } else if (status) { 16435079b853SAkeem G Abodunrin dev_err(&pf->pdev->dev, 16445079b853SAkeem G Abodunrin "Error removing VLAN %d on vsi %i error: %d\n", 16455079b853SAkeem G Abodunrin vid, vsi->vsi_num, status); 16465079b853SAkeem G Abodunrin err = -EIO; 164745d3d428SAnirudh Venkataramanan } 164845d3d428SAnirudh Venkataramanan 164945d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 16505079b853SAkeem G Abodunrin return err; 165145d3d428SAnirudh Venkataramanan } 165245d3d428SAnirudh Venkataramanan 165345d3d428SAnirudh Venkataramanan /** 165472adf242SAnirudh Venkataramanan * ice_vsi_cfg_rxqs - Configure the VSI for Rx 165572adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 165672adf242SAnirudh Venkataramanan * 165772adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 165872adf242SAnirudh Venkataramanan * Configure the Rx VSI for operation. 165972adf242SAnirudh Venkataramanan */ 166072adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi) 166172adf242SAnirudh Venkataramanan { 166272adf242SAnirudh Venkataramanan u16 i; 166372adf242SAnirudh Venkataramanan 16648ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 16658ede0178SAnirudh Venkataramanan goto setup_rings; 16668ede0178SAnirudh Venkataramanan 166772adf242SAnirudh Venkataramanan if (vsi->netdev && vsi->netdev->mtu > ETH_DATA_LEN) 166872adf242SAnirudh Venkataramanan vsi->max_frame = vsi->netdev->mtu + 166972adf242SAnirudh Venkataramanan ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; 167072adf242SAnirudh Venkataramanan else 167172adf242SAnirudh Venkataramanan vsi->max_frame = ICE_RXBUF_2048; 167272adf242SAnirudh Venkataramanan 167372adf242SAnirudh Venkataramanan vsi->rx_buf_len = ICE_RXBUF_2048; 16748ede0178SAnirudh Venkataramanan setup_rings: 167572adf242SAnirudh Venkataramanan /* set up individual rings */ 16761553f4f7SBrett Creeley for (i = 0; i < vsi->num_rxq; i++) { 16771553f4f7SBrett Creeley int err; 167872adf242SAnirudh Venkataramanan 16791553f4f7SBrett Creeley err = ice_setup_rx_ctx(vsi->rx_rings[i]); 168072adf242SAnirudh Venkataramanan if (err) { 16811553f4f7SBrett Creeley dev_err(&vsi->back->pdev->dev, 16821553f4f7SBrett Creeley "ice_setup_rx_ctx failed for RxQ %d, err %d\n", 16831553f4f7SBrett Creeley i, err); 168472adf242SAnirudh Venkataramanan return err; 168572adf242SAnirudh Venkataramanan } 16861553f4f7SBrett Creeley } 16871553f4f7SBrett Creeley 16881553f4f7SBrett Creeley return 0; 16891553f4f7SBrett Creeley } 169072adf242SAnirudh Venkataramanan 169172adf242SAnirudh Venkataramanan /** 1692d02f734cSMaciej Fijalkowski * ice_vsi_cfg_txq - Configure single Tx queue 1693d02f734cSMaciej Fijalkowski * @vsi: the VSI that queue belongs to 1694d02f734cSMaciej Fijalkowski * @ring: Tx ring to be configured 1695d02f734cSMaciej Fijalkowski * @tc_q_idx: queue index within given TC 1696d02f734cSMaciej Fijalkowski * @qg_buf: queue group buffer 1697d02f734cSMaciej Fijalkowski * @tc: TC that Tx ring belongs to 1698d02f734cSMaciej Fijalkowski */ 1699d02f734cSMaciej Fijalkowski static int 1700d02f734cSMaciej Fijalkowski ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_ring *ring, u16 tc_q_idx, 1701d02f734cSMaciej Fijalkowski struct ice_aqc_add_tx_qgrp *qg_buf, u8 tc) 1702d02f734cSMaciej Fijalkowski { 1703d02f734cSMaciej Fijalkowski struct ice_tlan_ctx tlan_ctx = { 0 }; 1704d02f734cSMaciej Fijalkowski struct ice_aqc_add_txqs_perq *txq; 1705d02f734cSMaciej Fijalkowski struct ice_pf *pf = vsi->back; 1706d02f734cSMaciej Fijalkowski u8 buf_len = sizeof(*qg_buf); 1707d02f734cSMaciej Fijalkowski enum ice_status status; 1708d02f734cSMaciej Fijalkowski u16 pf_q; 1709d02f734cSMaciej Fijalkowski 1710d02f734cSMaciej Fijalkowski pf_q = ring->reg_idx; 1711d02f734cSMaciej Fijalkowski ice_setup_tx_ctx(ring, &tlan_ctx, pf_q); 1712d02f734cSMaciej Fijalkowski /* copy context contents into the qg_buf */ 1713d02f734cSMaciej Fijalkowski qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q); 1714d02f734cSMaciej Fijalkowski ice_set_ctx((u8 *)&tlan_ctx, qg_buf->txqs[0].txq_ctx, 1715d02f734cSMaciej Fijalkowski ice_tlan_ctx_info); 1716d02f734cSMaciej Fijalkowski 1717d02f734cSMaciej Fijalkowski /* init queue specific tail reg. It is referred as 1718d02f734cSMaciej Fijalkowski * transmit comm scheduler queue doorbell. 1719d02f734cSMaciej Fijalkowski */ 1720d02f734cSMaciej Fijalkowski ring->tail = pf->hw.hw_addr + QTX_COMM_DBELL(pf_q); 1721d02f734cSMaciej Fijalkowski 1722d02f734cSMaciej Fijalkowski /* Add unique software queue handle of the Tx queue per 1723d02f734cSMaciej Fijalkowski * TC into the VSI Tx ring 1724d02f734cSMaciej Fijalkowski */ 1725d02f734cSMaciej Fijalkowski ring->q_handle = tc_q_idx; 1726d02f734cSMaciej Fijalkowski 1727d02f734cSMaciej Fijalkowski status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc, ring->q_handle, 1728d02f734cSMaciej Fijalkowski 1, qg_buf, buf_len, NULL); 1729d02f734cSMaciej Fijalkowski if (status) { 1730d02f734cSMaciej Fijalkowski dev_err(&pf->pdev->dev, 1731d02f734cSMaciej Fijalkowski "Failed to set LAN Tx queue context, error: %d\n", 1732d02f734cSMaciej Fijalkowski status); 1733d02f734cSMaciej Fijalkowski return -ENODEV; 1734d02f734cSMaciej Fijalkowski } 1735d02f734cSMaciej Fijalkowski 1736d02f734cSMaciej Fijalkowski /* Add Tx Queue TEID into the VSI Tx ring from the 1737d02f734cSMaciej Fijalkowski * response. This will complete configuring and 1738d02f734cSMaciej Fijalkowski * enabling the queue. 1739d02f734cSMaciej Fijalkowski */ 1740d02f734cSMaciej Fijalkowski txq = &qg_buf->txqs[0]; 1741d02f734cSMaciej Fijalkowski if (pf_q == le16_to_cpu(txq->txq_id)) 1742d02f734cSMaciej Fijalkowski ring->txq_teid = le32_to_cpu(txq->q_teid); 1743d02f734cSMaciej Fijalkowski 1744d02f734cSMaciej Fijalkowski return 0; 1745d02f734cSMaciej Fijalkowski } 1746d02f734cSMaciej Fijalkowski 1747d02f734cSMaciej Fijalkowski /** 174872adf242SAnirudh Venkataramanan * ice_vsi_cfg_txqs - Configure the VSI for Tx 174972adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 175003f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be configured 175103f7a986SAnirudh Venkataramanan * @offset: offset within vsi->txq_map 175272adf242SAnirudh Venkataramanan * 175372adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 175472adf242SAnirudh Venkataramanan * Configure the Tx VSI for operation. 175572adf242SAnirudh Venkataramanan */ 175603f7a986SAnirudh Venkataramanan static int 175703f7a986SAnirudh Venkataramanan ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, int offset) 175872adf242SAnirudh Venkataramanan { 175972adf242SAnirudh Venkataramanan struct ice_aqc_add_tx_qgrp *qg_buf; 176072adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1761d02f734cSMaciej Fijalkowski u16 q_idx = 0, i; 1762d02f734cSMaciej Fijalkowski int err = 0; 1763d02f734cSMaciej Fijalkowski u8 tc; 176472adf242SAnirudh Venkataramanan 1765d02f734cSMaciej Fijalkowski qg_buf = devm_kzalloc(&pf->pdev->dev, sizeof(*qg_buf), GFP_KERNEL); 176672adf242SAnirudh Venkataramanan if (!qg_buf) 176772adf242SAnirudh Venkataramanan return -ENOMEM; 176872adf242SAnirudh Venkataramanan 176972adf242SAnirudh Venkataramanan qg_buf->num_txqs = 1; 177072adf242SAnirudh Venkataramanan 1771c5a2a4a3SUsha Ketineni /* set up and configure the Tx queues for each enabled TC */ 17722bdc97beSBruce Allan ice_for_each_traffic_class(tc) { 1773c5a2a4a3SUsha Ketineni if (!(vsi->tc_cfg.ena_tc & BIT(tc))) 1774c5a2a4a3SUsha Ketineni break; 1775c5a2a4a3SUsha Ketineni 1776c5a2a4a3SUsha Ketineni for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) { 1777d02f734cSMaciej Fijalkowski err = ice_vsi_cfg_txq(vsi, rings[q_idx], i + offset, 1778d02f734cSMaciej Fijalkowski qg_buf, tc); 1779d02f734cSMaciej Fijalkowski if (err) 178072adf242SAnirudh Venkataramanan goto err_cfg_txqs; 1781c5a2a4a3SUsha Ketineni 1782c5a2a4a3SUsha Ketineni q_idx++; 1783c5a2a4a3SUsha Ketineni } 178472adf242SAnirudh Venkataramanan } 178572adf242SAnirudh Venkataramanan err_cfg_txqs: 178672adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, qg_buf); 178772adf242SAnirudh Venkataramanan return err; 178872adf242SAnirudh Venkataramanan } 178972adf242SAnirudh Venkataramanan 179072adf242SAnirudh Venkataramanan /** 179103f7a986SAnirudh Venkataramanan * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx 179203f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 179303f7a986SAnirudh Venkataramanan * 179403f7a986SAnirudh Venkataramanan * Return 0 on success and a negative value on error 179503f7a986SAnirudh Venkataramanan * Configure the Tx VSI for operation. 179603f7a986SAnirudh Venkataramanan */ 179703f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) 179803f7a986SAnirudh Venkataramanan { 179903f7a986SAnirudh Venkataramanan return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, 0); 180003f7a986SAnirudh Venkataramanan } 180103f7a986SAnirudh Venkataramanan 180203f7a986SAnirudh Venkataramanan /** 18039e4ab4c2SBrett Creeley * ice_intrl_usec_to_reg - convert interrupt rate limit to register value 18049e4ab4c2SBrett Creeley * @intrl: interrupt rate limit in usecs 18059e4ab4c2SBrett Creeley * @gran: interrupt rate limit granularity in usecs 18069e4ab4c2SBrett Creeley * 18079e4ab4c2SBrett Creeley * This function converts a decimal interrupt rate limit in usecs to the format 18089e4ab4c2SBrett Creeley * expected by firmware. 18099e4ab4c2SBrett Creeley */ 1810b9c8bb06SBrett Creeley u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) 18119e4ab4c2SBrett Creeley { 18129e4ab4c2SBrett Creeley u32 val = intrl / gran; 18139e4ab4c2SBrett Creeley 18149e4ab4c2SBrett Creeley if (val) 18159e4ab4c2SBrett Creeley return val | GLINT_RATE_INTRL_ENA_M; 18169e4ab4c2SBrett Creeley return 0; 18179e4ab4c2SBrett Creeley } 18189e4ab4c2SBrett Creeley 18199e4ab4c2SBrett Creeley /** 182070457520SBrett Creeley * ice_cfg_itr_gran - set the ITR granularity to 2 usecs if not already set 182170457520SBrett Creeley * @hw: board specific structure 182270457520SBrett Creeley */ 182370457520SBrett Creeley static void ice_cfg_itr_gran(struct ice_hw *hw) 182470457520SBrett Creeley { 182570457520SBrett Creeley u32 regval = rd32(hw, GLINT_CTL); 182670457520SBrett Creeley 182770457520SBrett Creeley /* no need to update global register if ITR gran is already set */ 182870457520SBrett Creeley if (!(regval & GLINT_CTL_DIS_AUTOMASK_M) && 182970457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_200_M) >> 183070457520SBrett Creeley GLINT_CTL_ITR_GRAN_200_S) == ICE_ITR_GRAN_US) && 183170457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_100_M) >> 183270457520SBrett Creeley GLINT_CTL_ITR_GRAN_100_S) == ICE_ITR_GRAN_US) && 183370457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_50_M) >> 183470457520SBrett Creeley GLINT_CTL_ITR_GRAN_50_S) == ICE_ITR_GRAN_US) && 183570457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_25_M) >> 183670457520SBrett Creeley GLINT_CTL_ITR_GRAN_25_S) == ICE_ITR_GRAN_US)) 183770457520SBrett Creeley return; 183870457520SBrett Creeley 183970457520SBrett Creeley regval = ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_200_S) & 184070457520SBrett Creeley GLINT_CTL_ITR_GRAN_200_M) | 184170457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_100_S) & 184270457520SBrett Creeley GLINT_CTL_ITR_GRAN_100_M) | 184370457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_50_S) & 184470457520SBrett Creeley GLINT_CTL_ITR_GRAN_50_M) | 184570457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_25_S) & 184670457520SBrett Creeley GLINT_CTL_ITR_GRAN_25_M); 184770457520SBrett Creeley wr32(hw, GLINT_CTL, regval); 184870457520SBrett Creeley } 184970457520SBrett Creeley 185070457520SBrett Creeley /** 1851d2b464a7SBrett Creeley * ice_cfg_itr - configure the initial interrupt throttle values 1852d2b464a7SBrett Creeley * @hw: pointer to the HW structure 1853d2b464a7SBrett Creeley * @q_vector: interrupt vector that's being configured 1854d2b464a7SBrett Creeley * 1855d2b464a7SBrett Creeley * Configure interrupt throttling values for the ring containers that are 1856d2b464a7SBrett Creeley * associated with the interrupt vector passed in. 1857d2b464a7SBrett Creeley */ 1858d2b464a7SBrett Creeley static void 1859b07833a0SBrett Creeley ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector) 1860d2b464a7SBrett Creeley { 186170457520SBrett Creeley ice_cfg_itr_gran(hw); 186270457520SBrett Creeley 1863d2b464a7SBrett Creeley if (q_vector->num_ring_rx) { 1864d2b464a7SBrett Creeley struct ice_ring_container *rc = &q_vector->rx; 1865d2b464a7SBrett Creeley 186663f545edSBrett Creeley /* if this value is set then don't overwrite with default */ 186763f545edSBrett Creeley if (!rc->itr_setting) 186863f545edSBrett Creeley rc->itr_setting = ICE_DFLT_RX_ITR; 186963f545edSBrett Creeley 187063f545edSBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 187163f545edSBrett Creeley rc->next_update = jiffies + 1; 187263f545edSBrett Creeley rc->current_itr = rc->target_itr; 1873b07833a0SBrett Creeley wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), 187463f545edSBrett Creeley ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); 1875d2b464a7SBrett Creeley } 1876d2b464a7SBrett Creeley 1877d2b464a7SBrett Creeley if (q_vector->num_ring_tx) { 1878d2b464a7SBrett Creeley struct ice_ring_container *rc = &q_vector->tx; 1879d2b464a7SBrett Creeley 188063f545edSBrett Creeley /* if this value is set then don't overwrite with default */ 188163f545edSBrett Creeley if (!rc->itr_setting) 188263f545edSBrett Creeley rc->itr_setting = ICE_DFLT_TX_ITR; 188363f545edSBrett Creeley 188463f545edSBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 188563f545edSBrett Creeley rc->next_update = jiffies + 1; 188663f545edSBrett Creeley rc->current_itr = rc->target_itr; 1887b07833a0SBrett Creeley wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), 188863f545edSBrett Creeley ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); 1889d2b464a7SBrett Creeley } 1890d2b464a7SBrett Creeley } 1891d2b464a7SBrett Creeley 1892d2b464a7SBrett Creeley /** 1893047e52c0SAnirudh Venkataramanan * ice_cfg_txq_interrupt - configure interrupt on Tx queue 1894047e52c0SAnirudh Venkataramanan * @vsi: the VSI being configured 1895047e52c0SAnirudh Venkataramanan * @txq: Tx queue being mapped to MSI-X vector 1896047e52c0SAnirudh Venkataramanan * @msix_idx: MSI-X vector index within the function 1897047e52c0SAnirudh Venkataramanan * @itr_idx: ITR index of the interrupt cause 1898047e52c0SAnirudh Venkataramanan * 1899047e52c0SAnirudh Venkataramanan * Configure interrupt on Tx queue by associating Tx queue to MSI-X vector 1900047e52c0SAnirudh Venkataramanan * within the function space. 1901047e52c0SAnirudh Venkataramanan */ 1902047e52c0SAnirudh Venkataramanan #ifdef CONFIG_PCI_IOV 1903047e52c0SAnirudh Venkataramanan void 1904047e52c0SAnirudh Venkataramanan ice_cfg_txq_interrupt(struct ice_vsi *vsi, u16 txq, u16 msix_idx, u16 itr_idx) 1905047e52c0SAnirudh Venkataramanan #else 1906047e52c0SAnirudh Venkataramanan static void 1907047e52c0SAnirudh Venkataramanan ice_cfg_txq_interrupt(struct ice_vsi *vsi, u16 txq, u16 msix_idx, u16 itr_idx) 1908047e52c0SAnirudh Venkataramanan #endif /* CONFIG_PCI_IOV */ 1909047e52c0SAnirudh Venkataramanan { 1910047e52c0SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1911047e52c0SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1912047e52c0SAnirudh Venkataramanan u32 val; 1913047e52c0SAnirudh Venkataramanan 1914047e52c0SAnirudh Venkataramanan itr_idx = (itr_idx << QINT_TQCTL_ITR_INDX_S) & QINT_TQCTL_ITR_INDX_M; 1915047e52c0SAnirudh Venkataramanan 1916047e52c0SAnirudh Venkataramanan val = QINT_TQCTL_CAUSE_ENA_M | itr_idx | 1917047e52c0SAnirudh Venkataramanan ((msix_idx << QINT_TQCTL_MSIX_INDX_S) & QINT_TQCTL_MSIX_INDX_M); 1918047e52c0SAnirudh Venkataramanan 1919047e52c0SAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), val); 1920047e52c0SAnirudh Venkataramanan } 1921047e52c0SAnirudh Venkataramanan 1922047e52c0SAnirudh Venkataramanan /** 1923047e52c0SAnirudh Venkataramanan * ice_cfg_rxq_interrupt - configure interrupt on Rx queue 1924047e52c0SAnirudh Venkataramanan * @vsi: the VSI being configured 1925047e52c0SAnirudh Venkataramanan * @rxq: Rx queue being mapped to MSI-X vector 1926047e52c0SAnirudh Venkataramanan * @msix_idx: MSI-X vector index within the function 1927047e52c0SAnirudh Venkataramanan * @itr_idx: ITR index of the interrupt cause 1928047e52c0SAnirudh Venkataramanan * 1929047e52c0SAnirudh Venkataramanan * Configure interrupt on Rx queue by associating Rx queue to MSI-X vector 1930047e52c0SAnirudh Venkataramanan * within the function space. 1931047e52c0SAnirudh Venkataramanan */ 1932047e52c0SAnirudh Venkataramanan #ifdef CONFIG_PCI_IOV 1933047e52c0SAnirudh Venkataramanan void 1934047e52c0SAnirudh Venkataramanan ice_cfg_rxq_interrupt(struct ice_vsi *vsi, u16 rxq, u16 msix_idx, u16 itr_idx) 1935047e52c0SAnirudh Venkataramanan #else 1936047e52c0SAnirudh Venkataramanan static void 1937047e52c0SAnirudh Venkataramanan ice_cfg_rxq_interrupt(struct ice_vsi *vsi, u16 rxq, u16 msix_idx, u16 itr_idx) 1938047e52c0SAnirudh Venkataramanan #endif /* CONFIG_PCI_IOV */ 1939047e52c0SAnirudh Venkataramanan { 1940047e52c0SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1941047e52c0SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1942047e52c0SAnirudh Venkataramanan u32 val; 1943047e52c0SAnirudh Venkataramanan 1944047e52c0SAnirudh Venkataramanan itr_idx = (itr_idx << QINT_RQCTL_ITR_INDX_S) & QINT_RQCTL_ITR_INDX_M; 1945047e52c0SAnirudh Venkataramanan 1946047e52c0SAnirudh Venkataramanan val = QINT_RQCTL_CAUSE_ENA_M | itr_idx | 1947047e52c0SAnirudh Venkataramanan ((msix_idx << QINT_RQCTL_MSIX_INDX_S) & QINT_RQCTL_MSIX_INDX_M); 1948047e52c0SAnirudh Venkataramanan 1949047e52c0SAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), val); 1950047e52c0SAnirudh Venkataramanan 1951047e52c0SAnirudh Venkataramanan ice_flush(hw); 1952047e52c0SAnirudh Venkataramanan } 1953047e52c0SAnirudh Venkataramanan 1954047e52c0SAnirudh Venkataramanan /** 195572adf242SAnirudh Venkataramanan * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW 195672adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 1957047e52c0SAnirudh Venkataramanan * 1958047e52c0SAnirudh Venkataramanan * This configures MSIX mode interrupts for the PF VSI, and should not be used 1959047e52c0SAnirudh Venkataramanan * for the VF VSI. 196072adf242SAnirudh Venkataramanan */ 196172adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi) 196272adf242SAnirudh Venkataramanan { 196372adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 196472adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 196572adf242SAnirudh Venkataramanan u32 txq = 0, rxq = 0; 1966d2b464a7SBrett Creeley int i, q; 196772adf242SAnirudh Venkataramanan 1968b07833a0SBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 196972adf242SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1970b07833a0SBrett Creeley u16 reg_idx = q_vector->reg_idx; 197172adf242SAnirudh Venkataramanan 1972b07833a0SBrett Creeley ice_cfg_itr(hw, q_vector); 19739e4ab4c2SBrett Creeley 1974b07833a0SBrett Creeley wr32(hw, GLINT_RATE(reg_idx), 19759e4ab4c2SBrett Creeley ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); 197672adf242SAnirudh Venkataramanan 197772adf242SAnirudh Venkataramanan /* Both Transmit Queue Interrupt Cause Control register 197872adf242SAnirudh Venkataramanan * and Receive Queue Interrupt Cause control register 197972adf242SAnirudh Venkataramanan * expects MSIX_INDX field to be the vector index 198072adf242SAnirudh Venkataramanan * within the function space and not the absolute 198172adf242SAnirudh Venkataramanan * vector index across PF or across device. 198272adf242SAnirudh Venkataramanan * For SR-IOV VF VSIs queue vector index always starts 198372adf242SAnirudh Venkataramanan * with 1 since first vector index(0) is used for OICR 198472adf242SAnirudh Venkataramanan * in VF space. Since VMDq and other PF VSIs are within 198572adf242SAnirudh Venkataramanan * the PF function space, use the vector index that is 198672adf242SAnirudh Venkataramanan * tracked for this PF. 198772adf242SAnirudh Venkataramanan */ 198872adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 1989047e52c0SAnirudh Venkataramanan ice_cfg_txq_interrupt(vsi, txq, reg_idx, 1990047e52c0SAnirudh Venkataramanan q_vector->tx.itr_idx); 199172adf242SAnirudh Venkataramanan txq++; 199272adf242SAnirudh Venkataramanan } 199372adf242SAnirudh Venkataramanan 199472adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 1995047e52c0SAnirudh Venkataramanan ice_cfg_rxq_interrupt(vsi, rxq, reg_idx, 1996047e52c0SAnirudh Venkataramanan q_vector->rx.itr_idx); 199772adf242SAnirudh Venkataramanan rxq++; 199872adf242SAnirudh Venkataramanan } 199972adf242SAnirudh Venkataramanan } 200072adf242SAnirudh Venkataramanan } 200172adf242SAnirudh Venkataramanan 200272adf242SAnirudh Venkataramanan /** 200345d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx 200445d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 200545d3d428SAnirudh Venkataramanan */ 200645d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) 200745d3d428SAnirudh Venkataramanan { 200845d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 200945d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 2010198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 201145d3d428SAnirudh Venkataramanan enum ice_status status; 2012198a666aSBruce Allan int ret = 0; 2013198a666aSBruce Allan 2014198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 2015198a666aSBruce Allan if (!ctxt) 2016198a666aSBruce Allan return -ENOMEM; 201745d3d428SAnirudh Venkataramanan 201845d3d428SAnirudh Venkataramanan /* Here we are configuring the VSI to let the driver add VLAN tags by 201945d3d428SAnirudh Venkataramanan * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag 202045d3d428SAnirudh Venkataramanan * insertion happens in the Tx hot path, in ice_tx_map. 202145d3d428SAnirudh Venkataramanan */ 2022198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; 202345d3d428SAnirudh Venkataramanan 2024e80e76dbSTony Nguyen /* Preserve existing VLAN strip setting */ 2025e80e76dbSTony Nguyen ctxt->info.vlan_flags |= (vsi->info.vlan_flags & 2026e80e76dbSTony Nguyen ICE_AQ_VSI_VLAN_EMOD_M); 2027e80e76dbSTony Nguyen 2028198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 202945d3d428SAnirudh Venkataramanan 2030198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 203145d3d428SAnirudh Venkataramanan if (status) { 203245d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n", 203345d3d428SAnirudh Venkataramanan status, hw->adminq.sq_last_status); 2034198a666aSBruce Allan ret = -EIO; 2035198a666aSBruce Allan goto out; 203645d3d428SAnirudh Venkataramanan } 203745d3d428SAnirudh Venkataramanan 2038198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 2039198a666aSBruce Allan out: 2040198a666aSBruce Allan devm_kfree(dev, ctxt); 2041198a666aSBruce Allan return ret; 204245d3d428SAnirudh Venkataramanan } 204345d3d428SAnirudh Venkataramanan 204445d3d428SAnirudh Venkataramanan /** 204545d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx 204645d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 204745d3d428SAnirudh Venkataramanan * @ena: boolean value indicating if this is a enable or disable request 204845d3d428SAnirudh Venkataramanan */ 204945d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) 205045d3d428SAnirudh Venkataramanan { 205145d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 205245d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 2053198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 205445d3d428SAnirudh Venkataramanan enum ice_status status; 2055198a666aSBruce Allan int ret = 0; 2056198a666aSBruce Allan 2057198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 2058198a666aSBruce Allan if (!ctxt) 2059198a666aSBruce Allan return -ENOMEM; 206045d3d428SAnirudh Venkataramanan 206145d3d428SAnirudh Venkataramanan /* Here we are configuring what the VSI should do with the VLAN tag in 206245d3d428SAnirudh Venkataramanan * the Rx packet. We can either leave the tag in the packet or put it in 206345d3d428SAnirudh Venkataramanan * the Rx descriptor. 206445d3d428SAnirudh Venkataramanan */ 2065198a666aSBruce Allan if (ena) 206645d3d428SAnirudh Venkataramanan /* Strip VLAN tag from Rx packet and put it in the desc */ 2067198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; 2068198a666aSBruce Allan else 206945d3d428SAnirudh Venkataramanan /* Disable stripping. Leave tag in packet */ 2070198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; 207145d3d428SAnirudh Venkataramanan 207245d3d428SAnirudh Venkataramanan /* Allow all packets untagged/tagged */ 2073198a666aSBruce Allan ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; 207445d3d428SAnirudh Venkataramanan 2075198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 207645d3d428SAnirudh Venkataramanan 2077198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 207845d3d428SAnirudh Venkataramanan if (status) { 207945d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n", 208045d3d428SAnirudh Venkataramanan ena, status, hw->adminq.sq_last_status); 2081198a666aSBruce Allan ret = -EIO; 2082198a666aSBruce Allan goto out; 208345d3d428SAnirudh Venkataramanan } 208445d3d428SAnirudh Venkataramanan 2085198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 2086198a666aSBruce Allan out: 2087198a666aSBruce Allan devm_kfree(dev, ctxt); 2088198a666aSBruce Allan return ret; 208945d3d428SAnirudh Venkataramanan } 209072adf242SAnirudh Venkataramanan 209172adf242SAnirudh Venkataramanan /** 209272adf242SAnirudh Venkataramanan * ice_vsi_start_rx_rings - start VSI's Rx rings 209372adf242SAnirudh Venkataramanan * @vsi: the VSI whose rings are to be started 209472adf242SAnirudh Venkataramanan * 209572adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 209672adf242SAnirudh Venkataramanan */ 209772adf242SAnirudh Venkataramanan int ice_vsi_start_rx_rings(struct ice_vsi *vsi) 209872adf242SAnirudh Venkataramanan { 209972adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, true); 210072adf242SAnirudh Venkataramanan } 210172adf242SAnirudh Venkataramanan 210272adf242SAnirudh Venkataramanan /** 210372adf242SAnirudh Venkataramanan * ice_vsi_stop_rx_rings - stop VSI's Rx rings 210472adf242SAnirudh Venkataramanan * @vsi: the VSI 210572adf242SAnirudh Venkataramanan * 210672adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 210772adf242SAnirudh Venkataramanan */ 210872adf242SAnirudh Venkataramanan int ice_vsi_stop_rx_rings(struct ice_vsi *vsi) 210972adf242SAnirudh Venkataramanan { 211072adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, false); 211172adf242SAnirudh Venkataramanan } 211272adf242SAnirudh Venkataramanan 211372adf242SAnirudh Venkataramanan /** 2114e89e899fSBrett Creeley * ice_trigger_sw_intr - trigger a software interrupt 2115e89e899fSBrett Creeley * @hw: pointer to the HW structure 2116e89e899fSBrett Creeley * @q_vector: interrupt vector to trigger the software interrupt for 2117e89e899fSBrett Creeley */ 2118e89e899fSBrett Creeley void ice_trigger_sw_intr(struct ice_hw *hw, struct ice_q_vector *q_vector) 2119e89e899fSBrett Creeley { 2120e89e899fSBrett Creeley wr32(hw, GLINT_DYN_CTL(q_vector->reg_idx), 2121e89e899fSBrett Creeley (ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S) | 2122e89e899fSBrett Creeley GLINT_DYN_CTL_SWINT_TRIG_M | 2123e89e899fSBrett Creeley GLINT_DYN_CTL_INTENA_M); 2124e89e899fSBrett Creeley } 2125e89e899fSBrett Creeley 2126e89e899fSBrett Creeley /** 2127d02f734cSMaciej Fijalkowski * ice_vsi_stop_tx_ring - Disable single Tx ring 212872adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 2129ddf30f7fSAnirudh Venkataramanan * @rst_src: reset source 2130f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 2131d02f734cSMaciej Fijalkowski * @ring: Tx ring to be stopped 2132d02f734cSMaciej Fijalkowski * @txq_meta: Meta data of Tx ring to be stopped 213372adf242SAnirudh Venkataramanan */ 213477ca27c4SPaul Greenwalt #ifndef CONFIG_PCI_IOV 213577ca27c4SPaul Greenwalt static 213677ca27c4SPaul Greenwalt #endif /* !CONFIG_PCI_IOV */ 213777ca27c4SPaul Greenwalt int 2138d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 2139d02f734cSMaciej Fijalkowski u16 rel_vmvf_num, struct ice_ring *ring, 2140d02f734cSMaciej Fijalkowski struct ice_txq_meta *txq_meta) 214172adf242SAnirudh Venkataramanan { 214272adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2143e89e899fSBrett Creeley struct ice_q_vector *q_vector; 2144d02f734cSMaciej Fijalkowski struct ice_hw *hw = &pf->hw; 2145d02f734cSMaciej Fijalkowski enum ice_status status; 2146d02f734cSMaciej Fijalkowski u32 val; 214772adf242SAnirudh Venkataramanan 214872adf242SAnirudh Venkataramanan /* clear cause_ena bit for disabled queues */ 2149d02f734cSMaciej Fijalkowski val = rd32(hw, QINT_TQCTL(ring->reg_idx)); 215072adf242SAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 2151d02f734cSMaciej Fijalkowski wr32(hw, QINT_TQCTL(ring->reg_idx), val); 215272adf242SAnirudh Venkataramanan 215372adf242SAnirudh Venkataramanan /* software is expected to wait for 100 ns */ 215472adf242SAnirudh Venkataramanan ndelay(100); 215572adf242SAnirudh Venkataramanan 2156bb87ee0eSAnirudh Venkataramanan /* trigger a software interrupt for the vector 2157bb87ee0eSAnirudh Venkataramanan * associated to the queue to schedule NAPI handler 215872adf242SAnirudh Venkataramanan */ 2159d02f734cSMaciej Fijalkowski q_vector = ring->q_vector; 2160e89e899fSBrett Creeley if (q_vector) 2161e89e899fSBrett Creeley ice_trigger_sw_intr(hw, q_vector); 21620e674aebSAnirudh Venkataramanan 2163d02f734cSMaciej Fijalkowski status = ice_dis_vsi_txq(vsi->port_info, txq_meta->vsi_idx, 2164d02f734cSMaciej Fijalkowski txq_meta->tc, 1, &txq_meta->q_handle, 2165d02f734cSMaciej Fijalkowski &txq_meta->q_id, &txq_meta->q_teid, rst_src, 2166d02f734cSMaciej Fijalkowski rel_vmvf_num, NULL); 2167bb87ee0eSAnirudh Venkataramanan 2168d02f734cSMaciej Fijalkowski /* if the disable queue command was exercised during an 2169d02f734cSMaciej Fijalkowski * active reset flow, ICE_ERR_RESET_ONGOING is returned. 2170d02f734cSMaciej Fijalkowski * This is not an error as the reset operation disables 2171d02f734cSMaciej Fijalkowski * queues at the hardware level anyway. 217272adf242SAnirudh Venkataramanan */ 217372adf242SAnirudh Venkataramanan if (status == ICE_ERR_RESET_ONGOING) { 2174d02f734cSMaciej Fijalkowski dev_dbg(&vsi->back->pdev->dev, 217572adf242SAnirudh Venkataramanan "Reset in progress. LAN Tx queues already disabled\n"); 217699214944SAkeem G Abodunrin } else if (status == ICE_ERR_DOES_NOT_EXIST) { 2177d02f734cSMaciej Fijalkowski dev_dbg(&vsi->back->pdev->dev, 2178d02f734cSMaciej Fijalkowski "LAN Tx queues do not exist, nothing to disable\n"); 217972adf242SAnirudh Venkataramanan } else if (status) { 2180d02f734cSMaciej Fijalkowski dev_err(&vsi->back->pdev->dev, 2181d02f734cSMaciej Fijalkowski "Failed to disable LAN Tx queues, error: %d\n", status); 2182d02f734cSMaciej Fijalkowski return -ENODEV; 2183d02f734cSMaciej Fijalkowski } 2184d02f734cSMaciej Fijalkowski 2185d02f734cSMaciej Fijalkowski return 0; 2186d02f734cSMaciej Fijalkowski } 2187d02f734cSMaciej Fijalkowski 2188d02f734cSMaciej Fijalkowski /** 2189d02f734cSMaciej Fijalkowski * ice_fill_txq_meta - Prepare the Tx queue's meta data 2190d02f734cSMaciej Fijalkowski * @vsi: VSI that ring belongs to 2191d02f734cSMaciej Fijalkowski * @ring: ring that txq_meta will be based on 2192d02f734cSMaciej Fijalkowski * @txq_meta: a helper struct that wraps Tx queue's information 2193d02f734cSMaciej Fijalkowski * 2194d02f734cSMaciej Fijalkowski * Set up a helper struct that will contain all the necessary fields that 2195d02f734cSMaciej Fijalkowski * are needed for stopping Tx queue 2196d02f734cSMaciej Fijalkowski */ 219777ca27c4SPaul Greenwalt #ifndef CONFIG_PCI_IOV 219877ca27c4SPaul Greenwalt static 219977ca27c4SPaul Greenwalt #endif /* !CONFIG_PCI_IOV */ 220077ca27c4SPaul Greenwalt void 2201d02f734cSMaciej Fijalkowski ice_fill_txq_meta(struct ice_vsi *vsi, struct ice_ring *ring, 2202d02f734cSMaciej Fijalkowski struct ice_txq_meta *txq_meta) 2203d02f734cSMaciej Fijalkowski { 2204d02f734cSMaciej Fijalkowski u8 tc = 0; 2205d02f734cSMaciej Fijalkowski 2206d02f734cSMaciej Fijalkowski #ifdef CONFIG_DCB 2207d02f734cSMaciej Fijalkowski tc = ring->dcb_tc; 2208d02f734cSMaciej Fijalkowski #endif /* CONFIG_DCB */ 2209d02f734cSMaciej Fijalkowski txq_meta->q_id = ring->reg_idx; 2210d02f734cSMaciej Fijalkowski txq_meta->q_teid = ring->txq_teid; 2211d02f734cSMaciej Fijalkowski txq_meta->q_handle = ring->q_handle; 2212d02f734cSMaciej Fijalkowski txq_meta->vsi_idx = vsi->idx; 2213d02f734cSMaciej Fijalkowski txq_meta->tc = tc; 2214d02f734cSMaciej Fijalkowski } 2215d02f734cSMaciej Fijalkowski 2216d02f734cSMaciej Fijalkowski /** 2217d02f734cSMaciej Fijalkowski * ice_vsi_stop_tx_rings - Disable Tx rings 2218d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 2219d02f734cSMaciej Fijalkowski * @rst_src: reset source 2220d02f734cSMaciej Fijalkowski * @rel_vmvf_num: Relative ID of VF/VM 2221d02f734cSMaciej Fijalkowski * @rings: Tx ring array to be stopped 2222d02f734cSMaciej Fijalkowski */ 2223d02f734cSMaciej Fijalkowski static int 2224d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 2225d02f734cSMaciej Fijalkowski u16 rel_vmvf_num, struct ice_ring **rings) 2226d02f734cSMaciej Fijalkowski { 2227d02f734cSMaciej Fijalkowski u16 i, q_idx = 0; 2228d02f734cSMaciej Fijalkowski int status; 2229d02f734cSMaciej Fijalkowski u8 tc; 2230d02f734cSMaciej Fijalkowski 2231d02f734cSMaciej Fijalkowski if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS) 2232d02f734cSMaciej Fijalkowski return -EINVAL; 2233d02f734cSMaciej Fijalkowski 2234d02f734cSMaciej Fijalkowski /* set up the Tx queue list to be disabled for each enabled TC */ 2235d02f734cSMaciej Fijalkowski ice_for_each_traffic_class(tc) { 2236d02f734cSMaciej Fijalkowski if (!(vsi->tc_cfg.ena_tc & BIT(tc))) 2237d02f734cSMaciej Fijalkowski break; 2238d02f734cSMaciej Fijalkowski 2239d02f734cSMaciej Fijalkowski for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) { 2240d02f734cSMaciej Fijalkowski struct ice_txq_meta txq_meta = { }; 2241d02f734cSMaciej Fijalkowski 2242d02f734cSMaciej Fijalkowski if (!rings || !rings[q_idx]) 2243d02f734cSMaciej Fijalkowski return -EINVAL; 2244d02f734cSMaciej Fijalkowski 2245d02f734cSMaciej Fijalkowski ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta); 2246d02f734cSMaciej Fijalkowski status = ice_vsi_stop_tx_ring(vsi, rst_src, 2247d02f734cSMaciej Fijalkowski rel_vmvf_num, 2248d02f734cSMaciej Fijalkowski rings[q_idx], &txq_meta); 2249d02f734cSMaciej Fijalkowski 2250d02f734cSMaciej Fijalkowski if (status) 2251d02f734cSMaciej Fijalkowski return status; 2252d02f734cSMaciej Fijalkowski 2253d02f734cSMaciej Fijalkowski q_idx++; 225472adf242SAnirudh Venkataramanan } 2255bb87ee0eSAnirudh Venkataramanan } 225672adf242SAnirudh Venkataramanan 2257d02f734cSMaciej Fijalkowski return 0; 225872adf242SAnirudh Venkataramanan } 22595153a18eSAnirudh Venkataramanan 22605153a18eSAnirudh Venkataramanan /** 226103f7a986SAnirudh Venkataramanan * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings 226203f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 226303f7a986SAnirudh Venkataramanan * @rst_src: reset source 2264f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 226503f7a986SAnirudh Venkataramanan */ 2266c8b7abddSBruce Allan int 2267c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 2268c8b7abddSBruce Allan u16 rel_vmvf_num) 226903f7a986SAnirudh Venkataramanan { 2270d02f734cSMaciej Fijalkowski return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings); 227103f7a986SAnirudh Venkataramanan } 227203f7a986SAnirudh Venkataramanan 227303f7a986SAnirudh Venkataramanan /** 22745153a18eSAnirudh Venkataramanan * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 22755153a18eSAnirudh Venkataramanan * @vsi: VSI to enable or disable VLAN pruning on 22765153a18eSAnirudh Venkataramanan * @ena: set to true to enable VLAN pruning and false to disable it 22775eda8afdSAkeem G Abodunrin * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode 22785153a18eSAnirudh Venkataramanan * 22795153a18eSAnirudh Venkataramanan * returns 0 if VSI is updated, negative otherwise 22805153a18eSAnirudh Venkataramanan */ 22815eda8afdSAkeem G Abodunrin int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc) 22825153a18eSAnirudh Venkataramanan { 22835153a18eSAnirudh Venkataramanan struct ice_vsi_ctx *ctxt; 22845153a18eSAnirudh Venkataramanan struct device *dev; 2285819d8998SJesse Brandeburg struct ice_pf *pf; 22865153a18eSAnirudh Venkataramanan int status; 22875153a18eSAnirudh Venkataramanan 22885153a18eSAnirudh Venkataramanan if (!vsi) 22895153a18eSAnirudh Venkataramanan return -EINVAL; 22905153a18eSAnirudh Venkataramanan 2291819d8998SJesse Brandeburg pf = vsi->back; 2292819d8998SJesse Brandeburg dev = &pf->pdev->dev; 22935153a18eSAnirudh Venkataramanan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 22945153a18eSAnirudh Venkataramanan if (!ctxt) 22955153a18eSAnirudh Venkataramanan return -ENOMEM; 22965153a18eSAnirudh Venkataramanan 22975153a18eSAnirudh Venkataramanan ctxt->info = vsi->info; 22985153a18eSAnirudh Venkataramanan 22995153a18eSAnirudh Venkataramanan if (ena) { 23005153a18eSAnirudh Venkataramanan ctxt->info.sec_flags |= 23015153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 23025153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S; 23035153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 23045153a18eSAnirudh Venkataramanan } else { 23055153a18eSAnirudh Venkataramanan ctxt->info.sec_flags &= 23065153a18eSAnirudh Venkataramanan ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 23075153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 23085153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 23095153a18eSAnirudh Venkataramanan } 23105153a18eSAnirudh Venkataramanan 23115eda8afdSAkeem G Abodunrin if (!vlan_promisc) 23125eda8afdSAkeem G Abodunrin ctxt->info.valid_sections = 23135eda8afdSAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID | 23145153a18eSAnirudh Venkataramanan ICE_AQ_VSI_PROP_SW_VALID); 23155726ca0eSAnirudh Venkataramanan 2316819d8998SJesse Brandeburg status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL); 23175153a18eSAnirudh Venkataramanan if (status) { 23185726ca0eSAnirudh Venkataramanan netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %d\n", 231931082519SAnirudh Venkataramanan ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status, 2320819d8998SJesse Brandeburg pf->hw.adminq.sq_last_status); 23215153a18eSAnirudh Venkataramanan goto err_out; 23225153a18eSAnirudh Venkataramanan } 23235153a18eSAnirudh Venkataramanan 23245153a18eSAnirudh Venkataramanan vsi->info.sec_flags = ctxt->info.sec_flags; 23255153a18eSAnirudh Venkataramanan vsi->info.sw_flags2 = ctxt->info.sw_flags2; 23265153a18eSAnirudh Venkataramanan 23275153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 23285153a18eSAnirudh Venkataramanan return 0; 23295153a18eSAnirudh Venkataramanan 23305153a18eSAnirudh Venkataramanan err_out: 23315153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 23325153a18eSAnirudh Venkataramanan return -EIO; 23335153a18eSAnirudh Venkataramanan } 23345153a18eSAnirudh Venkataramanan 23357b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) 23367b9ffc76SAnirudh Venkataramanan { 23377b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *cfg = &vsi->port_info->local_dcbx_cfg; 23387b9ffc76SAnirudh Venkataramanan 23397b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg); 23407b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg); 23417b9ffc76SAnirudh Venkataramanan } 23427b9ffc76SAnirudh Venkataramanan 23435153a18eSAnirudh Venkataramanan /** 2344b07833a0SBrett Creeley * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors 2345b07833a0SBrett Creeley * @vsi: VSI to set the q_vectors register index on 2346b07833a0SBrett Creeley */ 2347b07833a0SBrett Creeley static int 2348b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi) 2349b07833a0SBrett Creeley { 2350b07833a0SBrett Creeley u16 i; 2351b07833a0SBrett Creeley 2352b07833a0SBrett Creeley if (!vsi || !vsi->q_vectors) 2353b07833a0SBrett Creeley return -EINVAL; 2354b07833a0SBrett Creeley 2355b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 2356b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2357b07833a0SBrett Creeley 2358b07833a0SBrett Creeley if (!q_vector) { 2359b07833a0SBrett Creeley dev_err(&vsi->back->pdev->dev, 2360b07833a0SBrett Creeley "Failed to set reg_idx on q_vector %d VSI %d\n", 2361b07833a0SBrett Creeley i, vsi->vsi_num); 2362b07833a0SBrett Creeley goto clear_reg_idx; 2363b07833a0SBrett Creeley } 2364b07833a0SBrett Creeley 2365cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) { 2366cbe66bfeSBrett Creeley struct ice_vf *vf = &vsi->back->vf[vsi->vf_id]; 2367cbe66bfeSBrett Creeley 2368cbe66bfeSBrett Creeley q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector); 2369cbe66bfeSBrett Creeley } else { 2370cbe66bfeSBrett Creeley q_vector->reg_idx = 2371cbe66bfeSBrett Creeley q_vector->v_idx + vsi->base_vector; 2372cbe66bfeSBrett Creeley } 2373b07833a0SBrett Creeley } 2374b07833a0SBrett Creeley 2375b07833a0SBrett Creeley return 0; 2376b07833a0SBrett Creeley 2377b07833a0SBrett Creeley clear_reg_idx: 2378b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 2379b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2380b07833a0SBrett Creeley 2381b07833a0SBrett Creeley if (q_vector) 2382b07833a0SBrett Creeley q_vector->reg_idx = 0; 2383b07833a0SBrett Creeley } 2384b07833a0SBrett Creeley 2385b07833a0SBrett Creeley return -EINVAL; 2386b07833a0SBrett Creeley } 2387b07833a0SBrett Creeley 2388b07833a0SBrett Creeley /** 2389d95276ceSAkeem G Abodunrin * ice_vsi_add_rem_eth_mac - Program VSI ethertype based filter with rule 2390d95276ceSAkeem G Abodunrin * @vsi: the VSI being configured 2391d95276ceSAkeem G Abodunrin * @add_rule: boolean value to add or remove ethertype filter rule 2392d95276ceSAkeem G Abodunrin */ 2393d95276ceSAkeem G Abodunrin static void 2394d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(struct ice_vsi *vsi, bool add_rule) 2395d95276ceSAkeem G Abodunrin { 2396d95276ceSAkeem G Abodunrin struct ice_fltr_list_entry *list; 2397d95276ceSAkeem G Abodunrin struct ice_pf *pf = vsi->back; 2398d95276ceSAkeem G Abodunrin LIST_HEAD(tmp_add_list); 2399d95276ceSAkeem G Abodunrin enum ice_status status; 2400d95276ceSAkeem G Abodunrin 2401d95276ceSAkeem G Abodunrin list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 2402d95276ceSAkeem G Abodunrin if (!list) 2403d95276ceSAkeem G Abodunrin return; 2404d95276ceSAkeem G Abodunrin 2405d95276ceSAkeem G Abodunrin list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 2406d95276ceSAkeem G Abodunrin list->fltr_info.fltr_act = ICE_DROP_PACKET; 2407d95276ceSAkeem G Abodunrin list->fltr_info.flag = ICE_FLTR_TX; 2408d95276ceSAkeem G Abodunrin list->fltr_info.src_id = ICE_SRC_ID_VSI; 2409d95276ceSAkeem G Abodunrin list->fltr_info.vsi_handle = vsi->idx; 2410d95276ceSAkeem G Abodunrin list->fltr_info.l_data.ethertype_mac.ethertype = vsi->ethtype; 2411d95276ceSAkeem G Abodunrin 2412d95276ceSAkeem G Abodunrin INIT_LIST_HEAD(&list->list_entry); 2413d95276ceSAkeem G Abodunrin list_add(&list->list_entry, &tmp_add_list); 2414d95276ceSAkeem G Abodunrin 2415d95276ceSAkeem G Abodunrin if (add_rule) 2416d95276ceSAkeem G Abodunrin status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 2417d95276ceSAkeem G Abodunrin else 2418d95276ceSAkeem G Abodunrin status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 2419d95276ceSAkeem G Abodunrin 2420d95276ceSAkeem G Abodunrin if (status) 2421d95276ceSAkeem G Abodunrin dev_err(&pf->pdev->dev, 2422d95276ceSAkeem G Abodunrin "Failure Adding or Removing Ethertype on VSI %i error: %d\n", 2423d95276ceSAkeem G Abodunrin vsi->vsi_num, status); 2424d95276ceSAkeem G Abodunrin 2425d95276ceSAkeem G Abodunrin ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 2426d95276ceSAkeem G Abodunrin } 2427d95276ceSAkeem G Abodunrin 24282e0e6228SDave Ertman /** 24292e0e6228SDave Ertman * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling 24302e0e6228SDave Ertman * @vsi: the VSI being configured 24312e0e6228SDave Ertman * @tx: bool to determine Tx or Rx rule 24322e0e6228SDave Ertman * @create: bool to determine create or remove Rule 24332e0e6228SDave Ertman */ 24342e0e6228SDave Ertman void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create) 24352e0e6228SDave Ertman { 24362e0e6228SDave Ertman struct ice_fltr_list_entry *list; 24372e0e6228SDave Ertman struct ice_pf *pf = vsi->back; 24382e0e6228SDave Ertman LIST_HEAD(tmp_add_list); 24392e0e6228SDave Ertman enum ice_status status; 24402e0e6228SDave Ertman 24412e0e6228SDave Ertman list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 24422e0e6228SDave Ertman if (!list) 24432e0e6228SDave Ertman return; 24442e0e6228SDave Ertman 24452e0e6228SDave Ertman list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 24462e0e6228SDave Ertman list->fltr_info.vsi_handle = vsi->idx; 24473aea1736SJeff Kirsher list->fltr_info.l_data.ethertype_mac.ethertype = ETH_P_LLDP; 24482e0e6228SDave Ertman 24492e0e6228SDave Ertman if (tx) { 24502e0e6228SDave Ertman list->fltr_info.fltr_act = ICE_DROP_PACKET; 24512e0e6228SDave Ertman list->fltr_info.flag = ICE_FLTR_TX; 24522e0e6228SDave Ertman list->fltr_info.src_id = ICE_SRC_ID_VSI; 24532e0e6228SDave Ertman } else { 24542e0e6228SDave Ertman list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 24552e0e6228SDave Ertman list->fltr_info.flag = ICE_FLTR_RX; 24562e0e6228SDave Ertman list->fltr_info.src_id = ICE_SRC_ID_LPORT; 24572e0e6228SDave Ertman } 24582e0e6228SDave Ertman 24592e0e6228SDave Ertman INIT_LIST_HEAD(&list->list_entry); 24602e0e6228SDave Ertman list_add(&list->list_entry, &tmp_add_list); 24612e0e6228SDave Ertman 24622e0e6228SDave Ertman if (create) 24632e0e6228SDave Ertman status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 24642e0e6228SDave Ertman else 24652e0e6228SDave Ertman status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 24662e0e6228SDave Ertman 24672e0e6228SDave Ertman if (status) 24682e0e6228SDave Ertman dev_err(&pf->pdev->dev, 24692e0e6228SDave Ertman "Fail %s %s LLDP rule on VSI %i error: %d\n", 24702e0e6228SDave Ertman create ? "adding" : "removing", tx ? "TX" : "RX", 24712e0e6228SDave Ertman vsi->vsi_num, status); 24722e0e6228SDave Ertman 24732e0e6228SDave Ertman ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 24742e0e6228SDave Ertman } 24752e0e6228SDave Ertman 2476d95276ceSAkeem G Abodunrin /** 247737bb8390SAnirudh Venkataramanan * ice_vsi_setup - Set up a VSI by a given type 247837bb8390SAnirudh Venkataramanan * @pf: board private structure 247937bb8390SAnirudh Venkataramanan * @pi: pointer to the port_info instance 248037bb8390SAnirudh Venkataramanan * @type: VSI type 2481f9867df6SAnirudh Venkataramanan * @vf_id: defines VF ID to which this VSI connects. This field is meant to be 248237bb8390SAnirudh Venkataramanan * used only for ICE_VSI_VF VSI type. For other VSI types, should 248337bb8390SAnirudh Venkataramanan * fill-in ICE_INVAL_VFID as input. 248437bb8390SAnirudh Venkataramanan * 248537bb8390SAnirudh Venkataramanan * This allocates the sw VSI structure and its queue resources. 248637bb8390SAnirudh Venkataramanan * 248737bb8390SAnirudh Venkataramanan * Returns pointer to the successfully allocated and configured VSI sw struct on 248837bb8390SAnirudh Venkataramanan * success, NULL on failure. 248937bb8390SAnirudh Venkataramanan */ 249037bb8390SAnirudh Venkataramanan struct ice_vsi * 249137bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, 24928ede0178SAnirudh Venkataramanan enum ice_vsi_type type, u16 vf_id) 249337bb8390SAnirudh Venkataramanan { 249437bb8390SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 249537bb8390SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 2496d31530e8SAkeem G Abodunrin enum ice_status status; 249737bb8390SAnirudh Venkataramanan struct ice_vsi *vsi; 249837bb8390SAnirudh Venkataramanan int ret, i; 249937bb8390SAnirudh Venkataramanan 25005743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 25015743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, vf_id); 25025743020dSAkeem G Abodunrin else 25035743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, ICE_INVAL_VFID); 25045743020dSAkeem G Abodunrin 250537bb8390SAnirudh Venkataramanan if (!vsi) { 250637bb8390SAnirudh Venkataramanan dev_err(dev, "could not allocate VSI\n"); 250737bb8390SAnirudh Venkataramanan return NULL; 250837bb8390SAnirudh Venkataramanan } 250937bb8390SAnirudh Venkataramanan 251037bb8390SAnirudh Venkataramanan vsi->port_info = pi; 251137bb8390SAnirudh Venkataramanan vsi->vsw = pf->first_sw; 2512d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 2513d95276ceSAkeem G Abodunrin vsi->ethtype = ETH_P_PAUSE; 2514d95276ceSAkeem G Abodunrin 25158ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 25168ede0178SAnirudh Venkataramanan vsi->vf_id = vf_id; 251737bb8390SAnirudh Venkataramanan 251837bb8390SAnirudh Venkataramanan if (ice_vsi_get_qs(vsi)) { 251937bb8390SAnirudh Venkataramanan dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", 252037bb8390SAnirudh Venkataramanan vsi->idx); 252137bb8390SAnirudh Venkataramanan goto unroll_get_qs; 252237bb8390SAnirudh Venkataramanan } 252337bb8390SAnirudh Venkataramanan 252437bb8390SAnirudh Venkataramanan /* set RSS capabilities */ 252537bb8390SAnirudh Venkataramanan ice_vsi_set_rss_params(vsi); 252637bb8390SAnirudh Venkataramanan 2527f9867df6SAnirudh Venkataramanan /* set TC configuration */ 2528c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2529c5a2a4a3SUsha Ketineni 253037bb8390SAnirudh Venkataramanan /* create the VSI */ 253137bb8390SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 253237bb8390SAnirudh Venkataramanan if (ret) 253337bb8390SAnirudh Venkataramanan goto unroll_get_qs; 253437bb8390SAnirudh Venkataramanan 253537bb8390SAnirudh Venkataramanan switch (vsi->type) { 253637bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 253737bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 253837bb8390SAnirudh Venkataramanan if (ret) 253937bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 254037bb8390SAnirudh Venkataramanan 254137bb8390SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 254237bb8390SAnirudh Venkataramanan if (ret) 254337bb8390SAnirudh Venkataramanan goto unroll_alloc_q_vector; 254437bb8390SAnirudh Venkataramanan 2545b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2546b07833a0SBrett Creeley if (ret) 2547b07833a0SBrett Creeley goto unroll_vector_base; 2548b07833a0SBrett Creeley 254937bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 255037bb8390SAnirudh Venkataramanan if (ret) 255137bb8390SAnirudh Venkataramanan goto unroll_vector_base; 255237bb8390SAnirudh Venkataramanan 255337bb8390SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 255437bb8390SAnirudh Venkataramanan 255537bb8390SAnirudh Venkataramanan /* Do not exit if configuring RSS had an issue, at least 255637bb8390SAnirudh Venkataramanan * receive traffic on first queue. Hence no need to capture 255737bb8390SAnirudh Venkataramanan * return value 255837bb8390SAnirudh Venkataramanan */ 255937bb8390SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 256037bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_lut_key(vsi); 256137bb8390SAnirudh Venkataramanan break; 25628ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 25638ede0178SAnirudh Venkataramanan /* VF driver will take care of creating netdev for this type and 25648ede0178SAnirudh Venkataramanan * map queues to vectors through Virtchnl, PF driver only 25658ede0178SAnirudh Venkataramanan * creates a VSI and corresponding structures for bookkeeping 25668ede0178SAnirudh Venkataramanan * purpose 25678ede0178SAnirudh Venkataramanan */ 25688ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 25698ede0178SAnirudh Venkataramanan if (ret) 25708ede0178SAnirudh Venkataramanan goto unroll_vsi_init; 25718ede0178SAnirudh Venkataramanan 25728ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 25738ede0178SAnirudh Venkataramanan if (ret) 25748ede0178SAnirudh Venkataramanan goto unroll_alloc_q_vector; 25758ede0178SAnirudh Venkataramanan 2576b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2577b07833a0SBrett Creeley if (ret) 2578b07833a0SBrett Creeley goto unroll_vector_base; 2579b07833a0SBrett Creeley 25808ede0178SAnirudh Venkataramanan pf->q_left_tx -= vsi->alloc_txq; 25818ede0178SAnirudh Venkataramanan pf->q_left_rx -= vsi->alloc_rxq; 25823a9e32bbSMd Fahad Iqbal Polash 25833a9e32bbSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 25843a9e32bbSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 25853a9e32bbSMd Fahad Iqbal Polash * return value 25863a9e32bbSMd Fahad Iqbal Polash */ 25873a9e32bbSMd Fahad Iqbal Polash if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 25883a9e32bbSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 25898ede0178SAnirudh Venkataramanan break; 25900e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 25910e674aebSAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 25920e674aebSAnirudh Venkataramanan if (ret) 25930e674aebSAnirudh Venkataramanan goto unroll_vsi_init; 25940e674aebSAnirudh Venkataramanan break; 259537bb8390SAnirudh Venkataramanan default: 2596df17b7e0SAnirudh Venkataramanan /* clean up the resources and exit */ 259737bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 259837bb8390SAnirudh Venkataramanan } 259937bb8390SAnirudh Venkataramanan 260037bb8390SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 260137bb8390SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2602d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 260337bb8390SAnirudh Venkataramanan 2604d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 26054fb33f31SAnirudh Venkataramanan max_txqs); 2606d31530e8SAkeem G Abodunrin if (status) { 260720ce2a1aSBrett Creeley dev_err(&pf->pdev->dev, 260820ce2a1aSBrett Creeley "VSI %d failed lan queue config, error %d\n", 2609d31530e8SAkeem G Abodunrin vsi->vsi_num, status); 261037bb8390SAnirudh Venkataramanan goto unroll_vector_base; 261137bb8390SAnirudh Venkataramanan } 261237bb8390SAnirudh Venkataramanan 2613d95276ceSAkeem G Abodunrin /* Add switch rule to drop all Tx Flow Control Frames, of look up 2614d95276ceSAkeem G Abodunrin * type ETHERTYPE from VSIs, and restrict malicious VF from sending 2615d95276ceSAkeem G Abodunrin * out PAUSE or PFC frames. If enabled, FW can still send FC frames. 2616d95276ceSAkeem G Abodunrin * The rule is added once for PF VSI in order to create appropriate 2617d95276ceSAkeem G Abodunrin * recipe, since VSI/VSI list is ignored with drop action... 26182e0e6228SDave Ertman * Also add rules to handle LLDP Tx and Rx packets. Tx LLDP packets 26192e0e6228SDave Ertman * need to be dropped so that VFs cannot send LLDP packets to reconfig 26202f2da36eSAnirudh Venkataramanan * DCB settings in the HW. Also, if the FW DCBX engine is not running 26212e0e6228SDave Ertman * then Rx LLDP packets need to be redirected up the stack. 2622d95276ceSAkeem G Abodunrin */ 26232e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 2624d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, true); 2625d95276ceSAkeem G Abodunrin 26262e0e6228SDave Ertman /* Tx LLDP packets */ 26272e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, true); 26282e0e6228SDave Ertman 26292e0e6228SDave Ertman /* Rx LLDP packets */ 263084a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) 26312e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, true); 26322e0e6228SDave Ertman } 26332e0e6228SDave Ertman 263437bb8390SAnirudh Venkataramanan return vsi; 263537bb8390SAnirudh Venkataramanan 263637bb8390SAnirudh Venkataramanan unroll_vector_base: 2637eb0208ecSPreethi Banala /* reclaim SW interrupts back to the common pool */ 2638cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 2639eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 264037bb8390SAnirudh Venkataramanan unroll_alloc_q_vector: 264137bb8390SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 264237bb8390SAnirudh Venkataramanan unroll_vsi_init: 264337bb8390SAnirudh Venkataramanan ice_vsi_delete(vsi); 264437bb8390SAnirudh Venkataramanan unroll_get_qs: 264537bb8390SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 264637bb8390SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 264737bb8390SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 264837bb8390SAnirudh Venkataramanan ice_vsi_clear(vsi); 264937bb8390SAnirudh Venkataramanan 265037bb8390SAnirudh Venkataramanan return NULL; 265137bb8390SAnirudh Venkataramanan } 265237bb8390SAnirudh Venkataramanan 265337bb8390SAnirudh Venkataramanan /** 26545153a18eSAnirudh Venkataramanan * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW 26555153a18eSAnirudh Venkataramanan * @vsi: the VSI being cleaned up 26565153a18eSAnirudh Venkataramanan */ 26575153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi) 26585153a18eSAnirudh Venkataramanan { 26595153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 26605153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 26615153a18eSAnirudh Venkataramanan u32 txq = 0; 26625153a18eSAnirudh Venkataramanan u32 rxq = 0; 26635153a18eSAnirudh Venkataramanan int i, q; 26645153a18eSAnirudh Venkataramanan 2665cbe66bfeSBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 26665153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2667cbe66bfeSBrett Creeley u16 reg_idx = q_vector->reg_idx; 26685153a18eSAnirudh Venkataramanan 2669cbe66bfeSBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0); 2670cbe66bfeSBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0); 26715153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 26725153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); 26735153a18eSAnirudh Venkataramanan txq++; 26745153a18eSAnirudh Venkataramanan } 26755153a18eSAnirudh Venkataramanan 26765153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 26775153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0); 26785153a18eSAnirudh Venkataramanan rxq++; 26795153a18eSAnirudh Venkataramanan } 26805153a18eSAnirudh Venkataramanan } 26815153a18eSAnirudh Venkataramanan 26825153a18eSAnirudh Venkataramanan ice_flush(hw); 26835153a18eSAnirudh Venkataramanan } 26845153a18eSAnirudh Venkataramanan 26855153a18eSAnirudh Venkataramanan /** 26865153a18eSAnirudh Venkataramanan * ice_vsi_free_irq - Free the IRQ association with the OS 26875153a18eSAnirudh Venkataramanan * @vsi: the VSI being configured 26885153a18eSAnirudh Venkataramanan */ 26895153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi) 26905153a18eSAnirudh Venkataramanan { 26915153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2692cbe66bfeSBrett Creeley int base = vsi->base_vector; 26935153a18eSAnirudh Venkataramanan int i; 26945153a18eSAnirudh Venkataramanan 26955153a18eSAnirudh Venkataramanan if (!vsi->q_vectors || !vsi->irqs_ready) 26965153a18eSAnirudh Venkataramanan return; 26975153a18eSAnirudh Venkataramanan 2698eb0208ecSPreethi Banala ice_vsi_release_msix(vsi); 26998ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 27008ede0178SAnirudh Venkataramanan return; 2701eb0208ecSPreethi Banala 27025153a18eSAnirudh Venkataramanan vsi->irqs_ready = false; 27030c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) { 27045153a18eSAnirudh Venkataramanan u16 vector = i + base; 27055153a18eSAnirudh Venkataramanan int irq_num; 27065153a18eSAnirudh Venkataramanan 27075153a18eSAnirudh Venkataramanan irq_num = pf->msix_entries[vector].vector; 27085153a18eSAnirudh Venkataramanan 27095153a18eSAnirudh Venkataramanan /* free only the irqs that were actually requested */ 27105153a18eSAnirudh Venkataramanan if (!vsi->q_vectors[i] || 27115153a18eSAnirudh Venkataramanan !(vsi->q_vectors[i]->num_ring_tx || 27125153a18eSAnirudh Venkataramanan vsi->q_vectors[i]->num_ring_rx)) 27135153a18eSAnirudh Venkataramanan continue; 27145153a18eSAnirudh Venkataramanan 27155153a18eSAnirudh Venkataramanan /* clear the affinity notifier in the IRQ descriptor */ 27165153a18eSAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 27175153a18eSAnirudh Venkataramanan 27185153a18eSAnirudh Venkataramanan /* clear the affinity_mask in the IRQ descriptor */ 27195153a18eSAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 27205153a18eSAnirudh Venkataramanan synchronize_irq(irq_num); 27215153a18eSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, 27225153a18eSAnirudh Venkataramanan vsi->q_vectors[i]); 27235153a18eSAnirudh Venkataramanan } 27245153a18eSAnirudh Venkataramanan } 27255153a18eSAnirudh Venkataramanan 27265153a18eSAnirudh Venkataramanan /** 27275153a18eSAnirudh Venkataramanan * ice_vsi_free_tx_rings - Free Tx resources for VSI queues 27285153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 27295153a18eSAnirudh Venkataramanan */ 27305153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi) 27315153a18eSAnirudh Venkataramanan { 27325153a18eSAnirudh Venkataramanan int i; 27335153a18eSAnirudh Venkataramanan 27345153a18eSAnirudh Venkataramanan if (!vsi->tx_rings) 27355153a18eSAnirudh Venkataramanan return; 27365153a18eSAnirudh Venkataramanan 27375153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) 27385153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 27395153a18eSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 27405153a18eSAnirudh Venkataramanan } 27415153a18eSAnirudh Venkataramanan 27425153a18eSAnirudh Venkataramanan /** 27435153a18eSAnirudh Venkataramanan * ice_vsi_free_rx_rings - Free Rx resources for VSI queues 27445153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 27455153a18eSAnirudh Venkataramanan */ 27465153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi) 27475153a18eSAnirudh Venkataramanan { 27485153a18eSAnirudh Venkataramanan int i; 27495153a18eSAnirudh Venkataramanan 27505153a18eSAnirudh Venkataramanan if (!vsi->rx_rings) 27515153a18eSAnirudh Venkataramanan return; 27525153a18eSAnirudh Venkataramanan 27535153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 27545153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) 27555153a18eSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 27565153a18eSAnirudh Venkataramanan } 27575153a18eSAnirudh Venkataramanan 27585153a18eSAnirudh Venkataramanan /** 275907309a0eSAnirudh Venkataramanan * ice_vsi_close - Shut down a VSI 276007309a0eSAnirudh Venkataramanan * @vsi: the VSI being shut down 276107309a0eSAnirudh Venkataramanan */ 276207309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi) 276307309a0eSAnirudh Venkataramanan { 276407309a0eSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) 276507309a0eSAnirudh Venkataramanan ice_down(vsi); 276607309a0eSAnirudh Venkataramanan 276707309a0eSAnirudh Venkataramanan ice_vsi_free_irq(vsi); 276807309a0eSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 276907309a0eSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 277007309a0eSAnirudh Venkataramanan } 277107309a0eSAnirudh Venkataramanan 277207309a0eSAnirudh Venkataramanan /** 27735153a18eSAnirudh Venkataramanan * ice_free_res - free a block of resources 27745153a18eSAnirudh Venkataramanan * @res: pointer to the resource 27755153a18eSAnirudh Venkataramanan * @index: starting index previously returned by ice_get_res 27765153a18eSAnirudh Venkataramanan * @id: identifier to track owner 27775153a18eSAnirudh Venkataramanan * 27785153a18eSAnirudh Venkataramanan * Returns number of resources freed 27795153a18eSAnirudh Venkataramanan */ 27805153a18eSAnirudh Venkataramanan int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) 27815153a18eSAnirudh Venkataramanan { 27825153a18eSAnirudh Venkataramanan int count = 0; 27835153a18eSAnirudh Venkataramanan int i; 27845153a18eSAnirudh Venkataramanan 2785cbe66bfeSBrett Creeley if (!res || index >= res->end) 27865153a18eSAnirudh Venkataramanan return -EINVAL; 27875153a18eSAnirudh Venkataramanan 27885153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 2789cbe66bfeSBrett Creeley for (i = index; i < res->end && res->list[i] == id; i++) { 27905153a18eSAnirudh Venkataramanan res->list[i] = 0; 27915153a18eSAnirudh Venkataramanan count++; 27925153a18eSAnirudh Venkataramanan } 27935153a18eSAnirudh Venkataramanan 27945153a18eSAnirudh Venkataramanan return count; 27955153a18eSAnirudh Venkataramanan } 27965153a18eSAnirudh Venkataramanan 27975153a18eSAnirudh Venkataramanan /** 27985153a18eSAnirudh Venkataramanan * ice_search_res - Search the tracker for a block of resources 27995153a18eSAnirudh Venkataramanan * @res: pointer to the resource 28005153a18eSAnirudh Venkataramanan * @needed: size of the block needed 28015153a18eSAnirudh Venkataramanan * @id: identifier to track owner 28025153a18eSAnirudh Venkataramanan * 28035153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 28045153a18eSAnirudh Venkataramanan */ 28055153a18eSAnirudh Venkataramanan static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) 28065153a18eSAnirudh Venkataramanan { 2807cbe66bfeSBrett Creeley int start = 0, end = 0; 28085153a18eSAnirudh Venkataramanan 2809cbe66bfeSBrett Creeley if (needed > res->end) 2810eb0208ecSPreethi Banala return -ENOMEM; 2811eb0208ecSPreethi Banala 28125153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 28135153a18eSAnirudh Venkataramanan 28145153a18eSAnirudh Venkataramanan do { 28155153a18eSAnirudh Venkataramanan /* skip already allocated entries */ 28165153a18eSAnirudh Venkataramanan if (res->list[end++] & ICE_RES_VALID_BIT) { 28175153a18eSAnirudh Venkataramanan start = end; 2818cbe66bfeSBrett Creeley if ((start + needed) > res->end) 28195153a18eSAnirudh Venkataramanan break; 28205153a18eSAnirudh Venkataramanan } 28215153a18eSAnirudh Venkataramanan 28225153a18eSAnirudh Venkataramanan if (end == (start + needed)) { 28235153a18eSAnirudh Venkataramanan int i = start; 28245153a18eSAnirudh Venkataramanan 28255153a18eSAnirudh Venkataramanan /* there was enough, so assign it to the requestor */ 28265153a18eSAnirudh Venkataramanan while (i != end) 28275153a18eSAnirudh Venkataramanan res->list[i++] = id; 28285153a18eSAnirudh Venkataramanan 28295153a18eSAnirudh Venkataramanan return start; 28305153a18eSAnirudh Venkataramanan } 2831cbe66bfeSBrett Creeley } while (end < res->end); 28325153a18eSAnirudh Venkataramanan 28335153a18eSAnirudh Venkataramanan return -ENOMEM; 28345153a18eSAnirudh Venkataramanan } 28355153a18eSAnirudh Venkataramanan 28365153a18eSAnirudh Venkataramanan /** 28375153a18eSAnirudh Venkataramanan * ice_get_res - get a block of resources 28385153a18eSAnirudh Venkataramanan * @pf: board private structure 28395153a18eSAnirudh Venkataramanan * @res: pointer to the resource 28405153a18eSAnirudh Venkataramanan * @needed: size of the block needed 28415153a18eSAnirudh Venkataramanan * @id: identifier to track owner 28425153a18eSAnirudh Venkataramanan * 2843cbe66bfeSBrett Creeley * Returns the base item index of the block, or negative for error 28445153a18eSAnirudh Venkataramanan */ 28455153a18eSAnirudh Venkataramanan int 28465153a18eSAnirudh Venkataramanan ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) 28475153a18eSAnirudh Venkataramanan { 28485153a18eSAnirudh Venkataramanan if (!res || !pf) 28495153a18eSAnirudh Venkataramanan return -EINVAL; 28505153a18eSAnirudh Venkataramanan 28515153a18eSAnirudh Venkataramanan if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { 28525153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 28535153a18eSAnirudh Venkataramanan "param err: needed=%d, num_entries = %d id=0x%04x\n", 28545153a18eSAnirudh Venkataramanan needed, res->num_entries, id); 28555153a18eSAnirudh Venkataramanan return -EINVAL; 28565153a18eSAnirudh Venkataramanan } 28575153a18eSAnirudh Venkataramanan 2858cbe66bfeSBrett Creeley return ice_search_res(res, needed, id); 28595153a18eSAnirudh Venkataramanan } 28605153a18eSAnirudh Venkataramanan 28615153a18eSAnirudh Venkataramanan /** 28625153a18eSAnirudh Venkataramanan * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI 28635153a18eSAnirudh Venkataramanan * @vsi: the VSI being un-configured 28645153a18eSAnirudh Venkataramanan */ 28655153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi) 28665153a18eSAnirudh Venkataramanan { 2867cbe66bfeSBrett Creeley int base = vsi->base_vector; 28685153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 28695153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 28705153a18eSAnirudh Venkataramanan u32 val; 28715153a18eSAnirudh Venkataramanan int i; 28725153a18eSAnirudh Venkataramanan 28735153a18eSAnirudh Venkataramanan /* disable interrupt causation from each queue */ 28745153a18eSAnirudh Venkataramanan if (vsi->tx_rings) { 28755153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 28765153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i]) { 28775153a18eSAnirudh Venkataramanan u16 reg; 28785153a18eSAnirudh Venkataramanan 28795153a18eSAnirudh Venkataramanan reg = vsi->tx_rings[i]->reg_idx; 28805153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(reg)); 28815153a18eSAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 28825153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(reg), val); 28835153a18eSAnirudh Venkataramanan } 28845153a18eSAnirudh Venkataramanan } 28855153a18eSAnirudh Venkataramanan } 28865153a18eSAnirudh Venkataramanan 28875153a18eSAnirudh Venkataramanan if (vsi->rx_rings) { 28885153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 28895153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i]) { 28905153a18eSAnirudh Venkataramanan u16 reg; 28915153a18eSAnirudh Venkataramanan 28925153a18eSAnirudh Venkataramanan reg = vsi->rx_rings[i]->reg_idx; 28935153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_RQCTL(reg)); 28945153a18eSAnirudh Venkataramanan val &= ~QINT_RQCTL_CAUSE_ENA_M; 28955153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(reg), val); 28965153a18eSAnirudh Venkataramanan } 28975153a18eSAnirudh Venkataramanan } 28985153a18eSAnirudh Venkataramanan } 28995153a18eSAnirudh Venkataramanan 29005153a18eSAnirudh Venkataramanan /* disable each interrupt */ 2901b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) 2902b07833a0SBrett Creeley wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); 29035153a18eSAnirudh Venkataramanan 29045153a18eSAnirudh Venkataramanan ice_flush(hw); 2905b07833a0SBrett Creeley 2906da4a9e73SBrett Creeley /* don't call synchronize_irq() for VF's from the host */ 2907da4a9e73SBrett Creeley if (vsi->type == ICE_VSI_VF) 2908da4a9e73SBrett Creeley return; 2909da4a9e73SBrett Creeley 29100c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) 29115153a18eSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[i + base].vector); 29125153a18eSAnirudh Venkataramanan } 29135153a18eSAnirudh Venkataramanan 29145153a18eSAnirudh Venkataramanan /** 2915561f4379STony Nguyen * ice_napi_del - Remove NAPI handler for the VSI 2916561f4379STony Nguyen * @vsi: VSI for which NAPI handler is to be removed 2917561f4379STony Nguyen */ 2918561f4379STony Nguyen void ice_napi_del(struct ice_vsi *vsi) 2919561f4379STony Nguyen { 2920561f4379STony Nguyen int v_idx; 2921561f4379STony Nguyen 2922561f4379STony Nguyen if (!vsi->netdev) 2923561f4379STony Nguyen return; 2924561f4379STony Nguyen 2925561f4379STony Nguyen ice_for_each_q_vector(vsi, v_idx) 2926561f4379STony Nguyen netif_napi_del(&vsi->q_vectors[v_idx]->napi); 2927561f4379STony Nguyen } 2928561f4379STony Nguyen 2929561f4379STony Nguyen /** 2930df0f8479SAnirudh Venkataramanan * ice_vsi_release - Delete a VSI and free its resources 2931df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 2932df0f8479SAnirudh Venkataramanan * 2933df0f8479SAnirudh Venkataramanan * Returns 0 on success or < 0 on error 2934df0f8479SAnirudh Venkataramanan */ 2935df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi) 2936df0f8479SAnirudh Venkataramanan { 2937df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 2938df0f8479SAnirudh Venkataramanan 2939df0f8479SAnirudh Venkataramanan if (!vsi->back) 2940df0f8479SAnirudh Venkataramanan return -ENODEV; 2941df0f8479SAnirudh Venkataramanan pf = vsi->back; 2942b751930cSBrett Creeley 2943aa6ccf3fSBrett Creeley /* do not unregister while driver is in the reset recovery pending 2944aa6ccf3fSBrett Creeley * state. Since reset/rebuild happens through PF service task workqueue, 2945aa6ccf3fSBrett Creeley * it's not a good idea to unregister netdev that is associated to the 2946aa6ccf3fSBrett Creeley * PF that is running the work queue items currently. This is done to 2947aa6ccf3fSBrett Creeley * avoid check_flush_dependency() warning on this wq 2948df0f8479SAnirudh Venkataramanan */ 2949aa6ccf3fSBrett Creeley if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) 2950df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2951df0f8479SAnirudh Venkataramanan 2952df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 2953df0f8479SAnirudh Venkataramanan ice_rss_clean(vsi); 2954df0f8479SAnirudh Venkataramanan 2955df0f8479SAnirudh Venkataramanan /* Disable VSI and free resources */ 29560e674aebSAnirudh Venkataramanan if (vsi->type != ICE_VSI_LB) 2957df0f8479SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 2958df0f8479SAnirudh Venkataramanan ice_vsi_close(vsi); 2959df0f8479SAnirudh Venkataramanan 2960cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 2961cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 2962cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 2963cbe66bfeSBrett Creeley * cleared in the same manner. 2964cbe66bfeSBrett Creeley */ 29658ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 29668ede0178SAnirudh Venkataramanan /* reclaim SW interrupts back to the common pool */ 2967cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 2968eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 29698ede0178SAnirudh Venkataramanan } 2970df0f8479SAnirudh Venkataramanan 29712e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 2972d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, false); 29732e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, false); 29742e0e6228SDave Ertman /* The Rx rule will only exist to remove if the LLDP FW 29752e0e6228SDave Ertman * engine is currently stopped 29762e0e6228SDave Ertman */ 297784a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) 29782e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, false); 29792e0e6228SDave Ertman } 2980d95276ceSAkeem G Abodunrin 29815726ca0eSAnirudh Venkataramanan ice_remove_vsi_fltr(&pf->hw, vsi->idx); 298210e03a22SAnirudh Venkataramanan ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2983df0f8479SAnirudh Venkataramanan ice_vsi_delete(vsi); 2984df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2985aa6ccf3fSBrett Creeley 2986aa6ccf3fSBrett Creeley /* make sure unregister_netdev() was called by checking __ICE_DOWN */ 2987aa6ccf3fSBrett Creeley if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) { 2988aa6ccf3fSBrett Creeley free_netdev(vsi->netdev); 2989aa6ccf3fSBrett Creeley vsi->netdev = NULL; 2990aa6ccf3fSBrett Creeley } 2991aa6ccf3fSBrett Creeley 2992df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2993df0f8479SAnirudh Venkataramanan 2994df0f8479SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2995df0f8479SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 2996df0f8479SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 2997df0f8479SAnirudh Venkataramanan 2998df0f8479SAnirudh Venkataramanan /* retain SW VSI data structure since it is needed to unregister and 2999df0f8479SAnirudh Venkataramanan * free VSI netdev when PF is not in reset recovery pending state,\ 3000df0f8479SAnirudh Venkataramanan * for ex: during rmmod. 3001df0f8479SAnirudh Venkataramanan */ 30025df7e45dSDave Ertman if (!ice_is_reset_in_progress(pf->state)) 3003df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 3004df0f8479SAnirudh Venkataramanan 3005df0f8479SAnirudh Venkataramanan return 0; 3006df0f8479SAnirudh Venkataramanan } 3007df0f8479SAnirudh Venkataramanan 3008df0f8479SAnirudh Venkataramanan /** 3009df0f8479SAnirudh Venkataramanan * ice_vsi_rebuild - Rebuild VSI after reset 3010df0f8479SAnirudh Venkataramanan * @vsi: VSI to be rebuild 3011df0f8479SAnirudh Venkataramanan * 3012df0f8479SAnirudh Venkataramanan * Returns 0 on success and negative value on failure 3013df0f8479SAnirudh Venkataramanan */ 3014df0f8479SAnirudh Venkataramanan int ice_vsi_rebuild(struct ice_vsi *vsi) 3015df0f8479SAnirudh Venkataramanan { 3016df0f8479SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 30177eeac889SAkeem G Abodunrin struct ice_vf *vf = NULL; 3018d31530e8SAkeem G Abodunrin enum ice_status status; 3019c5a2a4a3SUsha Ketineni struct ice_pf *pf; 3020df0f8479SAnirudh Venkataramanan int ret, i; 3021df0f8479SAnirudh Venkataramanan 3022df0f8479SAnirudh Venkataramanan if (!vsi) 3023df0f8479SAnirudh Venkataramanan return -EINVAL; 3024df0f8479SAnirudh Venkataramanan 3025c5a2a4a3SUsha Ketineni pf = vsi->back; 30267eeac889SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 30277eeac889SAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 30287eeac889SAkeem G Abodunrin 302947e3e53cSHenry Tieman ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 3030df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 30317eeac889SAkeem G Abodunrin 3032cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 3033cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 3034cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 3035cbe66bfeSBrett Creeley * cleared in the same manner. 3036cbe66bfeSBrett Creeley */ 30377eeac889SAkeem G Abodunrin if (vsi->type != ICE_VSI_VF) { 30387eeac889SAkeem G Abodunrin /* reclaim SW interrupts back to the common pool */ 3039cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 30407eeac889SAkeem G Abodunrin pf->num_avail_sw_msix += vsi->num_q_vectors; 3041cbe66bfeSBrett Creeley vsi->base_vector = 0; 30427eeac889SAkeem G Abodunrin } 30437eeac889SAkeem G Abodunrin 304478b5713aSAnirudh Venkataramanan ice_vsi_put_qs(vsi); 3045df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 3046a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 3047819d8998SJesse Brandeburg ice_dev_onetime_setup(&pf->hw); 30485743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 30495743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf->vf_id); 30505743020dSAkeem G Abodunrin else 30515743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 305278b5713aSAnirudh Venkataramanan 305378b5713aSAnirudh Venkataramanan ret = ice_vsi_alloc_arrays(vsi); 305478b5713aSAnirudh Venkataramanan if (ret < 0) 305578b5713aSAnirudh Venkataramanan goto err_vsi; 305678b5713aSAnirudh Venkataramanan 305778b5713aSAnirudh Venkataramanan ice_vsi_get_qs(vsi); 3058c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 3059df0f8479SAnirudh Venkataramanan 3060df0f8479SAnirudh Venkataramanan /* Initialize VSI struct elements and create VSI in FW */ 3061df0f8479SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 3062df0f8479SAnirudh Venkataramanan if (ret < 0) 3063df0f8479SAnirudh Venkataramanan goto err_vsi; 3064df0f8479SAnirudh Venkataramanan 3065df0f8479SAnirudh Venkataramanan 3066df0f8479SAnirudh Venkataramanan switch (vsi->type) { 3067df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 3068df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 3069df0f8479SAnirudh Venkataramanan if (ret) 3070df0f8479SAnirudh Venkataramanan goto err_rings; 3071df0f8479SAnirudh Venkataramanan 307217bc6d07STony Nguyen ret = ice_vsi_setup_vector_base(vsi); 307317bc6d07STony Nguyen if (ret) 307417bc6d07STony Nguyen goto err_vectors; 307517bc6d07STony Nguyen 3076b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 3077b07833a0SBrett Creeley if (ret) 3078b07833a0SBrett Creeley goto err_vectors; 3079b07833a0SBrett Creeley 3080df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 3081df0f8479SAnirudh Venkataramanan if (ret) 3082df0f8479SAnirudh Venkataramanan goto err_vectors; 3083df0f8479SAnirudh Venkataramanan 3084df0f8479SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 308527a98affSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 308627a98affSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 308727a98affSMd Fahad Iqbal Polash * return value 308827a98affSMd Fahad Iqbal Polash */ 3089819d8998SJesse Brandeburg if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 309027a98affSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 3091df0f8479SAnirudh Venkataramanan break; 30928ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 30938ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 30948ede0178SAnirudh Venkataramanan if (ret) 30958ede0178SAnirudh Venkataramanan goto err_rings; 30968ede0178SAnirudh Venkataramanan 3097b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 3098b07833a0SBrett Creeley if (ret) 3099b07833a0SBrett Creeley goto err_vectors; 3100b07833a0SBrett Creeley 31018ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 31028ede0178SAnirudh Venkataramanan if (ret) 31038ede0178SAnirudh Venkataramanan goto err_vectors; 31048ede0178SAnirudh Venkataramanan 3105819d8998SJesse Brandeburg pf->q_left_tx -= vsi->alloc_txq; 3106819d8998SJesse Brandeburg pf->q_left_rx -= vsi->alloc_rxq; 31078ede0178SAnirudh Venkataramanan break; 3108df0f8479SAnirudh Venkataramanan default: 3109df0f8479SAnirudh Venkataramanan break; 3110df0f8479SAnirudh Venkataramanan } 3111df0f8479SAnirudh Venkataramanan 3112df0f8479SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 3113df0f8479SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 3114d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 3115df0f8479SAnirudh Venkataramanan 3116d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 31174fb33f31SAnirudh Venkataramanan max_txqs); 3118d31530e8SAkeem G Abodunrin if (status) { 311920ce2a1aSBrett Creeley dev_err(&pf->pdev->dev, 312020ce2a1aSBrett Creeley "VSI %d failed lan queue config, error %d\n", 3121d31530e8SAkeem G Abodunrin vsi->vsi_num, status); 3122df0f8479SAnirudh Venkataramanan goto err_vectors; 3123df0f8479SAnirudh Venkataramanan } 3124df0f8479SAnirudh Venkataramanan return 0; 3125df0f8479SAnirudh Venkataramanan 3126df0f8479SAnirudh Venkataramanan err_vectors: 3127df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 3128df0f8479SAnirudh Venkataramanan err_rings: 3129df0f8479SAnirudh Venkataramanan if (vsi->netdev) { 3130df0f8479SAnirudh Venkataramanan vsi->current_netdev_flags = 0; 3131df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 3132df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 3133df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 3134df0f8479SAnirudh Venkataramanan } 3135df0f8479SAnirudh Venkataramanan err_vsi: 3136df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 3137819d8998SJesse Brandeburg set_bit(__ICE_RESET_FAILED, pf->state); 3138df0f8479SAnirudh Venkataramanan return ret; 3139df0f8479SAnirudh Venkataramanan } 3140df0f8479SAnirudh Venkataramanan 3141df0f8479SAnirudh Venkataramanan /** 31425df7e45dSDave Ertman * ice_is_reset_in_progress - check for a reset in progress 31432f2da36eSAnirudh Venkataramanan * @state: PF state field 31445153a18eSAnirudh Venkataramanan */ 31455df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state) 31465153a18eSAnirudh Venkataramanan { 31475df7e45dSDave Ertman return test_bit(__ICE_RESET_OICR_RECV, state) || 31485df7e45dSDave Ertman test_bit(__ICE_PFR_REQ, state) || 31495df7e45dSDave Ertman test_bit(__ICE_CORER_REQ, state) || 31505df7e45dSDave Ertman test_bit(__ICE_GLOBR_REQ, state); 31515153a18eSAnirudh Venkataramanan } 31527b9ffc76SAnirudh Venkataramanan 31537b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 31547b9ffc76SAnirudh Venkataramanan /** 31557b9ffc76SAnirudh Venkataramanan * ice_vsi_update_q_map - update our copy of the VSI info with new queue map 31567b9ffc76SAnirudh Venkataramanan * @vsi: VSI being configured 31577b9ffc76SAnirudh Venkataramanan * @ctx: the context buffer returned from AQ VSI update command 31587b9ffc76SAnirudh Venkataramanan */ 31597b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx) 31607b9ffc76SAnirudh Venkataramanan { 31617b9ffc76SAnirudh Venkataramanan vsi->info.mapping_flags = ctx->info.mapping_flags; 31627b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping, 31637b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.q_mapping)); 31647b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping, 31657b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.tc_mapping)); 31667b9ffc76SAnirudh Venkataramanan } 31677b9ffc76SAnirudh Venkataramanan 31687b9ffc76SAnirudh Venkataramanan /** 31697b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration 31707b9ffc76SAnirudh Venkataramanan * @vsi: the VSI being configured 31717b9ffc76SAnirudh Venkataramanan * @ena_tc: TC map to be enabled 31727b9ffc76SAnirudh Venkataramanan */ 31737b9ffc76SAnirudh Venkataramanan static void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc) 31747b9ffc76SAnirudh Venkataramanan { 31757b9ffc76SAnirudh Venkataramanan struct net_device *netdev = vsi->netdev; 31767b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 31777b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg; 31787b9ffc76SAnirudh Venkataramanan u8 netdev_tc; 31797b9ffc76SAnirudh Venkataramanan int i; 31807b9ffc76SAnirudh Venkataramanan 31817b9ffc76SAnirudh Venkataramanan if (!netdev) 31827b9ffc76SAnirudh Venkataramanan return; 31837b9ffc76SAnirudh Venkataramanan 31847b9ffc76SAnirudh Venkataramanan if (!ena_tc) { 31857b9ffc76SAnirudh Venkataramanan netdev_reset_tc(netdev); 31867b9ffc76SAnirudh Venkataramanan return; 31877b9ffc76SAnirudh Venkataramanan } 31887b9ffc76SAnirudh Venkataramanan 31897b9ffc76SAnirudh Venkataramanan if (netdev_set_num_tc(netdev, vsi->tc_cfg.numtc)) 31907b9ffc76SAnirudh Venkataramanan return; 31917b9ffc76SAnirudh Venkataramanan 31927b9ffc76SAnirudh Venkataramanan dcbcfg = &pf->hw.port_info->local_dcbx_cfg; 31937b9ffc76SAnirudh Venkataramanan 31947b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) 31957b9ffc76SAnirudh Venkataramanan if (vsi->tc_cfg.ena_tc & BIT(i)) 31967b9ffc76SAnirudh Venkataramanan netdev_set_tc_queue(netdev, 31977b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].netdev_tc, 31987b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qcount_tx, 31997b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset); 32007b9ffc76SAnirudh Venkataramanan 32017b9ffc76SAnirudh Venkataramanan for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 32027b9ffc76SAnirudh Venkataramanan u8 ets_tc = dcbcfg->etscfg.prio_table[i]; 32037b9ffc76SAnirudh Venkataramanan 32047b9ffc76SAnirudh Venkataramanan /* Get the mapped netdev TC# for the UP */ 32057b9ffc76SAnirudh Venkataramanan netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc; 32067b9ffc76SAnirudh Venkataramanan netdev_set_prio_tc_map(netdev, i, netdev_tc); 32077b9ffc76SAnirudh Venkataramanan } 32087b9ffc76SAnirudh Venkataramanan } 32097b9ffc76SAnirudh Venkataramanan 32107b9ffc76SAnirudh Venkataramanan /** 32117b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map 32127b9ffc76SAnirudh Venkataramanan * @vsi: VSI to be configured 32137b9ffc76SAnirudh Venkataramanan * @ena_tc: TC bitmap 32147b9ffc76SAnirudh Venkataramanan * 32157b9ffc76SAnirudh Venkataramanan * VSI queues expected to be quiesced before calling this function 32167b9ffc76SAnirudh Venkataramanan */ 32177b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) 32187b9ffc76SAnirudh Venkataramanan { 32197b9ffc76SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 32207b9ffc76SAnirudh Venkataramanan struct ice_vsi_ctx *ctx; 32217b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 32227b9ffc76SAnirudh Venkataramanan enum ice_status status; 32237b9ffc76SAnirudh Venkataramanan int i, ret = 0; 32247b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 32257b9ffc76SAnirudh Venkataramanan 32267b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) { 32277b9ffc76SAnirudh Venkataramanan /* build bitmap of enabled TCs */ 32287b9ffc76SAnirudh Venkataramanan if (ena_tc & BIT(i)) 32297b9ffc76SAnirudh Venkataramanan num_tc++; 32307b9ffc76SAnirudh Venkataramanan /* populate max_txqs per TC */ 3231d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 32327b9ffc76SAnirudh Venkataramanan } 32337b9ffc76SAnirudh Venkataramanan 32347b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ena_tc; 32357b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = num_tc; 32367b9ffc76SAnirudh Venkataramanan 32377b9ffc76SAnirudh Venkataramanan ctx = devm_kzalloc(&pf->pdev->dev, sizeof(*ctx), GFP_KERNEL); 32387b9ffc76SAnirudh Venkataramanan if (!ctx) 32397b9ffc76SAnirudh Venkataramanan return -ENOMEM; 32407b9ffc76SAnirudh Venkataramanan 32417b9ffc76SAnirudh Venkataramanan ctx->vf_num = 0; 32427b9ffc76SAnirudh Venkataramanan ctx->info = vsi->info; 32437b9ffc76SAnirudh Venkataramanan 32447b9ffc76SAnirudh Venkataramanan ice_vsi_setup_q_map(vsi, ctx); 32457b9ffc76SAnirudh Venkataramanan 32467b9ffc76SAnirudh Venkataramanan /* must to indicate which section of VSI context are being modified */ 32477b9ffc76SAnirudh Venkataramanan ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 32487b9ffc76SAnirudh Venkataramanan status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL); 32497b9ffc76SAnirudh Venkataramanan if (status) { 32507b9ffc76SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "Failed VSI Update\n"); 32517b9ffc76SAnirudh Venkataramanan ret = -EIO; 32527b9ffc76SAnirudh Venkataramanan goto out; 32537b9ffc76SAnirudh Venkataramanan } 32547b9ffc76SAnirudh Venkataramanan 32557b9ffc76SAnirudh Venkataramanan status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 32567b9ffc76SAnirudh Venkataramanan max_txqs); 32577b9ffc76SAnirudh Venkataramanan 32587b9ffc76SAnirudh Venkataramanan if (status) { 32597b9ffc76SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 32607b9ffc76SAnirudh Venkataramanan "VSI %d failed TC config, error %d\n", 32617b9ffc76SAnirudh Venkataramanan vsi->vsi_num, status); 32627b9ffc76SAnirudh Venkataramanan ret = -EIO; 32637b9ffc76SAnirudh Venkataramanan goto out; 32647b9ffc76SAnirudh Venkataramanan } 32657b9ffc76SAnirudh Venkataramanan ice_vsi_update_q_map(vsi, ctx); 32667b9ffc76SAnirudh Venkataramanan vsi->info.valid_sections = 0; 32677b9ffc76SAnirudh Venkataramanan 32687b9ffc76SAnirudh Venkataramanan ice_vsi_cfg_netdev_tc(vsi, ena_tc); 32697b9ffc76SAnirudh Venkataramanan out: 32707b9ffc76SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, ctx); 32717b9ffc76SAnirudh Venkataramanan return ret; 32727b9ffc76SAnirudh Venkataramanan } 32737b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 3274bbb968e8SAkeem G Abodunrin 3275bbb968e8SAkeem G Abodunrin /** 3276bbb968e8SAkeem G Abodunrin * ice_vsi_cfg_mac_fltr - Add or remove a MAC address filter for a VSI 3277bbb968e8SAkeem G Abodunrin * @vsi: the VSI being configured MAC filter 3278bbb968e8SAkeem G Abodunrin * @macaddr: the MAC address to be added. 3279bbb968e8SAkeem G Abodunrin * @set: Add or delete a MAC filter 3280bbb968e8SAkeem G Abodunrin * 3281bbb968e8SAkeem G Abodunrin * Adds or removes MAC address filter entry for VF VSI 3282bbb968e8SAkeem G Abodunrin */ 3283bbb968e8SAkeem G Abodunrin enum ice_status 3284bbb968e8SAkeem G Abodunrin ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set) 3285bbb968e8SAkeem G Abodunrin { 3286bbb968e8SAkeem G Abodunrin LIST_HEAD(tmp_add_list); 3287bbb968e8SAkeem G Abodunrin enum ice_status status; 3288bbb968e8SAkeem G Abodunrin 3289bbb968e8SAkeem G Abodunrin /* Update MAC filter list to be added or removed for a VSI */ 3290bbb968e8SAkeem G Abodunrin if (ice_add_mac_to_list(vsi, &tmp_add_list, macaddr)) { 3291bbb968e8SAkeem G Abodunrin status = ICE_ERR_NO_MEMORY; 3292bbb968e8SAkeem G Abodunrin goto cfg_mac_fltr_exit; 3293bbb968e8SAkeem G Abodunrin } 3294bbb968e8SAkeem G Abodunrin 3295bbb968e8SAkeem G Abodunrin if (set) 3296bbb968e8SAkeem G Abodunrin status = ice_add_mac(&vsi->back->hw, &tmp_add_list); 3297bbb968e8SAkeem G Abodunrin else 3298bbb968e8SAkeem G Abodunrin status = ice_remove_mac(&vsi->back->hw, &tmp_add_list); 3299bbb968e8SAkeem G Abodunrin 3300bbb968e8SAkeem G Abodunrin cfg_mac_fltr_exit: 3301bbb968e8SAkeem G Abodunrin ice_free_fltr_list(&vsi->back->pdev->dev, &tmp_add_list); 3302bbb968e8SAkeem G Abodunrin return status; 3303bbb968e8SAkeem G Abodunrin } 3304