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
126dae8aa0SBruce Allan  * @vsi_type: VSI type enum
13964674f1SAnirudh Venkataramanan  */
146dae8aa0SBruce Allan const char *ice_vsi_type_str(enum ice_vsi_type vsi_type)
15964674f1SAnirudh Venkataramanan {
166dae8aa0SBruce Allan 	switch (vsi_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 /**
2913a6233bSBrett Creeley  * ice_vsi_ctrl_all_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
3213a6233bSBrett Creeley  *
3313a6233bSBrett Creeley  * First enable/disable all of the Rx rings, flush any remaining writes, and
3413a6233bSBrett Creeley  * then verify that they have all been enabled/disabled successfully. This will
3513a6233bSBrett Creeley  * let all of the register writes complete when enabling/disabling the Rx rings
3613a6233bSBrett Creeley  * before waiting for the change in hardware to complete.
37d02f734cSMaciej Fijalkowski  */
3813a6233bSBrett Creeley static int ice_vsi_ctrl_all_rx_rings(struct ice_vsi *vsi, bool ena)
39d02f734cSMaciej Fijalkowski {
40d02f734cSMaciej Fijalkowski 	int i, ret = 0;
41d02f734cSMaciej Fijalkowski 
4213a6233bSBrett Creeley 	for (i = 0; i < vsi->num_rxq; i++)
4313a6233bSBrett Creeley 		ice_vsi_ctrl_one_rx_ring(vsi, ena, i, false);
4413a6233bSBrett Creeley 
4513a6233bSBrett Creeley 	ice_flush(&vsi->back->hw);
4613a6233bSBrett Creeley 
47d02f734cSMaciej Fijalkowski 	for (i = 0; i < vsi->num_rxq; i++) {
4813a6233bSBrett Creeley 		ret = ice_vsi_wait_one_rx_ring(vsi, ena, i);
49d02f734cSMaciej Fijalkowski 		if (ret)
50d02f734cSMaciej Fijalkowski 			break;
5172adf242SAnirudh Venkataramanan 	}
5272adf242SAnirudh Venkataramanan 
5372adf242SAnirudh Venkataramanan 	return ret;
5472adf242SAnirudh Venkataramanan }
5572adf242SAnirudh Venkataramanan 
5672adf242SAnirudh Venkataramanan /**
5728c2a645SAnirudh Venkataramanan  * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI
5828c2a645SAnirudh Venkataramanan  * @vsi: VSI pointer
5928c2a645SAnirudh Venkataramanan  *
6028c2a645SAnirudh Venkataramanan  * On error: returns error code (negative)
6128c2a645SAnirudh Venkataramanan  * On success: returns 0
6228c2a645SAnirudh Venkataramanan  */
63a85a3847SBrett Creeley static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
6428c2a645SAnirudh Venkataramanan {
6528c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
664015d11eSBrett Creeley 	struct device *dev;
674015d11eSBrett Creeley 
684015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
6928c2a645SAnirudh Venkataramanan 
7028c2a645SAnirudh Venkataramanan 	/* allocate memory for both Tx and Rx ring pointers */
714015d11eSBrett Creeley 	vsi->tx_rings = devm_kcalloc(dev, vsi->alloc_txq,
72c6dfd690SBruce Allan 				     sizeof(*vsi->tx_rings), GFP_KERNEL);
7328c2a645SAnirudh Venkataramanan 	if (!vsi->tx_rings)
7478b5713aSAnirudh Venkataramanan 		return -ENOMEM;
7528c2a645SAnirudh Venkataramanan 
764015d11eSBrett Creeley 	vsi->rx_rings = devm_kcalloc(dev, vsi->alloc_rxq,
77c6dfd690SBruce Allan 				     sizeof(*vsi->rx_rings), GFP_KERNEL);
7828c2a645SAnirudh Venkataramanan 	if (!vsi->rx_rings)
7978b5713aSAnirudh Venkataramanan 		goto err_rings;
8078b5713aSAnirudh Venkataramanan 
81efc2214bSMaciej Fijalkowski 	/* XDP will have vsi->alloc_txq Tx queues as well, so double the size */
824015d11eSBrett Creeley 	vsi->txq_map = devm_kcalloc(dev, (2 * vsi->alloc_txq),
8378b5713aSAnirudh Venkataramanan 				    sizeof(*vsi->txq_map), GFP_KERNEL);
8478b5713aSAnirudh Venkataramanan 
8578b5713aSAnirudh Venkataramanan 	if (!vsi->txq_map)
8678b5713aSAnirudh Venkataramanan 		goto err_txq_map;
8778b5713aSAnirudh Venkataramanan 
884015d11eSBrett Creeley 	vsi->rxq_map = devm_kcalloc(dev, vsi->alloc_rxq,
8978b5713aSAnirudh Venkataramanan 				    sizeof(*vsi->rxq_map), GFP_KERNEL);
9078b5713aSAnirudh Venkataramanan 	if (!vsi->rxq_map)
9178b5713aSAnirudh Venkataramanan 		goto err_rxq_map;
9278b5713aSAnirudh Venkataramanan 
930e674aebSAnirudh Venkataramanan 	/* There is no need to allocate q_vectors for a loopback VSI. */
940e674aebSAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_LB)
950e674aebSAnirudh Venkataramanan 		return 0;
960e674aebSAnirudh Venkataramanan 
9728c2a645SAnirudh Venkataramanan 	/* allocate memory for q_vector pointers */
984015d11eSBrett Creeley 	vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors,
99a85a3847SBrett Creeley 				      sizeof(*vsi->q_vectors), GFP_KERNEL);
10028c2a645SAnirudh Venkataramanan 	if (!vsi->q_vectors)
10128c2a645SAnirudh Venkataramanan 		goto err_vectors;
10228c2a645SAnirudh Venkataramanan 
10328c2a645SAnirudh Venkataramanan 	return 0;
10428c2a645SAnirudh Venkataramanan 
10528c2a645SAnirudh Venkataramanan err_vectors:
1064015d11eSBrett Creeley 	devm_kfree(dev, vsi->rxq_map);
10778b5713aSAnirudh Venkataramanan err_rxq_map:
1084015d11eSBrett Creeley 	devm_kfree(dev, vsi->txq_map);
10978b5713aSAnirudh Venkataramanan err_txq_map:
1104015d11eSBrett Creeley 	devm_kfree(dev, vsi->rx_rings);
11178b5713aSAnirudh Venkataramanan err_rings:
1124015d11eSBrett Creeley 	devm_kfree(dev, vsi->tx_rings);
11328c2a645SAnirudh Venkataramanan 	return -ENOMEM;
11428c2a645SAnirudh Venkataramanan }
11528c2a645SAnirudh Venkataramanan 
11628c2a645SAnirudh Venkataramanan /**
117ad71b256SBrett Creeley  * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI
118ad71b256SBrett Creeley  * @vsi: the VSI being configured
119ad71b256SBrett Creeley  */
120ad71b256SBrett Creeley static void ice_vsi_set_num_desc(struct ice_vsi *vsi)
121ad71b256SBrett Creeley {
122ad71b256SBrett Creeley 	switch (vsi->type) {
123ad71b256SBrett Creeley 	case ICE_VSI_PF:
1240e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
125ad71b256SBrett Creeley 		vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC;
126ad71b256SBrett Creeley 		vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC;
127ad71b256SBrett Creeley 		break;
128ad71b256SBrett Creeley 	default:
12919cce2c6SAnirudh Venkataramanan 		dev_dbg(ice_pf_to_dev(vsi->back), "Not setting number of Tx/Rx descriptors for VSI type %d\n",
130ad71b256SBrett Creeley 			vsi->type);
131ad71b256SBrett Creeley 		break;
132ad71b256SBrett Creeley 	}
133ad71b256SBrett Creeley }
134ad71b256SBrett Creeley 
135ad71b256SBrett Creeley /**
136ad71b256SBrett Creeley  * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI
13728c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
138f9867df6SAnirudh Venkataramanan  * @vf_id: ID of the VF being configured
13928c2a645SAnirudh Venkataramanan  *
14028c2a645SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
14128c2a645SAnirudh Venkataramanan  */
1425743020dSAkeem G Abodunrin static void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
14328c2a645SAnirudh Venkataramanan {
14428c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
1455743020dSAkeem G Abodunrin 	struct ice_vf *vf = NULL;
1465743020dSAkeem G Abodunrin 
1475743020dSAkeem G Abodunrin 	if (vsi->type == ICE_VSI_VF)
1485743020dSAkeem G Abodunrin 		vsi->vf_id = vf_id;
1495743020dSAkeem G Abodunrin 
15028c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
15128c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
1528c243700SAnirudh Venkataramanan 		vsi->alloc_txq = min_t(int, ice_get_avail_txq_count(pf),
1538c243700SAnirudh Venkataramanan 				       num_online_cpus());
15487324e74SHenry Tieman 		if (vsi->req_txq) {
15587324e74SHenry Tieman 			vsi->alloc_txq = vsi->req_txq;
15687324e74SHenry Tieman 			vsi->num_txq = vsi->req_txq;
15787324e74SHenry Tieman 		}
1588c243700SAnirudh Venkataramanan 
1598c243700SAnirudh Venkataramanan 		pf->num_lan_tx = vsi->alloc_txq;
1608c243700SAnirudh Venkataramanan 
1618c243700SAnirudh Venkataramanan 		/* only 1 Rx queue unless RSS is enabled */
16287324e74SHenry Tieman 		if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
1638c243700SAnirudh Venkataramanan 			vsi->alloc_rxq = 1;
16487324e74SHenry Tieman 		} else {
1658c243700SAnirudh Venkataramanan 			vsi->alloc_rxq = min_t(int, ice_get_avail_rxq_count(pf),
1668c243700SAnirudh Venkataramanan 					       num_online_cpus());
16787324e74SHenry Tieman 			if (vsi->req_rxq) {
16887324e74SHenry Tieman 				vsi->alloc_rxq = vsi->req_rxq;
16987324e74SHenry Tieman 				vsi->num_rxq = vsi->req_rxq;
17087324e74SHenry Tieman 			}
17187324e74SHenry Tieman 		}
1728c243700SAnirudh Venkataramanan 
1738c243700SAnirudh Venkataramanan 		pf->num_lan_rx = vsi->alloc_rxq;
1748c243700SAnirudh Venkataramanan 
17534cdcb16SBrett Creeley 		vsi->num_q_vectors = max_t(int, vsi->alloc_rxq, vsi->alloc_txq);
17628c2a645SAnirudh Venkataramanan 		break;
1778ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
1785743020dSAkeem G Abodunrin 		vf = &pf->vf[vsi->vf_id];
1795743020dSAkeem G Abodunrin 		vsi->alloc_txq = vf->num_vf_qs;
1805743020dSAkeem G Abodunrin 		vsi->alloc_rxq = vf->num_vf_qs;
18146c276ceSBrett Creeley 		/* pf->num_msix_per_vf includes (VF miscellaneous vector +
1828ede0178SAnirudh Venkataramanan 		 * data queue interrupts). Since vsi->num_q_vectors is number
183047e52c0SAnirudh Venkataramanan 		 * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the
184047e52c0SAnirudh Venkataramanan 		 * original vector count
1858ede0178SAnirudh Venkataramanan 		 */
18646c276ceSBrett Creeley 		vsi->num_q_vectors = pf->num_msix_per_vf - ICE_NONQ_VECS_VF;
1878ede0178SAnirudh Venkataramanan 		break;
1880e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
1890e674aebSAnirudh Venkataramanan 		vsi->alloc_txq = 1;
1900e674aebSAnirudh Venkataramanan 		vsi->alloc_rxq = 1;
1910e674aebSAnirudh Venkataramanan 		break;
19228c2a645SAnirudh Venkataramanan 	default:
1934015d11eSBrett Creeley 		dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi->type);
19428c2a645SAnirudh Venkataramanan 		break;
19528c2a645SAnirudh Venkataramanan 	}
196ad71b256SBrett Creeley 
197ad71b256SBrett Creeley 	ice_vsi_set_num_desc(vsi);
19828c2a645SAnirudh Venkataramanan }
19928c2a645SAnirudh Venkataramanan 
20028c2a645SAnirudh Venkataramanan /**
20128c2a645SAnirudh Venkataramanan  * ice_get_free_slot - get the next non-NULL location index in array
20228c2a645SAnirudh Venkataramanan  * @array: array to search
20328c2a645SAnirudh Venkataramanan  * @size: size of the array
20428c2a645SAnirudh Venkataramanan  * @curr: last known occupied index to be used as a search hint
20528c2a645SAnirudh Venkataramanan  *
20628c2a645SAnirudh Venkataramanan  * void * is being used to keep the functionality generic. This lets us use this
20728c2a645SAnirudh Venkataramanan  * function on any array of pointers.
20828c2a645SAnirudh Venkataramanan  */
20937bb8390SAnirudh Venkataramanan static int ice_get_free_slot(void *array, int size, int curr)
21028c2a645SAnirudh Venkataramanan {
21128c2a645SAnirudh Venkataramanan 	int **tmp_array = (int **)array;
21228c2a645SAnirudh Venkataramanan 	int next;
21328c2a645SAnirudh Venkataramanan 
21428c2a645SAnirudh Venkataramanan 	if (curr < (size - 1) && !tmp_array[curr + 1]) {
21528c2a645SAnirudh Venkataramanan 		next = curr + 1;
21628c2a645SAnirudh Venkataramanan 	} else {
21728c2a645SAnirudh Venkataramanan 		int i = 0;
21828c2a645SAnirudh Venkataramanan 
21928c2a645SAnirudh Venkataramanan 		while ((i < size) && (tmp_array[i]))
22028c2a645SAnirudh Venkataramanan 			i++;
22128c2a645SAnirudh Venkataramanan 		if (i == size)
22228c2a645SAnirudh Venkataramanan 			next = ICE_NO_VSI;
22328c2a645SAnirudh Venkataramanan 		else
22428c2a645SAnirudh Venkataramanan 			next = i;
22528c2a645SAnirudh Venkataramanan 	}
22628c2a645SAnirudh Venkataramanan 	return next;
22728c2a645SAnirudh Venkataramanan }
22828c2a645SAnirudh Venkataramanan 
22928c2a645SAnirudh Venkataramanan /**
2305153a18eSAnirudh Venkataramanan  * ice_vsi_delete - delete a VSI from the switch
2315153a18eSAnirudh Venkataramanan  * @vsi: pointer to VSI being removed
2325153a18eSAnirudh Venkataramanan  */
2335153a18eSAnirudh Venkataramanan void ice_vsi_delete(struct ice_vsi *vsi)
2345153a18eSAnirudh Venkataramanan {
2355153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
236198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
2375153a18eSAnirudh Venkataramanan 	enum ice_status status;
2385153a18eSAnirudh Venkataramanan 
2399efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
240198a666aSBruce Allan 	if (!ctxt)
241198a666aSBruce Allan 		return;
242198a666aSBruce Allan 
2438ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
244198a666aSBruce Allan 		ctxt->vf_num = vsi->vf_id;
245198a666aSBruce Allan 	ctxt->vsi_num = vsi->vsi_num;
2465153a18eSAnirudh Venkataramanan 
247198a666aSBruce Allan 	memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info));
2485153a18eSAnirudh Venkataramanan 
249198a666aSBruce Allan 	status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL);
2505153a18eSAnirudh Venkataramanan 	if (status)
2510fee3577SLihong Yang 		dev_err(ice_pf_to_dev(pf), "Failed to delete VSI %i in FW - error: %s\n",
2520fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
253198a666aSBruce Allan 
2549efe35d0STony Nguyen 	kfree(ctxt);
2555153a18eSAnirudh Venkataramanan }
2565153a18eSAnirudh Venkataramanan 
2575153a18eSAnirudh Venkataramanan /**
258a85a3847SBrett Creeley  * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI
25907309a0eSAnirudh Venkataramanan  * @vsi: pointer to VSI being cleared
26007309a0eSAnirudh Venkataramanan  */
261a85a3847SBrett Creeley static void ice_vsi_free_arrays(struct ice_vsi *vsi)
26207309a0eSAnirudh Venkataramanan {
26307309a0eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2644015d11eSBrett Creeley 	struct device *dev;
2654015d11eSBrett Creeley 
2664015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
26707309a0eSAnirudh Venkataramanan 
26807309a0eSAnirudh Venkataramanan 	/* free the ring and vector containers */
269a85a3847SBrett Creeley 	if (vsi->q_vectors) {
2704015d11eSBrett Creeley 		devm_kfree(dev, vsi->q_vectors);
27107309a0eSAnirudh Venkataramanan 		vsi->q_vectors = NULL;
27207309a0eSAnirudh Venkataramanan 	}
27307309a0eSAnirudh Venkataramanan 	if (vsi->tx_rings) {
2744015d11eSBrett Creeley 		devm_kfree(dev, vsi->tx_rings);
27507309a0eSAnirudh Venkataramanan 		vsi->tx_rings = NULL;
27607309a0eSAnirudh Venkataramanan 	}
27707309a0eSAnirudh Venkataramanan 	if (vsi->rx_rings) {
2784015d11eSBrett Creeley 		devm_kfree(dev, vsi->rx_rings);
27907309a0eSAnirudh Venkataramanan 		vsi->rx_rings = NULL;
28007309a0eSAnirudh Venkataramanan 	}
28178b5713aSAnirudh Venkataramanan 	if (vsi->txq_map) {
2824015d11eSBrett Creeley 		devm_kfree(dev, vsi->txq_map);
28378b5713aSAnirudh Venkataramanan 		vsi->txq_map = NULL;
28478b5713aSAnirudh Venkataramanan 	}
28578b5713aSAnirudh Venkataramanan 	if (vsi->rxq_map) {
2864015d11eSBrett Creeley 		devm_kfree(dev, vsi->rxq_map);
28778b5713aSAnirudh Venkataramanan 		vsi->rxq_map = NULL;
28878b5713aSAnirudh Venkataramanan 	}
28907309a0eSAnirudh Venkataramanan }
29007309a0eSAnirudh Venkataramanan 
29107309a0eSAnirudh Venkataramanan /**
29207309a0eSAnirudh Venkataramanan  * ice_vsi_clear - clean up and deallocate the provided VSI
29307309a0eSAnirudh Venkataramanan  * @vsi: pointer to VSI being cleared
29407309a0eSAnirudh Venkataramanan  *
29507309a0eSAnirudh Venkataramanan  * This deallocates the VSI's queue resources, removes it from the PF's
29607309a0eSAnirudh Venkataramanan  * VSI array if necessary, and deallocates the VSI
29707309a0eSAnirudh Venkataramanan  *
29807309a0eSAnirudh Venkataramanan  * Returns 0 on success, negative on failure
29907309a0eSAnirudh Venkataramanan  */
30007309a0eSAnirudh Venkataramanan int ice_vsi_clear(struct ice_vsi *vsi)
30107309a0eSAnirudh Venkataramanan {
30207309a0eSAnirudh Venkataramanan 	struct ice_pf *pf = NULL;
3034015d11eSBrett Creeley 	struct device *dev;
30407309a0eSAnirudh Venkataramanan 
30507309a0eSAnirudh Venkataramanan 	if (!vsi)
30607309a0eSAnirudh Venkataramanan 		return 0;
30707309a0eSAnirudh Venkataramanan 
30807309a0eSAnirudh Venkataramanan 	if (!vsi->back)
30907309a0eSAnirudh Venkataramanan 		return -EINVAL;
31007309a0eSAnirudh Venkataramanan 
31107309a0eSAnirudh Venkataramanan 	pf = vsi->back;
3124015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
31307309a0eSAnirudh Venkataramanan 
31407309a0eSAnirudh Venkataramanan 	if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) {
3154015d11eSBrett Creeley 		dev_dbg(dev, "vsi does not exist at pf->vsi[%d]\n", vsi->idx);
31607309a0eSAnirudh Venkataramanan 		return -EINVAL;
31707309a0eSAnirudh Venkataramanan 	}
31807309a0eSAnirudh Venkataramanan 
31907309a0eSAnirudh Venkataramanan 	mutex_lock(&pf->sw_mutex);
32007309a0eSAnirudh Venkataramanan 	/* updates the PF for this cleared VSI */
32107309a0eSAnirudh Venkataramanan 
32207309a0eSAnirudh Venkataramanan 	pf->vsi[vsi->idx] = NULL;
32307309a0eSAnirudh Venkataramanan 	if (vsi->idx < pf->next_vsi)
32407309a0eSAnirudh Venkataramanan 		pf->next_vsi = vsi->idx;
32507309a0eSAnirudh Venkataramanan 
326a85a3847SBrett Creeley 	ice_vsi_free_arrays(vsi);
32707309a0eSAnirudh Venkataramanan 	mutex_unlock(&pf->sw_mutex);
3284015d11eSBrett Creeley 	devm_kfree(dev, vsi);
32907309a0eSAnirudh Venkataramanan 
33007309a0eSAnirudh Venkataramanan 	return 0;
33107309a0eSAnirudh Venkataramanan }
33207309a0eSAnirudh Venkataramanan 
33307309a0eSAnirudh Venkataramanan /**
3345153a18eSAnirudh Venkataramanan  * ice_msix_clean_rings - MSIX mode Interrupt Handler
3355153a18eSAnirudh Venkataramanan  * @irq: interrupt number
3365153a18eSAnirudh Venkataramanan  * @data: pointer to a q_vector
3375153a18eSAnirudh Venkataramanan  */
338f3aaaaaaSAnirudh Venkataramanan static irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
3395153a18eSAnirudh Venkataramanan {
3405153a18eSAnirudh Venkataramanan 	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
3415153a18eSAnirudh Venkataramanan 
3425153a18eSAnirudh Venkataramanan 	if (!q_vector->tx.ring && !q_vector->rx.ring)
3435153a18eSAnirudh Venkataramanan 		return IRQ_HANDLED;
3445153a18eSAnirudh Venkataramanan 
3455153a18eSAnirudh Venkataramanan 	napi_schedule(&q_vector->napi);
3465153a18eSAnirudh Venkataramanan 
3475153a18eSAnirudh Venkataramanan 	return IRQ_HANDLED;
3485153a18eSAnirudh Venkataramanan }
3495153a18eSAnirudh Venkataramanan 
3505153a18eSAnirudh Venkataramanan /**
35137bb8390SAnirudh Venkataramanan  * ice_vsi_alloc - Allocates the next available struct VSI in the PF
35237bb8390SAnirudh Venkataramanan  * @pf: board private structure
3536dae8aa0SBruce Allan  * @vsi_type: type of VSI
354f9867df6SAnirudh Venkataramanan  * @vf_id: ID of the VF being configured
35537bb8390SAnirudh Venkataramanan  *
35637bb8390SAnirudh Venkataramanan  * returns a pointer to a VSI on success, NULL on failure.
35737bb8390SAnirudh Venkataramanan  */
3585743020dSAkeem G Abodunrin static struct ice_vsi *
3596dae8aa0SBruce Allan ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type, u16 vf_id)
36037bb8390SAnirudh Venkataramanan {
3614015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
36237bb8390SAnirudh Venkataramanan 	struct ice_vsi *vsi = NULL;
36337bb8390SAnirudh Venkataramanan 
36437bb8390SAnirudh Venkataramanan 	/* Need to protect the allocation of the VSIs at the PF level */
36537bb8390SAnirudh Venkataramanan 	mutex_lock(&pf->sw_mutex);
36637bb8390SAnirudh Venkataramanan 
36737bb8390SAnirudh Venkataramanan 	/* If we have already allocated our maximum number of VSIs,
36837bb8390SAnirudh Venkataramanan 	 * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index
36937bb8390SAnirudh Venkataramanan 	 * is available to be populated
37037bb8390SAnirudh Venkataramanan 	 */
37137bb8390SAnirudh Venkataramanan 	if (pf->next_vsi == ICE_NO_VSI) {
3724015d11eSBrett Creeley 		dev_dbg(dev, "out of VSI slots!\n");
37337bb8390SAnirudh Venkataramanan 		goto unlock_pf;
37437bb8390SAnirudh Venkataramanan 	}
37537bb8390SAnirudh Venkataramanan 
3764015d11eSBrett Creeley 	vsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL);
37737bb8390SAnirudh Venkataramanan 	if (!vsi)
37837bb8390SAnirudh Venkataramanan 		goto unlock_pf;
37937bb8390SAnirudh Venkataramanan 
3806dae8aa0SBruce Allan 	vsi->type = vsi_type;
38137bb8390SAnirudh Venkataramanan 	vsi->back = pf;
38237bb8390SAnirudh Venkataramanan 	set_bit(__ICE_DOWN, vsi->state);
3839d56b7fdSJesse Brandeburg 
38437bb8390SAnirudh Venkataramanan 	vsi->idx = pf->next_vsi;
38537bb8390SAnirudh Venkataramanan 
3866dae8aa0SBruce Allan 	if (vsi_type == ICE_VSI_VF)
3875743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, vf_id);
3885743020dSAkeem G Abodunrin 	else
3895743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
39037bb8390SAnirudh Venkataramanan 
39137bb8390SAnirudh Venkataramanan 	switch (vsi->type) {
39237bb8390SAnirudh Venkataramanan 	case ICE_VSI_PF:
393a85a3847SBrett Creeley 		if (ice_vsi_alloc_arrays(vsi))
39437bb8390SAnirudh Venkataramanan 			goto err_rings;
39537bb8390SAnirudh Venkataramanan 
39637bb8390SAnirudh Venkataramanan 		/* Setup default MSIX irq handler for VSI */
39737bb8390SAnirudh Venkataramanan 		vsi->irq_handler = ice_msix_clean_rings;
39837bb8390SAnirudh Venkataramanan 		break;
3998ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
400a85a3847SBrett Creeley 		if (ice_vsi_alloc_arrays(vsi))
4018ede0178SAnirudh Venkataramanan 			goto err_rings;
4028ede0178SAnirudh Venkataramanan 		break;
4030e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
4040e674aebSAnirudh Venkataramanan 		if (ice_vsi_alloc_arrays(vsi))
4050e674aebSAnirudh Venkataramanan 			goto err_rings;
4060e674aebSAnirudh Venkataramanan 		break;
40737bb8390SAnirudh Venkataramanan 	default:
4084015d11eSBrett Creeley 		dev_warn(dev, "Unknown VSI type %d\n", vsi->type);
40937bb8390SAnirudh Venkataramanan 		goto unlock_pf;
41037bb8390SAnirudh Venkataramanan 	}
41137bb8390SAnirudh Venkataramanan 
41237bb8390SAnirudh Venkataramanan 	/* fill VSI slot in the PF struct */
41337bb8390SAnirudh Venkataramanan 	pf->vsi[pf->next_vsi] = vsi;
41437bb8390SAnirudh Venkataramanan 
41537bb8390SAnirudh Venkataramanan 	/* prepare pf->next_vsi for next use */
41637bb8390SAnirudh Venkataramanan 	pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi,
41737bb8390SAnirudh Venkataramanan 					 pf->next_vsi);
41837bb8390SAnirudh Venkataramanan 	goto unlock_pf;
41937bb8390SAnirudh Venkataramanan 
42037bb8390SAnirudh Venkataramanan err_rings:
4214015d11eSBrett Creeley 	devm_kfree(dev, vsi);
42237bb8390SAnirudh Venkataramanan 	vsi = NULL;
42337bb8390SAnirudh Venkataramanan unlock_pf:
42437bb8390SAnirudh Venkataramanan 	mutex_unlock(&pf->sw_mutex);
42537bb8390SAnirudh Venkataramanan 	return vsi;
42637bb8390SAnirudh Venkataramanan }
42737bb8390SAnirudh Venkataramanan 
42837bb8390SAnirudh Venkataramanan /**
429df0f8479SAnirudh Venkataramanan  * ice_vsi_get_qs - Assign queues from PF to VSI
430df0f8479SAnirudh Venkataramanan  * @vsi: the VSI to assign queues to
431df0f8479SAnirudh Venkataramanan  *
432df0f8479SAnirudh Venkataramanan  * Returns 0 on success and a negative value on error
433df0f8479SAnirudh Venkataramanan  */
43437bb8390SAnirudh Venkataramanan static int ice_vsi_get_qs(struct ice_vsi *vsi)
435df0f8479SAnirudh Venkataramanan {
43603f7a986SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
43703f7a986SAnirudh Venkataramanan 	struct ice_qs_cfg tx_qs_cfg = {
43803f7a986SAnirudh Venkataramanan 		.qs_mutex = &pf->avail_q_mutex,
43903f7a986SAnirudh Venkataramanan 		.pf_map = pf->avail_txqs,
44078b5713aSAnirudh Venkataramanan 		.pf_map_size = pf->max_pf_txqs,
44103f7a986SAnirudh Venkataramanan 		.q_count = vsi->alloc_txq,
44203f7a986SAnirudh Venkataramanan 		.scatter_count = ICE_MAX_SCATTER_TXQS,
44303f7a986SAnirudh Venkataramanan 		.vsi_map = vsi->txq_map,
44403f7a986SAnirudh Venkataramanan 		.vsi_map_offset = 0,
44539066dc5SBrett Creeley 		.mapping_mode = ICE_VSI_MAP_CONTIG
44603f7a986SAnirudh Venkataramanan 	};
44703f7a986SAnirudh Venkataramanan 	struct ice_qs_cfg rx_qs_cfg = {
44803f7a986SAnirudh Venkataramanan 		.qs_mutex = &pf->avail_q_mutex,
44903f7a986SAnirudh Venkataramanan 		.pf_map = pf->avail_rxqs,
45078b5713aSAnirudh Venkataramanan 		.pf_map_size = pf->max_pf_rxqs,
45103f7a986SAnirudh Venkataramanan 		.q_count = vsi->alloc_rxq,
45203f7a986SAnirudh Venkataramanan 		.scatter_count = ICE_MAX_SCATTER_RXQS,
45303f7a986SAnirudh Venkataramanan 		.vsi_map = vsi->rxq_map,
45403f7a986SAnirudh Venkataramanan 		.vsi_map_offset = 0,
45539066dc5SBrett Creeley 		.mapping_mode = ICE_VSI_MAP_CONTIG
45603f7a986SAnirudh Venkataramanan 	};
45739066dc5SBrett Creeley 	int ret;
458df0f8479SAnirudh Venkataramanan 
45903f7a986SAnirudh Venkataramanan 	ret = __ice_vsi_get_qs(&tx_qs_cfg);
46039066dc5SBrett Creeley 	if (ret)
461df0f8479SAnirudh Venkataramanan 		return ret;
46239066dc5SBrett Creeley 	vsi->tx_mapping_mode = tx_qs_cfg.mapping_mode;
46339066dc5SBrett Creeley 
46439066dc5SBrett Creeley 	ret = __ice_vsi_get_qs(&rx_qs_cfg);
46539066dc5SBrett Creeley 	if (ret)
46639066dc5SBrett Creeley 		return ret;
46739066dc5SBrett Creeley 	vsi->rx_mapping_mode = rx_qs_cfg.mapping_mode;
46839066dc5SBrett Creeley 
46939066dc5SBrett Creeley 	return 0;
470df0f8479SAnirudh Venkataramanan }
471df0f8479SAnirudh Venkataramanan 
472df0f8479SAnirudh Venkataramanan /**
4735153a18eSAnirudh Venkataramanan  * ice_vsi_put_qs - Release queues from VSI to PF
4745153a18eSAnirudh Venkataramanan  * @vsi: the VSI that is going to release queues
4755153a18eSAnirudh Venkataramanan  */
4765153a18eSAnirudh Venkataramanan void ice_vsi_put_qs(struct ice_vsi *vsi)
4775153a18eSAnirudh Venkataramanan {
4785153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
4795153a18eSAnirudh Venkataramanan 	int i;
4805153a18eSAnirudh Venkataramanan 
4815153a18eSAnirudh Venkataramanan 	mutex_lock(&pf->avail_q_mutex);
4825153a18eSAnirudh Venkataramanan 
4835153a18eSAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_txq; i++) {
4845153a18eSAnirudh Venkataramanan 		clear_bit(vsi->txq_map[i], pf->avail_txqs);
4855153a18eSAnirudh Venkataramanan 		vsi->txq_map[i] = ICE_INVAL_Q_INDEX;
4865153a18eSAnirudh Venkataramanan 	}
4875153a18eSAnirudh Venkataramanan 
4885153a18eSAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_rxq; i++) {
4895153a18eSAnirudh Venkataramanan 		clear_bit(vsi->rxq_map[i], pf->avail_rxqs);
4905153a18eSAnirudh Venkataramanan 		vsi->rxq_map[i] = ICE_INVAL_Q_INDEX;
4915153a18eSAnirudh Venkataramanan 	}
4925153a18eSAnirudh Venkataramanan 
4935153a18eSAnirudh Venkataramanan 	mutex_unlock(&pf->avail_q_mutex);
4945153a18eSAnirudh Venkataramanan }
4955153a18eSAnirudh Venkataramanan 
4965153a18eSAnirudh Venkataramanan /**
497462acf6aSTony Nguyen  * ice_is_safe_mode
498462acf6aSTony Nguyen  * @pf: pointer to the PF struct
499462acf6aSTony Nguyen  *
500462acf6aSTony Nguyen  * returns true if driver is in safe mode, false otherwise
501462acf6aSTony Nguyen  */
502462acf6aSTony Nguyen bool ice_is_safe_mode(struct ice_pf *pf)
503462acf6aSTony Nguyen {
504462acf6aSTony Nguyen 	return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
505462acf6aSTony Nguyen }
506462acf6aSTony Nguyen 
507462acf6aSTony Nguyen /**
5082c61054cSTony Nguyen  * ice_vsi_clean_rss_flow_fld - Delete RSS configuration
5092c61054cSTony Nguyen  * @vsi: the VSI being cleaned up
5102c61054cSTony Nguyen  *
5112c61054cSTony Nguyen  * This function deletes RSS input set for all flows that were configured
5122c61054cSTony Nguyen  * for this VSI
5132c61054cSTony Nguyen  */
5142c61054cSTony Nguyen static void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi)
5152c61054cSTony Nguyen {
5162c61054cSTony Nguyen 	struct ice_pf *pf = vsi->back;
5172c61054cSTony Nguyen 	enum ice_status status;
5182c61054cSTony Nguyen 
5192c61054cSTony Nguyen 	if (ice_is_safe_mode(pf))
5202c61054cSTony Nguyen 		return;
5212c61054cSTony Nguyen 
5222c61054cSTony Nguyen 	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
5232c61054cSTony Nguyen 	if (status)
5240fee3577SLihong Yang 		dev_dbg(ice_pf_to_dev(pf), "ice_rem_vsi_rss_cfg failed for vsi = %d, error = %s\n",
5250fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
5262c61054cSTony Nguyen }
5272c61054cSTony Nguyen 
5282c61054cSTony Nguyen /**
5292c61054cSTony Nguyen  * ice_rss_clean - Delete RSS related VSI structures and configuration
530df0f8479SAnirudh Venkataramanan  * @vsi: the VSI being removed
531df0f8479SAnirudh Venkataramanan  */
532df0f8479SAnirudh Venkataramanan static void ice_rss_clean(struct ice_vsi *vsi)
533df0f8479SAnirudh Venkataramanan {
5344015d11eSBrett Creeley 	struct ice_pf *pf = vsi->back;
5354015d11eSBrett Creeley 	struct device *dev;
536df0f8479SAnirudh Venkataramanan 
5374015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
538df0f8479SAnirudh Venkataramanan 
539df0f8479SAnirudh Venkataramanan 	if (vsi->rss_hkey_user)
5404015d11eSBrett Creeley 		devm_kfree(dev, vsi->rss_hkey_user);
541df0f8479SAnirudh Venkataramanan 	if (vsi->rss_lut_user)
5424015d11eSBrett Creeley 		devm_kfree(dev, vsi->rss_lut_user);
5432c61054cSTony Nguyen 
5442c61054cSTony Nguyen 	ice_vsi_clean_rss_flow_fld(vsi);
5452c61054cSTony Nguyen 	/* remove RSS replay list */
5462c61054cSTony Nguyen 	if (!ice_is_safe_mode(pf))
5472c61054cSTony Nguyen 		ice_rem_vsi_rss_list(&pf->hw, vsi->idx);
548df0f8479SAnirudh Venkataramanan }
549df0f8479SAnirudh Venkataramanan 
550df0f8479SAnirudh Venkataramanan /**
55128c2a645SAnirudh Venkataramanan  * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type
55228c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
55328c2a645SAnirudh Venkataramanan  */
55437bb8390SAnirudh Venkataramanan static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
55528c2a645SAnirudh Venkataramanan {
55628c2a645SAnirudh Venkataramanan 	struct ice_hw_common_caps *cap;
55728c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
55828c2a645SAnirudh Venkataramanan 
55928c2a645SAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
56028c2a645SAnirudh Venkataramanan 		vsi->rss_size = 1;
56128c2a645SAnirudh Venkataramanan 		return;
56228c2a645SAnirudh Venkataramanan 	}
56328c2a645SAnirudh Venkataramanan 
56428c2a645SAnirudh Venkataramanan 	cap = &pf->hw.func_caps.common_cap;
56528c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
56628c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
56728c2a645SAnirudh Venkataramanan 		/* PF VSI will inherit RSS instance of PF */
56828c2a645SAnirudh Venkataramanan 		vsi->rss_table_size = cap->rss_table_size;
56928c2a645SAnirudh Venkataramanan 		vsi->rss_size = min_t(int, num_online_cpus(),
57028c2a645SAnirudh Venkataramanan 				      BIT(cap->rss_table_entry_width));
57128c2a645SAnirudh Venkataramanan 		vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF;
57228c2a645SAnirudh Venkataramanan 		break;
5738ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
5740ca469fbSMitch Williams 		/* VF VSI will get a small RSS table.
5750ca469fbSMitch Williams 		 * For VSI_LUT, LUT size should be set to 64 bytes.
5768ede0178SAnirudh Venkataramanan 		 */
5778ede0178SAnirudh Venkataramanan 		vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE;
5780ca469fbSMitch Williams 		vsi->rss_size = ICE_MAX_RSS_QS_PER_VF;
5798ede0178SAnirudh Venkataramanan 		vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI;
5808ede0178SAnirudh Venkataramanan 		break;
5810e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
5820e674aebSAnirudh Venkataramanan 		break;
58328c2a645SAnirudh Venkataramanan 	default:
5844015d11eSBrett Creeley 		dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n",
58528c2a645SAnirudh Venkataramanan 			 vsi->type);
58628c2a645SAnirudh Venkataramanan 		break;
58728c2a645SAnirudh Venkataramanan 	}
58828c2a645SAnirudh Venkataramanan }
58928c2a645SAnirudh Venkataramanan 
59028c2a645SAnirudh Venkataramanan /**
59128c2a645SAnirudh Venkataramanan  * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
59228c2a645SAnirudh Venkataramanan  * @ctxt: the VSI context being set
59328c2a645SAnirudh Venkataramanan  *
59428c2a645SAnirudh Venkataramanan  * This initializes a default VSI context for all sections except the Queues.
59528c2a645SAnirudh Venkataramanan  */
59628c2a645SAnirudh Venkataramanan static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
59728c2a645SAnirudh Venkataramanan {
59828c2a645SAnirudh Venkataramanan 	u32 table = 0;
59928c2a645SAnirudh Venkataramanan 
60028c2a645SAnirudh Venkataramanan 	memset(&ctxt->info, 0, sizeof(ctxt->info));
60128c2a645SAnirudh Venkataramanan 	/* VSI's should be allocated from shared pool */
60228c2a645SAnirudh Venkataramanan 	ctxt->alloc_from_pool = true;
60328c2a645SAnirudh Venkataramanan 	/* Src pruning enabled by default */
60428c2a645SAnirudh Venkataramanan 	ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
60528c2a645SAnirudh Venkataramanan 	/* Traffic from VSI can be sent to LAN */
60628c2a645SAnirudh Venkataramanan 	ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
60728c2a645SAnirudh Venkataramanan 	/* By default bits 3 and 4 in vlan_flags are 0's which results in legacy
60828c2a645SAnirudh Venkataramanan 	 * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all
60928c2a645SAnirudh Venkataramanan 	 * packets untagged/tagged.
61028c2a645SAnirudh Venkataramanan 	 */
61128c2a645SAnirudh Venkataramanan 	ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL &
61228c2a645SAnirudh Venkataramanan 				  ICE_AQ_VSI_VLAN_MODE_M) >>
61328c2a645SAnirudh Venkataramanan 				 ICE_AQ_VSI_VLAN_MODE_S);
61428c2a645SAnirudh Venkataramanan 	/* Have 1:1 UP mapping for both ingress/egress tables */
61528c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(0, 0);
61628c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(1, 1);
61728c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(2, 2);
61828c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(3, 3);
61928c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(4, 4);
62028c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(5, 5);
62128c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(6, 6);
62228c2a645SAnirudh Venkataramanan 	table |= ICE_UP_TABLE_TRANSLATE(7, 7);
62328c2a645SAnirudh Venkataramanan 	ctxt->info.ingress_table = cpu_to_le32(table);
62428c2a645SAnirudh Venkataramanan 	ctxt->info.egress_table = cpu_to_le32(table);
62528c2a645SAnirudh Venkataramanan 	/* Have 1:1 UP mapping for outer to inner UP table */
62628c2a645SAnirudh Venkataramanan 	ctxt->info.outer_up_table = cpu_to_le32(table);
62728c2a645SAnirudh Venkataramanan 	/* No Outer tag support outer_tag_flags remains to zero */
62828c2a645SAnirudh Venkataramanan }
62928c2a645SAnirudh Venkataramanan 
63028c2a645SAnirudh Venkataramanan /**
63128c2a645SAnirudh Venkataramanan  * ice_vsi_setup_q_map - Setup a VSI queue map
63228c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
63328c2a645SAnirudh Venkataramanan  * @ctxt: VSI context structure
63428c2a645SAnirudh Venkataramanan  */
63528c2a645SAnirudh Venkataramanan static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
63628c2a645SAnirudh Venkataramanan {
637c5a2a4a3SUsha Ketineni 	u16 offset = 0, qmap = 0, tx_count = 0;
63828c2a645SAnirudh Venkataramanan 	u16 qcount_tx = vsi->alloc_txq;
63928c2a645SAnirudh Venkataramanan 	u16 qcount_rx = vsi->alloc_rxq;
640c5a2a4a3SUsha Ketineni 	u16 tx_numq_tc, rx_numq_tc;
641c5a2a4a3SUsha Ketineni 	u16 pow = 0, max_rss = 0;
64228c2a645SAnirudh Venkataramanan 	bool ena_tc0 = false;
643c5a2a4a3SUsha Ketineni 	u8 netdev_tc = 0;
64428c2a645SAnirudh Venkataramanan 	int i;
64528c2a645SAnirudh Venkataramanan 
64628c2a645SAnirudh Venkataramanan 	/* at least TC0 should be enabled by default */
64728c2a645SAnirudh Venkataramanan 	if (vsi->tc_cfg.numtc) {
64828c2a645SAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(0)))
64928c2a645SAnirudh Venkataramanan 			ena_tc0 = true;
65028c2a645SAnirudh Venkataramanan 	} else {
65128c2a645SAnirudh Venkataramanan 		ena_tc0 = true;
65228c2a645SAnirudh Venkataramanan 	}
65328c2a645SAnirudh Venkataramanan 
65428c2a645SAnirudh Venkataramanan 	if (ena_tc0) {
65528c2a645SAnirudh Venkataramanan 		vsi->tc_cfg.numtc++;
65628c2a645SAnirudh Venkataramanan 		vsi->tc_cfg.ena_tc |= 1;
65728c2a645SAnirudh Venkataramanan 	}
65828c2a645SAnirudh Venkataramanan 
659c5a2a4a3SUsha Ketineni 	rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc;
660c5a2a4a3SUsha Ketineni 	if (!rx_numq_tc)
661c5a2a4a3SUsha Ketineni 		rx_numq_tc = 1;
662c5a2a4a3SUsha Ketineni 	tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc;
663c5a2a4a3SUsha Ketineni 	if (!tx_numq_tc)
664c5a2a4a3SUsha Ketineni 		tx_numq_tc = 1;
66528c2a645SAnirudh Venkataramanan 
66628c2a645SAnirudh Venkataramanan 	/* TC mapping is a function of the number of Rx queues assigned to the
66728c2a645SAnirudh Venkataramanan 	 * VSI for each traffic class and the offset of these queues.
66828c2a645SAnirudh Venkataramanan 	 * The first 10 bits are for queue offset for TC0, next 4 bits for no:of
66928c2a645SAnirudh Venkataramanan 	 * queues allocated to TC0. No:of queues is a power-of-2.
67028c2a645SAnirudh Venkataramanan 	 *
67128c2a645SAnirudh Venkataramanan 	 * If TC is not enabled, the queue offset is set to 0, and allocate one
67228c2a645SAnirudh Venkataramanan 	 * queue, this way, traffic for the given TC will be sent to the default
67328c2a645SAnirudh Venkataramanan 	 * queue.
67428c2a645SAnirudh Venkataramanan 	 *
67528c2a645SAnirudh Venkataramanan 	 * Setup number and offset of Rx queues for all TCs for the VSI
67628c2a645SAnirudh Venkataramanan 	 */
67728c2a645SAnirudh Venkataramanan 
678c5a2a4a3SUsha Ketineni 	qcount_rx = rx_numq_tc;
679c5a2a4a3SUsha Ketineni 
68028c2a645SAnirudh Venkataramanan 	/* qcount will change if RSS is enabled */
68128c2a645SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) {
6828ede0178SAnirudh Venkataramanan 		if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) {
68328c2a645SAnirudh Venkataramanan 			if (vsi->type == ICE_VSI_PF)
68428c2a645SAnirudh Venkataramanan 				max_rss = ICE_MAX_LG_RSS_QS;
68528c2a645SAnirudh Venkataramanan 			else
6860ca469fbSMitch Williams 				max_rss = ICE_MAX_RSS_QS_PER_VF;
687c5a2a4a3SUsha Ketineni 			qcount_rx = min_t(int, rx_numq_tc, max_rss);
68887324e74SHenry Tieman 			if (!vsi->req_rxq)
68987324e74SHenry Tieman 				qcount_rx = min_t(int, qcount_rx,
69087324e74SHenry Tieman 						  vsi->rss_size);
6918ede0178SAnirudh Venkataramanan 		}
69228c2a645SAnirudh Venkataramanan 	}
69328c2a645SAnirudh Venkataramanan 
69428c2a645SAnirudh Venkataramanan 	/* find the (rounded up) power-of-2 of qcount */
695c5a2a4a3SUsha Ketineni 	pow = order_base_2(qcount_rx);
69628c2a645SAnirudh Venkataramanan 
6972bdc97beSBruce Allan 	ice_for_each_traffic_class(i) {
69828c2a645SAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
69928c2a645SAnirudh Venkataramanan 			/* TC is not enabled */
70028c2a645SAnirudh Venkataramanan 			vsi->tc_cfg.tc_info[i].qoffset = 0;
701c5a2a4a3SUsha Ketineni 			vsi->tc_cfg.tc_info[i].qcount_rx = 1;
702c5a2a4a3SUsha Ketineni 			vsi->tc_cfg.tc_info[i].qcount_tx = 1;
703c5a2a4a3SUsha Ketineni 			vsi->tc_cfg.tc_info[i].netdev_tc = 0;
70428c2a645SAnirudh Venkataramanan 			ctxt->info.tc_mapping[i] = 0;
70528c2a645SAnirudh Venkataramanan 			continue;
70628c2a645SAnirudh Venkataramanan 		}
70728c2a645SAnirudh Venkataramanan 
70828c2a645SAnirudh Venkataramanan 		/* TC is enabled */
70928c2a645SAnirudh Venkataramanan 		vsi->tc_cfg.tc_info[i].qoffset = offset;
710c5a2a4a3SUsha Ketineni 		vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx;
711c5a2a4a3SUsha Ketineni 		vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc;
712c5a2a4a3SUsha Ketineni 		vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++;
71328c2a645SAnirudh Venkataramanan 
71428c2a645SAnirudh Venkataramanan 		qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
71528c2a645SAnirudh Venkataramanan 			ICE_AQ_VSI_TC_Q_OFFSET_M) |
71628c2a645SAnirudh Venkataramanan 			((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
71728c2a645SAnirudh Venkataramanan 			 ICE_AQ_VSI_TC_Q_NUM_M);
718c5a2a4a3SUsha Ketineni 		offset += qcount_rx;
719c5a2a4a3SUsha Ketineni 		tx_count += tx_numq_tc;
72028c2a645SAnirudh Venkataramanan 		ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
72128c2a645SAnirudh Venkataramanan 	}
72260dcc39eSKiran Patil 
72360dcc39eSKiran Patil 	/* if offset is non-zero, means it is calculated correctly based on
72460dcc39eSKiran Patil 	 * enabled TCs for a given VSI otherwise qcount_rx will always
72560dcc39eSKiran Patil 	 * be correct and non-zero because it is based off - VSI's
72660dcc39eSKiran Patil 	 * allocated Rx queues which is at least 1 (hence qcount_tx will be
72760dcc39eSKiran Patil 	 * at least 1)
72860dcc39eSKiran Patil 	 */
72960dcc39eSKiran Patil 	if (offset)
73028c2a645SAnirudh Venkataramanan 		vsi->num_rxq = offset;
73160dcc39eSKiran Patil 	else
73260dcc39eSKiran Patil 		vsi->num_rxq = qcount_rx;
73360dcc39eSKiran Patil 
734c5a2a4a3SUsha Ketineni 	vsi->num_txq = tx_count;
73528c2a645SAnirudh Venkataramanan 
7368ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
7379a946843SAnirudh 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");
7388ede0178SAnirudh Venkataramanan 		/* since there is a chance that num_rxq could have been changed
7398ede0178SAnirudh Venkataramanan 		 * in the above for loop, make num_txq equal to num_rxq.
7408ede0178SAnirudh Venkataramanan 		 */
7418ede0178SAnirudh Venkataramanan 		vsi->num_txq = vsi->num_rxq;
7428ede0178SAnirudh Venkataramanan 	}
7438ede0178SAnirudh Venkataramanan 
74428c2a645SAnirudh Venkataramanan 	/* Rx queue mapping */
74528c2a645SAnirudh Venkataramanan 	ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
74628c2a645SAnirudh Venkataramanan 	/* q_mapping buffer holds the info for the first queue allocated for
74728c2a645SAnirudh Venkataramanan 	 * this VSI in the PF space and also the number of queues associated
74828c2a645SAnirudh Venkataramanan 	 * with this VSI.
74928c2a645SAnirudh Venkataramanan 	 */
75028c2a645SAnirudh Venkataramanan 	ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
75128c2a645SAnirudh Venkataramanan 	ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
75228c2a645SAnirudh Venkataramanan }
75328c2a645SAnirudh Venkataramanan 
75428c2a645SAnirudh Venkataramanan /**
75528c2a645SAnirudh Venkataramanan  * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI
75628c2a645SAnirudh Venkataramanan  * @ctxt: the VSI context being set
75728c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
75828c2a645SAnirudh Venkataramanan  */
75928c2a645SAnirudh Venkataramanan static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
76028c2a645SAnirudh Venkataramanan {
76128c2a645SAnirudh Venkataramanan 	u8 lut_type, hash_type;
7624015d11eSBrett Creeley 	struct device *dev;
763819d8998SJesse Brandeburg 	struct ice_pf *pf;
764819d8998SJesse Brandeburg 
765819d8998SJesse Brandeburg 	pf = vsi->back;
7664015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
76728c2a645SAnirudh Venkataramanan 
76828c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
76928c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
77028c2a645SAnirudh Venkataramanan 		/* PF VSI will inherit RSS instance of PF */
77128c2a645SAnirudh Venkataramanan 		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
77228c2a645SAnirudh Venkataramanan 		hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
77328c2a645SAnirudh Venkataramanan 		break;
7748ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
7758ede0178SAnirudh Venkataramanan 		/* VF VSI will gets a small RSS table which is a VSI LUT type */
7768ede0178SAnirudh Venkataramanan 		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
7778ede0178SAnirudh Venkataramanan 		hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
7788ede0178SAnirudh Venkataramanan 		break;
7790e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
7804015d11eSBrett Creeley 		dev_dbg(dev, "Unsupported VSI type %s\n",
781964674f1SAnirudh Venkataramanan 			ice_vsi_type_str(vsi->type));
7820e674aebSAnirudh Venkataramanan 		return;
78328c2a645SAnirudh Venkataramanan 	default:
7844015d11eSBrett Creeley 		dev_warn(dev, "Unknown VSI type %d\n", vsi->type);
78528c2a645SAnirudh Venkataramanan 		return;
78628c2a645SAnirudh Venkataramanan 	}
78728c2a645SAnirudh Venkataramanan 
78828c2a645SAnirudh Venkataramanan 	ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
78928c2a645SAnirudh Venkataramanan 				ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
79028c2a645SAnirudh Venkataramanan 				((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) &
79128c2a645SAnirudh Venkataramanan 				 ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
79228c2a645SAnirudh Venkataramanan }
79328c2a645SAnirudh Venkataramanan 
79428c2a645SAnirudh Venkataramanan /**
79528c2a645SAnirudh Venkataramanan  * ice_vsi_init - Create and initialize a VSI
79628c2a645SAnirudh Venkataramanan  * @vsi: the VSI being configured
79787324e74SHenry Tieman  * @init_vsi: is this call creating a VSI
79828c2a645SAnirudh Venkataramanan  *
79928c2a645SAnirudh Venkataramanan  * This initializes a VSI context depending on the VSI type to be added and
80028c2a645SAnirudh Venkataramanan  * passes it down to the add_vsi aq command to create a new VSI.
80128c2a645SAnirudh Venkataramanan  */
80287324e74SHenry Tieman static int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
80328c2a645SAnirudh Venkataramanan {
80428c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
80528c2a645SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
806198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
80787324e74SHenry Tieman 	struct device *dev;
80828c2a645SAnirudh Venkataramanan 	int ret = 0;
80928c2a645SAnirudh Venkataramanan 
81087324e74SHenry Tieman 	dev = ice_pf_to_dev(pf);
8119efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
812198a666aSBruce Allan 	if (!ctxt)
813198a666aSBruce Allan 		return -ENOMEM;
814198a666aSBruce Allan 
815cb93a952SAkeem G Abodunrin 	ctxt->info = vsi->info;
81628c2a645SAnirudh Venkataramanan 	switch (vsi->type) {
8170e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
81828c2a645SAnirudh Venkataramanan 	case ICE_VSI_PF:
819198a666aSBruce Allan 		ctxt->flags = ICE_AQ_VSI_TYPE_PF;
82028c2a645SAnirudh Venkataramanan 		break;
8218ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
822198a666aSBruce Allan 		ctxt->flags = ICE_AQ_VSI_TYPE_VF;
8238ede0178SAnirudh Venkataramanan 		/* VF number here is the absolute VF number (0-255) */
824198a666aSBruce Allan 		ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id;
8258ede0178SAnirudh Venkataramanan 		break;
82628c2a645SAnirudh Venkataramanan 	default:
8279efe35d0STony Nguyen 		ret = -ENODEV;
8289efe35d0STony Nguyen 		goto out;
82928c2a645SAnirudh Venkataramanan 	}
83028c2a645SAnirudh Venkataramanan 
831198a666aSBruce Allan 	ice_set_dflt_vsi_ctx(ctxt);
83228c2a645SAnirudh Venkataramanan 	/* if the switch is in VEB mode, allow VSI loopback */
83328c2a645SAnirudh Venkataramanan 	if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
834198a666aSBruce Allan 		ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
83528c2a645SAnirudh Venkataramanan 
83628c2a645SAnirudh Venkataramanan 	/* Set LUT type and HASH type if RSS is enabled */
83787324e74SHenry Tieman 	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
838198a666aSBruce Allan 		ice_set_rss_vsi_ctx(ctxt, vsi);
83987324e74SHenry Tieman 		/* if updating VSI context, make sure to set valid_section:
84087324e74SHenry Tieman 		 * to indicate which section of VSI context being updated
84187324e74SHenry Tieman 		 */
84287324e74SHenry Tieman 		if (!init_vsi)
84387324e74SHenry Tieman 			ctxt->info.valid_sections |=
84487324e74SHenry Tieman 				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
84587324e74SHenry Tieman 	}
84628c2a645SAnirudh Venkataramanan 
847198a666aSBruce Allan 	ctxt->info.sw_id = vsi->port_info->sw_id;
848198a666aSBruce Allan 	ice_vsi_setup_q_map(vsi, ctxt);
84987324e74SHenry Tieman 	if (!init_vsi) /* means VSI being updated */
85087324e74SHenry Tieman 		/* must to indicate which section of VSI context are
85187324e74SHenry Tieman 		 * being modified
85287324e74SHenry Tieman 		 */
85387324e74SHenry Tieman 		ctxt->info.valid_sections |=
85487324e74SHenry Tieman 			cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
85528c2a645SAnirudh Venkataramanan 
856cd6d6b83SBrett Creeley 	/* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off
857cd6d6b83SBrett Creeley 	 * respectively
858cd6d6b83SBrett Creeley 	 */
859cd6d6b83SBrett Creeley 	if (vsi->type == ICE_VSI_VF) {
860cb93a952SAkeem G Abodunrin 		ctxt->info.valid_sections |=
861cb93a952SAkeem G Abodunrin 			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
862cd6d6b83SBrett Creeley 		if (pf->vf[vsi->vf_id].spoofchk) {
863cb93a952SAkeem G Abodunrin 			ctxt->info.sec_flags |=
864cd6d6b83SBrett Creeley 				ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
865cd6d6b83SBrett Creeley 				(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
866cd6d6b83SBrett Creeley 				 ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
867cd6d6b83SBrett Creeley 		} else {
868cd6d6b83SBrett Creeley 			ctxt->info.sec_flags &=
869cd6d6b83SBrett Creeley 				~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
870cd6d6b83SBrett Creeley 				  (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
871cd6d6b83SBrett Creeley 				   ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S));
872cd6d6b83SBrett Creeley 		}
873cb93a952SAkeem G Abodunrin 	}
874cb93a952SAkeem G Abodunrin 
8750c3a6101SDave Ertman 	/* Allow control frames out of main VSI */
8760c3a6101SDave Ertman 	if (vsi->type == ICE_VSI_PF) {
8770c3a6101SDave Ertman 		ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
8780c3a6101SDave Ertman 		ctxt->info.valid_sections |=
8790c3a6101SDave Ertman 			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
8800c3a6101SDave Ertman 	}
8810c3a6101SDave Ertman 
88287324e74SHenry Tieman 	if (init_vsi) {
883198a666aSBruce Allan 		ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
88428c2a645SAnirudh Venkataramanan 		if (ret) {
88587324e74SHenry Tieman 			dev_err(dev, "Add VSI failed, err %d\n", ret);
8869efe35d0STony Nguyen 			ret = -EIO;
8879efe35d0STony Nguyen 			goto out;
88828c2a645SAnirudh Venkataramanan 		}
88987324e74SHenry Tieman 	} else {
89087324e74SHenry Tieman 		ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
89187324e74SHenry Tieman 		if (ret) {
89287324e74SHenry Tieman 			dev_err(dev, "Update VSI failed, err %d\n", ret);
89387324e74SHenry Tieman 			ret = -EIO;
89487324e74SHenry Tieman 			goto out;
89587324e74SHenry Tieman 		}
89687324e74SHenry Tieman 	}
89728c2a645SAnirudh Venkataramanan 
89828c2a645SAnirudh Venkataramanan 	/* keep context for update VSI operations */
899198a666aSBruce Allan 	vsi->info = ctxt->info;
90028c2a645SAnirudh Venkataramanan 
90128c2a645SAnirudh Venkataramanan 	/* record VSI number returned */
902198a666aSBruce Allan 	vsi->vsi_num = ctxt->vsi_num;
90328c2a645SAnirudh Venkataramanan 
9049efe35d0STony Nguyen out:
9059efe35d0STony Nguyen 	kfree(ctxt);
90628c2a645SAnirudh Venkataramanan 	return ret;
90728c2a645SAnirudh Venkataramanan }
90828c2a645SAnirudh Venkataramanan 
90928c2a645SAnirudh Venkataramanan /**
91046c276ceSBrett Creeley  * ice_free_res - free a block of resources
91146c276ceSBrett Creeley  * @res: pointer to the resource
91246c276ceSBrett Creeley  * @index: starting index previously returned by ice_get_res
91346c276ceSBrett Creeley  * @id: identifier to track owner
91446c276ceSBrett Creeley  *
91546c276ceSBrett Creeley  * Returns number of resources freed
91646c276ceSBrett Creeley  */
91746c276ceSBrett Creeley int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
91846c276ceSBrett Creeley {
91946c276ceSBrett Creeley 	int count = 0;
92046c276ceSBrett Creeley 	int i;
92146c276ceSBrett Creeley 
92246c276ceSBrett Creeley 	if (!res || index >= res->end)
92346c276ceSBrett Creeley 		return -EINVAL;
92446c276ceSBrett Creeley 
92546c276ceSBrett Creeley 	id |= ICE_RES_VALID_BIT;
92646c276ceSBrett Creeley 	for (i = index; i < res->end && res->list[i] == id; i++) {
92746c276ceSBrett Creeley 		res->list[i] = 0;
92846c276ceSBrett Creeley 		count++;
92946c276ceSBrett Creeley 	}
93046c276ceSBrett Creeley 
93146c276ceSBrett Creeley 	return count;
93246c276ceSBrett Creeley }
93346c276ceSBrett Creeley 
93446c276ceSBrett Creeley /**
93546c276ceSBrett Creeley  * ice_search_res - Search the tracker for a block of resources
93646c276ceSBrett Creeley  * @res: pointer to the resource
93746c276ceSBrett Creeley  * @needed: size of the block needed
93846c276ceSBrett Creeley  * @id: identifier to track owner
93946c276ceSBrett Creeley  *
94046c276ceSBrett Creeley  * Returns the base item index of the block, or -ENOMEM for error
94146c276ceSBrett Creeley  */
94246c276ceSBrett Creeley static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
94346c276ceSBrett Creeley {
94446c276ceSBrett Creeley 	int start = 0, end = 0;
94546c276ceSBrett Creeley 
94646c276ceSBrett Creeley 	if (needed > res->end)
94746c276ceSBrett Creeley 		return -ENOMEM;
94846c276ceSBrett Creeley 
94946c276ceSBrett Creeley 	id |= ICE_RES_VALID_BIT;
95046c276ceSBrett Creeley 
95146c276ceSBrett Creeley 	do {
95246c276ceSBrett Creeley 		/* skip already allocated entries */
95346c276ceSBrett Creeley 		if (res->list[end++] & ICE_RES_VALID_BIT) {
95446c276ceSBrett Creeley 			start = end;
95546c276ceSBrett Creeley 			if ((start + needed) > res->end)
95646c276ceSBrett Creeley 				break;
95746c276ceSBrett Creeley 		}
95846c276ceSBrett Creeley 
95946c276ceSBrett Creeley 		if (end == (start + needed)) {
96046c276ceSBrett Creeley 			int i = start;
96146c276ceSBrett Creeley 
96246c276ceSBrett Creeley 			/* there was enough, so assign it to the requestor */
96346c276ceSBrett Creeley 			while (i != end)
96446c276ceSBrett Creeley 				res->list[i++] = id;
96546c276ceSBrett Creeley 
96646c276ceSBrett Creeley 			return start;
96746c276ceSBrett Creeley 		}
96846c276ceSBrett Creeley 	} while (end < res->end);
96946c276ceSBrett Creeley 
97046c276ceSBrett Creeley 	return -ENOMEM;
97146c276ceSBrett Creeley }
97246c276ceSBrett Creeley 
97346c276ceSBrett Creeley /**
97446c276ceSBrett Creeley  * ice_get_free_res_count - Get free count from a resource tracker
97546c276ceSBrett Creeley  * @res: Resource tracker instance
97646c276ceSBrett Creeley  */
97746c276ceSBrett Creeley static u16 ice_get_free_res_count(struct ice_res_tracker *res)
97846c276ceSBrett Creeley {
97946c276ceSBrett Creeley 	u16 i, count = 0;
98046c276ceSBrett Creeley 
98146c276ceSBrett Creeley 	for (i = 0; i < res->end; i++)
98246c276ceSBrett Creeley 		if (!(res->list[i] & ICE_RES_VALID_BIT))
98346c276ceSBrett Creeley 			count++;
98446c276ceSBrett Creeley 
98546c276ceSBrett Creeley 	return count;
98646c276ceSBrett Creeley }
98746c276ceSBrett Creeley 
98846c276ceSBrett Creeley /**
98946c276ceSBrett Creeley  * ice_get_res - get a block of resources
99046c276ceSBrett Creeley  * @pf: board private structure
99146c276ceSBrett Creeley  * @res: pointer to the resource
99246c276ceSBrett Creeley  * @needed: size of the block needed
99346c276ceSBrett Creeley  * @id: identifier to track owner
99446c276ceSBrett Creeley  *
99546c276ceSBrett Creeley  * Returns the base item index of the block, or negative for error
99646c276ceSBrett Creeley  */
99746c276ceSBrett Creeley int
99846c276ceSBrett Creeley ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
99946c276ceSBrett Creeley {
100046c276ceSBrett Creeley 	if (!res || !pf)
100146c276ceSBrett Creeley 		return -EINVAL;
100246c276ceSBrett Creeley 
100346c276ceSBrett Creeley 	if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) {
100446c276ceSBrett Creeley 		dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n",
100546c276ceSBrett Creeley 			needed, res->num_entries, id);
100646c276ceSBrett Creeley 		return -EINVAL;
100746c276ceSBrett Creeley 	}
100846c276ceSBrett Creeley 
100946c276ceSBrett Creeley 	return ice_search_res(res, needed, id);
101046c276ceSBrett Creeley }
101146c276ceSBrett Creeley 
101246c276ceSBrett Creeley /**
1013df0f8479SAnirudh Venkataramanan  * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
1014df0f8479SAnirudh Venkataramanan  * @vsi: ptr to the VSI
1015df0f8479SAnirudh Venkataramanan  *
1016df0f8479SAnirudh Venkataramanan  * This should only be called after ice_vsi_alloc() which allocates the
1017df0f8479SAnirudh Venkataramanan  * corresponding SW VSI structure and initializes num_queue_pairs for the
1018df0f8479SAnirudh Venkataramanan  * newly allocated VSI.
1019df0f8479SAnirudh Venkataramanan  *
1020df0f8479SAnirudh Venkataramanan  * Returns 0 on success or negative on failure
1021df0f8479SAnirudh Venkataramanan  */
102237bb8390SAnirudh Venkataramanan static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
1023df0f8479SAnirudh Venkataramanan {
1024df0f8479SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
10254015d11eSBrett Creeley 	struct device *dev;
1026cbe66bfeSBrett Creeley 	u16 num_q_vectors;
1027df0f8479SAnirudh Venkataramanan 
10284015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
1029cbe66bfeSBrett Creeley 	/* SRIOV doesn't grab irq_tracker entries for each VSI */
1030cbe66bfeSBrett Creeley 	if (vsi->type == ICE_VSI_VF)
1031cbe66bfeSBrett Creeley 		return 0;
1032cbe66bfeSBrett Creeley 
1033cbe66bfeSBrett Creeley 	if (vsi->base_vector) {
10344015d11eSBrett Creeley 		dev_dbg(dev, "VSI %d has non-zero base vector %d\n",
1035cbe66bfeSBrett Creeley 			vsi->vsi_num, vsi->base_vector);
1036df0f8479SAnirudh Venkataramanan 		return -EEXIST;
1037df0f8479SAnirudh Venkataramanan 	}
1038df0f8479SAnirudh Venkataramanan 
1039df0f8479SAnirudh Venkataramanan 	num_q_vectors = vsi->num_q_vectors;
1040eb0208ecSPreethi Banala 	/* reserve slots from OS requested IRQs */
1041cbe66bfeSBrett Creeley 	vsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
1042cbe66bfeSBrett Creeley 				       vsi->idx);
1043cbe66bfeSBrett Creeley 	if (vsi->base_vector < 0) {
104446c276ceSBrett Creeley 		dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n",
104546c276ceSBrett Creeley 			ice_get_free_res_count(pf->irq_tracker),
104646c276ceSBrett Creeley 			ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors);
1047eb0208ecSPreethi Banala 		return -ENOENT;
1048eb0208ecSPreethi Banala 	}
1049eb0208ecSPreethi Banala 	pf->num_avail_sw_msix -= num_q_vectors;
1050eb0208ecSPreethi Banala 
1051df0f8479SAnirudh Venkataramanan 	return 0;
1052df0f8479SAnirudh Venkataramanan }
1053df0f8479SAnirudh Venkataramanan 
1054df0f8479SAnirudh Venkataramanan /**
105528c2a645SAnirudh Venkataramanan  * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
105628c2a645SAnirudh Venkataramanan  * @vsi: the VSI having rings deallocated
105728c2a645SAnirudh Venkataramanan  */
1058df0f8479SAnirudh Venkataramanan static void ice_vsi_clear_rings(struct ice_vsi *vsi)
105928c2a645SAnirudh Venkataramanan {
106028c2a645SAnirudh Venkataramanan 	int i;
106128c2a645SAnirudh Venkataramanan 
106228c2a645SAnirudh Venkataramanan 	if (vsi->tx_rings) {
106328c2a645SAnirudh Venkataramanan 		for (i = 0; i < vsi->alloc_txq; i++) {
106428c2a645SAnirudh Venkataramanan 			if (vsi->tx_rings[i]) {
106528c2a645SAnirudh Venkataramanan 				kfree_rcu(vsi->tx_rings[i], rcu);
106628c2a645SAnirudh Venkataramanan 				vsi->tx_rings[i] = NULL;
106728c2a645SAnirudh Venkataramanan 			}
106828c2a645SAnirudh Venkataramanan 		}
106928c2a645SAnirudh Venkataramanan 	}
107028c2a645SAnirudh Venkataramanan 	if (vsi->rx_rings) {
107128c2a645SAnirudh Venkataramanan 		for (i = 0; i < vsi->alloc_rxq; i++) {
107228c2a645SAnirudh Venkataramanan 			if (vsi->rx_rings[i]) {
107328c2a645SAnirudh Venkataramanan 				kfree_rcu(vsi->rx_rings[i], rcu);
107428c2a645SAnirudh Venkataramanan 				vsi->rx_rings[i] = NULL;
107528c2a645SAnirudh Venkataramanan 			}
107628c2a645SAnirudh Venkataramanan 		}
107728c2a645SAnirudh Venkataramanan 	}
107828c2a645SAnirudh Venkataramanan }
107928c2a645SAnirudh Venkataramanan 
108028c2a645SAnirudh Venkataramanan /**
108128c2a645SAnirudh Venkataramanan  * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI
108228c2a645SAnirudh Venkataramanan  * @vsi: VSI which is having rings allocated
108328c2a645SAnirudh Venkataramanan  */
108437bb8390SAnirudh Venkataramanan static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
108528c2a645SAnirudh Venkataramanan {
108628c2a645SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
10874015d11eSBrett Creeley 	struct device *dev;
108828c2a645SAnirudh Venkataramanan 	int i;
108928c2a645SAnirudh Venkataramanan 
10904015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
1091d337f2afSAnirudh Venkataramanan 	/* Allocate Tx rings */
109228c2a645SAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_txq; i++) {
109328c2a645SAnirudh Venkataramanan 		struct ice_ring *ring;
109428c2a645SAnirudh Venkataramanan 
109528c2a645SAnirudh Venkataramanan 		/* allocate with kzalloc(), free with kfree_rcu() */
109628c2a645SAnirudh Venkataramanan 		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
109728c2a645SAnirudh Venkataramanan 
109828c2a645SAnirudh Venkataramanan 		if (!ring)
109928c2a645SAnirudh Venkataramanan 			goto err_out;
110028c2a645SAnirudh Venkataramanan 
110128c2a645SAnirudh Venkataramanan 		ring->q_index = i;
110228c2a645SAnirudh Venkataramanan 		ring->reg_idx = vsi->txq_map[i];
110328c2a645SAnirudh Venkataramanan 		ring->ring_active = false;
110428c2a645SAnirudh Venkataramanan 		ring->vsi = vsi;
11054015d11eSBrett Creeley 		ring->dev = dev;
1106ad71b256SBrett Creeley 		ring->count = vsi->num_tx_desc;
110728c2a645SAnirudh Venkataramanan 		vsi->tx_rings[i] = ring;
110828c2a645SAnirudh Venkataramanan 	}
110928c2a645SAnirudh Venkataramanan 
1110d337f2afSAnirudh Venkataramanan 	/* Allocate Rx rings */
111128c2a645SAnirudh Venkataramanan 	for (i = 0; i < vsi->alloc_rxq; i++) {
111228c2a645SAnirudh Venkataramanan 		struct ice_ring *ring;
111328c2a645SAnirudh Venkataramanan 
111428c2a645SAnirudh Venkataramanan 		/* allocate with kzalloc(), free with kfree_rcu() */
111528c2a645SAnirudh Venkataramanan 		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
111628c2a645SAnirudh Venkataramanan 		if (!ring)
111728c2a645SAnirudh Venkataramanan 			goto err_out;
111828c2a645SAnirudh Venkataramanan 
111928c2a645SAnirudh Venkataramanan 		ring->q_index = i;
112028c2a645SAnirudh Venkataramanan 		ring->reg_idx = vsi->rxq_map[i];
112128c2a645SAnirudh Venkataramanan 		ring->ring_active = false;
112228c2a645SAnirudh Venkataramanan 		ring->vsi = vsi;
112328c2a645SAnirudh Venkataramanan 		ring->netdev = vsi->netdev;
11244015d11eSBrett Creeley 		ring->dev = dev;
1125ad71b256SBrett Creeley 		ring->count = vsi->num_rx_desc;
112628c2a645SAnirudh Venkataramanan 		vsi->rx_rings[i] = ring;
112728c2a645SAnirudh Venkataramanan 	}
112828c2a645SAnirudh Venkataramanan 
112928c2a645SAnirudh Venkataramanan 	return 0;
113028c2a645SAnirudh Venkataramanan 
113128c2a645SAnirudh Venkataramanan err_out:
113228c2a645SAnirudh Venkataramanan 	ice_vsi_clear_rings(vsi);
113328c2a645SAnirudh Venkataramanan 	return -ENOMEM;
113428c2a645SAnirudh Venkataramanan }
113528c2a645SAnirudh Venkataramanan 
113628c2a645SAnirudh Venkataramanan /**
1137492af0abSMd Fahad Iqbal Polash  * ice_vsi_manage_rss_lut - disable/enable RSS
1138492af0abSMd Fahad Iqbal Polash  * @vsi: the VSI being changed
1139492af0abSMd Fahad Iqbal Polash  * @ena: boolean value indicating if this is an enable or disable request
1140492af0abSMd Fahad Iqbal Polash  *
1141492af0abSMd Fahad Iqbal Polash  * In the event of disable request for RSS, this function will zero out RSS
1142492af0abSMd Fahad Iqbal Polash  * LUT, while in the event of enable request for RSS, it will reconfigure RSS
1143492af0abSMd Fahad Iqbal Polash  * LUT.
1144492af0abSMd Fahad Iqbal Polash  */
1145492af0abSMd Fahad Iqbal Polash int ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena)
1146492af0abSMd Fahad Iqbal Polash {
1147492af0abSMd Fahad Iqbal Polash 	int err = 0;
1148492af0abSMd Fahad Iqbal Polash 	u8 *lut;
1149492af0abSMd Fahad Iqbal Polash 
11509efe35d0STony Nguyen 	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
1151492af0abSMd Fahad Iqbal Polash 	if (!lut)
1152492af0abSMd Fahad Iqbal Polash 		return -ENOMEM;
1153492af0abSMd Fahad Iqbal Polash 
1154492af0abSMd Fahad Iqbal Polash 	if (ena) {
1155492af0abSMd Fahad Iqbal Polash 		if (vsi->rss_lut_user)
1156492af0abSMd Fahad Iqbal Polash 			memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
1157492af0abSMd Fahad Iqbal Polash 		else
1158492af0abSMd Fahad Iqbal Polash 			ice_fill_rss_lut(lut, vsi->rss_table_size,
1159492af0abSMd Fahad Iqbal Polash 					 vsi->rss_size);
1160492af0abSMd Fahad Iqbal Polash 	}
1161492af0abSMd Fahad Iqbal Polash 
1162492af0abSMd Fahad Iqbal Polash 	err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size);
11639efe35d0STony Nguyen 	kfree(lut);
1164492af0abSMd Fahad Iqbal Polash 	return err;
1165492af0abSMd Fahad Iqbal Polash }
1166492af0abSMd Fahad Iqbal Polash 
1167492af0abSMd Fahad Iqbal Polash /**
116837bb8390SAnirudh Venkataramanan  * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI
116937bb8390SAnirudh Venkataramanan  * @vsi: VSI to be configured
117037bb8390SAnirudh Venkataramanan  */
117137bb8390SAnirudh Venkataramanan static int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi)
117237bb8390SAnirudh Venkataramanan {
117337bb8390SAnirudh Venkataramanan 	struct ice_aqc_get_set_rss_keys *key;
117437bb8390SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
117537bb8390SAnirudh Venkataramanan 	enum ice_status status;
11764015d11eSBrett Creeley 	struct device *dev;
117737bb8390SAnirudh Venkataramanan 	int err = 0;
117837bb8390SAnirudh Venkataramanan 	u8 *lut;
117937bb8390SAnirudh Venkataramanan 
11804015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
118137bb8390SAnirudh Venkataramanan 	vsi->rss_size = min_t(int, vsi->rss_size, vsi->num_rxq);
118237bb8390SAnirudh Venkataramanan 
11839efe35d0STony Nguyen 	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
118437bb8390SAnirudh Venkataramanan 	if (!lut)
118537bb8390SAnirudh Venkataramanan 		return -ENOMEM;
118637bb8390SAnirudh Venkataramanan 
118737bb8390SAnirudh Venkataramanan 	if (vsi->rss_lut_user)
118837bb8390SAnirudh Venkataramanan 		memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
118937bb8390SAnirudh Venkataramanan 	else
119037bb8390SAnirudh Venkataramanan 		ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size);
119137bb8390SAnirudh Venkataramanan 
11924fb33f31SAnirudh Venkataramanan 	status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut,
11934fb33f31SAnirudh Venkataramanan 				    vsi->rss_table_size);
119437bb8390SAnirudh Venkataramanan 
119537bb8390SAnirudh Venkataramanan 	if (status) {
11960fee3577SLihong Yang 		dev_err(dev, "set_rss_lut failed, error %s\n",
11970fee3577SLihong Yang 			ice_stat_str(status));
119837bb8390SAnirudh Venkataramanan 		err = -EIO;
119937bb8390SAnirudh Venkataramanan 		goto ice_vsi_cfg_rss_exit;
120037bb8390SAnirudh Venkataramanan 	}
120137bb8390SAnirudh Venkataramanan 
12029efe35d0STony Nguyen 	key = kzalloc(sizeof(*key), GFP_KERNEL);
120337bb8390SAnirudh Venkataramanan 	if (!key) {
120437bb8390SAnirudh Venkataramanan 		err = -ENOMEM;
120537bb8390SAnirudh Venkataramanan 		goto ice_vsi_cfg_rss_exit;
120637bb8390SAnirudh Venkataramanan 	}
120737bb8390SAnirudh Venkataramanan 
120837bb8390SAnirudh Venkataramanan 	if (vsi->rss_hkey_user)
1209b4b418b3SPaul Greenwalt 		memcpy(key,
1210b4b418b3SPaul Greenwalt 		       (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user,
1211b4b418b3SPaul Greenwalt 		       ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
121237bb8390SAnirudh Venkataramanan 	else
1213b4b418b3SPaul Greenwalt 		netdev_rss_key_fill((void *)key,
1214b4b418b3SPaul Greenwalt 				    ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
121537bb8390SAnirudh Venkataramanan 
12164fb33f31SAnirudh Venkataramanan 	status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key);
121737bb8390SAnirudh Venkataramanan 
121837bb8390SAnirudh Venkataramanan 	if (status) {
12190fee3577SLihong Yang 		dev_err(dev, "set_rss_key failed, error %s\n",
12200fee3577SLihong Yang 			ice_stat_str(status));
122137bb8390SAnirudh Venkataramanan 		err = -EIO;
122237bb8390SAnirudh Venkataramanan 	}
122337bb8390SAnirudh Venkataramanan 
12249efe35d0STony Nguyen 	kfree(key);
122537bb8390SAnirudh Venkataramanan ice_vsi_cfg_rss_exit:
12269efe35d0STony Nguyen 	kfree(lut);
122737bb8390SAnirudh Venkataramanan 	return err;
122837bb8390SAnirudh Venkataramanan }
122937bb8390SAnirudh Venkataramanan 
123037bb8390SAnirudh Venkataramanan /**
12311c01c8c6SMd Fahad Iqbal Polash  * ice_vsi_set_vf_rss_flow_fld - Sets VF VSI RSS input set for different flows
12321c01c8c6SMd Fahad Iqbal Polash  * @vsi: VSI to be configured
12331c01c8c6SMd Fahad Iqbal Polash  *
12341c01c8c6SMd Fahad Iqbal Polash  * This function will only be called during the VF VSI setup. Upon successful
12351c01c8c6SMd Fahad Iqbal Polash  * completion of package download, this function will configure default RSS
12361c01c8c6SMd Fahad Iqbal Polash  * input sets for VF VSI.
12371c01c8c6SMd Fahad Iqbal Polash  */
12381c01c8c6SMd Fahad Iqbal Polash static void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi)
12391c01c8c6SMd Fahad Iqbal Polash {
12401c01c8c6SMd Fahad Iqbal Polash 	struct ice_pf *pf = vsi->back;
12411c01c8c6SMd Fahad Iqbal Polash 	enum ice_status status;
12421c01c8c6SMd Fahad Iqbal Polash 	struct device *dev;
12431c01c8c6SMd Fahad Iqbal Polash 
12441c01c8c6SMd Fahad Iqbal Polash 	dev = ice_pf_to_dev(pf);
12451c01c8c6SMd Fahad Iqbal Polash 	if (ice_is_safe_mode(pf)) {
12461c01c8c6SMd Fahad Iqbal Polash 		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
12471c01c8c6SMd Fahad Iqbal Polash 			vsi->vsi_num);
12481c01c8c6SMd Fahad Iqbal Polash 		return;
12491c01c8c6SMd Fahad Iqbal Polash 	}
12501c01c8c6SMd Fahad Iqbal Polash 
12511c01c8c6SMd Fahad Iqbal Polash 	status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA);
12521c01c8c6SMd Fahad Iqbal Polash 	if (status)
12530fee3577SLihong Yang 		dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %s\n",
12540fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
12551c01c8c6SMd Fahad Iqbal Polash }
12561c01c8c6SMd Fahad Iqbal Polash 
12571c01c8c6SMd Fahad Iqbal Polash /**
1258c90ed40cSTony Nguyen  * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows
1259c90ed40cSTony Nguyen  * @vsi: VSI to be configured
1260c90ed40cSTony Nguyen  *
1261c90ed40cSTony Nguyen  * This function will only be called after successful download package call
1262c90ed40cSTony Nguyen  * during initialization of PF. Since the downloaded package will erase the
1263c90ed40cSTony Nguyen  * RSS section, this function will configure RSS input sets for different
1264c90ed40cSTony Nguyen  * flow types. The last profile added has the highest priority, therefore 2
1265c90ed40cSTony Nguyen  * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles
1266c90ed40cSTony Nguyen  * (i.e. IPv4 src/dst TCP src/dst port).
1267c90ed40cSTony Nguyen  */
1268c90ed40cSTony Nguyen static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
1269c90ed40cSTony Nguyen {
1270c90ed40cSTony Nguyen 	u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num;
1271c90ed40cSTony Nguyen 	struct ice_pf *pf = vsi->back;
1272c90ed40cSTony Nguyen 	struct ice_hw *hw = &pf->hw;
1273c90ed40cSTony Nguyen 	enum ice_status status;
1274c90ed40cSTony Nguyen 	struct device *dev;
1275c90ed40cSTony Nguyen 
1276c90ed40cSTony Nguyen 	dev = ice_pf_to_dev(pf);
1277c90ed40cSTony Nguyen 	if (ice_is_safe_mode(pf)) {
1278c90ed40cSTony Nguyen 		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
1279c90ed40cSTony Nguyen 			vsi_num);
1280c90ed40cSTony Nguyen 		return;
1281c90ed40cSTony Nguyen 	}
1282c90ed40cSTony Nguyen 	/* configure RSS for IPv4 with input set IP src/dst */
1283c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
1284c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_IPV4);
1285c90ed40cSTony Nguyen 	if (status)
12860fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %s\n",
12870fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1288c90ed40cSTony Nguyen 
1289c90ed40cSTony Nguyen 	/* configure RSS for IPv6 with input set IPv6 src/dst */
1290c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
1291c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_IPV6);
1292c90ed40cSTony Nguyen 	if (status)
12930fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %s\n",
12940fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1295c90ed40cSTony Nguyen 
1296c90ed40cSTony Nguyen 	/* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */
1297c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4,
1298c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4);
1299c90ed40cSTony Nguyen 	if (status)
13000fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %s\n",
13010fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1302c90ed40cSTony Nguyen 
1303c90ed40cSTony Nguyen 	/* configure RSS for udp4 with input set IP src/dst, UDP src/dst */
1304c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4,
1305c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4);
1306c90ed40cSTony Nguyen 	if (status)
13070fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %s\n",
13080fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1309c90ed40cSTony Nguyen 
1310c90ed40cSTony Nguyen 	/* configure RSS for sctp4 with input set IP src/dst */
1311c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
1312c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4);
1313c90ed40cSTony Nguyen 	if (status)
13140fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %s\n",
13150fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1316c90ed40cSTony Nguyen 
1317c90ed40cSTony Nguyen 	/* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */
1318c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6,
1319c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6);
1320c90ed40cSTony Nguyen 	if (status)
13210fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %s\n",
13220fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1323c90ed40cSTony Nguyen 
1324c90ed40cSTony Nguyen 	/* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */
1325c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6,
1326c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6);
1327c90ed40cSTony Nguyen 	if (status)
13280fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %s\n",
13290fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1330c90ed40cSTony Nguyen 
1331c90ed40cSTony Nguyen 	/* configure RSS for sctp6 with input set IPv6 src/dst */
1332c90ed40cSTony Nguyen 	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
1333c90ed40cSTony Nguyen 				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6);
1334c90ed40cSTony Nguyen 	if (status)
13350fee3577SLihong Yang 		dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %s\n",
13360fee3577SLihong Yang 			vsi_num, ice_stat_str(status));
1337c90ed40cSTony Nguyen }
1338c90ed40cSTony Nguyen 
1339c90ed40cSTony Nguyen /**
1340f9867df6SAnirudh Venkataramanan  * ice_add_mac_to_list - Add a MAC address filter entry to the list
134145d3d428SAnirudh Venkataramanan  * @vsi: the VSI to be forwarded to
134245d3d428SAnirudh Venkataramanan  * @add_list: pointer to the list which contains MAC filter entries
134345d3d428SAnirudh Venkataramanan  * @macaddr: the MAC address to be added.
134445d3d428SAnirudh Venkataramanan  *
1345f9867df6SAnirudh Venkataramanan  * Adds MAC address filter entry to the temp list
134645d3d428SAnirudh Venkataramanan  *
134745d3d428SAnirudh Venkataramanan  * Returns 0 on success or ENOMEM on failure.
134845d3d428SAnirudh Venkataramanan  */
13494ee656bbSTony Nguyen int
13504ee656bbSTony Nguyen ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
135145d3d428SAnirudh Venkataramanan 		    const u8 *macaddr)
135245d3d428SAnirudh Venkataramanan {
135345d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
135445d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
135545d3d428SAnirudh Venkataramanan 
13564015d11eSBrett Creeley 	tmp = devm_kzalloc(ice_pf_to_dev(pf), sizeof(*tmp), GFP_ATOMIC);
135745d3d428SAnirudh Venkataramanan 	if (!tmp)
135845d3d428SAnirudh Venkataramanan 		return -ENOMEM;
135945d3d428SAnirudh Venkataramanan 
136045d3d428SAnirudh Venkataramanan 	tmp->fltr_info.flag = ICE_FLTR_TX;
13615726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.src_id = ICE_SRC_ID_VSI;
136245d3d428SAnirudh Venkataramanan 	tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC;
136345d3d428SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
13645726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.vsi_handle = vsi->idx;
136545d3d428SAnirudh Venkataramanan 	ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr);
136645d3d428SAnirudh Venkataramanan 
136745d3d428SAnirudh Venkataramanan 	INIT_LIST_HEAD(&tmp->list_entry);
136845d3d428SAnirudh Venkataramanan 	list_add(&tmp->list_entry, add_list);
136945d3d428SAnirudh Venkataramanan 
137045d3d428SAnirudh Venkataramanan 	return 0;
137145d3d428SAnirudh Venkataramanan }
137245d3d428SAnirudh Venkataramanan 
137345d3d428SAnirudh Venkataramanan /**
137445d3d428SAnirudh Venkataramanan  * ice_update_eth_stats - Update VSI-specific ethernet statistics counters
137545d3d428SAnirudh Venkataramanan  * @vsi: the VSI to be updated
137645d3d428SAnirudh Venkataramanan  */
137745d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi)
137845d3d428SAnirudh Venkataramanan {
137945d3d428SAnirudh Venkataramanan 	struct ice_eth_stats *prev_es, *cur_es;
138045d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
138145d3d428SAnirudh Venkataramanan 	u16 vsi_num = vsi->vsi_num;    /* HW absolute index of a VSI */
138245d3d428SAnirudh Venkataramanan 
138345d3d428SAnirudh Venkataramanan 	prev_es = &vsi->eth_stats_prev;
138445d3d428SAnirudh Venkataramanan 	cur_es = &vsi->eth_stats;
138545d3d428SAnirudh Venkataramanan 
138636517fd3SJacob Keller 	ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded,
138736517fd3SJacob Keller 			  &prev_es->rx_bytes, &cur_es->rx_bytes);
138845d3d428SAnirudh Venkataramanan 
138936517fd3SJacob Keller 	ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded,
139036517fd3SJacob Keller 			  &prev_es->rx_unicast, &cur_es->rx_unicast);
139145d3d428SAnirudh Venkataramanan 
139236517fd3SJacob Keller 	ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded,
139336517fd3SJacob Keller 			  &prev_es->rx_multicast, &cur_es->rx_multicast);
139445d3d428SAnirudh Venkataramanan 
139536517fd3SJacob Keller 	ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded,
139636517fd3SJacob Keller 			  &prev_es->rx_broadcast, &cur_es->rx_broadcast);
139745d3d428SAnirudh Venkataramanan 
139845d3d428SAnirudh Venkataramanan 	ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded,
139945d3d428SAnirudh Venkataramanan 			  &prev_es->rx_discards, &cur_es->rx_discards);
140045d3d428SAnirudh Venkataramanan 
140136517fd3SJacob Keller 	ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded,
140236517fd3SJacob Keller 			  &prev_es->tx_bytes, &cur_es->tx_bytes);
140345d3d428SAnirudh Venkataramanan 
140436517fd3SJacob Keller 	ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded,
140536517fd3SJacob Keller 			  &prev_es->tx_unicast, &cur_es->tx_unicast);
140645d3d428SAnirudh Venkataramanan 
140736517fd3SJacob Keller 	ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded,
140836517fd3SJacob Keller 			  &prev_es->tx_multicast, &cur_es->tx_multicast);
140945d3d428SAnirudh Venkataramanan 
141036517fd3SJacob Keller 	ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded,
141136517fd3SJacob Keller 			  &prev_es->tx_broadcast, &cur_es->tx_broadcast);
141245d3d428SAnirudh Venkataramanan 
141345d3d428SAnirudh Venkataramanan 	ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded,
141445d3d428SAnirudh Venkataramanan 			  &prev_es->tx_errors, &cur_es->tx_errors);
141545d3d428SAnirudh Venkataramanan 
141645d3d428SAnirudh Venkataramanan 	vsi->stat_offsets_loaded = true;
141745d3d428SAnirudh Venkataramanan }
141845d3d428SAnirudh Venkataramanan 
141945d3d428SAnirudh Venkataramanan /**
142045d3d428SAnirudh Venkataramanan  * ice_free_fltr_list - free filter lists helper
142145d3d428SAnirudh Venkataramanan  * @dev: pointer to the device struct
142245d3d428SAnirudh Venkataramanan  * @h: pointer to the list head to be freed
142345d3d428SAnirudh Venkataramanan  *
142445d3d428SAnirudh Venkataramanan  * Helper function to free filter lists previously created using
142545d3d428SAnirudh Venkataramanan  * ice_add_mac_to_list
142645d3d428SAnirudh Venkataramanan  */
142745d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h)
142845d3d428SAnirudh Venkataramanan {
142945d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *e, *tmp;
143045d3d428SAnirudh Venkataramanan 
143145d3d428SAnirudh Venkataramanan 	list_for_each_entry_safe(e, tmp, h, list_entry) {
143245d3d428SAnirudh Venkataramanan 		list_del(&e->list_entry);
143345d3d428SAnirudh Venkataramanan 		devm_kfree(dev, e);
143445d3d428SAnirudh Venkataramanan 	}
143545d3d428SAnirudh Venkataramanan }
143645d3d428SAnirudh Venkataramanan 
143745d3d428SAnirudh Venkataramanan /**
143845d3d428SAnirudh Venkataramanan  * ice_vsi_add_vlan - Add VSI membership for given VLAN
143945d3d428SAnirudh Venkataramanan  * @vsi: the VSI being configured
1440f9867df6SAnirudh Venkataramanan  * @vid: VLAN ID to be added
144145d3d428SAnirudh Venkataramanan  */
144245d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid)
144345d3d428SAnirudh Venkataramanan {
144445d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
144545d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
144645d3d428SAnirudh Venkataramanan 	LIST_HEAD(tmp_add_list);
144745d3d428SAnirudh Venkataramanan 	enum ice_status status;
14484015d11eSBrett Creeley 	struct device *dev;
144945d3d428SAnirudh Venkataramanan 	int err = 0;
145045d3d428SAnirudh Venkataramanan 
14514015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
14524015d11eSBrett Creeley 	tmp = devm_kzalloc(dev, sizeof(*tmp), GFP_KERNEL);
145345d3d428SAnirudh Venkataramanan 	if (!tmp)
145445d3d428SAnirudh Venkataramanan 		return -ENOMEM;
145545d3d428SAnirudh Venkataramanan 
145645d3d428SAnirudh Venkataramanan 	tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN;
145745d3d428SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
145845d3d428SAnirudh Venkataramanan 	tmp->fltr_info.flag = ICE_FLTR_TX;
14595726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.src_id = ICE_SRC_ID_VSI;
14605726ca0eSAnirudh Venkataramanan 	tmp->fltr_info.vsi_handle = vsi->idx;
146145d3d428SAnirudh Venkataramanan 	tmp->fltr_info.l_data.vlan.vlan_id = vid;
146245d3d428SAnirudh Venkataramanan 
146345d3d428SAnirudh Venkataramanan 	INIT_LIST_HEAD(&tmp->list_entry);
146445d3d428SAnirudh Venkataramanan 	list_add(&tmp->list_entry, &tmp_add_list);
146545d3d428SAnirudh Venkataramanan 
146645d3d428SAnirudh Venkataramanan 	status = ice_add_vlan(&pf->hw, &tmp_add_list);
146742f3efefSBrett Creeley 	if (!status) {
146842f3efefSBrett Creeley 		vsi->num_vlan++;
146942f3efefSBrett Creeley 	} else {
147045d3d428SAnirudh Venkataramanan 		err = -ENODEV;
14714015d11eSBrett Creeley 		dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid,
14724015d11eSBrett Creeley 			vsi->vsi_num);
147345d3d428SAnirudh Venkataramanan 	}
147445d3d428SAnirudh Venkataramanan 
14754015d11eSBrett Creeley 	ice_free_fltr_list(dev, &tmp_add_list);
147645d3d428SAnirudh Venkataramanan 	return err;
147745d3d428SAnirudh Venkataramanan }
147845d3d428SAnirudh Venkataramanan 
147945d3d428SAnirudh Venkataramanan /**
148045d3d428SAnirudh Venkataramanan  * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN
148145d3d428SAnirudh Venkataramanan  * @vsi: the VSI being configured
1482f9867df6SAnirudh Venkataramanan  * @vid: VLAN ID to be removed
148345d3d428SAnirudh Venkataramanan  *
148445d3d428SAnirudh Venkataramanan  * Returns 0 on success and negative on failure
148545d3d428SAnirudh Venkataramanan  */
148645d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid)
148745d3d428SAnirudh Venkataramanan {
148845d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *list;
148945d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
149045d3d428SAnirudh Venkataramanan 	LIST_HEAD(tmp_add_list);
14915079b853SAkeem G Abodunrin 	enum ice_status status;
14924015d11eSBrett Creeley 	struct device *dev;
14935079b853SAkeem G Abodunrin 	int err = 0;
149445d3d428SAnirudh Venkataramanan 
14954015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
14964015d11eSBrett Creeley 	list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL);
149745d3d428SAnirudh Venkataramanan 	if (!list)
149845d3d428SAnirudh Venkataramanan 		return -ENOMEM;
149945d3d428SAnirudh Venkataramanan 
150045d3d428SAnirudh Venkataramanan 	list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN;
15015726ca0eSAnirudh Venkataramanan 	list->fltr_info.vsi_handle = vsi->idx;
150245d3d428SAnirudh Venkataramanan 	list->fltr_info.fltr_act = ICE_FWD_TO_VSI;
150345d3d428SAnirudh Venkataramanan 	list->fltr_info.l_data.vlan.vlan_id = vid;
150445d3d428SAnirudh Venkataramanan 	list->fltr_info.flag = ICE_FLTR_TX;
15055726ca0eSAnirudh Venkataramanan 	list->fltr_info.src_id = ICE_SRC_ID_VSI;
150645d3d428SAnirudh Venkataramanan 
150745d3d428SAnirudh Venkataramanan 	INIT_LIST_HEAD(&list->list_entry);
150845d3d428SAnirudh Venkataramanan 	list_add(&list->list_entry, &tmp_add_list);
150945d3d428SAnirudh Venkataramanan 
15105079b853SAkeem G Abodunrin 	status = ice_remove_vlan(&pf->hw, &tmp_add_list);
151142f3efefSBrett Creeley 	if (!status) {
151242f3efefSBrett Creeley 		vsi->num_vlan--;
151342f3efefSBrett Creeley 	} else if (status == ICE_ERR_DOES_NOT_EXIST) {
15140fee3577SLihong Yang 		dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, status: %s\n",
15150fee3577SLihong Yang 			vid, vsi->vsi_num, ice_stat_str(status));
151642f3efefSBrett Creeley 	} else {
15170fee3577SLihong Yang 		dev_err(dev, "Error removing VLAN %d on vsi %i error: %s\n",
15180fee3577SLihong Yang 			vid, vsi->vsi_num, ice_stat_str(status));
15195079b853SAkeem G Abodunrin 		err = -EIO;
152045d3d428SAnirudh Venkataramanan 	}
152145d3d428SAnirudh Venkataramanan 
15224015d11eSBrett Creeley 	ice_free_fltr_list(dev, &tmp_add_list);
15235079b853SAkeem G Abodunrin 	return err;
152445d3d428SAnirudh Venkataramanan }
152545d3d428SAnirudh Venkataramanan 
152645d3d428SAnirudh Venkataramanan /**
1527efc2214bSMaciej Fijalkowski  * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
1528efc2214bSMaciej Fijalkowski  * @vsi: VSI
1529efc2214bSMaciej Fijalkowski  */
1530efc2214bSMaciej Fijalkowski void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
1531efc2214bSMaciej Fijalkowski {
15327237f5b0SMaciej Fijalkowski 	if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
15337237f5b0SMaciej Fijalkowski 		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
1534efc2214bSMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_2048;
15357237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192)
153659bb0808SMaciej Fijalkowski 	} else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
153759bb0808SMaciej Fijalkowski 		   (vsi->netdev->mtu <= ETH_DATA_LEN)) {
15387237f5b0SMaciej Fijalkowski 		vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
15397237f5b0SMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
15407237f5b0SMaciej Fijalkowski #endif
15417237f5b0SMaciej Fijalkowski 	} else {
15427237f5b0SMaciej Fijalkowski 		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
15437237f5b0SMaciej Fijalkowski #if (PAGE_SIZE < 8192)
15447237f5b0SMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_3072;
15457237f5b0SMaciej Fijalkowski #else
15467237f5b0SMaciej Fijalkowski 		vsi->rx_buf_len = ICE_RXBUF_2048;
15477237f5b0SMaciej Fijalkowski #endif
15487237f5b0SMaciej Fijalkowski 	}
1549efc2214bSMaciej Fijalkowski }
1550efc2214bSMaciej Fijalkowski 
1551efc2214bSMaciej Fijalkowski /**
155272adf242SAnirudh Venkataramanan  * ice_vsi_cfg_rxqs - Configure the VSI for Rx
155372adf242SAnirudh Venkataramanan  * @vsi: the VSI being configured
155472adf242SAnirudh Venkataramanan  *
155572adf242SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
155672adf242SAnirudh Venkataramanan  * Configure the Rx VSI for operation.
155772adf242SAnirudh Venkataramanan  */
155872adf242SAnirudh Venkataramanan int ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
155972adf242SAnirudh Venkataramanan {
156072adf242SAnirudh Venkataramanan 	u16 i;
156172adf242SAnirudh Venkataramanan 
15628ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
15638ede0178SAnirudh Venkataramanan 		goto setup_rings;
15648ede0178SAnirudh Venkataramanan 
1565efc2214bSMaciej Fijalkowski 	ice_vsi_cfg_frame_size(vsi);
15668ede0178SAnirudh Venkataramanan setup_rings:
156772adf242SAnirudh Venkataramanan 	/* set up individual rings */
15681553f4f7SBrett Creeley 	for (i = 0; i < vsi->num_rxq; i++) {
15691553f4f7SBrett Creeley 		int err;
157072adf242SAnirudh Venkataramanan 
15711553f4f7SBrett Creeley 		err = ice_setup_rx_ctx(vsi->rx_rings[i]);
157272adf242SAnirudh Venkataramanan 		if (err) {
157319cce2c6SAnirudh Venkataramanan 			dev_err(ice_pf_to_dev(vsi->back), "ice_setup_rx_ctx failed for RxQ %d, err %d\n",
15741553f4f7SBrett Creeley 				i, err);
157572adf242SAnirudh Venkataramanan 			return err;
157672adf242SAnirudh Venkataramanan 		}
15771553f4f7SBrett Creeley 	}
15781553f4f7SBrett Creeley 
15791553f4f7SBrett Creeley 	return 0;
15801553f4f7SBrett Creeley }
158172adf242SAnirudh Venkataramanan 
158272adf242SAnirudh Venkataramanan /**
158372adf242SAnirudh Venkataramanan  * ice_vsi_cfg_txqs - Configure the VSI for Tx
158472adf242SAnirudh Venkataramanan  * @vsi: the VSI being configured
158503f7a986SAnirudh Venkataramanan  * @rings: Tx ring array to be configured
158672adf242SAnirudh Venkataramanan  *
158772adf242SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
158872adf242SAnirudh Venkataramanan  * Configure the Tx VSI for operation.
158972adf242SAnirudh Venkataramanan  */
159003f7a986SAnirudh Venkataramanan static int
1591e75d1b2cSMaciej Fijalkowski ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings)
159272adf242SAnirudh Venkataramanan {
159372adf242SAnirudh Venkataramanan 	struct ice_aqc_add_tx_qgrp *qg_buf;
1594e75d1b2cSMaciej Fijalkowski 	u16 q_idx = 0;
1595d02f734cSMaciej Fijalkowski 	int err = 0;
159672adf242SAnirudh Venkataramanan 
1597e75d1b2cSMaciej Fijalkowski 	qg_buf = kzalloc(sizeof(*qg_buf), GFP_KERNEL);
159872adf242SAnirudh Venkataramanan 	if (!qg_buf)
159972adf242SAnirudh Venkataramanan 		return -ENOMEM;
160072adf242SAnirudh Venkataramanan 
160172adf242SAnirudh Venkataramanan 	qg_buf->num_txqs = 1;
160272adf242SAnirudh Venkataramanan 
1603e75d1b2cSMaciej Fijalkowski 	for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) {
1604e75d1b2cSMaciej Fijalkowski 		err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf);
1605d02f734cSMaciej Fijalkowski 		if (err)
160672adf242SAnirudh Venkataramanan 			goto err_cfg_txqs;
1607e75d1b2cSMaciej Fijalkowski 	}
1608c5a2a4a3SUsha Ketineni 
160972adf242SAnirudh Venkataramanan err_cfg_txqs:
1610e75d1b2cSMaciej Fijalkowski 	kfree(qg_buf);
161172adf242SAnirudh Venkataramanan 	return err;
161272adf242SAnirudh Venkataramanan }
161372adf242SAnirudh Venkataramanan 
161472adf242SAnirudh Venkataramanan /**
161503f7a986SAnirudh Venkataramanan  * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
161603f7a986SAnirudh Venkataramanan  * @vsi: the VSI being configured
161703f7a986SAnirudh Venkataramanan  *
161803f7a986SAnirudh Venkataramanan  * Return 0 on success and a negative value on error
161903f7a986SAnirudh Venkataramanan  * Configure the Tx VSI for operation.
162003f7a986SAnirudh Venkataramanan  */
162103f7a986SAnirudh Venkataramanan int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
162203f7a986SAnirudh Venkataramanan {
1623e75d1b2cSMaciej Fijalkowski 	return ice_vsi_cfg_txqs(vsi, vsi->tx_rings);
162403f7a986SAnirudh Venkataramanan }
162503f7a986SAnirudh Venkataramanan 
162603f7a986SAnirudh Venkataramanan /**
1627efc2214bSMaciej Fijalkowski  * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI
1628efc2214bSMaciej Fijalkowski  * @vsi: the VSI being configured
1629efc2214bSMaciej Fijalkowski  *
1630efc2214bSMaciej Fijalkowski  * Return 0 on success and a negative value on error
1631efc2214bSMaciej Fijalkowski  * Configure the Tx queues dedicated for XDP in given VSI for operation.
1632efc2214bSMaciej Fijalkowski  */
1633efc2214bSMaciej Fijalkowski int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
1634efc2214bSMaciej Fijalkowski {
16352d4238f5SKrzysztof Kazimierczak 	int ret;
16362d4238f5SKrzysztof Kazimierczak 	int i;
16372d4238f5SKrzysztof Kazimierczak 
16382d4238f5SKrzysztof Kazimierczak 	ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings);
16392d4238f5SKrzysztof Kazimierczak 	if (ret)
16402d4238f5SKrzysztof Kazimierczak 		return ret;
16412d4238f5SKrzysztof Kazimierczak 
16422d4238f5SKrzysztof Kazimierczak 	for (i = 0; i < vsi->num_xdp_txq; i++)
16432d4238f5SKrzysztof Kazimierczak 		vsi->xdp_rings[i]->xsk_umem = ice_xsk_umem(vsi->xdp_rings[i]);
16442d4238f5SKrzysztof Kazimierczak 
16452d4238f5SKrzysztof Kazimierczak 	return ret;
1646efc2214bSMaciej Fijalkowski }
1647efc2214bSMaciej Fijalkowski 
1648efc2214bSMaciej Fijalkowski /**
16499e4ab4c2SBrett Creeley  * ice_intrl_usec_to_reg - convert interrupt rate limit to register value
16509e4ab4c2SBrett Creeley  * @intrl: interrupt rate limit in usecs
16519e4ab4c2SBrett Creeley  * @gran: interrupt rate limit granularity in usecs
16529e4ab4c2SBrett Creeley  *
16539e4ab4c2SBrett Creeley  * This function converts a decimal interrupt rate limit in usecs to the format
16549e4ab4c2SBrett Creeley  * expected by firmware.
16559e4ab4c2SBrett Creeley  */
1656b9c8bb06SBrett Creeley u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran)
16579e4ab4c2SBrett Creeley {
16589e4ab4c2SBrett Creeley 	u32 val = intrl / gran;
16599e4ab4c2SBrett Creeley 
16609e4ab4c2SBrett Creeley 	if (val)
16619e4ab4c2SBrett Creeley 		return val | GLINT_RATE_INTRL_ENA_M;
16629e4ab4c2SBrett Creeley 	return 0;
16639e4ab4c2SBrett Creeley }
16649e4ab4c2SBrett Creeley 
16659e4ab4c2SBrett Creeley /**
166672adf242SAnirudh Venkataramanan  * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW
166772adf242SAnirudh Venkataramanan  * @vsi: the VSI being configured
1668047e52c0SAnirudh Venkataramanan  *
1669047e52c0SAnirudh Venkataramanan  * This configures MSIX mode interrupts for the PF VSI, and should not be used
1670047e52c0SAnirudh Venkataramanan  * for the VF VSI.
167172adf242SAnirudh Venkataramanan  */
167272adf242SAnirudh Venkataramanan void ice_vsi_cfg_msix(struct ice_vsi *vsi)
167372adf242SAnirudh Venkataramanan {
167472adf242SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
167572adf242SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
167672adf242SAnirudh Venkataramanan 	u32 txq = 0, rxq = 0;
1677d2b464a7SBrett Creeley 	int i, q;
167872adf242SAnirudh Venkataramanan 
1679b07833a0SBrett Creeley 	for (i = 0; i < vsi->num_q_vectors; i++) {
168072adf242SAnirudh Venkataramanan 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
1681b07833a0SBrett Creeley 		u16 reg_idx = q_vector->reg_idx;
168272adf242SAnirudh Venkataramanan 
1683b07833a0SBrett Creeley 		ice_cfg_itr(hw, q_vector);
16849e4ab4c2SBrett Creeley 
1685b07833a0SBrett Creeley 		wr32(hw, GLINT_RATE(reg_idx),
16869e4ab4c2SBrett Creeley 		     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
168772adf242SAnirudh Venkataramanan 
168872adf242SAnirudh Venkataramanan 		/* Both Transmit Queue Interrupt Cause Control register
168972adf242SAnirudh Venkataramanan 		 * and Receive Queue Interrupt Cause control register
169072adf242SAnirudh Venkataramanan 		 * expects MSIX_INDX field to be the vector index
169172adf242SAnirudh Venkataramanan 		 * within the function space and not the absolute
169272adf242SAnirudh Venkataramanan 		 * vector index across PF or across device.
169372adf242SAnirudh Venkataramanan 		 * For SR-IOV VF VSIs queue vector index always starts
169472adf242SAnirudh Venkataramanan 		 * with 1 since first vector index(0) is used for OICR
169572adf242SAnirudh Venkataramanan 		 * in VF space. Since VMDq and other PF VSIs are within
169672adf242SAnirudh Venkataramanan 		 * the PF function space, use the vector index that is
169772adf242SAnirudh Venkataramanan 		 * tracked for this PF.
169872adf242SAnirudh Venkataramanan 		 */
169972adf242SAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_tx; q++) {
1700047e52c0SAnirudh Venkataramanan 			ice_cfg_txq_interrupt(vsi, txq, reg_idx,
1701047e52c0SAnirudh Venkataramanan 					      q_vector->tx.itr_idx);
170272adf242SAnirudh Venkataramanan 			txq++;
170372adf242SAnirudh Venkataramanan 		}
170472adf242SAnirudh Venkataramanan 
170572adf242SAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_rx; q++) {
1706047e52c0SAnirudh Venkataramanan 			ice_cfg_rxq_interrupt(vsi, rxq, reg_idx,
1707047e52c0SAnirudh Venkataramanan 					      q_vector->rx.itr_idx);
170872adf242SAnirudh Venkataramanan 			rxq++;
170972adf242SAnirudh Venkataramanan 		}
171072adf242SAnirudh Venkataramanan 	}
171172adf242SAnirudh Venkataramanan }
171272adf242SAnirudh Venkataramanan 
171372adf242SAnirudh Venkataramanan /**
171445d3d428SAnirudh Venkataramanan  * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
171545d3d428SAnirudh Venkataramanan  * @vsi: the VSI being changed
171645d3d428SAnirudh Venkataramanan  */
171745d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
171845d3d428SAnirudh Venkataramanan {
171945d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
1720198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
172145d3d428SAnirudh Venkataramanan 	enum ice_status status;
1722198a666aSBruce Allan 	int ret = 0;
1723198a666aSBruce Allan 
17249efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
1725198a666aSBruce Allan 	if (!ctxt)
1726198a666aSBruce Allan 		return -ENOMEM;
172745d3d428SAnirudh Venkataramanan 
172845d3d428SAnirudh Venkataramanan 	/* Here we are configuring the VSI to let the driver add VLAN tags by
172945d3d428SAnirudh Venkataramanan 	 * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
173045d3d428SAnirudh Venkataramanan 	 * insertion happens in the Tx hot path, in ice_tx_map.
173145d3d428SAnirudh Venkataramanan 	 */
1732198a666aSBruce Allan 	ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
173345d3d428SAnirudh Venkataramanan 
1734e80e76dbSTony Nguyen 	/* Preserve existing VLAN strip setting */
1735e80e76dbSTony Nguyen 	ctxt->info.vlan_flags |= (vsi->info.vlan_flags &
1736e80e76dbSTony Nguyen 				  ICE_AQ_VSI_VLAN_EMOD_M);
1737e80e76dbSTony Nguyen 
1738198a666aSBruce Allan 	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
173945d3d428SAnirudh Venkataramanan 
1740198a666aSBruce Allan 	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
174145d3d428SAnirudh Venkataramanan 	if (status) {
17420fee3577SLihong Yang 		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %s aq_err %s\n",
17430fee3577SLihong Yang 			ice_stat_str(status),
17440fee3577SLihong Yang 			ice_aq_str(hw->adminq.sq_last_status));
1745198a666aSBruce Allan 		ret = -EIO;
1746198a666aSBruce Allan 		goto out;
174745d3d428SAnirudh Venkataramanan 	}
174845d3d428SAnirudh Venkataramanan 
1749198a666aSBruce Allan 	vsi->info.vlan_flags = ctxt->info.vlan_flags;
1750198a666aSBruce Allan out:
17519efe35d0STony Nguyen 	kfree(ctxt);
1752198a666aSBruce Allan 	return ret;
175345d3d428SAnirudh Venkataramanan }
175445d3d428SAnirudh Venkataramanan 
175545d3d428SAnirudh Venkataramanan /**
175645d3d428SAnirudh Venkataramanan  * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
175745d3d428SAnirudh Venkataramanan  * @vsi: the VSI being changed
175845d3d428SAnirudh Venkataramanan  * @ena: boolean value indicating if this is a enable or disable request
175945d3d428SAnirudh Venkataramanan  */
176045d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
176145d3d428SAnirudh Venkataramanan {
176245d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
1763198a666aSBruce Allan 	struct ice_vsi_ctx *ctxt;
176445d3d428SAnirudh Venkataramanan 	enum ice_status status;
1765198a666aSBruce Allan 	int ret = 0;
1766198a666aSBruce Allan 
17679efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
1768198a666aSBruce Allan 	if (!ctxt)
1769198a666aSBruce Allan 		return -ENOMEM;
177045d3d428SAnirudh Venkataramanan 
177145d3d428SAnirudh Venkataramanan 	/* Here we are configuring what the VSI should do with the VLAN tag in
177245d3d428SAnirudh Venkataramanan 	 * the Rx packet. We can either leave the tag in the packet or put it in
177345d3d428SAnirudh Venkataramanan 	 * the Rx descriptor.
177445d3d428SAnirudh Venkataramanan 	 */
1775198a666aSBruce Allan 	if (ena)
177645d3d428SAnirudh Venkataramanan 		/* Strip VLAN tag from Rx packet and put it in the desc */
1777198a666aSBruce Allan 		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
1778198a666aSBruce Allan 	else
177945d3d428SAnirudh Venkataramanan 		/* Disable stripping. Leave tag in packet */
1780198a666aSBruce Allan 		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
178145d3d428SAnirudh Venkataramanan 
178245d3d428SAnirudh Venkataramanan 	/* Allow all packets untagged/tagged */
1783198a666aSBruce Allan 	ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
178445d3d428SAnirudh Venkataramanan 
1785198a666aSBruce Allan 	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
178645d3d428SAnirudh Venkataramanan 
1787198a666aSBruce Allan 	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
178845d3d428SAnirudh Venkataramanan 	if (status) {
17890fee3577SLihong Yang 		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %s aq_err %s\n",
17900fee3577SLihong Yang 			ena, ice_stat_str(status),
17910fee3577SLihong Yang 			ice_aq_str(hw->adminq.sq_last_status));
1792198a666aSBruce Allan 		ret = -EIO;
1793198a666aSBruce Allan 		goto out;
179445d3d428SAnirudh Venkataramanan 	}
179545d3d428SAnirudh Venkataramanan 
1796198a666aSBruce Allan 	vsi->info.vlan_flags = ctxt->info.vlan_flags;
1797198a666aSBruce Allan out:
17989efe35d0STony Nguyen 	kfree(ctxt);
1799198a666aSBruce Allan 	return ret;
180045d3d428SAnirudh Venkataramanan }
180172adf242SAnirudh Venkataramanan 
180272adf242SAnirudh Venkataramanan /**
180313a6233bSBrett Creeley  * ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings
180413a6233bSBrett Creeley  * @vsi: the VSI whose rings are to be enabled
180572adf242SAnirudh Venkataramanan  *
180672adf242SAnirudh Venkataramanan  * Returns 0 on success and a negative value on error
180772adf242SAnirudh Venkataramanan  */
180813a6233bSBrett Creeley int ice_vsi_start_all_rx_rings(struct ice_vsi *vsi)
180972adf242SAnirudh Venkataramanan {
181013a6233bSBrett Creeley 	return ice_vsi_ctrl_all_rx_rings(vsi, true);
181172adf242SAnirudh Venkataramanan }
181272adf242SAnirudh Venkataramanan 
181372adf242SAnirudh Venkataramanan /**
181413a6233bSBrett Creeley  * ice_vsi_stop_all_rx_rings - stop/disable all of a VSI's Rx rings
181513a6233bSBrett Creeley  * @vsi: the VSI whose rings are to be disabled
181672adf242SAnirudh Venkataramanan  *
181772adf242SAnirudh Venkataramanan  * Returns 0 on success and a negative value on error
181872adf242SAnirudh Venkataramanan  */
181913a6233bSBrett Creeley int ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi)
182072adf242SAnirudh Venkataramanan {
182113a6233bSBrett Creeley 	return ice_vsi_ctrl_all_rx_rings(vsi, false);
182272adf242SAnirudh Venkataramanan }
182372adf242SAnirudh Venkataramanan 
182472adf242SAnirudh Venkataramanan /**
1825d02f734cSMaciej Fijalkowski  * ice_vsi_stop_tx_rings - Disable Tx rings
1826d02f734cSMaciej Fijalkowski  * @vsi: the VSI being configured
1827d02f734cSMaciej Fijalkowski  * @rst_src: reset source
1828d02f734cSMaciej Fijalkowski  * @rel_vmvf_num: Relative ID of VF/VM
1829d02f734cSMaciej Fijalkowski  * @rings: Tx ring array to be stopped
1830d02f734cSMaciej Fijalkowski  */
1831d02f734cSMaciej Fijalkowski static int
1832d02f734cSMaciej Fijalkowski ice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
1833d02f734cSMaciej Fijalkowski 		      u16 rel_vmvf_num, struct ice_ring **rings)
1834d02f734cSMaciej Fijalkowski {
1835e75d1b2cSMaciej Fijalkowski 	u16 q_idx;
1836d02f734cSMaciej Fijalkowski 
1837d02f734cSMaciej Fijalkowski 	if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS)
1838d02f734cSMaciej Fijalkowski 		return -EINVAL;
1839d02f734cSMaciej Fijalkowski 
1840e75d1b2cSMaciej Fijalkowski 	for (q_idx = 0; q_idx < vsi->num_txq; q_idx++) {
1841d02f734cSMaciej Fijalkowski 		struct ice_txq_meta txq_meta = { };
1842e75d1b2cSMaciej Fijalkowski 		int status;
1843d02f734cSMaciej Fijalkowski 
1844d02f734cSMaciej Fijalkowski 		if (!rings || !rings[q_idx])
1845d02f734cSMaciej Fijalkowski 			return -EINVAL;
1846d02f734cSMaciej Fijalkowski 
1847d02f734cSMaciej Fijalkowski 		ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta);
1848e75d1b2cSMaciej Fijalkowski 		status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num,
1849d02f734cSMaciej Fijalkowski 					      rings[q_idx], &txq_meta);
1850d02f734cSMaciej Fijalkowski 
1851d02f734cSMaciej Fijalkowski 		if (status)
1852d02f734cSMaciej Fijalkowski 			return status;
1853bb87ee0eSAnirudh Venkataramanan 	}
185472adf242SAnirudh Venkataramanan 
1855d02f734cSMaciej Fijalkowski 	return 0;
185672adf242SAnirudh Venkataramanan }
18575153a18eSAnirudh Venkataramanan 
18585153a18eSAnirudh Venkataramanan /**
185903f7a986SAnirudh Venkataramanan  * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings
186003f7a986SAnirudh Venkataramanan  * @vsi: the VSI being configured
186103f7a986SAnirudh Venkataramanan  * @rst_src: reset source
1862f9867df6SAnirudh Venkataramanan  * @rel_vmvf_num: Relative ID of VF/VM
186303f7a986SAnirudh Venkataramanan  */
1864c8b7abddSBruce Allan int
1865c8b7abddSBruce Allan ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
1866c8b7abddSBruce Allan 			  u16 rel_vmvf_num)
186703f7a986SAnirudh Venkataramanan {
1868d02f734cSMaciej Fijalkowski 	return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings);
186903f7a986SAnirudh Venkataramanan }
187003f7a986SAnirudh Venkataramanan 
187103f7a986SAnirudh Venkataramanan /**
1872efc2214bSMaciej Fijalkowski  * ice_vsi_stop_xdp_tx_rings - Disable XDP Tx rings
1873efc2214bSMaciej Fijalkowski  * @vsi: the VSI being configured
1874efc2214bSMaciej Fijalkowski  */
1875efc2214bSMaciej Fijalkowski int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi)
1876efc2214bSMaciej Fijalkowski {
1877efc2214bSMaciej Fijalkowski 	return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings);
1878efc2214bSMaciej Fijalkowski }
1879efc2214bSMaciej Fijalkowski 
1880efc2214bSMaciej Fijalkowski /**
188142f3efefSBrett Creeley  * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not
188242f3efefSBrett Creeley  * @vsi: VSI to check whether or not VLAN pruning is enabled.
188342f3efefSBrett Creeley  *
1884345be791SBrett Creeley  * returns true if Rx VLAN pruning is enabled and false otherwise.
188542f3efefSBrett Creeley  */
188642f3efefSBrett Creeley bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi)
188742f3efefSBrett Creeley {
188842f3efefSBrett Creeley 	if (!vsi)
188942f3efefSBrett Creeley 		return false;
189042f3efefSBrett Creeley 
1891345be791SBrett Creeley 	return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA);
189242f3efefSBrett Creeley }
189342f3efefSBrett Creeley 
189442f3efefSBrett Creeley /**
18955153a18eSAnirudh Venkataramanan  * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
18965153a18eSAnirudh Venkataramanan  * @vsi: VSI to enable or disable VLAN pruning on
18975153a18eSAnirudh Venkataramanan  * @ena: set to true to enable VLAN pruning and false to disable it
18985eda8afdSAkeem G Abodunrin  * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
18995153a18eSAnirudh Venkataramanan  *
19005153a18eSAnirudh Venkataramanan  * returns 0 if VSI is updated, negative otherwise
19015153a18eSAnirudh Venkataramanan  */
19025eda8afdSAkeem G Abodunrin int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
19035153a18eSAnirudh Venkataramanan {
19045153a18eSAnirudh Venkataramanan 	struct ice_vsi_ctx *ctxt;
1905819d8998SJesse Brandeburg 	struct ice_pf *pf;
19065153a18eSAnirudh Venkataramanan 	int status;
19075153a18eSAnirudh Venkataramanan 
19085153a18eSAnirudh Venkataramanan 	if (!vsi)
19095153a18eSAnirudh Venkataramanan 		return -EINVAL;
19105153a18eSAnirudh Venkataramanan 
1911819d8998SJesse Brandeburg 	pf = vsi->back;
19129efe35d0STony Nguyen 	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
19135153a18eSAnirudh Venkataramanan 	if (!ctxt)
19145153a18eSAnirudh Venkataramanan 		return -ENOMEM;
19155153a18eSAnirudh Venkataramanan 
19165153a18eSAnirudh Venkataramanan 	ctxt->info = vsi->info;
19175153a18eSAnirudh Venkataramanan 
1918cd6d6b83SBrett Creeley 	if (ena)
19195153a18eSAnirudh Venkataramanan 		ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
1920cd6d6b83SBrett Creeley 	else
19215153a18eSAnirudh Venkataramanan 		ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
19225153a18eSAnirudh Venkataramanan 
19235eda8afdSAkeem G Abodunrin 	if (!vlan_promisc)
19245eda8afdSAkeem G Abodunrin 		ctxt->info.valid_sections =
1925cd6d6b83SBrett Creeley 			cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
19265726ca0eSAnirudh Venkataramanan 
1927819d8998SJesse Brandeburg 	status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL);
19285153a18eSAnirudh Venkataramanan 	if (status) {
19290fee3577SLihong Yang 		netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %s, aq_err = %s\n",
19300fee3577SLihong Yang 			   ena ? "En" : "Dis", vsi->idx, vsi->vsi_num,
19310fee3577SLihong Yang 			   ice_stat_str(status),
19320fee3577SLihong Yang 			   ice_aq_str(pf->hw.adminq.sq_last_status));
19335153a18eSAnirudh Venkataramanan 		goto err_out;
19345153a18eSAnirudh Venkataramanan 	}
19355153a18eSAnirudh Venkataramanan 
19365153a18eSAnirudh Venkataramanan 	vsi->info.sw_flags2 = ctxt->info.sw_flags2;
19375153a18eSAnirudh Venkataramanan 
19389efe35d0STony Nguyen 	kfree(ctxt);
19395153a18eSAnirudh Venkataramanan 	return 0;
19405153a18eSAnirudh Venkataramanan 
19415153a18eSAnirudh Venkataramanan err_out:
19429efe35d0STony Nguyen 	kfree(ctxt);
19435153a18eSAnirudh Venkataramanan 	return -EIO;
19445153a18eSAnirudh Venkataramanan }
19455153a18eSAnirudh Venkataramanan 
19467b9ffc76SAnirudh Venkataramanan static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
19477b9ffc76SAnirudh Venkataramanan {
19487b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *cfg = &vsi->port_info->local_dcbx_cfg;
19497b9ffc76SAnirudh Venkataramanan 
19507b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg);
19517b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg);
19527b9ffc76SAnirudh Venkataramanan }
19537b9ffc76SAnirudh Venkataramanan 
19545153a18eSAnirudh Venkataramanan /**
1955b07833a0SBrett Creeley  * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors
1956b07833a0SBrett Creeley  * @vsi: VSI to set the q_vectors register index on
1957b07833a0SBrett Creeley  */
1958b07833a0SBrett Creeley static int
1959b07833a0SBrett Creeley ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
1960b07833a0SBrett Creeley {
1961b07833a0SBrett Creeley 	u16 i;
1962b07833a0SBrett Creeley 
1963b07833a0SBrett Creeley 	if (!vsi || !vsi->q_vectors)
1964b07833a0SBrett Creeley 		return -EINVAL;
1965b07833a0SBrett Creeley 
1966b07833a0SBrett Creeley 	ice_for_each_q_vector(vsi, i) {
1967b07833a0SBrett Creeley 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
1968b07833a0SBrett Creeley 
1969b07833a0SBrett Creeley 		if (!q_vector) {
197019cce2c6SAnirudh Venkataramanan 			dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n",
1971b07833a0SBrett Creeley 				i, vsi->vsi_num);
1972b07833a0SBrett Creeley 			goto clear_reg_idx;
1973b07833a0SBrett Creeley 		}
1974b07833a0SBrett Creeley 
1975cbe66bfeSBrett Creeley 		if (vsi->type == ICE_VSI_VF) {
1976cbe66bfeSBrett Creeley 			struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
1977cbe66bfeSBrett Creeley 
1978cbe66bfeSBrett Creeley 			q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
1979cbe66bfeSBrett Creeley 		} else {
1980cbe66bfeSBrett Creeley 			q_vector->reg_idx =
1981cbe66bfeSBrett Creeley 				q_vector->v_idx + vsi->base_vector;
1982cbe66bfeSBrett Creeley 		}
1983b07833a0SBrett Creeley 	}
1984b07833a0SBrett Creeley 
1985b07833a0SBrett Creeley 	return 0;
1986b07833a0SBrett Creeley 
1987b07833a0SBrett Creeley clear_reg_idx:
1988b07833a0SBrett Creeley 	ice_for_each_q_vector(vsi, i) {
1989b07833a0SBrett Creeley 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
1990b07833a0SBrett Creeley 
1991b07833a0SBrett Creeley 		if (q_vector)
1992b07833a0SBrett Creeley 			q_vector->reg_idx = 0;
1993b07833a0SBrett Creeley 	}
1994b07833a0SBrett Creeley 
1995b07833a0SBrett Creeley 	return -EINVAL;
1996b07833a0SBrett Creeley }
1997b07833a0SBrett Creeley 
1998b07833a0SBrett Creeley /**
1999d95276ceSAkeem G Abodunrin  * ice_vsi_add_rem_eth_mac - Program VSI ethertype based filter with rule
2000d95276ceSAkeem G Abodunrin  * @vsi: the VSI being configured
2001d95276ceSAkeem G Abodunrin  * @add_rule: boolean value to add or remove ethertype filter rule
2002d95276ceSAkeem G Abodunrin  */
2003d95276ceSAkeem G Abodunrin static void
2004d95276ceSAkeem G Abodunrin ice_vsi_add_rem_eth_mac(struct ice_vsi *vsi, bool add_rule)
2005d95276ceSAkeem G Abodunrin {
2006d95276ceSAkeem G Abodunrin 	struct ice_fltr_list_entry *list;
2007d95276ceSAkeem G Abodunrin 	struct ice_pf *pf = vsi->back;
2008d95276ceSAkeem G Abodunrin 	LIST_HEAD(tmp_add_list);
2009d95276ceSAkeem G Abodunrin 	enum ice_status status;
20104015d11eSBrett Creeley 	struct device *dev;
2011d95276ceSAkeem G Abodunrin 
20124015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
20134015d11eSBrett Creeley 	list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL);
2014d95276ceSAkeem G Abodunrin 	if (!list)
2015d95276ceSAkeem G Abodunrin 		return;
2016d95276ceSAkeem G Abodunrin 
2017d95276ceSAkeem G Abodunrin 	list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE;
2018d95276ceSAkeem G Abodunrin 	list->fltr_info.fltr_act = ICE_DROP_PACKET;
2019d95276ceSAkeem G Abodunrin 	list->fltr_info.flag = ICE_FLTR_TX;
2020d95276ceSAkeem G Abodunrin 	list->fltr_info.src_id = ICE_SRC_ID_VSI;
2021d95276ceSAkeem G Abodunrin 	list->fltr_info.vsi_handle = vsi->idx;
2022d95276ceSAkeem G Abodunrin 	list->fltr_info.l_data.ethertype_mac.ethertype = vsi->ethtype;
2023d95276ceSAkeem G Abodunrin 
2024d95276ceSAkeem G Abodunrin 	INIT_LIST_HEAD(&list->list_entry);
2025d95276ceSAkeem G Abodunrin 	list_add(&list->list_entry, &tmp_add_list);
2026d95276ceSAkeem G Abodunrin 
2027d95276ceSAkeem G Abodunrin 	if (add_rule)
2028d95276ceSAkeem G Abodunrin 		status = ice_add_eth_mac(&pf->hw, &tmp_add_list);
2029d95276ceSAkeem G Abodunrin 	else
2030d95276ceSAkeem G Abodunrin 		status = ice_remove_eth_mac(&pf->hw, &tmp_add_list);
2031d95276ceSAkeem G Abodunrin 
2032d95276ceSAkeem G Abodunrin 	if (status)
20330fee3577SLihong Yang 		dev_err(dev, "Failure Adding or Removing Ethertype on VSI %i error: %s\n",
20340fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
2035d95276ceSAkeem G Abodunrin 
20364015d11eSBrett Creeley 	ice_free_fltr_list(dev, &tmp_add_list);
2037d95276ceSAkeem G Abodunrin }
2038d95276ceSAkeem G Abodunrin 
20392e0e6228SDave Ertman /**
20402e0e6228SDave Ertman  * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
20412e0e6228SDave Ertman  * @vsi: the VSI being configured
20422e0e6228SDave Ertman  * @tx: bool to determine Tx or Rx rule
20432e0e6228SDave Ertman  * @create: bool to determine create or remove Rule
20442e0e6228SDave Ertman  */
20452e0e6228SDave Ertman void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create)
20462e0e6228SDave Ertman {
20472e0e6228SDave Ertman 	struct ice_fltr_list_entry *list;
20482e0e6228SDave Ertman 	struct ice_pf *pf = vsi->back;
20492e0e6228SDave Ertman 	LIST_HEAD(tmp_add_list);
20502e0e6228SDave Ertman 	enum ice_status status;
20514015d11eSBrett Creeley 	struct device *dev;
20522e0e6228SDave Ertman 
20534015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
20544015d11eSBrett Creeley 	list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL);
20552e0e6228SDave Ertman 	if (!list)
20562e0e6228SDave Ertman 		return;
20572e0e6228SDave Ertman 
20582e0e6228SDave Ertman 	list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE;
20592e0e6228SDave Ertman 	list->fltr_info.vsi_handle = vsi->idx;
20603aea1736SJeff Kirsher 	list->fltr_info.l_data.ethertype_mac.ethertype = ETH_P_LLDP;
20612e0e6228SDave Ertman 
20622e0e6228SDave Ertman 	if (tx) {
20632e0e6228SDave Ertman 		list->fltr_info.fltr_act = ICE_DROP_PACKET;
20642e0e6228SDave Ertman 		list->fltr_info.flag = ICE_FLTR_TX;
20652e0e6228SDave Ertman 		list->fltr_info.src_id = ICE_SRC_ID_VSI;
20662e0e6228SDave Ertman 	} else {
20672e0e6228SDave Ertman 		list->fltr_info.fltr_act = ICE_FWD_TO_VSI;
20682e0e6228SDave Ertman 		list->fltr_info.flag = ICE_FLTR_RX;
20692e0e6228SDave Ertman 		list->fltr_info.src_id = ICE_SRC_ID_LPORT;
20702e0e6228SDave Ertman 	}
20712e0e6228SDave Ertman 
20722e0e6228SDave Ertman 	INIT_LIST_HEAD(&list->list_entry);
20732e0e6228SDave Ertman 	list_add(&list->list_entry, &tmp_add_list);
20742e0e6228SDave Ertman 
20752e0e6228SDave Ertman 	if (create)
20762e0e6228SDave Ertman 		status = ice_add_eth_mac(&pf->hw, &tmp_add_list);
20772e0e6228SDave Ertman 	else
20782e0e6228SDave Ertman 		status = ice_remove_eth_mac(&pf->hw, &tmp_add_list);
20792e0e6228SDave Ertman 
20802e0e6228SDave Ertman 	if (status)
20810fee3577SLihong Yang 		dev_err(dev, "Fail %s %s LLDP rule on VSI %i error: %s\n",
20822e0e6228SDave Ertman 			create ? "adding" : "removing", tx ? "TX" : "RX",
20830fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
20842e0e6228SDave Ertman 
20854015d11eSBrett Creeley 	ice_free_fltr_list(dev, &tmp_add_list);
20862e0e6228SDave Ertman }
20872e0e6228SDave Ertman 
2088d95276ceSAkeem G Abodunrin /**
208937bb8390SAnirudh Venkataramanan  * ice_vsi_setup - Set up a VSI by a given type
209037bb8390SAnirudh Venkataramanan  * @pf: board private structure
209137bb8390SAnirudh Venkataramanan  * @pi: pointer to the port_info instance
20926dae8aa0SBruce Allan  * @vsi_type: VSI type
2093f9867df6SAnirudh Venkataramanan  * @vf_id: defines VF ID to which this VSI connects. This field is meant to be
209437bb8390SAnirudh Venkataramanan  *         used only for ICE_VSI_VF VSI type. For other VSI types, should
209537bb8390SAnirudh Venkataramanan  *         fill-in ICE_INVAL_VFID as input.
209637bb8390SAnirudh Venkataramanan  *
209737bb8390SAnirudh Venkataramanan  * This allocates the sw VSI structure and its queue resources.
209837bb8390SAnirudh Venkataramanan  *
209937bb8390SAnirudh Venkataramanan  * Returns pointer to the successfully allocated and configured VSI sw struct on
210037bb8390SAnirudh Venkataramanan  * success, NULL on failure.
210137bb8390SAnirudh Venkataramanan  */
210237bb8390SAnirudh Venkataramanan struct ice_vsi *
210337bb8390SAnirudh Venkataramanan ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
21046dae8aa0SBruce Allan 	      enum ice_vsi_type vsi_type, u16 vf_id)
210537bb8390SAnirudh Venkataramanan {
210637bb8390SAnirudh Venkataramanan 	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
21074015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
2108d31530e8SAkeem G Abodunrin 	enum ice_status status;
210937bb8390SAnirudh Venkataramanan 	struct ice_vsi *vsi;
211037bb8390SAnirudh Venkataramanan 	int ret, i;
211137bb8390SAnirudh Venkataramanan 
21126dae8aa0SBruce Allan 	if (vsi_type == ICE_VSI_VF)
21136dae8aa0SBruce Allan 		vsi = ice_vsi_alloc(pf, vsi_type, vf_id);
21145743020dSAkeem G Abodunrin 	else
21156dae8aa0SBruce Allan 		vsi = ice_vsi_alloc(pf, vsi_type, ICE_INVAL_VFID);
21165743020dSAkeem G Abodunrin 
211737bb8390SAnirudh Venkataramanan 	if (!vsi) {
211837bb8390SAnirudh Venkataramanan 		dev_err(dev, "could not allocate VSI\n");
211937bb8390SAnirudh Venkataramanan 		return NULL;
212037bb8390SAnirudh Venkataramanan 	}
212137bb8390SAnirudh Venkataramanan 
212237bb8390SAnirudh Venkataramanan 	vsi->port_info = pi;
212337bb8390SAnirudh Venkataramanan 	vsi->vsw = pf->first_sw;
2124d95276ceSAkeem G Abodunrin 	if (vsi->type == ICE_VSI_PF)
2125d95276ceSAkeem G Abodunrin 		vsi->ethtype = ETH_P_PAUSE;
2126d95276ceSAkeem G Abodunrin 
21278ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
21288ede0178SAnirudh Venkataramanan 		vsi->vf_id = vf_id;
212937bb8390SAnirudh Venkataramanan 
213037bb8390SAnirudh Venkataramanan 	if (ice_vsi_get_qs(vsi)) {
213137bb8390SAnirudh Venkataramanan 		dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n",
213237bb8390SAnirudh Venkataramanan 			vsi->idx);
213337bb8390SAnirudh Venkataramanan 		goto unroll_get_qs;
213437bb8390SAnirudh Venkataramanan 	}
213537bb8390SAnirudh Venkataramanan 
213637bb8390SAnirudh Venkataramanan 	/* set RSS capabilities */
213737bb8390SAnirudh Venkataramanan 	ice_vsi_set_rss_params(vsi);
213837bb8390SAnirudh Venkataramanan 
2139f9867df6SAnirudh Venkataramanan 	/* set TC configuration */
2140c5a2a4a3SUsha Ketineni 	ice_vsi_set_tc_cfg(vsi);
2141c5a2a4a3SUsha Ketineni 
214237bb8390SAnirudh Venkataramanan 	/* create the VSI */
214387324e74SHenry Tieman 	ret = ice_vsi_init(vsi, true);
214437bb8390SAnirudh Venkataramanan 	if (ret)
214537bb8390SAnirudh Venkataramanan 		goto unroll_get_qs;
214637bb8390SAnirudh Venkataramanan 
214737bb8390SAnirudh Venkataramanan 	switch (vsi->type) {
214837bb8390SAnirudh Venkataramanan 	case ICE_VSI_PF:
214937bb8390SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
215037bb8390SAnirudh Venkataramanan 		if (ret)
215137bb8390SAnirudh Venkataramanan 			goto unroll_vsi_init;
215237bb8390SAnirudh Venkataramanan 
215337bb8390SAnirudh Venkataramanan 		ret = ice_vsi_setup_vector_base(vsi);
215437bb8390SAnirudh Venkataramanan 		if (ret)
215537bb8390SAnirudh Venkataramanan 			goto unroll_alloc_q_vector;
215637bb8390SAnirudh Venkataramanan 
2157b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2158b07833a0SBrett Creeley 		if (ret)
2159b07833a0SBrett Creeley 			goto unroll_vector_base;
2160b07833a0SBrett Creeley 
216137bb8390SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
216237bb8390SAnirudh Venkataramanan 		if (ret)
216337bb8390SAnirudh Venkataramanan 			goto unroll_vector_base;
216437bb8390SAnirudh Venkataramanan 
216542f3efefSBrett Creeley 		/* Always add VLAN ID 0 switch rule by default. This is needed
216642f3efefSBrett Creeley 		 * in order to allow all untagged and 0 tagged priority traffic
216742f3efefSBrett Creeley 		 * if Rx VLAN pruning is enabled. Also there are cases where we
216842f3efefSBrett Creeley 		 * don't get the call to add VLAN 0 via ice_vlan_rx_add_vid()
216942f3efefSBrett Creeley 		 * so this handles those cases (i.e. adding the PF to a bridge
217042f3efefSBrett Creeley 		 * without the 8021q module loaded).
217142f3efefSBrett Creeley 		 */
217242f3efefSBrett Creeley 		ret = ice_vsi_add_vlan(vsi, 0);
217342f3efefSBrett Creeley 		if (ret)
217442f3efefSBrett Creeley 			goto unroll_clear_rings;
217542f3efefSBrett Creeley 
217637bb8390SAnirudh Venkataramanan 		ice_vsi_map_rings_to_vectors(vsi);
217737bb8390SAnirudh Venkataramanan 
217837bb8390SAnirudh Venkataramanan 		/* Do not exit if configuring RSS had an issue, at least
217937bb8390SAnirudh Venkataramanan 		 * receive traffic on first queue. Hence no need to capture
218037bb8390SAnirudh Venkataramanan 		 * return value
218137bb8390SAnirudh Venkataramanan 		 */
2182c90ed40cSTony Nguyen 		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
218337bb8390SAnirudh Venkataramanan 			ice_vsi_cfg_rss_lut_key(vsi);
2184c90ed40cSTony Nguyen 			ice_vsi_set_rss_flow_fld(vsi);
2185c90ed40cSTony Nguyen 		}
218637bb8390SAnirudh Venkataramanan 		break;
21878ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
21888ede0178SAnirudh Venkataramanan 		/* VF driver will take care of creating netdev for this type and
21898ede0178SAnirudh Venkataramanan 		 * map queues to vectors through Virtchnl, PF driver only
21908ede0178SAnirudh Venkataramanan 		 * creates a VSI and corresponding structures for bookkeeping
21918ede0178SAnirudh Venkataramanan 		 * purpose
21928ede0178SAnirudh Venkataramanan 		 */
21938ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
21948ede0178SAnirudh Venkataramanan 		if (ret)
21958ede0178SAnirudh Venkataramanan 			goto unroll_vsi_init;
21968ede0178SAnirudh Venkataramanan 
21978ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
21988ede0178SAnirudh Venkataramanan 		if (ret)
21998ede0178SAnirudh Venkataramanan 			goto unroll_alloc_q_vector;
22008ede0178SAnirudh Venkataramanan 
2201b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2202b07833a0SBrett Creeley 		if (ret)
2203b07833a0SBrett Creeley 			goto unroll_vector_base;
2204b07833a0SBrett Creeley 
22053a9e32bbSMd Fahad Iqbal Polash 		/* Do not exit if configuring RSS had an issue, at least
22063a9e32bbSMd Fahad Iqbal Polash 		 * receive traffic on first queue. Hence no need to capture
22073a9e32bbSMd Fahad Iqbal Polash 		 * return value
22083a9e32bbSMd Fahad Iqbal Polash 		 */
22091c01c8c6SMd Fahad Iqbal Polash 		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
22103a9e32bbSMd Fahad Iqbal Polash 			ice_vsi_cfg_rss_lut_key(vsi);
22111c01c8c6SMd Fahad Iqbal Polash 			ice_vsi_set_vf_rss_flow_fld(vsi);
22121c01c8c6SMd Fahad Iqbal Polash 		}
22138ede0178SAnirudh Venkataramanan 		break;
22140e674aebSAnirudh Venkataramanan 	case ICE_VSI_LB:
22150e674aebSAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
22160e674aebSAnirudh Venkataramanan 		if (ret)
22170e674aebSAnirudh Venkataramanan 			goto unroll_vsi_init;
22180e674aebSAnirudh Venkataramanan 		break;
221937bb8390SAnirudh Venkataramanan 	default:
2220df17b7e0SAnirudh Venkataramanan 		/* clean up the resources and exit */
222137bb8390SAnirudh Venkataramanan 		goto unroll_vsi_init;
222237bb8390SAnirudh Venkataramanan 	}
222337bb8390SAnirudh Venkataramanan 
222437bb8390SAnirudh Venkataramanan 	/* configure VSI nodes based on number of queues and TC's */
222537bb8390SAnirudh Venkataramanan 	for (i = 0; i < vsi->tc_cfg.numtc; i++)
2226d5a46359SAkeem G Abodunrin 		max_txqs[i] = vsi->alloc_txq;
222737bb8390SAnirudh Venkataramanan 
2228d31530e8SAkeem G Abodunrin 	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
22294fb33f31SAnirudh Venkataramanan 				 max_txqs);
2230d31530e8SAkeem G Abodunrin 	if (status) {
22310fee3577SLihong Yang 		dev_err(dev, "VSI %d failed lan queue config, error %s\n",
22320fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
223337bb8390SAnirudh Venkataramanan 		goto unroll_vector_base;
223437bb8390SAnirudh Venkataramanan 	}
223537bb8390SAnirudh Venkataramanan 
2236d95276ceSAkeem G Abodunrin 	/* Add switch rule to drop all Tx Flow Control Frames, of look up
2237d95276ceSAkeem G Abodunrin 	 * type ETHERTYPE from VSIs, and restrict malicious VF from sending
2238d95276ceSAkeem G Abodunrin 	 * out PAUSE or PFC frames. If enabled, FW can still send FC frames.
2239d95276ceSAkeem G Abodunrin 	 * The rule is added once for PF VSI in order to create appropriate
2240d95276ceSAkeem G Abodunrin 	 * recipe, since VSI/VSI list is ignored with drop action...
2241241c8cf0SPaul Greenwalt 	 * Also add rules to handle LLDP Tx packets.  Tx LLDP packets need to
2242241c8cf0SPaul Greenwalt 	 * be dropped so that VFs cannot send LLDP packets to reconfig DCB
2243241c8cf0SPaul Greenwalt 	 * settings in the HW.
2244d95276ceSAkeem G Abodunrin 	 */
2245241c8cf0SPaul Greenwalt 	if (!ice_is_safe_mode(pf))
22462e0e6228SDave Ertman 		if (vsi->type == ICE_VSI_PF) {
2247d95276ceSAkeem G Abodunrin 			ice_vsi_add_rem_eth_mac(vsi, true);
2248d95276ceSAkeem G Abodunrin 
22492e0e6228SDave Ertman 			/* Tx LLDP packets */
22502e0e6228SDave Ertman 			ice_cfg_sw_lldp(vsi, true, true);
2251462acf6aSTony Nguyen 		}
22522e0e6228SDave Ertman 
225337bb8390SAnirudh Venkataramanan 	return vsi;
225437bb8390SAnirudh Venkataramanan 
225542f3efefSBrett Creeley unroll_clear_rings:
225642f3efefSBrett Creeley 	ice_vsi_clear_rings(vsi);
225737bb8390SAnirudh Venkataramanan unroll_vector_base:
2258eb0208ecSPreethi Banala 	/* reclaim SW interrupts back to the common pool */
2259cbe66bfeSBrett Creeley 	ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
2260eb0208ecSPreethi Banala 	pf->num_avail_sw_msix += vsi->num_q_vectors;
226137bb8390SAnirudh Venkataramanan unroll_alloc_q_vector:
226237bb8390SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
226337bb8390SAnirudh Venkataramanan unroll_vsi_init:
226437bb8390SAnirudh Venkataramanan 	ice_vsi_delete(vsi);
226537bb8390SAnirudh Venkataramanan unroll_get_qs:
226637bb8390SAnirudh Venkataramanan 	ice_vsi_put_qs(vsi);
226737bb8390SAnirudh Venkataramanan 	ice_vsi_clear(vsi);
226837bb8390SAnirudh Venkataramanan 
226937bb8390SAnirudh Venkataramanan 	return NULL;
227037bb8390SAnirudh Venkataramanan }
227137bb8390SAnirudh Venkataramanan 
227237bb8390SAnirudh Venkataramanan /**
22735153a18eSAnirudh Venkataramanan  * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW
22745153a18eSAnirudh Venkataramanan  * @vsi: the VSI being cleaned up
22755153a18eSAnirudh Venkataramanan  */
22765153a18eSAnirudh Venkataramanan static void ice_vsi_release_msix(struct ice_vsi *vsi)
22775153a18eSAnirudh Venkataramanan {
22785153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
22795153a18eSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
22805153a18eSAnirudh Venkataramanan 	u32 txq = 0;
22815153a18eSAnirudh Venkataramanan 	u32 rxq = 0;
22825153a18eSAnirudh Venkataramanan 	int i, q;
22835153a18eSAnirudh Venkataramanan 
2284cbe66bfeSBrett Creeley 	for (i = 0; i < vsi->num_q_vectors; i++) {
22855153a18eSAnirudh Venkataramanan 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
2286cbe66bfeSBrett Creeley 		u16 reg_idx = q_vector->reg_idx;
22875153a18eSAnirudh Venkataramanan 
2288cbe66bfeSBrett Creeley 		wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0);
2289cbe66bfeSBrett Creeley 		wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0);
22905153a18eSAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_tx; q++) {
22915153a18eSAnirudh Venkataramanan 			wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0);
2292efc2214bSMaciej Fijalkowski 			if (ice_is_xdp_ena_vsi(vsi)) {
2293efc2214bSMaciej Fijalkowski 				u32 xdp_txq = txq + vsi->num_xdp_txq;
2294efc2214bSMaciej Fijalkowski 
2295efc2214bSMaciej Fijalkowski 				wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0);
2296efc2214bSMaciej Fijalkowski 			}
22975153a18eSAnirudh Venkataramanan 			txq++;
22985153a18eSAnirudh Venkataramanan 		}
22995153a18eSAnirudh Venkataramanan 
23005153a18eSAnirudh Venkataramanan 		for (q = 0; q < q_vector->num_ring_rx; q++) {
23015153a18eSAnirudh Venkataramanan 			wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0);
23025153a18eSAnirudh Venkataramanan 			rxq++;
23035153a18eSAnirudh Venkataramanan 		}
23045153a18eSAnirudh Venkataramanan 	}
23055153a18eSAnirudh Venkataramanan 
23065153a18eSAnirudh Venkataramanan 	ice_flush(hw);
23075153a18eSAnirudh Venkataramanan }
23085153a18eSAnirudh Venkataramanan 
23095153a18eSAnirudh Venkataramanan /**
23105153a18eSAnirudh Venkataramanan  * ice_vsi_free_irq - Free the IRQ association with the OS
23115153a18eSAnirudh Venkataramanan  * @vsi: the VSI being configured
23125153a18eSAnirudh Venkataramanan  */
23135153a18eSAnirudh Venkataramanan void ice_vsi_free_irq(struct ice_vsi *vsi)
23145153a18eSAnirudh Venkataramanan {
23155153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2316cbe66bfeSBrett Creeley 	int base = vsi->base_vector;
23175153a18eSAnirudh Venkataramanan 	int i;
23185153a18eSAnirudh Venkataramanan 
23195153a18eSAnirudh Venkataramanan 	if (!vsi->q_vectors || !vsi->irqs_ready)
23205153a18eSAnirudh Venkataramanan 		return;
23215153a18eSAnirudh Venkataramanan 
2322eb0208ecSPreethi Banala 	ice_vsi_release_msix(vsi);
23238ede0178SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_VF)
23248ede0178SAnirudh Venkataramanan 		return;
2325eb0208ecSPreethi Banala 
23265153a18eSAnirudh Venkataramanan 	vsi->irqs_ready = false;
23270c2561c8SBrett Creeley 	ice_for_each_q_vector(vsi, i) {
23285153a18eSAnirudh Venkataramanan 		u16 vector = i + base;
23295153a18eSAnirudh Venkataramanan 		int irq_num;
23305153a18eSAnirudh Venkataramanan 
23315153a18eSAnirudh Venkataramanan 		irq_num = pf->msix_entries[vector].vector;
23325153a18eSAnirudh Venkataramanan 
23335153a18eSAnirudh Venkataramanan 		/* free only the irqs that were actually requested */
23345153a18eSAnirudh Venkataramanan 		if (!vsi->q_vectors[i] ||
23355153a18eSAnirudh Venkataramanan 		    !(vsi->q_vectors[i]->num_ring_tx ||
23365153a18eSAnirudh Venkataramanan 		      vsi->q_vectors[i]->num_ring_rx))
23375153a18eSAnirudh Venkataramanan 			continue;
23385153a18eSAnirudh Venkataramanan 
23395153a18eSAnirudh Venkataramanan 		/* clear the affinity notifier in the IRQ descriptor */
23405153a18eSAnirudh Venkataramanan 		irq_set_affinity_notifier(irq_num, NULL);
23415153a18eSAnirudh Venkataramanan 
23425153a18eSAnirudh Venkataramanan 		/* clear the affinity_mask in the IRQ descriptor */
23435153a18eSAnirudh Venkataramanan 		irq_set_affinity_hint(irq_num, NULL);
23445153a18eSAnirudh Venkataramanan 		synchronize_irq(irq_num);
23454015d11eSBrett Creeley 		devm_free_irq(ice_pf_to_dev(pf), irq_num, vsi->q_vectors[i]);
23465153a18eSAnirudh Venkataramanan 	}
23475153a18eSAnirudh Venkataramanan }
23485153a18eSAnirudh Venkataramanan 
23495153a18eSAnirudh Venkataramanan /**
23505153a18eSAnirudh Venkataramanan  * ice_vsi_free_tx_rings - Free Tx resources for VSI queues
23515153a18eSAnirudh Venkataramanan  * @vsi: the VSI having resources freed
23525153a18eSAnirudh Venkataramanan  */
23535153a18eSAnirudh Venkataramanan void ice_vsi_free_tx_rings(struct ice_vsi *vsi)
23545153a18eSAnirudh Venkataramanan {
23555153a18eSAnirudh Venkataramanan 	int i;
23565153a18eSAnirudh Venkataramanan 
23575153a18eSAnirudh Venkataramanan 	if (!vsi->tx_rings)
23585153a18eSAnirudh Venkataramanan 		return;
23595153a18eSAnirudh Venkataramanan 
23605153a18eSAnirudh Venkataramanan 	ice_for_each_txq(vsi, i)
23615153a18eSAnirudh Venkataramanan 		if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc)
23625153a18eSAnirudh Venkataramanan 			ice_free_tx_ring(vsi->tx_rings[i]);
23635153a18eSAnirudh Venkataramanan }
23645153a18eSAnirudh Venkataramanan 
23655153a18eSAnirudh Venkataramanan /**
23665153a18eSAnirudh Venkataramanan  * ice_vsi_free_rx_rings - Free Rx resources for VSI queues
23675153a18eSAnirudh Venkataramanan  * @vsi: the VSI having resources freed
23685153a18eSAnirudh Venkataramanan  */
23695153a18eSAnirudh Venkataramanan void ice_vsi_free_rx_rings(struct ice_vsi *vsi)
23705153a18eSAnirudh Venkataramanan {
23715153a18eSAnirudh Venkataramanan 	int i;
23725153a18eSAnirudh Venkataramanan 
23735153a18eSAnirudh Venkataramanan 	if (!vsi->rx_rings)
23745153a18eSAnirudh Venkataramanan 		return;
23755153a18eSAnirudh Venkataramanan 
23765153a18eSAnirudh Venkataramanan 	ice_for_each_rxq(vsi, i)
23775153a18eSAnirudh Venkataramanan 		if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
23785153a18eSAnirudh Venkataramanan 			ice_free_rx_ring(vsi->rx_rings[i]);
23795153a18eSAnirudh Venkataramanan }
23805153a18eSAnirudh Venkataramanan 
23815153a18eSAnirudh Venkataramanan /**
238207309a0eSAnirudh Venkataramanan  * ice_vsi_close - Shut down a VSI
238307309a0eSAnirudh Venkataramanan  * @vsi: the VSI being shut down
238407309a0eSAnirudh Venkataramanan  */
238507309a0eSAnirudh Venkataramanan void ice_vsi_close(struct ice_vsi *vsi)
238607309a0eSAnirudh Venkataramanan {
238707309a0eSAnirudh Venkataramanan 	if (!test_and_set_bit(__ICE_DOWN, vsi->state))
238807309a0eSAnirudh Venkataramanan 		ice_down(vsi);
238907309a0eSAnirudh Venkataramanan 
239007309a0eSAnirudh Venkataramanan 	ice_vsi_free_irq(vsi);
239107309a0eSAnirudh Venkataramanan 	ice_vsi_free_tx_rings(vsi);
239207309a0eSAnirudh Venkataramanan 	ice_vsi_free_rx_rings(vsi);
239307309a0eSAnirudh Venkataramanan }
239407309a0eSAnirudh Venkataramanan 
239507309a0eSAnirudh Venkataramanan /**
23969d614b64SAnirudh Venkataramanan  * ice_ena_vsi - resume a VSI
23979d614b64SAnirudh Venkataramanan  * @vsi: the VSI being resume
23989d614b64SAnirudh Venkataramanan  * @locked: is the rtnl_lock already held
23999d614b64SAnirudh Venkataramanan  */
24009d614b64SAnirudh Venkataramanan int ice_ena_vsi(struct ice_vsi *vsi, bool locked)
24019d614b64SAnirudh Venkataramanan {
24029d614b64SAnirudh Venkataramanan 	int err = 0;
24039d614b64SAnirudh Venkataramanan 
24049d614b64SAnirudh Venkataramanan 	if (!test_bit(__ICE_NEEDS_RESTART, vsi->state))
24059d614b64SAnirudh Venkataramanan 		return 0;
24069d614b64SAnirudh Venkataramanan 
24079d614b64SAnirudh Venkataramanan 	clear_bit(__ICE_NEEDS_RESTART, vsi->state);
24089d614b64SAnirudh Venkataramanan 
24099d614b64SAnirudh Venkataramanan 	if (vsi->netdev && vsi->type == ICE_VSI_PF) {
24109d614b64SAnirudh Venkataramanan 		if (netif_running(vsi->netdev)) {
24119d614b64SAnirudh Venkataramanan 			if (!locked)
24129d614b64SAnirudh Venkataramanan 				rtnl_lock();
24139d614b64SAnirudh Venkataramanan 
24149d614b64SAnirudh Venkataramanan 			err = ice_open(vsi->netdev);
24159d614b64SAnirudh Venkataramanan 
24169d614b64SAnirudh Venkataramanan 			if (!locked)
24179d614b64SAnirudh Venkataramanan 				rtnl_unlock();
24189d614b64SAnirudh Venkataramanan 		}
24199d614b64SAnirudh Venkataramanan 	}
24209d614b64SAnirudh Venkataramanan 
24219d614b64SAnirudh Venkataramanan 	return err;
24229d614b64SAnirudh Venkataramanan }
24239d614b64SAnirudh Venkataramanan 
24249d614b64SAnirudh Venkataramanan /**
24259d614b64SAnirudh Venkataramanan  * ice_dis_vsi - pause a VSI
24269d614b64SAnirudh Venkataramanan  * @vsi: the VSI being paused
24279d614b64SAnirudh Venkataramanan  * @locked: is the rtnl_lock already held
24289d614b64SAnirudh Venkataramanan  */
24299d614b64SAnirudh Venkataramanan void ice_dis_vsi(struct ice_vsi *vsi, bool locked)
24309d614b64SAnirudh Venkataramanan {
24319d614b64SAnirudh Venkataramanan 	if (test_bit(__ICE_DOWN, vsi->state))
24329d614b64SAnirudh Venkataramanan 		return;
24339d614b64SAnirudh Venkataramanan 
24349d614b64SAnirudh Venkataramanan 	set_bit(__ICE_NEEDS_RESTART, vsi->state);
24359d614b64SAnirudh Venkataramanan 
24369d614b64SAnirudh Venkataramanan 	if (vsi->type == ICE_VSI_PF && vsi->netdev) {
24379d614b64SAnirudh Venkataramanan 		if (netif_running(vsi->netdev)) {
24389d614b64SAnirudh Venkataramanan 			if (!locked)
24399d614b64SAnirudh Venkataramanan 				rtnl_lock();
24409d614b64SAnirudh Venkataramanan 
24419d614b64SAnirudh Venkataramanan 			ice_stop(vsi->netdev);
24429d614b64SAnirudh Venkataramanan 
24439d614b64SAnirudh Venkataramanan 			if (!locked)
24449d614b64SAnirudh Venkataramanan 				rtnl_unlock();
24459d614b64SAnirudh Venkataramanan 		} else {
24469d614b64SAnirudh Venkataramanan 			ice_vsi_close(vsi);
24479d614b64SAnirudh Venkataramanan 		}
24489d614b64SAnirudh Venkataramanan 	}
24499d614b64SAnirudh Venkataramanan }
24509d614b64SAnirudh Venkataramanan 
24519d614b64SAnirudh Venkataramanan /**
24525153a18eSAnirudh Venkataramanan  * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI
24535153a18eSAnirudh Venkataramanan  * @vsi: the VSI being un-configured
24545153a18eSAnirudh Venkataramanan  */
24555153a18eSAnirudh Venkataramanan void ice_vsi_dis_irq(struct ice_vsi *vsi)
24565153a18eSAnirudh Venkataramanan {
2457cbe66bfeSBrett Creeley 	int base = vsi->base_vector;
24585153a18eSAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
24595153a18eSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
24605153a18eSAnirudh Venkataramanan 	u32 val;
24615153a18eSAnirudh Venkataramanan 	int i;
24625153a18eSAnirudh Venkataramanan 
24635153a18eSAnirudh Venkataramanan 	/* disable interrupt causation from each queue */
24645153a18eSAnirudh Venkataramanan 	if (vsi->tx_rings) {
24655153a18eSAnirudh Venkataramanan 		ice_for_each_txq(vsi, i) {
24665153a18eSAnirudh Venkataramanan 			if (vsi->tx_rings[i]) {
24675153a18eSAnirudh Venkataramanan 				u16 reg;
24685153a18eSAnirudh Venkataramanan 
24695153a18eSAnirudh Venkataramanan 				reg = vsi->tx_rings[i]->reg_idx;
24705153a18eSAnirudh Venkataramanan 				val = rd32(hw, QINT_TQCTL(reg));
24715153a18eSAnirudh Venkataramanan 				val &= ~QINT_TQCTL_CAUSE_ENA_M;
24725153a18eSAnirudh Venkataramanan 				wr32(hw, QINT_TQCTL(reg), val);
24735153a18eSAnirudh Venkataramanan 			}
24745153a18eSAnirudh Venkataramanan 		}
24755153a18eSAnirudh Venkataramanan 	}
24765153a18eSAnirudh Venkataramanan 
24775153a18eSAnirudh Venkataramanan 	if (vsi->rx_rings) {
24785153a18eSAnirudh Venkataramanan 		ice_for_each_rxq(vsi, i) {
24795153a18eSAnirudh Venkataramanan 			if (vsi->rx_rings[i]) {
24805153a18eSAnirudh Venkataramanan 				u16 reg;
24815153a18eSAnirudh Venkataramanan 
24825153a18eSAnirudh Venkataramanan 				reg = vsi->rx_rings[i]->reg_idx;
24835153a18eSAnirudh Venkataramanan 				val = rd32(hw, QINT_RQCTL(reg));
24845153a18eSAnirudh Venkataramanan 				val &= ~QINT_RQCTL_CAUSE_ENA_M;
24855153a18eSAnirudh Venkataramanan 				wr32(hw, QINT_RQCTL(reg), val);
24865153a18eSAnirudh Venkataramanan 			}
24875153a18eSAnirudh Venkataramanan 		}
24885153a18eSAnirudh Venkataramanan 	}
24895153a18eSAnirudh Venkataramanan 
24905153a18eSAnirudh Venkataramanan 	/* disable each interrupt */
2491462acf6aSTony Nguyen 	ice_for_each_q_vector(vsi, i) {
2492462acf6aSTony Nguyen 		if (!vsi->q_vectors[i])
2493462acf6aSTony Nguyen 			continue;
2494b07833a0SBrett Creeley 		wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0);
2495462acf6aSTony Nguyen 	}
24965153a18eSAnirudh Venkataramanan 
24975153a18eSAnirudh Venkataramanan 	ice_flush(hw);
2498b07833a0SBrett Creeley 
2499da4a9e73SBrett Creeley 	/* don't call synchronize_irq() for VF's from the host */
2500da4a9e73SBrett Creeley 	if (vsi->type == ICE_VSI_VF)
2501da4a9e73SBrett Creeley 		return;
2502da4a9e73SBrett Creeley 
25030c2561c8SBrett Creeley 	ice_for_each_q_vector(vsi, i)
25045153a18eSAnirudh Venkataramanan 		synchronize_irq(pf->msix_entries[i + base].vector);
25055153a18eSAnirudh Venkataramanan }
25065153a18eSAnirudh Venkataramanan 
25075153a18eSAnirudh Venkataramanan /**
2508561f4379STony Nguyen  * ice_napi_del - Remove NAPI handler for the VSI
2509561f4379STony Nguyen  * @vsi: VSI for which NAPI handler is to be removed
2510561f4379STony Nguyen  */
2511561f4379STony Nguyen void ice_napi_del(struct ice_vsi *vsi)
2512561f4379STony Nguyen {
2513561f4379STony Nguyen 	int v_idx;
2514561f4379STony Nguyen 
2515561f4379STony Nguyen 	if (!vsi->netdev)
2516561f4379STony Nguyen 		return;
2517561f4379STony Nguyen 
2518561f4379STony Nguyen 	ice_for_each_q_vector(vsi, v_idx)
2519561f4379STony Nguyen 		netif_napi_del(&vsi->q_vectors[v_idx]->napi);
2520561f4379STony Nguyen }
2521561f4379STony Nguyen 
2522561f4379STony Nguyen /**
2523df0f8479SAnirudh Venkataramanan  * ice_vsi_release - Delete a VSI and free its resources
2524df0f8479SAnirudh Venkataramanan  * @vsi: the VSI being removed
2525df0f8479SAnirudh Venkataramanan  *
2526df0f8479SAnirudh Venkataramanan  * Returns 0 on success or < 0 on error
2527df0f8479SAnirudh Venkataramanan  */
2528df0f8479SAnirudh Venkataramanan int ice_vsi_release(struct ice_vsi *vsi)
2529df0f8479SAnirudh Venkataramanan {
2530df0f8479SAnirudh Venkataramanan 	struct ice_pf *pf;
2531df0f8479SAnirudh Venkataramanan 
2532df0f8479SAnirudh Venkataramanan 	if (!vsi->back)
2533df0f8479SAnirudh Venkataramanan 		return -ENODEV;
2534df0f8479SAnirudh Venkataramanan 	pf = vsi->back;
2535b751930cSBrett Creeley 
2536aa6ccf3fSBrett Creeley 	/* do not unregister while driver is in the reset recovery pending
2537aa6ccf3fSBrett Creeley 	 * state. Since reset/rebuild happens through PF service task workqueue,
2538aa6ccf3fSBrett Creeley 	 * it's not a good idea to unregister netdev that is associated to the
2539aa6ccf3fSBrett Creeley 	 * PF that is running the work queue items currently. This is done to
2540aa6ccf3fSBrett Creeley 	 * avoid check_flush_dependency() warning on this wq
2541df0f8479SAnirudh Venkataramanan 	 */
2542aa6ccf3fSBrett Creeley 	if (vsi->netdev && !ice_is_reset_in_progress(pf->state))
2543df0f8479SAnirudh Venkataramanan 		unregister_netdev(vsi->netdev);
2544df0f8479SAnirudh Venkataramanan 
2545df0f8479SAnirudh Venkataramanan 	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
2546df0f8479SAnirudh Venkataramanan 		ice_rss_clean(vsi);
2547df0f8479SAnirudh Venkataramanan 
2548df0f8479SAnirudh Venkataramanan 	/* Disable VSI and free resources */
25490e674aebSAnirudh Venkataramanan 	if (vsi->type != ICE_VSI_LB)
2550df0f8479SAnirudh Venkataramanan 		ice_vsi_dis_irq(vsi);
2551df0f8479SAnirudh Venkataramanan 	ice_vsi_close(vsi);
2552df0f8479SAnirudh Venkataramanan 
2553cbe66bfeSBrett Creeley 	/* SR-IOV determines needed MSIX resources all at once instead of per
2554cbe66bfeSBrett Creeley 	 * VSI since when VFs are spawned we know how many VFs there are and how
2555cbe66bfeSBrett Creeley 	 * many interrupts each VF needs. SR-IOV MSIX resources are also
2556cbe66bfeSBrett Creeley 	 * cleared in the same manner.
2557cbe66bfeSBrett Creeley 	 */
25588ede0178SAnirudh Venkataramanan 	if (vsi->type != ICE_VSI_VF) {
25598ede0178SAnirudh Venkataramanan 		/* reclaim SW interrupts back to the common pool */
2560cbe66bfeSBrett Creeley 		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
2561eb0208ecSPreethi Banala 		pf->num_avail_sw_msix += vsi->num_q_vectors;
25628ede0178SAnirudh Venkataramanan 	}
2563df0f8479SAnirudh Venkataramanan 
2564462acf6aSTony Nguyen 	if (!ice_is_safe_mode(pf)) {
25652e0e6228SDave Ertman 		if (vsi->type == ICE_VSI_PF) {
2566d95276ceSAkeem G Abodunrin 			ice_vsi_add_rem_eth_mac(vsi, false);
25672e0e6228SDave Ertman 			ice_cfg_sw_lldp(vsi, true, false);
25682e0e6228SDave Ertman 			/* The Rx rule will only exist to remove if the LLDP FW
25692e0e6228SDave Ertman 			 * engine is currently stopped
25702e0e6228SDave Ertman 			 */
257184a118abSDave Ertman 			if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
25722e0e6228SDave Ertman 				ice_cfg_sw_lldp(vsi, false, false);
25732e0e6228SDave Ertman 		}
2574462acf6aSTony Nguyen 	}
2575d95276ceSAkeem G Abodunrin 
25765726ca0eSAnirudh Venkataramanan 	ice_remove_vsi_fltr(&pf->hw, vsi->idx);
257710e03a22SAnirudh Venkataramanan 	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
2578df0f8479SAnirudh Venkataramanan 	ice_vsi_delete(vsi);
2579df0f8479SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
2580aa6ccf3fSBrett Creeley 
2581aa6ccf3fSBrett Creeley 	/* make sure unregister_netdev() was called by checking __ICE_DOWN */
2582aa6ccf3fSBrett Creeley 	if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) {
2583aa6ccf3fSBrett Creeley 		free_netdev(vsi->netdev);
2584aa6ccf3fSBrett Creeley 		vsi->netdev = NULL;
2585aa6ccf3fSBrett Creeley 	}
2586aa6ccf3fSBrett Creeley 
2587df0f8479SAnirudh Venkataramanan 	ice_vsi_clear_rings(vsi);
2588df0f8479SAnirudh Venkataramanan 
2589df0f8479SAnirudh Venkataramanan 	ice_vsi_put_qs(vsi);
2590df0f8479SAnirudh Venkataramanan 
2591df0f8479SAnirudh Venkataramanan 	/* retain SW VSI data structure since it is needed to unregister and
2592df0f8479SAnirudh Venkataramanan 	 * free VSI netdev when PF is not in reset recovery pending state,\
2593df0f8479SAnirudh Venkataramanan 	 * for ex: during rmmod.
2594df0f8479SAnirudh Venkataramanan 	 */
25955df7e45dSDave Ertman 	if (!ice_is_reset_in_progress(pf->state))
2596df0f8479SAnirudh Venkataramanan 		ice_vsi_clear(vsi);
2597df0f8479SAnirudh Venkataramanan 
2598df0f8479SAnirudh Venkataramanan 	return 0;
2599df0f8479SAnirudh Venkataramanan }
2600df0f8479SAnirudh Venkataramanan 
2601df0f8479SAnirudh Venkataramanan /**
260261dc79ceSMichal Swiatkowski  * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector
260361dc79ceSMichal Swiatkowski  * @q_vector: pointer to q_vector which is being updated
260461dc79ceSMichal Swiatkowski  * @coalesce: pointer to array of struct with stored coalesce
260561dc79ceSMichal Swiatkowski  *
260661dc79ceSMichal Swiatkowski  * Set coalesce param in q_vector and update these parameters in HW.
260761dc79ceSMichal Swiatkowski  */
260861dc79ceSMichal Swiatkowski static void
260961dc79ceSMichal Swiatkowski ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector,
261061dc79ceSMichal Swiatkowski 				struct ice_coalesce_stored *coalesce)
261161dc79ceSMichal Swiatkowski {
261261dc79ceSMichal Swiatkowski 	struct ice_ring_container *rx_rc = &q_vector->rx;
261361dc79ceSMichal Swiatkowski 	struct ice_ring_container *tx_rc = &q_vector->tx;
261461dc79ceSMichal Swiatkowski 	struct ice_hw *hw = &q_vector->vsi->back->hw;
261561dc79ceSMichal Swiatkowski 
261661dc79ceSMichal Swiatkowski 	tx_rc->itr_setting = coalesce->itr_tx;
261761dc79ceSMichal Swiatkowski 	rx_rc->itr_setting = coalesce->itr_rx;
261861dc79ceSMichal Swiatkowski 
261961dc79ceSMichal Swiatkowski 	/* dynamic ITR values will be updated during Tx/Rx */
262061dc79ceSMichal Swiatkowski 	if (!ITR_IS_DYNAMIC(tx_rc->itr_setting))
262161dc79ceSMichal Swiatkowski 		wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx),
262261dc79ceSMichal Swiatkowski 		     ITR_REG_ALIGN(tx_rc->itr_setting) >>
262361dc79ceSMichal Swiatkowski 		     ICE_ITR_GRAN_S);
262461dc79ceSMichal Swiatkowski 	if (!ITR_IS_DYNAMIC(rx_rc->itr_setting))
262561dc79ceSMichal Swiatkowski 		wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx),
262661dc79ceSMichal Swiatkowski 		     ITR_REG_ALIGN(rx_rc->itr_setting) >>
262761dc79ceSMichal Swiatkowski 		     ICE_ITR_GRAN_S);
262861dc79ceSMichal Swiatkowski 
262961dc79ceSMichal Swiatkowski 	q_vector->intrl = coalesce->intrl;
263061dc79ceSMichal Swiatkowski 	wr32(hw, GLINT_RATE(q_vector->reg_idx),
263161dc79ceSMichal Swiatkowski 	     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
263261dc79ceSMichal Swiatkowski }
263361dc79ceSMichal Swiatkowski 
263461dc79ceSMichal Swiatkowski /**
263561dc79ceSMichal Swiatkowski  * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
263661dc79ceSMichal Swiatkowski  * @vsi: VSI connected with q_vectors
263761dc79ceSMichal Swiatkowski  * @coalesce: array of struct with stored coalesce
263861dc79ceSMichal Swiatkowski  *
263961dc79ceSMichal Swiatkowski  * Returns array size.
264061dc79ceSMichal Swiatkowski  */
264161dc79ceSMichal Swiatkowski static int
264261dc79ceSMichal Swiatkowski ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
264361dc79ceSMichal Swiatkowski 			     struct ice_coalesce_stored *coalesce)
264461dc79ceSMichal Swiatkowski {
264561dc79ceSMichal Swiatkowski 	int i;
264661dc79ceSMichal Swiatkowski 
264761dc79ceSMichal Swiatkowski 	ice_for_each_q_vector(vsi, i) {
264861dc79ceSMichal Swiatkowski 		struct ice_q_vector *q_vector = vsi->q_vectors[i];
264961dc79ceSMichal Swiatkowski 
265061dc79ceSMichal Swiatkowski 		coalesce[i].itr_tx = q_vector->tx.itr_setting;
265161dc79ceSMichal Swiatkowski 		coalesce[i].itr_rx = q_vector->rx.itr_setting;
265261dc79ceSMichal Swiatkowski 		coalesce[i].intrl = q_vector->intrl;
265361dc79ceSMichal Swiatkowski 	}
265461dc79ceSMichal Swiatkowski 
265561dc79ceSMichal Swiatkowski 	return vsi->num_q_vectors;
265661dc79ceSMichal Swiatkowski }
265761dc79ceSMichal Swiatkowski 
265861dc79ceSMichal Swiatkowski /**
265961dc79ceSMichal Swiatkowski  * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays
266061dc79ceSMichal Swiatkowski  * @vsi: VSI connected with q_vectors
266161dc79ceSMichal Swiatkowski  * @coalesce: pointer to array of struct with stored coalesce
266261dc79ceSMichal Swiatkowski  * @size: size of coalesce array
266361dc79ceSMichal Swiatkowski  *
266461dc79ceSMichal Swiatkowski  * Before this function, ice_vsi_rebuild_get_coalesce should be called to save
266561dc79ceSMichal Swiatkowski  * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce
266661dc79ceSMichal Swiatkowski  * to default value.
266761dc79ceSMichal Swiatkowski  */
266861dc79ceSMichal Swiatkowski static void
266961dc79ceSMichal Swiatkowski ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
267061dc79ceSMichal Swiatkowski 			     struct ice_coalesce_stored *coalesce, int size)
267161dc79ceSMichal Swiatkowski {
267261dc79ceSMichal Swiatkowski 	int i;
267361dc79ceSMichal Swiatkowski 
267461dc79ceSMichal Swiatkowski 	if ((size && !coalesce) || !vsi)
267561dc79ceSMichal Swiatkowski 		return;
267661dc79ceSMichal Swiatkowski 
267761dc79ceSMichal Swiatkowski 	for (i = 0; i < size && i < vsi->num_q_vectors; i++)
267861dc79ceSMichal Swiatkowski 		ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
267961dc79ceSMichal Swiatkowski 						&coalesce[i]);
268061dc79ceSMichal Swiatkowski 
268161dc79ceSMichal Swiatkowski 	for (; i < vsi->num_q_vectors; i++) {
268261dc79ceSMichal Swiatkowski 		struct ice_coalesce_stored coalesce_dflt = {
268361dc79ceSMichal Swiatkowski 			.itr_tx = ICE_DFLT_TX_ITR,
268461dc79ceSMichal Swiatkowski 			.itr_rx = ICE_DFLT_RX_ITR,
268561dc79ceSMichal Swiatkowski 			.intrl = 0
268661dc79ceSMichal Swiatkowski 		};
268761dc79ceSMichal Swiatkowski 		ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
268861dc79ceSMichal Swiatkowski 						&coalesce_dflt);
268961dc79ceSMichal Swiatkowski 	}
269061dc79ceSMichal Swiatkowski }
269161dc79ceSMichal Swiatkowski 
269261dc79ceSMichal Swiatkowski /**
2693df0f8479SAnirudh Venkataramanan  * ice_vsi_rebuild - Rebuild VSI after reset
2694df0f8479SAnirudh Venkataramanan  * @vsi: VSI to be rebuild
269587324e74SHenry Tieman  * @init_vsi: is this an initialization or a reconfigure of the VSI
2696df0f8479SAnirudh Venkataramanan  *
2697df0f8479SAnirudh Venkataramanan  * Returns 0 on success and negative value on failure
2698df0f8479SAnirudh Venkataramanan  */
269987324e74SHenry Tieman int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
2700df0f8479SAnirudh Venkataramanan {
2701df0f8479SAnirudh Venkataramanan 	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
270261dc79ceSMichal Swiatkowski 	struct ice_coalesce_stored *coalesce;
270361dc79ceSMichal Swiatkowski 	int prev_num_q_vectors = 0;
27047eeac889SAkeem G Abodunrin 	struct ice_vf *vf = NULL;
2705d31530e8SAkeem G Abodunrin 	enum ice_status status;
2706c5a2a4a3SUsha Ketineni 	struct ice_pf *pf;
2707df0f8479SAnirudh Venkataramanan 	int ret, i;
2708df0f8479SAnirudh Venkataramanan 
2709df0f8479SAnirudh Venkataramanan 	if (!vsi)
2710df0f8479SAnirudh Venkataramanan 		return -EINVAL;
2711df0f8479SAnirudh Venkataramanan 
2712c5a2a4a3SUsha Ketineni 	pf = vsi->back;
27137eeac889SAkeem G Abodunrin 	if (vsi->type == ICE_VSI_VF)
27147eeac889SAkeem G Abodunrin 		vf = &pf->vf[vsi->vf_id];
27157eeac889SAkeem G Abodunrin 
271661dc79ceSMichal Swiatkowski 	coalesce = kcalloc(vsi->num_q_vectors,
271761dc79ceSMichal Swiatkowski 			   sizeof(struct ice_coalesce_stored), GFP_KERNEL);
271861dc79ceSMichal Swiatkowski 	if (coalesce)
271961dc79ceSMichal Swiatkowski 		prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi,
272061dc79ceSMichal Swiatkowski 								  coalesce);
272147e3e53cSHenry Tieman 	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
2722df0f8479SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
27237eeac889SAkeem G Abodunrin 
2724cbe66bfeSBrett Creeley 	/* SR-IOV determines needed MSIX resources all at once instead of per
2725cbe66bfeSBrett Creeley 	 * VSI since when VFs are spawned we know how many VFs there are and how
2726cbe66bfeSBrett Creeley 	 * many interrupts each VF needs. SR-IOV MSIX resources are also
2727cbe66bfeSBrett Creeley 	 * cleared in the same manner.
2728cbe66bfeSBrett Creeley 	 */
27297eeac889SAkeem G Abodunrin 	if (vsi->type != ICE_VSI_VF) {
27307eeac889SAkeem G Abodunrin 		/* reclaim SW interrupts back to the common pool */
2731cbe66bfeSBrett Creeley 		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
27327eeac889SAkeem G Abodunrin 		pf->num_avail_sw_msix += vsi->num_q_vectors;
2733cbe66bfeSBrett Creeley 		vsi->base_vector = 0;
27347eeac889SAkeem G Abodunrin 	}
27357eeac889SAkeem G Abodunrin 
2736efc2214bSMaciej Fijalkowski 	if (ice_is_xdp_ena_vsi(vsi))
2737efc2214bSMaciej Fijalkowski 		/* return value check can be skipped here, it always returns
2738efc2214bSMaciej Fijalkowski 		 * 0 if reset is in progress
2739efc2214bSMaciej Fijalkowski 		 */
2740efc2214bSMaciej Fijalkowski 		ice_destroy_xdp_rings(vsi);
274178b5713aSAnirudh Venkataramanan 	ice_vsi_put_qs(vsi);
2742df0f8479SAnirudh Venkataramanan 	ice_vsi_clear_rings(vsi);
2743a85a3847SBrett Creeley 	ice_vsi_free_arrays(vsi);
27445743020dSAkeem G Abodunrin 	if (vsi->type == ICE_VSI_VF)
27455743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, vf->vf_id);
27465743020dSAkeem G Abodunrin 	else
27475743020dSAkeem G Abodunrin 		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
274878b5713aSAnirudh Venkataramanan 
274978b5713aSAnirudh Venkataramanan 	ret = ice_vsi_alloc_arrays(vsi);
275078b5713aSAnirudh Venkataramanan 	if (ret < 0)
275178b5713aSAnirudh Venkataramanan 		goto err_vsi;
275278b5713aSAnirudh Venkataramanan 
275378b5713aSAnirudh Venkataramanan 	ice_vsi_get_qs(vsi);
2754c5a2a4a3SUsha Ketineni 	ice_vsi_set_tc_cfg(vsi);
2755df0f8479SAnirudh Venkataramanan 
2756df0f8479SAnirudh Venkataramanan 	/* Initialize VSI struct elements and create VSI in FW */
275787324e74SHenry Tieman 	ret = ice_vsi_init(vsi, init_vsi);
2758df0f8479SAnirudh Venkataramanan 	if (ret < 0)
2759df0f8479SAnirudh Venkataramanan 		goto err_vsi;
2760df0f8479SAnirudh Venkataramanan 
2761df0f8479SAnirudh Venkataramanan 	switch (vsi->type) {
2762df0f8479SAnirudh Venkataramanan 	case ICE_VSI_PF:
2763df0f8479SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
2764df0f8479SAnirudh Venkataramanan 		if (ret)
2765df0f8479SAnirudh Venkataramanan 			goto err_rings;
2766df0f8479SAnirudh Venkataramanan 
276717bc6d07STony Nguyen 		ret = ice_vsi_setup_vector_base(vsi);
276817bc6d07STony Nguyen 		if (ret)
276917bc6d07STony Nguyen 			goto err_vectors;
277017bc6d07STony Nguyen 
2771b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2772b07833a0SBrett Creeley 		if (ret)
2773b07833a0SBrett Creeley 			goto err_vectors;
2774b07833a0SBrett Creeley 
2775df0f8479SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
2776df0f8479SAnirudh Venkataramanan 		if (ret)
2777df0f8479SAnirudh Venkataramanan 			goto err_vectors;
2778df0f8479SAnirudh Venkataramanan 
2779df0f8479SAnirudh Venkataramanan 		ice_vsi_map_rings_to_vectors(vsi);
2780efc2214bSMaciej Fijalkowski 		if (ice_is_xdp_ena_vsi(vsi)) {
2781efc2214bSMaciej Fijalkowski 			vsi->num_xdp_txq = vsi->alloc_txq;
2782efc2214bSMaciej Fijalkowski 			ret = ice_prepare_xdp_rings(vsi, vsi->xdp_prog);
2783efc2214bSMaciej Fijalkowski 			if (ret)
2784efc2214bSMaciej Fijalkowski 				goto err_vectors;
2785efc2214bSMaciej Fijalkowski 		}
278627a98affSMd Fahad Iqbal Polash 		/* Do not exit if configuring RSS had an issue, at least
278727a98affSMd Fahad Iqbal Polash 		 * receive traffic on first queue. Hence no need to capture
278827a98affSMd Fahad Iqbal Polash 		 * return value
278927a98affSMd Fahad Iqbal Polash 		 */
2790819d8998SJesse Brandeburg 		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
279127a98affSMd Fahad Iqbal Polash 			ice_vsi_cfg_rss_lut_key(vsi);
2792df0f8479SAnirudh Venkataramanan 		break;
27938ede0178SAnirudh Venkataramanan 	case ICE_VSI_VF:
27948ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_q_vectors(vsi);
27958ede0178SAnirudh Venkataramanan 		if (ret)
27968ede0178SAnirudh Venkataramanan 			goto err_rings;
27978ede0178SAnirudh Venkataramanan 
2798b07833a0SBrett Creeley 		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
2799b07833a0SBrett Creeley 		if (ret)
2800b07833a0SBrett Creeley 			goto err_vectors;
2801b07833a0SBrett Creeley 
28028ede0178SAnirudh Venkataramanan 		ret = ice_vsi_alloc_rings(vsi);
28038ede0178SAnirudh Venkataramanan 		if (ret)
28048ede0178SAnirudh Venkataramanan 			goto err_vectors;
28058ede0178SAnirudh Venkataramanan 
28068ede0178SAnirudh Venkataramanan 		break;
2807df0f8479SAnirudh Venkataramanan 	default:
2808df0f8479SAnirudh Venkataramanan 		break;
2809df0f8479SAnirudh Venkataramanan 	}
2810df0f8479SAnirudh Venkataramanan 
2811df0f8479SAnirudh Venkataramanan 	/* configure VSI nodes based on number of queues and TC's */
2812efc2214bSMaciej Fijalkowski 	for (i = 0; i < vsi->tc_cfg.numtc; i++) {
2813d5a46359SAkeem G Abodunrin 		max_txqs[i] = vsi->alloc_txq;
2814df0f8479SAnirudh Venkataramanan 
2815efc2214bSMaciej Fijalkowski 		if (ice_is_xdp_ena_vsi(vsi))
2816efc2214bSMaciej Fijalkowski 			max_txqs[i] += vsi->num_xdp_txq;
2817efc2214bSMaciej Fijalkowski 	}
2818efc2214bSMaciej Fijalkowski 
2819d31530e8SAkeem G Abodunrin 	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
28204fb33f31SAnirudh Venkataramanan 				 max_txqs);
2821d31530e8SAkeem G Abodunrin 	if (status) {
28220fee3577SLihong Yang 		dev_err(ice_pf_to_dev(pf), "VSI %d failed lan queue config, error %s\n",
28230fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
282487324e74SHenry Tieman 		if (init_vsi) {
282587324e74SHenry Tieman 			ret = -EIO;
2826df0f8479SAnirudh Venkataramanan 			goto err_vectors;
282787324e74SHenry Tieman 		} else {
282887324e74SHenry Tieman 			return ice_schedule_reset(pf, ICE_RESET_PFR);
282987324e74SHenry Tieman 		}
2830df0f8479SAnirudh Venkataramanan 	}
283161dc79ceSMichal Swiatkowski 	ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors);
283261dc79ceSMichal Swiatkowski 	kfree(coalesce);
283361dc79ceSMichal Swiatkowski 
2834df0f8479SAnirudh Venkataramanan 	return 0;
2835df0f8479SAnirudh Venkataramanan 
2836df0f8479SAnirudh Venkataramanan err_vectors:
2837df0f8479SAnirudh Venkataramanan 	ice_vsi_free_q_vectors(vsi);
2838df0f8479SAnirudh Venkataramanan err_rings:
2839df0f8479SAnirudh Venkataramanan 	if (vsi->netdev) {
2840df0f8479SAnirudh Venkataramanan 		vsi->current_netdev_flags = 0;
2841df0f8479SAnirudh Venkataramanan 		unregister_netdev(vsi->netdev);
2842df0f8479SAnirudh Venkataramanan 		free_netdev(vsi->netdev);
2843df0f8479SAnirudh Venkataramanan 		vsi->netdev = NULL;
2844df0f8479SAnirudh Venkataramanan 	}
2845df0f8479SAnirudh Venkataramanan err_vsi:
2846df0f8479SAnirudh Venkataramanan 	ice_vsi_clear(vsi);
2847819d8998SJesse Brandeburg 	set_bit(__ICE_RESET_FAILED, pf->state);
284861dc79ceSMichal Swiatkowski 	kfree(coalesce);
2849df0f8479SAnirudh Venkataramanan 	return ret;
2850df0f8479SAnirudh Venkataramanan }
2851df0f8479SAnirudh Venkataramanan 
2852df0f8479SAnirudh Venkataramanan /**
28535df7e45dSDave Ertman  * ice_is_reset_in_progress - check for a reset in progress
28542f2da36eSAnirudh Venkataramanan  * @state: PF state field
28555153a18eSAnirudh Venkataramanan  */
28565df7e45dSDave Ertman bool ice_is_reset_in_progress(unsigned long *state)
28575153a18eSAnirudh Venkataramanan {
28585df7e45dSDave Ertman 	return test_bit(__ICE_RESET_OICR_RECV, state) ||
2859b94b013eSDave Ertman 	       test_bit(__ICE_DCBNL_DEVRESET, state) ||
28605df7e45dSDave Ertman 	       test_bit(__ICE_PFR_REQ, state) ||
28615df7e45dSDave Ertman 	       test_bit(__ICE_CORER_REQ, state) ||
28625df7e45dSDave Ertman 	       test_bit(__ICE_GLOBR_REQ, state);
28635153a18eSAnirudh Venkataramanan }
28647b9ffc76SAnirudh Venkataramanan 
28657b9ffc76SAnirudh Venkataramanan #ifdef CONFIG_DCB
28667b9ffc76SAnirudh Venkataramanan /**
28677b9ffc76SAnirudh Venkataramanan  * ice_vsi_update_q_map - update our copy of the VSI info with new queue map
28687b9ffc76SAnirudh Venkataramanan  * @vsi: VSI being configured
28697b9ffc76SAnirudh Venkataramanan  * @ctx: the context buffer returned from AQ VSI update command
28707b9ffc76SAnirudh Venkataramanan  */
28717b9ffc76SAnirudh Venkataramanan static void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx)
28727b9ffc76SAnirudh Venkataramanan {
28737b9ffc76SAnirudh Venkataramanan 	vsi->info.mapping_flags = ctx->info.mapping_flags;
28747b9ffc76SAnirudh Venkataramanan 	memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping,
28757b9ffc76SAnirudh Venkataramanan 	       sizeof(vsi->info.q_mapping));
28767b9ffc76SAnirudh Venkataramanan 	memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping,
28777b9ffc76SAnirudh Venkataramanan 	       sizeof(vsi->info.tc_mapping));
28787b9ffc76SAnirudh Venkataramanan }
28797b9ffc76SAnirudh Venkataramanan 
28807b9ffc76SAnirudh Venkataramanan /**
28817b9ffc76SAnirudh Venkataramanan  * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map
28827b9ffc76SAnirudh Venkataramanan  * @vsi: VSI to be configured
28837b9ffc76SAnirudh Venkataramanan  * @ena_tc: TC bitmap
28847b9ffc76SAnirudh Venkataramanan  *
28857b9ffc76SAnirudh Venkataramanan  * VSI queues expected to be quiesced before calling this function
28867b9ffc76SAnirudh Venkataramanan  */
28877b9ffc76SAnirudh Venkataramanan int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
28887b9ffc76SAnirudh Venkataramanan {
28897b9ffc76SAnirudh Venkataramanan 	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
28907b9ffc76SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
28914ee656bbSTony Nguyen 	struct ice_vsi_ctx *ctx;
28927b9ffc76SAnirudh Venkataramanan 	enum ice_status status;
28934015d11eSBrett Creeley 	struct device *dev;
28947b9ffc76SAnirudh Venkataramanan 	int i, ret = 0;
28957b9ffc76SAnirudh Venkataramanan 	u8 num_tc = 0;
28967b9ffc76SAnirudh Venkataramanan 
28974015d11eSBrett Creeley 	dev = ice_pf_to_dev(pf);
28984015d11eSBrett Creeley 
28997b9ffc76SAnirudh Venkataramanan 	ice_for_each_traffic_class(i) {
29007b9ffc76SAnirudh Venkataramanan 		/* build bitmap of enabled TCs */
29017b9ffc76SAnirudh Venkataramanan 		if (ena_tc & BIT(i))
29027b9ffc76SAnirudh Venkataramanan 			num_tc++;
29037b9ffc76SAnirudh Venkataramanan 		/* populate max_txqs per TC */
2904d5a46359SAkeem G Abodunrin 		max_txqs[i] = vsi->alloc_txq;
29057b9ffc76SAnirudh Venkataramanan 	}
29067b9ffc76SAnirudh Venkataramanan 
29077b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.ena_tc = ena_tc;
29087b9ffc76SAnirudh Venkataramanan 	vsi->tc_cfg.numtc = num_tc;
29097b9ffc76SAnirudh Venkataramanan 
29109efe35d0STony Nguyen 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
29117b9ffc76SAnirudh Venkataramanan 	if (!ctx)
29127b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
29137b9ffc76SAnirudh Venkataramanan 
29147b9ffc76SAnirudh Venkataramanan 	ctx->vf_num = 0;
29157b9ffc76SAnirudh Venkataramanan 	ctx->info = vsi->info;
29167b9ffc76SAnirudh Venkataramanan 
29177b9ffc76SAnirudh Venkataramanan 	ice_vsi_setup_q_map(vsi, ctx);
29187b9ffc76SAnirudh Venkataramanan 
29197b9ffc76SAnirudh Venkataramanan 	/* must to indicate which section of VSI context are being modified */
29207b9ffc76SAnirudh Venkataramanan 	ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
29217b9ffc76SAnirudh Venkataramanan 	status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL);
29227b9ffc76SAnirudh Venkataramanan 	if (status) {
29234015d11eSBrett Creeley 		dev_info(dev, "Failed VSI Update\n");
29247b9ffc76SAnirudh Venkataramanan 		ret = -EIO;
29257b9ffc76SAnirudh Venkataramanan 		goto out;
29267b9ffc76SAnirudh Venkataramanan 	}
29277b9ffc76SAnirudh Venkataramanan 
29287b9ffc76SAnirudh Venkataramanan 	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
29297b9ffc76SAnirudh Venkataramanan 				 max_txqs);
29307b9ffc76SAnirudh Venkataramanan 
29317b9ffc76SAnirudh Venkataramanan 	if (status) {
29320fee3577SLihong Yang 		dev_err(dev, "VSI %d failed TC config, error %s\n",
29330fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
29347b9ffc76SAnirudh Venkataramanan 		ret = -EIO;
29357b9ffc76SAnirudh Venkataramanan 		goto out;
29367b9ffc76SAnirudh Venkataramanan 	}
29377b9ffc76SAnirudh Venkataramanan 	ice_vsi_update_q_map(vsi, ctx);
29387b9ffc76SAnirudh Venkataramanan 	vsi->info.valid_sections = 0;
29397b9ffc76SAnirudh Venkataramanan 
29407b9ffc76SAnirudh Venkataramanan 	ice_vsi_cfg_netdev_tc(vsi, ena_tc);
29417b9ffc76SAnirudh Venkataramanan out:
29429efe35d0STony Nguyen 	kfree(ctx);
29437b9ffc76SAnirudh Venkataramanan 	return ret;
29447b9ffc76SAnirudh Venkataramanan }
29457b9ffc76SAnirudh Venkataramanan #endif /* CONFIG_DCB */
2946bbb968e8SAkeem G Abodunrin 
2947bbb968e8SAkeem G Abodunrin /**
29482d4238f5SKrzysztof Kazimierczak  * ice_update_ring_stats - Update ring statistics
29492d4238f5SKrzysztof Kazimierczak  * @ring: ring to update
29502d4238f5SKrzysztof Kazimierczak  * @cont: used to increment per-vector counters
29512d4238f5SKrzysztof Kazimierczak  * @pkts: number of processed packets
29522d4238f5SKrzysztof Kazimierczak  * @bytes: number of processed bytes
29532d4238f5SKrzysztof Kazimierczak  *
29542d4238f5SKrzysztof Kazimierczak  * This function assumes that caller has acquired a u64_stats_sync lock.
29552d4238f5SKrzysztof Kazimierczak  */
29562d4238f5SKrzysztof Kazimierczak static void
29572d4238f5SKrzysztof Kazimierczak ice_update_ring_stats(struct ice_ring *ring, struct ice_ring_container *cont,
29582d4238f5SKrzysztof Kazimierczak 		      u64 pkts, u64 bytes)
29592d4238f5SKrzysztof Kazimierczak {
29602d4238f5SKrzysztof Kazimierczak 	ring->stats.bytes += bytes;
29612d4238f5SKrzysztof Kazimierczak 	ring->stats.pkts += pkts;
29622d4238f5SKrzysztof Kazimierczak 	cont->total_bytes += bytes;
29632d4238f5SKrzysztof Kazimierczak 	cont->total_pkts += pkts;
29642d4238f5SKrzysztof Kazimierczak }
29652d4238f5SKrzysztof Kazimierczak 
29662d4238f5SKrzysztof Kazimierczak /**
29672d4238f5SKrzysztof Kazimierczak  * ice_update_tx_ring_stats - Update Tx ring specific counters
29682d4238f5SKrzysztof Kazimierczak  * @tx_ring: ring to update
29692d4238f5SKrzysztof Kazimierczak  * @pkts: number of processed packets
29702d4238f5SKrzysztof Kazimierczak  * @bytes: number of processed bytes
29712d4238f5SKrzysztof Kazimierczak  */
29722d4238f5SKrzysztof Kazimierczak void ice_update_tx_ring_stats(struct ice_ring *tx_ring, u64 pkts, u64 bytes)
29732d4238f5SKrzysztof Kazimierczak {
29742d4238f5SKrzysztof Kazimierczak 	u64_stats_update_begin(&tx_ring->syncp);
29752d4238f5SKrzysztof Kazimierczak 	ice_update_ring_stats(tx_ring, &tx_ring->q_vector->tx, pkts, bytes);
29762d4238f5SKrzysztof Kazimierczak 	u64_stats_update_end(&tx_ring->syncp);
29772d4238f5SKrzysztof Kazimierczak }
29782d4238f5SKrzysztof Kazimierczak 
29792d4238f5SKrzysztof Kazimierczak /**
29802d4238f5SKrzysztof Kazimierczak  * ice_update_rx_ring_stats - Update Rx ring specific counters
29812d4238f5SKrzysztof Kazimierczak  * @rx_ring: ring to update
29822d4238f5SKrzysztof Kazimierczak  * @pkts: number of processed packets
29832d4238f5SKrzysztof Kazimierczak  * @bytes: number of processed bytes
29842d4238f5SKrzysztof Kazimierczak  */
29852d4238f5SKrzysztof Kazimierczak void ice_update_rx_ring_stats(struct ice_ring *rx_ring, u64 pkts, u64 bytes)
29862d4238f5SKrzysztof Kazimierczak {
29872d4238f5SKrzysztof Kazimierczak 	u64_stats_update_begin(&rx_ring->syncp);
29882d4238f5SKrzysztof Kazimierczak 	ice_update_ring_stats(rx_ring, &rx_ring->q_vector->rx, pkts, bytes);
29892d4238f5SKrzysztof Kazimierczak 	u64_stats_update_end(&rx_ring->syncp);
29902d4238f5SKrzysztof Kazimierczak }
29912d4238f5SKrzysztof Kazimierczak 
29922d4238f5SKrzysztof Kazimierczak /**
2993bbb968e8SAkeem G Abodunrin  * ice_vsi_cfg_mac_fltr - Add or remove a MAC address filter for a VSI
2994bbb968e8SAkeem G Abodunrin  * @vsi: the VSI being configured MAC filter
2995bbb968e8SAkeem G Abodunrin  * @macaddr: the MAC address to be added.
2996bbb968e8SAkeem G Abodunrin  * @set: Add or delete a MAC filter
2997bbb968e8SAkeem G Abodunrin  *
2998bbb968e8SAkeem G Abodunrin  * Adds or removes MAC address filter entry for VF VSI
2999bbb968e8SAkeem G Abodunrin  */
3000bbb968e8SAkeem G Abodunrin enum ice_status
3001bbb968e8SAkeem G Abodunrin ice_vsi_cfg_mac_fltr(struct ice_vsi *vsi, const u8 *macaddr, bool set)
3002bbb968e8SAkeem G Abodunrin {
3003bbb968e8SAkeem G Abodunrin 	LIST_HEAD(tmp_add_list);
3004bbb968e8SAkeem G Abodunrin 	enum ice_status status;
3005bbb968e8SAkeem G Abodunrin 
3006bbb968e8SAkeem G Abodunrin 	 /* Update MAC filter list to be added or removed for a VSI */
3007bbb968e8SAkeem G Abodunrin 	if (ice_add_mac_to_list(vsi, &tmp_add_list, macaddr)) {
3008bbb968e8SAkeem G Abodunrin 		status = ICE_ERR_NO_MEMORY;
3009bbb968e8SAkeem G Abodunrin 		goto cfg_mac_fltr_exit;
3010bbb968e8SAkeem G Abodunrin 	}
3011bbb968e8SAkeem G Abodunrin 
3012bbb968e8SAkeem G Abodunrin 	if (set)
3013bbb968e8SAkeem G Abodunrin 		status = ice_add_mac(&vsi->back->hw, &tmp_add_list);
3014bbb968e8SAkeem G Abodunrin 	else
3015bbb968e8SAkeem G Abodunrin 		status = ice_remove_mac(&vsi->back->hw, &tmp_add_list);
3016bbb968e8SAkeem G Abodunrin 
3017bbb968e8SAkeem G Abodunrin cfg_mac_fltr_exit:
30189a946843SAnirudh Venkataramanan 	ice_free_fltr_list(ice_pf_to_dev(vsi->back), &tmp_add_list);
3019bbb968e8SAkeem G Abodunrin 	return status;
3020bbb968e8SAkeem G Abodunrin }
3021fc0f39bcSBrett Creeley 
3022fc0f39bcSBrett Creeley /**
3023fc0f39bcSBrett Creeley  * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
3024fc0f39bcSBrett Creeley  * @sw: switch to check if its default forwarding VSI is free
3025fc0f39bcSBrett Creeley  *
3026fc0f39bcSBrett Creeley  * Return true if the default forwarding VSI is already being used, else returns
3027fc0f39bcSBrett Creeley  * false signalling that it's available to use.
3028fc0f39bcSBrett Creeley  */
3029fc0f39bcSBrett Creeley bool ice_is_dflt_vsi_in_use(struct ice_sw *sw)
3030fc0f39bcSBrett Creeley {
3031fc0f39bcSBrett Creeley 	return (sw->dflt_vsi && sw->dflt_vsi_ena);
3032fc0f39bcSBrett Creeley }
3033fc0f39bcSBrett Creeley 
3034fc0f39bcSBrett Creeley /**
3035fc0f39bcSBrett Creeley  * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI
3036fc0f39bcSBrett Creeley  * @sw: switch for the default forwarding VSI to compare against
3037fc0f39bcSBrett Creeley  * @vsi: VSI to compare against default forwarding VSI
3038fc0f39bcSBrett Creeley  *
3039fc0f39bcSBrett Creeley  * If this VSI passed in is the default forwarding VSI then return true, else
3040fc0f39bcSBrett Creeley  * return false
3041fc0f39bcSBrett Creeley  */
3042fc0f39bcSBrett Creeley bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
3043fc0f39bcSBrett Creeley {
3044fc0f39bcSBrett Creeley 	return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena);
3045fc0f39bcSBrett Creeley }
3046fc0f39bcSBrett Creeley 
3047fc0f39bcSBrett Creeley /**
3048fc0f39bcSBrett Creeley  * ice_set_dflt_vsi - set the default forwarding VSI
3049fc0f39bcSBrett Creeley  * @sw: switch used to assign the default forwarding VSI
3050fc0f39bcSBrett Creeley  * @vsi: VSI getting set as the default forwarding VSI on the switch
3051fc0f39bcSBrett Creeley  *
3052fc0f39bcSBrett Creeley  * If the VSI passed in is already the default VSI and it's enabled just return
3053fc0f39bcSBrett Creeley  * success.
3054fc0f39bcSBrett Creeley  *
3055fc0f39bcSBrett Creeley  * If there is already a default VSI on the switch and it's enabled then return
3056fc0f39bcSBrett Creeley  * -EEXIST since there can only be one default VSI per switch.
3057fc0f39bcSBrett Creeley  *
3058fc0f39bcSBrett Creeley  *  Otherwise try to set the VSI passed in as the switch's default VSI and
3059fc0f39bcSBrett Creeley  *  return the result.
3060fc0f39bcSBrett Creeley  */
3061fc0f39bcSBrett Creeley int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
3062fc0f39bcSBrett Creeley {
3063fc0f39bcSBrett Creeley 	enum ice_status status;
3064fc0f39bcSBrett Creeley 	struct device *dev;
3065fc0f39bcSBrett Creeley 
3066fc0f39bcSBrett Creeley 	if (!sw || !vsi)
3067fc0f39bcSBrett Creeley 		return -EINVAL;
3068fc0f39bcSBrett Creeley 
3069fc0f39bcSBrett Creeley 	dev = ice_pf_to_dev(vsi->back);
3070fc0f39bcSBrett Creeley 
3071fc0f39bcSBrett Creeley 	/* the VSI passed in is already the default VSI */
3072fc0f39bcSBrett Creeley 	if (ice_is_vsi_dflt_vsi(sw, vsi)) {
3073fc0f39bcSBrett Creeley 		dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
3074fc0f39bcSBrett Creeley 			vsi->vsi_num);
3075fc0f39bcSBrett Creeley 		return 0;
3076fc0f39bcSBrett Creeley 	}
3077fc0f39bcSBrett Creeley 
3078fc0f39bcSBrett Creeley 	/* another VSI is already the default VSI for this switch */
3079fc0f39bcSBrett Creeley 	if (ice_is_dflt_vsi_in_use(sw)) {
308019cce2c6SAnirudh Venkataramanan 		dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n",
3081fc0f39bcSBrett Creeley 			sw->dflt_vsi->vsi_num);
3082fc0f39bcSBrett Creeley 		return -EEXIST;
3083fc0f39bcSBrett Creeley 	}
3084fc0f39bcSBrett Creeley 
3085fc0f39bcSBrett Creeley 	status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX);
3086fc0f39bcSBrett Creeley 	if (status) {
30870fee3577SLihong Yang 		dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %s\n",
30880fee3577SLihong Yang 			vsi->vsi_num, ice_stat_str(status));
3089fc0f39bcSBrett Creeley 		return -EIO;
3090fc0f39bcSBrett Creeley 	}
3091fc0f39bcSBrett Creeley 
3092fc0f39bcSBrett Creeley 	sw->dflt_vsi = vsi;
3093fc0f39bcSBrett Creeley 	sw->dflt_vsi_ena = true;
3094fc0f39bcSBrett Creeley 
3095fc0f39bcSBrett Creeley 	return 0;
3096fc0f39bcSBrett Creeley }
3097fc0f39bcSBrett Creeley 
3098fc0f39bcSBrett Creeley /**
3099fc0f39bcSBrett Creeley  * ice_clear_dflt_vsi - clear the default forwarding VSI
3100fc0f39bcSBrett Creeley  * @sw: switch used to clear the default VSI
3101fc0f39bcSBrett Creeley  *
3102fc0f39bcSBrett Creeley  * If the switch has no default VSI or it's not enabled then return error.
3103fc0f39bcSBrett Creeley  *
3104fc0f39bcSBrett Creeley  * Otherwise try to clear the default VSI and return the result.
3105fc0f39bcSBrett Creeley  */
3106fc0f39bcSBrett Creeley int ice_clear_dflt_vsi(struct ice_sw *sw)
3107fc0f39bcSBrett Creeley {
3108fc0f39bcSBrett Creeley 	struct ice_vsi *dflt_vsi;
3109fc0f39bcSBrett Creeley 	enum ice_status status;
3110fc0f39bcSBrett Creeley 	struct device *dev;
3111fc0f39bcSBrett Creeley 
3112fc0f39bcSBrett Creeley 	if (!sw)
3113fc0f39bcSBrett Creeley 		return -EINVAL;
3114fc0f39bcSBrett Creeley 
3115fc0f39bcSBrett Creeley 	dev = ice_pf_to_dev(sw->pf);
3116fc0f39bcSBrett Creeley 
3117fc0f39bcSBrett Creeley 	dflt_vsi = sw->dflt_vsi;
3118fc0f39bcSBrett Creeley 
3119fc0f39bcSBrett Creeley 	/* there is no default VSI configured */
3120fc0f39bcSBrett Creeley 	if (!ice_is_dflt_vsi_in_use(sw))
3121fc0f39bcSBrett Creeley 		return -ENODEV;
3122fc0f39bcSBrett Creeley 
3123fc0f39bcSBrett Creeley 	status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false,
3124fc0f39bcSBrett Creeley 				  ICE_FLTR_RX);
3125fc0f39bcSBrett Creeley 	if (status) {
31260fee3577SLihong Yang 		dev_err(dev, "Failed to clear the default forwarding VSI %d, error %s\n",
31270fee3577SLihong Yang 			dflt_vsi->vsi_num, ice_stat_str(status));
3128fc0f39bcSBrett Creeley 		return -EIO;
3129fc0f39bcSBrett Creeley 	}
3130fc0f39bcSBrett Creeley 
3131fc0f39bcSBrett Creeley 	sw->dflt_vsi = NULL;
3132fc0f39bcSBrett Creeley 	sw->dflt_vsi_ena = false;
3133fc0f39bcSBrett Creeley 
3134fc0f39bcSBrett Creeley 	return 0;
3135fc0f39bcSBrett Creeley }
3136