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" 81b8f15b6SMichal Swiatkowski #include "ice_fltr.h" 97b9ffc76SAnirudh Venkataramanan #include "ice_dcb_lib.h" 1048d40025SJacob Keller #include "ice_devlink.h" 1145d3d428SAnirudh Venkataramanan 1245d3d428SAnirudh Venkataramanan /** 13964674f1SAnirudh Venkataramanan * ice_vsi_type_str - maps VSI type enum to string equivalents 146dae8aa0SBruce Allan * @vsi_type: VSI type enum 15964674f1SAnirudh Venkataramanan */ 166dae8aa0SBruce Allan const char *ice_vsi_type_str(enum ice_vsi_type vsi_type) 17964674f1SAnirudh Venkataramanan { 186dae8aa0SBruce Allan switch (vsi_type) { 19964674f1SAnirudh Venkataramanan case ICE_VSI_PF: 20964674f1SAnirudh Venkataramanan return "ICE_VSI_PF"; 21964674f1SAnirudh Venkataramanan case ICE_VSI_VF: 22964674f1SAnirudh Venkataramanan return "ICE_VSI_VF"; 23148beb61SHenry Tieman case ICE_VSI_CTRL: 24148beb61SHenry Tieman return "ICE_VSI_CTRL"; 250754d65bSKiran Patil case ICE_VSI_CHNL: 260754d65bSKiran Patil return "ICE_VSI_CHNL"; 27964674f1SAnirudh Venkataramanan case ICE_VSI_LB: 28964674f1SAnirudh Venkataramanan return "ICE_VSI_LB"; 29f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 30f66756e0SGrzegorz Nitka return "ICE_VSI_SWITCHDEV_CTRL"; 31964674f1SAnirudh Venkataramanan default: 32964674f1SAnirudh Venkataramanan return "unknown"; 33964674f1SAnirudh Venkataramanan } 34964674f1SAnirudh Venkataramanan } 35964674f1SAnirudh Venkataramanan 36964674f1SAnirudh Venkataramanan /** 3713a6233bSBrett Creeley * ice_vsi_ctrl_all_rx_rings - Start or stop a VSI's Rx rings 38d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 39d02f734cSMaciej Fijalkowski * @ena: start or stop the Rx rings 4013a6233bSBrett Creeley * 4113a6233bSBrett Creeley * First enable/disable all of the Rx rings, flush any remaining writes, and 4213a6233bSBrett Creeley * then verify that they have all been enabled/disabled successfully. This will 4313a6233bSBrett Creeley * let all of the register writes complete when enabling/disabling the Rx rings 4413a6233bSBrett Creeley * before waiting for the change in hardware to complete. 45d02f734cSMaciej Fijalkowski */ 4613a6233bSBrett Creeley static int ice_vsi_ctrl_all_rx_rings(struct ice_vsi *vsi, bool ena) 47d02f734cSMaciej Fijalkowski { 4888865fc4SKarol Kolacinski int ret = 0; 4988865fc4SKarol Kolacinski u16 i; 50d02f734cSMaciej Fijalkowski 512faf63b6SMaciej Fijalkowski ice_for_each_rxq(vsi, i) 5213a6233bSBrett Creeley ice_vsi_ctrl_one_rx_ring(vsi, ena, i, false); 5313a6233bSBrett Creeley 5413a6233bSBrett Creeley ice_flush(&vsi->back->hw); 5513a6233bSBrett Creeley 562faf63b6SMaciej Fijalkowski ice_for_each_rxq(vsi, i) { 5713a6233bSBrett Creeley ret = ice_vsi_wait_one_rx_ring(vsi, ena, i); 58d02f734cSMaciej Fijalkowski if (ret) 59d02f734cSMaciej Fijalkowski break; 6072adf242SAnirudh Venkataramanan } 6172adf242SAnirudh Venkataramanan 6272adf242SAnirudh Venkataramanan return ret; 6372adf242SAnirudh Venkataramanan } 6472adf242SAnirudh Venkataramanan 6572adf242SAnirudh Venkataramanan /** 6628c2a645SAnirudh Venkataramanan * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI 6728c2a645SAnirudh Venkataramanan * @vsi: VSI pointer 6828c2a645SAnirudh Venkataramanan * 6928c2a645SAnirudh Venkataramanan * On error: returns error code (negative) 7028c2a645SAnirudh Venkataramanan * On success: returns 0 7128c2a645SAnirudh Venkataramanan */ 72a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi) 7328c2a645SAnirudh Venkataramanan { 7428c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 754015d11eSBrett Creeley struct device *dev; 764015d11eSBrett Creeley 774015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 780754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) 790754d65bSKiran Patil return 0; 8028c2a645SAnirudh Venkataramanan 8128c2a645SAnirudh Venkataramanan /* allocate memory for both Tx and Rx ring pointers */ 824015d11eSBrett Creeley vsi->tx_rings = devm_kcalloc(dev, vsi->alloc_txq, 83c6dfd690SBruce Allan sizeof(*vsi->tx_rings), GFP_KERNEL); 8428c2a645SAnirudh Venkataramanan if (!vsi->tx_rings) 8578b5713aSAnirudh Venkataramanan return -ENOMEM; 8628c2a645SAnirudh Venkataramanan 874015d11eSBrett Creeley vsi->rx_rings = devm_kcalloc(dev, vsi->alloc_rxq, 88c6dfd690SBruce Allan sizeof(*vsi->rx_rings), GFP_KERNEL); 8928c2a645SAnirudh Venkataramanan if (!vsi->rx_rings) 9078b5713aSAnirudh Venkataramanan goto err_rings; 9178b5713aSAnirudh Venkataramanan 92792b2086SMaciej Fijalkowski /* txq_map needs to have enough space to track both Tx (stack) rings 93792b2086SMaciej Fijalkowski * and XDP rings; at this point vsi->num_xdp_txq might not be set, 94792b2086SMaciej Fijalkowski * so use num_possible_cpus() as we want to always provide XDP ring 95792b2086SMaciej Fijalkowski * per CPU, regardless of queue count settings from user that might 96792b2086SMaciej Fijalkowski * have come from ethtool's set_channels() callback; 97792b2086SMaciej Fijalkowski */ 98792b2086SMaciej Fijalkowski vsi->txq_map = devm_kcalloc(dev, (vsi->alloc_txq + num_possible_cpus()), 9978b5713aSAnirudh Venkataramanan sizeof(*vsi->txq_map), GFP_KERNEL); 10078b5713aSAnirudh Venkataramanan 10178b5713aSAnirudh Venkataramanan if (!vsi->txq_map) 10278b5713aSAnirudh Venkataramanan goto err_txq_map; 10378b5713aSAnirudh Venkataramanan 1044015d11eSBrett Creeley vsi->rxq_map = devm_kcalloc(dev, vsi->alloc_rxq, 10578b5713aSAnirudh Venkataramanan sizeof(*vsi->rxq_map), GFP_KERNEL); 10678b5713aSAnirudh Venkataramanan if (!vsi->rxq_map) 10778b5713aSAnirudh Venkataramanan goto err_rxq_map; 10878b5713aSAnirudh Venkataramanan 1090e674aebSAnirudh Venkataramanan /* There is no need to allocate q_vectors for a loopback VSI. */ 1100e674aebSAnirudh Venkataramanan if (vsi->type == ICE_VSI_LB) 1110e674aebSAnirudh Venkataramanan return 0; 1120e674aebSAnirudh Venkataramanan 11328c2a645SAnirudh Venkataramanan /* allocate memory for q_vector pointers */ 1144015d11eSBrett Creeley vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors, 115a85a3847SBrett Creeley sizeof(*vsi->q_vectors), GFP_KERNEL); 11628c2a645SAnirudh Venkataramanan if (!vsi->q_vectors) 11728c2a645SAnirudh Venkataramanan goto err_vectors; 11828c2a645SAnirudh Venkataramanan 119e102db78SMaciej Fijalkowski vsi->af_xdp_zc_qps = bitmap_zalloc(max_t(int, vsi->alloc_txq, vsi->alloc_rxq), GFP_KERNEL); 120e102db78SMaciej Fijalkowski if (!vsi->af_xdp_zc_qps) 121e102db78SMaciej Fijalkowski goto err_zc_qps; 122e102db78SMaciej Fijalkowski 12328c2a645SAnirudh Venkataramanan return 0; 12428c2a645SAnirudh Venkataramanan 125e102db78SMaciej Fijalkowski err_zc_qps: 126e102db78SMaciej Fijalkowski devm_kfree(dev, vsi->q_vectors); 12728c2a645SAnirudh Venkataramanan err_vectors: 1284015d11eSBrett Creeley devm_kfree(dev, vsi->rxq_map); 12978b5713aSAnirudh Venkataramanan err_rxq_map: 1304015d11eSBrett Creeley devm_kfree(dev, vsi->txq_map); 13178b5713aSAnirudh Venkataramanan err_txq_map: 1324015d11eSBrett Creeley devm_kfree(dev, vsi->rx_rings); 13378b5713aSAnirudh Venkataramanan err_rings: 1344015d11eSBrett Creeley devm_kfree(dev, vsi->tx_rings); 13528c2a645SAnirudh Venkataramanan return -ENOMEM; 13628c2a645SAnirudh Venkataramanan } 13728c2a645SAnirudh Venkataramanan 13828c2a645SAnirudh Venkataramanan /** 139ad71b256SBrett Creeley * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI 140ad71b256SBrett Creeley * @vsi: the VSI being configured 141ad71b256SBrett Creeley */ 142ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi) 143ad71b256SBrett Creeley { 144ad71b256SBrett Creeley switch (vsi->type) { 145ad71b256SBrett Creeley case ICE_VSI_PF: 146f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 147148beb61SHenry Tieman case ICE_VSI_CTRL: 1480e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 149a02016deSPaul M Stillwell Jr /* a user could change the values of num_[tr]x_desc using 150a02016deSPaul M Stillwell Jr * ethtool -G so we should keep those values instead of 151a02016deSPaul M Stillwell Jr * overwriting them with the defaults. 152a02016deSPaul M Stillwell Jr */ 153a02016deSPaul M Stillwell Jr if (!vsi->num_rx_desc) 154ad71b256SBrett Creeley vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC; 155a02016deSPaul M Stillwell Jr if (!vsi->num_tx_desc) 156ad71b256SBrett Creeley vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC; 157ad71b256SBrett Creeley break; 158ad71b256SBrett Creeley default: 15919cce2c6SAnirudh Venkataramanan dev_dbg(ice_pf_to_dev(vsi->back), "Not setting number of Tx/Rx descriptors for VSI type %d\n", 160ad71b256SBrett Creeley vsi->type); 161ad71b256SBrett Creeley break; 162ad71b256SBrett Creeley } 163ad71b256SBrett Creeley } 164ad71b256SBrett Creeley 165ad71b256SBrett Creeley /** 166ad71b256SBrett Creeley * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI 16728c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 168f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 16928c2a645SAnirudh Venkataramanan * 17028c2a645SAnirudh Venkataramanan * Return 0 on success and a negative value on error 17128c2a645SAnirudh Venkataramanan */ 1725743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id) 17328c2a645SAnirudh Venkataramanan { 17428c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 1755743020dSAkeem G Abodunrin struct ice_vf *vf = NULL; 1765743020dSAkeem G Abodunrin 1775743020dSAkeem G Abodunrin if (vsi->type == ICE_VSI_VF) 1785743020dSAkeem G Abodunrin vsi->vf_id = vf_id; 179c931c782SBrett Creeley else 180c931c782SBrett Creeley vsi->vf_id = ICE_INVAL_VFID; 1815743020dSAkeem G Abodunrin 18228c2a645SAnirudh Venkataramanan switch (vsi->type) { 18328c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 18487324e74SHenry Tieman if (vsi->req_txq) { 18587324e74SHenry Tieman vsi->alloc_txq = vsi->req_txq; 18687324e74SHenry Tieman vsi->num_txq = vsi->req_txq; 187b38b7f2bSSalil Mehta } else { 188b38b7f2bSSalil Mehta vsi->alloc_txq = min3(pf->num_lan_msix, 189b38b7f2bSSalil Mehta ice_get_avail_txq_count(pf), 190b38b7f2bSSalil Mehta (u16)num_online_cpus()); 19187324e74SHenry Tieman } 1928c243700SAnirudh Venkataramanan 1938c243700SAnirudh Venkataramanan pf->num_lan_tx = vsi->alloc_txq; 1948c243700SAnirudh Venkataramanan 1958c243700SAnirudh Venkataramanan /* only 1 Rx queue unless RSS is enabled */ 19687324e74SHenry Tieman if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 1978c243700SAnirudh Venkataramanan vsi->alloc_rxq = 1; 19887324e74SHenry Tieman } else { 19987324e74SHenry Tieman if (vsi->req_rxq) { 20087324e74SHenry Tieman vsi->alloc_rxq = vsi->req_rxq; 20187324e74SHenry Tieman vsi->num_rxq = vsi->req_rxq; 202b38b7f2bSSalil Mehta } else { 203b38b7f2bSSalil Mehta vsi->alloc_rxq = min3(pf->num_lan_msix, 204b38b7f2bSSalil Mehta ice_get_avail_rxq_count(pf), 205b38b7f2bSSalil Mehta (u16)num_online_cpus()); 20687324e74SHenry Tieman } 20787324e74SHenry Tieman } 2088c243700SAnirudh Venkataramanan 2098c243700SAnirudh Venkataramanan pf->num_lan_rx = vsi->alloc_rxq; 2108c243700SAnirudh Venkataramanan 211f3fe97f6SBrett Creeley vsi->num_q_vectors = min_t(int, pf->num_lan_msix, 212f3fe97f6SBrett Creeley max_t(int, vsi->alloc_rxq, 213f3fe97f6SBrett Creeley vsi->alloc_txq)); 21428c2a645SAnirudh Venkataramanan break; 215f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 216f66756e0SGrzegorz Nitka /* The number of queues for ctrl VSI is equal to number of VFs. 217f66756e0SGrzegorz Nitka * Each ring is associated to the corresponding VF_PR netdev. 218f66756e0SGrzegorz Nitka */ 219f66756e0SGrzegorz Nitka vsi->alloc_txq = pf->num_alloc_vfs; 220f66756e0SGrzegorz Nitka vsi->alloc_rxq = pf->num_alloc_vfs; 221f66756e0SGrzegorz Nitka vsi->num_q_vectors = 1; 222f66756e0SGrzegorz Nitka break; 2238ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 2245743020dSAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 225f0457690SBrett Creeley if (vf->num_req_qs) 226f0457690SBrett Creeley vf->num_vf_qs = vf->num_req_qs; 2275743020dSAkeem G Abodunrin vsi->alloc_txq = vf->num_vf_qs; 2285743020dSAkeem G Abodunrin vsi->alloc_rxq = vf->num_vf_qs; 22946c276ceSBrett Creeley /* pf->num_msix_per_vf includes (VF miscellaneous vector + 2308ede0178SAnirudh Venkataramanan * data queue interrupts). Since vsi->num_q_vectors is number 231047e52c0SAnirudh Venkataramanan * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the 232047e52c0SAnirudh Venkataramanan * original vector count 2338ede0178SAnirudh Venkataramanan */ 23446c276ceSBrett Creeley vsi->num_q_vectors = pf->num_msix_per_vf - ICE_NONQ_VECS_VF; 2358ede0178SAnirudh Venkataramanan break; 236148beb61SHenry Tieman case ICE_VSI_CTRL: 237148beb61SHenry Tieman vsi->alloc_txq = 1; 238148beb61SHenry Tieman vsi->alloc_rxq = 1; 239148beb61SHenry Tieman vsi->num_q_vectors = 1; 240148beb61SHenry Tieman break; 2410754d65bSKiran Patil case ICE_VSI_CHNL: 2420754d65bSKiran Patil vsi->alloc_txq = 0; 2430754d65bSKiran Patil vsi->alloc_rxq = 0; 2440754d65bSKiran Patil break; 2450e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 2460e674aebSAnirudh Venkataramanan vsi->alloc_txq = 1; 2470e674aebSAnirudh Venkataramanan vsi->alloc_rxq = 1; 2480e674aebSAnirudh Venkataramanan break; 24928c2a645SAnirudh Venkataramanan default: 2504015d11eSBrett Creeley dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi->type); 25128c2a645SAnirudh Venkataramanan break; 25228c2a645SAnirudh Venkataramanan } 253ad71b256SBrett Creeley 254ad71b256SBrett Creeley ice_vsi_set_num_desc(vsi); 25528c2a645SAnirudh Venkataramanan } 25628c2a645SAnirudh Venkataramanan 25728c2a645SAnirudh Venkataramanan /** 25828c2a645SAnirudh Venkataramanan * ice_get_free_slot - get the next non-NULL location index in array 25928c2a645SAnirudh Venkataramanan * @array: array to search 26028c2a645SAnirudh Venkataramanan * @size: size of the array 26128c2a645SAnirudh Venkataramanan * @curr: last known occupied index to be used as a search hint 26228c2a645SAnirudh Venkataramanan * 26328c2a645SAnirudh Venkataramanan * void * is being used to keep the functionality generic. This lets us use this 26428c2a645SAnirudh Venkataramanan * function on any array of pointers. 26528c2a645SAnirudh Venkataramanan */ 26637bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr) 26728c2a645SAnirudh Venkataramanan { 26828c2a645SAnirudh Venkataramanan int **tmp_array = (int **)array; 26928c2a645SAnirudh Venkataramanan int next; 27028c2a645SAnirudh Venkataramanan 27128c2a645SAnirudh Venkataramanan if (curr < (size - 1) && !tmp_array[curr + 1]) { 27228c2a645SAnirudh Venkataramanan next = curr + 1; 27328c2a645SAnirudh Venkataramanan } else { 27428c2a645SAnirudh Venkataramanan int i = 0; 27528c2a645SAnirudh Venkataramanan 27628c2a645SAnirudh Venkataramanan while ((i < size) && (tmp_array[i])) 27728c2a645SAnirudh Venkataramanan i++; 27828c2a645SAnirudh Venkataramanan if (i == size) 27928c2a645SAnirudh Venkataramanan next = ICE_NO_VSI; 28028c2a645SAnirudh Venkataramanan else 28128c2a645SAnirudh Venkataramanan next = i; 28228c2a645SAnirudh Venkataramanan } 28328c2a645SAnirudh Venkataramanan return next; 28428c2a645SAnirudh Venkataramanan } 28528c2a645SAnirudh Venkataramanan 28628c2a645SAnirudh Venkataramanan /** 2875153a18eSAnirudh Venkataramanan * ice_vsi_delete - delete a VSI from the switch 2885153a18eSAnirudh Venkataramanan * @vsi: pointer to VSI being removed 2895153a18eSAnirudh Venkataramanan */ 2900754d65bSKiran Patil void ice_vsi_delete(struct ice_vsi *vsi) 2915153a18eSAnirudh Venkataramanan { 2925153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 293198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 2945e24d598STony Nguyen int status; 2955153a18eSAnirudh Venkataramanan 2969efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 297198a666aSBruce Allan if (!ctxt) 298198a666aSBruce Allan return; 299198a666aSBruce Allan 3008ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 301198a666aSBruce Allan ctxt->vf_num = vsi->vf_id; 302198a666aSBruce Allan ctxt->vsi_num = vsi->vsi_num; 3035153a18eSAnirudh Venkataramanan 304198a666aSBruce Allan memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info)); 3055153a18eSAnirudh Venkataramanan 306198a666aSBruce Allan status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL); 3075153a18eSAnirudh Venkataramanan if (status) 3085f87ec48STony Nguyen dev_err(ice_pf_to_dev(pf), "Failed to delete VSI %i in FW - error: %d\n", 3095f87ec48STony Nguyen vsi->vsi_num, status); 310198a666aSBruce Allan 3119efe35d0STony Nguyen kfree(ctxt); 3125153a18eSAnirudh Venkataramanan } 3135153a18eSAnirudh Venkataramanan 3145153a18eSAnirudh Venkataramanan /** 315a85a3847SBrett Creeley * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI 31607309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 31707309a0eSAnirudh Venkataramanan */ 318a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi) 31907309a0eSAnirudh Venkataramanan { 32007309a0eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 3214015d11eSBrett Creeley struct device *dev; 3224015d11eSBrett Creeley 3234015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 32407309a0eSAnirudh Venkataramanan 325e102db78SMaciej Fijalkowski if (vsi->af_xdp_zc_qps) { 326e102db78SMaciej Fijalkowski bitmap_free(vsi->af_xdp_zc_qps); 327e102db78SMaciej Fijalkowski vsi->af_xdp_zc_qps = NULL; 328e102db78SMaciej Fijalkowski } 32907309a0eSAnirudh Venkataramanan /* free the ring and vector containers */ 330a85a3847SBrett Creeley if (vsi->q_vectors) { 3314015d11eSBrett Creeley devm_kfree(dev, vsi->q_vectors); 33207309a0eSAnirudh Venkataramanan vsi->q_vectors = NULL; 33307309a0eSAnirudh Venkataramanan } 33407309a0eSAnirudh Venkataramanan if (vsi->tx_rings) { 3354015d11eSBrett Creeley devm_kfree(dev, vsi->tx_rings); 33607309a0eSAnirudh Venkataramanan vsi->tx_rings = NULL; 33707309a0eSAnirudh Venkataramanan } 33807309a0eSAnirudh Venkataramanan if (vsi->rx_rings) { 3394015d11eSBrett Creeley devm_kfree(dev, vsi->rx_rings); 34007309a0eSAnirudh Venkataramanan vsi->rx_rings = NULL; 34107309a0eSAnirudh Venkataramanan } 34278b5713aSAnirudh Venkataramanan if (vsi->txq_map) { 3434015d11eSBrett Creeley devm_kfree(dev, vsi->txq_map); 34478b5713aSAnirudh Venkataramanan vsi->txq_map = NULL; 34578b5713aSAnirudh Venkataramanan } 34678b5713aSAnirudh Venkataramanan if (vsi->rxq_map) { 3474015d11eSBrett Creeley devm_kfree(dev, vsi->rxq_map); 34878b5713aSAnirudh Venkataramanan vsi->rxq_map = NULL; 34978b5713aSAnirudh Venkataramanan } 35007309a0eSAnirudh Venkataramanan } 35107309a0eSAnirudh Venkataramanan 35207309a0eSAnirudh Venkataramanan /** 35307309a0eSAnirudh Venkataramanan * ice_vsi_clear - clean up and deallocate the provided VSI 35407309a0eSAnirudh Venkataramanan * @vsi: pointer to VSI being cleared 35507309a0eSAnirudh Venkataramanan * 35607309a0eSAnirudh Venkataramanan * This deallocates the VSI's queue resources, removes it from the PF's 35707309a0eSAnirudh Venkataramanan * VSI array if necessary, and deallocates the VSI 35807309a0eSAnirudh Venkataramanan * 35907309a0eSAnirudh Venkataramanan * Returns 0 on success, negative on failure 36007309a0eSAnirudh Venkataramanan */ 3610754d65bSKiran Patil int ice_vsi_clear(struct ice_vsi *vsi) 36207309a0eSAnirudh Venkataramanan { 36307309a0eSAnirudh Venkataramanan struct ice_pf *pf = NULL; 3644015d11eSBrett Creeley struct device *dev; 36507309a0eSAnirudh Venkataramanan 36607309a0eSAnirudh Venkataramanan if (!vsi) 36707309a0eSAnirudh Venkataramanan return 0; 36807309a0eSAnirudh Venkataramanan 36907309a0eSAnirudh Venkataramanan if (!vsi->back) 37007309a0eSAnirudh Venkataramanan return -EINVAL; 37107309a0eSAnirudh Venkataramanan 37207309a0eSAnirudh Venkataramanan pf = vsi->back; 3734015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 37407309a0eSAnirudh Venkataramanan 37507309a0eSAnirudh Venkataramanan if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) { 3764015d11eSBrett Creeley dev_dbg(dev, "vsi does not exist at pf->vsi[%d]\n", vsi->idx); 37707309a0eSAnirudh Venkataramanan return -EINVAL; 37807309a0eSAnirudh Venkataramanan } 37907309a0eSAnirudh Venkataramanan 38007309a0eSAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 38107309a0eSAnirudh Venkataramanan /* updates the PF for this cleared VSI */ 38207309a0eSAnirudh Venkataramanan 38307309a0eSAnirudh Venkataramanan pf->vsi[vsi->idx] = NULL; 384148beb61SHenry Tieman if (vsi->idx < pf->next_vsi && vsi->type != ICE_VSI_CTRL) 38507309a0eSAnirudh Venkataramanan pf->next_vsi = vsi->idx; 386da62c5ffSQi Zhang if (vsi->idx < pf->next_vsi && vsi->type == ICE_VSI_CTRL && 387da62c5ffSQi Zhang vsi->vf_id != ICE_INVAL_VFID) 388da62c5ffSQi Zhang pf->next_vsi = vsi->idx; 38907309a0eSAnirudh Venkataramanan 390a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 39107309a0eSAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 3924015d11eSBrett Creeley devm_kfree(dev, vsi); 39307309a0eSAnirudh Venkataramanan 39407309a0eSAnirudh Venkataramanan return 0; 39507309a0eSAnirudh Venkataramanan } 39607309a0eSAnirudh Venkataramanan 39707309a0eSAnirudh Venkataramanan /** 398148beb61SHenry Tieman * ice_msix_clean_ctrl_vsi - MSIX mode interrupt handler for ctrl VSI 399148beb61SHenry Tieman * @irq: interrupt number 400148beb61SHenry Tieman * @data: pointer to a q_vector 401148beb61SHenry Tieman */ 402148beb61SHenry Tieman static irqreturn_t ice_msix_clean_ctrl_vsi(int __always_unused irq, void *data) 403148beb61SHenry Tieman { 404148beb61SHenry Tieman struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 405148beb61SHenry Tieman 406e72bba21SMaciej Fijalkowski if (!q_vector->tx.tx_ring) 407148beb61SHenry Tieman return IRQ_HANDLED; 408148beb61SHenry Tieman 409148beb61SHenry Tieman #define FDIR_RX_DESC_CLEAN_BUDGET 64 410e72bba21SMaciej Fijalkowski ice_clean_rx_irq(q_vector->rx.rx_ring, FDIR_RX_DESC_CLEAN_BUDGET); 411e72bba21SMaciej Fijalkowski ice_clean_ctrl_tx_irq(q_vector->tx.tx_ring); 412148beb61SHenry Tieman 413148beb61SHenry Tieman return IRQ_HANDLED; 414148beb61SHenry Tieman } 415148beb61SHenry Tieman 416148beb61SHenry Tieman /** 4175153a18eSAnirudh Venkataramanan * ice_msix_clean_rings - MSIX mode Interrupt Handler 4185153a18eSAnirudh Venkataramanan * @irq: interrupt number 4195153a18eSAnirudh Venkataramanan * @data: pointer to a q_vector 4205153a18eSAnirudh Venkataramanan */ 421f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data) 4225153a18eSAnirudh Venkataramanan { 4235153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 4245153a18eSAnirudh Venkataramanan 425e72bba21SMaciej Fijalkowski if (!q_vector->tx.tx_ring && !q_vector->rx.rx_ring) 4265153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 4275153a18eSAnirudh Venkataramanan 428cdf1f1f1SJacob Keller q_vector->total_events++; 429cdf1f1f1SJacob Keller 4305153a18eSAnirudh Venkataramanan napi_schedule(&q_vector->napi); 4315153a18eSAnirudh Venkataramanan 4325153a18eSAnirudh Venkataramanan return IRQ_HANDLED; 4335153a18eSAnirudh Venkataramanan } 4345153a18eSAnirudh Venkataramanan 435f66756e0SGrzegorz Nitka static irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *data) 436f66756e0SGrzegorz Nitka { 437f66756e0SGrzegorz Nitka struct ice_q_vector *q_vector = (struct ice_q_vector *)data; 438f66756e0SGrzegorz Nitka struct ice_pf *pf = q_vector->vsi->back; 439f66756e0SGrzegorz Nitka int i; 440f66756e0SGrzegorz Nitka 441e72bba21SMaciej Fijalkowski if (!q_vector->tx.tx_ring && !q_vector->rx.rx_ring) 442f66756e0SGrzegorz Nitka return IRQ_HANDLED; 443f66756e0SGrzegorz Nitka 444f66756e0SGrzegorz Nitka ice_for_each_vf(pf, i) 445f66756e0SGrzegorz Nitka napi_schedule(&pf->vf[i].repr->q_vector->napi); 446f66756e0SGrzegorz Nitka 447f66756e0SGrzegorz Nitka return IRQ_HANDLED; 448f66756e0SGrzegorz Nitka } 449f66756e0SGrzegorz Nitka 4505153a18eSAnirudh Venkataramanan /** 45137bb8390SAnirudh Venkataramanan * ice_vsi_alloc - Allocates the next available struct VSI in the PF 45237bb8390SAnirudh Venkataramanan * @pf: board private structure 4536dae8aa0SBruce Allan * @vsi_type: type of VSI 4540754d65bSKiran Patil * @ch: ptr to channel 455f9867df6SAnirudh Venkataramanan * @vf_id: ID of the VF being configured 45637bb8390SAnirudh Venkataramanan * 45737bb8390SAnirudh Venkataramanan * returns a pointer to a VSI on success, NULL on failure. 45837bb8390SAnirudh Venkataramanan */ 4595743020dSAkeem G Abodunrin static struct ice_vsi * 4600754d65bSKiran Patil ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type, 4610754d65bSKiran Patil struct ice_channel *ch, u16 vf_id) 46237bb8390SAnirudh Venkataramanan { 4634015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 46437bb8390SAnirudh Venkataramanan struct ice_vsi *vsi = NULL; 46537bb8390SAnirudh Venkataramanan 46637bb8390SAnirudh Venkataramanan /* Need to protect the allocation of the VSIs at the PF level */ 46737bb8390SAnirudh Venkataramanan mutex_lock(&pf->sw_mutex); 46837bb8390SAnirudh Venkataramanan 46937bb8390SAnirudh Venkataramanan /* If we have already allocated our maximum number of VSIs, 47037bb8390SAnirudh Venkataramanan * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index 47137bb8390SAnirudh Venkataramanan * is available to be populated 47237bb8390SAnirudh Venkataramanan */ 47337bb8390SAnirudh Venkataramanan if (pf->next_vsi == ICE_NO_VSI) { 4744015d11eSBrett Creeley dev_dbg(dev, "out of VSI slots!\n"); 47537bb8390SAnirudh Venkataramanan goto unlock_pf; 47637bb8390SAnirudh Venkataramanan } 47737bb8390SAnirudh Venkataramanan 4784015d11eSBrett Creeley vsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL); 47937bb8390SAnirudh Venkataramanan if (!vsi) 48037bb8390SAnirudh Venkataramanan goto unlock_pf; 48137bb8390SAnirudh Venkataramanan 4826dae8aa0SBruce Allan vsi->type = vsi_type; 48337bb8390SAnirudh Venkataramanan vsi->back = pf; 484e97fb1aeSAnirudh Venkataramanan set_bit(ICE_VSI_DOWN, vsi->state); 4859d56b7fdSJesse Brandeburg 4866dae8aa0SBruce Allan if (vsi_type == ICE_VSI_VF) 4875743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf_id); 4880754d65bSKiran Patil else if (vsi_type != ICE_VSI_CHNL) 4895743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 49037bb8390SAnirudh Venkataramanan 49137bb8390SAnirudh Venkataramanan switch (vsi->type) { 492f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 493f66756e0SGrzegorz Nitka if (ice_vsi_alloc_arrays(vsi)) 494f66756e0SGrzegorz Nitka goto err_rings; 495f66756e0SGrzegorz Nitka 496f66756e0SGrzegorz Nitka /* Setup eswitch MSIX irq handler for VSI */ 497f66756e0SGrzegorz Nitka vsi->irq_handler = ice_eswitch_msix_clean_rings; 498f66756e0SGrzegorz Nitka break; 49937bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 500a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 50137bb8390SAnirudh Venkataramanan goto err_rings; 50237bb8390SAnirudh Venkataramanan 50337bb8390SAnirudh Venkataramanan /* Setup default MSIX irq handler for VSI */ 50437bb8390SAnirudh Venkataramanan vsi->irq_handler = ice_msix_clean_rings; 50537bb8390SAnirudh Venkataramanan break; 506148beb61SHenry Tieman case ICE_VSI_CTRL: 507148beb61SHenry Tieman if (ice_vsi_alloc_arrays(vsi)) 508148beb61SHenry Tieman goto err_rings; 509148beb61SHenry Tieman 510148beb61SHenry Tieman /* Setup ctrl VSI MSIX irq handler */ 511148beb61SHenry Tieman vsi->irq_handler = ice_msix_clean_ctrl_vsi; 512148beb61SHenry Tieman break; 5138ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 514a85a3847SBrett Creeley if (ice_vsi_alloc_arrays(vsi)) 5158ede0178SAnirudh Venkataramanan goto err_rings; 5168ede0178SAnirudh Venkataramanan break; 5170754d65bSKiran Patil case ICE_VSI_CHNL: 5180754d65bSKiran Patil if (!ch) 5190754d65bSKiran Patil goto err_rings; 5200754d65bSKiran Patil vsi->num_rxq = ch->num_rxq; 5210754d65bSKiran Patil vsi->num_txq = ch->num_txq; 5220754d65bSKiran Patil vsi->next_base_q = ch->base_q; 5230754d65bSKiran Patil break; 5240e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 5250e674aebSAnirudh Venkataramanan if (ice_vsi_alloc_arrays(vsi)) 5260e674aebSAnirudh Venkataramanan goto err_rings; 5270e674aebSAnirudh Venkataramanan break; 52837bb8390SAnirudh Venkataramanan default: 5294015d11eSBrett Creeley dev_warn(dev, "Unknown VSI type %d\n", vsi->type); 53037bb8390SAnirudh Venkataramanan goto unlock_pf; 53137bb8390SAnirudh Venkataramanan } 53237bb8390SAnirudh Venkataramanan 533da62c5ffSQi Zhang if (vsi->type == ICE_VSI_CTRL && vf_id == ICE_INVAL_VFID) { 534da62c5ffSQi Zhang /* Use the last VSI slot as the index for PF control VSI */ 535148beb61SHenry Tieman vsi->idx = pf->num_alloc_vsi - 1; 536148beb61SHenry Tieman pf->ctrl_vsi_idx = vsi->idx; 537148beb61SHenry Tieman pf->vsi[vsi->idx] = vsi; 538148beb61SHenry Tieman } else { 539148beb61SHenry Tieman /* fill slot and make note of the index */ 540148beb61SHenry Tieman vsi->idx = pf->next_vsi; 54137bb8390SAnirudh Venkataramanan pf->vsi[pf->next_vsi] = vsi; 54237bb8390SAnirudh Venkataramanan 54337bb8390SAnirudh Venkataramanan /* prepare pf->next_vsi for next use */ 54437bb8390SAnirudh Venkataramanan pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi, 54537bb8390SAnirudh Venkataramanan pf->next_vsi); 546148beb61SHenry Tieman } 547da62c5ffSQi Zhang 548da62c5ffSQi Zhang if (vsi->type == ICE_VSI_CTRL && vf_id != ICE_INVAL_VFID) 549da62c5ffSQi Zhang pf->vf[vf_id].ctrl_vsi_idx = vsi->idx; 55037bb8390SAnirudh Venkataramanan goto unlock_pf; 55137bb8390SAnirudh Venkataramanan 55237bb8390SAnirudh Venkataramanan err_rings: 5534015d11eSBrett Creeley devm_kfree(dev, vsi); 55437bb8390SAnirudh Venkataramanan vsi = NULL; 55537bb8390SAnirudh Venkataramanan unlock_pf: 55637bb8390SAnirudh Venkataramanan mutex_unlock(&pf->sw_mutex); 55737bb8390SAnirudh Venkataramanan return vsi; 55837bb8390SAnirudh Venkataramanan } 55937bb8390SAnirudh Venkataramanan 56037bb8390SAnirudh Venkataramanan /** 561148beb61SHenry Tieman * ice_alloc_fd_res - Allocate FD resource for a VSI 562148beb61SHenry Tieman * @vsi: pointer to the ice_vsi 563148beb61SHenry Tieman * 564148beb61SHenry Tieman * This allocates the FD resources 565148beb61SHenry Tieman * 566148beb61SHenry Tieman * Returns 0 on success, -EPERM on no-op or -EIO on failure 567148beb61SHenry Tieman */ 568148beb61SHenry Tieman static int ice_alloc_fd_res(struct ice_vsi *vsi) 569148beb61SHenry Tieman { 570148beb61SHenry Tieman struct ice_pf *pf = vsi->back; 571148beb61SHenry Tieman u32 g_val, b_val; 572148beb61SHenry Tieman 573148beb61SHenry Tieman /* Flow Director filters are only allocated/assigned to the PF VSI which 574148beb61SHenry Tieman * passes the traffic. The CTRL VSI is only used to add/delete filters 575148beb61SHenry Tieman * so we don't allocate resources to it 576148beb61SHenry Tieman */ 577148beb61SHenry Tieman 578148beb61SHenry Tieman /* FD filters from guaranteed pool per VSI */ 579148beb61SHenry Tieman g_val = pf->hw.func_caps.fd_fltr_guar; 580148beb61SHenry Tieman if (!g_val) 581148beb61SHenry Tieman return -EPERM; 582148beb61SHenry Tieman 583148beb61SHenry Tieman /* FD filters from best effort pool */ 584148beb61SHenry Tieman b_val = pf->hw.func_caps.fd_fltr_best_effort; 585148beb61SHenry Tieman if (!b_val) 586148beb61SHenry Tieman return -EPERM; 587148beb61SHenry Tieman 588da62c5ffSQi Zhang if (!(vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF)) 589148beb61SHenry Tieman return -EPERM; 590148beb61SHenry Tieman 591148beb61SHenry Tieman if (!test_bit(ICE_FLAG_FD_ENA, pf->flags)) 592148beb61SHenry Tieman return -EPERM; 593148beb61SHenry Tieman 594148beb61SHenry Tieman vsi->num_gfltr = g_val / pf->num_alloc_vsi; 595148beb61SHenry Tieman 596148beb61SHenry Tieman /* each VSI gets same "best_effort" quota */ 597148beb61SHenry Tieman vsi->num_bfltr = b_val; 598148beb61SHenry Tieman 599da62c5ffSQi Zhang if (vsi->type == ICE_VSI_VF) { 600da62c5ffSQi Zhang vsi->num_gfltr = 0; 601da62c5ffSQi Zhang 602da62c5ffSQi Zhang /* each VSI gets same "best_effort" quota */ 603da62c5ffSQi Zhang vsi->num_bfltr = b_val; 604da62c5ffSQi Zhang } 605da62c5ffSQi Zhang 606148beb61SHenry Tieman return 0; 607148beb61SHenry Tieman } 608148beb61SHenry Tieman 609148beb61SHenry Tieman /** 610df0f8479SAnirudh Venkataramanan * ice_vsi_get_qs - Assign queues from PF to VSI 611df0f8479SAnirudh Venkataramanan * @vsi: the VSI to assign queues to 612df0f8479SAnirudh Venkataramanan * 613df0f8479SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 614df0f8479SAnirudh Venkataramanan */ 61537bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi) 616df0f8479SAnirudh Venkataramanan { 61703f7a986SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 61803f7a986SAnirudh Venkataramanan struct ice_qs_cfg tx_qs_cfg = { 61903f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 62003f7a986SAnirudh Venkataramanan .pf_map = pf->avail_txqs, 62178b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_txqs, 62203f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_txq, 62303f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_TXQS, 62403f7a986SAnirudh Venkataramanan .vsi_map = vsi->txq_map, 62503f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 62639066dc5SBrett Creeley .mapping_mode = ICE_VSI_MAP_CONTIG 62703f7a986SAnirudh Venkataramanan }; 62803f7a986SAnirudh Venkataramanan struct ice_qs_cfg rx_qs_cfg = { 62903f7a986SAnirudh Venkataramanan .qs_mutex = &pf->avail_q_mutex, 63003f7a986SAnirudh Venkataramanan .pf_map = pf->avail_rxqs, 63178b5713aSAnirudh Venkataramanan .pf_map_size = pf->max_pf_rxqs, 63203f7a986SAnirudh Venkataramanan .q_count = vsi->alloc_rxq, 63303f7a986SAnirudh Venkataramanan .scatter_count = ICE_MAX_SCATTER_RXQS, 63403f7a986SAnirudh Venkataramanan .vsi_map = vsi->rxq_map, 63503f7a986SAnirudh Venkataramanan .vsi_map_offset = 0, 63639066dc5SBrett Creeley .mapping_mode = ICE_VSI_MAP_CONTIG 63703f7a986SAnirudh Venkataramanan }; 63839066dc5SBrett Creeley int ret; 639df0f8479SAnirudh Venkataramanan 6400754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) 6410754d65bSKiran Patil return 0; 6420754d65bSKiran Patil 64303f7a986SAnirudh Venkataramanan ret = __ice_vsi_get_qs(&tx_qs_cfg); 64439066dc5SBrett Creeley if (ret) 645df0f8479SAnirudh Venkataramanan return ret; 64639066dc5SBrett Creeley vsi->tx_mapping_mode = tx_qs_cfg.mapping_mode; 64739066dc5SBrett Creeley 64839066dc5SBrett Creeley ret = __ice_vsi_get_qs(&rx_qs_cfg); 64939066dc5SBrett Creeley if (ret) 65039066dc5SBrett Creeley return ret; 65139066dc5SBrett Creeley vsi->rx_mapping_mode = rx_qs_cfg.mapping_mode; 65239066dc5SBrett Creeley 65339066dc5SBrett Creeley return 0; 654df0f8479SAnirudh Venkataramanan } 655df0f8479SAnirudh Venkataramanan 656df0f8479SAnirudh Venkataramanan /** 6575153a18eSAnirudh Venkataramanan * ice_vsi_put_qs - Release queues from VSI to PF 6585153a18eSAnirudh Venkataramanan * @vsi: the VSI that is going to release queues 6595153a18eSAnirudh Venkataramanan */ 660135f4b9eSJacob Keller static void ice_vsi_put_qs(struct ice_vsi *vsi) 6615153a18eSAnirudh Venkataramanan { 6625153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 6635153a18eSAnirudh Venkataramanan int i; 6645153a18eSAnirudh Venkataramanan 6655153a18eSAnirudh Venkataramanan mutex_lock(&pf->avail_q_mutex); 6665153a18eSAnirudh Venkataramanan 6672faf63b6SMaciej Fijalkowski ice_for_each_alloc_txq(vsi, i) { 6685153a18eSAnirudh Venkataramanan clear_bit(vsi->txq_map[i], pf->avail_txqs); 6695153a18eSAnirudh Venkataramanan vsi->txq_map[i] = ICE_INVAL_Q_INDEX; 6705153a18eSAnirudh Venkataramanan } 6715153a18eSAnirudh Venkataramanan 6722faf63b6SMaciej Fijalkowski ice_for_each_alloc_rxq(vsi, i) { 6735153a18eSAnirudh Venkataramanan clear_bit(vsi->rxq_map[i], pf->avail_rxqs); 6745153a18eSAnirudh Venkataramanan vsi->rxq_map[i] = ICE_INVAL_Q_INDEX; 6755153a18eSAnirudh Venkataramanan } 6765153a18eSAnirudh Venkataramanan 6775153a18eSAnirudh Venkataramanan mutex_unlock(&pf->avail_q_mutex); 6785153a18eSAnirudh Venkataramanan } 6795153a18eSAnirudh Venkataramanan 6805153a18eSAnirudh Venkataramanan /** 681462acf6aSTony Nguyen * ice_is_safe_mode 682462acf6aSTony Nguyen * @pf: pointer to the PF struct 683462acf6aSTony Nguyen * 684462acf6aSTony Nguyen * returns true if driver is in safe mode, false otherwise 685462acf6aSTony Nguyen */ 686462acf6aSTony Nguyen bool ice_is_safe_mode(struct ice_pf *pf) 687462acf6aSTony Nguyen { 688462acf6aSTony Nguyen return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags); 689462acf6aSTony Nguyen } 690462acf6aSTony Nguyen 691462acf6aSTony Nguyen /** 692d25a0fc4SDave Ertman * ice_is_aux_ena 693d25a0fc4SDave Ertman * @pf: pointer to the PF struct 694d25a0fc4SDave Ertman * 695d25a0fc4SDave Ertman * returns true if AUX devices/drivers are supported, false otherwise 696d25a0fc4SDave Ertman */ 697d25a0fc4SDave Ertman bool ice_is_aux_ena(struct ice_pf *pf) 698d25a0fc4SDave Ertman { 699d25a0fc4SDave Ertman return test_bit(ICE_FLAG_AUX_ENA, pf->flags); 700d25a0fc4SDave Ertman } 701d25a0fc4SDave Ertman 702d25a0fc4SDave Ertman /** 7032c61054cSTony Nguyen * ice_vsi_clean_rss_flow_fld - Delete RSS configuration 7042c61054cSTony Nguyen * @vsi: the VSI being cleaned up 7052c61054cSTony Nguyen * 7062c61054cSTony Nguyen * This function deletes RSS input set for all flows that were configured 7072c61054cSTony Nguyen * for this VSI 7082c61054cSTony Nguyen */ 7092c61054cSTony Nguyen static void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi) 7102c61054cSTony Nguyen { 7112c61054cSTony Nguyen struct ice_pf *pf = vsi->back; 7125e24d598STony Nguyen int status; 7132c61054cSTony Nguyen 7142c61054cSTony Nguyen if (ice_is_safe_mode(pf)) 7152c61054cSTony Nguyen return; 7162c61054cSTony Nguyen 7172c61054cSTony Nguyen status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx); 7182c61054cSTony Nguyen if (status) 7195f87ec48STony Nguyen dev_dbg(ice_pf_to_dev(pf), "ice_rem_vsi_rss_cfg failed for vsi = %d, error = %d\n", 7205f87ec48STony Nguyen vsi->vsi_num, status); 7212c61054cSTony Nguyen } 7222c61054cSTony Nguyen 7232c61054cSTony Nguyen /** 7242c61054cSTony Nguyen * ice_rss_clean - Delete RSS related VSI structures and configuration 725df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 726df0f8479SAnirudh Venkataramanan */ 727df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi) 728df0f8479SAnirudh Venkataramanan { 7294015d11eSBrett Creeley struct ice_pf *pf = vsi->back; 7304015d11eSBrett Creeley struct device *dev; 731df0f8479SAnirudh Venkataramanan 7324015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 733df0f8479SAnirudh Venkataramanan 734df0f8479SAnirudh Venkataramanan if (vsi->rss_hkey_user) 7354015d11eSBrett Creeley devm_kfree(dev, vsi->rss_hkey_user); 736df0f8479SAnirudh Venkataramanan if (vsi->rss_lut_user) 7374015d11eSBrett Creeley devm_kfree(dev, vsi->rss_lut_user); 7382c61054cSTony Nguyen 7392c61054cSTony Nguyen ice_vsi_clean_rss_flow_fld(vsi); 7402c61054cSTony Nguyen /* remove RSS replay list */ 7412c61054cSTony Nguyen if (!ice_is_safe_mode(pf)) 7422c61054cSTony Nguyen ice_rem_vsi_rss_list(&pf->hw, vsi->idx); 743df0f8479SAnirudh Venkataramanan } 744df0f8479SAnirudh Venkataramanan 745df0f8479SAnirudh Venkataramanan /** 74628c2a645SAnirudh Venkataramanan * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type 74728c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 74828c2a645SAnirudh Venkataramanan */ 74937bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi) 75028c2a645SAnirudh Venkataramanan { 75128c2a645SAnirudh Venkataramanan struct ice_hw_common_caps *cap; 75228c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 75328c2a645SAnirudh Venkataramanan 75428c2a645SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 75528c2a645SAnirudh Venkataramanan vsi->rss_size = 1; 75628c2a645SAnirudh Venkataramanan return; 75728c2a645SAnirudh Venkataramanan } 75828c2a645SAnirudh Venkataramanan 75928c2a645SAnirudh Venkataramanan cap = &pf->hw.func_caps.common_cap; 76028c2a645SAnirudh Venkataramanan switch (vsi->type) { 7610754d65bSKiran Patil case ICE_VSI_CHNL: 76228c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 76328c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 76488865fc4SKarol Kolacinski vsi->rss_table_size = (u16)cap->rss_table_size; 7650754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) 7660754d65bSKiran Patil vsi->rss_size = min_t(u16, vsi->num_rxq, 7670754d65bSKiran Patil BIT(cap->rss_table_entry_width)); 7680754d65bSKiran Patil else 76988865fc4SKarol Kolacinski vsi->rss_size = min_t(u16, num_online_cpus(), 77028c2a645SAnirudh Venkataramanan BIT(cap->rss_table_entry_width)); 77128c2a645SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF; 77228c2a645SAnirudh Venkataramanan break; 773f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 774f66756e0SGrzegorz Nitka vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 775f66756e0SGrzegorz Nitka vsi->rss_size = min_t(u16, num_online_cpus(), 776f66756e0SGrzegorz Nitka BIT(cap->rss_table_entry_width)); 777f66756e0SGrzegorz Nitka vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 778f66756e0SGrzegorz Nitka break; 7798ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 7800ca469fbSMitch Williams /* VF VSI will get a small RSS table. 7810ca469fbSMitch Williams * For VSI_LUT, LUT size should be set to 64 bytes. 7828ede0178SAnirudh Venkataramanan */ 7838ede0178SAnirudh Venkataramanan vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE; 7840ca469fbSMitch Williams vsi->rss_size = ICE_MAX_RSS_QS_PER_VF; 7858ede0178SAnirudh Venkataramanan vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI; 7868ede0178SAnirudh Venkataramanan break; 7870e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 7880e674aebSAnirudh Venkataramanan break; 78928c2a645SAnirudh Venkataramanan default: 790148beb61SHenry Tieman dev_dbg(ice_pf_to_dev(pf), "Unsupported VSI type %s\n", 791148beb61SHenry Tieman ice_vsi_type_str(vsi->type)); 79228c2a645SAnirudh Venkataramanan break; 79328c2a645SAnirudh Venkataramanan } 79428c2a645SAnirudh Venkataramanan } 79528c2a645SAnirudh Venkataramanan 79628c2a645SAnirudh Venkataramanan /** 79728c2a645SAnirudh Venkataramanan * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI 79828c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 79928c2a645SAnirudh Venkataramanan * 80028c2a645SAnirudh Venkataramanan * This initializes a default VSI context for all sections except the Queues. 80128c2a645SAnirudh Venkataramanan */ 80228c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt) 80328c2a645SAnirudh Venkataramanan { 80428c2a645SAnirudh Venkataramanan u32 table = 0; 80528c2a645SAnirudh Venkataramanan 80628c2a645SAnirudh Venkataramanan memset(&ctxt->info, 0, sizeof(ctxt->info)); 80728c2a645SAnirudh Venkataramanan /* VSI's should be allocated from shared pool */ 80828c2a645SAnirudh Venkataramanan ctxt->alloc_from_pool = true; 80928c2a645SAnirudh Venkataramanan /* Src pruning enabled by default */ 81028c2a645SAnirudh Venkataramanan ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE; 81128c2a645SAnirudh Venkataramanan /* Traffic from VSI can be sent to LAN */ 81228c2a645SAnirudh Venkataramanan ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA; 81328c2a645SAnirudh Venkataramanan /* By default bits 3 and 4 in vlan_flags are 0's which results in legacy 81428c2a645SAnirudh Venkataramanan * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all 81528c2a645SAnirudh Venkataramanan * packets untagged/tagged. 81628c2a645SAnirudh Venkataramanan */ 81728c2a645SAnirudh Venkataramanan ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL & 81828c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_M) >> 81928c2a645SAnirudh Venkataramanan ICE_AQ_VSI_VLAN_MODE_S); 82028c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for both ingress/egress tables */ 82128c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(0, 0); 82228c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(1, 1); 82328c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(2, 2); 82428c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(3, 3); 82528c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(4, 4); 82628c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(5, 5); 82728c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(6, 6); 82828c2a645SAnirudh Venkataramanan table |= ICE_UP_TABLE_TRANSLATE(7, 7); 82928c2a645SAnirudh Venkataramanan ctxt->info.ingress_table = cpu_to_le32(table); 83028c2a645SAnirudh Venkataramanan ctxt->info.egress_table = cpu_to_le32(table); 83128c2a645SAnirudh Venkataramanan /* Have 1:1 UP mapping for outer to inner UP table */ 83228c2a645SAnirudh Venkataramanan ctxt->info.outer_up_table = cpu_to_le32(table); 83328c2a645SAnirudh Venkataramanan /* No Outer tag support outer_tag_flags remains to zero */ 83428c2a645SAnirudh Venkataramanan } 83528c2a645SAnirudh Venkataramanan 83628c2a645SAnirudh Venkataramanan /** 83728c2a645SAnirudh Venkataramanan * ice_vsi_setup_q_map - Setup a VSI queue map 83828c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 83928c2a645SAnirudh Venkataramanan * @ctxt: VSI context structure 84028c2a645SAnirudh Venkataramanan */ 84128c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 84228c2a645SAnirudh Venkataramanan { 8438134d5ffSBrett Creeley u16 offset = 0, qmap = 0, tx_count = 0, pow = 0; 8448134d5ffSBrett Creeley u16 num_txq_per_tc, num_rxq_per_tc; 84528c2a645SAnirudh Venkataramanan u16 qcount_tx = vsi->alloc_txq; 84628c2a645SAnirudh Venkataramanan u16 qcount_rx = vsi->alloc_rxq; 847c5a2a4a3SUsha Ketineni u8 netdev_tc = 0; 84828c2a645SAnirudh Venkataramanan int i; 84928c2a645SAnirudh Venkataramanan 8500754d65bSKiran Patil if (!vsi->tc_cfg.numtc) { 85128c2a645SAnirudh Venkataramanan /* at least TC0 should be enabled by default */ 8520754d65bSKiran Patil vsi->tc_cfg.numtc = 1; 8530754d65bSKiran Patil vsi->tc_cfg.ena_tc = 1; 85428c2a645SAnirudh Venkataramanan } 85528c2a645SAnirudh Venkataramanan 8568134d5ffSBrett Creeley num_rxq_per_tc = min_t(u16, qcount_rx / vsi->tc_cfg.numtc, ICE_MAX_RXQS_PER_TC); 8578134d5ffSBrett Creeley if (!num_rxq_per_tc) 8588134d5ffSBrett Creeley num_rxq_per_tc = 1; 8598134d5ffSBrett Creeley num_txq_per_tc = qcount_tx / vsi->tc_cfg.numtc; 8608134d5ffSBrett Creeley if (!num_txq_per_tc) 8618134d5ffSBrett Creeley num_txq_per_tc = 1; 8628134d5ffSBrett Creeley 8638134d5ffSBrett Creeley /* find the (rounded up) power-of-2 of qcount */ 8648134d5ffSBrett Creeley pow = (u16)order_base_2(num_rxq_per_tc); 86528c2a645SAnirudh Venkataramanan 86628c2a645SAnirudh Venkataramanan /* TC mapping is a function of the number of Rx queues assigned to the 86728c2a645SAnirudh Venkataramanan * VSI for each traffic class and the offset of these queues. 86828c2a645SAnirudh Venkataramanan * The first 10 bits are for queue offset for TC0, next 4 bits for no:of 86928c2a645SAnirudh Venkataramanan * queues allocated to TC0. No:of queues is a power-of-2. 87028c2a645SAnirudh Venkataramanan * 87128c2a645SAnirudh Venkataramanan * If TC is not enabled, the queue offset is set to 0, and allocate one 87228c2a645SAnirudh Venkataramanan * queue, this way, traffic for the given TC will be sent to the default 87328c2a645SAnirudh Venkataramanan * queue. 87428c2a645SAnirudh Venkataramanan * 87528c2a645SAnirudh Venkataramanan * Setup number and offset of Rx queues for all TCs for the VSI 87628c2a645SAnirudh Venkataramanan */ 8772bdc97beSBruce Allan ice_for_each_traffic_class(i) { 87828c2a645SAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 87928c2a645SAnirudh Venkataramanan /* TC is not enabled */ 88028c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = 0; 881c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_rx = 1; 882c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].qcount_tx = 1; 883c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = 0; 88428c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = 0; 88528c2a645SAnirudh Venkataramanan continue; 88628c2a645SAnirudh Venkataramanan } 88728c2a645SAnirudh Venkataramanan 88828c2a645SAnirudh Venkataramanan /* TC is enabled */ 88928c2a645SAnirudh Venkataramanan vsi->tc_cfg.tc_info[i].qoffset = offset; 8908134d5ffSBrett Creeley vsi->tc_cfg.tc_info[i].qcount_rx = num_rxq_per_tc; 8918134d5ffSBrett Creeley vsi->tc_cfg.tc_info[i].qcount_tx = num_txq_per_tc; 892c5a2a4a3SUsha Ketineni vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 89328c2a645SAnirudh Venkataramanan 89428c2a645SAnirudh Venkataramanan qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 89528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_OFFSET_M) | 89628c2a645SAnirudh Venkataramanan ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 89728c2a645SAnirudh Venkataramanan ICE_AQ_VSI_TC_Q_NUM_M); 8988134d5ffSBrett Creeley offset += num_rxq_per_tc; 8998134d5ffSBrett Creeley tx_count += num_txq_per_tc; 90028c2a645SAnirudh Venkataramanan ctxt->info.tc_mapping[i] = cpu_to_le16(qmap); 90128c2a645SAnirudh Venkataramanan } 90260dcc39eSKiran Patil 90360dcc39eSKiran Patil /* if offset is non-zero, means it is calculated correctly based on 90460dcc39eSKiran Patil * enabled TCs for a given VSI otherwise qcount_rx will always 90560dcc39eSKiran Patil * be correct and non-zero because it is based off - VSI's 90660dcc39eSKiran Patil * allocated Rx queues which is at least 1 (hence qcount_tx will be 90760dcc39eSKiran Patil * at least 1) 90860dcc39eSKiran Patil */ 90960dcc39eSKiran Patil if (offset) 91028c2a645SAnirudh Venkataramanan vsi->num_rxq = offset; 91160dcc39eSKiran Patil else 9128134d5ffSBrett Creeley vsi->num_rxq = num_rxq_per_tc; 91360dcc39eSKiran Patil 914c5a2a4a3SUsha Ketineni vsi->num_txq = tx_count; 91528c2a645SAnirudh Venkataramanan 9168ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) { 9179a946843SAnirudh 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"); 9188ede0178SAnirudh Venkataramanan /* since there is a chance that num_rxq could have been changed 9198ede0178SAnirudh Venkataramanan * in the above for loop, make num_txq equal to num_rxq. 9208ede0178SAnirudh Venkataramanan */ 9218ede0178SAnirudh Venkataramanan vsi->num_txq = vsi->num_rxq; 9228ede0178SAnirudh Venkataramanan } 9238ede0178SAnirudh Venkataramanan 92428c2a645SAnirudh Venkataramanan /* Rx queue mapping */ 92528c2a645SAnirudh Venkataramanan ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 92628c2a645SAnirudh Venkataramanan /* q_mapping buffer holds the info for the first queue allocated for 92728c2a645SAnirudh Venkataramanan * this VSI in the PF space and also the number of queues associated 92828c2a645SAnirudh Venkataramanan * with this VSI. 92928c2a645SAnirudh Venkataramanan */ 93028c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 93128c2a645SAnirudh Venkataramanan ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq); 93228c2a645SAnirudh Venkataramanan } 93328c2a645SAnirudh Venkataramanan 93428c2a645SAnirudh Venkataramanan /** 935148beb61SHenry Tieman * ice_set_fd_vsi_ctx - Set FD VSI context before adding a VSI 936148beb61SHenry Tieman * @ctxt: the VSI context being set 937148beb61SHenry Tieman * @vsi: the VSI being configured 938148beb61SHenry Tieman */ 939148beb61SHenry Tieman static void ice_set_fd_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 940148beb61SHenry Tieman { 941148beb61SHenry Tieman u8 dflt_q_group, dflt_q_prio; 942148beb61SHenry Tieman u16 dflt_q, report_q, val; 943148beb61SHenry Tieman 944da62c5ffSQi Zhang if (vsi->type != ICE_VSI_PF && vsi->type != ICE_VSI_CTRL && 945da62c5ffSQi Zhang vsi->type != ICE_VSI_VF) 946148beb61SHenry Tieman return; 947148beb61SHenry Tieman 948148beb61SHenry Tieman val = ICE_AQ_VSI_PROP_FLOW_DIR_VALID; 949148beb61SHenry Tieman ctxt->info.valid_sections |= cpu_to_le16(val); 950148beb61SHenry Tieman dflt_q = 0; 951148beb61SHenry Tieman dflt_q_group = 0; 952148beb61SHenry Tieman report_q = 0; 953148beb61SHenry Tieman dflt_q_prio = 0; 954148beb61SHenry Tieman 955148beb61SHenry Tieman /* enable flow director filtering/programming */ 956148beb61SHenry Tieman val = ICE_AQ_VSI_FD_ENABLE | ICE_AQ_VSI_FD_PROG_ENABLE; 957148beb61SHenry Tieman ctxt->info.fd_options = cpu_to_le16(val); 958148beb61SHenry Tieman /* max of allocated flow director filters */ 959148beb61SHenry Tieman ctxt->info.max_fd_fltr_dedicated = 960148beb61SHenry Tieman cpu_to_le16(vsi->num_gfltr); 961148beb61SHenry Tieman /* max of shared flow director filters any VSI may program */ 962148beb61SHenry Tieman ctxt->info.max_fd_fltr_shared = 963148beb61SHenry Tieman cpu_to_le16(vsi->num_bfltr); 964148beb61SHenry Tieman /* default queue index within the VSI of the default FD */ 965148beb61SHenry Tieman val = ((dflt_q << ICE_AQ_VSI_FD_DEF_Q_S) & 966148beb61SHenry Tieman ICE_AQ_VSI_FD_DEF_Q_M); 967148beb61SHenry Tieman /* target queue or queue group to the FD filter */ 968148beb61SHenry Tieman val |= ((dflt_q_group << ICE_AQ_VSI_FD_DEF_GRP_S) & 969148beb61SHenry Tieman ICE_AQ_VSI_FD_DEF_GRP_M); 970148beb61SHenry Tieman ctxt->info.fd_def_q = cpu_to_le16(val); 971148beb61SHenry Tieman /* queue index on which FD filter completion is reported */ 972148beb61SHenry Tieman val = ((report_q << ICE_AQ_VSI_FD_REPORT_Q_S) & 973148beb61SHenry Tieman ICE_AQ_VSI_FD_REPORT_Q_M); 974148beb61SHenry Tieman /* priority of the default qindex action */ 975148beb61SHenry Tieman val |= ((dflt_q_prio << ICE_AQ_VSI_FD_DEF_PRIORITY_S) & 976148beb61SHenry Tieman ICE_AQ_VSI_FD_DEF_PRIORITY_M); 977148beb61SHenry Tieman ctxt->info.fd_report_opt = cpu_to_le16(val); 978148beb61SHenry Tieman } 979148beb61SHenry Tieman 980148beb61SHenry Tieman /** 98128c2a645SAnirudh Venkataramanan * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI 98228c2a645SAnirudh Venkataramanan * @ctxt: the VSI context being set 98328c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 98428c2a645SAnirudh Venkataramanan */ 98528c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) 98628c2a645SAnirudh Venkataramanan { 98728c2a645SAnirudh Venkataramanan u8 lut_type, hash_type; 9884015d11eSBrett Creeley struct device *dev; 989819d8998SJesse Brandeburg struct ice_pf *pf; 990819d8998SJesse Brandeburg 991819d8998SJesse Brandeburg pf = vsi->back; 9924015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 99328c2a645SAnirudh Venkataramanan 99428c2a645SAnirudh Venkataramanan switch (vsi->type) { 9950754d65bSKiran Patil case ICE_VSI_CHNL: 99628c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 99728c2a645SAnirudh Venkataramanan /* PF VSI will inherit RSS instance of PF */ 99828c2a645SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF; 99928c2a645SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 100028c2a645SAnirudh Venkataramanan break; 10018ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 10028ede0178SAnirudh Venkataramanan /* VF VSI will gets a small RSS table which is a VSI LUT type */ 10038ede0178SAnirudh Venkataramanan lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI; 10048ede0178SAnirudh Venkataramanan hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ; 10058ede0178SAnirudh Venkataramanan break; 1006148beb61SHenry Tieman default: 10074015d11eSBrett Creeley dev_dbg(dev, "Unsupported VSI type %s\n", 1008964674f1SAnirudh Venkataramanan ice_vsi_type_str(vsi->type)); 10090e674aebSAnirudh Venkataramanan return; 101028c2a645SAnirudh Venkataramanan } 101128c2a645SAnirudh Venkataramanan 101228c2a645SAnirudh Venkataramanan ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & 101328c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | 101428c2a645SAnirudh Venkataramanan ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & 101528c2a645SAnirudh Venkataramanan ICE_AQ_VSI_Q_OPT_RSS_HASH_M); 101628c2a645SAnirudh Venkataramanan } 101728c2a645SAnirudh Venkataramanan 10180754d65bSKiran Patil static void 10190754d65bSKiran Patil ice_chnl_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt) 10200754d65bSKiran Patil { 10210754d65bSKiran Patil struct ice_pf *pf = vsi->back; 10220754d65bSKiran Patil u16 qcount, qmap; 10230754d65bSKiran Patil u8 offset = 0; 10240754d65bSKiran Patil int pow; 10250754d65bSKiran Patil 10260754d65bSKiran Patil qcount = min_t(int, vsi->num_rxq, pf->num_lan_msix); 10270754d65bSKiran Patil 10280754d65bSKiran Patil pow = order_base_2(qcount); 10290754d65bSKiran Patil qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 10300754d65bSKiran Patil ICE_AQ_VSI_TC_Q_OFFSET_M) | 10310754d65bSKiran Patil ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & 10320754d65bSKiran Patil ICE_AQ_VSI_TC_Q_NUM_M); 10330754d65bSKiran Patil 10340754d65bSKiran Patil ctxt->info.tc_mapping[0] = cpu_to_le16(qmap); 10350754d65bSKiran Patil ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG); 10360754d65bSKiran Patil ctxt->info.q_mapping[0] = cpu_to_le16(vsi->next_base_q); 10370754d65bSKiran Patil ctxt->info.q_mapping[1] = cpu_to_le16(qcount); 10380754d65bSKiran Patil } 10390754d65bSKiran Patil 104028c2a645SAnirudh Venkataramanan /** 104128c2a645SAnirudh Venkataramanan * ice_vsi_init - Create and initialize a VSI 104228c2a645SAnirudh Venkataramanan * @vsi: the VSI being configured 104387324e74SHenry Tieman * @init_vsi: is this call creating a VSI 104428c2a645SAnirudh Venkataramanan * 104528c2a645SAnirudh Venkataramanan * This initializes a VSI context depending on the VSI type to be added and 104628c2a645SAnirudh Venkataramanan * passes it down to the add_vsi aq command to create a new VSI. 104728c2a645SAnirudh Venkataramanan */ 104887324e74SHenry Tieman static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi) 104928c2a645SAnirudh Venkataramanan { 105028c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 105128c2a645SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 1052198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 105387324e74SHenry Tieman struct device *dev; 105428c2a645SAnirudh Venkataramanan int ret = 0; 105528c2a645SAnirudh Venkataramanan 105687324e74SHenry Tieman dev = ice_pf_to_dev(pf); 10579efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 1058198a666aSBruce Allan if (!ctxt) 1059198a666aSBruce Allan return -ENOMEM; 1060198a666aSBruce Allan 106128c2a645SAnirudh Venkataramanan switch (vsi->type) { 1062148beb61SHenry Tieman case ICE_VSI_CTRL: 10630e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 106428c2a645SAnirudh Venkataramanan case ICE_VSI_PF: 1065198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_PF; 106628c2a645SAnirudh Venkataramanan break; 1067f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 10680754d65bSKiran Patil case ICE_VSI_CHNL: 1069f66756e0SGrzegorz Nitka ctxt->flags = ICE_AQ_VSI_TYPE_VMDQ2; 1070f66756e0SGrzegorz Nitka break; 10718ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 1072198a666aSBruce Allan ctxt->flags = ICE_AQ_VSI_TYPE_VF; 10738ede0178SAnirudh Venkataramanan /* VF number here is the absolute VF number (0-255) */ 1074198a666aSBruce Allan ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id; 10758ede0178SAnirudh Venkataramanan break; 107628c2a645SAnirudh Venkataramanan default: 10779efe35d0STony Nguyen ret = -ENODEV; 10789efe35d0STony Nguyen goto out; 107928c2a645SAnirudh Venkataramanan } 108028c2a645SAnirudh Venkataramanan 10810754d65bSKiran Patil /* Handle VLAN pruning for channel VSI if main VSI has VLAN 10820754d65bSKiran Patil * prune enabled 10830754d65bSKiran Patil */ 10840754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) { 10850754d65bSKiran Patil struct ice_vsi *main_vsi; 10860754d65bSKiran Patil 10870754d65bSKiran Patil main_vsi = ice_get_main_vsi(pf); 10880754d65bSKiran Patil if (main_vsi && ice_vsi_is_vlan_pruning_ena(main_vsi)) 10890754d65bSKiran Patil ctxt->info.sw_flags2 |= 10900754d65bSKiran Patil ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 10910754d65bSKiran Patil else 10920754d65bSKiran Patil ctxt->info.sw_flags2 &= 10930754d65bSKiran Patil ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 10940754d65bSKiran Patil } 10950754d65bSKiran Patil 1096198a666aSBruce Allan ice_set_dflt_vsi_ctx(ctxt); 1097148beb61SHenry Tieman if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) 1098148beb61SHenry Tieman ice_set_fd_vsi_ctx(ctxt, vsi); 109928c2a645SAnirudh Venkataramanan /* if the switch is in VEB mode, allow VSI loopback */ 110028c2a645SAnirudh Venkataramanan if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB) 1101198a666aSBruce Allan ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB; 110228c2a645SAnirudh Venkataramanan 110328c2a645SAnirudh Venkataramanan /* Set LUT type and HASH type if RSS is enabled */ 1104148beb61SHenry Tieman if (test_bit(ICE_FLAG_RSS_ENA, pf->flags) && 1105148beb61SHenry Tieman vsi->type != ICE_VSI_CTRL) { 1106198a666aSBruce Allan ice_set_rss_vsi_ctx(ctxt, vsi); 110787324e74SHenry Tieman /* if updating VSI context, make sure to set valid_section: 110887324e74SHenry Tieman * to indicate which section of VSI context being updated 110987324e74SHenry Tieman */ 111087324e74SHenry Tieman if (!init_vsi) 111187324e74SHenry Tieman ctxt->info.valid_sections |= 111287324e74SHenry Tieman cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID); 111387324e74SHenry Tieman } 111428c2a645SAnirudh Venkataramanan 1115198a666aSBruce Allan ctxt->info.sw_id = vsi->port_info->sw_id; 11160754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) { 11170754d65bSKiran Patil ice_chnl_vsi_setup_q_map(vsi, ctxt); 11180754d65bSKiran Patil } else { 1119198a666aSBruce Allan ice_vsi_setup_q_map(vsi, ctxt); 112087324e74SHenry Tieman if (!init_vsi) /* means VSI being updated */ 112187324e74SHenry Tieman /* must to indicate which section of VSI context are 112287324e74SHenry Tieman * being modified 112387324e74SHenry Tieman */ 112487324e74SHenry Tieman ctxt->info.valid_sections |= 112587324e74SHenry Tieman cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 11260754d65bSKiran Patil } 112728c2a645SAnirudh Venkataramanan 1128cd6d6b83SBrett Creeley /* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off 1129cd6d6b83SBrett Creeley * respectively 1130cd6d6b83SBrett Creeley */ 1131cd6d6b83SBrett Creeley if (vsi->type == ICE_VSI_VF) { 1132cb93a952SAkeem G Abodunrin ctxt->info.valid_sections |= 1133cb93a952SAkeem G Abodunrin cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 1134cd6d6b83SBrett Creeley if (pf->vf[vsi->vf_id].spoofchk) { 1135cb93a952SAkeem G Abodunrin ctxt->info.sec_flags |= 1136cd6d6b83SBrett Creeley ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | 1137cd6d6b83SBrett Creeley (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 1138cd6d6b83SBrett Creeley ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 1139cd6d6b83SBrett Creeley } else { 1140cd6d6b83SBrett Creeley ctxt->info.sec_flags &= 1141cd6d6b83SBrett Creeley ~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | 1142cd6d6b83SBrett Creeley (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 1143cd6d6b83SBrett Creeley ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S)); 1144cd6d6b83SBrett Creeley } 1145cb93a952SAkeem G Abodunrin } 1146cb93a952SAkeem G Abodunrin 11470c3a6101SDave Ertman /* Allow control frames out of main VSI */ 11480c3a6101SDave Ertman if (vsi->type == ICE_VSI_PF) { 11490c3a6101SDave Ertman ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; 11500c3a6101SDave Ertman ctxt->info.valid_sections |= 11510c3a6101SDave Ertman cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 11520c3a6101SDave Ertman } 11530c3a6101SDave Ertman 115487324e74SHenry Tieman if (init_vsi) { 1155198a666aSBruce Allan ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL); 115628c2a645SAnirudh Venkataramanan if (ret) { 115787324e74SHenry Tieman dev_err(dev, "Add VSI failed, err %d\n", ret); 11589efe35d0STony Nguyen ret = -EIO; 11599efe35d0STony Nguyen goto out; 116028c2a645SAnirudh Venkataramanan } 116187324e74SHenry Tieman } else { 116287324e74SHenry Tieman ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 116387324e74SHenry Tieman if (ret) { 116487324e74SHenry Tieman dev_err(dev, "Update VSI failed, err %d\n", ret); 116587324e74SHenry Tieman ret = -EIO; 116687324e74SHenry Tieman goto out; 116787324e74SHenry Tieman } 116887324e74SHenry Tieman } 116928c2a645SAnirudh Venkataramanan 117028c2a645SAnirudh Venkataramanan /* keep context for update VSI operations */ 1171198a666aSBruce Allan vsi->info = ctxt->info; 117228c2a645SAnirudh Venkataramanan 117328c2a645SAnirudh Venkataramanan /* record VSI number returned */ 1174198a666aSBruce Allan vsi->vsi_num = ctxt->vsi_num; 117528c2a645SAnirudh Venkataramanan 11769efe35d0STony Nguyen out: 11779efe35d0STony Nguyen kfree(ctxt); 117828c2a645SAnirudh Venkataramanan return ret; 117928c2a645SAnirudh Venkataramanan } 118028c2a645SAnirudh Venkataramanan 118128c2a645SAnirudh Venkataramanan /** 118246c276ceSBrett Creeley * ice_free_res - free a block of resources 118346c276ceSBrett Creeley * @res: pointer to the resource 118446c276ceSBrett Creeley * @index: starting index previously returned by ice_get_res 118546c276ceSBrett Creeley * @id: identifier to track owner 118646c276ceSBrett Creeley * 118746c276ceSBrett Creeley * Returns number of resources freed 118846c276ceSBrett Creeley */ 118946c276ceSBrett Creeley int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id) 119046c276ceSBrett Creeley { 119146c276ceSBrett Creeley int count = 0; 119246c276ceSBrett Creeley int i; 119346c276ceSBrett Creeley 119446c276ceSBrett Creeley if (!res || index >= res->end) 119546c276ceSBrett Creeley return -EINVAL; 119646c276ceSBrett Creeley 119746c276ceSBrett Creeley id |= ICE_RES_VALID_BIT; 119846c276ceSBrett Creeley for (i = index; i < res->end && res->list[i] == id; i++) { 119946c276ceSBrett Creeley res->list[i] = 0; 120046c276ceSBrett Creeley count++; 120146c276ceSBrett Creeley } 120246c276ceSBrett Creeley 120346c276ceSBrett Creeley return count; 120446c276ceSBrett Creeley } 120546c276ceSBrett Creeley 120646c276ceSBrett Creeley /** 120746c276ceSBrett Creeley * ice_search_res - Search the tracker for a block of resources 120846c276ceSBrett Creeley * @res: pointer to the resource 120946c276ceSBrett Creeley * @needed: size of the block needed 121046c276ceSBrett Creeley * @id: identifier to track owner 121146c276ceSBrett Creeley * 121246c276ceSBrett Creeley * Returns the base item index of the block, or -ENOMEM for error 121346c276ceSBrett Creeley */ 121446c276ceSBrett Creeley static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) 121546c276ceSBrett Creeley { 121688865fc4SKarol Kolacinski u16 start = 0, end = 0; 121746c276ceSBrett Creeley 121846c276ceSBrett Creeley if (needed > res->end) 121946c276ceSBrett Creeley return -ENOMEM; 122046c276ceSBrett Creeley 122146c276ceSBrett Creeley id |= ICE_RES_VALID_BIT; 122246c276ceSBrett Creeley 122346c276ceSBrett Creeley do { 122446c276ceSBrett Creeley /* skip already allocated entries */ 122546c276ceSBrett Creeley if (res->list[end++] & ICE_RES_VALID_BIT) { 122646c276ceSBrett Creeley start = end; 122746c276ceSBrett Creeley if ((start + needed) > res->end) 122846c276ceSBrett Creeley break; 122946c276ceSBrett Creeley } 123046c276ceSBrett Creeley 123146c276ceSBrett Creeley if (end == (start + needed)) { 123246c276ceSBrett Creeley int i = start; 123346c276ceSBrett Creeley 123446c276ceSBrett Creeley /* there was enough, so assign it to the requestor */ 123546c276ceSBrett Creeley while (i != end) 123646c276ceSBrett Creeley res->list[i++] = id; 123746c276ceSBrett Creeley 123846c276ceSBrett Creeley return start; 123946c276ceSBrett Creeley } 124046c276ceSBrett Creeley } while (end < res->end); 124146c276ceSBrett Creeley 124246c276ceSBrett Creeley return -ENOMEM; 124346c276ceSBrett Creeley } 124446c276ceSBrett Creeley 124546c276ceSBrett Creeley /** 124646c276ceSBrett Creeley * ice_get_free_res_count - Get free count from a resource tracker 124746c276ceSBrett Creeley * @res: Resource tracker instance 124846c276ceSBrett Creeley */ 124946c276ceSBrett Creeley static u16 ice_get_free_res_count(struct ice_res_tracker *res) 125046c276ceSBrett Creeley { 125146c276ceSBrett Creeley u16 i, count = 0; 125246c276ceSBrett Creeley 125346c276ceSBrett Creeley for (i = 0; i < res->end; i++) 125446c276ceSBrett Creeley if (!(res->list[i] & ICE_RES_VALID_BIT)) 125546c276ceSBrett Creeley count++; 125646c276ceSBrett Creeley 125746c276ceSBrett Creeley return count; 125846c276ceSBrett Creeley } 125946c276ceSBrett Creeley 126046c276ceSBrett Creeley /** 126146c276ceSBrett Creeley * ice_get_res - get a block of resources 126246c276ceSBrett Creeley * @pf: board private structure 126346c276ceSBrett Creeley * @res: pointer to the resource 126446c276ceSBrett Creeley * @needed: size of the block needed 126546c276ceSBrett Creeley * @id: identifier to track owner 126646c276ceSBrett Creeley * 126746c276ceSBrett Creeley * Returns the base item index of the block, or negative for error 126846c276ceSBrett Creeley */ 126946c276ceSBrett Creeley int 127046c276ceSBrett Creeley ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) 127146c276ceSBrett Creeley { 127246c276ceSBrett Creeley if (!res || !pf) 127346c276ceSBrett Creeley return -EINVAL; 127446c276ceSBrett Creeley 127546c276ceSBrett Creeley if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) { 127646c276ceSBrett Creeley dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n", 127746c276ceSBrett Creeley needed, res->num_entries, id); 127846c276ceSBrett Creeley return -EINVAL; 127946c276ceSBrett Creeley } 128046c276ceSBrett Creeley 128146c276ceSBrett Creeley return ice_search_res(res, needed, id); 128246c276ceSBrett Creeley } 128346c276ceSBrett Creeley 128446c276ceSBrett Creeley /** 1285df0f8479SAnirudh Venkataramanan * ice_vsi_setup_vector_base - Set up the base vector for the given VSI 1286df0f8479SAnirudh Venkataramanan * @vsi: ptr to the VSI 1287df0f8479SAnirudh Venkataramanan * 1288df0f8479SAnirudh Venkataramanan * This should only be called after ice_vsi_alloc() which allocates the 1289df0f8479SAnirudh Venkataramanan * corresponding SW VSI structure and initializes num_queue_pairs for the 1290df0f8479SAnirudh Venkataramanan * newly allocated VSI. 1291df0f8479SAnirudh Venkataramanan * 1292df0f8479SAnirudh Venkataramanan * Returns 0 on success or negative on failure 1293df0f8479SAnirudh Venkataramanan */ 129437bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) 1295df0f8479SAnirudh Venkataramanan { 1296df0f8479SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 12974015d11eSBrett Creeley struct device *dev; 1298cbe66bfeSBrett Creeley u16 num_q_vectors; 129988865fc4SKarol Kolacinski int base; 1300df0f8479SAnirudh Venkataramanan 13014015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 1302cbe66bfeSBrett Creeley /* SRIOV doesn't grab irq_tracker entries for each VSI */ 1303cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) 1304cbe66bfeSBrett Creeley return 0; 13050754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) 13060754d65bSKiran Patil return 0; 1307cbe66bfeSBrett Creeley 1308cbe66bfeSBrett Creeley if (vsi->base_vector) { 13094015d11eSBrett Creeley dev_dbg(dev, "VSI %d has non-zero base vector %d\n", 1310cbe66bfeSBrett Creeley vsi->vsi_num, vsi->base_vector); 1311df0f8479SAnirudh Venkataramanan return -EEXIST; 1312df0f8479SAnirudh Venkataramanan } 1313df0f8479SAnirudh Venkataramanan 1314df0f8479SAnirudh Venkataramanan num_q_vectors = vsi->num_q_vectors; 1315eb0208ecSPreethi Banala /* reserve slots from OS requested IRQs */ 1316da62c5ffSQi Zhang if (vsi->type == ICE_VSI_CTRL && vsi->vf_id != ICE_INVAL_VFID) { 1317da62c5ffSQi Zhang int i; 1318da62c5ffSQi Zhang 1319da62c5ffSQi Zhang ice_for_each_vf(pf, i) { 1320b6b0501dSPaul M Stillwell Jr struct ice_vf *vf = &pf->vf[i]; 1321b6b0501dSPaul M Stillwell Jr 1322da62c5ffSQi Zhang if (i != vsi->vf_id && vf->ctrl_vsi_idx != ICE_NO_VSI) { 1323da62c5ffSQi Zhang base = pf->vsi[vf->ctrl_vsi_idx]->base_vector; 1324da62c5ffSQi Zhang break; 1325da62c5ffSQi Zhang } 1326da62c5ffSQi Zhang } 1327da62c5ffSQi Zhang if (i == pf->num_alloc_vfs) 1328da62c5ffSQi Zhang base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, 1329da62c5ffSQi Zhang ICE_RES_VF_CTRL_VEC_ID); 1330da62c5ffSQi Zhang } else { 1331da62c5ffSQi Zhang base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, 1332da62c5ffSQi Zhang vsi->idx); 1333da62c5ffSQi Zhang } 133488865fc4SKarol Kolacinski 133588865fc4SKarol Kolacinski if (base < 0) { 133646c276ceSBrett Creeley dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n", 133746c276ceSBrett Creeley ice_get_free_res_count(pf->irq_tracker), 133846c276ceSBrett Creeley ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors); 1339eb0208ecSPreethi Banala return -ENOENT; 1340eb0208ecSPreethi Banala } 134188865fc4SKarol Kolacinski vsi->base_vector = (u16)base; 1342eb0208ecSPreethi Banala pf->num_avail_sw_msix -= num_q_vectors; 1343eb0208ecSPreethi Banala 1344df0f8479SAnirudh Venkataramanan return 0; 1345df0f8479SAnirudh Venkataramanan } 1346df0f8479SAnirudh Venkataramanan 1347df0f8479SAnirudh Venkataramanan /** 134828c2a645SAnirudh Venkataramanan * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI 134928c2a645SAnirudh Venkataramanan * @vsi: the VSI having rings deallocated 135028c2a645SAnirudh Venkataramanan */ 1351df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi) 135228c2a645SAnirudh Venkataramanan { 135328c2a645SAnirudh Venkataramanan int i; 135428c2a645SAnirudh Venkataramanan 1355f6a07271SJacob Keller /* Avoid stale references by clearing map from vector to ring */ 1356f6a07271SJacob Keller if (vsi->q_vectors) { 1357f6a07271SJacob Keller ice_for_each_q_vector(vsi, i) { 1358f6a07271SJacob Keller struct ice_q_vector *q_vector = vsi->q_vectors[i]; 1359f6a07271SJacob Keller 1360f6a07271SJacob Keller if (q_vector) { 1361e72bba21SMaciej Fijalkowski q_vector->tx.tx_ring = NULL; 1362e72bba21SMaciej Fijalkowski q_vector->rx.rx_ring = NULL; 1363f6a07271SJacob Keller } 1364f6a07271SJacob Keller } 1365f6a07271SJacob Keller } 1366f6a07271SJacob Keller 136728c2a645SAnirudh Venkataramanan if (vsi->tx_rings) { 13682faf63b6SMaciej Fijalkowski ice_for_each_alloc_txq(vsi, i) { 136928c2a645SAnirudh Venkataramanan if (vsi->tx_rings[i]) { 137028c2a645SAnirudh Venkataramanan kfree_rcu(vsi->tx_rings[i], rcu); 1371b1d95cc2SCiara Loftus WRITE_ONCE(vsi->tx_rings[i], NULL); 137228c2a645SAnirudh Venkataramanan } 137328c2a645SAnirudh Venkataramanan } 137428c2a645SAnirudh Venkataramanan } 137528c2a645SAnirudh Venkataramanan if (vsi->rx_rings) { 13762faf63b6SMaciej Fijalkowski ice_for_each_alloc_rxq(vsi, i) { 137728c2a645SAnirudh Venkataramanan if (vsi->rx_rings[i]) { 137828c2a645SAnirudh Venkataramanan kfree_rcu(vsi->rx_rings[i], rcu); 1379b1d95cc2SCiara Loftus WRITE_ONCE(vsi->rx_rings[i], NULL); 138028c2a645SAnirudh Venkataramanan } 138128c2a645SAnirudh Venkataramanan } 138228c2a645SAnirudh Venkataramanan } 138328c2a645SAnirudh Venkataramanan } 138428c2a645SAnirudh Venkataramanan 138528c2a645SAnirudh Venkataramanan /** 138628c2a645SAnirudh Venkataramanan * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI 138728c2a645SAnirudh Venkataramanan * @vsi: VSI which is having rings allocated 138828c2a645SAnirudh Venkataramanan */ 138937bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi) 139028c2a645SAnirudh Venkataramanan { 139128c2a645SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 13924015d11eSBrett Creeley struct device *dev; 139388865fc4SKarol Kolacinski u16 i; 139428c2a645SAnirudh Venkataramanan 13954015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 1396d337f2afSAnirudh Venkataramanan /* Allocate Tx rings */ 13972faf63b6SMaciej Fijalkowski ice_for_each_alloc_txq(vsi, i) { 1398e72bba21SMaciej Fijalkowski struct ice_tx_ring *ring; 139928c2a645SAnirudh Venkataramanan 140028c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 140128c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 140228c2a645SAnirudh Venkataramanan 140328c2a645SAnirudh Venkataramanan if (!ring) 140428c2a645SAnirudh Venkataramanan goto err_out; 140528c2a645SAnirudh Venkataramanan 140628c2a645SAnirudh Venkataramanan ring->q_index = i; 140728c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->txq_map[i]; 140828c2a645SAnirudh Venkataramanan ring->vsi = vsi; 1409ea9b847cSJacob Keller ring->tx_tstamps = &pf->ptp.port.tx; 14104015d11eSBrett Creeley ring->dev = dev; 1411ad71b256SBrett Creeley ring->count = vsi->num_tx_desc; 1412b1d95cc2SCiara Loftus WRITE_ONCE(vsi->tx_rings[i], ring); 141328c2a645SAnirudh Venkataramanan } 141428c2a645SAnirudh Venkataramanan 1415d337f2afSAnirudh Venkataramanan /* Allocate Rx rings */ 14162faf63b6SMaciej Fijalkowski ice_for_each_alloc_rxq(vsi, i) { 1417e72bba21SMaciej Fijalkowski struct ice_rx_ring *ring; 141828c2a645SAnirudh Venkataramanan 141928c2a645SAnirudh Venkataramanan /* allocate with kzalloc(), free with kfree_rcu() */ 142028c2a645SAnirudh Venkataramanan ring = kzalloc(sizeof(*ring), GFP_KERNEL); 142128c2a645SAnirudh Venkataramanan if (!ring) 142228c2a645SAnirudh Venkataramanan goto err_out; 142328c2a645SAnirudh Venkataramanan 142428c2a645SAnirudh Venkataramanan ring->q_index = i; 142528c2a645SAnirudh Venkataramanan ring->reg_idx = vsi->rxq_map[i]; 142628c2a645SAnirudh Venkataramanan ring->vsi = vsi; 142728c2a645SAnirudh Venkataramanan ring->netdev = vsi->netdev; 14284015d11eSBrett Creeley ring->dev = dev; 1429ad71b256SBrett Creeley ring->count = vsi->num_rx_desc; 1430b1d95cc2SCiara Loftus WRITE_ONCE(vsi->rx_rings[i], ring); 143128c2a645SAnirudh Venkataramanan } 143228c2a645SAnirudh Venkataramanan 143328c2a645SAnirudh Venkataramanan return 0; 143428c2a645SAnirudh Venkataramanan 143528c2a645SAnirudh Venkataramanan err_out: 143628c2a645SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 143728c2a645SAnirudh Venkataramanan return -ENOMEM; 143828c2a645SAnirudh Venkataramanan } 143928c2a645SAnirudh Venkataramanan 144028c2a645SAnirudh Venkataramanan /** 1441492af0abSMd Fahad Iqbal Polash * ice_vsi_manage_rss_lut - disable/enable RSS 1442492af0abSMd Fahad Iqbal Polash * @vsi: the VSI being changed 1443492af0abSMd Fahad Iqbal Polash * @ena: boolean value indicating if this is an enable or disable request 1444492af0abSMd Fahad Iqbal Polash * 1445492af0abSMd Fahad Iqbal Polash * In the event of disable request for RSS, this function will zero out RSS 1446492af0abSMd Fahad Iqbal Polash * LUT, while in the event of enable request for RSS, it will reconfigure RSS 1447492af0abSMd Fahad Iqbal Polash * LUT. 1448492af0abSMd Fahad Iqbal Polash */ 14494fe36226SPaul M Stillwell Jr void ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena) 1450492af0abSMd Fahad Iqbal Polash { 1451492af0abSMd Fahad Iqbal Polash u8 *lut; 1452492af0abSMd Fahad Iqbal Polash 14539efe35d0STony Nguyen lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); 1454492af0abSMd Fahad Iqbal Polash if (!lut) 14554fe36226SPaul M Stillwell Jr return; 1456492af0abSMd Fahad Iqbal Polash 1457492af0abSMd Fahad Iqbal Polash if (ena) { 1458492af0abSMd Fahad Iqbal Polash if (vsi->rss_lut_user) 1459492af0abSMd Fahad Iqbal Polash memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 1460492af0abSMd Fahad Iqbal Polash else 1461492af0abSMd Fahad Iqbal Polash ice_fill_rss_lut(lut, vsi->rss_table_size, 1462492af0abSMd Fahad Iqbal Polash vsi->rss_size); 1463492af0abSMd Fahad Iqbal Polash } 1464492af0abSMd Fahad Iqbal Polash 14654fe36226SPaul M Stillwell Jr ice_set_rss_lut(vsi, lut, vsi->rss_table_size); 14669efe35d0STony Nguyen kfree(lut); 1467492af0abSMd Fahad Iqbal Polash } 1468492af0abSMd Fahad Iqbal Polash 1469492af0abSMd Fahad Iqbal Polash /** 147037bb8390SAnirudh Venkataramanan * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI 147137bb8390SAnirudh Venkataramanan * @vsi: VSI to be configured 147237bb8390SAnirudh Venkataramanan */ 14730754d65bSKiran Patil int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi) 147437bb8390SAnirudh Venkataramanan { 147537bb8390SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 14764015d11eSBrett Creeley struct device *dev; 1477b66a972aSBrett Creeley u8 *lut, *key; 1478b66a972aSBrett Creeley int err; 147937bb8390SAnirudh Venkataramanan 14804015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 14810754d65bSKiran Patil if (vsi->type == ICE_VSI_PF && vsi->ch_rss_size && 14820754d65bSKiran Patil (test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))) { 14830754d65bSKiran Patil vsi->rss_size = min_t(u16, vsi->rss_size, vsi->ch_rss_size); 14840754d65bSKiran Patil } else { 148588865fc4SKarol Kolacinski vsi->rss_size = min_t(u16, vsi->rss_size, vsi->num_rxq); 148637bb8390SAnirudh Venkataramanan 14870754d65bSKiran Patil /* If orig_rss_size is valid and it is less than determined 14880754d65bSKiran Patil * main VSI's rss_size, update main VSI's rss_size to be 14890754d65bSKiran Patil * orig_rss_size so that when tc-qdisc is deleted, main VSI 14900754d65bSKiran Patil * RSS table gets programmed to be correct (whatever it was 14910754d65bSKiran Patil * to begin with (prior to setup-tc for ADQ config) 14920754d65bSKiran Patil */ 14930754d65bSKiran Patil if (vsi->orig_rss_size && vsi->rss_size < vsi->orig_rss_size && 14940754d65bSKiran Patil vsi->orig_rss_size <= vsi->num_rxq) { 14950754d65bSKiran Patil vsi->rss_size = vsi->orig_rss_size; 14960754d65bSKiran Patil /* now orig_rss_size is used, reset it to zero */ 14970754d65bSKiran Patil vsi->orig_rss_size = 0; 14980754d65bSKiran Patil } 14990754d65bSKiran Patil } 15000754d65bSKiran Patil 15019efe35d0STony Nguyen lut = kzalloc(vsi->rss_table_size, GFP_KERNEL); 150237bb8390SAnirudh Venkataramanan if (!lut) 150337bb8390SAnirudh Venkataramanan return -ENOMEM; 150437bb8390SAnirudh Venkataramanan 150537bb8390SAnirudh Venkataramanan if (vsi->rss_lut_user) 150637bb8390SAnirudh Venkataramanan memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size); 150737bb8390SAnirudh Venkataramanan else 150837bb8390SAnirudh Venkataramanan ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size); 150937bb8390SAnirudh Venkataramanan 1510b66a972aSBrett Creeley err = ice_set_rss_lut(vsi, lut, vsi->rss_table_size); 1511b66a972aSBrett Creeley if (err) { 1512b66a972aSBrett Creeley dev_err(dev, "set_rss_lut failed, error %d\n", err); 151337bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 151437bb8390SAnirudh Venkataramanan } 151537bb8390SAnirudh Venkataramanan 1516b66a972aSBrett Creeley key = kzalloc(ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE, GFP_KERNEL); 151737bb8390SAnirudh Venkataramanan if (!key) { 151837bb8390SAnirudh Venkataramanan err = -ENOMEM; 151937bb8390SAnirudh Venkataramanan goto ice_vsi_cfg_rss_exit; 152037bb8390SAnirudh Venkataramanan } 152137bb8390SAnirudh Venkataramanan 152237bb8390SAnirudh Venkataramanan if (vsi->rss_hkey_user) 1523b66a972aSBrett Creeley memcpy(key, vsi->rss_hkey_user, ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 152437bb8390SAnirudh Venkataramanan else 1525b66a972aSBrett Creeley netdev_rss_key_fill((void *)key, ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE); 152637bb8390SAnirudh Venkataramanan 1527b66a972aSBrett Creeley err = ice_set_rss_key(vsi, key); 1528b66a972aSBrett Creeley if (err) 1529b66a972aSBrett Creeley dev_err(dev, "set_rss_key failed, error %d\n", err); 153037bb8390SAnirudh Venkataramanan 15319efe35d0STony Nguyen kfree(key); 153237bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit: 15339efe35d0STony Nguyen kfree(lut); 153437bb8390SAnirudh Venkataramanan return err; 153537bb8390SAnirudh Venkataramanan } 153637bb8390SAnirudh Venkataramanan 153737bb8390SAnirudh Venkataramanan /** 15381c01c8c6SMd Fahad Iqbal Polash * ice_vsi_set_vf_rss_flow_fld - Sets VF VSI RSS input set for different flows 15391c01c8c6SMd Fahad Iqbal Polash * @vsi: VSI to be configured 15401c01c8c6SMd Fahad Iqbal Polash * 15411c01c8c6SMd Fahad Iqbal Polash * This function will only be called during the VF VSI setup. Upon successful 15421c01c8c6SMd Fahad Iqbal Polash * completion of package download, this function will configure default RSS 15431c01c8c6SMd Fahad Iqbal Polash * input sets for VF VSI. 15441c01c8c6SMd Fahad Iqbal Polash */ 15451c01c8c6SMd Fahad Iqbal Polash static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi) 15461c01c8c6SMd Fahad Iqbal Polash { 15471c01c8c6SMd Fahad Iqbal Polash struct ice_pf *pf = vsi->back; 15485e24d598STony Nguyen int status; 15491c01c8c6SMd Fahad Iqbal Polash struct device *dev; 15501c01c8c6SMd Fahad Iqbal Polash 15511c01c8c6SMd Fahad Iqbal Polash dev = ice_pf_to_dev(pf); 15521c01c8c6SMd Fahad Iqbal Polash if (ice_is_safe_mode(pf)) { 15531c01c8c6SMd Fahad Iqbal Polash dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n", 15541c01c8c6SMd Fahad Iqbal Polash vsi->vsi_num); 15551c01c8c6SMd Fahad Iqbal Polash return; 15561c01c8c6SMd Fahad Iqbal Polash } 15571c01c8c6SMd Fahad Iqbal Polash 15581c01c8c6SMd Fahad Iqbal Polash status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA); 15591c01c8c6SMd Fahad Iqbal Polash if (status) 15605f87ec48STony Nguyen dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %d\n", 15615f87ec48STony Nguyen vsi->vsi_num, status); 15621c01c8c6SMd Fahad Iqbal Polash } 15631c01c8c6SMd Fahad Iqbal Polash 15641c01c8c6SMd Fahad Iqbal Polash /** 1565c90ed40cSTony Nguyen * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows 1566c90ed40cSTony Nguyen * @vsi: VSI to be configured 1567c90ed40cSTony Nguyen * 1568c90ed40cSTony Nguyen * This function will only be called after successful download package call 1569c90ed40cSTony Nguyen * during initialization of PF. Since the downloaded package will erase the 1570c90ed40cSTony Nguyen * RSS section, this function will configure RSS input sets for different 1571c90ed40cSTony Nguyen * flow types. The last profile added has the highest priority, therefore 2 1572c90ed40cSTony Nguyen * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles 1573c90ed40cSTony Nguyen * (i.e. IPv4 src/dst TCP src/dst port). 1574c90ed40cSTony Nguyen */ 1575c90ed40cSTony Nguyen static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi) 1576c90ed40cSTony Nguyen { 1577c90ed40cSTony Nguyen u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num; 1578c90ed40cSTony Nguyen struct ice_pf *pf = vsi->back; 1579c90ed40cSTony Nguyen struct ice_hw *hw = &pf->hw; 15805e24d598STony Nguyen int status; 1581c90ed40cSTony Nguyen struct device *dev; 1582c90ed40cSTony Nguyen 1583c90ed40cSTony Nguyen dev = ice_pf_to_dev(pf); 1584c90ed40cSTony Nguyen if (ice_is_safe_mode(pf)) { 1585c90ed40cSTony Nguyen dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n", 1586c90ed40cSTony Nguyen vsi_num); 1587c90ed40cSTony Nguyen return; 1588c90ed40cSTony Nguyen } 1589c90ed40cSTony Nguyen /* configure RSS for IPv4 with input set IP src/dst */ 1590c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4, 1591c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_IPV4); 1592c90ed40cSTony Nguyen if (status) 15935f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %d\n", 15945f87ec48STony Nguyen vsi_num, status); 1595c90ed40cSTony Nguyen 1596c90ed40cSTony Nguyen /* configure RSS for IPv6 with input set IPv6 src/dst */ 1597c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6, 1598c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_IPV6); 1599c90ed40cSTony Nguyen if (status) 16005f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %d\n", 16015f87ec48STony Nguyen vsi_num, status); 1602c90ed40cSTony Nguyen 1603c90ed40cSTony Nguyen /* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */ 1604c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4, 1605c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4); 1606c90ed40cSTony Nguyen if (status) 16075f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %d\n", 16085f87ec48STony Nguyen vsi_num, status); 1609c90ed40cSTony Nguyen 1610c90ed40cSTony Nguyen /* configure RSS for udp4 with input set IP src/dst, UDP src/dst */ 1611c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4, 1612c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4); 1613c90ed40cSTony Nguyen if (status) 16145f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %d\n", 16155f87ec48STony Nguyen vsi_num, status); 1616c90ed40cSTony Nguyen 1617c90ed40cSTony Nguyen /* configure RSS for sctp4 with input set IP src/dst */ 1618c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4, 1619c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4); 1620c90ed40cSTony Nguyen if (status) 16215f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %d\n", 16225f87ec48STony Nguyen vsi_num, status); 1623c90ed40cSTony Nguyen 1624c90ed40cSTony Nguyen /* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */ 1625c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6, 1626c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6); 1627c90ed40cSTony Nguyen if (status) 16285f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %d\n", 16295f87ec48STony Nguyen vsi_num, status); 1630c90ed40cSTony Nguyen 1631c90ed40cSTony Nguyen /* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */ 1632c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6, 1633c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6); 1634c90ed40cSTony Nguyen if (status) 16355f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %d\n", 16365f87ec48STony Nguyen vsi_num, status); 1637c90ed40cSTony Nguyen 1638c90ed40cSTony Nguyen /* configure RSS for sctp6 with input set IPv6 src/dst */ 1639c90ed40cSTony Nguyen status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6, 1640c90ed40cSTony Nguyen ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6); 1641c90ed40cSTony Nguyen if (status) 16425f87ec48STony Nguyen dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %d\n", 16435f87ec48STony Nguyen vsi_num, status); 1644c90ed40cSTony Nguyen } 1645c90ed40cSTony Nguyen 1646c90ed40cSTony Nguyen /** 1647769c500dSAkeem G Abodunrin * ice_pf_state_is_nominal - checks the PF for nominal state 1648769c500dSAkeem G Abodunrin * @pf: pointer to PF to check 1649769c500dSAkeem G Abodunrin * 1650769c500dSAkeem G Abodunrin * Check the PF's state for a collection of bits that would indicate 1651769c500dSAkeem G Abodunrin * the PF is in a state that would inhibit normal operation for 1652769c500dSAkeem G Abodunrin * driver functionality. 1653769c500dSAkeem G Abodunrin * 1654769c500dSAkeem G Abodunrin * Returns true if PF is in a nominal state, false otherwise 1655769c500dSAkeem G Abodunrin */ 1656769c500dSAkeem G Abodunrin bool ice_pf_state_is_nominal(struct ice_pf *pf) 1657769c500dSAkeem G Abodunrin { 16587e408e07SAnirudh Venkataramanan DECLARE_BITMAP(check_bits, ICE_STATE_NBITS) = { 0 }; 1659769c500dSAkeem G Abodunrin 1660769c500dSAkeem G Abodunrin if (!pf) 1661769c500dSAkeem G Abodunrin return false; 1662769c500dSAkeem G Abodunrin 16637e408e07SAnirudh Venkataramanan bitmap_set(check_bits, 0, ICE_STATE_NOMINAL_CHECK_BITS); 16647e408e07SAnirudh Venkataramanan if (bitmap_intersects(pf->state, check_bits, ICE_STATE_NBITS)) 1665769c500dSAkeem G Abodunrin return false; 1666769c500dSAkeem G Abodunrin 1667769c500dSAkeem G Abodunrin return true; 1668769c500dSAkeem G Abodunrin } 1669769c500dSAkeem G Abodunrin 1670769c500dSAkeem G Abodunrin /** 167145d3d428SAnirudh Venkataramanan * ice_update_eth_stats - Update VSI-specific ethernet statistics counters 167245d3d428SAnirudh Venkataramanan * @vsi: the VSI to be updated 167345d3d428SAnirudh Venkataramanan */ 167445d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi) 167545d3d428SAnirudh Venkataramanan { 167645d3d428SAnirudh Venkataramanan struct ice_eth_stats *prev_es, *cur_es; 167745d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 167845d3d428SAnirudh Venkataramanan u16 vsi_num = vsi->vsi_num; /* HW absolute index of a VSI */ 167945d3d428SAnirudh Venkataramanan 168045d3d428SAnirudh Venkataramanan prev_es = &vsi->eth_stats_prev; 168145d3d428SAnirudh Venkataramanan cur_es = &vsi->eth_stats; 168245d3d428SAnirudh Venkataramanan 168336517fd3SJacob Keller ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded, 168436517fd3SJacob Keller &prev_es->rx_bytes, &cur_es->rx_bytes); 168545d3d428SAnirudh Venkataramanan 168636517fd3SJacob Keller ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded, 168736517fd3SJacob Keller &prev_es->rx_unicast, &cur_es->rx_unicast); 168845d3d428SAnirudh Venkataramanan 168936517fd3SJacob Keller ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded, 169036517fd3SJacob Keller &prev_es->rx_multicast, &cur_es->rx_multicast); 169145d3d428SAnirudh Venkataramanan 169236517fd3SJacob Keller ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded, 169336517fd3SJacob Keller &prev_es->rx_broadcast, &cur_es->rx_broadcast); 169445d3d428SAnirudh Venkataramanan 169545d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded, 169645d3d428SAnirudh Venkataramanan &prev_es->rx_discards, &cur_es->rx_discards); 169745d3d428SAnirudh Venkataramanan 169836517fd3SJacob Keller ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded, 169936517fd3SJacob Keller &prev_es->tx_bytes, &cur_es->tx_bytes); 170045d3d428SAnirudh Venkataramanan 170136517fd3SJacob Keller ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded, 170236517fd3SJacob Keller &prev_es->tx_unicast, &cur_es->tx_unicast); 170345d3d428SAnirudh Venkataramanan 170436517fd3SJacob Keller ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded, 170536517fd3SJacob Keller &prev_es->tx_multicast, &cur_es->tx_multicast); 170645d3d428SAnirudh Venkataramanan 170736517fd3SJacob Keller ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded, 170836517fd3SJacob Keller &prev_es->tx_broadcast, &cur_es->tx_broadcast); 170945d3d428SAnirudh Venkataramanan 171045d3d428SAnirudh Venkataramanan ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded, 171145d3d428SAnirudh Venkataramanan &prev_es->tx_errors, &cur_es->tx_errors); 171245d3d428SAnirudh Venkataramanan 171345d3d428SAnirudh Venkataramanan vsi->stat_offsets_loaded = true; 171445d3d428SAnirudh Venkataramanan } 171545d3d428SAnirudh Venkataramanan 171645d3d428SAnirudh Venkataramanan /** 171745d3d428SAnirudh Venkataramanan * ice_vsi_add_vlan - Add VSI membership for given VLAN 171845d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1719f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be added 17201b8f15b6SMichal Swiatkowski * @action: filter action to be performed on match 172145d3d428SAnirudh Venkataramanan */ 17221b8f15b6SMichal Swiatkowski int 17231b8f15b6SMichal Swiatkowski ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action) 172445d3d428SAnirudh Venkataramanan { 172545d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 17264015d11eSBrett Creeley struct device *dev; 172745d3d428SAnirudh Venkataramanan int err = 0; 172845d3d428SAnirudh Venkataramanan 17294015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 173045d3d428SAnirudh Venkataramanan 17311b8f15b6SMichal Swiatkowski if (!ice_fltr_add_vlan(vsi, vid, action)) { 173242f3efefSBrett Creeley vsi->num_vlan++; 173342f3efefSBrett Creeley } else { 173445d3d428SAnirudh Venkataramanan err = -ENODEV; 17354015d11eSBrett Creeley dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid, 17364015d11eSBrett Creeley vsi->vsi_num); 173745d3d428SAnirudh Venkataramanan } 173845d3d428SAnirudh Venkataramanan 173945d3d428SAnirudh Venkataramanan return err; 174045d3d428SAnirudh Venkataramanan } 174145d3d428SAnirudh Venkataramanan 174245d3d428SAnirudh Venkataramanan /** 174345d3d428SAnirudh Venkataramanan * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN 174445d3d428SAnirudh Venkataramanan * @vsi: the VSI being configured 1745f9867df6SAnirudh Venkataramanan * @vid: VLAN ID to be removed 174645d3d428SAnirudh Venkataramanan * 174745d3d428SAnirudh Venkataramanan * Returns 0 on success and negative on failure 174845d3d428SAnirudh Venkataramanan */ 174945d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid) 175045d3d428SAnirudh Venkataramanan { 175145d3d428SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 17525e24d598STony Nguyen int status; 17534015d11eSBrett Creeley struct device *dev; 17545079b853SAkeem G Abodunrin int err = 0; 175545d3d428SAnirudh Venkataramanan 17564015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 175745d3d428SAnirudh Venkataramanan 17581b8f15b6SMichal Swiatkowski status = ice_fltr_remove_vlan(vsi, vid, ICE_FWD_TO_VSI); 175942f3efefSBrett Creeley if (!status) { 176042f3efefSBrett Creeley vsi->num_vlan--; 1761*d54699e2STony Nguyen } else if (status == -ENOENT) { 17625f87ec48STony Nguyen dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, error: %d\n", 17635f87ec48STony Nguyen vid, vsi->vsi_num, status); 176442f3efefSBrett Creeley } else { 17655f87ec48STony Nguyen dev_err(dev, "Error removing VLAN %d on vsi %i error: %d\n", 17665f87ec48STony Nguyen vid, vsi->vsi_num, status); 17675079b853SAkeem G Abodunrin err = -EIO; 176845d3d428SAnirudh Venkataramanan } 176945d3d428SAnirudh Venkataramanan 17705079b853SAkeem G Abodunrin return err; 177145d3d428SAnirudh Venkataramanan } 177245d3d428SAnirudh Venkataramanan 177345d3d428SAnirudh Venkataramanan /** 1774efc2214bSMaciej Fijalkowski * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length 1775efc2214bSMaciej Fijalkowski * @vsi: VSI 1776efc2214bSMaciej Fijalkowski */ 1777efc2214bSMaciej Fijalkowski void ice_vsi_cfg_frame_size(struct ice_vsi *vsi) 1778efc2214bSMaciej Fijalkowski { 17797237f5b0SMaciej Fijalkowski if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) { 17807237f5b0SMaciej Fijalkowski vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX; 1781efc2214bSMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_2048; 17827237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192) 178359bb0808SMaciej Fijalkowski } else if (!ICE_2K_TOO_SMALL_WITH_PADDING && 178459bb0808SMaciej Fijalkowski (vsi->netdev->mtu <= ETH_DATA_LEN)) { 17857237f5b0SMaciej Fijalkowski vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN; 17867237f5b0SMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN; 17877237f5b0SMaciej Fijalkowski #endif 17887237f5b0SMaciej Fijalkowski } else { 17897237f5b0SMaciej Fijalkowski vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX; 17907237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192) 17917237f5b0SMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_3072; 17927237f5b0SMaciej Fijalkowski #else 17937237f5b0SMaciej Fijalkowski vsi->rx_buf_len = ICE_RXBUF_2048; 17947237f5b0SMaciej Fijalkowski #endif 17957237f5b0SMaciej Fijalkowski } 1796efc2214bSMaciej Fijalkowski } 1797efc2214bSMaciej Fijalkowski 1798efc2214bSMaciej Fijalkowski /** 1799401ce33bSBrett Creeley * ice_write_qrxflxp_cntxt - write/configure QRXFLXP_CNTXT register 1800401ce33bSBrett Creeley * @hw: HW pointer 1801401ce33bSBrett Creeley * @pf_q: index of the Rx queue in the PF's queue space 1802401ce33bSBrett Creeley * @rxdid: flexible descriptor RXDID 1803401ce33bSBrett Creeley * @prio: priority for the RXDID for this queue 180477a78115SJacob Keller * @ena_ts: true to enable timestamp and false to disable timestamp 1805401ce33bSBrett Creeley */ 1806401ce33bSBrett Creeley void 180777a78115SJacob Keller ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio, 180877a78115SJacob Keller bool ena_ts) 1809401ce33bSBrett Creeley { 1810401ce33bSBrett Creeley int regval = rd32(hw, QRXFLXP_CNTXT(pf_q)); 1811401ce33bSBrett Creeley 1812401ce33bSBrett Creeley /* clear any previous values */ 1813401ce33bSBrett Creeley regval &= ~(QRXFLXP_CNTXT_RXDID_IDX_M | 1814401ce33bSBrett Creeley QRXFLXP_CNTXT_RXDID_PRIO_M | 1815401ce33bSBrett Creeley QRXFLXP_CNTXT_TS_M); 1816401ce33bSBrett Creeley 1817401ce33bSBrett Creeley regval |= (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) & 1818401ce33bSBrett Creeley QRXFLXP_CNTXT_RXDID_IDX_M; 1819401ce33bSBrett Creeley 1820401ce33bSBrett Creeley regval |= (prio << QRXFLXP_CNTXT_RXDID_PRIO_S) & 1821401ce33bSBrett Creeley QRXFLXP_CNTXT_RXDID_PRIO_M; 1822401ce33bSBrett Creeley 182377a78115SJacob Keller if (ena_ts) 182477a78115SJacob Keller /* Enable TimeSync on this queue */ 182577a78115SJacob Keller regval |= QRXFLXP_CNTXT_TS_M; 182677a78115SJacob Keller 1827401ce33bSBrett Creeley wr32(hw, QRXFLXP_CNTXT(pf_q), regval); 1828401ce33bSBrett Creeley } 1829401ce33bSBrett Creeley 18307ad15440SBrett Creeley int ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx) 18317ad15440SBrett Creeley { 18327ad15440SBrett Creeley if (q_idx >= vsi->num_rxq) 18337ad15440SBrett Creeley return -EINVAL; 18347ad15440SBrett Creeley 18357ad15440SBrett Creeley return ice_vsi_cfg_rxq(vsi->rx_rings[q_idx]); 18367ad15440SBrett Creeley } 18377ad15440SBrett Creeley 1838e72bba21SMaciej Fijalkowski int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings, u16 q_idx) 18397ad15440SBrett Creeley { 18407ad15440SBrett Creeley struct ice_aqc_add_tx_qgrp *qg_buf; 18417ad15440SBrett Creeley int err; 18427ad15440SBrett Creeley 18437ad15440SBrett Creeley if (q_idx >= vsi->alloc_txq || !tx_rings || !tx_rings[q_idx]) 18447ad15440SBrett Creeley return -EINVAL; 18457ad15440SBrett Creeley 18467ad15440SBrett Creeley qg_buf = kzalloc(struct_size(qg_buf, txqs, 1), GFP_KERNEL); 18477ad15440SBrett Creeley if (!qg_buf) 18487ad15440SBrett Creeley return -ENOMEM; 18497ad15440SBrett Creeley 18507ad15440SBrett Creeley qg_buf->num_txqs = 1; 18517ad15440SBrett Creeley 18527ad15440SBrett Creeley err = ice_vsi_cfg_txq(vsi, tx_rings[q_idx], qg_buf); 18537ad15440SBrett Creeley kfree(qg_buf); 18547ad15440SBrett Creeley return err; 18557ad15440SBrett Creeley } 18567ad15440SBrett Creeley 1857401ce33bSBrett Creeley /** 185872adf242SAnirudh Venkataramanan * ice_vsi_cfg_rxqs - Configure the VSI for Rx 185972adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 186072adf242SAnirudh Venkataramanan * 186172adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 186272adf242SAnirudh Venkataramanan * Configure the Rx VSI for operation. 186372adf242SAnirudh Venkataramanan */ 186472adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi) 186572adf242SAnirudh Venkataramanan { 186672adf242SAnirudh Venkataramanan u16 i; 186772adf242SAnirudh Venkataramanan 18688ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 18698ede0178SAnirudh Venkataramanan goto setup_rings; 18708ede0178SAnirudh Venkataramanan 1871efc2214bSMaciej Fijalkowski ice_vsi_cfg_frame_size(vsi); 18728ede0178SAnirudh Venkataramanan setup_rings: 187372adf242SAnirudh Venkataramanan /* set up individual rings */ 187443c7f919SKrzysztof Kazimierczak ice_for_each_rxq(vsi, i) { 187543c7f919SKrzysztof Kazimierczak int err = ice_vsi_cfg_rxq(vsi->rx_rings[i]); 187672adf242SAnirudh Venkataramanan 187743c7f919SKrzysztof Kazimierczak if (err) 187872adf242SAnirudh Venkataramanan return err; 187972adf242SAnirudh Venkataramanan } 18801553f4f7SBrett Creeley 18811553f4f7SBrett Creeley return 0; 18821553f4f7SBrett Creeley } 188372adf242SAnirudh Venkataramanan 188472adf242SAnirudh Venkataramanan /** 188572adf242SAnirudh Venkataramanan * ice_vsi_cfg_txqs - Configure the VSI for Tx 188672adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 188703f7a986SAnirudh Venkataramanan * @rings: Tx ring array to be configured 18882e84f6b3SMaciej Fijalkowski * @count: number of Tx ring array elements 188972adf242SAnirudh Venkataramanan * 189072adf242SAnirudh Venkataramanan * Return 0 on success and a negative value on error 189172adf242SAnirudh Venkataramanan * Configure the Tx VSI for operation. 189272adf242SAnirudh Venkataramanan */ 189303f7a986SAnirudh Venkataramanan static int 1894e72bba21SMaciej Fijalkowski ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_tx_ring **rings, u16 count) 189572adf242SAnirudh Venkataramanan { 189672adf242SAnirudh Venkataramanan struct ice_aqc_add_tx_qgrp *qg_buf; 1897e75d1b2cSMaciej Fijalkowski u16 q_idx = 0; 1898d02f734cSMaciej Fijalkowski int err = 0; 189972adf242SAnirudh Venkataramanan 190066486d89SBruce Allan qg_buf = kzalloc(struct_size(qg_buf, txqs, 1), GFP_KERNEL); 190172adf242SAnirudh Venkataramanan if (!qg_buf) 190272adf242SAnirudh Venkataramanan return -ENOMEM; 190372adf242SAnirudh Venkataramanan 190472adf242SAnirudh Venkataramanan qg_buf->num_txqs = 1; 190572adf242SAnirudh Venkataramanan 19062e84f6b3SMaciej Fijalkowski for (q_idx = 0; q_idx < count; q_idx++) { 1907e75d1b2cSMaciej Fijalkowski err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf); 1908d02f734cSMaciej Fijalkowski if (err) 190972adf242SAnirudh Venkataramanan goto err_cfg_txqs; 1910e75d1b2cSMaciej Fijalkowski } 1911c5a2a4a3SUsha Ketineni 191272adf242SAnirudh Venkataramanan err_cfg_txqs: 1913e75d1b2cSMaciej Fijalkowski kfree(qg_buf); 191472adf242SAnirudh Venkataramanan return err; 191572adf242SAnirudh Venkataramanan } 191672adf242SAnirudh Venkataramanan 191772adf242SAnirudh Venkataramanan /** 191803f7a986SAnirudh Venkataramanan * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx 191903f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 192003f7a986SAnirudh Venkataramanan * 192103f7a986SAnirudh Venkataramanan * Return 0 on success and a negative value on error 192203f7a986SAnirudh Venkataramanan * Configure the Tx VSI for operation. 192303f7a986SAnirudh Venkataramanan */ 192403f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi) 192503f7a986SAnirudh Venkataramanan { 19262e84f6b3SMaciej Fijalkowski return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, vsi->num_txq); 192703f7a986SAnirudh Venkataramanan } 192803f7a986SAnirudh Venkataramanan 192903f7a986SAnirudh Venkataramanan /** 1930efc2214bSMaciej Fijalkowski * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI 1931efc2214bSMaciej Fijalkowski * @vsi: the VSI being configured 1932efc2214bSMaciej Fijalkowski * 1933efc2214bSMaciej Fijalkowski * Return 0 on success and a negative value on error 1934efc2214bSMaciej Fijalkowski * Configure the Tx queues dedicated for XDP in given VSI for operation. 1935efc2214bSMaciej Fijalkowski */ 1936efc2214bSMaciej Fijalkowski int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi) 1937efc2214bSMaciej Fijalkowski { 19382d4238f5SKrzysztof Kazimierczak int ret; 19392d4238f5SKrzysztof Kazimierczak int i; 19402d4238f5SKrzysztof Kazimierczak 19412e84f6b3SMaciej Fijalkowski ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings, vsi->num_xdp_txq); 19422d4238f5SKrzysztof Kazimierczak if (ret) 19432d4238f5SKrzysztof Kazimierczak return ret; 19442d4238f5SKrzysztof Kazimierczak 19452faf63b6SMaciej Fijalkowski ice_for_each_xdp_txq(vsi, i) 1946e72bba21SMaciej Fijalkowski vsi->xdp_rings[i]->xsk_pool = ice_tx_xsk_pool(vsi->xdp_rings[i]); 19472d4238f5SKrzysztof Kazimierczak 19482d4238f5SKrzysztof Kazimierczak return ret; 1949efc2214bSMaciej Fijalkowski } 1950efc2214bSMaciej Fijalkowski 1951efc2214bSMaciej Fijalkowski /** 19529e4ab4c2SBrett Creeley * ice_intrl_usec_to_reg - convert interrupt rate limit to register value 19539e4ab4c2SBrett Creeley * @intrl: interrupt rate limit in usecs 19549e4ab4c2SBrett Creeley * @gran: interrupt rate limit granularity in usecs 19559e4ab4c2SBrett Creeley * 19569e4ab4c2SBrett Creeley * This function converts a decimal interrupt rate limit in usecs to the format 19579e4ab4c2SBrett Creeley * expected by firmware. 19589e4ab4c2SBrett Creeley */ 1959b8b47723SJesse Brandeburg static u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran) 19609e4ab4c2SBrett Creeley { 19619e4ab4c2SBrett Creeley u32 val = intrl / gran; 19629e4ab4c2SBrett Creeley 19639e4ab4c2SBrett Creeley if (val) 19649e4ab4c2SBrett Creeley return val | GLINT_RATE_INTRL_ENA_M; 19659e4ab4c2SBrett Creeley return 0; 19669e4ab4c2SBrett Creeley } 19679e4ab4c2SBrett Creeley 19689e4ab4c2SBrett Creeley /** 1969b8b47723SJesse Brandeburg * ice_write_intrl - write throttle rate limit to interrupt specific register 1970b8b47723SJesse Brandeburg * @q_vector: pointer to interrupt specific structure 1971b8b47723SJesse Brandeburg * @intrl: throttle rate limit in microseconds to write 1972b8b47723SJesse Brandeburg */ 1973b8b47723SJesse Brandeburg void ice_write_intrl(struct ice_q_vector *q_vector, u8 intrl) 1974b8b47723SJesse Brandeburg { 1975b8b47723SJesse Brandeburg struct ice_hw *hw = &q_vector->vsi->back->hw; 1976b8b47723SJesse Brandeburg 1977b8b47723SJesse Brandeburg wr32(hw, GLINT_RATE(q_vector->reg_idx), 1978b8b47723SJesse Brandeburg ice_intrl_usec_to_reg(intrl, ICE_INTRL_GRAN_ABOVE_25)); 1979b8b47723SJesse Brandeburg } 1980b8b47723SJesse Brandeburg 1981e72bba21SMaciej Fijalkowski static struct ice_q_vector *ice_pull_qvec_from_rc(struct ice_ring_container *rc) 1982e72bba21SMaciej Fijalkowski { 1983e72bba21SMaciej Fijalkowski switch (rc->type) { 1984e72bba21SMaciej Fijalkowski case ICE_RX_CONTAINER: 1985e72bba21SMaciej Fijalkowski if (rc->rx_ring) 1986e72bba21SMaciej Fijalkowski return rc->rx_ring->q_vector; 1987e72bba21SMaciej Fijalkowski break; 1988e72bba21SMaciej Fijalkowski case ICE_TX_CONTAINER: 1989e72bba21SMaciej Fijalkowski if (rc->tx_ring) 1990e72bba21SMaciej Fijalkowski return rc->tx_ring->q_vector; 1991370764e6SNathan Chancellor break; 1992e72bba21SMaciej Fijalkowski default: 1993e72bba21SMaciej Fijalkowski break; 1994e72bba21SMaciej Fijalkowski } 1995e72bba21SMaciej Fijalkowski 1996e72bba21SMaciej Fijalkowski return NULL; 1997e72bba21SMaciej Fijalkowski } 1998e72bba21SMaciej Fijalkowski 1999b8b47723SJesse Brandeburg /** 2000b8b47723SJesse Brandeburg * __ice_write_itr - write throttle rate to register 2001b8b47723SJesse Brandeburg * @q_vector: pointer to interrupt data structure 2002b8b47723SJesse Brandeburg * @rc: pointer to ring container 2003b8b47723SJesse Brandeburg * @itr: throttle rate in microseconds to write 2004b8b47723SJesse Brandeburg */ 2005b8b47723SJesse Brandeburg static void __ice_write_itr(struct ice_q_vector *q_vector, 2006b8b47723SJesse Brandeburg struct ice_ring_container *rc, u16 itr) 2007b8b47723SJesse Brandeburg { 2008b8b47723SJesse Brandeburg struct ice_hw *hw = &q_vector->vsi->back->hw; 2009b8b47723SJesse Brandeburg 2010b8b47723SJesse Brandeburg wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx), 2011b8b47723SJesse Brandeburg ITR_REG_ALIGN(itr) >> ICE_ITR_GRAN_S); 2012b8b47723SJesse Brandeburg } 2013b8b47723SJesse Brandeburg 2014b8b47723SJesse Brandeburg /** 2015b8b47723SJesse Brandeburg * ice_write_itr - write throttle rate to queue specific register 2016b8b47723SJesse Brandeburg * @rc: pointer to ring container 2017b8b47723SJesse Brandeburg * @itr: throttle rate in microseconds to write 2018b8b47723SJesse Brandeburg */ 2019b8b47723SJesse Brandeburg void ice_write_itr(struct ice_ring_container *rc, u16 itr) 2020b8b47723SJesse Brandeburg { 2021b8b47723SJesse Brandeburg struct ice_q_vector *q_vector; 2022b8b47723SJesse Brandeburg 2023e72bba21SMaciej Fijalkowski q_vector = ice_pull_qvec_from_rc(rc); 2024e72bba21SMaciej Fijalkowski if (!q_vector) 2025b8b47723SJesse Brandeburg return; 2026b8b47723SJesse Brandeburg 2027b8b47723SJesse Brandeburg __ice_write_itr(q_vector, rc, itr); 2028b8b47723SJesse Brandeburg } 2029b8b47723SJesse Brandeburg 2030b8b47723SJesse Brandeburg /** 2031d8eb7ad5SJesse Brandeburg * ice_set_q_vector_intrl - set up interrupt rate limiting 2032d8eb7ad5SJesse Brandeburg * @q_vector: the vector to be configured 2033d8eb7ad5SJesse Brandeburg * 2034d8eb7ad5SJesse Brandeburg * Interrupt rate limiting is local to the vector, not per-queue so we must 2035d8eb7ad5SJesse Brandeburg * detect if either ring container has dynamic moderation enabled to decide 2036d8eb7ad5SJesse Brandeburg * what to set the interrupt rate limit to via INTRL settings. In the case that 2037d8eb7ad5SJesse Brandeburg * dynamic moderation is disabled on both, write the value with the cached 2038d8eb7ad5SJesse Brandeburg * setting to make sure INTRL register matches the user visible value. 2039d8eb7ad5SJesse Brandeburg */ 2040d8eb7ad5SJesse Brandeburg void ice_set_q_vector_intrl(struct ice_q_vector *q_vector) 2041d8eb7ad5SJesse Brandeburg { 2042d8eb7ad5SJesse Brandeburg if (ITR_IS_DYNAMIC(&q_vector->tx) || ITR_IS_DYNAMIC(&q_vector->rx)) { 2043d8eb7ad5SJesse Brandeburg /* in the case of dynamic enabled, cap each vector to no more 2044d8eb7ad5SJesse Brandeburg * than (4 us) 250,000 ints/sec, which allows low latency 2045d8eb7ad5SJesse Brandeburg * but still less than 500,000 interrupts per second, which 2046d8eb7ad5SJesse Brandeburg * reduces CPU a bit in the case of the lowest latency 2047d8eb7ad5SJesse Brandeburg * setting. The 4 here is a value in microseconds. 2048d8eb7ad5SJesse Brandeburg */ 2049d8eb7ad5SJesse Brandeburg ice_write_intrl(q_vector, 4); 2050d8eb7ad5SJesse Brandeburg } else { 2051d8eb7ad5SJesse Brandeburg ice_write_intrl(q_vector, q_vector->intrl); 2052d8eb7ad5SJesse Brandeburg } 2053d8eb7ad5SJesse Brandeburg } 2054d8eb7ad5SJesse Brandeburg 2055d8eb7ad5SJesse Brandeburg /** 205672adf242SAnirudh Venkataramanan * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW 205772adf242SAnirudh Venkataramanan * @vsi: the VSI being configured 2058047e52c0SAnirudh Venkataramanan * 2059047e52c0SAnirudh Venkataramanan * This configures MSIX mode interrupts for the PF VSI, and should not be used 2060047e52c0SAnirudh Venkataramanan * for the VF VSI. 206172adf242SAnirudh Venkataramanan */ 206272adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi) 206372adf242SAnirudh Venkataramanan { 206472adf242SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 206572adf242SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 206688865fc4SKarol Kolacinski u16 txq = 0, rxq = 0; 2067d2b464a7SBrett Creeley int i, q; 206872adf242SAnirudh Venkataramanan 20692faf63b6SMaciej Fijalkowski ice_for_each_q_vector(vsi, i) { 207072adf242SAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2071b07833a0SBrett Creeley u16 reg_idx = q_vector->reg_idx; 207272adf242SAnirudh Venkataramanan 2073b07833a0SBrett Creeley ice_cfg_itr(hw, q_vector); 20749e4ab4c2SBrett Creeley 207572adf242SAnirudh Venkataramanan /* Both Transmit Queue Interrupt Cause Control register 207672adf242SAnirudh Venkataramanan * and Receive Queue Interrupt Cause control register 207772adf242SAnirudh Venkataramanan * expects MSIX_INDX field to be the vector index 207872adf242SAnirudh Venkataramanan * within the function space and not the absolute 207972adf242SAnirudh Venkataramanan * vector index across PF or across device. 208072adf242SAnirudh Venkataramanan * For SR-IOV VF VSIs queue vector index always starts 208172adf242SAnirudh Venkataramanan * with 1 since first vector index(0) is used for OICR 208272adf242SAnirudh Venkataramanan * in VF space. Since VMDq and other PF VSIs are within 208372adf242SAnirudh Venkataramanan * the PF function space, use the vector index that is 208472adf242SAnirudh Venkataramanan * tracked for this PF. 208572adf242SAnirudh Venkataramanan */ 208672adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 2087047e52c0SAnirudh Venkataramanan ice_cfg_txq_interrupt(vsi, txq, reg_idx, 2088047e52c0SAnirudh Venkataramanan q_vector->tx.itr_idx); 208972adf242SAnirudh Venkataramanan txq++; 209072adf242SAnirudh Venkataramanan } 209172adf242SAnirudh Venkataramanan 209272adf242SAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 2093047e52c0SAnirudh Venkataramanan ice_cfg_rxq_interrupt(vsi, rxq, reg_idx, 2094047e52c0SAnirudh Venkataramanan q_vector->rx.itr_idx); 209572adf242SAnirudh Venkataramanan rxq++; 209672adf242SAnirudh Venkataramanan } 209772adf242SAnirudh Venkataramanan } 209872adf242SAnirudh Venkataramanan } 209972adf242SAnirudh Venkataramanan 210072adf242SAnirudh Venkataramanan /** 210145d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx 210245d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 210345d3d428SAnirudh Venkataramanan */ 210445d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi) 210545d3d428SAnirudh Venkataramanan { 210645d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 2107198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 21085e24d598STony Nguyen int status; 2109198a666aSBruce Allan int ret = 0; 2110198a666aSBruce Allan 21119efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 2112198a666aSBruce Allan if (!ctxt) 2113198a666aSBruce Allan return -ENOMEM; 211445d3d428SAnirudh Venkataramanan 211545d3d428SAnirudh Venkataramanan /* Here we are configuring the VSI to let the driver add VLAN tags by 211645d3d428SAnirudh Venkataramanan * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag 211745d3d428SAnirudh Venkataramanan * insertion happens in the Tx hot path, in ice_tx_map. 211845d3d428SAnirudh Venkataramanan */ 2119198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL; 212045d3d428SAnirudh Venkataramanan 2121e80e76dbSTony Nguyen /* Preserve existing VLAN strip setting */ 2122e80e76dbSTony Nguyen ctxt->info.vlan_flags |= (vsi->info.vlan_flags & 2123e80e76dbSTony Nguyen ICE_AQ_VSI_VLAN_EMOD_M); 2124e80e76dbSTony Nguyen 2125198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 212645d3d428SAnirudh Venkataramanan 2127198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 212845d3d428SAnirudh Venkataramanan if (status) { 21295f87ec48STony Nguyen dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %d aq_err %s\n", 21305f87ec48STony Nguyen status, 21310fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 2132198a666aSBruce Allan ret = -EIO; 2133198a666aSBruce Allan goto out; 213445d3d428SAnirudh Venkataramanan } 213545d3d428SAnirudh Venkataramanan 2136198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 2137198a666aSBruce Allan out: 21389efe35d0STony Nguyen kfree(ctxt); 2139198a666aSBruce Allan return ret; 214045d3d428SAnirudh Venkataramanan } 214145d3d428SAnirudh Venkataramanan 214245d3d428SAnirudh Venkataramanan /** 214345d3d428SAnirudh Venkataramanan * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx 214445d3d428SAnirudh Venkataramanan * @vsi: the VSI being changed 214545d3d428SAnirudh Venkataramanan * @ena: boolean value indicating if this is a enable or disable request 214645d3d428SAnirudh Venkataramanan */ 214745d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena) 214845d3d428SAnirudh Venkataramanan { 214945d3d428SAnirudh Venkataramanan struct ice_hw *hw = &vsi->back->hw; 2150198a666aSBruce Allan struct ice_vsi_ctx *ctxt; 21515e24d598STony Nguyen int status; 2152198a666aSBruce Allan int ret = 0; 2153198a666aSBruce Allan 215419608275SBrett Creeley /* do not allow modifying VLAN stripping when a port VLAN is configured 215519608275SBrett Creeley * on this VSI 215619608275SBrett Creeley */ 215719608275SBrett Creeley if (vsi->info.pvid) 215819608275SBrett Creeley return 0; 215919608275SBrett Creeley 21609efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 2161198a666aSBruce Allan if (!ctxt) 2162198a666aSBruce Allan return -ENOMEM; 216345d3d428SAnirudh Venkataramanan 216445d3d428SAnirudh Venkataramanan /* Here we are configuring what the VSI should do with the VLAN tag in 216545d3d428SAnirudh Venkataramanan * the Rx packet. We can either leave the tag in the packet or put it in 216645d3d428SAnirudh Venkataramanan * the Rx descriptor. 216745d3d428SAnirudh Venkataramanan */ 2168198a666aSBruce Allan if (ena) 216945d3d428SAnirudh Venkataramanan /* Strip VLAN tag from Rx packet and put it in the desc */ 2170198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH; 2171198a666aSBruce Allan else 217245d3d428SAnirudh Venkataramanan /* Disable stripping. Leave tag in packet */ 2173198a666aSBruce Allan ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING; 217445d3d428SAnirudh Venkataramanan 217545d3d428SAnirudh Venkataramanan /* Allow all packets untagged/tagged */ 2176198a666aSBruce Allan ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL; 217745d3d428SAnirudh Venkataramanan 2178198a666aSBruce Allan ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID); 217945d3d428SAnirudh Venkataramanan 2180198a666aSBruce Allan status = ice_update_vsi(hw, vsi->idx, ctxt, NULL); 218145d3d428SAnirudh Venkataramanan if (status) { 21825f87ec48STony Nguyen dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %d aq_err %s\n", 21835f87ec48STony Nguyen ena, status, 21840fee3577SLihong Yang ice_aq_str(hw->adminq.sq_last_status)); 2185198a666aSBruce Allan ret = -EIO; 2186198a666aSBruce Allan goto out; 218745d3d428SAnirudh Venkataramanan } 218845d3d428SAnirudh Venkataramanan 2189198a666aSBruce Allan vsi->info.vlan_flags = ctxt->info.vlan_flags; 2190198a666aSBruce Allan out: 21919efe35d0STony Nguyen kfree(ctxt); 2192198a666aSBruce Allan return ret; 219345d3d428SAnirudh Venkataramanan } 219472adf242SAnirudh Venkataramanan 219572adf242SAnirudh Venkataramanan /** 219613a6233bSBrett Creeley * ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings 219713a6233bSBrett Creeley * @vsi: the VSI whose rings are to be enabled 219872adf242SAnirudh Venkataramanan * 219972adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 220072adf242SAnirudh Venkataramanan */ 220113a6233bSBrett Creeley int ice_vsi_start_all_rx_rings(struct ice_vsi *vsi) 220272adf242SAnirudh Venkataramanan { 220313a6233bSBrett Creeley return ice_vsi_ctrl_all_rx_rings(vsi, true); 220472adf242SAnirudh Venkataramanan } 220572adf242SAnirudh Venkataramanan 220672adf242SAnirudh Venkataramanan /** 220713a6233bSBrett Creeley * ice_vsi_stop_all_rx_rings - stop/disable all of a VSI's Rx rings 220813a6233bSBrett Creeley * @vsi: the VSI whose rings are to be disabled 220972adf242SAnirudh Venkataramanan * 221072adf242SAnirudh Venkataramanan * Returns 0 on success and a negative value on error 221172adf242SAnirudh Venkataramanan */ 221213a6233bSBrett Creeley int ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi) 221372adf242SAnirudh Venkataramanan { 221413a6233bSBrett Creeley return ice_vsi_ctrl_all_rx_rings(vsi, false); 221572adf242SAnirudh Venkataramanan } 221672adf242SAnirudh Venkataramanan 221772adf242SAnirudh Venkataramanan /** 2218d02f734cSMaciej Fijalkowski * ice_vsi_stop_tx_rings - Disable Tx rings 2219d02f734cSMaciej Fijalkowski * @vsi: the VSI being configured 2220d02f734cSMaciej Fijalkowski * @rst_src: reset source 2221d02f734cSMaciej Fijalkowski * @rel_vmvf_num: Relative ID of VF/VM 2222d02f734cSMaciej Fijalkowski * @rings: Tx ring array to be stopped 22232e84f6b3SMaciej Fijalkowski * @count: number of Tx ring array elements 2224d02f734cSMaciej Fijalkowski */ 2225d02f734cSMaciej Fijalkowski static int 2226d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 2227e72bba21SMaciej Fijalkowski u16 rel_vmvf_num, struct ice_tx_ring **rings, u16 count) 2228d02f734cSMaciej Fijalkowski { 2229e75d1b2cSMaciej Fijalkowski u16 q_idx; 2230d02f734cSMaciej Fijalkowski 2231d02f734cSMaciej Fijalkowski if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS) 2232d02f734cSMaciej Fijalkowski return -EINVAL; 2233d02f734cSMaciej Fijalkowski 22342e84f6b3SMaciej Fijalkowski for (q_idx = 0; q_idx < count; q_idx++) { 2235d02f734cSMaciej Fijalkowski struct ice_txq_meta txq_meta = { }; 2236e75d1b2cSMaciej Fijalkowski int status; 2237d02f734cSMaciej Fijalkowski 2238d02f734cSMaciej Fijalkowski if (!rings || !rings[q_idx]) 2239d02f734cSMaciej Fijalkowski return -EINVAL; 2240d02f734cSMaciej Fijalkowski 2241d02f734cSMaciej Fijalkowski ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta); 2242e75d1b2cSMaciej Fijalkowski status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num, 2243d02f734cSMaciej Fijalkowski rings[q_idx], &txq_meta); 2244d02f734cSMaciej Fijalkowski 2245d02f734cSMaciej Fijalkowski if (status) 2246d02f734cSMaciej Fijalkowski return status; 2247bb87ee0eSAnirudh Venkataramanan } 224872adf242SAnirudh Venkataramanan 2249d02f734cSMaciej Fijalkowski return 0; 225072adf242SAnirudh Venkataramanan } 22515153a18eSAnirudh Venkataramanan 22525153a18eSAnirudh Venkataramanan /** 225303f7a986SAnirudh Venkataramanan * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings 225403f7a986SAnirudh Venkataramanan * @vsi: the VSI being configured 225503f7a986SAnirudh Venkataramanan * @rst_src: reset source 2256f9867df6SAnirudh Venkataramanan * @rel_vmvf_num: Relative ID of VF/VM 225703f7a986SAnirudh Venkataramanan */ 2258c8b7abddSBruce Allan int 2259c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, 2260c8b7abddSBruce Allan u16 rel_vmvf_num) 226103f7a986SAnirudh Venkataramanan { 22622e84f6b3SMaciej Fijalkowski return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings, vsi->num_txq); 226303f7a986SAnirudh Venkataramanan } 226403f7a986SAnirudh Venkataramanan 226503f7a986SAnirudh Venkataramanan /** 2266efc2214bSMaciej Fijalkowski * ice_vsi_stop_xdp_tx_rings - Disable XDP Tx rings 2267efc2214bSMaciej Fijalkowski * @vsi: the VSI being configured 2268efc2214bSMaciej Fijalkowski */ 2269efc2214bSMaciej Fijalkowski int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi) 2270efc2214bSMaciej Fijalkowski { 22712e84f6b3SMaciej Fijalkowski return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings, vsi->num_xdp_txq); 2272efc2214bSMaciej Fijalkowski } 2273efc2214bSMaciej Fijalkowski 2274efc2214bSMaciej Fijalkowski /** 227542f3efefSBrett Creeley * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not 227642f3efefSBrett Creeley * @vsi: VSI to check whether or not VLAN pruning is enabled. 227742f3efefSBrett Creeley * 2278345be791SBrett Creeley * returns true if Rx VLAN pruning is enabled and false otherwise. 227942f3efefSBrett Creeley */ 228042f3efefSBrett Creeley bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi) 228142f3efefSBrett Creeley { 228242f3efefSBrett Creeley if (!vsi) 228342f3efefSBrett Creeley return false; 228442f3efefSBrett Creeley 2285345be791SBrett Creeley return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA); 228642f3efefSBrett Creeley } 228742f3efefSBrett Creeley 228842f3efefSBrett Creeley /** 22895153a18eSAnirudh Venkataramanan * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI 22905153a18eSAnirudh Venkataramanan * @vsi: VSI to enable or disable VLAN pruning on 22915153a18eSAnirudh Venkataramanan * @ena: set to true to enable VLAN pruning and false to disable it 22925153a18eSAnirudh Venkataramanan * 22935153a18eSAnirudh Venkataramanan * returns 0 if VSI is updated, negative otherwise 22945153a18eSAnirudh Venkataramanan */ 229529e71f41SBrett Creeley int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena) 22965153a18eSAnirudh Venkataramanan { 22975153a18eSAnirudh Venkataramanan struct ice_vsi_ctx *ctxt; 2298819d8998SJesse Brandeburg struct ice_pf *pf; 22995153a18eSAnirudh Venkataramanan int status; 23005153a18eSAnirudh Venkataramanan 23015153a18eSAnirudh Venkataramanan if (!vsi) 23025153a18eSAnirudh Venkataramanan return -EINVAL; 23035153a18eSAnirudh Venkataramanan 230468d210a6SNick Nunley /* Don't enable VLAN pruning if the netdev is currently in promiscuous 230568d210a6SNick Nunley * mode. VLAN pruning will be enabled when the interface exits 230668d210a6SNick Nunley * promiscuous mode if any VLAN filters are active. 230768d210a6SNick Nunley */ 230868d210a6SNick Nunley if (vsi->netdev && vsi->netdev->flags & IFF_PROMISC && ena) 230968d210a6SNick Nunley return 0; 231068d210a6SNick Nunley 2311819d8998SJesse Brandeburg pf = vsi->back; 23129efe35d0STony Nguyen ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); 23135153a18eSAnirudh Venkataramanan if (!ctxt) 23145153a18eSAnirudh Venkataramanan return -ENOMEM; 23155153a18eSAnirudh Venkataramanan 23165153a18eSAnirudh Venkataramanan ctxt->info = vsi->info; 23175153a18eSAnirudh Venkataramanan 2318cd6d6b83SBrett Creeley if (ena) 23195153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 2320cd6d6b83SBrett Creeley else 23215153a18eSAnirudh Venkataramanan ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA; 23225153a18eSAnirudh Venkataramanan 232329e71f41SBrett Creeley ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID); 23245726ca0eSAnirudh Venkataramanan 2325819d8998SJesse Brandeburg status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL); 23265153a18eSAnirudh Venkataramanan if (status) { 23275f87ec48STony Nguyen netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %s\n", 23280fee3577SLihong Yang ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, 23295f87ec48STony Nguyen status, 23300fee3577SLihong Yang ice_aq_str(pf->hw.adminq.sq_last_status)); 23315153a18eSAnirudh Venkataramanan goto err_out; 23325153a18eSAnirudh Venkataramanan } 23335153a18eSAnirudh Venkataramanan 23345153a18eSAnirudh Venkataramanan vsi->info.sw_flags2 = ctxt->info.sw_flags2; 23355153a18eSAnirudh Venkataramanan 23369efe35d0STony Nguyen kfree(ctxt); 23375153a18eSAnirudh Venkataramanan return 0; 23385153a18eSAnirudh Venkataramanan 23395153a18eSAnirudh Venkataramanan err_out: 23409efe35d0STony Nguyen kfree(ctxt); 23415153a18eSAnirudh Venkataramanan return -EIO; 23425153a18eSAnirudh Venkataramanan } 23435153a18eSAnirudh Venkataramanan 23447b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi) 23457b9ffc76SAnirudh Venkataramanan { 23460754d65bSKiran Patil if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) { 23470754d65bSKiran Patil vsi->tc_cfg.ena_tc = ICE_DFLT_TRAFFIC_CLASS; 23480754d65bSKiran Patil vsi->tc_cfg.numtc = 1; 23490754d65bSKiran Patil return; 23500754d65bSKiran Patil } 23517b9ffc76SAnirudh Venkataramanan 23520754d65bSKiran Patil /* set VSI TC information based on DCB config */ 23530754d65bSKiran Patil ice_vsi_set_dcb_tc_cfg(vsi); 23547b9ffc76SAnirudh Venkataramanan } 23557b9ffc76SAnirudh Venkataramanan 23565153a18eSAnirudh Venkataramanan /** 2357b07833a0SBrett Creeley * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors 2358b07833a0SBrett Creeley * @vsi: VSI to set the q_vectors register index on 2359b07833a0SBrett Creeley */ 2360b07833a0SBrett Creeley static int 2361b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi) 2362b07833a0SBrett Creeley { 2363b07833a0SBrett Creeley u16 i; 2364b07833a0SBrett Creeley 2365b07833a0SBrett Creeley if (!vsi || !vsi->q_vectors) 2366b07833a0SBrett Creeley return -EINVAL; 2367b07833a0SBrett Creeley 2368b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 2369b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2370b07833a0SBrett Creeley 2371b07833a0SBrett Creeley if (!q_vector) { 237219cce2c6SAnirudh Venkataramanan dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n", 2373b07833a0SBrett Creeley i, vsi->vsi_num); 2374b07833a0SBrett Creeley goto clear_reg_idx; 2375b07833a0SBrett Creeley } 2376b07833a0SBrett Creeley 2377cbe66bfeSBrett Creeley if (vsi->type == ICE_VSI_VF) { 2378cbe66bfeSBrett Creeley struct ice_vf *vf = &vsi->back->vf[vsi->vf_id]; 2379cbe66bfeSBrett Creeley 2380cbe66bfeSBrett Creeley q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector); 2381cbe66bfeSBrett Creeley } else { 2382cbe66bfeSBrett Creeley q_vector->reg_idx = 2383cbe66bfeSBrett Creeley q_vector->v_idx + vsi->base_vector; 2384cbe66bfeSBrett Creeley } 2385b07833a0SBrett Creeley } 2386b07833a0SBrett Creeley 2387b07833a0SBrett Creeley return 0; 2388b07833a0SBrett Creeley 2389b07833a0SBrett Creeley clear_reg_idx: 2390b07833a0SBrett Creeley ice_for_each_q_vector(vsi, i) { 2391b07833a0SBrett Creeley struct ice_q_vector *q_vector = vsi->q_vectors[i]; 2392b07833a0SBrett Creeley 2393b07833a0SBrett Creeley if (q_vector) 2394b07833a0SBrett Creeley q_vector->reg_idx = 0; 2395b07833a0SBrett Creeley } 2396b07833a0SBrett Creeley 2397b07833a0SBrett Creeley return -EINVAL; 2398b07833a0SBrett Creeley } 2399b07833a0SBrett Creeley 2400b07833a0SBrett Creeley /** 24012e0e6228SDave Ertman * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling 24022e0e6228SDave Ertman * @vsi: the VSI being configured 24032e0e6228SDave Ertman * @tx: bool to determine Tx or Rx rule 24042e0e6228SDave Ertman * @create: bool to determine create or remove Rule 24052e0e6228SDave Ertman */ 24062e0e6228SDave Ertman void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create) 24072e0e6228SDave Ertman { 24085e24d598STony Nguyen int (*eth_fltr)(struct ice_vsi *v, u16 type, u16 flag, 24091b8f15b6SMichal Swiatkowski enum ice_sw_fwd_act_type act); 24102e0e6228SDave Ertman struct ice_pf *pf = vsi->back; 24115e24d598STony Nguyen int status; 24124015d11eSBrett Creeley struct device *dev; 24132e0e6228SDave Ertman 24144015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 24151b8f15b6SMichal Swiatkowski eth_fltr = create ? ice_fltr_add_eth : ice_fltr_remove_eth; 24162e0e6228SDave Ertman 241734295a36SDave Ertman if (tx) { 24181b8f15b6SMichal Swiatkowski status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_TX, 24191b8f15b6SMichal Swiatkowski ICE_DROP_PACKET); 242034295a36SDave Ertman } else { 242134295a36SDave Ertman if (ice_fw_supports_lldp_fltr_ctrl(&pf->hw)) { 242234295a36SDave Ertman status = ice_lldp_fltr_add_remove(&pf->hw, vsi->vsi_num, 242334295a36SDave Ertman create); 242434295a36SDave Ertman } else { 242534295a36SDave Ertman status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_RX, 242634295a36SDave Ertman ICE_FWD_TO_VSI); 242734295a36SDave Ertman } 242834295a36SDave Ertman } 24292e0e6228SDave Ertman 24302e0e6228SDave Ertman if (status) 24315f87ec48STony Nguyen dev_dbg(dev, "Fail %s %s LLDP rule on VSI %i error: %d\n", 24322e0e6228SDave Ertman create ? "adding" : "removing", tx ? "TX" : "RX", 24335f87ec48STony Nguyen vsi->vsi_num, status); 24342e0e6228SDave Ertman } 24352e0e6228SDave Ertman 2436d95276ceSAkeem G Abodunrin /** 2437b126bd6bSKiran Patil * ice_set_agg_vsi - sets up scheduler aggregator node and move VSI into it 2438b126bd6bSKiran Patil * @vsi: pointer to the VSI 2439b126bd6bSKiran Patil * 2440b126bd6bSKiran Patil * This function will allocate new scheduler aggregator now if needed and will 2441b126bd6bSKiran Patil * move specified VSI into it. 2442b126bd6bSKiran Patil */ 2443b126bd6bSKiran Patil static void ice_set_agg_vsi(struct ice_vsi *vsi) 2444b126bd6bSKiran Patil { 2445b126bd6bSKiran Patil struct device *dev = ice_pf_to_dev(vsi->back); 2446b126bd6bSKiran Patil struct ice_agg_node *agg_node_iter = NULL; 2447b126bd6bSKiran Patil u32 agg_id = ICE_INVALID_AGG_NODE_ID; 2448b126bd6bSKiran Patil struct ice_agg_node *agg_node = NULL; 2449b126bd6bSKiran Patil int node_offset, max_agg_nodes = 0; 2450b126bd6bSKiran Patil struct ice_port_info *port_info; 2451b126bd6bSKiran Patil struct ice_pf *pf = vsi->back; 2452b126bd6bSKiran Patil u32 agg_node_id_start = 0; 24535e24d598STony Nguyen int status; 2454b126bd6bSKiran Patil 2455b126bd6bSKiran Patil /* create (as needed) scheduler aggregator node and move VSI into 2456b126bd6bSKiran Patil * corresponding aggregator node 2457b126bd6bSKiran Patil * - PF aggregator node to contains VSIs of type _PF and _CTRL 2458b126bd6bSKiran Patil * - VF aggregator nodes will contain VF VSI 2459b126bd6bSKiran Patil */ 2460b126bd6bSKiran Patil port_info = pf->hw.port_info; 2461b126bd6bSKiran Patil if (!port_info) 2462b126bd6bSKiran Patil return; 2463b126bd6bSKiran Patil 2464b126bd6bSKiran Patil switch (vsi->type) { 2465b126bd6bSKiran Patil case ICE_VSI_CTRL: 24660754d65bSKiran Patil case ICE_VSI_CHNL: 2467b126bd6bSKiran Patil case ICE_VSI_LB: 2468b126bd6bSKiran Patil case ICE_VSI_PF: 2469f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 2470b126bd6bSKiran Patil max_agg_nodes = ICE_MAX_PF_AGG_NODES; 2471b126bd6bSKiran Patil agg_node_id_start = ICE_PF_AGG_NODE_ID_START; 2472b126bd6bSKiran Patil agg_node_iter = &pf->pf_agg_node[0]; 2473b126bd6bSKiran Patil break; 2474b126bd6bSKiran Patil case ICE_VSI_VF: 2475b126bd6bSKiran Patil /* user can create 'n' VFs on a given PF, but since max children 2476b126bd6bSKiran Patil * per aggregator node can be only 64. Following code handles 2477b126bd6bSKiran Patil * aggregator(s) for VF VSIs, either selects a agg_node which 2478b126bd6bSKiran Patil * was already created provided num_vsis < 64, otherwise 2479b126bd6bSKiran Patil * select next available node, which will be created 2480b126bd6bSKiran Patil */ 2481b126bd6bSKiran Patil max_agg_nodes = ICE_MAX_VF_AGG_NODES; 2482b126bd6bSKiran Patil agg_node_id_start = ICE_VF_AGG_NODE_ID_START; 2483b126bd6bSKiran Patil agg_node_iter = &pf->vf_agg_node[0]; 2484b126bd6bSKiran Patil break; 2485b126bd6bSKiran Patil default: 2486b126bd6bSKiran Patil /* other VSI type, handle later if needed */ 2487b126bd6bSKiran Patil dev_dbg(dev, "unexpected VSI type %s\n", 2488b126bd6bSKiran Patil ice_vsi_type_str(vsi->type)); 2489b126bd6bSKiran Patil return; 2490b126bd6bSKiran Patil } 2491b126bd6bSKiran Patil 2492b126bd6bSKiran Patil /* find the appropriate aggregator node */ 2493b126bd6bSKiran Patil for (node_offset = 0; node_offset < max_agg_nodes; node_offset++) { 2494b126bd6bSKiran Patil /* see if we can find space in previously created 2495b126bd6bSKiran Patil * node if num_vsis < 64, otherwise skip 2496b126bd6bSKiran Patil */ 2497b126bd6bSKiran Patil if (agg_node_iter->num_vsis && 2498b126bd6bSKiran Patil agg_node_iter->num_vsis == ICE_MAX_VSIS_IN_AGG_NODE) { 2499b126bd6bSKiran Patil agg_node_iter++; 2500b126bd6bSKiran Patil continue; 2501b126bd6bSKiran Patil } 2502b126bd6bSKiran Patil 2503b126bd6bSKiran Patil if (agg_node_iter->valid && 2504b126bd6bSKiran Patil agg_node_iter->agg_id != ICE_INVALID_AGG_NODE_ID) { 2505b126bd6bSKiran Patil agg_id = agg_node_iter->agg_id; 2506b126bd6bSKiran Patil agg_node = agg_node_iter; 2507b126bd6bSKiran Patil break; 2508b126bd6bSKiran Patil } 2509b126bd6bSKiran Patil 2510b126bd6bSKiran Patil /* find unclaimed agg_id */ 2511b126bd6bSKiran Patil if (agg_node_iter->agg_id == ICE_INVALID_AGG_NODE_ID) { 2512b126bd6bSKiran Patil agg_id = node_offset + agg_node_id_start; 2513b126bd6bSKiran Patil agg_node = agg_node_iter; 2514b126bd6bSKiran Patil break; 2515b126bd6bSKiran Patil } 2516b126bd6bSKiran Patil /* move to next agg_node */ 2517b126bd6bSKiran Patil agg_node_iter++; 2518b126bd6bSKiran Patil } 2519b126bd6bSKiran Patil 2520b126bd6bSKiran Patil if (!agg_node) 2521b126bd6bSKiran Patil return; 2522b126bd6bSKiran Patil 2523b126bd6bSKiran Patil /* if selected aggregator node was not created, create it */ 2524b126bd6bSKiran Patil if (!agg_node->valid) { 2525b126bd6bSKiran Patil status = ice_cfg_agg(port_info, agg_id, ICE_AGG_TYPE_AGG, 2526b126bd6bSKiran Patil (u8)vsi->tc_cfg.ena_tc); 2527b126bd6bSKiran Patil if (status) { 2528b126bd6bSKiran Patil dev_err(dev, "unable to create aggregator node with agg_id %u\n", 2529b126bd6bSKiran Patil agg_id); 2530b126bd6bSKiran Patil return; 2531b126bd6bSKiran Patil } 2532b126bd6bSKiran Patil /* aggregator node is created, store the neeeded info */ 2533b126bd6bSKiran Patil agg_node->valid = true; 2534b126bd6bSKiran Patil agg_node->agg_id = agg_id; 2535b126bd6bSKiran Patil } 2536b126bd6bSKiran Patil 2537b126bd6bSKiran Patil /* move VSI to corresponding aggregator node */ 2538b126bd6bSKiran Patil status = ice_move_vsi_to_agg(port_info, agg_id, vsi->idx, 2539b126bd6bSKiran Patil (u8)vsi->tc_cfg.ena_tc); 2540b126bd6bSKiran Patil if (status) { 2541b126bd6bSKiran Patil dev_err(dev, "unable to move VSI idx %u into aggregator %u node", 2542b126bd6bSKiran Patil vsi->idx, agg_id); 2543b126bd6bSKiran Patil return; 2544b126bd6bSKiran Patil } 2545b126bd6bSKiran Patil 2546b126bd6bSKiran Patil /* keep active children count for aggregator node */ 2547b126bd6bSKiran Patil agg_node->num_vsis++; 2548b126bd6bSKiran Patil 2549b126bd6bSKiran Patil /* cache the 'agg_id' in VSI, so that after reset - VSI will be moved 2550b126bd6bSKiran Patil * to aggregator node 2551b126bd6bSKiran Patil */ 2552b126bd6bSKiran Patil vsi->agg_node = agg_node; 2553b126bd6bSKiran Patil dev_dbg(dev, "successfully moved VSI idx %u tc_bitmap 0x%x) into aggregator node %d which has num_vsis %u\n", 2554b126bd6bSKiran Patil vsi->idx, vsi->tc_cfg.ena_tc, vsi->agg_node->agg_id, 2555b126bd6bSKiran Patil vsi->agg_node->num_vsis); 2556b126bd6bSKiran Patil } 2557b126bd6bSKiran Patil 2558b126bd6bSKiran Patil /** 255937bb8390SAnirudh Venkataramanan * ice_vsi_setup - Set up a VSI by a given type 256037bb8390SAnirudh Venkataramanan * @pf: board private structure 256137bb8390SAnirudh Venkataramanan * @pi: pointer to the port_info instance 25626dae8aa0SBruce Allan * @vsi_type: VSI type 2563f9867df6SAnirudh Venkataramanan * @vf_id: defines VF ID to which this VSI connects. This field is meant to be 256437bb8390SAnirudh Venkataramanan * used only for ICE_VSI_VF VSI type. For other VSI types, should 256537bb8390SAnirudh Venkataramanan * fill-in ICE_INVAL_VFID as input. 25660754d65bSKiran Patil * @ch: ptr to channel 256737bb8390SAnirudh Venkataramanan * 256837bb8390SAnirudh Venkataramanan * This allocates the sw VSI structure and its queue resources. 256937bb8390SAnirudh Venkataramanan * 257037bb8390SAnirudh Venkataramanan * Returns pointer to the successfully allocated and configured VSI sw struct on 257137bb8390SAnirudh Venkataramanan * success, NULL on failure. 257237bb8390SAnirudh Venkataramanan */ 257337bb8390SAnirudh Venkataramanan struct ice_vsi * 257437bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, 25750754d65bSKiran Patil enum ice_vsi_type vsi_type, u16 vf_id, struct ice_channel *ch) 257637bb8390SAnirudh Venkataramanan { 257737bb8390SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 25784015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 25795e24d598STony Nguyen int status; 258037bb8390SAnirudh Venkataramanan struct ice_vsi *vsi; 258137bb8390SAnirudh Venkataramanan int ret, i; 258237bb8390SAnirudh Venkataramanan 25830754d65bSKiran Patil if (vsi_type == ICE_VSI_CHNL) 25840754d65bSKiran Patil vsi = ice_vsi_alloc(pf, vsi_type, ch, ICE_INVAL_VFID); 25850754d65bSKiran Patil else if (vsi_type == ICE_VSI_VF || vsi_type == ICE_VSI_CTRL) 25860754d65bSKiran Patil vsi = ice_vsi_alloc(pf, vsi_type, NULL, vf_id); 25875743020dSAkeem G Abodunrin else 25880754d65bSKiran Patil vsi = ice_vsi_alloc(pf, vsi_type, NULL, ICE_INVAL_VFID); 25895743020dSAkeem G Abodunrin 259037bb8390SAnirudh Venkataramanan if (!vsi) { 259137bb8390SAnirudh Venkataramanan dev_err(dev, "could not allocate VSI\n"); 259237bb8390SAnirudh Venkataramanan return NULL; 259337bb8390SAnirudh Venkataramanan } 259437bb8390SAnirudh Venkataramanan 259537bb8390SAnirudh Venkataramanan vsi->port_info = pi; 259637bb8390SAnirudh Venkataramanan vsi->vsw = pf->first_sw; 2597d95276ceSAkeem G Abodunrin if (vsi->type == ICE_VSI_PF) 2598d95276ceSAkeem G Abodunrin vsi->ethtype = ETH_P_PAUSE; 2599d95276ceSAkeem G Abodunrin 2600da62c5ffSQi Zhang if (vsi->type == ICE_VSI_VF || vsi->type == ICE_VSI_CTRL) 26018ede0178SAnirudh Venkataramanan vsi->vf_id = vf_id; 260237bb8390SAnirudh Venkataramanan 2603148beb61SHenry Tieman ice_alloc_fd_res(vsi); 2604148beb61SHenry Tieman 26050754d65bSKiran Patil if (vsi_type != ICE_VSI_CHNL) { 260637bb8390SAnirudh Venkataramanan if (ice_vsi_get_qs(vsi)) { 260737bb8390SAnirudh Venkataramanan dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n", 260837bb8390SAnirudh Venkataramanan vsi->idx); 2609148beb61SHenry Tieman goto unroll_vsi_alloc; 261037bb8390SAnirudh Venkataramanan } 26110754d65bSKiran Patil } 261237bb8390SAnirudh Venkataramanan 261337bb8390SAnirudh Venkataramanan /* set RSS capabilities */ 261437bb8390SAnirudh Venkataramanan ice_vsi_set_rss_params(vsi); 261537bb8390SAnirudh Venkataramanan 2616f9867df6SAnirudh Venkataramanan /* set TC configuration */ 2617c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 2618c5a2a4a3SUsha Ketineni 261937bb8390SAnirudh Venkataramanan /* create the VSI */ 262087324e74SHenry Tieman ret = ice_vsi_init(vsi, true); 262137bb8390SAnirudh Venkataramanan if (ret) 262237bb8390SAnirudh Venkataramanan goto unroll_get_qs; 262337bb8390SAnirudh Venkataramanan 262437bb8390SAnirudh Venkataramanan switch (vsi->type) { 2625148beb61SHenry Tieman case ICE_VSI_CTRL: 2626f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 262737bb8390SAnirudh Venkataramanan case ICE_VSI_PF: 262837bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 262937bb8390SAnirudh Venkataramanan if (ret) 263037bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 263137bb8390SAnirudh Venkataramanan 263237bb8390SAnirudh Venkataramanan ret = ice_vsi_setup_vector_base(vsi); 263337bb8390SAnirudh Venkataramanan if (ret) 263437bb8390SAnirudh Venkataramanan goto unroll_alloc_q_vector; 263537bb8390SAnirudh Venkataramanan 2636b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2637b07833a0SBrett Creeley if (ret) 2638b07833a0SBrett Creeley goto unroll_vector_base; 2639b07833a0SBrett Creeley 264037bb8390SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 264137bb8390SAnirudh Venkataramanan if (ret) 264237bb8390SAnirudh Venkataramanan goto unroll_vector_base; 264337bb8390SAnirudh Venkataramanan 264442f3efefSBrett Creeley /* Always add VLAN ID 0 switch rule by default. This is needed 264542f3efefSBrett Creeley * in order to allow all untagged and 0 tagged priority traffic 264642f3efefSBrett Creeley * if Rx VLAN pruning is enabled. Also there are cases where we 264742f3efefSBrett Creeley * don't get the call to add VLAN 0 via ice_vlan_rx_add_vid() 264842f3efefSBrett Creeley * so this handles those cases (i.e. adding the PF to a bridge 264942f3efefSBrett Creeley * without the 8021q module loaded). 265042f3efefSBrett Creeley */ 26511b8f15b6SMichal Swiatkowski ret = ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI); 265242f3efefSBrett Creeley if (ret) 265342f3efefSBrett Creeley goto unroll_clear_rings; 265442f3efefSBrett Creeley 265537bb8390SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 265637bb8390SAnirudh Venkataramanan 2657148beb61SHenry Tieman /* ICE_VSI_CTRL does not need RSS so skip RSS processing */ 2658148beb61SHenry Tieman if (vsi->type != ICE_VSI_CTRL) 2659148beb61SHenry Tieman /* Do not exit if configuring RSS had an issue, at 2660148beb61SHenry Tieman * least receive traffic on first queue. Hence no 2661148beb61SHenry Tieman * need to capture return value 266237bb8390SAnirudh Venkataramanan */ 2663c90ed40cSTony Nguyen if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 266437bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_lut_key(vsi); 2665c90ed40cSTony Nguyen ice_vsi_set_rss_flow_fld(vsi); 2666c90ed40cSTony Nguyen } 266728bf2672SBrett Creeley ice_init_arfs(vsi); 266837bb8390SAnirudh Venkataramanan break; 26690754d65bSKiran Patil case ICE_VSI_CHNL: 26700754d65bSKiran Patil if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 26710754d65bSKiran Patil ice_vsi_cfg_rss_lut_key(vsi); 26720754d65bSKiran Patil ice_vsi_set_rss_flow_fld(vsi); 26730754d65bSKiran Patil } 26740754d65bSKiran Patil break; 26758ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 26768ede0178SAnirudh Venkataramanan /* VF driver will take care of creating netdev for this type and 26778ede0178SAnirudh Venkataramanan * map queues to vectors through Virtchnl, PF driver only 26788ede0178SAnirudh Venkataramanan * creates a VSI and corresponding structures for bookkeeping 26798ede0178SAnirudh Venkataramanan * purpose 26808ede0178SAnirudh Venkataramanan */ 26818ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 26828ede0178SAnirudh Venkataramanan if (ret) 26838ede0178SAnirudh Venkataramanan goto unroll_vsi_init; 26848ede0178SAnirudh Venkataramanan 26858ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 26868ede0178SAnirudh Venkataramanan if (ret) 26878ede0178SAnirudh Venkataramanan goto unroll_alloc_q_vector; 26888ede0178SAnirudh Venkataramanan 2689b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 2690b07833a0SBrett Creeley if (ret) 2691b07833a0SBrett Creeley goto unroll_vector_base; 2692b07833a0SBrett Creeley 26933a9e32bbSMd Fahad Iqbal Polash /* Do not exit if configuring RSS had an issue, at least 26943a9e32bbSMd Fahad Iqbal Polash * receive traffic on first queue. Hence no need to capture 26953a9e32bbSMd Fahad Iqbal Polash * return value 26963a9e32bbSMd Fahad Iqbal Polash */ 26971c01c8c6SMd Fahad Iqbal Polash if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 26983a9e32bbSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 26991c01c8c6SMd Fahad Iqbal Polash ice_vsi_set_vf_rss_flow_fld(vsi); 27001c01c8c6SMd Fahad Iqbal Polash } 27018ede0178SAnirudh Venkataramanan break; 27020e674aebSAnirudh Venkataramanan case ICE_VSI_LB: 27030e674aebSAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 27040e674aebSAnirudh Venkataramanan if (ret) 27050e674aebSAnirudh Venkataramanan goto unroll_vsi_init; 27060e674aebSAnirudh Venkataramanan break; 270737bb8390SAnirudh Venkataramanan default: 2708df17b7e0SAnirudh Venkataramanan /* clean up the resources and exit */ 270937bb8390SAnirudh Venkataramanan goto unroll_vsi_init; 271037bb8390SAnirudh Venkataramanan } 271137bb8390SAnirudh Venkataramanan 271237bb8390SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 27130754d65bSKiran Patil ice_for_each_traffic_class(i) { 27140754d65bSKiran Patil if (!(vsi->tc_cfg.ena_tc & BIT(i))) 27150754d65bSKiran Patil continue; 271637bb8390SAnirudh Venkataramanan 27170754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) { 27180754d65bSKiran Patil if (!vsi->alloc_txq && vsi->num_txq) 27190754d65bSKiran Patil max_txqs[i] = vsi->num_txq; 27200754d65bSKiran Patil else 27210754d65bSKiran Patil max_txqs[i] = pf->num_lan_tx; 27220754d65bSKiran Patil } else { 27230754d65bSKiran Patil max_txqs[i] = vsi->alloc_txq; 27240754d65bSKiran Patil } 27250754d65bSKiran Patil } 27260754d65bSKiran Patil 27270754d65bSKiran Patil dev_dbg(dev, "vsi->tc_cfg.ena_tc = %d\n", vsi->tc_cfg.ena_tc); 2728d31530e8SAkeem G Abodunrin status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 27294fb33f31SAnirudh Venkataramanan max_txqs); 2730d31530e8SAkeem G Abodunrin if (status) { 27315f87ec48STony Nguyen dev_err(dev, "VSI %d failed lan queue config, error %d\n", 27325f87ec48STony Nguyen vsi->vsi_num, status); 2733f6a07271SJacob Keller goto unroll_clear_rings; 273437bb8390SAnirudh Venkataramanan } 273537bb8390SAnirudh Venkataramanan 2736d95276ceSAkeem G Abodunrin /* Add switch rule to drop all Tx Flow Control Frames, of look up 2737d95276ceSAkeem G Abodunrin * type ETHERTYPE from VSIs, and restrict malicious VF from sending 2738d95276ceSAkeem G Abodunrin * out PAUSE or PFC frames. If enabled, FW can still send FC frames. 2739d95276ceSAkeem G Abodunrin * The rule is added once for PF VSI in order to create appropriate 2740d95276ceSAkeem G Abodunrin * recipe, since VSI/VSI list is ignored with drop action... 2741241c8cf0SPaul Greenwalt * Also add rules to handle LLDP Tx packets. Tx LLDP packets need to 2742241c8cf0SPaul Greenwalt * be dropped so that VFs cannot send LLDP packets to reconfig DCB 2743241c8cf0SPaul Greenwalt * settings in the HW. 2744d95276ceSAkeem G Abodunrin */ 2745241c8cf0SPaul Greenwalt if (!ice_is_safe_mode(pf)) 27462e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 27471b8f15b6SMichal Swiatkowski ice_fltr_add_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX, 27481b8f15b6SMichal Swiatkowski ICE_DROP_PACKET); 27492e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, true); 2750462acf6aSTony Nguyen } 27512e0e6228SDave Ertman 2752b126bd6bSKiran Patil if (!vsi->agg_node) 2753b126bd6bSKiran Patil ice_set_agg_vsi(vsi); 275437bb8390SAnirudh Venkataramanan return vsi; 275537bb8390SAnirudh Venkataramanan 275642f3efefSBrett Creeley unroll_clear_rings: 275742f3efefSBrett Creeley ice_vsi_clear_rings(vsi); 275837bb8390SAnirudh Venkataramanan unroll_vector_base: 2759eb0208ecSPreethi Banala /* reclaim SW interrupts back to the common pool */ 2760cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 2761eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 276237bb8390SAnirudh Venkataramanan unroll_alloc_q_vector: 276337bb8390SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 276437bb8390SAnirudh Venkataramanan unroll_vsi_init: 276537bb8390SAnirudh Venkataramanan ice_vsi_delete(vsi); 276637bb8390SAnirudh Venkataramanan unroll_get_qs: 276737bb8390SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 2768148beb61SHenry Tieman unroll_vsi_alloc: 2769df006dd4SDave Ertman if (vsi_type == ICE_VSI_VF) 2770df006dd4SDave Ertman ice_enable_lag(pf->lag); 277137bb8390SAnirudh Venkataramanan ice_vsi_clear(vsi); 277237bb8390SAnirudh Venkataramanan 277337bb8390SAnirudh Venkataramanan return NULL; 277437bb8390SAnirudh Venkataramanan } 277537bb8390SAnirudh Venkataramanan 277637bb8390SAnirudh Venkataramanan /** 27775153a18eSAnirudh Venkataramanan * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW 27785153a18eSAnirudh Venkataramanan * @vsi: the VSI being cleaned up 27795153a18eSAnirudh Venkataramanan */ 27805153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi) 27815153a18eSAnirudh Venkataramanan { 27825153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 27835153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 27845153a18eSAnirudh Venkataramanan u32 txq = 0; 27855153a18eSAnirudh Venkataramanan u32 rxq = 0; 27865153a18eSAnirudh Venkataramanan int i, q; 27875153a18eSAnirudh Venkataramanan 27882faf63b6SMaciej Fijalkowski ice_for_each_q_vector(vsi, i) { 27895153a18eSAnirudh Venkataramanan struct ice_q_vector *q_vector = vsi->q_vectors[i]; 27905153a18eSAnirudh Venkataramanan 2791b8b47723SJesse Brandeburg ice_write_intrl(q_vector, 0); 27925153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_tx; q++) { 2793b8b47723SJesse Brandeburg ice_write_itr(&q_vector->tx, 0); 27945153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0); 2795efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) { 2796efc2214bSMaciej Fijalkowski u32 xdp_txq = txq + vsi->num_xdp_txq; 2797efc2214bSMaciej Fijalkowski 2798efc2214bSMaciej Fijalkowski wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0); 2799efc2214bSMaciej Fijalkowski } 28005153a18eSAnirudh Venkataramanan txq++; 28015153a18eSAnirudh Venkataramanan } 28025153a18eSAnirudh Venkataramanan 28035153a18eSAnirudh Venkataramanan for (q = 0; q < q_vector->num_ring_rx; q++) { 2804b8b47723SJesse Brandeburg ice_write_itr(&q_vector->rx, 0); 28055153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0); 28065153a18eSAnirudh Venkataramanan rxq++; 28075153a18eSAnirudh Venkataramanan } 28085153a18eSAnirudh Venkataramanan } 28095153a18eSAnirudh Venkataramanan 28105153a18eSAnirudh Venkataramanan ice_flush(hw); 28115153a18eSAnirudh Venkataramanan } 28125153a18eSAnirudh Venkataramanan 28135153a18eSAnirudh Venkataramanan /** 28145153a18eSAnirudh Venkataramanan * ice_vsi_free_irq - Free the IRQ association with the OS 28155153a18eSAnirudh Venkataramanan * @vsi: the VSI being configured 28165153a18eSAnirudh Venkataramanan */ 28175153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi) 28185153a18eSAnirudh Venkataramanan { 28195153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 2820cbe66bfeSBrett Creeley int base = vsi->base_vector; 28215153a18eSAnirudh Venkataramanan int i; 28225153a18eSAnirudh Venkataramanan 28235153a18eSAnirudh Venkataramanan if (!vsi->q_vectors || !vsi->irqs_ready) 28245153a18eSAnirudh Venkataramanan return; 28255153a18eSAnirudh Venkataramanan 2826eb0208ecSPreethi Banala ice_vsi_release_msix(vsi); 28278ede0178SAnirudh Venkataramanan if (vsi->type == ICE_VSI_VF) 28288ede0178SAnirudh Venkataramanan return; 2829eb0208ecSPreethi Banala 28305153a18eSAnirudh Venkataramanan vsi->irqs_ready = false; 28310c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) { 28325153a18eSAnirudh Venkataramanan u16 vector = i + base; 28335153a18eSAnirudh Venkataramanan int irq_num; 28345153a18eSAnirudh Venkataramanan 28355153a18eSAnirudh Venkataramanan irq_num = pf->msix_entries[vector].vector; 28365153a18eSAnirudh Venkataramanan 28375153a18eSAnirudh Venkataramanan /* free only the irqs that were actually requested */ 28385153a18eSAnirudh Venkataramanan if (!vsi->q_vectors[i] || 28395153a18eSAnirudh Venkataramanan !(vsi->q_vectors[i]->num_ring_tx || 28405153a18eSAnirudh Venkataramanan vsi->q_vectors[i]->num_ring_rx)) 28415153a18eSAnirudh Venkataramanan continue; 28425153a18eSAnirudh Venkataramanan 28435153a18eSAnirudh Venkataramanan /* clear the affinity notifier in the IRQ descriptor */ 28445153a18eSAnirudh Venkataramanan irq_set_affinity_notifier(irq_num, NULL); 28455153a18eSAnirudh Venkataramanan 28465153a18eSAnirudh Venkataramanan /* clear the affinity_mask in the IRQ descriptor */ 28475153a18eSAnirudh Venkataramanan irq_set_affinity_hint(irq_num, NULL); 28485153a18eSAnirudh Venkataramanan synchronize_irq(irq_num); 28494015d11eSBrett Creeley devm_free_irq(ice_pf_to_dev(pf), irq_num, vsi->q_vectors[i]); 28505153a18eSAnirudh Venkataramanan } 28515153a18eSAnirudh Venkataramanan } 28525153a18eSAnirudh Venkataramanan 28535153a18eSAnirudh Venkataramanan /** 28545153a18eSAnirudh Venkataramanan * ice_vsi_free_tx_rings - Free Tx resources for VSI queues 28555153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 28565153a18eSAnirudh Venkataramanan */ 28575153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi) 28585153a18eSAnirudh Venkataramanan { 28595153a18eSAnirudh Venkataramanan int i; 28605153a18eSAnirudh Venkataramanan 28615153a18eSAnirudh Venkataramanan if (!vsi->tx_rings) 28625153a18eSAnirudh Venkataramanan return; 28635153a18eSAnirudh Venkataramanan 28645153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) 28655153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc) 28665153a18eSAnirudh Venkataramanan ice_free_tx_ring(vsi->tx_rings[i]); 28675153a18eSAnirudh Venkataramanan } 28685153a18eSAnirudh Venkataramanan 28695153a18eSAnirudh Venkataramanan /** 28705153a18eSAnirudh Venkataramanan * ice_vsi_free_rx_rings - Free Rx resources for VSI queues 28715153a18eSAnirudh Venkataramanan * @vsi: the VSI having resources freed 28725153a18eSAnirudh Venkataramanan */ 28735153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi) 28745153a18eSAnirudh Venkataramanan { 28755153a18eSAnirudh Venkataramanan int i; 28765153a18eSAnirudh Venkataramanan 28775153a18eSAnirudh Venkataramanan if (!vsi->rx_rings) 28785153a18eSAnirudh Venkataramanan return; 28795153a18eSAnirudh Venkataramanan 28805153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) 28815153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc) 28825153a18eSAnirudh Venkataramanan ice_free_rx_ring(vsi->rx_rings[i]); 28835153a18eSAnirudh Venkataramanan } 28845153a18eSAnirudh Venkataramanan 28855153a18eSAnirudh Venkataramanan /** 288607309a0eSAnirudh Venkataramanan * ice_vsi_close - Shut down a VSI 288707309a0eSAnirudh Venkataramanan * @vsi: the VSI being shut down 288807309a0eSAnirudh Venkataramanan */ 288907309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi) 289007309a0eSAnirudh Venkataramanan { 2891e97fb1aeSAnirudh Venkataramanan if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) 289207309a0eSAnirudh Venkataramanan ice_down(vsi); 289307309a0eSAnirudh Venkataramanan 289407309a0eSAnirudh Venkataramanan ice_vsi_free_irq(vsi); 289507309a0eSAnirudh Venkataramanan ice_vsi_free_tx_rings(vsi); 289607309a0eSAnirudh Venkataramanan ice_vsi_free_rx_rings(vsi); 289707309a0eSAnirudh Venkataramanan } 289807309a0eSAnirudh Venkataramanan 289907309a0eSAnirudh Venkataramanan /** 29009d614b64SAnirudh Venkataramanan * ice_ena_vsi - resume a VSI 29019d614b64SAnirudh Venkataramanan * @vsi: the VSI being resume 29029d614b64SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 29039d614b64SAnirudh Venkataramanan */ 29049d614b64SAnirudh Venkataramanan int ice_ena_vsi(struct ice_vsi *vsi, bool locked) 29059d614b64SAnirudh Venkataramanan { 29069d614b64SAnirudh Venkataramanan int err = 0; 29079d614b64SAnirudh Venkataramanan 2908e97fb1aeSAnirudh Venkataramanan if (!test_bit(ICE_VSI_NEEDS_RESTART, vsi->state)) 29099d614b64SAnirudh Venkataramanan return 0; 29109d614b64SAnirudh Venkataramanan 2911e97fb1aeSAnirudh Venkataramanan clear_bit(ICE_VSI_NEEDS_RESTART, vsi->state); 29129d614b64SAnirudh Venkataramanan 29139d614b64SAnirudh Venkataramanan if (vsi->netdev && vsi->type == ICE_VSI_PF) { 29149d614b64SAnirudh Venkataramanan if (netif_running(vsi->netdev)) { 29159d614b64SAnirudh Venkataramanan if (!locked) 29169d614b64SAnirudh Venkataramanan rtnl_lock(); 29179d614b64SAnirudh Venkataramanan 2918e95fc857SKrzysztof Goreczny err = ice_open_internal(vsi->netdev); 29199d614b64SAnirudh Venkataramanan 29209d614b64SAnirudh Venkataramanan if (!locked) 29219d614b64SAnirudh Venkataramanan rtnl_unlock(); 29229d614b64SAnirudh Venkataramanan } 2923148beb61SHenry Tieman } else if (vsi->type == ICE_VSI_CTRL) { 2924148beb61SHenry Tieman err = ice_vsi_open_ctrl(vsi); 29259d614b64SAnirudh Venkataramanan } 29269d614b64SAnirudh Venkataramanan 29279d614b64SAnirudh Venkataramanan return err; 29289d614b64SAnirudh Venkataramanan } 29299d614b64SAnirudh Venkataramanan 29309d614b64SAnirudh Venkataramanan /** 29319d614b64SAnirudh Venkataramanan * ice_dis_vsi - pause a VSI 29329d614b64SAnirudh Venkataramanan * @vsi: the VSI being paused 29339d614b64SAnirudh Venkataramanan * @locked: is the rtnl_lock already held 29349d614b64SAnirudh Venkataramanan */ 29359d614b64SAnirudh Venkataramanan void ice_dis_vsi(struct ice_vsi *vsi, bool locked) 29369d614b64SAnirudh Venkataramanan { 2937e97fb1aeSAnirudh Venkataramanan if (test_bit(ICE_VSI_DOWN, vsi->state)) 29389d614b64SAnirudh Venkataramanan return; 29399d614b64SAnirudh Venkataramanan 2940e97fb1aeSAnirudh Venkataramanan set_bit(ICE_VSI_NEEDS_RESTART, vsi->state); 29419d614b64SAnirudh Venkataramanan 29429d614b64SAnirudh Venkataramanan if (vsi->type == ICE_VSI_PF && vsi->netdev) { 29439d614b64SAnirudh Venkataramanan if (netif_running(vsi->netdev)) { 29449d614b64SAnirudh Venkataramanan if (!locked) 29459d614b64SAnirudh Venkataramanan rtnl_lock(); 29469d614b64SAnirudh Venkataramanan 2947e95fc857SKrzysztof Goreczny ice_vsi_close(vsi); 29489d614b64SAnirudh Venkataramanan 29499d614b64SAnirudh Venkataramanan if (!locked) 29509d614b64SAnirudh Venkataramanan rtnl_unlock(); 29519d614b64SAnirudh Venkataramanan } else { 29529d614b64SAnirudh Venkataramanan ice_vsi_close(vsi); 29539d614b64SAnirudh Venkataramanan } 2954f66756e0SGrzegorz Nitka } else if (vsi->type == ICE_VSI_CTRL || 2955f66756e0SGrzegorz Nitka vsi->type == ICE_VSI_SWITCHDEV_CTRL) { 2956148beb61SHenry Tieman ice_vsi_close(vsi); 29579d614b64SAnirudh Venkataramanan } 29589d614b64SAnirudh Venkataramanan } 29599d614b64SAnirudh Venkataramanan 29609d614b64SAnirudh Venkataramanan /** 29615153a18eSAnirudh Venkataramanan * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI 29625153a18eSAnirudh Venkataramanan * @vsi: the VSI being un-configured 29635153a18eSAnirudh Venkataramanan */ 29645153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi) 29655153a18eSAnirudh Venkataramanan { 2966cbe66bfeSBrett Creeley int base = vsi->base_vector; 29675153a18eSAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 29685153a18eSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 29695153a18eSAnirudh Venkataramanan u32 val; 29705153a18eSAnirudh Venkataramanan int i; 29715153a18eSAnirudh Venkataramanan 29725153a18eSAnirudh Venkataramanan /* disable interrupt causation from each queue */ 29735153a18eSAnirudh Venkataramanan if (vsi->tx_rings) { 29745153a18eSAnirudh Venkataramanan ice_for_each_txq(vsi, i) { 29755153a18eSAnirudh Venkataramanan if (vsi->tx_rings[i]) { 29765153a18eSAnirudh Venkataramanan u16 reg; 29775153a18eSAnirudh Venkataramanan 29785153a18eSAnirudh Venkataramanan reg = vsi->tx_rings[i]->reg_idx; 29795153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_TQCTL(reg)); 29805153a18eSAnirudh Venkataramanan val &= ~QINT_TQCTL_CAUSE_ENA_M; 29815153a18eSAnirudh Venkataramanan wr32(hw, QINT_TQCTL(reg), val); 29825153a18eSAnirudh Venkataramanan } 29835153a18eSAnirudh Venkataramanan } 29845153a18eSAnirudh Venkataramanan } 29855153a18eSAnirudh Venkataramanan 29865153a18eSAnirudh Venkataramanan if (vsi->rx_rings) { 29875153a18eSAnirudh Venkataramanan ice_for_each_rxq(vsi, i) { 29885153a18eSAnirudh Venkataramanan if (vsi->rx_rings[i]) { 29895153a18eSAnirudh Venkataramanan u16 reg; 29905153a18eSAnirudh Venkataramanan 29915153a18eSAnirudh Venkataramanan reg = vsi->rx_rings[i]->reg_idx; 29925153a18eSAnirudh Venkataramanan val = rd32(hw, QINT_RQCTL(reg)); 29935153a18eSAnirudh Venkataramanan val &= ~QINT_RQCTL_CAUSE_ENA_M; 29945153a18eSAnirudh Venkataramanan wr32(hw, QINT_RQCTL(reg), val); 29955153a18eSAnirudh Venkataramanan } 29965153a18eSAnirudh Venkataramanan } 29975153a18eSAnirudh Venkataramanan } 29985153a18eSAnirudh Venkataramanan 29995153a18eSAnirudh Venkataramanan /* disable each interrupt */ 3000462acf6aSTony Nguyen ice_for_each_q_vector(vsi, i) { 3001462acf6aSTony Nguyen if (!vsi->q_vectors[i]) 3002462acf6aSTony Nguyen continue; 3003b07833a0SBrett Creeley wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); 3004462acf6aSTony Nguyen } 30055153a18eSAnirudh Venkataramanan 30065153a18eSAnirudh Venkataramanan ice_flush(hw); 3007b07833a0SBrett Creeley 3008da4a9e73SBrett Creeley /* don't call synchronize_irq() for VF's from the host */ 3009da4a9e73SBrett Creeley if (vsi->type == ICE_VSI_VF) 3010da4a9e73SBrett Creeley return; 3011da4a9e73SBrett Creeley 30120c2561c8SBrett Creeley ice_for_each_q_vector(vsi, i) 30135153a18eSAnirudh Venkataramanan synchronize_irq(pf->msix_entries[i + base].vector); 30145153a18eSAnirudh Venkataramanan } 30155153a18eSAnirudh Venkataramanan 30165153a18eSAnirudh Venkataramanan /** 3017561f4379STony Nguyen * ice_napi_del - Remove NAPI handler for the VSI 3018561f4379STony Nguyen * @vsi: VSI for which NAPI handler is to be removed 3019561f4379STony Nguyen */ 3020561f4379STony Nguyen void ice_napi_del(struct ice_vsi *vsi) 3021561f4379STony Nguyen { 3022561f4379STony Nguyen int v_idx; 3023561f4379STony Nguyen 3024561f4379STony Nguyen if (!vsi->netdev) 3025561f4379STony Nguyen return; 3026561f4379STony Nguyen 3027561f4379STony Nguyen ice_for_each_q_vector(vsi, v_idx) 3028561f4379STony Nguyen netif_napi_del(&vsi->q_vectors[v_idx]->napi); 3029561f4379STony Nguyen } 3030561f4379STony Nguyen 3031561f4379STony Nguyen /** 3032df0f8479SAnirudh Venkataramanan * ice_vsi_release - Delete a VSI and free its resources 3033df0f8479SAnirudh Venkataramanan * @vsi: the VSI being removed 3034df0f8479SAnirudh Venkataramanan * 3035df0f8479SAnirudh Venkataramanan * Returns 0 on success or < 0 on error 3036df0f8479SAnirudh Venkataramanan */ 3037df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi) 3038df0f8479SAnirudh Venkataramanan { 3039*d54699e2STony Nguyen int err; 3040df0f8479SAnirudh Venkataramanan struct ice_pf *pf; 3041df0f8479SAnirudh Venkataramanan 3042df0f8479SAnirudh Venkataramanan if (!vsi->back) 3043df0f8479SAnirudh Venkataramanan return -ENODEV; 3044df0f8479SAnirudh Venkataramanan pf = vsi->back; 3045b751930cSBrett Creeley 3046aa6ccf3fSBrett Creeley /* do not unregister while driver is in the reset recovery pending 3047aa6ccf3fSBrett Creeley * state. Since reset/rebuild happens through PF service task workqueue, 3048aa6ccf3fSBrett Creeley * it's not a good idea to unregister netdev that is associated to the 3049aa6ccf3fSBrett Creeley * PF that is running the work queue items currently. This is done to 3050aa6ccf3fSBrett Creeley * avoid check_flush_dependency() warning on this wq 3051df0f8479SAnirudh Venkataramanan */ 3052a476d72aSAnirudh Venkataramanan if (vsi->netdev && !ice_is_reset_in_progress(pf->state) && 3053a476d72aSAnirudh Venkataramanan (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state))) { 3054df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 3055a476d72aSAnirudh Venkataramanan clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state); 305648d40025SJacob Keller } 3057df0f8479SAnirudh Venkataramanan 30582ae0aa47SWojciech Drewek if (vsi->type == ICE_VSI_PF) 30592ae0aa47SWojciech Drewek ice_devlink_destroy_pf_port(pf); 3060a476d72aSAnirudh Venkataramanan 3061df0f8479SAnirudh Venkataramanan if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 3062df0f8479SAnirudh Venkataramanan ice_rss_clean(vsi); 3063df0f8479SAnirudh Venkataramanan 3064df0f8479SAnirudh Venkataramanan /* Disable VSI and free resources */ 30650e674aebSAnirudh Venkataramanan if (vsi->type != ICE_VSI_LB) 3066df0f8479SAnirudh Venkataramanan ice_vsi_dis_irq(vsi); 3067df0f8479SAnirudh Venkataramanan ice_vsi_close(vsi); 3068df0f8479SAnirudh Venkataramanan 3069cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 3070cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 3071cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 3072cbe66bfeSBrett Creeley * cleared in the same manner. 3073cbe66bfeSBrett Creeley */ 3074da62c5ffSQi Zhang if (vsi->type == ICE_VSI_CTRL && vsi->vf_id != ICE_INVAL_VFID) { 3075da62c5ffSQi Zhang int i; 3076da62c5ffSQi Zhang 3077da62c5ffSQi Zhang ice_for_each_vf(pf, i) { 3078b6b0501dSPaul M Stillwell Jr struct ice_vf *vf = &pf->vf[i]; 3079b6b0501dSPaul M Stillwell Jr 3080da62c5ffSQi Zhang if (i != vsi->vf_id && vf->ctrl_vsi_idx != ICE_NO_VSI) 3081da62c5ffSQi Zhang break; 3082da62c5ffSQi Zhang } 3083da62c5ffSQi Zhang if (i == pf->num_alloc_vfs) { 3084da62c5ffSQi Zhang /* No other VFs left that have control VSI, reclaim SW 3085da62c5ffSQi Zhang * interrupts back to the common pool 3086da62c5ffSQi Zhang */ 3087da62c5ffSQi Zhang ice_free_res(pf->irq_tracker, vsi->base_vector, 3088da62c5ffSQi Zhang ICE_RES_VF_CTRL_VEC_ID); 3089da62c5ffSQi Zhang pf->num_avail_sw_msix += vsi->num_q_vectors; 3090da62c5ffSQi Zhang } 3091da62c5ffSQi Zhang } else if (vsi->type != ICE_VSI_VF) { 30928ede0178SAnirudh Venkataramanan /* reclaim SW interrupts back to the common pool */ 3093cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 3094eb0208ecSPreethi Banala pf->num_avail_sw_msix += vsi->num_q_vectors; 30958ede0178SAnirudh Venkataramanan } 3096df0f8479SAnirudh Venkataramanan 3097462acf6aSTony Nguyen if (!ice_is_safe_mode(pf)) { 30982e0e6228SDave Ertman if (vsi->type == ICE_VSI_PF) { 30991b8f15b6SMichal Swiatkowski ice_fltr_remove_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX, 31001b8f15b6SMichal Swiatkowski ICE_DROP_PACKET); 31012e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, true, false); 31022e0e6228SDave Ertman /* The Rx rule will only exist to remove if the LLDP FW 31032e0e6228SDave Ertman * engine is currently stopped 31042e0e6228SDave Ertman */ 310584a118abSDave Ertman if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags)) 31062e0e6228SDave Ertman ice_cfg_sw_lldp(vsi, false, false); 31072e0e6228SDave Ertman } 3108462acf6aSTony Nguyen } 3109d95276ceSAkeem G Abodunrin 31101b8f15b6SMichal Swiatkowski ice_fltr_remove_all(vsi); 311110e03a22SAnirudh Venkataramanan ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 3112ff7e9321SBrett Creeley err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx); 3113ff7e9321SBrett Creeley if (err) 3114ff7e9321SBrett Creeley dev_err(ice_pf_to_dev(vsi->back), "Failed to remove RDMA scheduler config for VSI %u, err %d\n", 3115ff7e9321SBrett Creeley vsi->vsi_num, err); 3116df0f8479SAnirudh Venkataramanan ice_vsi_delete(vsi); 3117df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 3118aa6ccf3fSBrett Creeley 3119a476d72aSAnirudh Venkataramanan if (vsi->netdev) { 3120a476d72aSAnirudh Venkataramanan if (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state)) { 3121a476d72aSAnirudh Venkataramanan unregister_netdev(vsi->netdev); 3122a476d72aSAnirudh Venkataramanan clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state); 3123a476d72aSAnirudh Venkataramanan } 3124a476d72aSAnirudh Venkataramanan if (test_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state)) { 3125aa6ccf3fSBrett Creeley free_netdev(vsi->netdev); 3126aa6ccf3fSBrett Creeley vsi->netdev = NULL; 3127a476d72aSAnirudh Venkataramanan clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state); 3128a476d72aSAnirudh Venkataramanan } 3129aa6ccf3fSBrett Creeley } 3130aa6ccf3fSBrett Creeley 3131b126bd6bSKiran Patil if (vsi->type == ICE_VSI_VF && 3132b126bd6bSKiran Patil vsi->agg_node && vsi->agg_node->valid) 3133b126bd6bSKiran Patil vsi->agg_node->num_vsis--; 3134df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 3135df0f8479SAnirudh Venkataramanan 3136df0f8479SAnirudh Venkataramanan ice_vsi_put_qs(vsi); 3137df0f8479SAnirudh Venkataramanan 3138df0f8479SAnirudh Venkataramanan /* retain SW VSI data structure since it is needed to unregister and 3139df0f8479SAnirudh Venkataramanan * free VSI netdev when PF is not in reset recovery pending state,\ 3140df0f8479SAnirudh Venkataramanan * for ex: during rmmod. 3141df0f8479SAnirudh Venkataramanan */ 31425df7e45dSDave Ertman if (!ice_is_reset_in_progress(pf->state)) 3143df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 3144df0f8479SAnirudh Venkataramanan 3145df0f8479SAnirudh Venkataramanan return 0; 3146df0f8479SAnirudh Venkataramanan } 3147df0f8479SAnirudh Venkataramanan 3148df0f8479SAnirudh Venkataramanan /** 314961dc79ceSMichal Swiatkowski * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors 315061dc79ceSMichal Swiatkowski * @vsi: VSI connected with q_vectors 315161dc79ceSMichal Swiatkowski * @coalesce: array of struct with stored coalesce 315261dc79ceSMichal Swiatkowski * 315361dc79ceSMichal Swiatkowski * Returns array size. 315461dc79ceSMichal Swiatkowski */ 315561dc79ceSMichal Swiatkowski static int 315661dc79ceSMichal Swiatkowski ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi, 315761dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce) 315861dc79ceSMichal Swiatkowski { 315961dc79ceSMichal Swiatkowski int i; 316061dc79ceSMichal Swiatkowski 316161dc79ceSMichal Swiatkowski ice_for_each_q_vector(vsi, i) { 316261dc79ceSMichal Swiatkowski struct ice_q_vector *q_vector = vsi->q_vectors[i]; 316361dc79ceSMichal Swiatkowski 316461dc79ceSMichal Swiatkowski coalesce[i].itr_tx = q_vector->tx.itr_setting; 316561dc79ceSMichal Swiatkowski coalesce[i].itr_rx = q_vector->rx.itr_setting; 316661dc79ceSMichal Swiatkowski coalesce[i].intrl = q_vector->intrl; 31672ec56385SPaul M Stillwell Jr 31682ec56385SPaul M Stillwell Jr if (i < vsi->num_txq) 31692ec56385SPaul M Stillwell Jr coalesce[i].tx_valid = true; 31702ec56385SPaul M Stillwell Jr if (i < vsi->num_rxq) 31712ec56385SPaul M Stillwell Jr coalesce[i].rx_valid = true; 317261dc79ceSMichal Swiatkowski } 317361dc79ceSMichal Swiatkowski 317461dc79ceSMichal Swiatkowski return vsi->num_q_vectors; 317561dc79ceSMichal Swiatkowski } 317661dc79ceSMichal Swiatkowski 317761dc79ceSMichal Swiatkowski /** 317861dc79ceSMichal Swiatkowski * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays 317961dc79ceSMichal Swiatkowski * @vsi: VSI connected with q_vectors 318061dc79ceSMichal Swiatkowski * @coalesce: pointer to array of struct with stored coalesce 318161dc79ceSMichal Swiatkowski * @size: size of coalesce array 318261dc79ceSMichal Swiatkowski * 318361dc79ceSMichal Swiatkowski * Before this function, ice_vsi_rebuild_get_coalesce should be called to save 318461dc79ceSMichal Swiatkowski * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce 318561dc79ceSMichal Swiatkowski * to default value. 318661dc79ceSMichal Swiatkowski */ 318761dc79ceSMichal Swiatkowski static void 318861dc79ceSMichal Swiatkowski ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi, 318961dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce, int size) 319061dc79ceSMichal Swiatkowski { 3191b8b47723SJesse Brandeburg struct ice_ring_container *rc; 319261dc79ceSMichal Swiatkowski int i; 319361dc79ceSMichal Swiatkowski 319461dc79ceSMichal Swiatkowski if ((size && !coalesce) || !vsi) 319561dc79ceSMichal Swiatkowski return; 319661dc79ceSMichal Swiatkowski 31972ec56385SPaul M Stillwell Jr /* There are a couple of cases that have to be handled here: 31982ec56385SPaul M Stillwell Jr * 1. The case where the number of queue vectors stays the same, but 31992ec56385SPaul M Stillwell Jr * the number of Tx or Rx rings changes (the first for loop) 32002ec56385SPaul M Stillwell Jr * 2. The case where the number of queue vectors increased (the 32012ec56385SPaul M Stillwell Jr * second for loop) 3202a039f6fcSBrett Creeley */ 32032ec56385SPaul M Stillwell Jr for (i = 0; i < size && i < vsi->num_q_vectors; i++) { 32042ec56385SPaul M Stillwell Jr /* There are 2 cases to handle here and they are the same for 32052ec56385SPaul M Stillwell Jr * both Tx and Rx: 32062ec56385SPaul M Stillwell Jr * if the entry was valid previously (coalesce[i].[tr]x_valid 32072ec56385SPaul M Stillwell Jr * and the loop variable is less than the number of rings 32082ec56385SPaul M Stillwell Jr * allocated, then write the previous values 32092ec56385SPaul M Stillwell Jr * 32102ec56385SPaul M Stillwell Jr * if the entry was not valid previously, but the number of 32112ec56385SPaul M Stillwell Jr * rings is less than are allocated (this means the number of 32122ec56385SPaul M Stillwell Jr * rings increased from previously), then write out the 32132ec56385SPaul M Stillwell Jr * values in the first element 3214b8b47723SJesse Brandeburg * 3215b8b47723SJesse Brandeburg * Also, always write the ITR, even if in ITR_IS_DYNAMIC 3216b8b47723SJesse Brandeburg * as there is no harm because the dynamic algorithm 3217b8b47723SJesse Brandeburg * will just overwrite. 32182ec56385SPaul M Stillwell Jr */ 3219b8b47723SJesse Brandeburg if (i < vsi->alloc_rxq && coalesce[i].rx_valid) { 3220b8b47723SJesse Brandeburg rc = &vsi->q_vectors[i]->rx; 3221b8b47723SJesse Brandeburg rc->itr_setting = coalesce[i].itr_rx; 3222b8b47723SJesse Brandeburg ice_write_itr(rc, rc->itr_setting); 3223b8b47723SJesse Brandeburg } else if (i < vsi->alloc_rxq) { 3224b8b47723SJesse Brandeburg rc = &vsi->q_vectors[i]->rx; 3225b8b47723SJesse Brandeburg rc->itr_setting = coalesce[0].itr_rx; 3226b8b47723SJesse Brandeburg ice_write_itr(rc, rc->itr_setting); 3227b8b47723SJesse Brandeburg } 32282ec56385SPaul M Stillwell Jr 3229b8b47723SJesse Brandeburg if (i < vsi->alloc_txq && coalesce[i].tx_valid) { 3230b8b47723SJesse Brandeburg rc = &vsi->q_vectors[i]->tx; 3231b8b47723SJesse Brandeburg rc->itr_setting = coalesce[i].itr_tx; 3232b8b47723SJesse Brandeburg ice_write_itr(rc, rc->itr_setting); 3233b8b47723SJesse Brandeburg } else if (i < vsi->alloc_txq) { 3234b8b47723SJesse Brandeburg rc = &vsi->q_vectors[i]->tx; 3235b8b47723SJesse Brandeburg rc->itr_setting = coalesce[0].itr_tx; 3236b8b47723SJesse Brandeburg ice_write_itr(rc, rc->itr_setting); 3237b8b47723SJesse Brandeburg } 32382ec56385SPaul M Stillwell Jr 3239b8b47723SJesse Brandeburg vsi->q_vectors[i]->intrl = coalesce[i].intrl; 3240d16a4f45SJesse Brandeburg ice_set_q_vector_intrl(vsi->q_vectors[i]); 32412ec56385SPaul M Stillwell Jr } 32422ec56385SPaul M Stillwell Jr 32432ec56385SPaul M Stillwell Jr /* the number of queue vectors increased so write whatever is in 32442ec56385SPaul M Stillwell Jr * the first element 32452ec56385SPaul M Stillwell Jr */ 32462ec56385SPaul M Stillwell Jr for (; i < vsi->num_q_vectors; i++) { 3247b8b47723SJesse Brandeburg /* transmit */ 3248b8b47723SJesse Brandeburg rc = &vsi->q_vectors[i]->tx; 3249b8b47723SJesse Brandeburg rc->itr_setting = coalesce[0].itr_tx; 3250b8b47723SJesse Brandeburg ice_write_itr(rc, rc->itr_setting); 3251b8b47723SJesse Brandeburg 3252b8b47723SJesse Brandeburg /* receive */ 3253b8b47723SJesse Brandeburg rc = &vsi->q_vectors[i]->rx; 3254b8b47723SJesse Brandeburg rc->itr_setting = coalesce[0].itr_rx; 3255b8b47723SJesse Brandeburg ice_write_itr(rc, rc->itr_setting); 3256b8b47723SJesse Brandeburg 3257b8b47723SJesse Brandeburg vsi->q_vectors[i]->intrl = coalesce[0].intrl; 3258d16a4f45SJesse Brandeburg ice_set_q_vector_intrl(vsi->q_vectors[i]); 32592ec56385SPaul M Stillwell Jr } 326061dc79ceSMichal Swiatkowski } 326161dc79ceSMichal Swiatkowski 326261dc79ceSMichal Swiatkowski /** 3263df0f8479SAnirudh Venkataramanan * ice_vsi_rebuild - Rebuild VSI after reset 3264df0f8479SAnirudh Venkataramanan * @vsi: VSI to be rebuild 326587324e74SHenry Tieman * @init_vsi: is this an initialization or a reconfigure of the VSI 3266df0f8479SAnirudh Venkataramanan * 3267df0f8479SAnirudh Venkataramanan * Returns 0 on success and negative value on failure 3268df0f8479SAnirudh Venkataramanan */ 326987324e74SHenry Tieman int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi) 3270df0f8479SAnirudh Venkataramanan { 3271df0f8479SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 327261dc79ceSMichal Swiatkowski struct ice_coalesce_stored *coalesce; 327361dc79ceSMichal Swiatkowski int prev_num_q_vectors = 0; 32747eeac889SAkeem G Abodunrin struct ice_vf *vf = NULL; 327558623c52SJesse Brandeburg enum ice_vsi_type vtype; 32765e24d598STony Nguyen int status; 3277c5a2a4a3SUsha Ketineni struct ice_pf *pf; 3278df0f8479SAnirudh Venkataramanan int ret, i; 3279df0f8479SAnirudh Venkataramanan 3280df0f8479SAnirudh Venkataramanan if (!vsi) 3281df0f8479SAnirudh Venkataramanan return -EINVAL; 3282df0f8479SAnirudh Venkataramanan 3283c5a2a4a3SUsha Ketineni pf = vsi->back; 328458623c52SJesse Brandeburg vtype = vsi->type; 328558623c52SJesse Brandeburg if (vtype == ICE_VSI_VF) 32867eeac889SAkeem G Abodunrin vf = &pf->vf[vsi->vf_id]; 32877eeac889SAkeem G Abodunrin 328861dc79ceSMichal Swiatkowski coalesce = kcalloc(vsi->num_q_vectors, 328961dc79ceSMichal Swiatkowski sizeof(struct ice_coalesce_stored), GFP_KERNEL); 32902ec56385SPaul M Stillwell Jr if (!coalesce) 32912ec56385SPaul M Stillwell Jr return -ENOMEM; 32922ec56385SPaul M Stillwell Jr 32932ec56385SPaul M Stillwell Jr prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce); 32942ec56385SPaul M Stillwell Jr 329547e3e53cSHenry Tieman ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx); 3296ff7e9321SBrett Creeley ret = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx); 3297ff7e9321SBrett Creeley if (ret) 3298ff7e9321SBrett Creeley dev_err(ice_pf_to_dev(vsi->back), "Failed to remove RDMA scheduler config for VSI %u, err %d\n", 3299ff7e9321SBrett Creeley vsi->vsi_num, ret); 3300df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 33017eeac889SAkeem G Abodunrin 3302cbe66bfeSBrett Creeley /* SR-IOV determines needed MSIX resources all at once instead of per 3303cbe66bfeSBrett Creeley * VSI since when VFs are spawned we know how many VFs there are and how 3304cbe66bfeSBrett Creeley * many interrupts each VF needs. SR-IOV MSIX resources are also 3305cbe66bfeSBrett Creeley * cleared in the same manner. 3306cbe66bfeSBrett Creeley */ 330758623c52SJesse Brandeburg if (vtype != ICE_VSI_VF) { 33087eeac889SAkeem G Abodunrin /* reclaim SW interrupts back to the common pool */ 3309cbe66bfeSBrett Creeley ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx); 33107eeac889SAkeem G Abodunrin pf->num_avail_sw_msix += vsi->num_q_vectors; 3311cbe66bfeSBrett Creeley vsi->base_vector = 0; 33127eeac889SAkeem G Abodunrin } 33137eeac889SAkeem G Abodunrin 3314efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) 3315efc2214bSMaciej Fijalkowski /* return value check can be skipped here, it always returns 3316efc2214bSMaciej Fijalkowski * 0 if reset is in progress 3317efc2214bSMaciej Fijalkowski */ 3318efc2214bSMaciej Fijalkowski ice_destroy_xdp_rings(vsi); 331978b5713aSAnirudh Venkataramanan ice_vsi_put_qs(vsi); 3320df0f8479SAnirudh Venkataramanan ice_vsi_clear_rings(vsi); 3321a85a3847SBrett Creeley ice_vsi_free_arrays(vsi); 332258623c52SJesse Brandeburg if (vtype == ICE_VSI_VF) 33235743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, vf->vf_id); 33245743020dSAkeem G Abodunrin else 33255743020dSAkeem G Abodunrin ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID); 332678b5713aSAnirudh Venkataramanan 332778b5713aSAnirudh Venkataramanan ret = ice_vsi_alloc_arrays(vsi); 332878b5713aSAnirudh Venkataramanan if (ret < 0) 332978b5713aSAnirudh Venkataramanan goto err_vsi; 333078b5713aSAnirudh Venkataramanan 333178b5713aSAnirudh Venkataramanan ice_vsi_get_qs(vsi); 333283af0039SHenry Tieman 333383af0039SHenry Tieman ice_alloc_fd_res(vsi); 3334c5a2a4a3SUsha Ketineni ice_vsi_set_tc_cfg(vsi); 3335df0f8479SAnirudh Venkataramanan 3336df0f8479SAnirudh Venkataramanan /* Initialize VSI struct elements and create VSI in FW */ 333787324e74SHenry Tieman ret = ice_vsi_init(vsi, init_vsi); 3338df0f8479SAnirudh Venkataramanan if (ret < 0) 3339df0f8479SAnirudh Venkataramanan goto err_vsi; 3340df0f8479SAnirudh Venkataramanan 334158623c52SJesse Brandeburg switch (vtype) { 334283af0039SHenry Tieman case ICE_VSI_CTRL: 3343f66756e0SGrzegorz Nitka case ICE_VSI_SWITCHDEV_CTRL: 3344df0f8479SAnirudh Venkataramanan case ICE_VSI_PF: 3345df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 3346df0f8479SAnirudh Venkataramanan if (ret) 3347df0f8479SAnirudh Venkataramanan goto err_rings; 3348df0f8479SAnirudh Venkataramanan 334917bc6d07STony Nguyen ret = ice_vsi_setup_vector_base(vsi); 335017bc6d07STony Nguyen if (ret) 335117bc6d07STony Nguyen goto err_vectors; 335217bc6d07STony Nguyen 3353b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 3354b07833a0SBrett Creeley if (ret) 3355b07833a0SBrett Creeley goto err_vectors; 3356b07833a0SBrett Creeley 3357df0f8479SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 3358df0f8479SAnirudh Venkataramanan if (ret) 3359df0f8479SAnirudh Venkataramanan goto err_vectors; 3360df0f8479SAnirudh Venkataramanan 3361df0f8479SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(vsi); 3362efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) { 336322bf877eSMaciej Fijalkowski ret = ice_vsi_determine_xdp_res(vsi); 336422bf877eSMaciej Fijalkowski if (ret) 336522bf877eSMaciej Fijalkowski goto err_vectors; 3366efc2214bSMaciej Fijalkowski ret = ice_prepare_xdp_rings(vsi, vsi->xdp_prog); 3367efc2214bSMaciej Fijalkowski if (ret) 3368efc2214bSMaciej Fijalkowski goto err_vectors; 3369efc2214bSMaciej Fijalkowski } 337083af0039SHenry Tieman /* ICE_VSI_CTRL does not need RSS so skip RSS processing */ 337158623c52SJesse Brandeburg if (vtype != ICE_VSI_CTRL) 337283af0039SHenry Tieman /* Do not exit if configuring RSS had an issue, at 337383af0039SHenry Tieman * least receive traffic on first queue. Hence no 337483af0039SHenry Tieman * need to capture return value 337527a98affSMd Fahad Iqbal Polash */ 3376819d8998SJesse Brandeburg if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) 337727a98affSMd Fahad Iqbal Polash ice_vsi_cfg_rss_lut_key(vsi); 3378df0f8479SAnirudh Venkataramanan break; 33798ede0178SAnirudh Venkataramanan case ICE_VSI_VF: 33808ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_q_vectors(vsi); 33818ede0178SAnirudh Venkataramanan if (ret) 33828ede0178SAnirudh Venkataramanan goto err_rings; 33838ede0178SAnirudh Venkataramanan 3384b07833a0SBrett Creeley ret = ice_vsi_set_q_vectors_reg_idx(vsi); 3385b07833a0SBrett Creeley if (ret) 3386b07833a0SBrett Creeley goto err_vectors; 3387b07833a0SBrett Creeley 33888ede0178SAnirudh Venkataramanan ret = ice_vsi_alloc_rings(vsi); 33898ede0178SAnirudh Venkataramanan if (ret) 33908ede0178SAnirudh Venkataramanan goto err_vectors; 33918ede0178SAnirudh Venkataramanan 33928ede0178SAnirudh Venkataramanan break; 33930754d65bSKiran Patil case ICE_VSI_CHNL: 33940754d65bSKiran Patil if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) { 33950754d65bSKiran Patil ice_vsi_cfg_rss_lut_key(vsi); 33960754d65bSKiran Patil ice_vsi_set_rss_flow_fld(vsi); 33970754d65bSKiran Patil } 33980754d65bSKiran Patil break; 3399df0f8479SAnirudh Venkataramanan default: 3400df0f8479SAnirudh Venkataramanan break; 3401df0f8479SAnirudh Venkataramanan } 3402df0f8479SAnirudh Venkataramanan 3403df0f8479SAnirudh Venkataramanan /* configure VSI nodes based on number of queues and TC's */ 3404efc2214bSMaciej Fijalkowski for (i = 0; i < vsi->tc_cfg.numtc; i++) { 34050754d65bSKiran Patil /* configure VSI nodes based on number of queues and TC's. 34060754d65bSKiran Patil * ADQ creates VSIs for each TC/Channel but doesn't 34070754d65bSKiran Patil * allocate queues instead it reconfigures the PF queues 34080754d65bSKiran Patil * as per the TC command. So max_txqs should point to the 34090754d65bSKiran Patil * PF Tx queues. 34100754d65bSKiran Patil */ 34110754d65bSKiran Patil if (vtype == ICE_VSI_CHNL) 34120754d65bSKiran Patil max_txqs[i] = pf->num_lan_tx; 34130754d65bSKiran Patil else 3414d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 3415df0f8479SAnirudh Venkataramanan 3416efc2214bSMaciej Fijalkowski if (ice_is_xdp_ena_vsi(vsi)) 3417efc2214bSMaciej Fijalkowski max_txqs[i] += vsi->num_xdp_txq; 3418efc2214bSMaciej Fijalkowski } 3419efc2214bSMaciej Fijalkowski 34200754d65bSKiran Patil if (test_bit(ICE_FLAG_TC_MQPRIO, pf->flags)) 34210754d65bSKiran Patil /* If MQPRIO is set, means channel code path, hence for main 34220754d65bSKiran Patil * VSI's, use TC as 1 34230754d65bSKiran Patil */ 34240754d65bSKiran Patil status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, 1, max_txqs); 34250754d65bSKiran Patil else 34260754d65bSKiran Patil status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, 34270754d65bSKiran Patil vsi->tc_cfg.ena_tc, max_txqs); 34280754d65bSKiran Patil 3429d31530e8SAkeem G Abodunrin if (status) { 34305f87ec48STony Nguyen dev_err(ice_pf_to_dev(pf), "VSI %d failed lan queue config, error %d\n", 34315f87ec48STony Nguyen vsi->vsi_num, status); 343287324e74SHenry Tieman if (init_vsi) { 343387324e74SHenry Tieman ret = -EIO; 3434df0f8479SAnirudh Venkataramanan goto err_vectors; 343587324e74SHenry Tieman } else { 343687324e74SHenry Tieman return ice_schedule_reset(pf, ICE_RESET_PFR); 343787324e74SHenry Tieman } 3438df0f8479SAnirudh Venkataramanan } 343961dc79ceSMichal Swiatkowski ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors); 344061dc79ceSMichal Swiatkowski kfree(coalesce); 344161dc79ceSMichal Swiatkowski 3442df0f8479SAnirudh Venkataramanan return 0; 3443df0f8479SAnirudh Venkataramanan 3444df0f8479SAnirudh Venkataramanan err_vectors: 3445df0f8479SAnirudh Venkataramanan ice_vsi_free_q_vectors(vsi); 3446df0f8479SAnirudh Venkataramanan err_rings: 3447df0f8479SAnirudh Venkataramanan if (vsi->netdev) { 3448df0f8479SAnirudh Venkataramanan vsi->current_netdev_flags = 0; 3449df0f8479SAnirudh Venkataramanan unregister_netdev(vsi->netdev); 3450df0f8479SAnirudh Venkataramanan free_netdev(vsi->netdev); 3451df0f8479SAnirudh Venkataramanan vsi->netdev = NULL; 3452df0f8479SAnirudh Venkataramanan } 3453df0f8479SAnirudh Venkataramanan err_vsi: 3454df0f8479SAnirudh Venkataramanan ice_vsi_clear(vsi); 34557e408e07SAnirudh Venkataramanan set_bit(ICE_RESET_FAILED, pf->state); 345661dc79ceSMichal Swiatkowski kfree(coalesce); 3457df0f8479SAnirudh Venkataramanan return ret; 3458df0f8479SAnirudh Venkataramanan } 3459df0f8479SAnirudh Venkataramanan 3460df0f8479SAnirudh Venkataramanan /** 34615df7e45dSDave Ertman * ice_is_reset_in_progress - check for a reset in progress 34622f2da36eSAnirudh Venkataramanan * @state: PF state field 34635153a18eSAnirudh Venkataramanan */ 34645df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state) 34655153a18eSAnirudh Venkataramanan { 34667e408e07SAnirudh Venkataramanan return test_bit(ICE_RESET_OICR_RECV, state) || 34677e408e07SAnirudh Venkataramanan test_bit(ICE_PFR_REQ, state) || 34687e408e07SAnirudh Venkataramanan test_bit(ICE_CORER_REQ, state) || 34697e408e07SAnirudh Venkataramanan test_bit(ICE_GLOBR_REQ, state); 34705153a18eSAnirudh Venkataramanan } 34717b9ffc76SAnirudh Venkataramanan 34721c08052eSJacob Keller /** 34731c08052eSJacob Keller * ice_wait_for_reset - Wait for driver to finish reset and rebuild 34741c08052eSJacob Keller * @pf: pointer to the PF structure 34751c08052eSJacob Keller * @timeout: length of time to wait, in jiffies 34761c08052eSJacob Keller * 34771c08052eSJacob Keller * Wait (sleep) for a short time until the driver finishes cleaning up from 34781c08052eSJacob Keller * a device reset. The caller must be able to sleep. Use this to delay 34791c08052eSJacob Keller * operations that could fail while the driver is cleaning up after a device 34801c08052eSJacob Keller * reset. 34811c08052eSJacob Keller * 34821c08052eSJacob Keller * Returns 0 on success, -EBUSY if the reset is not finished within the 34831c08052eSJacob Keller * timeout, and -ERESTARTSYS if the thread was interrupted. 34841c08052eSJacob Keller */ 34851c08052eSJacob Keller int ice_wait_for_reset(struct ice_pf *pf, unsigned long timeout) 34861c08052eSJacob Keller { 34871c08052eSJacob Keller long ret; 34881c08052eSJacob Keller 34891c08052eSJacob Keller ret = wait_event_interruptible_timeout(pf->reset_wait_queue, 34901c08052eSJacob Keller !ice_is_reset_in_progress(pf->state), 34911c08052eSJacob Keller timeout); 34921c08052eSJacob Keller if (ret < 0) 34931c08052eSJacob Keller return ret; 34941c08052eSJacob Keller else if (!ret) 34951c08052eSJacob Keller return -EBUSY; 34961c08052eSJacob Keller else 34971c08052eSJacob Keller return 0; 34981c08052eSJacob Keller } 34991c08052eSJacob Keller 35007b9ffc76SAnirudh Venkataramanan /** 35017b9ffc76SAnirudh Venkataramanan * ice_vsi_update_q_map - update our copy of the VSI info with new queue map 35027b9ffc76SAnirudh Venkataramanan * @vsi: VSI being configured 35037b9ffc76SAnirudh Venkataramanan * @ctx: the context buffer returned from AQ VSI update command 35047b9ffc76SAnirudh Venkataramanan */ 35057b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx) 35067b9ffc76SAnirudh Venkataramanan { 35077b9ffc76SAnirudh Venkataramanan vsi->info.mapping_flags = ctx->info.mapping_flags; 35087b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping, 35097b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.q_mapping)); 35107b9ffc76SAnirudh Venkataramanan memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping, 35117b9ffc76SAnirudh Venkataramanan sizeof(vsi->info.tc_mapping)); 35127b9ffc76SAnirudh Venkataramanan } 35137b9ffc76SAnirudh Venkataramanan 35147b9ffc76SAnirudh Venkataramanan /** 35150754d65bSKiran Patil * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration 35160754d65bSKiran Patil * @vsi: the VSI being configured 35170754d65bSKiran Patil * @ena_tc: TC map to be enabled 35180754d65bSKiran Patil */ 35190754d65bSKiran Patil void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc) 35200754d65bSKiran Patil { 35210754d65bSKiran Patil struct net_device *netdev = vsi->netdev; 35220754d65bSKiran Patil struct ice_pf *pf = vsi->back; 35230754d65bSKiran Patil int numtc = vsi->tc_cfg.numtc; 35240754d65bSKiran Patil struct ice_dcbx_cfg *dcbcfg; 35250754d65bSKiran Patil u8 netdev_tc; 35260754d65bSKiran Patil int i; 35270754d65bSKiran Patil 35280754d65bSKiran Patil if (!netdev) 35290754d65bSKiran Patil return; 35300754d65bSKiran Patil 35310754d65bSKiran Patil /* CHNL VSI doesn't have it's own netdev, hence, no netdev_tc */ 35320754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL) 35330754d65bSKiran Patil return; 35340754d65bSKiran Patil 35350754d65bSKiran Patil if (!ena_tc) { 35360754d65bSKiran Patil netdev_reset_tc(netdev); 35370754d65bSKiran Patil return; 35380754d65bSKiran Patil } 35390754d65bSKiran Patil 35400754d65bSKiran Patil if (vsi->type == ICE_VSI_PF && ice_is_adq_active(pf)) 35410754d65bSKiran Patil numtc = vsi->all_numtc; 35420754d65bSKiran Patil 35430754d65bSKiran Patil if (netdev_set_num_tc(netdev, numtc)) 35440754d65bSKiran Patil return; 35450754d65bSKiran Patil 35460754d65bSKiran Patil dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 35470754d65bSKiran Patil 35480754d65bSKiran Patil ice_for_each_traffic_class(i) 35490754d65bSKiran Patil if (vsi->tc_cfg.ena_tc & BIT(i)) 35500754d65bSKiran Patil netdev_set_tc_queue(netdev, 35510754d65bSKiran Patil vsi->tc_cfg.tc_info[i].netdev_tc, 35520754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qcount_tx, 35530754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qoffset); 35540754d65bSKiran Patil /* setup TC queue map for CHNL TCs */ 35550754d65bSKiran Patil ice_for_each_chnl_tc(i) { 35560754d65bSKiran Patil if (!(vsi->all_enatc & BIT(i))) 35570754d65bSKiran Patil break; 35580754d65bSKiran Patil if (!vsi->mqprio_qopt.qopt.count[i]) 35590754d65bSKiran Patil break; 35600754d65bSKiran Patil netdev_set_tc_queue(netdev, i, 35610754d65bSKiran Patil vsi->mqprio_qopt.qopt.count[i], 35620754d65bSKiran Patil vsi->mqprio_qopt.qopt.offset[i]); 35630754d65bSKiran Patil } 35640754d65bSKiran Patil 35650754d65bSKiran Patil if (test_bit(ICE_FLAG_TC_MQPRIO, pf->flags)) 35660754d65bSKiran Patil return; 35670754d65bSKiran Patil 35680754d65bSKiran Patil for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) { 35690754d65bSKiran Patil u8 ets_tc = dcbcfg->etscfg.prio_table[i]; 35700754d65bSKiran Patil 35710754d65bSKiran Patil /* Get the mapped netdev TC# for the UP */ 35720754d65bSKiran Patil netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc; 35730754d65bSKiran Patil netdev_set_prio_tc_map(netdev, i, netdev_tc); 35740754d65bSKiran Patil } 35750754d65bSKiran Patil } 35760754d65bSKiran Patil 35770754d65bSKiran Patil /** 35780754d65bSKiran Patil * ice_vsi_setup_q_map_mqprio - Prepares mqprio based tc_config 35790754d65bSKiran Patil * @vsi: the VSI being configured, 35800754d65bSKiran Patil * @ctxt: VSI context structure 35810754d65bSKiran Patil * @ena_tc: number of traffic classes to enable 35820754d65bSKiran Patil * 35830754d65bSKiran Patil * Prepares VSI tc_config to have queue configurations based on MQPRIO options. 35840754d65bSKiran Patil */ 35850754d65bSKiran Patil static void 35860754d65bSKiran Patil ice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt, 35870754d65bSKiran Patil u8 ena_tc) 35880754d65bSKiran Patil { 35890754d65bSKiran Patil u16 pow, offset = 0, qcount_tx = 0, qcount_rx = 0, qmap; 35900754d65bSKiran Patil u16 tc0_offset = vsi->mqprio_qopt.qopt.offset[0]; 35910754d65bSKiran Patil int tc0_qcount = vsi->mqprio_qopt.qopt.count[0]; 35920754d65bSKiran Patil u8 netdev_tc = 0; 35930754d65bSKiran Patil int i; 35940754d65bSKiran Patil 35950754d65bSKiran Patil vsi->tc_cfg.ena_tc = ena_tc ? ena_tc : 1; 35960754d65bSKiran Patil 35970754d65bSKiran Patil pow = order_base_2(tc0_qcount); 35980754d65bSKiran Patil qmap = ((tc0_offset << ICE_AQ_VSI_TC_Q_OFFSET_S) & 35990754d65bSKiran Patil ICE_AQ_VSI_TC_Q_OFFSET_M) | 36000754d65bSKiran Patil ((pow << ICE_AQ_VSI_TC_Q_NUM_S) & ICE_AQ_VSI_TC_Q_NUM_M); 36010754d65bSKiran Patil 36020754d65bSKiran Patil ice_for_each_traffic_class(i) { 36030754d65bSKiran Patil if (!(vsi->tc_cfg.ena_tc & BIT(i))) { 36040754d65bSKiran Patil /* TC is not enabled */ 36050754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qoffset = 0; 36060754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qcount_rx = 1; 36070754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qcount_tx = 1; 36080754d65bSKiran Patil vsi->tc_cfg.tc_info[i].netdev_tc = 0; 36090754d65bSKiran Patil ctxt->info.tc_mapping[i] = 0; 36100754d65bSKiran Patil continue; 36110754d65bSKiran Patil } 36120754d65bSKiran Patil 36130754d65bSKiran Patil offset = vsi->mqprio_qopt.qopt.offset[i]; 36140754d65bSKiran Patil qcount_rx = vsi->mqprio_qopt.qopt.count[i]; 36150754d65bSKiran Patil qcount_tx = vsi->mqprio_qopt.qopt.count[i]; 36160754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qoffset = offset; 36170754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx; 36180754d65bSKiran Patil vsi->tc_cfg.tc_info[i].qcount_tx = qcount_tx; 36190754d65bSKiran Patil vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++; 36200754d65bSKiran Patil } 36210754d65bSKiran Patil 36220754d65bSKiran Patil if (vsi->all_numtc && vsi->all_numtc != vsi->tc_cfg.numtc) { 36230754d65bSKiran Patil ice_for_each_chnl_tc(i) { 36240754d65bSKiran Patil if (!(vsi->all_enatc & BIT(i))) 36250754d65bSKiran Patil continue; 36260754d65bSKiran Patil offset = vsi->mqprio_qopt.qopt.offset[i]; 36270754d65bSKiran Patil qcount_rx = vsi->mqprio_qopt.qopt.count[i]; 36280754d65bSKiran Patil qcount_tx = vsi->mqprio_qopt.qopt.count[i]; 36290754d65bSKiran Patil } 36300754d65bSKiran Patil } 36310754d65bSKiran Patil 36320754d65bSKiran Patil /* Set actual Tx/Rx queue pairs */ 36330754d65bSKiran Patil vsi->num_txq = offset + qcount_tx; 36340754d65bSKiran Patil vsi->num_rxq = offset + qcount_rx; 36350754d65bSKiran Patil 36360754d65bSKiran Patil /* Setup queue TC[0].qmap for given VSI context */ 36370754d65bSKiran Patil ctxt->info.tc_mapping[0] = cpu_to_le16(qmap); 36380754d65bSKiran Patil ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]); 36390754d65bSKiran Patil ctxt->info.q_mapping[1] = cpu_to_le16(tc0_qcount); 36400754d65bSKiran Patil 36410754d65bSKiran Patil /* Find queue count available for channel VSIs and starting offset 36420754d65bSKiran Patil * for channel VSIs 36430754d65bSKiran Patil */ 36440754d65bSKiran Patil if (tc0_qcount && tc0_qcount < vsi->num_rxq) { 36450754d65bSKiran Patil vsi->cnt_q_avail = vsi->num_rxq - tc0_qcount; 36460754d65bSKiran Patil vsi->next_base_q = tc0_qcount; 36470754d65bSKiran Patil } 36480754d65bSKiran Patil dev_dbg(ice_pf_to_dev(vsi->back), "vsi->num_txq = %d\n", vsi->num_txq); 36490754d65bSKiran Patil dev_dbg(ice_pf_to_dev(vsi->back), "vsi->num_rxq = %d\n", vsi->num_rxq); 36500754d65bSKiran Patil dev_dbg(ice_pf_to_dev(vsi->back), "all_numtc %u, all_enatc: 0x%04x, tc_cfg.numtc %u\n", 36510754d65bSKiran Patil vsi->all_numtc, vsi->all_enatc, vsi->tc_cfg.numtc); 36520754d65bSKiran Patil } 36530754d65bSKiran Patil 36540754d65bSKiran Patil /** 36557b9ffc76SAnirudh Venkataramanan * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map 36567b9ffc76SAnirudh Venkataramanan * @vsi: VSI to be configured 36577b9ffc76SAnirudh Venkataramanan * @ena_tc: TC bitmap 36587b9ffc76SAnirudh Venkataramanan * 36597b9ffc76SAnirudh Venkataramanan * VSI queues expected to be quiesced before calling this function 36607b9ffc76SAnirudh Venkataramanan */ 36617b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc) 36627b9ffc76SAnirudh Venkataramanan { 36637b9ffc76SAnirudh Venkataramanan u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 }; 36647b9ffc76SAnirudh Venkataramanan struct ice_pf *pf = vsi->back; 36654ee656bbSTony Nguyen struct ice_vsi_ctx *ctx; 36665e24d598STony Nguyen int status; 36674015d11eSBrett Creeley struct device *dev; 36687b9ffc76SAnirudh Venkataramanan int i, ret = 0; 36697b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 36707b9ffc76SAnirudh Venkataramanan 36714015d11eSBrett Creeley dev = ice_pf_to_dev(pf); 36720754d65bSKiran Patil if (vsi->tc_cfg.ena_tc == ena_tc && 36730754d65bSKiran Patil vsi->mqprio_qopt.mode != TC_MQPRIO_MODE_CHANNEL) 36740754d65bSKiran Patil return ret; 36754015d11eSBrett Creeley 36767b9ffc76SAnirudh Venkataramanan ice_for_each_traffic_class(i) { 36777b9ffc76SAnirudh Venkataramanan /* build bitmap of enabled TCs */ 36787b9ffc76SAnirudh Venkataramanan if (ena_tc & BIT(i)) 36797b9ffc76SAnirudh Venkataramanan num_tc++; 36807b9ffc76SAnirudh Venkataramanan /* populate max_txqs per TC */ 3681d5a46359SAkeem G Abodunrin max_txqs[i] = vsi->alloc_txq; 36820754d65bSKiran Patil /* Update max_txqs if it is CHNL VSI, because alloc_t[r]xq are 36830754d65bSKiran Patil * zero for CHNL VSI, hence use num_txq instead as max_txqs 36840754d65bSKiran Patil */ 36850754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL && 36860754d65bSKiran Patil test_bit(ICE_FLAG_TC_MQPRIO, pf->flags)) 36870754d65bSKiran Patil max_txqs[i] = vsi->num_txq; 36887b9ffc76SAnirudh Venkataramanan } 36897b9ffc76SAnirudh Venkataramanan 36907b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.ena_tc = ena_tc; 36917b9ffc76SAnirudh Venkataramanan vsi->tc_cfg.numtc = num_tc; 36927b9ffc76SAnirudh Venkataramanan 36939efe35d0STony Nguyen ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 36947b9ffc76SAnirudh Venkataramanan if (!ctx) 36957b9ffc76SAnirudh Venkataramanan return -ENOMEM; 36967b9ffc76SAnirudh Venkataramanan 36977b9ffc76SAnirudh Venkataramanan ctx->vf_num = 0; 36987b9ffc76SAnirudh Venkataramanan ctx->info = vsi->info; 36997b9ffc76SAnirudh Venkataramanan 37000754d65bSKiran Patil if (vsi->type == ICE_VSI_PF && 37010754d65bSKiran Patil test_bit(ICE_FLAG_TC_MQPRIO, pf->flags)) 37020754d65bSKiran Patil ice_vsi_setup_q_map_mqprio(vsi, ctx, ena_tc); 37030754d65bSKiran Patil else 37047b9ffc76SAnirudh Venkataramanan ice_vsi_setup_q_map(vsi, ctx); 37057b9ffc76SAnirudh Venkataramanan 37067b9ffc76SAnirudh Venkataramanan /* must to indicate which section of VSI context are being modified */ 37077b9ffc76SAnirudh Venkataramanan ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID); 37087b9ffc76SAnirudh Venkataramanan status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL); 37097b9ffc76SAnirudh Venkataramanan if (status) { 37104015d11eSBrett Creeley dev_info(dev, "Failed VSI Update\n"); 37117b9ffc76SAnirudh Venkataramanan ret = -EIO; 37127b9ffc76SAnirudh Venkataramanan goto out; 37137b9ffc76SAnirudh Venkataramanan } 37147b9ffc76SAnirudh Venkataramanan 37150754d65bSKiran Patil if (vsi->type == ICE_VSI_PF && 37160754d65bSKiran Patil test_bit(ICE_FLAG_TC_MQPRIO, pf->flags)) 37170754d65bSKiran Patil status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, 1, 37187b9ffc76SAnirudh Venkataramanan max_txqs); 37190754d65bSKiran Patil else 37200754d65bSKiran Patil status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, 37210754d65bSKiran Patil vsi->tc_cfg.ena_tc, max_txqs); 37227b9ffc76SAnirudh Venkataramanan 37237b9ffc76SAnirudh Venkataramanan if (status) { 37245f87ec48STony Nguyen dev_err(dev, "VSI %d failed TC config, error %d\n", 37255f87ec48STony Nguyen vsi->vsi_num, status); 37267b9ffc76SAnirudh Venkataramanan ret = -EIO; 37277b9ffc76SAnirudh Venkataramanan goto out; 37287b9ffc76SAnirudh Venkataramanan } 37297b9ffc76SAnirudh Venkataramanan ice_vsi_update_q_map(vsi, ctx); 37307b9ffc76SAnirudh Venkataramanan vsi->info.valid_sections = 0; 37317b9ffc76SAnirudh Venkataramanan 37327b9ffc76SAnirudh Venkataramanan ice_vsi_cfg_netdev_tc(vsi, ena_tc); 37337b9ffc76SAnirudh Venkataramanan out: 37349efe35d0STony Nguyen kfree(ctx); 37357b9ffc76SAnirudh Venkataramanan return ret; 37367b9ffc76SAnirudh Venkataramanan } 3737bbb968e8SAkeem G Abodunrin 3738bbb968e8SAkeem G Abodunrin /** 37392d4238f5SKrzysztof Kazimierczak * ice_update_ring_stats - Update ring statistics 3740e72bba21SMaciej Fijalkowski * @stats: stats to be updated 37412d4238f5SKrzysztof Kazimierczak * @pkts: number of processed packets 37422d4238f5SKrzysztof Kazimierczak * @bytes: number of processed bytes 37432d4238f5SKrzysztof Kazimierczak * 37442d4238f5SKrzysztof Kazimierczak * This function assumes that caller has acquired a u64_stats_sync lock. 37452d4238f5SKrzysztof Kazimierczak */ 3746e72bba21SMaciej Fijalkowski static void ice_update_ring_stats(struct ice_q_stats *stats, u64 pkts, u64 bytes) 37472d4238f5SKrzysztof Kazimierczak { 3748e72bba21SMaciej Fijalkowski stats->bytes += bytes; 3749e72bba21SMaciej Fijalkowski stats->pkts += pkts; 37502d4238f5SKrzysztof Kazimierczak } 37512d4238f5SKrzysztof Kazimierczak 37522d4238f5SKrzysztof Kazimierczak /** 37532d4238f5SKrzysztof Kazimierczak * ice_update_tx_ring_stats - Update Tx ring specific counters 37542d4238f5SKrzysztof Kazimierczak * @tx_ring: ring to update 37552d4238f5SKrzysztof Kazimierczak * @pkts: number of processed packets 37562d4238f5SKrzysztof Kazimierczak * @bytes: number of processed bytes 37572d4238f5SKrzysztof Kazimierczak */ 3758e72bba21SMaciej Fijalkowski void ice_update_tx_ring_stats(struct ice_tx_ring *tx_ring, u64 pkts, u64 bytes) 37592d4238f5SKrzysztof Kazimierczak { 37602d4238f5SKrzysztof Kazimierczak u64_stats_update_begin(&tx_ring->syncp); 3761e72bba21SMaciej Fijalkowski ice_update_ring_stats(&tx_ring->stats, pkts, bytes); 37622d4238f5SKrzysztof Kazimierczak u64_stats_update_end(&tx_ring->syncp); 37632d4238f5SKrzysztof Kazimierczak } 37642d4238f5SKrzysztof Kazimierczak 37652d4238f5SKrzysztof Kazimierczak /** 37662d4238f5SKrzysztof Kazimierczak * ice_update_rx_ring_stats - Update Rx ring specific counters 37672d4238f5SKrzysztof Kazimierczak * @rx_ring: ring to update 37682d4238f5SKrzysztof Kazimierczak * @pkts: number of processed packets 37692d4238f5SKrzysztof Kazimierczak * @bytes: number of processed bytes 37702d4238f5SKrzysztof Kazimierczak */ 3771e72bba21SMaciej Fijalkowski void ice_update_rx_ring_stats(struct ice_rx_ring *rx_ring, u64 pkts, u64 bytes) 37722d4238f5SKrzysztof Kazimierczak { 37732d4238f5SKrzysztof Kazimierczak u64_stats_update_begin(&rx_ring->syncp); 3774e72bba21SMaciej Fijalkowski ice_update_ring_stats(&rx_ring->stats, pkts, bytes); 37752d4238f5SKrzysztof Kazimierczak u64_stats_update_end(&rx_ring->syncp); 37762d4238f5SKrzysztof Kazimierczak } 37772d4238f5SKrzysztof Kazimierczak 37782d4238f5SKrzysztof Kazimierczak /** 3779fc0f39bcSBrett Creeley * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used 3780fc0f39bcSBrett Creeley * @sw: switch to check if its default forwarding VSI is free 3781fc0f39bcSBrett Creeley * 3782fc0f39bcSBrett Creeley * Return true if the default forwarding VSI is already being used, else returns 3783fc0f39bcSBrett Creeley * false signalling that it's available to use. 3784fc0f39bcSBrett Creeley */ 3785fc0f39bcSBrett Creeley bool ice_is_dflt_vsi_in_use(struct ice_sw *sw) 3786fc0f39bcSBrett Creeley { 3787fc0f39bcSBrett Creeley return (sw->dflt_vsi && sw->dflt_vsi_ena); 3788fc0f39bcSBrett Creeley } 3789fc0f39bcSBrett Creeley 3790fc0f39bcSBrett Creeley /** 3791fc0f39bcSBrett Creeley * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI 3792fc0f39bcSBrett Creeley * @sw: switch for the default forwarding VSI to compare against 3793fc0f39bcSBrett Creeley * @vsi: VSI to compare against default forwarding VSI 3794fc0f39bcSBrett Creeley * 3795fc0f39bcSBrett Creeley * If this VSI passed in is the default forwarding VSI then return true, else 3796fc0f39bcSBrett Creeley * return false 3797fc0f39bcSBrett Creeley */ 3798fc0f39bcSBrett Creeley bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi) 3799fc0f39bcSBrett Creeley { 3800fc0f39bcSBrett Creeley return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena); 3801fc0f39bcSBrett Creeley } 3802fc0f39bcSBrett Creeley 3803fc0f39bcSBrett Creeley /** 3804fc0f39bcSBrett Creeley * ice_set_dflt_vsi - set the default forwarding VSI 3805fc0f39bcSBrett Creeley * @sw: switch used to assign the default forwarding VSI 3806fc0f39bcSBrett Creeley * @vsi: VSI getting set as the default forwarding VSI on the switch 3807fc0f39bcSBrett Creeley * 3808fc0f39bcSBrett Creeley * If the VSI passed in is already the default VSI and it's enabled just return 3809fc0f39bcSBrett Creeley * success. 3810fc0f39bcSBrett Creeley * 3811fc0f39bcSBrett Creeley * If there is already a default VSI on the switch and it's enabled then return 3812fc0f39bcSBrett Creeley * -EEXIST since there can only be one default VSI per switch. 3813fc0f39bcSBrett Creeley * 3814fc0f39bcSBrett Creeley * Otherwise try to set the VSI passed in as the switch's default VSI and 3815fc0f39bcSBrett Creeley * return the result. 3816fc0f39bcSBrett Creeley */ 3817fc0f39bcSBrett Creeley int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi) 3818fc0f39bcSBrett Creeley { 38195e24d598STony Nguyen int status; 3820fc0f39bcSBrett Creeley struct device *dev; 3821fc0f39bcSBrett Creeley 3822fc0f39bcSBrett Creeley if (!sw || !vsi) 3823fc0f39bcSBrett Creeley return -EINVAL; 3824fc0f39bcSBrett Creeley 3825fc0f39bcSBrett Creeley dev = ice_pf_to_dev(vsi->back); 3826fc0f39bcSBrett Creeley 3827fc0f39bcSBrett Creeley /* the VSI passed in is already the default VSI */ 3828fc0f39bcSBrett Creeley if (ice_is_vsi_dflt_vsi(sw, vsi)) { 3829fc0f39bcSBrett Creeley dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n", 3830fc0f39bcSBrett Creeley vsi->vsi_num); 3831fc0f39bcSBrett Creeley return 0; 3832fc0f39bcSBrett Creeley } 3833fc0f39bcSBrett Creeley 3834fc0f39bcSBrett Creeley /* another VSI is already the default VSI for this switch */ 3835fc0f39bcSBrett Creeley if (ice_is_dflt_vsi_in_use(sw)) { 383619cce2c6SAnirudh Venkataramanan dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n", 3837fc0f39bcSBrett Creeley sw->dflt_vsi->vsi_num); 3838fc0f39bcSBrett Creeley return -EEXIST; 3839fc0f39bcSBrett Creeley } 3840fc0f39bcSBrett Creeley 3841fc0f39bcSBrett Creeley status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX); 3842fc0f39bcSBrett Creeley if (status) { 38435f87ec48STony Nguyen dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n", 38445f87ec48STony Nguyen vsi->vsi_num, status); 3845fc0f39bcSBrett Creeley return -EIO; 3846fc0f39bcSBrett Creeley } 3847fc0f39bcSBrett Creeley 3848fc0f39bcSBrett Creeley sw->dflt_vsi = vsi; 3849fc0f39bcSBrett Creeley sw->dflt_vsi_ena = true; 3850fc0f39bcSBrett Creeley 3851fc0f39bcSBrett Creeley return 0; 3852fc0f39bcSBrett Creeley } 3853fc0f39bcSBrett Creeley 3854fc0f39bcSBrett Creeley /** 3855fc0f39bcSBrett Creeley * ice_clear_dflt_vsi - clear the default forwarding VSI 3856fc0f39bcSBrett Creeley * @sw: switch used to clear the default VSI 3857fc0f39bcSBrett Creeley * 3858fc0f39bcSBrett Creeley * If the switch has no default VSI or it's not enabled then return error. 3859fc0f39bcSBrett Creeley * 3860fc0f39bcSBrett Creeley * Otherwise try to clear the default VSI and return the result. 3861fc0f39bcSBrett Creeley */ 3862fc0f39bcSBrett Creeley int ice_clear_dflt_vsi(struct ice_sw *sw) 3863fc0f39bcSBrett Creeley { 3864fc0f39bcSBrett Creeley struct ice_vsi *dflt_vsi; 38655e24d598STony Nguyen int status; 3866fc0f39bcSBrett Creeley struct device *dev; 3867fc0f39bcSBrett Creeley 3868fc0f39bcSBrett Creeley if (!sw) 3869fc0f39bcSBrett Creeley return -EINVAL; 3870fc0f39bcSBrett Creeley 3871fc0f39bcSBrett Creeley dev = ice_pf_to_dev(sw->pf); 3872fc0f39bcSBrett Creeley 3873fc0f39bcSBrett Creeley dflt_vsi = sw->dflt_vsi; 3874fc0f39bcSBrett Creeley 3875fc0f39bcSBrett Creeley /* there is no default VSI configured */ 3876fc0f39bcSBrett Creeley if (!ice_is_dflt_vsi_in_use(sw)) 3877fc0f39bcSBrett Creeley return -ENODEV; 3878fc0f39bcSBrett Creeley 3879fc0f39bcSBrett Creeley status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false, 3880fc0f39bcSBrett Creeley ICE_FLTR_RX); 3881fc0f39bcSBrett Creeley if (status) { 38825f87ec48STony Nguyen dev_err(dev, "Failed to clear the default forwarding VSI %d, error %d\n", 38835f87ec48STony Nguyen dflt_vsi->vsi_num, status); 3884fc0f39bcSBrett Creeley return -EIO; 3885fc0f39bcSBrett Creeley } 3886fc0f39bcSBrett Creeley 3887fc0f39bcSBrett Creeley sw->dflt_vsi = NULL; 3888fc0f39bcSBrett Creeley sw->dflt_vsi_ena = false; 3889fc0f39bcSBrett Creeley 3890fc0f39bcSBrett Creeley return 0; 3891fc0f39bcSBrett Creeley } 3892d348d517SAnirudh Venkataramanan 3893d348d517SAnirudh Venkataramanan /** 38944ecc8633SBrett Creeley * ice_get_link_speed_mbps - get link speed in Mbps 38954ecc8633SBrett Creeley * @vsi: the VSI whose link speed is being queried 38964ecc8633SBrett Creeley * 38974ecc8633SBrett Creeley * Return current VSI link speed and 0 if the speed is unknown. 38984ecc8633SBrett Creeley */ 38994ecc8633SBrett Creeley int ice_get_link_speed_mbps(struct ice_vsi *vsi) 39004ecc8633SBrett Creeley { 39014ecc8633SBrett Creeley switch (vsi->port_info->phy.link_info.link_speed) { 39024ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_100GB: 39034ecc8633SBrett Creeley return SPEED_100000; 39044ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_50GB: 39054ecc8633SBrett Creeley return SPEED_50000; 39064ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_40GB: 39074ecc8633SBrett Creeley return SPEED_40000; 39084ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_25GB: 39094ecc8633SBrett Creeley return SPEED_25000; 39104ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_20GB: 39114ecc8633SBrett Creeley return SPEED_20000; 39124ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_10GB: 39134ecc8633SBrett Creeley return SPEED_10000; 39144ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_5GB: 39154ecc8633SBrett Creeley return SPEED_5000; 39164ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_2500MB: 39174ecc8633SBrett Creeley return SPEED_2500; 39184ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_1000MB: 39194ecc8633SBrett Creeley return SPEED_1000; 39204ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_100MB: 39214ecc8633SBrett Creeley return SPEED_100; 39224ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_10MB: 39234ecc8633SBrett Creeley return SPEED_10; 39244ecc8633SBrett Creeley case ICE_AQ_LINK_SPEED_UNKNOWN: 39254ecc8633SBrett Creeley default: 39264ecc8633SBrett Creeley return 0; 39274ecc8633SBrett Creeley } 39284ecc8633SBrett Creeley } 39294ecc8633SBrett Creeley 39304ecc8633SBrett Creeley /** 39314ecc8633SBrett Creeley * ice_get_link_speed_kbps - get link speed in Kbps 39324ecc8633SBrett Creeley * @vsi: the VSI whose link speed is being queried 39334ecc8633SBrett Creeley * 39344ecc8633SBrett Creeley * Return current VSI link speed and 0 if the speed is unknown. 39354ecc8633SBrett Creeley */ 3936fbc7b27aSKiran Patil int ice_get_link_speed_kbps(struct ice_vsi *vsi) 39374ecc8633SBrett Creeley { 39384ecc8633SBrett Creeley int speed_mbps; 39394ecc8633SBrett Creeley 39404ecc8633SBrett Creeley speed_mbps = ice_get_link_speed_mbps(vsi); 39414ecc8633SBrett Creeley 39424ecc8633SBrett Creeley return speed_mbps * 1000; 39434ecc8633SBrett Creeley } 39444ecc8633SBrett Creeley 39454ecc8633SBrett Creeley /** 39464ecc8633SBrett Creeley * ice_set_min_bw_limit - setup minimum BW limit for Tx based on min_tx_rate 39474ecc8633SBrett Creeley * @vsi: VSI to be configured 39484ecc8633SBrett Creeley * @min_tx_rate: min Tx rate in Kbps to be configured as BW limit 39494ecc8633SBrett Creeley * 39504ecc8633SBrett Creeley * If the min_tx_rate is specified as 0 that means to clear the minimum BW limit 39514ecc8633SBrett Creeley * profile, otherwise a non-zero value will force a minimum BW limit for the VSI 39524ecc8633SBrett Creeley * on TC 0. 39534ecc8633SBrett Creeley */ 39544ecc8633SBrett Creeley int ice_set_min_bw_limit(struct ice_vsi *vsi, u64 min_tx_rate) 39554ecc8633SBrett Creeley { 39564ecc8633SBrett Creeley struct ice_pf *pf = vsi->back; 39575e24d598STony Nguyen int status; 39584ecc8633SBrett Creeley struct device *dev; 39594ecc8633SBrett Creeley int speed; 39604ecc8633SBrett Creeley 39614ecc8633SBrett Creeley dev = ice_pf_to_dev(pf); 39624ecc8633SBrett Creeley if (!vsi->port_info) { 39634ecc8633SBrett Creeley dev_dbg(dev, "VSI %d, type %u specified doesn't have valid port_info\n", 39644ecc8633SBrett Creeley vsi->idx, vsi->type); 39654ecc8633SBrett Creeley return -EINVAL; 39664ecc8633SBrett Creeley } 39674ecc8633SBrett Creeley 39684ecc8633SBrett Creeley speed = ice_get_link_speed_kbps(vsi); 39694ecc8633SBrett Creeley if (min_tx_rate > (u64)speed) { 39704ecc8633SBrett Creeley dev_err(dev, "invalid min Tx rate %llu Kbps specified for %s %d is greater than current link speed %u Kbps\n", 39714ecc8633SBrett Creeley min_tx_rate, ice_vsi_type_str(vsi->type), vsi->idx, 39724ecc8633SBrett Creeley speed); 39734ecc8633SBrett Creeley return -EINVAL; 39744ecc8633SBrett Creeley } 39754ecc8633SBrett Creeley 39764ecc8633SBrett Creeley /* Configure min BW for VSI limit */ 39774ecc8633SBrett Creeley if (min_tx_rate) { 39784ecc8633SBrett Creeley status = ice_cfg_vsi_bw_lmt_per_tc(vsi->port_info, vsi->idx, 0, 39794ecc8633SBrett Creeley ICE_MIN_BW, min_tx_rate); 39804ecc8633SBrett Creeley if (status) { 39814ecc8633SBrett Creeley dev_err(dev, "failed to set min Tx rate(%llu Kbps) for %s %d\n", 39824ecc8633SBrett Creeley min_tx_rate, ice_vsi_type_str(vsi->type), 39834ecc8633SBrett Creeley vsi->idx); 39844ecc8633SBrett Creeley return -EIO; 39854ecc8633SBrett Creeley } 39864ecc8633SBrett Creeley 39874ecc8633SBrett Creeley dev_dbg(dev, "set min Tx rate(%llu Kbps) for %s\n", 39884ecc8633SBrett Creeley min_tx_rate, ice_vsi_type_str(vsi->type)); 39894ecc8633SBrett Creeley } else { 39904ecc8633SBrett Creeley status = ice_cfg_vsi_bw_dflt_lmt_per_tc(vsi->port_info, 39914ecc8633SBrett Creeley vsi->idx, 0, 39924ecc8633SBrett Creeley ICE_MIN_BW); 39934ecc8633SBrett Creeley if (status) { 39944ecc8633SBrett Creeley dev_err(dev, "failed to clear min Tx rate configuration for %s %d\n", 39954ecc8633SBrett Creeley ice_vsi_type_str(vsi->type), vsi->idx); 39964ecc8633SBrett Creeley return -EIO; 39974ecc8633SBrett Creeley } 39984ecc8633SBrett Creeley 39994ecc8633SBrett Creeley dev_dbg(dev, "cleared min Tx rate configuration for %s %d\n", 40004ecc8633SBrett Creeley ice_vsi_type_str(vsi->type), vsi->idx); 40014ecc8633SBrett Creeley } 40024ecc8633SBrett Creeley 40034ecc8633SBrett Creeley return 0; 40044ecc8633SBrett Creeley } 40054ecc8633SBrett Creeley 40064ecc8633SBrett Creeley /** 40074ecc8633SBrett Creeley * ice_set_max_bw_limit - setup maximum BW limit for Tx based on max_tx_rate 40084ecc8633SBrett Creeley * @vsi: VSI to be configured 40094ecc8633SBrett Creeley * @max_tx_rate: max Tx rate in Kbps to be configured as BW limit 40104ecc8633SBrett Creeley * 40114ecc8633SBrett Creeley * If the max_tx_rate is specified as 0 that means to clear the maximum BW limit 40124ecc8633SBrett Creeley * profile, otherwise a non-zero value will force a maximum BW limit for the VSI 40134ecc8633SBrett Creeley * on TC 0. 40144ecc8633SBrett Creeley */ 40154ecc8633SBrett Creeley int ice_set_max_bw_limit(struct ice_vsi *vsi, u64 max_tx_rate) 40164ecc8633SBrett Creeley { 40174ecc8633SBrett Creeley struct ice_pf *pf = vsi->back; 40185e24d598STony Nguyen int status; 40194ecc8633SBrett Creeley struct device *dev; 40204ecc8633SBrett Creeley int speed; 40214ecc8633SBrett Creeley 40224ecc8633SBrett Creeley dev = ice_pf_to_dev(pf); 40234ecc8633SBrett Creeley if (!vsi->port_info) { 40244ecc8633SBrett Creeley dev_dbg(dev, "VSI %d, type %u specified doesn't have valid port_info\n", 40254ecc8633SBrett Creeley vsi->idx, vsi->type); 40264ecc8633SBrett Creeley return -EINVAL; 40274ecc8633SBrett Creeley } 40284ecc8633SBrett Creeley 40294ecc8633SBrett Creeley speed = ice_get_link_speed_kbps(vsi); 40304ecc8633SBrett Creeley if (max_tx_rate > (u64)speed) { 40314ecc8633SBrett Creeley dev_err(dev, "invalid max Tx rate %llu Kbps specified for %s %d is greater than current link speed %u Kbps\n", 40324ecc8633SBrett Creeley max_tx_rate, ice_vsi_type_str(vsi->type), vsi->idx, 40334ecc8633SBrett Creeley speed); 40344ecc8633SBrett Creeley return -EINVAL; 40354ecc8633SBrett Creeley } 40364ecc8633SBrett Creeley 40374ecc8633SBrett Creeley /* Configure max BW for VSI limit */ 40384ecc8633SBrett Creeley if (max_tx_rate) { 40394ecc8633SBrett Creeley status = ice_cfg_vsi_bw_lmt_per_tc(vsi->port_info, vsi->idx, 0, 40404ecc8633SBrett Creeley ICE_MAX_BW, max_tx_rate); 40414ecc8633SBrett Creeley if (status) { 40424ecc8633SBrett Creeley dev_err(dev, "failed setting max Tx rate(%llu Kbps) for %s %d\n", 40434ecc8633SBrett Creeley max_tx_rate, ice_vsi_type_str(vsi->type), 40444ecc8633SBrett Creeley vsi->idx); 40454ecc8633SBrett Creeley return -EIO; 40464ecc8633SBrett Creeley } 40474ecc8633SBrett Creeley 40484ecc8633SBrett Creeley dev_dbg(dev, "set max Tx rate(%llu Kbps) for %s %d\n", 40494ecc8633SBrett Creeley max_tx_rate, ice_vsi_type_str(vsi->type), vsi->idx); 40504ecc8633SBrett Creeley } else { 40514ecc8633SBrett Creeley status = ice_cfg_vsi_bw_dflt_lmt_per_tc(vsi->port_info, 40524ecc8633SBrett Creeley vsi->idx, 0, 40534ecc8633SBrett Creeley ICE_MAX_BW); 40544ecc8633SBrett Creeley if (status) { 40554ecc8633SBrett Creeley dev_err(dev, "failed clearing max Tx rate configuration for %s %d\n", 40564ecc8633SBrett Creeley ice_vsi_type_str(vsi->type), vsi->idx); 40574ecc8633SBrett Creeley return -EIO; 40584ecc8633SBrett Creeley } 40594ecc8633SBrett Creeley 40604ecc8633SBrett Creeley dev_dbg(dev, "cleared max Tx rate configuration for %s %d\n", 40614ecc8633SBrett Creeley ice_vsi_type_str(vsi->type), vsi->idx); 40624ecc8633SBrett Creeley } 40634ecc8633SBrett Creeley 40644ecc8633SBrett Creeley return 0; 40654ecc8633SBrett Creeley } 40664ecc8633SBrett Creeley 40674ecc8633SBrett Creeley /** 4068d348d517SAnirudh Venkataramanan * ice_set_link - turn on/off physical link 4069d348d517SAnirudh Venkataramanan * @vsi: VSI to modify physical link on 4070d348d517SAnirudh Venkataramanan * @ena: turn on/off physical link 4071d348d517SAnirudh Venkataramanan */ 4072d348d517SAnirudh Venkataramanan int ice_set_link(struct ice_vsi *vsi, bool ena) 4073d348d517SAnirudh Venkataramanan { 4074d348d517SAnirudh Venkataramanan struct device *dev = ice_pf_to_dev(vsi->back); 4075d348d517SAnirudh Venkataramanan struct ice_port_info *pi = vsi->port_info; 4076d348d517SAnirudh Venkataramanan struct ice_hw *hw = pi->hw; 40775e24d598STony Nguyen int status; 4078d348d517SAnirudh Venkataramanan 4079d348d517SAnirudh Venkataramanan if (vsi->type != ICE_VSI_PF) 4080d348d517SAnirudh Venkataramanan return -EINVAL; 4081d348d517SAnirudh Venkataramanan 4082d348d517SAnirudh Venkataramanan status = ice_aq_set_link_restart_an(pi, ena, NULL); 4083d348d517SAnirudh Venkataramanan 4084d348d517SAnirudh Venkataramanan /* if link is owned by manageability, FW will return ICE_AQ_RC_EMODE. 4085d348d517SAnirudh Venkataramanan * this is not a fatal error, so print a warning message and return 4086d348d517SAnirudh Venkataramanan * a success code. Return an error if FW returns an error code other 4087d348d517SAnirudh Venkataramanan * than ICE_AQ_RC_EMODE 4088d348d517SAnirudh Venkataramanan */ 4089*d54699e2STony Nguyen if (status == -EIO) { 4090d348d517SAnirudh Venkataramanan if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE) 40915f87ec48STony Nguyen dev_warn(dev, "can't set link to %s, err %d aq_err %s. not fatal, continuing\n", 40925f87ec48STony Nguyen (ena ? "ON" : "OFF"), status, 4093d348d517SAnirudh Venkataramanan ice_aq_str(hw->adminq.sq_last_status)); 4094d348d517SAnirudh Venkataramanan } else if (status) { 40955f87ec48STony Nguyen dev_err(dev, "can't set link to %s, err %d aq_err %s\n", 40965f87ec48STony Nguyen (ena ? "ON" : "OFF"), status, 4097d348d517SAnirudh Venkataramanan ice_aq_str(hw->adminq.sq_last_status)); 4098d348d517SAnirudh Venkataramanan return -EIO; 4099d348d517SAnirudh Venkataramanan } 4100d348d517SAnirudh Venkataramanan 4101d348d517SAnirudh Venkataramanan return 0; 4102d348d517SAnirudh Venkataramanan } 410340b24760SAnirudh Venkataramanan 410440b24760SAnirudh Venkataramanan /** 410540b24760SAnirudh Venkataramanan * ice_is_feature_supported 410640b24760SAnirudh Venkataramanan * @pf: pointer to the struct ice_pf instance 410740b24760SAnirudh Venkataramanan * @f: feature enum to be checked 410840b24760SAnirudh Venkataramanan * 410940b24760SAnirudh Venkataramanan * returns true if feature is supported, false otherwise 411040b24760SAnirudh Venkataramanan */ 411140b24760SAnirudh Venkataramanan bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f) 411240b24760SAnirudh Venkataramanan { 411340b24760SAnirudh Venkataramanan if (f < 0 || f >= ICE_F_MAX) 411440b24760SAnirudh Venkataramanan return false; 411540b24760SAnirudh Venkataramanan 411640b24760SAnirudh Venkataramanan return test_bit(f, pf->features); 411740b24760SAnirudh Venkataramanan } 411840b24760SAnirudh Venkataramanan 411940b24760SAnirudh Venkataramanan /** 412040b24760SAnirudh Venkataramanan * ice_set_feature_support 412140b24760SAnirudh Venkataramanan * @pf: pointer to the struct ice_pf instance 412240b24760SAnirudh Venkataramanan * @f: feature enum to set 412340b24760SAnirudh Venkataramanan */ 412440b24760SAnirudh Venkataramanan static void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f) 412540b24760SAnirudh Venkataramanan { 412640b24760SAnirudh Venkataramanan if (f < 0 || f >= ICE_F_MAX) 412740b24760SAnirudh Venkataramanan return; 412840b24760SAnirudh Venkataramanan 412940b24760SAnirudh Venkataramanan set_bit(f, pf->features); 413040b24760SAnirudh Venkataramanan } 413140b24760SAnirudh Venkataramanan 413240b24760SAnirudh Venkataramanan /** 4133325b2064SMaciej Machnikowski * ice_clear_feature_support 4134325b2064SMaciej Machnikowski * @pf: pointer to the struct ice_pf instance 4135325b2064SMaciej Machnikowski * @f: feature enum to clear 4136325b2064SMaciej Machnikowski */ 4137325b2064SMaciej Machnikowski void ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f) 4138325b2064SMaciej Machnikowski { 4139325b2064SMaciej Machnikowski if (f < 0 || f >= ICE_F_MAX) 4140325b2064SMaciej Machnikowski return; 4141325b2064SMaciej Machnikowski 4142325b2064SMaciej Machnikowski clear_bit(f, pf->features); 4143325b2064SMaciej Machnikowski } 4144325b2064SMaciej Machnikowski 4145325b2064SMaciej Machnikowski /** 414640b24760SAnirudh Venkataramanan * ice_init_feature_support 414740b24760SAnirudh Venkataramanan * @pf: pointer to the struct ice_pf instance 414840b24760SAnirudh Venkataramanan * 414940b24760SAnirudh Venkataramanan * called during init to setup supported feature 415040b24760SAnirudh Venkataramanan */ 415140b24760SAnirudh Venkataramanan void ice_init_feature_support(struct ice_pf *pf) 415240b24760SAnirudh Venkataramanan { 415340b24760SAnirudh Venkataramanan switch (pf->hw.device_id) { 415440b24760SAnirudh Venkataramanan case ICE_DEV_ID_E810C_BACKPLANE: 415540b24760SAnirudh Venkataramanan case ICE_DEV_ID_E810C_QSFP: 415640b24760SAnirudh Venkataramanan case ICE_DEV_ID_E810C_SFP: 415740b24760SAnirudh Venkataramanan ice_set_feature_support(pf, ICE_F_DSCP); 4158325b2064SMaciej Machnikowski if (ice_is_e810t(&pf->hw)) 4159325b2064SMaciej Machnikowski ice_set_feature_support(pf, ICE_F_SMA_CTRL); 416040b24760SAnirudh Venkataramanan break; 416140b24760SAnirudh Venkataramanan default: 416240b24760SAnirudh Venkataramanan break; 416340b24760SAnirudh Venkataramanan } 416440b24760SAnirudh Venkataramanan } 4165ff5411efSMichal Swiatkowski 4166ff5411efSMichal Swiatkowski /** 4167ff5411efSMichal Swiatkowski * ice_vsi_update_security - update security block in VSI 4168ff5411efSMichal Swiatkowski * @vsi: pointer to VSI structure 4169ff5411efSMichal Swiatkowski * @fill: function pointer to fill ctx 4170ff5411efSMichal Swiatkowski */ 4171ff5411efSMichal Swiatkowski int 4172ff5411efSMichal Swiatkowski ice_vsi_update_security(struct ice_vsi *vsi, void (*fill)(struct ice_vsi_ctx *)) 4173ff5411efSMichal Swiatkowski { 4174ff5411efSMichal Swiatkowski struct ice_vsi_ctx ctx = { 0 }; 4175ff5411efSMichal Swiatkowski 4176ff5411efSMichal Swiatkowski ctx.info = vsi->info; 4177ff5411efSMichal Swiatkowski ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID); 4178ff5411efSMichal Swiatkowski fill(&ctx); 4179ff5411efSMichal Swiatkowski 4180ff5411efSMichal Swiatkowski if (ice_update_vsi(&vsi->back->hw, vsi->idx, &ctx, NULL)) 4181ff5411efSMichal Swiatkowski return -ENODEV; 4182ff5411efSMichal Swiatkowski 4183ff5411efSMichal Swiatkowski vsi->info = ctx.info; 4184ff5411efSMichal Swiatkowski return 0; 4185ff5411efSMichal Swiatkowski } 4186ff5411efSMichal Swiatkowski 4187ff5411efSMichal Swiatkowski /** 4188ff5411efSMichal Swiatkowski * ice_vsi_ctx_set_antispoof - set antispoof function in VSI ctx 4189ff5411efSMichal Swiatkowski * @ctx: pointer to VSI ctx structure 4190ff5411efSMichal Swiatkowski */ 4191ff5411efSMichal Swiatkowski void ice_vsi_ctx_set_antispoof(struct ice_vsi_ctx *ctx) 4192ff5411efSMichal Swiatkowski { 4193ff5411efSMichal Swiatkowski ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF | 4194ff5411efSMichal Swiatkowski (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 4195ff5411efSMichal Swiatkowski ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 4196ff5411efSMichal Swiatkowski } 4197ff5411efSMichal Swiatkowski 4198ff5411efSMichal Swiatkowski /** 4199ff5411efSMichal Swiatkowski * ice_vsi_ctx_clear_antispoof - clear antispoof function in VSI ctx 4200ff5411efSMichal Swiatkowski * @ctx: pointer to VSI ctx structure 4201ff5411efSMichal Swiatkowski */ 4202ff5411efSMichal Swiatkowski void ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx) 4203ff5411efSMichal Swiatkowski { 4204ff5411efSMichal Swiatkowski ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF & 4205ff5411efSMichal Swiatkowski ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA << 4206ff5411efSMichal Swiatkowski ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S); 4207ff5411efSMichal Swiatkowski } 4208ff5411efSMichal Swiatkowski 4209ff5411efSMichal Swiatkowski /** 4210ff5411efSMichal Swiatkowski * ice_vsi_ctx_set_allow_override - allow destination override on VSI 4211ff5411efSMichal Swiatkowski * @ctx: pointer to VSI ctx structure 4212ff5411efSMichal Swiatkowski */ 4213ff5411efSMichal Swiatkowski void ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx) 4214ff5411efSMichal Swiatkowski { 4215ff5411efSMichal Swiatkowski ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; 4216ff5411efSMichal Swiatkowski } 4217ff5411efSMichal Swiatkowski 4218ff5411efSMichal Swiatkowski /** 4219ff5411efSMichal Swiatkowski * ice_vsi_ctx_clear_allow_override - turn off destination override on VSI 4220ff5411efSMichal Swiatkowski * @ctx: pointer to VSI ctx structure 4221ff5411efSMichal Swiatkowski */ 4222ff5411efSMichal Swiatkowski void ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx) 4223ff5411efSMichal Swiatkowski { 4224ff5411efSMichal Swiatkowski ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD; 4225ff5411efSMichal Swiatkowski } 4226