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