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" 6c90ed40cSTony Nguyen #include "ice_flow.h" 745d3d428SAnirudh Venkataramanan #include "ice_lib.h" 87b9ffc76SAnirudh Venkataramanan #include "ice_dcb_lib.h" 945d3d428SAnirudh Venkataramanan 1045d3d428SAnirudh Venkataramanan /** 11964674f1SAnirudh Venkataramanan * ice_vsi_type_str - maps VSI type enum to string equivalents 12964674f1SAnirudh Venkataramanan * @type: VSI type enum 13964674f1SAnirudh Venkataramanan */ 14964674f1SAnirudh Venkataramanan const char *ice_vsi_type_str(enum ice_vsi_type type) 15964674f1SAnirudh Venkataramanan { 16964674f1SAnirudh Venkataramanan switch (type) { 17964674f1SAnirudh Venkataramanan case ICE_VSI_PF: 18964674f1SAnirudh Venkataramanan return "ICE_VSI_PF"; 19964674f1SAnirudh Venkataramanan case ICE_VSI_VF: 20964674f1SAnirudh Venkataramanan return "ICE_VSI_VF"; 21964674f1SAnirudh Venkataramanan case ICE_VSI_LB: 22964674f1SAnirudh Venkataramanan return "ICE_VSI_LB"; 23964674f1SAnirudh Venkataramanan default: 24964674f1SAnirudh Venkataramanan return "unknown"; 25964674f1SAnirudh Venkataramanan } 26964674f1SAnirudh Venkataramanan } 27964674f1SAnirudh Venkataramanan 28964674f1SAnirudh Venkataramanan /** 29d02f734cSMaciej Fijalkowski * ice_vsi_ctrl_rx_rings - Start or stop a VSI's Rx rings 30d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 31d02f734cSMaciej Fijalkowski * @ena: start or stop the Rx rings 32d02f734cSMaciej Fijalkowski */ 33d02f734cSMaciej Fijalkowski static int ice_vsi_ctrl_rx_rings(struct ice_vsi *vsi, bool ena) 34d02f734cSMaciej Fijalkowski { 35d02f734cSMaciej Fijalkowski int i, ret = 0; 36d02f734cSMaciej Fijalkowski 37d02f734cSMaciej Fijalkowski for (i = 0; i < vsi->num_rxq; i++) { 38d02f734cSMaciej Fijalkowski ret = ice_vsi_ctrl_rx_ring(vsi, ena, i); 39d02f734cSMaciej Fijalkowski if (ret) 40d02f734cSMaciej Fijalkowski break; 4172adf242SAnirudh Venkataramanan } 4272adf242SAnirudh Venkataramanan 4372adf242SAnirudh Venkataramanan return ret; 4472adf242SAnirudh Venkataramanan } 4572adf242SAnirudh Venkataramanan 4672adf242SAnirudh Venkataramanan /** 4728c2a645SAnirudh Venkataramanan * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI 4828c2a645SAnirudh Venkataramanan * @vsi: VSI pointer 4928c2a645SAnirudh Venkataramanan * 5028c2a645SAnirudh Venkataramanan * On error: returns error code (negative) 5128c2a645SAnirudh Venkataramanan * On success: returns 0 5228c2a645SAnirudh Venkataramanan */ 53a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) 5428c2a645SAnirudh Venkataramanan { 5528c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 564015d11eSBrett Creeley struct device *dev; 574015d11eSBrett Creeley 584015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 5928c2a645SAnirudh Venkataramanan 6028c2a645SAnirudh Venkataramanan /* allocate memory for both Tx and Rx ring pointers */ 614015d11eSBrett Creeley vsi->tx_rings = devm_kcalloc(dev, vsi->alloc_txq, 62c6dfd690SBruce Allan sizeof(*vsi->tx_rings), GFP_KERNEL); 6328c2a645SAnirudh Venkataramanan if (!vsi->tx_rings) 6478b5713aSAnirudh Venkataramanan return -ENOMEM; 6528c2a645SAnirudh Venkataramanan 664015d11eSBrett Creeley vsi->rx_rings = devm_kcalloc(dev, vsi->alloc_rxq, 67c6dfd690SBruce Allan sizeof(*vsi->rx_rings), GFP_KERNEL); 6828c2a645SAnirudh Venkataramanan if (!vsi->rx_rings) 6978b5713aSAnirudh Venkataramanan goto err_rings; 7078b5713aSAnirudh Venkataramanan 71efc2214bSMaciej Fijalkowski /* XDP will have vsi->alloc_txq Tx queues as well, so double the size */ 724015d11eSBrett Creeley vsi->txq_map = devm_kcalloc(dev, (2 * vsi->alloc_txq), 7378b5713aSAnirudh Venkataramanan sizeof(*vsi->txq_map), GFP_KERNEL); 7478b5713aSAnirudh Venkataramanan 7578b5713aSAnirudh Venkataramanan if (!vsi->txq_map) 7678b5713aSAnirudh Venkataramanan goto err_txq_map; 7778b5713aSAnirudh Venkataramanan 784015d11eSBrett Creeley vsi->rxq_map = devm_kcalloc(dev, vsi->alloc_rxq, 7978b5713aSAnirudh Venkataramanan sizeof(*vsi->rxq_map), GFP_KERNEL); 8078b5713aSAnirudh Venkataramanan if (!vsi->rxq_map) 8178b5713aSAnirudh Venkataramanan goto err_rxq_map; 8278b5713aSAnirudh Venkataramanan 830e674aebSAnirudh Venkataramanan /* There is no need to allocate q_vectors for a loopback VSI. */ 840e674aebSAnirudh Venkataramanan if (vsi->type == ICE_VSI_LB) 850e674aebSAnirudh Venkataramanan return 0; 860e674aebSAnirudh Venkataramanan 8728c2a645SAnirudh Venkataramanan /* allocate memory for q_vector pointers */ 884015d11eSBrett Creeley vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors, 89a85a3847SBrett Creeley sizeof(*vsi->q_vectors), GFP_KERNEL); 9028c2a645SAnirudh Venkataramanan if (!vsi->q_vectors) 9128c2a645SAnirudh Venkataramanan goto err_vectors; 9228c2a645SAnirudh Venkataramanan 9328c2a645SAnirudh Venkataramanan return 0; 9428c2a645SAnirudh Venkataramanan 9528c2a645SAnirudh Venkataramanan err_vectors: 964015d11eSBrett Creeley devm_kfree(dev, vsi->rxq_map); 9778b5713aSAnirudh Venkataramanan err_rxq_map: 984015d11eSBrett Creeley devm_kfree(dev, vsi->txq_map); 9978b5713aSAnirudh Venkataramanan err_txq_map: 1004015d11eSBrett Creeley devm_kfree(dev, vsi->rx_rings); 10178b5713aSAnirudh Venkataramanan err_rings: 1024015d11eSBrett Creeley devm_kfree(dev, vsi->tx_rings); 10328c2a645SAnirudh Venkataramanan return -ENOMEM; 10428c2a645SAnirudh Venkataramanan } 10528c2a645SAnirudh Venkataramanan 10628c2a645SAnirudh Venkataramanan /** 107ad71b256SBrett Creeley * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI 108ad71b256SBrett Creeley * @vsi: the VSI being configured 109ad71b256SBrett Creeley */ 110ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi) 111ad71b256SBrett Creeley { 112ad71b256SBrett Creeley switch (vsi->type) { 113ad71b256SBrett Creeley case ICE_VSI_PF: 1140e674aebSAnirudh Venkataramanan /* fall through */ 1150e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 116ad71b256SBrett Creeley vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC; 117ad71b256SBrett Creeley vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC; 118ad71b256SBrett Creeley break; 119ad71b256SBrett Creeley default: 12019cce2c6SAnirudh Venkataramanan dev_dbg(ice_pf_to_dev(vsi->back), "Not setting number of Tx/Rx descriptors for VSI type %d\n", 121ad71b256SBrett Creeley vsi->type); 122ad71b256SBrett Creeley break; 123ad71b256SBrett Creeley } 124ad71b256SBrett Creeley } 125ad71b256SBrett Creeley 126ad71b256SBrett Creeley /** 127ad71b256SBrett Creeley * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI 12828c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 129f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 13028c2a645SAnirudh Venkataramanan * 13128c2a645SAnirudh Venkataramanan * Return 0 on success and a negative value on error 13228c2a645SAnirudh Venkataramanan */ 1335743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) 13428c2a645SAnirudh Venkataramanan { 13528c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1365743020dSAkeem G Abodunrin struct ice_vf *vf = NULL; 1375743020dSAkeem G Abodunrin 1385743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 1395743020dSAkeem G Abodunrin vsi->vf_id = vf_id; 1405743020dSAkeem G Abodunrin 14128c2a645SAnirudh Venkataramanan switch (vsi->type) { 14228c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 1438c243700SAnirudh Venkataramanan vsi->alloc_txq = min_t(int, ice_get_avail_txq_count(pf), 1448c243700SAnirudh Venkataramanan num_online_cpus()); 14587324e74SHenry Tieman if (vsi->req_txq) { 14687324e74SHenry Tieman vsi->alloc_txq = vsi->req_txq; 14787324e74SHenry Tieman vsi->num_txq = vsi->req_txq; 14887324e74SHenry Tieman } 1498c243700SAnirudh Venkataramanan 1508c243700SAnirudh Venkataramanan pf->num_lan_tx = vsi->alloc_txq; 1518c243700SAnirudh Venkataramanan 1528c243700SAnirudh Venkataramanan /* only 1 Rx queue unless RSS is enabled */ 15387324e74SHenry Tieman if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 1548c243700SAnirudh Venkataramanan vsi->alloc_rxq = 1; 15587324e74SHenry Tieman } else { 1568c243700SAnirudh Venkataramanan vsi->alloc_rxq = min_t(int, ice_get_avail_rxq_count(pf), 1578c243700SAnirudh Venkataramanan num_online_cpus()); 15887324e74SHenry Tieman if (vsi->req_rxq) { 15987324e74SHenry Tieman vsi->alloc_rxq = vsi->req_rxq; 16087324e74SHenry Tieman vsi->num_rxq = vsi->req_rxq; 16187324e74SHenry Tieman } 16287324e74SHenry Tieman } 1638c243700SAnirudh Venkataramanan 1648c243700SAnirudh Venkataramanan pf->num_lan_rx = vsi->alloc_rxq; 1658c243700SAnirudh Venkataramanan 16634cdcb16SBrett Creeley vsi->num_q_vectors = max_t(int, vsi->alloc_rxq, vsi->alloc_txq); 16728c2a645SAnirudh Venkataramanan break; 1688ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 1695743020dSAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 1705743020dSAkeem G Abodunrin vsi->alloc_txq = vf->num_vf_qs; 1715743020dSAkeem G Abodunrin vsi->alloc_rxq = vf->num_vf_qs; 1728ede0178SAnirudh Venkataramanan /* pf->num_vf_msix includes (VF miscellaneous vector + 1738ede0178SAnirudh Venkataramanan * data queue interrupts). Since vsi->num_q_vectors is number 174047e52c0SAnirudh Venkataramanan * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the 175047e52c0SAnirudh Venkataramanan * original vector count 1768ede0178SAnirudh Venkataramanan */ 177047e52c0SAnirudh Venkataramanan vsi->num_q_vectors = pf->num_vf_msix - ICE_NONQ_VECS_VF; 1788ede0178SAnirudh Venkataramanan break; 1790e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 1800e674aebSAnirudh Venkataramanan vsi->alloc_txq = 1; 1810e674aebSAnirudh Venkataramanan vsi->alloc_rxq = 1; 1820e674aebSAnirudh Venkataramanan break; 18328c2a645SAnirudh Venkataramanan default: 1844015d11eSBrett Creeley dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi->type); 18528c2a645SAnirudh Venkataramanan break; 18628c2a645SAnirudh Venkataramanan } 187ad71b256SBrett Creeley 188ad71b256SBrett Creeley ice_vsi_set_num_desc(vsi); 18928c2a645SAnirudh Venkataramanan } 19028c2a645SAnirudh Venkataramanan 19128c2a645SAnirudh Venkataramanan /** 19228c2a645SAnirudh Venkataramanan * ice_get_free_slot - get the next non-NULL location index in array 19328c2a645SAnirudh Venkataramanan * @array: array to search 19428c2a645SAnirudh Venkataramanan * @size: size of the array 19528c2a645SAnirudh Venkataramanan * @curr: last known occupied index to be used as a search hint 19628c2a645SAnirudh Venkataramanan * 19728c2a645SAnirudh Venkataramanan * void * is being used to keep the functionality generic. This lets us use this 19828c2a645SAnirudh Venkataramanan * function on any array of pointers. 19928c2a645SAnirudh Venkataramanan */ 20037bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr) 20128c2a645SAnirudh Venkataramanan { 20228c2a645SAnirudh Venkataramanan int **tmp_array = (int **)array; 20328c2a645SAnirudh Venkataramanan int next; 20428c2a645SAnirudh Venkataramanan 20528c2a645SAnirudh Venkataramanan if (curr < (size - 1) && !tmp_array[curr + 1]) { 20628c2a645SAnirudh Venkataramanan next = curr + 1; 20728c2a645SAnirudh Venkataramanan } else { 20828c2a645SAnirudh Venkataramanan int i = 0; 20928c2a645SAnirudh Venkataramanan 21028c2a645SAnirudh Venkataramanan while ((i < size) && (tmp_array[i])) 21128c2a645SAnirudh Venkataramanan i++; 21228c2a645SAnirudh Venkataramanan if (i == size) 21328c2a645SAnirudh Venkataramanan next = ICE_NO_VSI; 21428c2a645SAnirudh Venkataramanan else 21528c2a645SAnirudh Venkataramanan next = i; 21628c2a645SAnirudh Venkataramanan } 21728c2a645SAnirudh Venkataramanan return next; 21828c2a645SAnirudh Venkataramanan } 21928c2a645SAnirudh Venkataramanan 22028c2a645SAnirudh Venkataramanan /** 2215153a18eSAnirudh Venkataramanan * ice_vsi_delete - delete a VSI from the switch 2225153a18eSAnirudh Venkataramanan * @vsi: pointer to VSI being removed 2235153a18eSAnirudh Venkataramanan */ 2245153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi) 2255153a18eSAnirudh Venkataramanan { 2265153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 227198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 2285153a18eSAnirudh Venkataramanan enum ice_status status; 2295153a18eSAnirudh Venkataramanan 2309efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 231198a666aSBruce Allan if (!ctxt) 232198a666aSBruce Allan return; 233198a666aSBruce Allan 2348ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 235198a666aSBruce Allan ctxt->vf_num = vsi->vf_id; 236198a666aSBruce Allan ctxt->vsi_num = vsi->vsi_num; 2375153a18eSAnirudh Venkataramanan 238198a666aSBruce Allan memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); 2395153a18eSAnirudh Venkataramanan 240198a666aSBruce Allan status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); 2415153a18eSAnirudh Venkataramanan if (status) 2424015d11eSBrett Creeley dev_err(ice_pf_to_dev(pf), "Failed to delete VSI %i in FW - error: %d\n", 2434015d11eSBrett Creeley vsi->vsi_num, status); 244198a666aSBruce Allan 2459efe35d0STony Nguyen kfree(ctxt); 2465153a18eSAnirudh Venkataramanan } 2475153a18eSAnirudh Venkataramanan 2485153a18eSAnirudh Venkataramanan /** 249a85a3847SBrett Creeley * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI 25007309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 25107309a0eSAnirudh Venkataramanan */ 252a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi) 25307309a0eSAnirudh Venkataramanan { 25407309a0eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2554015d11eSBrett Creeley struct device *dev; 2564015d11eSBrett Creeley 2574015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 25807309a0eSAnirudh Venkataramanan 25907309a0eSAnirudh Venkataramanan /* free the ring and vector containers */ 260a85a3847SBrett Creeley if (vsi->q_vectors) { 2614015d11eSBrett Creeley devm_kfree(dev, vsi->q_vectors); 26207309a0eSAnirudh Venkataramanan vsi->q_vectors = NULL; 26307309a0eSAnirudh Venkataramanan } 26407309a0eSAnirudh Venkataramanan if (vsi->tx_rings) { 2654015d11eSBrett Creeley devm_kfree(dev, vsi->tx_rings); 26607309a0eSAnirudh Venkataramanan vsi->tx_rings = NULL; 26707309a0eSAnirudh Venkataramanan } 26807309a0eSAnirudh Venkataramanan if (vsi->rx_rings) { 2694015d11eSBrett Creeley devm_kfree(dev, vsi->rx_rings); 27007309a0eSAnirudh Venkataramanan vsi->rx_rings = NULL; 27107309a0eSAnirudh Venkataramanan } 27278b5713aSAnirudh Venkataramanan if (vsi->txq_map) { 2734015d11eSBrett Creeley devm_kfree(dev, vsi->txq_map); 27478b5713aSAnirudh Venkataramanan vsi->txq_map = NULL; 27578b5713aSAnirudh Venkataramanan } 27678b5713aSAnirudh Venkataramanan if (vsi->rxq_map) { 2774015d11eSBrett Creeley devm_kfree(dev, vsi->rxq_map); 27878b5713aSAnirudh Venkataramanan vsi->rxq_map = NULL; 27978b5713aSAnirudh Venkataramanan } 28007309a0eSAnirudh Venkataramanan } 28107309a0eSAnirudh Venkataramanan 28207309a0eSAnirudh Venkataramanan /** 28307309a0eSAnirudh Venkataramanan * ice_vsi_clear - clean up and deallocate the provided VSI 28407309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 28507309a0eSAnirudh Venkataramanan * 28607309a0eSAnirudh Venkataramanan * This deallocates the VSI's queue resources, removes it from the PF's 28707309a0eSAnirudh Venkataramanan * VSI array if necessary, and deallocates the VSI 28807309a0eSAnirudh Venkataramanan * 28907309a0eSAnirudh Venkataramanan * Returns 0 on success, negative on failure 29007309a0eSAnirudh Venkataramanan */ 29107309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi) 29207309a0eSAnirudh Venkataramanan { 29307309a0eSAnirudh Venkataramanan struct ice_pf *pf = NULL; 2944015d11eSBrett Creeley struct device *dev; 29507309a0eSAnirudh Venkataramanan 29607309a0eSAnirudh Venkataramanan if (!vsi) 29707309a0eSAnirudh Venkataramanan return 0; 29807309a0eSAnirudh Venkataramanan 29907309a0eSAnirudh Venkataramanan if (!vsi->back) 30007309a0eSAnirudh Venkataramanan return -EINVAL; 30107309a0eSAnirudh Venkataramanan 30207309a0eSAnirudh Venkataramanan pf = vsi->back; 3034015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 30407309a0eSAnirudh Venkataramanan 30507309a0eSAnirudh Venkataramanan if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) { 3064015d11eSBrett Creeley dev_dbg(dev, "vsi does not exist at pf->vsi[%d]\n", vsi->idx); 30707309a0eSAnirudh Venkataramanan return -EINVAL; 30807309a0eSAnirudh Venkataramanan } 30907309a0eSAnirudh Venkataramanan 31007309a0eSAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 31107309a0eSAnirudh Venkataramanan /* updates the PF for this cleared VSI */ 31207309a0eSAnirudh Venkataramanan 31307309a0eSAnirudh Venkataramanan pf->vsi[vsi->idx] = NULL; 31407309a0eSAnirudh Venkataramanan if (vsi->idx < pf->next_vsi) 31507309a0eSAnirudh Venkataramanan pf->next_vsi = vsi->idx; 31607309a0eSAnirudh Venkataramanan 317a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 31807309a0eSAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 3194015d11eSBrett Creeley devm_kfree(dev, vsi); 32007309a0eSAnirudh Venkataramanan 32107309a0eSAnirudh Venkataramanan return 0; 32207309a0eSAnirudh Venkataramanan } 32307309a0eSAnirudh Venkataramanan 32407309a0eSAnirudh Venkataramanan /** 3255153a18eSAnirudh Venkataramanan * ice_msix_clean_rings - MSIX mode Interrupt Handler 3265153a18eSAnirudh Venkataramanan * @irq: interrupt number 3275153a18eSAnirudh Venkataramanan * @data: pointer to a q_vector 3285153a18eSAnirudh Venkataramanan */ 329f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data) 3305153a18eSAnirudh Venkataramanan { 3315153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 3325153a18eSAnirudh Venkataramanan 3335153a18eSAnirudh Venkataramanan if (!q_vector->tx.ring && !q_vector->rx.ring) 3345153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 3355153a18eSAnirudh Venkataramanan 3365153a18eSAnirudh Venkataramanan napi_schedule(&q_vector->napi); 3375153a18eSAnirudh Venkataramanan 3385153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 3395153a18eSAnirudh Venkataramanan } 3405153a18eSAnirudh Venkataramanan 3415153a18eSAnirudh Venkataramanan /** 34237bb8390SAnirudh Venkataramanan * ice_vsi_alloc - Allocates the next available struct VSI in the PF 34337bb8390SAnirudh Venkataramanan * @pf: board private structure 34437bb8390SAnirudh Venkataramanan * @type: type of VSI 345f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 34637bb8390SAnirudh Venkataramanan * 34737bb8390SAnirudh Venkataramanan * returns a pointer to a VSI on success, NULL on failure. 34837bb8390SAnirudh Venkataramanan */ 3495743020dSAkeem G Abodunrin static struct ice_vsi * 3505743020dSAkeem G Abodunrin ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type type, u16 vf_id) 35137bb8390SAnirudh Venkataramanan { 3524015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 35337bb8390SAnirudh Venkataramanan struct ice_vsi *vsi = NULL; 35437bb8390SAnirudh Venkataramanan 35537bb8390SAnirudh Venkataramanan /* Need to protect the allocation of the VSIs at the PF level */ 35637bb8390SAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 35737bb8390SAnirudh Venkataramanan 35837bb8390SAnirudh Venkataramanan /* If we have already allocated our maximum number of VSIs, 35937bb8390SAnirudh Venkataramanan * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index 36037bb8390SAnirudh Venkataramanan * is available to be populated 36137bb8390SAnirudh Venkataramanan */ 36237bb8390SAnirudh Venkataramanan if (pf->next_vsi == ICE_NO_VSI) { 3634015d11eSBrett Creeley dev_dbg(dev, "out of VSI slots!\n"); 36437bb8390SAnirudh Venkataramanan goto unlock_pf; 36537bb8390SAnirudh Venkataramanan } 36637bb8390SAnirudh Venkataramanan 3674015d11eSBrett Creeley vsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL); 36837bb8390SAnirudh Venkataramanan if (!vsi) 36937bb8390SAnirudh Venkataramanan goto unlock_pf; 37037bb8390SAnirudh Venkataramanan 37137bb8390SAnirudh Venkataramanan vsi->type = type; 37237bb8390SAnirudh Venkataramanan vsi->back = pf; 37337bb8390SAnirudh Venkataramanan set_bit(__ICE_DOWN, vsi->state); 3749d56b7fdSJesse Brandeburg 37537bb8390SAnirudh Venkataramanan vsi->idx = pf->next_vsi; 37637bb8390SAnirudh Venkataramanan 3775743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 3785743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf_id); 3795743020dSAkeem G Abodunrin else 3805743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 38137bb8390SAnirudh Venkataramanan 38237bb8390SAnirudh Venkataramanan switch (vsi->type) { 38337bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 384a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 38537bb8390SAnirudh Venkataramanan goto err_rings; 38637bb8390SAnirudh Venkataramanan 38737bb8390SAnirudh Venkataramanan /* Setup default MSIX irq handler for VSI */ 38837bb8390SAnirudh Venkataramanan vsi->irq_handler = ice_msix_clean_rings; 38937bb8390SAnirudh Venkataramanan break; 3908ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 391a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 3928ede0178SAnirudh Venkataramanan goto err_rings; 3938ede0178SAnirudh Venkataramanan break; 3940e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 3950e674aebSAnirudh Venkataramanan if (ice_vsi_alloc_arrays(vsi)) 3960e674aebSAnirudh Venkataramanan goto err_rings; 3970e674aebSAnirudh Venkataramanan break; 39837bb8390SAnirudh Venkataramanan default: 3994015d11eSBrett Creeley dev_warn(dev, "Unknown VSI type %d\n", vsi->type); 40037bb8390SAnirudh Venkataramanan goto unlock_pf; 40137bb8390SAnirudh Venkataramanan } 40237bb8390SAnirudh Venkataramanan 40337bb8390SAnirudh Venkataramanan /* fill VSI slot in the PF struct */ 40437bb8390SAnirudh Venkataramanan pf->vsi[pf->next_vsi] = vsi; 40537bb8390SAnirudh Venkataramanan 40637bb8390SAnirudh Venkataramanan /* prepare pf->next_vsi for next use */ 40737bb8390SAnirudh Venkataramanan pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi, 40837bb8390SAnirudh Venkataramanan pf->next_vsi); 40937bb8390SAnirudh Venkataramanan goto unlock_pf; 41037bb8390SAnirudh Venkataramanan 41137bb8390SAnirudh Venkataramanan err_rings: 4124015d11eSBrett Creeley devm_kfree(dev, vsi); 41337bb8390SAnirudh Venkataramanan vsi = NULL; 41437bb8390SAnirudh Venkataramanan unlock_pf: 41537bb8390SAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 41637bb8390SAnirudh Venkataramanan return vsi; 41737bb8390SAnirudh Venkataramanan } 41837bb8390SAnirudh Venkataramanan 41937bb8390SAnirudh Venkataramanan /** 420df0f8479SAnirudh Venkataramanan * ice_vsi_get_qs - Assign queues from PF to VSI 421df0f8479SAnirudh Venkataramanan * @vsi: the VSI to assign queues to 422df0f8479SAnirudh Venkataramanan * 423df0f8479SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 424df0f8479SAnirudh Venkataramanan */ 42537bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi) 426df0f8479SAnirudh Venkataramanan { 42703f7a986SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 42803f7a986SAnirudh Venkataramanan struct ice_qs_cfg tx_qs_cfg = { 42903f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 43003f7a986SAnirudh Venkataramanan .pf_map = pf->avail_txqs, 43178b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_txqs, 43203f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_txq, 43303f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_TXQS, 43403f7a986SAnirudh Venkataramanan .vsi_map = vsi->txq_map, 43503f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 43603f7a986SAnirudh Venkataramanan .mapping_mode = vsi->tx_mapping_mode 43703f7a986SAnirudh Venkataramanan }; 43803f7a986SAnirudh Venkataramanan struct ice_qs_cfg rx_qs_cfg = { 43903f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 44003f7a986SAnirudh Venkataramanan .pf_map = pf->avail_rxqs, 44178b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_rxqs, 44203f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_rxq, 44303f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_RXQS, 44403f7a986SAnirudh Venkataramanan .vsi_map = vsi->rxq_map, 44503f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 44603f7a986SAnirudh Venkataramanan .mapping_mode = vsi->rx_mapping_mode 44703f7a986SAnirudh Venkataramanan }; 448df0f8479SAnirudh Venkataramanan int ret = 0; 449df0f8479SAnirudh Venkataramanan 450df0f8479SAnirudh Venkataramanan vsi->tx_mapping_mode = ICE_VSI_MAP_CONTIG; 451df0f8479SAnirudh Venkataramanan vsi->rx_mapping_mode = ICE_VSI_MAP_CONTIG; 452df0f8479SAnirudh Venkataramanan 45303f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&tx_qs_cfg); 45403f7a986SAnirudh Venkataramanan if (!ret) 45503f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&rx_qs_cfg); 456df0f8479SAnirudh Venkataramanan 457df0f8479SAnirudh Venkataramanan return ret; 458df0f8479SAnirudh Venkataramanan } 459df0f8479SAnirudh Venkataramanan 460df0f8479SAnirudh Venkataramanan /** 4615153a18eSAnirudh Venkataramanan * ice_vsi_put_qs - Release queues from VSI to PF 4625153a18eSAnirudh Venkataramanan * @vsi: the VSI that is going to release queues 4635153a18eSAnirudh Venkataramanan */ 4645153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi) 4655153a18eSAnirudh Venkataramanan { 4665153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 4675153a18eSAnirudh Venkataramanan int i; 4685153a18eSAnirudh Venkataramanan 4695153a18eSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 4705153a18eSAnirudh Venkataramanan 4715153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 4725153a18eSAnirudh Venkataramanan clear_bit(vsi->txq_map[i], pf->avail_txqs); 4735153a18eSAnirudh Venkataramanan vsi->txq_map[i] = ICE_INVAL_Q_INDEX; 4745153a18eSAnirudh Venkataramanan } 4755153a18eSAnirudh Venkataramanan 4765153a18eSAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 4775153a18eSAnirudh Venkataramanan clear_bit(vsi->rxq_map[i], pf->avail_rxqs); 4785153a18eSAnirudh Venkataramanan vsi->rxq_map[i] = ICE_INVAL_Q_INDEX; 4795153a18eSAnirudh Venkataramanan } 4805153a18eSAnirudh Venkataramanan 4815153a18eSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 4825153a18eSAnirudh Venkataramanan } 4835153a18eSAnirudh Venkataramanan 4845153a18eSAnirudh Venkataramanan /** 485462acf6aSTony Nguyen * ice_is_safe_mode 486462acf6aSTony Nguyen * @pf: pointer to the PF struct 487462acf6aSTony Nguyen * 488462acf6aSTony Nguyen * returns true if driver is in safe mode, false otherwise 489462acf6aSTony Nguyen */ 490462acf6aSTony Nguyen bool ice_is_safe_mode(struct ice_pf *pf) 491462acf6aSTony Nguyen { 492462acf6aSTony Nguyen return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags); 493462acf6aSTony Nguyen } 494462acf6aSTony Nguyen 495462acf6aSTony Nguyen /** 4962c61054cSTony Nguyen * ice_vsi_clean_rss_flow_fld - Delete RSS configuration 4972c61054cSTony Nguyen * @vsi: the VSI being cleaned up 4982c61054cSTony Nguyen * 4992c61054cSTony Nguyen * This function deletes RSS input set for all flows that were configured 5002c61054cSTony Nguyen * for this VSI 5012c61054cSTony Nguyen */ 5022c61054cSTony Nguyen static void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi) 5032c61054cSTony Nguyen { 5042c61054cSTony Nguyen struct ice_pf *pf = vsi->back; 5052c61054cSTony Nguyen enum ice_status status; 5062c61054cSTony Nguyen 5072c61054cSTony Nguyen if (ice_is_safe_mode(pf)) 5082c61054cSTony Nguyen return; 5092c61054cSTony Nguyen 5102c61054cSTony Nguyen status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx); 5112c61054cSTony Nguyen if (status) 5122c61054cSTony Nguyen dev_dbg(ice_pf_to_dev(pf), "ice_rem_vsi_rss_cfg failed for vsi = %d, error = %d\n", 5132c61054cSTony Nguyen vsi->vsi_num, status); 5142c61054cSTony Nguyen } 5152c61054cSTony Nguyen 5162c61054cSTony Nguyen /** 5172c61054cSTony Nguyen * ice_rss_clean - Delete RSS related VSI structures and configuration 518df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 519df0f8479SAnirudh Venkataramanan */ 520df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi) 521df0f8479SAnirudh Venkataramanan { 5224015d11eSBrett Creeley struct ice_pf *pf = vsi->back; 5234015d11eSBrett Creeley struct device *dev; 524df0f8479SAnirudh Venkataramanan 5254015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 526df0f8479SAnirudh Venkataramanan 527df0f8479SAnirudh Venkataramanan if (vsi->rss_hkey_user) 5284015d11eSBrett Creeley devm_kfree(dev, vsi->rss_hkey_user); 529df0f8479SAnirudh Venkataramanan if (vsi->rss_lut_user) 5304015d11eSBrett Creeley devm_kfree(dev, vsi->rss_lut_user); 5312c61054cSTony Nguyen 5322c61054cSTony Nguyen ice_vsi_clean_rss_flow_fld(vsi); 5332c61054cSTony Nguyen /* remove RSS replay list */ 5342c61054cSTony Nguyen if (!ice_is_safe_mode(pf)) 5352c61054cSTony Nguyen ice_rem_vsi_rss_list(&pf->hw, vsi->idx); 536df0f8479SAnirudh Venkataramanan } 537df0f8479SAnirudh Venkataramanan 538df0f8479SAnirudh Venkataramanan /** 53928c2a645SAnirudh Venkataramanan * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type 54028c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 54128c2a645SAnirudh Venkataramanan */ 54237bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi) 54328c2a645SAnirudh Venkataramanan { 54428c2a645SAnirudh Venkataramanan struct ice_hw_common_caps *cap; 54528c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 54628c2a645SAnirudh Venkataramanan 54728c2a645SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 54828c2a645SAnirudh Venkataramanan vsi->rss_size = 1; 54928c2a645SAnirudh Venkataramanan return; 55028c2a645SAnirudh Venkataramanan } 55128c2a645SAnirudh Venkataramanan 55228c2a645SAnirudh Venkataramanan cap = &pf->hw.func_caps.common_cap; 55328c2a645SAnirudh Venkataramanan switch (vsi->type) { 55428c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 55528c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 55628c2a645SAnirudh Venkataramanan vsi->rss_table_size = cap->rss_table_size; 55728c2a645SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 55828c2a645SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 55928c2a645SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; 56028c2a645SAnirudh Venkataramanan break; 5618ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 5628ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table 5638ede0178SAnirudh Venkataramanan * For VSI_LUT, LUT size should be set to 64 bytes 5648ede0178SAnirudh Venkataramanan */ 5658ede0178SAnirudh Venkataramanan vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 5668ede0178SAnirudh Venkataramanan vsi->rss_size = min_t(int, num_online_cpus(), 5678ede0178SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 5688ede0178SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 5698ede0178SAnirudh Venkataramanan break; 5700e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 5710e674aebSAnirudh Venkataramanan break; 57228c2a645SAnirudh Venkataramanan default: 5734015d11eSBrett Creeley dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", 57428c2a645SAnirudh Venkataramanan vsi->type); 57528c2a645SAnirudh Venkataramanan break; 57628c2a645SAnirudh Venkataramanan } 57728c2a645SAnirudh Venkataramanan } 57828c2a645SAnirudh Venkataramanan 57928c2a645SAnirudh Venkataramanan /** 58028c2a645SAnirudh Venkataramanan * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI 58128c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 58228c2a645SAnirudh Venkataramanan * 58328c2a645SAnirudh Venkataramanan * This initializes a default VSI context for all sections except the Queues. 58428c2a645SAnirudh Venkataramanan */ 58528c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) 58628c2a645SAnirudh Venkataramanan { 58728c2a645SAnirudh Venkataramanan u32 table = 0; 58828c2a645SAnirudh Venkataramanan 58928c2a645SAnirudh Venkataramanan memset(&ctxt->info, 0, sizeof(ctxt->info)); 59028c2a645SAnirudh Venkataramanan /* VSI's should be allocated from shared pool */ 59128c2a645SAnirudh Venkataramanan ctxt->alloc_from_pool = true; 59228c2a645SAnirudh Venkataramanan /* Src pruning enabled by default */ 59328c2a645SAnirudh Venkataramanan ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; 59428c2a645SAnirudh Venkataramanan /* Traffic from VSI can be sent to LAN */ 59528c2a645SAnirudh Venkataramanan ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; 59628c2a645SAnirudh Venkataramanan /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy 59728c2a645SAnirudh Venkataramanan * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all 59828c2a645SAnirudh Venkataramanan * packets untagged/tagged. 59928c2a645SAnirudh Venkataramanan */ 60028c2a645SAnirudh Venkataramanan ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & 60128c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_M) >> 60228c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_S); 60328c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for both ingress/egress tables */ 60428c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(0, 0); 60528c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(1, 1); 60628c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(2, 2); 60728c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(3, 3); 60828c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(4, 4); 60928c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(5, 5); 61028c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(6, 6); 61128c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(7, 7); 61228c2a645SAnirudh Venkataramanan ctxt->info.ingress_table = cpu_to_le32(table); 61328c2a645SAnirudh Venkataramanan ctxt->info.egress_table = cpu_to_le32(table); 61428c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for outer to inner UP table */ 61528c2a645SAnirudh Venkataramanan ctxt->info.outer_up_table = cpu_to_le32(table); 61628c2a645SAnirudh Venkataramanan /* No Outer tag support outer_tag_flags remains to zero */ 61728c2a645SAnirudh Venkataramanan } 61828c2a645SAnirudh Venkataramanan 61928c2a645SAnirudh Venkataramanan /** 62028c2a645SAnirudh Venkataramanan * ice_vsi_setup_q_map - Setup a VSI queue map 62128c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 62228c2a645SAnirudh Venkataramanan * @ctxt: VSI context structure 62328c2a645SAnirudh Venkataramanan */ 62428c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 62528c2a645SAnirudh Venkataramanan { 626c5a2a4a3SUsha Ketineni u16 offset = 0, qmap = 0, tx_count = 0; 62728c2a645SAnirudh Venkataramanan u16 qcount_tx = vsi->alloc_txq; 62828c2a645SAnirudh Venkataramanan u16 qcount_rx = vsi->alloc_rxq; 629c5a2a4a3SUsha Ketineni u16 tx_numq_tc, rx_numq_tc; 630c5a2a4a3SUsha Ketineni u16 pow = 0, max_rss = 0; 63128c2a645SAnirudh Venkataramanan bool ena_tc0 = false; 632c5a2a4a3SUsha Ketineni u8 netdev_tc = 0; 63328c2a645SAnirudh Venkataramanan int i; 63428c2a645SAnirudh Venkataramanan 63528c2a645SAnirudh Venkataramanan /* at least TC0 should be enabled by default */ 63628c2a645SAnirudh Venkataramanan if (vsi->tc_cfg.numtc) { 63728c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(0))) 63828c2a645SAnirudh Venkataramanan ena_tc0 = true; 63928c2a645SAnirudh Venkataramanan } else { 64028c2a645SAnirudh Venkataramanan ena_tc0 = true; 64128c2a645SAnirudh Venkataramanan } 64228c2a645SAnirudh Venkataramanan 64328c2a645SAnirudh Venkataramanan if (ena_tc0) { 64428c2a645SAnirudh Venkataramanan vsi->tc_cfg.numtc++; 64528c2a645SAnirudh Venkataramanan vsi->tc_cfg.ena_tc |= 1; 64628c2a645SAnirudh Venkataramanan } 64728c2a645SAnirudh Venkataramanan 648c5a2a4a3SUsha Ketineni rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc; 649c5a2a4a3SUsha Ketineni if (!rx_numq_tc) 650c5a2a4a3SUsha Ketineni rx_numq_tc = 1; 651c5a2a4a3SUsha Ketineni tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc; 652c5a2a4a3SUsha Ketineni if (!tx_numq_tc) 653c5a2a4a3SUsha Ketineni tx_numq_tc = 1; 65428c2a645SAnirudh Venkataramanan 65528c2a645SAnirudh Venkataramanan /* TC mapping is a function of the number of Rx queues assigned to the 65628c2a645SAnirudh Venkataramanan * VSI for each traffic class and the offset of these queues. 65728c2a645SAnirudh Venkataramanan * The first 10 bits are for queue offset for TC0, next 4 bits for no:of 65828c2a645SAnirudh Venkataramanan * queues allocated to TC0. No:of queues is a power-of-2. 65928c2a645SAnirudh Venkataramanan * 66028c2a645SAnirudh Venkataramanan * If TC is not enabled, the queue offset is set to 0, and allocate one 66128c2a645SAnirudh Venkataramanan * queue, this way, traffic for the given TC will be sent to the default 66228c2a645SAnirudh Venkataramanan * queue. 66328c2a645SAnirudh Venkataramanan * 66428c2a645SAnirudh Venkataramanan * Setup number and offset of Rx queues for all TCs for the VSI 66528c2a645SAnirudh Venkataramanan */ 66628c2a645SAnirudh Venkataramanan 667c5a2a4a3SUsha Ketineni qcount_rx = rx_numq_tc; 668c5a2a4a3SUsha Ketineni 66928c2a645SAnirudh Venkataramanan /* qcount will change if RSS is enabled */ 67028c2a645SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) { 6718ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) { 67228c2a645SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF) 67328c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_LG_RSS_QS; 67428c2a645SAnirudh Venkataramanan else 67528c2a645SAnirudh Venkataramanan max_rss = ICE_MAX_SMALL_RSS_QS; 676c5a2a4a3SUsha Ketineni qcount_rx = min_t(int, rx_numq_tc, max_rss); 67787324e74SHenry Tieman if (!vsi->req_rxq) 67887324e74SHenry Tieman qcount_rx = min_t(int, qcount_rx, 67987324e74SHenry Tieman vsi->rss_size); 6808ede0178SAnirudh Venkataramanan } 68128c2a645SAnirudh Venkataramanan } 68228c2a645SAnirudh Venkataramanan 68328c2a645SAnirudh Venkataramanan /* find the (rounded up) power-of-2 of qcount */ 684c5a2a4a3SUsha Ketineni pow = order_base_2(qcount_rx); 68528c2a645SAnirudh Venkataramanan 6862bdc97beSBruce Allan ice_for_each_traffic_class(i) { 68728c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 68828c2a645SAnirudh Venkataramanan /* TC is not enabled */ 68928c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = 0; 690c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = 1; 691c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = 1; 692c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = 0; 69328c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = 0; 69428c2a645SAnirudh Venkataramanan continue; 69528c2a645SAnirudh Venkataramanan } 69628c2a645SAnirudh Venkataramanan 69728c2a645SAnirudh Venkataramanan /* TC is enabled */ 69828c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = offset; 699c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx; 700c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc; 701c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 70228c2a645SAnirudh Venkataramanan 70328c2a645SAnirudh Venkataramanan qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 70428c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_OFFSET_M) | 70528c2a645SAnirudh Venkataramanan ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 70628c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_NUM_M); 707c5a2a4a3SUsha Ketineni offset += qcount_rx; 708c5a2a4a3SUsha Ketineni tx_count += tx_numq_tc; 70928c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); 71028c2a645SAnirudh Venkataramanan } 71160dcc39eSKiran Patil 71260dcc39eSKiran Patil /* if offset is non-zero, means it is calculated correctly based on 71360dcc39eSKiran Patil * enabled TCs for a given VSI otherwise qcount_rx will always 71460dcc39eSKiran Patil * be correct and non-zero because it is based off - VSI's 71560dcc39eSKiran Patil * allocated Rx queues which is at least 1 (hence qcount_tx will be 71660dcc39eSKiran Patil * at least 1) 71760dcc39eSKiran Patil */ 71860dcc39eSKiran Patil if (offset) 71928c2a645SAnirudh Venkataramanan vsi->num_rxq = offset; 72060dcc39eSKiran Patil else 72160dcc39eSKiran Patil vsi->num_rxq = qcount_rx; 72260dcc39eSKiran Patil 723c5a2a4a3SUsha Ketineni vsi->num_txq = tx_count; 72428c2a645SAnirudh Venkataramanan 7258ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) { 7269a946843SAnirudh Venkataramanan dev_dbg(ice_pf_to_dev(vsi->back), "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n"); 7278ede0178SAnirudh Venkataramanan /* since there is a chance that num_rxq could have been changed 7288ede0178SAnirudh Venkataramanan * in the above for loop, make num_txq equal to num_rxq. 7298ede0178SAnirudh Venkataramanan */ 7308ede0178SAnirudh Venkataramanan vsi->num_txq = vsi->num_rxq; 7318ede0178SAnirudh Venkataramanan } 7328ede0178SAnirudh Venkataramanan 73328c2a645SAnirudh Venkataramanan /* Rx queue mapping */ 73428c2a645SAnirudh Venkataramanan ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 73528c2a645SAnirudh Venkataramanan /* q_mapping buffer holds the info for the first queue allocated for 73628c2a645SAnirudh Venkataramanan * this VSI in the PF space and also the number of queues associated 73728c2a645SAnirudh Venkataramanan * with this VSI. 73828c2a645SAnirudh Venkataramanan */ 73928c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 74028c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq); 74128c2a645SAnirudh Venkataramanan } 74228c2a645SAnirudh Venkataramanan 74328c2a645SAnirudh Venkataramanan /** 74428c2a645SAnirudh Venkataramanan * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI 74528c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 74628c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 74728c2a645SAnirudh Venkataramanan */ 74828c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 74928c2a645SAnirudh Venkataramanan { 75028c2a645SAnirudh Venkataramanan u8 lut_type, hash_type; 7514015d11eSBrett Creeley struct device *dev; 752819d8998SJesse Brandeburg struct ice_pf *pf; 753819d8998SJesse Brandeburg 754819d8998SJesse Brandeburg pf = vsi->back; 7554015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 75628c2a645SAnirudh Venkataramanan 75728c2a645SAnirudh Venkataramanan switch (vsi->type) { 75828c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 75928c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 76028c2a645SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; 76128c2a645SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 76228c2a645SAnirudh Venkataramanan break; 7638ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 7648ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table which is a VSI LUT type */ 7658ede0178SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 7668ede0178SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 7678ede0178SAnirudh Venkataramanan break; 7680e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 7694015d11eSBrett Creeley dev_dbg(dev, "Unsupported VSI type %s\n", 770964674f1SAnirudh Venkataramanan ice_vsi_type_str(vsi->type)); 7710e674aebSAnirudh Venkataramanan return; 77228c2a645SAnirudh Venkataramanan default: 7734015d11eSBrett Creeley dev_warn(dev, "Unknown VSI type %d\n", vsi->type); 77428c2a645SAnirudh Venkataramanan return; 77528c2a645SAnirudh Venkataramanan } 77628c2a645SAnirudh Venkataramanan 77728c2a645SAnirudh Venkataramanan ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & 77828c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | 77928c2a645SAnirudh Venkataramanan ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & 78028c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_HASH_M); 78128c2a645SAnirudh Venkataramanan } 78228c2a645SAnirudh Venkataramanan 78328c2a645SAnirudh Venkataramanan /** 78428c2a645SAnirudh Venkataramanan * ice_vsi_init - Create and initialize a VSI 78528c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 78687324e74SHenry Tieman * @init_vsi: is this call creating a VSI 78728c2a645SAnirudh Venkataramanan * 78828c2a645SAnirudh Venkataramanan * This initializes a VSI context depending on the VSI type to be added and 78928c2a645SAnirudh Venkataramanan * passes it down to the add_vsi aq command to create a new VSI. 79028c2a645SAnirudh Venkataramanan */ 79187324e74SHenry Tieman static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi) 79228c2a645SAnirudh Venkataramanan { 79328c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 79428c2a645SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 795198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 79687324e74SHenry Tieman struct device *dev; 79728c2a645SAnirudh Venkataramanan int ret = 0; 79828c2a645SAnirudh Venkataramanan 79987324e74SHenry Tieman dev = ice_pf_to_dev(pf); 8009efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 801198a666aSBruce Allan if (!ctxt) 802198a666aSBruce Allan return -ENOMEM; 803198a666aSBruce Allan 804cb93a952SAkeem G Abodunrin ctxt->info = vsi->info; 80528c2a645SAnirudh Venkataramanan switch (vsi->type) { 8060e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 8070e674aebSAnirudh Venkataramanan /* fall through */ 80828c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 809198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_PF; 81028c2a645SAnirudh Venkataramanan break; 8118ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 812198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_VF; 8138ede0178SAnirudh Venkataramanan /* VF number here is the absolute VF number (0-255) */ 814198a666aSBruce Allan ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; 8158ede0178SAnirudh Venkataramanan break; 81628c2a645SAnirudh Venkataramanan default: 8179efe35d0STony Nguyen ret = -ENODEV; 8189efe35d0STony Nguyen goto out; 81928c2a645SAnirudh Venkataramanan } 82028c2a645SAnirudh Venkataramanan 821198a666aSBruce Allan ice_set_dflt_vsi_ctx(ctxt); 82228c2a645SAnirudh Venkataramanan /* if the switch is in VEB mode, allow VSI loopback */ 82328c2a645SAnirudh Venkataramanan if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) 824198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 82528c2a645SAnirudh Venkataramanan 82628c2a645SAnirudh Venkataramanan /* Set LUT type and HASH type if RSS is enabled */ 82787324e74SHenry Tieman if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 828198a666aSBruce Allan ice_set_rss_vsi_ctx(ctxt, vsi); 82987324e74SHenry Tieman /* if updating VSI context, make sure to set valid_section: 83087324e74SHenry Tieman * to indicate which section of VSI context being updated 83187324e74SHenry Tieman */ 83287324e74SHenry Tieman if (!init_vsi) 83387324e74SHenry Tieman ctxt->info.valid_sections |= 83487324e74SHenry Tieman cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID); 83587324e74SHenry Tieman } 83628c2a645SAnirudh Venkataramanan 837198a666aSBruce Allan ctxt->info.sw_id = vsi->port_info->sw_id; 838198a666aSBruce Allan ice_vsi_setup_q_map(vsi, ctxt); 83987324e74SHenry Tieman if (!init_vsi) /* means VSI being updated */ 84087324e74SHenry Tieman /* must to indicate which section of VSI context are 84187324e74SHenry Tieman * being modified 84287324e74SHenry Tieman */ 84387324e74SHenry Tieman ctxt->info.valid_sections |= 84487324e74SHenry Tieman cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 84528c2a645SAnirudh Venkataramanan 846cd6d6b83SBrett Creeley /* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off 847cd6d6b83SBrett Creeley * respectively 848cd6d6b83SBrett Creeley */ 849cd6d6b83SBrett Creeley if (vsi->type == ICE_VSI_VF) { 850cb93a952SAkeem G Abodunrin ctxt->info.valid_sections |= 851cb93a952SAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 852cd6d6b83SBrett Creeley if (pf->vf[vsi->vf_id].spoofchk) { 853cb93a952SAkeem G Abodunrin ctxt->info.sec_flags |= 854cd6d6b83SBrett Creeley ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | 855cd6d6b83SBrett Creeley (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 856cd6d6b83SBrett Creeley ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 857cd6d6b83SBrett Creeley } else { 858cd6d6b83SBrett Creeley ctxt->info.sec_flags &= 859cd6d6b83SBrett Creeley ~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | 860cd6d6b83SBrett Creeley (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 861cd6d6b83SBrett Creeley ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S)); 862cd6d6b83SBrett Creeley } 863cb93a952SAkeem G Abodunrin } 864cb93a952SAkeem G Abodunrin 8650c3a6101SDave Ertman /* Allow control frames out of main VSI */ 8660c3a6101SDave Ertman if (vsi->type == ICE_VSI_PF) { 8670c3a6101SDave Ertman ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; 8680c3a6101SDave Ertman ctxt->info.valid_sections |= 8690c3a6101SDave Ertman cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 8700c3a6101SDave Ertman } 8710c3a6101SDave Ertman 87287324e74SHenry Tieman if (init_vsi) { 873198a666aSBruce Allan ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); 87428c2a645SAnirudh Venkataramanan if (ret) { 87587324e74SHenry Tieman dev_err(dev, "Add VSI failed, err %d\n", ret); 8769efe35d0STony Nguyen ret = -EIO; 8779efe35d0STony Nguyen goto out; 87828c2a645SAnirudh Venkataramanan } 87987324e74SHenry Tieman } else { 88087324e74SHenry Tieman ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 88187324e74SHenry Tieman if (ret) { 88287324e74SHenry Tieman dev_err(dev, "Update VSI failed, err %d\n", ret); 88387324e74SHenry Tieman ret = -EIO; 88487324e74SHenry Tieman goto out; 88587324e74SHenry Tieman } 88687324e74SHenry Tieman } 88728c2a645SAnirudh Venkataramanan 88828c2a645SAnirudh Venkataramanan /* keep context for update VSI operations */ 889198a666aSBruce Allan vsi->info = ctxt->info; 89028c2a645SAnirudh Venkataramanan 89128c2a645SAnirudh Venkataramanan /* record VSI number returned */ 892198a666aSBruce Allan vsi->vsi_num = ctxt->vsi_num; 89328c2a645SAnirudh Venkataramanan 8949efe35d0STony Nguyen out: 8959efe35d0STony Nguyen kfree(ctxt); 89628c2a645SAnirudh Venkataramanan return ret; 89728c2a645SAnirudh Venkataramanan } 89828c2a645SAnirudh Venkataramanan 89928c2a645SAnirudh Venkataramanan /** 900df0f8479SAnirudh Venkataramanan * ice_vsi_setup_vector_base - Set up the base vector for the given VSI 901df0f8479SAnirudh Venkataramanan * @vsi: ptr to the VSI 902df0f8479SAnirudh Venkataramanan * 903df0f8479SAnirudh Venkataramanan * This should only be called after ice_vsi_alloc() which allocates the 904df0f8479SAnirudh Venkataramanan * corresponding SW VSI structure and initializes num_queue_pairs for the 905df0f8479SAnirudh Venkataramanan * newly allocated VSI. 906df0f8479SAnirudh Venkataramanan * 907df0f8479SAnirudh Venkataramanan * Returns 0 on success or negative on failure 908df0f8479SAnirudh Venkataramanan */ 90937bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) 910df0f8479SAnirudh Venkataramanan { 911df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 9124015d11eSBrett Creeley struct device *dev; 913cbe66bfeSBrett Creeley u16 num_q_vectors; 914df0f8479SAnirudh Venkataramanan 9154015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 916cbe66bfeSBrett Creeley /* SRIOV doesn't grab irq_tracker entries for each VSI */ 917cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) 918cbe66bfeSBrett Creeley return 0; 919cbe66bfeSBrett Creeley 920cbe66bfeSBrett Creeley if (vsi->base_vector) { 9214015d11eSBrett Creeley dev_dbg(dev, "VSI %d has non-zero base vector %d\n", 922cbe66bfeSBrett Creeley vsi->vsi_num, vsi->base_vector); 923df0f8479SAnirudh Venkataramanan return -EEXIST; 924df0f8479SAnirudh Venkataramanan } 925df0f8479SAnirudh Venkataramanan 926df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 927eb0208ecSPreethi Banala /* reserve slots from OS requested IRQs */ 928cbe66bfeSBrett Creeley vsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors, 929cbe66bfeSBrett Creeley vsi->idx); 930cbe66bfeSBrett Creeley if (vsi->base_vector < 0) { 93119cce2c6SAnirudh Venkataramanan dev_err(dev, "Failed to get tracking for %d vectors for VSI %d, err=%d\n", 932cbe66bfeSBrett Creeley num_q_vectors, vsi->vsi_num, vsi->base_vector); 933eb0208ecSPreethi Banala return -ENOENT; 934eb0208ecSPreethi Banala } 935eb0208ecSPreethi Banala pf->num_avail_sw_msix -= num_q_vectors; 936eb0208ecSPreethi Banala 937df0f8479SAnirudh Venkataramanan return 0; 938df0f8479SAnirudh Venkataramanan } 939df0f8479SAnirudh Venkataramanan 940df0f8479SAnirudh Venkataramanan /** 94128c2a645SAnirudh Venkataramanan * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI 94228c2a645SAnirudh Venkataramanan * @vsi: the VSI having rings deallocated 94328c2a645SAnirudh Venkataramanan */ 944df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi) 94528c2a645SAnirudh Venkataramanan { 94628c2a645SAnirudh Venkataramanan int i; 94728c2a645SAnirudh Venkataramanan 94828c2a645SAnirudh Venkataramanan if (vsi->tx_rings) { 94928c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 95028c2a645SAnirudh Venkataramanan if (vsi->tx_rings[i]) { 95128c2a645SAnirudh Venkataramanan kfree_rcu(vsi->tx_rings[i], rcu); 95228c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = NULL; 95328c2a645SAnirudh Venkataramanan } 95428c2a645SAnirudh Venkataramanan } 95528c2a645SAnirudh Venkataramanan } 95628c2a645SAnirudh Venkataramanan if (vsi->rx_rings) { 95728c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 95828c2a645SAnirudh Venkataramanan if (vsi->rx_rings[i]) { 95928c2a645SAnirudh Venkataramanan kfree_rcu(vsi->rx_rings[i], rcu); 96028c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = NULL; 96128c2a645SAnirudh Venkataramanan } 96228c2a645SAnirudh Venkataramanan } 96328c2a645SAnirudh Venkataramanan } 96428c2a645SAnirudh Venkataramanan } 96528c2a645SAnirudh Venkataramanan 96628c2a645SAnirudh Venkataramanan /** 96728c2a645SAnirudh Venkataramanan * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI 96828c2a645SAnirudh Venkataramanan * @vsi: VSI which is having rings allocated 96928c2a645SAnirudh Venkataramanan */ 97037bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi) 97128c2a645SAnirudh Venkataramanan { 97228c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 9734015d11eSBrett Creeley struct device *dev; 97428c2a645SAnirudh Venkataramanan int i; 97528c2a645SAnirudh Venkataramanan 9764015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 977d337f2afSAnirudh Venkataramanan /* Allocate Tx rings */ 97828c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_txq; i++) { 97928c2a645SAnirudh Venkataramanan struct ice_ring *ring; 98028c2a645SAnirudh Venkataramanan 98128c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 98228c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 98328c2a645SAnirudh Venkataramanan 98428c2a645SAnirudh Venkataramanan if (!ring) 98528c2a645SAnirudh Venkataramanan goto err_out; 98628c2a645SAnirudh Venkataramanan 98728c2a645SAnirudh Venkataramanan ring->q_index = i; 98828c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->txq_map[i]; 98928c2a645SAnirudh Venkataramanan ring->ring_active = false; 99028c2a645SAnirudh Venkataramanan ring->vsi = vsi; 9914015d11eSBrett Creeley ring->dev = dev; 992ad71b256SBrett Creeley ring->count = vsi->num_tx_desc; 99328c2a645SAnirudh Venkataramanan vsi->tx_rings[i] = ring; 99428c2a645SAnirudh Venkataramanan } 99528c2a645SAnirudh Venkataramanan 996d337f2afSAnirudh Venkataramanan /* Allocate Rx rings */ 99728c2a645SAnirudh Venkataramanan for (i = 0; i < vsi->alloc_rxq; i++) { 99828c2a645SAnirudh Venkataramanan struct ice_ring *ring; 99928c2a645SAnirudh Venkataramanan 100028c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 100128c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 100228c2a645SAnirudh Venkataramanan if (!ring) 100328c2a645SAnirudh Venkataramanan goto err_out; 100428c2a645SAnirudh Venkataramanan 100528c2a645SAnirudh Venkataramanan ring->q_index = i; 100628c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->rxq_map[i]; 100728c2a645SAnirudh Venkataramanan ring->ring_active = false; 100828c2a645SAnirudh Venkataramanan ring->vsi = vsi; 100928c2a645SAnirudh Venkataramanan ring->netdev = vsi->netdev; 10104015d11eSBrett Creeley ring->dev = dev; 1011ad71b256SBrett Creeley ring->count = vsi->num_rx_desc; 101228c2a645SAnirudh Venkataramanan vsi->rx_rings[i] = ring; 101328c2a645SAnirudh Venkataramanan } 101428c2a645SAnirudh Venkataramanan 101528c2a645SAnirudh Venkataramanan return 0; 101628c2a645SAnirudh Venkataramanan 101728c2a645SAnirudh Venkataramanan err_out: 101828c2a645SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 101928c2a645SAnirudh Venkataramanan return -ENOMEM; 102028c2a645SAnirudh Venkataramanan } 102128c2a645SAnirudh Venkataramanan 102228c2a645SAnirudh Venkataramanan /** 1023492af0abSMd Fahad Iqbal Polash * ice_vsi_manage_rss_lut - disable/enable RSS 1024492af0abSMd Fahad Iqbal Polash * @vsi: the VSI being changed 1025492af0abSMd Fahad Iqbal Polash * @ena: boolean value indicating if this is an enable or disable request 1026492af0abSMd Fahad Iqbal Polash * 1027492af0abSMd Fahad Iqbal Polash * In the event of disable request for RSS, this function will zero out RSS 1028492af0abSMd Fahad Iqbal Polash * LUT, while in the event of enable request for RSS, it will reconfigure RSS 1029492af0abSMd Fahad Iqbal Polash * LUT. 1030492af0abSMd Fahad Iqbal Polash */ 1031492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena) 1032492af0abSMd Fahad Iqbal Polash { 1033492af0abSMd Fahad Iqbal Polash int err = 0; 1034492af0abSMd Fahad Iqbal Polash u8 *lut; 1035492af0abSMd Fahad Iqbal Polash 10369efe35d0STony Nguyen lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); 1037492af0abSMd Fahad Iqbal Polash if (!lut) 1038492af0abSMd Fahad Iqbal Polash return -ENOMEM; 1039492af0abSMd Fahad Iqbal Polash 1040492af0abSMd Fahad Iqbal Polash if (ena) { 1041492af0abSMd Fahad Iqbal Polash if (vsi->rss_lut_user) 1042492af0abSMd Fahad Iqbal Polash memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 1043492af0abSMd Fahad Iqbal Polash else 1044492af0abSMd Fahad Iqbal Polash ice_fill_rss_lut(lut, vsi->rss_table_size, 1045492af0abSMd Fahad Iqbal Polash vsi->rss_size); 1046492af0abSMd Fahad Iqbal Polash } 1047492af0abSMd Fahad Iqbal Polash 1048492af0abSMd Fahad Iqbal Polash err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size); 10499efe35d0STony Nguyen kfree(lut); 1050492af0abSMd Fahad Iqbal Polash return err; 1051492af0abSMd Fahad Iqbal Polash } 1052492af0abSMd Fahad Iqbal Polash 1053492af0abSMd Fahad Iqbal Polash /** 105437bb8390SAnirudh Venkataramanan * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI 105537bb8390SAnirudh Venkataramanan * @vsi: VSI to be configured 105637bb8390SAnirudh Venkataramanan */ 105737bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi) 105837bb8390SAnirudh Venkataramanan { 105937bb8390SAnirudh Venkataramanan struct ice_aqc_get_set_rss_keys *key; 106037bb8390SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 106137bb8390SAnirudh Venkataramanan enum ice_status status; 10624015d11eSBrett Creeley struct device *dev; 106337bb8390SAnirudh Venkataramanan int err = 0; 106437bb8390SAnirudh Venkataramanan u8 *lut; 106537bb8390SAnirudh Venkataramanan 10664015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 106737bb8390SAnirudh Venkataramanan vsi->rss_size = min_t(int, vsi->rss_size, vsi->num_rxq); 106837bb8390SAnirudh Venkataramanan 10699efe35d0STony Nguyen lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); 107037bb8390SAnirudh Venkataramanan if (!lut) 107137bb8390SAnirudh Venkataramanan return -ENOMEM; 107237bb8390SAnirudh Venkataramanan 107337bb8390SAnirudh Venkataramanan if (vsi->rss_lut_user) 107437bb8390SAnirudh Venkataramanan memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 107537bb8390SAnirudh Venkataramanan else 107637bb8390SAnirudh Venkataramanan ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 107737bb8390SAnirudh Venkataramanan 10784fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut, 10794fb33f31SAnirudh Venkataramanan vsi->rss_table_size); 108037bb8390SAnirudh Venkataramanan 108137bb8390SAnirudh Venkataramanan if (status) { 10824015d11eSBrett Creeley dev_err(dev, "set_rss_lut failed, error %d\n", status); 108337bb8390SAnirudh Venkataramanan err = -EIO; 108437bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 108537bb8390SAnirudh Venkataramanan } 108637bb8390SAnirudh Venkataramanan 10879efe35d0STony Nguyen key = kzalloc(sizeof(*key), GFP_KERNEL); 108837bb8390SAnirudh Venkataramanan if (!key) { 108937bb8390SAnirudh Venkataramanan err = -ENOMEM; 109037bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 109137bb8390SAnirudh Venkataramanan } 109237bb8390SAnirudh Venkataramanan 109337bb8390SAnirudh Venkataramanan if (vsi->rss_hkey_user) 1094b4b418b3SPaul Greenwalt memcpy(key, 1095b4b418b3SPaul Greenwalt (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user, 1096b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 109737bb8390SAnirudh Venkataramanan else 1098b4b418b3SPaul Greenwalt netdev_rss_key_fill((void *)key, 1099b4b418b3SPaul Greenwalt ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 110037bb8390SAnirudh Venkataramanan 11014fb33f31SAnirudh Venkataramanan status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key); 110237bb8390SAnirudh Venkataramanan 110337bb8390SAnirudh Venkataramanan if (status) { 11044015d11eSBrett Creeley dev_err(dev, "set_rss_key failed, error %d\n", status); 110537bb8390SAnirudh Venkataramanan err = -EIO; 110637bb8390SAnirudh Venkataramanan } 110737bb8390SAnirudh Venkataramanan 11089efe35d0STony Nguyen kfree(key); 110937bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit: 11109efe35d0STony Nguyen kfree(lut); 111137bb8390SAnirudh Venkataramanan return err; 111237bb8390SAnirudh Venkataramanan } 111337bb8390SAnirudh Venkataramanan 111437bb8390SAnirudh Venkataramanan /** 11151c01c8c6SMd Fahad Iqbal Polash * ice_vsi_set_vf_rss_flow_fld - Sets VF VSI RSS input set for different flows 11161c01c8c6SMd Fahad Iqbal Polash * @vsi: VSI to be configured 11171c01c8c6SMd Fahad Iqbal Polash * 11181c01c8c6SMd Fahad Iqbal Polash * This function will only be called during the VF VSI setup. Upon successful 11191c01c8c6SMd Fahad Iqbal Polash * completion of package download, this function will configure default RSS 11201c01c8c6SMd Fahad Iqbal Polash * input sets for VF VSI. 11211c01c8c6SMd Fahad Iqbal Polash */ 11221c01c8c6SMd Fahad Iqbal Polash static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi) 11231c01c8c6SMd Fahad Iqbal Polash { 11241c01c8c6SMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 11251c01c8c6SMd Fahad Iqbal Polash enum ice_status status; 11261c01c8c6SMd Fahad Iqbal Polash struct device *dev; 11271c01c8c6SMd Fahad Iqbal Polash 11281c01c8c6SMd Fahad Iqbal Polash dev = ice_pf_to_dev(pf); 11291c01c8c6SMd Fahad Iqbal Polash if (ice_is_safe_mode(pf)) { 11301c01c8c6SMd Fahad Iqbal Polash dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n", 11311c01c8c6SMd Fahad Iqbal Polash vsi->vsi_num); 11321c01c8c6SMd Fahad Iqbal Polash return; 11331c01c8c6SMd Fahad Iqbal Polash } 11341c01c8c6SMd Fahad Iqbal Polash 11351c01c8c6SMd Fahad Iqbal Polash status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA); 11361c01c8c6SMd Fahad Iqbal Polash if (status) 11371c01c8c6SMd Fahad Iqbal Polash dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %d\n", 11381c01c8c6SMd Fahad Iqbal Polash vsi->vsi_num, status); 11391c01c8c6SMd Fahad Iqbal Polash } 11401c01c8c6SMd Fahad Iqbal Polash 11411c01c8c6SMd Fahad Iqbal Polash /** 1142c90ed40cSTony Nguyen * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows 1143c90ed40cSTony Nguyen * @vsi: VSI to be configured 1144c90ed40cSTony Nguyen * 1145c90ed40cSTony Nguyen * This function will only be called after successful download package call 1146c90ed40cSTony Nguyen * during initialization of PF. Since the downloaded package will erase the 1147c90ed40cSTony Nguyen * RSS section, this function will configure RSS input sets for different 1148c90ed40cSTony Nguyen * flow types. The last profile added has the highest priority, therefore 2 1149c90ed40cSTony Nguyen * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles 1150c90ed40cSTony Nguyen * (i.e. IPv4 src/dst TCP src/dst port). 1151c90ed40cSTony Nguyen */ 1152c90ed40cSTony Nguyen static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) 1153c90ed40cSTony Nguyen { 1154c90ed40cSTony Nguyen u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num; 1155c90ed40cSTony Nguyen struct ice_pf *pf = vsi->back; 1156c90ed40cSTony Nguyen struct ice_hw *hw = &pf->hw; 1157c90ed40cSTony Nguyen enum ice_status status; 1158c90ed40cSTony Nguyen struct device *dev; 1159c90ed40cSTony Nguyen 1160c90ed40cSTony Nguyen dev = ice_pf_to_dev(pf); 1161c90ed40cSTony Nguyen if (ice_is_safe_mode(pf)) { 1162c90ed40cSTony Nguyen dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n", 1163c90ed40cSTony Nguyen vsi_num); 1164c90ed40cSTony Nguyen return; 1165c90ed40cSTony Nguyen } 1166c90ed40cSTony Nguyen /* configure RSS for IPv4 with input set IP src/dst */ 1167c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4, 1168c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_IPV4); 1169c90ed40cSTony Nguyen if (status) 1170c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %d\n", 1171c90ed40cSTony Nguyen vsi_num, status); 1172c90ed40cSTony Nguyen 1173c90ed40cSTony Nguyen /* configure RSS for IPv6 with input set IPv6 src/dst */ 1174c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6, 1175c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_IPV6); 1176c90ed40cSTony Nguyen if (status) 1177c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %d\n", 1178c90ed40cSTony Nguyen vsi_num, status); 1179c90ed40cSTony Nguyen 1180c90ed40cSTony Nguyen /* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */ 1181c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4, 1182c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4); 1183c90ed40cSTony Nguyen if (status) 1184c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %d\n", 1185c90ed40cSTony Nguyen vsi_num, status); 1186c90ed40cSTony Nguyen 1187c90ed40cSTony Nguyen /* configure RSS for udp4 with input set IP src/dst, UDP src/dst */ 1188c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4, 1189c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4); 1190c90ed40cSTony Nguyen if (status) 1191c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %d\n", 1192c90ed40cSTony Nguyen vsi_num, status); 1193c90ed40cSTony Nguyen 1194c90ed40cSTony Nguyen /* configure RSS for sctp4 with input set IP src/dst */ 1195c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4, 1196c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4); 1197c90ed40cSTony Nguyen if (status) 1198c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %d\n", 1199c90ed40cSTony Nguyen vsi_num, status); 1200c90ed40cSTony Nguyen 1201c90ed40cSTony Nguyen /* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */ 1202c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6, 1203c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6); 1204c90ed40cSTony Nguyen if (status) 1205c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %d\n", 1206c90ed40cSTony Nguyen vsi_num, status); 1207c90ed40cSTony Nguyen 1208c90ed40cSTony Nguyen /* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */ 1209c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6, 1210c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6); 1211c90ed40cSTony Nguyen if (status) 1212c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %d\n", 1213c90ed40cSTony Nguyen vsi_num, status); 1214c90ed40cSTony Nguyen 1215c90ed40cSTony Nguyen /* configure RSS for sctp6 with input set IPv6 src/dst */ 1216c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6, 1217c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6); 1218c90ed40cSTony Nguyen if (status) 1219c90ed40cSTony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %d\n", 1220c90ed40cSTony Nguyen vsi_num, status); 1221c90ed40cSTony Nguyen } 1222c90ed40cSTony Nguyen 1223c90ed40cSTony Nguyen /** 1224f9867df6SAnirudh Venkataramanan * ice_add_mac_to_list - Add a MAC address filter entry to the list 122545d3d428SAnirudh Venkataramanan * @vsi: the VSI to be forwarded to 122645d3d428SAnirudh Venkataramanan * @add_list: pointer to the list which contains MAC filter entries 122745d3d428SAnirudh Venkataramanan * @macaddr: the MAC address to be added. 122845d3d428SAnirudh Venkataramanan * 1229f9867df6SAnirudh Venkataramanan * Adds MAC address filter entry to the temp list 123045d3d428SAnirudh Venkataramanan * 123145d3d428SAnirudh Venkataramanan * Returns 0 on success or ENOMEM on failure. 123245d3d428SAnirudh Venkataramanan */ 12334ee656bbSTony Nguyen int 12344ee656bbSTony Nguyen ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list, 123545d3d428SAnirudh Venkataramanan const u8 *macaddr) 123645d3d428SAnirudh Venkataramanan { 123745d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 123845d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 123945d3d428SAnirudh Venkataramanan 12404015d11eSBrett Creeley tmp = devm_kzalloc(ice_pf_to_dev(pf), sizeof(*tmp), GFP_ATOMIC); 124145d3d428SAnirudh Venkataramanan if (!tmp) 124245d3d428SAnirudh Venkataramanan return -ENOMEM; 124345d3d428SAnirudh Venkataramanan 124445d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 12455726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 124645d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC; 124745d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 12485726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 124945d3d428SAnirudh Venkataramanan ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr); 125045d3d428SAnirudh Venkataramanan 125145d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 125245d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, add_list); 125345d3d428SAnirudh Venkataramanan 125445d3d428SAnirudh Venkataramanan return 0; 125545d3d428SAnirudh Venkataramanan } 125645d3d428SAnirudh Venkataramanan 125745d3d428SAnirudh Venkataramanan /** 125845d3d428SAnirudh Venkataramanan * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 125945d3d428SAnirudh Venkataramanan * @vsi: the VSI to be updated 126045d3d428SAnirudh Venkataramanan */ 126145d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi) 126245d3d428SAnirudh Venkataramanan { 126345d3d428SAnirudh Venkataramanan struct ice_eth_stats *prev_es, *cur_es; 126445d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 126545d3d428SAnirudh Venkataramanan u16 vsi_num = vsi->vsi_num; /* HW absolute index of a VSI */ 126645d3d428SAnirudh Venkataramanan 126745d3d428SAnirudh Venkataramanan prev_es = &vsi->eth_stats_prev; 126845d3d428SAnirudh Venkataramanan cur_es = &vsi->eth_stats; 126945d3d428SAnirudh Venkataramanan 127036517fd3SJacob Keller ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded, 127136517fd3SJacob Keller &prev_es->rx_bytes, &cur_es->rx_bytes); 127245d3d428SAnirudh Venkataramanan 127336517fd3SJacob Keller ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded, 127436517fd3SJacob Keller &prev_es->rx_unicast, &cur_es->rx_unicast); 127545d3d428SAnirudh Venkataramanan 127636517fd3SJacob Keller ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded, 127736517fd3SJacob Keller &prev_es->rx_multicast, &cur_es->rx_multicast); 127845d3d428SAnirudh Venkataramanan 127936517fd3SJacob Keller ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded, 128036517fd3SJacob Keller &prev_es->rx_broadcast, &cur_es->rx_broadcast); 128145d3d428SAnirudh Venkataramanan 128245d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, 128345d3d428SAnirudh Venkataramanan &prev_es->rx_discards, &cur_es->rx_discards); 128445d3d428SAnirudh Venkataramanan 128536517fd3SJacob Keller ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded, 128636517fd3SJacob Keller &prev_es->tx_bytes, &cur_es->tx_bytes); 128745d3d428SAnirudh Venkataramanan 128836517fd3SJacob Keller ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded, 128936517fd3SJacob Keller &prev_es->tx_unicast, &cur_es->tx_unicast); 129045d3d428SAnirudh Venkataramanan 129136517fd3SJacob Keller ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded, 129236517fd3SJacob Keller &prev_es->tx_multicast, &cur_es->tx_multicast); 129345d3d428SAnirudh Venkataramanan 129436517fd3SJacob Keller ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded, 129536517fd3SJacob Keller &prev_es->tx_broadcast, &cur_es->tx_broadcast); 129645d3d428SAnirudh Venkataramanan 129745d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, 129845d3d428SAnirudh Venkataramanan &prev_es->tx_errors, &cur_es->tx_errors); 129945d3d428SAnirudh Venkataramanan 130045d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded = true; 130145d3d428SAnirudh Venkataramanan } 130245d3d428SAnirudh Venkataramanan 130345d3d428SAnirudh Venkataramanan /** 130445d3d428SAnirudh Venkataramanan * ice_free_fltr_list - free filter lists helper 130545d3d428SAnirudh Venkataramanan * @dev: pointer to the device struct 130645d3d428SAnirudh Venkataramanan * @h: pointer to the list head to be freed 130745d3d428SAnirudh Venkataramanan * 130845d3d428SAnirudh Venkataramanan * Helper function to free filter lists previously created using 130945d3d428SAnirudh Venkataramanan * ice_add_mac_to_list 131045d3d428SAnirudh Venkataramanan */ 131145d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h) 131245d3d428SAnirudh Venkataramanan { 131345d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *e, *tmp; 131445d3d428SAnirudh Venkataramanan 131545d3d428SAnirudh Venkataramanan list_for_each_entry_safe(e, tmp, h, list_entry) { 131645d3d428SAnirudh Venkataramanan list_del(&e->list_entry); 131745d3d428SAnirudh Venkataramanan devm_kfree(dev, e); 131845d3d428SAnirudh Venkataramanan } 131945d3d428SAnirudh Venkataramanan } 132045d3d428SAnirudh Venkataramanan 132145d3d428SAnirudh Venkataramanan /** 132245d3d428SAnirudh Venkataramanan * ice_vsi_add_vlan - Add VSI membership for given VLAN 132345d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1324f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be added 132545d3d428SAnirudh Venkataramanan */ 132645d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid) 132745d3d428SAnirudh Venkataramanan { 132845d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *tmp; 132945d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 133045d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 133145d3d428SAnirudh Venkataramanan enum ice_status status; 13324015d11eSBrett Creeley struct device *dev; 133345d3d428SAnirudh Venkataramanan int err = 0; 133445d3d428SAnirudh Venkataramanan 13354015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 13364015d11eSBrett Creeley tmp = devm_kzalloc(dev, sizeof(*tmp), GFP_KERNEL); 133745d3d428SAnirudh Venkataramanan if (!tmp) 133845d3d428SAnirudh Venkataramanan return -ENOMEM; 133945d3d428SAnirudh Venkataramanan 134045d3d428SAnirudh Venkataramanan tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 134145d3d428SAnirudh Venkataramanan tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI; 134245d3d428SAnirudh Venkataramanan tmp->fltr_info.flag = ICE_FLTR_TX; 13435726ca0eSAnirudh Venkataramanan tmp->fltr_info.src_id = ICE_SRC_ID_VSI; 13445726ca0eSAnirudh Venkataramanan tmp->fltr_info.vsi_handle = vsi->idx; 134545d3d428SAnirudh Venkataramanan tmp->fltr_info.l_data.vlan.vlan_id = vid; 134645d3d428SAnirudh Venkataramanan 134745d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&tmp->list_entry); 134845d3d428SAnirudh Venkataramanan list_add(&tmp->list_entry, &tmp_add_list); 134945d3d428SAnirudh Venkataramanan 135045d3d428SAnirudh Venkataramanan status = ice_add_vlan(&pf->hw, &tmp_add_list); 135142f3efefSBrett Creeley if (!status) { 135242f3efefSBrett Creeley vsi->num_vlan++; 135342f3efefSBrett Creeley } else { 135445d3d428SAnirudh Venkataramanan err = -ENODEV; 13554015d11eSBrett Creeley dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid, 13564015d11eSBrett Creeley vsi->vsi_num); 135745d3d428SAnirudh Venkataramanan } 135845d3d428SAnirudh Venkataramanan 13594015d11eSBrett Creeley ice_free_fltr_list(dev, &tmp_add_list); 136045d3d428SAnirudh Venkataramanan return err; 136145d3d428SAnirudh Venkataramanan } 136245d3d428SAnirudh Venkataramanan 136345d3d428SAnirudh Venkataramanan /** 136445d3d428SAnirudh Venkataramanan * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN 136545d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1366f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be removed 136745d3d428SAnirudh Venkataramanan * 136845d3d428SAnirudh Venkataramanan * Returns 0 on success and negative on failure 136945d3d428SAnirudh Venkataramanan */ 137045d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid) 137145d3d428SAnirudh Venkataramanan { 137245d3d428SAnirudh Venkataramanan struct ice_fltr_list_entry *list; 137345d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 137445d3d428SAnirudh Venkataramanan LIST_HEAD(tmp_add_list); 13755079b853SAkeem G Abodunrin enum ice_status status; 13764015d11eSBrett Creeley struct device *dev; 13775079b853SAkeem G Abodunrin int err = 0; 137845d3d428SAnirudh Venkataramanan 13794015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 13804015d11eSBrett Creeley list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL); 138145d3d428SAnirudh Venkataramanan if (!list) 138245d3d428SAnirudh Venkataramanan return -ENOMEM; 138345d3d428SAnirudh Venkataramanan 138445d3d428SAnirudh Venkataramanan list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN; 13855726ca0eSAnirudh Venkataramanan list->fltr_info.vsi_handle = vsi->idx; 138645d3d428SAnirudh Venkataramanan list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 138745d3d428SAnirudh Venkataramanan list->fltr_info.l_data.vlan.vlan_id = vid; 138845d3d428SAnirudh Venkataramanan list->fltr_info.flag = ICE_FLTR_TX; 13895726ca0eSAnirudh Venkataramanan list->fltr_info.src_id = ICE_SRC_ID_VSI; 139045d3d428SAnirudh Venkataramanan 139145d3d428SAnirudh Venkataramanan INIT_LIST_HEAD(&list->list_entry); 139245d3d428SAnirudh Venkataramanan list_add(&list->list_entry, &tmp_add_list); 139345d3d428SAnirudh Venkataramanan 13945079b853SAkeem G Abodunrin status = ice_remove_vlan(&pf->hw, &tmp_add_list); 139542f3efefSBrett Creeley if (!status) { 139642f3efefSBrett Creeley vsi->num_vlan--; 139742f3efefSBrett Creeley } else if (status == ICE_ERR_DOES_NOT_EXIST) { 139819cce2c6SAnirudh Venkataramanan dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, status: %d\n", 1399bb877b22SAkeem G Abodunrin vid, vsi->vsi_num, status); 140042f3efefSBrett Creeley } else { 140119cce2c6SAnirudh Venkataramanan dev_err(dev, "Error removing VLAN %d on vsi %i error: %d\n", 14025079b853SAkeem G Abodunrin vid, vsi->vsi_num, status); 14035079b853SAkeem G Abodunrin err = -EIO; 140445d3d428SAnirudh Venkataramanan } 140545d3d428SAnirudh Venkataramanan 14064015d11eSBrett Creeley ice_free_fltr_list(dev, &tmp_add_list); 14075079b853SAkeem G Abodunrin return err; 140845d3d428SAnirudh Venkataramanan } 140945d3d428SAnirudh Venkataramanan 141045d3d428SAnirudh Venkataramanan /** 1411efc2214bSMaciej Fijalkowski * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length 1412efc2214bSMaciej Fijalkowski * @vsi: VSI 1413efc2214bSMaciej Fijalkowski */ 1414efc2214bSMaciej Fijalkowski void ice_vsi_cfg_frame_size(struct ice_vsi *vsi) 1415efc2214bSMaciej Fijalkowski { 14167237f5b0SMaciej Fijalkowski if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) { 14177237f5b0SMaciej Fijalkowski vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX; 1418efc2214bSMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_2048; 14197237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192) 142059bb0808SMaciej Fijalkowski } else if (!ICE_2K_TOO_SMALL_WITH_PADDING && 142159bb0808SMaciej Fijalkowski (vsi->netdev->mtu <= ETH_DATA_LEN)) { 14227237f5b0SMaciej Fijalkowski vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN; 14237237f5b0SMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN; 14247237f5b0SMaciej Fijalkowski #endif 14257237f5b0SMaciej Fijalkowski } else { 14267237f5b0SMaciej Fijalkowski vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX; 14277237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192) 14287237f5b0SMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_3072; 14297237f5b0SMaciej Fijalkowski #else 14307237f5b0SMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_2048; 14317237f5b0SMaciej Fijalkowski #endif 14327237f5b0SMaciej Fijalkowski } 1433efc2214bSMaciej Fijalkowski } 1434efc2214bSMaciej Fijalkowski 1435efc2214bSMaciej Fijalkowski /** 143672adf242SAnirudh Venkataramanan * ice_vsi_cfg_rxqs - Configure the VSI for Rx 143772adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 143872adf242SAnirudh Venkataramanan * 143972adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 144072adf242SAnirudh Venkataramanan * Configure the Rx VSI for operation. 144172adf242SAnirudh Venkataramanan */ 144272adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi) 144372adf242SAnirudh Venkataramanan { 144472adf242SAnirudh Venkataramanan u16 i; 144572adf242SAnirudh Venkataramanan 14468ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 14478ede0178SAnirudh Venkataramanan goto setup_rings; 14488ede0178SAnirudh Venkataramanan 1449efc2214bSMaciej Fijalkowski ice_vsi_cfg_frame_size(vsi); 14508ede0178SAnirudh Venkataramanan setup_rings: 145172adf242SAnirudh Venkataramanan /* set up individual rings */ 14521553f4f7SBrett Creeley for (i = 0; i < vsi->num_rxq; i++) { 14531553f4f7SBrett Creeley int err; 145472adf242SAnirudh Venkataramanan 14551553f4f7SBrett Creeley err = ice_setup_rx_ctx(vsi->rx_rings[i]); 145672adf242SAnirudh Venkataramanan if (err) { 145719cce2c6SAnirudh Venkataramanan dev_err(ice_pf_to_dev(vsi->back), "ice_setup_rx_ctx failed for RxQ %d, err %d\n", 14581553f4f7SBrett Creeley i, err); 145972adf242SAnirudh Venkataramanan return err; 146072adf242SAnirudh Venkataramanan } 14611553f4f7SBrett Creeley } 14621553f4f7SBrett Creeley 14631553f4f7SBrett Creeley return 0; 14641553f4f7SBrett Creeley } 146572adf242SAnirudh Venkataramanan 146672adf242SAnirudh Venkataramanan /** 146772adf242SAnirudh Venkataramanan * ice_vsi_cfg_txqs - Configure the VSI for Tx 146872adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 146903f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be configured 147072adf242SAnirudh Venkataramanan * 147172adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 147272adf242SAnirudh Venkataramanan * Configure the Tx VSI for operation. 147372adf242SAnirudh Venkataramanan */ 147403f7a986SAnirudh Venkataramanan static int 1475e75d1b2cSMaciej Fijalkowski ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings) 147672adf242SAnirudh Venkataramanan { 147772adf242SAnirudh Venkataramanan struct ice_aqc_add_tx_qgrp *qg_buf; 1478e75d1b2cSMaciej Fijalkowski u16 q_idx = 0; 1479d02f734cSMaciej Fijalkowski int err = 0; 148072adf242SAnirudh Venkataramanan 1481e75d1b2cSMaciej Fijalkowski qg_buf = kzalloc(sizeof(*qg_buf), GFP_KERNEL); 148272adf242SAnirudh Venkataramanan if (!qg_buf) 148372adf242SAnirudh Venkataramanan return -ENOMEM; 148472adf242SAnirudh Venkataramanan 148572adf242SAnirudh Venkataramanan qg_buf->num_txqs = 1; 148672adf242SAnirudh Venkataramanan 1487e75d1b2cSMaciej Fijalkowski for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) { 1488e75d1b2cSMaciej Fijalkowski err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf); 1489d02f734cSMaciej Fijalkowski if (err) 149072adf242SAnirudh Venkataramanan goto err_cfg_txqs; 1491e75d1b2cSMaciej Fijalkowski } 1492c5a2a4a3SUsha Ketineni 149372adf242SAnirudh Venkataramanan err_cfg_txqs: 1494e75d1b2cSMaciej Fijalkowski kfree(qg_buf); 149572adf242SAnirudh Venkataramanan return err; 149672adf242SAnirudh Venkataramanan } 149772adf242SAnirudh Venkataramanan 149872adf242SAnirudh Venkataramanan /** 149903f7a986SAnirudh Venkataramanan * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx 150003f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 150103f7a986SAnirudh Venkataramanan * 150203f7a986SAnirudh Venkataramanan * Return 0 on success and a negative value on error 150303f7a986SAnirudh Venkataramanan * Configure the Tx VSI for operation. 150403f7a986SAnirudh Venkataramanan */ 150503f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) 150603f7a986SAnirudh Venkataramanan { 1507e75d1b2cSMaciej Fijalkowski return ice_vsi_cfg_txqs(vsi, vsi->tx_rings); 150803f7a986SAnirudh Venkataramanan } 150903f7a986SAnirudh Venkataramanan 151003f7a986SAnirudh Venkataramanan /** 1511efc2214bSMaciej Fijalkowski * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI 1512efc2214bSMaciej Fijalkowski * @vsi: the VSI being configured 1513efc2214bSMaciej Fijalkowski * 1514efc2214bSMaciej Fijalkowski * Return 0 on success and a negative value on error 1515efc2214bSMaciej Fijalkowski * Configure the Tx queues dedicated for XDP in given VSI for operation. 1516efc2214bSMaciej Fijalkowski */ 1517efc2214bSMaciej Fijalkowski int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi) 1518efc2214bSMaciej Fijalkowski { 15192d4238f5SKrzysztof Kazimierczak int ret; 15202d4238f5SKrzysztof Kazimierczak int i; 15212d4238f5SKrzysztof Kazimierczak 15222d4238f5SKrzysztof Kazimierczak ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings); 15232d4238f5SKrzysztof Kazimierczak if (ret) 15242d4238f5SKrzysztof Kazimierczak return ret; 15252d4238f5SKrzysztof Kazimierczak 15262d4238f5SKrzysztof Kazimierczak for (i = 0; i < vsi->num_xdp_txq; i++) 15272d4238f5SKrzysztof Kazimierczak vsi->xdp_rings[i]->xsk_umem = ice_xsk_umem(vsi->xdp_rings[i]); 15282d4238f5SKrzysztof Kazimierczak 15292d4238f5SKrzysztof Kazimierczak return ret; 1530efc2214bSMaciej Fijalkowski } 1531efc2214bSMaciej Fijalkowski 1532efc2214bSMaciej Fijalkowski /** 15339e4ab4c2SBrett Creeley * ice_intrl_usec_to_reg - convert interrupt rate limit to register value 15349e4ab4c2SBrett Creeley * @intrl: interrupt rate limit in usecs 15359e4ab4c2SBrett Creeley * @gran: interrupt rate limit granularity in usecs 15369e4ab4c2SBrett Creeley * 15379e4ab4c2SBrett Creeley * This function converts a decimal interrupt rate limit in usecs to the format 15389e4ab4c2SBrett Creeley * expected by firmware. 15399e4ab4c2SBrett Creeley */ 1540b9c8bb06SBrett Creeley u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) 15419e4ab4c2SBrett Creeley { 15429e4ab4c2SBrett Creeley u32 val = intrl / gran; 15439e4ab4c2SBrett Creeley 15449e4ab4c2SBrett Creeley if (val) 15459e4ab4c2SBrett Creeley return val | GLINT_RATE_INTRL_ENA_M; 15469e4ab4c2SBrett Creeley return 0; 15479e4ab4c2SBrett Creeley } 15489e4ab4c2SBrett Creeley 15499e4ab4c2SBrett Creeley /** 155072adf242SAnirudh Venkataramanan * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW 155172adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 1552047e52c0SAnirudh Venkataramanan * 1553047e52c0SAnirudh Venkataramanan * This configures MSIX mode interrupts for the PF VSI, and should not be used 1554047e52c0SAnirudh Venkataramanan * for the VF VSI. 155572adf242SAnirudh Venkataramanan */ 155672adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi) 155772adf242SAnirudh Venkataramanan { 155872adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 155972adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 156072adf242SAnirudh Venkataramanan u32 txq = 0, rxq = 0; 1561d2b464a7SBrett Creeley int i, q; 156272adf242SAnirudh Venkataramanan 1563b07833a0SBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 156472adf242SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1565b07833a0SBrett Creeley u16 reg_idx = q_vector->reg_idx; 156672adf242SAnirudh Venkataramanan 1567b07833a0SBrett Creeley ice_cfg_itr(hw, q_vector); 15689e4ab4c2SBrett Creeley 1569b07833a0SBrett Creeley wr32(hw, GLINT_RATE(reg_idx), 15709e4ab4c2SBrett Creeley ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); 157172adf242SAnirudh Venkataramanan 157272adf242SAnirudh Venkataramanan /* Both Transmit Queue Interrupt Cause Control register 157372adf242SAnirudh Venkataramanan * and Receive Queue Interrupt Cause control register 157472adf242SAnirudh Venkataramanan * expects MSIX_INDX field to be the vector index 157572adf242SAnirudh Venkataramanan * within the function space and not the absolute 157672adf242SAnirudh Venkataramanan * vector index across PF or across device. 157772adf242SAnirudh Venkataramanan * For SR-IOV VF VSIs queue vector index always starts 157872adf242SAnirudh Venkataramanan * with 1 since first vector index(0) is used for OICR 157972adf242SAnirudh Venkataramanan * in VF space. Since VMDq and other PF VSIs are within 158072adf242SAnirudh Venkataramanan * the PF function space, use the vector index that is 158172adf242SAnirudh Venkataramanan * tracked for this PF. 158272adf242SAnirudh Venkataramanan */ 158372adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 1584047e52c0SAnirudh Venkataramanan ice_cfg_txq_interrupt(vsi, txq, reg_idx, 1585047e52c0SAnirudh Venkataramanan q_vector->tx.itr_idx); 158672adf242SAnirudh Venkataramanan txq++; 158772adf242SAnirudh Venkataramanan } 158872adf242SAnirudh Venkataramanan 158972adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 1590047e52c0SAnirudh Venkataramanan ice_cfg_rxq_interrupt(vsi, rxq, reg_idx, 1591047e52c0SAnirudh Venkataramanan q_vector->rx.itr_idx); 159272adf242SAnirudh Venkataramanan rxq++; 159372adf242SAnirudh Venkataramanan } 159472adf242SAnirudh Venkataramanan } 159572adf242SAnirudh Venkataramanan } 159672adf242SAnirudh Venkataramanan 159772adf242SAnirudh Venkataramanan /** 159845d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx 159945d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 160045d3d428SAnirudh Venkataramanan */ 160145d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) 160245d3d428SAnirudh Venkataramanan { 160345d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1604198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 160545d3d428SAnirudh Venkataramanan enum ice_status status; 1606198a666aSBruce Allan int ret = 0; 1607198a666aSBruce Allan 16089efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 1609198a666aSBruce Allan if (!ctxt) 1610198a666aSBruce Allan return -ENOMEM; 161145d3d428SAnirudh Venkataramanan 161245d3d428SAnirudh Venkataramanan /* Here we are configuring the VSI to let the driver add VLAN tags by 161345d3d428SAnirudh Venkataramanan * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag 161445d3d428SAnirudh Venkataramanan * insertion happens in the Tx hot path, in ice_tx_map. 161545d3d428SAnirudh Venkataramanan */ 1616198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; 161745d3d428SAnirudh Venkataramanan 1618e80e76dbSTony Nguyen /* Preserve existing VLAN strip setting */ 1619e80e76dbSTony Nguyen ctxt->info.vlan_flags |= (vsi->info.vlan_flags & 1620e80e76dbSTony Nguyen ICE_AQ_VSI_VLAN_EMOD_M); 1621e80e76dbSTony Nguyen 1622198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 162345d3d428SAnirudh Venkataramanan 1624198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 162545d3d428SAnirudh Venkataramanan if (status) { 16269a946843SAnirudh Venkataramanan dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %d aq_err %d\n", 162745d3d428SAnirudh Venkataramanan status, hw->adminq.sq_last_status); 1628198a666aSBruce Allan ret = -EIO; 1629198a666aSBruce Allan goto out; 163045d3d428SAnirudh Venkataramanan } 163145d3d428SAnirudh Venkataramanan 1632198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1633198a666aSBruce Allan out: 16349efe35d0STony Nguyen kfree(ctxt); 1635198a666aSBruce Allan return ret; 163645d3d428SAnirudh Venkataramanan } 163745d3d428SAnirudh Venkataramanan 163845d3d428SAnirudh Venkataramanan /** 163945d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx 164045d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 164145d3d428SAnirudh Venkataramanan * @ena: boolean value indicating if this is a enable or disable request 164245d3d428SAnirudh Venkataramanan */ 164345d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) 164445d3d428SAnirudh Venkataramanan { 164545d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 1646198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 164745d3d428SAnirudh Venkataramanan enum ice_status status; 1648198a666aSBruce Allan int ret = 0; 1649198a666aSBruce Allan 16509efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 1651198a666aSBruce Allan if (!ctxt) 1652198a666aSBruce Allan return -ENOMEM; 165345d3d428SAnirudh Venkataramanan 165445d3d428SAnirudh Venkataramanan /* Here we are configuring what the VSI should do with the VLAN tag in 165545d3d428SAnirudh Venkataramanan * the Rx packet. We can either leave the tag in the packet or put it in 165645d3d428SAnirudh Venkataramanan * the Rx descriptor. 165745d3d428SAnirudh Venkataramanan */ 1658198a666aSBruce Allan if (ena) 165945d3d428SAnirudh Venkataramanan /* Strip VLAN tag from Rx packet and put it in the desc */ 1660198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; 1661198a666aSBruce Allan else 166245d3d428SAnirudh Venkataramanan /* Disable stripping. Leave tag in packet */ 1663198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; 166445d3d428SAnirudh Venkataramanan 166545d3d428SAnirudh Venkataramanan /* Allow all packets untagged/tagged */ 1666198a666aSBruce Allan ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; 166745d3d428SAnirudh Venkataramanan 1668198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 166945d3d428SAnirudh Venkataramanan 1670198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 167145d3d428SAnirudh Venkataramanan if (status) { 16729a946843SAnirudh Venkataramanan dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n", 167345d3d428SAnirudh Venkataramanan ena, status, hw->adminq.sq_last_status); 1674198a666aSBruce Allan ret = -EIO; 1675198a666aSBruce Allan goto out; 167645d3d428SAnirudh Venkataramanan } 167745d3d428SAnirudh Venkataramanan 1678198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 1679198a666aSBruce Allan out: 16809efe35d0STony Nguyen kfree(ctxt); 1681198a666aSBruce Allan return ret; 168245d3d428SAnirudh Venkataramanan } 168372adf242SAnirudh Venkataramanan 168472adf242SAnirudh Venkataramanan /** 168572adf242SAnirudh Venkataramanan * ice_vsi_start_rx_rings - start VSI's Rx rings 168672adf242SAnirudh Venkataramanan * @vsi: the VSI whose rings are to be started 168772adf242SAnirudh Venkataramanan * 168872adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 168972adf242SAnirudh Venkataramanan */ 169072adf242SAnirudh Venkataramanan int ice_vsi_start_rx_rings(struct ice_vsi *vsi) 169172adf242SAnirudh Venkataramanan { 169272adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, true); 169372adf242SAnirudh Venkataramanan } 169472adf242SAnirudh Venkataramanan 169572adf242SAnirudh Venkataramanan /** 169672adf242SAnirudh Venkataramanan * ice_vsi_stop_rx_rings - stop VSI's Rx rings 169772adf242SAnirudh Venkataramanan * @vsi: the VSI 169872adf242SAnirudh Venkataramanan * 169972adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 170072adf242SAnirudh Venkataramanan */ 170172adf242SAnirudh Venkataramanan int ice_vsi_stop_rx_rings(struct ice_vsi *vsi) 170272adf242SAnirudh Venkataramanan { 170372adf242SAnirudh Venkataramanan return ice_vsi_ctrl_rx_rings(vsi, false); 170472adf242SAnirudh Venkataramanan } 170572adf242SAnirudh Venkataramanan 170672adf242SAnirudh Venkataramanan /** 1707d02f734cSMaciej Fijalkowski * ice_vsi_stop_tx_rings - Disable Tx rings 1708d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 1709d02f734cSMaciej Fijalkowski * @rst_src: reset source 1710d02f734cSMaciej Fijalkowski * @rel_vmvf_num: Relative ID of VF/VM 1711d02f734cSMaciej Fijalkowski * @rings: Tx ring array to be stopped 1712d02f734cSMaciej Fijalkowski */ 1713d02f734cSMaciej Fijalkowski static int 1714d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 1715d02f734cSMaciej Fijalkowski u16 rel_vmvf_num, struct ice_ring **rings) 1716d02f734cSMaciej Fijalkowski { 1717e75d1b2cSMaciej Fijalkowski u16 q_idx; 1718d02f734cSMaciej Fijalkowski 1719d02f734cSMaciej Fijalkowski if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS) 1720d02f734cSMaciej Fijalkowski return -EINVAL; 1721d02f734cSMaciej Fijalkowski 1722e75d1b2cSMaciej Fijalkowski for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) { 1723d02f734cSMaciej Fijalkowski struct ice_txq_meta txq_meta = { }; 1724e75d1b2cSMaciej Fijalkowski int status; 1725d02f734cSMaciej Fijalkowski 1726d02f734cSMaciej Fijalkowski if (!rings || !rings[q_idx]) 1727d02f734cSMaciej Fijalkowski return -EINVAL; 1728d02f734cSMaciej Fijalkowski 1729d02f734cSMaciej Fijalkowski ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta); 1730e75d1b2cSMaciej Fijalkowski status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num, 1731d02f734cSMaciej Fijalkowski rings[q_idx], &txq_meta); 1732d02f734cSMaciej Fijalkowski 1733d02f734cSMaciej Fijalkowski if (status) 1734d02f734cSMaciej Fijalkowski return status; 1735bb87ee0eSAnirudh Venkataramanan } 173672adf242SAnirudh Venkataramanan 1737d02f734cSMaciej Fijalkowski return 0; 173872adf242SAnirudh Venkataramanan } 17395153a18eSAnirudh Venkataramanan 17405153a18eSAnirudh Venkataramanan /** 174103f7a986SAnirudh Venkataramanan * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings 174203f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 174303f7a986SAnirudh Venkataramanan * @rst_src: reset source 1744f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 174503f7a986SAnirudh Venkataramanan */ 1746c8b7abddSBruce Allan int 1747c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 1748c8b7abddSBruce Allan u16 rel_vmvf_num) 174903f7a986SAnirudh Venkataramanan { 1750d02f734cSMaciej Fijalkowski return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings); 175103f7a986SAnirudh Venkataramanan } 175203f7a986SAnirudh Venkataramanan 175303f7a986SAnirudh Venkataramanan /** 1754efc2214bSMaciej Fijalkowski * ice_vsi_stop_xdp_tx_rings - Disable XDP Tx rings 1755efc2214bSMaciej Fijalkowski * @vsi: the VSI being configured 1756efc2214bSMaciej Fijalkowski */ 1757efc2214bSMaciej Fijalkowski int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi) 1758efc2214bSMaciej Fijalkowski { 1759efc2214bSMaciej Fijalkowski return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings); 1760efc2214bSMaciej Fijalkowski } 1761efc2214bSMaciej Fijalkowski 1762efc2214bSMaciej Fijalkowski /** 176342f3efefSBrett Creeley * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not 176442f3efefSBrett Creeley * @vsi: VSI to check whether or not VLAN pruning is enabled. 176542f3efefSBrett Creeley * 176642f3efefSBrett Creeley * returns true if Rx VLAN pruning and Tx VLAN anti-spoof is enabled and false 176742f3efefSBrett Creeley * otherwise. 176842f3efefSBrett Creeley */ 176942f3efefSBrett Creeley bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi) 177042f3efefSBrett Creeley { 177142f3efefSBrett Creeley u8 rx_pruning = ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 177242f3efefSBrett Creeley u8 tx_pruning = ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 177342f3efefSBrett Creeley ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S; 177442f3efefSBrett Creeley 177542f3efefSBrett Creeley if (!vsi) 177642f3efefSBrett Creeley return false; 177742f3efefSBrett Creeley 177842f3efefSBrett Creeley return ((vsi->info.sw_flags2 & rx_pruning) && 177942f3efefSBrett Creeley (vsi->info.sec_flags & tx_pruning)); 178042f3efefSBrett Creeley } 178142f3efefSBrett Creeley 178242f3efefSBrett Creeley /** 17835153a18eSAnirudh Venkataramanan * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 17845153a18eSAnirudh Venkataramanan * @vsi: VSI to enable or disable VLAN pruning on 17855153a18eSAnirudh Venkataramanan * @ena: set to true to enable VLAN pruning and false to disable it 17865eda8afdSAkeem G Abodunrin * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode 17875153a18eSAnirudh Venkataramanan * 17885153a18eSAnirudh Venkataramanan * returns 0 if VSI is updated, negative otherwise 17895153a18eSAnirudh Venkataramanan */ 17905eda8afdSAkeem G Abodunrin int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc) 17915153a18eSAnirudh Venkataramanan { 17925153a18eSAnirudh Venkataramanan struct ice_vsi_ctx *ctxt; 1793819d8998SJesse Brandeburg struct ice_pf *pf; 17945153a18eSAnirudh Venkataramanan int status; 17955153a18eSAnirudh Venkataramanan 17965153a18eSAnirudh Venkataramanan if (!vsi) 17975153a18eSAnirudh Venkataramanan return -EINVAL; 17985153a18eSAnirudh Venkataramanan 1799819d8998SJesse Brandeburg pf = vsi->back; 18009efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 18015153a18eSAnirudh Venkataramanan if (!ctxt) 18025153a18eSAnirudh Venkataramanan return -ENOMEM; 18035153a18eSAnirudh Venkataramanan 18045153a18eSAnirudh Venkataramanan ctxt->info = vsi->info; 18055153a18eSAnirudh Venkataramanan 1806cd6d6b83SBrett Creeley if (ena) 18075153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 1808cd6d6b83SBrett Creeley else 18095153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 18105153a18eSAnirudh Venkataramanan 18115eda8afdSAkeem G Abodunrin if (!vlan_promisc) 18125eda8afdSAkeem G Abodunrin ctxt->info.valid_sections = 1813cd6d6b83SBrett Creeley cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); 18145726ca0eSAnirudh Venkataramanan 1815819d8998SJesse Brandeburg status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL); 18165153a18eSAnirudh Venkataramanan if (status) { 18175726ca0eSAnirudh Venkataramanan netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %d\n", 181831082519SAnirudh Venkataramanan ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status, 1819819d8998SJesse Brandeburg pf->hw.adminq.sq_last_status); 18205153a18eSAnirudh Venkataramanan goto err_out; 18215153a18eSAnirudh Venkataramanan } 18225153a18eSAnirudh Venkataramanan 18235153a18eSAnirudh Venkataramanan vsi->info.sw_flags2 = ctxt->info.sw_flags2; 18245153a18eSAnirudh Venkataramanan 18259efe35d0STony Nguyen kfree(ctxt); 18265153a18eSAnirudh Venkataramanan return 0; 18275153a18eSAnirudh Venkataramanan 18285153a18eSAnirudh Venkataramanan err_out: 18299efe35d0STony Nguyen kfree(ctxt); 18305153a18eSAnirudh Venkataramanan return -EIO; 18315153a18eSAnirudh Venkataramanan } 18325153a18eSAnirudh Venkataramanan 18337b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) 18347b9ffc76SAnirudh Venkataramanan { 18357b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *cfg = &vsi->port_info->local_dcbx_cfg; 18367b9ffc76SAnirudh Venkataramanan 18377b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg); 18387b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg); 18397b9ffc76SAnirudh Venkataramanan } 18407b9ffc76SAnirudh Venkataramanan 18415153a18eSAnirudh Venkataramanan /** 1842b07833a0SBrett Creeley * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors 1843b07833a0SBrett Creeley * @vsi: VSI to set the q_vectors register index on 1844b07833a0SBrett Creeley */ 1845b07833a0SBrett Creeley static int 1846b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi) 1847b07833a0SBrett Creeley { 1848b07833a0SBrett Creeley u16 i; 1849b07833a0SBrett Creeley 1850b07833a0SBrett Creeley if (!vsi || !vsi->q_vectors) 1851b07833a0SBrett Creeley return -EINVAL; 1852b07833a0SBrett Creeley 1853b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 1854b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1855b07833a0SBrett Creeley 1856b07833a0SBrett Creeley if (!q_vector) { 185719cce2c6SAnirudh Venkataramanan dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n", 1858b07833a0SBrett Creeley i, vsi->vsi_num); 1859b07833a0SBrett Creeley goto clear_reg_idx; 1860b07833a0SBrett Creeley } 1861b07833a0SBrett Creeley 1862cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) { 1863cbe66bfeSBrett Creeley struct ice_vf *vf = &vsi->back->vf[vsi->vf_id]; 1864cbe66bfeSBrett Creeley 1865cbe66bfeSBrett Creeley q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector); 1866cbe66bfeSBrett Creeley } else { 1867cbe66bfeSBrett Creeley q_vector->reg_idx = 1868cbe66bfeSBrett Creeley q_vector->v_idx + vsi->base_vector; 1869cbe66bfeSBrett Creeley } 1870b07833a0SBrett Creeley } 1871b07833a0SBrett Creeley 1872b07833a0SBrett Creeley return 0; 1873b07833a0SBrett Creeley 1874b07833a0SBrett Creeley clear_reg_idx: 1875b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 1876b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1877b07833a0SBrett Creeley 1878b07833a0SBrett Creeley if (q_vector) 1879b07833a0SBrett Creeley q_vector->reg_idx = 0; 1880b07833a0SBrett Creeley } 1881b07833a0SBrett Creeley 1882b07833a0SBrett Creeley return -EINVAL; 1883b07833a0SBrett Creeley } 1884b07833a0SBrett Creeley 1885b07833a0SBrett Creeley /** 1886d95276ceSAkeem G Abodunrin * ice_vsi_add_rem_eth_mac - Program VSI ethertype based filter with rule 1887d95276ceSAkeem G Abodunrin * @vsi: the VSI being configured 1888d95276ceSAkeem G Abodunrin * @add_rule: boolean value to add or remove ethertype filter rule 1889d95276ceSAkeem G Abodunrin */ 1890d95276ceSAkeem G Abodunrin static void 1891d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(struct ice_vsi *vsi, bool add_rule) 1892d95276ceSAkeem G Abodunrin { 1893d95276ceSAkeem G Abodunrin struct ice_fltr_list_entry *list; 1894d95276ceSAkeem G Abodunrin struct ice_pf *pf = vsi->back; 1895d95276ceSAkeem G Abodunrin LIST_HEAD(tmp_add_list); 1896d95276ceSAkeem G Abodunrin enum ice_status status; 18974015d11eSBrett Creeley struct device *dev; 1898d95276ceSAkeem G Abodunrin 18994015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 19004015d11eSBrett Creeley list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL); 1901d95276ceSAkeem G Abodunrin if (!list) 1902d95276ceSAkeem G Abodunrin return; 1903d95276ceSAkeem G Abodunrin 1904d95276ceSAkeem G Abodunrin list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 1905d95276ceSAkeem G Abodunrin list->fltr_info.fltr_act = ICE_DROP_PACKET; 1906d95276ceSAkeem G Abodunrin list->fltr_info.flag = ICE_FLTR_TX; 1907d95276ceSAkeem G Abodunrin list->fltr_info.src_id = ICE_SRC_ID_VSI; 1908d95276ceSAkeem G Abodunrin list->fltr_info.vsi_handle = vsi->idx; 1909d95276ceSAkeem G Abodunrin list->fltr_info.l_data.ethertype_mac.ethertype = vsi->ethtype; 1910d95276ceSAkeem G Abodunrin 1911d95276ceSAkeem G Abodunrin INIT_LIST_HEAD(&list->list_entry); 1912d95276ceSAkeem G Abodunrin list_add(&list->list_entry, &tmp_add_list); 1913d95276ceSAkeem G Abodunrin 1914d95276ceSAkeem G Abodunrin if (add_rule) 1915d95276ceSAkeem G Abodunrin status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 1916d95276ceSAkeem G Abodunrin else 1917d95276ceSAkeem G Abodunrin status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 1918d95276ceSAkeem G Abodunrin 1919d95276ceSAkeem G Abodunrin if (status) 192019cce2c6SAnirudh Venkataramanan dev_err(dev, "Failure Adding or Removing Ethertype on VSI %i error: %d\n", 1921d95276ceSAkeem G Abodunrin vsi->vsi_num, status); 1922d95276ceSAkeem G Abodunrin 19234015d11eSBrett Creeley ice_free_fltr_list(dev, &tmp_add_list); 1924d95276ceSAkeem G Abodunrin } 1925d95276ceSAkeem G Abodunrin 19262e0e6228SDave Ertman /** 19272e0e6228SDave Ertman * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling 19282e0e6228SDave Ertman * @vsi: the VSI being configured 19292e0e6228SDave Ertman * @tx: bool to determine Tx or Rx rule 19302e0e6228SDave Ertman * @create: bool to determine create or remove Rule 19312e0e6228SDave Ertman */ 19322e0e6228SDave Ertman void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create) 19332e0e6228SDave Ertman { 19342e0e6228SDave Ertman struct ice_fltr_list_entry *list; 19352e0e6228SDave Ertman struct ice_pf *pf = vsi->back; 19362e0e6228SDave Ertman LIST_HEAD(tmp_add_list); 19372e0e6228SDave Ertman enum ice_status status; 19384015d11eSBrett Creeley struct device *dev; 19392e0e6228SDave Ertman 19404015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 19414015d11eSBrett Creeley list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL); 19422e0e6228SDave Ertman if (!list) 19432e0e6228SDave Ertman return; 19442e0e6228SDave Ertman 19452e0e6228SDave Ertman list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 19462e0e6228SDave Ertman list->fltr_info.vsi_handle = vsi->idx; 19473aea1736SJeff Kirsher list->fltr_info.l_data.ethertype_mac.ethertype = ETH_P_LLDP; 19482e0e6228SDave Ertman 19492e0e6228SDave Ertman if (tx) { 19502e0e6228SDave Ertman list->fltr_info.fltr_act = ICE_DROP_PACKET; 19512e0e6228SDave Ertman list->fltr_info.flag = ICE_FLTR_TX; 19522e0e6228SDave Ertman list->fltr_info.src_id = ICE_SRC_ID_VSI; 19532e0e6228SDave Ertman } else { 19542e0e6228SDave Ertman list->fltr_info.fltr_act = ICE_FWD_TO_VSI; 19552e0e6228SDave Ertman list->fltr_info.flag = ICE_FLTR_RX; 19562e0e6228SDave Ertman list->fltr_info.src_id = ICE_SRC_ID_LPORT; 19572e0e6228SDave Ertman } 19582e0e6228SDave Ertman 19592e0e6228SDave Ertman INIT_LIST_HEAD(&list->list_entry); 19602e0e6228SDave Ertman list_add(&list->list_entry, &tmp_add_list); 19612e0e6228SDave Ertman 19622e0e6228SDave Ertman if (create) 19632e0e6228SDave Ertman status = ice_add_eth_mac(&pf->hw, &tmp_add_list); 19642e0e6228SDave Ertman else 19652e0e6228SDave Ertman status = ice_remove_eth_mac(&pf->hw, &tmp_add_list); 19662e0e6228SDave Ertman 19672e0e6228SDave Ertman if (status) 19684015d11eSBrett Creeley dev_err(dev, "Fail %s %s LLDP rule on VSI %i error: %d\n", 19692e0e6228SDave Ertman create ? "adding" : "removing", tx ? "TX" : "RX", 19702e0e6228SDave Ertman vsi->vsi_num, status); 19712e0e6228SDave Ertman 19724015d11eSBrett Creeley ice_free_fltr_list(dev, &tmp_add_list); 19732e0e6228SDave Ertman } 19742e0e6228SDave Ertman 1975d95276ceSAkeem G Abodunrin /** 197637bb8390SAnirudh Venkataramanan * ice_vsi_setup - Set up a VSI by a given type 197737bb8390SAnirudh Venkataramanan * @pf: board private structure 197837bb8390SAnirudh Venkataramanan * @pi: pointer to the port_info instance 197937bb8390SAnirudh Venkataramanan * @type: VSI type 1980f9867df6SAnirudh Venkataramanan * @vf_id: defines VF ID to which this VSI connects. This field is meant to be 198137bb8390SAnirudh Venkataramanan * used only for ICE_VSI_VF VSI type. For other VSI types, should 198237bb8390SAnirudh Venkataramanan * fill-in ICE_INVAL_VFID as input. 198337bb8390SAnirudh Venkataramanan * 198437bb8390SAnirudh Venkataramanan * This allocates the sw VSI structure and its queue resources. 198537bb8390SAnirudh Venkataramanan * 198637bb8390SAnirudh Venkataramanan * Returns pointer to the successfully allocated and configured VSI sw struct on 198737bb8390SAnirudh Venkataramanan * success, NULL on failure. 198837bb8390SAnirudh Venkataramanan */ 198937bb8390SAnirudh Venkataramanan struct ice_vsi * 199037bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, 19918ede0178SAnirudh Venkataramanan enum ice_vsi_type type, u16 vf_id) 199237bb8390SAnirudh Venkataramanan { 199337bb8390SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 19944015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 1995d31530e8SAkeem G Abodunrin enum ice_status status; 199637bb8390SAnirudh Venkataramanan struct ice_vsi *vsi; 199737bb8390SAnirudh Venkataramanan int ret, i; 199837bb8390SAnirudh Venkataramanan 19995743020dSAkeem G Abodunrin if (type == ICE_VSI_VF) 20005743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, vf_id); 20015743020dSAkeem G Abodunrin else 20025743020dSAkeem G Abodunrin vsi = ice_vsi_alloc(pf, type, ICE_INVAL_VFID); 20035743020dSAkeem G Abodunrin 200437bb8390SAnirudh Venkataramanan if (!vsi) { 200537bb8390SAnirudh Venkataramanan dev_err(dev, "could not allocate VSI\n"); 200637bb8390SAnirudh Venkataramanan return NULL; 200737bb8390SAnirudh Venkataramanan } 200837bb8390SAnirudh Venkataramanan 200937bb8390SAnirudh Venkataramanan vsi->port_info = pi; 201037bb8390SAnirudh Venkataramanan vsi->vsw = pf->first_sw; 2011d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 2012d95276ceSAkeem G Abodunrin vsi->ethtype = ETH_P_PAUSE; 2013d95276ceSAkeem G Abodunrin 20148ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 20158ede0178SAnirudh Venkataramanan vsi->vf_id = vf_id; 201637bb8390SAnirudh Venkataramanan 201737bb8390SAnirudh Venkataramanan if (ice_vsi_get_qs(vsi)) { 201837bb8390SAnirudh Venkataramanan dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", 201937bb8390SAnirudh Venkataramanan vsi->idx); 202037bb8390SAnirudh Venkataramanan goto unroll_get_qs; 202137bb8390SAnirudh Venkataramanan } 202237bb8390SAnirudh Venkataramanan 202337bb8390SAnirudh Venkataramanan /* set RSS capabilities */ 202437bb8390SAnirudh Venkataramanan ice_vsi_set_rss_params(vsi); 202537bb8390SAnirudh Venkataramanan 2026f9867df6SAnirudh Venkataramanan /* set TC configuration */ 2027c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2028c5a2a4a3SUsha Ketineni 202937bb8390SAnirudh Venkataramanan /* create the VSI */ 203087324e74SHenry Tieman ret = ice_vsi_init(vsi, true); 203137bb8390SAnirudh Venkataramanan if (ret) 203237bb8390SAnirudh Venkataramanan goto unroll_get_qs; 203337bb8390SAnirudh Venkataramanan 203437bb8390SAnirudh Venkataramanan switch (vsi->type) { 203537bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 203637bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 203737bb8390SAnirudh Venkataramanan if (ret) 203837bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 203937bb8390SAnirudh Venkataramanan 204037bb8390SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 204137bb8390SAnirudh Venkataramanan if (ret) 204237bb8390SAnirudh Venkataramanan goto unroll_alloc_q_vector; 204337bb8390SAnirudh Venkataramanan 2044b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2045b07833a0SBrett Creeley if (ret) 2046b07833a0SBrett Creeley goto unroll_vector_base; 2047b07833a0SBrett Creeley 204837bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 204937bb8390SAnirudh Venkataramanan if (ret) 205037bb8390SAnirudh Venkataramanan goto unroll_vector_base; 205137bb8390SAnirudh Venkataramanan 205242f3efefSBrett Creeley /* Always add VLAN ID 0 switch rule by default. This is needed 205342f3efefSBrett Creeley * in order to allow all untagged and 0 tagged priority traffic 205442f3efefSBrett Creeley * if Rx VLAN pruning is enabled. Also there are cases where we 205542f3efefSBrett Creeley * don't get the call to add VLAN 0 via ice_vlan_rx_add_vid() 205642f3efefSBrett Creeley * so this handles those cases (i.e. adding the PF to a bridge 205742f3efefSBrett Creeley * without the 8021q module loaded). 205842f3efefSBrett Creeley */ 205942f3efefSBrett Creeley ret = ice_vsi_add_vlan(vsi, 0); 206042f3efefSBrett Creeley if (ret) 206142f3efefSBrett Creeley goto unroll_clear_rings; 206242f3efefSBrett Creeley 206337bb8390SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 206437bb8390SAnirudh Venkataramanan 206537bb8390SAnirudh Venkataramanan /* Do not exit if configuring RSS had an issue, at least 206637bb8390SAnirudh Venkataramanan * receive traffic on first queue. Hence no need to capture 206737bb8390SAnirudh Venkataramanan * return value 206837bb8390SAnirudh Venkataramanan */ 2069c90ed40cSTony Nguyen if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 207037bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_lut_key(vsi); 2071c90ed40cSTony Nguyen ice_vsi_set_rss_flow_fld(vsi); 2072c90ed40cSTony Nguyen } 207337bb8390SAnirudh Venkataramanan break; 20748ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 20758ede0178SAnirudh Venkataramanan /* VF driver will take care of creating netdev for this type and 20768ede0178SAnirudh Venkataramanan * map queues to vectors through Virtchnl, PF driver only 20778ede0178SAnirudh Venkataramanan * creates a VSI and corresponding structures for bookkeeping 20788ede0178SAnirudh Venkataramanan * purpose 20798ede0178SAnirudh Venkataramanan */ 20808ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 20818ede0178SAnirudh Venkataramanan if (ret) 20828ede0178SAnirudh Venkataramanan goto unroll_vsi_init; 20838ede0178SAnirudh Venkataramanan 20848ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 20858ede0178SAnirudh Venkataramanan if (ret) 20868ede0178SAnirudh Venkataramanan goto unroll_alloc_q_vector; 20878ede0178SAnirudh Venkataramanan 2088b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2089b07833a0SBrett Creeley if (ret) 2090b07833a0SBrett Creeley goto unroll_vector_base; 2091b07833a0SBrett Creeley 20923a9e32bbSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 20933a9e32bbSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 20943a9e32bbSMd Fahad Iqbal Polash * return value 20953a9e32bbSMd Fahad Iqbal Polash */ 20961c01c8c6SMd Fahad Iqbal Polash if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 20973a9e32bbSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 20981c01c8c6SMd Fahad Iqbal Polash ice_vsi_set_vf_rss_flow_fld(vsi); 20991c01c8c6SMd Fahad Iqbal Polash } 21008ede0178SAnirudh Venkataramanan break; 21010e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 21020e674aebSAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 21030e674aebSAnirudh Venkataramanan if (ret) 21040e674aebSAnirudh Venkataramanan goto unroll_vsi_init; 21050e674aebSAnirudh Venkataramanan break; 210637bb8390SAnirudh Venkataramanan default: 2107df17b7e0SAnirudh Venkataramanan /* clean up the resources and exit */ 210837bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 210937bb8390SAnirudh Venkataramanan } 211037bb8390SAnirudh Venkataramanan 211137bb8390SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 211237bb8390SAnirudh Venkataramanan for (i = 0; i < vsi->tc_cfg.numtc; i++) 2113d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 211437bb8390SAnirudh Venkataramanan 2115d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 21164fb33f31SAnirudh Venkataramanan max_txqs); 2117d31530e8SAkeem G Abodunrin if (status) { 21184015d11eSBrett Creeley dev_err(dev, "VSI %d failed lan queue config, error %d\n", 2119d31530e8SAkeem G Abodunrin vsi->vsi_num, status); 212037bb8390SAnirudh Venkataramanan goto unroll_vector_base; 212137bb8390SAnirudh Venkataramanan } 212237bb8390SAnirudh Venkataramanan 2123d95276ceSAkeem G Abodunrin /* Add switch rule to drop all Tx Flow Control Frames, of look up 2124d95276ceSAkeem G Abodunrin * type ETHERTYPE from VSIs, and restrict malicious VF from sending 2125d95276ceSAkeem G Abodunrin * out PAUSE or PFC frames. If enabled, FW can still send FC frames. 2126d95276ceSAkeem G Abodunrin * The rule is added once for PF VSI in order to create appropriate 2127d95276ceSAkeem G Abodunrin * recipe, since VSI/VSI list is ignored with drop action... 2128241c8cf0SPaul Greenwalt * Also add rules to handle LLDP Tx packets. Tx LLDP packets need to 2129241c8cf0SPaul Greenwalt * be dropped so that VFs cannot send LLDP packets to reconfig DCB 2130241c8cf0SPaul Greenwalt * settings in the HW. 2131d95276ceSAkeem G Abodunrin */ 2132241c8cf0SPaul Greenwalt if (!ice_is_safe_mode(pf)) 21332e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 2134d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, true); 2135d95276ceSAkeem G Abodunrin 21362e0e6228SDave Ertman /* Tx LLDP packets */ 21372e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, true); 2138462acf6aSTony Nguyen } 21392e0e6228SDave Ertman 214037bb8390SAnirudh Venkataramanan return vsi; 214137bb8390SAnirudh Venkataramanan 214242f3efefSBrett Creeley unroll_clear_rings: 214342f3efefSBrett Creeley ice_vsi_clear_rings(vsi); 214437bb8390SAnirudh Venkataramanan unroll_vector_base: 2145eb0208ecSPreethi Banala /* reclaim SW interrupts back to the common pool */ 2146cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 2147eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 214837bb8390SAnirudh Venkataramanan unroll_alloc_q_vector: 214937bb8390SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 215037bb8390SAnirudh Venkataramanan unroll_vsi_init: 215137bb8390SAnirudh Venkataramanan ice_vsi_delete(vsi); 215237bb8390SAnirudh Venkataramanan unroll_get_qs: 215337bb8390SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 215437bb8390SAnirudh Venkataramanan ice_vsi_clear(vsi); 215537bb8390SAnirudh Venkataramanan 215637bb8390SAnirudh Venkataramanan return NULL; 215737bb8390SAnirudh Venkataramanan } 215837bb8390SAnirudh Venkataramanan 215937bb8390SAnirudh Venkataramanan /** 21605153a18eSAnirudh Venkataramanan * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW 21615153a18eSAnirudh Venkataramanan * @vsi: the VSI being cleaned up 21625153a18eSAnirudh Venkataramanan */ 21635153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi) 21645153a18eSAnirudh Venkataramanan { 21655153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 21665153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 21675153a18eSAnirudh Venkataramanan u32 txq = 0; 21685153a18eSAnirudh Venkataramanan u32 rxq = 0; 21695153a18eSAnirudh Venkataramanan int i, q; 21705153a18eSAnirudh Venkataramanan 2171cbe66bfeSBrett Creeley for (i = 0; i < vsi->num_q_vectors; i++) { 21725153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2173cbe66bfeSBrett Creeley u16 reg_idx = q_vector->reg_idx; 21745153a18eSAnirudh Venkataramanan 2175cbe66bfeSBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0); 2176cbe66bfeSBrett Creeley wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0); 21775153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 21785153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); 2179efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) { 2180efc2214bSMaciej Fijalkowski u32 xdp_txq = txq + vsi->num_xdp_txq; 2181efc2214bSMaciej Fijalkowski 2182efc2214bSMaciej Fijalkowski wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0); 2183efc2214bSMaciej Fijalkowski } 21845153a18eSAnirudh Venkataramanan txq++; 21855153a18eSAnirudh Venkataramanan } 21865153a18eSAnirudh Venkataramanan 21875153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 21885153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0); 21895153a18eSAnirudh Venkataramanan rxq++; 21905153a18eSAnirudh Venkataramanan } 21915153a18eSAnirudh Venkataramanan } 21925153a18eSAnirudh Venkataramanan 21935153a18eSAnirudh Venkataramanan ice_flush(hw); 21945153a18eSAnirudh Venkataramanan } 21955153a18eSAnirudh Venkataramanan 21965153a18eSAnirudh Venkataramanan /** 21975153a18eSAnirudh Venkataramanan * ice_vsi_free_irq - Free the IRQ association with the OS 21985153a18eSAnirudh Venkataramanan * @vsi: the VSI being configured 21995153a18eSAnirudh Venkataramanan */ 22005153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi) 22015153a18eSAnirudh Venkataramanan { 22025153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2203cbe66bfeSBrett Creeley int base = vsi->base_vector; 22045153a18eSAnirudh Venkataramanan int i; 22055153a18eSAnirudh Venkataramanan 22065153a18eSAnirudh Venkataramanan if (!vsi->q_vectors || !vsi->irqs_ready) 22075153a18eSAnirudh Venkataramanan return; 22085153a18eSAnirudh Venkataramanan 2209eb0208ecSPreethi Banala ice_vsi_release_msix(vsi); 22108ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 22118ede0178SAnirudh Venkataramanan return; 2212eb0208ecSPreethi Banala 22135153a18eSAnirudh Venkataramanan vsi->irqs_ready = false; 22140c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) { 22155153a18eSAnirudh Venkataramanan u16 vector = i + base; 22165153a18eSAnirudh Venkataramanan int irq_num; 22175153a18eSAnirudh Venkataramanan 22185153a18eSAnirudh Venkataramanan irq_num = pf->msix_entries[vector].vector; 22195153a18eSAnirudh Venkataramanan 22205153a18eSAnirudh Venkataramanan /* free only the irqs that were actually requested */ 22215153a18eSAnirudh Venkataramanan if (!vsi->q_vectors[i] || 22225153a18eSAnirudh Venkataramanan !(vsi->q_vectors[i]->num_ring_tx || 22235153a18eSAnirudh Venkataramanan vsi->q_vectors[i]->num_ring_rx)) 22245153a18eSAnirudh Venkataramanan continue; 22255153a18eSAnirudh Venkataramanan 22265153a18eSAnirudh Venkataramanan /* clear the affinity notifier in the IRQ descriptor */ 22275153a18eSAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 22285153a18eSAnirudh Venkataramanan 22295153a18eSAnirudh Venkataramanan /* clear the affinity_mask in the IRQ descriptor */ 22305153a18eSAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 22315153a18eSAnirudh Venkataramanan synchronize_irq(irq_num); 22324015d11eSBrett Creeley devm_free_irq(ice_pf_to_dev(pf), irq_num, vsi->q_vectors[i]); 22335153a18eSAnirudh Venkataramanan } 22345153a18eSAnirudh Venkataramanan } 22355153a18eSAnirudh Venkataramanan 22365153a18eSAnirudh Venkataramanan /** 22375153a18eSAnirudh Venkataramanan * ice_vsi_free_tx_rings - Free Tx resources for VSI queues 22385153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 22395153a18eSAnirudh Venkataramanan */ 22405153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi) 22415153a18eSAnirudh Venkataramanan { 22425153a18eSAnirudh Venkataramanan int i; 22435153a18eSAnirudh Venkataramanan 22445153a18eSAnirudh Venkataramanan if (!vsi->tx_rings) 22455153a18eSAnirudh Venkataramanan return; 22465153a18eSAnirudh Venkataramanan 22475153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) 22485153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 22495153a18eSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 22505153a18eSAnirudh Venkataramanan } 22515153a18eSAnirudh Venkataramanan 22525153a18eSAnirudh Venkataramanan /** 22535153a18eSAnirudh Venkataramanan * ice_vsi_free_rx_rings - Free Rx resources for VSI queues 22545153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 22555153a18eSAnirudh Venkataramanan */ 22565153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi) 22575153a18eSAnirudh Venkataramanan { 22585153a18eSAnirudh Venkataramanan int i; 22595153a18eSAnirudh Venkataramanan 22605153a18eSAnirudh Venkataramanan if (!vsi->rx_rings) 22615153a18eSAnirudh Venkataramanan return; 22625153a18eSAnirudh Venkataramanan 22635153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 22645153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) 22655153a18eSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 22665153a18eSAnirudh Venkataramanan } 22675153a18eSAnirudh Venkataramanan 22685153a18eSAnirudh Venkataramanan /** 226907309a0eSAnirudh Venkataramanan * ice_vsi_close - Shut down a VSI 227007309a0eSAnirudh Venkataramanan * @vsi: the VSI being shut down 227107309a0eSAnirudh Venkataramanan */ 227207309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi) 227307309a0eSAnirudh Venkataramanan { 227407309a0eSAnirudh Venkataramanan if (!test_and_set_bit(__ICE_DOWN, vsi->state)) 227507309a0eSAnirudh Venkataramanan ice_down(vsi); 227607309a0eSAnirudh Venkataramanan 227707309a0eSAnirudh Venkataramanan ice_vsi_free_irq(vsi); 227807309a0eSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 227907309a0eSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 228007309a0eSAnirudh Venkataramanan } 228107309a0eSAnirudh Venkataramanan 228207309a0eSAnirudh Venkataramanan /** 22839d614b64SAnirudh Venkataramanan * ice_ena_vsi - resume a VSI 22849d614b64SAnirudh Venkataramanan * @vsi: the VSI being resume 22859d614b64SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 22869d614b64SAnirudh Venkataramanan */ 22879d614b64SAnirudh Venkataramanan int ice_ena_vsi(struct ice_vsi *vsi, bool locked) 22889d614b64SAnirudh Venkataramanan { 22899d614b64SAnirudh Venkataramanan int err = 0; 22909d614b64SAnirudh Venkataramanan 22919d614b64SAnirudh Venkataramanan if (!test_bit(__ICE_NEEDS_RESTART, vsi->state)) 22929d614b64SAnirudh Venkataramanan return 0; 22939d614b64SAnirudh Venkataramanan 22949d614b64SAnirudh Venkataramanan clear_bit(__ICE_NEEDS_RESTART, vsi->state); 22959d614b64SAnirudh Venkataramanan 22969d614b64SAnirudh Venkataramanan if (vsi->netdev && vsi->type == ICE_VSI_PF) { 22979d614b64SAnirudh Venkataramanan if (netif_running(vsi->netdev)) { 22989d614b64SAnirudh Venkataramanan if (!locked) 22999d614b64SAnirudh Venkataramanan rtnl_lock(); 23009d614b64SAnirudh Venkataramanan 23019d614b64SAnirudh Venkataramanan err = ice_open(vsi->netdev); 23029d614b64SAnirudh Venkataramanan 23039d614b64SAnirudh Venkataramanan if (!locked) 23049d614b64SAnirudh Venkataramanan rtnl_unlock(); 23059d614b64SAnirudh Venkataramanan } 23069d614b64SAnirudh Venkataramanan } 23079d614b64SAnirudh Venkataramanan 23089d614b64SAnirudh Venkataramanan return err; 23099d614b64SAnirudh Venkataramanan } 23109d614b64SAnirudh Venkataramanan 23119d614b64SAnirudh Venkataramanan /** 23129d614b64SAnirudh Venkataramanan * ice_dis_vsi - pause a VSI 23139d614b64SAnirudh Venkataramanan * @vsi: the VSI being paused 23149d614b64SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 23159d614b64SAnirudh Venkataramanan */ 23169d614b64SAnirudh Venkataramanan void ice_dis_vsi(struct ice_vsi *vsi, bool locked) 23179d614b64SAnirudh Venkataramanan { 23189d614b64SAnirudh Venkataramanan if (test_bit(__ICE_DOWN, vsi->state)) 23199d614b64SAnirudh Venkataramanan return; 23209d614b64SAnirudh Venkataramanan 23219d614b64SAnirudh Venkataramanan set_bit(__ICE_NEEDS_RESTART, vsi->state); 23229d614b64SAnirudh Venkataramanan 23239d614b64SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF && vsi->netdev) { 23249d614b64SAnirudh Venkataramanan if (netif_running(vsi->netdev)) { 23259d614b64SAnirudh Venkataramanan if (!locked) 23269d614b64SAnirudh Venkataramanan rtnl_lock(); 23279d614b64SAnirudh Venkataramanan 23289d614b64SAnirudh Venkataramanan ice_stop(vsi->netdev); 23299d614b64SAnirudh Venkataramanan 23309d614b64SAnirudh Venkataramanan if (!locked) 23319d614b64SAnirudh Venkataramanan rtnl_unlock(); 23329d614b64SAnirudh Venkataramanan } else { 23339d614b64SAnirudh Venkataramanan ice_vsi_close(vsi); 23349d614b64SAnirudh Venkataramanan } 23359d614b64SAnirudh Venkataramanan } 23369d614b64SAnirudh Venkataramanan } 23379d614b64SAnirudh Venkataramanan 23389d614b64SAnirudh Venkataramanan /** 23395153a18eSAnirudh Venkataramanan * ice_free_res - free a block of resources 23405153a18eSAnirudh Venkataramanan * @res: pointer to the resource 23415153a18eSAnirudh Venkataramanan * @index: starting index previously returned by ice_get_res 23425153a18eSAnirudh Venkataramanan * @id: identifier to track owner 23435153a18eSAnirudh Venkataramanan * 23445153a18eSAnirudh Venkataramanan * Returns number of resources freed 23455153a18eSAnirudh Venkataramanan */ 23465153a18eSAnirudh Venkataramanan int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) 23475153a18eSAnirudh Venkataramanan { 23485153a18eSAnirudh Venkataramanan int count = 0; 23495153a18eSAnirudh Venkataramanan int i; 23505153a18eSAnirudh Venkataramanan 2351cbe66bfeSBrett Creeley if (!res || index >= res->end) 23525153a18eSAnirudh Venkataramanan return -EINVAL; 23535153a18eSAnirudh Venkataramanan 23545153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 2355cbe66bfeSBrett Creeley for (i = index; i < res->end && res->list[i] == id; i++) { 23565153a18eSAnirudh Venkataramanan res->list[i] = 0; 23575153a18eSAnirudh Venkataramanan count++; 23585153a18eSAnirudh Venkataramanan } 23595153a18eSAnirudh Venkataramanan 23605153a18eSAnirudh Venkataramanan return count; 23615153a18eSAnirudh Venkataramanan } 23625153a18eSAnirudh Venkataramanan 23635153a18eSAnirudh Venkataramanan /** 23645153a18eSAnirudh Venkataramanan * ice_search_res - Search the tracker for a block of resources 23655153a18eSAnirudh Venkataramanan * @res: pointer to the resource 23665153a18eSAnirudh Venkataramanan * @needed: size of the block needed 23675153a18eSAnirudh Venkataramanan * @id: identifier to track owner 23685153a18eSAnirudh Venkataramanan * 23695153a18eSAnirudh Venkataramanan * Returns the base item index of the block, or -ENOMEM for error 23705153a18eSAnirudh Venkataramanan */ 23715153a18eSAnirudh Venkataramanan static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) 23725153a18eSAnirudh Venkataramanan { 2373cbe66bfeSBrett Creeley int start = 0, end = 0; 23745153a18eSAnirudh Venkataramanan 2375cbe66bfeSBrett Creeley if (needed > res->end) 2376eb0208ecSPreethi Banala return -ENOMEM; 2377eb0208ecSPreethi Banala 23785153a18eSAnirudh Venkataramanan id |= ICE_RES_VALID_BIT; 23795153a18eSAnirudh Venkataramanan 23805153a18eSAnirudh Venkataramanan do { 23815153a18eSAnirudh Venkataramanan /* skip already allocated entries */ 23825153a18eSAnirudh Venkataramanan if (res->list[end++] & ICE_RES_VALID_BIT) { 23835153a18eSAnirudh Venkataramanan start = end; 2384cbe66bfeSBrett Creeley if ((start + needed) > res->end) 23855153a18eSAnirudh Venkataramanan break; 23865153a18eSAnirudh Venkataramanan } 23875153a18eSAnirudh Venkataramanan 23885153a18eSAnirudh Venkataramanan if (end == (start + needed)) { 23895153a18eSAnirudh Venkataramanan int i = start; 23905153a18eSAnirudh Venkataramanan 23915153a18eSAnirudh Venkataramanan /* there was enough, so assign it to the requestor */ 23925153a18eSAnirudh Venkataramanan while (i != end) 23935153a18eSAnirudh Venkataramanan res->list[i++] = id; 23945153a18eSAnirudh Venkataramanan 23955153a18eSAnirudh Venkataramanan return start; 23965153a18eSAnirudh Venkataramanan } 2397cbe66bfeSBrett Creeley } while (end < res->end); 23985153a18eSAnirudh Venkataramanan 23995153a18eSAnirudh Venkataramanan return -ENOMEM; 24005153a18eSAnirudh Venkataramanan } 24015153a18eSAnirudh Venkataramanan 24025153a18eSAnirudh Venkataramanan /** 24035153a18eSAnirudh Venkataramanan * ice_get_res - get a block of resources 24045153a18eSAnirudh Venkataramanan * @pf: board private structure 24055153a18eSAnirudh Venkataramanan * @res: pointer to the resource 24065153a18eSAnirudh Venkataramanan * @needed: size of the block needed 24075153a18eSAnirudh Venkataramanan * @id: identifier to track owner 24085153a18eSAnirudh Venkataramanan * 2409cbe66bfeSBrett Creeley * Returns the base item index of the block, or negative for error 24105153a18eSAnirudh Venkataramanan */ 24115153a18eSAnirudh Venkataramanan int 24125153a18eSAnirudh Venkataramanan ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) 24135153a18eSAnirudh Venkataramanan { 24145153a18eSAnirudh Venkataramanan if (!res || !pf) 24155153a18eSAnirudh Venkataramanan return -EINVAL; 24165153a18eSAnirudh Venkataramanan 24175153a18eSAnirudh Venkataramanan if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { 241819cce2c6SAnirudh Venkataramanan dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n", 24195153a18eSAnirudh Venkataramanan needed, res->num_entries, id); 24205153a18eSAnirudh Venkataramanan return -EINVAL; 24215153a18eSAnirudh Venkataramanan } 24225153a18eSAnirudh Venkataramanan 2423cbe66bfeSBrett Creeley return ice_search_res(res, needed, id); 24245153a18eSAnirudh Venkataramanan } 24255153a18eSAnirudh Venkataramanan 24265153a18eSAnirudh Venkataramanan /** 24275153a18eSAnirudh Venkataramanan * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI 24285153a18eSAnirudh Venkataramanan * @vsi: the VSI being un-configured 24295153a18eSAnirudh Venkataramanan */ 24305153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi) 24315153a18eSAnirudh Venkataramanan { 2432cbe66bfeSBrett Creeley int base = vsi->base_vector; 24335153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 24345153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 24355153a18eSAnirudh Venkataramanan u32 val; 24365153a18eSAnirudh Venkataramanan int i; 24375153a18eSAnirudh Venkataramanan 24385153a18eSAnirudh Venkataramanan /* disable interrupt causation from each queue */ 24395153a18eSAnirudh Venkataramanan if (vsi->tx_rings) { 24405153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 24415153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i]) { 24425153a18eSAnirudh Venkataramanan u16 reg; 24435153a18eSAnirudh Venkataramanan 24445153a18eSAnirudh Venkataramanan reg = vsi->tx_rings[i]->reg_idx; 24455153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(reg)); 24465153a18eSAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 24475153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(reg), val); 24485153a18eSAnirudh Venkataramanan } 24495153a18eSAnirudh Venkataramanan } 24505153a18eSAnirudh Venkataramanan } 24515153a18eSAnirudh Venkataramanan 24525153a18eSAnirudh Venkataramanan if (vsi->rx_rings) { 24535153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 24545153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i]) { 24555153a18eSAnirudh Venkataramanan u16 reg; 24565153a18eSAnirudh Venkataramanan 24575153a18eSAnirudh Venkataramanan reg = vsi->rx_rings[i]->reg_idx; 24585153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_RQCTL(reg)); 24595153a18eSAnirudh Venkataramanan val &= ~QINT_RQCTL_CAUSE_ENA_M; 24605153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(reg), val); 24615153a18eSAnirudh Venkataramanan } 24625153a18eSAnirudh Venkataramanan } 24635153a18eSAnirudh Venkataramanan } 24645153a18eSAnirudh Venkataramanan 24655153a18eSAnirudh Venkataramanan /* disable each interrupt */ 2466462acf6aSTony Nguyen ice_for_each_q_vector(vsi, i) { 2467462acf6aSTony Nguyen if (!vsi->q_vectors[i]) 2468462acf6aSTony Nguyen continue; 2469b07833a0SBrett Creeley wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); 2470462acf6aSTony Nguyen } 24715153a18eSAnirudh Venkataramanan 24725153a18eSAnirudh Venkataramanan ice_flush(hw); 2473b07833a0SBrett Creeley 2474da4a9e73SBrett Creeley /* don't call synchronize_irq() for VF's from the host */ 2475da4a9e73SBrett Creeley if (vsi->type == ICE_VSI_VF) 2476da4a9e73SBrett Creeley return; 2477da4a9e73SBrett Creeley 24780c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) 24795153a18eSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[i + base].vector); 24805153a18eSAnirudh Venkataramanan } 24815153a18eSAnirudh Venkataramanan 24825153a18eSAnirudh Venkataramanan /** 2483561f4379STony Nguyen * ice_napi_del - Remove NAPI handler for the VSI 2484561f4379STony Nguyen * @vsi: VSI for which NAPI handler is to be removed 2485561f4379STony Nguyen */ 2486561f4379STony Nguyen void ice_napi_del(struct ice_vsi *vsi) 2487561f4379STony Nguyen { 2488561f4379STony Nguyen int v_idx; 2489561f4379STony Nguyen 2490561f4379STony Nguyen if (!vsi->netdev) 2491561f4379STony Nguyen return; 2492561f4379STony Nguyen 2493561f4379STony Nguyen ice_for_each_q_vector(vsi, v_idx) 2494561f4379STony Nguyen netif_napi_del(&vsi->q_vectors[v_idx]->napi); 2495561f4379STony Nguyen } 2496561f4379STony Nguyen 2497561f4379STony Nguyen /** 2498df0f8479SAnirudh Venkataramanan * ice_vsi_release - Delete a VSI and free its resources 2499df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 2500df0f8479SAnirudh Venkataramanan * 2501df0f8479SAnirudh Venkataramanan * Returns 0 on success or < 0 on error 2502df0f8479SAnirudh Venkataramanan */ 2503df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi) 2504df0f8479SAnirudh Venkataramanan { 2505df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 2506df0f8479SAnirudh Venkataramanan 2507df0f8479SAnirudh Venkataramanan if (!vsi->back) 2508df0f8479SAnirudh Venkataramanan return -ENODEV; 2509df0f8479SAnirudh Venkataramanan pf = vsi->back; 2510b751930cSBrett Creeley 2511aa6ccf3fSBrett Creeley /* do not unregister while driver is in the reset recovery pending 2512aa6ccf3fSBrett Creeley * state. Since reset/rebuild happens through PF service task workqueue, 2513aa6ccf3fSBrett Creeley * it's not a good idea to unregister netdev that is associated to the 2514aa6ccf3fSBrett Creeley * PF that is running the work queue items currently. This is done to 2515aa6ccf3fSBrett Creeley * avoid check_flush_dependency() warning on this wq 2516df0f8479SAnirudh Venkataramanan */ 2517aa6ccf3fSBrett Creeley if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) 2518df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2519df0f8479SAnirudh Venkataramanan 2520df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 2521df0f8479SAnirudh Venkataramanan ice_rss_clean(vsi); 2522df0f8479SAnirudh Venkataramanan 2523df0f8479SAnirudh Venkataramanan /* Disable VSI and free resources */ 25240e674aebSAnirudh Venkataramanan if (vsi->type != ICE_VSI_LB) 2525df0f8479SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 2526df0f8479SAnirudh Venkataramanan ice_vsi_close(vsi); 2527df0f8479SAnirudh Venkataramanan 2528cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 2529cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 2530cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 2531cbe66bfeSBrett Creeley * cleared in the same manner. 2532cbe66bfeSBrett Creeley */ 25338ede0178SAnirudh Venkataramanan if (vsi->type != ICE_VSI_VF) { 25348ede0178SAnirudh Venkataramanan /* reclaim SW interrupts back to the common pool */ 2535cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 2536eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 25378ede0178SAnirudh Venkataramanan } 2538df0f8479SAnirudh Venkataramanan 2539462acf6aSTony Nguyen if (!ice_is_safe_mode(pf)) { 25402e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 2541d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(vsi, false); 25422e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, false); 25432e0e6228SDave Ertman /* The Rx rule will only exist to remove if the LLDP FW 25442e0e6228SDave Ertman * engine is currently stopped 25452e0e6228SDave Ertman */ 254684a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) 25472e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, false); 25482e0e6228SDave Ertman } 2549462acf6aSTony Nguyen } 2550d95276ceSAkeem G Abodunrin 25515726ca0eSAnirudh Venkataramanan ice_remove_vsi_fltr(&pf->hw, vsi->idx); 255210e03a22SAnirudh Venkataramanan ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2553df0f8479SAnirudh Venkataramanan ice_vsi_delete(vsi); 2554df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2555aa6ccf3fSBrett Creeley 2556aa6ccf3fSBrett Creeley /* make sure unregister_netdev() was called by checking __ICE_DOWN */ 2557aa6ccf3fSBrett Creeley if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) { 2558aa6ccf3fSBrett Creeley free_netdev(vsi->netdev); 2559aa6ccf3fSBrett Creeley vsi->netdev = NULL; 2560aa6ccf3fSBrett Creeley } 2561aa6ccf3fSBrett Creeley 2562df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2563df0f8479SAnirudh Venkataramanan 2564df0f8479SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2565df0f8479SAnirudh Venkataramanan 2566df0f8479SAnirudh Venkataramanan /* retain SW VSI data structure since it is needed to unregister and 2567df0f8479SAnirudh Venkataramanan * free VSI netdev when PF is not in reset recovery pending state,\ 2568df0f8479SAnirudh Venkataramanan * for ex: during rmmod. 2569df0f8479SAnirudh Venkataramanan */ 25705df7e45dSDave Ertman if (!ice_is_reset_in_progress(pf->state)) 2571df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2572df0f8479SAnirudh Venkataramanan 2573df0f8479SAnirudh Venkataramanan return 0; 2574df0f8479SAnirudh Venkataramanan } 2575df0f8479SAnirudh Venkataramanan 2576df0f8479SAnirudh Venkataramanan /** 257761dc79ceSMichal Swiatkowski * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector 257861dc79ceSMichal Swiatkowski * @q_vector: pointer to q_vector which is being updated 257961dc79ceSMichal Swiatkowski * @coalesce: pointer to array of struct with stored coalesce 258061dc79ceSMichal Swiatkowski * 258161dc79ceSMichal Swiatkowski * Set coalesce param in q_vector and update these parameters in HW. 258261dc79ceSMichal Swiatkowski */ 258361dc79ceSMichal Swiatkowski static void 258461dc79ceSMichal Swiatkowski ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector, 258561dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce) 258661dc79ceSMichal Swiatkowski { 258761dc79ceSMichal Swiatkowski struct ice_ring_container *rx_rc = &q_vector->rx; 258861dc79ceSMichal Swiatkowski struct ice_ring_container *tx_rc = &q_vector->tx; 258961dc79ceSMichal Swiatkowski struct ice_hw *hw = &q_vector->vsi->back->hw; 259061dc79ceSMichal Swiatkowski 259161dc79ceSMichal Swiatkowski tx_rc->itr_setting = coalesce->itr_tx; 259261dc79ceSMichal Swiatkowski rx_rc->itr_setting = coalesce->itr_rx; 259361dc79ceSMichal Swiatkowski 259461dc79ceSMichal Swiatkowski /* dynamic ITR values will be updated during Tx/Rx */ 259561dc79ceSMichal Swiatkowski if (!ITR_IS_DYNAMIC(tx_rc->itr_setting)) 259661dc79ceSMichal Swiatkowski wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx), 259761dc79ceSMichal Swiatkowski ITR_REG_ALIGN(tx_rc->itr_setting) >> 259861dc79ceSMichal Swiatkowski ICE_ITR_GRAN_S); 259961dc79ceSMichal Swiatkowski if (!ITR_IS_DYNAMIC(rx_rc->itr_setting)) 260061dc79ceSMichal Swiatkowski wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx), 260161dc79ceSMichal Swiatkowski ITR_REG_ALIGN(rx_rc->itr_setting) >> 260261dc79ceSMichal Swiatkowski ICE_ITR_GRAN_S); 260361dc79ceSMichal Swiatkowski 260461dc79ceSMichal Swiatkowski q_vector->intrl = coalesce->intrl; 260561dc79ceSMichal Swiatkowski wr32(hw, GLINT_RATE(q_vector->reg_idx), 260661dc79ceSMichal Swiatkowski ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran)); 260761dc79ceSMichal Swiatkowski } 260861dc79ceSMichal Swiatkowski 260961dc79ceSMichal Swiatkowski /** 261061dc79ceSMichal Swiatkowski * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors 261161dc79ceSMichal Swiatkowski * @vsi: VSI connected with q_vectors 261261dc79ceSMichal Swiatkowski * @coalesce: array of struct with stored coalesce 261361dc79ceSMichal Swiatkowski * 261461dc79ceSMichal Swiatkowski * Returns array size. 261561dc79ceSMichal Swiatkowski */ 261661dc79ceSMichal Swiatkowski static int 261761dc79ceSMichal Swiatkowski ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi, 261861dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce) 261961dc79ceSMichal Swiatkowski { 262061dc79ceSMichal Swiatkowski int i; 262161dc79ceSMichal Swiatkowski 262261dc79ceSMichal Swiatkowski ice_for_each_q_vector(vsi, i) { 262361dc79ceSMichal Swiatkowski struct ice_q_vector *q_vector = vsi->q_vectors[i]; 262461dc79ceSMichal Swiatkowski 262561dc79ceSMichal Swiatkowski coalesce[i].itr_tx = q_vector->tx.itr_setting; 262661dc79ceSMichal Swiatkowski coalesce[i].itr_rx = q_vector->rx.itr_setting; 262761dc79ceSMichal Swiatkowski coalesce[i].intrl = q_vector->intrl; 262861dc79ceSMichal Swiatkowski } 262961dc79ceSMichal Swiatkowski 263061dc79ceSMichal Swiatkowski return vsi->num_q_vectors; 263161dc79ceSMichal Swiatkowski } 263261dc79ceSMichal Swiatkowski 263361dc79ceSMichal Swiatkowski /** 263461dc79ceSMichal Swiatkowski * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays 263561dc79ceSMichal Swiatkowski * @vsi: VSI connected with q_vectors 263661dc79ceSMichal Swiatkowski * @coalesce: pointer to array of struct with stored coalesce 263761dc79ceSMichal Swiatkowski * @size: size of coalesce array 263861dc79ceSMichal Swiatkowski * 263961dc79ceSMichal Swiatkowski * Before this function, ice_vsi_rebuild_get_coalesce should be called to save 264061dc79ceSMichal Swiatkowski * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce 264161dc79ceSMichal Swiatkowski * to default value. 264261dc79ceSMichal Swiatkowski */ 264361dc79ceSMichal Swiatkowski static void 264461dc79ceSMichal Swiatkowski ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi, 264561dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce, int size) 264661dc79ceSMichal Swiatkowski { 264761dc79ceSMichal Swiatkowski int i; 264861dc79ceSMichal Swiatkowski 264961dc79ceSMichal Swiatkowski if ((size && !coalesce) || !vsi) 265061dc79ceSMichal Swiatkowski return; 265161dc79ceSMichal Swiatkowski 265261dc79ceSMichal Swiatkowski for (i = 0; i < size && i < vsi->num_q_vectors; i++) 265361dc79ceSMichal Swiatkowski ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], 265461dc79ceSMichal Swiatkowski &coalesce[i]); 265561dc79ceSMichal Swiatkowski 265661dc79ceSMichal Swiatkowski for (; i < vsi->num_q_vectors; i++) { 265761dc79ceSMichal Swiatkowski struct ice_coalesce_stored coalesce_dflt = { 265861dc79ceSMichal Swiatkowski .itr_tx = ICE_DFLT_TX_ITR, 265961dc79ceSMichal Swiatkowski .itr_rx = ICE_DFLT_RX_ITR, 266061dc79ceSMichal Swiatkowski .intrl = 0 266161dc79ceSMichal Swiatkowski }; 266261dc79ceSMichal Swiatkowski ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i], 266361dc79ceSMichal Swiatkowski &coalesce_dflt); 266461dc79ceSMichal Swiatkowski } 266561dc79ceSMichal Swiatkowski } 266661dc79ceSMichal Swiatkowski 266761dc79ceSMichal Swiatkowski /** 2668df0f8479SAnirudh Venkataramanan * ice_vsi_rebuild - Rebuild VSI after reset 2669df0f8479SAnirudh Venkataramanan * @vsi: VSI to be rebuild 267087324e74SHenry Tieman * @init_vsi: is this an initialization or a reconfigure of the VSI 2671df0f8479SAnirudh Venkataramanan * 2672df0f8479SAnirudh Venkataramanan * Returns 0 on success and negative value on failure 2673df0f8479SAnirudh Venkataramanan */ 267487324e74SHenry Tieman int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) 2675df0f8479SAnirudh Venkataramanan { 2676df0f8479SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 267761dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce; 267861dc79ceSMichal Swiatkowski int prev_num_q_vectors = 0; 26797eeac889SAkeem G Abodunrin struct ice_vf *vf = NULL; 2680d31530e8SAkeem G Abodunrin enum ice_status status; 2681c5a2a4a3SUsha Ketineni struct ice_pf *pf; 2682df0f8479SAnirudh Venkataramanan int ret, i; 2683df0f8479SAnirudh Venkataramanan 2684df0f8479SAnirudh Venkataramanan if (!vsi) 2685df0f8479SAnirudh Venkataramanan return -EINVAL; 2686df0f8479SAnirudh Venkataramanan 2687c5a2a4a3SUsha Ketineni pf = vsi->back; 26887eeac889SAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 26897eeac889SAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 26907eeac889SAkeem G Abodunrin 269161dc79ceSMichal Swiatkowski coalesce = kcalloc(vsi->num_q_vectors, 269261dc79ceSMichal Swiatkowski sizeof(struct ice_coalesce_stored), GFP_KERNEL); 269361dc79ceSMichal Swiatkowski if (coalesce) 269461dc79ceSMichal Swiatkowski prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, 269561dc79ceSMichal Swiatkowski coalesce); 269647e3e53cSHenry Tieman ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 2697df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 26987eeac889SAkeem G Abodunrin 2699cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 2700cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 2701cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 2702cbe66bfeSBrett Creeley * cleared in the same manner. 2703cbe66bfeSBrett Creeley */ 27047eeac889SAkeem G Abodunrin if (vsi->type != ICE_VSI_VF) { 27057eeac889SAkeem G Abodunrin /* reclaim SW interrupts back to the common pool */ 2706cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 27077eeac889SAkeem G Abodunrin pf->num_avail_sw_msix += vsi->num_q_vectors; 2708cbe66bfeSBrett Creeley vsi->base_vector = 0; 27097eeac889SAkeem G Abodunrin } 27107eeac889SAkeem G Abodunrin 2711efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) 2712efc2214bSMaciej Fijalkowski /* return value check can be skipped here, it always returns 2713efc2214bSMaciej Fijalkowski * 0 if reset is in progress 2714efc2214bSMaciej Fijalkowski */ 2715efc2214bSMaciej Fijalkowski ice_destroy_xdp_rings(vsi); 271678b5713aSAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2717df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 2718a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 27195743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 27205743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf->vf_id); 27215743020dSAkeem G Abodunrin else 27225743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 272378b5713aSAnirudh Venkataramanan 272478b5713aSAnirudh Venkataramanan ret = ice_vsi_alloc_arrays(vsi); 272578b5713aSAnirudh Venkataramanan if (ret < 0) 272678b5713aSAnirudh Venkataramanan goto err_vsi; 272778b5713aSAnirudh Venkataramanan 272878b5713aSAnirudh Venkataramanan ice_vsi_get_qs(vsi); 2729c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2730df0f8479SAnirudh Venkataramanan 2731df0f8479SAnirudh Venkataramanan /* Initialize VSI struct elements and create VSI in FW */ 273287324e74SHenry Tieman ret = ice_vsi_init(vsi, init_vsi); 2733df0f8479SAnirudh Venkataramanan if (ret < 0) 2734df0f8479SAnirudh Venkataramanan goto err_vsi; 2735df0f8479SAnirudh Venkataramanan 2736df0f8479SAnirudh Venkataramanan switch (vsi->type) { 2737df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 2738df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 2739df0f8479SAnirudh Venkataramanan if (ret) 2740df0f8479SAnirudh Venkataramanan goto err_rings; 2741df0f8479SAnirudh Venkataramanan 274217bc6d07STony Nguyen ret = ice_vsi_setup_vector_base(vsi); 274317bc6d07STony Nguyen if (ret) 274417bc6d07STony Nguyen goto err_vectors; 274517bc6d07STony Nguyen 2746b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2747b07833a0SBrett Creeley if (ret) 2748b07833a0SBrett Creeley goto err_vectors; 2749b07833a0SBrett Creeley 2750df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 2751df0f8479SAnirudh Venkataramanan if (ret) 2752df0f8479SAnirudh Venkataramanan goto err_vectors; 2753df0f8479SAnirudh Venkataramanan 2754df0f8479SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 2755efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) { 2756efc2214bSMaciej Fijalkowski vsi->num_xdp_txq = vsi->alloc_txq; 2757efc2214bSMaciej Fijalkowski ret = ice_prepare_xdp_rings(vsi, vsi->xdp_prog); 2758efc2214bSMaciej Fijalkowski if (ret) 2759efc2214bSMaciej Fijalkowski goto err_vectors; 2760efc2214bSMaciej Fijalkowski } 276127a98affSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 276227a98affSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 276327a98affSMd Fahad Iqbal Polash * return value 276427a98affSMd Fahad Iqbal Polash */ 2765819d8998SJesse Brandeburg if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 276627a98affSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 2767df0f8479SAnirudh Venkataramanan break; 27688ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 27698ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 27708ede0178SAnirudh Venkataramanan if (ret) 27718ede0178SAnirudh Venkataramanan goto err_rings; 27728ede0178SAnirudh Venkataramanan 2773b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2774b07833a0SBrett Creeley if (ret) 2775b07833a0SBrett Creeley goto err_vectors; 2776b07833a0SBrett Creeley 27778ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 27788ede0178SAnirudh Venkataramanan if (ret) 27798ede0178SAnirudh Venkataramanan goto err_vectors; 27808ede0178SAnirudh Venkataramanan 27818ede0178SAnirudh Venkataramanan break; 2782df0f8479SAnirudh Venkataramanan default: 2783df0f8479SAnirudh Venkataramanan break; 2784df0f8479SAnirudh Venkataramanan } 2785df0f8479SAnirudh Venkataramanan 2786df0f8479SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 2787efc2214bSMaciej Fijalkowski for (i = 0; i < vsi->tc_cfg.numtc; i++) { 2788d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 2789df0f8479SAnirudh Venkataramanan 2790efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) 2791efc2214bSMaciej Fijalkowski max_txqs[i] += vsi->num_xdp_txq; 2792efc2214bSMaciej Fijalkowski } 2793efc2214bSMaciej Fijalkowski 2794d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 27954fb33f31SAnirudh Venkataramanan max_txqs); 2796d31530e8SAkeem G Abodunrin if (status) { 279719cce2c6SAnirudh Venkataramanan dev_err(ice_pf_to_dev(pf), "VSI %d failed lan queue config, error %d\n", 2798d31530e8SAkeem G Abodunrin vsi->vsi_num, status); 279987324e74SHenry Tieman if (init_vsi) { 280087324e74SHenry Tieman ret = -EIO; 2801df0f8479SAnirudh Venkataramanan goto err_vectors; 280287324e74SHenry Tieman } else { 280387324e74SHenry Tieman return ice_schedule_reset(pf, ICE_RESET_PFR); 280487324e74SHenry Tieman } 2805df0f8479SAnirudh Venkataramanan } 280661dc79ceSMichal Swiatkowski ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors); 280761dc79ceSMichal Swiatkowski kfree(coalesce); 280861dc79ceSMichal Swiatkowski 2809df0f8479SAnirudh Venkataramanan return 0; 2810df0f8479SAnirudh Venkataramanan 2811df0f8479SAnirudh Venkataramanan err_vectors: 2812df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 2813df0f8479SAnirudh Venkataramanan err_rings: 2814df0f8479SAnirudh Venkataramanan if (vsi->netdev) { 2815df0f8479SAnirudh Venkataramanan vsi->current_netdev_flags = 0; 2816df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 2817df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 2818df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 2819df0f8479SAnirudh Venkataramanan } 2820df0f8479SAnirudh Venkataramanan err_vsi: 2821df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 2822819d8998SJesse Brandeburg set_bit(__ICE_RESET_FAILED, pf->state); 282361dc79ceSMichal Swiatkowski kfree(coalesce); 2824df0f8479SAnirudh Venkataramanan return ret; 2825df0f8479SAnirudh Venkataramanan } 2826df0f8479SAnirudh Venkataramanan 2827df0f8479SAnirudh Venkataramanan /** 28285df7e45dSDave Ertman * ice_is_reset_in_progress - check for a reset in progress 28292f2da36eSAnirudh Venkataramanan * @state: PF state field 28305153a18eSAnirudh Venkataramanan */ 28315df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state) 28325153a18eSAnirudh Venkataramanan { 28335df7e45dSDave Ertman return test_bit(__ICE_RESET_OICR_RECV, state) || 2834b94b013eSDave Ertman test_bit(__ICE_DCBNL_DEVRESET, state) || 28355df7e45dSDave Ertman test_bit(__ICE_PFR_REQ, state) || 28365df7e45dSDave Ertman test_bit(__ICE_CORER_REQ, state) || 28375df7e45dSDave Ertman test_bit(__ICE_GLOBR_REQ, state); 28385153a18eSAnirudh Venkataramanan } 28397b9ffc76SAnirudh Venkataramanan 28407b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB 28417b9ffc76SAnirudh Venkataramanan /** 28427b9ffc76SAnirudh Venkataramanan * ice_vsi_update_q_map - update our copy of the VSI info with new queue map 28437b9ffc76SAnirudh Venkataramanan * @vsi: VSI being configured 28447b9ffc76SAnirudh Venkataramanan * @ctx: the context buffer returned from AQ VSI update command 28457b9ffc76SAnirudh Venkataramanan */ 28467b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx) 28477b9ffc76SAnirudh Venkataramanan { 28487b9ffc76SAnirudh Venkataramanan vsi->info.mapping_flags = ctx->info.mapping_flags; 28497b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping, 28507b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.q_mapping)); 28517b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping, 28527b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.tc_mapping)); 28537b9ffc76SAnirudh Venkataramanan } 28547b9ffc76SAnirudh Venkataramanan 28557b9ffc76SAnirudh Venkataramanan /** 28567b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map 28577b9ffc76SAnirudh Venkataramanan * @vsi: VSI to be configured 28587b9ffc76SAnirudh Venkataramanan * @ena_tc: TC bitmap 28597b9ffc76SAnirudh Venkataramanan * 28607b9ffc76SAnirudh Venkataramanan * VSI queues expected to be quiesced before calling this function 28617b9ffc76SAnirudh Venkataramanan */ 28627b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) 28637b9ffc76SAnirudh Venkataramanan { 28647b9ffc76SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 28657b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 28664ee656bbSTony Nguyen struct ice_vsi_ctx *ctx; 28677b9ffc76SAnirudh Venkataramanan enum ice_status status; 28684015d11eSBrett Creeley struct device *dev; 28697b9ffc76SAnirudh Venkataramanan int i, ret = 0; 28707b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 28717b9ffc76SAnirudh Venkataramanan 28724015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 28734015d11eSBrett Creeley 28747b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) { 28757b9ffc76SAnirudh Venkataramanan /* build bitmap of enabled TCs */ 28767b9ffc76SAnirudh Venkataramanan if (ena_tc & BIT(i)) 28777b9ffc76SAnirudh Venkataramanan num_tc++; 28787b9ffc76SAnirudh Venkataramanan /* populate max_txqs per TC */ 2879d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 28807b9ffc76SAnirudh Venkataramanan } 28817b9ffc76SAnirudh Venkataramanan 28827b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ena_tc; 28837b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = num_tc; 28847b9ffc76SAnirudh Venkataramanan 28859efe35d0STony Nguyen ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 28867b9ffc76SAnirudh Venkataramanan if (!ctx) 28877b9ffc76SAnirudh Venkataramanan return -ENOMEM; 28887b9ffc76SAnirudh Venkataramanan 28897b9ffc76SAnirudh Venkataramanan ctx->vf_num = 0; 28907b9ffc76SAnirudh Venkataramanan ctx->info = vsi->info; 28917b9ffc76SAnirudh Venkataramanan 28927b9ffc76SAnirudh Venkataramanan ice_vsi_setup_q_map(vsi, ctx); 28937b9ffc76SAnirudh Venkataramanan 28947b9ffc76SAnirudh Venkataramanan /* must to indicate which section of VSI context are being modified */ 28957b9ffc76SAnirudh Venkataramanan ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 28967b9ffc76SAnirudh Venkataramanan status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL); 28977b9ffc76SAnirudh Venkataramanan if (status) { 28984015d11eSBrett Creeley dev_info(dev, "Failed VSI Update\n"); 28997b9ffc76SAnirudh Venkataramanan ret = -EIO; 29007b9ffc76SAnirudh Venkataramanan goto out; 29017b9ffc76SAnirudh Venkataramanan } 29027b9ffc76SAnirudh Venkataramanan 29037b9ffc76SAnirudh Venkataramanan status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 29047b9ffc76SAnirudh Venkataramanan max_txqs); 29057b9ffc76SAnirudh Venkataramanan 29067b9ffc76SAnirudh Venkataramanan if (status) { 29074015d11eSBrett Creeley dev_err(dev, "VSI %d failed TC config, error %d\n", 29087b9ffc76SAnirudh Venkataramanan vsi->vsi_num, status); 29097b9ffc76SAnirudh Venkataramanan ret = -EIO; 29107b9ffc76SAnirudh Venkataramanan goto out; 29117b9ffc76SAnirudh Venkataramanan } 29127b9ffc76SAnirudh Venkataramanan ice_vsi_update_q_map(vsi, ctx); 29137b9ffc76SAnirudh Venkataramanan vsi->info.valid_sections = 0; 29147b9ffc76SAnirudh Venkataramanan 29157b9ffc76SAnirudh Venkataramanan ice_vsi_cfg_netdev_tc(vsi, ena_tc); 29167b9ffc76SAnirudh Venkataramanan out: 29179efe35d0STony Nguyen kfree(ctx); 29187b9ffc76SAnirudh Venkataramanan return ret; 29197b9ffc76SAnirudh Venkataramanan } 29207b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */ 2921bbb968e8SAkeem G Abodunrin 2922bbb968e8SAkeem G Abodunrin /** 29232d4238f5SKrzysztof Kazimierczak * ice_update_ring_stats - Update ring statistics 29242d4238f5SKrzysztof Kazimierczak * @ring: ring to update 29252d4238f5SKrzysztof Kazimierczak * @cont: used to increment per-vector counters 29262d4238f5SKrzysztof Kazimierczak * @pkts: number of processed packets 29272d4238f5SKrzysztof Kazimierczak * @bytes: number of processed bytes 29282d4238f5SKrzysztof Kazimierczak * 29292d4238f5SKrzysztof Kazimierczak * This function assumes that caller has acquired a u64_stats_sync lock. 29302d4238f5SKrzysztof Kazimierczak */ 29312d4238f5SKrzysztof Kazimierczak static void 29322d4238f5SKrzysztof Kazimierczak ice_update_ring_stats(struct ice_ring *ring, struct ice_ring_container *cont, 29332d4238f5SKrzysztof Kazimierczak u64 pkts, u64 bytes) 29342d4238f5SKrzysztof Kazimierczak { 29352d4238f5SKrzysztof Kazimierczak ring->stats.bytes += bytes; 29362d4238f5SKrzysztof Kazimierczak ring->stats.pkts += pkts; 29372d4238f5SKrzysztof Kazimierczak cont->total_bytes += bytes; 29382d4238f5SKrzysztof Kazimierczak cont->total_pkts += pkts; 29392d4238f5SKrzysztof Kazimierczak } 29402d4238f5SKrzysztof Kazimierczak 29412d4238f5SKrzysztof Kazimierczak /** 29422d4238f5SKrzysztof Kazimierczak * ice_update_tx_ring_stats - Update Tx ring specific counters 29432d4238f5SKrzysztof Kazimierczak * @tx_ring: ring to update 29442d4238f5SKrzysztof Kazimierczak * @pkts: number of processed packets 29452d4238f5SKrzysztof Kazimierczak * @bytes: number of processed bytes 29462d4238f5SKrzysztof Kazimierczak */ 29472d4238f5SKrzysztof Kazimierczak void ice_update_tx_ring_stats(struct ice_ring *tx_ring, u64 pkts, u64 bytes) 29482d4238f5SKrzysztof Kazimierczak { 29492d4238f5SKrzysztof Kazimierczak u64_stats_update_begin(&tx_ring->syncp); 29502d4238f5SKrzysztof Kazimierczak ice_update_ring_stats(tx_ring, &tx_ring->q_vector->tx, pkts, bytes); 29512d4238f5SKrzysztof Kazimierczak u64_stats_update_end(&tx_ring->syncp); 29522d4238f5SKrzysztof Kazimierczak } 29532d4238f5SKrzysztof Kazimierczak 29542d4238f5SKrzysztof Kazimierczak /** 29552d4238f5SKrzysztof Kazimierczak * ice_update_rx_ring_stats - Update Rx ring specific counters 29562d4238f5SKrzysztof Kazimierczak * @rx_ring: ring to update 29572d4238f5SKrzysztof Kazimierczak * @pkts: number of processed packets 29582d4238f5SKrzysztof Kazimierczak * @bytes: number of processed bytes 29592d4238f5SKrzysztof Kazimierczak */ 29602d4238f5SKrzysztof Kazimierczak void ice_update_rx_ring_stats(struct ice_ring *rx_ring, u64 pkts, u64 bytes) 29612d4238f5SKrzysztof Kazimierczak { 29622d4238f5SKrzysztof Kazimierczak u64_stats_update_begin(&rx_ring->syncp); 29632d4238f5SKrzysztof Kazimierczak ice_update_ring_stats(rx_ring, &rx_ring->q_vector->rx, pkts, bytes); 29642d4238f5SKrzysztof Kazimierczak u64_stats_update_end(&rx_ring->syncp); 29652d4238f5SKrzysztof Kazimierczak } 29662d4238f5SKrzysztof Kazimierczak 29672d4238f5SKrzysztof Kazimierczak /** 2968bbb968e8SAkeem G Abodunrin * ice_vsi_cfg_mac_fltr - Add or remove a MAC address filter for a VSI 2969bbb968e8SAkeem G Abodunrin * @vsi: the VSI being configured MAC filter 2970bbb968e8SAkeem G Abodunrin * @macaddr: the MAC address to be added. 2971bbb968e8SAkeem G Abodunrin * @set: Add or delete a MAC filter 2972bbb968e8SAkeem G Abodunrin * 2973bbb968e8SAkeem G Abodunrin * Adds or removes MAC address filter entry for VF VSI 2974bbb968e8SAkeem G Abodunrin */ 2975bbb968e8SAkeem G Abodunrin enum ice_status 2976bbb968e8SAkeem G Abodunrin ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set) 2977bbb968e8SAkeem G Abodunrin { 2978bbb968e8SAkeem G Abodunrin LIST_HEAD(tmp_add_list); 2979bbb968e8SAkeem G Abodunrin enum ice_status status; 2980bbb968e8SAkeem G Abodunrin 2981bbb968e8SAkeem G Abodunrin /* Update MAC filter list to be added or removed for a VSI */ 2982bbb968e8SAkeem G Abodunrin if (ice_add_mac_to_list(vsi, &tmp_add_list, macaddr)) { 2983bbb968e8SAkeem G Abodunrin status = ICE_ERR_NO_MEMORY; 2984bbb968e8SAkeem G Abodunrin goto cfg_mac_fltr_exit; 2985bbb968e8SAkeem G Abodunrin } 2986bbb968e8SAkeem G Abodunrin 2987bbb968e8SAkeem G Abodunrin if (set) 2988bbb968e8SAkeem G Abodunrin status = ice_add_mac(&vsi->back->hw, &tmp_add_list); 2989bbb968e8SAkeem G Abodunrin else 2990bbb968e8SAkeem G Abodunrin status = ice_remove_mac(&vsi->back->hw, &tmp_add_list); 2991bbb968e8SAkeem G Abodunrin 2992bbb968e8SAkeem G Abodunrin cfg_mac_fltr_exit: 29939a946843SAnirudh Venkataramanan ice_free_fltr_list(ice_pf_to_dev(vsi->back), &tmp_add_list); 2994bbb968e8SAkeem G Abodunrin return status; 2995bbb968e8SAkeem G Abodunrin } 2996fc0f39bcSBrett Creeley 2997fc0f39bcSBrett Creeley /** 2998fc0f39bcSBrett Creeley * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used 2999fc0f39bcSBrett Creeley * @sw: switch to check if its default forwarding VSI is free 3000fc0f39bcSBrett Creeley * 3001fc0f39bcSBrett Creeley * Return true if the default forwarding VSI is already being used, else returns 3002fc0f39bcSBrett Creeley * false signalling that it's available to use. 3003fc0f39bcSBrett Creeley */ 3004fc0f39bcSBrett Creeley bool ice_is_dflt_vsi_in_use(struct ice_sw *sw) 3005fc0f39bcSBrett Creeley { 3006fc0f39bcSBrett Creeley return (sw->dflt_vsi && sw->dflt_vsi_ena); 3007fc0f39bcSBrett Creeley } 3008fc0f39bcSBrett Creeley 3009fc0f39bcSBrett Creeley /** 3010fc0f39bcSBrett Creeley * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI 3011fc0f39bcSBrett Creeley * @sw: switch for the default forwarding VSI to compare against 3012fc0f39bcSBrett Creeley * @vsi: VSI to compare against default forwarding VSI 3013fc0f39bcSBrett Creeley * 3014fc0f39bcSBrett Creeley * If this VSI passed in is the default forwarding VSI then return true, else 3015fc0f39bcSBrett Creeley * return false 3016fc0f39bcSBrett Creeley */ 3017fc0f39bcSBrett Creeley bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi) 3018fc0f39bcSBrett Creeley { 3019fc0f39bcSBrett Creeley return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena); 3020fc0f39bcSBrett Creeley } 3021fc0f39bcSBrett Creeley 3022fc0f39bcSBrett Creeley /** 3023fc0f39bcSBrett Creeley * ice_set_dflt_vsi - set the default forwarding VSI 3024fc0f39bcSBrett Creeley * @sw: switch used to assign the default forwarding VSI 3025fc0f39bcSBrett Creeley * @vsi: VSI getting set as the default forwarding VSI on the switch 3026fc0f39bcSBrett Creeley * 3027fc0f39bcSBrett Creeley * If the VSI passed in is already the default VSI and it's enabled just return 3028fc0f39bcSBrett Creeley * success. 3029fc0f39bcSBrett Creeley * 3030fc0f39bcSBrett Creeley * If there is already a default VSI on the switch and it's enabled then return 3031fc0f39bcSBrett Creeley * -EEXIST since there can only be one default VSI per switch. 3032fc0f39bcSBrett Creeley * 3033fc0f39bcSBrett Creeley * Otherwise try to set the VSI passed in as the switch's default VSI and 3034fc0f39bcSBrett Creeley * return the result. 3035fc0f39bcSBrett Creeley */ 3036fc0f39bcSBrett Creeley int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi) 3037fc0f39bcSBrett Creeley { 3038fc0f39bcSBrett Creeley enum ice_status status; 3039fc0f39bcSBrett Creeley struct device *dev; 3040fc0f39bcSBrett Creeley 3041fc0f39bcSBrett Creeley if (!sw || !vsi) 3042fc0f39bcSBrett Creeley return -EINVAL; 3043fc0f39bcSBrett Creeley 3044fc0f39bcSBrett Creeley dev = ice_pf_to_dev(vsi->back); 3045fc0f39bcSBrett Creeley 3046fc0f39bcSBrett Creeley /* the VSI passed in is already the default VSI */ 3047fc0f39bcSBrett Creeley if (ice_is_vsi_dflt_vsi(sw, vsi)) { 3048fc0f39bcSBrett Creeley dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n", 3049fc0f39bcSBrett Creeley vsi->vsi_num); 3050fc0f39bcSBrett Creeley return 0; 3051fc0f39bcSBrett Creeley } 3052fc0f39bcSBrett Creeley 3053fc0f39bcSBrett Creeley /* another VSI is already the default VSI for this switch */ 3054fc0f39bcSBrett Creeley if (ice_is_dflt_vsi_in_use(sw)) { 305519cce2c6SAnirudh Venkataramanan dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n", 3056fc0f39bcSBrett Creeley sw->dflt_vsi->vsi_num); 3057fc0f39bcSBrett Creeley return -EEXIST; 3058fc0f39bcSBrett Creeley } 3059fc0f39bcSBrett Creeley 3060fc0f39bcSBrett Creeley status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX); 3061fc0f39bcSBrett Creeley if (status) { 306219cce2c6SAnirudh Venkataramanan dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n", 3063fc0f39bcSBrett Creeley vsi->vsi_num, status); 3064fc0f39bcSBrett Creeley return -EIO; 3065fc0f39bcSBrett Creeley } 3066fc0f39bcSBrett Creeley 3067fc0f39bcSBrett Creeley sw->dflt_vsi = vsi; 3068fc0f39bcSBrett Creeley sw->dflt_vsi_ena = true; 3069fc0f39bcSBrett Creeley 3070fc0f39bcSBrett Creeley return 0; 3071fc0f39bcSBrett Creeley } 3072fc0f39bcSBrett Creeley 3073fc0f39bcSBrett Creeley /** 3074fc0f39bcSBrett Creeley * ice_clear_dflt_vsi - clear the default forwarding VSI 3075fc0f39bcSBrett Creeley * @sw: switch used to clear the default VSI 3076fc0f39bcSBrett Creeley * 3077fc0f39bcSBrett Creeley * If the switch has no default VSI or it's not enabled then return error. 3078fc0f39bcSBrett Creeley * 3079fc0f39bcSBrett Creeley * Otherwise try to clear the default VSI and return the result. 3080fc0f39bcSBrett Creeley */ 3081fc0f39bcSBrett Creeley int ice_clear_dflt_vsi(struct ice_sw *sw) 3082fc0f39bcSBrett Creeley { 3083fc0f39bcSBrett Creeley struct ice_vsi *dflt_vsi; 3084fc0f39bcSBrett Creeley enum ice_status status; 3085fc0f39bcSBrett Creeley struct device *dev; 3086fc0f39bcSBrett Creeley 3087fc0f39bcSBrett Creeley if (!sw) 3088fc0f39bcSBrett Creeley return -EINVAL; 3089fc0f39bcSBrett Creeley 3090fc0f39bcSBrett Creeley dev = ice_pf_to_dev(sw->pf); 3091fc0f39bcSBrett Creeley 3092fc0f39bcSBrett Creeley dflt_vsi = sw->dflt_vsi; 3093fc0f39bcSBrett Creeley 3094fc0f39bcSBrett Creeley /* there is no default VSI configured */ 3095fc0f39bcSBrett Creeley if (!ice_is_dflt_vsi_in_use(sw)) 3096fc0f39bcSBrett Creeley return -ENODEV; 3097fc0f39bcSBrett Creeley 3098fc0f39bcSBrett Creeley status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false, 3099fc0f39bcSBrett Creeley ICE_FLTR_RX); 3100fc0f39bcSBrett Creeley if (status) { 310119cce2c6SAnirudh Venkataramanan dev_err(dev, "Failed to clear the default forwarding VSI %d, error %d\n", 3102fc0f39bcSBrett Creeley dflt_vsi->vsi_num, status); 3103fc0f39bcSBrett Creeley return -EIO; 3104fc0f39bcSBrett Creeley } 3105fc0f39bcSBrett Creeley 3106fc0f39bcSBrett Creeley sw->dflt_vsi = NULL; 3107fc0f39bcSBrett Creeley sw->dflt_vsi_ena = false; 3108fc0f39bcSBrett Creeley 3109fc0f39bcSBrett Creeley return 0; 3110fc0f39bcSBrett Creeley } 3111