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"
1045d3d428SAnirudh Venkataramanan 
1145d3d428SAnirudh Venkataramanan /**
12964674f1SAnirudh Venkataramanan  * ice_vsi_type_str - maps VSI type enum to string equivalents
136dae8aa0SBruce Allan  * @vsi_type: VSI type enum
14964674f1SAnirudh Venkataramanan  */
156dae8aa0SBruce Allan const char *ice_vsi_type_str(enum ice_vsi_type vsi_type)
16964674f1SAnirudh Venkataramanan {
176dae8aa0SBruce Allan 	switch (vsi_type) {
18964674f1SAnirudh Venkataramanan 	case ICE_VSI_PF:
19964674f1SAnirudh Venkataramanan 		return "ICE_VSI_PF";
20964674f1SAnirudh Venkataramanan 	case ICE_VSI_VF:
21964674f1SAnirudh Venkataramanan 		return "ICE_VSI_VF";
22148beb61SHenry Tieman 	case ICE_VSI_CTRL:
23148beb61SHenry Tieman 		return "ICE_VSI_CTRL";
24964674f1SAnirudh Venkataramanan 	case ICE_VSI_LB:
25964674f1SAnirudh Venkataramanan 		return "ICE_VSI_LB";
26964674f1SAnirudh Venkataramanan 	default:
27964674f1SAnirudh Venkataramanan 		return "unknown";
28964674f1SAnirudh Venkataramanan 	}
29964674f1SAnirudh Venkataramanan }
30964674f1SAnirudh Venkataramanan 
31964674f1SAnirudh Venkataramanan /**
3213a6233bSBrett Creeley  * ice_vsi_ctrl_all_rx_rings - Start or stop a VSI's Rx rings
33d02f734cSMaciej Fijalkowski  * @vsi: the VSI being configured
34d02f734cSMaciej Fijalkowski  * @ena: start or stop the Rx rings
3513a6233bSBrett Creeley  *
3613a6233bSBrett Creeley  * First enable/disable all of the Rx rings, flush any remaining writes, and
3713a6233bSBrett Creeley  * then verify that they have all been enabled/disabled successfully. This will
3813a6233bSBrett Creeley  * let all of the register writes complete when enabling/disabling the Rx rings
3913a6233bSBrett Creeley  * before waiting for the change in hardware to complete.
40d02f734cSMaciej Fijalkowski  */
4113a6233bSBrett Creeley static int ice_vsi_ctrl_all_rx_rings(struct ice_vsi *vsi, bool ena)
42d02f734cSMaciej Fijalkowski {
4388865fc4SKarol Kolacinski 	int ret = 0;
4488865fc4SKarol Kolacinski 	u16 i;
45d02f734cSMaciej Fijalkowski 
4613a6233bSBrett Creeley 	for (i = 0; i < vsi->num_rxq; i++)
4713a6233bSBrett Creeley 		ice_vsi_ctrl_one_rx_ring(vsi, ena, i, false);
4813a6233bSBrett Creeley 
4913a6233bSBrett Creeley 	ice_flush(&vsi->back->hw);
5013a6233bSBrett Creeley 
51d02f734cSMaciej Fijalkowski 	for (i = 0; i < vsi->num_rxq; i++) {
5213a6233bSBrett Creeley 		ret = ice_vsi_wait_one_rx_ring(vsi, ena, i);
53d02f734cSMaciej Fijalkowski 		if (ret)
54d02f734cSMaciej Fijalkowski 			break;
5572adf242SAnirudh Venkataramanan 	}
5672adf242SAnirudh Venkataramanan 
5772adf242SAnirudh Venkataramanan 	return ret;
5872adf242SAnirudh Venkataramanan }
5972adf242SAnirudh Venkataramanan 
6072adf242SAnirudh Venkataramanan /**
6128c2a645SAnirudh Venkataramanan  * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI
6228c2a645SAnirudh Venkataramanan  * @vsi: VSI pointer
6328c2a645SAnirudh Venkataramanan  *
6428c2a645SAnirudh Venkataramanan  * On error: returns error code (negative)
6528c2a645SAnirudh Venkataramanan  * On success: returns 0
6628c2a645SAnirudh Venkataramanan  */
67a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
6828c2a645SAnirudh Venkataramanan {
6928c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
704015d11eSBrett Creeley 	struct device *dev;
714015d11eSBrett Creeley 
724015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
7328c2a645SAnirudh Venkataramanan 
7428c2a645SAnirudh Venkataramanan 	/* allocate memory for both Tx and Rx ring pointers */
754015d11eSBrett Creeley 	vsi->tx_rings = devm_kcalloc(dev, vsi->alloc_txq,
76c6dfd690SBruce Allan 				     sizeof(*vsi->tx_rings), GFP_KERNEL);
7728c2a645SAnirudh Venkataramanan 	if (!vsi->tx_rings)
7878b5713aSAnirudh Venkataramanan 		return -ENOMEM;
7928c2a645SAnirudh Venkataramanan 
804015d11eSBrett Creeley 	vsi->rx_rings = devm_kcalloc(dev, vsi->alloc_rxq,
81c6dfd690SBruce Allan 				     sizeof(*vsi->rx_rings), GFP_KERNEL);
8228c2a645SAnirudh Venkataramanan 	if (!vsi->rx_rings)
8378b5713aSAnirudh Venkataramanan 		goto err_rings;
8478b5713aSAnirudh Venkataramanan 
85efc2214bSMaciej Fijalkowski 	/* XDP will have vsi->alloc_txq Tx queues as well, so double the size */
864015d11eSBrett Creeley 	vsi->txq_map = devm_kcalloc(dev, (2 * vsi->alloc_txq),
8778b5713aSAnirudh Venkataramanan 				    sizeof(*vsi->txq_map), GFP_KERNEL);
8878b5713aSAnirudh Venkataramanan 
8978b5713aSAnirudh Venkataramanan 	if (!vsi->txq_map)
9078b5713aSAnirudh Venkataramanan 		goto err_txq_map;
9178b5713aSAnirudh Venkataramanan 
924015d11eSBrett Creeley 	vsi->rxq_map = devm_kcalloc(dev, vsi->alloc_rxq,
9378b5713aSAnirudh Venkataramanan 				    sizeof(*vsi->rxq_map), GFP_KERNEL);
9478b5713aSAnirudh Venkataramanan 	if (!vsi->rxq_map)
9578b5713aSAnirudh Venkataramanan 		goto err_rxq_map;
9678b5713aSAnirudh Venkataramanan 
970e674aebSAnirudh Venkataramanan 	/* There is no need to allocate q_vectors for a loopback VSI. */
980e674aebSAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_LB)
990e674aebSAnirudh Venkataramanan 		return 0;
1000e674aebSAnirudh Venkataramanan 
10128c2a645SAnirudh Venkataramanan 	/* allocate memory for q_vector pointers */
1024015d11eSBrett Creeley 	vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors,
103a85a3847SBrett Creeley 				      sizeof(*vsi->q_vectors), GFP_KERNEL);
10428c2a645SAnirudh Venkataramanan 	if (!vsi->q_vectors)
10528c2a645SAnirudh Venkataramanan 		goto err_vectors;
10628c2a645SAnirudh Venkataramanan 
10728c2a645SAnirudh Venkataramanan 	return 0;
10828c2a645SAnirudh Venkataramanan 
10928c2a645SAnirudh Venkataramanan err_vectors:
1104015d11eSBrett Creeley 	devm_kfree(dev, vsi->rxq_map);
11178b5713aSAnirudh Venkataramanan err_rxq_map:
1124015d11eSBrett Creeley 	devm_kfree(dev, vsi->txq_map);
11378b5713aSAnirudh Venkataramanan err_txq_map:
1144015d11eSBrett Creeley 	devm_kfree(dev, vsi->rx_rings);
11578b5713aSAnirudh Venkataramanan err_rings:
1164015d11eSBrett Creeley 	devm_kfree(dev, vsi->tx_rings);
11728c2a645SAnirudh Venkataramanan 	return -ENOMEM;
11828c2a645SAnirudh Venkataramanan }
11928c2a645SAnirudh Venkataramanan 
12028c2a645SAnirudh Venkataramanan /**
121ad71b256SBrett Creeley  * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI
122ad71b256SBrett Creeley  * @vsi: the VSI being configured
123ad71b256SBrett Creeley  */
124ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
125ad71b256SBrett Creeley {
126ad71b256SBrett Creeley 	switch (vsi->type) {
127ad71b256SBrett Creeley 	case ICE_VSI_PF:
128148beb61SHenry Tieman 	case ICE_VSI_CTRL:
1290e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
130ad71b256SBrett Creeley 		vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC;
131ad71b256SBrett Creeley 		vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC;
132ad71b256SBrett Creeley 		break;
133ad71b256SBrett Creeley 	default:
13419cce2c6SAnirudh Venkataramanan 		dev_dbg(ice_pf_to_dev(vsi->back), "Not setting number of Tx/Rx descriptors for VSI type %d\n",
135ad71b256SBrett Creeley 			vsi->type);
136ad71b256SBrett Creeley 		break;
137ad71b256SBrett Creeley 	}
138ad71b256SBrett Creeley }
139ad71b256SBrett Creeley 
140ad71b256SBrett Creeley /**
141ad71b256SBrett Creeley  * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI
14228c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
143f9867df6SAnirudh Venkataramanan  * @vf_id: ID of the VF being configured
14428c2a645SAnirudh Venkataramanan  *
14528c2a645SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
14628c2a645SAnirudh Venkataramanan  */
1475743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
14828c2a645SAnirudh Venkataramanan {
14928c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
1505743020dSAkeem G Abodunrin 	struct ice_vf *vf = NULL;
1515743020dSAkeem G Abodunrin 
1525743020dSAkeem G Abodunrin 	if (vsi->type == ICE_VSI_VF)
1535743020dSAkeem G Abodunrin 		vsi->vf_id = vf_id;
1545743020dSAkeem G Abodunrin 
15528c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
15628c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
1578c243700SAnirudh Venkataramanan 		vsi->alloc_txq = min_t(int, ice_get_avail_txq_count(pf),
1588c243700SAnirudh Venkataramanan 				       num_online_cpus());
15987324e74SHenry Tieman 		if (vsi->req_txq) {
16087324e74SHenry Tieman 			vsi->alloc_txq = vsi->req_txq;
16187324e74SHenry Tieman 			vsi->num_txq = vsi->req_txq;
16287324e74SHenry Tieman 		}
1638c243700SAnirudh Venkataramanan 
1648c243700SAnirudh Venkataramanan 		pf->num_lan_tx = vsi->alloc_txq;
1658c243700SAnirudh Venkataramanan 
1668c243700SAnirudh Venkataramanan 		/* only 1 Rx queue unless RSS is enabled */
16787324e74SHenry Tieman 		if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
1688c243700SAnirudh Venkataramanan 			vsi->alloc_rxq = 1;
16987324e74SHenry Tieman 		} else {
1708c243700SAnirudh Venkataramanan 			vsi->alloc_rxq = min_t(int, ice_get_avail_rxq_count(pf),
1718c243700SAnirudh Venkataramanan 					       num_online_cpus());
17287324e74SHenry Tieman 			if (vsi->req_rxq) {
17387324e74SHenry Tieman 				vsi->alloc_rxq = vsi->req_rxq;
17487324e74SHenry Tieman 				vsi->num_rxq = vsi->req_rxq;
17587324e74SHenry Tieman 			}
17687324e74SHenry Tieman 		}
1778c243700SAnirudh Venkataramanan 
1788c243700SAnirudh Venkataramanan 		pf->num_lan_rx = vsi->alloc_rxq;
1798c243700SAnirudh Venkataramanan 
18034cdcb16SBrett Creeley 		vsi->num_q_vectors = max_t(int, vsi->alloc_rxq, vsi->alloc_txq);
18128c2a645SAnirudh Venkataramanan 		break;
1828ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
1835743020dSAkeem G Abodunrin 		vf = &pf->vf[vsi->vf_id];
1845743020dSAkeem G Abodunrin 		vsi->alloc_txq = vf->num_vf_qs;
1855743020dSAkeem G Abodunrin 		vsi->alloc_rxq = vf->num_vf_qs;
18646c276ceSBrett Creeley 		/* pf->num_msix_per_vf includes (VF miscellaneous vector +
1878ede0178SAnirudh Venkataramanan 		 * data queue interrupts). Since vsi->num_q_vectors is number
188047e52c0SAnirudh Venkataramanan 		 * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the
189047e52c0SAnirudh Venkataramanan 		 * original vector count
1908ede0178SAnirudh Venkataramanan 		 */
19146c276ceSBrett Creeley 		vsi->num_q_vectors = pf->num_msix_per_vf - ICE_NONQ_VECS_VF;
1928ede0178SAnirudh Venkataramanan 		break;
193148beb61SHenry Tieman 	case ICE_VSI_CTRL:
194148beb61SHenry Tieman 		vsi->alloc_txq = 1;
195148beb61SHenry Tieman 		vsi->alloc_rxq = 1;
196148beb61SHenry Tieman 		vsi->num_q_vectors = 1;
197148beb61SHenry Tieman 		break;
1980e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
1990e674aebSAnirudh Venkataramanan 		vsi->alloc_txq = 1;
2000e674aebSAnirudh Venkataramanan 		vsi->alloc_rxq = 1;
2010e674aebSAnirudh Venkataramanan 		break;
20228c2a645SAnirudh Venkataramanan 	default:
2034015d11eSBrett Creeley 		dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi->type);
20428c2a645SAnirudh Venkataramanan 		break;
20528c2a645SAnirudh Venkataramanan 	}
206ad71b256SBrett Creeley 
207ad71b256SBrett Creeley 	ice_vsi_set_num_desc(vsi);
20828c2a645SAnirudh Venkataramanan }
20928c2a645SAnirudh Venkataramanan 
21028c2a645SAnirudh Venkataramanan /**
21128c2a645SAnirudh Venkataramanan  * ice_get_free_slot - get the next non-NULL location index in array
21228c2a645SAnirudh Venkataramanan  * @array: array to search
21328c2a645SAnirudh Venkataramanan  * @size: size of the array
21428c2a645SAnirudh Venkataramanan  * @curr: last known occupied index to be used as a search hint
21528c2a645SAnirudh Venkataramanan  *
21628c2a645SAnirudh Venkataramanan  * void * is being used to keep the functionality generic. This lets us use this
21728c2a645SAnirudh Venkataramanan  * function on any array of pointers.
21828c2a645SAnirudh Venkataramanan  */
21937bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr)
22028c2a645SAnirudh Venkataramanan {
22128c2a645SAnirudh Venkataramanan 	int **tmp_array = (int **)array;
22228c2a645SAnirudh Venkataramanan 	int next;
22328c2a645SAnirudh Venkataramanan 
22428c2a645SAnirudh Venkataramanan 	if (curr < (size - 1) && !tmp_array[curr + 1]) {
22528c2a645SAnirudh Venkataramanan 		next = curr + 1;
22628c2a645SAnirudh Venkataramanan 	} else {
22728c2a645SAnirudh Venkataramanan 		int i = 0;
22828c2a645SAnirudh Venkataramanan 
22928c2a645SAnirudh Venkataramanan 		while ((i < size) && (tmp_array[i]))
23028c2a645SAnirudh Venkataramanan 			i++;
23128c2a645SAnirudh Venkataramanan 		if (i == size)
23228c2a645SAnirudh Venkataramanan 			next = ICE_NO_VSI;
23328c2a645SAnirudh Venkataramanan 		else
23428c2a645SAnirudh Venkataramanan 			next = i;
23528c2a645SAnirudh Venkataramanan 	}
23628c2a645SAnirudh Venkataramanan 	return next;
23728c2a645SAnirudh Venkataramanan }
23828c2a645SAnirudh Venkataramanan 
23928c2a645SAnirudh Venkataramanan /**
2405153a18eSAnirudh Venkataramanan  * ice_vsi_delete - delete a VSI from the switch
2415153a18eSAnirudh Venkataramanan  * @vsi: pointer to VSI being removed
2425153a18eSAnirudh Venkataramanan  */
2435153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi)
2445153a18eSAnirudh Venkataramanan {
2455153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
246198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
2475153a18eSAnirudh Venkataramanan 	enum ice_status status;
2485153a18eSAnirudh Venkataramanan 
2499efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
250198a666aSBruce Allan 	if (!ctxt)
251198a666aSBruce Allan 		return;
252198a666aSBruce Allan 
2538ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
254198a666aSBruce Allan 		ctxt->vf_num = vsi->vf_id;
255198a666aSBruce Allan 	ctxt->vsi_num = vsi->vsi_num;
2565153a18eSAnirudh Venkataramanan 
257198a666aSBruce Allan 	memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info));
2585153a18eSAnirudh Venkataramanan 
259198a666aSBruce Allan 	status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL);
2605153a18eSAnirudh Venkataramanan 	if (status)
2610fee3577SLihong Yang 		dev_err(ice_pf_to_dev(pf), "Failed to delete VSI %i in FW - error: %s\n",
2620fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
263198a666aSBruce Allan 
2649efe35d0STony Nguyen 	kfree(ctxt);
2655153a18eSAnirudh Venkataramanan }
2665153a18eSAnirudh Venkataramanan 
2675153a18eSAnirudh Venkataramanan /**
268a85a3847SBrett Creeley  * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI
26907309a0eSAnirudh Venkataramanan  * @vsi: pointer to VSI being cleared
27007309a0eSAnirudh Venkataramanan  */
271a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi)
27207309a0eSAnirudh Venkataramanan {
27307309a0eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2744015d11eSBrett Creeley 	struct device *dev;
2754015d11eSBrett Creeley 
2764015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
27707309a0eSAnirudh Venkataramanan 
27807309a0eSAnirudh Venkataramanan 	/* free the ring and vector containers */
279a85a3847SBrett Creeley 	if (vsi->q_vectors) {
2804015d11eSBrett Creeley 		devm_kfree(dev, vsi->q_vectors);
28107309a0eSAnirudh Venkataramanan 		vsi->q_vectors = NULL;
28207309a0eSAnirudh Venkataramanan 	}
28307309a0eSAnirudh Venkataramanan 	if (vsi->tx_rings) {
2844015d11eSBrett Creeley 		devm_kfree(dev, vsi->tx_rings);
28507309a0eSAnirudh Venkataramanan 		vsi->tx_rings = NULL;
28607309a0eSAnirudh Venkataramanan 	}
28707309a0eSAnirudh Venkataramanan 	if (vsi->rx_rings) {
2884015d11eSBrett Creeley 		devm_kfree(dev, vsi->rx_rings);
28907309a0eSAnirudh Venkataramanan 		vsi->rx_rings = NULL;
29007309a0eSAnirudh Venkataramanan 	}
29178b5713aSAnirudh Venkataramanan 	if (vsi->txq_map) {
2924015d11eSBrett Creeley 		devm_kfree(dev, vsi->txq_map);
29378b5713aSAnirudh Venkataramanan 		vsi->txq_map = NULL;
29478b5713aSAnirudh Venkataramanan 	}
29578b5713aSAnirudh Venkataramanan 	if (vsi->rxq_map) {
2964015d11eSBrett Creeley 		devm_kfree(dev, vsi->rxq_map);
29778b5713aSAnirudh Venkataramanan 		vsi->rxq_map = NULL;
29878b5713aSAnirudh Venkataramanan 	}
29907309a0eSAnirudh Venkataramanan }
30007309a0eSAnirudh Venkataramanan 
30107309a0eSAnirudh Venkataramanan /**
30207309a0eSAnirudh Venkataramanan  * ice_vsi_clear - clean up and deallocate the provided VSI
30307309a0eSAnirudh Venkataramanan  * @vsi: pointer to VSI being cleared
30407309a0eSAnirudh Venkataramanan  *
30507309a0eSAnirudh Venkataramanan  * This deallocates the VSI's queue resources, removes it from the PF's
30607309a0eSAnirudh Venkataramanan  * VSI array if necessary, and deallocates the VSI
30707309a0eSAnirudh Venkataramanan  *
30807309a0eSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
30907309a0eSAnirudh Venkataramanan  */
31007309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi)
31107309a0eSAnirudh Venkataramanan {
31207309a0eSAnirudh Venkataramanan 	struct ice_pf *pf = NULL;
3134015d11eSBrett Creeley 	struct device *dev;
31407309a0eSAnirudh Venkataramanan 
31507309a0eSAnirudh Venkataramanan 	if (!vsi)
31607309a0eSAnirudh Venkataramanan 		return 0;
31707309a0eSAnirudh Venkataramanan 
31807309a0eSAnirudh Venkataramanan 	if (!vsi->back)
31907309a0eSAnirudh Venkataramanan 		return -EINVAL;
32007309a0eSAnirudh Venkataramanan 
32107309a0eSAnirudh Venkataramanan 	pf = vsi->back;
3224015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
32307309a0eSAnirudh Venkataramanan 
32407309a0eSAnirudh Venkataramanan 	if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) {
3254015d11eSBrett Creeley 		dev_dbg(dev, "vsi does not exist at pf->vsi[%d]\n", vsi->idx);
32607309a0eSAnirudh Venkataramanan 		return -EINVAL;
32707309a0eSAnirudh Venkataramanan 	}
32807309a0eSAnirudh Venkataramanan 
32907309a0eSAnirudh Venkataramanan 	mutex_lock(&pf->sw_mutex);
33007309a0eSAnirudh Venkataramanan 	/* updates the PF for this cleared VSI */
33107309a0eSAnirudh Venkataramanan 
33207309a0eSAnirudh Venkataramanan 	pf->vsi[vsi->idx] = NULL;
333148beb61SHenry Tieman 	if (vsi->idx < pf->next_vsi && vsi->type != ICE_VSI_CTRL)
33407309a0eSAnirudh Venkataramanan 		pf->next_vsi = vsi->idx;
33507309a0eSAnirudh Venkataramanan 
336a85a3847SBrett Creeley 	ice_vsi_free_arrays(vsi);
33707309a0eSAnirudh Venkataramanan 	mutex_unlock(&pf->sw_mutex);
3384015d11eSBrett Creeley 	devm_kfree(dev, vsi);
33907309a0eSAnirudh Venkataramanan 
34007309a0eSAnirudh Venkataramanan 	return 0;
34107309a0eSAnirudh Venkataramanan }
34207309a0eSAnirudh Venkataramanan 
34307309a0eSAnirudh Venkataramanan /**
344148beb61SHenry Tieman  * ice_msix_clean_ctrl_vsi - MSIX mode interrupt handler for ctrl VSI
345148beb61SHenry Tieman  * @irq: interrupt number
346148beb61SHenry Tieman  * @data: pointer to a q_vector
347148beb61SHenry Tieman  */
348148beb61SHenry Tieman static irqreturn_t ice_msix_clean_ctrl_vsi(int __always_unused irq, void *data)
349148beb61SHenry Tieman {
350148beb61SHenry Tieman 	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
351148beb61SHenry Tieman 
352148beb61SHenry Tieman 	if (!q_vector->tx.ring)
353148beb61SHenry Tieman 		return IRQ_HANDLED;
354148beb61SHenry Tieman 
355148beb61SHenry Tieman #define FDIR_RX_DESC_CLEAN_BUDGET 64
356148beb61SHenry Tieman 	ice_clean_rx_irq(q_vector->rx.ring, FDIR_RX_DESC_CLEAN_BUDGET);
357148beb61SHenry Tieman 	ice_clean_ctrl_tx_irq(q_vector->tx.ring);
358148beb61SHenry Tieman 
359148beb61SHenry Tieman 	return IRQ_HANDLED;
360148beb61SHenry Tieman }
361148beb61SHenry Tieman 
362148beb61SHenry Tieman /**
3635153a18eSAnirudh Venkataramanan  * ice_msix_clean_rings - MSIX mode Interrupt Handler
3645153a18eSAnirudh Venkataramanan  * @irq: interrupt number
3655153a18eSAnirudh Venkataramanan  * @data: pointer to a q_vector
3665153a18eSAnirudh Venkataramanan  */
367f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
3685153a18eSAnirudh Venkataramanan {
3695153a18eSAnirudh Venkataramanan 	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
3705153a18eSAnirudh Venkataramanan 
3715153a18eSAnirudh Venkataramanan 	if (!q_vector->tx.ring && !q_vector->rx.ring)
3725153a18eSAnirudh Venkataramanan 		return IRQ_HANDLED;
3735153a18eSAnirudh Venkataramanan 
3745153a18eSAnirudh Venkataramanan 	napi_schedule(&q_vector->napi);
3755153a18eSAnirudh Venkataramanan 
3765153a18eSAnirudh Venkataramanan 	return IRQ_HANDLED;
3775153a18eSAnirudh Venkataramanan }
3785153a18eSAnirudh Venkataramanan 
3795153a18eSAnirudh Venkataramanan /**
38037bb8390SAnirudh Venkataramanan  * ice_vsi_alloc - Allocates the next available struct VSI in the PF
38137bb8390SAnirudh Venkataramanan  * @pf: board private structure
3826dae8aa0SBruce Allan  * @vsi_type: type of VSI
383f9867df6SAnirudh Venkataramanan  * @vf_id: ID of the VF being configured
38437bb8390SAnirudh Venkataramanan  *
38537bb8390SAnirudh Venkataramanan  * returns a pointer to a VSI on success, NULL on failure.
38637bb8390SAnirudh Venkataramanan  */
3875743020dSAkeem G Abodunrin static struct ice_vsi *
3886dae8aa0SBruce Allan ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type, u16 vf_id)
38937bb8390SAnirudh Venkataramanan {
3904015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
39137bb8390SAnirudh Venkataramanan 	struct ice_vsi *vsi = NULL;
39237bb8390SAnirudh Venkataramanan 
39337bb8390SAnirudh Venkataramanan 	/* Need to protect the allocation of the VSIs at the PF level */
39437bb8390SAnirudh Venkataramanan 	mutex_lock(&pf->sw_mutex);
39537bb8390SAnirudh Venkataramanan 
39637bb8390SAnirudh Venkataramanan 	/* If we have already allocated our maximum number of VSIs,
39737bb8390SAnirudh Venkataramanan 	 * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index
39837bb8390SAnirudh Venkataramanan 	 * is available to be populated
39937bb8390SAnirudh Venkataramanan 	 */
40037bb8390SAnirudh Venkataramanan 	if (pf->next_vsi == ICE_NO_VSI) {
4014015d11eSBrett Creeley 		dev_dbg(dev, "out of VSI slots!\n");
40237bb8390SAnirudh Venkataramanan 		goto unlock_pf;
40337bb8390SAnirudh Venkataramanan 	}
40437bb8390SAnirudh Venkataramanan 
4054015d11eSBrett Creeley 	vsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL);
40637bb8390SAnirudh Venkataramanan 	if (!vsi)
40737bb8390SAnirudh Venkataramanan 		goto unlock_pf;
40837bb8390SAnirudh Venkataramanan 
4096dae8aa0SBruce Allan 	vsi->type = vsi_type;
41037bb8390SAnirudh Venkataramanan 	vsi->back = pf;
41137bb8390SAnirudh Venkataramanan 	set_bit(__ICE_DOWN, vsi->state);
4129d56b7fdSJesse Brandeburg 
4136dae8aa0SBruce Allan 	if (vsi_type == ICE_VSI_VF)
4145743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, vf_id);
4155743020dSAkeem G Abodunrin 	else
4165743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
41737bb8390SAnirudh Venkataramanan 
41837bb8390SAnirudh Venkataramanan 	switch (vsi->type) {
41937bb8390SAnirudh Venkataramanan 	case ICE_VSI_PF:
420a85a3847SBrett Creeley 		if (ice_vsi_alloc_arrays(vsi))
42137bb8390SAnirudh Venkataramanan 			goto err_rings;
42237bb8390SAnirudh Venkataramanan 
42337bb8390SAnirudh Venkataramanan 		/* Setup default MSIX irq handler for VSI */
42437bb8390SAnirudh Venkataramanan 		vsi->irq_handler = ice_msix_clean_rings;
42537bb8390SAnirudh Venkataramanan 		break;
426148beb61SHenry Tieman 	case ICE_VSI_CTRL:
427148beb61SHenry Tieman 		if (ice_vsi_alloc_arrays(vsi))
428148beb61SHenry Tieman 			goto err_rings;
429148beb61SHenry Tieman 
430148beb61SHenry Tieman 		/* Setup ctrl VSI MSIX irq handler */
431148beb61SHenry Tieman 		vsi->irq_handler = ice_msix_clean_ctrl_vsi;
432148beb61SHenry Tieman 		break;
4338ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
434a85a3847SBrett Creeley 		if (ice_vsi_alloc_arrays(vsi))
4358ede0178SAnirudh Venkataramanan 			goto err_rings;
4368ede0178SAnirudh Venkataramanan 		break;
4370e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
4380e674aebSAnirudh Venkataramanan 		if (ice_vsi_alloc_arrays(vsi))
4390e674aebSAnirudh Venkataramanan 			goto err_rings;
4400e674aebSAnirudh Venkataramanan 		break;
44137bb8390SAnirudh Venkataramanan 	default:
4424015d11eSBrett Creeley 		dev_warn(dev, "Unknown VSI type %d\n", vsi->type);
44337bb8390SAnirudh Venkataramanan 		goto unlock_pf;
44437bb8390SAnirudh Venkataramanan 	}
44537bb8390SAnirudh Venkataramanan 
446148beb61SHenry Tieman 	if (vsi->type == ICE_VSI_CTRL) {
447148beb61SHenry Tieman 		/* Use the last VSI slot as the index for the control VSI */
448148beb61SHenry Tieman 		vsi->idx = pf->num_alloc_vsi - 1;
449148beb61SHenry Tieman 		pf->ctrl_vsi_idx = vsi->idx;
450148beb61SHenry Tieman 		pf->vsi[vsi->idx] = vsi;
451148beb61SHenry Tieman 	} else {
452148beb61SHenry Tieman 		/* fill slot and make note of the index */
453148beb61SHenry Tieman 		vsi->idx = pf->next_vsi;
45437bb8390SAnirudh Venkataramanan 		pf->vsi[pf->next_vsi] = vsi;
45537bb8390SAnirudh Venkataramanan 
45637bb8390SAnirudh Venkataramanan 		/* prepare pf->next_vsi for next use */
45737bb8390SAnirudh Venkataramanan 		pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi,
45837bb8390SAnirudh Venkataramanan 						 pf->next_vsi);
459148beb61SHenry Tieman 	}
46037bb8390SAnirudh Venkataramanan 	goto unlock_pf;
46137bb8390SAnirudh Venkataramanan 
46237bb8390SAnirudh Venkataramanan err_rings:
4634015d11eSBrett Creeley 	devm_kfree(dev, vsi);
46437bb8390SAnirudh Venkataramanan 	vsi = NULL;
46537bb8390SAnirudh Venkataramanan unlock_pf:
46637bb8390SAnirudh Venkataramanan 	mutex_unlock(&pf->sw_mutex);
46737bb8390SAnirudh Venkataramanan 	return vsi;
46837bb8390SAnirudh Venkataramanan }
46937bb8390SAnirudh Venkataramanan 
47037bb8390SAnirudh Venkataramanan /**
471148beb61SHenry Tieman  * ice_alloc_fd_res - Allocate FD resource for a VSI
472148beb61SHenry Tieman  * @vsi: pointer to the ice_vsi
473148beb61SHenry Tieman  *
474148beb61SHenry Tieman  * This allocates the FD resources
475148beb61SHenry Tieman  *
476148beb61SHenry Tieman  * Returns 0 on success, -EPERM on no-op or -EIO on failure
477148beb61SHenry Tieman  */
478148beb61SHenry Tieman static int ice_alloc_fd_res(struct ice_vsi *vsi)
479148beb61SHenry Tieman {
480148beb61SHenry Tieman 	struct ice_pf *pf = vsi->back;
481148beb61SHenry Tieman 	u32 g_val, b_val;
482148beb61SHenry Tieman 
483148beb61SHenry Tieman 	/* Flow Director filters are only allocated/assigned to the PF VSI which
484148beb61SHenry Tieman 	 * passes the traffic. The CTRL VSI is only used to add/delete filters
485148beb61SHenry Tieman 	 * so we don't allocate resources to it
486148beb61SHenry Tieman 	 */
487148beb61SHenry Tieman 
488148beb61SHenry Tieman 	/* FD filters from guaranteed pool per VSI */
489148beb61SHenry Tieman 	g_val = pf->hw.func_caps.fd_fltr_guar;
490148beb61SHenry Tieman 	if (!g_val)
491148beb61SHenry Tieman 		return -EPERM;
492148beb61SHenry Tieman 
493148beb61SHenry Tieman 	/* FD filters from best effort pool */
494148beb61SHenry Tieman 	b_val = pf->hw.func_caps.fd_fltr_best_effort;
495148beb61SHenry Tieman 	if (!b_val)
496148beb61SHenry Tieman 		return -EPERM;
497148beb61SHenry Tieman 
498148beb61SHenry Tieman 	if (vsi->type != ICE_VSI_PF)
499148beb61SHenry Tieman 		return -EPERM;
500148beb61SHenry Tieman 
501148beb61SHenry Tieman 	if (!test_bit(ICE_FLAG_FD_ENA, pf->flags))
502148beb61SHenry Tieman 		return -EPERM;
503148beb61SHenry Tieman 
504148beb61SHenry Tieman 	vsi->num_gfltr = g_val / pf->num_alloc_vsi;
505148beb61SHenry Tieman 
506148beb61SHenry Tieman 	/* each VSI gets same "best_effort" quota */
507148beb61SHenry Tieman 	vsi->num_bfltr = b_val;
508148beb61SHenry Tieman 
509148beb61SHenry Tieman 	return 0;
510148beb61SHenry Tieman }
511148beb61SHenry Tieman 
512148beb61SHenry Tieman /**
513df0f8479SAnirudh Venkataramanan  * ice_vsi_get_qs - Assign queues from PF to VSI
514df0f8479SAnirudh Venkataramanan  * @vsi: the VSI to assign queues to
515df0f8479SAnirudh Venkataramanan  *
516df0f8479SAnirudh Venkataramanan  * Returns 0 on success and a negative value on error
517df0f8479SAnirudh Venkataramanan  */
51837bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi)
519df0f8479SAnirudh Venkataramanan {
52003f7a986SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
52103f7a986SAnirudh Venkataramanan 	struct ice_qs_cfg tx_qs_cfg = {
52203f7a986SAnirudh Venkataramanan 		.qs_mutex = &pf->avail_q_mutex,
52303f7a986SAnirudh Venkataramanan 		.pf_map = pf->avail_txqs,
52478b5713aSAnirudh Venkataramanan 		.pf_map_size = pf->max_pf_txqs,
52503f7a986SAnirudh Venkataramanan 		.q_count = vsi->alloc_txq,
52603f7a986SAnirudh Venkataramanan 		.scatter_count = ICE_MAX_SCATTER_TXQS,
52703f7a986SAnirudh Venkataramanan 		.vsi_map = vsi->txq_map,
52803f7a986SAnirudh Venkataramanan 		.vsi_map_offset = 0,
52939066dc5SBrett Creeley 		.mapping_mode = ICE_VSI_MAP_CONTIG
53003f7a986SAnirudh Venkataramanan 	};
53103f7a986SAnirudh Venkataramanan 	struct ice_qs_cfg rx_qs_cfg = {
53203f7a986SAnirudh Venkataramanan 		.qs_mutex = &pf->avail_q_mutex,
53303f7a986SAnirudh Venkataramanan 		.pf_map = pf->avail_rxqs,
53478b5713aSAnirudh Venkataramanan 		.pf_map_size = pf->max_pf_rxqs,
53503f7a986SAnirudh Venkataramanan 		.q_count = vsi->alloc_rxq,
53603f7a986SAnirudh Venkataramanan 		.scatter_count = ICE_MAX_SCATTER_RXQS,
53703f7a986SAnirudh Venkataramanan 		.vsi_map = vsi->rxq_map,
53803f7a986SAnirudh Venkataramanan 		.vsi_map_offset = 0,
53939066dc5SBrett Creeley 		.mapping_mode = ICE_VSI_MAP_CONTIG
54003f7a986SAnirudh Venkataramanan 	};
54139066dc5SBrett Creeley 	int ret;
542df0f8479SAnirudh Venkataramanan 
54303f7a986SAnirudh Venkataramanan 	ret = __ice_vsi_get_qs(&tx_qs_cfg);
54439066dc5SBrett Creeley 	if (ret)
545df0f8479SAnirudh Venkataramanan 		return ret;
54639066dc5SBrett Creeley 	vsi->tx_mapping_mode = tx_qs_cfg.mapping_mode;
54739066dc5SBrett Creeley 
54839066dc5SBrett Creeley 	ret = __ice_vsi_get_qs(&rx_qs_cfg);
54939066dc5SBrett Creeley 	if (ret)
55039066dc5SBrett Creeley 		return ret;
55139066dc5SBrett Creeley 	vsi->rx_mapping_mode = rx_qs_cfg.mapping_mode;
55239066dc5SBrett Creeley 
55339066dc5SBrett Creeley 	return 0;
554df0f8479SAnirudh Venkataramanan }
555df0f8479SAnirudh Venkataramanan 
556df0f8479SAnirudh Venkataramanan /**
5575153a18eSAnirudh Venkataramanan  * ice_vsi_put_qs - Release queues from VSI to PF
5585153a18eSAnirudh Venkataramanan  * @vsi: the VSI that is going to release queues
5595153a18eSAnirudh Venkataramanan  */
5605153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi)
5615153a18eSAnirudh Venkataramanan {
5625153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
5635153a18eSAnirudh Venkataramanan 	int i;
5645153a18eSAnirudh Venkataramanan 
5655153a18eSAnirudh Venkataramanan 	mutex_lock(&pf->avail_q_mutex);
5665153a18eSAnirudh Venkataramanan 
5675153a18eSAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_txq; i++) {
5685153a18eSAnirudh Venkataramanan 		clear_bit(vsi->txq_map[i], pf->avail_txqs);
5695153a18eSAnirudh Venkataramanan 		vsi->txq_map[i] = ICE_INVAL_Q_INDEX;
5705153a18eSAnirudh Venkataramanan 	}
5715153a18eSAnirudh Venkataramanan 
5725153a18eSAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_rxq; i++) {
5735153a18eSAnirudh Venkataramanan 		clear_bit(vsi->rxq_map[i], pf->avail_rxqs);
5745153a18eSAnirudh Venkataramanan 		vsi->rxq_map[i] = ICE_INVAL_Q_INDEX;
5755153a18eSAnirudh Venkataramanan 	}
5765153a18eSAnirudh Venkataramanan 
5775153a18eSAnirudh Venkataramanan 	mutex_unlock(&pf->avail_q_mutex);
5785153a18eSAnirudh Venkataramanan }
5795153a18eSAnirudh Venkataramanan 
5805153a18eSAnirudh Venkataramanan /**
581462acf6aSTony Nguyen  * ice_is_safe_mode
582462acf6aSTony Nguyen  * @pf: pointer to the PF struct
583462acf6aSTony Nguyen  *
584462acf6aSTony Nguyen  * returns true if driver is in safe mode, false otherwise
585462acf6aSTony Nguyen  */
586462acf6aSTony Nguyen bool ice_is_safe_mode(struct ice_pf *pf)
587462acf6aSTony Nguyen {
588462acf6aSTony Nguyen 	return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
589462acf6aSTony Nguyen }
590462acf6aSTony Nguyen 
591462acf6aSTony Nguyen /**
5922c61054cSTony Nguyen  * ice_vsi_clean_rss_flow_fld - Delete RSS configuration
5932c61054cSTony Nguyen  * @vsi: the VSI being cleaned up
5942c61054cSTony Nguyen  *
5952c61054cSTony Nguyen  * This function deletes RSS input set for all flows that were configured
5962c61054cSTony Nguyen  * for this VSI
5972c61054cSTony Nguyen  */
5982c61054cSTony Nguyen static void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi)
5992c61054cSTony Nguyen {
6002c61054cSTony Nguyen 	struct ice_pf *pf = vsi->back;
6012c61054cSTony Nguyen 	enum ice_status status;
6022c61054cSTony Nguyen 
6032c61054cSTony Nguyen 	if (ice_is_safe_mode(pf))
6042c61054cSTony Nguyen 		return;
6052c61054cSTony Nguyen 
6062c61054cSTony Nguyen 	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
6072c61054cSTony Nguyen 	if (status)
6080fee3577SLihong Yang 		dev_dbg(ice_pf_to_dev(pf), "ice_rem_vsi_rss_cfg failed for vsi = %d, error = %s\n",
6090fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
6102c61054cSTony Nguyen }
6112c61054cSTony Nguyen 
6122c61054cSTony Nguyen /**
6132c61054cSTony Nguyen  * ice_rss_clean - Delete RSS related VSI structures and configuration
614df0f8479SAnirudh Venkataramanan  * @vsi: the VSI being removed
615df0f8479SAnirudh Venkataramanan  */
616df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi)
617df0f8479SAnirudh Venkataramanan {
6184015d11eSBrett Creeley 	struct ice_pf *pf = vsi->back;
6194015d11eSBrett Creeley 	struct device *dev;
620df0f8479SAnirudh Venkataramanan 
6214015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
622df0f8479SAnirudh Venkataramanan 
623df0f8479SAnirudh Venkataramanan 	if (vsi->rss_hkey_user)
6244015d11eSBrett Creeley 		devm_kfree(dev, vsi->rss_hkey_user);
625df0f8479SAnirudh Venkataramanan 	if (vsi->rss_lut_user)
6264015d11eSBrett Creeley 		devm_kfree(dev, vsi->rss_lut_user);
6272c61054cSTony Nguyen 
6282c61054cSTony Nguyen 	ice_vsi_clean_rss_flow_fld(vsi);
6292c61054cSTony Nguyen 	/* remove RSS replay list */
6302c61054cSTony Nguyen 	if (!ice_is_safe_mode(pf))
6312c61054cSTony Nguyen 		ice_rem_vsi_rss_list(&pf->hw, vsi->idx);
632df0f8479SAnirudh Venkataramanan }
633df0f8479SAnirudh Venkataramanan 
634df0f8479SAnirudh Venkataramanan /**
63528c2a645SAnirudh Venkataramanan  * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type
63628c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
63728c2a645SAnirudh Venkataramanan  */
63837bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
63928c2a645SAnirudh Venkataramanan {
64028c2a645SAnirudh Venkataramanan 	struct ice_hw_common_caps *cap;
64128c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
64228c2a645SAnirudh Venkataramanan 
64328c2a645SAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
64428c2a645SAnirudh Venkataramanan 		vsi->rss_size = 1;
64528c2a645SAnirudh Venkataramanan 		return;
64628c2a645SAnirudh Venkataramanan 	}
64728c2a645SAnirudh Venkataramanan 
64828c2a645SAnirudh Venkataramanan 	cap = &pf->hw.func_caps.common_cap;
64928c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
65028c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
65128c2a645SAnirudh Venkataramanan 		/* PF VSI will inherit RSS instance of PF */
65288865fc4SKarol Kolacinski 		vsi->rss_table_size = (u16)cap->rss_table_size;
65388865fc4SKarol Kolacinski 		vsi->rss_size = min_t(u16, num_online_cpus(),
65428c2a645SAnirudh Venkataramanan 				      BIT(cap->rss_table_entry_width));
65528c2a645SAnirudh Venkataramanan 		vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF;
65628c2a645SAnirudh Venkataramanan 		break;
6578ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
6580ca469fbSMitch Williams 		/* VF VSI will get a small RSS table.
6590ca469fbSMitch Williams 		 * For VSI_LUT, LUT size should be set to 64 bytes.
6608ede0178SAnirudh Venkataramanan 		 */
6618ede0178SAnirudh Venkataramanan 		vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE;
6620ca469fbSMitch Williams 		vsi->rss_size = ICE_MAX_RSS_QS_PER_VF;
6638ede0178SAnirudh Venkataramanan 		vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI;
6648ede0178SAnirudh Venkataramanan 		break;
6650e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
6660e674aebSAnirudh Venkataramanan 		break;
66728c2a645SAnirudh Venkataramanan 	default:
668148beb61SHenry Tieman 		dev_dbg(ice_pf_to_dev(pf), "Unsupported VSI type %s\n",
669148beb61SHenry Tieman 			ice_vsi_type_str(vsi->type));
67028c2a645SAnirudh Venkataramanan 		break;
67128c2a645SAnirudh Venkataramanan 	}
67228c2a645SAnirudh Venkataramanan }
67328c2a645SAnirudh Venkataramanan 
67428c2a645SAnirudh Venkataramanan /**
67528c2a645SAnirudh Venkataramanan  * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
67628c2a645SAnirudh Venkataramanan  * @ctxt: the VSI context being set
67728c2a645SAnirudh Venkataramanan  *
67828c2a645SAnirudh Venkataramanan  * This initializes a default VSI context for all sections except the Queues.
67928c2a645SAnirudh Venkataramanan  */
68028c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
68128c2a645SAnirudh Venkataramanan {
68228c2a645SAnirudh Venkataramanan 	u32 table = 0;
68328c2a645SAnirudh Venkataramanan 
68428c2a645SAnirudh Venkataramanan 	memset(&ctxt->info, 0, sizeof(ctxt->info));
68528c2a645SAnirudh Venkataramanan 	/* VSI's should be allocated from shared pool */
68628c2a645SAnirudh Venkataramanan 	ctxt->alloc_from_pool = true;
68728c2a645SAnirudh Venkataramanan 	/* Src pruning enabled by default */
68828c2a645SAnirudh Venkataramanan 	ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
68928c2a645SAnirudh Venkataramanan 	/* Traffic from VSI can be sent to LAN */
69028c2a645SAnirudh Venkataramanan 	ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
69128c2a645SAnirudh Venkataramanan 	/* By default bits 3 and 4 in vlan_flags are 0's which results in legacy
69228c2a645SAnirudh Venkataramanan 	 * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all
69328c2a645SAnirudh Venkataramanan 	 * packets untagged/tagged.
69428c2a645SAnirudh Venkataramanan 	 */
69528c2a645SAnirudh Venkataramanan 	ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL &
69628c2a645SAnirudh Venkataramanan 				  ICE_AQ_VSI_VLAN_MODE_M) >>
69728c2a645SAnirudh Venkataramanan 				 ICE_AQ_VSI_VLAN_MODE_S);
69828c2a645SAnirudh Venkataramanan 	/* Have 1:1 UP mapping for both ingress/egress tables */
69928c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(0, 0);
70028c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(1, 1);
70128c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(2, 2);
70228c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(3, 3);
70328c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(4, 4);
70428c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(5, 5);
70528c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(6, 6);
70628c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(7, 7);
70728c2a645SAnirudh Venkataramanan 	ctxt->info.ingress_table = cpu_to_le32(table);
70828c2a645SAnirudh Venkataramanan 	ctxt->info.egress_table = cpu_to_le32(table);
70928c2a645SAnirudh Venkataramanan 	/* Have 1:1 UP mapping for outer to inner UP table */
71028c2a645SAnirudh Venkataramanan 	ctxt->info.outer_up_table = cpu_to_le32(table);
71128c2a645SAnirudh Venkataramanan 	/* No Outer tag support outer_tag_flags remains to zero */
71228c2a645SAnirudh Venkataramanan }
71328c2a645SAnirudh Venkataramanan 
71428c2a645SAnirudh Venkataramanan /**
71528c2a645SAnirudh Venkataramanan  * ice_vsi_setup_q_map - Setup a VSI queue map
71628c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
71728c2a645SAnirudh Venkataramanan  * @ctxt: VSI context structure
71828c2a645SAnirudh Venkataramanan  */
71928c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
72028c2a645SAnirudh Venkataramanan {
721c5a2a4a3SUsha Ketineni 	u16 offset = 0, qmap = 0, tx_count = 0;
72228c2a645SAnirudh Venkataramanan 	u16 qcount_tx = vsi->alloc_txq;
72328c2a645SAnirudh Venkataramanan 	u16 qcount_rx = vsi->alloc_rxq;
724c5a2a4a3SUsha Ketineni 	u16 tx_numq_tc, rx_numq_tc;
725c5a2a4a3SUsha Ketineni 	u16 pow = 0, max_rss = 0;
72628c2a645SAnirudh Venkataramanan 	bool ena_tc0 = false;
727c5a2a4a3SUsha Ketineni 	u8 netdev_tc = 0;
72828c2a645SAnirudh Venkataramanan 	int i;
72928c2a645SAnirudh Venkataramanan 
73028c2a645SAnirudh Venkataramanan 	/* at least TC0 should be enabled by default */
73128c2a645SAnirudh Venkataramanan 	if (vsi->tc_cfg.numtc) {
73228c2a645SAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(0)))
73328c2a645SAnirudh Venkataramanan 			ena_tc0 = true;
73428c2a645SAnirudh Venkataramanan 	} else {
73528c2a645SAnirudh Venkataramanan 		ena_tc0 = true;
73628c2a645SAnirudh Venkataramanan 	}
73728c2a645SAnirudh Venkataramanan 
73828c2a645SAnirudh Venkataramanan 	if (ena_tc0) {
73928c2a645SAnirudh Venkataramanan 		vsi->tc_cfg.numtc++;
74028c2a645SAnirudh Venkataramanan 		vsi->tc_cfg.ena_tc |= 1;
74128c2a645SAnirudh Venkataramanan 	}
74228c2a645SAnirudh Venkataramanan 
743c5a2a4a3SUsha Ketineni 	rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc;
744c5a2a4a3SUsha Ketineni 	if (!rx_numq_tc)
745c5a2a4a3SUsha Ketineni 		rx_numq_tc = 1;
746c5a2a4a3SUsha Ketineni 	tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc;
747c5a2a4a3SUsha Ketineni 	if (!tx_numq_tc)
748c5a2a4a3SUsha Ketineni 		tx_numq_tc = 1;
74928c2a645SAnirudh Venkataramanan 
75028c2a645SAnirudh Venkataramanan 	/* TC mapping is a function of the number of Rx queues assigned to the
75128c2a645SAnirudh Venkataramanan 	 * VSI for each traffic class and the offset of these queues.
75228c2a645SAnirudh Venkataramanan 	 * The first 10 bits are for queue offset for TC0, next 4 bits for no:of
75328c2a645SAnirudh Venkataramanan 	 * queues allocated to TC0. No:of queues is a power-of-2.
75428c2a645SAnirudh Venkataramanan 	 *
75528c2a645SAnirudh Venkataramanan 	 * If TC is not enabled, the queue offset is set to 0, and allocate one
75628c2a645SAnirudh Venkataramanan 	 * queue, this way, traffic for the given TC will be sent to the default
75728c2a645SAnirudh Venkataramanan 	 * queue.
75828c2a645SAnirudh Venkataramanan 	 *
75928c2a645SAnirudh Venkataramanan 	 * Setup number and offset of Rx queues for all TCs for the VSI
76028c2a645SAnirudh Venkataramanan 	 */
76128c2a645SAnirudh Venkataramanan 
762c5a2a4a3SUsha Ketineni 	qcount_rx = rx_numq_tc;
763c5a2a4a3SUsha Ketineni 
76428c2a645SAnirudh Venkataramanan 	/* qcount will change if RSS is enabled */
76528c2a645SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) {
7668ede0178SAnirudh Venkataramanan 		if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) {
76728c2a645SAnirudh Venkataramanan 			if (vsi->type == ICE_VSI_PF)
76828c2a645SAnirudh Venkataramanan 				max_rss = ICE_MAX_LG_RSS_QS;
76928c2a645SAnirudh Venkataramanan 			else
7700ca469fbSMitch Williams 				max_rss = ICE_MAX_RSS_QS_PER_VF;
77188865fc4SKarol Kolacinski 			qcount_rx = min_t(u16, rx_numq_tc, max_rss);
77287324e74SHenry Tieman 			if (!vsi->req_rxq)
77388865fc4SKarol Kolacinski 				qcount_rx = min_t(u16, qcount_rx,
77487324e74SHenry Tieman 						  vsi->rss_size);
7758ede0178SAnirudh Venkataramanan 		}
77628c2a645SAnirudh Venkataramanan 	}
77728c2a645SAnirudh Venkataramanan 
77828c2a645SAnirudh Venkataramanan 	/* find the (rounded up) power-of-2 of qcount */
77988865fc4SKarol Kolacinski 	pow = (u16)order_base_2(qcount_rx);
78028c2a645SAnirudh Venkataramanan 
7812bdc97beSBruce Allan 	ice_for_each_traffic_class(i) {
78228c2a645SAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
78328c2a645SAnirudh Venkataramanan 			/* TC is not enabled */
78428c2a645SAnirudh Venkataramanan 			vsi->tc_cfg.tc_info[i].qoffset = 0;
785c5a2a4a3SUsha Ketineni 			vsi->tc_cfg.tc_info[i].qcount_rx = 1;
786c5a2a4a3SUsha Ketineni 			vsi->tc_cfg.tc_info[i].qcount_tx = 1;
787c5a2a4a3SUsha Ketineni 			vsi->tc_cfg.tc_info[i].netdev_tc = 0;
78828c2a645SAnirudh Venkataramanan 			ctxt->info.tc_mapping[i] = 0;
78928c2a645SAnirudh Venkataramanan 			continue;
79028c2a645SAnirudh Venkataramanan 		}
79128c2a645SAnirudh Venkataramanan 
79228c2a645SAnirudh Venkataramanan 		/* TC is enabled */
79328c2a645SAnirudh Venkataramanan 		vsi->tc_cfg.tc_info[i].qoffset = offset;
794c5a2a4a3SUsha Ketineni 		vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx;
795c5a2a4a3SUsha Ketineni 		vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc;
796c5a2a4a3SUsha Ketineni 		vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++;
79728c2a645SAnirudh Venkataramanan 
79828c2a645SAnirudh Venkataramanan 		qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
79928c2a645SAnirudh Venkataramanan 			ICE_AQ_VSI_TC_Q_OFFSET_M) |
80028c2a645SAnirudh Venkataramanan 			((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
80128c2a645SAnirudh Venkataramanan 			 ICE_AQ_VSI_TC_Q_NUM_M);
802c5a2a4a3SUsha Ketineni 		offset += qcount_rx;
803c5a2a4a3SUsha Ketineni 		tx_count += tx_numq_tc;
80428c2a645SAnirudh Venkataramanan 		ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
80528c2a645SAnirudh Venkataramanan 	}
80660dcc39eSKiran Patil 
80760dcc39eSKiran Patil 	/* if offset is non-zero, means it is calculated correctly based on
80860dcc39eSKiran Patil 	 * enabled TCs for a given VSI otherwise qcount_rx will always
80960dcc39eSKiran Patil 	 * be correct and non-zero because it is based off - VSI's
81060dcc39eSKiran Patil 	 * allocated Rx queues which is at least 1 (hence qcount_tx will be
81160dcc39eSKiran Patil 	 * at least 1)
81260dcc39eSKiran Patil 	 */
81360dcc39eSKiran Patil 	if (offset)
81428c2a645SAnirudh Venkataramanan 		vsi->num_rxq = offset;
81560dcc39eSKiran Patil 	else
81660dcc39eSKiran Patil 		vsi->num_rxq = qcount_rx;
81760dcc39eSKiran Patil 
818c5a2a4a3SUsha Ketineni 	vsi->num_txq = tx_count;
81928c2a645SAnirudh Venkataramanan 
8208ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
8219a946843SAnirudh 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");
8228ede0178SAnirudh Venkataramanan 		/* since there is a chance that num_rxq could have been changed
8238ede0178SAnirudh Venkataramanan 		 * in the above for loop, make num_txq equal to num_rxq.
8248ede0178SAnirudh Venkataramanan 		 */
8258ede0178SAnirudh Venkataramanan 		vsi->num_txq = vsi->num_rxq;
8268ede0178SAnirudh Venkataramanan 	}
8278ede0178SAnirudh Venkataramanan 
82828c2a645SAnirudh Venkataramanan 	/* Rx queue mapping */
82928c2a645SAnirudh Venkataramanan 	ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
83028c2a645SAnirudh Venkataramanan 	/* q_mapping buffer holds the info for the first queue allocated for
83128c2a645SAnirudh Venkataramanan 	 * this VSI in the PF space and also the number of queues associated
83228c2a645SAnirudh Venkataramanan 	 * with this VSI.
83328c2a645SAnirudh Venkataramanan 	 */
83428c2a645SAnirudh Venkataramanan 	ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
83528c2a645SAnirudh Venkataramanan 	ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
83628c2a645SAnirudh Venkataramanan }
83728c2a645SAnirudh Venkataramanan 
83828c2a645SAnirudh Venkataramanan /**
839148beb61SHenry Tieman  * ice_set_fd_vsi_ctx - Set FD VSI context before adding a VSI
840148beb61SHenry Tieman  * @ctxt: the VSI context being set
841148beb61SHenry Tieman  * @vsi: the VSI being configured
842148beb61SHenry Tieman  */
843148beb61SHenry Tieman static void ice_set_fd_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
844148beb61SHenry Tieman {
845148beb61SHenry Tieman 	u8 dflt_q_group, dflt_q_prio;
846148beb61SHenry Tieman 	u16 dflt_q, report_q, val;
847148beb61SHenry Tieman 
848148beb61SHenry Tieman 	if (vsi->type != ICE_VSI_PF && vsi->type != ICE_VSI_CTRL)
849148beb61SHenry Tieman 		return;
850148beb61SHenry Tieman 
851148beb61SHenry Tieman 	val = ICE_AQ_VSI_PROP_FLOW_DIR_VALID;
852148beb61SHenry Tieman 	ctxt->info.valid_sections |= cpu_to_le16(val);
853148beb61SHenry Tieman 	dflt_q = 0;
854148beb61SHenry Tieman 	dflt_q_group = 0;
855148beb61SHenry Tieman 	report_q = 0;
856148beb61SHenry Tieman 	dflt_q_prio = 0;
857148beb61SHenry Tieman 
858148beb61SHenry Tieman 	/* enable flow director filtering/programming */
859148beb61SHenry Tieman 	val = ICE_AQ_VSI_FD_ENABLE | ICE_AQ_VSI_FD_PROG_ENABLE;
860148beb61SHenry Tieman 	ctxt->info.fd_options = cpu_to_le16(val);
861148beb61SHenry Tieman 	/* max of allocated flow director filters */
862148beb61SHenry Tieman 	ctxt->info.max_fd_fltr_dedicated =
863148beb61SHenry Tieman 			cpu_to_le16(vsi->num_gfltr);
864148beb61SHenry Tieman 	/* max of shared flow director filters any VSI may program */
865148beb61SHenry Tieman 	ctxt->info.max_fd_fltr_shared =
866148beb61SHenry Tieman 			cpu_to_le16(vsi->num_bfltr);
867148beb61SHenry Tieman 	/* default queue index within the VSI of the default FD */
868148beb61SHenry Tieman 	val = ((dflt_q << ICE_AQ_VSI_FD_DEF_Q_S) &
869148beb61SHenry Tieman 	       ICE_AQ_VSI_FD_DEF_Q_M);
870148beb61SHenry Tieman 	/* target queue or queue group to the FD filter */
871148beb61SHenry Tieman 	val |= ((dflt_q_group << ICE_AQ_VSI_FD_DEF_GRP_S) &
872148beb61SHenry Tieman 		ICE_AQ_VSI_FD_DEF_GRP_M);
873148beb61SHenry Tieman 	ctxt->info.fd_def_q = cpu_to_le16(val);
874148beb61SHenry Tieman 	/* queue index on which FD filter completion is reported */
875148beb61SHenry Tieman 	val = ((report_q << ICE_AQ_VSI_FD_REPORT_Q_S) &
876148beb61SHenry Tieman 	       ICE_AQ_VSI_FD_REPORT_Q_M);
877148beb61SHenry Tieman 	/* priority of the default qindex action */
878148beb61SHenry Tieman 	val |= ((dflt_q_prio << ICE_AQ_VSI_FD_DEF_PRIORITY_S) &
879148beb61SHenry Tieman 		ICE_AQ_VSI_FD_DEF_PRIORITY_M);
880148beb61SHenry Tieman 	ctxt->info.fd_report_opt = cpu_to_le16(val);
881148beb61SHenry Tieman }
882148beb61SHenry Tieman 
883148beb61SHenry Tieman /**
88428c2a645SAnirudh Venkataramanan  * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI
88528c2a645SAnirudh Venkataramanan  * @ctxt: the VSI context being set
88628c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
88728c2a645SAnirudh Venkataramanan  */
88828c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
88928c2a645SAnirudh Venkataramanan {
89028c2a645SAnirudh Venkataramanan 	u8 lut_type, hash_type;
8914015d11eSBrett Creeley 	struct device *dev;
892819d8998SJesse Brandeburg 	struct ice_pf *pf;
893819d8998SJesse Brandeburg 
894819d8998SJesse Brandeburg 	pf = vsi->back;
8954015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
89628c2a645SAnirudh Venkataramanan 
89728c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
89828c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
89928c2a645SAnirudh Venkataramanan 		/* PF VSI will inherit RSS instance of PF */
90028c2a645SAnirudh Venkataramanan 		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
90128c2a645SAnirudh Venkataramanan 		hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
90228c2a645SAnirudh Venkataramanan 		break;
9038ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
9048ede0178SAnirudh Venkataramanan 		/* VF VSI will gets a small RSS table which is a VSI LUT type */
9058ede0178SAnirudh Venkataramanan 		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
9068ede0178SAnirudh Venkataramanan 		hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
9078ede0178SAnirudh Venkataramanan 		break;
908148beb61SHenry Tieman 	default:
9094015d11eSBrett Creeley 		dev_dbg(dev, "Unsupported VSI type %s\n",
910964674f1SAnirudh Venkataramanan 			ice_vsi_type_str(vsi->type));
9110e674aebSAnirudh Venkataramanan 		return;
91228c2a645SAnirudh Venkataramanan 	}
91328c2a645SAnirudh Venkataramanan 
91428c2a645SAnirudh Venkataramanan 	ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
91528c2a645SAnirudh Venkataramanan 				ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
91628c2a645SAnirudh Venkataramanan 				((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) &
91728c2a645SAnirudh Venkataramanan 				 ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
91828c2a645SAnirudh Venkataramanan }
91928c2a645SAnirudh Venkataramanan 
92028c2a645SAnirudh Venkataramanan /**
92128c2a645SAnirudh Venkataramanan  * ice_vsi_init - Create and initialize a VSI
92228c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
92387324e74SHenry Tieman  * @init_vsi: is this call creating a VSI
92428c2a645SAnirudh Venkataramanan  *
92528c2a645SAnirudh Venkataramanan  * This initializes a VSI context depending on the VSI type to be added and
92628c2a645SAnirudh Venkataramanan  * passes it down to the add_vsi aq command to create a new VSI.
92728c2a645SAnirudh Venkataramanan  */
92887324e74SHenry Tieman static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
92928c2a645SAnirudh Venkataramanan {
93028c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
93128c2a645SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
932198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
93387324e74SHenry Tieman 	struct device *dev;
93428c2a645SAnirudh Venkataramanan 	int ret = 0;
93528c2a645SAnirudh Venkataramanan 
93687324e74SHenry Tieman 	dev = ice_pf_to_dev(pf);
9379efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
938198a666aSBruce Allan 	if (!ctxt)
939198a666aSBruce Allan 		return -ENOMEM;
940198a666aSBruce Allan 
94128c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
942148beb61SHenry Tieman 	case ICE_VSI_CTRL:
9430e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
94428c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
945198a666aSBruce Allan 		ctxt->flags = ICE_AQ_VSI_TYPE_PF;
94628c2a645SAnirudh Venkataramanan 		break;
9478ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
948198a666aSBruce Allan 		ctxt->flags = ICE_AQ_VSI_TYPE_VF;
9498ede0178SAnirudh Venkataramanan 		/* VF number here is the absolute VF number (0-255) */
950198a666aSBruce Allan 		ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id;
9518ede0178SAnirudh Venkataramanan 		break;
95228c2a645SAnirudh Venkataramanan 	default:
9539efe35d0STony Nguyen 		ret = -ENODEV;
9549efe35d0STony Nguyen 		goto out;
95528c2a645SAnirudh Venkataramanan 	}
95628c2a645SAnirudh Venkataramanan 
957198a666aSBruce Allan 	ice_set_dflt_vsi_ctx(ctxt);
958148beb61SHenry Tieman 	if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
959148beb61SHenry Tieman 		ice_set_fd_vsi_ctx(ctxt, vsi);
96028c2a645SAnirudh Venkataramanan 	/* if the switch is in VEB mode, allow VSI loopback */
96128c2a645SAnirudh Venkataramanan 	if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
962198a666aSBruce Allan 		ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
96328c2a645SAnirudh Venkataramanan 
96428c2a645SAnirudh Venkataramanan 	/* Set LUT type and HASH type if RSS is enabled */
965148beb61SHenry Tieman 	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags) &&
966148beb61SHenry Tieman 	    vsi->type != ICE_VSI_CTRL) {
967198a666aSBruce Allan 		ice_set_rss_vsi_ctx(ctxt, vsi);
96887324e74SHenry Tieman 		/* if updating VSI context, make sure to set valid_section:
96987324e74SHenry Tieman 		 * to indicate which section of VSI context being updated
97087324e74SHenry Tieman 		 */
97187324e74SHenry Tieman 		if (!init_vsi)
97287324e74SHenry Tieman 			ctxt->info.valid_sections |=
97387324e74SHenry Tieman 				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
97487324e74SHenry Tieman 	}
97528c2a645SAnirudh Venkataramanan 
976198a666aSBruce Allan 	ctxt->info.sw_id = vsi->port_info->sw_id;
977198a666aSBruce Allan 	ice_vsi_setup_q_map(vsi, ctxt);
97887324e74SHenry Tieman 	if (!init_vsi) /* means VSI being updated */
97987324e74SHenry Tieman 		/* must to indicate which section of VSI context are
98087324e74SHenry Tieman 		 * being modified
98187324e74SHenry Tieman 		 */
98287324e74SHenry Tieman 		ctxt->info.valid_sections |=
98387324e74SHenry Tieman 			cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
98428c2a645SAnirudh Venkataramanan 
985cd6d6b83SBrett Creeley 	/* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off
986cd6d6b83SBrett Creeley 	 * respectively
987cd6d6b83SBrett Creeley 	 */
988cd6d6b83SBrett Creeley 	if (vsi->type == ICE_VSI_VF) {
989cb93a952SAkeem G Abodunrin 		ctxt->info.valid_sections |=
990cb93a952SAkeem G Abodunrin 			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
991cd6d6b83SBrett Creeley 		if (pf->vf[vsi->vf_id].spoofchk) {
992cb93a952SAkeem G Abodunrin 			ctxt->info.sec_flags |=
993cd6d6b83SBrett Creeley 				ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
994cd6d6b83SBrett Creeley 				(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
995cd6d6b83SBrett Creeley 				 ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
996cd6d6b83SBrett Creeley 		} else {
997cd6d6b83SBrett Creeley 			ctxt->info.sec_flags &=
998cd6d6b83SBrett Creeley 				~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
999cd6d6b83SBrett Creeley 				  (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
1000cd6d6b83SBrett Creeley 				   ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S));
1001cd6d6b83SBrett Creeley 		}
1002cb93a952SAkeem G Abodunrin 	}
1003cb93a952SAkeem G Abodunrin 
10040c3a6101SDave Ertman 	/* Allow control frames out of main VSI */
10050c3a6101SDave Ertman 	if (vsi->type == ICE_VSI_PF) {
10060c3a6101SDave Ertman 		ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
10070c3a6101SDave Ertman 		ctxt->info.valid_sections |=
10080c3a6101SDave Ertman 			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
10090c3a6101SDave Ertman 	}
10100c3a6101SDave Ertman 
101187324e74SHenry Tieman 	if (init_vsi) {
1012198a666aSBruce Allan 		ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
101328c2a645SAnirudh Venkataramanan 		if (ret) {
101487324e74SHenry Tieman 			dev_err(dev, "Add VSI failed, err %d\n", ret);
10159efe35d0STony Nguyen 			ret = -EIO;
10169efe35d0STony Nguyen 			goto out;
101728c2a645SAnirudh Venkataramanan 		}
101887324e74SHenry Tieman 	} else {
101987324e74SHenry Tieman 		ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
102087324e74SHenry Tieman 		if (ret) {
102187324e74SHenry Tieman 			dev_err(dev, "Update VSI failed, err %d\n", ret);
102287324e74SHenry Tieman 			ret = -EIO;
102387324e74SHenry Tieman 			goto out;
102487324e74SHenry Tieman 		}
102587324e74SHenry Tieman 	}
102628c2a645SAnirudh Venkataramanan 
102728c2a645SAnirudh Venkataramanan 	/* keep context for update VSI operations */
1028198a666aSBruce Allan 	vsi->info = ctxt->info;
102928c2a645SAnirudh Venkataramanan 
103028c2a645SAnirudh Venkataramanan 	/* record VSI number returned */
1031198a666aSBruce Allan 	vsi->vsi_num = ctxt->vsi_num;
103228c2a645SAnirudh Venkataramanan 
10339efe35d0STony Nguyen out:
10349efe35d0STony Nguyen 	kfree(ctxt);
103528c2a645SAnirudh Venkataramanan 	return ret;
103628c2a645SAnirudh Venkataramanan }
103728c2a645SAnirudh Venkataramanan 
103828c2a645SAnirudh Venkataramanan /**
103946c276ceSBrett Creeley  * ice_free_res - free a block of resources
104046c276ceSBrett Creeley  * @res: pointer to the resource
104146c276ceSBrett Creeley  * @index: starting index previously returned by ice_get_res
104246c276ceSBrett Creeley  * @id: identifier to track owner
104346c276ceSBrett Creeley  *
104446c276ceSBrett Creeley  * Returns number of resources freed
104546c276ceSBrett Creeley  */
104646c276ceSBrett Creeley int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
104746c276ceSBrett Creeley {
104846c276ceSBrett Creeley 	int count = 0;
104946c276ceSBrett Creeley 	int i;
105046c276ceSBrett Creeley 
105146c276ceSBrett Creeley 	if (!res || index >= res->end)
105246c276ceSBrett Creeley 		return -EINVAL;
105346c276ceSBrett Creeley 
105446c276ceSBrett Creeley 	id |= ICE_RES_VALID_BIT;
105546c276ceSBrett Creeley 	for (i = index; i < res->end && res->list[i] == id; i++) {
105646c276ceSBrett Creeley 		res->list[i] = 0;
105746c276ceSBrett Creeley 		count++;
105846c276ceSBrett Creeley 	}
105946c276ceSBrett Creeley 
106046c276ceSBrett Creeley 	return count;
106146c276ceSBrett Creeley }
106246c276ceSBrett Creeley 
106346c276ceSBrett Creeley /**
106446c276ceSBrett Creeley  * ice_search_res - Search the tracker for a block of resources
106546c276ceSBrett Creeley  * @res: pointer to the resource
106646c276ceSBrett Creeley  * @needed: size of the block needed
106746c276ceSBrett Creeley  * @id: identifier to track owner
106846c276ceSBrett Creeley  *
106946c276ceSBrett Creeley  * Returns the base item index of the block, or -ENOMEM for error
107046c276ceSBrett Creeley  */
107146c276ceSBrett Creeley static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
107246c276ceSBrett Creeley {
107388865fc4SKarol Kolacinski 	u16 start = 0, end = 0;
107446c276ceSBrett Creeley 
107546c276ceSBrett Creeley 	if (needed > res->end)
107646c276ceSBrett Creeley 		return -ENOMEM;
107746c276ceSBrett Creeley 
107846c276ceSBrett Creeley 	id |= ICE_RES_VALID_BIT;
107946c276ceSBrett Creeley 
108046c276ceSBrett Creeley 	do {
108146c276ceSBrett Creeley 		/* skip already allocated entries */
108246c276ceSBrett Creeley 		if (res->list[end++] & ICE_RES_VALID_BIT) {
108346c276ceSBrett Creeley 			start = end;
108446c276ceSBrett Creeley 			if ((start + needed) > res->end)
108546c276ceSBrett Creeley 				break;
108646c276ceSBrett Creeley 		}
108746c276ceSBrett Creeley 
108846c276ceSBrett Creeley 		if (end == (start + needed)) {
108946c276ceSBrett Creeley 			int i = start;
109046c276ceSBrett Creeley 
109146c276ceSBrett Creeley 			/* there was enough, so assign it to the requestor */
109246c276ceSBrett Creeley 			while (i != end)
109346c276ceSBrett Creeley 				res->list[i++] = id;
109446c276ceSBrett Creeley 
109546c276ceSBrett Creeley 			return start;
109646c276ceSBrett Creeley 		}
109746c276ceSBrett Creeley 	} while (end < res->end);
109846c276ceSBrett Creeley 
109946c276ceSBrett Creeley 	return -ENOMEM;
110046c276ceSBrett Creeley }
110146c276ceSBrett Creeley 
110246c276ceSBrett Creeley /**
110346c276ceSBrett Creeley  * ice_get_free_res_count - Get free count from a resource tracker
110446c276ceSBrett Creeley  * @res: Resource tracker instance
110546c276ceSBrett Creeley  */
110646c276ceSBrett Creeley static u16 ice_get_free_res_count(struct ice_res_tracker *res)
110746c276ceSBrett Creeley {
110846c276ceSBrett Creeley 	u16 i, count = 0;
110946c276ceSBrett Creeley 
111046c276ceSBrett Creeley 	for (i = 0; i < res->end; i++)
111146c276ceSBrett Creeley 		if (!(res->list[i] & ICE_RES_VALID_BIT))
111246c276ceSBrett Creeley 			count++;
111346c276ceSBrett Creeley 
111446c276ceSBrett Creeley 	return count;
111546c276ceSBrett Creeley }
111646c276ceSBrett Creeley 
111746c276ceSBrett Creeley /**
111846c276ceSBrett Creeley  * ice_get_res - get a block of resources
111946c276ceSBrett Creeley  * @pf: board private structure
112046c276ceSBrett Creeley  * @res: pointer to the resource
112146c276ceSBrett Creeley  * @needed: size of the block needed
112246c276ceSBrett Creeley  * @id: identifier to track owner
112346c276ceSBrett Creeley  *
112446c276ceSBrett Creeley  * Returns the base item index of the block, or negative for error
112546c276ceSBrett Creeley  */
112646c276ceSBrett Creeley int
112746c276ceSBrett Creeley ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
112846c276ceSBrett Creeley {
112946c276ceSBrett Creeley 	if (!res || !pf)
113046c276ceSBrett Creeley 		return -EINVAL;
113146c276ceSBrett Creeley 
113246c276ceSBrett Creeley 	if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) {
113346c276ceSBrett Creeley 		dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n",
113446c276ceSBrett Creeley 			needed, res->num_entries, id);
113546c276ceSBrett Creeley 		return -EINVAL;
113646c276ceSBrett Creeley 	}
113746c276ceSBrett Creeley 
113846c276ceSBrett Creeley 	return ice_search_res(res, needed, id);
113946c276ceSBrett Creeley }
114046c276ceSBrett Creeley 
114146c276ceSBrett Creeley /**
1142df0f8479SAnirudh Venkataramanan  * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
1143df0f8479SAnirudh Venkataramanan  * @vsi: ptr to the VSI
1144df0f8479SAnirudh Venkataramanan  *
1145df0f8479SAnirudh Venkataramanan  * This should only be called after ice_vsi_alloc() which allocates the
1146df0f8479SAnirudh Venkataramanan  * corresponding SW VSI structure and initializes num_queue_pairs for the
1147df0f8479SAnirudh Venkataramanan  * newly allocated VSI.
1148df0f8479SAnirudh Venkataramanan  *
1149df0f8479SAnirudh Venkataramanan  * Returns 0 on success or negative on failure
1150df0f8479SAnirudh Venkataramanan  */
115137bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
1152df0f8479SAnirudh Venkataramanan {
1153df0f8479SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
11544015d11eSBrett Creeley 	struct device *dev;
1155cbe66bfeSBrett Creeley 	u16 num_q_vectors;
115688865fc4SKarol Kolacinski 	int base;
1157df0f8479SAnirudh Venkataramanan 
11584015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
1159cbe66bfeSBrett Creeley 	/* SRIOV doesn't grab irq_tracker entries for each VSI */
1160cbe66bfeSBrett Creeley 	if (vsi->type == ICE_VSI_VF)
1161cbe66bfeSBrett Creeley 		return 0;
1162cbe66bfeSBrett Creeley 
1163cbe66bfeSBrett Creeley 	if (vsi->base_vector) {
11644015d11eSBrett Creeley 		dev_dbg(dev, "VSI %d has non-zero base vector %d\n",
1165cbe66bfeSBrett Creeley 			vsi->vsi_num, vsi->base_vector);
1166df0f8479SAnirudh Venkataramanan 		return -EEXIST;
1167df0f8479SAnirudh Venkataramanan 	}
1168df0f8479SAnirudh Venkataramanan 
1169df0f8479SAnirudh Venkataramanan 	num_q_vectors = vsi->num_q_vectors;
1170eb0208ecSPreethi Banala 	/* reserve slots from OS requested IRQs */
117188865fc4SKarol Kolacinski 	base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, vsi->idx);
117288865fc4SKarol Kolacinski 
117388865fc4SKarol Kolacinski 	if (base < 0) {
117446c276ceSBrett Creeley 		dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n",
117546c276ceSBrett Creeley 			ice_get_free_res_count(pf->irq_tracker),
117646c276ceSBrett Creeley 			ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors);
1177eb0208ecSPreethi Banala 		return -ENOENT;
1178eb0208ecSPreethi Banala 	}
117988865fc4SKarol Kolacinski 	vsi->base_vector = (u16)base;
1180eb0208ecSPreethi Banala 	pf->num_avail_sw_msix -= num_q_vectors;
1181eb0208ecSPreethi Banala 
1182df0f8479SAnirudh Venkataramanan 	return 0;
1183df0f8479SAnirudh Venkataramanan }
1184df0f8479SAnirudh Venkataramanan 
1185df0f8479SAnirudh Venkataramanan /**
118628c2a645SAnirudh Venkataramanan  * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
118728c2a645SAnirudh Venkataramanan  * @vsi: the VSI having rings deallocated
118828c2a645SAnirudh Venkataramanan  */
1189df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi)
119028c2a645SAnirudh Venkataramanan {
119128c2a645SAnirudh Venkataramanan 	int i;
119228c2a645SAnirudh Venkataramanan 
119328c2a645SAnirudh Venkataramanan 	if (vsi->tx_rings) {
119428c2a645SAnirudh Venkataramanan 		for (i = 0; i < vsi->alloc_txq; i++) {
119528c2a645SAnirudh Venkataramanan 			if (vsi->tx_rings[i]) {
119628c2a645SAnirudh Venkataramanan 				kfree_rcu(vsi->tx_rings[i], rcu);
119728c2a645SAnirudh Venkataramanan 				vsi->tx_rings[i] = NULL;
119828c2a645SAnirudh Venkataramanan 			}
119928c2a645SAnirudh Venkataramanan 		}
120028c2a645SAnirudh Venkataramanan 	}
120128c2a645SAnirudh Venkataramanan 	if (vsi->rx_rings) {
120228c2a645SAnirudh Venkataramanan 		for (i = 0; i < vsi->alloc_rxq; i++) {
120328c2a645SAnirudh Venkataramanan 			if (vsi->rx_rings[i]) {
120428c2a645SAnirudh Venkataramanan 				kfree_rcu(vsi->rx_rings[i], rcu);
120528c2a645SAnirudh Venkataramanan 				vsi->rx_rings[i] = NULL;
120628c2a645SAnirudh Venkataramanan 			}
120728c2a645SAnirudh Venkataramanan 		}
120828c2a645SAnirudh Venkataramanan 	}
120928c2a645SAnirudh Venkataramanan }
121028c2a645SAnirudh Venkataramanan 
121128c2a645SAnirudh Venkataramanan /**
121228c2a645SAnirudh Venkataramanan  * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI
121328c2a645SAnirudh Venkataramanan  * @vsi: VSI which is having rings allocated
121428c2a645SAnirudh Venkataramanan  */
121537bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
121628c2a645SAnirudh Venkataramanan {
121728c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
12184015d11eSBrett Creeley 	struct device *dev;
121988865fc4SKarol Kolacinski 	u16 i;
122028c2a645SAnirudh Venkataramanan 
12214015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
1222d337f2afSAnirudh Venkataramanan 	/* Allocate Tx rings */
122328c2a645SAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_txq; i++) {
122428c2a645SAnirudh Venkataramanan 		struct ice_ring *ring;
122528c2a645SAnirudh Venkataramanan 
122628c2a645SAnirudh Venkataramanan 		/* allocate with kzalloc(), free with kfree_rcu() */
122728c2a645SAnirudh Venkataramanan 		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
122828c2a645SAnirudh Venkataramanan 
122928c2a645SAnirudh Venkataramanan 		if (!ring)
123028c2a645SAnirudh Venkataramanan 			goto err_out;
123128c2a645SAnirudh Venkataramanan 
123228c2a645SAnirudh Venkataramanan 		ring->q_index = i;
123328c2a645SAnirudh Venkataramanan 		ring->reg_idx = vsi->txq_map[i];
123428c2a645SAnirudh Venkataramanan 		ring->ring_active = false;
123528c2a645SAnirudh Venkataramanan 		ring->vsi = vsi;
12364015d11eSBrett Creeley 		ring->dev = dev;
1237ad71b256SBrett Creeley 		ring->count = vsi->num_tx_desc;
123828c2a645SAnirudh Venkataramanan 		vsi->tx_rings[i] = ring;
123928c2a645SAnirudh Venkataramanan 	}
124028c2a645SAnirudh Venkataramanan 
1241d337f2afSAnirudh Venkataramanan 	/* Allocate Rx rings */
124228c2a645SAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_rxq; i++) {
124328c2a645SAnirudh Venkataramanan 		struct ice_ring *ring;
124428c2a645SAnirudh Venkataramanan 
124528c2a645SAnirudh Venkataramanan 		/* allocate with kzalloc(), free with kfree_rcu() */
124628c2a645SAnirudh Venkataramanan 		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
124728c2a645SAnirudh Venkataramanan 		if (!ring)
124828c2a645SAnirudh Venkataramanan 			goto err_out;
124928c2a645SAnirudh Venkataramanan 
125028c2a645SAnirudh Venkataramanan 		ring->q_index = i;
125128c2a645SAnirudh Venkataramanan 		ring->reg_idx = vsi->rxq_map[i];
125228c2a645SAnirudh Venkataramanan 		ring->ring_active = false;
125328c2a645SAnirudh Venkataramanan 		ring->vsi = vsi;
125428c2a645SAnirudh Venkataramanan 		ring->netdev = vsi->netdev;
12554015d11eSBrett Creeley 		ring->dev = dev;
1256ad71b256SBrett Creeley 		ring->count = vsi->num_rx_desc;
125728c2a645SAnirudh Venkataramanan 		vsi->rx_rings[i] = ring;
125828c2a645SAnirudh Venkataramanan 	}
125928c2a645SAnirudh Venkataramanan 
126028c2a645SAnirudh Venkataramanan 	return 0;
126128c2a645SAnirudh Venkataramanan 
126228c2a645SAnirudh Venkataramanan err_out:
126328c2a645SAnirudh Venkataramanan 	ice_vsi_clear_rings(vsi);
126428c2a645SAnirudh Venkataramanan 	return -ENOMEM;
126528c2a645SAnirudh Venkataramanan }
126628c2a645SAnirudh Venkataramanan 
126728c2a645SAnirudh Venkataramanan /**
1268492af0abSMd Fahad Iqbal Polash  * ice_vsi_manage_rss_lut - disable/enable RSS
1269492af0abSMd Fahad Iqbal Polash  * @vsi: the VSI being changed
1270492af0abSMd Fahad Iqbal Polash  * @ena: boolean value indicating if this is an enable or disable request
1271492af0abSMd Fahad Iqbal Polash  *
1272492af0abSMd Fahad Iqbal Polash  * In the event of disable request for RSS, this function will zero out RSS
1273492af0abSMd Fahad Iqbal Polash  * LUT, while in the event of enable request for RSS, it will reconfigure RSS
1274492af0abSMd Fahad Iqbal Polash  * LUT.
1275492af0abSMd Fahad Iqbal Polash  */
1276492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena)
1277492af0abSMd Fahad Iqbal Polash {
1278492af0abSMd Fahad Iqbal Polash 	int err = 0;
1279492af0abSMd Fahad Iqbal Polash 	u8 *lut;
1280492af0abSMd Fahad Iqbal Polash 
12819efe35d0STony Nguyen 	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
1282492af0abSMd Fahad Iqbal Polash 	if (!lut)
1283492af0abSMd Fahad Iqbal Polash 		return -ENOMEM;
1284492af0abSMd Fahad Iqbal Polash 
1285492af0abSMd Fahad Iqbal Polash 	if (ena) {
1286492af0abSMd Fahad Iqbal Polash 		if (vsi->rss_lut_user)
1287492af0abSMd Fahad Iqbal Polash 			memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
1288492af0abSMd Fahad Iqbal Polash 		else
1289492af0abSMd Fahad Iqbal Polash 			ice_fill_rss_lut(lut, vsi->rss_table_size,
1290492af0abSMd Fahad Iqbal Polash 					 vsi->rss_size);
1291492af0abSMd Fahad Iqbal Polash 	}
1292492af0abSMd Fahad Iqbal Polash 
1293492af0abSMd Fahad Iqbal Polash 	err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size);
12949efe35d0STony Nguyen 	kfree(lut);
1295492af0abSMd Fahad Iqbal Polash 	return err;
1296492af0abSMd Fahad Iqbal Polash }
1297492af0abSMd Fahad Iqbal Polash 
1298492af0abSMd Fahad Iqbal Polash /**
129937bb8390SAnirudh Venkataramanan  * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI
130037bb8390SAnirudh Venkataramanan  * @vsi: VSI to be configured
130137bb8390SAnirudh Venkataramanan  */
130237bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi)
130337bb8390SAnirudh Venkataramanan {
130437bb8390SAnirudh Venkataramanan 	struct ice_aqc_get_set_rss_keys *key;
130537bb8390SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
130637bb8390SAnirudh Venkataramanan 	enum ice_status status;
13074015d11eSBrett Creeley 	struct device *dev;
130837bb8390SAnirudh Venkataramanan 	int err = 0;
130937bb8390SAnirudh Venkataramanan 	u8 *lut;
131037bb8390SAnirudh Venkataramanan 
13114015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
131288865fc4SKarol Kolacinski 	vsi->rss_size = min_t(u16, vsi->rss_size, vsi->num_rxq);
131337bb8390SAnirudh Venkataramanan 
13149efe35d0STony Nguyen 	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
131537bb8390SAnirudh Venkataramanan 	if (!lut)
131637bb8390SAnirudh Venkataramanan 		return -ENOMEM;
131737bb8390SAnirudh Venkataramanan 
131837bb8390SAnirudh Venkataramanan 	if (vsi->rss_lut_user)
131937bb8390SAnirudh Venkataramanan 		memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
132037bb8390SAnirudh Venkataramanan 	else
132137bb8390SAnirudh Venkataramanan 		ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size);
132237bb8390SAnirudh Venkataramanan 
13234fb33f31SAnirudh Venkataramanan 	status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut,
13244fb33f31SAnirudh Venkataramanan 				    vsi->rss_table_size);
132537bb8390SAnirudh Venkataramanan 
132637bb8390SAnirudh Venkataramanan 	if (status) {
13270fee3577SLihong Yang 		dev_err(dev, "set_rss_lut failed, error %s\n",
13280fee3577SLihong Yang 			ice_stat_str(status));
132937bb8390SAnirudh Venkataramanan 		err = -EIO;
133037bb8390SAnirudh Venkataramanan 		goto ice_vsi_cfg_rss_exit;
133137bb8390SAnirudh Venkataramanan 	}
133237bb8390SAnirudh Venkataramanan 
13339efe35d0STony Nguyen 	key = kzalloc(sizeof(*key), GFP_KERNEL);
133437bb8390SAnirudh Venkataramanan 	if (!key) {
133537bb8390SAnirudh Venkataramanan 		err = -ENOMEM;
133637bb8390SAnirudh Venkataramanan 		goto ice_vsi_cfg_rss_exit;
133737bb8390SAnirudh Venkataramanan 	}
133837bb8390SAnirudh Venkataramanan 
133937bb8390SAnirudh Venkataramanan 	if (vsi->rss_hkey_user)
1340b4b418b3SPaul Greenwalt 		memcpy(key,
1341b4b418b3SPaul Greenwalt 		       (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user,
1342b4b418b3SPaul Greenwalt 		       ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
134337bb8390SAnirudh Venkataramanan 	else
1344b4b418b3SPaul Greenwalt 		netdev_rss_key_fill((void *)key,
1345b4b418b3SPaul Greenwalt 				    ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
134637bb8390SAnirudh Venkataramanan 
13474fb33f31SAnirudh Venkataramanan 	status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key);
134837bb8390SAnirudh Venkataramanan 
134937bb8390SAnirudh Venkataramanan 	if (status) {
13500fee3577SLihong Yang 		dev_err(dev, "set_rss_key failed, error %s\n",
13510fee3577SLihong Yang 			ice_stat_str(status));
135237bb8390SAnirudh Venkataramanan 		err = -EIO;
135337bb8390SAnirudh Venkataramanan 	}
135437bb8390SAnirudh Venkataramanan 
13559efe35d0STony Nguyen 	kfree(key);
135637bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit:
13579efe35d0STony Nguyen 	kfree(lut);
135837bb8390SAnirudh Venkataramanan 	return err;
135937bb8390SAnirudh Venkataramanan }
136037bb8390SAnirudh Venkataramanan 
136137bb8390SAnirudh Venkataramanan /**
13621c01c8c6SMd Fahad Iqbal Polash  * ice_vsi_set_vf_rss_flow_fld - Sets VF VSI RSS input set for different flows
13631c01c8c6SMd Fahad Iqbal Polash  * @vsi: VSI to be configured
13641c01c8c6SMd Fahad Iqbal Polash  *
13651c01c8c6SMd Fahad Iqbal Polash  * This function will only be called during the VF VSI setup. Upon successful
13661c01c8c6SMd Fahad Iqbal Polash  * completion of package download, this function will configure default RSS
13671c01c8c6SMd Fahad Iqbal Polash  * input sets for VF VSI.
13681c01c8c6SMd Fahad Iqbal Polash  */
13691c01c8c6SMd Fahad Iqbal Polash static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi)
13701c01c8c6SMd Fahad Iqbal Polash {
13711c01c8c6SMd Fahad Iqbal Polash 	struct ice_pf *pf = vsi->back;
13721c01c8c6SMd Fahad Iqbal Polash 	enum ice_status status;
13731c01c8c6SMd Fahad Iqbal Polash 	struct device *dev;
13741c01c8c6SMd Fahad Iqbal Polash 
13751c01c8c6SMd Fahad Iqbal Polash 	dev = ice_pf_to_dev(pf);
13761c01c8c6SMd Fahad Iqbal Polash 	if (ice_is_safe_mode(pf)) {
13771c01c8c6SMd Fahad Iqbal Polash 		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
13781c01c8c6SMd Fahad Iqbal Polash 			vsi->vsi_num);
13791c01c8c6SMd Fahad Iqbal Polash 		return;
13801c01c8c6SMd Fahad Iqbal Polash 	}
13811c01c8c6SMd Fahad Iqbal Polash 
13821c01c8c6SMd Fahad Iqbal Polash 	status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA);
13831c01c8c6SMd Fahad Iqbal Polash 	if (status)
13840fee3577SLihong Yang 		dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %s\n",
13850fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
13861c01c8c6SMd Fahad Iqbal Polash }
13871c01c8c6SMd Fahad Iqbal Polash 
13881c01c8c6SMd Fahad Iqbal Polash /**
1389c90ed40cSTony Nguyen  * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows
1390c90ed40cSTony Nguyen  * @vsi: VSI to be configured
1391c90ed40cSTony Nguyen  *
1392c90ed40cSTony Nguyen  * This function will only be called after successful download package call
1393c90ed40cSTony Nguyen  * during initialization of PF. Since the downloaded package will erase the
1394c90ed40cSTony Nguyen  * RSS section, this function will configure RSS input sets for different
1395c90ed40cSTony Nguyen  * flow types. The last profile added has the highest priority, therefore 2
1396c90ed40cSTony Nguyen  * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles
1397c90ed40cSTony Nguyen  * (i.e. IPv4 src/dst TCP src/dst port).
1398c90ed40cSTony Nguyen  */
1399c90ed40cSTony Nguyen static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
1400c90ed40cSTony Nguyen {
1401c90ed40cSTony Nguyen 	u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num;
1402c90ed40cSTony Nguyen 	struct ice_pf *pf = vsi->back;
1403c90ed40cSTony Nguyen 	struct ice_hw *hw = &pf->hw;
1404c90ed40cSTony Nguyen 	enum ice_status status;
1405c90ed40cSTony Nguyen 	struct device *dev;
1406c90ed40cSTony Nguyen 
1407c90ed40cSTony Nguyen 	dev = ice_pf_to_dev(pf);
1408c90ed40cSTony Nguyen 	if (ice_is_safe_mode(pf)) {
1409c90ed40cSTony Nguyen 		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
1410c90ed40cSTony Nguyen 			vsi_num);
1411c90ed40cSTony Nguyen 		return;
1412c90ed40cSTony Nguyen 	}
1413c90ed40cSTony Nguyen 	/* configure RSS for IPv4 with input set IP src/dst */
1414c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
1415c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_IPV4);
1416c90ed40cSTony Nguyen 	if (status)
14170fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %s\n",
14180fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1419c90ed40cSTony Nguyen 
1420c90ed40cSTony Nguyen 	/* configure RSS for IPv6 with input set IPv6 src/dst */
1421c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
1422c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_IPV6);
1423c90ed40cSTony Nguyen 	if (status)
14240fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %s\n",
14250fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1426c90ed40cSTony Nguyen 
1427c90ed40cSTony Nguyen 	/* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */
1428c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4,
1429c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4);
1430c90ed40cSTony Nguyen 	if (status)
14310fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %s\n",
14320fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1433c90ed40cSTony Nguyen 
1434c90ed40cSTony Nguyen 	/* configure RSS for udp4 with input set IP src/dst, UDP src/dst */
1435c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4,
1436c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4);
1437c90ed40cSTony Nguyen 	if (status)
14380fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %s\n",
14390fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1440c90ed40cSTony Nguyen 
1441c90ed40cSTony Nguyen 	/* configure RSS for sctp4 with input set IP src/dst */
1442c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
1443c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4);
1444c90ed40cSTony Nguyen 	if (status)
14450fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %s\n",
14460fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1447c90ed40cSTony Nguyen 
1448c90ed40cSTony Nguyen 	/* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */
1449c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6,
1450c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6);
1451c90ed40cSTony Nguyen 	if (status)
14520fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %s\n",
14530fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1454c90ed40cSTony Nguyen 
1455c90ed40cSTony Nguyen 	/* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */
1456c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6,
1457c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6);
1458c90ed40cSTony Nguyen 	if (status)
14590fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %s\n",
14600fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1461c90ed40cSTony Nguyen 
1462c90ed40cSTony Nguyen 	/* configure RSS for sctp6 with input set IPv6 src/dst */
1463c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
1464c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6);
1465c90ed40cSTony Nguyen 	if (status)
14660fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %s\n",
14670fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1468c90ed40cSTony Nguyen }
1469c90ed40cSTony Nguyen 
1470c90ed40cSTony Nguyen /**
147145d3d428SAnirudh Venkataramanan  * ice_update_eth_stats - Update VSI-specific ethernet statistics counters
147245d3d428SAnirudh Venkataramanan  * @vsi: the VSI to be updated
147345d3d428SAnirudh Venkataramanan  */
147445d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi)
147545d3d428SAnirudh Venkataramanan {
147645d3d428SAnirudh Venkataramanan 	struct ice_eth_stats *prev_es, *cur_es;
147745d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
147845d3d428SAnirudh Venkataramanan 	u16 vsi_num = vsi->vsi_num;    /* HW absolute index of a VSI */
147945d3d428SAnirudh Venkataramanan 
148045d3d428SAnirudh Venkataramanan 	prev_es = &vsi->eth_stats_prev;
148145d3d428SAnirudh Venkataramanan 	cur_es = &vsi->eth_stats;
148245d3d428SAnirudh Venkataramanan 
148336517fd3SJacob Keller 	ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded,
148436517fd3SJacob Keller 			  &prev_es->rx_bytes, &cur_es->rx_bytes);
148545d3d428SAnirudh Venkataramanan 
148636517fd3SJacob Keller 	ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded,
148736517fd3SJacob Keller 			  &prev_es->rx_unicast, &cur_es->rx_unicast);
148845d3d428SAnirudh Venkataramanan 
148936517fd3SJacob Keller 	ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded,
149036517fd3SJacob Keller 			  &prev_es->rx_multicast, &cur_es->rx_multicast);
149145d3d428SAnirudh Venkataramanan 
149236517fd3SJacob Keller 	ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded,
149336517fd3SJacob Keller 			  &prev_es->rx_broadcast, &cur_es->rx_broadcast);
149445d3d428SAnirudh Venkataramanan 
149545d3d428SAnirudh Venkataramanan 	ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded,
149645d3d428SAnirudh Venkataramanan 			  &prev_es->rx_discards, &cur_es->rx_discards);
149745d3d428SAnirudh Venkataramanan 
149836517fd3SJacob Keller 	ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded,
149936517fd3SJacob Keller 			  &prev_es->tx_bytes, &cur_es->tx_bytes);
150045d3d428SAnirudh Venkataramanan 
150136517fd3SJacob Keller 	ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded,
150236517fd3SJacob Keller 			  &prev_es->tx_unicast, &cur_es->tx_unicast);
150345d3d428SAnirudh Venkataramanan 
150436517fd3SJacob Keller 	ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded,
150536517fd3SJacob Keller 			  &prev_es->tx_multicast, &cur_es->tx_multicast);
150645d3d428SAnirudh Venkataramanan 
150736517fd3SJacob Keller 	ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded,
150836517fd3SJacob Keller 			  &prev_es->tx_broadcast, &cur_es->tx_broadcast);
150945d3d428SAnirudh Venkataramanan 
151045d3d428SAnirudh Venkataramanan 	ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded,
151145d3d428SAnirudh Venkataramanan 			  &prev_es->tx_errors, &cur_es->tx_errors);
151245d3d428SAnirudh Venkataramanan 
151345d3d428SAnirudh Venkataramanan 	vsi->stat_offsets_loaded = true;
151445d3d428SAnirudh Venkataramanan }
151545d3d428SAnirudh Venkataramanan 
151645d3d428SAnirudh Venkataramanan /**
151745d3d428SAnirudh Venkataramanan  * ice_vsi_add_vlan - Add VSI membership for given VLAN
151845d3d428SAnirudh Venkataramanan  * @vsi: the VSI being configured
1519f9867df6SAnirudh Venkataramanan  * @vid: VLAN ID to be added
15201b8f15b6SMichal Swiatkowski  * @action: filter action to be performed on match
152145d3d428SAnirudh Venkataramanan  */
15221b8f15b6SMichal Swiatkowski int
15231b8f15b6SMichal Swiatkowski ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action)
152445d3d428SAnirudh Venkataramanan {
152545d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
15264015d11eSBrett Creeley 	struct device *dev;
152745d3d428SAnirudh Venkataramanan 	int err = 0;
152845d3d428SAnirudh Venkataramanan 
15294015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
153045d3d428SAnirudh Venkataramanan 
15311b8f15b6SMichal Swiatkowski 	if (!ice_fltr_add_vlan(vsi, vid, action)) {
153242f3efefSBrett Creeley 		vsi->num_vlan++;
153342f3efefSBrett Creeley 	} else {
153445d3d428SAnirudh Venkataramanan 		err = -ENODEV;
15354015d11eSBrett Creeley 		dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid,
15364015d11eSBrett Creeley 			vsi->vsi_num);
153745d3d428SAnirudh Venkataramanan 	}
153845d3d428SAnirudh Venkataramanan 
153945d3d428SAnirudh Venkataramanan 	return err;
154045d3d428SAnirudh Venkataramanan }
154145d3d428SAnirudh Venkataramanan 
154245d3d428SAnirudh Venkataramanan /**
154345d3d428SAnirudh Venkataramanan  * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN
154445d3d428SAnirudh Venkataramanan  * @vsi: the VSI being configured
1545f9867df6SAnirudh Venkataramanan  * @vid: VLAN ID to be removed
154645d3d428SAnirudh Venkataramanan  *
154745d3d428SAnirudh Venkataramanan  * Returns 0 on success and negative on failure
154845d3d428SAnirudh Venkataramanan  */
154945d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid)
155045d3d428SAnirudh Venkataramanan {
155145d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
15525079b853SAkeem G Abodunrin 	enum ice_status status;
15534015d11eSBrett Creeley 	struct device *dev;
15545079b853SAkeem G Abodunrin 	int err = 0;
155545d3d428SAnirudh Venkataramanan 
15564015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
155745d3d428SAnirudh Venkataramanan 
15581b8f15b6SMichal Swiatkowski 	status = ice_fltr_remove_vlan(vsi, vid, ICE_FWD_TO_VSI);
155942f3efefSBrett Creeley 	if (!status) {
156042f3efefSBrett Creeley 		vsi->num_vlan--;
156142f3efefSBrett Creeley 	} else if (status == ICE_ERR_DOES_NOT_EXIST) {
15620fee3577SLihong Yang 		dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, status: %s\n",
15630fee3577SLihong Yang 			vid, vsi->vsi_num, ice_stat_str(status));
156442f3efefSBrett Creeley 	} else {
15650fee3577SLihong Yang 		dev_err(dev, "Error removing VLAN %d on vsi %i error: %s\n",
15660fee3577SLihong Yang 			vid, vsi->vsi_num, ice_stat_str(status));
15675079b853SAkeem G Abodunrin 		err = -EIO;
156845d3d428SAnirudh Venkataramanan 	}
156945d3d428SAnirudh Venkataramanan 
15705079b853SAkeem G Abodunrin 	return err;
157145d3d428SAnirudh Venkataramanan }
157245d3d428SAnirudh Venkataramanan 
157345d3d428SAnirudh Venkataramanan /**
1574efc2214bSMaciej Fijalkowski  * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
1575efc2214bSMaciej Fijalkowski  * @vsi: VSI
1576efc2214bSMaciej Fijalkowski  */
1577efc2214bSMaciej Fijalkowski void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
1578efc2214bSMaciej Fijalkowski {
15797237f5b0SMaciej Fijalkowski 	if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
15807237f5b0SMaciej Fijalkowski 		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
1581efc2214bSMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_2048;
15827237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192)
158359bb0808SMaciej Fijalkowski 	} else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
158459bb0808SMaciej Fijalkowski 		   (vsi->netdev->mtu <= ETH_DATA_LEN)) {
15857237f5b0SMaciej Fijalkowski 		vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
15867237f5b0SMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
15877237f5b0SMaciej Fijalkowski #endif
15887237f5b0SMaciej Fijalkowski 	} else {
15897237f5b0SMaciej Fijalkowski 		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
15907237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192)
15917237f5b0SMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_3072;
15927237f5b0SMaciej Fijalkowski #else
15937237f5b0SMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_2048;
15947237f5b0SMaciej Fijalkowski #endif
15957237f5b0SMaciej Fijalkowski 	}
1596efc2214bSMaciej Fijalkowski }
1597efc2214bSMaciej Fijalkowski 
1598efc2214bSMaciej Fijalkowski /**
1599401ce33bSBrett Creeley  * ice_write_qrxflxp_cntxt - write/configure QRXFLXP_CNTXT register
1600401ce33bSBrett Creeley  * @hw: HW pointer
1601401ce33bSBrett Creeley  * @pf_q: index of the Rx queue in the PF's queue space
1602401ce33bSBrett Creeley  * @rxdid: flexible descriptor RXDID
1603401ce33bSBrett Creeley  * @prio: priority for the RXDID for this queue
1604401ce33bSBrett Creeley  */
1605401ce33bSBrett Creeley void
1606401ce33bSBrett Creeley ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio)
1607401ce33bSBrett Creeley {
1608401ce33bSBrett Creeley 	int regval = rd32(hw, QRXFLXP_CNTXT(pf_q));
1609401ce33bSBrett Creeley 
1610401ce33bSBrett Creeley 	/* clear any previous values */
1611401ce33bSBrett Creeley 	regval &= ~(QRXFLXP_CNTXT_RXDID_IDX_M |
1612401ce33bSBrett Creeley 		    QRXFLXP_CNTXT_RXDID_PRIO_M |
1613401ce33bSBrett Creeley 		    QRXFLXP_CNTXT_TS_M);
1614401ce33bSBrett Creeley 
1615401ce33bSBrett Creeley 	regval |= (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) &
1616401ce33bSBrett Creeley 		QRXFLXP_CNTXT_RXDID_IDX_M;
1617401ce33bSBrett Creeley 
1618401ce33bSBrett Creeley 	regval |= (prio << QRXFLXP_CNTXT_RXDID_PRIO_S) &
1619401ce33bSBrett Creeley 		QRXFLXP_CNTXT_RXDID_PRIO_M;
1620401ce33bSBrett Creeley 
1621401ce33bSBrett Creeley 	wr32(hw, QRXFLXP_CNTXT(pf_q), regval);
1622401ce33bSBrett Creeley }
1623401ce33bSBrett Creeley 
1624401ce33bSBrett Creeley /**
162572adf242SAnirudh Venkataramanan  * ice_vsi_cfg_rxqs - Configure the VSI for Rx
162672adf242SAnirudh Venkataramanan  * @vsi: the VSI being configured
162772adf242SAnirudh Venkataramanan  *
162872adf242SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
162972adf242SAnirudh Venkataramanan  * Configure the Rx VSI for operation.
163072adf242SAnirudh Venkataramanan  */
163172adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
163272adf242SAnirudh Venkataramanan {
163372adf242SAnirudh Venkataramanan 	u16 i;
163472adf242SAnirudh Venkataramanan 
16358ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
16368ede0178SAnirudh Venkataramanan 		goto setup_rings;
16378ede0178SAnirudh Venkataramanan 
1638efc2214bSMaciej Fijalkowski 	ice_vsi_cfg_frame_size(vsi);
16398ede0178SAnirudh Venkataramanan setup_rings:
164072adf242SAnirudh Venkataramanan 	/* set up individual rings */
16411553f4f7SBrett Creeley 	for (i = 0; i < vsi->num_rxq; i++) {
16421553f4f7SBrett Creeley 		int err;
164372adf242SAnirudh Venkataramanan 
16441553f4f7SBrett Creeley 		err = ice_setup_rx_ctx(vsi->rx_rings[i]);
164572adf242SAnirudh Venkataramanan 		if (err) {
164619cce2c6SAnirudh Venkataramanan 			dev_err(ice_pf_to_dev(vsi->back), "ice_setup_rx_ctx failed for RxQ %d, err %d\n",
16471553f4f7SBrett Creeley 				i, err);
164872adf242SAnirudh Venkataramanan 			return err;
164972adf242SAnirudh Venkataramanan 		}
16501553f4f7SBrett Creeley 	}
16511553f4f7SBrett Creeley 
16521553f4f7SBrett Creeley 	return 0;
16531553f4f7SBrett Creeley }
165472adf242SAnirudh Venkataramanan 
165572adf242SAnirudh Venkataramanan /**
165672adf242SAnirudh Venkataramanan  * ice_vsi_cfg_txqs - Configure the VSI for Tx
165772adf242SAnirudh Venkataramanan  * @vsi: the VSI being configured
165803f7a986SAnirudh Venkataramanan  * @rings: Tx ring array to be configured
165972adf242SAnirudh Venkataramanan  *
166072adf242SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
166172adf242SAnirudh Venkataramanan  * Configure the Tx VSI for operation.
166272adf242SAnirudh Venkataramanan  */
166303f7a986SAnirudh Venkataramanan static int
1664e75d1b2cSMaciej Fijalkowski ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings)
166572adf242SAnirudh Venkataramanan {
166672adf242SAnirudh Venkataramanan 	struct ice_aqc_add_tx_qgrp *qg_buf;
1667e75d1b2cSMaciej Fijalkowski 	u16 q_idx = 0;
1668d02f734cSMaciej Fijalkowski 	int err = 0;
166972adf242SAnirudh Venkataramanan 
1670e75d1b2cSMaciej Fijalkowski 	qg_buf = kzalloc(sizeof(*qg_buf), GFP_KERNEL);
167172adf242SAnirudh Venkataramanan 	if (!qg_buf)
167272adf242SAnirudh Venkataramanan 		return -ENOMEM;
167372adf242SAnirudh Venkataramanan 
167472adf242SAnirudh Venkataramanan 	qg_buf->num_txqs = 1;
167572adf242SAnirudh Venkataramanan 
1676e75d1b2cSMaciej Fijalkowski 	for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) {
1677e75d1b2cSMaciej Fijalkowski 		err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf);
1678d02f734cSMaciej Fijalkowski 		if (err)
167972adf242SAnirudh Venkataramanan 			goto err_cfg_txqs;
1680e75d1b2cSMaciej Fijalkowski 	}
1681c5a2a4a3SUsha Ketineni 
168272adf242SAnirudh Venkataramanan err_cfg_txqs:
1683e75d1b2cSMaciej Fijalkowski 	kfree(qg_buf);
168472adf242SAnirudh Venkataramanan 	return err;
168572adf242SAnirudh Venkataramanan }
168672adf242SAnirudh Venkataramanan 
168772adf242SAnirudh Venkataramanan /**
168803f7a986SAnirudh Venkataramanan  * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
168903f7a986SAnirudh Venkataramanan  * @vsi: the VSI being configured
169003f7a986SAnirudh Venkataramanan  *
169103f7a986SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
169203f7a986SAnirudh Venkataramanan  * Configure the Tx VSI for operation.
169303f7a986SAnirudh Venkataramanan  */
169403f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
169503f7a986SAnirudh Venkataramanan {
1696e75d1b2cSMaciej Fijalkowski 	return ice_vsi_cfg_txqs(vsi, vsi->tx_rings);
169703f7a986SAnirudh Venkataramanan }
169803f7a986SAnirudh Venkataramanan 
169903f7a986SAnirudh Venkataramanan /**
1700efc2214bSMaciej Fijalkowski  * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI
1701efc2214bSMaciej Fijalkowski  * @vsi: the VSI being configured
1702efc2214bSMaciej Fijalkowski  *
1703efc2214bSMaciej Fijalkowski  * Return 0 on success and a negative value on error
1704efc2214bSMaciej Fijalkowski  * Configure the Tx queues dedicated for XDP in given VSI for operation.
1705efc2214bSMaciej Fijalkowski  */
1706efc2214bSMaciej Fijalkowski int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
1707efc2214bSMaciej Fijalkowski {
17082d4238f5SKrzysztof Kazimierczak 	int ret;
17092d4238f5SKrzysztof Kazimierczak 	int i;
17102d4238f5SKrzysztof Kazimierczak 
17112d4238f5SKrzysztof Kazimierczak 	ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings);
17122d4238f5SKrzysztof Kazimierczak 	if (ret)
17132d4238f5SKrzysztof Kazimierczak 		return ret;
17142d4238f5SKrzysztof Kazimierczak 
17152d4238f5SKrzysztof Kazimierczak 	for (i = 0; i < vsi->num_xdp_txq; i++)
17162d4238f5SKrzysztof Kazimierczak 		vsi->xdp_rings[i]->xsk_umem = ice_xsk_umem(vsi->xdp_rings[i]);
17172d4238f5SKrzysztof Kazimierczak 
17182d4238f5SKrzysztof Kazimierczak 	return ret;
1719efc2214bSMaciej Fijalkowski }
1720efc2214bSMaciej Fijalkowski 
1721efc2214bSMaciej Fijalkowski /**
17229e4ab4c2SBrett Creeley  * ice_intrl_usec_to_reg - convert interrupt rate limit to register value
17239e4ab4c2SBrett Creeley  * @intrl: interrupt rate limit in usecs
17249e4ab4c2SBrett Creeley  * @gran: interrupt rate limit granularity in usecs
17259e4ab4c2SBrett Creeley  *
17269e4ab4c2SBrett Creeley  * This function converts a decimal interrupt rate limit in usecs to the format
17279e4ab4c2SBrett Creeley  * expected by firmware.
17289e4ab4c2SBrett Creeley  */
1729b9c8bb06SBrett Creeley u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran)
17309e4ab4c2SBrett Creeley {
17319e4ab4c2SBrett Creeley 	u32 val = intrl / gran;
17329e4ab4c2SBrett Creeley 
17339e4ab4c2SBrett Creeley 	if (val)
17349e4ab4c2SBrett Creeley 		return val | GLINT_RATE_INTRL_ENA_M;
17359e4ab4c2SBrett Creeley 	return 0;
17369e4ab4c2SBrett Creeley }
17379e4ab4c2SBrett Creeley 
17389e4ab4c2SBrett Creeley /**
173972adf242SAnirudh Venkataramanan  * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW
174072adf242SAnirudh Venkataramanan  * @vsi: the VSI being configured
1741047e52c0SAnirudh Venkataramanan  *
1742047e52c0SAnirudh Venkataramanan  * This configures MSIX mode interrupts for the PF VSI, and should not be used
1743047e52c0SAnirudh Venkataramanan  * for the VF VSI.
174472adf242SAnirudh Venkataramanan  */
174572adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi)
174672adf242SAnirudh Venkataramanan {
174772adf242SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
174872adf242SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
174988865fc4SKarol Kolacinski 	u16 txq = 0, rxq = 0;
1750d2b464a7SBrett Creeley 	int i, q;
175172adf242SAnirudh Venkataramanan 
1752b07833a0SBrett Creeley 	for (i = 0; i < vsi->num_q_vectors; i++) {
175372adf242SAnirudh Venkataramanan 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
1754b07833a0SBrett Creeley 		u16 reg_idx = q_vector->reg_idx;
175572adf242SAnirudh Venkataramanan 
1756b07833a0SBrett Creeley 		ice_cfg_itr(hw, q_vector);
17579e4ab4c2SBrett Creeley 
1758b07833a0SBrett Creeley 		wr32(hw, GLINT_RATE(reg_idx),
17599e4ab4c2SBrett Creeley 		     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
176072adf242SAnirudh Venkataramanan 
176172adf242SAnirudh Venkataramanan 		/* Both Transmit Queue Interrupt Cause Control register
176272adf242SAnirudh Venkataramanan 		 * and Receive Queue Interrupt Cause control register
176372adf242SAnirudh Venkataramanan 		 * expects MSIX_INDX field to be the vector index
176472adf242SAnirudh Venkataramanan 		 * within the function space and not the absolute
176572adf242SAnirudh Venkataramanan 		 * vector index across PF or across device.
176672adf242SAnirudh Venkataramanan 		 * For SR-IOV VF VSIs queue vector index always starts
176772adf242SAnirudh Venkataramanan 		 * with 1 since first vector index(0) is used for OICR
176872adf242SAnirudh Venkataramanan 		 * in VF space. Since VMDq and other PF VSIs are within
176972adf242SAnirudh Venkataramanan 		 * the PF function space, use the vector index that is
177072adf242SAnirudh Venkataramanan 		 * tracked for this PF.
177172adf242SAnirudh Venkataramanan 		 */
177272adf242SAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_tx; q++) {
1773047e52c0SAnirudh Venkataramanan 			ice_cfg_txq_interrupt(vsi, txq, reg_idx,
1774047e52c0SAnirudh Venkataramanan 					      q_vector->tx.itr_idx);
177572adf242SAnirudh Venkataramanan 			txq++;
177672adf242SAnirudh Venkataramanan 		}
177772adf242SAnirudh Venkataramanan 
177872adf242SAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_rx; q++) {
1779047e52c0SAnirudh Venkataramanan 			ice_cfg_rxq_interrupt(vsi, rxq, reg_idx,
1780047e52c0SAnirudh Venkataramanan 					      q_vector->rx.itr_idx);
178172adf242SAnirudh Venkataramanan 			rxq++;
178272adf242SAnirudh Venkataramanan 		}
178372adf242SAnirudh Venkataramanan 	}
178472adf242SAnirudh Venkataramanan }
178572adf242SAnirudh Venkataramanan 
178672adf242SAnirudh Venkataramanan /**
178745d3d428SAnirudh Venkataramanan  * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
178845d3d428SAnirudh Venkataramanan  * @vsi: the VSI being changed
178945d3d428SAnirudh Venkataramanan  */
179045d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
179145d3d428SAnirudh Venkataramanan {
179245d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
1793198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
179445d3d428SAnirudh Venkataramanan 	enum ice_status status;
1795198a666aSBruce Allan 	int ret = 0;
1796198a666aSBruce Allan 
17979efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
1798198a666aSBruce Allan 	if (!ctxt)
1799198a666aSBruce Allan 		return -ENOMEM;
180045d3d428SAnirudh Venkataramanan 
180145d3d428SAnirudh Venkataramanan 	/* Here we are configuring the VSI to let the driver add VLAN tags by
180245d3d428SAnirudh Venkataramanan 	 * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
180345d3d428SAnirudh Venkataramanan 	 * insertion happens in the Tx hot path, in ice_tx_map.
180445d3d428SAnirudh Venkataramanan 	 */
1805198a666aSBruce Allan 	ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
180645d3d428SAnirudh Venkataramanan 
1807e80e76dbSTony Nguyen 	/* Preserve existing VLAN strip setting */
1808e80e76dbSTony Nguyen 	ctxt->info.vlan_flags |= (vsi->info.vlan_flags &
1809e80e76dbSTony Nguyen 				  ICE_AQ_VSI_VLAN_EMOD_M);
1810e80e76dbSTony Nguyen 
1811198a666aSBruce Allan 	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
181245d3d428SAnirudh Venkataramanan 
1813198a666aSBruce Allan 	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
181445d3d428SAnirudh Venkataramanan 	if (status) {
18150fee3577SLihong Yang 		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %s aq_err %s\n",
18160fee3577SLihong Yang 			ice_stat_str(status),
18170fee3577SLihong Yang 			ice_aq_str(hw->adminq.sq_last_status));
1818198a666aSBruce Allan 		ret = -EIO;
1819198a666aSBruce Allan 		goto out;
182045d3d428SAnirudh Venkataramanan 	}
182145d3d428SAnirudh Venkataramanan 
1822198a666aSBruce Allan 	vsi->info.vlan_flags = ctxt->info.vlan_flags;
1823198a666aSBruce Allan out:
18249efe35d0STony Nguyen 	kfree(ctxt);
1825198a666aSBruce Allan 	return ret;
182645d3d428SAnirudh Venkataramanan }
182745d3d428SAnirudh Venkataramanan 
182845d3d428SAnirudh Venkataramanan /**
182945d3d428SAnirudh Venkataramanan  * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
183045d3d428SAnirudh Venkataramanan  * @vsi: the VSI being changed
183145d3d428SAnirudh Venkataramanan  * @ena: boolean value indicating if this is a enable or disable request
183245d3d428SAnirudh Venkataramanan  */
183345d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
183445d3d428SAnirudh Venkataramanan {
183545d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
1836198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
183745d3d428SAnirudh Venkataramanan 	enum ice_status status;
1838198a666aSBruce Allan 	int ret = 0;
1839198a666aSBruce Allan 
184019608275SBrett Creeley 	/* do not allow modifying VLAN stripping when a port VLAN is configured
184119608275SBrett Creeley 	 * on this VSI
184219608275SBrett Creeley 	 */
184319608275SBrett Creeley 	if (vsi->info.pvid)
184419608275SBrett Creeley 		return 0;
184519608275SBrett Creeley 
18469efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
1847198a666aSBruce Allan 	if (!ctxt)
1848198a666aSBruce Allan 		return -ENOMEM;
184945d3d428SAnirudh Venkataramanan 
185045d3d428SAnirudh Venkataramanan 	/* Here we are configuring what the VSI should do with the VLAN tag in
185145d3d428SAnirudh Venkataramanan 	 * the Rx packet. We can either leave the tag in the packet or put it in
185245d3d428SAnirudh Venkataramanan 	 * the Rx descriptor.
185345d3d428SAnirudh Venkataramanan 	 */
1854198a666aSBruce Allan 	if (ena)
185545d3d428SAnirudh Venkataramanan 		/* Strip VLAN tag from Rx packet and put it in the desc */
1856198a666aSBruce Allan 		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
1857198a666aSBruce Allan 	else
185845d3d428SAnirudh Venkataramanan 		/* Disable stripping. Leave tag in packet */
1859198a666aSBruce Allan 		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
186045d3d428SAnirudh Venkataramanan 
186145d3d428SAnirudh Venkataramanan 	/* Allow all packets untagged/tagged */
1862198a666aSBruce Allan 	ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
186345d3d428SAnirudh Venkataramanan 
1864198a666aSBruce Allan 	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
186545d3d428SAnirudh Venkataramanan 
1866198a666aSBruce Allan 	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
186745d3d428SAnirudh Venkataramanan 	if (status) {
18680fee3577SLihong Yang 		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %s aq_err %s\n",
18690fee3577SLihong Yang 			ena, ice_stat_str(status),
18700fee3577SLihong Yang 			ice_aq_str(hw->adminq.sq_last_status));
1871198a666aSBruce Allan 		ret = -EIO;
1872198a666aSBruce Allan 		goto out;
187345d3d428SAnirudh Venkataramanan 	}
187445d3d428SAnirudh Venkataramanan 
1875198a666aSBruce Allan 	vsi->info.vlan_flags = ctxt->info.vlan_flags;
1876198a666aSBruce Allan out:
18779efe35d0STony Nguyen 	kfree(ctxt);
1878198a666aSBruce Allan 	return ret;
187945d3d428SAnirudh Venkataramanan }
188072adf242SAnirudh Venkataramanan 
188172adf242SAnirudh Venkataramanan /**
188213a6233bSBrett Creeley  * ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings
188313a6233bSBrett Creeley  * @vsi: the VSI whose rings are to be enabled
188472adf242SAnirudh Venkataramanan  *
188572adf242SAnirudh Venkataramanan  * Returns 0 on success and a negative value on error
188672adf242SAnirudh Venkataramanan  */
188713a6233bSBrett Creeley int ice_vsi_start_all_rx_rings(struct ice_vsi *vsi)
188872adf242SAnirudh Venkataramanan {
188913a6233bSBrett Creeley 	return ice_vsi_ctrl_all_rx_rings(vsi, true);
189072adf242SAnirudh Venkataramanan }
189172adf242SAnirudh Venkataramanan 
189272adf242SAnirudh Venkataramanan /**
189313a6233bSBrett Creeley  * ice_vsi_stop_all_rx_rings - stop/disable all of a VSI's Rx rings
189413a6233bSBrett Creeley  * @vsi: the VSI whose rings are to be disabled
189572adf242SAnirudh Venkataramanan  *
189672adf242SAnirudh Venkataramanan  * Returns 0 on success and a negative value on error
189772adf242SAnirudh Venkataramanan  */
189813a6233bSBrett Creeley int ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi)
189972adf242SAnirudh Venkataramanan {
190013a6233bSBrett Creeley 	return ice_vsi_ctrl_all_rx_rings(vsi, false);
190172adf242SAnirudh Venkataramanan }
190272adf242SAnirudh Venkataramanan 
190372adf242SAnirudh Venkataramanan /**
1904d02f734cSMaciej Fijalkowski  * ice_vsi_stop_tx_rings - Disable Tx rings
1905d02f734cSMaciej Fijalkowski  * @vsi: the VSI being configured
1906d02f734cSMaciej Fijalkowski  * @rst_src: reset source
1907d02f734cSMaciej Fijalkowski  * @rel_vmvf_num: Relative ID of VF/VM
1908d02f734cSMaciej Fijalkowski  * @rings: Tx ring array to be stopped
1909d02f734cSMaciej Fijalkowski  */
1910d02f734cSMaciej Fijalkowski static int
1911d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
1912d02f734cSMaciej Fijalkowski 		      u16 rel_vmvf_num, struct ice_ring **rings)
1913d02f734cSMaciej Fijalkowski {
1914e75d1b2cSMaciej Fijalkowski 	u16 q_idx;
1915d02f734cSMaciej Fijalkowski 
1916d02f734cSMaciej Fijalkowski 	if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS)
1917d02f734cSMaciej Fijalkowski 		return -EINVAL;
1918d02f734cSMaciej Fijalkowski 
1919e75d1b2cSMaciej Fijalkowski 	for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) {
1920d02f734cSMaciej Fijalkowski 		struct ice_txq_meta txq_meta = { };
1921e75d1b2cSMaciej Fijalkowski 		int status;
1922d02f734cSMaciej Fijalkowski 
1923d02f734cSMaciej Fijalkowski 		if (!rings || !rings[q_idx])
1924d02f734cSMaciej Fijalkowski 			return -EINVAL;
1925d02f734cSMaciej Fijalkowski 
1926d02f734cSMaciej Fijalkowski 		ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta);
1927e75d1b2cSMaciej Fijalkowski 		status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num,
1928d02f734cSMaciej Fijalkowski 					      rings[q_idx], &txq_meta);
1929d02f734cSMaciej Fijalkowski 
1930d02f734cSMaciej Fijalkowski 		if (status)
1931d02f734cSMaciej Fijalkowski 			return status;
1932bb87ee0eSAnirudh Venkataramanan 	}
193372adf242SAnirudh Venkataramanan 
1934d02f734cSMaciej Fijalkowski 	return 0;
193572adf242SAnirudh Venkataramanan }
19365153a18eSAnirudh Venkataramanan 
19375153a18eSAnirudh Venkataramanan /**
193803f7a986SAnirudh Venkataramanan  * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings
193903f7a986SAnirudh Venkataramanan  * @vsi: the VSI being configured
194003f7a986SAnirudh Venkataramanan  * @rst_src: reset source
1941f9867df6SAnirudh Venkataramanan  * @rel_vmvf_num: Relative ID of VF/VM
194203f7a986SAnirudh Venkataramanan  */
1943c8b7abddSBruce Allan int
1944c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
1945c8b7abddSBruce Allan 			  u16 rel_vmvf_num)
194603f7a986SAnirudh Venkataramanan {
1947d02f734cSMaciej Fijalkowski 	return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings);
194803f7a986SAnirudh Venkataramanan }
194903f7a986SAnirudh Venkataramanan 
195003f7a986SAnirudh Venkataramanan /**
1951efc2214bSMaciej Fijalkowski  * ice_vsi_stop_xdp_tx_rings - Disable XDP Tx rings
1952efc2214bSMaciej Fijalkowski  * @vsi: the VSI being configured
1953efc2214bSMaciej Fijalkowski  */
1954efc2214bSMaciej Fijalkowski int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi)
1955efc2214bSMaciej Fijalkowski {
1956efc2214bSMaciej Fijalkowski 	return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings);
1957efc2214bSMaciej Fijalkowski }
1958efc2214bSMaciej Fijalkowski 
1959efc2214bSMaciej Fijalkowski /**
196042f3efefSBrett Creeley  * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not
196142f3efefSBrett Creeley  * @vsi: VSI to check whether or not VLAN pruning is enabled.
196242f3efefSBrett Creeley  *
1963345be791SBrett Creeley  * returns true if Rx VLAN pruning is enabled and false otherwise.
196442f3efefSBrett Creeley  */
196542f3efefSBrett Creeley bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi)
196642f3efefSBrett Creeley {
196742f3efefSBrett Creeley 	if (!vsi)
196842f3efefSBrett Creeley 		return false;
196942f3efefSBrett Creeley 
1970345be791SBrett Creeley 	return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA);
197142f3efefSBrett Creeley }
197242f3efefSBrett Creeley 
197342f3efefSBrett Creeley /**
19745153a18eSAnirudh Venkataramanan  * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
19755153a18eSAnirudh Venkataramanan  * @vsi: VSI to enable or disable VLAN pruning on
19765153a18eSAnirudh Venkataramanan  * @ena: set to true to enable VLAN pruning and false to disable it
19775eda8afdSAkeem G Abodunrin  * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
19785153a18eSAnirudh Venkataramanan  *
19795153a18eSAnirudh Venkataramanan  * returns 0 if VSI is updated, negative otherwise
19805153a18eSAnirudh Venkataramanan  */
19815eda8afdSAkeem G Abodunrin int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
19825153a18eSAnirudh Venkataramanan {
19835153a18eSAnirudh Venkataramanan 	struct ice_vsi_ctx *ctxt;
1984819d8998SJesse Brandeburg 	struct ice_pf *pf;
19855153a18eSAnirudh Venkataramanan 	int status;
19865153a18eSAnirudh Venkataramanan 
19875153a18eSAnirudh Venkataramanan 	if (!vsi)
19885153a18eSAnirudh Venkataramanan 		return -EINVAL;
19895153a18eSAnirudh Venkataramanan 
1990819d8998SJesse Brandeburg 	pf = vsi->back;
19919efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
19925153a18eSAnirudh Venkataramanan 	if (!ctxt)
19935153a18eSAnirudh Venkataramanan 		return -ENOMEM;
19945153a18eSAnirudh Venkataramanan 
19955153a18eSAnirudh Venkataramanan 	ctxt->info = vsi->info;
19965153a18eSAnirudh Venkataramanan 
1997cd6d6b83SBrett Creeley 	if (ena)
19985153a18eSAnirudh Venkataramanan 		ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
1999cd6d6b83SBrett Creeley 	else
20005153a18eSAnirudh Venkataramanan 		ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
20015153a18eSAnirudh Venkataramanan 
20025eda8afdSAkeem G Abodunrin 	if (!vlan_promisc)
20035eda8afdSAkeem G Abodunrin 		ctxt->info.valid_sections =
2004cd6d6b83SBrett Creeley 			cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
20055726ca0eSAnirudh Venkataramanan 
2006819d8998SJesse Brandeburg 	status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL);
20075153a18eSAnirudh Venkataramanan 	if (status) {
20080fee3577SLihong Yang 		netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %s, aq_err = %s\n",
20090fee3577SLihong Yang 			   ena ? "En" : "Dis", vsi->idx, vsi->vsi_num,
20100fee3577SLihong Yang 			   ice_stat_str(status),
20110fee3577SLihong Yang 			   ice_aq_str(pf->hw.adminq.sq_last_status));
20125153a18eSAnirudh Venkataramanan 		goto err_out;
20135153a18eSAnirudh Venkataramanan 	}
20145153a18eSAnirudh Venkataramanan 
20155153a18eSAnirudh Venkataramanan 	vsi->info.sw_flags2 = ctxt->info.sw_flags2;
20165153a18eSAnirudh Venkataramanan 
20179efe35d0STony Nguyen 	kfree(ctxt);
20185153a18eSAnirudh Venkataramanan 	return 0;
20195153a18eSAnirudh Venkataramanan 
20205153a18eSAnirudh Venkataramanan err_out:
20219efe35d0STony Nguyen 	kfree(ctxt);
20225153a18eSAnirudh Venkataramanan 	return -EIO;
20235153a18eSAnirudh Venkataramanan }
20245153a18eSAnirudh Venkataramanan 
20257b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
20267b9ffc76SAnirudh Venkataramanan {
20277b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *cfg = &vsi->port_info->local_dcbx_cfg;
20287b9ffc76SAnirudh Venkataramanan 
20297b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg);
20307b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg);
20317b9ffc76SAnirudh Venkataramanan }
20327b9ffc76SAnirudh Venkataramanan 
20335153a18eSAnirudh Venkataramanan /**
2034b07833a0SBrett Creeley  * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors
2035b07833a0SBrett Creeley  * @vsi: VSI to set the q_vectors register index on
2036b07833a0SBrett Creeley  */
2037b07833a0SBrett Creeley static int
2038b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
2039b07833a0SBrett Creeley {
2040b07833a0SBrett Creeley 	u16 i;
2041b07833a0SBrett Creeley 
2042b07833a0SBrett Creeley 	if (!vsi || !vsi->q_vectors)
2043b07833a0SBrett Creeley 		return -EINVAL;
2044b07833a0SBrett Creeley 
2045b07833a0SBrett Creeley 	ice_for_each_q_vector(vsi, i) {
2046b07833a0SBrett Creeley 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
2047b07833a0SBrett Creeley 
2048b07833a0SBrett Creeley 		if (!q_vector) {
204919cce2c6SAnirudh Venkataramanan 			dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n",
2050b07833a0SBrett Creeley 				i, vsi->vsi_num);
2051b07833a0SBrett Creeley 			goto clear_reg_idx;
2052b07833a0SBrett Creeley 		}
2053b07833a0SBrett Creeley 
2054cbe66bfeSBrett Creeley 		if (vsi->type == ICE_VSI_VF) {
2055cbe66bfeSBrett Creeley 			struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
2056cbe66bfeSBrett Creeley 
2057cbe66bfeSBrett Creeley 			q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
2058cbe66bfeSBrett Creeley 		} else {
2059cbe66bfeSBrett Creeley 			q_vector->reg_idx =
2060cbe66bfeSBrett Creeley 				q_vector->v_idx + vsi->base_vector;
2061cbe66bfeSBrett Creeley 		}
2062b07833a0SBrett Creeley 	}
2063b07833a0SBrett Creeley 
2064b07833a0SBrett Creeley 	return 0;
2065b07833a0SBrett Creeley 
2066b07833a0SBrett Creeley clear_reg_idx:
2067b07833a0SBrett Creeley 	ice_for_each_q_vector(vsi, i) {
2068b07833a0SBrett Creeley 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
2069b07833a0SBrett Creeley 
2070b07833a0SBrett Creeley 		if (q_vector)
2071b07833a0SBrett Creeley 			q_vector->reg_idx = 0;
2072b07833a0SBrett Creeley 	}
2073b07833a0SBrett Creeley 
2074b07833a0SBrett Creeley 	return -EINVAL;
2075b07833a0SBrett Creeley }
2076b07833a0SBrett Creeley 
2077b07833a0SBrett Creeley /**
20782e0e6228SDave Ertman  * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
20792e0e6228SDave Ertman  * @vsi: the VSI being configured
20802e0e6228SDave Ertman  * @tx: bool to determine Tx or Rx rule
20812e0e6228SDave Ertman  * @create: bool to determine create or remove Rule
20822e0e6228SDave Ertman  */
20832e0e6228SDave Ertman void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create)
20842e0e6228SDave Ertman {
20851b8f15b6SMichal Swiatkowski 	enum ice_status (*eth_fltr)(struct ice_vsi *v, u16 type, u16 flag,
20861b8f15b6SMichal Swiatkowski 				    enum ice_sw_fwd_act_type act);
20872e0e6228SDave Ertman 	struct ice_pf *pf = vsi->back;
20882e0e6228SDave Ertman 	enum ice_status status;
20894015d11eSBrett Creeley 	struct device *dev;
20902e0e6228SDave Ertman 
20914015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
20921b8f15b6SMichal Swiatkowski 	eth_fltr = create ? ice_fltr_add_eth : ice_fltr_remove_eth;
20932e0e6228SDave Ertman 
20941b8f15b6SMichal Swiatkowski 	if (tx)
20951b8f15b6SMichal Swiatkowski 		status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_TX,
20961b8f15b6SMichal Swiatkowski 				  ICE_DROP_PACKET);
20972e0e6228SDave Ertman 	else
20981b8f15b6SMichal Swiatkowski 		status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_RX, ICE_FWD_TO_VSI);
20992e0e6228SDave Ertman 
21002e0e6228SDave Ertman 	if (status)
21010fee3577SLihong Yang 		dev_err(dev, "Fail %s %s LLDP rule on VSI %i error: %s\n",
21022e0e6228SDave Ertman 			create ? "adding" : "removing", tx ? "TX" : "RX",
21030fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
21042e0e6228SDave Ertman }
21052e0e6228SDave Ertman 
2106d95276ceSAkeem G Abodunrin /**
210737bb8390SAnirudh Venkataramanan  * ice_vsi_setup - Set up a VSI by a given type
210837bb8390SAnirudh Venkataramanan  * @pf: board private structure
210937bb8390SAnirudh Venkataramanan  * @pi: pointer to the port_info instance
21106dae8aa0SBruce Allan  * @vsi_type: VSI type
2111f9867df6SAnirudh Venkataramanan  * @vf_id: defines VF ID to which this VSI connects. This field is meant to be
211237bb8390SAnirudh Venkataramanan  *         used only for ICE_VSI_VF VSI type. For other VSI types, should
211337bb8390SAnirudh Venkataramanan  *         fill-in ICE_INVAL_VFID as input.
211437bb8390SAnirudh Venkataramanan  *
211537bb8390SAnirudh Venkataramanan  * This allocates the sw VSI structure and its queue resources.
211637bb8390SAnirudh Venkataramanan  *
211737bb8390SAnirudh Venkataramanan  * Returns pointer to the successfully allocated and configured VSI sw struct on
211837bb8390SAnirudh Venkataramanan  * success, NULL on failure.
211937bb8390SAnirudh Venkataramanan  */
212037bb8390SAnirudh Venkataramanan struct ice_vsi *
212137bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
21226dae8aa0SBruce Allan 	      enum ice_vsi_type vsi_type, u16 vf_id)
212337bb8390SAnirudh Venkataramanan {
212437bb8390SAnirudh Venkataramanan 	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
21254015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
2126d31530e8SAkeem G Abodunrin 	enum ice_status status;
212737bb8390SAnirudh Venkataramanan 	struct ice_vsi *vsi;
212837bb8390SAnirudh Venkataramanan 	int ret, i;
212937bb8390SAnirudh Venkataramanan 
21306dae8aa0SBruce Allan 	if (vsi_type == ICE_VSI_VF)
21316dae8aa0SBruce Allan 		vsi = ice_vsi_alloc(pf, vsi_type, vf_id);
21325743020dSAkeem G Abodunrin 	else
21336dae8aa0SBruce Allan 		vsi = ice_vsi_alloc(pf, vsi_type, ICE_INVAL_VFID);
21345743020dSAkeem G Abodunrin 
213537bb8390SAnirudh Venkataramanan 	if (!vsi) {
213637bb8390SAnirudh Venkataramanan 		dev_err(dev, "could not allocate VSI\n");
213737bb8390SAnirudh Venkataramanan 		return NULL;
213837bb8390SAnirudh Venkataramanan 	}
213937bb8390SAnirudh Venkataramanan 
214037bb8390SAnirudh Venkataramanan 	vsi->port_info = pi;
214137bb8390SAnirudh Venkataramanan 	vsi->vsw = pf->first_sw;
2142d95276ceSAkeem G Abodunrin 	if (vsi->type == ICE_VSI_PF)
2143d95276ceSAkeem G Abodunrin 		vsi->ethtype = ETH_P_PAUSE;
2144d95276ceSAkeem G Abodunrin 
21458ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
21468ede0178SAnirudh Venkataramanan 		vsi->vf_id = vf_id;
214737bb8390SAnirudh Venkataramanan 
2148148beb61SHenry Tieman 	ice_alloc_fd_res(vsi);
2149148beb61SHenry Tieman 
215037bb8390SAnirudh Venkataramanan 	if (ice_vsi_get_qs(vsi)) {
215137bb8390SAnirudh Venkataramanan 		dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n",
215237bb8390SAnirudh Venkataramanan 			vsi->idx);
2153148beb61SHenry Tieman 		goto unroll_vsi_alloc;
215437bb8390SAnirudh Venkataramanan 	}
215537bb8390SAnirudh Venkataramanan 
215637bb8390SAnirudh Venkataramanan 	/* set RSS capabilities */
215737bb8390SAnirudh Venkataramanan 	ice_vsi_set_rss_params(vsi);
215837bb8390SAnirudh Venkataramanan 
2159f9867df6SAnirudh Venkataramanan 	/* set TC configuration */
2160c5a2a4a3SUsha Ketineni 	ice_vsi_set_tc_cfg(vsi);
2161c5a2a4a3SUsha Ketineni 
216237bb8390SAnirudh Venkataramanan 	/* create the VSI */
216387324e74SHenry Tieman 	ret = ice_vsi_init(vsi, true);
216437bb8390SAnirudh Venkataramanan 	if (ret)
216537bb8390SAnirudh Venkataramanan 		goto unroll_get_qs;
216637bb8390SAnirudh Venkataramanan 
216737bb8390SAnirudh Venkataramanan 	switch (vsi->type) {
2168148beb61SHenry Tieman 	case ICE_VSI_CTRL:
216937bb8390SAnirudh Venkataramanan 	case ICE_VSI_PF:
217037bb8390SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
217137bb8390SAnirudh Venkataramanan 		if (ret)
217237bb8390SAnirudh Venkataramanan 			goto unroll_vsi_init;
217337bb8390SAnirudh Venkataramanan 
217437bb8390SAnirudh Venkataramanan 		ret = ice_vsi_setup_vector_base(vsi);
217537bb8390SAnirudh Venkataramanan 		if (ret)
217637bb8390SAnirudh Venkataramanan 			goto unroll_alloc_q_vector;
217737bb8390SAnirudh Venkataramanan 
2178b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2179b07833a0SBrett Creeley 		if (ret)
2180b07833a0SBrett Creeley 			goto unroll_vector_base;
2181b07833a0SBrett Creeley 
218237bb8390SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
218337bb8390SAnirudh Venkataramanan 		if (ret)
218437bb8390SAnirudh Venkataramanan 			goto unroll_vector_base;
218537bb8390SAnirudh Venkataramanan 
218642f3efefSBrett Creeley 		/* Always add VLAN ID 0 switch rule by default. This is needed
218742f3efefSBrett Creeley 		 * in order to allow all untagged and 0 tagged priority traffic
218842f3efefSBrett Creeley 		 * if Rx VLAN pruning is enabled. Also there are cases where we
218942f3efefSBrett Creeley 		 * don't get the call to add VLAN 0 via ice_vlan_rx_add_vid()
219042f3efefSBrett Creeley 		 * so this handles those cases (i.e. adding the PF to a bridge
219142f3efefSBrett Creeley 		 * without the 8021q module loaded).
219242f3efefSBrett Creeley 		 */
21931b8f15b6SMichal Swiatkowski 		ret = ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI);
219442f3efefSBrett Creeley 		if (ret)
219542f3efefSBrett Creeley 			goto unroll_clear_rings;
219642f3efefSBrett Creeley 
219737bb8390SAnirudh Venkataramanan 		ice_vsi_map_rings_to_vectors(vsi);
219837bb8390SAnirudh Venkataramanan 
2199148beb61SHenry Tieman 		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
2200148beb61SHenry Tieman 		if (vsi->type != ICE_VSI_CTRL)
2201148beb61SHenry Tieman 			/* Do not exit if configuring RSS had an issue, at
2202148beb61SHenry Tieman 			 * least receive traffic on first queue. Hence no
2203148beb61SHenry Tieman 			 * need to capture return value
220437bb8390SAnirudh Venkataramanan 			 */
2205c90ed40cSTony Nguyen 			if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
220637bb8390SAnirudh Venkataramanan 				ice_vsi_cfg_rss_lut_key(vsi);
2207c90ed40cSTony Nguyen 				ice_vsi_set_rss_flow_fld(vsi);
2208c90ed40cSTony Nguyen 			}
220928bf2672SBrett Creeley 		ice_init_arfs(vsi);
221037bb8390SAnirudh Venkataramanan 		break;
22118ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
22128ede0178SAnirudh Venkataramanan 		/* VF driver will take care of creating netdev for this type and
22138ede0178SAnirudh Venkataramanan 		 * map queues to vectors through Virtchnl, PF driver only
22148ede0178SAnirudh Venkataramanan 		 * creates a VSI and corresponding structures for bookkeeping
22158ede0178SAnirudh Venkataramanan 		 * purpose
22168ede0178SAnirudh Venkataramanan 		 */
22178ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
22188ede0178SAnirudh Venkataramanan 		if (ret)
22198ede0178SAnirudh Venkataramanan 			goto unroll_vsi_init;
22208ede0178SAnirudh Venkataramanan 
22218ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
22228ede0178SAnirudh Venkataramanan 		if (ret)
22238ede0178SAnirudh Venkataramanan 			goto unroll_alloc_q_vector;
22248ede0178SAnirudh Venkataramanan 
2225b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2226b07833a0SBrett Creeley 		if (ret)
2227b07833a0SBrett Creeley 			goto unroll_vector_base;
2228b07833a0SBrett Creeley 
22293a9e32bbSMd Fahad Iqbal Polash 		/* Do not exit if configuring RSS had an issue, at least
22303a9e32bbSMd Fahad Iqbal Polash 		 * receive traffic on first queue. Hence no need to capture
22313a9e32bbSMd Fahad Iqbal Polash 		 * return value
22323a9e32bbSMd Fahad Iqbal Polash 		 */
22331c01c8c6SMd Fahad Iqbal Polash 		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
22343a9e32bbSMd Fahad Iqbal Polash 			ice_vsi_cfg_rss_lut_key(vsi);
22351c01c8c6SMd Fahad Iqbal Polash 			ice_vsi_set_vf_rss_flow_fld(vsi);
22361c01c8c6SMd Fahad Iqbal Polash 		}
22378ede0178SAnirudh Venkataramanan 		break;
22380e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
22390e674aebSAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
22400e674aebSAnirudh Venkataramanan 		if (ret)
22410e674aebSAnirudh Venkataramanan 			goto unroll_vsi_init;
22420e674aebSAnirudh Venkataramanan 		break;
224337bb8390SAnirudh Venkataramanan 	default:
2244df17b7e0SAnirudh Venkataramanan 		/* clean up the resources and exit */
224537bb8390SAnirudh Venkataramanan 		goto unroll_vsi_init;
224637bb8390SAnirudh Venkataramanan 	}
224737bb8390SAnirudh Venkataramanan 
224837bb8390SAnirudh Venkataramanan 	/* configure VSI nodes based on number of queues and TC's */
224937bb8390SAnirudh Venkataramanan 	for (i = 0; i < vsi->tc_cfg.numtc; i++)
2250d5a46359SAkeem G Abodunrin 		max_txqs[i] = vsi->alloc_txq;
225137bb8390SAnirudh Venkataramanan 
2252d31530e8SAkeem G Abodunrin 	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
22534fb33f31SAnirudh Venkataramanan 				 max_txqs);
2254d31530e8SAkeem G Abodunrin 	if (status) {
22550fee3577SLihong Yang 		dev_err(dev, "VSI %d failed lan queue config, error %s\n",
22560fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
225737bb8390SAnirudh Venkataramanan 		goto unroll_vector_base;
225837bb8390SAnirudh Venkataramanan 	}
225937bb8390SAnirudh Venkataramanan 
2260d95276ceSAkeem G Abodunrin 	/* Add switch rule to drop all Tx Flow Control Frames, of look up
2261d95276ceSAkeem G Abodunrin 	 * type ETHERTYPE from VSIs, and restrict malicious VF from sending
2262d95276ceSAkeem G Abodunrin 	 * out PAUSE or PFC frames. If enabled, FW can still send FC frames.
2263d95276ceSAkeem G Abodunrin 	 * The rule is added once for PF VSI in order to create appropriate
2264d95276ceSAkeem G Abodunrin 	 * recipe, since VSI/VSI list is ignored with drop action...
2265241c8cf0SPaul Greenwalt 	 * Also add rules to handle LLDP Tx packets.  Tx LLDP packets need to
2266241c8cf0SPaul Greenwalt 	 * be dropped so that VFs cannot send LLDP packets to reconfig DCB
2267241c8cf0SPaul Greenwalt 	 * settings in the HW.
2268d95276ceSAkeem G Abodunrin 	 */
2269241c8cf0SPaul Greenwalt 	if (!ice_is_safe_mode(pf))
22702e0e6228SDave Ertman 		if (vsi->type == ICE_VSI_PF) {
22711b8f15b6SMichal Swiatkowski 			ice_fltr_add_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX,
22721b8f15b6SMichal Swiatkowski 					 ICE_DROP_PACKET);
22732e0e6228SDave Ertman 			ice_cfg_sw_lldp(vsi, true, true);
2274462acf6aSTony Nguyen 		}
22752e0e6228SDave Ertman 
227637bb8390SAnirudh Venkataramanan 	return vsi;
227737bb8390SAnirudh Venkataramanan 
227842f3efefSBrett Creeley unroll_clear_rings:
227942f3efefSBrett Creeley 	ice_vsi_clear_rings(vsi);
228037bb8390SAnirudh Venkataramanan unroll_vector_base:
2281eb0208ecSPreethi Banala 	/* reclaim SW interrupts back to the common pool */
2282cbe66bfeSBrett Creeley 	ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
2283eb0208ecSPreethi Banala 	pf->num_avail_sw_msix += vsi->num_q_vectors;
228437bb8390SAnirudh Venkataramanan unroll_alloc_q_vector:
228537bb8390SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
228637bb8390SAnirudh Venkataramanan unroll_vsi_init:
228737bb8390SAnirudh Venkataramanan 	ice_vsi_delete(vsi);
228837bb8390SAnirudh Venkataramanan unroll_get_qs:
228937bb8390SAnirudh Venkataramanan 	ice_vsi_put_qs(vsi);
2290148beb61SHenry Tieman unroll_vsi_alloc:
229137bb8390SAnirudh Venkataramanan 	ice_vsi_clear(vsi);
229237bb8390SAnirudh Venkataramanan 
229337bb8390SAnirudh Venkataramanan 	return NULL;
229437bb8390SAnirudh Venkataramanan }
229537bb8390SAnirudh Venkataramanan 
229637bb8390SAnirudh Venkataramanan /**
22975153a18eSAnirudh Venkataramanan  * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW
22985153a18eSAnirudh Venkataramanan  * @vsi: the VSI being cleaned up
22995153a18eSAnirudh Venkataramanan  */
23005153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi)
23015153a18eSAnirudh Venkataramanan {
23025153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
23035153a18eSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
23045153a18eSAnirudh Venkataramanan 	u32 txq = 0;
23055153a18eSAnirudh Venkataramanan 	u32 rxq = 0;
23065153a18eSAnirudh Venkataramanan 	int i, q;
23075153a18eSAnirudh Venkataramanan 
2308cbe66bfeSBrett Creeley 	for (i = 0; i < vsi->num_q_vectors; i++) {
23095153a18eSAnirudh Venkataramanan 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
2310cbe66bfeSBrett Creeley 		u16 reg_idx = q_vector->reg_idx;
23115153a18eSAnirudh Venkataramanan 
2312cbe66bfeSBrett Creeley 		wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0);
2313cbe66bfeSBrett Creeley 		wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0);
23145153a18eSAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_tx; q++) {
23155153a18eSAnirudh Venkataramanan 			wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0);
2316efc2214bSMaciej Fijalkowski 			if (ice_is_xdp_ena_vsi(vsi)) {
2317efc2214bSMaciej Fijalkowski 				u32 xdp_txq = txq + vsi->num_xdp_txq;
2318efc2214bSMaciej Fijalkowski 
2319efc2214bSMaciej Fijalkowski 				wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0);
2320efc2214bSMaciej Fijalkowski 			}
23215153a18eSAnirudh Venkataramanan 			txq++;
23225153a18eSAnirudh Venkataramanan 		}
23235153a18eSAnirudh Venkataramanan 
23245153a18eSAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_rx; q++) {
23255153a18eSAnirudh Venkataramanan 			wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0);
23265153a18eSAnirudh Venkataramanan 			rxq++;
23275153a18eSAnirudh Venkataramanan 		}
23285153a18eSAnirudh Venkataramanan 	}
23295153a18eSAnirudh Venkataramanan 
23305153a18eSAnirudh Venkataramanan 	ice_flush(hw);
23315153a18eSAnirudh Venkataramanan }
23325153a18eSAnirudh Venkataramanan 
23335153a18eSAnirudh Venkataramanan /**
23345153a18eSAnirudh Venkataramanan  * ice_vsi_free_irq - Free the IRQ association with the OS
23355153a18eSAnirudh Venkataramanan  * @vsi: the VSI being configured
23365153a18eSAnirudh Venkataramanan  */
23375153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi)
23385153a18eSAnirudh Venkataramanan {
23395153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2340cbe66bfeSBrett Creeley 	int base = vsi->base_vector;
23415153a18eSAnirudh Venkataramanan 	int i;
23425153a18eSAnirudh Venkataramanan 
23435153a18eSAnirudh Venkataramanan 	if (!vsi->q_vectors || !vsi->irqs_ready)
23445153a18eSAnirudh Venkataramanan 		return;
23455153a18eSAnirudh Venkataramanan 
2346eb0208ecSPreethi Banala 	ice_vsi_release_msix(vsi);
23478ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
23488ede0178SAnirudh Venkataramanan 		return;
2349eb0208ecSPreethi Banala 
23505153a18eSAnirudh Venkataramanan 	vsi->irqs_ready = false;
23510c2561c8SBrett Creeley 	ice_for_each_q_vector(vsi, i) {
23525153a18eSAnirudh Venkataramanan 		u16 vector = i + base;
23535153a18eSAnirudh Venkataramanan 		int irq_num;
23545153a18eSAnirudh Venkataramanan 
23555153a18eSAnirudh Venkataramanan 		irq_num = pf->msix_entries[vector].vector;
23565153a18eSAnirudh Venkataramanan 
23575153a18eSAnirudh Venkataramanan 		/* free only the irqs that were actually requested */
23585153a18eSAnirudh Venkataramanan 		if (!vsi->q_vectors[i] ||
23595153a18eSAnirudh Venkataramanan 		    !(vsi->q_vectors[i]->num_ring_tx ||
23605153a18eSAnirudh Venkataramanan 		      vsi->q_vectors[i]->num_ring_rx))
23615153a18eSAnirudh Venkataramanan 			continue;
23625153a18eSAnirudh Venkataramanan 
23635153a18eSAnirudh Venkataramanan 		/* clear the affinity notifier in the IRQ descriptor */
23645153a18eSAnirudh Venkataramanan 		irq_set_affinity_notifier(irq_num, NULL);
23655153a18eSAnirudh Venkataramanan 
23665153a18eSAnirudh Venkataramanan 		/* clear the affinity_mask in the IRQ descriptor */
23675153a18eSAnirudh Venkataramanan 		irq_set_affinity_hint(irq_num, NULL);
23685153a18eSAnirudh Venkataramanan 		synchronize_irq(irq_num);
23694015d11eSBrett Creeley 		devm_free_irq(ice_pf_to_dev(pf), irq_num, vsi->q_vectors[i]);
23705153a18eSAnirudh Venkataramanan 	}
23715153a18eSAnirudh Venkataramanan }
23725153a18eSAnirudh Venkataramanan 
23735153a18eSAnirudh Venkataramanan /**
23745153a18eSAnirudh Venkataramanan  * ice_vsi_free_tx_rings - Free Tx resources for VSI queues
23755153a18eSAnirudh Venkataramanan  * @vsi: the VSI having resources freed
23765153a18eSAnirudh Venkataramanan  */
23775153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi)
23785153a18eSAnirudh Venkataramanan {
23795153a18eSAnirudh Venkataramanan 	int i;
23805153a18eSAnirudh Venkataramanan 
23815153a18eSAnirudh Venkataramanan 	if (!vsi->tx_rings)
23825153a18eSAnirudh Venkataramanan 		return;
23835153a18eSAnirudh Venkataramanan 
23845153a18eSAnirudh Venkataramanan 	ice_for_each_txq(vsi, i)
23855153a18eSAnirudh Venkataramanan 		if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc)
23865153a18eSAnirudh Venkataramanan 			ice_free_tx_ring(vsi->tx_rings[i]);
23875153a18eSAnirudh Venkataramanan }
23885153a18eSAnirudh Venkataramanan 
23895153a18eSAnirudh Venkataramanan /**
23905153a18eSAnirudh Venkataramanan  * ice_vsi_free_rx_rings - Free Rx resources for VSI queues
23915153a18eSAnirudh Venkataramanan  * @vsi: the VSI having resources freed
23925153a18eSAnirudh Venkataramanan  */
23935153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi)
23945153a18eSAnirudh Venkataramanan {
23955153a18eSAnirudh Venkataramanan 	int i;
23965153a18eSAnirudh Venkataramanan 
23975153a18eSAnirudh Venkataramanan 	if (!vsi->rx_rings)
23985153a18eSAnirudh Venkataramanan 		return;
23995153a18eSAnirudh Venkataramanan 
24005153a18eSAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i)
24015153a18eSAnirudh Venkataramanan 		if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
24025153a18eSAnirudh Venkataramanan 			ice_free_rx_ring(vsi->rx_rings[i]);
24035153a18eSAnirudh Venkataramanan }
24045153a18eSAnirudh Venkataramanan 
24055153a18eSAnirudh Venkataramanan /**
240607309a0eSAnirudh Venkataramanan  * ice_vsi_close - Shut down a VSI
240707309a0eSAnirudh Venkataramanan  * @vsi: the VSI being shut down
240807309a0eSAnirudh Venkataramanan  */
240907309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi)
241007309a0eSAnirudh Venkataramanan {
241107309a0eSAnirudh Venkataramanan 	if (!test_and_set_bit(__ICE_DOWN, vsi->state))
241207309a0eSAnirudh Venkataramanan 		ice_down(vsi);
241307309a0eSAnirudh Venkataramanan 
241407309a0eSAnirudh Venkataramanan 	ice_vsi_free_irq(vsi);
241507309a0eSAnirudh Venkataramanan 	ice_vsi_free_tx_rings(vsi);
241607309a0eSAnirudh Venkataramanan 	ice_vsi_free_rx_rings(vsi);
241707309a0eSAnirudh Venkataramanan }
241807309a0eSAnirudh Venkataramanan 
241907309a0eSAnirudh Venkataramanan /**
24209d614b64SAnirudh Venkataramanan  * ice_ena_vsi - resume a VSI
24219d614b64SAnirudh Venkataramanan  * @vsi: the VSI being resume
24229d614b64SAnirudh Venkataramanan  * @locked: is the rtnl_lock already held
24239d614b64SAnirudh Venkataramanan  */
24249d614b64SAnirudh Venkataramanan int ice_ena_vsi(struct ice_vsi *vsi, bool locked)
24259d614b64SAnirudh Venkataramanan {
24269d614b64SAnirudh Venkataramanan 	int err = 0;
24279d614b64SAnirudh Venkataramanan 
24289d614b64SAnirudh Venkataramanan 	if (!test_bit(__ICE_NEEDS_RESTART, vsi->state))
24299d614b64SAnirudh Venkataramanan 		return 0;
24309d614b64SAnirudh Venkataramanan 
24319d614b64SAnirudh Venkataramanan 	clear_bit(__ICE_NEEDS_RESTART, vsi->state);
24329d614b64SAnirudh Venkataramanan 
24339d614b64SAnirudh Venkataramanan 	if (vsi->netdev && vsi->type == ICE_VSI_PF) {
24349d614b64SAnirudh Venkataramanan 		if (netif_running(vsi->netdev)) {
24359d614b64SAnirudh Venkataramanan 			if (!locked)
24369d614b64SAnirudh Venkataramanan 				rtnl_lock();
24379d614b64SAnirudh Venkataramanan 
24389d614b64SAnirudh Venkataramanan 			err = ice_open(vsi->netdev);
24399d614b64SAnirudh Venkataramanan 
24409d614b64SAnirudh Venkataramanan 			if (!locked)
24419d614b64SAnirudh Venkataramanan 				rtnl_unlock();
24429d614b64SAnirudh Venkataramanan 		}
2443148beb61SHenry Tieman 	} else if (vsi->type == ICE_VSI_CTRL) {
2444148beb61SHenry Tieman 		err = ice_vsi_open_ctrl(vsi);
24459d614b64SAnirudh Venkataramanan 	}
24469d614b64SAnirudh Venkataramanan 
24479d614b64SAnirudh Venkataramanan 	return err;
24489d614b64SAnirudh Venkataramanan }
24499d614b64SAnirudh Venkataramanan 
24509d614b64SAnirudh Venkataramanan /**
24519d614b64SAnirudh Venkataramanan  * ice_dis_vsi - pause a VSI
24529d614b64SAnirudh Venkataramanan  * @vsi: the VSI being paused
24539d614b64SAnirudh Venkataramanan  * @locked: is the rtnl_lock already held
24549d614b64SAnirudh Venkataramanan  */
24559d614b64SAnirudh Venkataramanan void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
24569d614b64SAnirudh Venkataramanan {
24579d614b64SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state))
24589d614b64SAnirudh Venkataramanan 		return;
24599d614b64SAnirudh Venkataramanan 
24609d614b64SAnirudh Venkataramanan 	set_bit(__ICE_NEEDS_RESTART, vsi->state);
24619d614b64SAnirudh Venkataramanan 
24629d614b64SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF && vsi->netdev) {
24639d614b64SAnirudh Venkataramanan 		if (netif_running(vsi->netdev)) {
24649d614b64SAnirudh Venkataramanan 			if (!locked)
24659d614b64SAnirudh Venkataramanan 				rtnl_lock();
24669d614b64SAnirudh Venkataramanan 
24679d614b64SAnirudh Venkataramanan 			ice_stop(vsi->netdev);
24689d614b64SAnirudh Venkataramanan 
24699d614b64SAnirudh Venkataramanan 			if (!locked)
24709d614b64SAnirudh Venkataramanan 				rtnl_unlock();
24719d614b64SAnirudh Venkataramanan 		} else {
24729d614b64SAnirudh Venkataramanan 			ice_vsi_close(vsi);
24739d614b64SAnirudh Venkataramanan 		}
2474148beb61SHenry Tieman 	} else if (vsi->type == ICE_VSI_CTRL) {
2475148beb61SHenry Tieman 		ice_vsi_close(vsi);
24769d614b64SAnirudh Venkataramanan 	}
24779d614b64SAnirudh Venkataramanan }
24789d614b64SAnirudh Venkataramanan 
24799d614b64SAnirudh Venkataramanan /**
24805153a18eSAnirudh Venkataramanan  * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI
24815153a18eSAnirudh Venkataramanan  * @vsi: the VSI being un-configured
24825153a18eSAnirudh Venkataramanan  */
24835153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi)
24845153a18eSAnirudh Venkataramanan {
2485cbe66bfeSBrett Creeley 	int base = vsi->base_vector;
24865153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
24875153a18eSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
24885153a18eSAnirudh Venkataramanan 	u32 val;
24895153a18eSAnirudh Venkataramanan 	int i;
24905153a18eSAnirudh Venkataramanan 
24915153a18eSAnirudh Venkataramanan 	/* disable interrupt causation from each queue */
24925153a18eSAnirudh Venkataramanan 	if (vsi->tx_rings) {
24935153a18eSAnirudh Venkataramanan 		ice_for_each_txq(vsi, i) {
24945153a18eSAnirudh Venkataramanan 			if (vsi->tx_rings[i]) {
24955153a18eSAnirudh Venkataramanan 				u16 reg;
24965153a18eSAnirudh Venkataramanan 
24975153a18eSAnirudh Venkataramanan 				reg = vsi->tx_rings[i]->reg_idx;
24985153a18eSAnirudh Venkataramanan 				val = rd32(hw, QINT_TQCTL(reg));
24995153a18eSAnirudh Venkataramanan 				val &= ~QINT_TQCTL_CAUSE_ENA_M;
25005153a18eSAnirudh Venkataramanan 				wr32(hw, QINT_TQCTL(reg), val);
25015153a18eSAnirudh Venkataramanan 			}
25025153a18eSAnirudh Venkataramanan 		}
25035153a18eSAnirudh Venkataramanan 	}
25045153a18eSAnirudh Venkataramanan 
25055153a18eSAnirudh Venkataramanan 	if (vsi->rx_rings) {
25065153a18eSAnirudh Venkataramanan 		ice_for_each_rxq(vsi, i) {
25075153a18eSAnirudh Venkataramanan 			if (vsi->rx_rings[i]) {
25085153a18eSAnirudh Venkataramanan 				u16 reg;
25095153a18eSAnirudh Venkataramanan 
25105153a18eSAnirudh Venkataramanan 				reg = vsi->rx_rings[i]->reg_idx;
25115153a18eSAnirudh Venkataramanan 				val = rd32(hw, QINT_RQCTL(reg));
25125153a18eSAnirudh Venkataramanan 				val &= ~QINT_RQCTL_CAUSE_ENA_M;
25135153a18eSAnirudh Venkataramanan 				wr32(hw, QINT_RQCTL(reg), val);
25145153a18eSAnirudh Venkataramanan 			}
25155153a18eSAnirudh Venkataramanan 		}
25165153a18eSAnirudh Venkataramanan 	}
25175153a18eSAnirudh Venkataramanan 
25185153a18eSAnirudh Venkataramanan 	/* disable each interrupt */
2519462acf6aSTony Nguyen 	ice_for_each_q_vector(vsi, i) {
2520462acf6aSTony Nguyen 		if (!vsi->q_vectors[i])
2521462acf6aSTony Nguyen 			continue;
2522b07833a0SBrett Creeley 		wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0);
2523462acf6aSTony Nguyen 	}
25245153a18eSAnirudh Venkataramanan 
25255153a18eSAnirudh Venkataramanan 	ice_flush(hw);
2526b07833a0SBrett Creeley 
2527da4a9e73SBrett Creeley 	/* don't call synchronize_irq() for VF's from the host */
2528da4a9e73SBrett Creeley 	if (vsi->type == ICE_VSI_VF)
2529da4a9e73SBrett Creeley 		return;
2530da4a9e73SBrett Creeley 
25310c2561c8SBrett Creeley 	ice_for_each_q_vector(vsi, i)
25325153a18eSAnirudh Venkataramanan 		synchronize_irq(pf->msix_entries[i + base].vector);
25335153a18eSAnirudh Venkataramanan }
25345153a18eSAnirudh Venkataramanan 
25355153a18eSAnirudh Venkataramanan /**
2536561f4379STony Nguyen  * ice_napi_del - Remove NAPI handler for the VSI
2537561f4379STony Nguyen  * @vsi: VSI for which NAPI handler is to be removed
2538561f4379STony Nguyen  */
2539561f4379STony Nguyen void ice_napi_del(struct ice_vsi *vsi)
2540561f4379STony Nguyen {
2541561f4379STony Nguyen 	int v_idx;
2542561f4379STony Nguyen 
2543561f4379STony Nguyen 	if (!vsi->netdev)
2544561f4379STony Nguyen 		return;
2545561f4379STony Nguyen 
2546561f4379STony Nguyen 	ice_for_each_q_vector(vsi, v_idx)
2547561f4379STony Nguyen 		netif_napi_del(&vsi->q_vectors[v_idx]->napi);
2548561f4379STony Nguyen }
2549561f4379STony Nguyen 
2550561f4379STony Nguyen /**
2551df0f8479SAnirudh Venkataramanan  * ice_vsi_release - Delete a VSI and free its resources
2552df0f8479SAnirudh Venkataramanan  * @vsi: the VSI being removed
2553df0f8479SAnirudh Venkataramanan  *
2554df0f8479SAnirudh Venkataramanan  * Returns 0 on success or < 0 on error
2555df0f8479SAnirudh Venkataramanan  */
2556df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi)
2557df0f8479SAnirudh Venkataramanan {
2558df0f8479SAnirudh Venkataramanan 	struct ice_pf *pf;
2559df0f8479SAnirudh Venkataramanan 
2560df0f8479SAnirudh Venkataramanan 	if (!vsi->back)
2561df0f8479SAnirudh Venkataramanan 		return -ENODEV;
2562df0f8479SAnirudh Venkataramanan 	pf = vsi->back;
2563b751930cSBrett Creeley 
2564aa6ccf3fSBrett Creeley 	/* do not unregister while driver is in the reset recovery pending
2565aa6ccf3fSBrett Creeley 	 * state. Since reset/rebuild happens through PF service task workqueue,
2566aa6ccf3fSBrett Creeley 	 * it's not a good idea to unregister netdev that is associated to the
2567aa6ccf3fSBrett Creeley 	 * PF that is running the work queue items currently. This is done to
2568aa6ccf3fSBrett Creeley 	 * avoid check_flush_dependency() warning on this wq
2569df0f8479SAnirudh Venkataramanan 	 */
2570aa6ccf3fSBrett Creeley 	if (vsi->netdev && !ice_is_reset_in_progress(pf->state))
2571df0f8479SAnirudh Venkataramanan 		unregister_netdev(vsi->netdev);
2572df0f8479SAnirudh Venkataramanan 
2573df0f8479SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
2574df0f8479SAnirudh Venkataramanan 		ice_rss_clean(vsi);
2575df0f8479SAnirudh Venkataramanan 
2576df0f8479SAnirudh Venkataramanan 	/* Disable VSI and free resources */
25770e674aebSAnirudh Venkataramanan 	if (vsi->type != ICE_VSI_LB)
2578df0f8479SAnirudh Venkataramanan 		ice_vsi_dis_irq(vsi);
2579df0f8479SAnirudh Venkataramanan 	ice_vsi_close(vsi);
2580df0f8479SAnirudh Venkataramanan 
2581cbe66bfeSBrett Creeley 	/* SR-IOV determines needed MSIX resources all at once instead of per
2582cbe66bfeSBrett Creeley 	 * VSI since when VFs are spawned we know how many VFs there are and how
2583cbe66bfeSBrett Creeley 	 * many interrupts each VF needs. SR-IOV MSIX resources are also
2584cbe66bfeSBrett Creeley 	 * cleared in the same manner.
2585cbe66bfeSBrett Creeley 	 */
25868ede0178SAnirudh Venkataramanan 	if (vsi->type != ICE_VSI_VF) {
25878ede0178SAnirudh Venkataramanan 		/* reclaim SW interrupts back to the common pool */
2588cbe66bfeSBrett Creeley 		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
2589eb0208ecSPreethi Banala 		pf->num_avail_sw_msix += vsi->num_q_vectors;
25908ede0178SAnirudh Venkataramanan 	}
2591df0f8479SAnirudh Venkataramanan 
2592462acf6aSTony Nguyen 	if (!ice_is_safe_mode(pf)) {
25932e0e6228SDave Ertman 		if (vsi->type == ICE_VSI_PF) {
25941b8f15b6SMichal Swiatkowski 			ice_fltr_remove_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX,
25951b8f15b6SMichal Swiatkowski 					    ICE_DROP_PACKET);
25962e0e6228SDave Ertman 			ice_cfg_sw_lldp(vsi, true, false);
25972e0e6228SDave Ertman 			/* The Rx rule will only exist to remove if the LLDP FW
25982e0e6228SDave Ertman 			 * engine is currently stopped
25992e0e6228SDave Ertman 			 */
260084a118abSDave Ertman 			if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
26012e0e6228SDave Ertman 				ice_cfg_sw_lldp(vsi, false, false);
26022e0e6228SDave Ertman 		}
2603462acf6aSTony Nguyen 	}
2604d95276ceSAkeem G Abodunrin 
26051b8f15b6SMichal Swiatkowski 	ice_fltr_remove_all(vsi);
260610e03a22SAnirudh Venkataramanan 	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
2607df0f8479SAnirudh Venkataramanan 	ice_vsi_delete(vsi);
2608df0f8479SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
2609aa6ccf3fSBrett Creeley 
2610aa6ccf3fSBrett Creeley 	/* make sure unregister_netdev() was called by checking __ICE_DOWN */
2611aa6ccf3fSBrett Creeley 	if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) {
2612aa6ccf3fSBrett Creeley 		free_netdev(vsi->netdev);
2613aa6ccf3fSBrett Creeley 		vsi->netdev = NULL;
2614aa6ccf3fSBrett Creeley 	}
2615aa6ccf3fSBrett Creeley 
2616df0f8479SAnirudh Venkataramanan 	ice_vsi_clear_rings(vsi);
2617df0f8479SAnirudh Venkataramanan 
2618df0f8479SAnirudh Venkataramanan 	ice_vsi_put_qs(vsi);
2619df0f8479SAnirudh Venkataramanan 
2620df0f8479SAnirudh Venkataramanan 	/* retain SW VSI data structure since it is needed to unregister and
2621df0f8479SAnirudh Venkataramanan 	 * free VSI netdev when PF is not in reset recovery pending state,\
2622df0f8479SAnirudh Venkataramanan 	 * for ex: during rmmod.
2623df0f8479SAnirudh Venkataramanan 	 */
26245df7e45dSDave Ertman 	if (!ice_is_reset_in_progress(pf->state))
2625df0f8479SAnirudh Venkataramanan 		ice_vsi_clear(vsi);
2626df0f8479SAnirudh Venkataramanan 
2627df0f8479SAnirudh Venkataramanan 	return 0;
2628df0f8479SAnirudh Venkataramanan }
2629df0f8479SAnirudh Venkataramanan 
2630df0f8479SAnirudh Venkataramanan /**
263161dc79ceSMichal Swiatkowski  * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector
263261dc79ceSMichal Swiatkowski  * @q_vector: pointer to q_vector which is being updated
263361dc79ceSMichal Swiatkowski  * @coalesce: pointer to array of struct with stored coalesce
263461dc79ceSMichal Swiatkowski  *
263561dc79ceSMichal Swiatkowski  * Set coalesce param in q_vector and update these parameters in HW.
263661dc79ceSMichal Swiatkowski  */
263761dc79ceSMichal Swiatkowski static void
263861dc79ceSMichal Swiatkowski ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector,
263961dc79ceSMichal Swiatkowski 				struct ice_coalesce_stored *coalesce)
264061dc79ceSMichal Swiatkowski {
264161dc79ceSMichal Swiatkowski 	struct ice_ring_container *rx_rc = &q_vector->rx;
264261dc79ceSMichal Swiatkowski 	struct ice_ring_container *tx_rc = &q_vector->tx;
264361dc79ceSMichal Swiatkowski 	struct ice_hw *hw = &q_vector->vsi->back->hw;
264461dc79ceSMichal Swiatkowski 
264561dc79ceSMichal Swiatkowski 	tx_rc->itr_setting = coalesce->itr_tx;
264661dc79ceSMichal Swiatkowski 	rx_rc->itr_setting = coalesce->itr_rx;
264761dc79ceSMichal Swiatkowski 
264861dc79ceSMichal Swiatkowski 	/* dynamic ITR values will be updated during Tx/Rx */
264961dc79ceSMichal Swiatkowski 	if (!ITR_IS_DYNAMIC(tx_rc->itr_setting))
265061dc79ceSMichal Swiatkowski 		wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx),
265161dc79ceSMichal Swiatkowski 		     ITR_REG_ALIGN(tx_rc->itr_setting) >>
265261dc79ceSMichal Swiatkowski 		     ICE_ITR_GRAN_S);
265361dc79ceSMichal Swiatkowski 	if (!ITR_IS_DYNAMIC(rx_rc->itr_setting))
265461dc79ceSMichal Swiatkowski 		wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx),
265561dc79ceSMichal Swiatkowski 		     ITR_REG_ALIGN(rx_rc->itr_setting) >>
265661dc79ceSMichal Swiatkowski 		     ICE_ITR_GRAN_S);
265761dc79ceSMichal Swiatkowski 
265861dc79ceSMichal Swiatkowski 	q_vector->intrl = coalesce->intrl;
265961dc79ceSMichal Swiatkowski 	wr32(hw, GLINT_RATE(q_vector->reg_idx),
266061dc79ceSMichal Swiatkowski 	     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
266161dc79ceSMichal Swiatkowski }
266261dc79ceSMichal Swiatkowski 
266361dc79ceSMichal Swiatkowski /**
266461dc79ceSMichal Swiatkowski  * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
266561dc79ceSMichal Swiatkowski  * @vsi: VSI connected with q_vectors
266661dc79ceSMichal Swiatkowski  * @coalesce: array of struct with stored coalesce
266761dc79ceSMichal Swiatkowski  *
266861dc79ceSMichal Swiatkowski  * Returns array size.
266961dc79ceSMichal Swiatkowski  */
267061dc79ceSMichal Swiatkowski static int
267161dc79ceSMichal Swiatkowski ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
267261dc79ceSMichal Swiatkowski 			     struct ice_coalesce_stored *coalesce)
267361dc79ceSMichal Swiatkowski {
267461dc79ceSMichal Swiatkowski 	int i;
267561dc79ceSMichal Swiatkowski 
267661dc79ceSMichal Swiatkowski 	ice_for_each_q_vector(vsi, i) {
267761dc79ceSMichal Swiatkowski 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
267861dc79ceSMichal Swiatkowski 
267961dc79ceSMichal Swiatkowski 		coalesce[i].itr_tx = q_vector->tx.itr_setting;
268061dc79ceSMichal Swiatkowski 		coalesce[i].itr_rx = q_vector->rx.itr_setting;
268161dc79ceSMichal Swiatkowski 		coalesce[i].intrl = q_vector->intrl;
268261dc79ceSMichal Swiatkowski 	}
268361dc79ceSMichal Swiatkowski 
268461dc79ceSMichal Swiatkowski 	return vsi->num_q_vectors;
268561dc79ceSMichal Swiatkowski }
268661dc79ceSMichal Swiatkowski 
268761dc79ceSMichal Swiatkowski /**
268861dc79ceSMichal Swiatkowski  * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays
268961dc79ceSMichal Swiatkowski  * @vsi: VSI connected with q_vectors
269061dc79ceSMichal Swiatkowski  * @coalesce: pointer to array of struct with stored coalesce
269161dc79ceSMichal Swiatkowski  * @size: size of coalesce array
269261dc79ceSMichal Swiatkowski  *
269361dc79ceSMichal Swiatkowski  * Before this function, ice_vsi_rebuild_get_coalesce should be called to save
269461dc79ceSMichal Swiatkowski  * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce
269561dc79ceSMichal Swiatkowski  * to default value.
269661dc79ceSMichal Swiatkowski  */
269761dc79ceSMichal Swiatkowski static void
269861dc79ceSMichal Swiatkowski ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
269961dc79ceSMichal Swiatkowski 			     struct ice_coalesce_stored *coalesce, int size)
270061dc79ceSMichal Swiatkowski {
270161dc79ceSMichal Swiatkowski 	int i;
270261dc79ceSMichal Swiatkowski 
270361dc79ceSMichal Swiatkowski 	if ((size && !coalesce) || !vsi)
270461dc79ceSMichal Swiatkowski 		return;
270561dc79ceSMichal Swiatkowski 
270661dc79ceSMichal Swiatkowski 	for (i = 0; i < size && i < vsi->num_q_vectors; i++)
270761dc79ceSMichal Swiatkowski 		ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
270861dc79ceSMichal Swiatkowski 						&coalesce[i]);
270961dc79ceSMichal Swiatkowski 
271061dc79ceSMichal Swiatkowski 	for (; i < vsi->num_q_vectors; i++) {
271161dc79ceSMichal Swiatkowski 		struct ice_coalesce_stored coalesce_dflt = {
271261dc79ceSMichal Swiatkowski 			.itr_tx = ICE_DFLT_TX_ITR,
271361dc79ceSMichal Swiatkowski 			.itr_rx = ICE_DFLT_RX_ITR,
271461dc79ceSMichal Swiatkowski 			.intrl = 0
271561dc79ceSMichal Swiatkowski 		};
271661dc79ceSMichal Swiatkowski 		ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
271761dc79ceSMichal Swiatkowski 						&coalesce_dflt);
271861dc79ceSMichal Swiatkowski 	}
271961dc79ceSMichal Swiatkowski }
272061dc79ceSMichal Swiatkowski 
272161dc79ceSMichal Swiatkowski /**
2722df0f8479SAnirudh Venkataramanan  * ice_vsi_rebuild - Rebuild VSI after reset
2723df0f8479SAnirudh Venkataramanan  * @vsi: VSI to be rebuild
272487324e74SHenry Tieman  * @init_vsi: is this an initialization or a reconfigure of the VSI
2725df0f8479SAnirudh Venkataramanan  *
2726df0f8479SAnirudh Venkataramanan  * Returns 0 on success and negative value on failure
2727df0f8479SAnirudh Venkataramanan  */
272887324e74SHenry Tieman int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
2729df0f8479SAnirudh Venkataramanan {
2730df0f8479SAnirudh Venkataramanan 	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
273161dc79ceSMichal Swiatkowski 	struct ice_coalesce_stored *coalesce;
273261dc79ceSMichal Swiatkowski 	int prev_num_q_vectors = 0;
27337eeac889SAkeem G Abodunrin 	struct ice_vf *vf = NULL;
2734d31530e8SAkeem G Abodunrin 	enum ice_status status;
2735c5a2a4a3SUsha Ketineni 	struct ice_pf *pf;
2736df0f8479SAnirudh Venkataramanan 	int ret, i;
2737df0f8479SAnirudh Venkataramanan 
2738df0f8479SAnirudh Venkataramanan 	if (!vsi)
2739df0f8479SAnirudh Venkataramanan 		return -EINVAL;
2740df0f8479SAnirudh Venkataramanan 
2741c5a2a4a3SUsha Ketineni 	pf = vsi->back;
27427eeac889SAkeem G Abodunrin 	if (vsi->type == ICE_VSI_VF)
27437eeac889SAkeem G Abodunrin 		vf = &pf->vf[vsi->vf_id];
27447eeac889SAkeem G Abodunrin 
274561dc79ceSMichal Swiatkowski 	coalesce = kcalloc(vsi->num_q_vectors,
274661dc79ceSMichal Swiatkowski 			   sizeof(struct ice_coalesce_stored), GFP_KERNEL);
274761dc79ceSMichal Swiatkowski 	if (coalesce)
274861dc79ceSMichal Swiatkowski 		prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi,
274961dc79ceSMichal Swiatkowski 								  coalesce);
275047e3e53cSHenry Tieman 	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
2751df0f8479SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
27527eeac889SAkeem G Abodunrin 
2753cbe66bfeSBrett Creeley 	/* SR-IOV determines needed MSIX resources all at once instead of per
2754cbe66bfeSBrett Creeley 	 * VSI since when VFs are spawned we know how many VFs there are and how
2755cbe66bfeSBrett Creeley 	 * many interrupts each VF needs. SR-IOV MSIX resources are also
2756cbe66bfeSBrett Creeley 	 * cleared in the same manner.
2757cbe66bfeSBrett Creeley 	 */
27587eeac889SAkeem G Abodunrin 	if (vsi->type != ICE_VSI_VF) {
27597eeac889SAkeem G Abodunrin 		/* reclaim SW interrupts back to the common pool */
2760cbe66bfeSBrett Creeley 		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
27617eeac889SAkeem G Abodunrin 		pf->num_avail_sw_msix += vsi->num_q_vectors;
2762cbe66bfeSBrett Creeley 		vsi->base_vector = 0;
27637eeac889SAkeem G Abodunrin 	}
27647eeac889SAkeem G Abodunrin 
2765efc2214bSMaciej Fijalkowski 	if (ice_is_xdp_ena_vsi(vsi))
2766efc2214bSMaciej Fijalkowski 		/* return value check can be skipped here, it always returns
2767efc2214bSMaciej Fijalkowski 		 * 0 if reset is in progress
2768efc2214bSMaciej Fijalkowski 		 */
2769efc2214bSMaciej Fijalkowski 		ice_destroy_xdp_rings(vsi);
277078b5713aSAnirudh Venkataramanan 	ice_vsi_put_qs(vsi);
2771df0f8479SAnirudh Venkataramanan 	ice_vsi_clear_rings(vsi);
2772a85a3847SBrett Creeley 	ice_vsi_free_arrays(vsi);
27735743020dSAkeem G Abodunrin 	if (vsi->type == ICE_VSI_VF)
27745743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, vf->vf_id);
27755743020dSAkeem G Abodunrin 	else
27765743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
277778b5713aSAnirudh Venkataramanan 
277878b5713aSAnirudh Venkataramanan 	ret = ice_vsi_alloc_arrays(vsi);
277978b5713aSAnirudh Venkataramanan 	if (ret < 0)
278078b5713aSAnirudh Venkataramanan 		goto err_vsi;
278178b5713aSAnirudh Venkataramanan 
278278b5713aSAnirudh Venkataramanan 	ice_vsi_get_qs(vsi);
278383af0039SHenry Tieman 
278483af0039SHenry Tieman 	ice_alloc_fd_res(vsi);
2785c5a2a4a3SUsha Ketineni 	ice_vsi_set_tc_cfg(vsi);
2786df0f8479SAnirudh Venkataramanan 
2787df0f8479SAnirudh Venkataramanan 	/* Initialize VSI struct elements and create VSI in FW */
278887324e74SHenry Tieman 	ret = ice_vsi_init(vsi, init_vsi);
2789df0f8479SAnirudh Venkataramanan 	if (ret < 0)
2790df0f8479SAnirudh Venkataramanan 		goto err_vsi;
2791df0f8479SAnirudh Venkataramanan 
2792df0f8479SAnirudh Venkataramanan 	switch (vsi->type) {
279383af0039SHenry Tieman 	case ICE_VSI_CTRL:
2794df0f8479SAnirudh Venkataramanan 	case ICE_VSI_PF:
2795df0f8479SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
2796df0f8479SAnirudh Venkataramanan 		if (ret)
2797df0f8479SAnirudh Venkataramanan 			goto err_rings;
2798df0f8479SAnirudh Venkataramanan 
279917bc6d07STony Nguyen 		ret = ice_vsi_setup_vector_base(vsi);
280017bc6d07STony Nguyen 		if (ret)
280117bc6d07STony Nguyen 			goto err_vectors;
280217bc6d07STony Nguyen 
2803b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2804b07833a0SBrett Creeley 		if (ret)
2805b07833a0SBrett Creeley 			goto err_vectors;
2806b07833a0SBrett Creeley 
2807df0f8479SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
2808df0f8479SAnirudh Venkataramanan 		if (ret)
2809df0f8479SAnirudh Venkataramanan 			goto err_vectors;
2810df0f8479SAnirudh Venkataramanan 
2811df0f8479SAnirudh Venkataramanan 		ice_vsi_map_rings_to_vectors(vsi);
2812efc2214bSMaciej Fijalkowski 		if (ice_is_xdp_ena_vsi(vsi)) {
2813ae15e0baSMarta Plantykow 			vsi->num_xdp_txq = vsi->alloc_rxq;
2814efc2214bSMaciej Fijalkowski 			ret = ice_prepare_xdp_rings(vsi, vsi->xdp_prog);
2815efc2214bSMaciej Fijalkowski 			if (ret)
2816efc2214bSMaciej Fijalkowski 				goto err_vectors;
2817efc2214bSMaciej Fijalkowski 		}
281883af0039SHenry Tieman 		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
281983af0039SHenry Tieman 		if (vsi->type != ICE_VSI_CTRL)
282083af0039SHenry Tieman 			/* Do not exit if configuring RSS had an issue, at
282183af0039SHenry Tieman 			 * least receive traffic on first queue. Hence no
282283af0039SHenry Tieman 			 * need to capture return value
282327a98affSMd Fahad Iqbal Polash 			 */
2824819d8998SJesse Brandeburg 			if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
282527a98affSMd Fahad Iqbal Polash 				ice_vsi_cfg_rss_lut_key(vsi);
2826df0f8479SAnirudh Venkataramanan 		break;
28278ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
28288ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
28298ede0178SAnirudh Venkataramanan 		if (ret)
28308ede0178SAnirudh Venkataramanan 			goto err_rings;
28318ede0178SAnirudh Venkataramanan 
2832b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2833b07833a0SBrett Creeley 		if (ret)
2834b07833a0SBrett Creeley 			goto err_vectors;
2835b07833a0SBrett Creeley 
28368ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
28378ede0178SAnirudh Venkataramanan 		if (ret)
28388ede0178SAnirudh Venkataramanan 			goto err_vectors;
28398ede0178SAnirudh Venkataramanan 
28408ede0178SAnirudh Venkataramanan 		break;
2841df0f8479SAnirudh Venkataramanan 	default:
2842df0f8479SAnirudh Venkataramanan 		break;
2843df0f8479SAnirudh Venkataramanan 	}
2844df0f8479SAnirudh Venkataramanan 
2845df0f8479SAnirudh Venkataramanan 	/* configure VSI nodes based on number of queues and TC's */
2846efc2214bSMaciej Fijalkowski 	for (i = 0; i < vsi->tc_cfg.numtc; i++) {
2847d5a46359SAkeem G Abodunrin 		max_txqs[i] = vsi->alloc_txq;
2848df0f8479SAnirudh Venkataramanan 
2849efc2214bSMaciej Fijalkowski 		if (ice_is_xdp_ena_vsi(vsi))
2850efc2214bSMaciej Fijalkowski 			max_txqs[i] += vsi->num_xdp_txq;
2851efc2214bSMaciej Fijalkowski 	}
2852efc2214bSMaciej Fijalkowski 
2853d31530e8SAkeem G Abodunrin 	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
28544fb33f31SAnirudh Venkataramanan 				 max_txqs);
2855d31530e8SAkeem G Abodunrin 	if (status) {
28560fee3577SLihong Yang 		dev_err(ice_pf_to_dev(pf), "VSI %d failed lan queue config, error %s\n",
28570fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
285887324e74SHenry Tieman 		if (init_vsi) {
285987324e74SHenry Tieman 			ret = -EIO;
2860df0f8479SAnirudh Venkataramanan 			goto err_vectors;
286187324e74SHenry Tieman 		} else {
286287324e74SHenry Tieman 			return ice_schedule_reset(pf, ICE_RESET_PFR);
286387324e74SHenry Tieman 		}
2864df0f8479SAnirudh Venkataramanan 	}
286561dc79ceSMichal Swiatkowski 	ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors);
286661dc79ceSMichal Swiatkowski 	kfree(coalesce);
286761dc79ceSMichal Swiatkowski 
2868df0f8479SAnirudh Venkataramanan 	return 0;
2869df0f8479SAnirudh Venkataramanan 
2870df0f8479SAnirudh Venkataramanan err_vectors:
2871df0f8479SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
2872df0f8479SAnirudh Venkataramanan err_rings:
2873df0f8479SAnirudh Venkataramanan 	if (vsi->netdev) {
2874df0f8479SAnirudh Venkataramanan 		vsi->current_netdev_flags = 0;
2875df0f8479SAnirudh Venkataramanan 		unregister_netdev(vsi->netdev);
2876df0f8479SAnirudh Venkataramanan 		free_netdev(vsi->netdev);
2877df0f8479SAnirudh Venkataramanan 		vsi->netdev = NULL;
2878df0f8479SAnirudh Venkataramanan 	}
2879df0f8479SAnirudh Venkataramanan err_vsi:
2880df0f8479SAnirudh Venkataramanan 	ice_vsi_clear(vsi);
2881819d8998SJesse Brandeburg 	set_bit(__ICE_RESET_FAILED, pf->state);
288261dc79ceSMichal Swiatkowski 	kfree(coalesce);
2883df0f8479SAnirudh Venkataramanan 	return ret;
2884df0f8479SAnirudh Venkataramanan }
2885df0f8479SAnirudh Venkataramanan 
2886df0f8479SAnirudh Venkataramanan /**
28875df7e45dSDave Ertman  * ice_is_reset_in_progress - check for a reset in progress
28882f2da36eSAnirudh Venkataramanan  * @state: PF state field
28895153a18eSAnirudh Venkataramanan  */
28905df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state)
28915153a18eSAnirudh Venkataramanan {
28925df7e45dSDave Ertman 	return test_bit(__ICE_RESET_OICR_RECV, state) ||
2893b94b013eSDave Ertman 	       test_bit(__ICE_DCBNL_DEVRESET, state) ||
28945df7e45dSDave Ertman 	       test_bit(__ICE_PFR_REQ, state) ||
28955df7e45dSDave Ertman 	       test_bit(__ICE_CORER_REQ, state) ||
28965df7e45dSDave Ertman 	       test_bit(__ICE_GLOBR_REQ, state);
28975153a18eSAnirudh Venkataramanan }
28987b9ffc76SAnirudh Venkataramanan 
28997b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB
29007b9ffc76SAnirudh Venkataramanan /**
29017b9ffc76SAnirudh Venkataramanan  * ice_vsi_update_q_map - update our copy of the VSI info with new queue map
29027b9ffc76SAnirudh Venkataramanan  * @vsi: VSI being configured
29037b9ffc76SAnirudh Venkataramanan  * @ctx: the context buffer returned from AQ VSI update command
29047b9ffc76SAnirudh Venkataramanan  */
29057b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx)
29067b9ffc76SAnirudh Venkataramanan {
29077b9ffc76SAnirudh Venkataramanan 	vsi->info.mapping_flags = ctx->info.mapping_flags;
29087b9ffc76SAnirudh Venkataramanan 	memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping,
29097b9ffc76SAnirudh Venkataramanan 	       sizeof(vsi->info.q_mapping));
29107b9ffc76SAnirudh Venkataramanan 	memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping,
29117b9ffc76SAnirudh Venkataramanan 	       sizeof(vsi->info.tc_mapping));
29127b9ffc76SAnirudh Venkataramanan }
29137b9ffc76SAnirudh Venkataramanan 
29147b9ffc76SAnirudh Venkataramanan /**
29157b9ffc76SAnirudh Venkataramanan  * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map
29167b9ffc76SAnirudh Venkataramanan  * @vsi: VSI to be configured
29177b9ffc76SAnirudh Venkataramanan  * @ena_tc: TC bitmap
29187b9ffc76SAnirudh Venkataramanan  *
29197b9ffc76SAnirudh Venkataramanan  * VSI queues expected to be quiesced before calling this function
29207b9ffc76SAnirudh Venkataramanan  */
29217b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
29227b9ffc76SAnirudh Venkataramanan {
29237b9ffc76SAnirudh Venkataramanan 	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
29247b9ffc76SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
29254ee656bbSTony Nguyen 	struct ice_vsi_ctx *ctx;
29267b9ffc76SAnirudh Venkataramanan 	enum ice_status status;
29274015d11eSBrett Creeley 	struct device *dev;
29287b9ffc76SAnirudh Venkataramanan 	int i, ret = 0;
29297b9ffc76SAnirudh Venkataramanan 	u8 num_tc = 0;
29307b9ffc76SAnirudh Venkataramanan 
29314015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
29324015d11eSBrett Creeley 
29337b9ffc76SAnirudh Venkataramanan 	ice_for_each_traffic_class(i) {
29347b9ffc76SAnirudh Venkataramanan 		/* build bitmap of enabled TCs */
29357b9ffc76SAnirudh Venkataramanan 		if (ena_tc & BIT(i))
29367b9ffc76SAnirudh Venkataramanan 			num_tc++;
29377b9ffc76SAnirudh Venkataramanan 		/* populate max_txqs per TC */
2938d5a46359SAkeem G Abodunrin 		max_txqs[i] = vsi->alloc_txq;
29397b9ffc76SAnirudh Venkataramanan 	}
29407b9ffc76SAnirudh Venkataramanan 
29417b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.ena_tc = ena_tc;
29427b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.numtc = num_tc;
29437b9ffc76SAnirudh Venkataramanan 
29449efe35d0STony Nguyen 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
29457b9ffc76SAnirudh Venkataramanan 	if (!ctx)
29467b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
29477b9ffc76SAnirudh Venkataramanan 
29487b9ffc76SAnirudh Venkataramanan 	ctx->vf_num = 0;
29497b9ffc76SAnirudh Venkataramanan 	ctx->info = vsi->info;
29507b9ffc76SAnirudh Venkataramanan 
29517b9ffc76SAnirudh Venkataramanan 	ice_vsi_setup_q_map(vsi, ctx);
29527b9ffc76SAnirudh Venkataramanan 
29537b9ffc76SAnirudh Venkataramanan 	/* must to indicate which section of VSI context are being modified */
29547b9ffc76SAnirudh Venkataramanan 	ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
29557b9ffc76SAnirudh Venkataramanan 	status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL);
29567b9ffc76SAnirudh Venkataramanan 	if (status) {
29574015d11eSBrett Creeley 		dev_info(dev, "Failed VSI Update\n");
29587b9ffc76SAnirudh Venkataramanan 		ret = -EIO;
29597b9ffc76SAnirudh Venkataramanan 		goto out;
29607b9ffc76SAnirudh Venkataramanan 	}
29617b9ffc76SAnirudh Venkataramanan 
29627b9ffc76SAnirudh Venkataramanan 	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
29637b9ffc76SAnirudh Venkataramanan 				 max_txqs);
29647b9ffc76SAnirudh Venkataramanan 
29657b9ffc76SAnirudh Venkataramanan 	if (status) {
29660fee3577SLihong Yang 		dev_err(dev, "VSI %d failed TC config, error %s\n",
29670fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
29687b9ffc76SAnirudh Venkataramanan 		ret = -EIO;
29697b9ffc76SAnirudh Venkataramanan 		goto out;
29707b9ffc76SAnirudh Venkataramanan 	}
29717b9ffc76SAnirudh Venkataramanan 	ice_vsi_update_q_map(vsi, ctx);
29727b9ffc76SAnirudh Venkataramanan 	vsi->info.valid_sections = 0;
29737b9ffc76SAnirudh Venkataramanan 
29747b9ffc76SAnirudh Venkataramanan 	ice_vsi_cfg_netdev_tc(vsi, ena_tc);
29757b9ffc76SAnirudh Venkataramanan out:
29769efe35d0STony Nguyen 	kfree(ctx);
29777b9ffc76SAnirudh Venkataramanan 	return ret;
29787b9ffc76SAnirudh Venkataramanan }
29797b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */
2980bbb968e8SAkeem G Abodunrin 
2981bbb968e8SAkeem G Abodunrin /**
29822d4238f5SKrzysztof Kazimierczak  * ice_update_ring_stats - Update ring statistics
29832d4238f5SKrzysztof Kazimierczak  * @ring: ring to update
29842d4238f5SKrzysztof Kazimierczak  * @cont: used to increment per-vector counters
29852d4238f5SKrzysztof Kazimierczak  * @pkts: number of processed packets
29862d4238f5SKrzysztof Kazimierczak  * @bytes: number of processed bytes
29872d4238f5SKrzysztof Kazimierczak  *
29882d4238f5SKrzysztof Kazimierczak  * This function assumes that caller has acquired a u64_stats_sync lock.
29892d4238f5SKrzysztof Kazimierczak  */
29902d4238f5SKrzysztof Kazimierczak static void
29912d4238f5SKrzysztof Kazimierczak ice_update_ring_stats(struct ice_ring *ring, struct ice_ring_container *cont,
29922d4238f5SKrzysztof Kazimierczak 		      u64 pkts, u64 bytes)
29932d4238f5SKrzysztof Kazimierczak {
29942d4238f5SKrzysztof Kazimierczak 	ring->stats.bytes += bytes;
29952d4238f5SKrzysztof Kazimierczak 	ring->stats.pkts += pkts;
29962d4238f5SKrzysztof Kazimierczak 	cont->total_bytes += bytes;
29972d4238f5SKrzysztof Kazimierczak 	cont->total_pkts += pkts;
29982d4238f5SKrzysztof Kazimierczak }
29992d4238f5SKrzysztof Kazimierczak 
30002d4238f5SKrzysztof Kazimierczak /**
30012d4238f5SKrzysztof Kazimierczak  * ice_update_tx_ring_stats - Update Tx ring specific counters
30022d4238f5SKrzysztof Kazimierczak  * @tx_ring: ring to update
30032d4238f5SKrzysztof Kazimierczak  * @pkts: number of processed packets
30042d4238f5SKrzysztof Kazimierczak  * @bytes: number of processed bytes
30052d4238f5SKrzysztof Kazimierczak  */
30062d4238f5SKrzysztof Kazimierczak void ice_update_tx_ring_stats(struct ice_ring *tx_ring, u64 pkts, u64 bytes)
30072d4238f5SKrzysztof Kazimierczak {
30082d4238f5SKrzysztof Kazimierczak 	u64_stats_update_begin(&tx_ring->syncp);
30092d4238f5SKrzysztof Kazimierczak 	ice_update_ring_stats(tx_ring, &tx_ring->q_vector->tx, pkts, bytes);
30102d4238f5SKrzysztof Kazimierczak 	u64_stats_update_end(&tx_ring->syncp);
30112d4238f5SKrzysztof Kazimierczak }
30122d4238f5SKrzysztof Kazimierczak 
30132d4238f5SKrzysztof Kazimierczak /**
30142d4238f5SKrzysztof Kazimierczak  * ice_update_rx_ring_stats - Update Rx ring specific counters
30152d4238f5SKrzysztof Kazimierczak  * @rx_ring: ring to update
30162d4238f5SKrzysztof Kazimierczak  * @pkts: number of processed packets
30172d4238f5SKrzysztof Kazimierczak  * @bytes: number of processed bytes
30182d4238f5SKrzysztof Kazimierczak  */
30192d4238f5SKrzysztof Kazimierczak void ice_update_rx_ring_stats(struct ice_ring *rx_ring, u64 pkts, u64 bytes)
30202d4238f5SKrzysztof Kazimierczak {
30212d4238f5SKrzysztof Kazimierczak 	u64_stats_update_begin(&rx_ring->syncp);
30222d4238f5SKrzysztof Kazimierczak 	ice_update_ring_stats(rx_ring, &rx_ring->q_vector->rx, pkts, bytes);
30232d4238f5SKrzysztof Kazimierczak 	u64_stats_update_end(&rx_ring->syncp);
30242d4238f5SKrzysztof Kazimierczak }
30252d4238f5SKrzysztof Kazimierczak 
30262d4238f5SKrzysztof Kazimierczak /**
3027148beb61SHenry Tieman  * ice_status_to_errno - convert from enum ice_status to Linux errno
3028148beb61SHenry Tieman  * @err: ice_status value to convert
3029148beb61SHenry Tieman  */
3030148beb61SHenry Tieman int ice_status_to_errno(enum ice_status err)
3031148beb61SHenry Tieman {
3032148beb61SHenry Tieman 	switch (err) {
3033148beb61SHenry Tieman 	case ICE_SUCCESS:
3034148beb61SHenry Tieman 		return 0;
3035148beb61SHenry Tieman 	case ICE_ERR_DOES_NOT_EXIST:
3036148beb61SHenry Tieman 		return -ENOENT;
3037148beb61SHenry Tieman 	case ICE_ERR_OUT_OF_RANGE:
3038148beb61SHenry Tieman 		return -ENOTTY;
3039148beb61SHenry Tieman 	case ICE_ERR_PARAM:
3040148beb61SHenry Tieman 		return -EINVAL;
3041148beb61SHenry Tieman 	case ICE_ERR_NO_MEMORY:
3042148beb61SHenry Tieman 		return -ENOMEM;
3043148beb61SHenry Tieman 	case ICE_ERR_MAX_LIMIT:
3044148beb61SHenry Tieman 		return -EAGAIN;
3045148beb61SHenry Tieman 	default:
3046148beb61SHenry Tieman 		return -EINVAL;
3047148beb61SHenry Tieman 	}
3048148beb61SHenry Tieman }
3049148beb61SHenry Tieman 
3050148beb61SHenry Tieman /**
3051fc0f39bcSBrett Creeley  * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
3052fc0f39bcSBrett Creeley  * @sw: switch to check if its default forwarding VSI is free
3053fc0f39bcSBrett Creeley  *
3054fc0f39bcSBrett Creeley  * Return true if the default forwarding VSI is already being used, else returns
3055fc0f39bcSBrett Creeley  * false signalling that it's available to use.
3056fc0f39bcSBrett Creeley  */
3057fc0f39bcSBrett Creeley bool ice_is_dflt_vsi_in_use(struct ice_sw *sw)
3058fc0f39bcSBrett Creeley {
3059fc0f39bcSBrett Creeley 	return (sw->dflt_vsi && sw->dflt_vsi_ena);
3060fc0f39bcSBrett Creeley }
3061fc0f39bcSBrett Creeley 
3062fc0f39bcSBrett Creeley /**
3063fc0f39bcSBrett Creeley  * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI
3064fc0f39bcSBrett Creeley  * @sw: switch for the default forwarding VSI to compare against
3065fc0f39bcSBrett Creeley  * @vsi: VSI to compare against default forwarding VSI
3066fc0f39bcSBrett Creeley  *
3067fc0f39bcSBrett Creeley  * If this VSI passed in is the default forwarding VSI then return true, else
3068fc0f39bcSBrett Creeley  * return false
3069fc0f39bcSBrett Creeley  */
3070fc0f39bcSBrett Creeley bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
3071fc0f39bcSBrett Creeley {
3072fc0f39bcSBrett Creeley 	return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena);
3073fc0f39bcSBrett Creeley }
3074fc0f39bcSBrett Creeley 
3075fc0f39bcSBrett Creeley /**
3076fc0f39bcSBrett Creeley  * ice_set_dflt_vsi - set the default forwarding VSI
3077fc0f39bcSBrett Creeley  * @sw: switch used to assign the default forwarding VSI
3078fc0f39bcSBrett Creeley  * @vsi: VSI getting set as the default forwarding VSI on the switch
3079fc0f39bcSBrett Creeley  *
3080fc0f39bcSBrett Creeley  * If the VSI passed in is already the default VSI and it's enabled just return
3081fc0f39bcSBrett Creeley  * success.
3082fc0f39bcSBrett Creeley  *
3083fc0f39bcSBrett Creeley  * If there is already a default VSI on the switch and it's enabled then return
3084fc0f39bcSBrett Creeley  * -EEXIST since there can only be one default VSI per switch.
3085fc0f39bcSBrett Creeley  *
3086fc0f39bcSBrett Creeley  *  Otherwise try to set the VSI passed in as the switch's default VSI and
3087fc0f39bcSBrett Creeley  *  return the result.
3088fc0f39bcSBrett Creeley  */
3089fc0f39bcSBrett Creeley int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
3090fc0f39bcSBrett Creeley {
3091fc0f39bcSBrett Creeley 	enum ice_status status;
3092fc0f39bcSBrett Creeley 	struct device *dev;
3093fc0f39bcSBrett Creeley 
3094fc0f39bcSBrett Creeley 	if (!sw || !vsi)
3095fc0f39bcSBrett Creeley 		return -EINVAL;
3096fc0f39bcSBrett Creeley 
3097fc0f39bcSBrett Creeley 	dev = ice_pf_to_dev(vsi->back);
3098fc0f39bcSBrett Creeley 
3099fc0f39bcSBrett Creeley 	/* the VSI passed in is already the default VSI */
3100fc0f39bcSBrett Creeley 	if (ice_is_vsi_dflt_vsi(sw, vsi)) {
3101fc0f39bcSBrett Creeley 		dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
3102fc0f39bcSBrett Creeley 			vsi->vsi_num);
3103fc0f39bcSBrett Creeley 		return 0;
3104fc0f39bcSBrett Creeley 	}
3105fc0f39bcSBrett Creeley 
3106fc0f39bcSBrett Creeley 	/* another VSI is already the default VSI for this switch */
3107fc0f39bcSBrett Creeley 	if (ice_is_dflt_vsi_in_use(sw)) {
310819cce2c6SAnirudh Venkataramanan 		dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n",
3109fc0f39bcSBrett Creeley 			sw->dflt_vsi->vsi_num);
3110fc0f39bcSBrett Creeley 		return -EEXIST;
3111fc0f39bcSBrett Creeley 	}
3112fc0f39bcSBrett Creeley 
3113fc0f39bcSBrett Creeley 	status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX);
3114fc0f39bcSBrett Creeley 	if (status) {
31150fee3577SLihong Yang 		dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %s\n",
31160fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
3117fc0f39bcSBrett Creeley 		return -EIO;
3118fc0f39bcSBrett Creeley 	}
3119fc0f39bcSBrett Creeley 
3120fc0f39bcSBrett Creeley 	sw->dflt_vsi = vsi;
3121fc0f39bcSBrett Creeley 	sw->dflt_vsi_ena = true;
3122fc0f39bcSBrett Creeley 
3123fc0f39bcSBrett Creeley 	return 0;
3124fc0f39bcSBrett Creeley }
3125fc0f39bcSBrett Creeley 
3126fc0f39bcSBrett Creeley /**
3127fc0f39bcSBrett Creeley  * ice_clear_dflt_vsi - clear the default forwarding VSI
3128fc0f39bcSBrett Creeley  * @sw: switch used to clear the default VSI
3129fc0f39bcSBrett Creeley  *
3130fc0f39bcSBrett Creeley  * If the switch has no default VSI or it's not enabled then return error.
3131fc0f39bcSBrett Creeley  *
3132fc0f39bcSBrett Creeley  * Otherwise try to clear the default VSI and return the result.
3133fc0f39bcSBrett Creeley  */
3134fc0f39bcSBrett Creeley int ice_clear_dflt_vsi(struct ice_sw *sw)
3135fc0f39bcSBrett Creeley {
3136fc0f39bcSBrett Creeley 	struct ice_vsi *dflt_vsi;
3137fc0f39bcSBrett Creeley 	enum ice_status status;
3138fc0f39bcSBrett Creeley 	struct device *dev;
3139fc0f39bcSBrett Creeley 
3140fc0f39bcSBrett Creeley 	if (!sw)
3141fc0f39bcSBrett Creeley 		return -EINVAL;
3142fc0f39bcSBrett Creeley 
3143fc0f39bcSBrett Creeley 	dev = ice_pf_to_dev(sw->pf);
3144fc0f39bcSBrett Creeley 
3145fc0f39bcSBrett Creeley 	dflt_vsi = sw->dflt_vsi;
3146fc0f39bcSBrett Creeley 
3147fc0f39bcSBrett Creeley 	/* there is no default VSI configured */
3148fc0f39bcSBrett Creeley 	if (!ice_is_dflt_vsi_in_use(sw))
3149fc0f39bcSBrett Creeley 		return -ENODEV;
3150fc0f39bcSBrett Creeley 
3151fc0f39bcSBrett Creeley 	status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false,
3152fc0f39bcSBrett Creeley 				  ICE_FLTR_RX);
3153fc0f39bcSBrett Creeley 	if (status) {
31540fee3577SLihong Yang 		dev_err(dev, "Failed to clear the default forwarding VSI %d, error %s\n",
31550fee3577SLihong Yang 			dflt_vsi->vsi_num, ice_stat_str(status));
3156fc0f39bcSBrett Creeley 		return -EIO;
3157fc0f39bcSBrett Creeley 	}
3158fc0f39bcSBrett Creeley 
3159fc0f39bcSBrett Creeley 	sw->dflt_vsi = NULL;
3160fc0f39bcSBrett Creeley 	sw->dflt_vsi_ena = false;
3161fc0f39bcSBrett Creeley 
3162fc0f39bcSBrett Creeley 	return 0;
3163fc0f39bcSBrett Creeley }
3164