162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright (c) 2018, Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "ice.h"
562306a36Sopenharmony_ci#include "ice_base.h"
662306a36Sopenharmony_ci#include "ice_flow.h"
762306a36Sopenharmony_ci#include "ice_lib.h"
862306a36Sopenharmony_ci#include "ice_fltr.h"
962306a36Sopenharmony_ci#include "ice_dcb_lib.h"
1062306a36Sopenharmony_ci#include "ice_devlink.h"
1162306a36Sopenharmony_ci#include "ice_vsi_vlan_ops.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/**
1462306a36Sopenharmony_ci * ice_vsi_type_str - maps VSI type enum to string equivalents
1562306a36Sopenharmony_ci * @vsi_type: VSI type enum
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ciconst char *ice_vsi_type_str(enum ice_vsi_type vsi_type)
1862306a36Sopenharmony_ci{
1962306a36Sopenharmony_ci	switch (vsi_type) {
2062306a36Sopenharmony_ci	case ICE_VSI_PF:
2162306a36Sopenharmony_ci		return "ICE_VSI_PF";
2262306a36Sopenharmony_ci	case ICE_VSI_VF:
2362306a36Sopenharmony_ci		return "ICE_VSI_VF";
2462306a36Sopenharmony_ci	case ICE_VSI_CTRL:
2562306a36Sopenharmony_ci		return "ICE_VSI_CTRL";
2662306a36Sopenharmony_ci	case ICE_VSI_CHNL:
2762306a36Sopenharmony_ci		return "ICE_VSI_CHNL";
2862306a36Sopenharmony_ci	case ICE_VSI_LB:
2962306a36Sopenharmony_ci		return "ICE_VSI_LB";
3062306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
3162306a36Sopenharmony_ci		return "ICE_VSI_SWITCHDEV_CTRL";
3262306a36Sopenharmony_ci	default:
3362306a36Sopenharmony_ci		return "unknown";
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/**
3862306a36Sopenharmony_ci * ice_vsi_ctrl_all_rx_rings - Start or stop a VSI's Rx rings
3962306a36Sopenharmony_ci * @vsi: the VSI being configured
4062306a36Sopenharmony_ci * @ena: start or stop the Rx rings
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * First enable/disable all of the Rx rings, flush any remaining writes, and
4362306a36Sopenharmony_ci * then verify that they have all been enabled/disabled successfully. This will
4462306a36Sopenharmony_ci * let all of the register writes complete when enabling/disabling the Rx rings
4562306a36Sopenharmony_ci * before waiting for the change in hardware to complete.
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_cistatic int ice_vsi_ctrl_all_rx_rings(struct ice_vsi *vsi, bool ena)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	int ret = 0;
5062306a36Sopenharmony_ci	u16 i;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i)
5362306a36Sopenharmony_ci		ice_vsi_ctrl_one_rx_ring(vsi, ena, i, false);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	ice_flush(&vsi->back->hw);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i) {
5862306a36Sopenharmony_ci		ret = ice_vsi_wait_one_rx_ring(vsi, ena, i);
5962306a36Sopenharmony_ci		if (ret)
6062306a36Sopenharmony_ci			break;
6162306a36Sopenharmony_ci	}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	return ret;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/**
6762306a36Sopenharmony_ci * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI
6862306a36Sopenharmony_ci * @vsi: VSI pointer
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci * On error: returns error code (negative)
7162306a36Sopenharmony_ci * On success: returns 0
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistatic int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
7662306a36Sopenharmony_ci	struct device *dev;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
7962306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL)
8062306a36Sopenharmony_ci		return 0;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/* allocate memory for both Tx and Rx ring pointers */
8362306a36Sopenharmony_ci	vsi->tx_rings = devm_kcalloc(dev, vsi->alloc_txq,
8462306a36Sopenharmony_ci				     sizeof(*vsi->tx_rings), GFP_KERNEL);
8562306a36Sopenharmony_ci	if (!vsi->tx_rings)
8662306a36Sopenharmony_ci		return -ENOMEM;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	vsi->rx_rings = devm_kcalloc(dev, vsi->alloc_rxq,
8962306a36Sopenharmony_ci				     sizeof(*vsi->rx_rings), GFP_KERNEL);
9062306a36Sopenharmony_ci	if (!vsi->rx_rings)
9162306a36Sopenharmony_ci		goto err_rings;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	/* txq_map needs to have enough space to track both Tx (stack) rings
9462306a36Sopenharmony_ci	 * and XDP rings; at this point vsi->num_xdp_txq might not be set,
9562306a36Sopenharmony_ci	 * so use num_possible_cpus() as we want to always provide XDP ring
9662306a36Sopenharmony_ci	 * per CPU, regardless of queue count settings from user that might
9762306a36Sopenharmony_ci	 * have come from ethtool's set_channels() callback;
9862306a36Sopenharmony_ci	 */
9962306a36Sopenharmony_ci	vsi->txq_map = devm_kcalloc(dev, (vsi->alloc_txq + num_possible_cpus()),
10062306a36Sopenharmony_ci				    sizeof(*vsi->txq_map), GFP_KERNEL);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	if (!vsi->txq_map)
10362306a36Sopenharmony_ci		goto err_txq_map;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	vsi->rxq_map = devm_kcalloc(dev, vsi->alloc_rxq,
10662306a36Sopenharmony_ci				    sizeof(*vsi->rxq_map), GFP_KERNEL);
10762306a36Sopenharmony_ci	if (!vsi->rxq_map)
10862306a36Sopenharmony_ci		goto err_rxq_map;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/* There is no need to allocate q_vectors for a loopback VSI. */
11162306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_LB)
11262306a36Sopenharmony_ci		return 0;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	/* allocate memory for q_vector pointers */
11562306a36Sopenharmony_ci	vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors,
11662306a36Sopenharmony_ci				      sizeof(*vsi->q_vectors), GFP_KERNEL);
11762306a36Sopenharmony_ci	if (!vsi->q_vectors)
11862306a36Sopenharmony_ci		goto err_vectors;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	vsi->af_xdp_zc_qps = bitmap_zalloc(max_t(int, vsi->alloc_txq, vsi->alloc_rxq), GFP_KERNEL);
12162306a36Sopenharmony_ci	if (!vsi->af_xdp_zc_qps)
12262306a36Sopenharmony_ci		goto err_zc_qps;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return 0;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cierr_zc_qps:
12762306a36Sopenharmony_ci	devm_kfree(dev, vsi->q_vectors);
12862306a36Sopenharmony_cierr_vectors:
12962306a36Sopenharmony_ci	devm_kfree(dev, vsi->rxq_map);
13062306a36Sopenharmony_cierr_rxq_map:
13162306a36Sopenharmony_ci	devm_kfree(dev, vsi->txq_map);
13262306a36Sopenharmony_cierr_txq_map:
13362306a36Sopenharmony_ci	devm_kfree(dev, vsi->rx_rings);
13462306a36Sopenharmony_cierr_rings:
13562306a36Sopenharmony_ci	devm_kfree(dev, vsi->tx_rings);
13662306a36Sopenharmony_ci	return -ENOMEM;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/**
14062306a36Sopenharmony_ci * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI
14162306a36Sopenharmony_ci * @vsi: the VSI being configured
14262306a36Sopenharmony_ci */
14362306a36Sopenharmony_cistatic void ice_vsi_set_num_desc(struct ice_vsi *vsi)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	switch (vsi->type) {
14662306a36Sopenharmony_ci	case ICE_VSI_PF:
14762306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
14862306a36Sopenharmony_ci	case ICE_VSI_CTRL:
14962306a36Sopenharmony_ci	case ICE_VSI_LB:
15062306a36Sopenharmony_ci		/* a user could change the values of num_[tr]x_desc using
15162306a36Sopenharmony_ci		 * ethtool -G so we should keep those values instead of
15262306a36Sopenharmony_ci		 * overwriting them with the defaults.
15362306a36Sopenharmony_ci		 */
15462306a36Sopenharmony_ci		if (!vsi->num_rx_desc)
15562306a36Sopenharmony_ci			vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC;
15662306a36Sopenharmony_ci		if (!vsi->num_tx_desc)
15762306a36Sopenharmony_ci			vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC;
15862306a36Sopenharmony_ci		break;
15962306a36Sopenharmony_ci	default:
16062306a36Sopenharmony_ci		dev_dbg(ice_pf_to_dev(vsi->back), "Not setting number of Tx/Rx descriptors for VSI type %d\n",
16162306a36Sopenharmony_ci			vsi->type);
16262306a36Sopenharmony_ci		break;
16362306a36Sopenharmony_ci	}
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci/**
16762306a36Sopenharmony_ci * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI
16862306a36Sopenharmony_ci * @vsi: the VSI being configured
16962306a36Sopenharmony_ci *
17062306a36Sopenharmony_ci * Return 0 on success and a negative value on error
17162306a36Sopenharmony_ci */
17262306a36Sopenharmony_cistatic void ice_vsi_set_num_qs(struct ice_vsi *vsi)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	enum ice_vsi_type vsi_type = vsi->type;
17562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
17662306a36Sopenharmony_ci	struct ice_vf *vf = vsi->vf;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	if (WARN_ON(vsi_type == ICE_VSI_VF && !vf))
17962306a36Sopenharmony_ci		return;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	switch (vsi_type) {
18262306a36Sopenharmony_ci	case ICE_VSI_PF:
18362306a36Sopenharmony_ci		if (vsi->req_txq) {
18462306a36Sopenharmony_ci			vsi->alloc_txq = vsi->req_txq;
18562306a36Sopenharmony_ci			vsi->num_txq = vsi->req_txq;
18662306a36Sopenharmony_ci		} else {
18762306a36Sopenharmony_ci			vsi->alloc_txq = min3(pf->num_lan_msix,
18862306a36Sopenharmony_ci					      ice_get_avail_txq_count(pf),
18962306a36Sopenharmony_ci					      (u16)num_online_cpus());
19062306a36Sopenharmony_ci		}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci		pf->num_lan_tx = vsi->alloc_txq;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci		/* only 1 Rx queue unless RSS is enabled */
19562306a36Sopenharmony_ci		if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
19662306a36Sopenharmony_ci			vsi->alloc_rxq = 1;
19762306a36Sopenharmony_ci		} else {
19862306a36Sopenharmony_ci			if (vsi->req_rxq) {
19962306a36Sopenharmony_ci				vsi->alloc_rxq = vsi->req_rxq;
20062306a36Sopenharmony_ci				vsi->num_rxq = vsi->req_rxq;
20162306a36Sopenharmony_ci			} else {
20262306a36Sopenharmony_ci				vsi->alloc_rxq = min3(pf->num_lan_msix,
20362306a36Sopenharmony_ci						      ice_get_avail_rxq_count(pf),
20462306a36Sopenharmony_ci						      (u16)num_online_cpus());
20562306a36Sopenharmony_ci			}
20662306a36Sopenharmony_ci		}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci		pf->num_lan_rx = vsi->alloc_rxq;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci		vsi->num_q_vectors = min_t(int, pf->num_lan_msix,
21162306a36Sopenharmony_ci					   max_t(int, vsi->alloc_rxq,
21262306a36Sopenharmony_ci						 vsi->alloc_txq));
21362306a36Sopenharmony_ci		break;
21462306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
21562306a36Sopenharmony_ci		/* The number of queues for ctrl VSI is equal to number of VFs.
21662306a36Sopenharmony_ci		 * Each ring is associated to the corresponding VF_PR netdev.
21762306a36Sopenharmony_ci		 */
21862306a36Sopenharmony_ci		vsi->alloc_txq = ice_get_num_vfs(pf);
21962306a36Sopenharmony_ci		vsi->alloc_rxq = vsi->alloc_txq;
22062306a36Sopenharmony_ci		vsi->num_q_vectors = 1;
22162306a36Sopenharmony_ci		break;
22262306a36Sopenharmony_ci	case ICE_VSI_VF:
22362306a36Sopenharmony_ci		if (vf->num_req_qs)
22462306a36Sopenharmony_ci			vf->num_vf_qs = vf->num_req_qs;
22562306a36Sopenharmony_ci		vsi->alloc_txq = vf->num_vf_qs;
22662306a36Sopenharmony_ci		vsi->alloc_rxq = vf->num_vf_qs;
22762306a36Sopenharmony_ci		/* pf->vfs.num_msix_per includes (VF miscellaneous vector +
22862306a36Sopenharmony_ci		 * data queue interrupts). Since vsi->num_q_vectors is number
22962306a36Sopenharmony_ci		 * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the
23062306a36Sopenharmony_ci		 * original vector count
23162306a36Sopenharmony_ci		 */
23262306a36Sopenharmony_ci		vsi->num_q_vectors = pf->vfs.num_msix_per - ICE_NONQ_VECS_VF;
23362306a36Sopenharmony_ci		break;
23462306a36Sopenharmony_ci	case ICE_VSI_CTRL:
23562306a36Sopenharmony_ci		vsi->alloc_txq = 1;
23662306a36Sopenharmony_ci		vsi->alloc_rxq = 1;
23762306a36Sopenharmony_ci		vsi->num_q_vectors = 1;
23862306a36Sopenharmony_ci		break;
23962306a36Sopenharmony_ci	case ICE_VSI_CHNL:
24062306a36Sopenharmony_ci		vsi->alloc_txq = 0;
24162306a36Sopenharmony_ci		vsi->alloc_rxq = 0;
24262306a36Sopenharmony_ci		break;
24362306a36Sopenharmony_ci	case ICE_VSI_LB:
24462306a36Sopenharmony_ci		vsi->alloc_txq = 1;
24562306a36Sopenharmony_ci		vsi->alloc_rxq = 1;
24662306a36Sopenharmony_ci		break;
24762306a36Sopenharmony_ci	default:
24862306a36Sopenharmony_ci		dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi_type);
24962306a36Sopenharmony_ci		break;
25062306a36Sopenharmony_ci	}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	ice_vsi_set_num_desc(vsi);
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/**
25662306a36Sopenharmony_ci * ice_get_free_slot - get the next non-NULL location index in array
25762306a36Sopenharmony_ci * @array: array to search
25862306a36Sopenharmony_ci * @size: size of the array
25962306a36Sopenharmony_ci * @curr: last known occupied index to be used as a search hint
26062306a36Sopenharmony_ci *
26162306a36Sopenharmony_ci * void * is being used to keep the functionality generic. This lets us use this
26262306a36Sopenharmony_ci * function on any array of pointers.
26362306a36Sopenharmony_ci */
26462306a36Sopenharmony_cistatic int ice_get_free_slot(void *array, int size, int curr)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	int **tmp_array = (int **)array;
26762306a36Sopenharmony_ci	int next;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	if (curr < (size - 1) && !tmp_array[curr + 1]) {
27062306a36Sopenharmony_ci		next = curr + 1;
27162306a36Sopenharmony_ci	} else {
27262306a36Sopenharmony_ci		int i = 0;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci		while ((i < size) && (tmp_array[i]))
27562306a36Sopenharmony_ci			i++;
27662306a36Sopenharmony_ci		if (i == size)
27762306a36Sopenharmony_ci			next = ICE_NO_VSI;
27862306a36Sopenharmony_ci		else
27962306a36Sopenharmony_ci			next = i;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci	return next;
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci/**
28562306a36Sopenharmony_ci * ice_vsi_delete_from_hw - delete a VSI from the switch
28662306a36Sopenharmony_ci * @vsi: pointer to VSI being removed
28762306a36Sopenharmony_ci */
28862306a36Sopenharmony_cistatic void ice_vsi_delete_from_hw(struct ice_vsi *vsi)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
29162306a36Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
29262306a36Sopenharmony_ci	int status;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	ice_fltr_remove_all(vsi);
29562306a36Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
29662306a36Sopenharmony_ci	if (!ctxt)
29762306a36Sopenharmony_ci		return;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
30062306a36Sopenharmony_ci		ctxt->vf_num = vsi->vf->vf_id;
30162306a36Sopenharmony_ci	ctxt->vsi_num = vsi->vsi_num;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info));
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL);
30662306a36Sopenharmony_ci	if (status)
30762306a36Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Failed to delete VSI %i in FW - error: %d\n",
30862306a36Sopenharmony_ci			vsi->vsi_num, status);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	kfree(ctxt);
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci/**
31462306a36Sopenharmony_ci * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI
31562306a36Sopenharmony_ci * @vsi: pointer to VSI being cleared
31662306a36Sopenharmony_ci */
31762306a36Sopenharmony_cistatic void ice_vsi_free_arrays(struct ice_vsi *vsi)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
32062306a36Sopenharmony_ci	struct device *dev;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	bitmap_free(vsi->af_xdp_zc_qps);
32562306a36Sopenharmony_ci	vsi->af_xdp_zc_qps = NULL;
32662306a36Sopenharmony_ci	/* free the ring and vector containers */
32762306a36Sopenharmony_ci	devm_kfree(dev, vsi->q_vectors);
32862306a36Sopenharmony_ci	vsi->q_vectors = NULL;
32962306a36Sopenharmony_ci	devm_kfree(dev, vsi->tx_rings);
33062306a36Sopenharmony_ci	vsi->tx_rings = NULL;
33162306a36Sopenharmony_ci	devm_kfree(dev, vsi->rx_rings);
33262306a36Sopenharmony_ci	vsi->rx_rings = NULL;
33362306a36Sopenharmony_ci	devm_kfree(dev, vsi->txq_map);
33462306a36Sopenharmony_ci	vsi->txq_map = NULL;
33562306a36Sopenharmony_ci	devm_kfree(dev, vsi->rxq_map);
33662306a36Sopenharmony_ci	vsi->rxq_map = NULL;
33762306a36Sopenharmony_ci}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci/**
34062306a36Sopenharmony_ci * ice_vsi_free_stats - Free the ring statistics structures
34162306a36Sopenharmony_ci * @vsi: VSI pointer
34262306a36Sopenharmony_ci */
34362306a36Sopenharmony_cistatic void ice_vsi_free_stats(struct ice_vsi *vsi)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct ice_vsi_stats *vsi_stat;
34662306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
34762306a36Sopenharmony_ci	int i;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL)
35062306a36Sopenharmony_ci		return;
35162306a36Sopenharmony_ci	if (!pf->vsi_stats)
35262306a36Sopenharmony_ci		return;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	vsi_stat = pf->vsi_stats[vsi->idx];
35562306a36Sopenharmony_ci	if (!vsi_stat)
35662306a36Sopenharmony_ci		return;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	ice_for_each_alloc_txq(vsi, i) {
35962306a36Sopenharmony_ci		if (vsi_stat->tx_ring_stats[i]) {
36062306a36Sopenharmony_ci			kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
36162306a36Sopenharmony_ci			WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
36262306a36Sopenharmony_ci		}
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	ice_for_each_alloc_rxq(vsi, i) {
36662306a36Sopenharmony_ci		if (vsi_stat->rx_ring_stats[i]) {
36762306a36Sopenharmony_ci			kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
36862306a36Sopenharmony_ci			WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
36962306a36Sopenharmony_ci		}
37062306a36Sopenharmony_ci	}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	kfree(vsi_stat->tx_ring_stats);
37362306a36Sopenharmony_ci	kfree(vsi_stat->rx_ring_stats);
37462306a36Sopenharmony_ci	kfree(vsi_stat);
37562306a36Sopenharmony_ci	pf->vsi_stats[vsi->idx] = NULL;
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci/**
37962306a36Sopenharmony_ci * ice_vsi_alloc_ring_stats - Allocates Tx and Rx ring stats for the VSI
38062306a36Sopenharmony_ci * @vsi: VSI which is having stats allocated
38162306a36Sopenharmony_ci */
38262306a36Sopenharmony_cistatic int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	struct ice_ring_stats **tx_ring_stats;
38562306a36Sopenharmony_ci	struct ice_ring_stats **rx_ring_stats;
38662306a36Sopenharmony_ci	struct ice_vsi_stats *vsi_stats;
38762306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
38862306a36Sopenharmony_ci	u16 i;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	vsi_stats = pf->vsi_stats[vsi->idx];
39162306a36Sopenharmony_ci	tx_ring_stats = vsi_stats->tx_ring_stats;
39262306a36Sopenharmony_ci	rx_ring_stats = vsi_stats->rx_ring_stats;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/* Allocate Tx ring stats */
39562306a36Sopenharmony_ci	ice_for_each_alloc_txq(vsi, i) {
39662306a36Sopenharmony_ci		struct ice_ring_stats *ring_stats;
39762306a36Sopenharmony_ci		struct ice_tx_ring *ring;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci		ring = vsi->tx_rings[i];
40062306a36Sopenharmony_ci		ring_stats = tx_ring_stats[i];
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci		if (!ring_stats) {
40362306a36Sopenharmony_ci			ring_stats = kzalloc(sizeof(*ring_stats), GFP_KERNEL);
40462306a36Sopenharmony_ci			if (!ring_stats)
40562306a36Sopenharmony_ci				goto err_out;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci			WRITE_ONCE(tx_ring_stats[i], ring_stats);
40862306a36Sopenharmony_ci		}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci		ring->ring_stats = ring_stats;
41162306a36Sopenharmony_ci	}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	/* Allocate Rx ring stats */
41462306a36Sopenharmony_ci	ice_for_each_alloc_rxq(vsi, i) {
41562306a36Sopenharmony_ci		struct ice_ring_stats *ring_stats;
41662306a36Sopenharmony_ci		struct ice_rx_ring *ring;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		ring = vsi->rx_rings[i];
41962306a36Sopenharmony_ci		ring_stats = rx_ring_stats[i];
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci		if (!ring_stats) {
42262306a36Sopenharmony_ci			ring_stats = kzalloc(sizeof(*ring_stats), GFP_KERNEL);
42362306a36Sopenharmony_ci			if (!ring_stats)
42462306a36Sopenharmony_ci				goto err_out;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci			WRITE_ONCE(rx_ring_stats[i], ring_stats);
42762306a36Sopenharmony_ci		}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci		ring->ring_stats = ring_stats;
43062306a36Sopenharmony_ci	}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	return 0;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cierr_out:
43562306a36Sopenharmony_ci	ice_vsi_free_stats(vsi);
43662306a36Sopenharmony_ci	return -ENOMEM;
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci/**
44062306a36Sopenharmony_ci * ice_vsi_free - clean up and deallocate the provided VSI
44162306a36Sopenharmony_ci * @vsi: pointer to VSI being cleared
44262306a36Sopenharmony_ci *
44362306a36Sopenharmony_ci * This deallocates the VSI's queue resources, removes it from the PF's
44462306a36Sopenharmony_ci * VSI array if necessary, and deallocates the VSI
44562306a36Sopenharmony_ci */
44662306a36Sopenharmony_cistatic void ice_vsi_free(struct ice_vsi *vsi)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	struct ice_pf *pf = NULL;
44962306a36Sopenharmony_ci	struct device *dev;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	if (!vsi || !vsi->back)
45262306a36Sopenharmony_ci		return;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	pf = vsi->back;
45562306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) {
45862306a36Sopenharmony_ci		dev_dbg(dev, "vsi does not exist at pf->vsi[%d]\n", vsi->idx);
45962306a36Sopenharmony_ci		return;
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	mutex_lock(&pf->sw_mutex);
46362306a36Sopenharmony_ci	/* updates the PF for this cleared VSI */
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	pf->vsi[vsi->idx] = NULL;
46662306a36Sopenharmony_ci	pf->next_vsi = vsi->idx;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	ice_vsi_free_stats(vsi);
46962306a36Sopenharmony_ci	ice_vsi_free_arrays(vsi);
47062306a36Sopenharmony_ci	mutex_unlock(&pf->sw_mutex);
47162306a36Sopenharmony_ci	devm_kfree(dev, vsi);
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_civoid ice_vsi_delete(struct ice_vsi *vsi)
47562306a36Sopenharmony_ci{
47662306a36Sopenharmony_ci	ice_vsi_delete_from_hw(vsi);
47762306a36Sopenharmony_ci	ice_vsi_free(vsi);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci/**
48162306a36Sopenharmony_ci * ice_msix_clean_ctrl_vsi - MSIX mode interrupt handler for ctrl VSI
48262306a36Sopenharmony_ci * @irq: interrupt number
48362306a36Sopenharmony_ci * @data: pointer to a q_vector
48462306a36Sopenharmony_ci */
48562306a36Sopenharmony_cistatic irqreturn_t ice_msix_clean_ctrl_vsi(int __always_unused irq, void *data)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	if (!q_vector->tx.tx_ring)
49062306a36Sopenharmony_ci		return IRQ_HANDLED;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci#define FDIR_RX_DESC_CLEAN_BUDGET 64
49362306a36Sopenharmony_ci	ice_clean_rx_irq(q_vector->rx.rx_ring, FDIR_RX_DESC_CLEAN_BUDGET);
49462306a36Sopenharmony_ci	ice_clean_ctrl_tx_irq(q_vector->tx.tx_ring);
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	return IRQ_HANDLED;
49762306a36Sopenharmony_ci}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci/**
50062306a36Sopenharmony_ci * ice_msix_clean_rings - MSIX mode Interrupt Handler
50162306a36Sopenharmony_ci * @irq: interrupt number
50262306a36Sopenharmony_ci * @data: pointer to a q_vector
50362306a36Sopenharmony_ci */
50462306a36Sopenharmony_cistatic irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
50562306a36Sopenharmony_ci{
50662306a36Sopenharmony_ci	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (!q_vector->tx.tx_ring && !q_vector->rx.rx_ring)
50962306a36Sopenharmony_ci		return IRQ_HANDLED;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	q_vector->total_events++;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	napi_schedule(&q_vector->napi);
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	return IRQ_HANDLED;
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *data)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
52162306a36Sopenharmony_ci	struct ice_pf *pf = q_vector->vsi->back;
52262306a36Sopenharmony_ci	struct ice_vf *vf;
52362306a36Sopenharmony_ci	unsigned int bkt;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	if (!q_vector->tx.tx_ring && !q_vector->rx.rx_ring)
52662306a36Sopenharmony_ci		return IRQ_HANDLED;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	rcu_read_lock();
52962306a36Sopenharmony_ci	ice_for_each_vf_rcu(pf, bkt, vf)
53062306a36Sopenharmony_ci		napi_schedule(&vf->repr->q_vector->napi);
53162306a36Sopenharmony_ci	rcu_read_unlock();
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	return IRQ_HANDLED;
53462306a36Sopenharmony_ci}
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci/**
53762306a36Sopenharmony_ci * ice_vsi_alloc_stat_arrays - Allocate statistics arrays
53862306a36Sopenharmony_ci * @vsi: VSI pointer
53962306a36Sopenharmony_ci */
54062306a36Sopenharmony_cistatic int ice_vsi_alloc_stat_arrays(struct ice_vsi *vsi)
54162306a36Sopenharmony_ci{
54262306a36Sopenharmony_ci	struct ice_vsi_stats *vsi_stat;
54362306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL)
54662306a36Sopenharmony_ci		return 0;
54762306a36Sopenharmony_ci	if (!pf->vsi_stats)
54862306a36Sopenharmony_ci		return -ENOENT;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	if (pf->vsi_stats[vsi->idx])
55162306a36Sopenharmony_ci	/* realloc will happen in rebuild path */
55262306a36Sopenharmony_ci		return 0;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	vsi_stat = kzalloc(sizeof(*vsi_stat), GFP_KERNEL);
55562306a36Sopenharmony_ci	if (!vsi_stat)
55662306a36Sopenharmony_ci		return -ENOMEM;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	vsi_stat->tx_ring_stats =
55962306a36Sopenharmony_ci		kcalloc(vsi->alloc_txq, sizeof(*vsi_stat->tx_ring_stats),
56062306a36Sopenharmony_ci			GFP_KERNEL);
56162306a36Sopenharmony_ci	if (!vsi_stat->tx_ring_stats)
56262306a36Sopenharmony_ci		goto err_alloc_tx;
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	vsi_stat->rx_ring_stats =
56562306a36Sopenharmony_ci		kcalloc(vsi->alloc_rxq, sizeof(*vsi_stat->rx_ring_stats),
56662306a36Sopenharmony_ci			GFP_KERNEL);
56762306a36Sopenharmony_ci	if (!vsi_stat->rx_ring_stats)
56862306a36Sopenharmony_ci		goto err_alloc_rx;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	pf->vsi_stats[vsi->idx] = vsi_stat;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	return 0;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_cierr_alloc_rx:
57562306a36Sopenharmony_ci	kfree(vsi_stat->rx_ring_stats);
57662306a36Sopenharmony_cierr_alloc_tx:
57762306a36Sopenharmony_ci	kfree(vsi_stat->tx_ring_stats);
57862306a36Sopenharmony_ci	kfree(vsi_stat);
57962306a36Sopenharmony_ci	pf->vsi_stats[vsi->idx] = NULL;
58062306a36Sopenharmony_ci	return -ENOMEM;
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci/**
58462306a36Sopenharmony_ci * ice_vsi_alloc_def - set default values for already allocated VSI
58562306a36Sopenharmony_ci * @vsi: ptr to VSI
58662306a36Sopenharmony_ci * @ch: ptr to channel
58762306a36Sopenharmony_ci */
58862306a36Sopenharmony_cistatic int
58962306a36Sopenharmony_ciice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	if (vsi->type != ICE_VSI_CHNL) {
59262306a36Sopenharmony_ci		ice_vsi_set_num_qs(vsi);
59362306a36Sopenharmony_ci		if (ice_vsi_alloc_arrays(vsi))
59462306a36Sopenharmony_ci			return -ENOMEM;
59562306a36Sopenharmony_ci	}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	switch (vsi->type) {
59862306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
59962306a36Sopenharmony_ci		/* Setup eswitch MSIX irq handler for VSI */
60062306a36Sopenharmony_ci		vsi->irq_handler = ice_eswitch_msix_clean_rings;
60162306a36Sopenharmony_ci		break;
60262306a36Sopenharmony_ci	case ICE_VSI_PF:
60362306a36Sopenharmony_ci		/* Setup default MSIX irq handler for VSI */
60462306a36Sopenharmony_ci		vsi->irq_handler = ice_msix_clean_rings;
60562306a36Sopenharmony_ci		break;
60662306a36Sopenharmony_ci	case ICE_VSI_CTRL:
60762306a36Sopenharmony_ci		/* Setup ctrl VSI MSIX irq handler */
60862306a36Sopenharmony_ci		vsi->irq_handler = ice_msix_clean_ctrl_vsi;
60962306a36Sopenharmony_ci		break;
61062306a36Sopenharmony_ci	case ICE_VSI_CHNL:
61162306a36Sopenharmony_ci		if (!ch)
61262306a36Sopenharmony_ci			return -EINVAL;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci		vsi->num_rxq = ch->num_rxq;
61562306a36Sopenharmony_ci		vsi->num_txq = ch->num_txq;
61662306a36Sopenharmony_ci		vsi->next_base_q = ch->base_q;
61762306a36Sopenharmony_ci		break;
61862306a36Sopenharmony_ci	case ICE_VSI_VF:
61962306a36Sopenharmony_ci	case ICE_VSI_LB:
62062306a36Sopenharmony_ci		break;
62162306a36Sopenharmony_ci	default:
62262306a36Sopenharmony_ci		ice_vsi_free_arrays(vsi);
62362306a36Sopenharmony_ci		return -EINVAL;
62462306a36Sopenharmony_ci	}
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	return 0;
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci/**
63062306a36Sopenharmony_ci * ice_vsi_alloc - Allocates the next available struct VSI in the PF
63162306a36Sopenharmony_ci * @pf: board private structure
63262306a36Sopenharmony_ci *
63362306a36Sopenharmony_ci * Reserves a VSI index from the PF and allocates an empty VSI structure
63462306a36Sopenharmony_ci * without a type. The VSI structure must later be initialized by calling
63562306a36Sopenharmony_ci * ice_vsi_cfg().
63662306a36Sopenharmony_ci *
63762306a36Sopenharmony_ci * returns a pointer to a VSI on success, NULL on failure.
63862306a36Sopenharmony_ci */
63962306a36Sopenharmony_cistatic struct ice_vsi *ice_vsi_alloc(struct ice_pf *pf)
64062306a36Sopenharmony_ci{
64162306a36Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
64262306a36Sopenharmony_ci	struct ice_vsi *vsi = NULL;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	/* Need to protect the allocation of the VSIs at the PF level */
64562306a36Sopenharmony_ci	mutex_lock(&pf->sw_mutex);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	/* If we have already allocated our maximum number of VSIs,
64862306a36Sopenharmony_ci	 * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index
64962306a36Sopenharmony_ci	 * is available to be populated
65062306a36Sopenharmony_ci	 */
65162306a36Sopenharmony_ci	if (pf->next_vsi == ICE_NO_VSI) {
65262306a36Sopenharmony_ci		dev_dbg(dev, "out of VSI slots!\n");
65362306a36Sopenharmony_ci		goto unlock_pf;
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	vsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL);
65762306a36Sopenharmony_ci	if (!vsi)
65862306a36Sopenharmony_ci		goto unlock_pf;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	vsi->back = pf;
66162306a36Sopenharmony_ci	set_bit(ICE_VSI_DOWN, vsi->state);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	/* fill slot and make note of the index */
66462306a36Sopenharmony_ci	vsi->idx = pf->next_vsi;
66562306a36Sopenharmony_ci	pf->vsi[pf->next_vsi] = vsi;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	/* prepare pf->next_vsi for next use */
66862306a36Sopenharmony_ci	pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi,
66962306a36Sopenharmony_ci					 pf->next_vsi);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ciunlock_pf:
67262306a36Sopenharmony_ci	mutex_unlock(&pf->sw_mutex);
67362306a36Sopenharmony_ci	return vsi;
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci/**
67762306a36Sopenharmony_ci * ice_alloc_fd_res - Allocate FD resource for a VSI
67862306a36Sopenharmony_ci * @vsi: pointer to the ice_vsi
67962306a36Sopenharmony_ci *
68062306a36Sopenharmony_ci * This allocates the FD resources
68162306a36Sopenharmony_ci *
68262306a36Sopenharmony_ci * Returns 0 on success, -EPERM on no-op or -EIO on failure
68362306a36Sopenharmony_ci */
68462306a36Sopenharmony_cistatic int ice_alloc_fd_res(struct ice_vsi *vsi)
68562306a36Sopenharmony_ci{
68662306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
68762306a36Sopenharmony_ci	u32 g_val, b_val;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	/* Flow Director filters are only allocated/assigned to the PF VSI or
69062306a36Sopenharmony_ci	 * CHNL VSI which passes the traffic. The CTRL VSI is only used to
69162306a36Sopenharmony_ci	 * add/delete filters so resources are not allocated to it
69262306a36Sopenharmony_ci	 */
69362306a36Sopenharmony_ci	if (!test_bit(ICE_FLAG_FD_ENA, pf->flags))
69462306a36Sopenharmony_ci		return -EPERM;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	if (!(vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF ||
69762306a36Sopenharmony_ci	      vsi->type == ICE_VSI_CHNL))
69862306a36Sopenharmony_ci		return -EPERM;
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	/* FD filters from guaranteed pool per VSI */
70162306a36Sopenharmony_ci	g_val = pf->hw.func_caps.fd_fltr_guar;
70262306a36Sopenharmony_ci	if (!g_val)
70362306a36Sopenharmony_ci		return -EPERM;
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	/* FD filters from best effort pool */
70662306a36Sopenharmony_ci	b_val = pf->hw.func_caps.fd_fltr_best_effort;
70762306a36Sopenharmony_ci	if (!b_val)
70862306a36Sopenharmony_ci		return -EPERM;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	/* PF main VSI gets only 64 FD resources from guaranteed pool
71162306a36Sopenharmony_ci	 * when ADQ is configured.
71262306a36Sopenharmony_ci	 */
71362306a36Sopenharmony_ci#define ICE_PF_VSI_GFLTR	64
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	/* determine FD filter resources per VSI from shared(best effort) and
71662306a36Sopenharmony_ci	 * dedicated pool
71762306a36Sopenharmony_ci	 */
71862306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF) {
71962306a36Sopenharmony_ci		vsi->num_gfltr = g_val;
72062306a36Sopenharmony_ci		/* if MQPRIO is configured, main VSI doesn't get all FD
72162306a36Sopenharmony_ci		 * resources from guaranteed pool. PF VSI gets 64 FD resources
72262306a36Sopenharmony_ci		 */
72362306a36Sopenharmony_ci		if (test_bit(ICE_FLAG_TC_MQPRIO, pf->flags)) {
72462306a36Sopenharmony_ci			if (g_val < ICE_PF_VSI_GFLTR)
72562306a36Sopenharmony_ci				return -EPERM;
72662306a36Sopenharmony_ci			/* allow bare minimum entries for PF VSI */
72762306a36Sopenharmony_ci			vsi->num_gfltr = ICE_PF_VSI_GFLTR;
72862306a36Sopenharmony_ci		}
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci		/* each VSI gets same "best_effort" quota */
73162306a36Sopenharmony_ci		vsi->num_bfltr = b_val;
73262306a36Sopenharmony_ci	} else if (vsi->type == ICE_VSI_VF) {
73362306a36Sopenharmony_ci		vsi->num_gfltr = 0;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci		/* each VSI gets same "best_effort" quota */
73662306a36Sopenharmony_ci		vsi->num_bfltr = b_val;
73762306a36Sopenharmony_ci	} else {
73862306a36Sopenharmony_ci		struct ice_vsi *main_vsi;
73962306a36Sopenharmony_ci		int numtc;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci		main_vsi = ice_get_main_vsi(pf);
74262306a36Sopenharmony_ci		if (!main_vsi)
74362306a36Sopenharmony_ci			return -EPERM;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci		if (!main_vsi->all_numtc)
74662306a36Sopenharmony_ci			return -EINVAL;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci		/* figure out ADQ numtc */
74962306a36Sopenharmony_ci		numtc = main_vsi->all_numtc - ICE_CHNL_START_TC;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci		/* only one TC but still asking resources for channels,
75262306a36Sopenharmony_ci		 * invalid config
75362306a36Sopenharmony_ci		 */
75462306a36Sopenharmony_ci		if (numtc < ICE_CHNL_START_TC)
75562306a36Sopenharmony_ci			return -EPERM;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci		g_val -= ICE_PF_VSI_GFLTR;
75862306a36Sopenharmony_ci		/* channel VSIs gets equal share from guaranteed pool */
75962306a36Sopenharmony_ci		vsi->num_gfltr = g_val / numtc;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci		/* each VSI gets same "best_effort" quota */
76262306a36Sopenharmony_ci		vsi->num_bfltr = b_val;
76362306a36Sopenharmony_ci	}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	return 0;
76662306a36Sopenharmony_ci}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci/**
76962306a36Sopenharmony_ci * ice_vsi_get_qs - Assign queues from PF to VSI
77062306a36Sopenharmony_ci * @vsi: the VSI to assign queues to
77162306a36Sopenharmony_ci *
77262306a36Sopenharmony_ci * Returns 0 on success and a negative value on error
77362306a36Sopenharmony_ci */
77462306a36Sopenharmony_cistatic int ice_vsi_get_qs(struct ice_vsi *vsi)
77562306a36Sopenharmony_ci{
77662306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
77762306a36Sopenharmony_ci	struct ice_qs_cfg tx_qs_cfg = {
77862306a36Sopenharmony_ci		.qs_mutex = &pf->avail_q_mutex,
77962306a36Sopenharmony_ci		.pf_map = pf->avail_txqs,
78062306a36Sopenharmony_ci		.pf_map_size = pf->max_pf_txqs,
78162306a36Sopenharmony_ci		.q_count = vsi->alloc_txq,
78262306a36Sopenharmony_ci		.scatter_count = ICE_MAX_SCATTER_TXQS,
78362306a36Sopenharmony_ci		.vsi_map = vsi->txq_map,
78462306a36Sopenharmony_ci		.vsi_map_offset = 0,
78562306a36Sopenharmony_ci		.mapping_mode = ICE_VSI_MAP_CONTIG
78662306a36Sopenharmony_ci	};
78762306a36Sopenharmony_ci	struct ice_qs_cfg rx_qs_cfg = {
78862306a36Sopenharmony_ci		.qs_mutex = &pf->avail_q_mutex,
78962306a36Sopenharmony_ci		.pf_map = pf->avail_rxqs,
79062306a36Sopenharmony_ci		.pf_map_size = pf->max_pf_rxqs,
79162306a36Sopenharmony_ci		.q_count = vsi->alloc_rxq,
79262306a36Sopenharmony_ci		.scatter_count = ICE_MAX_SCATTER_RXQS,
79362306a36Sopenharmony_ci		.vsi_map = vsi->rxq_map,
79462306a36Sopenharmony_ci		.vsi_map_offset = 0,
79562306a36Sopenharmony_ci		.mapping_mode = ICE_VSI_MAP_CONTIG
79662306a36Sopenharmony_ci	};
79762306a36Sopenharmony_ci	int ret;
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL)
80062306a36Sopenharmony_ci		return 0;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	ret = __ice_vsi_get_qs(&tx_qs_cfg);
80362306a36Sopenharmony_ci	if (ret)
80462306a36Sopenharmony_ci		return ret;
80562306a36Sopenharmony_ci	vsi->tx_mapping_mode = tx_qs_cfg.mapping_mode;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	ret = __ice_vsi_get_qs(&rx_qs_cfg);
80862306a36Sopenharmony_ci	if (ret)
80962306a36Sopenharmony_ci		return ret;
81062306a36Sopenharmony_ci	vsi->rx_mapping_mode = rx_qs_cfg.mapping_mode;
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	return 0;
81362306a36Sopenharmony_ci}
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci/**
81662306a36Sopenharmony_ci * ice_vsi_put_qs - Release queues from VSI to PF
81762306a36Sopenharmony_ci * @vsi: the VSI that is going to release queues
81862306a36Sopenharmony_ci */
81962306a36Sopenharmony_cistatic void ice_vsi_put_qs(struct ice_vsi *vsi)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
82262306a36Sopenharmony_ci	int i;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	mutex_lock(&pf->avail_q_mutex);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	ice_for_each_alloc_txq(vsi, i) {
82762306a36Sopenharmony_ci		clear_bit(vsi->txq_map[i], pf->avail_txqs);
82862306a36Sopenharmony_ci		vsi->txq_map[i] = ICE_INVAL_Q_INDEX;
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	ice_for_each_alloc_rxq(vsi, i) {
83262306a36Sopenharmony_ci		clear_bit(vsi->rxq_map[i], pf->avail_rxqs);
83362306a36Sopenharmony_ci		vsi->rxq_map[i] = ICE_INVAL_Q_INDEX;
83462306a36Sopenharmony_ci	}
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	mutex_unlock(&pf->avail_q_mutex);
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci/**
84062306a36Sopenharmony_ci * ice_is_safe_mode
84162306a36Sopenharmony_ci * @pf: pointer to the PF struct
84262306a36Sopenharmony_ci *
84362306a36Sopenharmony_ci * returns true if driver is in safe mode, false otherwise
84462306a36Sopenharmony_ci */
84562306a36Sopenharmony_cibool ice_is_safe_mode(struct ice_pf *pf)
84662306a36Sopenharmony_ci{
84762306a36Sopenharmony_ci	return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
84862306a36Sopenharmony_ci}
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci/**
85162306a36Sopenharmony_ci * ice_is_rdma_ena
85262306a36Sopenharmony_ci * @pf: pointer to the PF struct
85362306a36Sopenharmony_ci *
85462306a36Sopenharmony_ci * returns true if RDMA is currently supported, false otherwise
85562306a36Sopenharmony_ci */
85662306a36Sopenharmony_cibool ice_is_rdma_ena(struct ice_pf *pf)
85762306a36Sopenharmony_ci{
85862306a36Sopenharmony_ci	return test_bit(ICE_FLAG_RDMA_ENA, pf->flags);
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci/**
86262306a36Sopenharmony_ci * ice_vsi_clean_rss_flow_fld - Delete RSS configuration
86362306a36Sopenharmony_ci * @vsi: the VSI being cleaned up
86462306a36Sopenharmony_ci *
86562306a36Sopenharmony_ci * This function deletes RSS input set for all flows that were configured
86662306a36Sopenharmony_ci * for this VSI
86762306a36Sopenharmony_ci */
86862306a36Sopenharmony_cistatic void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi)
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
87162306a36Sopenharmony_ci	int status;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	if (ice_is_safe_mode(pf))
87462306a36Sopenharmony_ci		return;
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
87762306a36Sopenharmony_ci	if (status)
87862306a36Sopenharmony_ci		dev_dbg(ice_pf_to_dev(pf), "ice_rem_vsi_rss_cfg failed for vsi = %d, error = %d\n",
87962306a36Sopenharmony_ci			vsi->vsi_num, status);
88062306a36Sopenharmony_ci}
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci/**
88362306a36Sopenharmony_ci * ice_rss_clean - Delete RSS related VSI structures and configuration
88462306a36Sopenharmony_ci * @vsi: the VSI being removed
88562306a36Sopenharmony_ci */
88662306a36Sopenharmony_cistatic void ice_rss_clean(struct ice_vsi *vsi)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
88962306a36Sopenharmony_ci	struct device *dev;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	devm_kfree(dev, vsi->rss_hkey_user);
89462306a36Sopenharmony_ci	devm_kfree(dev, vsi->rss_lut_user);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci	ice_vsi_clean_rss_flow_fld(vsi);
89762306a36Sopenharmony_ci	/* remove RSS replay list */
89862306a36Sopenharmony_ci	if (!ice_is_safe_mode(pf))
89962306a36Sopenharmony_ci		ice_rem_vsi_rss_list(&pf->hw, vsi->idx);
90062306a36Sopenharmony_ci}
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci/**
90362306a36Sopenharmony_ci * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type
90462306a36Sopenharmony_ci * @vsi: the VSI being configured
90562306a36Sopenharmony_ci */
90662306a36Sopenharmony_cistatic void ice_vsi_set_rss_params(struct ice_vsi *vsi)
90762306a36Sopenharmony_ci{
90862306a36Sopenharmony_ci	struct ice_hw_common_caps *cap;
90962306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
91062306a36Sopenharmony_ci	u16 max_rss_size;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
91362306a36Sopenharmony_ci		vsi->rss_size = 1;
91462306a36Sopenharmony_ci		return;
91562306a36Sopenharmony_ci	}
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	cap = &pf->hw.func_caps.common_cap;
91862306a36Sopenharmony_ci	max_rss_size = BIT(cap->rss_table_entry_width);
91962306a36Sopenharmony_ci	switch (vsi->type) {
92062306a36Sopenharmony_ci	case ICE_VSI_CHNL:
92162306a36Sopenharmony_ci	case ICE_VSI_PF:
92262306a36Sopenharmony_ci		/* PF VSI will inherit RSS instance of PF */
92362306a36Sopenharmony_ci		vsi->rss_table_size = (u16)cap->rss_table_size;
92462306a36Sopenharmony_ci		if (vsi->type == ICE_VSI_CHNL)
92562306a36Sopenharmony_ci			vsi->rss_size = min_t(u16, vsi->num_rxq, max_rss_size);
92662306a36Sopenharmony_ci		else
92762306a36Sopenharmony_ci			vsi->rss_size = min_t(u16, num_online_cpus(),
92862306a36Sopenharmony_ci					      max_rss_size);
92962306a36Sopenharmony_ci		vsi->rss_lut_type = ICE_LUT_PF;
93062306a36Sopenharmony_ci		break;
93162306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
93262306a36Sopenharmony_ci		vsi->rss_table_size = ICE_LUT_VSI_SIZE;
93362306a36Sopenharmony_ci		vsi->rss_size = min_t(u16, num_online_cpus(), max_rss_size);
93462306a36Sopenharmony_ci		vsi->rss_lut_type = ICE_LUT_VSI;
93562306a36Sopenharmony_ci		break;
93662306a36Sopenharmony_ci	case ICE_VSI_VF:
93762306a36Sopenharmony_ci		/* VF VSI will get a small RSS table.
93862306a36Sopenharmony_ci		 * For VSI_LUT, LUT size should be set to 64 bytes.
93962306a36Sopenharmony_ci		 */
94062306a36Sopenharmony_ci		vsi->rss_table_size = ICE_LUT_VSI_SIZE;
94162306a36Sopenharmony_ci		vsi->rss_size = ICE_MAX_RSS_QS_PER_VF;
94262306a36Sopenharmony_ci		vsi->rss_lut_type = ICE_LUT_VSI;
94362306a36Sopenharmony_ci		break;
94462306a36Sopenharmony_ci	case ICE_VSI_LB:
94562306a36Sopenharmony_ci		break;
94662306a36Sopenharmony_ci	default:
94762306a36Sopenharmony_ci		dev_dbg(ice_pf_to_dev(pf), "Unsupported VSI type %s\n",
94862306a36Sopenharmony_ci			ice_vsi_type_str(vsi->type));
94962306a36Sopenharmony_ci		break;
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci/**
95462306a36Sopenharmony_ci * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
95562306a36Sopenharmony_ci * @hw: HW structure used to determine the VLAN mode of the device
95662306a36Sopenharmony_ci * @ctxt: the VSI context being set
95762306a36Sopenharmony_ci *
95862306a36Sopenharmony_ci * This initializes a default VSI context for all sections except the Queues.
95962306a36Sopenharmony_ci */
96062306a36Sopenharmony_cistatic void ice_set_dflt_vsi_ctx(struct ice_hw *hw, struct ice_vsi_ctx *ctxt)
96162306a36Sopenharmony_ci{
96262306a36Sopenharmony_ci	u32 table = 0;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	memset(&ctxt->info, 0, sizeof(ctxt->info));
96562306a36Sopenharmony_ci	/* VSI's should be allocated from shared pool */
96662306a36Sopenharmony_ci	ctxt->alloc_from_pool = true;
96762306a36Sopenharmony_ci	/* Src pruning enabled by default */
96862306a36Sopenharmony_ci	ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
96962306a36Sopenharmony_ci	/* Traffic from VSI can be sent to LAN */
97062306a36Sopenharmony_ci	ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
97162306a36Sopenharmony_ci	/* allow all untagged/tagged packets by default on Tx */
97262306a36Sopenharmony_ci	ctxt->info.inner_vlan_flags = ((ICE_AQ_VSI_INNER_VLAN_TX_MODE_ALL &
97362306a36Sopenharmony_ci				  ICE_AQ_VSI_INNER_VLAN_TX_MODE_M) >>
97462306a36Sopenharmony_ci				 ICE_AQ_VSI_INNER_VLAN_TX_MODE_S);
97562306a36Sopenharmony_ci	/* SVM - by default bits 3 and 4 in inner_vlan_flags are 0's which
97662306a36Sopenharmony_ci	 * results in legacy behavior (show VLAN, DEI, and UP) in descriptor.
97762306a36Sopenharmony_ci	 *
97862306a36Sopenharmony_ci	 * DVM - leave inner VLAN in packet by default
97962306a36Sopenharmony_ci	 */
98062306a36Sopenharmony_ci	if (ice_is_dvm_ena(hw)) {
98162306a36Sopenharmony_ci		ctxt->info.inner_vlan_flags |=
98262306a36Sopenharmony_ci			FIELD_PREP(ICE_AQ_VSI_INNER_VLAN_EMODE_M,
98362306a36Sopenharmony_ci				   ICE_AQ_VSI_INNER_VLAN_EMODE_NOTHING);
98462306a36Sopenharmony_ci		ctxt->info.outer_vlan_flags =
98562306a36Sopenharmony_ci			(ICE_AQ_VSI_OUTER_VLAN_TX_MODE_ALL <<
98662306a36Sopenharmony_ci			 ICE_AQ_VSI_OUTER_VLAN_TX_MODE_S) &
98762306a36Sopenharmony_ci			ICE_AQ_VSI_OUTER_VLAN_TX_MODE_M;
98862306a36Sopenharmony_ci		ctxt->info.outer_vlan_flags |=
98962306a36Sopenharmony_ci			(ICE_AQ_VSI_OUTER_TAG_VLAN_8100 <<
99062306a36Sopenharmony_ci			 ICE_AQ_VSI_OUTER_TAG_TYPE_S) &
99162306a36Sopenharmony_ci			ICE_AQ_VSI_OUTER_TAG_TYPE_M;
99262306a36Sopenharmony_ci		ctxt->info.outer_vlan_flags |=
99362306a36Sopenharmony_ci			FIELD_PREP(ICE_AQ_VSI_OUTER_VLAN_EMODE_M,
99462306a36Sopenharmony_ci				   ICE_AQ_VSI_OUTER_VLAN_EMODE_NOTHING);
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci	/* Have 1:1 UP mapping for both ingress/egress tables */
99762306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(0, 0);
99862306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(1, 1);
99962306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(2, 2);
100062306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(3, 3);
100162306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(4, 4);
100262306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(5, 5);
100362306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(6, 6);
100462306a36Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(7, 7);
100562306a36Sopenharmony_ci	ctxt->info.ingress_table = cpu_to_le32(table);
100662306a36Sopenharmony_ci	ctxt->info.egress_table = cpu_to_le32(table);
100762306a36Sopenharmony_ci	/* Have 1:1 UP mapping for outer to inner UP table */
100862306a36Sopenharmony_ci	ctxt->info.outer_up_table = cpu_to_le32(table);
100962306a36Sopenharmony_ci	/* No Outer tag support outer_tag_flags remains to zero */
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci/**
101362306a36Sopenharmony_ci * ice_vsi_setup_q_map - Setup a VSI queue map
101462306a36Sopenharmony_ci * @vsi: the VSI being configured
101562306a36Sopenharmony_ci * @ctxt: VSI context structure
101662306a36Sopenharmony_ci */
101762306a36Sopenharmony_cistatic int ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
101862306a36Sopenharmony_ci{
101962306a36Sopenharmony_ci	u16 offset = 0, qmap = 0, tx_count = 0, rx_count = 0, pow = 0;
102062306a36Sopenharmony_ci	u16 num_txq_per_tc, num_rxq_per_tc;
102162306a36Sopenharmony_ci	u16 qcount_tx = vsi->alloc_txq;
102262306a36Sopenharmony_ci	u16 qcount_rx = vsi->alloc_rxq;
102362306a36Sopenharmony_ci	u8 netdev_tc = 0;
102462306a36Sopenharmony_ci	int i;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	if (!vsi->tc_cfg.numtc) {
102762306a36Sopenharmony_ci		/* at least TC0 should be enabled by default */
102862306a36Sopenharmony_ci		vsi->tc_cfg.numtc = 1;
102962306a36Sopenharmony_ci		vsi->tc_cfg.ena_tc = 1;
103062306a36Sopenharmony_ci	}
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	num_rxq_per_tc = min_t(u16, qcount_rx / vsi->tc_cfg.numtc, ICE_MAX_RXQS_PER_TC);
103362306a36Sopenharmony_ci	if (!num_rxq_per_tc)
103462306a36Sopenharmony_ci		num_rxq_per_tc = 1;
103562306a36Sopenharmony_ci	num_txq_per_tc = qcount_tx / vsi->tc_cfg.numtc;
103662306a36Sopenharmony_ci	if (!num_txq_per_tc)
103762306a36Sopenharmony_ci		num_txq_per_tc = 1;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	/* find the (rounded up) power-of-2 of qcount */
104062306a36Sopenharmony_ci	pow = (u16)order_base_2(num_rxq_per_tc);
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	/* TC mapping is a function of the number of Rx queues assigned to the
104362306a36Sopenharmony_ci	 * VSI for each traffic class and the offset of these queues.
104462306a36Sopenharmony_ci	 * The first 10 bits are for queue offset for TC0, next 4 bits for no:of
104562306a36Sopenharmony_ci	 * queues allocated to TC0. No:of queues is a power-of-2.
104662306a36Sopenharmony_ci	 *
104762306a36Sopenharmony_ci	 * If TC is not enabled, the queue offset is set to 0, and allocate one
104862306a36Sopenharmony_ci	 * queue, this way, traffic for the given TC will be sent to the default
104962306a36Sopenharmony_ci	 * queue.
105062306a36Sopenharmony_ci	 *
105162306a36Sopenharmony_ci	 * Setup number and offset of Rx queues for all TCs for the VSI
105262306a36Sopenharmony_ci	 */
105362306a36Sopenharmony_ci	ice_for_each_traffic_class(i) {
105462306a36Sopenharmony_ci		if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
105562306a36Sopenharmony_ci			/* TC is not enabled */
105662306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qoffset = 0;
105762306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qcount_rx = 1;
105862306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qcount_tx = 1;
105962306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].netdev_tc = 0;
106062306a36Sopenharmony_ci			ctxt->info.tc_mapping[i] = 0;
106162306a36Sopenharmony_ci			continue;
106262306a36Sopenharmony_ci		}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci		/* TC is enabled */
106562306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qoffset = offset;
106662306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qcount_rx = num_rxq_per_tc;
106762306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qcount_tx = num_txq_per_tc;
106862306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci		qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
107162306a36Sopenharmony_ci			ICE_AQ_VSI_TC_Q_OFFSET_M) |
107262306a36Sopenharmony_ci			((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
107362306a36Sopenharmony_ci			 ICE_AQ_VSI_TC_Q_NUM_M);
107462306a36Sopenharmony_ci		offset += num_rxq_per_tc;
107562306a36Sopenharmony_ci		tx_count += num_txq_per_tc;
107662306a36Sopenharmony_ci		ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
107762306a36Sopenharmony_ci	}
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	/* if offset is non-zero, means it is calculated correctly based on
108062306a36Sopenharmony_ci	 * enabled TCs for a given VSI otherwise qcount_rx will always
108162306a36Sopenharmony_ci	 * be correct and non-zero because it is based off - VSI's
108262306a36Sopenharmony_ci	 * allocated Rx queues which is at least 1 (hence qcount_tx will be
108362306a36Sopenharmony_ci	 * at least 1)
108462306a36Sopenharmony_ci	 */
108562306a36Sopenharmony_ci	if (offset)
108662306a36Sopenharmony_ci		rx_count = offset;
108762306a36Sopenharmony_ci	else
108862306a36Sopenharmony_ci		rx_count = num_rxq_per_tc;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	if (rx_count > vsi->alloc_rxq) {
109162306a36Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Rx queues (%u), than were allocated (%u)!\n",
109262306a36Sopenharmony_ci			rx_count, vsi->alloc_rxq);
109362306a36Sopenharmony_ci		return -EINVAL;
109462306a36Sopenharmony_ci	}
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	if (tx_count > vsi->alloc_txq) {
109762306a36Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Tx queues (%u), than were allocated (%u)!\n",
109862306a36Sopenharmony_ci			tx_count, vsi->alloc_txq);
109962306a36Sopenharmony_ci		return -EINVAL;
110062306a36Sopenharmony_ci	}
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	vsi->num_txq = tx_count;
110362306a36Sopenharmony_ci	vsi->num_rxq = rx_count;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
110662306a36Sopenharmony_ci		dev_dbg(ice_pf_to_dev(vsi->back), "VF VSI should have same number of Tx and Rx queues. Hence making them equal\n");
110762306a36Sopenharmony_ci		/* since there is a chance that num_rxq could have been changed
110862306a36Sopenharmony_ci		 * in the above for loop, make num_txq equal to num_rxq.
110962306a36Sopenharmony_ci		 */
111062306a36Sopenharmony_ci		vsi->num_txq = vsi->num_rxq;
111162306a36Sopenharmony_ci	}
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	/* Rx queue mapping */
111462306a36Sopenharmony_ci	ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
111562306a36Sopenharmony_ci	/* q_mapping buffer holds the info for the first queue allocated for
111662306a36Sopenharmony_ci	 * this VSI in the PF space and also the number of queues associated
111762306a36Sopenharmony_ci	 * with this VSI.
111862306a36Sopenharmony_ci	 */
111962306a36Sopenharmony_ci	ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
112062306a36Sopenharmony_ci	ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	return 0;
112362306a36Sopenharmony_ci}
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci/**
112662306a36Sopenharmony_ci * ice_set_fd_vsi_ctx - Set FD VSI context before adding a VSI
112762306a36Sopenharmony_ci * @ctxt: the VSI context being set
112862306a36Sopenharmony_ci * @vsi: the VSI being configured
112962306a36Sopenharmony_ci */
113062306a36Sopenharmony_cistatic void ice_set_fd_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
113162306a36Sopenharmony_ci{
113262306a36Sopenharmony_ci	u8 dflt_q_group, dflt_q_prio;
113362306a36Sopenharmony_ci	u16 dflt_q, report_q, val;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	if (vsi->type != ICE_VSI_PF && vsi->type != ICE_VSI_CTRL &&
113662306a36Sopenharmony_ci	    vsi->type != ICE_VSI_VF && vsi->type != ICE_VSI_CHNL)
113762306a36Sopenharmony_ci		return;
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	val = ICE_AQ_VSI_PROP_FLOW_DIR_VALID;
114062306a36Sopenharmony_ci	ctxt->info.valid_sections |= cpu_to_le16(val);
114162306a36Sopenharmony_ci	dflt_q = 0;
114262306a36Sopenharmony_ci	dflt_q_group = 0;
114362306a36Sopenharmony_ci	report_q = 0;
114462306a36Sopenharmony_ci	dflt_q_prio = 0;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	/* enable flow director filtering/programming */
114762306a36Sopenharmony_ci	val = ICE_AQ_VSI_FD_ENABLE | ICE_AQ_VSI_FD_PROG_ENABLE;
114862306a36Sopenharmony_ci	ctxt->info.fd_options = cpu_to_le16(val);
114962306a36Sopenharmony_ci	/* max of allocated flow director filters */
115062306a36Sopenharmony_ci	ctxt->info.max_fd_fltr_dedicated =
115162306a36Sopenharmony_ci			cpu_to_le16(vsi->num_gfltr);
115262306a36Sopenharmony_ci	/* max of shared flow director filters any VSI may program */
115362306a36Sopenharmony_ci	ctxt->info.max_fd_fltr_shared =
115462306a36Sopenharmony_ci			cpu_to_le16(vsi->num_bfltr);
115562306a36Sopenharmony_ci	/* default queue index within the VSI of the default FD */
115662306a36Sopenharmony_ci	val = ((dflt_q << ICE_AQ_VSI_FD_DEF_Q_S) &
115762306a36Sopenharmony_ci	       ICE_AQ_VSI_FD_DEF_Q_M);
115862306a36Sopenharmony_ci	/* target queue or queue group to the FD filter */
115962306a36Sopenharmony_ci	val |= ((dflt_q_group << ICE_AQ_VSI_FD_DEF_GRP_S) &
116062306a36Sopenharmony_ci		ICE_AQ_VSI_FD_DEF_GRP_M);
116162306a36Sopenharmony_ci	ctxt->info.fd_def_q = cpu_to_le16(val);
116262306a36Sopenharmony_ci	/* queue index on which FD filter completion is reported */
116362306a36Sopenharmony_ci	val = ((report_q << ICE_AQ_VSI_FD_REPORT_Q_S) &
116462306a36Sopenharmony_ci	       ICE_AQ_VSI_FD_REPORT_Q_M);
116562306a36Sopenharmony_ci	/* priority of the default qindex action */
116662306a36Sopenharmony_ci	val |= ((dflt_q_prio << ICE_AQ_VSI_FD_DEF_PRIORITY_S) &
116762306a36Sopenharmony_ci		ICE_AQ_VSI_FD_DEF_PRIORITY_M);
116862306a36Sopenharmony_ci	ctxt->info.fd_report_opt = cpu_to_le16(val);
116962306a36Sopenharmony_ci}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci/**
117262306a36Sopenharmony_ci * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI
117362306a36Sopenharmony_ci * @ctxt: the VSI context being set
117462306a36Sopenharmony_ci * @vsi: the VSI being configured
117562306a36Sopenharmony_ci */
117662306a36Sopenharmony_cistatic void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
117762306a36Sopenharmony_ci{
117862306a36Sopenharmony_ci	u8 lut_type, hash_type;
117962306a36Sopenharmony_ci	struct device *dev;
118062306a36Sopenharmony_ci	struct ice_pf *pf;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	pf = vsi->back;
118362306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	switch (vsi->type) {
118662306a36Sopenharmony_ci	case ICE_VSI_CHNL:
118762306a36Sopenharmony_ci	case ICE_VSI_PF:
118862306a36Sopenharmony_ci		/* PF VSI will inherit RSS instance of PF */
118962306a36Sopenharmony_ci		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
119062306a36Sopenharmony_ci		hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
119162306a36Sopenharmony_ci		break;
119262306a36Sopenharmony_ci	case ICE_VSI_VF:
119362306a36Sopenharmony_ci		/* VF VSI will gets a small RSS table which is a VSI LUT type */
119462306a36Sopenharmony_ci		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
119562306a36Sopenharmony_ci		hash_type = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
119662306a36Sopenharmony_ci		break;
119762306a36Sopenharmony_ci	default:
119862306a36Sopenharmony_ci		dev_dbg(dev, "Unsupported VSI type %s\n",
119962306a36Sopenharmony_ci			ice_vsi_type_str(vsi->type));
120062306a36Sopenharmony_ci		return;
120162306a36Sopenharmony_ci	}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
120462306a36Sopenharmony_ci				ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
120562306a36Sopenharmony_ci				(hash_type & ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
120662306a36Sopenharmony_ci}
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_cistatic void
120962306a36Sopenharmony_ciice_chnl_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
121062306a36Sopenharmony_ci{
121162306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
121262306a36Sopenharmony_ci	u16 qcount, qmap;
121362306a36Sopenharmony_ci	u8 offset = 0;
121462306a36Sopenharmony_ci	int pow;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	qcount = min_t(int, vsi->num_rxq, pf->num_lan_msix);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	pow = order_base_2(qcount);
121962306a36Sopenharmony_ci	qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
122062306a36Sopenharmony_ci		 ICE_AQ_VSI_TC_Q_OFFSET_M) |
122162306a36Sopenharmony_ci		 ((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
122262306a36Sopenharmony_ci		   ICE_AQ_VSI_TC_Q_NUM_M);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	ctxt->info.tc_mapping[0] = cpu_to_le16(qmap);
122562306a36Sopenharmony_ci	ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
122662306a36Sopenharmony_ci	ctxt->info.q_mapping[0] = cpu_to_le16(vsi->next_base_q);
122762306a36Sopenharmony_ci	ctxt->info.q_mapping[1] = cpu_to_le16(qcount);
122862306a36Sopenharmony_ci}
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci/**
123162306a36Sopenharmony_ci * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not
123262306a36Sopenharmony_ci * @vsi: VSI to check whether or not VLAN pruning is enabled.
123362306a36Sopenharmony_ci *
123462306a36Sopenharmony_ci * returns true if Rx VLAN pruning is enabled and false otherwise.
123562306a36Sopenharmony_ci */
123662306a36Sopenharmony_cistatic bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi)
123762306a36Sopenharmony_ci{
123862306a36Sopenharmony_ci	return vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
123962306a36Sopenharmony_ci}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci/**
124262306a36Sopenharmony_ci * ice_vsi_init - Create and initialize a VSI
124362306a36Sopenharmony_ci * @vsi: the VSI being configured
124462306a36Sopenharmony_ci * @vsi_flags: VSI configuration flags
124562306a36Sopenharmony_ci *
124662306a36Sopenharmony_ci * Set ICE_FLAG_VSI_INIT to initialize a new VSI context, clear it to
124762306a36Sopenharmony_ci * reconfigure an existing context.
124862306a36Sopenharmony_ci *
124962306a36Sopenharmony_ci * This initializes a VSI context depending on the VSI type to be added and
125062306a36Sopenharmony_ci * passes it down to the add_vsi aq command to create a new VSI.
125162306a36Sopenharmony_ci */
125262306a36Sopenharmony_cistatic int ice_vsi_init(struct ice_vsi *vsi, u32 vsi_flags)
125362306a36Sopenharmony_ci{
125462306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
125562306a36Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
125662306a36Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
125762306a36Sopenharmony_ci	struct device *dev;
125862306a36Sopenharmony_ci	int ret = 0;
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
126162306a36Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
126262306a36Sopenharmony_ci	if (!ctxt)
126362306a36Sopenharmony_ci		return -ENOMEM;
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	switch (vsi->type) {
126662306a36Sopenharmony_ci	case ICE_VSI_CTRL:
126762306a36Sopenharmony_ci	case ICE_VSI_LB:
126862306a36Sopenharmony_ci	case ICE_VSI_PF:
126962306a36Sopenharmony_ci		ctxt->flags = ICE_AQ_VSI_TYPE_PF;
127062306a36Sopenharmony_ci		break;
127162306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
127262306a36Sopenharmony_ci	case ICE_VSI_CHNL:
127362306a36Sopenharmony_ci		ctxt->flags = ICE_AQ_VSI_TYPE_VMDQ2;
127462306a36Sopenharmony_ci		break;
127562306a36Sopenharmony_ci	case ICE_VSI_VF:
127662306a36Sopenharmony_ci		ctxt->flags = ICE_AQ_VSI_TYPE_VF;
127762306a36Sopenharmony_ci		/* VF number here is the absolute VF number (0-255) */
127862306a36Sopenharmony_ci		ctxt->vf_num = vsi->vf->vf_id + hw->func_caps.vf_base_id;
127962306a36Sopenharmony_ci		break;
128062306a36Sopenharmony_ci	default:
128162306a36Sopenharmony_ci		ret = -ENODEV;
128262306a36Sopenharmony_ci		goto out;
128362306a36Sopenharmony_ci	}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	/* Handle VLAN pruning for channel VSI if main VSI has VLAN
128662306a36Sopenharmony_ci	 * prune enabled
128762306a36Sopenharmony_ci	 */
128862306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL) {
128962306a36Sopenharmony_ci		struct ice_vsi *main_vsi;
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci		main_vsi = ice_get_main_vsi(pf);
129262306a36Sopenharmony_ci		if (main_vsi && ice_vsi_is_vlan_pruning_ena(main_vsi))
129362306a36Sopenharmony_ci			ctxt->info.sw_flags2 |=
129462306a36Sopenharmony_ci				ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
129562306a36Sopenharmony_ci		else
129662306a36Sopenharmony_ci			ctxt->info.sw_flags2 &=
129762306a36Sopenharmony_ci				~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
129862306a36Sopenharmony_ci	}
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci	ice_set_dflt_vsi_ctx(hw, ctxt);
130162306a36Sopenharmony_ci	if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
130262306a36Sopenharmony_ci		ice_set_fd_vsi_ctx(ctxt, vsi);
130362306a36Sopenharmony_ci	/* if the switch is in VEB mode, allow VSI loopback */
130462306a36Sopenharmony_ci	if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
130562306a36Sopenharmony_ci		ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci	/* Set LUT type and HASH type if RSS is enabled */
130862306a36Sopenharmony_ci	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags) &&
130962306a36Sopenharmony_ci	    vsi->type != ICE_VSI_CTRL) {
131062306a36Sopenharmony_ci		ice_set_rss_vsi_ctx(ctxt, vsi);
131162306a36Sopenharmony_ci		/* if updating VSI context, make sure to set valid_section:
131262306a36Sopenharmony_ci		 * to indicate which section of VSI context being updated
131362306a36Sopenharmony_ci		 */
131462306a36Sopenharmony_ci		if (!(vsi_flags & ICE_VSI_FLAG_INIT))
131562306a36Sopenharmony_ci			ctxt->info.valid_sections |=
131662306a36Sopenharmony_ci				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
131762306a36Sopenharmony_ci	}
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	ctxt->info.sw_id = vsi->port_info->sw_id;
132062306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL) {
132162306a36Sopenharmony_ci		ice_chnl_vsi_setup_q_map(vsi, ctxt);
132262306a36Sopenharmony_ci	} else {
132362306a36Sopenharmony_ci		ret = ice_vsi_setup_q_map(vsi, ctxt);
132462306a36Sopenharmony_ci		if (ret)
132562306a36Sopenharmony_ci			goto out;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci		if (!(vsi_flags & ICE_VSI_FLAG_INIT))
132862306a36Sopenharmony_ci			/* means VSI being updated */
132962306a36Sopenharmony_ci			/* must to indicate which section of VSI context are
133062306a36Sopenharmony_ci			 * being modified
133162306a36Sopenharmony_ci			 */
133262306a36Sopenharmony_ci			ctxt->info.valid_sections |=
133362306a36Sopenharmony_ci				cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
133462306a36Sopenharmony_ci	}
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	/* Allow control frames out of main VSI */
133762306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF) {
133862306a36Sopenharmony_ci		ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
133962306a36Sopenharmony_ci		ctxt->info.valid_sections |=
134062306a36Sopenharmony_ci			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
134162306a36Sopenharmony_ci	}
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	if (vsi_flags & ICE_VSI_FLAG_INIT) {
134462306a36Sopenharmony_ci		ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
134562306a36Sopenharmony_ci		if (ret) {
134662306a36Sopenharmony_ci			dev_err(dev, "Add VSI failed, err %d\n", ret);
134762306a36Sopenharmony_ci			ret = -EIO;
134862306a36Sopenharmony_ci			goto out;
134962306a36Sopenharmony_ci		}
135062306a36Sopenharmony_ci	} else {
135162306a36Sopenharmony_ci		ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
135262306a36Sopenharmony_ci		if (ret) {
135362306a36Sopenharmony_ci			dev_err(dev, "Update VSI failed, err %d\n", ret);
135462306a36Sopenharmony_ci			ret = -EIO;
135562306a36Sopenharmony_ci			goto out;
135662306a36Sopenharmony_ci		}
135762306a36Sopenharmony_ci	}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	/* keep context for update VSI operations */
136062306a36Sopenharmony_ci	vsi->info = ctxt->info;
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	/* record VSI number returned */
136362306a36Sopenharmony_ci	vsi->vsi_num = ctxt->vsi_num;
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ciout:
136662306a36Sopenharmony_ci	kfree(ctxt);
136762306a36Sopenharmony_ci	return ret;
136862306a36Sopenharmony_ci}
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci/**
137162306a36Sopenharmony_ci * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
137262306a36Sopenharmony_ci * @vsi: the VSI having rings deallocated
137362306a36Sopenharmony_ci */
137462306a36Sopenharmony_cistatic void ice_vsi_clear_rings(struct ice_vsi *vsi)
137562306a36Sopenharmony_ci{
137662306a36Sopenharmony_ci	int i;
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	/* Avoid stale references by clearing map from vector to ring */
137962306a36Sopenharmony_ci	if (vsi->q_vectors) {
138062306a36Sopenharmony_ci		ice_for_each_q_vector(vsi, i) {
138162306a36Sopenharmony_ci			struct ice_q_vector *q_vector = vsi->q_vectors[i];
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci			if (q_vector) {
138462306a36Sopenharmony_ci				q_vector->tx.tx_ring = NULL;
138562306a36Sopenharmony_ci				q_vector->rx.rx_ring = NULL;
138662306a36Sopenharmony_ci			}
138762306a36Sopenharmony_ci		}
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	if (vsi->tx_rings) {
139162306a36Sopenharmony_ci		ice_for_each_alloc_txq(vsi, i) {
139262306a36Sopenharmony_ci			if (vsi->tx_rings[i]) {
139362306a36Sopenharmony_ci				kfree_rcu(vsi->tx_rings[i], rcu);
139462306a36Sopenharmony_ci				WRITE_ONCE(vsi->tx_rings[i], NULL);
139562306a36Sopenharmony_ci			}
139662306a36Sopenharmony_ci		}
139762306a36Sopenharmony_ci	}
139862306a36Sopenharmony_ci	if (vsi->rx_rings) {
139962306a36Sopenharmony_ci		ice_for_each_alloc_rxq(vsi, i) {
140062306a36Sopenharmony_ci			if (vsi->rx_rings[i]) {
140162306a36Sopenharmony_ci				kfree_rcu(vsi->rx_rings[i], rcu);
140262306a36Sopenharmony_ci				WRITE_ONCE(vsi->rx_rings[i], NULL);
140362306a36Sopenharmony_ci			}
140462306a36Sopenharmony_ci		}
140562306a36Sopenharmony_ci	}
140662306a36Sopenharmony_ci}
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci/**
140962306a36Sopenharmony_ci * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI
141062306a36Sopenharmony_ci * @vsi: VSI which is having rings allocated
141162306a36Sopenharmony_ci */
141262306a36Sopenharmony_cistatic int ice_vsi_alloc_rings(struct ice_vsi *vsi)
141362306a36Sopenharmony_ci{
141462306a36Sopenharmony_ci	bool dvm_ena = ice_is_dvm_ena(&vsi->back->hw);
141562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
141662306a36Sopenharmony_ci	struct device *dev;
141762306a36Sopenharmony_ci	u16 i;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
142062306a36Sopenharmony_ci	/* Allocate Tx rings */
142162306a36Sopenharmony_ci	ice_for_each_alloc_txq(vsi, i) {
142262306a36Sopenharmony_ci		struct ice_tx_ring *ring;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci		/* allocate with kzalloc(), free with kfree_rcu() */
142562306a36Sopenharmony_ci		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci		if (!ring)
142862306a36Sopenharmony_ci			goto err_out;
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci		ring->q_index = i;
143162306a36Sopenharmony_ci		ring->reg_idx = vsi->txq_map[i];
143262306a36Sopenharmony_ci		ring->vsi = vsi;
143362306a36Sopenharmony_ci		ring->tx_tstamps = &pf->ptp.port.tx;
143462306a36Sopenharmony_ci		ring->dev = dev;
143562306a36Sopenharmony_ci		ring->count = vsi->num_tx_desc;
143662306a36Sopenharmony_ci		ring->txq_teid = ICE_INVAL_TEID;
143762306a36Sopenharmony_ci		if (dvm_ena)
143862306a36Sopenharmony_ci			ring->flags |= ICE_TX_FLAGS_RING_VLAN_L2TAG2;
143962306a36Sopenharmony_ci		else
144062306a36Sopenharmony_ci			ring->flags |= ICE_TX_FLAGS_RING_VLAN_L2TAG1;
144162306a36Sopenharmony_ci		WRITE_ONCE(vsi->tx_rings[i], ring);
144262306a36Sopenharmony_ci	}
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	/* Allocate Rx rings */
144562306a36Sopenharmony_ci	ice_for_each_alloc_rxq(vsi, i) {
144662306a36Sopenharmony_ci		struct ice_rx_ring *ring;
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci		/* allocate with kzalloc(), free with kfree_rcu() */
144962306a36Sopenharmony_ci		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
145062306a36Sopenharmony_ci		if (!ring)
145162306a36Sopenharmony_ci			goto err_out;
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci		ring->q_index = i;
145462306a36Sopenharmony_ci		ring->reg_idx = vsi->rxq_map[i];
145562306a36Sopenharmony_ci		ring->vsi = vsi;
145662306a36Sopenharmony_ci		ring->netdev = vsi->netdev;
145762306a36Sopenharmony_ci		ring->dev = dev;
145862306a36Sopenharmony_ci		ring->count = vsi->num_rx_desc;
145962306a36Sopenharmony_ci		ring->cached_phctime = pf->ptp.cached_phc_time;
146062306a36Sopenharmony_ci		WRITE_ONCE(vsi->rx_rings[i], ring);
146162306a36Sopenharmony_ci	}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	return 0;
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_cierr_out:
146662306a36Sopenharmony_ci	ice_vsi_clear_rings(vsi);
146762306a36Sopenharmony_ci	return -ENOMEM;
146862306a36Sopenharmony_ci}
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci/**
147162306a36Sopenharmony_ci * ice_vsi_manage_rss_lut - disable/enable RSS
147262306a36Sopenharmony_ci * @vsi: the VSI being changed
147362306a36Sopenharmony_ci * @ena: boolean value indicating if this is an enable or disable request
147462306a36Sopenharmony_ci *
147562306a36Sopenharmony_ci * In the event of disable request for RSS, this function will zero out RSS
147662306a36Sopenharmony_ci * LUT, while in the event of enable request for RSS, it will reconfigure RSS
147762306a36Sopenharmony_ci * LUT.
147862306a36Sopenharmony_ci */
147962306a36Sopenharmony_civoid ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena)
148062306a36Sopenharmony_ci{
148162306a36Sopenharmony_ci	u8 *lut;
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
148462306a36Sopenharmony_ci	if (!lut)
148562306a36Sopenharmony_ci		return;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	if (ena) {
148862306a36Sopenharmony_ci		if (vsi->rss_lut_user)
148962306a36Sopenharmony_ci			memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
149062306a36Sopenharmony_ci		else
149162306a36Sopenharmony_ci			ice_fill_rss_lut(lut, vsi->rss_table_size,
149262306a36Sopenharmony_ci					 vsi->rss_size);
149362306a36Sopenharmony_ci	}
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	ice_set_rss_lut(vsi, lut, vsi->rss_table_size);
149662306a36Sopenharmony_ci	kfree(lut);
149762306a36Sopenharmony_ci}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci/**
150062306a36Sopenharmony_ci * ice_vsi_cfg_crc_strip - Configure CRC stripping for a VSI
150162306a36Sopenharmony_ci * @vsi: VSI to be configured
150262306a36Sopenharmony_ci * @disable: set to true to have FCS / CRC in the frame data
150362306a36Sopenharmony_ci */
150462306a36Sopenharmony_civoid ice_vsi_cfg_crc_strip(struct ice_vsi *vsi, bool disable)
150562306a36Sopenharmony_ci{
150662306a36Sopenharmony_ci	int i;
150762306a36Sopenharmony_ci
150862306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i)
150962306a36Sopenharmony_ci		if (disable)
151062306a36Sopenharmony_ci			vsi->rx_rings[i]->flags |= ICE_RX_FLAGS_CRC_STRIP_DIS;
151162306a36Sopenharmony_ci		else
151262306a36Sopenharmony_ci			vsi->rx_rings[i]->flags &= ~ICE_RX_FLAGS_CRC_STRIP_DIS;
151362306a36Sopenharmony_ci}
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci/**
151662306a36Sopenharmony_ci * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI
151762306a36Sopenharmony_ci * @vsi: VSI to be configured
151862306a36Sopenharmony_ci */
151962306a36Sopenharmony_ciint ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi)
152062306a36Sopenharmony_ci{
152162306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
152262306a36Sopenharmony_ci	struct device *dev;
152362306a36Sopenharmony_ci	u8 *lut, *key;
152462306a36Sopenharmony_ci	int err;
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
152762306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF && vsi->ch_rss_size &&
152862306a36Sopenharmony_ci	    (test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))) {
152962306a36Sopenharmony_ci		vsi->rss_size = min_t(u16, vsi->rss_size, vsi->ch_rss_size);
153062306a36Sopenharmony_ci	} else {
153162306a36Sopenharmony_ci		vsi->rss_size = min_t(u16, vsi->rss_size, vsi->num_rxq);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci		/* If orig_rss_size is valid and it is less than determined
153462306a36Sopenharmony_ci		 * main VSI's rss_size, update main VSI's rss_size to be
153562306a36Sopenharmony_ci		 * orig_rss_size so that when tc-qdisc is deleted, main VSI
153662306a36Sopenharmony_ci		 * RSS table gets programmed to be correct (whatever it was
153762306a36Sopenharmony_ci		 * to begin with (prior to setup-tc for ADQ config)
153862306a36Sopenharmony_ci		 */
153962306a36Sopenharmony_ci		if (vsi->orig_rss_size && vsi->rss_size < vsi->orig_rss_size &&
154062306a36Sopenharmony_ci		    vsi->orig_rss_size <= vsi->num_rxq) {
154162306a36Sopenharmony_ci			vsi->rss_size = vsi->orig_rss_size;
154262306a36Sopenharmony_ci			/* now orig_rss_size is used, reset it to zero */
154362306a36Sopenharmony_ci			vsi->orig_rss_size = 0;
154462306a36Sopenharmony_ci		}
154562306a36Sopenharmony_ci	}
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
154862306a36Sopenharmony_ci	if (!lut)
154962306a36Sopenharmony_ci		return -ENOMEM;
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	if (vsi->rss_lut_user)
155262306a36Sopenharmony_ci		memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
155362306a36Sopenharmony_ci	else
155462306a36Sopenharmony_ci		ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	err = ice_set_rss_lut(vsi, lut, vsi->rss_table_size);
155762306a36Sopenharmony_ci	if (err) {
155862306a36Sopenharmony_ci		dev_err(dev, "set_rss_lut failed, error %d\n", err);
155962306a36Sopenharmony_ci		goto ice_vsi_cfg_rss_exit;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	key = kzalloc(ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE, GFP_KERNEL);
156362306a36Sopenharmony_ci	if (!key) {
156462306a36Sopenharmony_ci		err = -ENOMEM;
156562306a36Sopenharmony_ci		goto ice_vsi_cfg_rss_exit;
156662306a36Sopenharmony_ci	}
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	if (vsi->rss_hkey_user)
156962306a36Sopenharmony_ci		memcpy(key, vsi->rss_hkey_user, ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
157062306a36Sopenharmony_ci	else
157162306a36Sopenharmony_ci		netdev_rss_key_fill((void *)key, ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	err = ice_set_rss_key(vsi, key);
157462306a36Sopenharmony_ci	if (err)
157562306a36Sopenharmony_ci		dev_err(dev, "set_rss_key failed, error %d\n", err);
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci	kfree(key);
157862306a36Sopenharmony_ciice_vsi_cfg_rss_exit:
157962306a36Sopenharmony_ci	kfree(lut);
158062306a36Sopenharmony_ci	return err;
158162306a36Sopenharmony_ci}
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci/**
158462306a36Sopenharmony_ci * ice_vsi_set_vf_rss_flow_fld - Sets VF VSI RSS input set for different flows
158562306a36Sopenharmony_ci * @vsi: VSI to be configured
158662306a36Sopenharmony_ci *
158762306a36Sopenharmony_ci * This function will only be called during the VF VSI setup. Upon successful
158862306a36Sopenharmony_ci * completion of package download, this function will configure default RSS
158962306a36Sopenharmony_ci * input sets for VF VSI.
159062306a36Sopenharmony_ci */
159162306a36Sopenharmony_cistatic void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi)
159262306a36Sopenharmony_ci{
159362306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
159462306a36Sopenharmony_ci	struct device *dev;
159562306a36Sopenharmony_ci	int status;
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
159862306a36Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
159962306a36Sopenharmony_ci		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
160062306a36Sopenharmony_ci			vsi->vsi_num);
160162306a36Sopenharmony_ci		return;
160262306a36Sopenharmony_ci	}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA);
160562306a36Sopenharmony_ci	if (status)
160662306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %d\n",
160762306a36Sopenharmony_ci			vsi->vsi_num, status);
160862306a36Sopenharmony_ci}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci/**
161162306a36Sopenharmony_ci * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows
161262306a36Sopenharmony_ci * @vsi: VSI to be configured
161362306a36Sopenharmony_ci *
161462306a36Sopenharmony_ci * This function will only be called after successful download package call
161562306a36Sopenharmony_ci * during initialization of PF. Since the downloaded package will erase the
161662306a36Sopenharmony_ci * RSS section, this function will configure RSS input sets for different
161762306a36Sopenharmony_ci * flow types. The last profile added has the highest priority, therefore 2
161862306a36Sopenharmony_ci * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles
161962306a36Sopenharmony_ci * (i.e. IPv4 src/dst TCP src/dst port).
162062306a36Sopenharmony_ci */
162162306a36Sopenharmony_cistatic void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
162262306a36Sopenharmony_ci{
162362306a36Sopenharmony_ci	u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num;
162462306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
162562306a36Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
162662306a36Sopenharmony_ci	struct device *dev;
162762306a36Sopenharmony_ci	int status;
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
163062306a36Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
163162306a36Sopenharmony_ci		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
163262306a36Sopenharmony_ci			vsi_num);
163362306a36Sopenharmony_ci		return;
163462306a36Sopenharmony_ci	}
163562306a36Sopenharmony_ci	/* configure RSS for IPv4 with input set IP src/dst */
163662306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
163762306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_IPV4);
163862306a36Sopenharmony_ci	if (status)
163962306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %d\n",
164062306a36Sopenharmony_ci			vsi_num, status);
164162306a36Sopenharmony_ci
164262306a36Sopenharmony_ci	/* configure RSS for IPv6 with input set IPv6 src/dst */
164362306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
164462306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_IPV6);
164562306a36Sopenharmony_ci	if (status)
164662306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %d\n",
164762306a36Sopenharmony_ci			vsi_num, status);
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	/* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */
165062306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4,
165162306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4);
165262306a36Sopenharmony_ci	if (status)
165362306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %d\n",
165462306a36Sopenharmony_ci			vsi_num, status);
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	/* configure RSS for udp4 with input set IP src/dst, UDP src/dst */
165762306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4,
165862306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4);
165962306a36Sopenharmony_ci	if (status)
166062306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %d\n",
166162306a36Sopenharmony_ci			vsi_num, status);
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci	/* configure RSS for sctp4 with input set IP src/dst */
166462306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
166562306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4);
166662306a36Sopenharmony_ci	if (status)
166762306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %d\n",
166862306a36Sopenharmony_ci			vsi_num, status);
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	/* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */
167162306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6,
167262306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6);
167362306a36Sopenharmony_ci	if (status)
167462306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %d\n",
167562306a36Sopenharmony_ci			vsi_num, status);
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	/* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */
167862306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6,
167962306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6);
168062306a36Sopenharmony_ci	if (status)
168162306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %d\n",
168262306a36Sopenharmony_ci			vsi_num, status);
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	/* configure RSS for sctp6 with input set IPv6 src/dst */
168562306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
168662306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6);
168762306a36Sopenharmony_ci	if (status)
168862306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %d\n",
168962306a36Sopenharmony_ci			vsi_num, status);
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_ESP_SPI,
169262306a36Sopenharmony_ci				 ICE_FLOW_SEG_HDR_ESP);
169362306a36Sopenharmony_ci	if (status)
169462306a36Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for esp/spi flow, vsi = %d, error = %d\n",
169562306a36Sopenharmony_ci			vsi_num, status);
169662306a36Sopenharmony_ci}
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci/**
169962306a36Sopenharmony_ci * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
170062306a36Sopenharmony_ci * @vsi: VSI
170162306a36Sopenharmony_ci */
170262306a36Sopenharmony_cistatic void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
170362306a36Sopenharmony_ci{
170462306a36Sopenharmony_ci	if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
170562306a36Sopenharmony_ci		vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX;
170662306a36Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_1664;
170762306a36Sopenharmony_ci#if (PAGE_SIZE < 8192)
170862306a36Sopenharmony_ci	} else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
170962306a36Sopenharmony_ci		   (vsi->netdev->mtu <= ETH_DATA_LEN)) {
171062306a36Sopenharmony_ci		vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
171162306a36Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
171262306a36Sopenharmony_ci#endif
171362306a36Sopenharmony_ci	} else {
171462306a36Sopenharmony_ci		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
171562306a36Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_3072;
171662306a36Sopenharmony_ci	}
171762306a36Sopenharmony_ci}
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci/**
172062306a36Sopenharmony_ci * ice_pf_state_is_nominal - checks the PF for nominal state
172162306a36Sopenharmony_ci * @pf: pointer to PF to check
172262306a36Sopenharmony_ci *
172362306a36Sopenharmony_ci * Check the PF's state for a collection of bits that would indicate
172462306a36Sopenharmony_ci * the PF is in a state that would inhibit normal operation for
172562306a36Sopenharmony_ci * driver functionality.
172662306a36Sopenharmony_ci *
172762306a36Sopenharmony_ci * Returns true if PF is in a nominal state, false otherwise
172862306a36Sopenharmony_ci */
172962306a36Sopenharmony_cibool ice_pf_state_is_nominal(struct ice_pf *pf)
173062306a36Sopenharmony_ci{
173162306a36Sopenharmony_ci	DECLARE_BITMAP(check_bits, ICE_STATE_NBITS) = { 0 };
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	if (!pf)
173462306a36Sopenharmony_ci		return false;
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	bitmap_set(check_bits, 0, ICE_STATE_NOMINAL_CHECK_BITS);
173762306a36Sopenharmony_ci	if (bitmap_intersects(pf->state, check_bits, ICE_STATE_NBITS))
173862306a36Sopenharmony_ci		return false;
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	return true;
174162306a36Sopenharmony_ci}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci/**
174462306a36Sopenharmony_ci * ice_update_eth_stats - Update VSI-specific ethernet statistics counters
174562306a36Sopenharmony_ci * @vsi: the VSI to be updated
174662306a36Sopenharmony_ci */
174762306a36Sopenharmony_civoid ice_update_eth_stats(struct ice_vsi *vsi)
174862306a36Sopenharmony_ci{
174962306a36Sopenharmony_ci	struct ice_eth_stats *prev_es, *cur_es;
175062306a36Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
175162306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
175262306a36Sopenharmony_ci	u16 vsi_num = vsi->vsi_num;    /* HW absolute index of a VSI */
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	prev_es = &vsi->eth_stats_prev;
175562306a36Sopenharmony_ci	cur_es = &vsi->eth_stats;
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state))
175862306a36Sopenharmony_ci		vsi->stat_offsets_loaded = false;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded,
176162306a36Sopenharmony_ci			  &prev_es->rx_bytes, &cur_es->rx_bytes);
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded,
176462306a36Sopenharmony_ci			  &prev_es->rx_unicast, &cur_es->rx_unicast);
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded,
176762306a36Sopenharmony_ci			  &prev_es->rx_multicast, &cur_es->rx_multicast);
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded,
177062306a36Sopenharmony_ci			  &prev_es->rx_broadcast, &cur_es->rx_broadcast);
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded,
177362306a36Sopenharmony_ci			  &prev_es->rx_discards, &cur_es->rx_discards);
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded,
177662306a36Sopenharmony_ci			  &prev_es->tx_bytes, &cur_es->tx_bytes);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded,
177962306a36Sopenharmony_ci			  &prev_es->tx_unicast, &cur_es->tx_unicast);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded,
178262306a36Sopenharmony_ci			  &prev_es->tx_multicast, &cur_es->tx_multicast);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded,
178562306a36Sopenharmony_ci			  &prev_es->tx_broadcast, &cur_es->tx_broadcast);
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded,
178862306a36Sopenharmony_ci			  &prev_es->tx_errors, &cur_es->tx_errors);
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	vsi->stat_offsets_loaded = true;
179162306a36Sopenharmony_ci}
179262306a36Sopenharmony_ci
179362306a36Sopenharmony_ci/**
179462306a36Sopenharmony_ci * ice_write_qrxflxp_cntxt - write/configure QRXFLXP_CNTXT register
179562306a36Sopenharmony_ci * @hw: HW pointer
179662306a36Sopenharmony_ci * @pf_q: index of the Rx queue in the PF's queue space
179762306a36Sopenharmony_ci * @rxdid: flexible descriptor RXDID
179862306a36Sopenharmony_ci * @prio: priority for the RXDID for this queue
179962306a36Sopenharmony_ci * @ena_ts: true to enable timestamp and false to disable timestamp
180062306a36Sopenharmony_ci */
180162306a36Sopenharmony_civoid
180262306a36Sopenharmony_ciice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio,
180362306a36Sopenharmony_ci			bool ena_ts)
180462306a36Sopenharmony_ci{
180562306a36Sopenharmony_ci	int regval = rd32(hw, QRXFLXP_CNTXT(pf_q));
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	/* clear any previous values */
180862306a36Sopenharmony_ci	regval &= ~(QRXFLXP_CNTXT_RXDID_IDX_M |
180962306a36Sopenharmony_ci		    QRXFLXP_CNTXT_RXDID_PRIO_M |
181062306a36Sopenharmony_ci		    QRXFLXP_CNTXT_TS_M);
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	regval |= (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) &
181362306a36Sopenharmony_ci		QRXFLXP_CNTXT_RXDID_IDX_M;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	regval |= (prio << QRXFLXP_CNTXT_RXDID_PRIO_S) &
181662306a36Sopenharmony_ci		QRXFLXP_CNTXT_RXDID_PRIO_M;
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	if (ena_ts)
181962306a36Sopenharmony_ci		/* Enable TimeSync on this queue */
182062306a36Sopenharmony_ci		regval |= QRXFLXP_CNTXT_TS_M;
182162306a36Sopenharmony_ci
182262306a36Sopenharmony_ci	wr32(hw, QRXFLXP_CNTXT(pf_q), regval);
182362306a36Sopenharmony_ci}
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ciint ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx)
182662306a36Sopenharmony_ci{
182762306a36Sopenharmony_ci	if (q_idx >= vsi->num_rxq)
182862306a36Sopenharmony_ci		return -EINVAL;
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci	return ice_vsi_cfg_rxq(vsi->rx_rings[q_idx]);
183162306a36Sopenharmony_ci}
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ciint ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings, u16 q_idx)
183462306a36Sopenharmony_ci{
183562306a36Sopenharmony_ci	struct ice_aqc_add_tx_qgrp *qg_buf;
183662306a36Sopenharmony_ci	int err;
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	if (q_idx >= vsi->alloc_txq || !tx_rings || !tx_rings[q_idx])
183962306a36Sopenharmony_ci		return -EINVAL;
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	qg_buf = kzalloc(struct_size(qg_buf, txqs, 1), GFP_KERNEL);
184262306a36Sopenharmony_ci	if (!qg_buf)
184362306a36Sopenharmony_ci		return -ENOMEM;
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	qg_buf->num_txqs = 1;
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci	err = ice_vsi_cfg_txq(vsi, tx_rings[q_idx], qg_buf);
184862306a36Sopenharmony_ci	kfree(qg_buf);
184962306a36Sopenharmony_ci	return err;
185062306a36Sopenharmony_ci}
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci/**
185362306a36Sopenharmony_ci * ice_vsi_cfg_rxqs - Configure the VSI for Rx
185462306a36Sopenharmony_ci * @vsi: the VSI being configured
185562306a36Sopenharmony_ci *
185662306a36Sopenharmony_ci * Return 0 on success and a negative value on error
185762306a36Sopenharmony_ci * Configure the Rx VSI for operation.
185862306a36Sopenharmony_ci */
185962306a36Sopenharmony_ciint ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
186062306a36Sopenharmony_ci{
186162306a36Sopenharmony_ci	u16 i;
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
186462306a36Sopenharmony_ci		goto setup_rings;
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	ice_vsi_cfg_frame_size(vsi);
186762306a36Sopenharmony_cisetup_rings:
186862306a36Sopenharmony_ci	/* set up individual rings */
186962306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i) {
187062306a36Sopenharmony_ci		int err = ice_vsi_cfg_rxq(vsi->rx_rings[i]);
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci		if (err)
187362306a36Sopenharmony_ci			return err;
187462306a36Sopenharmony_ci	}
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci	return 0;
187762306a36Sopenharmony_ci}
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci/**
188062306a36Sopenharmony_ci * ice_vsi_cfg_txqs - Configure the VSI for Tx
188162306a36Sopenharmony_ci * @vsi: the VSI being configured
188262306a36Sopenharmony_ci * @rings: Tx ring array to be configured
188362306a36Sopenharmony_ci * @count: number of Tx ring array elements
188462306a36Sopenharmony_ci *
188562306a36Sopenharmony_ci * Return 0 on success and a negative value on error
188662306a36Sopenharmony_ci * Configure the Tx VSI for operation.
188762306a36Sopenharmony_ci */
188862306a36Sopenharmony_cistatic int
188962306a36Sopenharmony_ciice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_tx_ring **rings, u16 count)
189062306a36Sopenharmony_ci{
189162306a36Sopenharmony_ci	struct ice_aqc_add_tx_qgrp *qg_buf;
189262306a36Sopenharmony_ci	u16 q_idx = 0;
189362306a36Sopenharmony_ci	int err = 0;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	qg_buf = kzalloc(struct_size(qg_buf, txqs, 1), GFP_KERNEL);
189662306a36Sopenharmony_ci	if (!qg_buf)
189762306a36Sopenharmony_ci		return -ENOMEM;
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	qg_buf->num_txqs = 1;
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	for (q_idx = 0; q_idx < count; q_idx++) {
190262306a36Sopenharmony_ci		err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf);
190362306a36Sopenharmony_ci		if (err)
190462306a36Sopenharmony_ci			goto err_cfg_txqs;
190562306a36Sopenharmony_ci	}
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_cierr_cfg_txqs:
190862306a36Sopenharmony_ci	kfree(qg_buf);
190962306a36Sopenharmony_ci	return err;
191062306a36Sopenharmony_ci}
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci/**
191362306a36Sopenharmony_ci * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
191462306a36Sopenharmony_ci * @vsi: the VSI being configured
191562306a36Sopenharmony_ci *
191662306a36Sopenharmony_ci * Return 0 on success and a negative value on error
191762306a36Sopenharmony_ci * Configure the Tx VSI for operation.
191862306a36Sopenharmony_ci */
191962306a36Sopenharmony_ciint ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
192062306a36Sopenharmony_ci{
192162306a36Sopenharmony_ci	return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, vsi->num_txq);
192262306a36Sopenharmony_ci}
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci/**
192562306a36Sopenharmony_ci * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI
192662306a36Sopenharmony_ci * @vsi: the VSI being configured
192762306a36Sopenharmony_ci *
192862306a36Sopenharmony_ci * Return 0 on success and a negative value on error
192962306a36Sopenharmony_ci * Configure the Tx queues dedicated for XDP in given VSI for operation.
193062306a36Sopenharmony_ci */
193162306a36Sopenharmony_ciint ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
193262306a36Sopenharmony_ci{
193362306a36Sopenharmony_ci	int ret;
193462306a36Sopenharmony_ci	int i;
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings, vsi->num_xdp_txq);
193762306a36Sopenharmony_ci	if (ret)
193862306a36Sopenharmony_ci		return ret;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i)
194162306a36Sopenharmony_ci		ice_tx_xsk_pool(vsi, i);
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	return 0;
194462306a36Sopenharmony_ci}
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci/**
194762306a36Sopenharmony_ci * ice_intrl_usec_to_reg - convert interrupt rate limit to register value
194862306a36Sopenharmony_ci * @intrl: interrupt rate limit in usecs
194962306a36Sopenharmony_ci * @gran: interrupt rate limit granularity in usecs
195062306a36Sopenharmony_ci *
195162306a36Sopenharmony_ci * This function converts a decimal interrupt rate limit in usecs to the format
195262306a36Sopenharmony_ci * expected by firmware.
195362306a36Sopenharmony_ci */
195462306a36Sopenharmony_cistatic u32 ice_intrl_usec_to_reg(u8 intrl, u8 gran)
195562306a36Sopenharmony_ci{
195662306a36Sopenharmony_ci	u32 val = intrl / gran;
195762306a36Sopenharmony_ci
195862306a36Sopenharmony_ci	if (val)
195962306a36Sopenharmony_ci		return val | GLINT_RATE_INTRL_ENA_M;
196062306a36Sopenharmony_ci	return 0;
196162306a36Sopenharmony_ci}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci/**
196462306a36Sopenharmony_ci * ice_write_intrl - write throttle rate limit to interrupt specific register
196562306a36Sopenharmony_ci * @q_vector: pointer to interrupt specific structure
196662306a36Sopenharmony_ci * @intrl: throttle rate limit in microseconds to write
196762306a36Sopenharmony_ci */
196862306a36Sopenharmony_civoid ice_write_intrl(struct ice_q_vector *q_vector, u8 intrl)
196962306a36Sopenharmony_ci{
197062306a36Sopenharmony_ci	struct ice_hw *hw = &q_vector->vsi->back->hw;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	wr32(hw, GLINT_RATE(q_vector->reg_idx),
197362306a36Sopenharmony_ci	     ice_intrl_usec_to_reg(intrl, ICE_INTRL_GRAN_ABOVE_25));
197462306a36Sopenharmony_ci}
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_cistatic struct ice_q_vector *ice_pull_qvec_from_rc(struct ice_ring_container *rc)
197762306a36Sopenharmony_ci{
197862306a36Sopenharmony_ci	switch (rc->type) {
197962306a36Sopenharmony_ci	case ICE_RX_CONTAINER:
198062306a36Sopenharmony_ci		if (rc->rx_ring)
198162306a36Sopenharmony_ci			return rc->rx_ring->q_vector;
198262306a36Sopenharmony_ci		break;
198362306a36Sopenharmony_ci	case ICE_TX_CONTAINER:
198462306a36Sopenharmony_ci		if (rc->tx_ring)
198562306a36Sopenharmony_ci			return rc->tx_ring->q_vector;
198662306a36Sopenharmony_ci		break;
198762306a36Sopenharmony_ci	default:
198862306a36Sopenharmony_ci		break;
198962306a36Sopenharmony_ci	}
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	return NULL;
199262306a36Sopenharmony_ci}
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci/**
199562306a36Sopenharmony_ci * __ice_write_itr - write throttle rate to register
199662306a36Sopenharmony_ci * @q_vector: pointer to interrupt data structure
199762306a36Sopenharmony_ci * @rc: pointer to ring container
199862306a36Sopenharmony_ci * @itr: throttle rate in microseconds to write
199962306a36Sopenharmony_ci */
200062306a36Sopenharmony_cistatic void __ice_write_itr(struct ice_q_vector *q_vector,
200162306a36Sopenharmony_ci			    struct ice_ring_container *rc, u16 itr)
200262306a36Sopenharmony_ci{
200362306a36Sopenharmony_ci	struct ice_hw *hw = &q_vector->vsi->back->hw;
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_ci	wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx),
200662306a36Sopenharmony_ci	     ITR_REG_ALIGN(itr) >> ICE_ITR_GRAN_S);
200762306a36Sopenharmony_ci}
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci/**
201062306a36Sopenharmony_ci * ice_write_itr - write throttle rate to queue specific register
201162306a36Sopenharmony_ci * @rc: pointer to ring container
201262306a36Sopenharmony_ci * @itr: throttle rate in microseconds to write
201362306a36Sopenharmony_ci */
201462306a36Sopenharmony_civoid ice_write_itr(struct ice_ring_container *rc, u16 itr)
201562306a36Sopenharmony_ci{
201662306a36Sopenharmony_ci	struct ice_q_vector *q_vector;
201762306a36Sopenharmony_ci
201862306a36Sopenharmony_ci	q_vector = ice_pull_qvec_from_rc(rc);
201962306a36Sopenharmony_ci	if (!q_vector)
202062306a36Sopenharmony_ci		return;
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	__ice_write_itr(q_vector, rc, itr);
202362306a36Sopenharmony_ci}
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci/**
202662306a36Sopenharmony_ci * ice_set_q_vector_intrl - set up interrupt rate limiting
202762306a36Sopenharmony_ci * @q_vector: the vector to be configured
202862306a36Sopenharmony_ci *
202962306a36Sopenharmony_ci * Interrupt rate limiting is local to the vector, not per-queue so we must
203062306a36Sopenharmony_ci * detect if either ring container has dynamic moderation enabled to decide
203162306a36Sopenharmony_ci * what to set the interrupt rate limit to via INTRL settings. In the case that
203262306a36Sopenharmony_ci * dynamic moderation is disabled on both, write the value with the cached
203362306a36Sopenharmony_ci * setting to make sure INTRL register matches the user visible value.
203462306a36Sopenharmony_ci */
203562306a36Sopenharmony_civoid ice_set_q_vector_intrl(struct ice_q_vector *q_vector)
203662306a36Sopenharmony_ci{
203762306a36Sopenharmony_ci	if (ITR_IS_DYNAMIC(&q_vector->tx) || ITR_IS_DYNAMIC(&q_vector->rx)) {
203862306a36Sopenharmony_ci		/* in the case of dynamic enabled, cap each vector to no more
203962306a36Sopenharmony_ci		 * than (4 us) 250,000 ints/sec, which allows low latency
204062306a36Sopenharmony_ci		 * but still less than 500,000 interrupts per second, which
204162306a36Sopenharmony_ci		 * reduces CPU a bit in the case of the lowest latency
204262306a36Sopenharmony_ci		 * setting. The 4 here is a value in microseconds.
204362306a36Sopenharmony_ci		 */
204462306a36Sopenharmony_ci		ice_write_intrl(q_vector, 4);
204562306a36Sopenharmony_ci	} else {
204662306a36Sopenharmony_ci		ice_write_intrl(q_vector, q_vector->intrl);
204762306a36Sopenharmony_ci	}
204862306a36Sopenharmony_ci}
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci/**
205162306a36Sopenharmony_ci * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW
205262306a36Sopenharmony_ci * @vsi: the VSI being configured
205362306a36Sopenharmony_ci *
205462306a36Sopenharmony_ci * This configures MSIX mode interrupts for the PF VSI, and should not be used
205562306a36Sopenharmony_ci * for the VF VSI.
205662306a36Sopenharmony_ci */
205762306a36Sopenharmony_civoid ice_vsi_cfg_msix(struct ice_vsi *vsi)
205862306a36Sopenharmony_ci{
205962306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
206062306a36Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
206162306a36Sopenharmony_ci	u16 txq = 0, rxq = 0;
206262306a36Sopenharmony_ci	int i, q;
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
206562306a36Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
206662306a36Sopenharmony_ci		u16 reg_idx = q_vector->reg_idx;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci		ice_cfg_itr(hw, q_vector);
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci		/* Both Transmit Queue Interrupt Cause Control register
207162306a36Sopenharmony_ci		 * and Receive Queue Interrupt Cause control register
207262306a36Sopenharmony_ci		 * expects MSIX_INDX field to be the vector index
207362306a36Sopenharmony_ci		 * within the function space and not the absolute
207462306a36Sopenharmony_ci		 * vector index across PF or across device.
207562306a36Sopenharmony_ci		 * For SR-IOV VF VSIs queue vector index always starts
207662306a36Sopenharmony_ci		 * with 1 since first vector index(0) is used for OICR
207762306a36Sopenharmony_ci		 * in VF space. Since VMDq and other PF VSIs are within
207862306a36Sopenharmony_ci		 * the PF function space, use the vector index that is
207962306a36Sopenharmony_ci		 * tracked for this PF.
208062306a36Sopenharmony_ci		 */
208162306a36Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_tx; q++) {
208262306a36Sopenharmony_ci			ice_cfg_txq_interrupt(vsi, txq, reg_idx,
208362306a36Sopenharmony_ci					      q_vector->tx.itr_idx);
208462306a36Sopenharmony_ci			txq++;
208562306a36Sopenharmony_ci		}
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_rx; q++) {
208862306a36Sopenharmony_ci			ice_cfg_rxq_interrupt(vsi, rxq, reg_idx,
208962306a36Sopenharmony_ci					      q_vector->rx.itr_idx);
209062306a36Sopenharmony_ci			rxq++;
209162306a36Sopenharmony_ci		}
209262306a36Sopenharmony_ci	}
209362306a36Sopenharmony_ci}
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci/**
209662306a36Sopenharmony_ci * ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings
209762306a36Sopenharmony_ci * @vsi: the VSI whose rings are to be enabled
209862306a36Sopenharmony_ci *
209962306a36Sopenharmony_ci * Returns 0 on success and a negative value on error
210062306a36Sopenharmony_ci */
210162306a36Sopenharmony_ciint ice_vsi_start_all_rx_rings(struct ice_vsi *vsi)
210262306a36Sopenharmony_ci{
210362306a36Sopenharmony_ci	return ice_vsi_ctrl_all_rx_rings(vsi, true);
210462306a36Sopenharmony_ci}
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci/**
210762306a36Sopenharmony_ci * ice_vsi_stop_all_rx_rings - stop/disable all of a VSI's Rx rings
210862306a36Sopenharmony_ci * @vsi: the VSI whose rings are to be disabled
210962306a36Sopenharmony_ci *
211062306a36Sopenharmony_ci * Returns 0 on success and a negative value on error
211162306a36Sopenharmony_ci */
211262306a36Sopenharmony_ciint ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi)
211362306a36Sopenharmony_ci{
211462306a36Sopenharmony_ci	return ice_vsi_ctrl_all_rx_rings(vsi, false);
211562306a36Sopenharmony_ci}
211662306a36Sopenharmony_ci
211762306a36Sopenharmony_ci/**
211862306a36Sopenharmony_ci * ice_vsi_stop_tx_rings - Disable Tx rings
211962306a36Sopenharmony_ci * @vsi: the VSI being configured
212062306a36Sopenharmony_ci * @rst_src: reset source
212162306a36Sopenharmony_ci * @rel_vmvf_num: Relative ID of VF/VM
212262306a36Sopenharmony_ci * @rings: Tx ring array to be stopped
212362306a36Sopenharmony_ci * @count: number of Tx ring array elements
212462306a36Sopenharmony_ci */
212562306a36Sopenharmony_cistatic int
212662306a36Sopenharmony_ciice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
212762306a36Sopenharmony_ci		      u16 rel_vmvf_num, struct ice_tx_ring **rings, u16 count)
212862306a36Sopenharmony_ci{
212962306a36Sopenharmony_ci	u16 q_idx;
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_ci	if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS)
213262306a36Sopenharmony_ci		return -EINVAL;
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci	for (q_idx = 0; q_idx < count; q_idx++) {
213562306a36Sopenharmony_ci		struct ice_txq_meta txq_meta = { };
213662306a36Sopenharmony_ci		int status;
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci		if (!rings || !rings[q_idx])
213962306a36Sopenharmony_ci			return -EINVAL;
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci		ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta);
214262306a36Sopenharmony_ci		status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num,
214362306a36Sopenharmony_ci					      rings[q_idx], &txq_meta);
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci		if (status)
214662306a36Sopenharmony_ci			return status;
214762306a36Sopenharmony_ci	}
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci	return 0;
215062306a36Sopenharmony_ci}
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci/**
215362306a36Sopenharmony_ci * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings
215462306a36Sopenharmony_ci * @vsi: the VSI being configured
215562306a36Sopenharmony_ci * @rst_src: reset source
215662306a36Sopenharmony_ci * @rel_vmvf_num: Relative ID of VF/VM
215762306a36Sopenharmony_ci */
215862306a36Sopenharmony_ciint
215962306a36Sopenharmony_ciice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
216062306a36Sopenharmony_ci			  u16 rel_vmvf_num)
216162306a36Sopenharmony_ci{
216262306a36Sopenharmony_ci	return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings, vsi->num_txq);
216362306a36Sopenharmony_ci}
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci/**
216662306a36Sopenharmony_ci * ice_vsi_stop_xdp_tx_rings - Disable XDP Tx rings
216762306a36Sopenharmony_ci * @vsi: the VSI being configured
216862306a36Sopenharmony_ci */
216962306a36Sopenharmony_ciint ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi)
217062306a36Sopenharmony_ci{
217162306a36Sopenharmony_ci	return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings, vsi->num_xdp_txq);
217262306a36Sopenharmony_ci}
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci/**
217562306a36Sopenharmony_ci * ice_vsi_is_rx_queue_active
217662306a36Sopenharmony_ci * @vsi: the VSI being configured
217762306a36Sopenharmony_ci *
217862306a36Sopenharmony_ci * Return true if at least one queue is active.
217962306a36Sopenharmony_ci */
218062306a36Sopenharmony_cibool ice_vsi_is_rx_queue_active(struct ice_vsi *vsi)
218162306a36Sopenharmony_ci{
218262306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
218362306a36Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
218462306a36Sopenharmony_ci	int i;
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i) {
218762306a36Sopenharmony_ci		u32 rx_reg;
218862306a36Sopenharmony_ci		int pf_q;
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci		pf_q = vsi->rxq_map[i];
219162306a36Sopenharmony_ci		rx_reg = rd32(hw, QRX_CTRL(pf_q));
219262306a36Sopenharmony_ci		if (rx_reg & QRX_CTRL_QENA_STAT_M)
219362306a36Sopenharmony_ci			return true;
219462306a36Sopenharmony_ci	}
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	return false;
219762306a36Sopenharmony_ci}
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_cistatic void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
220062306a36Sopenharmony_ci{
220162306a36Sopenharmony_ci	if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
220262306a36Sopenharmony_ci		vsi->tc_cfg.ena_tc = ICE_DFLT_TRAFFIC_CLASS;
220362306a36Sopenharmony_ci		vsi->tc_cfg.numtc = 1;
220462306a36Sopenharmony_ci		return;
220562306a36Sopenharmony_ci	}
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	/* set VSI TC information based on DCB config */
220862306a36Sopenharmony_ci	ice_vsi_set_dcb_tc_cfg(vsi);
220962306a36Sopenharmony_ci}
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci/**
221262306a36Sopenharmony_ci * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
221362306a36Sopenharmony_ci * @vsi: the VSI being configured
221462306a36Sopenharmony_ci * @tx: bool to determine Tx or Rx rule
221562306a36Sopenharmony_ci * @create: bool to determine create or remove Rule
221662306a36Sopenharmony_ci */
221762306a36Sopenharmony_civoid ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create)
221862306a36Sopenharmony_ci{
221962306a36Sopenharmony_ci	int (*eth_fltr)(struct ice_vsi *v, u16 type, u16 flag,
222062306a36Sopenharmony_ci			enum ice_sw_fwd_act_type act);
222162306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
222262306a36Sopenharmony_ci	struct device *dev;
222362306a36Sopenharmony_ci	int status;
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
222662306a36Sopenharmony_ci	eth_fltr = create ? ice_fltr_add_eth : ice_fltr_remove_eth;
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	if (tx) {
222962306a36Sopenharmony_ci		status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_TX,
223062306a36Sopenharmony_ci				  ICE_DROP_PACKET);
223162306a36Sopenharmony_ci	} else {
223262306a36Sopenharmony_ci		if (ice_fw_supports_lldp_fltr_ctrl(&pf->hw)) {
223362306a36Sopenharmony_ci			status = ice_lldp_fltr_add_remove(&pf->hw, vsi->vsi_num,
223462306a36Sopenharmony_ci							  create);
223562306a36Sopenharmony_ci		} else {
223662306a36Sopenharmony_ci			status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_RX,
223762306a36Sopenharmony_ci					  ICE_FWD_TO_VSI);
223862306a36Sopenharmony_ci		}
223962306a36Sopenharmony_ci	}
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	if (status)
224262306a36Sopenharmony_ci		dev_dbg(dev, "Fail %s %s LLDP rule on VSI %i error: %d\n",
224362306a36Sopenharmony_ci			create ? "adding" : "removing", tx ? "TX" : "RX",
224462306a36Sopenharmony_ci			vsi->vsi_num, status);
224562306a36Sopenharmony_ci}
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci/**
224862306a36Sopenharmony_ci * ice_set_agg_vsi - sets up scheduler aggregator node and move VSI into it
224962306a36Sopenharmony_ci * @vsi: pointer to the VSI
225062306a36Sopenharmony_ci *
225162306a36Sopenharmony_ci * This function will allocate new scheduler aggregator now if needed and will
225262306a36Sopenharmony_ci * move specified VSI into it.
225362306a36Sopenharmony_ci */
225462306a36Sopenharmony_cistatic void ice_set_agg_vsi(struct ice_vsi *vsi)
225562306a36Sopenharmony_ci{
225662306a36Sopenharmony_ci	struct device *dev = ice_pf_to_dev(vsi->back);
225762306a36Sopenharmony_ci	struct ice_agg_node *agg_node_iter = NULL;
225862306a36Sopenharmony_ci	u32 agg_id = ICE_INVALID_AGG_NODE_ID;
225962306a36Sopenharmony_ci	struct ice_agg_node *agg_node = NULL;
226062306a36Sopenharmony_ci	int node_offset, max_agg_nodes = 0;
226162306a36Sopenharmony_ci	struct ice_port_info *port_info;
226262306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
226362306a36Sopenharmony_ci	u32 agg_node_id_start = 0;
226462306a36Sopenharmony_ci	int status;
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	/* create (as needed) scheduler aggregator node and move VSI into
226762306a36Sopenharmony_ci	 * corresponding aggregator node
226862306a36Sopenharmony_ci	 * - PF aggregator node to contains VSIs of type _PF and _CTRL
226962306a36Sopenharmony_ci	 * - VF aggregator nodes will contain VF VSI
227062306a36Sopenharmony_ci	 */
227162306a36Sopenharmony_ci	port_info = pf->hw.port_info;
227262306a36Sopenharmony_ci	if (!port_info)
227362306a36Sopenharmony_ci		return;
227462306a36Sopenharmony_ci
227562306a36Sopenharmony_ci	switch (vsi->type) {
227662306a36Sopenharmony_ci	case ICE_VSI_CTRL:
227762306a36Sopenharmony_ci	case ICE_VSI_CHNL:
227862306a36Sopenharmony_ci	case ICE_VSI_LB:
227962306a36Sopenharmony_ci	case ICE_VSI_PF:
228062306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
228162306a36Sopenharmony_ci		max_agg_nodes = ICE_MAX_PF_AGG_NODES;
228262306a36Sopenharmony_ci		agg_node_id_start = ICE_PF_AGG_NODE_ID_START;
228362306a36Sopenharmony_ci		agg_node_iter = &pf->pf_agg_node[0];
228462306a36Sopenharmony_ci		break;
228562306a36Sopenharmony_ci	case ICE_VSI_VF:
228662306a36Sopenharmony_ci		/* user can create 'n' VFs on a given PF, but since max children
228762306a36Sopenharmony_ci		 * per aggregator node can be only 64. Following code handles
228862306a36Sopenharmony_ci		 * aggregator(s) for VF VSIs, either selects a agg_node which
228962306a36Sopenharmony_ci		 * was already created provided num_vsis < 64, otherwise
229062306a36Sopenharmony_ci		 * select next available node, which will be created
229162306a36Sopenharmony_ci		 */
229262306a36Sopenharmony_ci		max_agg_nodes = ICE_MAX_VF_AGG_NODES;
229362306a36Sopenharmony_ci		agg_node_id_start = ICE_VF_AGG_NODE_ID_START;
229462306a36Sopenharmony_ci		agg_node_iter = &pf->vf_agg_node[0];
229562306a36Sopenharmony_ci		break;
229662306a36Sopenharmony_ci	default:
229762306a36Sopenharmony_ci		/* other VSI type, handle later if needed */
229862306a36Sopenharmony_ci		dev_dbg(dev, "unexpected VSI type %s\n",
229962306a36Sopenharmony_ci			ice_vsi_type_str(vsi->type));
230062306a36Sopenharmony_ci		return;
230162306a36Sopenharmony_ci	}
230262306a36Sopenharmony_ci
230362306a36Sopenharmony_ci	/* find the appropriate aggregator node */
230462306a36Sopenharmony_ci	for (node_offset = 0; node_offset < max_agg_nodes; node_offset++) {
230562306a36Sopenharmony_ci		/* see if we can find space in previously created
230662306a36Sopenharmony_ci		 * node if num_vsis < 64, otherwise skip
230762306a36Sopenharmony_ci		 */
230862306a36Sopenharmony_ci		if (agg_node_iter->num_vsis &&
230962306a36Sopenharmony_ci		    agg_node_iter->num_vsis == ICE_MAX_VSIS_IN_AGG_NODE) {
231062306a36Sopenharmony_ci			agg_node_iter++;
231162306a36Sopenharmony_ci			continue;
231262306a36Sopenharmony_ci		}
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_ci		if (agg_node_iter->valid &&
231562306a36Sopenharmony_ci		    agg_node_iter->agg_id != ICE_INVALID_AGG_NODE_ID) {
231662306a36Sopenharmony_ci			agg_id = agg_node_iter->agg_id;
231762306a36Sopenharmony_ci			agg_node = agg_node_iter;
231862306a36Sopenharmony_ci			break;
231962306a36Sopenharmony_ci		}
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci		/* find unclaimed agg_id */
232262306a36Sopenharmony_ci		if (agg_node_iter->agg_id == ICE_INVALID_AGG_NODE_ID) {
232362306a36Sopenharmony_ci			agg_id = node_offset + agg_node_id_start;
232462306a36Sopenharmony_ci			agg_node = agg_node_iter;
232562306a36Sopenharmony_ci			break;
232662306a36Sopenharmony_ci		}
232762306a36Sopenharmony_ci		/* move to next agg_node */
232862306a36Sopenharmony_ci		agg_node_iter++;
232962306a36Sopenharmony_ci	}
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	if (!agg_node)
233262306a36Sopenharmony_ci		return;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	/* if selected aggregator node was not created, create it */
233562306a36Sopenharmony_ci	if (!agg_node->valid) {
233662306a36Sopenharmony_ci		status = ice_cfg_agg(port_info, agg_id, ICE_AGG_TYPE_AGG,
233762306a36Sopenharmony_ci				     (u8)vsi->tc_cfg.ena_tc);
233862306a36Sopenharmony_ci		if (status) {
233962306a36Sopenharmony_ci			dev_err(dev, "unable to create aggregator node with agg_id %u\n",
234062306a36Sopenharmony_ci				agg_id);
234162306a36Sopenharmony_ci			return;
234262306a36Sopenharmony_ci		}
234362306a36Sopenharmony_ci		/* aggregator node is created, store the needed info */
234462306a36Sopenharmony_ci		agg_node->valid = true;
234562306a36Sopenharmony_ci		agg_node->agg_id = agg_id;
234662306a36Sopenharmony_ci	}
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci	/* move VSI to corresponding aggregator node */
234962306a36Sopenharmony_ci	status = ice_move_vsi_to_agg(port_info, agg_id, vsi->idx,
235062306a36Sopenharmony_ci				     (u8)vsi->tc_cfg.ena_tc);
235162306a36Sopenharmony_ci	if (status) {
235262306a36Sopenharmony_ci		dev_err(dev, "unable to move VSI idx %u into aggregator %u node",
235362306a36Sopenharmony_ci			vsi->idx, agg_id);
235462306a36Sopenharmony_ci		return;
235562306a36Sopenharmony_ci	}
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_ci	/* keep active children count for aggregator node */
235862306a36Sopenharmony_ci	agg_node->num_vsis++;
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	/* cache the 'agg_id' in VSI, so that after reset - VSI will be moved
236162306a36Sopenharmony_ci	 * to aggregator node
236262306a36Sopenharmony_ci	 */
236362306a36Sopenharmony_ci	vsi->agg_node = agg_node;
236462306a36Sopenharmony_ci	dev_dbg(dev, "successfully moved VSI idx %u tc_bitmap 0x%x) into aggregator node %d which has num_vsis %u\n",
236562306a36Sopenharmony_ci		vsi->idx, vsi->tc_cfg.ena_tc, vsi->agg_node->agg_id,
236662306a36Sopenharmony_ci		vsi->agg_node->num_vsis);
236762306a36Sopenharmony_ci}
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_cistatic int ice_vsi_cfg_tc_lan(struct ice_pf *pf, struct ice_vsi *vsi)
237062306a36Sopenharmony_ci{
237162306a36Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
237262306a36Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
237362306a36Sopenharmony_ci	int ret, i;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci	/* configure VSI nodes based on number of queues and TC's */
237662306a36Sopenharmony_ci	ice_for_each_traffic_class(i) {
237762306a36Sopenharmony_ci		if (!(vsi->tc_cfg.ena_tc & BIT(i)))
237862306a36Sopenharmony_ci			continue;
237962306a36Sopenharmony_ci
238062306a36Sopenharmony_ci		if (vsi->type == ICE_VSI_CHNL) {
238162306a36Sopenharmony_ci			if (!vsi->alloc_txq && vsi->num_txq)
238262306a36Sopenharmony_ci				max_txqs[i] = vsi->num_txq;
238362306a36Sopenharmony_ci			else
238462306a36Sopenharmony_ci				max_txqs[i] = pf->num_lan_tx;
238562306a36Sopenharmony_ci		} else {
238662306a36Sopenharmony_ci			max_txqs[i] = vsi->alloc_txq;
238762306a36Sopenharmony_ci		}
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci		if (vsi->type == ICE_VSI_PF)
239062306a36Sopenharmony_ci			max_txqs[i] += vsi->num_xdp_txq;
239162306a36Sopenharmony_ci	}
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	dev_dbg(dev, "vsi->tc_cfg.ena_tc = %d\n", vsi->tc_cfg.ena_tc);
239462306a36Sopenharmony_ci	ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
239562306a36Sopenharmony_ci			      max_txqs);
239662306a36Sopenharmony_ci	if (ret) {
239762306a36Sopenharmony_ci		dev_err(dev, "VSI %d failed lan queue config, error %d\n",
239862306a36Sopenharmony_ci			vsi->vsi_num, ret);
239962306a36Sopenharmony_ci		return ret;
240062306a36Sopenharmony_ci	}
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	return 0;
240362306a36Sopenharmony_ci}
240462306a36Sopenharmony_ci
240562306a36Sopenharmony_ci/**
240662306a36Sopenharmony_ci * ice_vsi_cfg_def - configure default VSI based on the type
240762306a36Sopenharmony_ci * @vsi: pointer to VSI
240862306a36Sopenharmony_ci * @params: the parameters to configure this VSI with
240962306a36Sopenharmony_ci */
241062306a36Sopenharmony_cistatic int
241162306a36Sopenharmony_ciice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
241262306a36Sopenharmony_ci{
241362306a36Sopenharmony_ci	struct device *dev = ice_pf_to_dev(vsi->back);
241462306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
241562306a36Sopenharmony_ci	int ret;
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	vsi->vsw = pf->first_sw;
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	ret = ice_vsi_alloc_def(vsi, params->ch);
242062306a36Sopenharmony_ci	if (ret)
242162306a36Sopenharmony_ci		return ret;
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	/* allocate memory for Tx/Rx ring stat pointers */
242462306a36Sopenharmony_ci	ret = ice_vsi_alloc_stat_arrays(vsi);
242562306a36Sopenharmony_ci	if (ret)
242662306a36Sopenharmony_ci		goto unroll_vsi_alloc;
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci	ice_alloc_fd_res(vsi);
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	ret = ice_vsi_get_qs(vsi);
243162306a36Sopenharmony_ci	if (ret) {
243262306a36Sopenharmony_ci		dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n",
243362306a36Sopenharmony_ci			vsi->idx);
243462306a36Sopenharmony_ci		goto unroll_vsi_alloc_stat;
243562306a36Sopenharmony_ci	}
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ci	/* set RSS capabilities */
243862306a36Sopenharmony_ci	ice_vsi_set_rss_params(vsi);
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci	/* set TC configuration */
244162306a36Sopenharmony_ci	ice_vsi_set_tc_cfg(vsi);
244262306a36Sopenharmony_ci
244362306a36Sopenharmony_ci	/* create the VSI */
244462306a36Sopenharmony_ci	ret = ice_vsi_init(vsi, params->flags);
244562306a36Sopenharmony_ci	if (ret)
244662306a36Sopenharmony_ci		goto unroll_get_qs;
244762306a36Sopenharmony_ci
244862306a36Sopenharmony_ci	ice_vsi_init_vlan_ops(vsi);
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	switch (vsi->type) {
245162306a36Sopenharmony_ci	case ICE_VSI_CTRL:
245262306a36Sopenharmony_ci	case ICE_VSI_SWITCHDEV_CTRL:
245362306a36Sopenharmony_ci	case ICE_VSI_PF:
245462306a36Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(vsi);
245562306a36Sopenharmony_ci		if (ret)
245662306a36Sopenharmony_ci			goto unroll_vsi_init;
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
245962306a36Sopenharmony_ci		if (ret)
246062306a36Sopenharmony_ci			goto unroll_vector_base;
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci		ret = ice_vsi_alloc_ring_stats(vsi);
246362306a36Sopenharmony_ci		if (ret)
246462306a36Sopenharmony_ci			goto unroll_vector_base;
246562306a36Sopenharmony_ci
246662306a36Sopenharmony_ci		ice_vsi_map_rings_to_vectors(vsi);
246762306a36Sopenharmony_ci		vsi->stat_offsets_loaded = false;
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci		if (ice_is_xdp_ena_vsi(vsi)) {
247062306a36Sopenharmony_ci			ret = ice_vsi_determine_xdp_res(vsi);
247162306a36Sopenharmony_ci			if (ret)
247262306a36Sopenharmony_ci				goto unroll_vector_base;
247362306a36Sopenharmony_ci			ret = ice_prepare_xdp_rings(vsi, vsi->xdp_prog);
247462306a36Sopenharmony_ci			if (ret)
247562306a36Sopenharmony_ci				goto unroll_vector_base;
247662306a36Sopenharmony_ci		}
247762306a36Sopenharmony_ci
247862306a36Sopenharmony_ci		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
247962306a36Sopenharmony_ci		if (vsi->type != ICE_VSI_CTRL)
248062306a36Sopenharmony_ci			/* Do not exit if configuring RSS had an issue, at
248162306a36Sopenharmony_ci			 * least receive traffic on first queue. Hence no
248262306a36Sopenharmony_ci			 * need to capture return value
248362306a36Sopenharmony_ci			 */
248462306a36Sopenharmony_ci			if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
248562306a36Sopenharmony_ci				ice_vsi_cfg_rss_lut_key(vsi);
248662306a36Sopenharmony_ci				ice_vsi_set_rss_flow_fld(vsi);
248762306a36Sopenharmony_ci			}
248862306a36Sopenharmony_ci		ice_init_arfs(vsi);
248962306a36Sopenharmony_ci		break;
249062306a36Sopenharmony_ci	case ICE_VSI_CHNL:
249162306a36Sopenharmony_ci		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
249262306a36Sopenharmony_ci			ice_vsi_cfg_rss_lut_key(vsi);
249362306a36Sopenharmony_ci			ice_vsi_set_rss_flow_fld(vsi);
249462306a36Sopenharmony_ci		}
249562306a36Sopenharmony_ci		break;
249662306a36Sopenharmony_ci	case ICE_VSI_VF:
249762306a36Sopenharmony_ci		/* VF driver will take care of creating netdev for this type and
249862306a36Sopenharmony_ci		 * map queues to vectors through Virtchnl, PF driver only
249962306a36Sopenharmony_ci		 * creates a VSI and corresponding structures for bookkeeping
250062306a36Sopenharmony_ci		 * purpose
250162306a36Sopenharmony_ci		 */
250262306a36Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(vsi);
250362306a36Sopenharmony_ci		if (ret)
250462306a36Sopenharmony_ci			goto unroll_vsi_init;
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
250762306a36Sopenharmony_ci		if (ret)
250862306a36Sopenharmony_ci			goto unroll_alloc_q_vector;
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci		ret = ice_vsi_alloc_ring_stats(vsi);
251162306a36Sopenharmony_ci		if (ret)
251262306a36Sopenharmony_ci			goto unroll_vector_base;
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci		vsi->stat_offsets_loaded = false;
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_ci		/* Do not exit if configuring RSS had an issue, at least
251762306a36Sopenharmony_ci		 * receive traffic on first queue. Hence no need to capture
251862306a36Sopenharmony_ci		 * return value
251962306a36Sopenharmony_ci		 */
252062306a36Sopenharmony_ci		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
252162306a36Sopenharmony_ci			ice_vsi_cfg_rss_lut_key(vsi);
252262306a36Sopenharmony_ci			ice_vsi_set_vf_rss_flow_fld(vsi);
252362306a36Sopenharmony_ci		}
252462306a36Sopenharmony_ci		break;
252562306a36Sopenharmony_ci	case ICE_VSI_LB:
252662306a36Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
252762306a36Sopenharmony_ci		if (ret)
252862306a36Sopenharmony_ci			goto unroll_vsi_init;
252962306a36Sopenharmony_ci
253062306a36Sopenharmony_ci		ret = ice_vsi_alloc_ring_stats(vsi);
253162306a36Sopenharmony_ci		if (ret)
253262306a36Sopenharmony_ci			goto unroll_vector_base;
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci		break;
253562306a36Sopenharmony_ci	default:
253662306a36Sopenharmony_ci		/* clean up the resources and exit */
253762306a36Sopenharmony_ci		ret = -EINVAL;
253862306a36Sopenharmony_ci		goto unroll_vsi_init;
253962306a36Sopenharmony_ci	}
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci	return 0;
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ciunroll_vector_base:
254462306a36Sopenharmony_ci	/* reclaim SW interrupts back to the common pool */
254562306a36Sopenharmony_ciunroll_alloc_q_vector:
254662306a36Sopenharmony_ci	ice_vsi_free_q_vectors(vsi);
254762306a36Sopenharmony_ciunroll_vsi_init:
254862306a36Sopenharmony_ci	ice_vsi_delete_from_hw(vsi);
254962306a36Sopenharmony_ciunroll_get_qs:
255062306a36Sopenharmony_ci	ice_vsi_put_qs(vsi);
255162306a36Sopenharmony_ciunroll_vsi_alloc_stat:
255262306a36Sopenharmony_ci	ice_vsi_free_stats(vsi);
255362306a36Sopenharmony_ciunroll_vsi_alloc:
255462306a36Sopenharmony_ci	ice_vsi_free_arrays(vsi);
255562306a36Sopenharmony_ci	return ret;
255662306a36Sopenharmony_ci}
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci/**
255962306a36Sopenharmony_ci * ice_vsi_cfg - configure a previously allocated VSI
256062306a36Sopenharmony_ci * @vsi: pointer to VSI
256162306a36Sopenharmony_ci * @params: parameters used to configure this VSI
256262306a36Sopenharmony_ci */
256362306a36Sopenharmony_ciint ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params)
256462306a36Sopenharmony_ci{
256562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
256662306a36Sopenharmony_ci	int ret;
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	if (WARN_ON(params->type == ICE_VSI_VF && !params->vf))
256962306a36Sopenharmony_ci		return -EINVAL;
257062306a36Sopenharmony_ci
257162306a36Sopenharmony_ci	vsi->type = params->type;
257262306a36Sopenharmony_ci	vsi->port_info = params->pi;
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_ci	/* For VSIs which don't have a connected VF, this will be NULL */
257562306a36Sopenharmony_ci	vsi->vf = params->vf;
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	ret = ice_vsi_cfg_def(vsi, params);
257862306a36Sopenharmony_ci	if (ret)
257962306a36Sopenharmony_ci		return ret;
258062306a36Sopenharmony_ci
258162306a36Sopenharmony_ci	ret = ice_vsi_cfg_tc_lan(vsi->back, vsi);
258262306a36Sopenharmony_ci	if (ret)
258362306a36Sopenharmony_ci		ice_vsi_decfg(vsi);
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CTRL) {
258662306a36Sopenharmony_ci		if (vsi->vf) {
258762306a36Sopenharmony_ci			WARN_ON(vsi->vf->ctrl_vsi_idx != ICE_NO_VSI);
258862306a36Sopenharmony_ci			vsi->vf->ctrl_vsi_idx = vsi->idx;
258962306a36Sopenharmony_ci		} else {
259062306a36Sopenharmony_ci			WARN_ON(pf->ctrl_vsi_idx != ICE_NO_VSI);
259162306a36Sopenharmony_ci			pf->ctrl_vsi_idx = vsi->idx;
259262306a36Sopenharmony_ci		}
259362306a36Sopenharmony_ci	}
259462306a36Sopenharmony_ci
259562306a36Sopenharmony_ci	return ret;
259662306a36Sopenharmony_ci}
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci/**
259962306a36Sopenharmony_ci * ice_vsi_decfg - remove all VSI configuration
260062306a36Sopenharmony_ci * @vsi: pointer to VSI
260162306a36Sopenharmony_ci */
260262306a36Sopenharmony_civoid ice_vsi_decfg(struct ice_vsi *vsi)
260362306a36Sopenharmony_ci{
260462306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
260562306a36Sopenharmony_ci	int err;
260662306a36Sopenharmony_ci
260762306a36Sopenharmony_ci	/* The Rx rule will only exist to remove if the LLDP FW
260862306a36Sopenharmony_ci	 * engine is currently stopped
260962306a36Sopenharmony_ci	 */
261062306a36Sopenharmony_ci	if (!ice_is_safe_mode(pf) && vsi->type == ICE_VSI_PF &&
261162306a36Sopenharmony_ci	    !test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
261262306a36Sopenharmony_ci		ice_cfg_sw_lldp(vsi, false, false);
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
261562306a36Sopenharmony_ci	err = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
261662306a36Sopenharmony_ci	if (err)
261762306a36Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Failed to remove RDMA scheduler config for VSI %u, err %d\n",
261862306a36Sopenharmony_ci			vsi->vsi_num, err);
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_ci	if (ice_is_xdp_ena_vsi(vsi))
262162306a36Sopenharmony_ci		/* return value check can be skipped here, it always returns
262262306a36Sopenharmony_ci		 * 0 if reset is in progress
262362306a36Sopenharmony_ci		 */
262462306a36Sopenharmony_ci		ice_destroy_xdp_rings(vsi);
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	ice_vsi_clear_rings(vsi);
262762306a36Sopenharmony_ci	ice_vsi_free_q_vectors(vsi);
262862306a36Sopenharmony_ci	ice_vsi_put_qs(vsi);
262962306a36Sopenharmony_ci	ice_vsi_free_arrays(vsi);
263062306a36Sopenharmony_ci
263162306a36Sopenharmony_ci	/* SR-IOV determines needed MSIX resources all at once instead of per
263262306a36Sopenharmony_ci	 * VSI since when VFs are spawned we know how many VFs there are and how
263362306a36Sopenharmony_ci	 * many interrupts each VF needs. SR-IOV MSIX resources are also
263462306a36Sopenharmony_ci	 * cleared in the same manner.
263562306a36Sopenharmony_ci	 */
263662306a36Sopenharmony_ci
263762306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF &&
263862306a36Sopenharmony_ci	    vsi->agg_node && vsi->agg_node->valid)
263962306a36Sopenharmony_ci		vsi->agg_node->num_vsis--;
264062306a36Sopenharmony_ci}
264162306a36Sopenharmony_ci
264262306a36Sopenharmony_ci/**
264362306a36Sopenharmony_ci * ice_vsi_setup - Set up a VSI by a given type
264462306a36Sopenharmony_ci * @pf: board private structure
264562306a36Sopenharmony_ci * @params: parameters to use when creating the VSI
264662306a36Sopenharmony_ci *
264762306a36Sopenharmony_ci * This allocates the sw VSI structure and its queue resources.
264862306a36Sopenharmony_ci *
264962306a36Sopenharmony_ci * Returns pointer to the successfully allocated and configured VSI sw struct on
265062306a36Sopenharmony_ci * success, NULL on failure.
265162306a36Sopenharmony_ci */
265262306a36Sopenharmony_cistruct ice_vsi *
265362306a36Sopenharmony_ciice_vsi_setup(struct ice_pf *pf, struct ice_vsi_cfg_params *params)
265462306a36Sopenharmony_ci{
265562306a36Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
265662306a36Sopenharmony_ci	struct ice_vsi *vsi;
265762306a36Sopenharmony_ci	int ret;
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci	/* ice_vsi_setup can only initialize a new VSI, and we must have
266062306a36Sopenharmony_ci	 * a port_info structure for it.
266162306a36Sopenharmony_ci	 */
266262306a36Sopenharmony_ci	if (WARN_ON(!(params->flags & ICE_VSI_FLAG_INIT)) ||
266362306a36Sopenharmony_ci	    WARN_ON(!params->pi))
266462306a36Sopenharmony_ci		return NULL;
266562306a36Sopenharmony_ci
266662306a36Sopenharmony_ci	vsi = ice_vsi_alloc(pf);
266762306a36Sopenharmony_ci	if (!vsi) {
266862306a36Sopenharmony_ci		dev_err(dev, "could not allocate VSI\n");
266962306a36Sopenharmony_ci		return NULL;
267062306a36Sopenharmony_ci	}
267162306a36Sopenharmony_ci
267262306a36Sopenharmony_ci	ret = ice_vsi_cfg(vsi, params);
267362306a36Sopenharmony_ci	if (ret)
267462306a36Sopenharmony_ci		goto err_vsi_cfg;
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	/* Add switch rule to drop all Tx Flow Control Frames, of look up
267762306a36Sopenharmony_ci	 * type ETHERTYPE from VSIs, and restrict malicious VF from sending
267862306a36Sopenharmony_ci	 * out PAUSE or PFC frames. If enabled, FW can still send FC frames.
267962306a36Sopenharmony_ci	 * The rule is added once for PF VSI in order to create appropriate
268062306a36Sopenharmony_ci	 * recipe, since VSI/VSI list is ignored with drop action...
268162306a36Sopenharmony_ci	 * Also add rules to handle LLDP Tx packets.  Tx LLDP packets need to
268262306a36Sopenharmony_ci	 * be dropped so that VFs cannot send LLDP packets to reconfig DCB
268362306a36Sopenharmony_ci	 * settings in the HW.
268462306a36Sopenharmony_ci	 */
268562306a36Sopenharmony_ci	if (!ice_is_safe_mode(pf) && vsi->type == ICE_VSI_PF) {
268662306a36Sopenharmony_ci		ice_fltr_add_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX,
268762306a36Sopenharmony_ci				 ICE_DROP_PACKET);
268862306a36Sopenharmony_ci		ice_cfg_sw_lldp(vsi, true, true);
268962306a36Sopenharmony_ci	}
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ci	if (!vsi->agg_node)
269262306a36Sopenharmony_ci		ice_set_agg_vsi(vsi);
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci	return vsi;
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_cierr_vsi_cfg:
269762306a36Sopenharmony_ci	ice_vsi_free(vsi);
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci	return NULL;
270062306a36Sopenharmony_ci}
270162306a36Sopenharmony_ci
270262306a36Sopenharmony_ci/**
270362306a36Sopenharmony_ci * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW
270462306a36Sopenharmony_ci * @vsi: the VSI being cleaned up
270562306a36Sopenharmony_ci */
270662306a36Sopenharmony_cistatic void ice_vsi_release_msix(struct ice_vsi *vsi)
270762306a36Sopenharmony_ci{
270862306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
270962306a36Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
271062306a36Sopenharmony_ci	u32 txq = 0;
271162306a36Sopenharmony_ci	u32 rxq = 0;
271262306a36Sopenharmony_ci	int i, q;
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
271562306a36Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
271662306a36Sopenharmony_ci
271762306a36Sopenharmony_ci		ice_write_intrl(q_vector, 0);
271862306a36Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_tx; q++) {
271962306a36Sopenharmony_ci			ice_write_itr(&q_vector->tx, 0);
272062306a36Sopenharmony_ci			wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0);
272162306a36Sopenharmony_ci			if (ice_is_xdp_ena_vsi(vsi)) {
272262306a36Sopenharmony_ci				u32 xdp_txq = txq + vsi->num_xdp_txq;
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci				wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0);
272562306a36Sopenharmony_ci			}
272662306a36Sopenharmony_ci			txq++;
272762306a36Sopenharmony_ci		}
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_rx; q++) {
273062306a36Sopenharmony_ci			ice_write_itr(&q_vector->rx, 0);
273162306a36Sopenharmony_ci			wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0);
273262306a36Sopenharmony_ci			rxq++;
273362306a36Sopenharmony_ci		}
273462306a36Sopenharmony_ci	}
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	ice_flush(hw);
273762306a36Sopenharmony_ci}
273862306a36Sopenharmony_ci
273962306a36Sopenharmony_ci/**
274062306a36Sopenharmony_ci * ice_vsi_free_irq - Free the IRQ association with the OS
274162306a36Sopenharmony_ci * @vsi: the VSI being configured
274262306a36Sopenharmony_ci */
274362306a36Sopenharmony_civoid ice_vsi_free_irq(struct ice_vsi *vsi)
274462306a36Sopenharmony_ci{
274562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
274662306a36Sopenharmony_ci	int i;
274762306a36Sopenharmony_ci
274862306a36Sopenharmony_ci	if (!vsi->q_vectors || !vsi->irqs_ready)
274962306a36Sopenharmony_ci		return;
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_ci	ice_vsi_release_msix(vsi);
275262306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
275362306a36Sopenharmony_ci		return;
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_ci	vsi->irqs_ready = false;
275662306a36Sopenharmony_ci	ice_free_cpu_rx_rmap(vsi);
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
275962306a36Sopenharmony_ci		int irq_num;
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci		irq_num = vsi->q_vectors[i]->irq.virq;
276262306a36Sopenharmony_ci
276362306a36Sopenharmony_ci		/* free only the irqs that were actually requested */
276462306a36Sopenharmony_ci		if (!vsi->q_vectors[i] ||
276562306a36Sopenharmony_ci		    !(vsi->q_vectors[i]->num_ring_tx ||
276662306a36Sopenharmony_ci		      vsi->q_vectors[i]->num_ring_rx))
276762306a36Sopenharmony_ci			continue;
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci		/* clear the affinity notifier in the IRQ descriptor */
277062306a36Sopenharmony_ci		if (!IS_ENABLED(CONFIG_RFS_ACCEL))
277162306a36Sopenharmony_ci			irq_set_affinity_notifier(irq_num, NULL);
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci		/* clear the affinity_mask in the IRQ descriptor */
277462306a36Sopenharmony_ci		irq_set_affinity_hint(irq_num, NULL);
277562306a36Sopenharmony_ci		synchronize_irq(irq_num);
277662306a36Sopenharmony_ci		devm_free_irq(ice_pf_to_dev(pf), irq_num, vsi->q_vectors[i]);
277762306a36Sopenharmony_ci	}
277862306a36Sopenharmony_ci}
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci/**
278162306a36Sopenharmony_ci * ice_vsi_free_tx_rings - Free Tx resources for VSI queues
278262306a36Sopenharmony_ci * @vsi: the VSI having resources freed
278362306a36Sopenharmony_ci */
278462306a36Sopenharmony_civoid ice_vsi_free_tx_rings(struct ice_vsi *vsi)
278562306a36Sopenharmony_ci{
278662306a36Sopenharmony_ci	int i;
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	if (!vsi->tx_rings)
278962306a36Sopenharmony_ci		return;
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	ice_for_each_txq(vsi, i)
279262306a36Sopenharmony_ci		if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc)
279362306a36Sopenharmony_ci			ice_free_tx_ring(vsi->tx_rings[i]);
279462306a36Sopenharmony_ci}
279562306a36Sopenharmony_ci
279662306a36Sopenharmony_ci/**
279762306a36Sopenharmony_ci * ice_vsi_free_rx_rings - Free Rx resources for VSI queues
279862306a36Sopenharmony_ci * @vsi: the VSI having resources freed
279962306a36Sopenharmony_ci */
280062306a36Sopenharmony_civoid ice_vsi_free_rx_rings(struct ice_vsi *vsi)
280162306a36Sopenharmony_ci{
280262306a36Sopenharmony_ci	int i;
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	if (!vsi->rx_rings)
280562306a36Sopenharmony_ci		return;
280662306a36Sopenharmony_ci
280762306a36Sopenharmony_ci	ice_for_each_rxq(vsi, i)
280862306a36Sopenharmony_ci		if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
280962306a36Sopenharmony_ci			ice_free_rx_ring(vsi->rx_rings[i]);
281062306a36Sopenharmony_ci}
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci/**
281362306a36Sopenharmony_ci * ice_vsi_close - Shut down a VSI
281462306a36Sopenharmony_ci * @vsi: the VSI being shut down
281562306a36Sopenharmony_ci */
281662306a36Sopenharmony_civoid ice_vsi_close(struct ice_vsi *vsi)
281762306a36Sopenharmony_ci{
281862306a36Sopenharmony_ci	if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state))
281962306a36Sopenharmony_ci		ice_down(vsi);
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	ice_vsi_free_irq(vsi);
282262306a36Sopenharmony_ci	ice_vsi_free_tx_rings(vsi);
282362306a36Sopenharmony_ci	ice_vsi_free_rx_rings(vsi);
282462306a36Sopenharmony_ci}
282562306a36Sopenharmony_ci
282662306a36Sopenharmony_ci/**
282762306a36Sopenharmony_ci * ice_ena_vsi - resume a VSI
282862306a36Sopenharmony_ci * @vsi: the VSI being resume
282962306a36Sopenharmony_ci * @locked: is the rtnl_lock already held
283062306a36Sopenharmony_ci */
283162306a36Sopenharmony_ciint ice_ena_vsi(struct ice_vsi *vsi, bool locked)
283262306a36Sopenharmony_ci{
283362306a36Sopenharmony_ci	int err = 0;
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci	if (!test_bit(ICE_VSI_NEEDS_RESTART, vsi->state))
283662306a36Sopenharmony_ci		return 0;
283762306a36Sopenharmony_ci
283862306a36Sopenharmony_ci	clear_bit(ICE_VSI_NEEDS_RESTART, vsi->state);
283962306a36Sopenharmony_ci
284062306a36Sopenharmony_ci	if (vsi->netdev && vsi->type == ICE_VSI_PF) {
284162306a36Sopenharmony_ci		if (netif_running(vsi->netdev)) {
284262306a36Sopenharmony_ci			if (!locked)
284362306a36Sopenharmony_ci				rtnl_lock();
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci			err = ice_open_internal(vsi->netdev);
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_ci			if (!locked)
284862306a36Sopenharmony_ci				rtnl_unlock();
284962306a36Sopenharmony_ci		}
285062306a36Sopenharmony_ci	} else if (vsi->type == ICE_VSI_CTRL) {
285162306a36Sopenharmony_ci		err = ice_vsi_open_ctrl(vsi);
285262306a36Sopenharmony_ci	}
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_ci	return err;
285562306a36Sopenharmony_ci}
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci/**
285862306a36Sopenharmony_ci * ice_dis_vsi - pause a VSI
285962306a36Sopenharmony_ci * @vsi: the VSI being paused
286062306a36Sopenharmony_ci * @locked: is the rtnl_lock already held
286162306a36Sopenharmony_ci */
286262306a36Sopenharmony_civoid ice_dis_vsi(struct ice_vsi *vsi, bool locked)
286362306a36Sopenharmony_ci{
286462306a36Sopenharmony_ci	if (test_bit(ICE_VSI_DOWN, vsi->state))
286562306a36Sopenharmony_ci		return;
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	set_bit(ICE_VSI_NEEDS_RESTART, vsi->state);
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF && vsi->netdev) {
287062306a36Sopenharmony_ci		if (netif_running(vsi->netdev)) {
287162306a36Sopenharmony_ci			if (!locked)
287262306a36Sopenharmony_ci				rtnl_lock();
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci			ice_vsi_close(vsi);
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci			if (!locked)
287762306a36Sopenharmony_ci				rtnl_unlock();
287862306a36Sopenharmony_ci		} else {
287962306a36Sopenharmony_ci			ice_vsi_close(vsi);
288062306a36Sopenharmony_ci		}
288162306a36Sopenharmony_ci	} else if (vsi->type == ICE_VSI_CTRL ||
288262306a36Sopenharmony_ci		   vsi->type == ICE_VSI_SWITCHDEV_CTRL) {
288362306a36Sopenharmony_ci		ice_vsi_close(vsi);
288462306a36Sopenharmony_ci	}
288562306a36Sopenharmony_ci}
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_ci/**
288862306a36Sopenharmony_ci * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI
288962306a36Sopenharmony_ci * @vsi: the VSI being un-configured
289062306a36Sopenharmony_ci */
289162306a36Sopenharmony_civoid ice_vsi_dis_irq(struct ice_vsi *vsi)
289262306a36Sopenharmony_ci{
289362306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
289462306a36Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
289562306a36Sopenharmony_ci	u32 val;
289662306a36Sopenharmony_ci	int i;
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	/* disable interrupt causation from each queue */
289962306a36Sopenharmony_ci	if (vsi->tx_rings) {
290062306a36Sopenharmony_ci		ice_for_each_txq(vsi, i) {
290162306a36Sopenharmony_ci			if (vsi->tx_rings[i]) {
290262306a36Sopenharmony_ci				u16 reg;
290362306a36Sopenharmony_ci
290462306a36Sopenharmony_ci				reg = vsi->tx_rings[i]->reg_idx;
290562306a36Sopenharmony_ci				val = rd32(hw, QINT_TQCTL(reg));
290662306a36Sopenharmony_ci				val &= ~QINT_TQCTL_CAUSE_ENA_M;
290762306a36Sopenharmony_ci				wr32(hw, QINT_TQCTL(reg), val);
290862306a36Sopenharmony_ci			}
290962306a36Sopenharmony_ci		}
291062306a36Sopenharmony_ci	}
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci	if (vsi->rx_rings) {
291362306a36Sopenharmony_ci		ice_for_each_rxq(vsi, i) {
291462306a36Sopenharmony_ci			if (vsi->rx_rings[i]) {
291562306a36Sopenharmony_ci				u16 reg;
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci				reg = vsi->rx_rings[i]->reg_idx;
291862306a36Sopenharmony_ci				val = rd32(hw, QINT_RQCTL(reg));
291962306a36Sopenharmony_ci				val &= ~QINT_RQCTL_CAUSE_ENA_M;
292062306a36Sopenharmony_ci				wr32(hw, QINT_RQCTL(reg), val);
292162306a36Sopenharmony_ci			}
292262306a36Sopenharmony_ci		}
292362306a36Sopenharmony_ci	}
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_ci	/* disable each interrupt */
292662306a36Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
292762306a36Sopenharmony_ci		if (!vsi->q_vectors[i])
292862306a36Sopenharmony_ci			continue;
292962306a36Sopenharmony_ci		wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0);
293062306a36Sopenharmony_ci	}
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	ice_flush(hw);
293362306a36Sopenharmony_ci
293462306a36Sopenharmony_ci	/* don't call synchronize_irq() for VF's from the host */
293562306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
293662306a36Sopenharmony_ci		return;
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	ice_for_each_q_vector(vsi, i)
293962306a36Sopenharmony_ci		synchronize_irq(vsi->q_vectors[i]->irq.virq);
294062306a36Sopenharmony_ci}
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci/**
294362306a36Sopenharmony_ci * ice_vsi_release - Delete a VSI and free its resources
294462306a36Sopenharmony_ci * @vsi: the VSI being removed
294562306a36Sopenharmony_ci *
294662306a36Sopenharmony_ci * Returns 0 on success or < 0 on error
294762306a36Sopenharmony_ci */
294862306a36Sopenharmony_ciint ice_vsi_release(struct ice_vsi *vsi)
294962306a36Sopenharmony_ci{
295062306a36Sopenharmony_ci	struct ice_pf *pf;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	if (!vsi->back)
295362306a36Sopenharmony_ci		return -ENODEV;
295462306a36Sopenharmony_ci	pf = vsi->back;
295562306a36Sopenharmony_ci
295662306a36Sopenharmony_ci	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
295762306a36Sopenharmony_ci		ice_rss_clean(vsi);
295862306a36Sopenharmony_ci
295962306a36Sopenharmony_ci	ice_vsi_close(vsi);
296062306a36Sopenharmony_ci	ice_vsi_decfg(vsi);
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	/* retain SW VSI data structure since it is needed to unregister and
296362306a36Sopenharmony_ci	 * free VSI netdev when PF is not in reset recovery pending state,\
296462306a36Sopenharmony_ci	 * for ex: during rmmod.
296562306a36Sopenharmony_ci	 */
296662306a36Sopenharmony_ci	if (!ice_is_reset_in_progress(pf->state))
296762306a36Sopenharmony_ci		ice_vsi_delete(vsi);
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_ci	return 0;
297062306a36Sopenharmony_ci}
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci/**
297362306a36Sopenharmony_ci * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
297462306a36Sopenharmony_ci * @vsi: VSI connected with q_vectors
297562306a36Sopenharmony_ci * @coalesce: array of struct with stored coalesce
297662306a36Sopenharmony_ci *
297762306a36Sopenharmony_ci * Returns array size.
297862306a36Sopenharmony_ci */
297962306a36Sopenharmony_cistatic int
298062306a36Sopenharmony_ciice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
298162306a36Sopenharmony_ci			     struct ice_coalesce_stored *coalesce)
298262306a36Sopenharmony_ci{
298362306a36Sopenharmony_ci	int i;
298462306a36Sopenharmony_ci
298562306a36Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
298662306a36Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci		coalesce[i].itr_tx = q_vector->tx.itr_settings;
298962306a36Sopenharmony_ci		coalesce[i].itr_rx = q_vector->rx.itr_settings;
299062306a36Sopenharmony_ci		coalesce[i].intrl = q_vector->intrl;
299162306a36Sopenharmony_ci
299262306a36Sopenharmony_ci		if (i < vsi->num_txq)
299362306a36Sopenharmony_ci			coalesce[i].tx_valid = true;
299462306a36Sopenharmony_ci		if (i < vsi->num_rxq)
299562306a36Sopenharmony_ci			coalesce[i].rx_valid = true;
299662306a36Sopenharmony_ci	}
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	return vsi->num_q_vectors;
299962306a36Sopenharmony_ci}
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_ci/**
300262306a36Sopenharmony_ci * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays
300362306a36Sopenharmony_ci * @vsi: VSI connected with q_vectors
300462306a36Sopenharmony_ci * @coalesce: pointer to array of struct with stored coalesce
300562306a36Sopenharmony_ci * @size: size of coalesce array
300662306a36Sopenharmony_ci *
300762306a36Sopenharmony_ci * Before this function, ice_vsi_rebuild_get_coalesce should be called to save
300862306a36Sopenharmony_ci * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce
300962306a36Sopenharmony_ci * to default value.
301062306a36Sopenharmony_ci */
301162306a36Sopenharmony_cistatic void
301262306a36Sopenharmony_ciice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
301362306a36Sopenharmony_ci			     struct ice_coalesce_stored *coalesce, int size)
301462306a36Sopenharmony_ci{
301562306a36Sopenharmony_ci	struct ice_ring_container *rc;
301662306a36Sopenharmony_ci	int i;
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci	if ((size && !coalesce) || !vsi)
301962306a36Sopenharmony_ci		return;
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_ci	/* There are a couple of cases that have to be handled here:
302262306a36Sopenharmony_ci	 *   1. The case where the number of queue vectors stays the same, but
302362306a36Sopenharmony_ci	 *      the number of Tx or Rx rings changes (the first for loop)
302462306a36Sopenharmony_ci	 *   2. The case where the number of queue vectors increased (the
302562306a36Sopenharmony_ci	 *      second for loop)
302662306a36Sopenharmony_ci	 */
302762306a36Sopenharmony_ci	for (i = 0; i < size && i < vsi->num_q_vectors; i++) {
302862306a36Sopenharmony_ci		/* There are 2 cases to handle here and they are the same for
302962306a36Sopenharmony_ci		 * both Tx and Rx:
303062306a36Sopenharmony_ci		 *   if the entry was valid previously (coalesce[i].[tr]x_valid
303162306a36Sopenharmony_ci		 *   and the loop variable is less than the number of rings
303262306a36Sopenharmony_ci		 *   allocated, then write the previous values
303362306a36Sopenharmony_ci		 *
303462306a36Sopenharmony_ci		 *   if the entry was not valid previously, but the number of
303562306a36Sopenharmony_ci		 *   rings is less than are allocated (this means the number of
303662306a36Sopenharmony_ci		 *   rings increased from previously), then write out the
303762306a36Sopenharmony_ci		 *   values in the first element
303862306a36Sopenharmony_ci		 *
303962306a36Sopenharmony_ci		 *   Also, always write the ITR, even if in ITR_IS_DYNAMIC
304062306a36Sopenharmony_ci		 *   as there is no harm because the dynamic algorithm
304162306a36Sopenharmony_ci		 *   will just overwrite.
304262306a36Sopenharmony_ci		 */
304362306a36Sopenharmony_ci		if (i < vsi->alloc_rxq && coalesce[i].rx_valid) {
304462306a36Sopenharmony_ci			rc = &vsi->q_vectors[i]->rx;
304562306a36Sopenharmony_ci			rc->itr_settings = coalesce[i].itr_rx;
304662306a36Sopenharmony_ci			ice_write_itr(rc, rc->itr_setting);
304762306a36Sopenharmony_ci		} else if (i < vsi->alloc_rxq) {
304862306a36Sopenharmony_ci			rc = &vsi->q_vectors[i]->rx;
304962306a36Sopenharmony_ci			rc->itr_settings = coalesce[0].itr_rx;
305062306a36Sopenharmony_ci			ice_write_itr(rc, rc->itr_setting);
305162306a36Sopenharmony_ci		}
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci		if (i < vsi->alloc_txq && coalesce[i].tx_valid) {
305462306a36Sopenharmony_ci			rc = &vsi->q_vectors[i]->tx;
305562306a36Sopenharmony_ci			rc->itr_settings = coalesce[i].itr_tx;
305662306a36Sopenharmony_ci			ice_write_itr(rc, rc->itr_setting);
305762306a36Sopenharmony_ci		} else if (i < vsi->alloc_txq) {
305862306a36Sopenharmony_ci			rc = &vsi->q_vectors[i]->tx;
305962306a36Sopenharmony_ci			rc->itr_settings = coalesce[0].itr_tx;
306062306a36Sopenharmony_ci			ice_write_itr(rc, rc->itr_setting);
306162306a36Sopenharmony_ci		}
306262306a36Sopenharmony_ci
306362306a36Sopenharmony_ci		vsi->q_vectors[i]->intrl = coalesce[i].intrl;
306462306a36Sopenharmony_ci		ice_set_q_vector_intrl(vsi->q_vectors[i]);
306562306a36Sopenharmony_ci	}
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	/* the number of queue vectors increased so write whatever is in
306862306a36Sopenharmony_ci	 * the first element
306962306a36Sopenharmony_ci	 */
307062306a36Sopenharmony_ci	for (; i < vsi->num_q_vectors; i++) {
307162306a36Sopenharmony_ci		/* transmit */
307262306a36Sopenharmony_ci		rc = &vsi->q_vectors[i]->tx;
307362306a36Sopenharmony_ci		rc->itr_settings = coalesce[0].itr_tx;
307462306a36Sopenharmony_ci		ice_write_itr(rc, rc->itr_setting);
307562306a36Sopenharmony_ci
307662306a36Sopenharmony_ci		/* receive */
307762306a36Sopenharmony_ci		rc = &vsi->q_vectors[i]->rx;
307862306a36Sopenharmony_ci		rc->itr_settings = coalesce[0].itr_rx;
307962306a36Sopenharmony_ci		ice_write_itr(rc, rc->itr_setting);
308062306a36Sopenharmony_ci
308162306a36Sopenharmony_ci		vsi->q_vectors[i]->intrl = coalesce[0].intrl;
308262306a36Sopenharmony_ci		ice_set_q_vector_intrl(vsi->q_vectors[i]);
308362306a36Sopenharmony_ci	}
308462306a36Sopenharmony_ci}
308562306a36Sopenharmony_ci
308662306a36Sopenharmony_ci/**
308762306a36Sopenharmony_ci * ice_vsi_realloc_stat_arrays - Frees unused stat structures
308862306a36Sopenharmony_ci * @vsi: VSI pointer
308962306a36Sopenharmony_ci * @prev_txq: Number of Tx rings before ring reallocation
309062306a36Sopenharmony_ci * @prev_rxq: Number of Rx rings before ring reallocation
309162306a36Sopenharmony_ci */
309262306a36Sopenharmony_cistatic void
309362306a36Sopenharmony_ciice_vsi_realloc_stat_arrays(struct ice_vsi *vsi, int prev_txq, int prev_rxq)
309462306a36Sopenharmony_ci{
309562306a36Sopenharmony_ci	struct ice_vsi_stats *vsi_stat;
309662306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
309762306a36Sopenharmony_ci	int i;
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ci	if (!prev_txq || !prev_rxq)
310062306a36Sopenharmony_ci		return;
310162306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL)
310262306a36Sopenharmony_ci		return;
310362306a36Sopenharmony_ci
310462306a36Sopenharmony_ci	vsi_stat = pf->vsi_stats[vsi->idx];
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	if (vsi->num_txq < prev_txq) {
310762306a36Sopenharmony_ci		for (i = vsi->num_txq; i < prev_txq; i++) {
310862306a36Sopenharmony_ci			if (vsi_stat->tx_ring_stats[i]) {
310962306a36Sopenharmony_ci				kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
311062306a36Sopenharmony_ci				WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
311162306a36Sopenharmony_ci			}
311262306a36Sopenharmony_ci		}
311362306a36Sopenharmony_ci	}
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	if (vsi->num_rxq < prev_rxq) {
311662306a36Sopenharmony_ci		for (i = vsi->num_rxq; i < prev_rxq; i++) {
311762306a36Sopenharmony_ci			if (vsi_stat->rx_ring_stats[i]) {
311862306a36Sopenharmony_ci				kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
311962306a36Sopenharmony_ci				WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
312062306a36Sopenharmony_ci			}
312162306a36Sopenharmony_ci		}
312262306a36Sopenharmony_ci	}
312362306a36Sopenharmony_ci}
312462306a36Sopenharmony_ci
312562306a36Sopenharmony_ci/**
312662306a36Sopenharmony_ci * ice_vsi_rebuild - Rebuild VSI after reset
312762306a36Sopenharmony_ci * @vsi: VSI to be rebuild
312862306a36Sopenharmony_ci * @vsi_flags: flags used for VSI rebuild flow
312962306a36Sopenharmony_ci *
313062306a36Sopenharmony_ci * Set vsi_flags to ICE_VSI_FLAG_INIT to initialize a new VSI, or
313162306a36Sopenharmony_ci * ICE_VSI_FLAG_NO_INIT to rebuild an existing VSI in hardware.
313262306a36Sopenharmony_ci *
313362306a36Sopenharmony_ci * Returns 0 on success and negative value on failure
313462306a36Sopenharmony_ci */
313562306a36Sopenharmony_ciint ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)
313662306a36Sopenharmony_ci{
313762306a36Sopenharmony_ci	struct ice_vsi_cfg_params params = {};
313862306a36Sopenharmony_ci	struct ice_coalesce_stored *coalesce;
313962306a36Sopenharmony_ci	int ret, prev_txq, prev_rxq;
314062306a36Sopenharmony_ci	int prev_num_q_vectors = 0;
314162306a36Sopenharmony_ci	struct ice_pf *pf;
314262306a36Sopenharmony_ci
314362306a36Sopenharmony_ci	if (!vsi)
314462306a36Sopenharmony_ci		return -EINVAL;
314562306a36Sopenharmony_ci
314662306a36Sopenharmony_ci	params = ice_vsi_to_params(vsi);
314762306a36Sopenharmony_ci	params.flags = vsi_flags;
314862306a36Sopenharmony_ci
314962306a36Sopenharmony_ci	pf = vsi->back;
315062306a36Sopenharmony_ci	if (WARN_ON(vsi->type == ICE_VSI_VF && !vsi->vf))
315162306a36Sopenharmony_ci		return -EINVAL;
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	coalesce = kcalloc(vsi->num_q_vectors,
315462306a36Sopenharmony_ci			   sizeof(struct ice_coalesce_stored), GFP_KERNEL);
315562306a36Sopenharmony_ci	if (!coalesce)
315662306a36Sopenharmony_ci		return -ENOMEM;
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci	prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
315962306a36Sopenharmony_ci
316062306a36Sopenharmony_ci	prev_txq = vsi->num_txq;
316162306a36Sopenharmony_ci	prev_rxq = vsi->num_rxq;
316262306a36Sopenharmony_ci
316362306a36Sopenharmony_ci	ice_vsi_decfg(vsi);
316462306a36Sopenharmony_ci	ret = ice_vsi_cfg_def(vsi, &params);
316562306a36Sopenharmony_ci	if (ret)
316662306a36Sopenharmony_ci		goto err_vsi_cfg;
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_ci	ret = ice_vsi_cfg_tc_lan(pf, vsi);
316962306a36Sopenharmony_ci	if (ret) {
317062306a36Sopenharmony_ci		if (vsi_flags & ICE_VSI_FLAG_INIT) {
317162306a36Sopenharmony_ci			ret = -EIO;
317262306a36Sopenharmony_ci			goto err_vsi_cfg_tc_lan;
317362306a36Sopenharmony_ci		}
317462306a36Sopenharmony_ci
317562306a36Sopenharmony_ci		kfree(coalesce);
317662306a36Sopenharmony_ci		return ice_schedule_reset(pf, ICE_RESET_PFR);
317762306a36Sopenharmony_ci	}
317862306a36Sopenharmony_ci
317962306a36Sopenharmony_ci	ice_vsi_realloc_stat_arrays(vsi, prev_txq, prev_rxq);
318062306a36Sopenharmony_ci
318162306a36Sopenharmony_ci	ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors);
318262306a36Sopenharmony_ci	kfree(coalesce);
318362306a36Sopenharmony_ci
318462306a36Sopenharmony_ci	return 0;
318562306a36Sopenharmony_ci
318662306a36Sopenharmony_cierr_vsi_cfg_tc_lan:
318762306a36Sopenharmony_ci	ice_vsi_decfg(vsi);
318862306a36Sopenharmony_cierr_vsi_cfg:
318962306a36Sopenharmony_ci	kfree(coalesce);
319062306a36Sopenharmony_ci	return ret;
319162306a36Sopenharmony_ci}
319262306a36Sopenharmony_ci
319362306a36Sopenharmony_ci/**
319462306a36Sopenharmony_ci * ice_is_reset_in_progress - check for a reset in progress
319562306a36Sopenharmony_ci * @state: PF state field
319662306a36Sopenharmony_ci */
319762306a36Sopenharmony_cibool ice_is_reset_in_progress(unsigned long *state)
319862306a36Sopenharmony_ci{
319962306a36Sopenharmony_ci	return test_bit(ICE_RESET_OICR_RECV, state) ||
320062306a36Sopenharmony_ci	       test_bit(ICE_PFR_REQ, state) ||
320162306a36Sopenharmony_ci	       test_bit(ICE_CORER_REQ, state) ||
320262306a36Sopenharmony_ci	       test_bit(ICE_GLOBR_REQ, state);
320362306a36Sopenharmony_ci}
320462306a36Sopenharmony_ci
320562306a36Sopenharmony_ci/**
320662306a36Sopenharmony_ci * ice_wait_for_reset - Wait for driver to finish reset and rebuild
320762306a36Sopenharmony_ci * @pf: pointer to the PF structure
320862306a36Sopenharmony_ci * @timeout: length of time to wait, in jiffies
320962306a36Sopenharmony_ci *
321062306a36Sopenharmony_ci * Wait (sleep) for a short time until the driver finishes cleaning up from
321162306a36Sopenharmony_ci * a device reset. The caller must be able to sleep. Use this to delay
321262306a36Sopenharmony_ci * operations that could fail while the driver is cleaning up after a device
321362306a36Sopenharmony_ci * reset.
321462306a36Sopenharmony_ci *
321562306a36Sopenharmony_ci * Returns 0 on success, -EBUSY if the reset is not finished within the
321662306a36Sopenharmony_ci * timeout, and -ERESTARTSYS if the thread was interrupted.
321762306a36Sopenharmony_ci */
321862306a36Sopenharmony_ciint ice_wait_for_reset(struct ice_pf *pf, unsigned long timeout)
321962306a36Sopenharmony_ci{
322062306a36Sopenharmony_ci	long ret;
322162306a36Sopenharmony_ci
322262306a36Sopenharmony_ci	ret = wait_event_interruptible_timeout(pf->reset_wait_queue,
322362306a36Sopenharmony_ci					       !ice_is_reset_in_progress(pf->state),
322462306a36Sopenharmony_ci					       timeout);
322562306a36Sopenharmony_ci	if (ret < 0)
322662306a36Sopenharmony_ci		return ret;
322762306a36Sopenharmony_ci	else if (!ret)
322862306a36Sopenharmony_ci		return -EBUSY;
322962306a36Sopenharmony_ci	else
323062306a36Sopenharmony_ci		return 0;
323162306a36Sopenharmony_ci}
323262306a36Sopenharmony_ci
323362306a36Sopenharmony_ci/**
323462306a36Sopenharmony_ci * ice_vsi_update_q_map - update our copy of the VSI info with new queue map
323562306a36Sopenharmony_ci * @vsi: VSI being configured
323662306a36Sopenharmony_ci * @ctx: the context buffer returned from AQ VSI update command
323762306a36Sopenharmony_ci */
323862306a36Sopenharmony_cistatic void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx)
323962306a36Sopenharmony_ci{
324062306a36Sopenharmony_ci	vsi->info.mapping_flags = ctx->info.mapping_flags;
324162306a36Sopenharmony_ci	memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping,
324262306a36Sopenharmony_ci	       sizeof(vsi->info.q_mapping));
324362306a36Sopenharmony_ci	memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping,
324462306a36Sopenharmony_ci	       sizeof(vsi->info.tc_mapping));
324562306a36Sopenharmony_ci}
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci/**
324862306a36Sopenharmony_ci * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration
324962306a36Sopenharmony_ci * @vsi: the VSI being configured
325062306a36Sopenharmony_ci * @ena_tc: TC map to be enabled
325162306a36Sopenharmony_ci */
325262306a36Sopenharmony_civoid ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)
325362306a36Sopenharmony_ci{
325462306a36Sopenharmony_ci	struct net_device *netdev = vsi->netdev;
325562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
325662306a36Sopenharmony_ci	int numtc = vsi->tc_cfg.numtc;
325762306a36Sopenharmony_ci	struct ice_dcbx_cfg *dcbcfg;
325862306a36Sopenharmony_ci	u8 netdev_tc;
325962306a36Sopenharmony_ci	int i;
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_ci	if (!netdev)
326262306a36Sopenharmony_ci		return;
326362306a36Sopenharmony_ci
326462306a36Sopenharmony_ci	/* CHNL VSI doesn't have it's own netdev, hence, no netdev_tc */
326562306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_CHNL)
326662306a36Sopenharmony_ci		return;
326762306a36Sopenharmony_ci
326862306a36Sopenharmony_ci	if (!ena_tc) {
326962306a36Sopenharmony_ci		netdev_reset_tc(netdev);
327062306a36Sopenharmony_ci		return;
327162306a36Sopenharmony_ci	}
327262306a36Sopenharmony_ci
327362306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF && ice_is_adq_active(pf))
327462306a36Sopenharmony_ci		numtc = vsi->all_numtc;
327562306a36Sopenharmony_ci
327662306a36Sopenharmony_ci	if (netdev_set_num_tc(netdev, numtc))
327762306a36Sopenharmony_ci		return;
327862306a36Sopenharmony_ci
327962306a36Sopenharmony_ci	dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_ci	ice_for_each_traffic_class(i)
328262306a36Sopenharmony_ci		if (vsi->tc_cfg.ena_tc & BIT(i))
328362306a36Sopenharmony_ci			netdev_set_tc_queue(netdev,
328462306a36Sopenharmony_ci					    vsi->tc_cfg.tc_info[i].netdev_tc,
328562306a36Sopenharmony_ci					    vsi->tc_cfg.tc_info[i].qcount_tx,
328662306a36Sopenharmony_ci					    vsi->tc_cfg.tc_info[i].qoffset);
328762306a36Sopenharmony_ci	/* setup TC queue map for CHNL TCs */
328862306a36Sopenharmony_ci	ice_for_each_chnl_tc(i) {
328962306a36Sopenharmony_ci		if (!(vsi->all_enatc & BIT(i)))
329062306a36Sopenharmony_ci			break;
329162306a36Sopenharmony_ci		if (!vsi->mqprio_qopt.qopt.count[i])
329262306a36Sopenharmony_ci			break;
329362306a36Sopenharmony_ci		netdev_set_tc_queue(netdev, i,
329462306a36Sopenharmony_ci				    vsi->mqprio_qopt.qopt.count[i],
329562306a36Sopenharmony_ci				    vsi->mqprio_qopt.qopt.offset[i]);
329662306a36Sopenharmony_ci	}
329762306a36Sopenharmony_ci
329862306a36Sopenharmony_ci	if (test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))
329962306a36Sopenharmony_ci		return;
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) {
330262306a36Sopenharmony_ci		u8 ets_tc = dcbcfg->etscfg.prio_table[i];
330362306a36Sopenharmony_ci
330462306a36Sopenharmony_ci		/* Get the mapped netdev TC# for the UP */
330562306a36Sopenharmony_ci		netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc;
330662306a36Sopenharmony_ci		netdev_set_prio_tc_map(netdev, i, netdev_tc);
330762306a36Sopenharmony_ci	}
330862306a36Sopenharmony_ci}
330962306a36Sopenharmony_ci
331062306a36Sopenharmony_ci/**
331162306a36Sopenharmony_ci * ice_vsi_setup_q_map_mqprio - Prepares mqprio based tc_config
331262306a36Sopenharmony_ci * @vsi: the VSI being configured,
331362306a36Sopenharmony_ci * @ctxt: VSI context structure
331462306a36Sopenharmony_ci * @ena_tc: number of traffic classes to enable
331562306a36Sopenharmony_ci *
331662306a36Sopenharmony_ci * Prepares VSI tc_config to have queue configurations based on MQPRIO options.
331762306a36Sopenharmony_ci */
331862306a36Sopenharmony_cistatic int
331962306a36Sopenharmony_ciice_vsi_setup_q_map_mqprio(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt,
332062306a36Sopenharmony_ci			   u8 ena_tc)
332162306a36Sopenharmony_ci{
332262306a36Sopenharmony_ci	u16 pow, offset = 0, qcount_tx = 0, qcount_rx = 0, qmap;
332362306a36Sopenharmony_ci	u16 tc0_offset = vsi->mqprio_qopt.qopt.offset[0];
332462306a36Sopenharmony_ci	int tc0_qcount = vsi->mqprio_qopt.qopt.count[0];
332562306a36Sopenharmony_ci	u16 new_txq, new_rxq;
332662306a36Sopenharmony_ci	u8 netdev_tc = 0;
332762306a36Sopenharmony_ci	int i;
332862306a36Sopenharmony_ci
332962306a36Sopenharmony_ci	vsi->tc_cfg.ena_tc = ena_tc ? ena_tc : 1;
333062306a36Sopenharmony_ci
333162306a36Sopenharmony_ci	pow = order_base_2(tc0_qcount);
333262306a36Sopenharmony_ci	qmap = ((tc0_offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
333362306a36Sopenharmony_ci		ICE_AQ_VSI_TC_Q_OFFSET_M) |
333462306a36Sopenharmony_ci		((pow << ICE_AQ_VSI_TC_Q_NUM_S) & ICE_AQ_VSI_TC_Q_NUM_M);
333562306a36Sopenharmony_ci
333662306a36Sopenharmony_ci	ice_for_each_traffic_class(i) {
333762306a36Sopenharmony_ci		if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
333862306a36Sopenharmony_ci			/* TC is not enabled */
333962306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qoffset = 0;
334062306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qcount_rx = 1;
334162306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qcount_tx = 1;
334262306a36Sopenharmony_ci			vsi->tc_cfg.tc_info[i].netdev_tc = 0;
334362306a36Sopenharmony_ci			ctxt->info.tc_mapping[i] = 0;
334462306a36Sopenharmony_ci			continue;
334562306a36Sopenharmony_ci		}
334662306a36Sopenharmony_ci
334762306a36Sopenharmony_ci		offset = vsi->mqprio_qopt.qopt.offset[i];
334862306a36Sopenharmony_ci		qcount_rx = vsi->mqprio_qopt.qopt.count[i];
334962306a36Sopenharmony_ci		qcount_tx = vsi->mqprio_qopt.qopt.count[i];
335062306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qoffset = offset;
335162306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx;
335262306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qcount_tx = qcount_tx;
335362306a36Sopenharmony_ci		vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++;
335462306a36Sopenharmony_ci	}
335562306a36Sopenharmony_ci
335662306a36Sopenharmony_ci	if (vsi->all_numtc && vsi->all_numtc != vsi->tc_cfg.numtc) {
335762306a36Sopenharmony_ci		ice_for_each_chnl_tc(i) {
335862306a36Sopenharmony_ci			if (!(vsi->all_enatc & BIT(i)))
335962306a36Sopenharmony_ci				continue;
336062306a36Sopenharmony_ci			offset = vsi->mqprio_qopt.qopt.offset[i];
336162306a36Sopenharmony_ci			qcount_rx = vsi->mqprio_qopt.qopt.count[i];
336262306a36Sopenharmony_ci			qcount_tx = vsi->mqprio_qopt.qopt.count[i];
336362306a36Sopenharmony_ci		}
336462306a36Sopenharmony_ci	}
336562306a36Sopenharmony_ci
336662306a36Sopenharmony_ci	new_txq = offset + qcount_tx;
336762306a36Sopenharmony_ci	if (new_txq > vsi->alloc_txq) {
336862306a36Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Tx queues (%u), than were allocated (%u)!\n",
336962306a36Sopenharmony_ci			new_txq, vsi->alloc_txq);
337062306a36Sopenharmony_ci		return -EINVAL;
337162306a36Sopenharmony_ci	}
337262306a36Sopenharmony_ci
337362306a36Sopenharmony_ci	new_rxq = offset + qcount_rx;
337462306a36Sopenharmony_ci	if (new_rxq > vsi->alloc_rxq) {
337562306a36Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Trying to use more Rx queues (%u), than were allocated (%u)!\n",
337662306a36Sopenharmony_ci			new_rxq, vsi->alloc_rxq);
337762306a36Sopenharmony_ci		return -EINVAL;
337862306a36Sopenharmony_ci	}
337962306a36Sopenharmony_ci
338062306a36Sopenharmony_ci	/* Set actual Tx/Rx queue pairs */
338162306a36Sopenharmony_ci	vsi->num_txq = new_txq;
338262306a36Sopenharmony_ci	vsi->num_rxq = new_rxq;
338362306a36Sopenharmony_ci
338462306a36Sopenharmony_ci	/* Setup queue TC[0].qmap for given VSI context */
338562306a36Sopenharmony_ci	ctxt->info.tc_mapping[0] = cpu_to_le16(qmap);
338662306a36Sopenharmony_ci	ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
338762306a36Sopenharmony_ci	ctxt->info.q_mapping[1] = cpu_to_le16(tc0_qcount);
338862306a36Sopenharmony_ci
338962306a36Sopenharmony_ci	/* Find queue count available for channel VSIs and starting offset
339062306a36Sopenharmony_ci	 * for channel VSIs
339162306a36Sopenharmony_ci	 */
339262306a36Sopenharmony_ci	if (tc0_qcount && tc0_qcount < vsi->num_rxq) {
339362306a36Sopenharmony_ci		vsi->cnt_q_avail = vsi->num_rxq - tc0_qcount;
339462306a36Sopenharmony_ci		vsi->next_base_q = tc0_qcount;
339562306a36Sopenharmony_ci	}
339662306a36Sopenharmony_ci	dev_dbg(ice_pf_to_dev(vsi->back), "vsi->num_txq = %d\n",  vsi->num_txq);
339762306a36Sopenharmony_ci	dev_dbg(ice_pf_to_dev(vsi->back), "vsi->num_rxq = %d\n",  vsi->num_rxq);
339862306a36Sopenharmony_ci	dev_dbg(ice_pf_to_dev(vsi->back), "all_numtc %u, all_enatc: 0x%04x, tc_cfg.numtc %u\n",
339962306a36Sopenharmony_ci		vsi->all_numtc, vsi->all_enatc, vsi->tc_cfg.numtc);
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	return 0;
340262306a36Sopenharmony_ci}
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_ci/**
340562306a36Sopenharmony_ci * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map
340662306a36Sopenharmony_ci * @vsi: VSI to be configured
340762306a36Sopenharmony_ci * @ena_tc: TC bitmap
340862306a36Sopenharmony_ci *
340962306a36Sopenharmony_ci * VSI queues expected to be quiesced before calling this function
341062306a36Sopenharmony_ci */
341162306a36Sopenharmony_ciint ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
341262306a36Sopenharmony_ci{
341362306a36Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
341462306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
341562306a36Sopenharmony_ci	struct ice_tc_cfg old_tc_cfg;
341662306a36Sopenharmony_ci	struct ice_vsi_ctx *ctx;
341762306a36Sopenharmony_ci	struct device *dev;
341862306a36Sopenharmony_ci	int i, ret = 0;
341962306a36Sopenharmony_ci	u8 num_tc = 0;
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
342262306a36Sopenharmony_ci	if (vsi->tc_cfg.ena_tc == ena_tc &&
342362306a36Sopenharmony_ci	    vsi->mqprio_qopt.mode != TC_MQPRIO_MODE_CHANNEL)
342462306a36Sopenharmony_ci		return 0;
342562306a36Sopenharmony_ci
342662306a36Sopenharmony_ci	ice_for_each_traffic_class(i) {
342762306a36Sopenharmony_ci		/* build bitmap of enabled TCs */
342862306a36Sopenharmony_ci		if (ena_tc & BIT(i))
342962306a36Sopenharmony_ci			num_tc++;
343062306a36Sopenharmony_ci		/* populate max_txqs per TC */
343162306a36Sopenharmony_ci		max_txqs[i] = vsi->alloc_txq;
343262306a36Sopenharmony_ci		/* Update max_txqs if it is CHNL VSI, because alloc_t[r]xq are
343362306a36Sopenharmony_ci		 * zero for CHNL VSI, hence use num_txq instead as max_txqs
343462306a36Sopenharmony_ci		 */
343562306a36Sopenharmony_ci		if (vsi->type == ICE_VSI_CHNL &&
343662306a36Sopenharmony_ci		    test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))
343762306a36Sopenharmony_ci			max_txqs[i] = vsi->num_txq;
343862306a36Sopenharmony_ci	}
343962306a36Sopenharmony_ci
344062306a36Sopenharmony_ci	memcpy(&old_tc_cfg, &vsi->tc_cfg, sizeof(old_tc_cfg));
344162306a36Sopenharmony_ci	vsi->tc_cfg.ena_tc = ena_tc;
344262306a36Sopenharmony_ci	vsi->tc_cfg.numtc = num_tc;
344362306a36Sopenharmony_ci
344462306a36Sopenharmony_ci	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
344562306a36Sopenharmony_ci	if (!ctx)
344662306a36Sopenharmony_ci		return -ENOMEM;
344762306a36Sopenharmony_ci
344862306a36Sopenharmony_ci	ctx->vf_num = 0;
344962306a36Sopenharmony_ci	ctx->info = vsi->info;
345062306a36Sopenharmony_ci
345162306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF &&
345262306a36Sopenharmony_ci	    test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))
345362306a36Sopenharmony_ci		ret = ice_vsi_setup_q_map_mqprio(vsi, ctx, ena_tc);
345462306a36Sopenharmony_ci	else
345562306a36Sopenharmony_ci		ret = ice_vsi_setup_q_map(vsi, ctx);
345662306a36Sopenharmony_ci
345762306a36Sopenharmony_ci	if (ret) {
345862306a36Sopenharmony_ci		memcpy(&vsi->tc_cfg, &old_tc_cfg, sizeof(vsi->tc_cfg));
345962306a36Sopenharmony_ci		goto out;
346062306a36Sopenharmony_ci	}
346162306a36Sopenharmony_ci
346262306a36Sopenharmony_ci	/* must to indicate which section of VSI context are being modified */
346362306a36Sopenharmony_ci	ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
346462306a36Sopenharmony_ci	ret = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL);
346562306a36Sopenharmony_ci	if (ret) {
346662306a36Sopenharmony_ci		dev_info(dev, "Failed VSI Update\n");
346762306a36Sopenharmony_ci		goto out;
346862306a36Sopenharmony_ci	}
346962306a36Sopenharmony_ci
347062306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_PF &&
347162306a36Sopenharmony_ci	    test_bit(ICE_FLAG_TC_MQPRIO, pf->flags))
347262306a36Sopenharmony_ci		ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, 1, max_txqs);
347362306a36Sopenharmony_ci	else
347462306a36Sopenharmony_ci		ret = ice_cfg_vsi_lan(vsi->port_info, vsi->idx,
347562306a36Sopenharmony_ci				      vsi->tc_cfg.ena_tc, max_txqs);
347662306a36Sopenharmony_ci
347762306a36Sopenharmony_ci	if (ret) {
347862306a36Sopenharmony_ci		dev_err(dev, "VSI %d failed TC config, error %d\n",
347962306a36Sopenharmony_ci			vsi->vsi_num, ret);
348062306a36Sopenharmony_ci		goto out;
348162306a36Sopenharmony_ci	}
348262306a36Sopenharmony_ci	ice_vsi_update_q_map(vsi, ctx);
348362306a36Sopenharmony_ci	vsi->info.valid_sections = 0;
348462306a36Sopenharmony_ci
348562306a36Sopenharmony_ci	ice_vsi_cfg_netdev_tc(vsi, ena_tc);
348662306a36Sopenharmony_ciout:
348762306a36Sopenharmony_ci	kfree(ctx);
348862306a36Sopenharmony_ci	return ret;
348962306a36Sopenharmony_ci}
349062306a36Sopenharmony_ci
349162306a36Sopenharmony_ci/**
349262306a36Sopenharmony_ci * ice_update_ring_stats - Update ring statistics
349362306a36Sopenharmony_ci * @stats: stats to be updated
349462306a36Sopenharmony_ci * @pkts: number of processed packets
349562306a36Sopenharmony_ci * @bytes: number of processed bytes
349662306a36Sopenharmony_ci *
349762306a36Sopenharmony_ci * This function assumes that caller has acquired a u64_stats_sync lock.
349862306a36Sopenharmony_ci */
349962306a36Sopenharmony_cistatic void ice_update_ring_stats(struct ice_q_stats *stats, u64 pkts, u64 bytes)
350062306a36Sopenharmony_ci{
350162306a36Sopenharmony_ci	stats->bytes += bytes;
350262306a36Sopenharmony_ci	stats->pkts += pkts;
350362306a36Sopenharmony_ci}
350462306a36Sopenharmony_ci
350562306a36Sopenharmony_ci/**
350662306a36Sopenharmony_ci * ice_update_tx_ring_stats - Update Tx ring specific counters
350762306a36Sopenharmony_ci * @tx_ring: ring to update
350862306a36Sopenharmony_ci * @pkts: number of processed packets
350962306a36Sopenharmony_ci * @bytes: number of processed bytes
351062306a36Sopenharmony_ci */
351162306a36Sopenharmony_civoid ice_update_tx_ring_stats(struct ice_tx_ring *tx_ring, u64 pkts, u64 bytes)
351262306a36Sopenharmony_ci{
351362306a36Sopenharmony_ci	u64_stats_update_begin(&tx_ring->ring_stats->syncp);
351462306a36Sopenharmony_ci	ice_update_ring_stats(&tx_ring->ring_stats->stats, pkts, bytes);
351562306a36Sopenharmony_ci	u64_stats_update_end(&tx_ring->ring_stats->syncp);
351662306a36Sopenharmony_ci}
351762306a36Sopenharmony_ci
351862306a36Sopenharmony_ci/**
351962306a36Sopenharmony_ci * ice_update_rx_ring_stats - Update Rx ring specific counters
352062306a36Sopenharmony_ci * @rx_ring: ring to update
352162306a36Sopenharmony_ci * @pkts: number of processed packets
352262306a36Sopenharmony_ci * @bytes: number of processed bytes
352362306a36Sopenharmony_ci */
352462306a36Sopenharmony_civoid ice_update_rx_ring_stats(struct ice_rx_ring *rx_ring, u64 pkts, u64 bytes)
352562306a36Sopenharmony_ci{
352662306a36Sopenharmony_ci	u64_stats_update_begin(&rx_ring->ring_stats->syncp);
352762306a36Sopenharmony_ci	ice_update_ring_stats(&rx_ring->ring_stats->stats, pkts, bytes);
352862306a36Sopenharmony_ci	u64_stats_update_end(&rx_ring->ring_stats->syncp);
352962306a36Sopenharmony_ci}
353062306a36Sopenharmony_ci
353162306a36Sopenharmony_ci/**
353262306a36Sopenharmony_ci * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
353362306a36Sopenharmony_ci * @pi: port info of the switch with default VSI
353462306a36Sopenharmony_ci *
353562306a36Sopenharmony_ci * Return true if the there is a single VSI in default forwarding VSI list
353662306a36Sopenharmony_ci */
353762306a36Sopenharmony_cibool ice_is_dflt_vsi_in_use(struct ice_port_info *pi)
353862306a36Sopenharmony_ci{
353962306a36Sopenharmony_ci	bool exists = false;
354062306a36Sopenharmony_ci
354162306a36Sopenharmony_ci	ice_check_if_dflt_vsi(pi, 0, &exists);
354262306a36Sopenharmony_ci	return exists;
354362306a36Sopenharmony_ci}
354462306a36Sopenharmony_ci
354562306a36Sopenharmony_ci/**
354662306a36Sopenharmony_ci * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI
354762306a36Sopenharmony_ci * @vsi: VSI to compare against default forwarding VSI
354862306a36Sopenharmony_ci *
354962306a36Sopenharmony_ci * If this VSI passed in is the default forwarding VSI then return true, else
355062306a36Sopenharmony_ci * return false
355162306a36Sopenharmony_ci */
355262306a36Sopenharmony_cibool ice_is_vsi_dflt_vsi(struct ice_vsi *vsi)
355362306a36Sopenharmony_ci{
355462306a36Sopenharmony_ci	return ice_check_if_dflt_vsi(vsi->port_info, vsi->idx, NULL);
355562306a36Sopenharmony_ci}
355662306a36Sopenharmony_ci
355762306a36Sopenharmony_ci/**
355862306a36Sopenharmony_ci * ice_set_dflt_vsi - set the default forwarding VSI
355962306a36Sopenharmony_ci * @vsi: VSI getting set as the default forwarding VSI on the switch
356062306a36Sopenharmony_ci *
356162306a36Sopenharmony_ci * If the VSI passed in is already the default VSI and it's enabled just return
356262306a36Sopenharmony_ci * success.
356362306a36Sopenharmony_ci *
356462306a36Sopenharmony_ci * Otherwise try to set the VSI passed in as the switch's default VSI and
356562306a36Sopenharmony_ci * return the result.
356662306a36Sopenharmony_ci */
356762306a36Sopenharmony_ciint ice_set_dflt_vsi(struct ice_vsi *vsi)
356862306a36Sopenharmony_ci{
356962306a36Sopenharmony_ci	struct device *dev;
357062306a36Sopenharmony_ci	int status;
357162306a36Sopenharmony_ci
357262306a36Sopenharmony_ci	if (!vsi)
357362306a36Sopenharmony_ci		return -EINVAL;
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_ci	dev = ice_pf_to_dev(vsi->back);
357662306a36Sopenharmony_ci
357762306a36Sopenharmony_ci	if (ice_lag_is_switchdev_running(vsi->back)) {
357862306a36Sopenharmony_ci		dev_dbg(dev, "VSI %d passed is a part of LAG containing interfaces in switchdev mode, nothing to do\n",
357962306a36Sopenharmony_ci			vsi->vsi_num);
358062306a36Sopenharmony_ci		return 0;
358162306a36Sopenharmony_ci	}
358262306a36Sopenharmony_ci
358362306a36Sopenharmony_ci	/* the VSI passed in is already the default VSI */
358462306a36Sopenharmony_ci	if (ice_is_vsi_dflt_vsi(vsi)) {
358562306a36Sopenharmony_ci		dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
358662306a36Sopenharmony_ci			vsi->vsi_num);
358762306a36Sopenharmony_ci		return 0;
358862306a36Sopenharmony_ci	}
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci	status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, true, ICE_FLTR_RX);
359162306a36Sopenharmony_ci	if (status) {
359262306a36Sopenharmony_ci		dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %d\n",
359362306a36Sopenharmony_ci			vsi->vsi_num, status);
359462306a36Sopenharmony_ci		return status;
359562306a36Sopenharmony_ci	}
359662306a36Sopenharmony_ci
359762306a36Sopenharmony_ci	return 0;
359862306a36Sopenharmony_ci}
359962306a36Sopenharmony_ci
360062306a36Sopenharmony_ci/**
360162306a36Sopenharmony_ci * ice_clear_dflt_vsi - clear the default forwarding VSI
360262306a36Sopenharmony_ci * @vsi: VSI to remove from filter list
360362306a36Sopenharmony_ci *
360462306a36Sopenharmony_ci * If the switch has no default VSI or it's not enabled then return error.
360562306a36Sopenharmony_ci *
360662306a36Sopenharmony_ci * Otherwise try to clear the default VSI and return the result.
360762306a36Sopenharmony_ci */
360862306a36Sopenharmony_ciint ice_clear_dflt_vsi(struct ice_vsi *vsi)
360962306a36Sopenharmony_ci{
361062306a36Sopenharmony_ci	struct device *dev;
361162306a36Sopenharmony_ci	int status;
361262306a36Sopenharmony_ci
361362306a36Sopenharmony_ci	if (!vsi)
361462306a36Sopenharmony_ci		return -EINVAL;
361562306a36Sopenharmony_ci
361662306a36Sopenharmony_ci	dev = ice_pf_to_dev(vsi->back);
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_ci	/* there is no default VSI configured */
361962306a36Sopenharmony_ci	if (!ice_is_dflt_vsi_in_use(vsi->port_info))
362062306a36Sopenharmony_ci		return -ENODEV;
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_ci	status = ice_cfg_dflt_vsi(vsi->port_info, vsi->idx, false,
362362306a36Sopenharmony_ci				  ICE_FLTR_RX);
362462306a36Sopenharmony_ci	if (status) {
362562306a36Sopenharmony_ci		dev_err(dev, "Failed to clear the default forwarding VSI %d, error %d\n",
362662306a36Sopenharmony_ci			vsi->vsi_num, status);
362762306a36Sopenharmony_ci		return -EIO;
362862306a36Sopenharmony_ci	}
362962306a36Sopenharmony_ci
363062306a36Sopenharmony_ci	return 0;
363162306a36Sopenharmony_ci}
363262306a36Sopenharmony_ci
363362306a36Sopenharmony_ci/**
363462306a36Sopenharmony_ci * ice_get_link_speed_mbps - get link speed in Mbps
363562306a36Sopenharmony_ci * @vsi: the VSI whose link speed is being queried
363662306a36Sopenharmony_ci *
363762306a36Sopenharmony_ci * Return current VSI link speed and 0 if the speed is unknown.
363862306a36Sopenharmony_ci */
363962306a36Sopenharmony_ciint ice_get_link_speed_mbps(struct ice_vsi *vsi)
364062306a36Sopenharmony_ci{
364162306a36Sopenharmony_ci	unsigned int link_speed;
364262306a36Sopenharmony_ci
364362306a36Sopenharmony_ci	link_speed = vsi->port_info->phy.link_info.link_speed;
364462306a36Sopenharmony_ci
364562306a36Sopenharmony_ci	return (int)ice_get_link_speed(fls(link_speed) - 1);
364662306a36Sopenharmony_ci}
364762306a36Sopenharmony_ci
364862306a36Sopenharmony_ci/**
364962306a36Sopenharmony_ci * ice_get_link_speed_kbps - get link speed in Kbps
365062306a36Sopenharmony_ci * @vsi: the VSI whose link speed is being queried
365162306a36Sopenharmony_ci *
365262306a36Sopenharmony_ci * Return current VSI link speed and 0 if the speed is unknown.
365362306a36Sopenharmony_ci */
365462306a36Sopenharmony_ciint ice_get_link_speed_kbps(struct ice_vsi *vsi)
365562306a36Sopenharmony_ci{
365662306a36Sopenharmony_ci	int speed_mbps;
365762306a36Sopenharmony_ci
365862306a36Sopenharmony_ci	speed_mbps = ice_get_link_speed_mbps(vsi);
365962306a36Sopenharmony_ci
366062306a36Sopenharmony_ci	return speed_mbps * 1000;
366162306a36Sopenharmony_ci}
366262306a36Sopenharmony_ci
366362306a36Sopenharmony_ci/**
366462306a36Sopenharmony_ci * ice_set_min_bw_limit - setup minimum BW limit for Tx based on min_tx_rate
366562306a36Sopenharmony_ci * @vsi: VSI to be configured
366662306a36Sopenharmony_ci * @min_tx_rate: min Tx rate in Kbps to be configured as BW limit
366762306a36Sopenharmony_ci *
366862306a36Sopenharmony_ci * If the min_tx_rate is specified as 0 that means to clear the minimum BW limit
366962306a36Sopenharmony_ci * profile, otherwise a non-zero value will force a minimum BW limit for the VSI
367062306a36Sopenharmony_ci * on TC 0.
367162306a36Sopenharmony_ci */
367262306a36Sopenharmony_ciint ice_set_min_bw_limit(struct ice_vsi *vsi, u64 min_tx_rate)
367362306a36Sopenharmony_ci{
367462306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
367562306a36Sopenharmony_ci	struct device *dev;
367662306a36Sopenharmony_ci	int status;
367762306a36Sopenharmony_ci	int speed;
367862306a36Sopenharmony_ci
367962306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
368062306a36Sopenharmony_ci	if (!vsi->port_info) {
368162306a36Sopenharmony_ci		dev_dbg(dev, "VSI %d, type %u specified doesn't have valid port_info\n",
368262306a36Sopenharmony_ci			vsi->idx, vsi->type);
368362306a36Sopenharmony_ci		return -EINVAL;
368462306a36Sopenharmony_ci	}
368562306a36Sopenharmony_ci
368662306a36Sopenharmony_ci	speed = ice_get_link_speed_kbps(vsi);
368762306a36Sopenharmony_ci	if (min_tx_rate > (u64)speed) {
368862306a36Sopenharmony_ci		dev_err(dev, "invalid min Tx rate %llu Kbps specified for %s %d is greater than current link speed %u Kbps\n",
368962306a36Sopenharmony_ci			min_tx_rate, ice_vsi_type_str(vsi->type), vsi->idx,
369062306a36Sopenharmony_ci			speed);
369162306a36Sopenharmony_ci		return -EINVAL;
369262306a36Sopenharmony_ci	}
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_ci	/* Configure min BW for VSI limit */
369562306a36Sopenharmony_ci	if (min_tx_rate) {
369662306a36Sopenharmony_ci		status = ice_cfg_vsi_bw_lmt_per_tc(vsi->port_info, vsi->idx, 0,
369762306a36Sopenharmony_ci						   ICE_MIN_BW, min_tx_rate);
369862306a36Sopenharmony_ci		if (status) {
369962306a36Sopenharmony_ci			dev_err(dev, "failed to set min Tx rate(%llu Kbps) for %s %d\n",
370062306a36Sopenharmony_ci				min_tx_rate, ice_vsi_type_str(vsi->type),
370162306a36Sopenharmony_ci				vsi->idx);
370262306a36Sopenharmony_ci			return status;
370362306a36Sopenharmony_ci		}
370462306a36Sopenharmony_ci
370562306a36Sopenharmony_ci		dev_dbg(dev, "set min Tx rate(%llu Kbps) for %s\n",
370662306a36Sopenharmony_ci			min_tx_rate, ice_vsi_type_str(vsi->type));
370762306a36Sopenharmony_ci	} else {
370862306a36Sopenharmony_ci		status = ice_cfg_vsi_bw_dflt_lmt_per_tc(vsi->port_info,
370962306a36Sopenharmony_ci							vsi->idx, 0,
371062306a36Sopenharmony_ci							ICE_MIN_BW);
371162306a36Sopenharmony_ci		if (status) {
371262306a36Sopenharmony_ci			dev_err(dev, "failed to clear min Tx rate configuration for %s %d\n",
371362306a36Sopenharmony_ci				ice_vsi_type_str(vsi->type), vsi->idx);
371462306a36Sopenharmony_ci			return status;
371562306a36Sopenharmony_ci		}
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_ci		dev_dbg(dev, "cleared min Tx rate configuration for %s %d\n",
371862306a36Sopenharmony_ci			ice_vsi_type_str(vsi->type), vsi->idx);
371962306a36Sopenharmony_ci	}
372062306a36Sopenharmony_ci
372162306a36Sopenharmony_ci	return 0;
372262306a36Sopenharmony_ci}
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_ci/**
372562306a36Sopenharmony_ci * ice_set_max_bw_limit - setup maximum BW limit for Tx based on max_tx_rate
372662306a36Sopenharmony_ci * @vsi: VSI to be configured
372762306a36Sopenharmony_ci * @max_tx_rate: max Tx rate in Kbps to be configured as BW limit
372862306a36Sopenharmony_ci *
372962306a36Sopenharmony_ci * If the max_tx_rate is specified as 0 that means to clear the maximum BW limit
373062306a36Sopenharmony_ci * profile, otherwise a non-zero value will force a maximum BW limit for the VSI
373162306a36Sopenharmony_ci * on TC 0.
373262306a36Sopenharmony_ci */
373362306a36Sopenharmony_ciint ice_set_max_bw_limit(struct ice_vsi *vsi, u64 max_tx_rate)
373462306a36Sopenharmony_ci{
373562306a36Sopenharmony_ci	struct ice_pf *pf = vsi->back;
373662306a36Sopenharmony_ci	struct device *dev;
373762306a36Sopenharmony_ci	int status;
373862306a36Sopenharmony_ci	int speed;
373962306a36Sopenharmony_ci
374062306a36Sopenharmony_ci	dev = ice_pf_to_dev(pf);
374162306a36Sopenharmony_ci	if (!vsi->port_info) {
374262306a36Sopenharmony_ci		dev_dbg(dev, "VSI %d, type %u specified doesn't have valid port_info\n",
374362306a36Sopenharmony_ci			vsi->idx, vsi->type);
374462306a36Sopenharmony_ci		return -EINVAL;
374562306a36Sopenharmony_ci	}
374662306a36Sopenharmony_ci
374762306a36Sopenharmony_ci	speed = ice_get_link_speed_kbps(vsi);
374862306a36Sopenharmony_ci	if (max_tx_rate > (u64)speed) {
374962306a36Sopenharmony_ci		dev_err(dev, "invalid max Tx rate %llu Kbps specified for %s %d is greater than current link speed %u Kbps\n",
375062306a36Sopenharmony_ci			max_tx_rate, ice_vsi_type_str(vsi->type), vsi->idx,
375162306a36Sopenharmony_ci			speed);
375262306a36Sopenharmony_ci		return -EINVAL;
375362306a36Sopenharmony_ci	}
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci	/* Configure max BW for VSI limit */
375662306a36Sopenharmony_ci	if (max_tx_rate) {
375762306a36Sopenharmony_ci		status = ice_cfg_vsi_bw_lmt_per_tc(vsi->port_info, vsi->idx, 0,
375862306a36Sopenharmony_ci						   ICE_MAX_BW, max_tx_rate);
375962306a36Sopenharmony_ci		if (status) {
376062306a36Sopenharmony_ci			dev_err(dev, "failed setting max Tx rate(%llu Kbps) for %s %d\n",
376162306a36Sopenharmony_ci				max_tx_rate, ice_vsi_type_str(vsi->type),
376262306a36Sopenharmony_ci				vsi->idx);
376362306a36Sopenharmony_ci			return status;
376462306a36Sopenharmony_ci		}
376562306a36Sopenharmony_ci
376662306a36Sopenharmony_ci		dev_dbg(dev, "set max Tx rate(%llu Kbps) for %s %d\n",
376762306a36Sopenharmony_ci			max_tx_rate, ice_vsi_type_str(vsi->type), vsi->idx);
376862306a36Sopenharmony_ci	} else {
376962306a36Sopenharmony_ci		status = ice_cfg_vsi_bw_dflt_lmt_per_tc(vsi->port_info,
377062306a36Sopenharmony_ci							vsi->idx, 0,
377162306a36Sopenharmony_ci							ICE_MAX_BW);
377262306a36Sopenharmony_ci		if (status) {
377362306a36Sopenharmony_ci			dev_err(dev, "failed clearing max Tx rate configuration for %s %d\n",
377462306a36Sopenharmony_ci				ice_vsi_type_str(vsi->type), vsi->idx);
377562306a36Sopenharmony_ci			return status;
377662306a36Sopenharmony_ci		}
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_ci		dev_dbg(dev, "cleared max Tx rate configuration for %s %d\n",
377962306a36Sopenharmony_ci			ice_vsi_type_str(vsi->type), vsi->idx);
378062306a36Sopenharmony_ci	}
378162306a36Sopenharmony_ci
378262306a36Sopenharmony_ci	return 0;
378362306a36Sopenharmony_ci}
378462306a36Sopenharmony_ci
378562306a36Sopenharmony_ci/**
378662306a36Sopenharmony_ci * ice_set_link - turn on/off physical link
378762306a36Sopenharmony_ci * @vsi: VSI to modify physical link on
378862306a36Sopenharmony_ci * @ena: turn on/off physical link
378962306a36Sopenharmony_ci */
379062306a36Sopenharmony_ciint ice_set_link(struct ice_vsi *vsi, bool ena)
379162306a36Sopenharmony_ci{
379262306a36Sopenharmony_ci	struct device *dev = ice_pf_to_dev(vsi->back);
379362306a36Sopenharmony_ci	struct ice_port_info *pi = vsi->port_info;
379462306a36Sopenharmony_ci	struct ice_hw *hw = pi->hw;
379562306a36Sopenharmony_ci	int status;
379662306a36Sopenharmony_ci
379762306a36Sopenharmony_ci	if (vsi->type != ICE_VSI_PF)
379862306a36Sopenharmony_ci		return -EINVAL;
379962306a36Sopenharmony_ci
380062306a36Sopenharmony_ci	status = ice_aq_set_link_restart_an(pi, ena, NULL);
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_ci	/* if link is owned by manageability, FW will return ICE_AQ_RC_EMODE.
380362306a36Sopenharmony_ci	 * this is not a fatal error, so print a warning message and return
380462306a36Sopenharmony_ci	 * a success code. Return an error if FW returns an error code other
380562306a36Sopenharmony_ci	 * than ICE_AQ_RC_EMODE
380662306a36Sopenharmony_ci	 */
380762306a36Sopenharmony_ci	if (status == -EIO) {
380862306a36Sopenharmony_ci		if (hw->adminq.sq_last_status == ICE_AQ_RC_EMODE)
380962306a36Sopenharmony_ci			dev_dbg(dev, "can't set link to %s, err %d aq_err %s. not fatal, continuing\n",
381062306a36Sopenharmony_ci				(ena ? "ON" : "OFF"), status,
381162306a36Sopenharmony_ci				ice_aq_str(hw->adminq.sq_last_status));
381262306a36Sopenharmony_ci	} else if (status) {
381362306a36Sopenharmony_ci		dev_err(dev, "can't set link to %s, err %d aq_err %s\n",
381462306a36Sopenharmony_ci			(ena ? "ON" : "OFF"), status,
381562306a36Sopenharmony_ci			ice_aq_str(hw->adminq.sq_last_status));
381662306a36Sopenharmony_ci		return status;
381762306a36Sopenharmony_ci	}
381862306a36Sopenharmony_ci
381962306a36Sopenharmony_ci	return 0;
382062306a36Sopenharmony_ci}
382162306a36Sopenharmony_ci
382262306a36Sopenharmony_ci/**
382362306a36Sopenharmony_ci * ice_vsi_add_vlan_zero - add VLAN 0 filter(s) for this VSI
382462306a36Sopenharmony_ci * @vsi: VSI used to add VLAN filters
382562306a36Sopenharmony_ci *
382662306a36Sopenharmony_ci * In Single VLAN Mode (SVM), single VLAN filters via ICE_SW_LKUP_VLAN are based
382762306a36Sopenharmony_ci * on the inner VLAN ID, so the VLAN TPID (i.e. 0x8100 or 0x888a8) doesn't
382862306a36Sopenharmony_ci * matter. In Double VLAN Mode (DVM), outer/single VLAN filters via
382962306a36Sopenharmony_ci * ICE_SW_LKUP_VLAN are based on the outer/single VLAN ID + VLAN TPID.
383062306a36Sopenharmony_ci *
383162306a36Sopenharmony_ci * For both modes add a VLAN 0 + no VLAN TPID filter to handle untagged traffic
383262306a36Sopenharmony_ci * when VLAN pruning is enabled. Also, this handles VLAN 0 priority tagged
383362306a36Sopenharmony_ci * traffic in SVM, since the VLAN TPID isn't part of filtering.
383462306a36Sopenharmony_ci *
383562306a36Sopenharmony_ci * If DVM is enabled then an explicit VLAN 0 + VLAN TPID filter needs to be
383662306a36Sopenharmony_ci * added to allow VLAN 0 priority tagged traffic in DVM, since the VLAN TPID is
383762306a36Sopenharmony_ci * part of filtering.
383862306a36Sopenharmony_ci */
383962306a36Sopenharmony_ciint ice_vsi_add_vlan_zero(struct ice_vsi *vsi)
384062306a36Sopenharmony_ci{
384162306a36Sopenharmony_ci	struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
384262306a36Sopenharmony_ci	struct ice_vlan vlan;
384362306a36Sopenharmony_ci	int err;
384462306a36Sopenharmony_ci
384562306a36Sopenharmony_ci	vlan = ICE_VLAN(0, 0, 0);
384662306a36Sopenharmony_ci	err = vlan_ops->add_vlan(vsi, &vlan);
384762306a36Sopenharmony_ci	if (err && err != -EEXIST)
384862306a36Sopenharmony_ci		return err;
384962306a36Sopenharmony_ci
385062306a36Sopenharmony_ci	/* in SVM both VLAN 0 filters are identical */
385162306a36Sopenharmony_ci	if (!ice_is_dvm_ena(&vsi->back->hw))
385262306a36Sopenharmony_ci		return 0;
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_ci	vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
385562306a36Sopenharmony_ci	err = vlan_ops->add_vlan(vsi, &vlan);
385662306a36Sopenharmony_ci	if (err && err != -EEXIST)
385762306a36Sopenharmony_ci		return err;
385862306a36Sopenharmony_ci
385962306a36Sopenharmony_ci	return 0;
386062306a36Sopenharmony_ci}
386162306a36Sopenharmony_ci
386262306a36Sopenharmony_ci/**
386362306a36Sopenharmony_ci * ice_vsi_del_vlan_zero - delete VLAN 0 filter(s) for this VSI
386462306a36Sopenharmony_ci * @vsi: VSI used to add VLAN filters
386562306a36Sopenharmony_ci *
386662306a36Sopenharmony_ci * Delete the VLAN 0 filters in the same manner that they were added in
386762306a36Sopenharmony_ci * ice_vsi_add_vlan_zero.
386862306a36Sopenharmony_ci */
386962306a36Sopenharmony_ciint ice_vsi_del_vlan_zero(struct ice_vsi *vsi)
387062306a36Sopenharmony_ci{
387162306a36Sopenharmony_ci	struct ice_vsi_vlan_ops *vlan_ops = ice_get_compat_vsi_vlan_ops(vsi);
387262306a36Sopenharmony_ci	struct ice_vlan vlan;
387362306a36Sopenharmony_ci	int err;
387462306a36Sopenharmony_ci
387562306a36Sopenharmony_ci	vlan = ICE_VLAN(0, 0, 0);
387662306a36Sopenharmony_ci	err = vlan_ops->del_vlan(vsi, &vlan);
387762306a36Sopenharmony_ci	if (err && err != -EEXIST)
387862306a36Sopenharmony_ci		return err;
387962306a36Sopenharmony_ci
388062306a36Sopenharmony_ci	/* in SVM both VLAN 0 filters are identical */
388162306a36Sopenharmony_ci	if (!ice_is_dvm_ena(&vsi->back->hw))
388262306a36Sopenharmony_ci		return 0;
388362306a36Sopenharmony_ci
388462306a36Sopenharmony_ci	vlan = ICE_VLAN(ETH_P_8021Q, 0, 0);
388562306a36Sopenharmony_ci	err = vlan_ops->del_vlan(vsi, &vlan);
388662306a36Sopenharmony_ci	if (err && err != -EEXIST)
388762306a36Sopenharmony_ci		return err;
388862306a36Sopenharmony_ci
388962306a36Sopenharmony_ci	/* when deleting the last VLAN filter, make sure to disable the VLAN
389062306a36Sopenharmony_ci	 * promisc mode so the filter isn't left by accident
389162306a36Sopenharmony_ci	 */
389262306a36Sopenharmony_ci	return ice_clear_vsi_promisc(&vsi->back->hw, vsi->idx,
389362306a36Sopenharmony_ci				    ICE_MCAST_VLAN_PROMISC_BITS, 0);
389462306a36Sopenharmony_ci}
389562306a36Sopenharmony_ci
389662306a36Sopenharmony_ci/**
389762306a36Sopenharmony_ci * ice_vsi_num_zero_vlans - get number of VLAN 0 filters based on VLAN mode
389862306a36Sopenharmony_ci * @vsi: VSI used to get the VLAN mode
389962306a36Sopenharmony_ci *
390062306a36Sopenharmony_ci * If DVM is enabled then 2 VLAN 0 filters are added, else if SVM is enabled
390162306a36Sopenharmony_ci * then 1 VLAN 0 filter is added. See ice_vsi_add_vlan_zero for more details.
390262306a36Sopenharmony_ci */
390362306a36Sopenharmony_cistatic u16 ice_vsi_num_zero_vlans(struct ice_vsi *vsi)
390462306a36Sopenharmony_ci{
390562306a36Sopenharmony_ci#define ICE_DVM_NUM_ZERO_VLAN_FLTRS	2
390662306a36Sopenharmony_ci#define ICE_SVM_NUM_ZERO_VLAN_FLTRS	1
390762306a36Sopenharmony_ci	/* no VLAN 0 filter is created when a port VLAN is active */
390862306a36Sopenharmony_ci	if (vsi->type == ICE_VSI_VF) {
390962306a36Sopenharmony_ci		if (WARN_ON(!vsi->vf))
391062306a36Sopenharmony_ci			return 0;
391162306a36Sopenharmony_ci
391262306a36Sopenharmony_ci		if (ice_vf_is_port_vlan_ena(vsi->vf))
391362306a36Sopenharmony_ci			return 0;
391462306a36Sopenharmony_ci	}
391562306a36Sopenharmony_ci
391662306a36Sopenharmony_ci	if (ice_is_dvm_ena(&vsi->back->hw))
391762306a36Sopenharmony_ci		return ICE_DVM_NUM_ZERO_VLAN_FLTRS;
391862306a36Sopenharmony_ci	else
391962306a36Sopenharmony_ci		return ICE_SVM_NUM_ZERO_VLAN_FLTRS;
392062306a36Sopenharmony_ci}
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_ci/**
392362306a36Sopenharmony_ci * ice_vsi_has_non_zero_vlans - check if VSI has any non-zero VLANs
392462306a36Sopenharmony_ci * @vsi: VSI used to determine if any non-zero VLANs have been added
392562306a36Sopenharmony_ci */
392662306a36Sopenharmony_cibool ice_vsi_has_non_zero_vlans(struct ice_vsi *vsi)
392762306a36Sopenharmony_ci{
392862306a36Sopenharmony_ci	return (vsi->num_vlan > ice_vsi_num_zero_vlans(vsi));
392962306a36Sopenharmony_ci}
393062306a36Sopenharmony_ci
393162306a36Sopenharmony_ci/**
393262306a36Sopenharmony_ci * ice_vsi_num_non_zero_vlans - get the number of non-zero VLANs for this VSI
393362306a36Sopenharmony_ci * @vsi: VSI used to get the number of non-zero VLANs added
393462306a36Sopenharmony_ci */
393562306a36Sopenharmony_ciu16 ice_vsi_num_non_zero_vlans(struct ice_vsi *vsi)
393662306a36Sopenharmony_ci{
393762306a36Sopenharmony_ci	return (vsi->num_vlan - ice_vsi_num_zero_vlans(vsi));
393862306a36Sopenharmony_ci}
393962306a36Sopenharmony_ci
394062306a36Sopenharmony_ci/**
394162306a36Sopenharmony_ci * ice_is_feature_supported
394262306a36Sopenharmony_ci * @pf: pointer to the struct ice_pf instance
394362306a36Sopenharmony_ci * @f: feature enum to be checked
394462306a36Sopenharmony_ci *
394562306a36Sopenharmony_ci * returns true if feature is supported, false otherwise
394662306a36Sopenharmony_ci */
394762306a36Sopenharmony_cibool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f)
394862306a36Sopenharmony_ci{
394962306a36Sopenharmony_ci	if (f < 0 || f >= ICE_F_MAX)
395062306a36Sopenharmony_ci		return false;
395162306a36Sopenharmony_ci
395262306a36Sopenharmony_ci	return test_bit(f, pf->features);
395362306a36Sopenharmony_ci}
395462306a36Sopenharmony_ci
395562306a36Sopenharmony_ci/**
395662306a36Sopenharmony_ci * ice_set_feature_support
395762306a36Sopenharmony_ci * @pf: pointer to the struct ice_pf instance
395862306a36Sopenharmony_ci * @f: feature enum to set
395962306a36Sopenharmony_ci */
396062306a36Sopenharmony_civoid ice_set_feature_support(struct ice_pf *pf, enum ice_feature f)
396162306a36Sopenharmony_ci{
396262306a36Sopenharmony_ci	if (f < 0 || f >= ICE_F_MAX)
396362306a36Sopenharmony_ci		return;
396462306a36Sopenharmony_ci
396562306a36Sopenharmony_ci	set_bit(f, pf->features);
396662306a36Sopenharmony_ci}
396762306a36Sopenharmony_ci
396862306a36Sopenharmony_ci/**
396962306a36Sopenharmony_ci * ice_clear_feature_support
397062306a36Sopenharmony_ci * @pf: pointer to the struct ice_pf instance
397162306a36Sopenharmony_ci * @f: feature enum to clear
397262306a36Sopenharmony_ci */
397362306a36Sopenharmony_civoid ice_clear_feature_support(struct ice_pf *pf, enum ice_feature f)
397462306a36Sopenharmony_ci{
397562306a36Sopenharmony_ci	if (f < 0 || f >= ICE_F_MAX)
397662306a36Sopenharmony_ci		return;
397762306a36Sopenharmony_ci
397862306a36Sopenharmony_ci	clear_bit(f, pf->features);
397962306a36Sopenharmony_ci}
398062306a36Sopenharmony_ci
398162306a36Sopenharmony_ci/**
398262306a36Sopenharmony_ci * ice_init_feature_support
398362306a36Sopenharmony_ci * @pf: pointer to the struct ice_pf instance
398462306a36Sopenharmony_ci *
398562306a36Sopenharmony_ci * called during init to setup supported feature
398662306a36Sopenharmony_ci */
398762306a36Sopenharmony_civoid ice_init_feature_support(struct ice_pf *pf)
398862306a36Sopenharmony_ci{
398962306a36Sopenharmony_ci	switch (pf->hw.device_id) {
399062306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_BACKPLANE:
399162306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_QSFP:
399262306a36Sopenharmony_ci	case ICE_DEV_ID_E810C_SFP:
399362306a36Sopenharmony_ci		ice_set_feature_support(pf, ICE_F_DSCP);
399462306a36Sopenharmony_ci		ice_set_feature_support(pf, ICE_F_PTP_EXTTS);
399562306a36Sopenharmony_ci		if (ice_is_e810t(&pf->hw)) {
399662306a36Sopenharmony_ci			ice_set_feature_support(pf, ICE_F_SMA_CTRL);
399762306a36Sopenharmony_ci			if (ice_gnss_is_gps_present(&pf->hw))
399862306a36Sopenharmony_ci				ice_set_feature_support(pf, ICE_F_GNSS);
399962306a36Sopenharmony_ci		}
400062306a36Sopenharmony_ci		break;
400162306a36Sopenharmony_ci	default:
400262306a36Sopenharmony_ci		break;
400362306a36Sopenharmony_ci	}
400462306a36Sopenharmony_ci}
400562306a36Sopenharmony_ci
400662306a36Sopenharmony_ci/**
400762306a36Sopenharmony_ci * ice_vsi_update_security - update security block in VSI
400862306a36Sopenharmony_ci * @vsi: pointer to VSI structure
400962306a36Sopenharmony_ci * @fill: function pointer to fill ctx
401062306a36Sopenharmony_ci */
401162306a36Sopenharmony_ciint
401262306a36Sopenharmony_ciice_vsi_update_security(struct ice_vsi *vsi, void (*fill)(struct ice_vsi_ctx *))
401362306a36Sopenharmony_ci{
401462306a36Sopenharmony_ci	struct ice_vsi_ctx ctx = { 0 };
401562306a36Sopenharmony_ci
401662306a36Sopenharmony_ci	ctx.info = vsi->info;
401762306a36Sopenharmony_ci	ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
401862306a36Sopenharmony_ci	fill(&ctx);
401962306a36Sopenharmony_ci
402062306a36Sopenharmony_ci	if (ice_update_vsi(&vsi->back->hw, vsi->idx, &ctx, NULL))
402162306a36Sopenharmony_ci		return -ENODEV;
402262306a36Sopenharmony_ci
402362306a36Sopenharmony_ci	vsi->info = ctx.info;
402462306a36Sopenharmony_ci	return 0;
402562306a36Sopenharmony_ci}
402662306a36Sopenharmony_ci
402762306a36Sopenharmony_ci/**
402862306a36Sopenharmony_ci * ice_vsi_ctx_set_antispoof - set antispoof function in VSI ctx
402962306a36Sopenharmony_ci * @ctx: pointer to VSI ctx structure
403062306a36Sopenharmony_ci */
403162306a36Sopenharmony_civoid ice_vsi_ctx_set_antispoof(struct ice_vsi_ctx *ctx)
403262306a36Sopenharmony_ci{
403362306a36Sopenharmony_ci	ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
403462306a36Sopenharmony_ci			       (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
403562306a36Sopenharmony_ci				ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
403662306a36Sopenharmony_ci}
403762306a36Sopenharmony_ci
403862306a36Sopenharmony_ci/**
403962306a36Sopenharmony_ci * ice_vsi_ctx_clear_antispoof - clear antispoof function in VSI ctx
404062306a36Sopenharmony_ci * @ctx: pointer to VSI ctx structure
404162306a36Sopenharmony_ci */
404262306a36Sopenharmony_civoid ice_vsi_ctx_clear_antispoof(struct ice_vsi_ctx *ctx)
404362306a36Sopenharmony_ci{
404462306a36Sopenharmony_ci	ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF &
404562306a36Sopenharmony_ci			       ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
404662306a36Sopenharmony_ci				 ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
404762306a36Sopenharmony_ci}
404862306a36Sopenharmony_ci
404962306a36Sopenharmony_ci/**
405062306a36Sopenharmony_ci * ice_vsi_ctx_set_allow_override - allow destination override on VSI
405162306a36Sopenharmony_ci * @ctx: pointer to VSI ctx structure
405262306a36Sopenharmony_ci */
405362306a36Sopenharmony_civoid ice_vsi_ctx_set_allow_override(struct ice_vsi_ctx *ctx)
405462306a36Sopenharmony_ci{
405562306a36Sopenharmony_ci	ctx->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
405662306a36Sopenharmony_ci}
405762306a36Sopenharmony_ci
405862306a36Sopenharmony_ci/**
405962306a36Sopenharmony_ci * ice_vsi_ctx_clear_allow_override - turn off destination override on VSI
406062306a36Sopenharmony_ci * @ctx: pointer to VSI ctx structure
406162306a36Sopenharmony_ci */
406262306a36Sopenharmony_civoid ice_vsi_ctx_clear_allow_override(struct ice_vsi_ctx *ctx)
406362306a36Sopenharmony_ci{
406462306a36Sopenharmony_ci	ctx->info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
406562306a36Sopenharmony_ci}
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci/**
406862306a36Sopenharmony_ci * ice_vsi_update_local_lb - update sw block in VSI with local loopback bit
406962306a36Sopenharmony_ci * @vsi: pointer to VSI structure
407062306a36Sopenharmony_ci * @set: set or unset the bit
407162306a36Sopenharmony_ci */
407262306a36Sopenharmony_ciint
407362306a36Sopenharmony_ciice_vsi_update_local_lb(struct ice_vsi *vsi, bool set)
407462306a36Sopenharmony_ci{
407562306a36Sopenharmony_ci	struct ice_vsi_ctx ctx = {
407662306a36Sopenharmony_ci		.info	= vsi->info,
407762306a36Sopenharmony_ci	};
407862306a36Sopenharmony_ci
407962306a36Sopenharmony_ci	ctx.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
408062306a36Sopenharmony_ci	if (set)
408162306a36Sopenharmony_ci		ctx.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_LOCAL_LB;
408262306a36Sopenharmony_ci	else
408362306a36Sopenharmony_ci		ctx.info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_LOCAL_LB;
408462306a36Sopenharmony_ci
408562306a36Sopenharmony_ci	if (ice_update_vsi(&vsi->back->hw, vsi->idx, &ctx, NULL))
408662306a36Sopenharmony_ci		return -ENODEV;
408762306a36Sopenharmony_ci
408862306a36Sopenharmony_ci	vsi->info = ctx.info;
408962306a36Sopenharmony_ci	return 0;
409062306a36Sopenharmony_ci}
4091