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" 645d3d428SAnirudh Venkataramanan 745d3d428SAnirudh Venkataramanan /** 872adf242SAnirudh Venkataramanan * ice_setup_rx_ctx - Configure a receive ring context 972adf242SAnirudh Venkataramanan * @ring: The Rx ring to configure 1072adf242SAnirudh Venkataramanan * 1172adf242SAnirudh Venkataramanan * Configure the Rx descriptor ring in RLAN context. 1272adf242SAnirudh Venkataramanan */ 1372adf242SAnirudh Venkataramanan static int ice_setup_rx_ctx(struct ice_ring *ring) 1472adf242SAnirudh Venkataramanan { 1572adf242SAnirudh Venkataramanan struct ice_vsi *vsi = ring->vsi; 1672adf242SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1772adf242SAnirudh Venkataramanan u32 rxdid = ICE_RXDID_FLEX_NIC; 1872adf242SAnirudh Venkataramanan struct ice_rlan_ctx rlan_ctx; 1972adf242SAnirudh Venkataramanan u32 regval; 2072adf242SAnirudh Venkataramanan u16 pf_q; 2172adf242SAnirudh Venkataramanan int err; 2272adf242SAnirudh Venkataramanan 23d337f2afSAnirudh Venkataramanan /* what is Rx queue number in global space of 2K Rx queues */ 2472adf242SAnirudh Venkataramanan pf_q = vsi->rxq_map[ring->q_index]; 2572adf242SAnirudh Venkataramanan 2672adf242SAnirudh Venkataramanan /* clear the context structure first */ 2772adf242SAnirudh Venkataramanan memset(&rlan_ctx, 0, sizeof(rlan_ctx)); 2872adf242SAnirudh Venkataramanan 2972adf242SAnirudh Venkataramanan rlan_ctx.base = ring->dma >> 7; 3072adf242SAnirudh Venkataramanan 3172adf242SAnirudh Venkataramanan rlan_ctx.qlen = ring->count; 3272adf242SAnirudh Venkataramanan 3372adf242SAnirudh Venkataramanan /* Receive Packet Data Buffer Size. 3472adf242SAnirudh Venkataramanan * The Packet Data Buffer Size is defined in 128 byte units. 3572adf242SAnirudh Venkataramanan */ 3672adf242SAnirudh Venkataramanan rlan_ctx.dbuf = vsi->rx_buf_len >> ICE_RLAN_CTX_DBUF_S; 3772adf242SAnirudh Venkataramanan 3872adf242SAnirudh Venkataramanan /* use 32 byte descriptors */ 3972adf242SAnirudh Venkataramanan rlan_ctx.dsize = 1; 4072adf242SAnirudh Venkataramanan 4172adf242SAnirudh Venkataramanan /* Strip the Ethernet CRC bytes before the packet is posted to host 4272adf242SAnirudh Venkataramanan * memory. 4372adf242SAnirudh Venkataramanan */ 4472adf242SAnirudh Venkataramanan rlan_ctx.crcstrip = 1; 4572adf242SAnirudh Venkataramanan 4672adf242SAnirudh Venkataramanan /* L2TSEL flag defines the reported L2 Tags in the receive descriptor */ 4772adf242SAnirudh Venkataramanan rlan_ctx.l2tsel = 1; 4872adf242SAnirudh Venkataramanan 4972adf242SAnirudh Venkataramanan rlan_ctx.dtype = ICE_RX_DTYPE_NO_SPLIT; 5072adf242SAnirudh Venkataramanan rlan_ctx.hsplit_0 = ICE_RLAN_RX_HSPLIT_0_NO_SPLIT; 5172adf242SAnirudh Venkataramanan rlan_ctx.hsplit_1 = ICE_RLAN_RX_HSPLIT_1_NO_SPLIT; 5272adf242SAnirudh Venkataramanan 5372adf242SAnirudh Venkataramanan /* This controls whether VLAN is stripped from inner headers 5472adf242SAnirudh Venkataramanan * The VLAN in the inner L2 header is stripped to the receive 5572adf242SAnirudh Venkataramanan * descriptor if enabled by this flag. 5672adf242SAnirudh Venkataramanan */ 5772adf242SAnirudh Venkataramanan rlan_ctx.showiv = 0; 5872adf242SAnirudh Venkataramanan 5972adf242SAnirudh Venkataramanan /* Max packet size for this queue - must not be set to a larger value 6072adf242SAnirudh Venkataramanan * than 5 x DBUF 6172adf242SAnirudh Venkataramanan */ 6272adf242SAnirudh Venkataramanan rlan_ctx.rxmax = min_t(u16, vsi->max_frame, 6372adf242SAnirudh Venkataramanan ICE_MAX_CHAINED_RX_BUFS * vsi->rx_buf_len); 6472adf242SAnirudh Venkataramanan 6572adf242SAnirudh Venkataramanan /* Rx queue threshold in units of 64 */ 6672adf242SAnirudh Venkataramanan rlan_ctx.lrxqthresh = 1; 6772adf242SAnirudh Venkataramanan 6872adf242SAnirudh Venkataramanan /* Enable Flexible Descriptors in the queue context which 6972adf242SAnirudh Venkataramanan * allows this driver to select a specific receive descriptor format 7072adf242SAnirudh Venkataramanan */ 718ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 7272adf242SAnirudh Venkataramanan regval = rd32(hw, QRXFLXP_CNTXT(pf_q)); 7372adf242SAnirudh Venkataramanan regval |= (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) & 7472adf242SAnirudh Venkataramanan QRXFLXP_CNTXT_RXDID_IDX_M; 7572adf242SAnirudh Venkataramanan 7672adf242SAnirudh Venkataramanan /* increasing context priority to pick up profile id; 7772adf242SAnirudh Venkataramanan * default is 0x01; setting to 0x03 to ensure profile 7872adf242SAnirudh Venkataramanan * is programming if prev context is of same priority 7972adf242SAnirudh Venkataramanan */ 8072adf242SAnirudh Venkataramanan regval |= (0x03 << QRXFLXP_CNTXT_RXDID_PRIO_S) & 8172adf242SAnirudh Venkataramanan QRXFLXP_CNTXT_RXDID_PRIO_M; 8272adf242SAnirudh Venkataramanan 8372adf242SAnirudh Venkataramanan wr32(hw, QRXFLXP_CNTXT(pf_q), regval); 848ede0178SAnirudh Venkataramanan } 8572adf242SAnirudh Venkataramanan 8672adf242SAnirudh Venkataramanan /* Absolute queue number out of 2K needs to be passed */ 8772adf242SAnirudh Venkataramanan err = ice_write_rxq_ctx(hw, &rlan_ctx, pf_q); 8872adf242SAnirudh Venkataramanan if (err) { 8972adf242SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, 9072adf242SAnirudh Venkataramanan "Failed to set LAN Rx queue context for absolute Rx queue %d error: %d\n", 9172adf242SAnirudh Venkataramanan pf_q, err); 9272adf242SAnirudh Venkataramanan return -EIO; 9372adf242SAnirudh Venkataramanan } 9472adf242SAnirudh Venkataramanan 958ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 968ede0178SAnirudh Venkataramanan return 0; 978ede0178SAnirudh Venkataramanan 9872adf242SAnirudh Venkataramanan /* init queue specific tail register */ 9972adf242SAnirudh Venkataramanan ring->tail = hw->hw_addr + QRX_TAIL(pf_q); 10072adf242SAnirudh Venkataramanan writel(0, ring->tail); 10172adf242SAnirudh Venkataramanan ice_alloc_rx_bufs(ring, ICE_DESC_UNUSED(ring)); 10272adf242SAnirudh Venkataramanan 10372adf242SAnirudh Venkataramanan return 0; 10472adf242SAnirudh Venkataramanan } 10572adf242SAnirudh Venkataramanan 10672adf242SAnirudh Venkataramanan /** 10772adf242SAnirudh Venkataramanan * ice_setup_tx_ctx - setup a struct ice_tlan_ctx instance 10872adf242SAnirudh Venkataramanan * @ring: The Tx ring to configure 10972adf242SAnirudh Venkataramanan * @tlan_ctx: Pointer to the Tx LAN queue context structure to be initialized 11072adf242SAnirudh Venkataramanan * @pf_q: queue index in the PF space 11172adf242SAnirudh Venkataramanan * 11272adf242SAnirudh Venkataramanan * Configure the Tx descriptor ring in TLAN context. 11372adf242SAnirudh Venkataramanan */ 11472adf242SAnirudh Venkataramanan static void 11572adf242SAnirudh Venkataramanan ice_setup_tx_ctx(struct ice_ring *ring, struct ice_tlan_ctx *tlan_ctx, u16 pf_q) 11672adf242SAnirudh Venkataramanan { 11772adf242SAnirudh Venkataramanan struct ice_vsi *vsi = ring->vsi; 11872adf242SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 11972adf242SAnirudh Venkataramanan 12072adf242SAnirudh Venkataramanan tlan_ctx->base = ring->dma >> ICE_TLAN_CTX_BASE_S; 12172adf242SAnirudh Venkataramanan 12272adf242SAnirudh Venkataramanan tlan_ctx->port_num = vsi->port_info->lport; 12372adf242SAnirudh Venkataramanan 12472adf242SAnirudh Venkataramanan /* Transmit Queue Length */ 12572adf242SAnirudh Venkataramanan tlan_ctx->qlen = ring->count; 12672adf242SAnirudh Venkataramanan 12772adf242SAnirudh Venkataramanan /* PF number */ 12872adf242SAnirudh Venkataramanan tlan_ctx->pf_num = hw->pf_id; 12972adf242SAnirudh Venkataramanan 13072adf242SAnirudh Venkataramanan /* queue belongs to a specific VSI type 13172adf242SAnirudh Venkataramanan * VF / VM index should be programmed per vmvf_type setting: 13272adf242SAnirudh Venkataramanan * for vmvf_type = VF, it is VF number between 0-256 13372adf242SAnirudh Venkataramanan * for vmvf_type = VM, it is VM number between 0-767 13472adf242SAnirudh Venkataramanan * for PF or EMP this field should be set to zero 13572adf242SAnirudh Venkataramanan */ 13672adf242SAnirudh Venkataramanan switch (vsi->type) { 13772adf242SAnirudh Venkataramanan case ICE_VSI_PF: 13872adf242SAnirudh Venkataramanan tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_PF; 13972adf242SAnirudh Venkataramanan break; 1408ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 1418ede0178SAnirudh Venkataramanan /* Firmware expects vmvf_num to be absolute VF id */ 1428ede0178SAnirudh Venkataramanan tlan_ctx->vmvf_num = hw->func_caps.vf_base_id + vsi->vf_id; 1438ede0178SAnirudh Venkataramanan tlan_ctx->vmvf_type = ICE_TLAN_CTX_VMVF_TYPE_VF; 1448ede0178SAnirudh Venkataramanan break; 14572adf242SAnirudh Venkataramanan default: 14672adf242SAnirudh Venkataramanan return; 14772adf242SAnirudh Venkataramanan } 14872adf242SAnirudh Venkataramanan 14972adf242SAnirudh Venkataramanan /* make sure the context is associated with the right VSI */ 1504fb33f31SAnirudh Venkataramanan tlan_ctx->src_vsi = ice_get_hw_vsi_num(hw, vsi->idx); 15172adf242SAnirudh Venkataramanan 15272adf242SAnirudh Venkataramanan tlan_ctx->tso_ena = ICE_TX_LEGACY; 15372adf242SAnirudh Venkataramanan tlan_ctx->tso_qnum = pf_q; 15472adf242SAnirudh Venkataramanan 15572adf242SAnirudh Venkataramanan /* Legacy or Advanced Host Interface: 15672adf242SAnirudh Venkataramanan * 0: Advanced Host Interface 15772adf242SAnirudh Venkataramanan * 1: Legacy Host Interface 15872adf242SAnirudh Venkataramanan */ 15972adf242SAnirudh Venkataramanan tlan_ctx->legacy_int = ICE_TX_LEGACY; 16072adf242SAnirudh Venkataramanan } 16172adf242SAnirudh Venkataramanan 16272adf242SAnirudh Venkataramanan /** 16372adf242SAnirudh Venkataramanan * ice_pf_rxq_wait - Wait for a PF's Rx queue to be enabled or disabled 16472adf242SAnirudh Venkataramanan * @pf: the PF being configured 16572adf242SAnirudh Venkataramanan * @pf_q: the PF queue 16672adf242SAnirudh Venkataramanan * @ena: enable or disable state of the queue 16772adf242SAnirudh Venkataramanan * 16872adf242SAnirudh Venkataramanan * This routine will wait for the given Rx queue of the PF to reach the 16972adf242SAnirudh Venkataramanan * enabled or disabled state. 17072adf242SAnirudh Venkataramanan * Returns -ETIMEDOUT in case of failing to reach the requested state after 17172adf242SAnirudh Venkataramanan * multiple retries; else will return 0 in case of success. 17272adf242SAnirudh Venkataramanan */ 17372adf242SAnirudh Venkataramanan static int ice_pf_rxq_wait(struct ice_pf *pf, int pf_q, bool ena) 17472adf242SAnirudh Venkataramanan { 17572adf242SAnirudh Venkataramanan int i; 17672adf242SAnirudh Venkataramanan 1777b8ff0f9SPiotr Raczynski for (i = 0; i < ICE_Q_WAIT_MAX_RETRY; i++) { 17816c3301bSBrett Creeley if (ena == !!(rd32(&pf->hw, QRX_CTRL(pf_q)) & 17916c3301bSBrett Creeley QRX_CTRL_QENA_STAT_M)) 18016c3301bSBrett Creeley return 0; 18172adf242SAnirudh Venkataramanan 1827b8ff0f9SPiotr Raczynski usleep_range(20, 40); 18372adf242SAnirudh Venkataramanan } 18472adf242SAnirudh Venkataramanan 18516c3301bSBrett Creeley return -ETIMEDOUT; 18672adf242SAnirudh Venkataramanan } 18772adf242SAnirudh Venkataramanan 18872adf242SAnirudh Venkataramanan /** 18972adf242SAnirudh Venkataramanan * ice_vsi_ctrl_rx_rings - Start or stop a VSI's Rx rings 19072adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 19172adf242SAnirudh Venkataramanan * @ena: start or stop the Rx rings 19272adf242SAnirudh Venkataramanan */ 19372adf242SAnirudh Venkataramanan static int ice_vsi_ctrl_rx_rings(struct ice_vsi *vsi, bool ena) 19472adf242SAnirudh Venkataramanan { 19572adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 19672adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 19772adf242SAnirudh Venkataramanan int i, j, ret = 0; 19872adf242SAnirudh Venkataramanan 19972adf242SAnirudh Venkataramanan for (i = 0; i < vsi->num_rxq; i++) { 20072adf242SAnirudh Venkataramanan int pf_q = vsi->rxq_map[i]; 20172adf242SAnirudh Venkataramanan u32 rx_reg; 20272adf242SAnirudh Venkataramanan 20372adf242SAnirudh Venkataramanan for (j = 0; j < ICE_Q_WAIT_MAX_RETRY; j++) { 20472adf242SAnirudh Venkataramanan rx_reg = rd32(hw, QRX_CTRL(pf_q)); 20572adf242SAnirudh Venkataramanan if (((rx_reg >> QRX_CTRL_QENA_REQ_S) & 1) == 20672adf242SAnirudh Venkataramanan ((rx_reg >> QRX_CTRL_QENA_STAT_S) & 1)) 20772adf242SAnirudh Venkataramanan break; 20872adf242SAnirudh Venkataramanan usleep_range(1000, 2000); 20972adf242SAnirudh Venkataramanan } 21072adf242SAnirudh Venkataramanan 21172adf242SAnirudh Venkataramanan /* Skip if the queue is already in the requested state */ 21272adf242SAnirudh Venkataramanan if (ena == !!(rx_reg & QRX_CTRL_QENA_STAT_M)) 21372adf242SAnirudh Venkataramanan continue; 21472adf242SAnirudh Venkataramanan 21572adf242SAnirudh Venkataramanan /* turn on/off the queue */ 21672adf242SAnirudh Venkataramanan if (ena) 21772adf242SAnirudh Venkataramanan rx_reg |= QRX_CTRL_QENA_REQ_M; 21872adf242SAnirudh Venkataramanan else 21972adf242SAnirudh Venkataramanan rx_reg &= ~QRX_CTRL_QENA_REQ_M; 22072adf242SAnirudh Venkataramanan wr32(hw, QRX_CTRL(pf_q), rx_reg); 22172adf242SAnirudh Venkataramanan 22272adf242SAnirudh Venkataramanan /* wait for the change to finish */ 22372adf242SAnirudh Venkataramanan ret = ice_pf_rxq_wait(pf, pf_q, ena); 22472adf242SAnirudh Venkataramanan if (ret) { 22572adf242SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 22672adf242SAnirudh Venkataramanan "VSI idx %d Rx ring %d %sable timeout\n", 22772adf242SAnirudh Venkataramanan vsi->idx, pf_q, (ena ? "en" : "dis")); 22872adf242SAnirudh Venkataramanan break; 22972adf242SAnirudh Venkataramanan } 23072adf242SAnirudh Venkataramanan } 23172adf242SAnirudh Venkataramanan 23272adf242SAnirudh Venkataramanan return ret; 23372adf242SAnirudh Venkataramanan } 23472adf242SAnirudh Venkataramanan 23572adf242SAnirudh Venkataramanan /** 23628c2a645SAnirudh Venkataramanan * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI 23728c2a645SAnirudh Venkataramanan * @vsi: VSI pointer 23828c2a645SAnirudh Venkataramanan * @alloc_qvectors: a bool to specify if q_vectors need to be allocated. 23928c2a645SAnirudh Venkataramanan * 24028c2a645SAnirudh Venkataramanan * On error: returns error code (negative) 24128c2a645SAnirudh Venkataramanan * On success: returns 0 24228c2a645SAnirudh Venkataramanan */ 24337bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors) 24428c2a645SAnirudh Venkataramanan { 24528c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 24628c2a645SAnirudh Venkataramanan 24728c2a645SAnirudh Venkataramanan /* allocate memory for both Tx and Rx ring pointers */ 24828c2a645SAnirudh Venkataramanan vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 249c6dfd690SBruce Allan sizeof(*vsi->tx_rings), GFP_KERNEL); 25028c2a645SAnirudh Venkataramanan if (!vsi->tx_rings) 25128c2a645SAnirudh Venkataramanan goto err_txrings; 25228c2a645SAnirudh Venkataramanan 25328c2a645SAnirudh Venkataramanan vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 254c6dfd690SBruce Allan sizeof(*vsi->rx_rings), GFP_KERNEL); 25528c2a645SAnirudh Venkataramanan if (!vsi->rx_rings) 25628c2a645SAnirudh Venkataramanan goto err_rxrings; 25728c2a645SAnirudh Venkataramanan 25828c2a645SAnirudh Venkataramanan if (alloc_qvectors) { 25928c2a645SAnirudh Venkataramanan /* allocate memory for q_vector pointers */ 26028c2a645SAnirudh Venkataramanan vsi->q_vectors = devm_kcalloc(&pf->pdev->dev, 26128c2a645SAnirudh Venkataramanan vsi->num_q_vectors, 262c6dfd690SBruce Allan sizeof(*vsi->q_vectors), 26328c2a645SAnirudh Venkataramanan GFP_KERNEL); 26428c2a645SAnirudh Venkataramanan if (!vsi->q_vectors) 26528c2a645SAnirudh Venkataramanan goto err_vectors; 26628c2a645SAnirudh Venkataramanan } 26728c2a645SAnirudh Venkataramanan 26828c2a645SAnirudh Venkataramanan return 0; 26928c2a645SAnirudh Venkataramanan 27028c2a645SAnirudh Venkataramanan err_vectors: 27128c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 27228c2a645SAnirudh Venkataramanan err_rxrings: 27328c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 27428c2a645SAnirudh Venkataramanan err_txrings: 27528c2a645SAnirudh Venkataramanan return -ENOMEM; 27628c2a645SAnirudh Venkataramanan } 27728c2a645SAnirudh Venkataramanan 27828c2a645SAnirudh Venkataramanan /** 27928c2a645SAnirudh Venkataramanan * ice_vsi_set_num_qs - Set num queues, descriptors and vectors for a VSI 28028c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 28128c2a645SAnirudh Venkataramanan * 28228c2a645SAnirudh Venkataramanan * Return 0 on success and a negative value on error 28328c2a645SAnirudh Venkataramanan */ 28437bb8390SAnirudh Venkataramanan static void ice_vsi_set_num_qs(struct ice_vsi *vsi) 28528c2a645SAnirudh Venkataramanan { 28628c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 28728c2a645SAnirudh Venkataramanan 28828c2a645SAnirudh Venkataramanan switch (vsi->type) { 28928c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 29028c2a645SAnirudh Venkataramanan vsi->alloc_txq = pf->num_lan_tx; 29128c2a645SAnirudh Venkataramanan vsi->alloc_rxq = pf->num_lan_rx; 29228c2a645SAnirudh Venkataramanan vsi->num_desc = ALIGN(ICE_DFLT_NUM_DESC, ICE_REQ_DESC_MULTIPLE); 29328c2a645SAnirudh Venkataramanan vsi->num_q_vectors = max_t(int, pf->num_lan_rx, pf->num_lan_tx); 29428c2a645SAnirudh Venkataramanan break; 2958ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 2968ede0178SAnirudh Venkataramanan vsi->alloc_txq = pf->num_vf_qps; 2978ede0178SAnirudh Venkataramanan vsi->alloc_rxq = pf->num_vf_qps; 2988ede0178SAnirudh Venkataramanan /* pf->num_vf_msix includes (VF miscellaneous vector + 2998ede0178SAnirudh Venkataramanan * data queue interrupts). Since vsi->num_q_vectors is number 3008ede0178SAnirudh Venkataramanan * of queues vectors, subtract 1 from the original vector 3018ede0178SAnirudh Venkataramanan * count 3028ede0178SAnirudh Venkataramanan */ 3038ede0178SAnirudh Venkataramanan vsi->num_q_vectors = pf->num_vf_msix - 1; 3048ede0178SAnirudh Venkataramanan break; 30528c2a645SAnirudh Venkataramanan default: 30628c2a645SAnirudh Venkataramanan dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n", 30728c2a645SAnirudh Venkataramanan vsi->type); 30828c2a645SAnirudh Venkataramanan break; 30928c2a645SAnirudh Venkataramanan } 31028c2a645SAnirudh Venkataramanan } 31128c2a645SAnirudh Venkataramanan 31228c2a645SAnirudh Venkataramanan /** 31328c2a645SAnirudh Venkataramanan * ice_get_free_slot - get the next non-NULL location index in array 31428c2a645SAnirudh Venkataramanan * @array: array to search 31528c2a645SAnirudh Venkataramanan * @size: size of the array 31628c2a645SAnirudh Venkataramanan * @curr: last known occupied index to be used as a search hint 31728c2a645SAnirudh Venkataramanan * 31828c2a645SAnirudh Venkataramanan * void * is being used to keep the functionality generic. This lets us use this 31928c2a645SAnirudh Venkataramanan * function on any array of pointers. 32028c2a645SAnirudh Venkataramanan */ 32137bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr) 32228c2a645SAnirudh Venkataramanan { 32328c2a645SAnirudh Venkataramanan int **tmp_array = (int **)array; 32428c2a645SAnirudh Venkataramanan int next; 32528c2a645SAnirudh Venkataramanan 32628c2a645SAnirudh Venkataramanan if (curr < (size - 1) && !tmp_array[curr + 1]) { 32728c2a645SAnirudh Venkataramanan next = curr + 1; 32828c2a645SAnirudh Venkataramanan } else { 32928c2a645SAnirudh Venkataramanan int i = 0; 33028c2a645SAnirudh Venkataramanan 33128c2a645SAnirudh Venkataramanan while ((i < size) && (tmp_array[i])) 33228c2a645SAnirudh Venkataramanan i++; 33328c2a645SAnirudh Venkataramanan if (i == size) 33428c2a645SAnirudh Venkataramanan next = ICE_NO_VSI; 33528c2a645SAnirudh Venkataramanan else 33628c2a645SAnirudh Venkataramanan next = i; 33728c2a645SAnirudh Venkataramanan } 33828c2a645SAnirudh Venkataramanan return next; 33928c2a645SAnirudh Venkataramanan } 34028c2a645SAnirudh Venkataramanan 34128c2a645SAnirudh Venkataramanan /** 3425153a18eSAnirudh Venkataramanan * ice_vsi_delete - delete a VSI from the switch 3435153a18eSAnirudh Venkataramanan * @vsi: pointer to VSI being removed 3445153a18eSAnirudh Venkataramanan */ 3455153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi) 3465153a18eSAnirudh Venkataramanan { 3475153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 348198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 3495153a18eSAnirudh Venkataramanan enum ice_status status; 3505153a18eSAnirudh Venkataramanan 351198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 352198a666aSBruce Allan if (!ctxt) 353198a666aSBruce Allan return; 354198a666aSBruce Allan 3558ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 356198a666aSBruce Allan ctxt->vf_num = vsi->vf_id; 357198a666aSBruce Allan ctxt->vsi_num = vsi->vsi_num; 3585153a18eSAnirudh Venkataramanan 359198a666aSBruce Allan memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); 3605153a18eSAnirudh Venkataramanan 361198a666aSBruce Allan status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); 3625153a18eSAnirudh Venkataramanan if (status) 3635153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failed to delete VSI %i in FW\n", 3645153a18eSAnirudh Venkataramanan vsi->vsi_num); 365198a666aSBruce Allan 366198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 3675153a18eSAnirudh Venkataramanan } 3685153a18eSAnirudh Venkataramanan 3695153a18eSAnirudh Venkataramanan /** 37007309a0eSAnirudh Venkataramanan * ice_vsi_free_arrays - clean up VSI resources 37107309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 37207309a0eSAnirudh Venkataramanan * @free_qvectors: bool to specify if q_vectors should be deallocated 37307309a0eSAnirudh Venkataramanan */ 374df0f8479SAnirudh Venkataramanan static void ice_vsi_free_arrays(struct ice_vsi *vsi, bool free_qvectors) 37507309a0eSAnirudh Venkataramanan { 37607309a0eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 37707309a0eSAnirudh Venkataramanan 37807309a0eSAnirudh Venkataramanan /* free the ring and vector containers */ 37907309a0eSAnirudh Venkataramanan if (free_qvectors && vsi->q_vectors) { 38007309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->q_vectors); 38107309a0eSAnirudh Venkataramanan vsi->q_vectors = NULL; 38207309a0eSAnirudh Venkataramanan } 38307309a0eSAnirudh Venkataramanan if (vsi->tx_rings) { 38407309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 38507309a0eSAnirudh Venkataramanan vsi->tx_rings = NULL; 38607309a0eSAnirudh Venkataramanan } 38707309a0eSAnirudh Venkataramanan if (vsi->rx_rings) { 38807309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 38907309a0eSAnirudh Venkataramanan vsi->rx_rings = NULL; 39007309a0eSAnirudh Venkataramanan } 39107309a0eSAnirudh Venkataramanan } 39207309a0eSAnirudh Venkataramanan 39307309a0eSAnirudh Venkataramanan /** 39407309a0eSAnirudh Venkataramanan * ice_vsi_clear - clean up and deallocate the provided VSI 39507309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 39607309a0eSAnirudh Venkataramanan * 39707309a0eSAnirudh Venkataramanan * This deallocates the VSI's queue resources, removes it from the PF's 39807309a0eSAnirudh Venkataramanan * VSI array if necessary, and deallocates the VSI 39907309a0eSAnirudh Venkataramanan * 40007309a0eSAnirudh Venkataramanan * Returns 0 on success, negative on failure 40107309a0eSAnirudh Venkataramanan */ 40207309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi) 40307309a0eSAnirudh Venkataramanan { 40407309a0eSAnirudh Venkataramanan struct ice_pf *pf = NULL; 40507309a0eSAnirudh Venkataramanan 40607309a0eSAnirudh Venkataramanan if (!vsi) 40707309a0eSAnirudh Venkataramanan return 0; 40807309a0eSAnirudh Venkataramanan 40907309a0eSAnirudh Venkataramanan if (!vsi->back) 41007309a0eSAnirudh Venkataramanan return -EINVAL; 41107309a0eSAnirudh Venkataramanan 41207309a0eSAnirudh Venkataramanan pf = vsi->back; 41307309a0eSAnirudh Venkataramanan 41407309a0eSAnirudh Venkataramanan if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) { 41507309a0eSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "vsi does not exist at pf->vsi[%d]\n", 41607309a0eSAnirudh Venkataramanan vsi->idx); 41707309a0eSAnirudh Venkataramanan return -EINVAL; 41807309a0eSAnirudh Venkataramanan } 41907309a0eSAnirudh Venkataramanan 42007309a0eSAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 42107309a0eSAnirudh Venkataramanan /* updates the PF for this cleared VSI */ 42207309a0eSAnirudh Venkataramanan 42307309a0eSAnirudh Venkataramanan pf->vsi[vsi->idx] = NULL; 42407309a0eSAnirudh Venkataramanan if (vsi->idx < pf->next_vsi) 42507309a0eSAnirudh Venkataramanan pf->next_vsi = vsi->idx; 42607309a0eSAnirudh Venkataramanan 42707309a0eSAnirudh Venkataramanan ice_vsi_free_arrays(vsi, true); 42807309a0eSAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 42907309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 43007309a0eSAnirudh Venkataramanan 43107309a0eSAnirudh Venkataramanan return 0; 43207309a0eSAnirudh Venkataramanan } 43307309a0eSAnirudh Venkataramanan 43407309a0eSAnirudh Venkataramanan /** 4355153a18eSAnirudh Venkataramanan * ice_msix_clean_rings - MSIX mode Interrupt Handler 4365153a18eSAnirudh Venkataramanan * @irq: interrupt number 4375153a18eSAnirudh Venkataramanan * @data: pointer to a q_vector 4385153a18eSAnirudh Venkataramanan */ 439f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data) 4405153a18eSAnirudh Venkataramanan { 4415153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 4425153a18eSAnirudh Venkataramanan 4435153a18eSAnirudh Venkataramanan if (!q_vector->tx.ring && !q_vector->rx.ring) 4445153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 4455153a18eSAnirudh Venkataramanan 4465153a18eSAnirudh Venkataramanan napi_schedule(&q_vector->napi); 4475153a18eSAnirudh Venkataramanan 4485153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 4495153a18eSAnirudh Venkataramanan } 4505153a18eSAnirudh Venkataramanan 4515153a18eSAnirudh Venkataramanan /** 45237bb8390SAnirudh Venkataramanan * ice_vsi_alloc - Allocates the next available struct VSI in the PF 45337bb8390SAnirudh Venkataramanan * @pf: board private structure 45437bb8390SAnirudh Venkataramanan * @type: type of VSI 45537bb8390SAnirudh Venkataramanan * 45637bb8390SAnirudh Venkataramanan * returns a pointer to a VSI on success, NULL on failure. 45737bb8390SAnirudh Venkataramanan */ 45837bb8390SAnirudh Venkataramanan static struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type) 45937bb8390SAnirudh Venkataramanan { 46037bb8390SAnirudh Venkataramanan struct ice_vsi *vsi = NULL; 46137bb8390SAnirudh Venkataramanan 46237bb8390SAnirudh Venkataramanan /* Need to protect the allocation of the VSIs at the PF level */ 46337bb8390SAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 46437bb8390SAnirudh Venkataramanan 46537bb8390SAnirudh Venkataramanan /* If we have already allocated our maximum number of VSIs, 46637bb8390SAnirudh Venkataramanan * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index 46737bb8390SAnirudh Venkataramanan * is available to be populated 46837bb8390SAnirudh Venkataramanan */ 46937bb8390SAnirudh Venkataramanan if (pf->next_vsi == ICE_NO_VSI) { 47037bb8390SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "out of VSI slots!\n"); 47137bb8390SAnirudh Venkataramanan goto unlock_pf; 47237bb8390SAnirudh Venkataramanan } 47337bb8390SAnirudh Venkataramanan 47437bb8390SAnirudh Venkataramanan vsi = devm_kzalloc(&pf->pdev->dev, sizeof(*vsi), GFP_KERNEL); 47537bb8390SAnirudh Venkataramanan if (!vsi) 47637bb8390SAnirudh Venkataramanan goto unlock_pf; 47737bb8390SAnirudh Venkataramanan 47837bb8390SAnirudh Venkataramanan vsi->type = type; 47937bb8390SAnirudh Venkataramanan vsi->back = pf; 48037bb8390SAnirudh Venkataramanan set_bit(__ICE_DOWN, vsi->state); 48137bb8390SAnirudh Venkataramanan vsi->idx = pf->next_vsi; 48237bb8390SAnirudh Venkataramanan vsi->work_lmt = ICE_DFLT_IRQ_WORK; 48337bb8390SAnirudh Venkataramanan 48437bb8390SAnirudh Venkataramanan ice_vsi_set_num_qs(vsi); 48537bb8390SAnirudh Venkataramanan 48637bb8390SAnirudh Venkataramanan switch (vsi->type) { 48737bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 48837bb8390SAnirudh Venkataramanan if (ice_vsi_alloc_arrays(vsi, true)) 48937bb8390SAnirudh Venkataramanan goto err_rings; 49037bb8390SAnirudh Venkataramanan 49137bb8390SAnirudh Venkataramanan /* Setup default MSIX irq handler for VSI */ 49237bb8390SAnirudh Venkataramanan vsi->irq_handler = ice_msix_clean_rings; 49337bb8390SAnirudh Venkataramanan break; 4948ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 4958ede0178SAnirudh Venkataramanan if (ice_vsi_alloc_arrays(vsi, true)) 4968ede0178SAnirudh Venkataramanan goto err_rings; 4978ede0178SAnirudh Venkataramanan break; 49837bb8390SAnirudh Venkataramanan default: 49937bb8390SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 50037bb8390SAnirudh Venkataramanan goto unlock_pf; 50137bb8390SAnirudh Venkataramanan } 50237bb8390SAnirudh Venkataramanan 50337bb8390SAnirudh Venkataramanan /* fill VSI slot in the PF struct */ 50437bb8390SAnirudh Venkataramanan pf->vsi[pf->next_vsi] = vsi; 50537bb8390SAnirudh Venkataramanan 50637bb8390SAnirudh Venkataramanan /* prepare pf->next_vsi for next use */ 50737bb8390SAnirudh Venkataramanan pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi, 50837bb8390SAnirudh Venkataramanan pf->next_vsi); 50937bb8390SAnirudh Venkataramanan goto unlock_pf; 51037bb8390SAnirudh Venkataramanan 51137bb8390SAnirudh Venkataramanan err_rings: 51237bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 51337bb8390SAnirudh Venkataramanan vsi = NULL; 51437bb8390SAnirudh Venkataramanan unlock_pf: 51537bb8390SAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 51637bb8390SAnirudh Venkataramanan return vsi; 51737bb8390SAnirudh Venkataramanan } 51837bb8390SAnirudh Venkataramanan 51937bb8390SAnirudh Venkataramanan /** 52003f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs_contig - Assign a contiguous chunk of queues to VSI 52103f7a986SAnirudh Venkataramanan * @qs_cfg: gathered variables needed for PF->VSI queues assignment 522df0f8479SAnirudh Venkataramanan * 52303f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 524df0f8479SAnirudh Venkataramanan */ 52503f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs_contig(struct ice_qs_cfg *qs_cfg) 526df0f8479SAnirudh Venkataramanan { 52703f7a986SAnirudh Venkataramanan int offset, i; 528df0f8479SAnirudh Venkataramanan 52903f7a986SAnirudh Venkataramanan mutex_lock(qs_cfg->qs_mutex); 53003f7a986SAnirudh Venkataramanan offset = bitmap_find_next_zero_area(qs_cfg->pf_map, qs_cfg->pf_map_size, 53103f7a986SAnirudh Venkataramanan 0, qs_cfg->q_count, 0); 53203f7a986SAnirudh Venkataramanan if (offset >= qs_cfg->pf_map_size) { 53303f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 53403f7a986SAnirudh Venkataramanan return -ENOMEM; 535df0f8479SAnirudh Venkataramanan } 536df0f8479SAnirudh Venkataramanan 53703f7a986SAnirudh Venkataramanan bitmap_set(qs_cfg->pf_map, offset, qs_cfg->q_count); 53803f7a986SAnirudh Venkataramanan for (i = 0; i < qs_cfg->q_count; i++) 53903f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = i + offset; 54003f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 541df0f8479SAnirudh Venkataramanan 54203f7a986SAnirudh Venkataramanan return 0; 543df0f8479SAnirudh Venkataramanan } 544df0f8479SAnirudh Venkataramanan 545df0f8479SAnirudh Venkataramanan /** 54603f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs_sc - Assign a scattered queues from PF to VSI 54703f7a986SAnirudh Venkataramanan * @qs_cfg: gathered variables needed for PF->VSI queues assignment 548df0f8479SAnirudh Venkataramanan * 54903f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 550df0f8479SAnirudh Venkataramanan */ 55103f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs_sc(struct ice_qs_cfg *qs_cfg) 552df0f8479SAnirudh Venkataramanan { 553df0f8479SAnirudh Venkataramanan int i, index = 0; 554df0f8479SAnirudh Venkataramanan 55503f7a986SAnirudh Venkataramanan mutex_lock(qs_cfg->qs_mutex); 55603f7a986SAnirudh Venkataramanan for (i = 0; i < qs_cfg->q_count; i++) { 55703f7a986SAnirudh Venkataramanan index = find_next_zero_bit(qs_cfg->pf_map, 55803f7a986SAnirudh Venkataramanan qs_cfg->pf_map_size, index); 55903f7a986SAnirudh Venkataramanan if (index >= qs_cfg->pf_map_size) 56003f7a986SAnirudh Venkataramanan goto err_scatter; 56103f7a986SAnirudh Venkataramanan set_bit(index, qs_cfg->pf_map); 56203f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[i + qs_cfg->vsi_map_offset] = index; 56303f7a986SAnirudh Venkataramanan } 56403f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 565df0f8479SAnirudh Venkataramanan 566df0f8479SAnirudh Venkataramanan return 0; 56703f7a986SAnirudh Venkataramanan err_scatter: 568df0f8479SAnirudh Venkataramanan for (index = 0; index < i; index++) { 56903f7a986SAnirudh Venkataramanan clear_bit(qs_cfg->vsi_map[index], qs_cfg->pf_map); 57003f7a986SAnirudh Venkataramanan qs_cfg->vsi_map[index + qs_cfg->vsi_map_offset] = 0; 571df0f8479SAnirudh Venkataramanan } 57203f7a986SAnirudh Venkataramanan mutex_unlock(qs_cfg->qs_mutex); 573df0f8479SAnirudh Venkataramanan 574df0f8479SAnirudh Venkataramanan return -ENOMEM; 575df0f8479SAnirudh Venkataramanan } 576df0f8479SAnirudh Venkataramanan 577df0f8479SAnirudh Venkataramanan /** 57803f7a986SAnirudh Venkataramanan * __ice_vsi_get_qs - helper function for assigning queues from PF to VSI 57903f7a986SAnirudh Venkataramanan * @qs_cfg: gathered variables needed for PF->VSI queues assignment 58003f7a986SAnirudh Venkataramanan * 58103f7a986SAnirudh Venkataramanan * This is an internal function for assigning queues from the PF to VSI and 58203f7a986SAnirudh Venkataramanan * initially tries to find contiguous space. If it is not successful to find 58303f7a986SAnirudh Venkataramanan * contiguous space, then it tries with the scatter approach. 58403f7a986SAnirudh Venkataramanan * 58503f7a986SAnirudh Venkataramanan * Return 0 on success and -ENOMEM in case of no left space in PF queue bitmap 58603f7a986SAnirudh Venkataramanan */ 58703f7a986SAnirudh Venkataramanan static int __ice_vsi_get_qs(struct ice_qs_cfg *qs_cfg) 58803f7a986SAnirudh Venkataramanan { 58903f7a986SAnirudh Venkataramanan int ret = 0; 59003f7a986SAnirudh Venkataramanan 59103f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs_contig(qs_cfg); 59203f7a986SAnirudh Venkataramanan if (ret) { 59303f7a986SAnirudh Venkataramanan /* contig failed, so try with scatter approach */ 59403f7a986SAnirudh Venkataramanan qs_cfg->mapping_mode = ICE_VSI_MAP_SCATTER; 59503f7a986SAnirudh Venkataramanan qs_cfg->q_count = min_t(u16, qs_cfg->q_count, 59603f7a986SAnirudh Venkataramanan qs_cfg->scatter_count); 59703f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs_sc(qs_cfg); 59803f7a986SAnirudh Venkataramanan } 59903f7a986SAnirudh Venkataramanan return ret; 60003f7a986SAnirudh Venkataramanan } 60103f7a986SAnirudh Venkataramanan 60203f7a986SAnirudh Venkataramanan /** 603df0f8479SAnirudh Venkataramanan * ice_vsi_get_qs - Assign queues from PF to VSI 604df0f8479SAnirudh Venkataramanan * @vsi: the VSI to assign queues to 605df0f8479SAnirudh Venkataramanan * 606df0f8479SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 607df0f8479SAnirudh Venkataramanan */ 60837bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi) 609df0f8479SAnirudh Venkataramanan { 61003f7a986SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 61103f7a986SAnirudh Venkataramanan struct ice_qs_cfg tx_qs_cfg = { 61203f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 61303f7a986SAnirudh Venkataramanan .pf_map = pf->avail_txqs, 61403f7a986SAnirudh Venkataramanan .pf_map_size = ICE_MAX_TXQS, 61503f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_txq, 61603f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_TXQS, 61703f7a986SAnirudh Venkataramanan .vsi_map = vsi->txq_map, 61803f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 61903f7a986SAnirudh Venkataramanan .mapping_mode = vsi->tx_mapping_mode 62003f7a986SAnirudh Venkataramanan }; 62103f7a986SAnirudh Venkataramanan struct ice_qs_cfg rx_qs_cfg = { 62203f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 62303f7a986SAnirudh Venkataramanan .pf_map = pf->avail_rxqs, 62403f7a986SAnirudh Venkataramanan .pf_map_size = ICE_MAX_RXQS, 62503f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_rxq, 62603f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_RXQS, 62703f7a986SAnirudh Venkataramanan .vsi_map = vsi->rxq_map, 62803f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 62903f7a986SAnirudh Venkataramanan .mapping_mode = vsi->rx_mapping_mode 63003f7a986SAnirudh Venkataramanan }; 631df0f8479SAnirudh Venkataramanan int ret = 0; 632df0f8479SAnirudh Venkataramanan 633df0f8479SAnirudh Venkataramanan vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG; 634df0f8479SAnirudh Venkataramanan vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG; 635df0f8479SAnirudh Venkataramanan 63603f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&tx_qs_cfg); 63703f7a986SAnirudh Venkataramanan if (!ret) 63803f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&rx_qs_cfg); 639df0f8479SAnirudh Venkataramanan 640df0f8479SAnirudh Venkataramanan return ret; 641df0f8479SAnirudh Venkataramanan } 642df0f8479SAnirudh Venkataramanan 643df0f8479SAnirudh Venkataramanan /** 6445153a18eSAnirudh Venkataramanan * ice_vsi_put_qs - Release queues from VSI to PF 6455153a18eSAnirudh Venkataramanan * @vsi: the VSI that is going to release queues 6465153a18eSAnirudh Venkataramanan */ 6475153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi) 6485153a18eSAnirudh Venkataramanan { 6495153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 6505153a18eSAnirudh Venkataramanan int i; 6515153a18eSAnirudh Venkataramanan 6525153a18eSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 6535153a18eSAnirudh Venkataramanan 6545153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 6555153a18eSAnirudh Venkataramanan clear_bit(vsi->txq_map[i], pf->avail_txqs); 6565153a18eSAnirudh Venkataramanan vsi->txq_map[i] = ICE_INVAL_Q_INDEX; 6575153a18eSAnirudh Venkataramanan } 6585153a18eSAnirudh Venkataramanan 6595153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 6605153a18eSAnirudh Venkataramanan clear_bit(vsi->rxq_map[i], pf->avail_rxqs); 6615153a18eSAnirudh Venkataramanan vsi->rxq_map[i] = ICE_INVAL_Q_INDEX; 6625153a18eSAnirudh Venkataramanan } 6635153a18eSAnirudh Venkataramanan 6645153a18eSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 6655153a18eSAnirudh Venkataramanan } 6665153a18eSAnirudh Venkataramanan 6675153a18eSAnirudh Venkataramanan /** 668df0f8479SAnirudh Venkataramanan * ice_rss_clean - Delete RSS related VSI structures that hold user inputs 669df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 670df0f8479SAnirudh Venkataramanan */ 671df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi) 672df0f8479SAnirudh Venkataramanan { 673df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 674df0f8479SAnirudh Venkataramanan 675df0f8479SAnirudh Venkataramanan pf = vsi->back; 676df0f8479SAnirudh Venkataramanan 677df0f8479SAnirudh Venkataramanan if (vsi->rss_hkey_user) 678df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_hkey_user); 679df0f8479SAnirudh Venkataramanan if (vsi->rss_lut_user) 680df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_lut_user); 681df0f8479SAnirudh Venkataramanan } 682df0f8479SAnirudh Venkataramanan 683df0f8479SAnirudh Venkataramanan /** 68428c2a645SAnirudh Venkataramanan * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type 68528c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 68628c2a645SAnirudh Venkataramanan */ 68737bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi) 68828c2a645SAnirudh Venkataramanan { 68928c2a645SAnirudh Venkataramanan struct ice_hw_common_caps *cap; 69028c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 69128c2a645SAnirudh Venkataramanan 69228c2a645SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 69328c2a645SAnirudh Venkataramanan vsi->rss_size = 1; 69428c2a645SAnirudh Venkataramanan return; 69528c2a645SAnirudh Venkataramanan } 69628c2a645SAnirudh Venkataramanan 69728c2a645SAnirudh Venkataramanan cap = &pf->hw.func_caps.common_cap; 69828c2a645SAnirudh Venkataramanan switch (vsi->type) { 69928c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 70028c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 70128c2a645SAnirudh Venkataramanan vsi->rss_table_size = cap->rss_table_size; 70228c2a645SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 70328c2a645SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 70428c2a645SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; 70528c2a645SAnirudh Venkataramanan break; 7068ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 7078ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table 7088ede0178SAnirudh Venkataramanan * For VSI_LUT, LUT size should be set to 64 bytes 7098ede0178SAnirudh Venkataramanan */ 7108ede0178SAnirudh Venkataramanan vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 7118ede0178SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 7128ede0178SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 7138ede0178SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 7148ede0178SAnirudh Venkataramanan break; 71528c2a645SAnirudh Venkataramanan default: 71628c2a645SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", 71728c2a645SAnirudh Venkataramanan vsi->type); 71828c2a645SAnirudh Venkataramanan break; 71928c2a645SAnirudh Venkataramanan } 72028c2a645SAnirudh Venkataramanan } 72128c2a645SAnirudh Venkataramanan 72228c2a645SAnirudh Venkataramanan /** 72328c2a645SAnirudh Venkataramanan * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI 72428c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 72528c2a645SAnirudh Venkataramanan * 72628c2a645SAnirudh Venkataramanan * This initializes a default VSI context for all sections except the Queues. 72728c2a645SAnirudh Venkataramanan */ 72828c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) 72928c2a645SAnirudh Venkataramanan { 73028c2a645SAnirudh Venkataramanan u32 table = 0; 73128c2a645SAnirudh Venkataramanan 73228c2a645SAnirudh Venkataramanan memset(&ctxt->info, 0, sizeof(ctxt->info)); 73328c2a645SAnirudh Venkataramanan /* VSI's should be allocated from shared pool */ 73428c2a645SAnirudh Venkataramanan ctxt->alloc_from_pool = true; 73528c2a645SAnirudh Venkataramanan /* Src pruning enabled by default */ 73628c2a645SAnirudh Venkataramanan ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; 73728c2a645SAnirudh Venkataramanan /* Traffic from VSI can be sent to LAN */ 73828c2a645SAnirudh Venkataramanan ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; 73928c2a645SAnirudh Venkataramanan /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy 74028c2a645SAnirudh Venkataramanan * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all 74128c2a645SAnirudh Venkataramanan * packets untagged/tagged. 74228c2a645SAnirudh Venkataramanan */ 74328c2a645SAnirudh Venkataramanan ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & 74428c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_M) >> 74528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_S); 74628c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for both ingress/egress tables */ 74728c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(0, 0); 74828c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(1, 1); 74928c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(2, 2); 75028c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(3, 3); 75128c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(4, 4); 75228c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(5, 5); 75328c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(6, 6); 75428c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(7, 7); 75528c2a645SAnirudh Venkataramanan ctxt->info.ingress_table = cpu_to_le32(table); 75628c2a645SAnirudh Venkataramanan ctxt->info.egress_table = cpu_to_le32(table); 75728c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for outer to inner UP table */ 75828c2a645SAnirudh Venkataramanan ctxt->info.outer_up_table = cpu_to_le32(table); 75928c2a645SAnirudh Venkataramanan /* No Outer tag support outer_tag_flags remains to zero */ 76028c2a645SAnirudh Venkataramanan } 76128c2a645SAnirudh Venkataramanan 76228c2a645SAnirudh Venkataramanan /** 76328c2a645SAnirudh Venkataramanan * ice_vsi_setup_q_map - Setup a VSI queue map 76428c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 76528c2a645SAnirudh Venkataramanan * @ctxt: VSI context structure 76628c2a645SAnirudh Venkataramanan */ 76728c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 76828c2a645SAnirudh Venkataramanan { 769c5a2a4a3SUsha Ketineni u16 offset = 0, qmap = 0, tx_count = 0; 77028c2a645SAnirudh Venkataramanan u16 qcount_tx = vsi->alloc_txq; 77128c2a645SAnirudh Venkataramanan u16 qcount_rx = vsi->alloc_rxq; 772c5a2a4a3SUsha Ketineni u16 tx_numq_tc, rx_numq_tc; 773c5a2a4a3SUsha Ketineni u16 pow = 0, max_rss = 0; 77428c2a645SAnirudh Venkataramanan bool ena_tc0 = false; 775c5a2a4a3SUsha Ketineni u8 netdev_tc = 0; 77628c2a645SAnirudh Venkataramanan int i; 77728c2a645SAnirudh Venkataramanan 77828c2a645SAnirudh Venkataramanan /* at least TC0 should be enabled by default */ 77928c2a645SAnirudh Venkataramanan if (vsi->tc_cfg.numtc) { 78028c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(0))) 78128c2a645SAnirudh Venkataramanan ena_tc0 = true; 78228c2a645SAnirudh Venkataramanan } else { 78328c2a645SAnirudh Venkataramanan ena_tc0 = true; 78428c2a645SAnirudh Venkataramanan } 78528c2a645SAnirudh Venkataramanan 78628c2a645SAnirudh Venkataramanan if (ena_tc0) { 78728c2a645SAnirudh Venkataramanan vsi->tc_cfg.numtc++; 78828c2a645SAnirudh Venkataramanan vsi->tc_cfg.ena_tc |= 1; 78928c2a645SAnirudh Venkataramanan } 79028c2a645SAnirudh Venkataramanan 791c5a2a4a3SUsha Ketineni rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc; 792c5a2a4a3SUsha Ketineni if (!rx_numq_tc) 793c5a2a4a3SUsha Ketineni rx_numq_tc = 1; 794c5a2a4a3SUsha Ketineni tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc; 795c5a2a4a3SUsha Ketineni if (!tx_numq_tc) 796c5a2a4a3SUsha Ketineni tx_numq_tc = 1; 79728c2a645SAnirudh Venkataramanan 79828c2a645SAnirudh Venkataramanan /* TC mapping is a function of the number of Rx queues assigned to the 79928c2a645SAnirudh Venkataramanan * VSI for each traffic class and the offset of these queues. 80028c2a645SAnirudh Venkataramanan * The first 10 bits are for queue offset for TC0, next 4 bits for no:of 80128c2a645SAnirudh Venkataramanan * queues allocated to TC0. No:of queues is a power-of-2. 80228c2a645SAnirudh Venkataramanan * 80328c2a645SAnirudh Venkataramanan * If TC is not enabled, the queue offset is set to 0, and allocate one 80428c2a645SAnirudh Venkataramanan * queue, this way, traffic for the given TC will be sent to the default 80528c2a645SAnirudh Venkataramanan * queue. 80628c2a645SAnirudh Venkataramanan * 80728c2a645SAnirudh Venkataramanan * Setup number and offset of Rx queues for all TCs for the VSI 80828c2a645SAnirudh Venkataramanan */ 80928c2a645SAnirudh Venkataramanan 810c5a2a4a3SUsha Ketineni qcount_rx = rx_numq_tc; 811c5a2a4a3SUsha Ketineni 81228c2a645SAnirudh Venkataramanan /* qcount will change if RSS is enabled */ 81328c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) { 8148ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) { 81528c2a645SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) 81628c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_LG_RSS_QS; 81728c2a645SAnirudh Venkataramanan else 81828c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_SMALL_RSS_QS; 819c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, rx_numq_tc, max_rss); 820c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, qcount_rx, vsi->rss_size); 8218ede0178SAnirudh Venkataramanan } 82228c2a645SAnirudh Venkataramanan } 82328c2a645SAnirudh Venkataramanan 82428c2a645SAnirudh Venkataramanan /* find the (rounded up) power-of-2 of qcount */ 825c5a2a4a3SUsha Ketineni pow = order_base_2(qcount_rx); 82628c2a645SAnirudh Venkataramanan 82728c2a645SAnirudh Venkataramanan for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) { 82828c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 82928c2a645SAnirudh Venkataramanan /* TC is not enabled */ 83028c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = 0; 831c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = 1; 832c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = 1; 833c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = 0; 83428c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = 0; 83528c2a645SAnirudh Venkataramanan continue; 83628c2a645SAnirudh Venkataramanan } 83728c2a645SAnirudh Venkataramanan 83828c2a645SAnirudh Venkataramanan /* TC is enabled */ 83928c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = offset; 840c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx; 841c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc; 842c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 84328c2a645SAnirudh Venkataramanan 84428c2a645SAnirudh Venkataramanan qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 84528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_OFFSET_M) | 84628c2a645SAnirudh Venkataramanan ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 84728c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_NUM_M); 848c5a2a4a3SUsha Ketineni offset += qcount_rx; 849c5a2a4a3SUsha Ketineni tx_count += tx_numq_tc; 85028c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); 85128c2a645SAnirudh Venkataramanan } 85228c2a645SAnirudh Venkataramanan vsi->num_rxq = offset; 853c5a2a4a3SUsha Ketineni vsi->num_txq = tx_count; 85428c2a645SAnirudh Venkataramanan 8558ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) { 8568ede0178SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n"); 8578ede0178SAnirudh Venkataramanan /* since there is a chance that num_rxq could have been changed 8588ede0178SAnirudh Venkataramanan * in the above for loop, make num_txq equal to num_rxq. 8598ede0178SAnirudh Venkataramanan */ 8608ede0178SAnirudh Venkataramanan vsi->num_txq = vsi->num_rxq; 8618ede0178SAnirudh Venkataramanan } 8628ede0178SAnirudh Venkataramanan 86328c2a645SAnirudh Venkataramanan /* Rx queue mapping */ 86428c2a645SAnirudh Venkataramanan ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 86528c2a645SAnirudh Venkataramanan /* q_mapping buffer holds the info for the first queue allocated for 86628c2a645SAnirudh Venkataramanan * this VSI in the PF space and also the number of queues associated 86728c2a645SAnirudh Venkataramanan * with this VSI. 86828c2a645SAnirudh Venkataramanan */ 86928c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 87028c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq); 87128c2a645SAnirudh Venkataramanan } 87228c2a645SAnirudh Venkataramanan 87328c2a645SAnirudh Venkataramanan /** 87428c2a645SAnirudh Venkataramanan * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI 87528c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 87628c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 87728c2a645SAnirudh Venkataramanan */ 87828c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 87928c2a645SAnirudh Venkataramanan { 88028c2a645SAnirudh Venkataramanan u8 lut_type, hash_type; 88128c2a645SAnirudh Venkataramanan 88228c2a645SAnirudh Venkataramanan switch (vsi->type) { 88328c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 88428c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 88528c2a645SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; 88628c2a645SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 88728c2a645SAnirudh Venkataramanan break; 8888ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 8898ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table which is a VSI LUT type */ 8908ede0178SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 8918ede0178SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 8928ede0178SAnirudh Venkataramanan break; 89328c2a645SAnirudh Venkataramanan default: 89428c2a645SAnirudh Venkataramanan dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n", 89528c2a645SAnirudh Venkataramanan vsi->type); 89628c2a645SAnirudh Venkataramanan return; 89728c2a645SAnirudh Venkataramanan } 89828c2a645SAnirudh Venkataramanan 89928c2a645SAnirudh Venkataramanan ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & 90028c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | 90128c2a645SAnirudh Venkataramanan ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & 90228c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_HASH_M); 90328c2a645SAnirudh Venkataramanan } 90428c2a645SAnirudh Venkataramanan 90528c2a645SAnirudh Venkataramanan /** 90628c2a645SAnirudh Venkataramanan * ice_vsi_init - Create and initialize a VSI 90728c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 90828c2a645SAnirudh Venkataramanan * 90928c2a645SAnirudh Venkataramanan * This initializes a VSI context depending on the VSI type to be added and 91028c2a645SAnirudh Venkataramanan * passes it down to the add_vsi aq command to create a new VSI. 91128c2a645SAnirudh Venkataramanan */ 91237bb8390SAnirudh Venkataramanan static int ice_vsi_init(struct ice_vsi *vsi) 91328c2a645SAnirudh Venkataramanan { 91428c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 91528c2a645SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 916198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 91728c2a645SAnirudh Venkataramanan int ret = 0; 91828c2a645SAnirudh Venkataramanan 919198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 920198a666aSBruce Allan if (!ctxt) 921198a666aSBruce Allan return -ENOMEM; 922198a666aSBruce Allan 92328c2a645SAnirudh Venkataramanan switch (vsi->type) { 92428c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 925198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_PF; 92628c2a645SAnirudh Venkataramanan break; 9278ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 928198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_VF; 9298ede0178SAnirudh Venkataramanan /* VF number here is the absolute VF number (0-255) */ 930198a666aSBruce Allan ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; 9318ede0178SAnirudh Venkataramanan break; 93228c2a645SAnirudh Venkataramanan default: 93328c2a645SAnirudh Venkataramanan return -ENODEV; 93428c2a645SAnirudh Venkataramanan } 93528c2a645SAnirudh Venkataramanan 936198a666aSBruce Allan ice_set_dflt_vsi_ctx(ctxt); 93728c2a645SAnirudh Venkataramanan /* if the switch is in VEB mode, allow VSI loopback */ 93828c2a645SAnirudh Venkataramanan if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) 939198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 94028c2a645SAnirudh Venkataramanan 94128c2a645SAnirudh Venkataramanan /* Set LUT type and HASH type if RSS is enabled */ 94228c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 943198a666aSBruce Allan ice_set_rss_vsi_ctx(ctxt, vsi); 94428c2a645SAnirudh Venkataramanan 945198a666aSBruce Allan ctxt->info.sw_id = vsi->port_info->sw_id; 946198a666aSBruce Allan ice_vsi_setup_q_map(vsi, ctxt); 94728c2a645SAnirudh Venkataramanan 948198a666aSBruce Allan ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); 94928c2a645SAnirudh Venkataramanan if (ret) { 95028c2a645SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 95128c2a645SAnirudh Venkataramanan "Add VSI failed, err %d\n", ret); 95228c2a645SAnirudh Venkataramanan return -EIO; 95328c2a645SAnirudh Venkataramanan } 95428c2a645SAnirudh Venkataramanan 95528c2a645SAnirudh Venkataramanan /* keep context for update VSI operations */ 956198a666aSBruce Allan vsi->info = ctxt->info; 95728c2a645SAnirudh Venkataramanan 95828c2a645SAnirudh Venkataramanan /* record VSI number returned */ 959198a666aSBruce Allan vsi->vsi_num = ctxt->vsi_num; 96028c2a645SAnirudh Venkataramanan 961198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 96228c2a645SAnirudh Venkataramanan return ret; 96328c2a645SAnirudh Venkataramanan } 96428c2a645SAnirudh Venkataramanan 96528c2a645SAnirudh Venkataramanan /** 966df0f8479SAnirudh Venkataramanan * ice_free_q_vector - Free memory allocated for a specific interrupt vector 967df0f8479SAnirudh Venkataramanan * @vsi: VSI having the memory freed 968df0f8479SAnirudh Venkataramanan * @v_idx: index of the vector to be freed 969df0f8479SAnirudh Venkataramanan */ 970df0f8479SAnirudh Venkataramanan static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx) 971df0f8479SAnirudh Venkataramanan { 972df0f8479SAnirudh Venkataramanan struct ice_q_vector *q_vector; 973df0f8479SAnirudh Venkataramanan struct ice_ring *ring; 974df0f8479SAnirudh Venkataramanan 975df0f8479SAnirudh Venkataramanan if (!vsi->q_vectors[v_idx]) { 976df0f8479SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, "Queue vector at index %d not found\n", 977df0f8479SAnirudh Venkataramanan v_idx); 978df0f8479SAnirudh Venkataramanan return; 979df0f8479SAnirudh Venkataramanan } 980df0f8479SAnirudh Venkataramanan q_vector = vsi->q_vectors[v_idx]; 981df0f8479SAnirudh Venkataramanan 982df0f8479SAnirudh Venkataramanan ice_for_each_ring(ring, q_vector->tx) 983df0f8479SAnirudh Venkataramanan ring->q_vector = NULL; 984df0f8479SAnirudh Venkataramanan ice_for_each_ring(ring, q_vector->rx) 985df0f8479SAnirudh Venkataramanan ring->q_vector = NULL; 986df0f8479SAnirudh Venkataramanan 987df0f8479SAnirudh Venkataramanan /* only VSI with an associated netdev is set up with NAPI */ 988df0f8479SAnirudh Venkataramanan if (vsi->netdev) 989df0f8479SAnirudh Venkataramanan netif_napi_del(&q_vector->napi); 990df0f8479SAnirudh Venkataramanan 991df0f8479SAnirudh Venkataramanan devm_kfree(&vsi->back->pdev->dev, q_vector); 992df0f8479SAnirudh Venkataramanan vsi->q_vectors[v_idx] = NULL; 993df0f8479SAnirudh Venkataramanan } 994df0f8479SAnirudh Venkataramanan 995df0f8479SAnirudh Venkataramanan /** 996df0f8479SAnirudh Venkataramanan * ice_vsi_free_q_vectors - Free memory allocated for interrupt vectors 997df0f8479SAnirudh Venkataramanan * @vsi: the VSI having memory freed 998df0f8479SAnirudh Venkataramanan */ 999df0f8479SAnirudh Venkataramanan void ice_vsi_free_q_vectors(struct ice_vsi *vsi) 1000df0f8479SAnirudh Venkataramanan { 1001df0f8479SAnirudh Venkataramanan int v_idx; 1002df0f8479SAnirudh Venkataramanan 1003df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) 1004df0f8479SAnirudh Venkataramanan ice_free_q_vector(vsi, v_idx); 1005df0f8479SAnirudh Venkataramanan } 1006df0f8479SAnirudh Venkataramanan 1007df0f8479SAnirudh Venkataramanan /** 1008df0f8479SAnirudh Venkataramanan * ice_vsi_alloc_q_vector - Allocate memory for a single interrupt vector 1009df0f8479SAnirudh Venkataramanan * @vsi: the VSI being configured 1010df0f8479SAnirudh Venkataramanan * @v_idx: index of the vector in the VSI struct 1011df0f8479SAnirudh Venkataramanan * 1012df0f8479SAnirudh Venkataramanan * We allocate one q_vector. If allocation fails we return -ENOMEM. 1013df0f8479SAnirudh Venkataramanan */ 1014df0f8479SAnirudh Venkataramanan static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, int v_idx) 1015df0f8479SAnirudh Venkataramanan { 1016df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1017df0f8479SAnirudh Venkataramanan struct ice_q_vector *q_vector; 1018df0f8479SAnirudh Venkataramanan 1019df0f8479SAnirudh Venkataramanan /* allocate q_vector */ 1020df0f8479SAnirudh Venkataramanan q_vector = devm_kzalloc(&pf->pdev->dev, sizeof(*q_vector), GFP_KERNEL); 1021df0f8479SAnirudh Venkataramanan if (!q_vector) 1022df0f8479SAnirudh Venkataramanan return -ENOMEM; 1023df0f8479SAnirudh Venkataramanan 1024df0f8479SAnirudh Venkataramanan q_vector->vsi = vsi; 1025df0f8479SAnirudh Venkataramanan q_vector->v_idx = v_idx; 10268ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 10278ede0178SAnirudh Venkataramanan goto out; 1028df0f8479SAnirudh Venkataramanan /* only set affinity_mask if the CPU is online */ 1029df0f8479SAnirudh Venkataramanan if (cpu_online(v_idx)) 1030df0f8479SAnirudh Venkataramanan cpumask_set_cpu(v_idx, &q_vector->affinity_mask); 1031df0f8479SAnirudh Venkataramanan 1032df0f8479SAnirudh Venkataramanan /* This will not be called in the driver load path because the netdev 1033df0f8479SAnirudh Venkataramanan * will not be created yet. All other cases with register the NAPI 1034df0f8479SAnirudh Venkataramanan * handler here (i.e. resume, reset/rebuild, etc.) 1035df0f8479SAnirudh Venkataramanan */ 1036df0f8479SAnirudh Venkataramanan if (vsi->netdev) 1037df0f8479SAnirudh Venkataramanan netif_napi_add(vsi->netdev, &q_vector->napi, ice_napi_poll, 1038df0f8479SAnirudh Venkataramanan NAPI_POLL_WEIGHT); 1039df0f8479SAnirudh Venkataramanan 10408ede0178SAnirudh Venkataramanan out: 1041df0f8479SAnirudh Venkataramanan /* tie q_vector and VSI together */ 1042df0f8479SAnirudh Venkataramanan vsi->q_vectors[v_idx] = q_vector; 1043df0f8479SAnirudh Venkataramanan 1044df0f8479SAnirudh Venkataramanan return 0; 1045df0f8479SAnirudh Venkataramanan } 1046df0f8479SAnirudh Venkataramanan 1047df0f8479SAnirudh Venkataramanan /** 1048df0f8479SAnirudh Venkataramanan * ice_vsi_alloc_q_vectors - Allocate memory for interrupt vectors 1049df0f8479SAnirudh Venkataramanan * @vsi: the VSI being configured 1050df0f8479SAnirudh Venkataramanan * 1051df0f8479SAnirudh Venkataramanan * We allocate one q_vector per queue interrupt. If allocation fails we 1052df0f8479SAnirudh Venkataramanan * return -ENOMEM. 1053df0f8479SAnirudh Venkataramanan */ 105437bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_q_vectors(struct ice_vsi *vsi) 1055df0f8479SAnirudh Venkataramanan { 1056df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1057df0f8479SAnirudh Venkataramanan int v_idx = 0, num_q_vectors; 1058df0f8479SAnirudh Venkataramanan int err; 1059df0f8479SAnirudh Venkataramanan 1060df0f8479SAnirudh Venkataramanan if (vsi->q_vectors[0]) { 1061df0f8479SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "VSI %d has existing q_vectors\n", 1062df0f8479SAnirudh Venkataramanan vsi->vsi_num); 1063df0f8479SAnirudh Venkataramanan return -EEXIST; 1064df0f8479SAnirudh Venkataramanan } 1065df0f8479SAnirudh Venkataramanan 1066df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 1067df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1068df0f8479SAnirudh Venkataramanan } else { 1069df0f8479SAnirudh Venkataramanan err = -EINVAL; 1070df0f8479SAnirudh Venkataramanan goto err_out; 1071df0f8479SAnirudh Venkataramanan } 1072df0f8479SAnirudh Venkataramanan 1073df0f8479SAnirudh Venkataramanan for (v_idx = 0; v_idx < num_q_vectors; v_idx++) { 1074df0f8479SAnirudh Venkataramanan err = ice_vsi_alloc_q_vector(vsi, v_idx); 1075df0f8479SAnirudh Venkataramanan if (err) 1076df0f8479SAnirudh Venkataramanan goto err_out; 1077df0f8479SAnirudh Venkataramanan } 1078df0f8479SAnirudh Venkataramanan 1079df0f8479SAnirudh Venkataramanan return 0; 1080df0f8479SAnirudh Venkataramanan 1081df0f8479SAnirudh Venkataramanan err_out: 1082df0f8479SAnirudh Venkataramanan while (v_idx--) 1083df0f8479SAnirudh Venkataramanan ice_free_q_vector(vsi, v_idx); 1084df0f8479SAnirudh Venkataramanan 1085df0f8479SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1086df0f8479SAnirudh Venkataramanan "Failed to allocate %d q_vector for VSI %d, ret=%d\n", 1087df0f8479SAnirudh Venkataramanan vsi->num_q_vectors, vsi->vsi_num, err); 1088df0f8479SAnirudh Venkataramanan vsi->num_q_vectors = 0; 1089df0f8479SAnirudh Venkataramanan return err; 1090df0f8479SAnirudh Venkataramanan } 1091df0f8479SAnirudh Venkataramanan 1092df0f8479SAnirudh Venkataramanan /** 1093df0f8479SAnirudh Venkataramanan * ice_vsi_setup_vector_base - Set up the base vector for the given VSI 1094df0f8479SAnirudh Venkataramanan * @vsi: ptr to the VSI 1095df0f8479SAnirudh Venkataramanan * 1096df0f8479SAnirudh Venkataramanan * This should only be called after ice_vsi_alloc() which allocates the 1097df0f8479SAnirudh Venkataramanan * corresponding SW VSI structure and initializes num_queue_pairs for the 1098df0f8479SAnirudh Venkataramanan * newly allocated VSI. 1099df0f8479SAnirudh Venkataramanan * 1100df0f8479SAnirudh Venkataramanan * Returns 0 on success or negative on failure 1101df0f8479SAnirudh Venkataramanan */ 110237bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) 1103df0f8479SAnirudh Venkataramanan { 1104df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1105df0f8479SAnirudh Venkataramanan int num_q_vectors = 0; 1106df0f8479SAnirudh Venkataramanan 1107eb0208ecSPreethi Banala if (vsi->sw_base_vector || vsi->hw_base_vector) { 1108eb0208ecSPreethi Banala dev_dbg(&pf->pdev->dev, "VSI %d has non-zero HW base vector %d or SW base vector %d\n", 1109eb0208ecSPreethi Banala vsi->vsi_num, vsi->hw_base_vector, vsi->sw_base_vector); 1110df0f8479SAnirudh Venkataramanan return -EEXIST; 1111df0f8479SAnirudh Venkataramanan } 1112df0f8479SAnirudh Venkataramanan 1113df0f8479SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) 1114df0f8479SAnirudh Venkataramanan return -ENOENT; 1115df0f8479SAnirudh Venkataramanan 1116df0f8479SAnirudh Venkataramanan switch (vsi->type) { 1117df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 1118df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1119eb0208ecSPreethi Banala /* reserve slots from OS requested IRQs */ 1120eb0208ecSPreethi Banala vsi->sw_base_vector = ice_get_res(pf, pf->sw_irq_tracker, 1121eb0208ecSPreethi Banala num_q_vectors, vsi->idx); 1122eb0208ecSPreethi Banala if (vsi->sw_base_vector < 0) { 1123eb0208ecSPreethi Banala dev_err(&pf->pdev->dev, 1124eb0208ecSPreethi Banala "Failed to get tracking for %d SW vectors for VSI %d, err=%d\n", 1125eb0208ecSPreethi Banala num_q_vectors, vsi->vsi_num, 1126eb0208ecSPreethi Banala vsi->sw_base_vector); 1127eb0208ecSPreethi Banala return -ENOENT; 1128eb0208ecSPreethi Banala } 1129eb0208ecSPreethi Banala pf->num_avail_sw_msix -= num_q_vectors; 1130eb0208ecSPreethi Banala 1131eb0208ecSPreethi Banala /* reserve slots from HW interrupts */ 1132eb0208ecSPreethi Banala vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker, 1133eb0208ecSPreethi Banala num_q_vectors, vsi->idx); 1134df0f8479SAnirudh Venkataramanan break; 11358ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 11368ede0178SAnirudh Venkataramanan /* take VF misc vector and data vectors into account */ 11378ede0178SAnirudh Venkataramanan num_q_vectors = pf->num_vf_msix; 11388ede0178SAnirudh Venkataramanan /* For VF VSI, reserve slots only from HW interrupts */ 11398ede0178SAnirudh Venkataramanan vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker, 11408ede0178SAnirudh Venkataramanan num_q_vectors, vsi->idx); 11418ede0178SAnirudh Venkataramanan break; 1142df0f8479SAnirudh Venkataramanan default: 1143df0f8479SAnirudh Venkataramanan dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n", 1144df0f8479SAnirudh Venkataramanan vsi->type); 1145df0f8479SAnirudh Venkataramanan break; 1146df0f8479SAnirudh Venkataramanan } 1147df0f8479SAnirudh Venkataramanan 1148eb0208ecSPreethi Banala if (vsi->hw_base_vector < 0) { 1149df0f8479SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1150eb0208ecSPreethi Banala "Failed to get tracking for %d HW vectors for VSI %d, err=%d\n", 1151eb0208ecSPreethi Banala num_q_vectors, vsi->vsi_num, vsi->hw_base_vector); 11528ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 11538ede0178SAnirudh Venkataramanan ice_free_res(vsi->back->sw_irq_tracker, 11548ede0178SAnirudh Venkataramanan vsi->sw_base_vector, vsi->idx); 1155eb0208ecSPreethi Banala pf->num_avail_sw_msix += num_q_vectors; 11568ede0178SAnirudh Venkataramanan } 1157df0f8479SAnirudh Venkataramanan return -ENOENT; 1158df0f8479SAnirudh Venkataramanan } 1159df0f8479SAnirudh Venkataramanan 1160eb0208ecSPreethi Banala pf->num_avail_hw_msix -= num_q_vectors; 1161eb0208ecSPreethi Banala 1162df0f8479SAnirudh Venkataramanan return 0; 1163df0f8479SAnirudh Venkataramanan } 1164df0f8479SAnirudh Venkataramanan 1165df0f8479SAnirudh Venkataramanan /** 116628c2a645SAnirudh Venkataramanan * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI 116728c2a645SAnirudh Venkataramanan * @vsi: the VSI having rings deallocated 116828c2a645SAnirudh Venkataramanan */ 1169df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi) 117028c2a645SAnirudh Venkataramanan { 117128c2a645SAnirudh Venkataramanan int i; 117228c2a645SAnirudh Venkataramanan 117328c2a645SAnirudh Venkataramanan if (vsi->tx_rings) { 117428c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 117528c2a645SAnirudh Venkataramanan if (vsi->tx_rings[i]) { 117628c2a645SAnirudh Venkataramanan kfree_rcu(vsi->tx_rings[i], rcu); 117728c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = NULL; 117828c2a645SAnirudh Venkataramanan } 117928c2a645SAnirudh Venkataramanan } 118028c2a645SAnirudh Venkataramanan } 118128c2a645SAnirudh Venkataramanan if (vsi->rx_rings) { 118228c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 118328c2a645SAnirudh Venkataramanan if (vsi->rx_rings[i]) { 118428c2a645SAnirudh Venkataramanan kfree_rcu(vsi->rx_rings[i], rcu); 118528c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = NULL; 118628c2a645SAnirudh Venkataramanan } 118728c2a645SAnirudh Venkataramanan } 118828c2a645SAnirudh Venkataramanan } 118928c2a645SAnirudh Venkataramanan } 119028c2a645SAnirudh Venkataramanan 119128c2a645SAnirudh Venkataramanan /** 119228c2a645SAnirudh Venkataramanan * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI 119328c2a645SAnirudh Venkataramanan * @vsi: VSI which is having rings allocated 119428c2a645SAnirudh Venkataramanan */ 119537bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi) 119628c2a645SAnirudh Venkataramanan { 119728c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 119828c2a645SAnirudh Venkataramanan int i; 119928c2a645SAnirudh Venkataramanan 1200d337f2afSAnirudh Venkataramanan /* Allocate Tx rings */ 120128c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 120228c2a645SAnirudh Venkataramanan struct ice_ring *ring; 120328c2a645SAnirudh Venkataramanan 120428c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 120528c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 120628c2a645SAnirudh Venkataramanan 120728c2a645SAnirudh Venkataramanan if (!ring) 120828c2a645SAnirudh Venkataramanan goto err_out; 120928c2a645SAnirudh Venkataramanan 121028c2a645SAnirudh Venkataramanan ring->q_index = i; 121128c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->txq_map[i]; 121228c2a645SAnirudh Venkataramanan ring->ring_active = false; 121328c2a645SAnirudh Venkataramanan ring->vsi = vsi; 121428c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 121528c2a645SAnirudh Venkataramanan ring->count = vsi->num_desc; 121628c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = ring; 121728c2a645SAnirudh Venkataramanan } 121828c2a645SAnirudh Venkataramanan 1219d337f2afSAnirudh Venkataramanan /* Allocate Rx rings */ 122028c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 122128c2a645SAnirudh Venkataramanan struct ice_ring *ring; 122228c2a645SAnirudh Venkataramanan 122328c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 122428c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 122528c2a645SAnirudh Venkataramanan if (!ring) 122628c2a645SAnirudh Venkataramanan goto err_out; 122728c2a645SAnirudh Venkataramanan 122828c2a645SAnirudh Venkataramanan ring->q_index = i; 122928c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->rxq_map[i]; 123028c2a645SAnirudh Venkataramanan ring->ring_active = false; 123128c2a645SAnirudh Venkataramanan ring->vsi = vsi; 123228c2a645SAnirudh Venkataramanan ring->netdev = vsi->netdev; 123328c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 123428c2a645SAnirudh Venkataramanan ring->count = vsi->num_desc; 123528c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = ring; 123628c2a645SAnirudh Venkataramanan } 123728c2a645SAnirudh Venkataramanan 123828c2a645SAnirudh Venkataramanan return 0; 123928c2a645SAnirudh Venkataramanan 124028c2a645SAnirudh Venkataramanan err_out: 124128c2a645SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 124228c2a645SAnirudh Venkataramanan return -ENOMEM; 124328c2a645SAnirudh Venkataramanan } 124428c2a645SAnirudh Venkataramanan 124528c2a645SAnirudh Venkataramanan /** 124607309a0eSAnirudh Venkataramanan * ice_vsi_map_rings_to_vectors - Map VSI rings to interrupt vectors 124707309a0eSAnirudh Venkataramanan * @vsi: the VSI being configured 124807309a0eSAnirudh Venkataramanan * 124907309a0eSAnirudh Venkataramanan * This function maps descriptor rings to the queue-specific vectors allotted 125007309a0eSAnirudh Venkataramanan * through the MSI-X enabling code. On a constrained vector budget, we map Tx 125107309a0eSAnirudh Venkataramanan * and Rx rings to the vector as "efficiently" as possible. 125207309a0eSAnirudh Venkataramanan */ 125337bb8390SAnirudh Venkataramanan static void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi) 125407309a0eSAnirudh Venkataramanan { 125507309a0eSAnirudh Venkataramanan int q_vectors = vsi->num_q_vectors; 125607309a0eSAnirudh Venkataramanan int tx_rings_rem, rx_rings_rem; 125707309a0eSAnirudh Venkataramanan int v_id; 125807309a0eSAnirudh Venkataramanan 125907309a0eSAnirudh Venkataramanan /* initially assigning remaining rings count to VSIs num queue value */ 126007309a0eSAnirudh Venkataramanan tx_rings_rem = vsi->num_txq; 126107309a0eSAnirudh Venkataramanan rx_rings_rem = vsi->num_rxq; 126207309a0eSAnirudh Venkataramanan 126307309a0eSAnirudh Venkataramanan for (v_id = 0; v_id < q_vectors; v_id++) { 126407309a0eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[v_id]; 126507309a0eSAnirudh Venkataramanan int tx_rings_per_v, rx_rings_per_v, q_id, q_base; 126607309a0eSAnirudh Venkataramanan 126707309a0eSAnirudh Venkataramanan /* Tx rings mapping to vector */ 126807309a0eSAnirudh Venkataramanan tx_rings_per_v = DIV_ROUND_UP(tx_rings_rem, q_vectors - v_id); 126907309a0eSAnirudh Venkataramanan q_vector->num_ring_tx = tx_rings_per_v; 127007309a0eSAnirudh Venkataramanan q_vector->tx.ring = NULL; 1271d2b464a7SBrett Creeley q_vector->tx.itr_idx = ICE_TX_ITR; 127207309a0eSAnirudh Venkataramanan q_base = vsi->num_txq - tx_rings_rem; 127307309a0eSAnirudh Venkataramanan 127407309a0eSAnirudh Venkataramanan for (q_id = q_base; q_id < (q_base + tx_rings_per_v); q_id++) { 127507309a0eSAnirudh Venkataramanan struct ice_ring *tx_ring = vsi->tx_rings[q_id]; 127607309a0eSAnirudh Venkataramanan 127707309a0eSAnirudh Venkataramanan tx_ring->q_vector = q_vector; 127807309a0eSAnirudh Venkataramanan tx_ring->next = q_vector->tx.ring; 127907309a0eSAnirudh Venkataramanan q_vector->tx.ring = tx_ring; 128007309a0eSAnirudh Venkataramanan } 128107309a0eSAnirudh Venkataramanan tx_rings_rem -= tx_rings_per_v; 128207309a0eSAnirudh Venkataramanan 128307309a0eSAnirudh Venkataramanan /* Rx rings mapping to vector */ 128407309a0eSAnirudh Venkataramanan rx_rings_per_v = DIV_ROUND_UP(rx_rings_rem, q_vectors - v_id); 128507309a0eSAnirudh Venkataramanan q_vector->num_ring_rx = rx_rings_per_v; 128607309a0eSAnirudh Venkataramanan q_vector->rx.ring = NULL; 1287d2b464a7SBrett Creeley q_vector->rx.itr_idx = ICE_RX_ITR; 128807309a0eSAnirudh Venkataramanan q_base = vsi->num_rxq - rx_rings_rem; 128907309a0eSAnirudh Venkataramanan 129007309a0eSAnirudh Venkataramanan for (q_id = q_base; q_id < (q_base + rx_rings_per_v); q_id++) { 129107309a0eSAnirudh Venkataramanan struct ice_ring *rx_ring = vsi->rx_rings[q_id]; 129207309a0eSAnirudh Venkataramanan 129307309a0eSAnirudh Venkataramanan rx_ring->q_vector = q_vector; 129407309a0eSAnirudh Venkataramanan rx_ring->next = q_vector->rx.ring; 129507309a0eSAnirudh Venkataramanan q_vector->rx.ring = rx_ring; 129607309a0eSAnirudh Venkataramanan } 129707309a0eSAnirudh Venkataramanan rx_rings_rem -= rx_rings_per_v; 129807309a0eSAnirudh Venkataramanan } 129907309a0eSAnirudh Venkataramanan } 130007309a0eSAnirudh Venkataramanan 130107309a0eSAnirudh Venkataramanan /** 1302492af0abSMd Fahad Iqbal Polash * ice_vsi_manage_rss_lut - disable/enable RSS 1303492af0abSMd Fahad Iqbal Polash * @vsi: the VSI being changed 1304492af0abSMd Fahad Iqbal Polash * @ena: boolean value indicating if this is an enable or disable request 1305492af0abSMd Fahad Iqbal Polash * 1306492af0abSMd Fahad Iqbal Polash * In the event of disable request for RSS, this function will zero out RSS 1307492af0abSMd Fahad Iqbal Polash * LUT, while in the event of enable request for RSS, it will reconfigure RSS 1308492af0abSMd Fahad Iqbal Polash * LUT. 1309492af0abSMd Fahad Iqbal Polash */ 1310492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena) 1311492af0abSMd Fahad Iqbal Polash { 1312492af0abSMd Fahad Iqbal Polash int err = 0; 1313492af0abSMd Fahad Iqbal Polash u8 *lut; 1314492af0abSMd Fahad Iqbal Polash 1315492af0abSMd Fahad Iqbal Polash lut = devm_kzalloc(&vsi->back->pdev->dev, vsi->rss_table_size, 1316492af0abSMd Fahad Iqbal Polash GFP_KERNEL); 1317492af0abSMd Fahad Iqbal Polash if (!lut) 1318492af0abSMd Fahad Iqbal Polash return -ENOMEM; 1319492af0abSMd Fahad Iqbal Polash 1320492af0abSMd Fahad Iqbal Polash if (ena) { 1321492af0abSMd Fahad Iqbal Polash if (vsi->rss_lut_user) 1322492af0abSMd Fahad Iqbal Polash memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 1323492af0abSMd Fahad Iqbal Polash else 1324492af0abSMd Fahad Iqbal Polash ice_fill_rss_lut(lut, vsi->rss_table_size, 1325492af0abSMd Fahad Iqbal Polash vsi->rss_size); 1326492af0abSMd Fahad Iqbal Polash } 1327492af0abSMd Fahad Iqbal Polash 1328492af0abSMd Fahad Iqbal Polash err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size); 1329492af0abSMd Fahad Iqbal Polash devm_kfree(&vsi->back->pdev->dev, lut); 1330492af0abSMd Fahad Iqbal Polash return err; 1331492af0abSMd Fahad Iqbal Polash } 1332492af0abSMd Fahad Iqbal Polash 1333492af0abSMd Fahad Iqbal Polash /** 133437bb8390SAnirudh Venkataramanan * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI 133537bb8390SAnirudh Venkataramanan * @vsi: VSI to be configured 133637bb8390SAnirudh Venkataramanan */ 133737bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi) 133837bb8390SAnirudh Venkataramanan { 133937bb8390SAnirudh Venkataramanan u8 seed[ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE]; 134037bb8390SAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *key; 134137bb8390SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 134237bb8390SAnirudh Venkataramanan enum ice_status status; 134337bb8390SAnirudh Venkataramanan int err = 0; 134437bb8390SAnirudh Venkataramanan u8 *lut; 134537bb8390SAnirudh Venkataramanan 134637bb8390SAnirudh Venkataramanan vsi->rss_size = min_t(int, vsi->rss_size, vsi->num_rxq); 134737bb8390SAnirudh Venkataramanan 134837bb8390SAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 134937bb8390SAnirudh Venkataramanan if (!lut) 135037bb8390SAnirudh Venkataramanan return -ENOMEM; 135137bb8390SAnirudh Venkataramanan 135237bb8390SAnirudh Venkataramanan if (vsi->rss_lut_user) 135337bb8390SAnirudh Venkataramanan memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 135437bb8390SAnirudh Venkataramanan else 135537bb8390SAnirudh Venkataramanan ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 135637bb8390SAnirudh Venkataramanan 13574fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut, 13584fb33f31SAnirudh Venkataramanan vsi->rss_table_size); 135937bb8390SAnirudh Venkataramanan 136037bb8390SAnirudh Venkataramanan if (status) { 136137bb8390SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, 136237bb8390SAnirudh Venkataramanan "set_rss_lut failed, error %d\n", status); 136337bb8390SAnirudh Venkataramanan err = -EIO; 136437bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 136537bb8390SAnirudh Venkataramanan } 136637bb8390SAnirudh Venkataramanan 136737bb8390SAnirudh Venkataramanan key = devm_kzalloc(&vsi->back->pdev->dev, sizeof(*key), GFP_KERNEL); 136837bb8390SAnirudh Venkataramanan if (!key) { 136937bb8390SAnirudh Venkataramanan err = -ENOMEM; 137037bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 137137bb8390SAnirudh Venkataramanan } 137237bb8390SAnirudh Venkataramanan 137337bb8390SAnirudh Venkataramanan if (vsi->rss_hkey_user) 137437bb8390SAnirudh Venkataramanan memcpy(seed, vsi->rss_hkey_user, 137537bb8390SAnirudh Venkataramanan ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE); 137637bb8390SAnirudh Venkataramanan else 137737bb8390SAnirudh Venkataramanan netdev_rss_key_fill((void *)seed, 137837bb8390SAnirudh Venkataramanan ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE); 137937bb8390SAnirudh Venkataramanan memcpy(&key->standard_rss_key, seed, 138037bb8390SAnirudh Venkataramanan ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE); 138137bb8390SAnirudh Venkataramanan 13824fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key); 138337bb8390SAnirudh Venkataramanan 138437bb8390SAnirudh Venkataramanan if (status) { 138537bb8390SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "set_rss_key failed, error %d\n", 138637bb8390SAnirudh Venkataramanan status); 138737bb8390SAnirudh Venkataramanan err = -EIO; 138837bb8390SAnirudh Venkataramanan } 138937bb8390SAnirudh Venkataramanan 139037bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, key); 139137bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit: 139237bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 139337bb8390SAnirudh Venkataramanan return err; 139437bb8390SAnirudh Venkataramanan } 139537bb8390SAnirudh Venkataramanan 139637bb8390SAnirudh Venkataramanan /** 139745d3d428SAnirudh Venkataramanan * ice_add_mac_to_list - Add a mac address filter entry to the list 139845d3d428SAnirudh Venkataramanan * @vsi: the VSI to be forwarded to 139945d3d428SAnirudh Venkataramanan * @add_list: pointer to the list which contains MAC filter entries 140045d3d428SAnirudh Venkataramanan * @macaddr: the MAC address to be added. 140145d3d428SAnirudh Venkataramanan * 140245d3d428SAnirudh Venkataramanan * Adds mac address filter entry to the temp list 140345d3d428SAnirudh Venkataramanan * 140445d3d428SAnirudh Venkataramanan * Returns 0 on success or ENOMEM on failure. 140545d3d428SAnirudh Venkataramanan */ 140645d3d428SAnirudh Venkataramanan int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list, 140745d3d428SAnirudh Venkataramanan const u8 *macaddr) 140845d3d428SAnirudh Venkataramanan { 140945d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 141045d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 141145d3d428SAnirudh Venkataramanan 141245d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC); 141345d3d428SAnirudh Venkataramanan if (!tmp) 141445d3d428SAnirudh Venkataramanan return -ENOMEM; 141545d3d428SAnirudh Venkataramanan 141645d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 14175726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 141845d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC; 141945d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 14205726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 142145d3d428SAnirudh Venkataramanan ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr); 142245d3d428SAnirudh Venkataramanan 142345d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 142445d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, add_list); 142545d3d428SAnirudh Venkataramanan 142645d3d428SAnirudh Venkataramanan return 0; 142745d3d428SAnirudh Venkataramanan } 142845d3d428SAnirudh Venkataramanan 142945d3d428SAnirudh Venkataramanan /** 143045d3d428SAnirudh Venkataramanan * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 143145d3d428SAnirudh Venkataramanan * @vsi: the VSI to be updated 143245d3d428SAnirudh Venkataramanan */ 143345d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi) 143445d3d428SAnirudh Venkataramanan { 143545d3d428SAnirudh Venkataramanan struct ice_eth_stats *prev_es, *cur_es; 143645d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 143745d3d428SAnirudh Venkataramanan u16 vsi_num = vsi->vsi_num; /* HW absolute index of a VSI */ 143845d3d428SAnirudh Venkataramanan 143945d3d428SAnirudh Venkataramanan prev_es = &vsi->eth_stats_prev; 144045d3d428SAnirudh Venkataramanan cur_es = &vsi->eth_stats; 144145d3d428SAnirudh Venkataramanan 144245d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_GORCH(vsi_num), GLV_GORCL(vsi_num), 144345d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_bytes, 144445d3d428SAnirudh Venkataramanan &cur_es->rx_bytes); 144545d3d428SAnirudh Venkataramanan 144645d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_UPRCH(vsi_num), GLV_UPRCL(vsi_num), 144745d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_unicast, 144845d3d428SAnirudh Venkataramanan &cur_es->rx_unicast); 144945d3d428SAnirudh Venkataramanan 145045d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_MPRCH(vsi_num), GLV_MPRCL(vsi_num), 145145d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_multicast, 145245d3d428SAnirudh Venkataramanan &cur_es->rx_multicast); 145345d3d428SAnirudh Venkataramanan 145445d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_BPRCH(vsi_num), GLV_BPRCL(vsi_num), 145545d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->rx_broadcast, 145645d3d428SAnirudh Venkataramanan &cur_es->rx_broadcast); 145745d3d428SAnirudh Venkataramanan 145845d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, 145945d3d428SAnirudh Venkataramanan &prev_es->rx_discards, &cur_es->rx_discards); 146045d3d428SAnirudh Venkataramanan 146145d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_GOTCH(vsi_num), GLV_GOTCL(vsi_num), 146245d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_bytes, 146345d3d428SAnirudh Venkataramanan &cur_es->tx_bytes); 146445d3d428SAnirudh Venkataramanan 146545d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_UPTCH(vsi_num), GLV_UPTCL(vsi_num), 146645d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_unicast, 146745d3d428SAnirudh Venkataramanan &cur_es->tx_unicast); 146845d3d428SAnirudh Venkataramanan 146945d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_MPTCH(vsi_num), GLV_MPTCL(vsi_num), 147045d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_multicast, 147145d3d428SAnirudh Venkataramanan &cur_es->tx_multicast); 147245d3d428SAnirudh Venkataramanan 147345d3d428SAnirudh Venkataramanan ice_stat_update40(hw, GLV_BPTCH(vsi_num), GLV_BPTCL(vsi_num), 147445d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded, &prev_es->tx_broadcast, 147545d3d428SAnirudh Venkataramanan &cur_es->tx_broadcast); 147645d3d428SAnirudh Venkataramanan 147745d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, 147845d3d428SAnirudh Venkataramanan &prev_es->tx_errors, &cur_es->tx_errors); 147945d3d428SAnirudh Venkataramanan 148045d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded = true; 148145d3d428SAnirudh Venkataramanan } 148245d3d428SAnirudh Venkataramanan 148345d3d428SAnirudh Venkataramanan /** 148445d3d428SAnirudh Venkataramanan * ice_free_fltr_list - free filter lists helper 148545d3d428SAnirudh Venkataramanan * @dev: pointer to the device struct 148645d3d428SAnirudh Venkataramanan * @h: pointer to the list head to be freed 148745d3d428SAnirudh Venkataramanan * 148845d3d428SAnirudh Venkataramanan * Helper function to free filter lists previously created using 148945d3d428SAnirudh Venkataramanan * ice_add_mac_to_list 149045d3d428SAnirudh Venkataramanan */ 149145d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h) 149245d3d428SAnirudh Venkataramanan { 149345d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *e, *tmp; 149445d3d428SAnirudh Venkataramanan 149545d3d428SAnirudh Venkataramanan list_for_each_entry_safe(e, tmp, h, list_entry) { 149645d3d428SAnirudh Venkataramanan list_del(&e->list_entry); 149745d3d428SAnirudh Venkataramanan devm_kfree(dev, e); 149845d3d428SAnirudh Venkataramanan } 149945d3d428SAnirudh Venkataramanan } 150045d3d428SAnirudh Venkataramanan 150145d3d428SAnirudh Venkataramanan /** 150245d3d428SAnirudh Venkataramanan * ice_vsi_add_vlan - Add VSI membership for given VLAN 150345d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 150445d3d428SAnirudh Venkataramanan * @vid: VLAN id to be added 150545d3d428SAnirudh Venkataramanan */ 150645d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid) 150745d3d428SAnirudh Venkataramanan { 150845d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 150945d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 151045d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 151145d3d428SAnirudh Venkataramanan enum ice_status status; 151245d3d428SAnirudh Venkataramanan int err = 0; 151345d3d428SAnirudh Venkataramanan 151445d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_KERNEL); 151545d3d428SAnirudh Venkataramanan if (!tmp) 151645d3d428SAnirudh Venkataramanan return -ENOMEM; 151745d3d428SAnirudh Venkataramanan 151845d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 151945d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 152045d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 15215726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 15225726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 152345d3d428SAnirudh Venkataramanan tmp->fltr_info.l_data.vlan.vlan_id = vid; 152445d3d428SAnirudh Venkataramanan 152545d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 152645d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, &tmp_add_list); 152745d3d428SAnirudh Venkataramanan 152845d3d428SAnirudh Venkataramanan status = ice_add_vlan(&pf->hw, &tmp_add_list); 152945d3d428SAnirudh Venkataramanan if (status) { 153045d3d428SAnirudh Venkataramanan err = -ENODEV; 153145d3d428SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failure Adding VLAN %d on VSI %i\n", 153245d3d428SAnirudh Venkataramanan vid, vsi->vsi_num); 153345d3d428SAnirudh Venkataramanan } 153445d3d428SAnirudh Venkataramanan 153545d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 153645d3d428SAnirudh Venkataramanan return err; 153745d3d428SAnirudh Venkataramanan } 153845d3d428SAnirudh Venkataramanan 153945d3d428SAnirudh Venkataramanan /** 154045d3d428SAnirudh Venkataramanan * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN 154145d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 154245d3d428SAnirudh Venkataramanan * @vid: VLAN id to be removed 154345d3d428SAnirudh Venkataramanan * 154445d3d428SAnirudh Venkataramanan * Returns 0 on success and negative on failure 154545d3d428SAnirudh Venkataramanan */ 154645d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid) 154745d3d428SAnirudh Venkataramanan { 154845d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *list; 154945d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 155045d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 155145d3d428SAnirudh Venkataramanan int status = 0; 155245d3d428SAnirudh Venkataramanan 155345d3d428SAnirudh Venkataramanan list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 155445d3d428SAnirudh Venkataramanan if (!list) 155545d3d428SAnirudh Venkataramanan return -ENOMEM; 155645d3d428SAnirudh Venkataramanan 155745d3d428SAnirudh Venkataramanan list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 15585726ca0eSAnirudh Venkataramanan list->fltr_info.vsi_handle = vsi->idx; 155945d3d428SAnirudh Venkataramanan list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 156045d3d428SAnirudh Venkataramanan list->fltr_info.l_data.vlan.vlan_id = vid; 156145d3d428SAnirudh Venkataramanan list->fltr_info.flag = ICE_FLTR_TX; 15625726ca0eSAnirudh Venkataramanan list->fltr_info.src_id = ICE_SRC_ID_VSI; 156345d3d428SAnirudh Venkataramanan 156445d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&list->list_entry); 156545d3d428SAnirudh Venkataramanan list_add(&list->list_entry, &tmp_add_list); 156645d3d428SAnirudh Venkataramanan 156745d3d428SAnirudh Venkataramanan if (ice_remove_vlan(&pf->hw, &tmp_add_list)) { 156845d3d428SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Error removing VLAN %d on vsi %i\n", 156945d3d428SAnirudh Venkataramanan vid, vsi->vsi_num); 157045d3d428SAnirudh Venkataramanan status = -EIO; 157145d3d428SAnirudh Venkataramanan } 157245d3d428SAnirudh Venkataramanan 157345d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 157445d3d428SAnirudh Venkataramanan return status; 157545d3d428SAnirudh Venkataramanan } 157645d3d428SAnirudh Venkataramanan 157745d3d428SAnirudh Venkataramanan /** 157872adf242SAnirudh Venkataramanan * ice_vsi_cfg_rxqs - Configure the VSI for Rx 157972adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 158072adf242SAnirudh Venkataramanan * 158172adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 158272adf242SAnirudh Venkataramanan * Configure the Rx VSI for operation. 158372adf242SAnirudh Venkataramanan */ 158472adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi) 158572adf242SAnirudh Venkataramanan { 158672adf242SAnirudh Venkataramanan int err = 0; 158772adf242SAnirudh Venkataramanan u16 i; 158872adf242SAnirudh Venkataramanan 15898ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 15908ede0178SAnirudh Venkataramanan goto setup_rings; 15918ede0178SAnirudh Venkataramanan 159272adf242SAnirudh Venkataramanan if (vsi->netdev && vsi->netdev->mtu > ETH_DATA_LEN) 159372adf242SAnirudh Venkataramanan vsi->max_frame = vsi->netdev->mtu + 159472adf242SAnirudh Venkataramanan ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; 159572adf242SAnirudh Venkataramanan else 159672adf242SAnirudh Venkataramanan vsi->max_frame = ICE_RXBUF_2048; 159772adf242SAnirudh Venkataramanan 159872adf242SAnirudh Venkataramanan vsi->rx_buf_len = ICE_RXBUF_2048; 15998ede0178SAnirudh Venkataramanan setup_rings: 160072adf242SAnirudh Venkataramanan /* set up individual rings */ 160172adf242SAnirudh Venkataramanan for (i = 0; i < vsi->num_rxq && !err; i++) 160272adf242SAnirudh Venkataramanan err = ice_setup_rx_ctx(vsi->rx_rings[i]); 160372adf242SAnirudh Venkataramanan 160472adf242SAnirudh Venkataramanan if (err) { 160572adf242SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, "ice_setup_rx_ctx failed\n"); 160672adf242SAnirudh Venkataramanan return -EIO; 160772adf242SAnirudh Venkataramanan } 160872adf242SAnirudh Venkataramanan return err; 160972adf242SAnirudh Venkataramanan } 161072adf242SAnirudh Venkataramanan 161172adf242SAnirudh Venkataramanan /** 161272adf242SAnirudh Venkataramanan * ice_vsi_cfg_txqs - Configure the VSI for Tx 161372adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 161403f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be configured 161503f7a986SAnirudh Venkataramanan * @offset: offset within vsi->txq_map 161672adf242SAnirudh Venkataramanan * 161772adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 161872adf242SAnirudh Venkataramanan * Configure the Tx VSI for operation. 161972adf242SAnirudh Venkataramanan */ 162003f7a986SAnirudh Venkataramanan static int 162103f7a986SAnirudh Venkataramanan ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, int offset) 162272adf242SAnirudh Venkataramanan { 162372adf242SAnirudh Venkataramanan struct ice_aqc_add_tx_qgrp *qg_buf; 162472adf242SAnirudh Venkataramanan struct ice_aqc_add_txqs_perq *txq; 162572adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1626c5a2a4a3SUsha Ketineni u8 num_q_grps, q_idx = 0; 162772adf242SAnirudh Venkataramanan enum ice_status status; 162872adf242SAnirudh Venkataramanan u16 buf_len, i, pf_q; 162903f7a986SAnirudh Venkataramanan int err = 0, tc; 163072adf242SAnirudh Venkataramanan 1631c6dfd690SBruce Allan buf_len = sizeof(*qg_buf); 163272adf242SAnirudh Venkataramanan qg_buf = devm_kzalloc(&pf->pdev->dev, buf_len, GFP_KERNEL); 163372adf242SAnirudh Venkataramanan if (!qg_buf) 163472adf242SAnirudh Venkataramanan return -ENOMEM; 163572adf242SAnirudh Venkataramanan 163672adf242SAnirudh Venkataramanan qg_buf->num_txqs = 1; 163772adf242SAnirudh Venkataramanan num_q_grps = 1; 163872adf242SAnirudh Venkataramanan 1639c5a2a4a3SUsha Ketineni /* set up and configure the Tx queues for each enabled TC */ 1640c5a2a4a3SUsha Ketineni for (tc = 0; tc < ICE_MAX_TRAFFIC_CLASS; tc++) { 1641c5a2a4a3SUsha Ketineni if (!(vsi->tc_cfg.ena_tc & BIT(tc))) 1642c5a2a4a3SUsha Ketineni break; 1643c5a2a4a3SUsha Ketineni 1644c5a2a4a3SUsha Ketineni for (i = 0; i < vsi->tc_cfg.tc_info[tc].qcount_tx; i++) { 164572adf242SAnirudh Venkataramanan struct ice_tlan_ctx tlan_ctx = { 0 }; 164672adf242SAnirudh Venkataramanan 164703f7a986SAnirudh Venkataramanan pf_q = vsi->txq_map[q_idx + offset]; 164803f7a986SAnirudh Venkataramanan ice_setup_tx_ctx(rings[q_idx], &tlan_ctx, pf_q); 164972adf242SAnirudh Venkataramanan /* copy context contents into the qg_buf */ 165072adf242SAnirudh Venkataramanan qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q); 165172adf242SAnirudh Venkataramanan ice_set_ctx((u8 *)&tlan_ctx, qg_buf->txqs[0].txq_ctx, 165272adf242SAnirudh Venkataramanan ice_tlan_ctx_info); 165372adf242SAnirudh Venkataramanan 1654c5a2a4a3SUsha Ketineni /* init queue specific tail reg. It is referred as 1655c5a2a4a3SUsha Ketineni * transmit comm scheduler queue doorbell. 165672adf242SAnirudh Venkataramanan */ 165703f7a986SAnirudh Venkataramanan rings[q_idx]->tail = 1658c5a2a4a3SUsha Ketineni pf->hw.hw_addr + QTX_COMM_DBELL(pf_q); 16594fb33f31SAnirudh Venkataramanan status = ice_ena_vsi_txq(vsi->port_info, vsi->idx, tc, 1660c5a2a4a3SUsha Ketineni num_q_grps, qg_buf, buf_len, 1661c5a2a4a3SUsha Ketineni NULL); 166272adf242SAnirudh Venkataramanan if (status) { 166372adf242SAnirudh Venkataramanan dev_err(&vsi->back->pdev->dev, 166472adf242SAnirudh Venkataramanan "Failed to set LAN Tx queue context, error: %d\n", 166572adf242SAnirudh Venkataramanan status); 166672adf242SAnirudh Venkataramanan err = -ENODEV; 166772adf242SAnirudh Venkataramanan goto err_cfg_txqs; 166872adf242SAnirudh Venkataramanan } 166972adf242SAnirudh Venkataramanan 1670c5a2a4a3SUsha Ketineni /* Add Tx Queue TEID into the VSI Tx ring from the 1671c5a2a4a3SUsha Ketineni * response. This will complete configuring and 1672c5a2a4a3SUsha Ketineni * enabling the queue. 167372adf242SAnirudh Venkataramanan */ 167472adf242SAnirudh Venkataramanan txq = &qg_buf->txqs[0]; 167572adf242SAnirudh Venkataramanan if (pf_q == le16_to_cpu(txq->txq_id)) 167603f7a986SAnirudh Venkataramanan rings[q_idx]->txq_teid = 167772adf242SAnirudh Venkataramanan le32_to_cpu(txq->q_teid); 1678c5a2a4a3SUsha Ketineni 1679c5a2a4a3SUsha Ketineni q_idx++; 1680c5a2a4a3SUsha Ketineni } 168172adf242SAnirudh Venkataramanan } 168272adf242SAnirudh Venkataramanan err_cfg_txqs: 168372adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, qg_buf); 168472adf242SAnirudh Venkataramanan return err; 168572adf242SAnirudh Venkataramanan } 168672adf242SAnirudh Venkataramanan 168772adf242SAnirudh Venkataramanan /** 168803f7a986SAnirudh Venkataramanan * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx 168903f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 169003f7a986SAnirudh Venkataramanan * 169103f7a986SAnirudh Venkataramanan * Return 0 on success and a negative value on error 169203f7a986SAnirudh Venkataramanan * Configure the Tx VSI for operation. 169303f7a986SAnirudh Venkataramanan */ 169403f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) 169503f7a986SAnirudh Venkataramanan { 169603f7a986SAnirudh Venkataramanan return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, 0); 169703f7a986SAnirudh Venkataramanan } 169803f7a986SAnirudh Venkataramanan 169903f7a986SAnirudh Venkataramanan /** 17009e4ab4c2SBrett Creeley * ice_intrl_usec_to_reg - convert interrupt rate limit to register value 17019e4ab4c2SBrett Creeley * @intrl: interrupt rate limit in usecs 17029e4ab4c2SBrett Creeley * @gran: interrupt rate limit granularity in usecs 17039e4ab4c2SBrett Creeley * 17049e4ab4c2SBrett Creeley * This function converts a decimal interrupt rate limit in usecs to the format 17059e4ab4c2SBrett Creeley * expected by firmware. 17069e4ab4c2SBrett Creeley */ 17079e4ab4c2SBrett Creeley static u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) 17089e4ab4c2SBrett Creeley { 17099e4ab4c2SBrett Creeley u32 val = intrl / gran; 17109e4ab4c2SBrett Creeley 17119e4ab4c2SBrett Creeley if (val) 17129e4ab4c2SBrett Creeley return val | GLINT_RATE_INTRL_ENA_M; 17139e4ab4c2SBrett Creeley return 0; 17149e4ab4c2SBrett Creeley } 17159e4ab4c2SBrett Creeley 17169e4ab4c2SBrett Creeley /** 171770457520SBrett Creeley * ice_cfg_itr_gran - set the ITR granularity to 2 usecs if not already set 171870457520SBrett Creeley * @hw: board specific structure 171970457520SBrett Creeley */ 172070457520SBrett Creeley static void ice_cfg_itr_gran(struct ice_hw *hw) 172170457520SBrett Creeley { 172270457520SBrett Creeley u32 regval = rd32(hw, GLINT_CTL); 172370457520SBrett Creeley 172470457520SBrett Creeley /* no need to update global register if ITR gran is already set */ 172570457520SBrett Creeley if (!(regval & GLINT_CTL_DIS_AUTOMASK_M) && 172670457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_200_M) >> 172770457520SBrett Creeley GLINT_CTL_ITR_GRAN_200_S) == ICE_ITR_GRAN_US) && 172870457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_100_M) >> 172970457520SBrett Creeley GLINT_CTL_ITR_GRAN_100_S) == ICE_ITR_GRAN_US) && 173070457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_50_M) >> 173170457520SBrett Creeley GLINT_CTL_ITR_GRAN_50_S) == ICE_ITR_GRAN_US) && 173270457520SBrett Creeley (((regval & GLINT_CTL_ITR_GRAN_25_M) >> 173370457520SBrett Creeley GLINT_CTL_ITR_GRAN_25_S) == ICE_ITR_GRAN_US)) 173470457520SBrett Creeley return; 173570457520SBrett Creeley 173670457520SBrett Creeley regval = ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_200_S) & 173770457520SBrett Creeley GLINT_CTL_ITR_GRAN_200_M) | 173870457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_100_S) & 173970457520SBrett Creeley GLINT_CTL_ITR_GRAN_100_M) | 174070457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_50_S) & 174170457520SBrett Creeley GLINT_CTL_ITR_GRAN_50_M) | 174270457520SBrett Creeley ((ICE_ITR_GRAN_US << GLINT_CTL_ITR_GRAN_25_S) & 174370457520SBrett Creeley GLINT_CTL_ITR_GRAN_25_M); 174470457520SBrett Creeley wr32(hw, GLINT_CTL, regval); 174570457520SBrett Creeley } 174670457520SBrett Creeley 174770457520SBrett Creeley /** 1748d2b464a7SBrett Creeley * ice_cfg_itr - configure the initial interrupt throttle values 1749d2b464a7SBrett Creeley * @hw: pointer to the HW structure 1750d2b464a7SBrett Creeley * @q_vector: interrupt vector that's being configured 1751d2b464a7SBrett Creeley * @vector: HW vector index to apply the interrupt throttling to 1752d2b464a7SBrett Creeley * 1753d2b464a7SBrett Creeley * Configure interrupt throttling values for the ring containers that are 1754d2b464a7SBrett Creeley * associated with the interrupt vector passed in. 1755d2b464a7SBrett Creeley */ 1756d2b464a7SBrett Creeley static void 1757d2b464a7SBrett Creeley ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector, u16 vector) 1758d2b464a7SBrett Creeley { 175970457520SBrett Creeley ice_cfg_itr_gran(hw); 176070457520SBrett Creeley 1761d2b464a7SBrett Creeley if (q_vector->num_ring_rx) { 1762d2b464a7SBrett Creeley struct ice_ring_container *rc = &q_vector->rx; 1763d2b464a7SBrett Creeley 176463f545edSBrett Creeley /* if this value is set then don't overwrite with default */ 176563f545edSBrett Creeley if (!rc->itr_setting) 176663f545edSBrett Creeley rc->itr_setting = ICE_DFLT_RX_ITR; 176763f545edSBrett Creeley 176863f545edSBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 176963f545edSBrett Creeley rc->next_update = jiffies + 1; 177063f545edSBrett Creeley rc->current_itr = rc->target_itr; 1771d2b464a7SBrett Creeley rc->latency_range = ICE_LOW_LATENCY; 177263f545edSBrett Creeley wr32(hw, GLINT_ITR(rc->itr_idx, vector), 177363f545edSBrett Creeley ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); 1774d2b464a7SBrett Creeley } 1775d2b464a7SBrett Creeley 1776d2b464a7SBrett Creeley if (q_vector->num_ring_tx) { 1777d2b464a7SBrett Creeley struct ice_ring_container *rc = &q_vector->tx; 1778d2b464a7SBrett Creeley 177963f545edSBrett Creeley /* if this value is set then don't overwrite with default */ 178063f545edSBrett Creeley if (!rc->itr_setting) 178163f545edSBrett Creeley rc->itr_setting = ICE_DFLT_TX_ITR; 178263f545edSBrett Creeley 178363f545edSBrett Creeley rc->target_itr = ITR_TO_REG(rc->itr_setting); 178463f545edSBrett Creeley rc->next_update = jiffies + 1; 178563f545edSBrett Creeley rc->current_itr = rc->target_itr; 1786d2b464a7SBrett Creeley rc->latency_range = ICE_LOW_LATENCY; 178763f545edSBrett Creeley wr32(hw, GLINT_ITR(rc->itr_idx, vector), 178863f545edSBrett Creeley ITR_REG_ALIGN(rc->current_itr) >> ICE_ITR_GRAN_S); 1789d2b464a7SBrett Creeley } 1790d2b464a7SBrett Creeley } 1791d2b464a7SBrett Creeley 1792d2b464a7SBrett Creeley /** 179372adf242SAnirudh Venkataramanan * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW 179472adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 179572adf242SAnirudh Venkataramanan */ 179672adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi) 179772adf242SAnirudh Venkataramanan { 179872adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1799eb0208ecSPreethi Banala u16 vector = vsi->hw_base_vector; 180072adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 180172adf242SAnirudh Venkataramanan u32 txq = 0, rxq = 0; 1802d2b464a7SBrett Creeley int i, q; 180372adf242SAnirudh Venkataramanan 180472adf242SAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++, vector++) { 180572adf242SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 180672adf242SAnirudh Venkataramanan 1807d2b464a7SBrett Creeley ice_cfg_itr(hw, q_vector, vector); 18089e4ab4c2SBrett Creeley 18099e4ab4c2SBrett Creeley wr32(hw, GLINT_RATE(vector), 18109e4ab4c2SBrett Creeley ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); 181172adf242SAnirudh Venkataramanan 181272adf242SAnirudh Venkataramanan /* Both Transmit Queue Interrupt Cause Control register 181372adf242SAnirudh Venkataramanan * and Receive Queue Interrupt Cause control register 181472adf242SAnirudh Venkataramanan * expects MSIX_INDX field to be the vector index 181572adf242SAnirudh Venkataramanan * within the function space and not the absolute 181672adf242SAnirudh Venkataramanan * vector index across PF or across device. 181772adf242SAnirudh Venkataramanan * For SR-IOV VF VSIs queue vector index always starts 181872adf242SAnirudh Venkataramanan * with 1 since first vector index(0) is used for OICR 181972adf242SAnirudh Venkataramanan * in VF space. Since VMDq and other PF VSIs are within 182072adf242SAnirudh Venkataramanan * the PF function space, use the vector index that is 182172adf242SAnirudh Venkataramanan * tracked for this PF. 182272adf242SAnirudh Venkataramanan */ 182372adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 1824d2b464a7SBrett Creeley int itr_idx = q_vector->tx.itr_idx; 182572adf242SAnirudh Venkataramanan u32 val; 182672adf242SAnirudh Venkataramanan 18278ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 18288ede0178SAnirudh Venkataramanan val = QINT_TQCTL_CAUSE_ENA_M | 1829d2b464a7SBrett Creeley (itr_idx << QINT_TQCTL_ITR_INDX_S) | 18308ede0178SAnirudh Venkataramanan ((i + 1) << QINT_TQCTL_MSIX_INDX_S); 18318ede0178SAnirudh Venkataramanan else 183272adf242SAnirudh Venkataramanan val = QINT_TQCTL_CAUSE_ENA_M | 1833d2b464a7SBrett Creeley (itr_idx << QINT_TQCTL_ITR_INDX_S) | 183472adf242SAnirudh Venkataramanan (vector << QINT_TQCTL_MSIX_INDX_S); 183572adf242SAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), val); 183672adf242SAnirudh Venkataramanan txq++; 183772adf242SAnirudh Venkataramanan } 183872adf242SAnirudh Venkataramanan 183972adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 1840d2b464a7SBrett Creeley int itr_idx = q_vector->rx.itr_idx; 184172adf242SAnirudh Venkataramanan u32 val; 184272adf242SAnirudh Venkataramanan 18438ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 18448ede0178SAnirudh Venkataramanan val = QINT_RQCTL_CAUSE_ENA_M | 1845d2b464a7SBrett Creeley (itr_idx << QINT_RQCTL_ITR_INDX_S) | 18468ede0178SAnirudh Venkataramanan ((i + 1) << QINT_RQCTL_MSIX_INDX_S); 18478ede0178SAnirudh Venkataramanan else 184872adf242SAnirudh Venkataramanan val = QINT_RQCTL_CAUSE_ENA_M | 1849d2b464a7SBrett Creeley (itr_idx << QINT_RQCTL_ITR_INDX_S) | 185072adf242SAnirudh Venkataramanan (vector << QINT_RQCTL_MSIX_INDX_S); 185172adf242SAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), val); 185272adf242SAnirudh Venkataramanan rxq++; 185372adf242SAnirudh Venkataramanan } 185472adf242SAnirudh Venkataramanan } 185572adf242SAnirudh Venkataramanan 185672adf242SAnirudh Venkataramanan ice_flush(hw); 185772adf242SAnirudh Venkataramanan } 185872adf242SAnirudh Venkataramanan 185972adf242SAnirudh Venkataramanan /** 186045d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx 186145d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 186245d3d428SAnirudh Venkataramanan */ 186345d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) 186445d3d428SAnirudh Venkataramanan { 186545d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 186645d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1867198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 186845d3d428SAnirudh Venkataramanan enum ice_status status; 1869198a666aSBruce Allan int ret = 0; 1870198a666aSBruce Allan 1871198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 1872198a666aSBruce Allan if (!ctxt) 1873198a666aSBruce Allan return -ENOMEM; 187445d3d428SAnirudh Venkataramanan 187545d3d428SAnirudh Venkataramanan /* Here we are configuring the VSI to let the driver add VLAN tags by 187645d3d428SAnirudh Venkataramanan * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag 187745d3d428SAnirudh Venkataramanan * insertion happens in the Tx hot path, in ice_tx_map. 187845d3d428SAnirudh Venkataramanan */ 1879198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; 188045d3d428SAnirudh Venkataramanan 1881198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 188245d3d428SAnirudh Venkataramanan 1883198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 188445d3d428SAnirudh Venkataramanan if (status) { 188545d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n", 188645d3d428SAnirudh Venkataramanan status, hw->adminq.sq_last_status); 1887198a666aSBruce Allan ret = -EIO; 1888198a666aSBruce Allan goto out; 188945d3d428SAnirudh Venkataramanan } 189045d3d428SAnirudh Venkataramanan 1891198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1892198a666aSBruce Allan out: 1893198a666aSBruce Allan devm_kfree(dev, ctxt); 1894198a666aSBruce Allan return ret; 189545d3d428SAnirudh Venkataramanan } 189645d3d428SAnirudh Venkataramanan 189745d3d428SAnirudh Venkataramanan /** 189845d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx 189945d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 190045d3d428SAnirudh Venkataramanan * @ena: boolean value indicating if this is a enable or disable request 190145d3d428SAnirudh Venkataramanan */ 190245d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) 190345d3d428SAnirudh Venkataramanan { 190445d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 190545d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1906198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 190745d3d428SAnirudh Venkataramanan enum ice_status status; 1908198a666aSBruce Allan int ret = 0; 1909198a666aSBruce Allan 1910198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 1911198a666aSBruce Allan if (!ctxt) 1912198a666aSBruce Allan return -ENOMEM; 191345d3d428SAnirudh Venkataramanan 191445d3d428SAnirudh Venkataramanan /* Here we are configuring what the VSI should do with the VLAN tag in 191545d3d428SAnirudh Venkataramanan * the Rx packet. We can either leave the tag in the packet or put it in 191645d3d428SAnirudh Venkataramanan * the Rx descriptor. 191745d3d428SAnirudh Venkataramanan */ 1918198a666aSBruce Allan if (ena) 191945d3d428SAnirudh Venkataramanan /* Strip VLAN tag from Rx packet and put it in the desc */ 1920198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; 1921198a666aSBruce Allan else 192245d3d428SAnirudh Venkataramanan /* Disable stripping. Leave tag in packet */ 1923198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; 192445d3d428SAnirudh Venkataramanan 192545d3d428SAnirudh Venkataramanan /* Allow all packets untagged/tagged */ 1926198a666aSBruce Allan ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; 192745d3d428SAnirudh Venkataramanan 1928198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 192945d3d428SAnirudh Venkataramanan 1930198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 193145d3d428SAnirudh Venkataramanan if (status) { 193245d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n", 193345d3d428SAnirudh Venkataramanan ena, status, hw->adminq.sq_last_status); 1934198a666aSBruce Allan ret = -EIO; 1935198a666aSBruce Allan goto out; 193645d3d428SAnirudh Venkataramanan } 193745d3d428SAnirudh Venkataramanan 1938198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1939198a666aSBruce Allan out: 1940198a666aSBruce Allan devm_kfree(dev, ctxt); 1941198a666aSBruce Allan return ret; 194245d3d428SAnirudh Venkataramanan } 194372adf242SAnirudh Venkataramanan 194472adf242SAnirudh Venkataramanan /** 194572adf242SAnirudh Venkataramanan * ice_vsi_start_rx_rings - start VSI's Rx rings 194672adf242SAnirudh Venkataramanan * @vsi: the VSI whose rings are to be started 194772adf242SAnirudh Venkataramanan * 194872adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 194972adf242SAnirudh Venkataramanan */ 195072adf242SAnirudh Venkataramanan int ice_vsi_start_rx_rings(struct ice_vsi *vsi) 195172adf242SAnirudh Venkataramanan { 195272adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, true); 195372adf242SAnirudh Venkataramanan } 195472adf242SAnirudh Venkataramanan 195572adf242SAnirudh Venkataramanan /** 195672adf242SAnirudh Venkataramanan * ice_vsi_stop_rx_rings - stop VSI's Rx rings 195772adf242SAnirudh Venkataramanan * @vsi: the VSI 195872adf242SAnirudh Venkataramanan * 195972adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 196072adf242SAnirudh Venkataramanan */ 196172adf242SAnirudh Venkataramanan int ice_vsi_stop_rx_rings(struct ice_vsi *vsi) 196272adf242SAnirudh Venkataramanan { 196372adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, false); 196472adf242SAnirudh Venkataramanan } 196572adf242SAnirudh Venkataramanan 196672adf242SAnirudh Venkataramanan /** 196772adf242SAnirudh Venkataramanan * ice_vsi_stop_tx_rings - Disable Tx rings 196872adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 1969ddf30f7fSAnirudh Venkataramanan * @rst_src: reset source 1970ddf30f7fSAnirudh Venkataramanan * @rel_vmvf_num: Relative id of VF/VM 197103f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be stopped 197203f7a986SAnirudh Venkataramanan * @offset: offset within vsi->txq_map 197372adf242SAnirudh Venkataramanan */ 197403f7a986SAnirudh Venkataramanan static int 197503f7a986SAnirudh Venkataramanan ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 197603f7a986SAnirudh Venkataramanan u16 rel_vmvf_num, struct ice_ring **rings, int offset) 197772adf242SAnirudh Venkataramanan { 197872adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 197972adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 198072adf242SAnirudh Venkataramanan enum ice_status status; 198172adf242SAnirudh Venkataramanan u32 *q_teids, val; 198272adf242SAnirudh Venkataramanan u16 *q_ids, i; 198372adf242SAnirudh Venkataramanan int err = 0; 198472adf242SAnirudh Venkataramanan 198572adf242SAnirudh Venkataramanan if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS) 198672adf242SAnirudh Venkataramanan return -EINVAL; 198772adf242SAnirudh Venkataramanan 198872adf242SAnirudh Venkataramanan q_teids = devm_kcalloc(&pf->pdev->dev, vsi->num_txq, sizeof(*q_teids), 198972adf242SAnirudh Venkataramanan GFP_KERNEL); 199072adf242SAnirudh Venkataramanan if (!q_teids) 199172adf242SAnirudh Venkataramanan return -ENOMEM; 199272adf242SAnirudh Venkataramanan 199372adf242SAnirudh Venkataramanan q_ids = devm_kcalloc(&pf->pdev->dev, vsi->num_txq, sizeof(*q_ids), 199472adf242SAnirudh Venkataramanan GFP_KERNEL); 199572adf242SAnirudh Venkataramanan if (!q_ids) { 199672adf242SAnirudh Venkataramanan err = -ENOMEM; 199772adf242SAnirudh Venkataramanan goto err_alloc_q_ids; 199872adf242SAnirudh Venkataramanan } 199972adf242SAnirudh Venkataramanan 200072adf242SAnirudh Venkataramanan /* set up the Tx queue list to be disabled */ 200172adf242SAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 200272adf242SAnirudh Venkataramanan u16 v_idx; 200372adf242SAnirudh Venkataramanan 200403f7a986SAnirudh Venkataramanan if (!rings || !rings[i] || !rings[i]->q_vector) { 200572adf242SAnirudh Venkataramanan err = -EINVAL; 200672adf242SAnirudh Venkataramanan goto err_out; 200772adf242SAnirudh Venkataramanan } 200872adf242SAnirudh Venkataramanan 200903f7a986SAnirudh Venkataramanan q_ids[i] = vsi->txq_map[i + offset]; 201003f7a986SAnirudh Venkataramanan q_teids[i] = rings[i]->txq_teid; 201172adf242SAnirudh Venkataramanan 201272adf242SAnirudh Venkataramanan /* clear cause_ena bit for disabled queues */ 201303f7a986SAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(rings[i]->reg_idx)); 201472adf242SAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 201503f7a986SAnirudh Venkataramanan wr32(hw, QINT_TQCTL(rings[i]->reg_idx), val); 201672adf242SAnirudh Venkataramanan 201772adf242SAnirudh Venkataramanan /* software is expected to wait for 100 ns */ 201872adf242SAnirudh Venkataramanan ndelay(100); 201972adf242SAnirudh Venkataramanan 202072adf242SAnirudh Venkataramanan /* trigger a software interrupt for the vector associated to 202172adf242SAnirudh Venkataramanan * the queue to schedule NAPI handler 202272adf242SAnirudh Venkataramanan */ 202303f7a986SAnirudh Venkataramanan v_idx = rings[i]->q_vector->v_idx; 2024eb0208ecSPreethi Banala wr32(hw, GLINT_DYN_CTL(vsi->hw_base_vector + v_idx), 202572adf242SAnirudh Venkataramanan GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M); 202672adf242SAnirudh Venkataramanan } 202772adf242SAnirudh Venkataramanan status = ice_dis_vsi_txq(vsi->port_info, vsi->num_txq, q_ids, q_teids, 2028ddf30f7fSAnirudh Venkataramanan rst_src, rel_vmvf_num, NULL); 202972adf242SAnirudh Venkataramanan /* if the disable queue command was exercised during an active reset 203072adf242SAnirudh Venkataramanan * flow, ICE_ERR_RESET_ONGOING is returned. This is not an error as 203172adf242SAnirudh Venkataramanan * the reset operation disables queues at the hardware level anyway. 203272adf242SAnirudh Venkataramanan */ 203372adf242SAnirudh Venkataramanan if (status == ICE_ERR_RESET_ONGOING) { 203472adf242SAnirudh Venkataramanan dev_info(&pf->pdev->dev, 203572adf242SAnirudh Venkataramanan "Reset in progress. LAN Tx queues already disabled\n"); 203672adf242SAnirudh Venkataramanan } else if (status) { 203772adf242SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 203872adf242SAnirudh Venkataramanan "Failed to disable LAN Tx queues, error: %d\n", 203972adf242SAnirudh Venkataramanan status); 204072adf242SAnirudh Venkataramanan err = -ENODEV; 204172adf242SAnirudh Venkataramanan } 204272adf242SAnirudh Venkataramanan 204372adf242SAnirudh Venkataramanan err_out: 204472adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, q_ids); 204572adf242SAnirudh Venkataramanan 204672adf242SAnirudh Venkataramanan err_alloc_q_ids: 204772adf242SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, q_teids); 204872adf242SAnirudh Venkataramanan 204972adf242SAnirudh Venkataramanan return err; 205072adf242SAnirudh Venkataramanan } 20515153a18eSAnirudh Venkataramanan 20525153a18eSAnirudh Venkataramanan /** 205303f7a986SAnirudh Venkataramanan * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings 205403f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 205503f7a986SAnirudh Venkataramanan * @rst_src: reset source 205603f7a986SAnirudh Venkataramanan * @rel_vmvf_num: Relative id of VF/VM 205703f7a986SAnirudh Venkataramanan */ 205803f7a986SAnirudh Venkataramanan int ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, 205903f7a986SAnirudh Venkataramanan enum ice_disq_rst_src rst_src, u16 rel_vmvf_num) 206003f7a986SAnirudh Venkataramanan { 206103f7a986SAnirudh Venkataramanan return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings, 206203f7a986SAnirudh Venkataramanan 0); 206303f7a986SAnirudh Venkataramanan } 206403f7a986SAnirudh Venkataramanan 206503f7a986SAnirudh Venkataramanan /** 20665153a18eSAnirudh Venkataramanan * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 20675153a18eSAnirudh Venkataramanan * @vsi: VSI to enable or disable VLAN pruning on 20685153a18eSAnirudh Venkataramanan * @ena: set to true to enable VLAN pruning and false to disable it 20695153a18eSAnirudh Venkataramanan * 20705153a18eSAnirudh Venkataramanan * returns 0 if VSI is updated, negative otherwise 20715153a18eSAnirudh Venkataramanan */ 20725153a18eSAnirudh Venkataramanan int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena) 20735153a18eSAnirudh Venkataramanan { 20745153a18eSAnirudh Venkataramanan struct ice_vsi_ctx *ctxt; 20755153a18eSAnirudh Venkataramanan struct device *dev; 20765153a18eSAnirudh Venkataramanan int status; 20775153a18eSAnirudh Venkataramanan 20785153a18eSAnirudh Venkataramanan if (!vsi) 20795153a18eSAnirudh Venkataramanan return -EINVAL; 20805153a18eSAnirudh Venkataramanan 20815153a18eSAnirudh Venkataramanan dev = &vsi->back->pdev->dev; 20825153a18eSAnirudh Venkataramanan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 20835153a18eSAnirudh Venkataramanan if (!ctxt) 20845153a18eSAnirudh Venkataramanan return -ENOMEM; 20855153a18eSAnirudh Venkataramanan 20865153a18eSAnirudh Venkataramanan ctxt->info = vsi->info; 20875153a18eSAnirudh Venkataramanan 20885153a18eSAnirudh Venkataramanan if (ena) { 20895153a18eSAnirudh Venkataramanan ctxt->info.sec_flags |= 20905153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 20915153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S; 20925153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 20935153a18eSAnirudh Venkataramanan } else { 20945153a18eSAnirudh Venkataramanan ctxt->info.sec_flags &= 20955153a18eSAnirudh Venkataramanan ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 20965153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 20975153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 20985153a18eSAnirudh Venkataramanan } 20995153a18eSAnirudh Venkataramanan 21005153a18eSAnirudh Venkataramanan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID | 21015153a18eSAnirudh Venkataramanan ICE_AQ_VSI_PROP_SW_VALID); 21025726ca0eSAnirudh Venkataramanan 21035726ca0eSAnirudh Venkataramanan status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL); 21045153a18eSAnirudh Venkataramanan if (status) { 21055726ca0eSAnirudh Venkataramanan netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %d\n", 210631082519SAnirudh Venkataramanan ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status, 21075153a18eSAnirudh Venkataramanan vsi->back->hw.adminq.sq_last_status); 21085153a18eSAnirudh Venkataramanan goto err_out; 21095153a18eSAnirudh Venkataramanan } 21105153a18eSAnirudh Venkataramanan 21115153a18eSAnirudh Venkataramanan vsi->info.sec_flags = ctxt->info.sec_flags; 21125153a18eSAnirudh Venkataramanan vsi->info.sw_flags2 = ctxt->info.sw_flags2; 21135153a18eSAnirudh Venkataramanan 21145153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 21155153a18eSAnirudh Venkataramanan return 0; 21165153a18eSAnirudh Venkataramanan 21175153a18eSAnirudh Venkataramanan err_out: 21185153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 21195153a18eSAnirudh Venkataramanan return -EIO; 21205153a18eSAnirudh Venkataramanan } 21215153a18eSAnirudh Venkataramanan 21225153a18eSAnirudh Venkataramanan /** 212337bb8390SAnirudh Venkataramanan * ice_vsi_setup - Set up a VSI by a given type 212437bb8390SAnirudh Venkataramanan * @pf: board private structure 212537bb8390SAnirudh Venkataramanan * @pi: pointer to the port_info instance 212637bb8390SAnirudh Venkataramanan * @type: VSI type 212737bb8390SAnirudh Venkataramanan * @vf_id: defines VF id to which this VSI connects. This field is meant to be 212837bb8390SAnirudh Venkataramanan * used only for ICE_VSI_VF VSI type. For other VSI types, should 212937bb8390SAnirudh Venkataramanan * fill-in ICE_INVAL_VFID as input. 213037bb8390SAnirudh Venkataramanan * 213137bb8390SAnirudh Venkataramanan * This allocates the sw VSI structure and its queue resources. 213237bb8390SAnirudh Venkataramanan * 213337bb8390SAnirudh Venkataramanan * Returns pointer to the successfully allocated and configured VSI sw struct on 213437bb8390SAnirudh Venkataramanan * success, NULL on failure. 213537bb8390SAnirudh Venkataramanan */ 213637bb8390SAnirudh Venkataramanan struct ice_vsi * 213737bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, 21388ede0178SAnirudh Venkataramanan enum ice_vsi_type type, u16 vf_id) 213937bb8390SAnirudh Venkataramanan { 214037bb8390SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 214137bb8390SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 214237bb8390SAnirudh Venkataramanan struct ice_vsi *vsi; 214337bb8390SAnirudh Venkataramanan int ret, i; 214437bb8390SAnirudh Venkataramanan 214537bb8390SAnirudh Venkataramanan vsi = ice_vsi_alloc(pf, type); 214637bb8390SAnirudh Venkataramanan if (!vsi) { 214737bb8390SAnirudh Venkataramanan dev_err(dev, "could not allocate VSI\n"); 214837bb8390SAnirudh Venkataramanan return NULL; 214937bb8390SAnirudh Venkataramanan } 215037bb8390SAnirudh Venkataramanan 215137bb8390SAnirudh Venkataramanan vsi->port_info = pi; 215237bb8390SAnirudh Venkataramanan vsi->vsw = pf->first_sw; 21538ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 21548ede0178SAnirudh Venkataramanan vsi->vf_id = vf_id; 215537bb8390SAnirudh Venkataramanan 215637bb8390SAnirudh Venkataramanan if (ice_vsi_get_qs(vsi)) { 215737bb8390SAnirudh Venkataramanan dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", 215837bb8390SAnirudh Venkataramanan vsi->idx); 215937bb8390SAnirudh Venkataramanan goto unroll_get_qs; 216037bb8390SAnirudh Venkataramanan } 216137bb8390SAnirudh Venkataramanan 216237bb8390SAnirudh Venkataramanan /* set RSS capabilities */ 216337bb8390SAnirudh Venkataramanan ice_vsi_set_rss_params(vsi); 216437bb8390SAnirudh Venkataramanan 2165c5a2a4a3SUsha Ketineni /* set tc configuration */ 2166c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2167c5a2a4a3SUsha Ketineni 216837bb8390SAnirudh Venkataramanan /* create the VSI */ 216937bb8390SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 217037bb8390SAnirudh Venkataramanan if (ret) 217137bb8390SAnirudh Venkataramanan goto unroll_get_qs; 217237bb8390SAnirudh Venkataramanan 217337bb8390SAnirudh Venkataramanan switch (vsi->type) { 217437bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 217537bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 217637bb8390SAnirudh Venkataramanan if (ret) 217737bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 217837bb8390SAnirudh Venkataramanan 217937bb8390SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 218037bb8390SAnirudh Venkataramanan if (ret) 218137bb8390SAnirudh Venkataramanan goto unroll_alloc_q_vector; 218237bb8390SAnirudh Venkataramanan 218337bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 218437bb8390SAnirudh Venkataramanan if (ret) 218537bb8390SAnirudh Venkataramanan goto unroll_vector_base; 218637bb8390SAnirudh Venkataramanan 218737bb8390SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 218837bb8390SAnirudh Venkataramanan 218937bb8390SAnirudh Venkataramanan /* Do not exit if configuring RSS had an issue, at least 219037bb8390SAnirudh Venkataramanan * receive traffic on first queue. Hence no need to capture 219137bb8390SAnirudh Venkataramanan * return value 219237bb8390SAnirudh Venkataramanan */ 219337bb8390SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 219437bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_lut_key(vsi); 219537bb8390SAnirudh Venkataramanan break; 21968ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 21978ede0178SAnirudh Venkataramanan /* VF driver will take care of creating netdev for this type and 21988ede0178SAnirudh Venkataramanan * map queues to vectors through Virtchnl, PF driver only 21998ede0178SAnirudh Venkataramanan * creates a VSI and corresponding structures for bookkeeping 22008ede0178SAnirudh Venkataramanan * purpose 22018ede0178SAnirudh Venkataramanan */ 22028ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 22038ede0178SAnirudh Venkataramanan if (ret) 22048ede0178SAnirudh Venkataramanan goto unroll_vsi_init; 22058ede0178SAnirudh Venkataramanan 22068ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 22078ede0178SAnirudh Venkataramanan if (ret) 22088ede0178SAnirudh Venkataramanan goto unroll_alloc_q_vector; 22098ede0178SAnirudh Venkataramanan 22108ede0178SAnirudh Venkataramanan /* Setup Vector base only during VF init phase or when VF asks 22118ede0178SAnirudh Venkataramanan * for more vectors than assigned number. In all other cases, 22128ede0178SAnirudh Venkataramanan * assign hw_base_vector to the value given earlier. 22138ede0178SAnirudh Venkataramanan */ 22148ede0178SAnirudh Venkataramanan if (test_bit(ICE_VF_STATE_CFG_INTR, pf->vf[vf_id].vf_states)) { 22158ede0178SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 22168ede0178SAnirudh Venkataramanan if (ret) 22178ede0178SAnirudh Venkataramanan goto unroll_vector_base; 22188ede0178SAnirudh Venkataramanan } else { 22198ede0178SAnirudh Venkataramanan vsi->hw_base_vector = pf->vf[vf_id].first_vector_idx; 22208ede0178SAnirudh Venkataramanan } 22218ede0178SAnirudh Venkataramanan pf->q_left_tx -= vsi->alloc_txq; 22228ede0178SAnirudh Venkataramanan pf->q_left_rx -= vsi->alloc_rxq; 22238ede0178SAnirudh Venkataramanan break; 222437bb8390SAnirudh Venkataramanan default: 2225df17b7e0SAnirudh Venkataramanan /* clean up the resources and exit */ 222637bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 222737bb8390SAnirudh Venkataramanan } 222837bb8390SAnirudh Venkataramanan 222937bb8390SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 223037bb8390SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2231c5a2a4a3SUsha Ketineni max_txqs[i] = pf->num_lan_tx; 223237bb8390SAnirudh Venkataramanan 22334fb33f31SAnirudh Venkataramanan ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 22344fb33f31SAnirudh Venkataramanan max_txqs); 223537bb8390SAnirudh Venkataramanan if (ret) { 223637bb8390SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "Failed VSI lan queue config\n"); 223737bb8390SAnirudh Venkataramanan goto unroll_vector_base; 223837bb8390SAnirudh Venkataramanan } 223937bb8390SAnirudh Venkataramanan 224037bb8390SAnirudh Venkataramanan return vsi; 224137bb8390SAnirudh Venkataramanan 224237bb8390SAnirudh Venkataramanan unroll_vector_base: 2243eb0208ecSPreethi Banala /* reclaim SW interrupts back to the common pool */ 2244eb0208ecSPreethi Banala ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); 2245eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 2246eb0208ecSPreethi Banala /* reclaim HW interrupt back to the common pool */ 2247eb0208ecSPreethi Banala ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); 2248eb0208ecSPreethi Banala pf->num_avail_hw_msix += vsi->num_q_vectors; 224937bb8390SAnirudh Venkataramanan unroll_alloc_q_vector: 225037bb8390SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 225137bb8390SAnirudh Venkataramanan unroll_vsi_init: 225237bb8390SAnirudh Venkataramanan ice_vsi_delete(vsi); 225337bb8390SAnirudh Venkataramanan unroll_get_qs: 225437bb8390SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 225537bb8390SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 225637bb8390SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 225737bb8390SAnirudh Venkataramanan ice_vsi_clear(vsi); 225837bb8390SAnirudh Venkataramanan 225937bb8390SAnirudh Venkataramanan return NULL; 226037bb8390SAnirudh Venkataramanan } 226137bb8390SAnirudh Venkataramanan 226237bb8390SAnirudh Venkataramanan /** 22635153a18eSAnirudh Venkataramanan * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW 22645153a18eSAnirudh Venkataramanan * @vsi: the VSI being cleaned up 22655153a18eSAnirudh Venkataramanan */ 22665153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi) 22675153a18eSAnirudh Venkataramanan { 22685153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2269eb0208ecSPreethi Banala u16 vector = vsi->hw_base_vector; 22705153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 22715153a18eSAnirudh Venkataramanan u32 txq = 0; 22725153a18eSAnirudh Venkataramanan u32 rxq = 0; 22735153a18eSAnirudh Venkataramanan int i, q; 22745153a18eSAnirudh Venkataramanan 22755153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++, vector++) { 22765153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 22775153a18eSAnirudh Venkataramanan 2278d2b464a7SBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR0, vector), 0); 2279d2b464a7SBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR1, vector), 0); 22805153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 22815153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); 22825153a18eSAnirudh Venkataramanan txq++; 22835153a18eSAnirudh Venkataramanan } 22845153a18eSAnirudh Venkataramanan 22855153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 22865153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0); 22875153a18eSAnirudh Venkataramanan rxq++; 22885153a18eSAnirudh Venkataramanan } 22895153a18eSAnirudh Venkataramanan } 22905153a18eSAnirudh Venkataramanan 22915153a18eSAnirudh Venkataramanan ice_flush(hw); 22925153a18eSAnirudh Venkataramanan } 22935153a18eSAnirudh Venkataramanan 22945153a18eSAnirudh Venkataramanan /** 22955153a18eSAnirudh Venkataramanan * ice_vsi_free_irq - Free the IRQ association with the OS 22965153a18eSAnirudh Venkataramanan * @vsi: the VSI being configured 22975153a18eSAnirudh Venkataramanan */ 22985153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi) 22995153a18eSAnirudh Venkataramanan { 23005153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2301eb0208ecSPreethi Banala int base = vsi->sw_base_vector; 23025153a18eSAnirudh Venkataramanan 23035153a18eSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 23045153a18eSAnirudh Venkataramanan int i; 23055153a18eSAnirudh Venkataramanan 23065153a18eSAnirudh Venkataramanan if (!vsi->q_vectors || !vsi->irqs_ready) 23075153a18eSAnirudh Venkataramanan return; 23085153a18eSAnirudh Venkataramanan 2309eb0208ecSPreethi Banala ice_vsi_release_msix(vsi); 23108ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 23118ede0178SAnirudh Venkataramanan return; 2312eb0208ecSPreethi Banala 23135153a18eSAnirudh Venkataramanan vsi->irqs_ready = false; 23145153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++) { 23155153a18eSAnirudh Venkataramanan u16 vector = i + base; 23165153a18eSAnirudh Venkataramanan int irq_num; 23175153a18eSAnirudh Venkataramanan 23185153a18eSAnirudh Venkataramanan irq_num = pf->msix_entries[vector].vector; 23195153a18eSAnirudh Venkataramanan 23205153a18eSAnirudh Venkataramanan /* free only the irqs that were actually requested */ 23215153a18eSAnirudh Venkataramanan if (!vsi->q_vectors[i] || 23225153a18eSAnirudh Venkataramanan !(vsi->q_vectors[i]->num_ring_tx || 23235153a18eSAnirudh Venkataramanan vsi->q_vectors[i]->num_ring_rx)) 23245153a18eSAnirudh Venkataramanan continue; 23255153a18eSAnirudh Venkataramanan 23265153a18eSAnirudh Venkataramanan /* clear the affinity notifier in the IRQ descriptor */ 23275153a18eSAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 23285153a18eSAnirudh Venkataramanan 23295153a18eSAnirudh Venkataramanan /* clear the affinity_mask in the IRQ descriptor */ 23305153a18eSAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 23315153a18eSAnirudh Venkataramanan synchronize_irq(irq_num); 23325153a18eSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, 23335153a18eSAnirudh Venkataramanan vsi->q_vectors[i]); 23345153a18eSAnirudh Venkataramanan } 23355153a18eSAnirudh Venkataramanan } 23365153a18eSAnirudh Venkataramanan } 23375153a18eSAnirudh Venkataramanan 23385153a18eSAnirudh Venkataramanan /** 23395153a18eSAnirudh Venkataramanan * ice_vsi_free_tx_rings - Free Tx resources for VSI queues 23405153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 23415153a18eSAnirudh Venkataramanan */ 23425153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi) 23435153a18eSAnirudh Venkataramanan { 23445153a18eSAnirudh Venkataramanan int i; 23455153a18eSAnirudh Venkataramanan 23465153a18eSAnirudh Venkataramanan if (!vsi->tx_rings) 23475153a18eSAnirudh Venkataramanan return; 23485153a18eSAnirudh Venkataramanan 23495153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) 23505153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 23515153a18eSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 23525153a18eSAnirudh Venkataramanan } 23535153a18eSAnirudh Venkataramanan 23545153a18eSAnirudh Venkataramanan /** 23555153a18eSAnirudh Venkataramanan * ice_vsi_free_rx_rings - Free Rx resources for VSI queues 23565153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 23575153a18eSAnirudh Venkataramanan */ 23585153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi) 23595153a18eSAnirudh Venkataramanan { 23605153a18eSAnirudh Venkataramanan int i; 23615153a18eSAnirudh Venkataramanan 23625153a18eSAnirudh Venkataramanan if (!vsi->rx_rings) 23635153a18eSAnirudh Venkataramanan return; 23645153a18eSAnirudh Venkataramanan 23655153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 23665153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) 23675153a18eSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 23685153a18eSAnirudh Venkataramanan } 23695153a18eSAnirudh Venkataramanan 23705153a18eSAnirudh Venkataramanan /** 237107309a0eSAnirudh Venkataramanan * ice_vsi_close - Shut down a VSI 237207309a0eSAnirudh Venkataramanan * @vsi: the VSI being shut down 237307309a0eSAnirudh Venkataramanan */ 237407309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi) 237507309a0eSAnirudh Venkataramanan { 237607309a0eSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) 237707309a0eSAnirudh Venkataramanan ice_down(vsi); 237807309a0eSAnirudh Venkataramanan 237907309a0eSAnirudh Venkataramanan ice_vsi_free_irq(vsi); 238007309a0eSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 238107309a0eSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 238207309a0eSAnirudh Venkataramanan } 238307309a0eSAnirudh Venkataramanan 238407309a0eSAnirudh Venkataramanan /** 23855153a18eSAnirudh Venkataramanan * ice_free_res - free a block of resources 23865153a18eSAnirudh Venkataramanan * @res: pointer to the resource 23875153a18eSAnirudh Venkataramanan * @index: starting index previously returned by ice_get_res 23885153a18eSAnirudh Venkataramanan * @id: identifier to track owner 23895153a18eSAnirudh Venkataramanan * 23905153a18eSAnirudh Venkataramanan * Returns number of resources freed 23915153a18eSAnirudh Venkataramanan */ 23925153a18eSAnirudh Venkataramanan int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) 23935153a18eSAnirudh Venkataramanan { 23945153a18eSAnirudh Venkataramanan int count = 0; 23955153a18eSAnirudh Venkataramanan int i; 23965153a18eSAnirudh Venkataramanan 23975153a18eSAnirudh Venkataramanan if (!res || index >= res->num_entries) 23985153a18eSAnirudh Venkataramanan return -EINVAL; 23995153a18eSAnirudh Venkataramanan 24005153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 24015153a18eSAnirudh Venkataramanan for (i = index; i < res->num_entries && res->list[i] == id; i++) { 24025153a18eSAnirudh Venkataramanan res->list[i] = 0; 24035153a18eSAnirudh Venkataramanan count++; 24045153a18eSAnirudh Venkataramanan } 24055153a18eSAnirudh Venkataramanan 24065153a18eSAnirudh Venkataramanan return count; 24075153a18eSAnirudh Venkataramanan } 24085153a18eSAnirudh Venkataramanan 24095153a18eSAnirudh Venkataramanan /** 24105153a18eSAnirudh Venkataramanan * ice_search_res - Search the tracker for a block of resources 24115153a18eSAnirudh Venkataramanan * @res: pointer to the resource 24125153a18eSAnirudh Venkataramanan * @needed: size of the block needed 24135153a18eSAnirudh Venkataramanan * @id: identifier to track owner 24145153a18eSAnirudh Venkataramanan * 24155153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 24165153a18eSAnirudh Venkataramanan */ 24175153a18eSAnirudh Venkataramanan static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) 24185153a18eSAnirudh Venkataramanan { 24195153a18eSAnirudh Venkataramanan int start = res->search_hint; 24205153a18eSAnirudh Venkataramanan int end = start; 24215153a18eSAnirudh Venkataramanan 2422eb0208ecSPreethi Banala if ((start + needed) > res->num_entries) 2423eb0208ecSPreethi Banala return -ENOMEM; 2424eb0208ecSPreethi Banala 24255153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 24265153a18eSAnirudh Venkataramanan 24275153a18eSAnirudh Venkataramanan do { 24285153a18eSAnirudh Venkataramanan /* skip already allocated entries */ 24295153a18eSAnirudh Venkataramanan if (res->list[end++] & ICE_RES_VALID_BIT) { 24305153a18eSAnirudh Venkataramanan start = end; 24315153a18eSAnirudh Venkataramanan if ((start + needed) > res->num_entries) 24325153a18eSAnirudh Venkataramanan break; 24335153a18eSAnirudh Venkataramanan } 24345153a18eSAnirudh Venkataramanan 24355153a18eSAnirudh Venkataramanan if (end == (start + needed)) { 24365153a18eSAnirudh Venkataramanan int i = start; 24375153a18eSAnirudh Venkataramanan 24385153a18eSAnirudh Venkataramanan /* there was enough, so assign it to the requestor */ 24395153a18eSAnirudh Venkataramanan while (i != end) 24405153a18eSAnirudh Venkataramanan res->list[i++] = id; 24415153a18eSAnirudh Venkataramanan 24425153a18eSAnirudh Venkataramanan if (end == res->num_entries) 24435153a18eSAnirudh Venkataramanan end = 0; 24445153a18eSAnirudh Venkataramanan 24455153a18eSAnirudh Venkataramanan res->search_hint = end; 24465153a18eSAnirudh Venkataramanan return start; 24475153a18eSAnirudh Venkataramanan } 24485153a18eSAnirudh Venkataramanan } while (1); 24495153a18eSAnirudh Venkataramanan 24505153a18eSAnirudh Venkataramanan return -ENOMEM; 24515153a18eSAnirudh Venkataramanan } 24525153a18eSAnirudh Venkataramanan 24535153a18eSAnirudh Venkataramanan /** 24545153a18eSAnirudh Venkataramanan * ice_get_res - get a block of resources 24555153a18eSAnirudh Venkataramanan * @pf: board private structure 24565153a18eSAnirudh Venkataramanan * @res: pointer to the resource 24575153a18eSAnirudh Venkataramanan * @needed: size of the block needed 24585153a18eSAnirudh Venkataramanan * @id: identifier to track owner 24595153a18eSAnirudh Venkataramanan * 24605153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 24615153a18eSAnirudh Venkataramanan * The search_hint trick and lack of advanced fit-finding only works 24625153a18eSAnirudh Venkataramanan * because we're highly likely to have all the same sized requests. 24635153a18eSAnirudh Venkataramanan * Linear search time and any fragmentation should be minimal. 24645153a18eSAnirudh Venkataramanan */ 24655153a18eSAnirudh Venkataramanan int 24665153a18eSAnirudh Venkataramanan ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) 24675153a18eSAnirudh Venkataramanan { 24685153a18eSAnirudh Venkataramanan int ret; 24695153a18eSAnirudh Venkataramanan 24705153a18eSAnirudh Venkataramanan if (!res || !pf) 24715153a18eSAnirudh Venkataramanan return -EINVAL; 24725153a18eSAnirudh Venkataramanan 24735153a18eSAnirudh Venkataramanan if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { 24745153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 24755153a18eSAnirudh Venkataramanan "param err: needed=%d, num_entries = %d id=0x%04x\n", 24765153a18eSAnirudh Venkataramanan needed, res->num_entries, id); 24775153a18eSAnirudh Venkataramanan return -EINVAL; 24785153a18eSAnirudh Venkataramanan } 24795153a18eSAnirudh Venkataramanan 24805153a18eSAnirudh Venkataramanan /* search based on search_hint */ 24815153a18eSAnirudh Venkataramanan ret = ice_search_res(res, needed, id); 24825153a18eSAnirudh Venkataramanan 24835153a18eSAnirudh Venkataramanan if (ret < 0) { 24845153a18eSAnirudh Venkataramanan /* previous search failed. Reset search hint and try again */ 24855153a18eSAnirudh Venkataramanan res->search_hint = 0; 24865153a18eSAnirudh Venkataramanan ret = ice_search_res(res, needed, id); 24875153a18eSAnirudh Venkataramanan } 24885153a18eSAnirudh Venkataramanan 24895153a18eSAnirudh Venkataramanan return ret; 24905153a18eSAnirudh Venkataramanan } 24915153a18eSAnirudh Venkataramanan 24925153a18eSAnirudh Venkataramanan /** 24935153a18eSAnirudh Venkataramanan * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI 24945153a18eSAnirudh Venkataramanan * @vsi: the VSI being un-configured 24955153a18eSAnirudh Venkataramanan */ 24965153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi) 24975153a18eSAnirudh Venkataramanan { 2498eb0208ecSPreethi Banala int base = vsi->sw_base_vector; 24995153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 25005153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 25015153a18eSAnirudh Venkataramanan u32 val; 25025153a18eSAnirudh Venkataramanan int i; 25035153a18eSAnirudh Venkataramanan 25045153a18eSAnirudh Venkataramanan /* disable interrupt causation from each queue */ 25055153a18eSAnirudh Venkataramanan if (vsi->tx_rings) { 25065153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 25075153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i]) { 25085153a18eSAnirudh Venkataramanan u16 reg; 25095153a18eSAnirudh Venkataramanan 25105153a18eSAnirudh Venkataramanan reg = vsi->tx_rings[i]->reg_idx; 25115153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(reg)); 25125153a18eSAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 25135153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(reg), val); 25145153a18eSAnirudh Venkataramanan } 25155153a18eSAnirudh Venkataramanan } 25165153a18eSAnirudh Venkataramanan } 25175153a18eSAnirudh Venkataramanan 25185153a18eSAnirudh Venkataramanan if (vsi->rx_rings) { 25195153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 25205153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i]) { 25215153a18eSAnirudh Venkataramanan u16 reg; 25225153a18eSAnirudh Venkataramanan 25235153a18eSAnirudh Venkataramanan reg = vsi->rx_rings[i]->reg_idx; 25245153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_RQCTL(reg)); 25255153a18eSAnirudh Venkataramanan val &= ~QINT_RQCTL_CAUSE_ENA_M; 25265153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(reg), val); 25275153a18eSAnirudh Venkataramanan } 25285153a18eSAnirudh Venkataramanan } 25295153a18eSAnirudh Venkataramanan } 25305153a18eSAnirudh Venkataramanan 25315153a18eSAnirudh Venkataramanan /* disable each interrupt */ 25325153a18eSAnirudh Venkataramanan if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { 2533eb0208ecSPreethi Banala for (i = vsi->hw_base_vector; 2534eb0208ecSPreethi Banala i < (vsi->num_q_vectors + vsi->hw_base_vector); i++) 25355153a18eSAnirudh Venkataramanan wr32(hw, GLINT_DYN_CTL(i), 0); 25365153a18eSAnirudh Venkataramanan 25375153a18eSAnirudh Venkataramanan ice_flush(hw); 25385153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->num_q_vectors; i++) 25395153a18eSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[i + base].vector); 25405153a18eSAnirudh Venkataramanan } 25415153a18eSAnirudh Venkataramanan } 25425153a18eSAnirudh Venkataramanan 25435153a18eSAnirudh Venkataramanan /** 2544df0f8479SAnirudh Venkataramanan * ice_vsi_release - Delete a VSI and free its resources 2545df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 2546df0f8479SAnirudh Venkataramanan * 2547df0f8479SAnirudh Venkataramanan * Returns 0 on success or < 0 on error 2548df0f8479SAnirudh Venkataramanan */ 2549df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi) 2550df0f8479SAnirudh Venkataramanan { 2551b751930cSBrett Creeley struct ice_vf *vf = NULL; 2552df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 2553df0f8479SAnirudh Venkataramanan 2554df0f8479SAnirudh Venkataramanan if (!vsi->back) 2555df0f8479SAnirudh Venkataramanan return -ENODEV; 2556df0f8479SAnirudh Venkataramanan pf = vsi->back; 2557b751930cSBrett Creeley 2558b751930cSBrett Creeley if (vsi->type == ICE_VSI_VF) 25598ede0178SAnirudh Venkataramanan vf = &pf->vf[vsi->vf_id]; 2560df0f8479SAnirudh Venkataramanan /* do not unregister and free netdevs while driver is in the reset 2561df0f8479SAnirudh Venkataramanan * recovery pending state. Since reset/rebuild happens through PF 2562df0f8479SAnirudh Venkataramanan * service task workqueue, its not a good idea to unregister netdev 2563df0f8479SAnirudh Venkataramanan * that is associated to the PF that is running the work queue items 2564df0f8479SAnirudh Venkataramanan * currently. This is done to avoid check_flush_dependency() warning 2565df0f8479SAnirudh Venkataramanan * on this wq 2566df0f8479SAnirudh Venkataramanan */ 25675df7e45dSDave Ertman if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) { 256825525b69SDave Ertman ice_napi_del(vsi); 2569df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2570df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 2571df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 2572df0f8479SAnirudh Venkataramanan } 2573df0f8479SAnirudh Venkataramanan 2574df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 2575df0f8479SAnirudh Venkataramanan ice_rss_clean(vsi); 2576df0f8479SAnirudh Venkataramanan 2577df0f8479SAnirudh Venkataramanan /* Disable VSI and free resources */ 2578df0f8479SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 2579df0f8479SAnirudh Venkataramanan ice_vsi_close(vsi); 2580df0f8479SAnirudh Venkataramanan 2581df0f8479SAnirudh Venkataramanan /* reclaim interrupt vectors back to PF */ 25828ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 25838ede0178SAnirudh Venkataramanan /* reclaim SW interrupts back to the common pool */ 25848ede0178SAnirudh Venkataramanan ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, 25858ede0178SAnirudh Venkataramanan vsi->idx); 2586eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 25878ede0178SAnirudh Venkataramanan /* reclaim HW interrupts back to the common pool */ 25888ede0178SAnirudh Venkataramanan ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, 25898ede0178SAnirudh Venkataramanan vsi->idx); 2590eb0208ecSPreethi Banala pf->num_avail_hw_msix += vsi->num_q_vectors; 25918ede0178SAnirudh Venkataramanan } else if (test_bit(ICE_VF_STATE_CFG_INTR, vf->vf_states)) { 25928ede0178SAnirudh Venkataramanan /* Reclaim VF resources back only while freeing all VFs or 25938ede0178SAnirudh Venkataramanan * vector reassignment is requested 25948ede0178SAnirudh Venkataramanan */ 25958ede0178SAnirudh Venkataramanan ice_free_res(vsi->back->hw_irq_tracker, vf->first_vector_idx, 25968ede0178SAnirudh Venkataramanan vsi->idx); 25978ede0178SAnirudh Venkataramanan pf->num_avail_hw_msix += pf->num_vf_msix; 25988ede0178SAnirudh Venkataramanan } 2599df0f8479SAnirudh Venkataramanan 26005726ca0eSAnirudh Venkataramanan ice_remove_vsi_fltr(&pf->hw, vsi->idx); 260110e03a22SAnirudh Venkataramanan ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2602df0f8479SAnirudh Venkataramanan ice_vsi_delete(vsi); 2603df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2604df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2605df0f8479SAnirudh Venkataramanan 2606df0f8479SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2607df0f8479SAnirudh Venkataramanan pf->q_left_tx += vsi->alloc_txq; 2608df0f8479SAnirudh Venkataramanan pf->q_left_rx += vsi->alloc_rxq; 2609df0f8479SAnirudh Venkataramanan 2610df0f8479SAnirudh Venkataramanan /* retain SW VSI data structure since it is needed to unregister and 2611df0f8479SAnirudh Venkataramanan * free VSI netdev when PF is not in reset recovery pending state,\ 2612df0f8479SAnirudh Venkataramanan * for ex: during rmmod. 2613df0f8479SAnirudh Venkataramanan */ 26145df7e45dSDave Ertman if (!ice_is_reset_in_progress(pf->state)) 2615df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2616df0f8479SAnirudh Venkataramanan 2617df0f8479SAnirudh Venkataramanan return 0; 2618df0f8479SAnirudh Venkataramanan } 2619df0f8479SAnirudh Venkataramanan 2620df0f8479SAnirudh Venkataramanan /** 2621df0f8479SAnirudh Venkataramanan * ice_vsi_rebuild - Rebuild VSI after reset 2622df0f8479SAnirudh Venkataramanan * @vsi: VSI to be rebuild 2623df0f8479SAnirudh Venkataramanan * 2624df0f8479SAnirudh Venkataramanan * Returns 0 on success and negative value on failure 2625df0f8479SAnirudh Venkataramanan */ 2626df0f8479SAnirudh Venkataramanan int ice_vsi_rebuild(struct ice_vsi *vsi) 2627df0f8479SAnirudh Venkataramanan { 2628df0f8479SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 2629c5a2a4a3SUsha Ketineni struct ice_pf *pf; 2630df0f8479SAnirudh Venkataramanan int ret, i; 2631df0f8479SAnirudh Venkataramanan 2632df0f8479SAnirudh Venkataramanan if (!vsi) 2633df0f8479SAnirudh Venkataramanan return -EINVAL; 2634df0f8479SAnirudh Venkataramanan 2635c5a2a4a3SUsha Ketineni pf = vsi->back; 263647e3e53cSHenry Tieman ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2637df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2638eb0208ecSPreethi Banala ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); 2639eb0208ecSPreethi Banala ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); 2640eb0208ecSPreethi Banala vsi->sw_base_vector = 0; 2641eb0208ecSPreethi Banala vsi->hw_base_vector = 0; 2642df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2643df0f8479SAnirudh Venkataramanan ice_vsi_free_arrays(vsi, false); 2644f203dca3SAnirudh Venkataramanan ice_dev_onetime_setup(&vsi->back->hw); 2645df0f8479SAnirudh Venkataramanan ice_vsi_set_num_qs(vsi); 2646c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2647df0f8479SAnirudh Venkataramanan 2648df0f8479SAnirudh Venkataramanan /* Initialize VSI struct elements and create VSI in FW */ 2649df0f8479SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 2650df0f8479SAnirudh Venkataramanan if (ret < 0) 2651df0f8479SAnirudh Venkataramanan goto err_vsi; 2652df0f8479SAnirudh Venkataramanan 2653df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_arrays(vsi, false); 2654df0f8479SAnirudh Venkataramanan if (ret < 0) 2655df0f8479SAnirudh Venkataramanan goto err_vsi; 2656df0f8479SAnirudh Venkataramanan 2657df0f8479SAnirudh Venkataramanan switch (vsi->type) { 2658df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 2659df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 2660df0f8479SAnirudh Venkataramanan if (ret) 2661df0f8479SAnirudh Venkataramanan goto err_rings; 2662df0f8479SAnirudh Venkataramanan 2663df0f8479SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 2664df0f8479SAnirudh Venkataramanan if (ret) 2665df0f8479SAnirudh Venkataramanan goto err_vectors; 2666df0f8479SAnirudh Venkataramanan 2667df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 2668df0f8479SAnirudh Venkataramanan if (ret) 2669df0f8479SAnirudh Venkataramanan goto err_vectors; 2670df0f8479SAnirudh Venkataramanan 2671df0f8479SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 267227a98affSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 267327a98affSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 267427a98affSMd Fahad Iqbal Polash * return value 267527a98affSMd Fahad Iqbal Polash */ 267627a98affSMd Fahad Iqbal Polash if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) 267727a98affSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 2678df0f8479SAnirudh Venkataramanan break; 26798ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 26808ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 26818ede0178SAnirudh Venkataramanan if (ret) 26828ede0178SAnirudh Venkataramanan goto err_rings; 26838ede0178SAnirudh Venkataramanan 26848ede0178SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 26858ede0178SAnirudh Venkataramanan if (ret) 26868ede0178SAnirudh Venkataramanan goto err_vectors; 26878ede0178SAnirudh Venkataramanan 26888ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 26898ede0178SAnirudh Venkataramanan if (ret) 26908ede0178SAnirudh Venkataramanan goto err_vectors; 26918ede0178SAnirudh Venkataramanan 26928ede0178SAnirudh Venkataramanan vsi->back->q_left_tx -= vsi->alloc_txq; 26938ede0178SAnirudh Venkataramanan vsi->back->q_left_rx -= vsi->alloc_rxq; 26948ede0178SAnirudh Venkataramanan break; 2695df0f8479SAnirudh Venkataramanan default: 2696df0f8479SAnirudh Venkataramanan break; 2697df0f8479SAnirudh Venkataramanan } 2698df0f8479SAnirudh Venkataramanan 2699df0f8479SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 2700df0f8479SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2701c5a2a4a3SUsha Ketineni max_txqs[i] = pf->num_lan_tx; 2702df0f8479SAnirudh Venkataramanan 27034fb33f31SAnirudh Venkataramanan ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 27044fb33f31SAnirudh Venkataramanan max_txqs); 2705df0f8479SAnirudh Venkataramanan if (ret) { 2706df0f8479SAnirudh Venkataramanan dev_info(&vsi->back->pdev->dev, 2707df0f8479SAnirudh Venkataramanan "Failed VSI lan queue config\n"); 2708df0f8479SAnirudh Venkataramanan goto err_vectors; 2709df0f8479SAnirudh Venkataramanan } 2710df0f8479SAnirudh Venkataramanan return 0; 2711df0f8479SAnirudh Venkataramanan 2712df0f8479SAnirudh Venkataramanan err_vectors: 2713df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2714df0f8479SAnirudh Venkataramanan err_rings: 2715df0f8479SAnirudh Venkataramanan if (vsi->netdev) { 2716df0f8479SAnirudh Venkataramanan vsi->current_netdev_flags = 0; 2717df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2718df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 2719df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 2720df0f8479SAnirudh Venkataramanan } 2721df0f8479SAnirudh Venkataramanan err_vsi: 2722df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2723df0f8479SAnirudh Venkataramanan set_bit(__ICE_RESET_FAILED, vsi->back->state); 2724df0f8479SAnirudh Venkataramanan return ret; 2725df0f8479SAnirudh Venkataramanan } 2726df0f8479SAnirudh Venkataramanan 2727df0f8479SAnirudh Venkataramanan /** 27285df7e45dSDave Ertman * ice_is_reset_in_progress - check for a reset in progress 27295153a18eSAnirudh Venkataramanan * @state: pf state field 27305153a18eSAnirudh Venkataramanan */ 27315df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state) 27325153a18eSAnirudh Venkataramanan { 27335df7e45dSDave Ertman return test_bit(__ICE_RESET_OICR_RECV, state) || 27345df7e45dSDave Ertman test_bit(__ICE_PFR_REQ, state) || 27355df7e45dSDave Ertman test_bit(__ICE_CORER_REQ, state) || 27365df7e45dSDave Ertman test_bit(__ICE_GLOBR_REQ, state); 27375153a18eSAnirudh Venkataramanan } 2738