145d3d428SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 245d3d428SAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */ 345d3d428SAnirudh Venkataramanan 445d3d428SAnirudh Venkataramanan #include "ice.h" 5eff380aaSAnirudh Venkataramanan #include "ice_base.h" 645d3d428SAnirudh Venkataramanan #include "ice_lib.h" 77b9ffc76SAnirudh Venkataramanan #include "ice_dcb_lib.h" 845d3d428SAnirudh Venkataramanan 945d3d428SAnirudh Venkataramanan /** 10d02f734cSMaciej Fijalkowski * ice_vsi_ctrl_rx_rings - Start or stop a VSI's Rx rings 11d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 12d02f734cSMaciej Fijalkowski * @ena: start or stop the Rx rings 13d02f734cSMaciej Fijalkowski */ 14d02f734cSMaciej Fijalkowski static int ice_vsi_ctrl_rx_rings(struct ice_vsi *vsi, bool ena) 15d02f734cSMaciej Fijalkowski { 16d02f734cSMaciej Fijalkowski int i, ret = 0; 17d02f734cSMaciej Fijalkowski 18d02f734cSMaciej Fijalkowski for (i = 0; i < vsi->num_rxq; i++) { 19d02f734cSMaciej Fijalkowski ret = ice_vsi_ctrl_rx_ring(vsi, ena, i); 20d02f734cSMaciej Fijalkowski if (ret) 21d02f734cSMaciej Fijalkowski break; 2272adf242SAnirudh Venkataramanan } 2372adf242SAnirudh Venkataramanan 2472adf242SAnirudh Venkataramanan return ret; 2572adf242SAnirudh Venkataramanan } 2672adf242SAnirudh Venkataramanan 2772adf242SAnirudh Venkataramanan /** 2828c2a645SAnirudh Venkataramanan * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI 2928c2a645SAnirudh Venkataramanan * @vsi: VSI pointer 3028c2a645SAnirudh Venkataramanan * 3128c2a645SAnirudh Venkataramanan * On error: returns error code (negative) 3228c2a645SAnirudh Venkataramanan * On success: returns 0 3328c2a645SAnirudh Venkataramanan */ 34a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) 3528c2a645SAnirudh Venkataramanan { 3628c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3728c2a645SAnirudh Venkataramanan 3828c2a645SAnirudh Venkataramanan /* allocate memory for both Tx and Rx ring pointers */ 3928c2a645SAnirudh Venkataramanan vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 40c6dfd690SBruce Allan sizeof(*vsi->tx_rings), GFP_KERNEL); 4128c2a645SAnirudh Venkataramanan if (!vsi->tx_rings) 4278b5713aSAnirudh Venkataramanan return -ENOMEM; 4328c2a645SAnirudh Venkataramanan 4428c2a645SAnirudh Venkataramanan vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 45c6dfd690SBruce Allan sizeof(*vsi->rx_rings), GFP_KERNEL); 4628c2a645SAnirudh Venkataramanan if (!vsi->rx_rings) 4778b5713aSAnirudh Venkataramanan goto err_rings; 4878b5713aSAnirudh Venkataramanan 4978b5713aSAnirudh Venkataramanan vsi->txq_map = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq, 5078b5713aSAnirudh Venkataramanan sizeof(*vsi->txq_map), GFP_KERNEL); 5178b5713aSAnirudh Venkataramanan 5278b5713aSAnirudh Venkataramanan if (!vsi->txq_map) 5378b5713aSAnirudh Venkataramanan goto err_txq_map; 5478b5713aSAnirudh Venkataramanan 5578b5713aSAnirudh Venkataramanan vsi->rxq_map = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq, 5678b5713aSAnirudh Venkataramanan sizeof(*vsi->rxq_map), GFP_KERNEL); 5778b5713aSAnirudh Venkataramanan if (!vsi->rxq_map) 5878b5713aSAnirudh Venkataramanan goto err_rxq_map; 5978b5713aSAnirudh Venkataramanan 600e674aebSAnirudh Venkataramanan /* There is no need to allocate q_vectors for a loopback VSI. */ 610e674aebSAnirudh Venkataramanan if (vsi->type == ICE_VSI_LB) 620e674aebSAnirudh Venkataramanan return 0; 630e674aebSAnirudh Venkataramanan 6428c2a645SAnirudh Venkataramanan /* allocate memory for q_vector pointers */ 65a85a3847SBrett Creeley vsi->q_vectors = devm_kcalloc(&pf->pdev->dev, vsi->num_q_vectors, 66a85a3847SBrett Creeley sizeof(*vsi->q_vectors), GFP_KERNEL); 6728c2a645SAnirudh Venkataramanan if (!vsi->q_vectors) 6828c2a645SAnirudh Venkataramanan goto err_vectors; 6928c2a645SAnirudh Venkataramanan 7028c2a645SAnirudh Venkataramanan return 0; 7128c2a645SAnirudh Venkataramanan 7228c2a645SAnirudh Venkataramanan err_vectors: 7378b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rxq_map); 7478b5713aSAnirudh Venkataramanan err_rxq_map: 7578b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->txq_map); 7678b5713aSAnirudh Venkataramanan err_txq_map: 7728c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 7878b5713aSAnirudh Venkataramanan err_rings: 7928c2a645SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 8028c2a645SAnirudh Venkataramanan return -ENOMEM; 8128c2a645SAnirudh Venkataramanan } 8228c2a645SAnirudh Venkataramanan 8328c2a645SAnirudh Venkataramanan /** 84ad71b256SBrett Creeley * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI 85ad71b256SBrett Creeley * @vsi: the VSI being configured 86ad71b256SBrett Creeley */ 87ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi) 88ad71b256SBrett Creeley { 89ad71b256SBrett Creeley switch (vsi->type) { 90ad71b256SBrett Creeley case ICE_VSI_PF: 910e674aebSAnirudh Venkataramanan /* fall through */ 920e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 93ad71b256SBrett Creeley vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC; 94ad71b256SBrett Creeley vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC; 95ad71b256SBrett Creeley break; 96ad71b256SBrett Creeley default: 97ad71b256SBrett Creeley dev_dbg(&vsi->back->pdev->dev, 98ad71b256SBrett Creeley "Not setting number of Tx/Rx descriptors for VSI type %d\n", 99ad71b256SBrett Creeley vsi->type); 100ad71b256SBrett Creeley break; 101ad71b256SBrett Creeley } 102ad71b256SBrett Creeley } 103ad71b256SBrett Creeley 104ad71b256SBrett Creeley /** 105ad71b256SBrett Creeley * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI 10628c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 107f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 10828c2a645SAnirudh Venkataramanan * 10928c2a645SAnirudh Venkataramanan * Return 0 on success and a negative value on error 11028c2a645SAnirudh Venkataramanan */ 1115743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) 11228c2a645SAnirudh Venkataramanan { 11328c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1145743020dSAkeem G Abodunrin struct ice_vf *vf = NULL; 1155743020dSAkeem G Abodunrin 1165743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 1175743020dSAkeem G Abodunrin vsi->vf_id = vf_id; 1185743020dSAkeem G Abodunrin 11928c2a645SAnirudh Venkataramanan switch (vsi->type) { 12028c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 1218c243700SAnirudh Venkataramanan vsi->alloc_txq = min_t(int, ice_get_avail_txq_count(pf), 1228c243700SAnirudh Venkataramanan num_online_cpus()); 1238c243700SAnirudh Venkataramanan 1248c243700SAnirudh Venkataramanan pf->num_lan_tx = vsi->alloc_txq; 1258c243700SAnirudh Venkataramanan 1268c243700SAnirudh Venkataramanan /* only 1 Rx queue unless RSS is enabled */ 1278c243700SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 1288c243700SAnirudh Venkataramanan vsi->alloc_rxq = 1; 1298c243700SAnirudh Venkataramanan else 1308c243700SAnirudh Venkataramanan vsi->alloc_rxq = min_t(int, ice_get_avail_rxq_count(pf), 1318c243700SAnirudh Venkataramanan num_online_cpus()); 1328c243700SAnirudh Venkataramanan 1338c243700SAnirudh Venkataramanan pf->num_lan_rx = vsi->alloc_rxq; 1348c243700SAnirudh Venkataramanan 13534cdcb16SBrett Creeley vsi->num_q_vectors = max_t(int, vsi->alloc_rxq, vsi->alloc_txq); 13628c2a645SAnirudh Venkataramanan break; 1378ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 1385743020dSAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 1395743020dSAkeem G Abodunrin vsi->alloc_txq = vf->num_vf_qs; 1405743020dSAkeem G Abodunrin vsi->alloc_rxq = vf->num_vf_qs; 1418ede0178SAnirudh Venkataramanan /* pf->num_vf_msix includes (VF miscellaneous vector + 1428ede0178SAnirudh Venkataramanan * data queue interrupts). Since vsi->num_q_vectors is number 143047e52c0SAnirudh Venkataramanan * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the 144047e52c0SAnirudh Venkataramanan * original vector count 1458ede0178SAnirudh Venkataramanan */ 146047e52c0SAnirudh Venkataramanan vsi->num_q_vectors = pf->num_vf_msix - ICE_NONQ_VECS_VF; 1478ede0178SAnirudh Venkataramanan break; 1480e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 1490e674aebSAnirudh Venkataramanan vsi->alloc_txq = 1; 1500e674aebSAnirudh Venkataramanan vsi->alloc_rxq = 1; 1510e674aebSAnirudh Venkataramanan break; 15228c2a645SAnirudh Venkataramanan default: 153819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 15428c2a645SAnirudh Venkataramanan break; 15528c2a645SAnirudh Venkataramanan } 156ad71b256SBrett Creeley 157ad71b256SBrett Creeley ice_vsi_set_num_desc(vsi); 15828c2a645SAnirudh Venkataramanan } 15928c2a645SAnirudh Venkataramanan 16028c2a645SAnirudh Venkataramanan /** 16128c2a645SAnirudh Venkataramanan * ice_get_free_slot - get the next non-NULL location index in array 16228c2a645SAnirudh Venkataramanan * @array: array to search 16328c2a645SAnirudh Venkataramanan * @size: size of the array 16428c2a645SAnirudh Venkataramanan * @curr: last known occupied index to be used as a search hint 16528c2a645SAnirudh Venkataramanan * 16628c2a645SAnirudh Venkataramanan * void * is being used to keep the functionality generic. This lets us use this 16728c2a645SAnirudh Venkataramanan * function on any array of pointers. 16828c2a645SAnirudh Venkataramanan */ 16937bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr) 17028c2a645SAnirudh Venkataramanan { 17128c2a645SAnirudh Venkataramanan int **tmp_array = (int **)array; 17228c2a645SAnirudh Venkataramanan int next; 17328c2a645SAnirudh Venkataramanan 17428c2a645SAnirudh Venkataramanan if (curr < (size - 1) && !tmp_array[curr + 1]) { 17528c2a645SAnirudh Venkataramanan next = curr + 1; 17628c2a645SAnirudh Venkataramanan } else { 17728c2a645SAnirudh Venkataramanan int i = 0; 17828c2a645SAnirudh Venkataramanan 17928c2a645SAnirudh Venkataramanan while ((i < size) && (tmp_array[i])) 18028c2a645SAnirudh Venkataramanan i++; 18128c2a645SAnirudh Venkataramanan if (i == size) 18228c2a645SAnirudh Venkataramanan next = ICE_NO_VSI; 18328c2a645SAnirudh Venkataramanan else 18428c2a645SAnirudh Venkataramanan next = i; 18528c2a645SAnirudh Venkataramanan } 18628c2a645SAnirudh Venkataramanan return next; 18728c2a645SAnirudh Venkataramanan } 18828c2a645SAnirudh Venkataramanan 18928c2a645SAnirudh Venkataramanan /** 1905153a18eSAnirudh Venkataramanan * ice_vsi_delete - delete a VSI from the switch 1915153a18eSAnirudh Venkataramanan * @vsi: pointer to VSI being removed 1925153a18eSAnirudh Venkataramanan */ 1935153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi) 1945153a18eSAnirudh Venkataramanan { 1955153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 196198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 1975153a18eSAnirudh Venkataramanan enum ice_status status; 1985153a18eSAnirudh Venkataramanan 199198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 200198a666aSBruce Allan if (!ctxt) 201198a666aSBruce Allan return; 202198a666aSBruce Allan 2038ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 204198a666aSBruce Allan ctxt->vf_num = vsi->vf_id; 205198a666aSBruce Allan ctxt->vsi_num = vsi->vsi_num; 2065153a18eSAnirudh Venkataramanan 207198a666aSBruce Allan memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); 2085153a18eSAnirudh Venkataramanan 209198a666aSBruce Allan status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); 2105153a18eSAnirudh Venkataramanan if (status) 2115153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failed to delete VSI %i in FW\n", 2125153a18eSAnirudh Venkataramanan vsi->vsi_num); 213198a666aSBruce Allan 214198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 2155153a18eSAnirudh Venkataramanan } 2165153a18eSAnirudh Venkataramanan 2175153a18eSAnirudh Venkataramanan /** 218a85a3847SBrett Creeley * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI 21907309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 22007309a0eSAnirudh Venkataramanan */ 221a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi) 22207309a0eSAnirudh Venkataramanan { 22307309a0eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 22407309a0eSAnirudh Venkataramanan 22507309a0eSAnirudh Venkataramanan /* free the ring and vector containers */ 226a85a3847SBrett Creeley if (vsi->q_vectors) { 22707309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->q_vectors); 22807309a0eSAnirudh Venkataramanan vsi->q_vectors = NULL; 22907309a0eSAnirudh Venkataramanan } 23007309a0eSAnirudh Venkataramanan if (vsi->tx_rings) { 23107309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->tx_rings); 23207309a0eSAnirudh Venkataramanan vsi->tx_rings = NULL; 23307309a0eSAnirudh Venkataramanan } 23407309a0eSAnirudh Venkataramanan if (vsi->rx_rings) { 23507309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rx_rings); 23607309a0eSAnirudh Venkataramanan vsi->rx_rings = NULL; 23707309a0eSAnirudh Venkataramanan } 23878b5713aSAnirudh Venkataramanan if (vsi->txq_map) { 23978b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->txq_map); 24078b5713aSAnirudh Venkataramanan vsi->txq_map = NULL; 24178b5713aSAnirudh Venkataramanan } 24278b5713aSAnirudh Venkataramanan if (vsi->rxq_map) { 24378b5713aSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rxq_map); 24478b5713aSAnirudh Venkataramanan vsi->rxq_map = NULL; 24578b5713aSAnirudh Venkataramanan } 24607309a0eSAnirudh Venkataramanan } 24707309a0eSAnirudh Venkataramanan 24807309a0eSAnirudh Venkataramanan /** 24907309a0eSAnirudh Venkataramanan * ice_vsi_clear - clean up and deallocate the provided VSI 25007309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 25107309a0eSAnirudh Venkataramanan * 25207309a0eSAnirudh Venkataramanan * This deallocates the VSI's queue resources, removes it from the PF's 25307309a0eSAnirudh Venkataramanan * VSI array if necessary, and deallocates the VSI 25407309a0eSAnirudh Venkataramanan * 25507309a0eSAnirudh Venkataramanan * Returns 0 on success, negative on failure 25607309a0eSAnirudh Venkataramanan */ 25707309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi) 25807309a0eSAnirudh Venkataramanan { 25907309a0eSAnirudh Venkataramanan struct ice_pf *pf = NULL; 26007309a0eSAnirudh Venkataramanan 26107309a0eSAnirudh Venkataramanan if (!vsi) 26207309a0eSAnirudh Venkataramanan return 0; 26307309a0eSAnirudh Venkataramanan 26407309a0eSAnirudh Venkataramanan if (!vsi->back) 26507309a0eSAnirudh Venkataramanan return -EINVAL; 26607309a0eSAnirudh Venkataramanan 26707309a0eSAnirudh Venkataramanan pf = vsi->back; 26807309a0eSAnirudh Venkataramanan 26907309a0eSAnirudh Venkataramanan if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) { 27007309a0eSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "vsi does not exist at pf->vsi[%d]\n", 27107309a0eSAnirudh Venkataramanan vsi->idx); 27207309a0eSAnirudh Venkataramanan return -EINVAL; 27307309a0eSAnirudh Venkataramanan } 27407309a0eSAnirudh Venkataramanan 27507309a0eSAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 27607309a0eSAnirudh Venkataramanan /* updates the PF for this cleared VSI */ 27707309a0eSAnirudh Venkataramanan 27807309a0eSAnirudh Venkataramanan pf->vsi[vsi->idx] = NULL; 27907309a0eSAnirudh Venkataramanan if (vsi->idx < pf->next_vsi) 28007309a0eSAnirudh Venkataramanan pf->next_vsi = vsi->idx; 28107309a0eSAnirudh Venkataramanan 282a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 28307309a0eSAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 28407309a0eSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 28507309a0eSAnirudh Venkataramanan 28607309a0eSAnirudh Venkataramanan return 0; 28707309a0eSAnirudh Venkataramanan } 28807309a0eSAnirudh Venkataramanan 28907309a0eSAnirudh Venkataramanan /** 2905153a18eSAnirudh Venkataramanan * ice_msix_clean_rings - MSIX mode Interrupt Handler 2915153a18eSAnirudh Venkataramanan * @irq: interrupt number 2925153a18eSAnirudh Venkataramanan * @data: pointer to a q_vector 2935153a18eSAnirudh Venkataramanan */ 294f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data) 2955153a18eSAnirudh Venkataramanan { 2965153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 2975153a18eSAnirudh Venkataramanan 2985153a18eSAnirudh Venkataramanan if (!q_vector->tx.ring && !q_vector->rx.ring) 2995153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 3005153a18eSAnirudh Venkataramanan 3015153a18eSAnirudh Venkataramanan napi_schedule(&q_vector->napi); 3025153a18eSAnirudh Venkataramanan 3035153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 3045153a18eSAnirudh Venkataramanan } 3055153a18eSAnirudh Venkataramanan 3065153a18eSAnirudh Venkataramanan /** 30737bb8390SAnirudh Venkataramanan * ice_vsi_alloc - Allocates the next available struct VSI in the PF 30837bb8390SAnirudh Venkataramanan * @pf: board private structure 30937bb8390SAnirudh Venkataramanan * @type: type of VSI 310f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 31137bb8390SAnirudh Venkataramanan * 31237bb8390SAnirudh Venkataramanan * returns a pointer to a VSI on success, NULL on failure. 31337bb8390SAnirudh Venkataramanan */ 3145743020dSAkeem G Abodunrin static struct ice_vsi * 3155743020dSAkeem G Abodunrin ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type, u16 vf_id) 31637bb8390SAnirudh Venkataramanan { 31737bb8390SAnirudh Venkataramanan struct ice_vsi *vsi = NULL; 31837bb8390SAnirudh Venkataramanan 31937bb8390SAnirudh Venkataramanan /* Need to protect the allocation of the VSIs at the PF level */ 32037bb8390SAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 32137bb8390SAnirudh Venkataramanan 32237bb8390SAnirudh Venkataramanan /* If we have already allocated our maximum number of VSIs, 32337bb8390SAnirudh Venkataramanan * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index 32437bb8390SAnirudh Venkataramanan * is available to be populated 32537bb8390SAnirudh Venkataramanan */ 32637bb8390SAnirudh Venkataramanan if (pf->next_vsi == ICE_NO_VSI) { 32737bb8390SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "out of VSI slots!\n"); 32837bb8390SAnirudh Venkataramanan goto unlock_pf; 32937bb8390SAnirudh Venkataramanan } 33037bb8390SAnirudh Venkataramanan 33137bb8390SAnirudh Venkataramanan vsi = devm_kzalloc(&pf->pdev->dev, sizeof(*vsi), GFP_KERNEL); 33237bb8390SAnirudh Venkataramanan if (!vsi) 33337bb8390SAnirudh Venkataramanan goto unlock_pf; 33437bb8390SAnirudh Venkataramanan 33537bb8390SAnirudh Venkataramanan vsi->type = type; 33637bb8390SAnirudh Venkataramanan vsi->back = pf; 33737bb8390SAnirudh Venkataramanan set_bit(__ICE_DOWN, vsi->state); 3389d56b7fdSJesse Brandeburg 33937bb8390SAnirudh Venkataramanan vsi->idx = pf->next_vsi; 34037bb8390SAnirudh Venkataramanan 3415743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 3425743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf_id); 3435743020dSAkeem G Abodunrin else 3445743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 34537bb8390SAnirudh Venkataramanan 34637bb8390SAnirudh Venkataramanan switch (vsi->type) { 34737bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 348a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 34937bb8390SAnirudh Venkataramanan goto err_rings; 35037bb8390SAnirudh Venkataramanan 35137bb8390SAnirudh Venkataramanan /* Setup default MSIX irq handler for VSI */ 35237bb8390SAnirudh Venkataramanan vsi->irq_handler = ice_msix_clean_rings; 35337bb8390SAnirudh Venkataramanan break; 3548ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 355a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 3568ede0178SAnirudh Venkataramanan goto err_rings; 3578ede0178SAnirudh Venkataramanan break; 3580e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 3590e674aebSAnirudh Venkataramanan if (ice_vsi_alloc_arrays(vsi)) 3600e674aebSAnirudh Venkataramanan goto err_rings; 3610e674aebSAnirudh Venkataramanan break; 36237bb8390SAnirudh Venkataramanan default: 36337bb8390SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 36437bb8390SAnirudh Venkataramanan goto unlock_pf; 36537bb8390SAnirudh Venkataramanan } 36637bb8390SAnirudh Venkataramanan 36737bb8390SAnirudh Venkataramanan /* fill VSI slot in the PF struct */ 36837bb8390SAnirudh Venkataramanan pf->vsi[pf->next_vsi] = vsi; 36937bb8390SAnirudh Venkataramanan 37037bb8390SAnirudh Venkataramanan /* prepare pf->next_vsi for next use */ 37137bb8390SAnirudh Venkataramanan pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi, 37237bb8390SAnirudh Venkataramanan pf->next_vsi); 37337bb8390SAnirudh Venkataramanan goto unlock_pf; 37437bb8390SAnirudh Venkataramanan 37537bb8390SAnirudh Venkataramanan err_rings: 37637bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi); 37737bb8390SAnirudh Venkataramanan vsi = NULL; 37837bb8390SAnirudh Venkataramanan unlock_pf: 37937bb8390SAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 38037bb8390SAnirudh Venkataramanan return vsi; 38137bb8390SAnirudh Venkataramanan } 38237bb8390SAnirudh Venkataramanan 38337bb8390SAnirudh Venkataramanan /** 384df0f8479SAnirudh Venkataramanan * ice_vsi_get_qs - Assign queues from PF to VSI 385df0f8479SAnirudh Venkataramanan * @vsi: the VSI to assign queues to 386df0f8479SAnirudh Venkataramanan * 387df0f8479SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 388df0f8479SAnirudh Venkataramanan */ 38937bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi) 390df0f8479SAnirudh Venkataramanan { 39103f7a986SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 39203f7a986SAnirudh Venkataramanan struct ice_qs_cfg tx_qs_cfg = { 39303f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 39403f7a986SAnirudh Venkataramanan .pf_map = pf->avail_txqs, 39578b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_txqs, 39603f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_txq, 39703f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_TXQS, 39803f7a986SAnirudh Venkataramanan .vsi_map = vsi->txq_map, 39903f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 40003f7a986SAnirudh Venkataramanan .mapping_mode = vsi->tx_mapping_mode 40103f7a986SAnirudh Venkataramanan }; 40203f7a986SAnirudh Venkataramanan struct ice_qs_cfg rx_qs_cfg = { 40303f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 40403f7a986SAnirudh Venkataramanan .pf_map = pf->avail_rxqs, 40578b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_rxqs, 40603f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_rxq, 40703f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_RXQS, 40803f7a986SAnirudh Venkataramanan .vsi_map = vsi->rxq_map, 40903f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 41003f7a986SAnirudh Venkataramanan .mapping_mode = vsi->rx_mapping_mode 41103f7a986SAnirudh Venkataramanan }; 412df0f8479SAnirudh Venkataramanan int ret = 0; 413df0f8479SAnirudh Venkataramanan 414df0f8479SAnirudh Venkataramanan vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG; 415df0f8479SAnirudh Venkataramanan vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG; 416df0f8479SAnirudh Venkataramanan 41703f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&tx_qs_cfg); 41803f7a986SAnirudh Venkataramanan if (!ret) 41903f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&rx_qs_cfg); 420df0f8479SAnirudh Venkataramanan 421df0f8479SAnirudh Venkataramanan return ret; 422df0f8479SAnirudh Venkataramanan } 423df0f8479SAnirudh Venkataramanan 424df0f8479SAnirudh Venkataramanan /** 4255153a18eSAnirudh Venkataramanan * ice_vsi_put_qs - Release queues from VSI to PF 4265153a18eSAnirudh Venkataramanan * @vsi: the VSI that is going to release queues 4275153a18eSAnirudh Venkataramanan */ 4285153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi) 4295153a18eSAnirudh Venkataramanan { 4305153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 4315153a18eSAnirudh Venkataramanan int i; 4325153a18eSAnirudh Venkataramanan 4335153a18eSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 4345153a18eSAnirudh Venkataramanan 4355153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 4365153a18eSAnirudh Venkataramanan clear_bit(vsi->txq_map[i], pf->avail_txqs); 4375153a18eSAnirudh Venkataramanan vsi->txq_map[i] = ICE_INVAL_Q_INDEX; 4385153a18eSAnirudh Venkataramanan } 4395153a18eSAnirudh Venkataramanan 4405153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 4415153a18eSAnirudh Venkataramanan clear_bit(vsi->rxq_map[i], pf->avail_rxqs); 4425153a18eSAnirudh Venkataramanan vsi->rxq_map[i] = ICE_INVAL_Q_INDEX; 4435153a18eSAnirudh Venkataramanan } 4445153a18eSAnirudh Venkataramanan 4455153a18eSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 4465153a18eSAnirudh Venkataramanan } 4475153a18eSAnirudh Venkataramanan 4485153a18eSAnirudh Venkataramanan /** 449462acf6aSTony Nguyen * ice_is_safe_mode 450462acf6aSTony Nguyen * @pf: pointer to the PF struct 451462acf6aSTony Nguyen * 452462acf6aSTony Nguyen * returns true if driver is in safe mode, false otherwise 453462acf6aSTony Nguyen */ 454462acf6aSTony Nguyen bool ice_is_safe_mode(struct ice_pf *pf) 455462acf6aSTony Nguyen { 456462acf6aSTony Nguyen return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags); 457462acf6aSTony Nguyen } 458462acf6aSTony Nguyen 459462acf6aSTony Nguyen /** 460df0f8479SAnirudh Venkataramanan * ice_rss_clean - Delete RSS related VSI structures that hold user inputs 461df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 462df0f8479SAnirudh Venkataramanan */ 463df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi) 464df0f8479SAnirudh Venkataramanan { 465df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 466df0f8479SAnirudh Venkataramanan 467df0f8479SAnirudh Venkataramanan pf = vsi->back; 468df0f8479SAnirudh Venkataramanan 469df0f8479SAnirudh Venkataramanan if (vsi->rss_hkey_user) 470df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_hkey_user); 471df0f8479SAnirudh Venkataramanan if (vsi->rss_lut_user) 472df0f8479SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, vsi->rss_lut_user); 473df0f8479SAnirudh Venkataramanan } 474df0f8479SAnirudh Venkataramanan 475df0f8479SAnirudh Venkataramanan /** 47628c2a645SAnirudh Venkataramanan * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type 47728c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 47828c2a645SAnirudh Venkataramanan */ 47937bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi) 48028c2a645SAnirudh Venkataramanan { 48128c2a645SAnirudh Venkataramanan struct ice_hw_common_caps *cap; 48228c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 48328c2a645SAnirudh Venkataramanan 48428c2a645SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 48528c2a645SAnirudh Venkataramanan vsi->rss_size = 1; 48628c2a645SAnirudh Venkataramanan return; 48728c2a645SAnirudh Venkataramanan } 48828c2a645SAnirudh Venkataramanan 48928c2a645SAnirudh Venkataramanan cap = &pf->hw.func_caps.common_cap; 49028c2a645SAnirudh Venkataramanan switch (vsi->type) { 49128c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 49228c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 49328c2a645SAnirudh Venkataramanan vsi->rss_table_size = cap->rss_table_size; 49428c2a645SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 49528c2a645SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 49628c2a645SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; 49728c2a645SAnirudh Venkataramanan break; 4988ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 4998ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table 5008ede0178SAnirudh Venkataramanan * For VSI_LUT, LUT size should be set to 64 bytes 5018ede0178SAnirudh Venkataramanan */ 5028ede0178SAnirudh Venkataramanan vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 5038ede0178SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 5048ede0178SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 5058ede0178SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 5068ede0178SAnirudh Venkataramanan break; 5070e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 5080e674aebSAnirudh Venkataramanan break; 50928c2a645SAnirudh Venkataramanan default: 51028c2a645SAnirudh Venkataramanan dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", 51128c2a645SAnirudh Venkataramanan vsi->type); 51228c2a645SAnirudh Venkataramanan break; 51328c2a645SAnirudh Venkataramanan } 51428c2a645SAnirudh Venkataramanan } 51528c2a645SAnirudh Venkataramanan 51628c2a645SAnirudh Venkataramanan /** 51728c2a645SAnirudh Venkataramanan * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI 51828c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 51928c2a645SAnirudh Venkataramanan * 52028c2a645SAnirudh Venkataramanan * This initializes a default VSI context for all sections except the Queues. 52128c2a645SAnirudh Venkataramanan */ 52228c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) 52328c2a645SAnirudh Venkataramanan { 52428c2a645SAnirudh Venkataramanan u32 table = 0; 52528c2a645SAnirudh Venkataramanan 52628c2a645SAnirudh Venkataramanan memset(&ctxt->info, 0, sizeof(ctxt->info)); 52728c2a645SAnirudh Venkataramanan /* VSI's should be allocated from shared pool */ 52828c2a645SAnirudh Venkataramanan ctxt->alloc_from_pool = true; 52928c2a645SAnirudh Venkataramanan /* Src pruning enabled by default */ 53028c2a645SAnirudh Venkataramanan ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; 53128c2a645SAnirudh Venkataramanan /* Traffic from VSI can be sent to LAN */ 53228c2a645SAnirudh Venkataramanan ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; 53328c2a645SAnirudh Venkataramanan /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy 53428c2a645SAnirudh Venkataramanan * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all 53528c2a645SAnirudh Venkataramanan * packets untagged/tagged. 53628c2a645SAnirudh Venkataramanan */ 53728c2a645SAnirudh Venkataramanan ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & 53828c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_M) >> 53928c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_S); 54028c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for both ingress/egress tables */ 54128c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(0, 0); 54228c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(1, 1); 54328c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(2, 2); 54428c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(3, 3); 54528c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(4, 4); 54628c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(5, 5); 54728c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(6, 6); 54828c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(7, 7); 54928c2a645SAnirudh Venkataramanan ctxt->info.ingress_table = cpu_to_le32(table); 55028c2a645SAnirudh Venkataramanan ctxt->info.egress_table = cpu_to_le32(table); 55128c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for outer to inner UP table */ 55228c2a645SAnirudh Venkataramanan ctxt->info.outer_up_table = cpu_to_le32(table); 55328c2a645SAnirudh Venkataramanan /* No Outer tag support outer_tag_flags remains to zero */ 55428c2a645SAnirudh Venkataramanan } 55528c2a645SAnirudh Venkataramanan 55628c2a645SAnirudh Venkataramanan /** 55728c2a645SAnirudh Venkataramanan * ice_vsi_setup_q_map - Setup a VSI queue map 55828c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 55928c2a645SAnirudh Venkataramanan * @ctxt: VSI context structure 56028c2a645SAnirudh Venkataramanan */ 56128c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 56228c2a645SAnirudh Venkataramanan { 563c5a2a4a3SUsha Ketineni u16 offset = 0, qmap = 0, tx_count = 0; 56428c2a645SAnirudh Venkataramanan u16 qcount_tx = vsi->alloc_txq; 56528c2a645SAnirudh Venkataramanan u16 qcount_rx = vsi->alloc_rxq; 566c5a2a4a3SUsha Ketineni u16 tx_numq_tc, rx_numq_tc; 567c5a2a4a3SUsha Ketineni u16 pow = 0, max_rss = 0; 56828c2a645SAnirudh Venkataramanan bool ena_tc0 = false; 569c5a2a4a3SUsha Ketineni u8 netdev_tc = 0; 57028c2a645SAnirudh Venkataramanan int i; 57128c2a645SAnirudh Venkataramanan 57228c2a645SAnirudh Venkataramanan /* at least TC0 should be enabled by default */ 57328c2a645SAnirudh Venkataramanan if (vsi->tc_cfg.numtc) { 57428c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(0))) 57528c2a645SAnirudh Venkataramanan ena_tc0 = true; 57628c2a645SAnirudh Venkataramanan } else { 57728c2a645SAnirudh Venkataramanan ena_tc0 = true; 57828c2a645SAnirudh Venkataramanan } 57928c2a645SAnirudh Venkataramanan 58028c2a645SAnirudh Venkataramanan if (ena_tc0) { 58128c2a645SAnirudh Venkataramanan vsi->tc_cfg.numtc++; 58228c2a645SAnirudh Venkataramanan vsi->tc_cfg.ena_tc |= 1; 58328c2a645SAnirudh Venkataramanan } 58428c2a645SAnirudh Venkataramanan 585c5a2a4a3SUsha Ketineni rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc; 586c5a2a4a3SUsha Ketineni if (!rx_numq_tc) 587c5a2a4a3SUsha Ketineni rx_numq_tc = 1; 588c5a2a4a3SUsha Ketineni tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc; 589c5a2a4a3SUsha Ketineni if (!tx_numq_tc) 590c5a2a4a3SUsha Ketineni tx_numq_tc = 1; 59128c2a645SAnirudh Venkataramanan 59228c2a645SAnirudh Venkataramanan /* TC mapping is a function of the number of Rx queues assigned to the 59328c2a645SAnirudh Venkataramanan * VSI for each traffic class and the offset of these queues. 59428c2a645SAnirudh Venkataramanan * The first 10 bits are for queue offset for TC0, next 4 bits for no:of 59528c2a645SAnirudh Venkataramanan * queues allocated to TC0. No:of queues is a power-of-2. 59628c2a645SAnirudh Venkataramanan * 59728c2a645SAnirudh Venkataramanan * If TC is not enabled, the queue offset is set to 0, and allocate one 59828c2a645SAnirudh Venkataramanan * queue, this way, traffic for the given TC will be sent to the default 59928c2a645SAnirudh Venkataramanan * queue. 60028c2a645SAnirudh Venkataramanan * 60128c2a645SAnirudh Venkataramanan * Setup number and offset of Rx queues for all TCs for the VSI 60228c2a645SAnirudh Venkataramanan */ 60328c2a645SAnirudh Venkataramanan 604c5a2a4a3SUsha Ketineni qcount_rx = rx_numq_tc; 605c5a2a4a3SUsha Ketineni 60628c2a645SAnirudh Venkataramanan /* qcount will change if RSS is enabled */ 60728c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) { 6088ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) { 60928c2a645SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) 61028c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_LG_RSS_QS; 61128c2a645SAnirudh Venkataramanan else 61228c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_SMALL_RSS_QS; 613c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, rx_numq_tc, max_rss); 614c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, qcount_rx, vsi->rss_size); 6158ede0178SAnirudh Venkataramanan } 61628c2a645SAnirudh Venkataramanan } 61728c2a645SAnirudh Venkataramanan 61828c2a645SAnirudh Venkataramanan /* find the (rounded up) power-of-2 of qcount */ 619c5a2a4a3SUsha Ketineni pow = order_base_2(qcount_rx); 62028c2a645SAnirudh Venkataramanan 6212bdc97beSBruce Allan ice_for_each_traffic_class(i) { 62228c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 62328c2a645SAnirudh Venkataramanan /* TC is not enabled */ 62428c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = 0; 625c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = 1; 626c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = 1; 627c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = 0; 62828c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = 0; 62928c2a645SAnirudh Venkataramanan continue; 63028c2a645SAnirudh Venkataramanan } 63128c2a645SAnirudh Venkataramanan 63228c2a645SAnirudh Venkataramanan /* TC is enabled */ 63328c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = offset; 634c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx; 635c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc; 636c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 63728c2a645SAnirudh Venkataramanan 63828c2a645SAnirudh Venkataramanan qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 63928c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_OFFSET_M) | 64028c2a645SAnirudh Venkataramanan ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 64128c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_NUM_M); 642c5a2a4a3SUsha Ketineni offset += qcount_rx; 643c5a2a4a3SUsha Ketineni tx_count += tx_numq_tc; 64428c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); 64528c2a645SAnirudh Venkataramanan } 64660dcc39eSKiran Patil 64760dcc39eSKiran Patil /* if offset is non-zero, means it is calculated correctly based on 64860dcc39eSKiran Patil * enabled TCs for a given VSI otherwise qcount_rx will always 64960dcc39eSKiran Patil * be correct and non-zero because it is based off - VSI's 65060dcc39eSKiran Patil * allocated Rx queues which is at least 1 (hence qcount_tx will be 65160dcc39eSKiran Patil * at least 1) 65260dcc39eSKiran Patil */ 65360dcc39eSKiran Patil if (offset) 65428c2a645SAnirudh Venkataramanan vsi->num_rxq = offset; 65560dcc39eSKiran Patil else 65660dcc39eSKiran Patil vsi->num_rxq = qcount_rx; 65760dcc39eSKiran Patil 658c5a2a4a3SUsha Ketineni vsi->num_txq = tx_count; 65928c2a645SAnirudh Venkataramanan 6608ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) { 6618ede0178SAnirudh Venkataramanan dev_dbg(&vsi->back->pdev->dev, "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n"); 6628ede0178SAnirudh Venkataramanan /* since there is a chance that num_rxq could have been changed 6638ede0178SAnirudh Venkataramanan * in the above for loop, make num_txq equal to num_rxq. 6648ede0178SAnirudh Venkataramanan */ 6658ede0178SAnirudh Venkataramanan vsi->num_txq = vsi->num_rxq; 6668ede0178SAnirudh Venkataramanan } 6678ede0178SAnirudh Venkataramanan 66828c2a645SAnirudh Venkataramanan /* Rx queue mapping */ 66928c2a645SAnirudh Venkataramanan ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 67028c2a645SAnirudh Venkataramanan /* q_mapping buffer holds the info for the first queue allocated for 67128c2a645SAnirudh Venkataramanan * this VSI in the PF space and also the number of queues associated 67228c2a645SAnirudh Venkataramanan * with this VSI. 67328c2a645SAnirudh Venkataramanan */ 67428c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 67528c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq); 67628c2a645SAnirudh Venkataramanan } 67728c2a645SAnirudh Venkataramanan 67828c2a645SAnirudh Venkataramanan /** 67928c2a645SAnirudh Venkataramanan * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI 68028c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 68128c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 68228c2a645SAnirudh Venkataramanan */ 68328c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 68428c2a645SAnirudh Venkataramanan { 68528c2a645SAnirudh Venkataramanan u8 lut_type, hash_type; 686819d8998SJesse Brandeburg struct ice_pf *pf; 687819d8998SJesse Brandeburg 688819d8998SJesse Brandeburg pf = vsi->back; 68928c2a645SAnirudh Venkataramanan 69028c2a645SAnirudh Venkataramanan switch (vsi->type) { 69128c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 69228c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 69328c2a645SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; 69428c2a645SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 69528c2a645SAnirudh Venkataramanan break; 6968ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 6978ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table which is a VSI LUT type */ 6988ede0178SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 6998ede0178SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 7008ede0178SAnirudh Venkataramanan break; 7010e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 7020e674aebSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "Unsupported VSI type %d\n", vsi->type); 7030e674aebSAnirudh Venkataramanan return; 70428c2a645SAnirudh Venkataramanan default: 705819d8998SJesse Brandeburg dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type); 70628c2a645SAnirudh Venkataramanan return; 70728c2a645SAnirudh Venkataramanan } 70828c2a645SAnirudh Venkataramanan 70928c2a645SAnirudh Venkataramanan ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & 71028c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | 71128c2a645SAnirudh Venkataramanan ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & 71228c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_HASH_M); 71328c2a645SAnirudh Venkataramanan } 71428c2a645SAnirudh Venkataramanan 71528c2a645SAnirudh Venkataramanan /** 71628c2a645SAnirudh Venkataramanan * ice_vsi_init - Create and initialize a VSI 71728c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 71828c2a645SAnirudh Venkataramanan * 71928c2a645SAnirudh Venkataramanan * This initializes a VSI context depending on the VSI type to be added and 72028c2a645SAnirudh Venkataramanan * passes it down to the add_vsi aq command to create a new VSI. 72128c2a645SAnirudh Venkataramanan */ 72237bb8390SAnirudh Venkataramanan static int ice_vsi_init(struct ice_vsi *vsi) 72328c2a645SAnirudh Venkataramanan { 72428c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 72528c2a645SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 726198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 72728c2a645SAnirudh Venkataramanan int ret = 0; 72828c2a645SAnirudh Venkataramanan 729198a666aSBruce Allan ctxt = devm_kzalloc(&pf->pdev->dev, sizeof(*ctxt), GFP_KERNEL); 730198a666aSBruce Allan if (!ctxt) 731198a666aSBruce Allan return -ENOMEM; 732198a666aSBruce Allan 733cb93a952SAkeem G Abodunrin ctxt->info = vsi->info; 73428c2a645SAnirudh Venkataramanan switch (vsi->type) { 7350e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 7360e674aebSAnirudh Venkataramanan /* fall through */ 73728c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 738198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_PF; 73928c2a645SAnirudh Venkataramanan break; 7408ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 741198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_VF; 7428ede0178SAnirudh Venkataramanan /* VF number here is the absolute VF number (0-255) */ 743198a666aSBruce Allan ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; 7448ede0178SAnirudh Venkataramanan break; 74528c2a645SAnirudh Venkataramanan default: 74628c2a645SAnirudh Venkataramanan return -ENODEV; 74728c2a645SAnirudh Venkataramanan } 74828c2a645SAnirudh Venkataramanan 749198a666aSBruce Allan ice_set_dflt_vsi_ctx(ctxt); 75028c2a645SAnirudh Venkataramanan /* if the switch is in VEB mode, allow VSI loopback */ 75128c2a645SAnirudh Venkataramanan if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) 752198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 75328c2a645SAnirudh Venkataramanan 75428c2a645SAnirudh Venkataramanan /* Set LUT type and HASH type if RSS is enabled */ 75528c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 756198a666aSBruce Allan ice_set_rss_vsi_ctx(ctxt, vsi); 75728c2a645SAnirudh Venkataramanan 758198a666aSBruce Allan ctxt->info.sw_id = vsi->port_info->sw_id; 759198a666aSBruce Allan ice_vsi_setup_q_map(vsi, ctxt); 76028c2a645SAnirudh Venkataramanan 761cb93a952SAkeem G Abodunrin /* Enable MAC Antispoof with new VSI being initialized or updated */ 762cb93a952SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF && pf->vf[vsi->vf_id].spoofchk) { 763cb93a952SAkeem G Abodunrin ctxt->info.valid_sections |= 764cb93a952SAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 765cb93a952SAkeem G Abodunrin ctxt->info.sec_flags |= 766cb93a952SAkeem G Abodunrin ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF; 767cb93a952SAkeem G Abodunrin } 768cb93a952SAkeem G Abodunrin 7690c3a6101SDave Ertman /* Allow control frames out of main VSI */ 7700c3a6101SDave Ertman if (vsi->type == ICE_VSI_PF) { 7710c3a6101SDave Ertman ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; 7720c3a6101SDave Ertman ctxt->info.valid_sections |= 7730c3a6101SDave Ertman cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 7740c3a6101SDave Ertman } 7750c3a6101SDave Ertman 776198a666aSBruce Allan ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); 77728c2a645SAnirudh Venkataramanan if (ret) { 77828c2a645SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 77928c2a645SAnirudh Venkataramanan "Add VSI failed, err %d\n", ret); 78028c2a645SAnirudh Venkataramanan return -EIO; 78128c2a645SAnirudh Venkataramanan } 78228c2a645SAnirudh Venkataramanan 78328c2a645SAnirudh Venkataramanan /* keep context for update VSI operations */ 784198a666aSBruce Allan vsi->info = ctxt->info; 78528c2a645SAnirudh Venkataramanan 78628c2a645SAnirudh Venkataramanan /* record VSI number returned */ 787198a666aSBruce Allan vsi->vsi_num = ctxt->vsi_num; 78828c2a645SAnirudh Venkataramanan 789198a666aSBruce Allan devm_kfree(&pf->pdev->dev, ctxt); 79028c2a645SAnirudh Venkataramanan return ret; 79128c2a645SAnirudh Venkataramanan } 79228c2a645SAnirudh Venkataramanan 79328c2a645SAnirudh Venkataramanan /** 794df0f8479SAnirudh Venkataramanan * ice_vsi_setup_vector_base - Set up the base vector for the given VSI 795df0f8479SAnirudh Venkataramanan * @vsi: ptr to the VSI 796df0f8479SAnirudh Venkataramanan * 797df0f8479SAnirudh Venkataramanan * This should only be called after ice_vsi_alloc() which allocates the 798df0f8479SAnirudh Venkataramanan * corresponding SW VSI structure and initializes num_queue_pairs for the 799df0f8479SAnirudh Venkataramanan * newly allocated VSI. 800df0f8479SAnirudh Venkataramanan * 801df0f8479SAnirudh Venkataramanan * Returns 0 on success or negative on failure 802df0f8479SAnirudh Venkataramanan */ 80337bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) 804df0f8479SAnirudh Venkataramanan { 805df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 806cbe66bfeSBrett Creeley u16 num_q_vectors; 807df0f8479SAnirudh Venkataramanan 808cbe66bfeSBrett Creeley /* SRIOV doesn't grab irq_tracker entries for each VSI */ 809cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) 810cbe66bfeSBrett Creeley return 0; 811cbe66bfeSBrett Creeley 812cbe66bfeSBrett Creeley if (vsi->base_vector) { 813cbe66bfeSBrett Creeley dev_dbg(&pf->pdev->dev, "VSI %d has non-zero base vector %d\n", 814cbe66bfeSBrett Creeley vsi->vsi_num, vsi->base_vector); 815df0f8479SAnirudh Venkataramanan return -EEXIST; 816df0f8479SAnirudh Venkataramanan } 817df0f8479SAnirudh Venkataramanan 818df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 819eb0208ecSPreethi Banala /* reserve slots from OS requested IRQs */ 820cbe66bfeSBrett Creeley vsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors, 821cbe66bfeSBrett Creeley vsi->idx); 822cbe66bfeSBrett Creeley if (vsi->base_vector < 0) { 823eb0208ecSPreethi Banala dev_err(&pf->pdev->dev, 824cbe66bfeSBrett Creeley "Failed to get tracking for %d vectors for VSI %d, err=%d\n", 825cbe66bfeSBrett Creeley num_q_vectors, vsi->vsi_num, vsi->base_vector); 826eb0208ecSPreethi Banala return -ENOENT; 827eb0208ecSPreethi Banala } 828eb0208ecSPreethi Banala pf->num_avail_sw_msix -= num_q_vectors; 829eb0208ecSPreethi Banala 830df0f8479SAnirudh Venkataramanan return 0; 831df0f8479SAnirudh Venkataramanan } 832df0f8479SAnirudh Venkataramanan 833df0f8479SAnirudh Venkataramanan /** 83428c2a645SAnirudh Venkataramanan * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI 83528c2a645SAnirudh Venkataramanan * @vsi: the VSI having rings deallocated 83628c2a645SAnirudh Venkataramanan */ 837df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi) 83828c2a645SAnirudh Venkataramanan { 83928c2a645SAnirudh Venkataramanan int i; 84028c2a645SAnirudh Venkataramanan 84128c2a645SAnirudh Venkataramanan if (vsi->tx_rings) { 84228c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 84328c2a645SAnirudh Venkataramanan if (vsi->tx_rings[i]) { 84428c2a645SAnirudh Venkataramanan kfree_rcu(vsi->tx_rings[i], rcu); 84528c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = NULL; 84628c2a645SAnirudh Venkataramanan } 84728c2a645SAnirudh Venkataramanan } 84828c2a645SAnirudh Venkataramanan } 84928c2a645SAnirudh Venkataramanan if (vsi->rx_rings) { 85028c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 85128c2a645SAnirudh Venkataramanan if (vsi->rx_rings[i]) { 85228c2a645SAnirudh Venkataramanan kfree_rcu(vsi->rx_rings[i], rcu); 85328c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = NULL; 85428c2a645SAnirudh Venkataramanan } 85528c2a645SAnirudh Venkataramanan } 85628c2a645SAnirudh Venkataramanan } 85728c2a645SAnirudh Venkataramanan } 85828c2a645SAnirudh Venkataramanan 85928c2a645SAnirudh Venkataramanan /** 86028c2a645SAnirudh Venkataramanan * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI 86128c2a645SAnirudh Venkataramanan * @vsi: VSI which is having rings allocated 86228c2a645SAnirudh Venkataramanan */ 86337bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi) 86428c2a645SAnirudh Venkataramanan { 86528c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 86628c2a645SAnirudh Venkataramanan int i; 86728c2a645SAnirudh Venkataramanan 868d337f2afSAnirudh Venkataramanan /* Allocate Tx rings */ 86928c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 87028c2a645SAnirudh Venkataramanan struct ice_ring *ring; 87128c2a645SAnirudh Venkataramanan 87228c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 87328c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 87428c2a645SAnirudh Venkataramanan 87528c2a645SAnirudh Venkataramanan if (!ring) 87628c2a645SAnirudh Venkataramanan goto err_out; 87728c2a645SAnirudh Venkataramanan 87828c2a645SAnirudh Venkataramanan ring->q_index = i; 87928c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->txq_map[i]; 88028c2a645SAnirudh Venkataramanan ring->ring_active = false; 88128c2a645SAnirudh Venkataramanan ring->vsi = vsi; 88228c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 883ad71b256SBrett Creeley ring->count = vsi->num_tx_desc; 88428c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = ring; 88528c2a645SAnirudh Venkataramanan } 88628c2a645SAnirudh Venkataramanan 887d337f2afSAnirudh Venkataramanan /* Allocate Rx rings */ 88828c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 88928c2a645SAnirudh Venkataramanan struct ice_ring *ring; 89028c2a645SAnirudh Venkataramanan 89128c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 89228c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 89328c2a645SAnirudh Venkataramanan if (!ring) 89428c2a645SAnirudh Venkataramanan goto err_out; 89528c2a645SAnirudh Venkataramanan 89628c2a645SAnirudh Venkataramanan ring->q_index = i; 89728c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->rxq_map[i]; 89828c2a645SAnirudh Venkataramanan ring->ring_active = false; 89928c2a645SAnirudh Venkataramanan ring->vsi = vsi; 90028c2a645SAnirudh Venkataramanan ring->netdev = vsi->netdev; 90128c2a645SAnirudh Venkataramanan ring->dev = &pf->pdev->dev; 902ad71b256SBrett Creeley ring->count = vsi->num_rx_desc; 90328c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = ring; 90428c2a645SAnirudh Venkataramanan } 90528c2a645SAnirudh Venkataramanan 90628c2a645SAnirudh Venkataramanan return 0; 90728c2a645SAnirudh Venkataramanan 90828c2a645SAnirudh Venkataramanan err_out: 90928c2a645SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 91028c2a645SAnirudh Venkataramanan return -ENOMEM; 91128c2a645SAnirudh Venkataramanan } 91228c2a645SAnirudh Venkataramanan 91328c2a645SAnirudh Venkataramanan /** 914492af0abSMd Fahad Iqbal Polash * ice_vsi_manage_rss_lut - disable/enable RSS 915492af0abSMd Fahad Iqbal Polash * @vsi: the VSI being changed 916492af0abSMd Fahad Iqbal Polash * @ena: boolean value indicating if this is an enable or disable request 917492af0abSMd Fahad Iqbal Polash * 918492af0abSMd Fahad Iqbal Polash * In the event of disable request for RSS, this function will zero out RSS 919492af0abSMd Fahad Iqbal Polash * LUT, while in the event of enable request for RSS, it will reconfigure RSS 920492af0abSMd Fahad Iqbal Polash * LUT. 921492af0abSMd Fahad Iqbal Polash */ 922492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena) 923492af0abSMd Fahad Iqbal Polash { 924492af0abSMd Fahad Iqbal Polash int err = 0; 925492af0abSMd Fahad Iqbal Polash u8 *lut; 926492af0abSMd Fahad Iqbal Polash 927492af0abSMd Fahad Iqbal Polash lut = devm_kzalloc(&vsi->back->pdev->dev, vsi->rss_table_size, 928492af0abSMd Fahad Iqbal Polash GFP_KERNEL); 929492af0abSMd Fahad Iqbal Polash if (!lut) 930492af0abSMd Fahad Iqbal Polash return -ENOMEM; 931492af0abSMd Fahad Iqbal Polash 932492af0abSMd Fahad Iqbal Polash if (ena) { 933492af0abSMd Fahad Iqbal Polash if (vsi->rss_lut_user) 934492af0abSMd Fahad Iqbal Polash memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 935492af0abSMd Fahad Iqbal Polash else 936492af0abSMd Fahad Iqbal Polash ice_fill_rss_lut(lut, vsi->rss_table_size, 937492af0abSMd Fahad Iqbal Polash vsi->rss_size); 938492af0abSMd Fahad Iqbal Polash } 939492af0abSMd Fahad Iqbal Polash 940492af0abSMd Fahad Iqbal Polash err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size); 941492af0abSMd Fahad Iqbal Polash devm_kfree(&vsi->back->pdev->dev, lut); 942492af0abSMd Fahad Iqbal Polash return err; 943492af0abSMd Fahad Iqbal Polash } 944492af0abSMd Fahad Iqbal Polash 945492af0abSMd Fahad Iqbal Polash /** 94637bb8390SAnirudh Venkataramanan * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI 94737bb8390SAnirudh Venkataramanan * @vsi: VSI to be configured 94837bb8390SAnirudh Venkataramanan */ 94937bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi) 95037bb8390SAnirudh Venkataramanan { 95137bb8390SAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *key; 95237bb8390SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 95337bb8390SAnirudh Venkataramanan enum ice_status status; 95437bb8390SAnirudh Venkataramanan int err = 0; 95537bb8390SAnirudh Venkataramanan u8 *lut; 95637bb8390SAnirudh Venkataramanan 95737bb8390SAnirudh Venkataramanan vsi->rss_size = min_t(int, vsi->rss_size, vsi->num_rxq); 95837bb8390SAnirudh Venkataramanan 95937bb8390SAnirudh Venkataramanan lut = devm_kzalloc(&pf->pdev->dev, vsi->rss_table_size, GFP_KERNEL); 96037bb8390SAnirudh Venkataramanan if (!lut) 96137bb8390SAnirudh Venkataramanan return -ENOMEM; 96237bb8390SAnirudh Venkataramanan 96337bb8390SAnirudh Venkataramanan if (vsi->rss_lut_user) 96437bb8390SAnirudh Venkataramanan memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 96537bb8390SAnirudh Venkataramanan else 96637bb8390SAnirudh Venkataramanan ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 96737bb8390SAnirudh Venkataramanan 9684fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut, 9694fb33f31SAnirudh Venkataramanan vsi->rss_table_size); 97037bb8390SAnirudh Venkataramanan 97137bb8390SAnirudh Venkataramanan if (status) { 972819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, 97337bb8390SAnirudh Venkataramanan "set_rss_lut failed, error %d\n", status); 97437bb8390SAnirudh Venkataramanan err = -EIO; 97537bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 97637bb8390SAnirudh Venkataramanan } 97737bb8390SAnirudh Venkataramanan 978819d8998SJesse Brandeburg key = devm_kzalloc(&pf->pdev->dev, sizeof(*key), GFP_KERNEL); 97937bb8390SAnirudh Venkataramanan if (!key) { 98037bb8390SAnirudh Venkataramanan err = -ENOMEM; 98137bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 98237bb8390SAnirudh Venkataramanan } 98337bb8390SAnirudh Venkataramanan 98437bb8390SAnirudh Venkataramanan if (vsi->rss_hkey_user) 985b4b418b3SPaul Greenwalt memcpy(key, 986b4b418b3SPaul Greenwalt (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user, 987b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 98837bb8390SAnirudh Venkataramanan else 989b4b418b3SPaul Greenwalt netdev_rss_key_fill((void *)key, 990b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 99137bb8390SAnirudh Venkataramanan 9924fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key); 99337bb8390SAnirudh Venkataramanan 99437bb8390SAnirudh Venkataramanan if (status) { 995819d8998SJesse Brandeburg dev_err(&pf->pdev->dev, "set_rss_key failed, error %d\n", 99637bb8390SAnirudh Venkataramanan status); 99737bb8390SAnirudh Venkataramanan err = -EIO; 99837bb8390SAnirudh Venkataramanan } 99937bb8390SAnirudh Venkataramanan 100037bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, key); 100137bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit: 100237bb8390SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, lut); 100337bb8390SAnirudh Venkataramanan return err; 100437bb8390SAnirudh Venkataramanan } 100537bb8390SAnirudh Venkataramanan 100637bb8390SAnirudh Venkataramanan /** 1007f9867df6SAnirudh Venkataramanan * ice_add_mac_to_list - Add a MAC address filter entry to the list 100845d3d428SAnirudh Venkataramanan * @vsi: the VSI to be forwarded to 100945d3d428SAnirudh Venkataramanan * @add_list: pointer to the list which contains MAC filter entries 101045d3d428SAnirudh Venkataramanan * @macaddr: the MAC address to be added. 101145d3d428SAnirudh Venkataramanan * 1012f9867df6SAnirudh Venkataramanan * Adds MAC address filter entry to the temp list 101345d3d428SAnirudh Venkataramanan * 101445d3d428SAnirudh Venkataramanan * Returns 0 on success or ENOMEM on failure. 101545d3d428SAnirudh Venkataramanan */ 101645d3d428SAnirudh Venkataramanan int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list, 101745d3d428SAnirudh Venkataramanan const u8 *macaddr) 101845d3d428SAnirudh Venkataramanan { 101945d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 102045d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 102145d3d428SAnirudh Venkataramanan 102245d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC); 102345d3d428SAnirudh Venkataramanan if (!tmp) 102445d3d428SAnirudh Venkataramanan return -ENOMEM; 102545d3d428SAnirudh Venkataramanan 102645d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 10275726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 102845d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC; 102945d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 10305726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 103145d3d428SAnirudh Venkataramanan ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr); 103245d3d428SAnirudh Venkataramanan 103345d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 103445d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, add_list); 103545d3d428SAnirudh Venkataramanan 103645d3d428SAnirudh Venkataramanan return 0; 103745d3d428SAnirudh Venkataramanan } 103845d3d428SAnirudh Venkataramanan 103945d3d428SAnirudh Venkataramanan /** 104045d3d428SAnirudh Venkataramanan * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 104145d3d428SAnirudh Venkataramanan * @vsi: the VSI to be updated 104245d3d428SAnirudh Venkataramanan */ 104345d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi) 104445d3d428SAnirudh Venkataramanan { 104545d3d428SAnirudh Venkataramanan struct ice_eth_stats *prev_es, *cur_es; 104645d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 104745d3d428SAnirudh Venkataramanan u16 vsi_num = vsi->vsi_num; /* HW absolute index of a VSI */ 104845d3d428SAnirudh Venkataramanan 104945d3d428SAnirudh Venkataramanan prev_es = &vsi->eth_stats_prev; 105045d3d428SAnirudh Venkataramanan cur_es = &vsi->eth_stats; 105145d3d428SAnirudh Venkataramanan 105236517fd3SJacob Keller ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded, 105336517fd3SJacob Keller &prev_es->rx_bytes, &cur_es->rx_bytes); 105445d3d428SAnirudh Venkataramanan 105536517fd3SJacob Keller ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded, 105636517fd3SJacob Keller &prev_es->rx_unicast, &cur_es->rx_unicast); 105745d3d428SAnirudh Venkataramanan 105836517fd3SJacob Keller ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded, 105936517fd3SJacob Keller &prev_es->rx_multicast, &cur_es->rx_multicast); 106045d3d428SAnirudh Venkataramanan 106136517fd3SJacob Keller ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded, 106236517fd3SJacob Keller &prev_es->rx_broadcast, &cur_es->rx_broadcast); 106345d3d428SAnirudh Venkataramanan 106445d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, 106545d3d428SAnirudh Venkataramanan &prev_es->rx_discards, &cur_es->rx_discards); 106645d3d428SAnirudh Venkataramanan 106736517fd3SJacob Keller ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded, 106836517fd3SJacob Keller &prev_es->tx_bytes, &cur_es->tx_bytes); 106945d3d428SAnirudh Venkataramanan 107036517fd3SJacob Keller ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded, 107136517fd3SJacob Keller &prev_es->tx_unicast, &cur_es->tx_unicast); 107245d3d428SAnirudh Venkataramanan 107336517fd3SJacob Keller ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded, 107436517fd3SJacob Keller &prev_es->tx_multicast, &cur_es->tx_multicast); 107545d3d428SAnirudh Venkataramanan 107636517fd3SJacob Keller ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded, 107736517fd3SJacob Keller &prev_es->tx_broadcast, &cur_es->tx_broadcast); 107845d3d428SAnirudh Venkataramanan 107945d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, 108045d3d428SAnirudh Venkataramanan &prev_es->tx_errors, &cur_es->tx_errors); 108145d3d428SAnirudh Venkataramanan 108245d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded = true; 108345d3d428SAnirudh Venkataramanan } 108445d3d428SAnirudh Venkataramanan 108545d3d428SAnirudh Venkataramanan /** 108645d3d428SAnirudh Venkataramanan * ice_free_fltr_list - free filter lists helper 108745d3d428SAnirudh Venkataramanan * @dev: pointer to the device struct 108845d3d428SAnirudh Venkataramanan * @h: pointer to the list head to be freed 108945d3d428SAnirudh Venkataramanan * 109045d3d428SAnirudh Venkataramanan * Helper function to free filter lists previously created using 109145d3d428SAnirudh Venkataramanan * ice_add_mac_to_list 109245d3d428SAnirudh Venkataramanan */ 109345d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h) 109445d3d428SAnirudh Venkataramanan { 109545d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *e, *tmp; 109645d3d428SAnirudh Venkataramanan 109745d3d428SAnirudh Venkataramanan list_for_each_entry_safe(e, tmp, h, list_entry) { 109845d3d428SAnirudh Venkataramanan list_del(&e->list_entry); 109945d3d428SAnirudh Venkataramanan devm_kfree(dev, e); 110045d3d428SAnirudh Venkataramanan } 110145d3d428SAnirudh Venkataramanan } 110245d3d428SAnirudh Venkataramanan 110345d3d428SAnirudh Venkataramanan /** 110445d3d428SAnirudh Venkataramanan * ice_vsi_add_vlan - Add VSI membership for given VLAN 110545d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1106f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be added 110745d3d428SAnirudh Venkataramanan */ 110845d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid) 110945d3d428SAnirudh Venkataramanan { 111045d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 111145d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 111245d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 111345d3d428SAnirudh Venkataramanan enum ice_status status; 111445d3d428SAnirudh Venkataramanan int err = 0; 111545d3d428SAnirudh Venkataramanan 111645d3d428SAnirudh Venkataramanan tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_KERNEL); 111745d3d428SAnirudh Venkataramanan if (!tmp) 111845d3d428SAnirudh Venkataramanan return -ENOMEM; 111945d3d428SAnirudh Venkataramanan 112045d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 112145d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 112245d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 11235726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 11245726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 112545d3d428SAnirudh Venkataramanan tmp->fltr_info.l_data.vlan.vlan_id = vid; 112645d3d428SAnirudh Venkataramanan 112745d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 112845d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, &tmp_add_list); 112945d3d428SAnirudh Venkataramanan 113045d3d428SAnirudh Venkataramanan status = ice_add_vlan(&pf->hw, &tmp_add_list); 113145d3d428SAnirudh Venkataramanan if (status) { 113245d3d428SAnirudh Venkataramanan err = -ENODEV; 113345d3d428SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failure Adding VLAN %d on VSI %i\n", 113445d3d428SAnirudh Venkataramanan vid, vsi->vsi_num); 113545d3d428SAnirudh Venkataramanan } 113645d3d428SAnirudh Venkataramanan 113745d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 113845d3d428SAnirudh Venkataramanan return err; 113945d3d428SAnirudh Venkataramanan } 114045d3d428SAnirudh Venkataramanan 114145d3d428SAnirudh Venkataramanan /** 114245d3d428SAnirudh Venkataramanan * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN 114345d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1144f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be removed 114545d3d428SAnirudh Venkataramanan * 114645d3d428SAnirudh Venkataramanan * Returns 0 on success and negative on failure 114745d3d428SAnirudh Venkataramanan */ 114845d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid) 114945d3d428SAnirudh Venkataramanan { 115045d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *list; 115145d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 115245d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 11535079b853SAkeem G Abodunrin enum ice_status status; 11545079b853SAkeem G Abodunrin int err = 0; 115545d3d428SAnirudh Venkataramanan 115645d3d428SAnirudh Venkataramanan list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 115745d3d428SAnirudh Venkataramanan if (!list) 115845d3d428SAnirudh Venkataramanan return -ENOMEM; 115945d3d428SAnirudh Venkataramanan 116045d3d428SAnirudh Venkataramanan list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 11615726ca0eSAnirudh Venkataramanan list->fltr_info.vsi_handle = vsi->idx; 116245d3d428SAnirudh Venkataramanan list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 116345d3d428SAnirudh Venkataramanan list->fltr_info.l_data.vlan.vlan_id = vid; 116445d3d428SAnirudh Venkataramanan list->fltr_info.flag = ICE_FLTR_TX; 11655726ca0eSAnirudh Venkataramanan list->fltr_info.src_id = ICE_SRC_ID_VSI; 116645d3d428SAnirudh Venkataramanan 116745d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&list->list_entry); 116845d3d428SAnirudh Venkataramanan list_add(&list->list_entry, &tmp_add_list); 116945d3d428SAnirudh Venkataramanan 11705079b853SAkeem G Abodunrin status = ice_remove_vlan(&pf->hw, &tmp_add_list); 1171bb877b22SAkeem G Abodunrin if (status == ICE_ERR_DOES_NOT_EXIST) { 1172bb877b22SAkeem G Abodunrin dev_dbg(&pf->pdev->dev, 1173bb877b22SAkeem G Abodunrin "Failed to remove VLAN %d on VSI %i, it does not exist, status: %d\n", 1174bb877b22SAkeem G Abodunrin vid, vsi->vsi_num, status); 1175bb877b22SAkeem G Abodunrin } else if (status) { 11765079b853SAkeem G Abodunrin dev_err(&pf->pdev->dev, 11775079b853SAkeem G Abodunrin "Error removing VLAN %d on vsi %i error: %d\n", 11785079b853SAkeem G Abodunrin vid, vsi->vsi_num, status); 11795079b853SAkeem G Abodunrin err = -EIO; 118045d3d428SAnirudh Venkataramanan } 118145d3d428SAnirudh Venkataramanan 118245d3d428SAnirudh Venkataramanan ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 11835079b853SAkeem G Abodunrin return err; 118445d3d428SAnirudh Venkataramanan } 118545d3d428SAnirudh Venkataramanan 118645d3d428SAnirudh Venkataramanan /** 118772adf242SAnirudh Venkataramanan * ice_vsi_cfg_rxqs - Configure the VSI for Rx 118872adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 118972adf242SAnirudh Venkataramanan * 119072adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 119172adf242SAnirudh Venkataramanan * Configure the Rx VSI for operation. 119272adf242SAnirudh Venkataramanan */ 119372adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi) 119472adf242SAnirudh Venkataramanan { 119572adf242SAnirudh Venkataramanan u16 i; 119672adf242SAnirudh Venkataramanan 11978ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 11988ede0178SAnirudh Venkataramanan goto setup_rings; 11998ede0178SAnirudh Venkataramanan 120072adf242SAnirudh Venkataramanan if (vsi->netdev && vsi->netdev->mtu > ETH_DATA_LEN) 120172adf242SAnirudh Venkataramanan vsi->max_frame = vsi->netdev->mtu + 120272adf242SAnirudh Venkataramanan ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; 120372adf242SAnirudh Venkataramanan else 120472adf242SAnirudh Venkataramanan vsi->max_frame = ICE_RXBUF_2048; 120572adf242SAnirudh Venkataramanan 120672adf242SAnirudh Venkataramanan vsi->rx_buf_len = ICE_RXBUF_2048; 12078ede0178SAnirudh Venkataramanan setup_rings: 120872adf242SAnirudh Venkataramanan /* set up individual rings */ 12091553f4f7SBrett Creeley for (i = 0; i < vsi->num_rxq; i++) { 12101553f4f7SBrett Creeley int err; 121172adf242SAnirudh Venkataramanan 12121553f4f7SBrett Creeley err = ice_setup_rx_ctx(vsi->rx_rings[i]); 121372adf242SAnirudh Venkataramanan if (err) { 12141553f4f7SBrett Creeley dev_err(&vsi->back->pdev->dev, 12151553f4f7SBrett Creeley "ice_setup_rx_ctx failed for RxQ %d, err %d\n", 12161553f4f7SBrett Creeley i, err); 121772adf242SAnirudh Venkataramanan return err; 121872adf242SAnirudh Venkataramanan } 12191553f4f7SBrett Creeley } 12201553f4f7SBrett Creeley 12211553f4f7SBrett Creeley return 0; 12221553f4f7SBrett Creeley } 122372adf242SAnirudh Venkataramanan 122472adf242SAnirudh Venkataramanan /** 122572adf242SAnirudh Venkataramanan * ice_vsi_cfg_txqs - Configure the VSI for Tx 122672adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 122703f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be configured 122872adf242SAnirudh Venkataramanan * 122972adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 123072adf242SAnirudh Venkataramanan * Configure the Tx VSI for operation. 123172adf242SAnirudh Venkataramanan */ 123203f7a986SAnirudh Venkataramanan static int 1233e75d1b2cSMaciej Fijalkowski ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings) 123472adf242SAnirudh Venkataramanan { 123572adf242SAnirudh Venkataramanan struct ice_aqc_add_tx_qgrp *qg_buf; 1236e75d1b2cSMaciej Fijalkowski u16 q_idx = 0; 1237d02f734cSMaciej Fijalkowski int err = 0; 123872adf242SAnirudh Venkataramanan 1239e75d1b2cSMaciej Fijalkowski qg_buf = kzalloc(sizeof(*qg_buf), GFP_KERNEL); 124072adf242SAnirudh Venkataramanan if (!qg_buf) 124172adf242SAnirudh Venkataramanan return -ENOMEM; 124272adf242SAnirudh Venkataramanan 124372adf242SAnirudh Venkataramanan qg_buf->num_txqs = 1; 124472adf242SAnirudh Venkataramanan 1245e75d1b2cSMaciej Fijalkowski for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) { 1246e75d1b2cSMaciej Fijalkowski err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf); 1247d02f734cSMaciej Fijalkowski if (err) 124872adf242SAnirudh Venkataramanan goto err_cfg_txqs; 1249e75d1b2cSMaciej Fijalkowski } 1250c5a2a4a3SUsha Ketineni 125172adf242SAnirudh Venkataramanan err_cfg_txqs: 1252e75d1b2cSMaciej Fijalkowski kfree(qg_buf); 125372adf242SAnirudh Venkataramanan return err; 125472adf242SAnirudh Venkataramanan } 125572adf242SAnirudh Venkataramanan 125672adf242SAnirudh Venkataramanan /** 125703f7a986SAnirudh Venkataramanan * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx 125803f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 125903f7a986SAnirudh Venkataramanan * 126003f7a986SAnirudh Venkataramanan * Return 0 on success and a negative value on error 126103f7a986SAnirudh Venkataramanan * Configure the Tx VSI for operation. 126203f7a986SAnirudh Venkataramanan */ 126303f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) 126403f7a986SAnirudh Venkataramanan { 1265e75d1b2cSMaciej Fijalkowski return ice_vsi_cfg_txqs(vsi, vsi->tx_rings); 126603f7a986SAnirudh Venkataramanan } 126703f7a986SAnirudh Venkataramanan 126803f7a986SAnirudh Venkataramanan /** 12699e4ab4c2SBrett Creeley * ice_intrl_usec_to_reg - convert interrupt rate limit to register value 12709e4ab4c2SBrett Creeley * @intrl: interrupt rate limit in usecs 12719e4ab4c2SBrett Creeley * @gran: interrupt rate limit granularity in usecs 12729e4ab4c2SBrett Creeley * 12739e4ab4c2SBrett Creeley * This function converts a decimal interrupt rate limit in usecs to the format 12749e4ab4c2SBrett Creeley * expected by firmware. 12759e4ab4c2SBrett Creeley */ 1276b9c8bb06SBrett Creeley u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) 12779e4ab4c2SBrett Creeley { 12789e4ab4c2SBrett Creeley u32 val = intrl / gran; 12799e4ab4c2SBrett Creeley 12809e4ab4c2SBrett Creeley if (val) 12819e4ab4c2SBrett Creeley return val | GLINT_RATE_INTRL_ENA_M; 12829e4ab4c2SBrett Creeley return 0; 12839e4ab4c2SBrett Creeley } 12849e4ab4c2SBrett Creeley 12859e4ab4c2SBrett Creeley /** 128672adf242SAnirudh Venkataramanan * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW 128772adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 1288047e52c0SAnirudh Venkataramanan * 1289047e52c0SAnirudh Venkataramanan * This configures MSIX mode interrupts for the PF VSI, and should not be used 1290047e52c0SAnirudh Venkataramanan * for the VF VSI. 129172adf242SAnirudh Venkataramanan */ 129272adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi) 129372adf242SAnirudh Venkataramanan { 129472adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 129572adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 129672adf242SAnirudh Venkataramanan u32 txq = 0, rxq = 0; 1297d2b464a7SBrett Creeley int i, q; 129872adf242SAnirudh Venkataramanan 1299b07833a0SBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 130072adf242SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1301b07833a0SBrett Creeley u16 reg_idx = q_vector->reg_idx; 130272adf242SAnirudh Venkataramanan 1303b07833a0SBrett Creeley ice_cfg_itr(hw, q_vector); 13049e4ab4c2SBrett Creeley 1305b07833a0SBrett Creeley wr32(hw, GLINT_RATE(reg_idx), 13069e4ab4c2SBrett Creeley ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); 130772adf242SAnirudh Venkataramanan 130872adf242SAnirudh Venkataramanan /* Both Transmit Queue Interrupt Cause Control register 130972adf242SAnirudh Venkataramanan * and Receive Queue Interrupt Cause control register 131072adf242SAnirudh Venkataramanan * expects MSIX_INDX field to be the vector index 131172adf242SAnirudh Venkataramanan * within the function space and not the absolute 131272adf242SAnirudh Venkataramanan * vector index across PF or across device. 131372adf242SAnirudh Venkataramanan * For SR-IOV VF VSIs queue vector index always starts 131472adf242SAnirudh Venkataramanan * with 1 since first vector index(0) is used for OICR 131572adf242SAnirudh Venkataramanan * in VF space. Since VMDq and other PF VSIs are within 131672adf242SAnirudh Venkataramanan * the PF function space, use the vector index that is 131772adf242SAnirudh Venkataramanan * tracked for this PF. 131872adf242SAnirudh Venkataramanan */ 131972adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 1320047e52c0SAnirudh Venkataramanan ice_cfg_txq_interrupt(vsi, txq, reg_idx, 1321047e52c0SAnirudh Venkataramanan q_vector->tx.itr_idx); 132272adf242SAnirudh Venkataramanan txq++; 132372adf242SAnirudh Venkataramanan } 132472adf242SAnirudh Venkataramanan 132572adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 1326047e52c0SAnirudh Venkataramanan ice_cfg_rxq_interrupt(vsi, rxq, reg_idx, 1327047e52c0SAnirudh Venkataramanan q_vector->rx.itr_idx); 132872adf242SAnirudh Venkataramanan rxq++; 132972adf242SAnirudh Venkataramanan } 133072adf242SAnirudh Venkataramanan } 133172adf242SAnirudh Venkataramanan } 133272adf242SAnirudh Venkataramanan 133372adf242SAnirudh Venkataramanan /** 133445d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx 133545d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 133645d3d428SAnirudh Venkataramanan */ 133745d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) 133845d3d428SAnirudh Venkataramanan { 133945d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 134045d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1341198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 134245d3d428SAnirudh Venkataramanan enum ice_status status; 1343198a666aSBruce Allan int ret = 0; 1344198a666aSBruce Allan 1345198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 1346198a666aSBruce Allan if (!ctxt) 1347198a666aSBruce Allan return -ENOMEM; 134845d3d428SAnirudh Venkataramanan 134945d3d428SAnirudh Venkataramanan /* Here we are configuring the VSI to let the driver add VLAN tags by 135045d3d428SAnirudh Venkataramanan * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag 135145d3d428SAnirudh Venkataramanan * insertion happens in the Tx hot path, in ice_tx_map. 135245d3d428SAnirudh Venkataramanan */ 1353198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; 135445d3d428SAnirudh Venkataramanan 1355e80e76dbSTony Nguyen /* Preserve existing VLAN strip setting */ 1356e80e76dbSTony Nguyen ctxt->info.vlan_flags |= (vsi->info.vlan_flags & 1357e80e76dbSTony Nguyen ICE_AQ_VSI_VLAN_EMOD_M); 1358e80e76dbSTony Nguyen 1359198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 136045d3d428SAnirudh Venkataramanan 1361198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 136245d3d428SAnirudh Venkataramanan if (status) { 136345d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n", 136445d3d428SAnirudh Venkataramanan status, hw->adminq.sq_last_status); 1365198a666aSBruce Allan ret = -EIO; 1366198a666aSBruce Allan goto out; 136745d3d428SAnirudh Venkataramanan } 136845d3d428SAnirudh Venkataramanan 1369198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1370198a666aSBruce Allan out: 1371198a666aSBruce Allan devm_kfree(dev, ctxt); 1372198a666aSBruce Allan return ret; 137345d3d428SAnirudh Venkataramanan } 137445d3d428SAnirudh Venkataramanan 137545d3d428SAnirudh Venkataramanan /** 137645d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx 137745d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 137845d3d428SAnirudh Venkataramanan * @ena: boolean value indicating if this is a enable or disable request 137945d3d428SAnirudh Venkataramanan */ 138045d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) 138145d3d428SAnirudh Venkataramanan { 138245d3d428SAnirudh Venkataramanan struct device *dev = &vsi->back->pdev->dev; 138345d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1384198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 138545d3d428SAnirudh Venkataramanan enum ice_status status; 1386198a666aSBruce Allan int ret = 0; 1387198a666aSBruce Allan 1388198a666aSBruce Allan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 1389198a666aSBruce Allan if (!ctxt) 1390198a666aSBruce Allan return -ENOMEM; 139145d3d428SAnirudh Venkataramanan 139245d3d428SAnirudh Venkataramanan /* Here we are configuring what the VSI should do with the VLAN tag in 139345d3d428SAnirudh Venkataramanan * the Rx packet. We can either leave the tag in the packet or put it in 139445d3d428SAnirudh Venkataramanan * the Rx descriptor. 139545d3d428SAnirudh Venkataramanan */ 1396198a666aSBruce Allan if (ena) 139745d3d428SAnirudh Venkataramanan /* Strip VLAN tag from Rx packet and put it in the desc */ 1398198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; 1399198a666aSBruce Allan else 140045d3d428SAnirudh Venkataramanan /* Disable stripping. Leave tag in packet */ 1401198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; 140245d3d428SAnirudh Venkataramanan 140345d3d428SAnirudh Venkataramanan /* Allow all packets untagged/tagged */ 1404198a666aSBruce Allan ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; 140545d3d428SAnirudh Venkataramanan 1406198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 140745d3d428SAnirudh Venkataramanan 1408198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 140945d3d428SAnirudh Venkataramanan if (status) { 141045d3d428SAnirudh Venkataramanan dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n", 141145d3d428SAnirudh Venkataramanan ena, status, hw->adminq.sq_last_status); 1412198a666aSBruce Allan ret = -EIO; 1413198a666aSBruce Allan goto out; 141445d3d428SAnirudh Venkataramanan } 141545d3d428SAnirudh Venkataramanan 1416198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1417198a666aSBruce Allan out: 1418198a666aSBruce Allan devm_kfree(dev, ctxt); 1419198a666aSBruce Allan return ret; 142045d3d428SAnirudh Venkataramanan } 142172adf242SAnirudh Venkataramanan 142272adf242SAnirudh Venkataramanan /** 142372adf242SAnirudh Venkataramanan * ice_vsi_start_rx_rings - start VSI's Rx rings 142472adf242SAnirudh Venkataramanan * @vsi: the VSI whose rings are to be started 142572adf242SAnirudh Venkataramanan * 142672adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 142772adf242SAnirudh Venkataramanan */ 142872adf242SAnirudh Venkataramanan int ice_vsi_start_rx_rings(struct ice_vsi *vsi) 142972adf242SAnirudh Venkataramanan { 143072adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, true); 143172adf242SAnirudh Venkataramanan } 143272adf242SAnirudh Venkataramanan 143372adf242SAnirudh Venkataramanan /** 143472adf242SAnirudh Venkataramanan * ice_vsi_stop_rx_rings - stop VSI's Rx rings 143572adf242SAnirudh Venkataramanan * @vsi: the VSI 143672adf242SAnirudh Venkataramanan * 143772adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 143872adf242SAnirudh Venkataramanan */ 143972adf242SAnirudh Venkataramanan int ice_vsi_stop_rx_rings(struct ice_vsi *vsi) 144072adf242SAnirudh Venkataramanan { 144172adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, false); 144272adf242SAnirudh Venkataramanan } 144372adf242SAnirudh Venkataramanan 144472adf242SAnirudh Venkataramanan /** 1445d02f734cSMaciej Fijalkowski * ice_vsi_stop_tx_rings - Disable Tx rings 1446d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 1447d02f734cSMaciej Fijalkowski * @rst_src: reset source 1448d02f734cSMaciej Fijalkowski * @rel_vmvf_num: Relative ID of VF/VM 1449d02f734cSMaciej Fijalkowski * @rings: Tx ring array to be stopped 1450d02f734cSMaciej Fijalkowski */ 1451d02f734cSMaciej Fijalkowski static int 1452d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 1453d02f734cSMaciej Fijalkowski u16 rel_vmvf_num, struct ice_ring **rings) 1454d02f734cSMaciej Fijalkowski { 1455e75d1b2cSMaciej Fijalkowski u16 q_idx; 1456d02f734cSMaciej Fijalkowski 1457d02f734cSMaciej Fijalkowski if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS) 1458d02f734cSMaciej Fijalkowski return -EINVAL; 1459d02f734cSMaciej Fijalkowski 1460e75d1b2cSMaciej Fijalkowski for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) { 1461d02f734cSMaciej Fijalkowski struct ice_txq_meta txq_meta = { }; 1462e75d1b2cSMaciej Fijalkowski int status; 1463d02f734cSMaciej Fijalkowski 1464d02f734cSMaciej Fijalkowski if (!rings || !rings[q_idx]) 1465d02f734cSMaciej Fijalkowski return -EINVAL; 1466d02f734cSMaciej Fijalkowski 1467d02f734cSMaciej Fijalkowski ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta); 1468e75d1b2cSMaciej Fijalkowski status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num, 1469d02f734cSMaciej Fijalkowski rings[q_idx], &txq_meta); 1470d02f734cSMaciej Fijalkowski 1471d02f734cSMaciej Fijalkowski if (status) 1472d02f734cSMaciej Fijalkowski return status; 1473bb87ee0eSAnirudh Venkataramanan } 147472adf242SAnirudh Venkataramanan 1475d02f734cSMaciej Fijalkowski return 0; 147672adf242SAnirudh Venkataramanan } 14775153a18eSAnirudh Venkataramanan 14785153a18eSAnirudh Venkataramanan /** 147903f7a986SAnirudh Venkataramanan * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings 148003f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 148103f7a986SAnirudh Venkataramanan * @rst_src: reset source 1482f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 148303f7a986SAnirudh Venkataramanan */ 1484c8b7abddSBruce Allan int 1485c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 1486c8b7abddSBruce Allan u16 rel_vmvf_num) 148703f7a986SAnirudh Venkataramanan { 1488d02f734cSMaciej Fijalkowski return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings); 148903f7a986SAnirudh Venkataramanan } 149003f7a986SAnirudh Venkataramanan 149103f7a986SAnirudh Venkataramanan /** 14925153a18eSAnirudh Venkataramanan * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 14935153a18eSAnirudh Venkataramanan * @vsi: VSI to enable or disable VLAN pruning on 14945153a18eSAnirudh Venkataramanan * @ena: set to true to enable VLAN pruning and false to disable it 14955eda8afdSAkeem G Abodunrin * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode 14965153a18eSAnirudh Venkataramanan * 14975153a18eSAnirudh Venkataramanan * returns 0 if VSI is updated, negative otherwise 14985153a18eSAnirudh Venkataramanan */ 14995eda8afdSAkeem G Abodunrin int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc) 15005153a18eSAnirudh Venkataramanan { 15015153a18eSAnirudh Venkataramanan struct ice_vsi_ctx *ctxt; 15025153a18eSAnirudh Venkataramanan struct device *dev; 1503819d8998SJesse Brandeburg struct ice_pf *pf; 15045153a18eSAnirudh Venkataramanan int status; 15055153a18eSAnirudh Venkataramanan 15065153a18eSAnirudh Venkataramanan if (!vsi) 15075153a18eSAnirudh Venkataramanan return -EINVAL; 15085153a18eSAnirudh Venkataramanan 1509819d8998SJesse Brandeburg pf = vsi->back; 1510819d8998SJesse Brandeburg dev = &pf->pdev->dev; 15115153a18eSAnirudh Venkataramanan ctxt = devm_kzalloc(dev, sizeof(*ctxt), GFP_KERNEL); 15125153a18eSAnirudh Venkataramanan if (!ctxt) 15135153a18eSAnirudh Venkataramanan return -ENOMEM; 15145153a18eSAnirudh Venkataramanan 15155153a18eSAnirudh Venkataramanan ctxt->info = vsi->info; 15165153a18eSAnirudh Venkataramanan 15175153a18eSAnirudh Venkataramanan if (ena) { 15185153a18eSAnirudh Venkataramanan ctxt->info.sec_flags |= 15195153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 15205153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S; 15215153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 15225153a18eSAnirudh Venkataramanan } else { 15235153a18eSAnirudh Venkataramanan ctxt->info.sec_flags &= 15245153a18eSAnirudh Venkataramanan ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 15255153a18eSAnirudh Venkataramanan ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 15265153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 15275153a18eSAnirudh Venkataramanan } 15285153a18eSAnirudh Venkataramanan 15295eda8afdSAkeem G Abodunrin if (!vlan_promisc) 15305eda8afdSAkeem G Abodunrin ctxt->info.valid_sections = 15315eda8afdSAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID | 15325153a18eSAnirudh Venkataramanan ICE_AQ_VSI_PROP_SW_VALID); 15335726ca0eSAnirudh Venkataramanan 1534819d8998SJesse Brandeburg status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL); 15355153a18eSAnirudh Venkataramanan if (status) { 15365726ca0eSAnirudh Venkataramanan netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %d\n", 153731082519SAnirudh Venkataramanan ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status, 1538819d8998SJesse Brandeburg pf->hw.adminq.sq_last_status); 15395153a18eSAnirudh Venkataramanan goto err_out; 15405153a18eSAnirudh Venkataramanan } 15415153a18eSAnirudh Venkataramanan 15425153a18eSAnirudh Venkataramanan vsi->info.sec_flags = ctxt->info.sec_flags; 15435153a18eSAnirudh Venkataramanan vsi->info.sw_flags2 = ctxt->info.sw_flags2; 15445153a18eSAnirudh Venkataramanan 15455153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 15465153a18eSAnirudh Venkataramanan return 0; 15475153a18eSAnirudh Venkataramanan 15485153a18eSAnirudh Venkataramanan err_out: 15495153a18eSAnirudh Venkataramanan devm_kfree(dev, ctxt); 15505153a18eSAnirudh Venkataramanan return -EIO; 15515153a18eSAnirudh Venkataramanan } 15525153a18eSAnirudh Venkataramanan 15537b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) 15547b9ffc76SAnirudh Venkataramanan { 15557b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *cfg = &vsi->port_info->local_dcbx_cfg; 15567b9ffc76SAnirudh Venkataramanan 15577b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg); 15587b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg); 15597b9ffc76SAnirudh Venkataramanan } 15607b9ffc76SAnirudh Venkataramanan 15615153a18eSAnirudh Venkataramanan /** 1562b07833a0SBrett Creeley * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors 1563b07833a0SBrett Creeley * @vsi: VSI to set the q_vectors register index on 1564b07833a0SBrett Creeley */ 1565b07833a0SBrett Creeley static int 1566b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi) 1567b07833a0SBrett Creeley { 1568b07833a0SBrett Creeley u16 i; 1569b07833a0SBrett Creeley 1570b07833a0SBrett Creeley if (!vsi || !vsi->q_vectors) 1571b07833a0SBrett Creeley return -EINVAL; 1572b07833a0SBrett Creeley 1573b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 1574b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1575b07833a0SBrett Creeley 1576b07833a0SBrett Creeley if (!q_vector) { 1577b07833a0SBrett Creeley dev_err(&vsi->back->pdev->dev, 1578b07833a0SBrett Creeley "Failed to set reg_idx on q_vector %d VSI %d\n", 1579b07833a0SBrett Creeley i, vsi->vsi_num); 1580b07833a0SBrett Creeley goto clear_reg_idx; 1581b07833a0SBrett Creeley } 1582b07833a0SBrett Creeley 1583cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) { 1584cbe66bfeSBrett Creeley struct ice_vf *vf = &vsi->back->vf[vsi->vf_id]; 1585cbe66bfeSBrett Creeley 1586cbe66bfeSBrett Creeley q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector); 1587cbe66bfeSBrett Creeley } else { 1588cbe66bfeSBrett Creeley q_vector->reg_idx = 1589cbe66bfeSBrett Creeley q_vector->v_idx + vsi->base_vector; 1590cbe66bfeSBrett Creeley } 1591b07833a0SBrett Creeley } 1592b07833a0SBrett Creeley 1593b07833a0SBrett Creeley return 0; 1594b07833a0SBrett Creeley 1595b07833a0SBrett Creeley clear_reg_idx: 1596b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 1597b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1598b07833a0SBrett Creeley 1599b07833a0SBrett Creeley if (q_vector) 1600b07833a0SBrett Creeley q_vector->reg_idx = 0; 1601b07833a0SBrett Creeley } 1602b07833a0SBrett Creeley 1603b07833a0SBrett Creeley return -EINVAL; 1604b07833a0SBrett Creeley } 1605b07833a0SBrett Creeley 1606b07833a0SBrett Creeley /** 1607d95276ceSAkeem G Abodunrin * ice_vsi_add_rem_eth_mac - Program VSI ethertype based filter with rule 1608d95276ceSAkeem G Abodunrin * @vsi: the VSI being configured 1609d95276ceSAkeem G Abodunrin * @add_rule: boolean value to add or remove ethertype filter rule 1610d95276ceSAkeem G Abodunrin */ 1611d95276ceSAkeem G Abodunrin static void 1612d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(struct ice_vsi *vsi, bool add_rule) 1613d95276ceSAkeem G Abodunrin { 1614d95276ceSAkeem G Abodunrin struct ice_fltr_list_entry *list; 1615d95276ceSAkeem G Abodunrin struct ice_pf *pf = vsi->back; 1616d95276ceSAkeem G Abodunrin LIST_HEAD(tmp_add_list); 1617d95276ceSAkeem G Abodunrin enum ice_status status; 1618d95276ceSAkeem G Abodunrin 1619d95276ceSAkeem G Abodunrin list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 1620d95276ceSAkeem G Abodunrin if (!list) 1621d95276ceSAkeem G Abodunrin return; 1622d95276ceSAkeem G Abodunrin 1623d95276ceSAkeem G Abodunrin list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 1624d95276ceSAkeem G Abodunrin list->fltr_info.fltr_act = ICE_DROP_PACKET; 1625d95276ceSAkeem G Abodunrin list->fltr_info.flag = ICE_FLTR_TX; 1626d95276ceSAkeem G Abodunrin list->fltr_info.src_id = ICE_SRC_ID_VSI; 1627d95276ceSAkeem G Abodunrin list->fltr_info.vsi_handle = vsi->idx; 1628d95276ceSAkeem G Abodunrin list->fltr_info.l_data.ethertype_mac.ethertype = vsi->ethtype; 1629d95276ceSAkeem G Abodunrin 1630d95276ceSAkeem G Abodunrin INIT_LIST_HEAD(&list->list_entry); 1631d95276ceSAkeem G Abodunrin list_add(&list->list_entry, &tmp_add_list); 1632d95276ceSAkeem G Abodunrin 1633d95276ceSAkeem G Abodunrin if (add_rule) 1634d95276ceSAkeem G Abodunrin status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 1635d95276ceSAkeem G Abodunrin else 1636d95276ceSAkeem G Abodunrin status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 1637d95276ceSAkeem G Abodunrin 1638d95276ceSAkeem G Abodunrin if (status) 1639d95276ceSAkeem G Abodunrin dev_err(&pf->pdev->dev, 1640d95276ceSAkeem G Abodunrin "Failure Adding or Removing Ethertype on VSI %i error: %d\n", 1641d95276ceSAkeem G Abodunrin vsi->vsi_num, status); 1642d95276ceSAkeem G Abodunrin 1643d95276ceSAkeem G Abodunrin ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 1644d95276ceSAkeem G Abodunrin } 1645d95276ceSAkeem G Abodunrin 16462e0e6228SDave Ertman /** 16472e0e6228SDave Ertman * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling 16482e0e6228SDave Ertman * @vsi: the VSI being configured 16492e0e6228SDave Ertman * @tx: bool to determine Tx or Rx rule 16502e0e6228SDave Ertman * @create: bool to determine create or remove Rule 16512e0e6228SDave Ertman */ 16522e0e6228SDave Ertman void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create) 16532e0e6228SDave Ertman { 16542e0e6228SDave Ertman struct ice_fltr_list_entry *list; 16552e0e6228SDave Ertman struct ice_pf *pf = vsi->back; 16562e0e6228SDave Ertman LIST_HEAD(tmp_add_list); 16572e0e6228SDave Ertman enum ice_status status; 16582e0e6228SDave Ertman 16592e0e6228SDave Ertman list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL); 16602e0e6228SDave Ertman if (!list) 16612e0e6228SDave Ertman return; 16622e0e6228SDave Ertman 16632e0e6228SDave Ertman list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 16642e0e6228SDave Ertman list->fltr_info.vsi_handle = vsi->idx; 16653aea1736SJeff Kirsher list->fltr_info.l_data.ethertype_mac.ethertype = ETH_P_LLDP; 16662e0e6228SDave Ertman 16672e0e6228SDave Ertman if (tx) { 16682e0e6228SDave Ertman list->fltr_info.fltr_act = ICE_DROP_PACKET; 16692e0e6228SDave Ertman list->fltr_info.flag = ICE_FLTR_TX; 16702e0e6228SDave Ertman list->fltr_info.src_id = ICE_SRC_ID_VSI; 16712e0e6228SDave Ertman } else { 16722e0e6228SDave Ertman list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 16732e0e6228SDave Ertman list->fltr_info.flag = ICE_FLTR_RX; 16742e0e6228SDave Ertman list->fltr_info.src_id = ICE_SRC_ID_LPORT; 16752e0e6228SDave Ertman } 16762e0e6228SDave Ertman 16772e0e6228SDave Ertman INIT_LIST_HEAD(&list->list_entry); 16782e0e6228SDave Ertman list_add(&list->list_entry, &tmp_add_list); 16792e0e6228SDave Ertman 16802e0e6228SDave Ertman if (create) 16812e0e6228SDave Ertman status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 16822e0e6228SDave Ertman else 16832e0e6228SDave Ertman status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 16842e0e6228SDave Ertman 16852e0e6228SDave Ertman if (status) 16862e0e6228SDave Ertman dev_err(&pf->pdev->dev, 16872e0e6228SDave Ertman "Fail %s %s LLDP rule on VSI %i error: %d\n", 16882e0e6228SDave Ertman create ? "adding" : "removing", tx ? "TX" : "RX", 16892e0e6228SDave Ertman vsi->vsi_num, status); 16902e0e6228SDave Ertman 16912e0e6228SDave Ertman ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list); 16922e0e6228SDave Ertman } 16932e0e6228SDave Ertman 1694d95276ceSAkeem G Abodunrin /** 169537bb8390SAnirudh Venkataramanan * ice_vsi_setup - Set up a VSI by a given type 169637bb8390SAnirudh Venkataramanan * @pf: board private structure 169737bb8390SAnirudh Venkataramanan * @pi: pointer to the port_info instance 169837bb8390SAnirudh Venkataramanan * @type: VSI type 1699f9867df6SAnirudh Venkataramanan * @vf_id: defines VF ID to which this VSI connects. This field is meant to be 170037bb8390SAnirudh Venkataramanan * used only for ICE_VSI_VF VSI type. For other VSI types, should 170137bb8390SAnirudh Venkataramanan * fill-in ICE_INVAL_VFID as input. 170237bb8390SAnirudh Venkataramanan * 170337bb8390SAnirudh Venkataramanan * This allocates the sw VSI structure and its queue resources. 170437bb8390SAnirudh Venkataramanan * 170537bb8390SAnirudh Venkataramanan * Returns pointer to the successfully allocated and configured VSI sw struct on 170637bb8390SAnirudh Venkataramanan * success, NULL on failure. 170737bb8390SAnirudh Venkataramanan */ 170837bb8390SAnirudh Venkataramanan struct ice_vsi * 170937bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, 17108ede0178SAnirudh Venkataramanan enum ice_vsi_type type, u16 vf_id) 171137bb8390SAnirudh Venkataramanan { 171237bb8390SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 171337bb8390SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 1714d31530e8SAkeem G Abodunrin enum ice_status status; 171537bb8390SAnirudh Venkataramanan struct ice_vsi *vsi; 171637bb8390SAnirudh Venkataramanan int ret, i; 171737bb8390SAnirudh Venkataramanan 17185743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 17195743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, vf_id); 17205743020dSAkeem G Abodunrin else 17215743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, ICE_INVAL_VFID); 17225743020dSAkeem G Abodunrin 172337bb8390SAnirudh Venkataramanan if (!vsi) { 172437bb8390SAnirudh Venkataramanan dev_err(dev, "could not allocate VSI\n"); 172537bb8390SAnirudh Venkataramanan return NULL; 172637bb8390SAnirudh Venkataramanan } 172737bb8390SAnirudh Venkataramanan 172837bb8390SAnirudh Venkataramanan vsi->port_info = pi; 172937bb8390SAnirudh Venkataramanan vsi->vsw = pf->first_sw; 1730d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 1731d95276ceSAkeem G Abodunrin vsi->ethtype = ETH_P_PAUSE; 1732d95276ceSAkeem G Abodunrin 17338ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 17348ede0178SAnirudh Venkataramanan vsi->vf_id = vf_id; 173537bb8390SAnirudh Venkataramanan 173637bb8390SAnirudh Venkataramanan if (ice_vsi_get_qs(vsi)) { 173737bb8390SAnirudh Venkataramanan dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", 173837bb8390SAnirudh Venkataramanan vsi->idx); 173937bb8390SAnirudh Venkataramanan goto unroll_get_qs; 174037bb8390SAnirudh Venkataramanan } 174137bb8390SAnirudh Venkataramanan 174237bb8390SAnirudh Venkataramanan /* set RSS capabilities */ 174337bb8390SAnirudh Venkataramanan ice_vsi_set_rss_params(vsi); 174437bb8390SAnirudh Venkataramanan 1745f9867df6SAnirudh Venkataramanan /* set TC configuration */ 1746c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 1747c5a2a4a3SUsha Ketineni 174837bb8390SAnirudh Venkataramanan /* create the VSI */ 174937bb8390SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 175037bb8390SAnirudh Venkataramanan if (ret) 175137bb8390SAnirudh Venkataramanan goto unroll_get_qs; 175237bb8390SAnirudh Venkataramanan 175337bb8390SAnirudh Venkataramanan switch (vsi->type) { 175437bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 175537bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 175637bb8390SAnirudh Venkataramanan if (ret) 175737bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 175837bb8390SAnirudh Venkataramanan 175937bb8390SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 176037bb8390SAnirudh Venkataramanan if (ret) 176137bb8390SAnirudh Venkataramanan goto unroll_alloc_q_vector; 176237bb8390SAnirudh Venkataramanan 1763b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 1764b07833a0SBrett Creeley if (ret) 1765b07833a0SBrett Creeley goto unroll_vector_base; 1766b07833a0SBrett Creeley 176737bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 176837bb8390SAnirudh Venkataramanan if (ret) 176937bb8390SAnirudh Venkataramanan goto unroll_vector_base; 177037bb8390SAnirudh Venkataramanan 177137bb8390SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 177237bb8390SAnirudh Venkataramanan 177337bb8390SAnirudh Venkataramanan /* Do not exit if configuring RSS had an issue, at least 177437bb8390SAnirudh Venkataramanan * receive traffic on first queue. Hence no need to capture 177537bb8390SAnirudh Venkataramanan * return value 177637bb8390SAnirudh Venkataramanan */ 177737bb8390SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 177837bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_lut_key(vsi); 177937bb8390SAnirudh Venkataramanan break; 17808ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 17818ede0178SAnirudh Venkataramanan /* VF driver will take care of creating netdev for this type and 17828ede0178SAnirudh Venkataramanan * map queues to vectors through Virtchnl, PF driver only 17838ede0178SAnirudh Venkataramanan * creates a VSI and corresponding structures for bookkeeping 17848ede0178SAnirudh Venkataramanan * purpose 17858ede0178SAnirudh Venkataramanan */ 17868ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 17878ede0178SAnirudh Venkataramanan if (ret) 17888ede0178SAnirudh Venkataramanan goto unroll_vsi_init; 17898ede0178SAnirudh Venkataramanan 17908ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 17918ede0178SAnirudh Venkataramanan if (ret) 17928ede0178SAnirudh Venkataramanan goto unroll_alloc_q_vector; 17938ede0178SAnirudh Venkataramanan 1794b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 1795b07833a0SBrett Creeley if (ret) 1796b07833a0SBrett Creeley goto unroll_vector_base; 1797b07833a0SBrett Creeley 17983a9e32bbSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 17993a9e32bbSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 18003a9e32bbSMd Fahad Iqbal Polash * return value 18013a9e32bbSMd Fahad Iqbal Polash */ 18023a9e32bbSMd Fahad Iqbal Polash if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 18033a9e32bbSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 18048ede0178SAnirudh Venkataramanan break; 18050e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 18060e674aebSAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 18070e674aebSAnirudh Venkataramanan if (ret) 18080e674aebSAnirudh Venkataramanan goto unroll_vsi_init; 18090e674aebSAnirudh Venkataramanan break; 181037bb8390SAnirudh Venkataramanan default: 1811df17b7e0SAnirudh Venkataramanan /* clean up the resources and exit */ 181237bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 181337bb8390SAnirudh Venkataramanan } 181437bb8390SAnirudh Venkataramanan 181537bb8390SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 181637bb8390SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 1817d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 181837bb8390SAnirudh Venkataramanan 1819d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 18204fb33f31SAnirudh Venkataramanan max_txqs); 1821d31530e8SAkeem G Abodunrin if (status) { 182220ce2a1aSBrett Creeley dev_err(&pf->pdev->dev, 182320ce2a1aSBrett Creeley "VSI %d failed lan queue config, error %d\n", 1824d31530e8SAkeem G Abodunrin vsi->vsi_num, status); 182537bb8390SAnirudh Venkataramanan goto unroll_vector_base; 182637bb8390SAnirudh Venkataramanan } 182737bb8390SAnirudh Venkataramanan 1828d95276ceSAkeem G Abodunrin /* Add switch rule to drop all Tx Flow Control Frames, of look up 1829d95276ceSAkeem G Abodunrin * type ETHERTYPE from VSIs, and restrict malicious VF from sending 1830d95276ceSAkeem G Abodunrin * out PAUSE or PFC frames. If enabled, FW can still send FC frames. 1831d95276ceSAkeem G Abodunrin * The rule is added once for PF VSI in order to create appropriate 1832d95276ceSAkeem G Abodunrin * recipe, since VSI/VSI list is ignored with drop action... 18332e0e6228SDave Ertman * Also add rules to handle LLDP Tx and Rx packets. Tx LLDP packets 18342e0e6228SDave Ertman * need to be dropped so that VFs cannot send LLDP packets to reconfig 18352f2da36eSAnirudh Venkataramanan * DCB settings in the HW. Also, if the FW DCBX engine is not running 18362e0e6228SDave Ertman * then Rx LLDP packets need to be redirected up the stack. 1837d95276ceSAkeem G Abodunrin */ 1838462acf6aSTony Nguyen if (!ice_is_safe_mode(pf)) { 18392e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 1840d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, true); 1841d95276ceSAkeem G Abodunrin 18422e0e6228SDave Ertman /* Tx LLDP packets */ 18432e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, true); 18442e0e6228SDave Ertman 18452e0e6228SDave Ertman /* Rx LLDP packets */ 184684a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) 18472e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, true); 18482e0e6228SDave Ertman } 1849462acf6aSTony Nguyen } 18502e0e6228SDave Ertman 185137bb8390SAnirudh Venkataramanan return vsi; 185237bb8390SAnirudh Venkataramanan 185337bb8390SAnirudh Venkataramanan unroll_vector_base: 1854eb0208ecSPreethi Banala /* reclaim SW interrupts back to the common pool */ 1855cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 1856eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 185737bb8390SAnirudh Venkataramanan unroll_alloc_q_vector: 185837bb8390SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 185937bb8390SAnirudh Venkataramanan unroll_vsi_init: 186037bb8390SAnirudh Venkataramanan ice_vsi_delete(vsi); 186137bb8390SAnirudh Venkataramanan unroll_get_qs: 186237bb8390SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 186337bb8390SAnirudh Venkataramanan ice_vsi_clear(vsi); 186437bb8390SAnirudh Venkataramanan 186537bb8390SAnirudh Venkataramanan return NULL; 186637bb8390SAnirudh Venkataramanan } 186737bb8390SAnirudh Venkataramanan 186837bb8390SAnirudh Venkataramanan /** 18695153a18eSAnirudh Venkataramanan * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW 18705153a18eSAnirudh Venkataramanan * @vsi: the VSI being cleaned up 18715153a18eSAnirudh Venkataramanan */ 18725153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi) 18735153a18eSAnirudh Venkataramanan { 18745153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 18755153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 18765153a18eSAnirudh Venkataramanan u32 txq = 0; 18775153a18eSAnirudh Venkataramanan u32 rxq = 0; 18785153a18eSAnirudh Venkataramanan int i, q; 18795153a18eSAnirudh Venkataramanan 1880cbe66bfeSBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 18815153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1882cbe66bfeSBrett Creeley u16 reg_idx = q_vector->reg_idx; 18835153a18eSAnirudh Venkataramanan 1884cbe66bfeSBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0); 1885cbe66bfeSBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0); 18865153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 18875153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); 18885153a18eSAnirudh Venkataramanan txq++; 18895153a18eSAnirudh Venkataramanan } 18905153a18eSAnirudh Venkataramanan 18915153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 18925153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0); 18935153a18eSAnirudh Venkataramanan rxq++; 18945153a18eSAnirudh Venkataramanan } 18955153a18eSAnirudh Venkataramanan } 18965153a18eSAnirudh Venkataramanan 18975153a18eSAnirudh Venkataramanan ice_flush(hw); 18985153a18eSAnirudh Venkataramanan } 18995153a18eSAnirudh Venkataramanan 19005153a18eSAnirudh Venkataramanan /** 19015153a18eSAnirudh Venkataramanan * ice_vsi_free_irq - Free the IRQ association with the OS 19025153a18eSAnirudh Venkataramanan * @vsi: the VSI being configured 19035153a18eSAnirudh Venkataramanan */ 19045153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi) 19055153a18eSAnirudh Venkataramanan { 19065153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1907cbe66bfeSBrett Creeley int base = vsi->base_vector; 19085153a18eSAnirudh Venkataramanan int i; 19095153a18eSAnirudh Venkataramanan 19105153a18eSAnirudh Venkataramanan if (!vsi->q_vectors || !vsi->irqs_ready) 19115153a18eSAnirudh Venkataramanan return; 19125153a18eSAnirudh Venkataramanan 1913eb0208ecSPreethi Banala ice_vsi_release_msix(vsi); 19148ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 19158ede0178SAnirudh Venkataramanan return; 1916eb0208ecSPreethi Banala 19175153a18eSAnirudh Venkataramanan vsi->irqs_ready = false; 19180c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) { 19195153a18eSAnirudh Venkataramanan u16 vector = i + base; 19205153a18eSAnirudh Venkataramanan int irq_num; 19215153a18eSAnirudh Venkataramanan 19225153a18eSAnirudh Venkataramanan irq_num = pf->msix_entries[vector].vector; 19235153a18eSAnirudh Venkataramanan 19245153a18eSAnirudh Venkataramanan /* free only the irqs that were actually requested */ 19255153a18eSAnirudh Venkataramanan if (!vsi->q_vectors[i] || 19265153a18eSAnirudh Venkataramanan !(vsi->q_vectors[i]->num_ring_tx || 19275153a18eSAnirudh Venkataramanan vsi->q_vectors[i]->num_ring_rx)) 19285153a18eSAnirudh Venkataramanan continue; 19295153a18eSAnirudh Venkataramanan 19305153a18eSAnirudh Venkataramanan /* clear the affinity notifier in the IRQ descriptor */ 19315153a18eSAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 19325153a18eSAnirudh Venkataramanan 19335153a18eSAnirudh Venkataramanan /* clear the affinity_mask in the IRQ descriptor */ 19345153a18eSAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 19355153a18eSAnirudh Venkataramanan synchronize_irq(irq_num); 19365153a18eSAnirudh Venkataramanan devm_free_irq(&pf->pdev->dev, irq_num, 19375153a18eSAnirudh Venkataramanan vsi->q_vectors[i]); 19385153a18eSAnirudh Venkataramanan } 19395153a18eSAnirudh Venkataramanan } 19405153a18eSAnirudh Venkataramanan 19415153a18eSAnirudh Venkataramanan /** 19425153a18eSAnirudh Venkataramanan * ice_vsi_free_tx_rings - Free Tx resources for VSI queues 19435153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 19445153a18eSAnirudh Venkataramanan */ 19455153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi) 19465153a18eSAnirudh Venkataramanan { 19475153a18eSAnirudh Venkataramanan int i; 19485153a18eSAnirudh Venkataramanan 19495153a18eSAnirudh Venkataramanan if (!vsi->tx_rings) 19505153a18eSAnirudh Venkataramanan return; 19515153a18eSAnirudh Venkataramanan 19525153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) 19535153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 19545153a18eSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 19555153a18eSAnirudh Venkataramanan } 19565153a18eSAnirudh Venkataramanan 19575153a18eSAnirudh Venkataramanan /** 19585153a18eSAnirudh Venkataramanan * ice_vsi_free_rx_rings - Free Rx resources for VSI queues 19595153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 19605153a18eSAnirudh Venkataramanan */ 19615153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi) 19625153a18eSAnirudh Venkataramanan { 19635153a18eSAnirudh Venkataramanan int i; 19645153a18eSAnirudh Venkataramanan 19655153a18eSAnirudh Venkataramanan if (!vsi->rx_rings) 19665153a18eSAnirudh Venkataramanan return; 19675153a18eSAnirudh Venkataramanan 19685153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 19695153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) 19705153a18eSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 19715153a18eSAnirudh Venkataramanan } 19725153a18eSAnirudh Venkataramanan 19735153a18eSAnirudh Venkataramanan /** 197407309a0eSAnirudh Venkataramanan * ice_vsi_close - Shut down a VSI 197507309a0eSAnirudh Venkataramanan * @vsi: the VSI being shut down 197607309a0eSAnirudh Venkataramanan */ 197707309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi) 197807309a0eSAnirudh Venkataramanan { 197907309a0eSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) 198007309a0eSAnirudh Venkataramanan ice_down(vsi); 198107309a0eSAnirudh Venkataramanan 198207309a0eSAnirudh Venkataramanan ice_vsi_free_irq(vsi); 198307309a0eSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 198407309a0eSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 198507309a0eSAnirudh Venkataramanan } 198607309a0eSAnirudh Venkataramanan 198707309a0eSAnirudh Venkataramanan /** 19885153a18eSAnirudh Venkataramanan * ice_free_res - free a block of resources 19895153a18eSAnirudh Venkataramanan * @res: pointer to the resource 19905153a18eSAnirudh Venkataramanan * @index: starting index previously returned by ice_get_res 19915153a18eSAnirudh Venkataramanan * @id: identifier to track owner 19925153a18eSAnirudh Venkataramanan * 19935153a18eSAnirudh Venkataramanan * Returns number of resources freed 19945153a18eSAnirudh Venkataramanan */ 19955153a18eSAnirudh Venkataramanan int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) 19965153a18eSAnirudh Venkataramanan { 19975153a18eSAnirudh Venkataramanan int count = 0; 19985153a18eSAnirudh Venkataramanan int i; 19995153a18eSAnirudh Venkataramanan 2000cbe66bfeSBrett Creeley if (!res || index >= res->end) 20015153a18eSAnirudh Venkataramanan return -EINVAL; 20025153a18eSAnirudh Venkataramanan 20035153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 2004cbe66bfeSBrett Creeley for (i = index; i < res->end && res->list[i] == id; i++) { 20055153a18eSAnirudh Venkataramanan res->list[i] = 0; 20065153a18eSAnirudh Venkataramanan count++; 20075153a18eSAnirudh Venkataramanan } 20085153a18eSAnirudh Venkataramanan 20095153a18eSAnirudh Venkataramanan return count; 20105153a18eSAnirudh Venkataramanan } 20115153a18eSAnirudh Venkataramanan 20125153a18eSAnirudh Venkataramanan /** 20135153a18eSAnirudh Venkataramanan * ice_search_res - Search the tracker for a block of resources 20145153a18eSAnirudh Venkataramanan * @res: pointer to the resource 20155153a18eSAnirudh Venkataramanan * @needed: size of the block needed 20165153a18eSAnirudh Venkataramanan * @id: identifier to track owner 20175153a18eSAnirudh Venkataramanan * 20185153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 20195153a18eSAnirudh Venkataramanan */ 20205153a18eSAnirudh Venkataramanan static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) 20215153a18eSAnirudh Venkataramanan { 2022cbe66bfeSBrett Creeley int start = 0, end = 0; 20235153a18eSAnirudh Venkataramanan 2024cbe66bfeSBrett Creeley if (needed > res->end) 2025eb0208ecSPreethi Banala return -ENOMEM; 2026eb0208ecSPreethi Banala 20275153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 20285153a18eSAnirudh Venkataramanan 20295153a18eSAnirudh Venkataramanan do { 20305153a18eSAnirudh Venkataramanan /* skip already allocated entries */ 20315153a18eSAnirudh Venkataramanan if (res->list[end++] & ICE_RES_VALID_BIT) { 20325153a18eSAnirudh Venkataramanan start = end; 2033cbe66bfeSBrett Creeley if ((start + needed) > res->end) 20345153a18eSAnirudh Venkataramanan break; 20355153a18eSAnirudh Venkataramanan } 20365153a18eSAnirudh Venkataramanan 20375153a18eSAnirudh Venkataramanan if (end == (start + needed)) { 20385153a18eSAnirudh Venkataramanan int i = start; 20395153a18eSAnirudh Venkataramanan 20405153a18eSAnirudh Venkataramanan /* there was enough, so assign it to the requestor */ 20415153a18eSAnirudh Venkataramanan while (i != end) 20425153a18eSAnirudh Venkataramanan res->list[i++] = id; 20435153a18eSAnirudh Venkataramanan 20445153a18eSAnirudh Venkataramanan return start; 20455153a18eSAnirudh Venkataramanan } 2046cbe66bfeSBrett Creeley } while (end < res->end); 20475153a18eSAnirudh Venkataramanan 20485153a18eSAnirudh Venkataramanan return -ENOMEM; 20495153a18eSAnirudh Venkataramanan } 20505153a18eSAnirudh Venkataramanan 20515153a18eSAnirudh Venkataramanan /** 20525153a18eSAnirudh Venkataramanan * ice_get_res - get a block of resources 20535153a18eSAnirudh Venkataramanan * @pf: board private structure 20545153a18eSAnirudh Venkataramanan * @res: pointer to the resource 20555153a18eSAnirudh Venkataramanan * @needed: size of the block needed 20565153a18eSAnirudh Venkataramanan * @id: identifier to track owner 20575153a18eSAnirudh Venkataramanan * 2058cbe66bfeSBrett Creeley * Returns the base item index of the block, or negative for error 20595153a18eSAnirudh Venkataramanan */ 20605153a18eSAnirudh Venkataramanan int 20615153a18eSAnirudh Venkataramanan ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) 20625153a18eSAnirudh Venkataramanan { 20635153a18eSAnirudh Venkataramanan if (!res || !pf) 20645153a18eSAnirudh Venkataramanan return -EINVAL; 20655153a18eSAnirudh Venkataramanan 20665153a18eSAnirudh Venkataramanan if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { 20675153a18eSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 20685153a18eSAnirudh Venkataramanan "param err: needed=%d, num_entries = %d id=0x%04x\n", 20695153a18eSAnirudh Venkataramanan needed, res->num_entries, id); 20705153a18eSAnirudh Venkataramanan return -EINVAL; 20715153a18eSAnirudh Venkataramanan } 20725153a18eSAnirudh Venkataramanan 2073cbe66bfeSBrett Creeley return ice_search_res(res, needed, id); 20745153a18eSAnirudh Venkataramanan } 20755153a18eSAnirudh Venkataramanan 20765153a18eSAnirudh Venkataramanan /** 20775153a18eSAnirudh Venkataramanan * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI 20785153a18eSAnirudh Venkataramanan * @vsi: the VSI being un-configured 20795153a18eSAnirudh Venkataramanan */ 20805153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi) 20815153a18eSAnirudh Venkataramanan { 2082cbe66bfeSBrett Creeley int base = vsi->base_vector; 20835153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 20845153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 20855153a18eSAnirudh Venkataramanan u32 val; 20865153a18eSAnirudh Venkataramanan int i; 20875153a18eSAnirudh Venkataramanan 20885153a18eSAnirudh Venkataramanan /* disable interrupt causation from each queue */ 20895153a18eSAnirudh Venkataramanan if (vsi->tx_rings) { 20905153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 20915153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i]) { 20925153a18eSAnirudh Venkataramanan u16 reg; 20935153a18eSAnirudh Venkataramanan 20945153a18eSAnirudh Venkataramanan reg = vsi->tx_rings[i]->reg_idx; 20955153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(reg)); 20965153a18eSAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 20975153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(reg), val); 20985153a18eSAnirudh Venkataramanan } 20995153a18eSAnirudh Venkataramanan } 21005153a18eSAnirudh Venkataramanan } 21015153a18eSAnirudh Venkataramanan 21025153a18eSAnirudh Venkataramanan if (vsi->rx_rings) { 21035153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 21045153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i]) { 21055153a18eSAnirudh Venkataramanan u16 reg; 21065153a18eSAnirudh Venkataramanan 21075153a18eSAnirudh Venkataramanan reg = vsi->rx_rings[i]->reg_idx; 21085153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_RQCTL(reg)); 21095153a18eSAnirudh Venkataramanan val &= ~QINT_RQCTL_CAUSE_ENA_M; 21105153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(reg), val); 21115153a18eSAnirudh Venkataramanan } 21125153a18eSAnirudh Venkataramanan } 21135153a18eSAnirudh Venkataramanan } 21145153a18eSAnirudh Venkataramanan 21155153a18eSAnirudh Venkataramanan /* disable each interrupt */ 2116462acf6aSTony Nguyen ice_for_each_q_vector(vsi, i) { 2117462acf6aSTony Nguyen if (!vsi->q_vectors[i]) 2118462acf6aSTony Nguyen continue; 2119b07833a0SBrett Creeley wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); 2120462acf6aSTony Nguyen } 21215153a18eSAnirudh Venkataramanan 21225153a18eSAnirudh Venkataramanan ice_flush(hw); 2123b07833a0SBrett Creeley 2124da4a9e73SBrett Creeley /* don't call synchronize_irq() for VF's from the host */ 2125da4a9e73SBrett Creeley if (vsi->type == ICE_VSI_VF) 2126da4a9e73SBrett Creeley return; 2127da4a9e73SBrett Creeley 21280c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) 21295153a18eSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[i + base].vector); 21305153a18eSAnirudh Venkataramanan } 21315153a18eSAnirudh Venkataramanan 21325153a18eSAnirudh Venkataramanan /** 2133561f4379STony Nguyen * ice_napi_del - Remove NAPI handler for the VSI 2134561f4379STony Nguyen * @vsi: VSI for which NAPI handler is to be removed 2135561f4379STony Nguyen */ 2136561f4379STony Nguyen void ice_napi_del(struct ice_vsi *vsi) 2137561f4379STony Nguyen { 2138561f4379STony Nguyen int v_idx; 2139561f4379STony Nguyen 2140561f4379STony Nguyen if (!vsi->netdev) 2141561f4379STony Nguyen return; 2142561f4379STony Nguyen 2143561f4379STony Nguyen ice_for_each_q_vector(vsi, v_idx) 2144561f4379STony Nguyen netif_napi_del(&vsi->q_vectors[v_idx]->napi); 2145561f4379STony Nguyen } 2146561f4379STony Nguyen 2147561f4379STony Nguyen /** 2148df0f8479SAnirudh Venkataramanan * ice_vsi_release - Delete a VSI and free its resources 2149df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 2150df0f8479SAnirudh Venkataramanan * 2151df0f8479SAnirudh Venkataramanan * Returns 0 on success or < 0 on error 2152df0f8479SAnirudh Venkataramanan */ 2153df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi) 2154df0f8479SAnirudh Venkataramanan { 2155df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 2156df0f8479SAnirudh Venkataramanan 2157df0f8479SAnirudh Venkataramanan if (!vsi->back) 2158df0f8479SAnirudh Venkataramanan return -ENODEV; 2159df0f8479SAnirudh Venkataramanan pf = vsi->back; 2160b751930cSBrett Creeley 2161aa6ccf3fSBrett Creeley /* do not unregister while driver is in the reset recovery pending 2162aa6ccf3fSBrett Creeley * state. Since reset/rebuild happens through PF service task workqueue, 2163aa6ccf3fSBrett Creeley * it's not a good idea to unregister netdev that is associated to the 2164aa6ccf3fSBrett Creeley * PF that is running the work queue items currently. This is done to 2165aa6ccf3fSBrett Creeley * avoid check_flush_dependency() warning on this wq 2166df0f8479SAnirudh Venkataramanan */ 2167aa6ccf3fSBrett Creeley if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) 2168df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2169df0f8479SAnirudh Venkataramanan 2170df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 2171df0f8479SAnirudh Venkataramanan ice_rss_clean(vsi); 2172df0f8479SAnirudh Venkataramanan 2173df0f8479SAnirudh Venkataramanan /* Disable VSI and free resources */ 21740e674aebSAnirudh Venkataramanan if (vsi->type != ICE_VSI_LB) 2175df0f8479SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 2176df0f8479SAnirudh Venkataramanan ice_vsi_close(vsi); 2177df0f8479SAnirudh Venkataramanan 2178cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 2179cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 2180cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 2181cbe66bfeSBrett Creeley * cleared in the same manner. 2182cbe66bfeSBrett Creeley */ 21838ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 21848ede0178SAnirudh Venkataramanan /* reclaim SW interrupts back to the common pool */ 2185cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 2186eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 21878ede0178SAnirudh Venkataramanan } 2188df0f8479SAnirudh Venkataramanan 2189462acf6aSTony Nguyen if (!ice_is_safe_mode(pf)) { 21902e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 2191d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, false); 21922e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, false); 21932e0e6228SDave Ertman /* The Rx rule will only exist to remove if the LLDP FW 21942e0e6228SDave Ertman * engine is currently stopped 21952e0e6228SDave Ertman */ 219684a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) 21972e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, false); 21982e0e6228SDave Ertman } 2199462acf6aSTony Nguyen } 2200d95276ceSAkeem G Abodunrin 22015726ca0eSAnirudh Venkataramanan ice_remove_vsi_fltr(&pf->hw, vsi->idx); 220210e03a22SAnirudh Venkataramanan ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2203df0f8479SAnirudh Venkataramanan ice_vsi_delete(vsi); 2204df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2205aa6ccf3fSBrett Creeley 2206aa6ccf3fSBrett Creeley /* make sure unregister_netdev() was called by checking __ICE_DOWN */ 2207aa6ccf3fSBrett Creeley if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) { 2208aa6ccf3fSBrett Creeley free_netdev(vsi->netdev); 2209aa6ccf3fSBrett Creeley vsi->netdev = NULL; 2210aa6ccf3fSBrett Creeley } 2211aa6ccf3fSBrett Creeley 2212df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2213df0f8479SAnirudh Venkataramanan 2214df0f8479SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2215df0f8479SAnirudh Venkataramanan 2216df0f8479SAnirudh Venkataramanan /* retain SW VSI data structure since it is needed to unregister and 2217df0f8479SAnirudh Venkataramanan * free VSI netdev when PF is not in reset recovery pending state,\ 2218df0f8479SAnirudh Venkataramanan * for ex: during rmmod. 2219df0f8479SAnirudh Venkataramanan */ 22205df7e45dSDave Ertman if (!ice_is_reset_in_progress(pf->state)) 2221df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2222df0f8479SAnirudh Venkataramanan 2223df0f8479SAnirudh Venkataramanan return 0; 2224df0f8479SAnirudh Venkataramanan } 2225df0f8479SAnirudh Venkataramanan 2226df0f8479SAnirudh Venkataramanan /** 2227df0f8479SAnirudh Venkataramanan * ice_vsi_rebuild - Rebuild VSI after reset 2228df0f8479SAnirudh Venkataramanan * @vsi: VSI to be rebuild 2229df0f8479SAnirudh Venkataramanan * 2230df0f8479SAnirudh Venkataramanan * Returns 0 on success and negative value on failure 2231df0f8479SAnirudh Venkataramanan */ 2232df0f8479SAnirudh Venkataramanan int ice_vsi_rebuild(struct ice_vsi *vsi) 2233df0f8479SAnirudh Venkataramanan { 2234df0f8479SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 22357eeac889SAkeem G Abodunrin struct ice_vf *vf = NULL; 2236d31530e8SAkeem G Abodunrin enum ice_status status; 2237c5a2a4a3SUsha Ketineni struct ice_pf *pf; 2238df0f8479SAnirudh Venkataramanan int ret, i; 2239df0f8479SAnirudh Venkataramanan 2240df0f8479SAnirudh Venkataramanan if (!vsi) 2241df0f8479SAnirudh Venkataramanan return -EINVAL; 2242df0f8479SAnirudh Venkataramanan 2243c5a2a4a3SUsha Ketineni pf = vsi->back; 22447eeac889SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 22457eeac889SAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 22467eeac889SAkeem G Abodunrin 224747e3e53cSHenry Tieman ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2248df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 22497eeac889SAkeem G Abodunrin 2250cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 2251cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 2252cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 2253cbe66bfeSBrett Creeley * cleared in the same manner. 2254cbe66bfeSBrett Creeley */ 22557eeac889SAkeem G Abodunrin if (vsi->type != ICE_VSI_VF) { 22567eeac889SAkeem G Abodunrin /* reclaim SW interrupts back to the common pool */ 2257cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 22587eeac889SAkeem G Abodunrin pf->num_avail_sw_msix += vsi->num_q_vectors; 2259cbe66bfeSBrett Creeley vsi->base_vector = 0; 22607eeac889SAkeem G Abodunrin } 22617eeac889SAkeem G Abodunrin 226278b5713aSAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2263df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2264a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 2265819d8998SJesse Brandeburg ice_dev_onetime_setup(&pf->hw); 22665743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 22675743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf->vf_id); 22685743020dSAkeem G Abodunrin else 22695743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 227078b5713aSAnirudh Venkataramanan 227178b5713aSAnirudh Venkataramanan ret = ice_vsi_alloc_arrays(vsi); 227278b5713aSAnirudh Venkataramanan if (ret < 0) 227378b5713aSAnirudh Venkataramanan goto err_vsi; 227478b5713aSAnirudh Venkataramanan 227578b5713aSAnirudh Venkataramanan ice_vsi_get_qs(vsi); 2276c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2277df0f8479SAnirudh Venkataramanan 2278df0f8479SAnirudh Venkataramanan /* Initialize VSI struct elements and create VSI in FW */ 2279df0f8479SAnirudh Venkataramanan ret = ice_vsi_init(vsi); 2280df0f8479SAnirudh Venkataramanan if (ret < 0) 2281df0f8479SAnirudh Venkataramanan goto err_vsi; 2282df0f8479SAnirudh Venkataramanan 2283df0f8479SAnirudh Venkataramanan switch (vsi->type) { 2284df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 2285df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 2286df0f8479SAnirudh Venkataramanan if (ret) 2287df0f8479SAnirudh Venkataramanan goto err_rings; 2288df0f8479SAnirudh Venkataramanan 228917bc6d07STony Nguyen ret = ice_vsi_setup_vector_base(vsi); 229017bc6d07STony Nguyen if (ret) 229117bc6d07STony Nguyen goto err_vectors; 229217bc6d07STony Nguyen 2293b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2294b07833a0SBrett Creeley if (ret) 2295b07833a0SBrett Creeley goto err_vectors; 2296b07833a0SBrett Creeley 2297df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 2298df0f8479SAnirudh Venkataramanan if (ret) 2299df0f8479SAnirudh Venkataramanan goto err_vectors; 2300df0f8479SAnirudh Venkataramanan 2301df0f8479SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 230227a98affSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 230327a98affSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 230427a98affSMd Fahad Iqbal Polash * return value 230527a98affSMd Fahad Iqbal Polash */ 2306819d8998SJesse Brandeburg if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 230727a98affSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 2308df0f8479SAnirudh Venkataramanan break; 23098ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 23108ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 23118ede0178SAnirudh Venkataramanan if (ret) 23128ede0178SAnirudh Venkataramanan goto err_rings; 23138ede0178SAnirudh Venkataramanan 2314b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2315b07833a0SBrett Creeley if (ret) 2316b07833a0SBrett Creeley goto err_vectors; 2317b07833a0SBrett Creeley 23188ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 23198ede0178SAnirudh Venkataramanan if (ret) 23208ede0178SAnirudh Venkataramanan goto err_vectors; 23218ede0178SAnirudh Venkataramanan 23228ede0178SAnirudh Venkataramanan break; 2323df0f8479SAnirudh Venkataramanan default: 2324df0f8479SAnirudh Venkataramanan break; 2325df0f8479SAnirudh Venkataramanan } 2326df0f8479SAnirudh Venkataramanan 2327df0f8479SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 2328df0f8479SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2329d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 2330df0f8479SAnirudh Venkataramanan 2331d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 23324fb33f31SAnirudh Venkataramanan max_txqs); 2333d31530e8SAkeem G Abodunrin if (status) { 233420ce2a1aSBrett Creeley dev_err(&pf->pdev->dev, 233520ce2a1aSBrett Creeley "VSI %d failed lan queue config, error %d\n", 2336d31530e8SAkeem G Abodunrin vsi->vsi_num, status); 2337df0f8479SAnirudh Venkataramanan goto err_vectors; 2338df0f8479SAnirudh Venkataramanan } 2339df0f8479SAnirudh Venkataramanan return 0; 2340df0f8479SAnirudh Venkataramanan 2341df0f8479SAnirudh Venkataramanan err_vectors: 2342df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2343df0f8479SAnirudh Venkataramanan err_rings: 2344df0f8479SAnirudh Venkataramanan if (vsi->netdev) { 2345df0f8479SAnirudh Venkataramanan vsi->current_netdev_flags = 0; 2346df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2347df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 2348df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 2349df0f8479SAnirudh Venkataramanan } 2350df0f8479SAnirudh Venkataramanan err_vsi: 2351df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2352819d8998SJesse Brandeburg set_bit(__ICE_RESET_FAILED, pf->state); 2353df0f8479SAnirudh Venkataramanan return ret; 2354df0f8479SAnirudh Venkataramanan } 2355df0f8479SAnirudh Venkataramanan 2356df0f8479SAnirudh Venkataramanan /** 23575df7e45dSDave Ertman * ice_is_reset_in_progress - check for a reset in progress 23582f2da36eSAnirudh Venkataramanan * @state: PF state field 23595153a18eSAnirudh Venkataramanan */ 23605df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state) 23615153a18eSAnirudh Venkataramanan { 23625df7e45dSDave Ertman return test_bit(__ICE_RESET_OICR_RECV, state) || 23635df7e45dSDave Ertman test_bit(__ICE_PFR_REQ, state) || 23645df7e45dSDave Ertman test_bit(__ICE_CORER_REQ, state) || 23655df7e45dSDave Ertman test_bit(__ICE_GLOBR_REQ, state); 23665153a18eSAnirudh Venkataramanan } 23677b9ffc76SAnirudh Venkataramanan 23687b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 23697b9ffc76SAnirudh Venkataramanan /** 23707b9ffc76SAnirudh Venkataramanan * ice_vsi_update_q_map - update our copy of the VSI info with new queue map 23717b9ffc76SAnirudh Venkataramanan * @vsi: VSI being configured 23727b9ffc76SAnirudh Venkataramanan * @ctx: the context buffer returned from AQ VSI update command 23737b9ffc76SAnirudh Venkataramanan */ 23747b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx) 23757b9ffc76SAnirudh Venkataramanan { 23767b9ffc76SAnirudh Venkataramanan vsi->info.mapping_flags = ctx->info.mapping_flags; 23777b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping, 23787b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.q_mapping)); 23797b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping, 23807b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.tc_mapping)); 23817b9ffc76SAnirudh Venkataramanan } 23827b9ffc76SAnirudh Venkataramanan 23837b9ffc76SAnirudh Venkataramanan /** 23847b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map 23857b9ffc76SAnirudh Venkataramanan * @vsi: VSI to be configured 23867b9ffc76SAnirudh Venkataramanan * @ena_tc: TC bitmap 23877b9ffc76SAnirudh Venkataramanan * 23887b9ffc76SAnirudh Venkataramanan * VSI queues expected to be quiesced before calling this function 23897b9ffc76SAnirudh Venkataramanan */ 23907b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) 23917b9ffc76SAnirudh Venkataramanan { 23927b9ffc76SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 23937b9ffc76SAnirudh Venkataramanan struct ice_vsi_ctx *ctx; 23947b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 23957b9ffc76SAnirudh Venkataramanan enum ice_status status; 23967b9ffc76SAnirudh Venkataramanan int i, ret = 0; 23977b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 23987b9ffc76SAnirudh Venkataramanan 23997b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) { 24007b9ffc76SAnirudh Venkataramanan /* build bitmap of enabled TCs */ 24017b9ffc76SAnirudh Venkataramanan if (ena_tc & BIT(i)) 24027b9ffc76SAnirudh Venkataramanan num_tc++; 24037b9ffc76SAnirudh Venkataramanan /* populate max_txqs per TC */ 2404d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 24057b9ffc76SAnirudh Venkataramanan } 24067b9ffc76SAnirudh Venkataramanan 24077b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ena_tc; 24087b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = num_tc; 24097b9ffc76SAnirudh Venkataramanan 24107b9ffc76SAnirudh Venkataramanan ctx = devm_kzalloc(&pf->pdev->dev, sizeof(*ctx), GFP_KERNEL); 24117b9ffc76SAnirudh Venkataramanan if (!ctx) 24127b9ffc76SAnirudh Venkataramanan return -ENOMEM; 24137b9ffc76SAnirudh Venkataramanan 24147b9ffc76SAnirudh Venkataramanan ctx->vf_num = 0; 24157b9ffc76SAnirudh Venkataramanan ctx->info = vsi->info; 24167b9ffc76SAnirudh Venkataramanan 24177b9ffc76SAnirudh Venkataramanan ice_vsi_setup_q_map(vsi, ctx); 24187b9ffc76SAnirudh Venkataramanan 24197b9ffc76SAnirudh Venkataramanan /* must to indicate which section of VSI context are being modified */ 24207b9ffc76SAnirudh Venkataramanan ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 24217b9ffc76SAnirudh Venkataramanan status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL); 24227b9ffc76SAnirudh Venkataramanan if (status) { 24237b9ffc76SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "Failed VSI Update\n"); 24247b9ffc76SAnirudh Venkataramanan ret = -EIO; 24257b9ffc76SAnirudh Venkataramanan goto out; 24267b9ffc76SAnirudh Venkataramanan } 24277b9ffc76SAnirudh Venkataramanan 24287b9ffc76SAnirudh Venkataramanan status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 24297b9ffc76SAnirudh Venkataramanan max_txqs); 24307b9ffc76SAnirudh Venkataramanan 24317b9ffc76SAnirudh Venkataramanan if (status) { 24327b9ffc76SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 24337b9ffc76SAnirudh Venkataramanan "VSI %d failed TC config, error %d\n", 24347b9ffc76SAnirudh Venkataramanan vsi->vsi_num, status); 24357b9ffc76SAnirudh Venkataramanan ret = -EIO; 24367b9ffc76SAnirudh Venkataramanan goto out; 24377b9ffc76SAnirudh Venkataramanan } 24387b9ffc76SAnirudh Venkataramanan ice_vsi_update_q_map(vsi, ctx); 24397b9ffc76SAnirudh Venkataramanan vsi->info.valid_sections = 0; 24407b9ffc76SAnirudh Venkataramanan 24417b9ffc76SAnirudh Venkataramanan ice_vsi_cfg_netdev_tc(vsi, ena_tc); 24427b9ffc76SAnirudh Venkataramanan out: 24437b9ffc76SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, ctx); 24447b9ffc76SAnirudh Venkataramanan return ret; 24457b9ffc76SAnirudh Venkataramanan } 24467b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 2447bbb968e8SAkeem G Abodunrin 2448bbb968e8SAkeem G Abodunrin /** 2449870f805eSLukasz Czapnik * ice_nvm_version_str - format the NVM version strings 2450870f805eSLukasz Czapnik * @hw: ptr to the hardware info 2451870f805eSLukasz Czapnik */ 2452870f805eSLukasz Czapnik char *ice_nvm_version_str(struct ice_hw *hw) 2453870f805eSLukasz Czapnik { 2454870f805eSLukasz Czapnik u8 oem_ver, oem_patch, ver_hi, ver_lo; 2455870f805eSLukasz Czapnik static char buf[ICE_NVM_VER_LEN]; 2456870f805eSLukasz Czapnik u16 oem_build; 2457870f805eSLukasz Czapnik 2458870f805eSLukasz Czapnik ice_get_nvm_version(hw, &oem_ver, &oem_build, &oem_patch, &ver_hi, 2459870f805eSLukasz Czapnik &ver_lo); 2460870f805eSLukasz Czapnik 2461870f805eSLukasz Czapnik snprintf(buf, sizeof(buf), "%x.%02x 0x%x %d.%d.%d", ver_hi, ver_lo, 2462870f805eSLukasz Czapnik hw->nvm.eetrack, oem_ver, oem_build, oem_patch); 2463870f805eSLukasz Czapnik 2464870f805eSLukasz Czapnik return buf; 2465870f805eSLukasz Czapnik } 2466870f805eSLukasz Czapnik 2467870f805eSLukasz Czapnik /** 2468bbb968e8SAkeem G Abodunrin * ice_vsi_cfg_mac_fltr - Add or remove a MAC address filter for a VSI 2469bbb968e8SAkeem G Abodunrin * @vsi: the VSI being configured MAC filter 2470bbb968e8SAkeem G Abodunrin * @macaddr: the MAC address to be added. 2471bbb968e8SAkeem G Abodunrin * @set: Add or delete a MAC filter 2472bbb968e8SAkeem G Abodunrin * 2473bbb968e8SAkeem G Abodunrin * Adds or removes MAC address filter entry for VF VSI 2474bbb968e8SAkeem G Abodunrin */ 2475bbb968e8SAkeem G Abodunrin enum ice_status 2476bbb968e8SAkeem G Abodunrin ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set) 2477bbb968e8SAkeem G Abodunrin { 2478bbb968e8SAkeem G Abodunrin LIST_HEAD(tmp_add_list); 2479bbb968e8SAkeem G Abodunrin enum ice_status status; 2480bbb968e8SAkeem G Abodunrin 2481bbb968e8SAkeem G Abodunrin /* Update MAC filter list to be added or removed for a VSI */ 2482bbb968e8SAkeem G Abodunrin if (ice_add_mac_to_list(vsi, &tmp_add_list, macaddr)) { 2483bbb968e8SAkeem G Abodunrin status = ICE_ERR_NO_MEMORY; 2484bbb968e8SAkeem G Abodunrin goto cfg_mac_fltr_exit; 2485bbb968e8SAkeem G Abodunrin } 2486bbb968e8SAkeem G Abodunrin 2487bbb968e8SAkeem G Abodunrin if (set) 2488bbb968e8SAkeem G Abodunrin status = ice_add_mac(&vsi->back->hw, &tmp_add_list); 2489bbb968e8SAkeem G Abodunrin else 2490bbb968e8SAkeem G Abodunrin status = ice_remove_mac(&vsi->back->hw, &tmp_add_list); 2491bbb968e8SAkeem G Abodunrin 2492bbb968e8SAkeem G Abodunrin cfg_mac_fltr_exit: 2493bbb968e8SAkeem G Abodunrin ice_free_fltr_list(&vsi->back->pdev->dev, &tmp_add_list); 2494bbb968e8SAkeem G Abodunrin return status; 2495bbb968e8SAkeem G Abodunrin } 2496