18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2018, Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include "ice.h"
58c2ecf20Sopenharmony_ci#include "ice_base.h"
68c2ecf20Sopenharmony_ci#include "ice_flow.h"
78c2ecf20Sopenharmony_ci#include "ice_lib.h"
88c2ecf20Sopenharmony_ci#include "ice_fltr.h"
98c2ecf20Sopenharmony_ci#include "ice_dcb_lib.h"
108c2ecf20Sopenharmony_ci#include "ice_devlink.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/**
138c2ecf20Sopenharmony_ci * ice_vsi_type_str - maps VSI type enum to string equivalents
148c2ecf20Sopenharmony_ci * @vsi_type: VSI type enum
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ciconst char *ice_vsi_type_str(enum ice_vsi_type vsi_type)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	switch (vsi_type) {
198c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
208c2ecf20Sopenharmony_ci		return "ICE_VSI_PF";
218c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
228c2ecf20Sopenharmony_ci		return "ICE_VSI_VF";
238c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
248c2ecf20Sopenharmony_ci		return "ICE_VSI_CTRL";
258c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
268c2ecf20Sopenharmony_ci		return "ICE_VSI_LB";
278c2ecf20Sopenharmony_ci	default:
288c2ecf20Sopenharmony_ci		return "unknown";
298c2ecf20Sopenharmony_ci	}
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/**
338c2ecf20Sopenharmony_ci * ice_vsi_ctrl_all_rx_rings - Start or stop a VSI's Rx rings
348c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
358c2ecf20Sopenharmony_ci * @ena: start or stop the Rx rings
368c2ecf20Sopenharmony_ci *
378c2ecf20Sopenharmony_ci * First enable/disable all of the Rx rings, flush any remaining writes, and
388c2ecf20Sopenharmony_ci * then verify that they have all been enabled/disabled successfully. This will
398c2ecf20Sopenharmony_ci * let all of the register writes complete when enabling/disabling the Rx rings
408c2ecf20Sopenharmony_ci * before waiting for the change in hardware to complete.
418c2ecf20Sopenharmony_ci */
428c2ecf20Sopenharmony_cistatic int ice_vsi_ctrl_all_rx_rings(struct ice_vsi *vsi, bool ena)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	int ret = 0;
458c2ecf20Sopenharmony_ci	u16 i;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_rxq; i++)
488c2ecf20Sopenharmony_ci		ice_vsi_ctrl_one_rx_ring(vsi, ena, i, false);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	ice_flush(&vsi->back->hw);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_rxq; i++) {
538c2ecf20Sopenharmony_ci		ret = ice_vsi_wait_one_rx_ring(vsi, ena, i);
548c2ecf20Sopenharmony_ci		if (ret)
558c2ecf20Sopenharmony_ci			break;
568c2ecf20Sopenharmony_ci	}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	return ret;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/**
628c2ecf20Sopenharmony_ci * ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI
638c2ecf20Sopenharmony_ci * @vsi: VSI pointer
648c2ecf20Sopenharmony_ci *
658c2ecf20Sopenharmony_ci * On error: returns error code (negative)
668c2ecf20Sopenharmony_ci * On success: returns 0
678c2ecf20Sopenharmony_ci */
688c2ecf20Sopenharmony_cistatic int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
718c2ecf20Sopenharmony_ci	struct device *dev;
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	/* allocate memory for both Tx and Rx ring pointers */
768c2ecf20Sopenharmony_ci	vsi->tx_rings = devm_kcalloc(dev, vsi->alloc_txq,
778c2ecf20Sopenharmony_ci				     sizeof(*vsi->tx_rings), GFP_KERNEL);
788c2ecf20Sopenharmony_ci	if (!vsi->tx_rings)
798c2ecf20Sopenharmony_ci		return -ENOMEM;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	vsi->rx_rings = devm_kcalloc(dev, vsi->alloc_rxq,
828c2ecf20Sopenharmony_ci				     sizeof(*vsi->rx_rings), GFP_KERNEL);
838c2ecf20Sopenharmony_ci	if (!vsi->rx_rings)
848c2ecf20Sopenharmony_ci		goto err_rings;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	/* txq_map needs to have enough space to track both Tx (stack) rings
878c2ecf20Sopenharmony_ci	 * and XDP rings; at this point vsi->num_xdp_txq might not be set,
888c2ecf20Sopenharmony_ci	 * so use num_possible_cpus() as we want to always provide XDP ring
898c2ecf20Sopenharmony_ci	 * per CPU, regardless of queue count settings from user that might
908c2ecf20Sopenharmony_ci	 * have come from ethtool's set_channels() callback;
918c2ecf20Sopenharmony_ci	 */
928c2ecf20Sopenharmony_ci	vsi->txq_map = devm_kcalloc(dev, (vsi->alloc_txq + num_possible_cpus()),
938c2ecf20Sopenharmony_ci				    sizeof(*vsi->txq_map), GFP_KERNEL);
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	if (!vsi->txq_map)
968c2ecf20Sopenharmony_ci		goto err_txq_map;
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	vsi->rxq_map = devm_kcalloc(dev, vsi->alloc_rxq,
998c2ecf20Sopenharmony_ci				    sizeof(*vsi->rxq_map), GFP_KERNEL);
1008c2ecf20Sopenharmony_ci	if (!vsi->rxq_map)
1018c2ecf20Sopenharmony_ci		goto err_rxq_map;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	/* There is no need to allocate q_vectors for a loopback VSI. */
1048c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_LB)
1058c2ecf20Sopenharmony_ci		return 0;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	/* allocate memory for q_vector pointers */
1088c2ecf20Sopenharmony_ci	vsi->q_vectors = devm_kcalloc(dev, vsi->num_q_vectors,
1098c2ecf20Sopenharmony_ci				      sizeof(*vsi->q_vectors), GFP_KERNEL);
1108c2ecf20Sopenharmony_ci	if (!vsi->q_vectors)
1118c2ecf20Sopenharmony_ci		goto err_vectors;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	return 0;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cierr_vectors:
1168c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi->rxq_map);
1178c2ecf20Sopenharmony_cierr_rxq_map:
1188c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi->txq_map);
1198c2ecf20Sopenharmony_cierr_txq_map:
1208c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi->rx_rings);
1218c2ecf20Sopenharmony_cierr_rings:
1228c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi->tx_rings);
1238c2ecf20Sopenharmony_ci	return -ENOMEM;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci/**
1278c2ecf20Sopenharmony_ci * ice_vsi_set_num_desc - Set number of descriptors for queues on this VSI
1288c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
1298c2ecf20Sopenharmony_ci */
1308c2ecf20Sopenharmony_cistatic void ice_vsi_set_num_desc(struct ice_vsi *vsi)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	switch (vsi->type) {
1338c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
1348c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
1358c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
1368c2ecf20Sopenharmony_ci		/* a user could change the values of num_[tr]x_desc using
1378c2ecf20Sopenharmony_ci		 * ethtool -G so we should keep those values instead of
1388c2ecf20Sopenharmony_ci		 * overwriting them with the defaults.
1398c2ecf20Sopenharmony_ci		 */
1408c2ecf20Sopenharmony_ci		if (!vsi->num_rx_desc)
1418c2ecf20Sopenharmony_ci			vsi->num_rx_desc = ICE_DFLT_NUM_RX_DESC;
1428c2ecf20Sopenharmony_ci		if (!vsi->num_tx_desc)
1438c2ecf20Sopenharmony_ci			vsi->num_tx_desc = ICE_DFLT_NUM_TX_DESC;
1448c2ecf20Sopenharmony_ci		break;
1458c2ecf20Sopenharmony_ci	default:
1468c2ecf20Sopenharmony_ci		dev_dbg(ice_pf_to_dev(vsi->back), "Not setting number of Tx/Rx descriptors for VSI type %d\n",
1478c2ecf20Sopenharmony_ci			vsi->type);
1488c2ecf20Sopenharmony_ci		break;
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/**
1538c2ecf20Sopenharmony_ci * ice_vsi_set_num_qs - Set number of queues, descriptors and vectors for a VSI
1548c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
1558c2ecf20Sopenharmony_ci * @vf_id: ID of the VF being configured
1568c2ecf20Sopenharmony_ci *
1578c2ecf20Sopenharmony_ci * Return 0 on success and a negative value on error
1588c2ecf20Sopenharmony_ci */
1598c2ecf20Sopenharmony_cistatic void ice_vsi_set_num_qs(struct ice_vsi *vsi, u16 vf_id)
1608c2ecf20Sopenharmony_ci{
1618c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
1628c2ecf20Sopenharmony_ci	struct ice_vf *vf = NULL;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
1658c2ecf20Sopenharmony_ci		vsi->vf_id = vf_id;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	switch (vsi->type) {
1688c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
1698c2ecf20Sopenharmony_ci		vsi->alloc_txq = min3(pf->num_lan_msix,
1708c2ecf20Sopenharmony_ci				      ice_get_avail_txq_count(pf),
1718c2ecf20Sopenharmony_ci				      (u16)num_online_cpus());
1728c2ecf20Sopenharmony_ci		if (vsi->req_txq) {
1738c2ecf20Sopenharmony_ci			vsi->alloc_txq = vsi->req_txq;
1748c2ecf20Sopenharmony_ci			vsi->num_txq = vsi->req_txq;
1758c2ecf20Sopenharmony_ci		}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		pf->num_lan_tx = vsi->alloc_txq;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci		/* only 1 Rx queue unless RSS is enabled */
1808c2ecf20Sopenharmony_ci		if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
1818c2ecf20Sopenharmony_ci			vsi->alloc_rxq = 1;
1828c2ecf20Sopenharmony_ci		} else {
1838c2ecf20Sopenharmony_ci			vsi->alloc_rxq = min3(pf->num_lan_msix,
1848c2ecf20Sopenharmony_ci					      ice_get_avail_rxq_count(pf),
1858c2ecf20Sopenharmony_ci					      (u16)num_online_cpus());
1868c2ecf20Sopenharmony_ci			if (vsi->req_rxq) {
1878c2ecf20Sopenharmony_ci				vsi->alloc_rxq = vsi->req_rxq;
1888c2ecf20Sopenharmony_ci				vsi->num_rxq = vsi->req_rxq;
1898c2ecf20Sopenharmony_ci			}
1908c2ecf20Sopenharmony_ci		}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci		pf->num_lan_rx = vsi->alloc_rxq;
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci		vsi->num_q_vectors = min_t(int, pf->num_lan_msix,
1958c2ecf20Sopenharmony_ci					   max_t(int, vsi->alloc_rxq,
1968c2ecf20Sopenharmony_ci						 vsi->alloc_txq));
1978c2ecf20Sopenharmony_ci		break;
1988c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
1998c2ecf20Sopenharmony_ci		vf = &pf->vf[vsi->vf_id];
2008c2ecf20Sopenharmony_ci		if (vf->num_req_qs)
2018c2ecf20Sopenharmony_ci			vf->num_vf_qs = vf->num_req_qs;
2028c2ecf20Sopenharmony_ci		vsi->alloc_txq = vf->num_vf_qs;
2038c2ecf20Sopenharmony_ci		vsi->alloc_rxq = vf->num_vf_qs;
2048c2ecf20Sopenharmony_ci		/* pf->num_msix_per_vf includes (VF miscellaneous vector +
2058c2ecf20Sopenharmony_ci		 * data queue interrupts). Since vsi->num_q_vectors is number
2068c2ecf20Sopenharmony_ci		 * of queues vectors, subtract 1 (ICE_NONQ_VECS_VF) from the
2078c2ecf20Sopenharmony_ci		 * original vector count
2088c2ecf20Sopenharmony_ci		 */
2098c2ecf20Sopenharmony_ci		vsi->num_q_vectors = pf->num_msix_per_vf - ICE_NONQ_VECS_VF;
2108c2ecf20Sopenharmony_ci		break;
2118c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
2128c2ecf20Sopenharmony_ci		vsi->alloc_txq = 1;
2138c2ecf20Sopenharmony_ci		vsi->alloc_rxq = 1;
2148c2ecf20Sopenharmony_ci		vsi->num_q_vectors = 1;
2158c2ecf20Sopenharmony_ci		break;
2168c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
2178c2ecf20Sopenharmony_ci		vsi->alloc_txq = 1;
2188c2ecf20Sopenharmony_ci		vsi->alloc_rxq = 1;
2198c2ecf20Sopenharmony_ci		break;
2208c2ecf20Sopenharmony_ci	default:
2218c2ecf20Sopenharmony_ci		dev_warn(ice_pf_to_dev(pf), "Unknown VSI type %d\n", vsi->type);
2228c2ecf20Sopenharmony_ci		break;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	ice_vsi_set_num_desc(vsi);
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/**
2298c2ecf20Sopenharmony_ci * ice_get_free_slot - get the next non-NULL location index in array
2308c2ecf20Sopenharmony_ci * @array: array to search
2318c2ecf20Sopenharmony_ci * @size: size of the array
2328c2ecf20Sopenharmony_ci * @curr: last known occupied index to be used as a search hint
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * void * is being used to keep the functionality generic. This lets us use this
2358c2ecf20Sopenharmony_ci * function on any array of pointers.
2368c2ecf20Sopenharmony_ci */
2378c2ecf20Sopenharmony_cistatic int ice_get_free_slot(void *array, int size, int curr)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	int **tmp_array = (int **)array;
2408c2ecf20Sopenharmony_ci	int next;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (curr < (size - 1) && !tmp_array[curr + 1]) {
2438c2ecf20Sopenharmony_ci		next = curr + 1;
2448c2ecf20Sopenharmony_ci	} else {
2458c2ecf20Sopenharmony_ci		int i = 0;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		while ((i < size) && (tmp_array[i]))
2488c2ecf20Sopenharmony_ci			i++;
2498c2ecf20Sopenharmony_ci		if (i == size)
2508c2ecf20Sopenharmony_ci			next = ICE_NO_VSI;
2518c2ecf20Sopenharmony_ci		else
2528c2ecf20Sopenharmony_ci			next = i;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci	return next;
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci/**
2588c2ecf20Sopenharmony_ci * ice_vsi_delete - delete a VSI from the switch
2598c2ecf20Sopenharmony_ci * @vsi: pointer to VSI being removed
2608c2ecf20Sopenharmony_ci */
2618c2ecf20Sopenharmony_cistatic void ice_vsi_delete(struct ice_vsi *vsi)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
2648c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
2658c2ecf20Sopenharmony_ci	enum ice_status status;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
2688c2ecf20Sopenharmony_ci	if (!ctxt)
2698c2ecf20Sopenharmony_ci		return;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
2728c2ecf20Sopenharmony_ci		ctxt->vf_num = vsi->vf_id;
2738c2ecf20Sopenharmony_ci	ctxt->vsi_num = vsi->vsi_num;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	memcpy(&ctxt->info, &vsi->info, sizeof(ctxt->info));
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	status = ice_free_vsi(&pf->hw, vsi->idx, ctxt, false, NULL);
2788c2ecf20Sopenharmony_ci	if (status)
2798c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Failed to delete VSI %i in FW - error: %s\n",
2808c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	kfree(ctxt);
2838c2ecf20Sopenharmony_ci}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/**
2868c2ecf20Sopenharmony_ci * ice_vsi_free_arrays - De-allocate queue and vector pointer arrays for the VSI
2878c2ecf20Sopenharmony_ci * @vsi: pointer to VSI being cleared
2888c2ecf20Sopenharmony_ci */
2898c2ecf20Sopenharmony_cistatic void ice_vsi_free_arrays(struct ice_vsi *vsi)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
2928c2ecf20Sopenharmony_ci	struct device *dev;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/* free the ring and vector containers */
2978c2ecf20Sopenharmony_ci	if (vsi->q_vectors) {
2988c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->q_vectors);
2998c2ecf20Sopenharmony_ci		vsi->q_vectors = NULL;
3008c2ecf20Sopenharmony_ci	}
3018c2ecf20Sopenharmony_ci	if (vsi->tx_rings) {
3028c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->tx_rings);
3038c2ecf20Sopenharmony_ci		vsi->tx_rings = NULL;
3048c2ecf20Sopenharmony_ci	}
3058c2ecf20Sopenharmony_ci	if (vsi->rx_rings) {
3068c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->rx_rings);
3078c2ecf20Sopenharmony_ci		vsi->rx_rings = NULL;
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci	if (vsi->txq_map) {
3108c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->txq_map);
3118c2ecf20Sopenharmony_ci		vsi->txq_map = NULL;
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci	if (vsi->rxq_map) {
3148c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->rxq_map);
3158c2ecf20Sopenharmony_ci		vsi->rxq_map = NULL;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci/**
3208c2ecf20Sopenharmony_ci * ice_vsi_clear - clean up and deallocate the provided VSI
3218c2ecf20Sopenharmony_ci * @vsi: pointer to VSI being cleared
3228c2ecf20Sopenharmony_ci *
3238c2ecf20Sopenharmony_ci * This deallocates the VSI's queue resources, removes it from the PF's
3248c2ecf20Sopenharmony_ci * VSI array if necessary, and deallocates the VSI
3258c2ecf20Sopenharmony_ci *
3268c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
3278c2ecf20Sopenharmony_ci */
3288c2ecf20Sopenharmony_cistatic int ice_vsi_clear(struct ice_vsi *vsi)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	struct ice_pf *pf = NULL;
3318c2ecf20Sopenharmony_ci	struct device *dev;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	if (!vsi)
3348c2ecf20Sopenharmony_ci		return 0;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	if (!vsi->back)
3378c2ecf20Sopenharmony_ci		return -EINVAL;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	pf = vsi->back;
3408c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	if (!pf->vsi[vsi->idx] || pf->vsi[vsi->idx] != vsi) {
3438c2ecf20Sopenharmony_ci		dev_dbg(dev, "vsi does not exist at pf->vsi[%d]\n", vsi->idx);
3448c2ecf20Sopenharmony_ci		return -EINVAL;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	mutex_lock(&pf->sw_mutex);
3488c2ecf20Sopenharmony_ci	/* updates the PF for this cleared VSI */
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	pf->vsi[vsi->idx] = NULL;
3518c2ecf20Sopenharmony_ci	if (vsi->idx < pf->next_vsi && vsi->type != ICE_VSI_CTRL)
3528c2ecf20Sopenharmony_ci		pf->next_vsi = vsi->idx;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ice_vsi_free_arrays(vsi);
3558c2ecf20Sopenharmony_ci	mutex_unlock(&pf->sw_mutex);
3568c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	return 0;
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci/**
3628c2ecf20Sopenharmony_ci * ice_msix_clean_ctrl_vsi - MSIX mode interrupt handler for ctrl VSI
3638c2ecf20Sopenharmony_ci * @irq: interrupt number
3648c2ecf20Sopenharmony_ci * @data: pointer to a q_vector
3658c2ecf20Sopenharmony_ci */
3668c2ecf20Sopenharmony_cistatic irqreturn_t ice_msix_clean_ctrl_vsi(int __always_unused irq, void *data)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	if (!q_vector->tx.ring)
3718c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci#define FDIR_RX_DESC_CLEAN_BUDGET 64
3748c2ecf20Sopenharmony_ci	ice_clean_rx_irq(q_vector->rx.ring, FDIR_RX_DESC_CLEAN_BUDGET);
3758c2ecf20Sopenharmony_ci	ice_clean_ctrl_tx_irq(q_vector->tx.ring);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci/**
3818c2ecf20Sopenharmony_ci * ice_msix_clean_rings - MSIX mode Interrupt Handler
3828c2ecf20Sopenharmony_ci * @irq: interrupt number
3838c2ecf20Sopenharmony_ci * @data: pointer to a q_vector
3848c2ecf20Sopenharmony_ci */
3858c2ecf20Sopenharmony_cistatic irqreturn_t ice_msix_clean_rings(int __always_unused irq, void *data)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct ice_q_vector *q_vector = (struct ice_q_vector *)data;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	if (!q_vector->tx.ring && !q_vector->rx.ring)
3908c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	napi_schedule(&q_vector->napi);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci/**
3988c2ecf20Sopenharmony_ci * ice_vsi_alloc - Allocates the next available struct VSI in the PF
3998c2ecf20Sopenharmony_ci * @pf: board private structure
4008c2ecf20Sopenharmony_ci * @vsi_type: type of VSI
4018c2ecf20Sopenharmony_ci * @vf_id: ID of the VF being configured
4028c2ecf20Sopenharmony_ci *
4038c2ecf20Sopenharmony_ci * returns a pointer to a VSI on success, NULL on failure.
4048c2ecf20Sopenharmony_ci */
4058c2ecf20Sopenharmony_cistatic struct ice_vsi *
4068c2ecf20Sopenharmony_ciice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type, u16 vf_id)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
4098c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = NULL;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	/* Need to protect the allocation of the VSIs at the PF level */
4128c2ecf20Sopenharmony_ci	mutex_lock(&pf->sw_mutex);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* If we have already allocated our maximum number of VSIs,
4158c2ecf20Sopenharmony_ci	 * pf->next_vsi will be ICE_NO_VSI. If not, pf->next_vsi index
4168c2ecf20Sopenharmony_ci	 * is available to be populated
4178c2ecf20Sopenharmony_ci	 */
4188c2ecf20Sopenharmony_ci	if (pf->next_vsi == ICE_NO_VSI) {
4198c2ecf20Sopenharmony_ci		dev_dbg(dev, "out of VSI slots!\n");
4208c2ecf20Sopenharmony_ci		goto unlock_pf;
4218c2ecf20Sopenharmony_ci	}
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci	vsi = devm_kzalloc(dev, sizeof(*vsi), GFP_KERNEL);
4248c2ecf20Sopenharmony_ci	if (!vsi)
4258c2ecf20Sopenharmony_ci		goto unlock_pf;
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	vsi->type = vsi_type;
4288c2ecf20Sopenharmony_ci	vsi->back = pf;
4298c2ecf20Sopenharmony_ci	set_bit(__ICE_DOWN, vsi->state);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	if (vsi_type == ICE_VSI_VF)
4328c2ecf20Sopenharmony_ci		ice_vsi_set_num_qs(vsi, vf_id);
4338c2ecf20Sopenharmony_ci	else
4348c2ecf20Sopenharmony_ci		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	switch (vsi->type) {
4378c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
4388c2ecf20Sopenharmony_ci		if (ice_vsi_alloc_arrays(vsi))
4398c2ecf20Sopenharmony_ci			goto err_rings;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci		/* Setup default MSIX irq handler for VSI */
4428c2ecf20Sopenharmony_ci		vsi->irq_handler = ice_msix_clean_rings;
4438c2ecf20Sopenharmony_ci		break;
4448c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
4458c2ecf20Sopenharmony_ci		if (ice_vsi_alloc_arrays(vsi))
4468c2ecf20Sopenharmony_ci			goto err_rings;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci		/* Setup ctrl VSI MSIX irq handler */
4498c2ecf20Sopenharmony_ci		vsi->irq_handler = ice_msix_clean_ctrl_vsi;
4508c2ecf20Sopenharmony_ci		break;
4518c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
4528c2ecf20Sopenharmony_ci		if (ice_vsi_alloc_arrays(vsi))
4538c2ecf20Sopenharmony_ci			goto err_rings;
4548c2ecf20Sopenharmony_ci		break;
4558c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
4568c2ecf20Sopenharmony_ci		if (ice_vsi_alloc_arrays(vsi))
4578c2ecf20Sopenharmony_ci			goto err_rings;
4588c2ecf20Sopenharmony_ci		break;
4598c2ecf20Sopenharmony_ci	default:
4608c2ecf20Sopenharmony_ci		dev_warn(dev, "Unknown VSI type %d\n", vsi->type);
4618c2ecf20Sopenharmony_ci		goto unlock_pf;
4628c2ecf20Sopenharmony_ci	}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_CTRL) {
4658c2ecf20Sopenharmony_ci		/* Use the last VSI slot as the index for the control VSI */
4668c2ecf20Sopenharmony_ci		vsi->idx = pf->num_alloc_vsi - 1;
4678c2ecf20Sopenharmony_ci		pf->ctrl_vsi_idx = vsi->idx;
4688c2ecf20Sopenharmony_ci		pf->vsi[vsi->idx] = vsi;
4698c2ecf20Sopenharmony_ci	} else {
4708c2ecf20Sopenharmony_ci		/* fill slot and make note of the index */
4718c2ecf20Sopenharmony_ci		vsi->idx = pf->next_vsi;
4728c2ecf20Sopenharmony_ci		pf->vsi[pf->next_vsi] = vsi;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci		/* prepare pf->next_vsi for next use */
4758c2ecf20Sopenharmony_ci		pf->next_vsi = ice_get_free_slot(pf->vsi, pf->num_alloc_vsi,
4768c2ecf20Sopenharmony_ci						 pf->next_vsi);
4778c2ecf20Sopenharmony_ci	}
4788c2ecf20Sopenharmony_ci	goto unlock_pf;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cierr_rings:
4818c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi);
4828c2ecf20Sopenharmony_ci	vsi = NULL;
4838c2ecf20Sopenharmony_ciunlock_pf:
4848c2ecf20Sopenharmony_ci	mutex_unlock(&pf->sw_mutex);
4858c2ecf20Sopenharmony_ci	return vsi;
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci/**
4898c2ecf20Sopenharmony_ci * ice_alloc_fd_res - Allocate FD resource for a VSI
4908c2ecf20Sopenharmony_ci * @vsi: pointer to the ice_vsi
4918c2ecf20Sopenharmony_ci *
4928c2ecf20Sopenharmony_ci * This allocates the FD resources
4938c2ecf20Sopenharmony_ci *
4948c2ecf20Sopenharmony_ci * Returns 0 on success, -EPERM on no-op or -EIO on failure
4958c2ecf20Sopenharmony_ci */
4968c2ecf20Sopenharmony_cistatic int ice_alloc_fd_res(struct ice_vsi *vsi)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
4998c2ecf20Sopenharmony_ci	u32 g_val, b_val;
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	/* Flow Director filters are only allocated/assigned to the PF VSI which
5028c2ecf20Sopenharmony_ci	 * passes the traffic. The CTRL VSI is only used to add/delete filters
5038c2ecf20Sopenharmony_ci	 * so we don't allocate resources to it
5048c2ecf20Sopenharmony_ci	 */
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	/* FD filters from guaranteed pool per VSI */
5078c2ecf20Sopenharmony_ci	g_val = pf->hw.func_caps.fd_fltr_guar;
5088c2ecf20Sopenharmony_ci	if (!g_val)
5098c2ecf20Sopenharmony_ci		return -EPERM;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	/* FD filters from best effort pool */
5128c2ecf20Sopenharmony_ci	b_val = pf->hw.func_caps.fd_fltr_best_effort;
5138c2ecf20Sopenharmony_ci	if (!b_val)
5148c2ecf20Sopenharmony_ci		return -EPERM;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_PF)
5178c2ecf20Sopenharmony_ci		return -EPERM;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (!test_bit(ICE_FLAG_FD_ENA, pf->flags))
5208c2ecf20Sopenharmony_ci		return -EPERM;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	vsi->num_gfltr = g_val / pf->num_alloc_vsi;
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	/* each VSI gets same "best_effort" quota */
5258c2ecf20Sopenharmony_ci	vsi->num_bfltr = b_val;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	return 0;
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci/**
5318c2ecf20Sopenharmony_ci * ice_vsi_get_qs - Assign queues from PF to VSI
5328c2ecf20Sopenharmony_ci * @vsi: the VSI to assign queues to
5338c2ecf20Sopenharmony_ci *
5348c2ecf20Sopenharmony_ci * Returns 0 on success and a negative value on error
5358c2ecf20Sopenharmony_ci */
5368c2ecf20Sopenharmony_cistatic int ice_vsi_get_qs(struct ice_vsi *vsi)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
5398c2ecf20Sopenharmony_ci	struct ice_qs_cfg tx_qs_cfg = {
5408c2ecf20Sopenharmony_ci		.qs_mutex = &pf->avail_q_mutex,
5418c2ecf20Sopenharmony_ci		.pf_map = pf->avail_txqs,
5428c2ecf20Sopenharmony_ci		.pf_map_size = pf->max_pf_txqs,
5438c2ecf20Sopenharmony_ci		.q_count = vsi->alloc_txq,
5448c2ecf20Sopenharmony_ci		.scatter_count = ICE_MAX_SCATTER_TXQS,
5458c2ecf20Sopenharmony_ci		.vsi_map = vsi->txq_map,
5468c2ecf20Sopenharmony_ci		.vsi_map_offset = 0,
5478c2ecf20Sopenharmony_ci		.mapping_mode = ICE_VSI_MAP_CONTIG
5488c2ecf20Sopenharmony_ci	};
5498c2ecf20Sopenharmony_ci	struct ice_qs_cfg rx_qs_cfg = {
5508c2ecf20Sopenharmony_ci		.qs_mutex = &pf->avail_q_mutex,
5518c2ecf20Sopenharmony_ci		.pf_map = pf->avail_rxqs,
5528c2ecf20Sopenharmony_ci		.pf_map_size = pf->max_pf_rxqs,
5538c2ecf20Sopenharmony_ci		.q_count = vsi->alloc_rxq,
5548c2ecf20Sopenharmony_ci		.scatter_count = ICE_MAX_SCATTER_RXQS,
5558c2ecf20Sopenharmony_ci		.vsi_map = vsi->rxq_map,
5568c2ecf20Sopenharmony_ci		.vsi_map_offset = 0,
5578c2ecf20Sopenharmony_ci		.mapping_mode = ICE_VSI_MAP_CONTIG
5588c2ecf20Sopenharmony_ci	};
5598c2ecf20Sopenharmony_ci	int ret;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	ret = __ice_vsi_get_qs(&tx_qs_cfg);
5628c2ecf20Sopenharmony_ci	if (ret)
5638c2ecf20Sopenharmony_ci		return ret;
5648c2ecf20Sopenharmony_ci	vsi->tx_mapping_mode = tx_qs_cfg.mapping_mode;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	ret = __ice_vsi_get_qs(&rx_qs_cfg);
5678c2ecf20Sopenharmony_ci	if (ret)
5688c2ecf20Sopenharmony_ci		return ret;
5698c2ecf20Sopenharmony_ci	vsi->rx_mapping_mode = rx_qs_cfg.mapping_mode;
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	return 0;
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci/**
5758c2ecf20Sopenharmony_ci * ice_vsi_put_qs - Release queues from VSI to PF
5768c2ecf20Sopenharmony_ci * @vsi: the VSI that is going to release queues
5778c2ecf20Sopenharmony_ci */
5788c2ecf20Sopenharmony_cistatic void ice_vsi_put_qs(struct ice_vsi *vsi)
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
5818c2ecf20Sopenharmony_ci	int i;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	mutex_lock(&pf->avail_q_mutex);
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->alloc_txq; i++) {
5868c2ecf20Sopenharmony_ci		clear_bit(vsi->txq_map[i], pf->avail_txqs);
5878c2ecf20Sopenharmony_ci		vsi->txq_map[i] = ICE_INVAL_Q_INDEX;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->alloc_rxq; i++) {
5918c2ecf20Sopenharmony_ci		clear_bit(vsi->rxq_map[i], pf->avail_rxqs);
5928c2ecf20Sopenharmony_ci		vsi->rxq_map[i] = ICE_INVAL_Q_INDEX;
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	mutex_unlock(&pf->avail_q_mutex);
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci/**
5998c2ecf20Sopenharmony_ci * ice_is_safe_mode
6008c2ecf20Sopenharmony_ci * @pf: pointer to the PF struct
6018c2ecf20Sopenharmony_ci *
6028c2ecf20Sopenharmony_ci * returns true if driver is in safe mode, false otherwise
6038c2ecf20Sopenharmony_ci */
6048c2ecf20Sopenharmony_cibool ice_is_safe_mode(struct ice_pf *pf)
6058c2ecf20Sopenharmony_ci{
6068c2ecf20Sopenharmony_ci	return !test_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci/**
6108c2ecf20Sopenharmony_ci * ice_vsi_clean_rss_flow_fld - Delete RSS configuration
6118c2ecf20Sopenharmony_ci * @vsi: the VSI being cleaned up
6128c2ecf20Sopenharmony_ci *
6138c2ecf20Sopenharmony_ci * This function deletes RSS input set for all flows that were configured
6148c2ecf20Sopenharmony_ci * for this VSI
6158c2ecf20Sopenharmony_ci */
6168c2ecf20Sopenharmony_cistatic void ice_vsi_clean_rss_flow_fld(struct ice_vsi *vsi)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
6198c2ecf20Sopenharmony_ci	enum ice_status status;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf))
6228c2ecf20Sopenharmony_ci		return;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
6258c2ecf20Sopenharmony_ci	if (status)
6268c2ecf20Sopenharmony_ci		dev_dbg(ice_pf_to_dev(pf), "ice_rem_vsi_rss_cfg failed for vsi = %d, error = %s\n",
6278c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
6288c2ecf20Sopenharmony_ci}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci/**
6318c2ecf20Sopenharmony_ci * ice_rss_clean - Delete RSS related VSI structures and configuration
6328c2ecf20Sopenharmony_ci * @vsi: the VSI being removed
6338c2ecf20Sopenharmony_ci */
6348c2ecf20Sopenharmony_cistatic void ice_rss_clean(struct ice_vsi *vsi)
6358c2ecf20Sopenharmony_ci{
6368c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
6378c2ecf20Sopenharmony_ci	struct device *dev;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	if (vsi->rss_hkey_user)
6428c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->rss_hkey_user);
6438c2ecf20Sopenharmony_ci	if (vsi->rss_lut_user)
6448c2ecf20Sopenharmony_ci		devm_kfree(dev, vsi->rss_lut_user);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	ice_vsi_clean_rss_flow_fld(vsi);
6478c2ecf20Sopenharmony_ci	/* remove RSS replay list */
6488c2ecf20Sopenharmony_ci	if (!ice_is_safe_mode(pf))
6498c2ecf20Sopenharmony_ci		ice_rem_vsi_rss_list(&pf->hw, vsi->idx);
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci/**
6538c2ecf20Sopenharmony_ci * ice_vsi_set_rss_params - Setup RSS capabilities per VSI type
6548c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
6558c2ecf20Sopenharmony_ci */
6568c2ecf20Sopenharmony_cistatic void ice_vsi_set_rss_params(struct ice_vsi *vsi)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	struct ice_hw_common_caps *cap;
6598c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
6628c2ecf20Sopenharmony_ci		vsi->rss_size = 1;
6638c2ecf20Sopenharmony_ci		return;
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	cap = &pf->hw.func_caps.common_cap;
6678c2ecf20Sopenharmony_ci	switch (vsi->type) {
6688c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
6698c2ecf20Sopenharmony_ci		/* PF VSI will inherit RSS instance of PF */
6708c2ecf20Sopenharmony_ci		vsi->rss_table_size = (u16)cap->rss_table_size;
6718c2ecf20Sopenharmony_ci		vsi->rss_size = min_t(u16, num_online_cpus(),
6728c2ecf20Sopenharmony_ci				      BIT(cap->rss_table_entry_width));
6738c2ecf20Sopenharmony_ci		vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF;
6748c2ecf20Sopenharmony_ci		break;
6758c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
6768c2ecf20Sopenharmony_ci		/* VF VSI will get a small RSS table.
6778c2ecf20Sopenharmony_ci		 * For VSI_LUT, LUT size should be set to 64 bytes.
6788c2ecf20Sopenharmony_ci		 */
6798c2ecf20Sopenharmony_ci		vsi->rss_table_size = ICE_VSIQF_HLUT_ARRAY_SIZE;
6808c2ecf20Sopenharmony_ci		vsi->rss_size = ICE_MAX_RSS_QS_PER_VF;
6818c2ecf20Sopenharmony_ci		vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_VSI;
6828c2ecf20Sopenharmony_ci		break;
6838c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
6848c2ecf20Sopenharmony_ci		break;
6858c2ecf20Sopenharmony_ci	default:
6868c2ecf20Sopenharmony_ci		dev_dbg(ice_pf_to_dev(pf), "Unsupported VSI type %s\n",
6878c2ecf20Sopenharmony_ci			ice_vsi_type_str(vsi->type));
6888c2ecf20Sopenharmony_ci		break;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci}
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci/**
6938c2ecf20Sopenharmony_ci * ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
6948c2ecf20Sopenharmony_ci * @ctxt: the VSI context being set
6958c2ecf20Sopenharmony_ci *
6968c2ecf20Sopenharmony_ci * This initializes a default VSI context for all sections except the Queues.
6978c2ecf20Sopenharmony_ci */
6988c2ecf20Sopenharmony_cistatic void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	u32 table = 0;
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	memset(&ctxt->info, 0, sizeof(ctxt->info));
7038c2ecf20Sopenharmony_ci	/* VSI's should be allocated from shared pool */
7048c2ecf20Sopenharmony_ci	ctxt->alloc_from_pool = true;
7058c2ecf20Sopenharmony_ci	/* Src pruning enabled by default */
7068c2ecf20Sopenharmony_ci	ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
7078c2ecf20Sopenharmony_ci	/* Traffic from VSI can be sent to LAN */
7088c2ecf20Sopenharmony_ci	ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
7098c2ecf20Sopenharmony_ci	/* By default bits 3 and 4 in vlan_flags are 0's which results in legacy
7108c2ecf20Sopenharmony_ci	 * behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all
7118c2ecf20Sopenharmony_ci	 * packets untagged/tagged.
7128c2ecf20Sopenharmony_ci	 */
7138c2ecf20Sopenharmony_ci	ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL &
7148c2ecf20Sopenharmony_ci				  ICE_AQ_VSI_VLAN_MODE_M) >>
7158c2ecf20Sopenharmony_ci				 ICE_AQ_VSI_VLAN_MODE_S);
7168c2ecf20Sopenharmony_ci	/* Have 1:1 UP mapping for both ingress/egress tables */
7178c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(0, 0);
7188c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(1, 1);
7198c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(2, 2);
7208c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(3, 3);
7218c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(4, 4);
7228c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(5, 5);
7238c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(6, 6);
7248c2ecf20Sopenharmony_ci	table |= ICE_UP_TABLE_TRANSLATE(7, 7);
7258c2ecf20Sopenharmony_ci	ctxt->info.ingress_table = cpu_to_le32(table);
7268c2ecf20Sopenharmony_ci	ctxt->info.egress_table = cpu_to_le32(table);
7278c2ecf20Sopenharmony_ci	/* Have 1:1 UP mapping for outer to inner UP table */
7288c2ecf20Sopenharmony_ci	ctxt->info.outer_up_table = cpu_to_le32(table);
7298c2ecf20Sopenharmony_ci	/* No Outer tag support outer_tag_flags remains to zero */
7308c2ecf20Sopenharmony_ci}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci/**
7338c2ecf20Sopenharmony_ci * ice_vsi_setup_q_map - Setup a VSI queue map
7348c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
7358c2ecf20Sopenharmony_ci * @ctxt: VSI context structure
7368c2ecf20Sopenharmony_ci */
7378c2ecf20Sopenharmony_cistatic void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
7388c2ecf20Sopenharmony_ci{
7398c2ecf20Sopenharmony_ci	u16 offset = 0, qmap = 0, tx_count = 0;
7408c2ecf20Sopenharmony_ci	u16 qcount_tx = vsi->alloc_txq;
7418c2ecf20Sopenharmony_ci	u16 qcount_rx = vsi->alloc_rxq;
7428c2ecf20Sopenharmony_ci	u16 tx_numq_tc, rx_numq_tc;
7438c2ecf20Sopenharmony_ci	u16 pow = 0, max_rss = 0;
7448c2ecf20Sopenharmony_ci	bool ena_tc0 = false;
7458c2ecf20Sopenharmony_ci	u8 netdev_tc = 0;
7468c2ecf20Sopenharmony_ci	int i;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	/* at least TC0 should be enabled by default */
7498c2ecf20Sopenharmony_ci	if (vsi->tc_cfg.numtc) {
7508c2ecf20Sopenharmony_ci		if (!(vsi->tc_cfg.ena_tc & BIT(0)))
7518c2ecf20Sopenharmony_ci			ena_tc0 = true;
7528c2ecf20Sopenharmony_ci	} else {
7538c2ecf20Sopenharmony_ci		ena_tc0 = true;
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	if (ena_tc0) {
7578c2ecf20Sopenharmony_ci		vsi->tc_cfg.numtc++;
7588c2ecf20Sopenharmony_ci		vsi->tc_cfg.ena_tc |= 1;
7598c2ecf20Sopenharmony_ci	}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	rx_numq_tc = qcount_rx / vsi->tc_cfg.numtc;
7628c2ecf20Sopenharmony_ci	if (!rx_numq_tc)
7638c2ecf20Sopenharmony_ci		rx_numq_tc = 1;
7648c2ecf20Sopenharmony_ci	tx_numq_tc = qcount_tx / vsi->tc_cfg.numtc;
7658c2ecf20Sopenharmony_ci	if (!tx_numq_tc)
7668c2ecf20Sopenharmony_ci		tx_numq_tc = 1;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	/* TC mapping is a function of the number of Rx queues assigned to the
7698c2ecf20Sopenharmony_ci	 * VSI for each traffic class and the offset of these queues.
7708c2ecf20Sopenharmony_ci	 * The first 10 bits are for queue offset for TC0, next 4 bits for no:of
7718c2ecf20Sopenharmony_ci	 * queues allocated to TC0. No:of queues is a power-of-2.
7728c2ecf20Sopenharmony_ci	 *
7738c2ecf20Sopenharmony_ci	 * If TC is not enabled, the queue offset is set to 0, and allocate one
7748c2ecf20Sopenharmony_ci	 * queue, this way, traffic for the given TC will be sent to the default
7758c2ecf20Sopenharmony_ci	 * queue.
7768c2ecf20Sopenharmony_ci	 *
7778c2ecf20Sopenharmony_ci	 * Setup number and offset of Rx queues for all TCs for the VSI
7788c2ecf20Sopenharmony_ci	 */
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	qcount_rx = rx_numq_tc;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	/* qcount will change if RSS is enabled */
7838c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) {
7848c2ecf20Sopenharmony_ci		if (vsi->type == ICE_VSI_PF || vsi->type == ICE_VSI_VF) {
7858c2ecf20Sopenharmony_ci			if (vsi->type == ICE_VSI_PF)
7868c2ecf20Sopenharmony_ci				max_rss = ICE_MAX_LG_RSS_QS;
7878c2ecf20Sopenharmony_ci			else
7888c2ecf20Sopenharmony_ci				max_rss = ICE_MAX_RSS_QS_PER_VF;
7898c2ecf20Sopenharmony_ci			qcount_rx = min_t(u16, rx_numq_tc, max_rss);
7908c2ecf20Sopenharmony_ci			if (!vsi->req_rxq)
7918c2ecf20Sopenharmony_ci				qcount_rx = min_t(u16, qcount_rx,
7928c2ecf20Sopenharmony_ci						  vsi->rss_size);
7938c2ecf20Sopenharmony_ci		}
7948c2ecf20Sopenharmony_ci	}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	/* find the (rounded up) power-of-2 of qcount */
7978c2ecf20Sopenharmony_ci	pow = (u16)order_base_2(qcount_rx);
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	ice_for_each_traffic_class(i) {
8008c2ecf20Sopenharmony_ci		if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
8018c2ecf20Sopenharmony_ci			/* TC is not enabled */
8028c2ecf20Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qoffset = 0;
8038c2ecf20Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qcount_rx = 1;
8048c2ecf20Sopenharmony_ci			vsi->tc_cfg.tc_info[i].qcount_tx = 1;
8058c2ecf20Sopenharmony_ci			vsi->tc_cfg.tc_info[i].netdev_tc = 0;
8068c2ecf20Sopenharmony_ci			ctxt->info.tc_mapping[i] = 0;
8078c2ecf20Sopenharmony_ci			continue;
8088c2ecf20Sopenharmony_ci		}
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci		/* TC is enabled */
8118c2ecf20Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qoffset = offset;
8128c2ecf20Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qcount_rx = qcount_rx;
8138c2ecf20Sopenharmony_ci		vsi->tc_cfg.tc_info[i].qcount_tx = tx_numq_tc;
8148c2ecf20Sopenharmony_ci		vsi->tc_cfg.tc_info[i].netdev_tc = netdev_tc++;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci		qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
8178c2ecf20Sopenharmony_ci			ICE_AQ_VSI_TC_Q_OFFSET_M) |
8188c2ecf20Sopenharmony_ci			((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
8198c2ecf20Sopenharmony_ci			 ICE_AQ_VSI_TC_Q_NUM_M);
8208c2ecf20Sopenharmony_ci		offset += qcount_rx;
8218c2ecf20Sopenharmony_ci		tx_count += tx_numq_tc;
8228c2ecf20Sopenharmony_ci		ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
8238c2ecf20Sopenharmony_ci	}
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	/* if offset is non-zero, means it is calculated correctly based on
8268c2ecf20Sopenharmony_ci	 * enabled TCs for a given VSI otherwise qcount_rx will always
8278c2ecf20Sopenharmony_ci	 * be correct and non-zero because it is based off - VSI's
8288c2ecf20Sopenharmony_ci	 * allocated Rx queues which is at least 1 (hence qcount_tx will be
8298c2ecf20Sopenharmony_ci	 * at least 1)
8308c2ecf20Sopenharmony_ci	 */
8318c2ecf20Sopenharmony_ci	if (offset)
8328c2ecf20Sopenharmony_ci		vsi->num_rxq = offset;
8338c2ecf20Sopenharmony_ci	else
8348c2ecf20Sopenharmony_ci		vsi->num_rxq = qcount_rx;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	vsi->num_txq = tx_count;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF && vsi->num_txq != vsi->num_rxq) {
8398c2ecf20Sopenharmony_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");
8408c2ecf20Sopenharmony_ci		/* since there is a chance that num_rxq could have been changed
8418c2ecf20Sopenharmony_ci		 * in the above for loop, make num_txq equal to num_rxq.
8428c2ecf20Sopenharmony_ci		 */
8438c2ecf20Sopenharmony_ci		vsi->num_txq = vsi->num_rxq;
8448c2ecf20Sopenharmony_ci	}
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	/* Rx queue mapping */
8478c2ecf20Sopenharmony_ci	ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
8488c2ecf20Sopenharmony_ci	/* q_mapping buffer holds the info for the first queue allocated for
8498c2ecf20Sopenharmony_ci	 * this VSI in the PF space and also the number of queues associated
8508c2ecf20Sopenharmony_ci	 * with this VSI.
8518c2ecf20Sopenharmony_ci	 */
8528c2ecf20Sopenharmony_ci	ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
8538c2ecf20Sopenharmony_ci	ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
8548c2ecf20Sopenharmony_ci}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci/**
8578c2ecf20Sopenharmony_ci * ice_set_fd_vsi_ctx - Set FD VSI context before adding a VSI
8588c2ecf20Sopenharmony_ci * @ctxt: the VSI context being set
8598c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
8608c2ecf20Sopenharmony_ci */
8618c2ecf20Sopenharmony_cistatic void ice_set_fd_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	u8 dflt_q_group, dflt_q_prio;
8648c2ecf20Sopenharmony_ci	u16 dflt_q, report_q, val;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_PF && vsi->type != ICE_VSI_CTRL)
8678c2ecf20Sopenharmony_ci		return;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	val = ICE_AQ_VSI_PROP_FLOW_DIR_VALID;
8708c2ecf20Sopenharmony_ci	ctxt->info.valid_sections |= cpu_to_le16(val);
8718c2ecf20Sopenharmony_ci	dflt_q = 0;
8728c2ecf20Sopenharmony_ci	dflt_q_group = 0;
8738c2ecf20Sopenharmony_ci	report_q = 0;
8748c2ecf20Sopenharmony_ci	dflt_q_prio = 0;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	/* enable flow director filtering/programming */
8778c2ecf20Sopenharmony_ci	val = ICE_AQ_VSI_FD_ENABLE | ICE_AQ_VSI_FD_PROG_ENABLE;
8788c2ecf20Sopenharmony_ci	ctxt->info.fd_options = cpu_to_le16(val);
8798c2ecf20Sopenharmony_ci	/* max of allocated flow director filters */
8808c2ecf20Sopenharmony_ci	ctxt->info.max_fd_fltr_dedicated =
8818c2ecf20Sopenharmony_ci			cpu_to_le16(vsi->num_gfltr);
8828c2ecf20Sopenharmony_ci	/* max of shared flow director filters any VSI may program */
8838c2ecf20Sopenharmony_ci	ctxt->info.max_fd_fltr_shared =
8848c2ecf20Sopenharmony_ci			cpu_to_le16(vsi->num_bfltr);
8858c2ecf20Sopenharmony_ci	/* default queue index within the VSI of the default FD */
8868c2ecf20Sopenharmony_ci	val = ((dflt_q << ICE_AQ_VSI_FD_DEF_Q_S) &
8878c2ecf20Sopenharmony_ci	       ICE_AQ_VSI_FD_DEF_Q_M);
8888c2ecf20Sopenharmony_ci	/* target queue or queue group to the FD filter */
8898c2ecf20Sopenharmony_ci	val |= ((dflt_q_group << ICE_AQ_VSI_FD_DEF_GRP_S) &
8908c2ecf20Sopenharmony_ci		ICE_AQ_VSI_FD_DEF_GRP_M);
8918c2ecf20Sopenharmony_ci	ctxt->info.fd_def_q = cpu_to_le16(val);
8928c2ecf20Sopenharmony_ci	/* queue index on which FD filter completion is reported */
8938c2ecf20Sopenharmony_ci	val = ((report_q << ICE_AQ_VSI_FD_REPORT_Q_S) &
8948c2ecf20Sopenharmony_ci	       ICE_AQ_VSI_FD_REPORT_Q_M);
8958c2ecf20Sopenharmony_ci	/* priority of the default qindex action */
8968c2ecf20Sopenharmony_ci	val |= ((dflt_q_prio << ICE_AQ_VSI_FD_DEF_PRIORITY_S) &
8978c2ecf20Sopenharmony_ci		ICE_AQ_VSI_FD_DEF_PRIORITY_M);
8988c2ecf20Sopenharmony_ci	ctxt->info.fd_report_opt = cpu_to_le16(val);
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci/**
9028c2ecf20Sopenharmony_ci * ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI
9038c2ecf20Sopenharmony_ci * @ctxt: the VSI context being set
9048c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
9058c2ecf20Sopenharmony_ci */
9068c2ecf20Sopenharmony_cistatic void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	u8 lut_type, hash_type;
9098c2ecf20Sopenharmony_ci	struct device *dev;
9108c2ecf20Sopenharmony_ci	struct ice_pf *pf;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci	pf = vsi->back;
9138c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	switch (vsi->type) {
9168c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
9178c2ecf20Sopenharmony_ci		/* PF VSI will inherit RSS instance of PF */
9188c2ecf20Sopenharmony_ci		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
9198c2ecf20Sopenharmony_ci		hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
9208c2ecf20Sopenharmony_ci		break;
9218c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
9228c2ecf20Sopenharmony_ci		/* VF VSI will gets a small RSS table which is a VSI LUT type */
9238c2ecf20Sopenharmony_ci		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
9248c2ecf20Sopenharmony_ci		hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
9258c2ecf20Sopenharmony_ci		break;
9268c2ecf20Sopenharmony_ci	default:
9278c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unsupported VSI type %s\n",
9288c2ecf20Sopenharmony_ci			ice_vsi_type_str(vsi->type));
9298c2ecf20Sopenharmony_ci		return;
9308c2ecf20Sopenharmony_ci	}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
9338c2ecf20Sopenharmony_ci				ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
9348c2ecf20Sopenharmony_ci				(hash_type & ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
9358c2ecf20Sopenharmony_ci}
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci/**
9388c2ecf20Sopenharmony_ci * ice_vsi_init - Create and initialize a VSI
9398c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
9408c2ecf20Sopenharmony_ci * @init_vsi: is this call creating a VSI
9418c2ecf20Sopenharmony_ci *
9428c2ecf20Sopenharmony_ci * This initializes a VSI context depending on the VSI type to be added and
9438c2ecf20Sopenharmony_ci * passes it down to the add_vsi aq command to create a new VSI.
9448c2ecf20Sopenharmony_ci */
9458c2ecf20Sopenharmony_cistatic int ice_vsi_init(struct ice_vsi *vsi, bool init_vsi)
9468c2ecf20Sopenharmony_ci{
9478c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
9488c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
9498c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
9508c2ecf20Sopenharmony_ci	struct device *dev;
9518c2ecf20Sopenharmony_ci	int ret = 0;
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
9548c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
9558c2ecf20Sopenharmony_ci	if (!ctxt)
9568c2ecf20Sopenharmony_ci		return -ENOMEM;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	switch (vsi->type) {
9598c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
9608c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
9618c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
9628c2ecf20Sopenharmony_ci		ctxt->flags = ICE_AQ_VSI_TYPE_PF;
9638c2ecf20Sopenharmony_ci		break;
9648c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
9658c2ecf20Sopenharmony_ci		ctxt->flags = ICE_AQ_VSI_TYPE_VF;
9668c2ecf20Sopenharmony_ci		/* VF number here is the absolute VF number (0-255) */
9678c2ecf20Sopenharmony_ci		ctxt->vf_num = vsi->vf_id + hw->func_caps.vf_base_id;
9688c2ecf20Sopenharmony_ci		break;
9698c2ecf20Sopenharmony_ci	default:
9708c2ecf20Sopenharmony_ci		ret = -ENODEV;
9718c2ecf20Sopenharmony_ci		goto out;
9728c2ecf20Sopenharmony_ci	}
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	ice_set_dflt_vsi_ctx(ctxt);
9758c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_FD_ENA, pf->flags))
9768c2ecf20Sopenharmony_ci		ice_set_fd_vsi_ctx(ctxt, vsi);
9778c2ecf20Sopenharmony_ci	/* if the switch is in VEB mode, allow VSI loopback */
9788c2ecf20Sopenharmony_ci	if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
9798c2ecf20Sopenharmony_ci		ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	/* Set LUT type and HASH type if RSS is enabled */
9828c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags) &&
9838c2ecf20Sopenharmony_ci	    vsi->type != ICE_VSI_CTRL) {
9848c2ecf20Sopenharmony_ci		ice_set_rss_vsi_ctx(ctxt, vsi);
9858c2ecf20Sopenharmony_ci		/* if updating VSI context, make sure to set valid_section:
9868c2ecf20Sopenharmony_ci		 * to indicate which section of VSI context being updated
9878c2ecf20Sopenharmony_ci		 */
9888c2ecf20Sopenharmony_ci		if (!init_vsi)
9898c2ecf20Sopenharmony_ci			ctxt->info.valid_sections |=
9908c2ecf20Sopenharmony_ci				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
9918c2ecf20Sopenharmony_ci	}
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	ctxt->info.sw_id = vsi->port_info->sw_id;
9948c2ecf20Sopenharmony_ci	ice_vsi_setup_q_map(vsi, ctxt);
9958c2ecf20Sopenharmony_ci	if (!init_vsi) /* means VSI being updated */
9968c2ecf20Sopenharmony_ci		/* must to indicate which section of VSI context are
9978c2ecf20Sopenharmony_ci		 * being modified
9988c2ecf20Sopenharmony_ci		 */
9998c2ecf20Sopenharmony_ci		ctxt->info.valid_sections |=
10008c2ecf20Sopenharmony_ci			cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	/* enable/disable MAC and VLAN anti-spoof when spoofchk is on/off
10038c2ecf20Sopenharmony_ci	 * respectively
10048c2ecf20Sopenharmony_ci	 */
10058c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF) {
10068c2ecf20Sopenharmony_ci		ctxt->info.valid_sections |=
10078c2ecf20Sopenharmony_ci			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
10088c2ecf20Sopenharmony_ci		if (pf->vf[vsi->vf_id].spoofchk) {
10098c2ecf20Sopenharmony_ci			ctxt->info.sec_flags |=
10108c2ecf20Sopenharmony_ci				ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
10118c2ecf20Sopenharmony_ci				(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
10128c2ecf20Sopenharmony_ci				 ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
10138c2ecf20Sopenharmony_ci		} else {
10148c2ecf20Sopenharmony_ci			ctxt->info.sec_flags &=
10158c2ecf20Sopenharmony_ci				~(ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF |
10168c2ecf20Sopenharmony_ci				  (ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
10178c2ecf20Sopenharmony_ci				   ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S));
10188c2ecf20Sopenharmony_ci		}
10198c2ecf20Sopenharmony_ci	}
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	/* Allow control frames out of main VSI */
10228c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF) {
10238c2ecf20Sopenharmony_ci		ctxt->info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ALLOW_DEST_OVRD;
10248c2ecf20Sopenharmony_ci		ctxt->info.valid_sections |=
10258c2ecf20Sopenharmony_ci			cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID);
10268c2ecf20Sopenharmony_ci	}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	if (init_vsi) {
10298c2ecf20Sopenharmony_ci		ret = ice_add_vsi(hw, vsi->idx, ctxt, NULL);
10308c2ecf20Sopenharmony_ci		if (ret) {
10318c2ecf20Sopenharmony_ci			dev_err(dev, "Add VSI failed, err %d\n", ret);
10328c2ecf20Sopenharmony_ci			ret = -EIO;
10338c2ecf20Sopenharmony_ci			goto out;
10348c2ecf20Sopenharmony_ci		}
10358c2ecf20Sopenharmony_ci	} else {
10368c2ecf20Sopenharmony_ci		ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
10378c2ecf20Sopenharmony_ci		if (ret) {
10388c2ecf20Sopenharmony_ci			dev_err(dev, "Update VSI failed, err %d\n", ret);
10398c2ecf20Sopenharmony_ci			ret = -EIO;
10408c2ecf20Sopenharmony_ci			goto out;
10418c2ecf20Sopenharmony_ci		}
10428c2ecf20Sopenharmony_ci	}
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_ci	/* keep context for update VSI operations */
10458c2ecf20Sopenharmony_ci	vsi->info = ctxt->info;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	/* record VSI number returned */
10488c2ecf20Sopenharmony_ci	vsi->vsi_num = ctxt->vsi_num;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ciout:
10518c2ecf20Sopenharmony_ci	kfree(ctxt);
10528c2ecf20Sopenharmony_ci	return ret;
10538c2ecf20Sopenharmony_ci}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci/**
10568c2ecf20Sopenharmony_ci * ice_free_res - free a block of resources
10578c2ecf20Sopenharmony_ci * @res: pointer to the resource
10588c2ecf20Sopenharmony_ci * @index: starting index previously returned by ice_get_res
10598c2ecf20Sopenharmony_ci * @id: identifier to track owner
10608c2ecf20Sopenharmony_ci *
10618c2ecf20Sopenharmony_ci * Returns number of resources freed
10628c2ecf20Sopenharmony_ci */
10638c2ecf20Sopenharmony_ciint ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
10648c2ecf20Sopenharmony_ci{
10658c2ecf20Sopenharmony_ci	int count = 0;
10668c2ecf20Sopenharmony_ci	int i;
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	if (!res || index >= res->end)
10698c2ecf20Sopenharmony_ci		return -EINVAL;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	id |= ICE_RES_VALID_BIT;
10728c2ecf20Sopenharmony_ci	for (i = index; i < res->end && res->list[i] == id; i++) {
10738c2ecf20Sopenharmony_ci		res->list[i] = 0;
10748c2ecf20Sopenharmony_ci		count++;
10758c2ecf20Sopenharmony_ci	}
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci	return count;
10788c2ecf20Sopenharmony_ci}
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci/**
10818c2ecf20Sopenharmony_ci * ice_search_res - Search the tracker for a block of resources
10828c2ecf20Sopenharmony_ci * @res: pointer to the resource
10838c2ecf20Sopenharmony_ci * @needed: size of the block needed
10848c2ecf20Sopenharmony_ci * @id: identifier to track owner
10858c2ecf20Sopenharmony_ci *
10868c2ecf20Sopenharmony_ci * Returns the base item index of the block, or -ENOMEM for error
10878c2ecf20Sopenharmony_ci */
10888c2ecf20Sopenharmony_cistatic int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	u16 start = 0, end = 0;
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	if (needed > res->end)
10938c2ecf20Sopenharmony_ci		return -ENOMEM;
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	id |= ICE_RES_VALID_BIT;
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	do {
10988c2ecf20Sopenharmony_ci		/* skip already allocated entries */
10998c2ecf20Sopenharmony_ci		if (res->list[end++] & ICE_RES_VALID_BIT) {
11008c2ecf20Sopenharmony_ci			start = end;
11018c2ecf20Sopenharmony_ci			if ((start + needed) > res->end)
11028c2ecf20Sopenharmony_ci				break;
11038c2ecf20Sopenharmony_ci		}
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		if (end == (start + needed)) {
11068c2ecf20Sopenharmony_ci			int i = start;
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci			/* there was enough, so assign it to the requestor */
11098c2ecf20Sopenharmony_ci			while (i != end)
11108c2ecf20Sopenharmony_ci				res->list[i++] = id;
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci			return start;
11138c2ecf20Sopenharmony_ci		}
11148c2ecf20Sopenharmony_ci	} while (end < res->end);
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	return -ENOMEM;
11178c2ecf20Sopenharmony_ci}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci/**
11208c2ecf20Sopenharmony_ci * ice_get_free_res_count - Get free count from a resource tracker
11218c2ecf20Sopenharmony_ci * @res: Resource tracker instance
11228c2ecf20Sopenharmony_ci */
11238c2ecf20Sopenharmony_cistatic u16 ice_get_free_res_count(struct ice_res_tracker *res)
11248c2ecf20Sopenharmony_ci{
11258c2ecf20Sopenharmony_ci	u16 i, count = 0;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	for (i = 0; i < res->end; i++)
11288c2ecf20Sopenharmony_ci		if (!(res->list[i] & ICE_RES_VALID_BIT))
11298c2ecf20Sopenharmony_ci			count++;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	return count;
11328c2ecf20Sopenharmony_ci}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci/**
11358c2ecf20Sopenharmony_ci * ice_get_res - get a block of resources
11368c2ecf20Sopenharmony_ci * @pf: board private structure
11378c2ecf20Sopenharmony_ci * @res: pointer to the resource
11388c2ecf20Sopenharmony_ci * @needed: size of the block needed
11398c2ecf20Sopenharmony_ci * @id: identifier to track owner
11408c2ecf20Sopenharmony_ci *
11418c2ecf20Sopenharmony_ci * Returns the base item index of the block, or negative for error
11428c2ecf20Sopenharmony_ci */
11438c2ecf20Sopenharmony_ciint
11448c2ecf20Sopenharmony_ciice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
11458c2ecf20Sopenharmony_ci{
11468c2ecf20Sopenharmony_ci	if (!res || !pf)
11478c2ecf20Sopenharmony_ci		return -EINVAL;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	if (!needed || needed > res->num_entries || id >= ICE_RES_VALID_BIT) {
11508c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "param err: needed=%d, num_entries = %d id=0x%04x\n",
11518c2ecf20Sopenharmony_ci			needed, res->num_entries, id);
11528c2ecf20Sopenharmony_ci		return -EINVAL;
11538c2ecf20Sopenharmony_ci	}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ci	return ice_search_res(res, needed, id);
11568c2ecf20Sopenharmony_ci}
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci/**
11598c2ecf20Sopenharmony_ci * ice_vsi_setup_vector_base - Set up the base vector for the given VSI
11608c2ecf20Sopenharmony_ci * @vsi: ptr to the VSI
11618c2ecf20Sopenharmony_ci *
11628c2ecf20Sopenharmony_ci * This should only be called after ice_vsi_alloc() which allocates the
11638c2ecf20Sopenharmony_ci * corresponding SW VSI structure and initializes num_queue_pairs for the
11648c2ecf20Sopenharmony_ci * newly allocated VSI.
11658c2ecf20Sopenharmony_ci *
11668c2ecf20Sopenharmony_ci * Returns 0 on success or negative on failure
11678c2ecf20Sopenharmony_ci */
11688c2ecf20Sopenharmony_cistatic int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
11698c2ecf20Sopenharmony_ci{
11708c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
11718c2ecf20Sopenharmony_ci	struct device *dev;
11728c2ecf20Sopenharmony_ci	u16 num_q_vectors;
11738c2ecf20Sopenharmony_ci	int base;
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
11768c2ecf20Sopenharmony_ci	/* SRIOV doesn't grab irq_tracker entries for each VSI */
11778c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
11788c2ecf20Sopenharmony_ci		return 0;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	if (vsi->base_vector) {
11818c2ecf20Sopenharmony_ci		dev_dbg(dev, "VSI %d has non-zero base vector %d\n",
11828c2ecf20Sopenharmony_ci			vsi->vsi_num, vsi->base_vector);
11838c2ecf20Sopenharmony_ci		return -EEXIST;
11848c2ecf20Sopenharmony_ci	}
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	num_q_vectors = vsi->num_q_vectors;
11878c2ecf20Sopenharmony_ci	/* reserve slots from OS requested IRQs */
11888c2ecf20Sopenharmony_ci	base = ice_get_res(pf, pf->irq_tracker, num_q_vectors, vsi->idx);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	if (base < 0) {
11918c2ecf20Sopenharmony_ci		dev_err(dev, "%d MSI-X interrupts available. %s %d failed to get %d MSI-X vectors\n",
11928c2ecf20Sopenharmony_ci			ice_get_free_res_count(pf->irq_tracker),
11938c2ecf20Sopenharmony_ci			ice_vsi_type_str(vsi->type), vsi->idx, num_q_vectors);
11948c2ecf20Sopenharmony_ci		return -ENOENT;
11958c2ecf20Sopenharmony_ci	}
11968c2ecf20Sopenharmony_ci	vsi->base_vector = (u16)base;
11978c2ecf20Sopenharmony_ci	pf->num_avail_sw_msix -= num_q_vectors;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	return 0;
12008c2ecf20Sopenharmony_ci}
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci/**
12038c2ecf20Sopenharmony_ci * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
12048c2ecf20Sopenharmony_ci * @vsi: the VSI having rings deallocated
12058c2ecf20Sopenharmony_ci */
12068c2ecf20Sopenharmony_cistatic void ice_vsi_clear_rings(struct ice_vsi *vsi)
12078c2ecf20Sopenharmony_ci{
12088c2ecf20Sopenharmony_ci	int i;
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	/* Avoid stale references by clearing map from vector to ring */
12118c2ecf20Sopenharmony_ci	if (vsi->q_vectors) {
12128c2ecf20Sopenharmony_ci		ice_for_each_q_vector(vsi, i) {
12138c2ecf20Sopenharmony_ci			struct ice_q_vector *q_vector = vsi->q_vectors[i];
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci			if (q_vector) {
12168c2ecf20Sopenharmony_ci				q_vector->tx.ring = NULL;
12178c2ecf20Sopenharmony_ci				q_vector->rx.ring = NULL;
12188c2ecf20Sopenharmony_ci			}
12198c2ecf20Sopenharmony_ci		}
12208c2ecf20Sopenharmony_ci	}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	if (vsi->tx_rings) {
12238c2ecf20Sopenharmony_ci		for (i = 0; i < vsi->alloc_txq; i++) {
12248c2ecf20Sopenharmony_ci			if (vsi->tx_rings[i]) {
12258c2ecf20Sopenharmony_ci				kfree_rcu(vsi->tx_rings[i], rcu);
12268c2ecf20Sopenharmony_ci				WRITE_ONCE(vsi->tx_rings[i], NULL);
12278c2ecf20Sopenharmony_ci			}
12288c2ecf20Sopenharmony_ci		}
12298c2ecf20Sopenharmony_ci	}
12308c2ecf20Sopenharmony_ci	if (vsi->rx_rings) {
12318c2ecf20Sopenharmony_ci		for (i = 0; i < vsi->alloc_rxq; i++) {
12328c2ecf20Sopenharmony_ci			if (vsi->rx_rings[i]) {
12338c2ecf20Sopenharmony_ci				kfree_rcu(vsi->rx_rings[i], rcu);
12348c2ecf20Sopenharmony_ci				WRITE_ONCE(vsi->rx_rings[i], NULL);
12358c2ecf20Sopenharmony_ci			}
12368c2ecf20Sopenharmony_ci		}
12378c2ecf20Sopenharmony_ci	}
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ci/**
12418c2ecf20Sopenharmony_ci * ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI
12428c2ecf20Sopenharmony_ci * @vsi: VSI which is having rings allocated
12438c2ecf20Sopenharmony_ci */
12448c2ecf20Sopenharmony_cistatic int ice_vsi_alloc_rings(struct ice_vsi *vsi)
12458c2ecf20Sopenharmony_ci{
12468c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
12478c2ecf20Sopenharmony_ci	struct device *dev;
12488c2ecf20Sopenharmony_ci	u16 i;
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
12518c2ecf20Sopenharmony_ci	/* Allocate Tx rings */
12528c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->alloc_txq; i++) {
12538c2ecf20Sopenharmony_ci		struct ice_ring *ring;
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci		/* allocate with kzalloc(), free with kfree_rcu() */
12568c2ecf20Sopenharmony_ci		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci		if (!ring)
12598c2ecf20Sopenharmony_ci			goto err_out;
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci		ring->q_index = i;
12628c2ecf20Sopenharmony_ci		ring->reg_idx = vsi->txq_map[i];
12638c2ecf20Sopenharmony_ci		ring->ring_active = false;
12648c2ecf20Sopenharmony_ci		ring->vsi = vsi;
12658c2ecf20Sopenharmony_ci		ring->dev = dev;
12668c2ecf20Sopenharmony_ci		ring->count = vsi->num_tx_desc;
12678c2ecf20Sopenharmony_ci		ring->txq_teid = ICE_INVAL_TEID;
12688c2ecf20Sopenharmony_ci		WRITE_ONCE(vsi->tx_rings[i], ring);
12698c2ecf20Sopenharmony_ci	}
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	/* Allocate Rx rings */
12728c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->alloc_rxq; i++) {
12738c2ecf20Sopenharmony_ci		struct ice_ring *ring;
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci		/* allocate with kzalloc(), free with kfree_rcu() */
12768c2ecf20Sopenharmony_ci		ring = kzalloc(sizeof(*ring), GFP_KERNEL);
12778c2ecf20Sopenharmony_ci		if (!ring)
12788c2ecf20Sopenharmony_ci			goto err_out;
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci		ring->q_index = i;
12818c2ecf20Sopenharmony_ci		ring->reg_idx = vsi->rxq_map[i];
12828c2ecf20Sopenharmony_ci		ring->ring_active = false;
12838c2ecf20Sopenharmony_ci		ring->vsi = vsi;
12848c2ecf20Sopenharmony_ci		ring->netdev = vsi->netdev;
12858c2ecf20Sopenharmony_ci		ring->dev = dev;
12868c2ecf20Sopenharmony_ci		ring->count = vsi->num_rx_desc;
12878c2ecf20Sopenharmony_ci		WRITE_ONCE(vsi->rx_rings[i], ring);
12888c2ecf20Sopenharmony_ci	}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	return 0;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_cierr_out:
12938c2ecf20Sopenharmony_ci	ice_vsi_clear_rings(vsi);
12948c2ecf20Sopenharmony_ci	return -ENOMEM;
12958c2ecf20Sopenharmony_ci}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci/**
12988c2ecf20Sopenharmony_ci * ice_vsi_manage_rss_lut - disable/enable RSS
12998c2ecf20Sopenharmony_ci * @vsi: the VSI being changed
13008c2ecf20Sopenharmony_ci * @ena: boolean value indicating if this is an enable or disable request
13018c2ecf20Sopenharmony_ci *
13028c2ecf20Sopenharmony_ci * In the event of disable request for RSS, this function will zero out RSS
13038c2ecf20Sopenharmony_ci * LUT, while in the event of enable request for RSS, it will reconfigure RSS
13048c2ecf20Sopenharmony_ci * LUT.
13058c2ecf20Sopenharmony_ci */
13068c2ecf20Sopenharmony_ciint ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena)
13078c2ecf20Sopenharmony_ci{
13088c2ecf20Sopenharmony_ci	int err = 0;
13098c2ecf20Sopenharmony_ci	u8 *lut;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
13128c2ecf20Sopenharmony_ci	if (!lut)
13138c2ecf20Sopenharmony_ci		return -ENOMEM;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	if (ena) {
13168c2ecf20Sopenharmony_ci		if (vsi->rss_lut_user)
13178c2ecf20Sopenharmony_ci			memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
13188c2ecf20Sopenharmony_ci		else
13198c2ecf20Sopenharmony_ci			ice_fill_rss_lut(lut, vsi->rss_table_size,
13208c2ecf20Sopenharmony_ci					 vsi->rss_size);
13218c2ecf20Sopenharmony_ci	}
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	err = ice_set_rss(vsi, NULL, lut, vsi->rss_table_size);
13248c2ecf20Sopenharmony_ci	kfree(lut);
13258c2ecf20Sopenharmony_ci	return err;
13268c2ecf20Sopenharmony_ci}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci/**
13298c2ecf20Sopenharmony_ci * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI
13308c2ecf20Sopenharmony_ci * @vsi: VSI to be configured
13318c2ecf20Sopenharmony_ci */
13328c2ecf20Sopenharmony_cistatic int ice_vsi_cfg_rss_lut_key(struct ice_vsi *vsi)
13338c2ecf20Sopenharmony_ci{
13348c2ecf20Sopenharmony_ci	struct ice_aqc_get_set_rss_keys *key;
13358c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
13368c2ecf20Sopenharmony_ci	enum ice_status status;
13378c2ecf20Sopenharmony_ci	struct device *dev;
13388c2ecf20Sopenharmony_ci	int err = 0;
13398c2ecf20Sopenharmony_ci	u8 *lut;
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
13428c2ecf20Sopenharmony_ci	vsi->rss_size = min_t(u16, vsi->rss_size, vsi->num_rxq);
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	lut = kzalloc(vsi->rss_table_size, GFP_KERNEL);
13458c2ecf20Sopenharmony_ci	if (!lut)
13468c2ecf20Sopenharmony_ci		return -ENOMEM;
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	if (vsi->rss_lut_user)
13498c2ecf20Sopenharmony_ci		memcpy(lut, vsi->rss_lut_user, vsi->rss_table_size);
13508c2ecf20Sopenharmony_ci	else
13518c2ecf20Sopenharmony_ci		ice_fill_rss_lut(lut, vsi->rss_table_size, vsi->rss_size);
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	status = ice_aq_set_rss_lut(&pf->hw, vsi->idx, vsi->rss_lut_type, lut,
13548c2ecf20Sopenharmony_ci				    vsi->rss_table_size);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	if (status) {
13578c2ecf20Sopenharmony_ci		dev_err(dev, "set_rss_lut failed, error %s\n",
13588c2ecf20Sopenharmony_ci			ice_stat_str(status));
13598c2ecf20Sopenharmony_ci		err = -EIO;
13608c2ecf20Sopenharmony_ci		goto ice_vsi_cfg_rss_exit;
13618c2ecf20Sopenharmony_ci	}
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci	key = kzalloc(sizeof(*key), GFP_KERNEL);
13648c2ecf20Sopenharmony_ci	if (!key) {
13658c2ecf20Sopenharmony_ci		err = -ENOMEM;
13668c2ecf20Sopenharmony_ci		goto ice_vsi_cfg_rss_exit;
13678c2ecf20Sopenharmony_ci	}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	if (vsi->rss_hkey_user)
13708c2ecf20Sopenharmony_ci		memcpy(key,
13718c2ecf20Sopenharmony_ci		       (struct ice_aqc_get_set_rss_keys *)vsi->rss_hkey_user,
13728c2ecf20Sopenharmony_ci		       ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
13738c2ecf20Sopenharmony_ci	else
13748c2ecf20Sopenharmony_ci		netdev_rss_key_fill((void *)key,
13758c2ecf20Sopenharmony_ci				    ICE_GET_SET_RSS_KEY_EXTEND_KEY_SIZE);
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	status = ice_aq_set_rss_key(&pf->hw, vsi->idx, key);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	if (status) {
13808c2ecf20Sopenharmony_ci		dev_err(dev, "set_rss_key failed, error %s\n",
13818c2ecf20Sopenharmony_ci			ice_stat_str(status));
13828c2ecf20Sopenharmony_ci		err = -EIO;
13838c2ecf20Sopenharmony_ci	}
13848c2ecf20Sopenharmony_ci
13858c2ecf20Sopenharmony_ci	kfree(key);
13868c2ecf20Sopenharmony_ciice_vsi_cfg_rss_exit:
13878c2ecf20Sopenharmony_ci	kfree(lut);
13888c2ecf20Sopenharmony_ci	return err;
13898c2ecf20Sopenharmony_ci}
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci/**
13928c2ecf20Sopenharmony_ci * ice_vsi_set_vf_rss_flow_fld - Sets VF VSI RSS input set for different flows
13938c2ecf20Sopenharmony_ci * @vsi: VSI to be configured
13948c2ecf20Sopenharmony_ci *
13958c2ecf20Sopenharmony_ci * This function will only be called during the VF VSI setup. Upon successful
13968c2ecf20Sopenharmony_ci * completion of package download, this function will configure default RSS
13978c2ecf20Sopenharmony_ci * input sets for VF VSI.
13988c2ecf20Sopenharmony_ci */
13998c2ecf20Sopenharmony_cistatic void ice_vsi_set_vf_rss_flow_fld(struct ice_vsi *vsi)
14008c2ecf20Sopenharmony_ci{
14018c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
14028c2ecf20Sopenharmony_ci	enum ice_status status;
14038c2ecf20Sopenharmony_ci	struct device *dev;
14048c2ecf20Sopenharmony_ci
14058c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
14068c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
14078c2ecf20Sopenharmony_ci		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
14088c2ecf20Sopenharmony_ci			vsi->vsi_num);
14098c2ecf20Sopenharmony_ci		return;
14108c2ecf20Sopenharmony_ci	}
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	status = ice_add_avf_rss_cfg(&pf->hw, vsi->idx, ICE_DEFAULT_RSS_HENA);
14138c2ecf20Sopenharmony_ci	if (status)
14148c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_avf_rss_cfg failed for vsi = %d, error = %s\n",
14158c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
14168c2ecf20Sopenharmony_ci}
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci/**
14198c2ecf20Sopenharmony_ci * ice_vsi_set_rss_flow_fld - Sets RSS input set for different flows
14208c2ecf20Sopenharmony_ci * @vsi: VSI to be configured
14218c2ecf20Sopenharmony_ci *
14228c2ecf20Sopenharmony_ci * This function will only be called after successful download package call
14238c2ecf20Sopenharmony_ci * during initialization of PF. Since the downloaded package will erase the
14248c2ecf20Sopenharmony_ci * RSS section, this function will configure RSS input sets for different
14258c2ecf20Sopenharmony_ci * flow types. The last profile added has the highest priority, therefore 2
14268c2ecf20Sopenharmony_ci * tuple profiles (i.e. IPv4 src/dst) are added before 4 tuple profiles
14278c2ecf20Sopenharmony_ci * (i.e. IPv4 src/dst TCP src/dst port).
14288c2ecf20Sopenharmony_ci */
14298c2ecf20Sopenharmony_cistatic void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
14308c2ecf20Sopenharmony_ci{
14318c2ecf20Sopenharmony_ci	u16 vsi_handle = vsi->idx, vsi_num = vsi->vsi_num;
14328c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
14338c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
14348c2ecf20Sopenharmony_ci	enum ice_status status;
14358c2ecf20Sopenharmony_ci	struct device *dev;
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
14388c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
14398c2ecf20Sopenharmony_ci		dev_dbg(dev, "Advanced RSS disabled. Package download failed, vsi num = %d\n",
14408c2ecf20Sopenharmony_ci			vsi_num);
14418c2ecf20Sopenharmony_ci		return;
14428c2ecf20Sopenharmony_ci	}
14438c2ecf20Sopenharmony_ci	/* configure RSS for IPv4 with input set IP src/dst */
14448c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
14458c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_IPV4);
14468c2ecf20Sopenharmony_ci	if (status)
14478c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for ipv4 flow, vsi = %d, error = %s\n",
14488c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	/* configure RSS for IPv6 with input set IPv6 src/dst */
14518c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
14528c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_IPV6);
14538c2ecf20Sopenharmony_ci	if (status)
14548c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for ipv6 flow, vsi = %d, error = %s\n",
14558c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	/* configure RSS for tcp4 with input set IP src/dst, TCP src/dst */
14588c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV4,
14598c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV4);
14608c2ecf20Sopenharmony_ci	if (status)
14618c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for tcp4 flow, vsi = %d, error = %s\n",
14628c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	/* configure RSS for udp4 with input set IP src/dst, UDP src/dst */
14658c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV4,
14668c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV4);
14678c2ecf20Sopenharmony_ci	if (status)
14688c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for udp4 flow, vsi = %d, error = %s\n",
14698c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci	/* configure RSS for sctp4 with input set IP src/dst */
14728c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV4,
14738c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV4);
14748c2ecf20Sopenharmony_ci	if (status)
14758c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for sctp4 flow, vsi = %d, error = %s\n",
14768c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	/* configure RSS for tcp6 with input set IPv6 src/dst, TCP src/dst */
14798c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_TCP_IPV6,
14808c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_IPV6);
14818c2ecf20Sopenharmony_ci	if (status)
14828c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for tcp6 flow, vsi = %d, error = %s\n",
14838c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci	/* configure RSS for udp6 with input set IPv6 src/dst, UDP src/dst */
14868c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_HASH_UDP_IPV6,
14878c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_IPV6);
14888c2ecf20Sopenharmony_ci	if (status)
14898c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for udp6 flow, vsi = %d, error = %s\n",
14908c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	/* configure RSS for sctp6 with input set IPv6 src/dst */
14938c2ecf20Sopenharmony_ci	status = ice_add_rss_cfg(hw, vsi_handle, ICE_FLOW_HASH_IPV6,
14948c2ecf20Sopenharmony_ci				 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_IPV6);
14958c2ecf20Sopenharmony_ci	if (status)
14968c2ecf20Sopenharmony_ci		dev_dbg(dev, "ice_add_rss_cfg failed for sctp6 flow, vsi = %d, error = %s\n",
14978c2ecf20Sopenharmony_ci			vsi_num, ice_stat_str(status));
14988c2ecf20Sopenharmony_ci}
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci/**
15018c2ecf20Sopenharmony_ci * ice_pf_state_is_nominal - checks the PF for nominal state
15028c2ecf20Sopenharmony_ci * @pf: pointer to PF to check
15038c2ecf20Sopenharmony_ci *
15048c2ecf20Sopenharmony_ci * Check the PF's state for a collection of bits that would indicate
15058c2ecf20Sopenharmony_ci * the PF is in a state that would inhibit normal operation for
15068c2ecf20Sopenharmony_ci * driver functionality.
15078c2ecf20Sopenharmony_ci *
15088c2ecf20Sopenharmony_ci * Returns true if PF is in a nominal state, false otherwise
15098c2ecf20Sopenharmony_ci */
15108c2ecf20Sopenharmony_cibool ice_pf_state_is_nominal(struct ice_pf *pf)
15118c2ecf20Sopenharmony_ci{
15128c2ecf20Sopenharmony_ci	DECLARE_BITMAP(check_bits, __ICE_STATE_NBITS) = { 0 };
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	if (!pf)
15158c2ecf20Sopenharmony_ci		return false;
15168c2ecf20Sopenharmony_ci
15178c2ecf20Sopenharmony_ci	bitmap_set(check_bits, 0, __ICE_STATE_NOMINAL_CHECK_BITS);
15188c2ecf20Sopenharmony_ci	if (bitmap_intersects(pf->state, check_bits, __ICE_STATE_NBITS))
15198c2ecf20Sopenharmony_ci		return false;
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	return true;
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci/**
15258c2ecf20Sopenharmony_ci * ice_update_eth_stats - Update VSI-specific ethernet statistics counters
15268c2ecf20Sopenharmony_ci * @vsi: the VSI to be updated
15278c2ecf20Sopenharmony_ci */
15288c2ecf20Sopenharmony_civoid ice_update_eth_stats(struct ice_vsi *vsi)
15298c2ecf20Sopenharmony_ci{
15308c2ecf20Sopenharmony_ci	struct ice_eth_stats *prev_es, *cur_es;
15318c2ecf20Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
15328c2ecf20Sopenharmony_ci	u16 vsi_num = vsi->vsi_num;    /* HW absolute index of a VSI */
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	prev_es = &vsi->eth_stats_prev;
15358c2ecf20Sopenharmony_ci	cur_es = &vsi->eth_stats;
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_GORCL(vsi_num), vsi->stat_offsets_loaded,
15388c2ecf20Sopenharmony_ci			  &prev_es->rx_bytes, &cur_es->rx_bytes);
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_UPRCL(vsi_num), vsi->stat_offsets_loaded,
15418c2ecf20Sopenharmony_ci			  &prev_es->rx_unicast, &cur_es->rx_unicast);
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_MPRCL(vsi_num), vsi->stat_offsets_loaded,
15448c2ecf20Sopenharmony_ci			  &prev_es->rx_multicast, &cur_es->rx_multicast);
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_BPRCL(vsi_num), vsi->stat_offsets_loaded,
15478c2ecf20Sopenharmony_ci			  &prev_es->rx_broadcast, &cur_es->rx_broadcast);
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded,
15508c2ecf20Sopenharmony_ci			  &prev_es->rx_discards, &cur_es->rx_discards);
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_GOTCL(vsi_num), vsi->stat_offsets_loaded,
15538c2ecf20Sopenharmony_ci			  &prev_es->tx_bytes, &cur_es->tx_bytes);
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_UPTCL(vsi_num), vsi->stat_offsets_loaded,
15568c2ecf20Sopenharmony_ci			  &prev_es->tx_unicast, &cur_es->tx_unicast);
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_MPTCL(vsi_num), vsi->stat_offsets_loaded,
15598c2ecf20Sopenharmony_ci			  &prev_es->tx_multicast, &cur_es->tx_multicast);
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLV_BPTCL(vsi_num), vsi->stat_offsets_loaded,
15628c2ecf20Sopenharmony_ci			  &prev_es->tx_broadcast, &cur_es->tx_broadcast);
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded,
15658c2ecf20Sopenharmony_ci			  &prev_es->tx_errors, &cur_es->tx_errors);
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	vsi->stat_offsets_loaded = true;
15688c2ecf20Sopenharmony_ci}
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_ci/**
15718c2ecf20Sopenharmony_ci * ice_vsi_add_vlan - Add VSI membership for given VLAN
15728c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
15738c2ecf20Sopenharmony_ci * @vid: VLAN ID to be added
15748c2ecf20Sopenharmony_ci * @action: filter action to be performed on match
15758c2ecf20Sopenharmony_ci */
15768c2ecf20Sopenharmony_ciint
15778c2ecf20Sopenharmony_ciice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action)
15788c2ecf20Sopenharmony_ci{
15798c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
15808c2ecf20Sopenharmony_ci	struct device *dev;
15818c2ecf20Sopenharmony_ci	int err = 0;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	if (!ice_fltr_add_vlan(vsi, vid, action)) {
15868c2ecf20Sopenharmony_ci		vsi->num_vlan++;
15878c2ecf20Sopenharmony_ci	} else {
15888c2ecf20Sopenharmony_ci		err = -ENODEV;
15898c2ecf20Sopenharmony_ci		dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid,
15908c2ecf20Sopenharmony_ci			vsi->vsi_num);
15918c2ecf20Sopenharmony_ci	}
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	return err;
15948c2ecf20Sopenharmony_ci}
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci/**
15978c2ecf20Sopenharmony_ci * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN
15988c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
15998c2ecf20Sopenharmony_ci * @vid: VLAN ID to be removed
16008c2ecf20Sopenharmony_ci *
16018c2ecf20Sopenharmony_ci * Returns 0 on success and negative on failure
16028c2ecf20Sopenharmony_ci */
16038c2ecf20Sopenharmony_ciint ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid)
16048c2ecf20Sopenharmony_ci{
16058c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
16068c2ecf20Sopenharmony_ci	enum ice_status status;
16078c2ecf20Sopenharmony_ci	struct device *dev;
16088c2ecf20Sopenharmony_ci	int err = 0;
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci	status = ice_fltr_remove_vlan(vsi, vid, ICE_FWD_TO_VSI);
16138c2ecf20Sopenharmony_ci	if (!status) {
16148c2ecf20Sopenharmony_ci		vsi->num_vlan--;
16158c2ecf20Sopenharmony_ci	} else if (status == ICE_ERR_DOES_NOT_EXIST) {
16168c2ecf20Sopenharmony_ci		dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, status: %s\n",
16178c2ecf20Sopenharmony_ci			vid, vsi->vsi_num, ice_stat_str(status));
16188c2ecf20Sopenharmony_ci	} else {
16198c2ecf20Sopenharmony_ci		dev_err(dev, "Error removing VLAN %d on vsi %i error: %s\n",
16208c2ecf20Sopenharmony_ci			vid, vsi->vsi_num, ice_stat_str(status));
16218c2ecf20Sopenharmony_ci		err = -EIO;
16228c2ecf20Sopenharmony_ci	}
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	return err;
16258c2ecf20Sopenharmony_ci}
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci/**
16288c2ecf20Sopenharmony_ci * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
16298c2ecf20Sopenharmony_ci * @vsi: VSI
16308c2ecf20Sopenharmony_ci */
16318c2ecf20Sopenharmony_civoid ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
16328c2ecf20Sopenharmony_ci{
16338c2ecf20Sopenharmony_ci	if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
16348c2ecf20Sopenharmony_ci		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
16358c2ecf20Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_2048;
16368c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192)
16378c2ecf20Sopenharmony_ci	} else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
16388c2ecf20Sopenharmony_ci		   (vsi->netdev->mtu <= ETH_DATA_LEN)) {
16398c2ecf20Sopenharmony_ci		vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
16408c2ecf20Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
16418c2ecf20Sopenharmony_ci#endif
16428c2ecf20Sopenharmony_ci	} else {
16438c2ecf20Sopenharmony_ci		vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
16448c2ecf20Sopenharmony_ci#if (PAGE_SIZE < 8192)
16458c2ecf20Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_3072;
16468c2ecf20Sopenharmony_ci#else
16478c2ecf20Sopenharmony_ci		vsi->rx_buf_len = ICE_RXBUF_2048;
16488c2ecf20Sopenharmony_ci#endif
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci/**
16538c2ecf20Sopenharmony_ci * ice_write_qrxflxp_cntxt - write/configure QRXFLXP_CNTXT register
16548c2ecf20Sopenharmony_ci * @hw: HW pointer
16558c2ecf20Sopenharmony_ci * @pf_q: index of the Rx queue in the PF's queue space
16568c2ecf20Sopenharmony_ci * @rxdid: flexible descriptor RXDID
16578c2ecf20Sopenharmony_ci * @prio: priority for the RXDID for this queue
16588c2ecf20Sopenharmony_ci */
16598c2ecf20Sopenharmony_civoid
16608c2ecf20Sopenharmony_ciice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio)
16618c2ecf20Sopenharmony_ci{
16628c2ecf20Sopenharmony_ci	int regval = rd32(hw, QRXFLXP_CNTXT(pf_q));
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	/* clear any previous values */
16658c2ecf20Sopenharmony_ci	regval &= ~(QRXFLXP_CNTXT_RXDID_IDX_M |
16668c2ecf20Sopenharmony_ci		    QRXFLXP_CNTXT_RXDID_PRIO_M |
16678c2ecf20Sopenharmony_ci		    QRXFLXP_CNTXT_TS_M);
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	regval |= (rxdid << QRXFLXP_CNTXT_RXDID_IDX_S) &
16708c2ecf20Sopenharmony_ci		QRXFLXP_CNTXT_RXDID_IDX_M;
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	regval |= (prio << QRXFLXP_CNTXT_RXDID_PRIO_S) &
16738c2ecf20Sopenharmony_ci		QRXFLXP_CNTXT_RXDID_PRIO_M;
16748c2ecf20Sopenharmony_ci
16758c2ecf20Sopenharmony_ci	wr32(hw, QRXFLXP_CNTXT(pf_q), regval);
16768c2ecf20Sopenharmony_ci}
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci/**
16798c2ecf20Sopenharmony_ci * ice_vsi_cfg_rxqs - Configure the VSI for Rx
16808c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
16818c2ecf20Sopenharmony_ci *
16828c2ecf20Sopenharmony_ci * Return 0 on success and a negative value on error
16838c2ecf20Sopenharmony_ci * Configure the Rx VSI for operation.
16848c2ecf20Sopenharmony_ci */
16858c2ecf20Sopenharmony_ciint ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
16868c2ecf20Sopenharmony_ci{
16878c2ecf20Sopenharmony_ci	u16 i;
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
16908c2ecf20Sopenharmony_ci		goto setup_rings;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	ice_vsi_cfg_frame_size(vsi);
16938c2ecf20Sopenharmony_cisetup_rings:
16948c2ecf20Sopenharmony_ci	/* set up individual rings */
16958c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_rxq; i++) {
16968c2ecf20Sopenharmony_ci		int err;
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci		err = ice_setup_rx_ctx(vsi->rx_rings[i]);
16998c2ecf20Sopenharmony_ci		if (err) {
17008c2ecf20Sopenharmony_ci			dev_err(ice_pf_to_dev(vsi->back), "ice_setup_rx_ctx failed for RxQ %d, err %d\n",
17018c2ecf20Sopenharmony_ci				i, err);
17028c2ecf20Sopenharmony_ci			return err;
17038c2ecf20Sopenharmony_ci		}
17048c2ecf20Sopenharmony_ci	}
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	return 0;
17078c2ecf20Sopenharmony_ci}
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci/**
17108c2ecf20Sopenharmony_ci * ice_vsi_cfg_txqs - Configure the VSI for Tx
17118c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
17128c2ecf20Sopenharmony_ci * @rings: Tx ring array to be configured
17138c2ecf20Sopenharmony_ci * @count: number of Tx ring array elements
17148c2ecf20Sopenharmony_ci *
17158c2ecf20Sopenharmony_ci * Return 0 on success and a negative value on error
17168c2ecf20Sopenharmony_ci * Configure the Tx VSI for operation.
17178c2ecf20Sopenharmony_ci */
17188c2ecf20Sopenharmony_cistatic int
17198c2ecf20Sopenharmony_ciice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_ring **rings, u16 count)
17208c2ecf20Sopenharmony_ci{
17218c2ecf20Sopenharmony_ci	struct ice_aqc_add_tx_qgrp *qg_buf;
17228c2ecf20Sopenharmony_ci	u16 q_idx = 0;
17238c2ecf20Sopenharmony_ci	int err = 0;
17248c2ecf20Sopenharmony_ci
17258c2ecf20Sopenharmony_ci	qg_buf = kzalloc(struct_size(qg_buf, txqs, 1), GFP_KERNEL);
17268c2ecf20Sopenharmony_ci	if (!qg_buf)
17278c2ecf20Sopenharmony_ci		return -ENOMEM;
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	qg_buf->num_txqs = 1;
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_ci	for (q_idx = 0; q_idx < count; q_idx++) {
17328c2ecf20Sopenharmony_ci		err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf);
17338c2ecf20Sopenharmony_ci		if (err)
17348c2ecf20Sopenharmony_ci			goto err_cfg_txqs;
17358c2ecf20Sopenharmony_ci	}
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_cierr_cfg_txqs:
17388c2ecf20Sopenharmony_ci	kfree(qg_buf);
17398c2ecf20Sopenharmony_ci	return err;
17408c2ecf20Sopenharmony_ci}
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci/**
17438c2ecf20Sopenharmony_ci * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
17448c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
17458c2ecf20Sopenharmony_ci *
17468c2ecf20Sopenharmony_ci * Return 0 on success and a negative value on error
17478c2ecf20Sopenharmony_ci * Configure the Tx VSI for operation.
17488c2ecf20Sopenharmony_ci */
17498c2ecf20Sopenharmony_ciint ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
17508c2ecf20Sopenharmony_ci{
17518c2ecf20Sopenharmony_ci	return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, vsi->num_txq);
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci/**
17558c2ecf20Sopenharmony_ci * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI
17568c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
17578c2ecf20Sopenharmony_ci *
17588c2ecf20Sopenharmony_ci * Return 0 on success and a negative value on error
17598c2ecf20Sopenharmony_ci * Configure the Tx queues dedicated for XDP in given VSI for operation.
17608c2ecf20Sopenharmony_ci */
17618c2ecf20Sopenharmony_ciint ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
17628c2ecf20Sopenharmony_ci{
17638c2ecf20Sopenharmony_ci	int ret;
17648c2ecf20Sopenharmony_ci	int i;
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings, vsi->num_xdp_txq);
17678c2ecf20Sopenharmony_ci	if (ret)
17688c2ecf20Sopenharmony_ci		return ret;
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_xdp_txq; i++)
17718c2ecf20Sopenharmony_ci		vsi->xdp_rings[i]->xsk_pool = ice_xsk_pool(vsi->xdp_rings[i]);
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	return ret;
17748c2ecf20Sopenharmony_ci}
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ci/**
17778c2ecf20Sopenharmony_ci * ice_intrl_usec_to_reg - convert interrupt rate limit to register value
17788c2ecf20Sopenharmony_ci * @intrl: interrupt rate limit in usecs
17798c2ecf20Sopenharmony_ci * @gran: interrupt rate limit granularity in usecs
17808c2ecf20Sopenharmony_ci *
17818c2ecf20Sopenharmony_ci * This function converts a decimal interrupt rate limit in usecs to the format
17828c2ecf20Sopenharmony_ci * expected by firmware.
17838c2ecf20Sopenharmony_ci */
17848c2ecf20Sopenharmony_ciu32 ice_intrl_usec_to_reg(u8 intrl, u8 gran)
17858c2ecf20Sopenharmony_ci{
17868c2ecf20Sopenharmony_ci	u32 val = intrl / gran;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	if (val)
17898c2ecf20Sopenharmony_ci		return val | GLINT_RATE_INTRL_ENA_M;
17908c2ecf20Sopenharmony_ci	return 0;
17918c2ecf20Sopenharmony_ci}
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci/**
17948c2ecf20Sopenharmony_ci * ice_vsi_cfg_msix - MSIX mode Interrupt Config in the HW
17958c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
17968c2ecf20Sopenharmony_ci *
17978c2ecf20Sopenharmony_ci * This configures MSIX mode interrupts for the PF VSI, and should not be used
17988c2ecf20Sopenharmony_ci * for the VF VSI.
17998c2ecf20Sopenharmony_ci */
18008c2ecf20Sopenharmony_civoid ice_vsi_cfg_msix(struct ice_vsi *vsi)
18018c2ecf20Sopenharmony_ci{
18028c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
18038c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
18048c2ecf20Sopenharmony_ci	u16 txq = 0, rxq = 0;
18058c2ecf20Sopenharmony_ci	int i, q;
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_q_vectors; i++) {
18088c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
18098c2ecf20Sopenharmony_ci		u16 reg_idx = q_vector->reg_idx;
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci		ice_cfg_itr(hw, q_vector);
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_ci		wr32(hw, GLINT_RATE(reg_idx),
18148c2ecf20Sopenharmony_ci		     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci		/* Both Transmit Queue Interrupt Cause Control register
18178c2ecf20Sopenharmony_ci		 * and Receive Queue Interrupt Cause control register
18188c2ecf20Sopenharmony_ci		 * expects MSIX_INDX field to be the vector index
18198c2ecf20Sopenharmony_ci		 * within the function space and not the absolute
18208c2ecf20Sopenharmony_ci		 * vector index across PF or across device.
18218c2ecf20Sopenharmony_ci		 * For SR-IOV VF VSIs queue vector index always starts
18228c2ecf20Sopenharmony_ci		 * with 1 since first vector index(0) is used for OICR
18238c2ecf20Sopenharmony_ci		 * in VF space. Since VMDq and other PF VSIs are within
18248c2ecf20Sopenharmony_ci		 * the PF function space, use the vector index that is
18258c2ecf20Sopenharmony_ci		 * tracked for this PF.
18268c2ecf20Sopenharmony_ci		 */
18278c2ecf20Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_tx; q++) {
18288c2ecf20Sopenharmony_ci			ice_cfg_txq_interrupt(vsi, txq, reg_idx,
18298c2ecf20Sopenharmony_ci					      q_vector->tx.itr_idx);
18308c2ecf20Sopenharmony_ci			txq++;
18318c2ecf20Sopenharmony_ci		}
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_rx; q++) {
18348c2ecf20Sopenharmony_ci			ice_cfg_rxq_interrupt(vsi, rxq, reg_idx,
18358c2ecf20Sopenharmony_ci					      q_vector->rx.itr_idx);
18368c2ecf20Sopenharmony_ci			rxq++;
18378c2ecf20Sopenharmony_ci		}
18388c2ecf20Sopenharmony_ci	}
18398c2ecf20Sopenharmony_ci}
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci/**
18428c2ecf20Sopenharmony_ci * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
18438c2ecf20Sopenharmony_ci * @vsi: the VSI being changed
18448c2ecf20Sopenharmony_ci */
18458c2ecf20Sopenharmony_ciint ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
18468c2ecf20Sopenharmony_ci{
18478c2ecf20Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
18488c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
18498c2ecf20Sopenharmony_ci	enum ice_status status;
18508c2ecf20Sopenharmony_ci	int ret = 0;
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
18538c2ecf20Sopenharmony_ci	if (!ctxt)
18548c2ecf20Sopenharmony_ci		return -ENOMEM;
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci	/* Here we are configuring the VSI to let the driver add VLAN tags by
18578c2ecf20Sopenharmony_ci	 * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
18588c2ecf20Sopenharmony_ci	 * insertion happens in the Tx hot path, in ice_tx_map.
18598c2ecf20Sopenharmony_ci	 */
18608c2ecf20Sopenharmony_ci	ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci	/* Preserve existing VLAN strip setting */
18638c2ecf20Sopenharmony_ci	ctxt->info.vlan_flags |= (vsi->info.vlan_flags &
18648c2ecf20Sopenharmony_ci				  ICE_AQ_VSI_VLAN_EMOD_M);
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
18698c2ecf20Sopenharmony_ci	if (status) {
18708c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %s aq_err %s\n",
18718c2ecf20Sopenharmony_ci			ice_stat_str(status),
18728c2ecf20Sopenharmony_ci			ice_aq_str(hw->adminq.sq_last_status));
18738c2ecf20Sopenharmony_ci		ret = -EIO;
18748c2ecf20Sopenharmony_ci		goto out;
18758c2ecf20Sopenharmony_ci	}
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	vsi->info.vlan_flags = ctxt->info.vlan_flags;
18788c2ecf20Sopenharmony_ciout:
18798c2ecf20Sopenharmony_ci	kfree(ctxt);
18808c2ecf20Sopenharmony_ci	return ret;
18818c2ecf20Sopenharmony_ci}
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci/**
18848c2ecf20Sopenharmony_ci * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
18858c2ecf20Sopenharmony_ci * @vsi: the VSI being changed
18868c2ecf20Sopenharmony_ci * @ena: boolean value indicating if this is a enable or disable request
18878c2ecf20Sopenharmony_ci */
18888c2ecf20Sopenharmony_ciint ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
18898c2ecf20Sopenharmony_ci{
18908c2ecf20Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
18918c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
18928c2ecf20Sopenharmony_ci	enum ice_status status;
18938c2ecf20Sopenharmony_ci	int ret = 0;
18948c2ecf20Sopenharmony_ci
18958c2ecf20Sopenharmony_ci	/* do not allow modifying VLAN stripping when a port VLAN is configured
18968c2ecf20Sopenharmony_ci	 * on this VSI
18978c2ecf20Sopenharmony_ci	 */
18988c2ecf20Sopenharmony_ci	if (vsi->info.pvid)
18998c2ecf20Sopenharmony_ci		return 0;
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
19028c2ecf20Sopenharmony_ci	if (!ctxt)
19038c2ecf20Sopenharmony_ci		return -ENOMEM;
19048c2ecf20Sopenharmony_ci
19058c2ecf20Sopenharmony_ci	/* Here we are configuring what the VSI should do with the VLAN tag in
19068c2ecf20Sopenharmony_ci	 * the Rx packet. We can either leave the tag in the packet or put it in
19078c2ecf20Sopenharmony_ci	 * the Rx descriptor.
19088c2ecf20Sopenharmony_ci	 */
19098c2ecf20Sopenharmony_ci	if (ena)
19108c2ecf20Sopenharmony_ci		/* Strip VLAN tag from Rx packet and put it in the desc */
19118c2ecf20Sopenharmony_ci		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
19128c2ecf20Sopenharmony_ci	else
19138c2ecf20Sopenharmony_ci		/* Disable stripping. Leave tag in packet */
19148c2ecf20Sopenharmony_ci		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ci	/* Allow all packets untagged/tagged */
19178c2ecf20Sopenharmony_ci	ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_ci	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
19228c2ecf20Sopenharmony_ci	if (status) {
19238c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %s aq_err %s\n",
19248c2ecf20Sopenharmony_ci			ena, ice_stat_str(status),
19258c2ecf20Sopenharmony_ci			ice_aq_str(hw->adminq.sq_last_status));
19268c2ecf20Sopenharmony_ci		ret = -EIO;
19278c2ecf20Sopenharmony_ci		goto out;
19288c2ecf20Sopenharmony_ci	}
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	vsi->info.vlan_flags = ctxt->info.vlan_flags;
19318c2ecf20Sopenharmony_ciout:
19328c2ecf20Sopenharmony_ci	kfree(ctxt);
19338c2ecf20Sopenharmony_ci	return ret;
19348c2ecf20Sopenharmony_ci}
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci/**
19378c2ecf20Sopenharmony_ci * ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings
19388c2ecf20Sopenharmony_ci * @vsi: the VSI whose rings are to be enabled
19398c2ecf20Sopenharmony_ci *
19408c2ecf20Sopenharmony_ci * Returns 0 on success and a negative value on error
19418c2ecf20Sopenharmony_ci */
19428c2ecf20Sopenharmony_ciint ice_vsi_start_all_rx_rings(struct ice_vsi *vsi)
19438c2ecf20Sopenharmony_ci{
19448c2ecf20Sopenharmony_ci	return ice_vsi_ctrl_all_rx_rings(vsi, true);
19458c2ecf20Sopenharmony_ci}
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci/**
19488c2ecf20Sopenharmony_ci * ice_vsi_stop_all_rx_rings - stop/disable all of a VSI's Rx rings
19498c2ecf20Sopenharmony_ci * @vsi: the VSI whose rings are to be disabled
19508c2ecf20Sopenharmony_ci *
19518c2ecf20Sopenharmony_ci * Returns 0 on success and a negative value on error
19528c2ecf20Sopenharmony_ci */
19538c2ecf20Sopenharmony_ciint ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi)
19548c2ecf20Sopenharmony_ci{
19558c2ecf20Sopenharmony_ci	return ice_vsi_ctrl_all_rx_rings(vsi, false);
19568c2ecf20Sopenharmony_ci}
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci/**
19598c2ecf20Sopenharmony_ci * ice_vsi_stop_tx_rings - Disable Tx rings
19608c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
19618c2ecf20Sopenharmony_ci * @rst_src: reset source
19628c2ecf20Sopenharmony_ci * @rel_vmvf_num: Relative ID of VF/VM
19638c2ecf20Sopenharmony_ci * @rings: Tx ring array to be stopped
19648c2ecf20Sopenharmony_ci * @count: number of Tx ring array elements
19658c2ecf20Sopenharmony_ci */
19668c2ecf20Sopenharmony_cistatic int
19678c2ecf20Sopenharmony_ciice_vsi_stop_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
19688c2ecf20Sopenharmony_ci		      u16 rel_vmvf_num, struct ice_ring **rings, u16 count)
19698c2ecf20Sopenharmony_ci{
19708c2ecf20Sopenharmony_ci	u16 q_idx;
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci	if (vsi->num_txq > ICE_LAN_TXQ_MAX_QDIS)
19738c2ecf20Sopenharmony_ci		return -EINVAL;
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci	for (q_idx = 0; q_idx < count; q_idx++) {
19768c2ecf20Sopenharmony_ci		struct ice_txq_meta txq_meta = { };
19778c2ecf20Sopenharmony_ci		int status;
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci		if (!rings || !rings[q_idx])
19808c2ecf20Sopenharmony_ci			return -EINVAL;
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_ci		ice_fill_txq_meta(vsi, rings[q_idx], &txq_meta);
19838c2ecf20Sopenharmony_ci		status = ice_vsi_stop_tx_ring(vsi, rst_src, rel_vmvf_num,
19848c2ecf20Sopenharmony_ci					      rings[q_idx], &txq_meta);
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci		if (status)
19878c2ecf20Sopenharmony_ci			return status;
19888c2ecf20Sopenharmony_ci	}
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci	return 0;
19918c2ecf20Sopenharmony_ci}
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci/**
19948c2ecf20Sopenharmony_ci * ice_vsi_stop_lan_tx_rings - Disable LAN Tx rings
19958c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
19968c2ecf20Sopenharmony_ci * @rst_src: reset source
19978c2ecf20Sopenharmony_ci * @rel_vmvf_num: Relative ID of VF/VM
19988c2ecf20Sopenharmony_ci */
19998c2ecf20Sopenharmony_ciint
20008c2ecf20Sopenharmony_ciice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
20018c2ecf20Sopenharmony_ci			  u16 rel_vmvf_num)
20028c2ecf20Sopenharmony_ci{
20038c2ecf20Sopenharmony_ci	return ice_vsi_stop_tx_rings(vsi, rst_src, rel_vmvf_num, vsi->tx_rings, vsi->num_txq);
20048c2ecf20Sopenharmony_ci}
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci/**
20078c2ecf20Sopenharmony_ci * ice_vsi_stop_xdp_tx_rings - Disable XDP Tx rings
20088c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
20098c2ecf20Sopenharmony_ci */
20108c2ecf20Sopenharmony_ciint ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi)
20118c2ecf20Sopenharmony_ci{
20128c2ecf20Sopenharmony_ci	return ice_vsi_stop_tx_rings(vsi, ICE_NO_RESET, 0, vsi->xdp_rings, vsi->num_xdp_txq);
20138c2ecf20Sopenharmony_ci}
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_ci/**
20168c2ecf20Sopenharmony_ci * ice_vsi_is_vlan_pruning_ena - check if VLAN pruning is enabled or not
20178c2ecf20Sopenharmony_ci * @vsi: VSI to check whether or not VLAN pruning is enabled.
20188c2ecf20Sopenharmony_ci *
20198c2ecf20Sopenharmony_ci * returns true if Rx VLAN pruning is enabled and false otherwise.
20208c2ecf20Sopenharmony_ci */
20218c2ecf20Sopenharmony_cibool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi)
20228c2ecf20Sopenharmony_ci{
20238c2ecf20Sopenharmony_ci	if (!vsi)
20248c2ecf20Sopenharmony_ci		return false;
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci	return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA);
20278c2ecf20Sopenharmony_ci}
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ci/**
20308c2ecf20Sopenharmony_ci * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
20318c2ecf20Sopenharmony_ci * @vsi: VSI to enable or disable VLAN pruning on
20328c2ecf20Sopenharmony_ci * @ena: set to true to enable VLAN pruning and false to disable it
20338c2ecf20Sopenharmony_ci * @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
20348c2ecf20Sopenharmony_ci *
20358c2ecf20Sopenharmony_ci * returns 0 if VSI is updated, negative otherwise
20368c2ecf20Sopenharmony_ci */
20378c2ecf20Sopenharmony_ciint ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
20388c2ecf20Sopenharmony_ci{
20398c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
20408c2ecf20Sopenharmony_ci	struct ice_pf *pf;
20418c2ecf20Sopenharmony_ci	int status;
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci	if (!vsi)
20448c2ecf20Sopenharmony_ci		return -EINVAL;
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci	/* Don't enable VLAN pruning if the netdev is currently in promiscuous
20478c2ecf20Sopenharmony_ci	 * mode. VLAN pruning will be enabled when the interface exits
20488c2ecf20Sopenharmony_ci	 * promiscuous mode if any VLAN filters are active.
20498c2ecf20Sopenharmony_ci	 */
20508c2ecf20Sopenharmony_ci	if (vsi->netdev && vsi->netdev->flags & IFF_PROMISC && ena)
20518c2ecf20Sopenharmony_ci		return 0;
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	pf = vsi->back;
20548c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
20558c2ecf20Sopenharmony_ci	if (!ctxt)
20568c2ecf20Sopenharmony_ci		return -ENOMEM;
20578c2ecf20Sopenharmony_ci
20588c2ecf20Sopenharmony_ci	ctxt->info = vsi->info;
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci	if (ena)
20618c2ecf20Sopenharmony_ci		ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
20628c2ecf20Sopenharmony_ci	else
20638c2ecf20Sopenharmony_ci		ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	if (!vlan_promisc)
20668c2ecf20Sopenharmony_ci		ctxt->info.valid_sections =
20678c2ecf20Sopenharmony_ci			cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci	status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL);
20708c2ecf20Sopenharmony_ci	if (status) {
20718c2ecf20Sopenharmony_ci		netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %s, aq_err = %s\n",
20728c2ecf20Sopenharmony_ci			   ena ? "En" : "Dis", vsi->idx, vsi->vsi_num,
20738c2ecf20Sopenharmony_ci			   ice_stat_str(status),
20748c2ecf20Sopenharmony_ci			   ice_aq_str(pf->hw.adminq.sq_last_status));
20758c2ecf20Sopenharmony_ci		goto err_out;
20768c2ecf20Sopenharmony_ci	}
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci	vsi->info.sw_flags2 = ctxt->info.sw_flags2;
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ci	kfree(ctxt);
20818c2ecf20Sopenharmony_ci	return 0;
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_cierr_out:
20848c2ecf20Sopenharmony_ci	kfree(ctxt);
20858c2ecf20Sopenharmony_ci	return -EIO;
20868c2ecf20Sopenharmony_ci}
20878c2ecf20Sopenharmony_ci
20888c2ecf20Sopenharmony_cistatic void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
20898c2ecf20Sopenharmony_ci{
20908c2ecf20Sopenharmony_ci	struct ice_dcbx_cfg *cfg = &vsi->port_info->qos_cfg.local_dcbx_cfg;
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg);
20938c2ecf20Sopenharmony_ci	vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg);
20948c2ecf20Sopenharmony_ci}
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci/**
20978c2ecf20Sopenharmony_ci * ice_vsi_set_q_vectors_reg_idx - set the HW register index for all q_vectors
20988c2ecf20Sopenharmony_ci * @vsi: VSI to set the q_vectors register index on
20998c2ecf20Sopenharmony_ci */
21008c2ecf20Sopenharmony_cistatic int
21018c2ecf20Sopenharmony_ciice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
21028c2ecf20Sopenharmony_ci{
21038c2ecf20Sopenharmony_ci	u16 i;
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci	if (!vsi || !vsi->q_vectors)
21068c2ecf20Sopenharmony_ci		return -EINVAL;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
21098c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ci		if (!q_vector) {
21128c2ecf20Sopenharmony_ci			dev_err(ice_pf_to_dev(vsi->back), "Failed to set reg_idx on q_vector %d VSI %d\n",
21138c2ecf20Sopenharmony_ci				i, vsi->vsi_num);
21148c2ecf20Sopenharmony_ci			goto clear_reg_idx;
21158c2ecf20Sopenharmony_ci		}
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci		if (vsi->type == ICE_VSI_VF) {
21188c2ecf20Sopenharmony_ci			struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];
21198c2ecf20Sopenharmony_ci
21208c2ecf20Sopenharmony_ci			q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
21218c2ecf20Sopenharmony_ci		} else {
21228c2ecf20Sopenharmony_ci			q_vector->reg_idx =
21238c2ecf20Sopenharmony_ci				q_vector->v_idx + vsi->base_vector;
21248c2ecf20Sopenharmony_ci		}
21258c2ecf20Sopenharmony_ci	}
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	return 0;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ciclear_reg_idx:
21308c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
21318c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci		if (q_vector)
21348c2ecf20Sopenharmony_ci			q_vector->reg_idx = 0;
21358c2ecf20Sopenharmony_ci	}
21368c2ecf20Sopenharmony_ci
21378c2ecf20Sopenharmony_ci	return -EINVAL;
21388c2ecf20Sopenharmony_ci}
21398c2ecf20Sopenharmony_ci
21408c2ecf20Sopenharmony_ci/**
21418c2ecf20Sopenharmony_ci * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
21428c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
21438c2ecf20Sopenharmony_ci * @tx: bool to determine Tx or Rx rule
21448c2ecf20Sopenharmony_ci * @create: bool to determine create or remove Rule
21458c2ecf20Sopenharmony_ci */
21468c2ecf20Sopenharmony_civoid ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create)
21478c2ecf20Sopenharmony_ci{
21488c2ecf20Sopenharmony_ci	enum ice_status (*eth_fltr)(struct ice_vsi *v, u16 type, u16 flag,
21498c2ecf20Sopenharmony_ci				    enum ice_sw_fwd_act_type act);
21508c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
21518c2ecf20Sopenharmony_ci	enum ice_status status;
21528c2ecf20Sopenharmony_ci	struct device *dev;
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
21558c2ecf20Sopenharmony_ci	eth_fltr = create ? ice_fltr_add_eth : ice_fltr_remove_eth;
21568c2ecf20Sopenharmony_ci
21578c2ecf20Sopenharmony_ci	if (tx)
21588c2ecf20Sopenharmony_ci		status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_TX,
21598c2ecf20Sopenharmony_ci				  ICE_DROP_PACKET);
21608c2ecf20Sopenharmony_ci	else
21618c2ecf20Sopenharmony_ci		status = eth_fltr(vsi, ETH_P_LLDP, ICE_FLTR_RX, ICE_FWD_TO_VSI);
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci	if (status)
21648c2ecf20Sopenharmony_ci		dev_err(dev, "Fail %s %s LLDP rule on VSI %i error: %s\n",
21658c2ecf20Sopenharmony_ci			create ? "adding" : "removing", tx ? "TX" : "RX",
21668c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
21678c2ecf20Sopenharmony_ci}
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci/**
21708c2ecf20Sopenharmony_ci * ice_vsi_setup - Set up a VSI by a given type
21718c2ecf20Sopenharmony_ci * @pf: board private structure
21728c2ecf20Sopenharmony_ci * @pi: pointer to the port_info instance
21738c2ecf20Sopenharmony_ci * @vsi_type: VSI type
21748c2ecf20Sopenharmony_ci * @vf_id: defines VF ID to which this VSI connects. This field is meant to be
21758c2ecf20Sopenharmony_ci *         used only for ICE_VSI_VF VSI type. For other VSI types, should
21768c2ecf20Sopenharmony_ci *         fill-in ICE_INVAL_VFID as input.
21778c2ecf20Sopenharmony_ci *
21788c2ecf20Sopenharmony_ci * This allocates the sw VSI structure and its queue resources.
21798c2ecf20Sopenharmony_ci *
21808c2ecf20Sopenharmony_ci * Returns pointer to the successfully allocated and configured VSI sw struct on
21818c2ecf20Sopenharmony_ci * success, NULL on failure.
21828c2ecf20Sopenharmony_ci */
21838c2ecf20Sopenharmony_cistruct ice_vsi *
21848c2ecf20Sopenharmony_ciice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
21858c2ecf20Sopenharmony_ci	      enum ice_vsi_type vsi_type, u16 vf_id)
21868c2ecf20Sopenharmony_ci{
21878c2ecf20Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
21888c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
21898c2ecf20Sopenharmony_ci	enum ice_status status;
21908c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
21918c2ecf20Sopenharmony_ci	int ret, i;
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci	if (vsi_type == ICE_VSI_VF)
21948c2ecf20Sopenharmony_ci		vsi = ice_vsi_alloc(pf, vsi_type, vf_id);
21958c2ecf20Sopenharmony_ci	else
21968c2ecf20Sopenharmony_ci		vsi = ice_vsi_alloc(pf, vsi_type, ICE_INVAL_VFID);
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci	if (!vsi) {
21998c2ecf20Sopenharmony_ci		dev_err(dev, "could not allocate VSI\n");
22008c2ecf20Sopenharmony_ci		return NULL;
22018c2ecf20Sopenharmony_ci	}
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	vsi->port_info = pi;
22048c2ecf20Sopenharmony_ci	vsi->vsw = pf->first_sw;
22058c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF)
22068c2ecf20Sopenharmony_ci		vsi->ethtype = ETH_P_PAUSE;
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
22098c2ecf20Sopenharmony_ci		vsi->vf_id = vf_id;
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ci	ice_alloc_fd_res(vsi);
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	if (ice_vsi_get_qs(vsi)) {
22148c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to allocate queues. vsi->idx = %d\n",
22158c2ecf20Sopenharmony_ci			vsi->idx);
22168c2ecf20Sopenharmony_ci		goto unroll_vsi_alloc;
22178c2ecf20Sopenharmony_ci	}
22188c2ecf20Sopenharmony_ci
22198c2ecf20Sopenharmony_ci	/* set RSS capabilities */
22208c2ecf20Sopenharmony_ci	ice_vsi_set_rss_params(vsi);
22218c2ecf20Sopenharmony_ci
22228c2ecf20Sopenharmony_ci	/* set TC configuration */
22238c2ecf20Sopenharmony_ci	ice_vsi_set_tc_cfg(vsi);
22248c2ecf20Sopenharmony_ci
22258c2ecf20Sopenharmony_ci	/* create the VSI */
22268c2ecf20Sopenharmony_ci	ret = ice_vsi_init(vsi, true);
22278c2ecf20Sopenharmony_ci	if (ret)
22288c2ecf20Sopenharmony_ci		goto unroll_get_qs;
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci	switch (vsi->type) {
22318c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
22328c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
22338c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(vsi);
22348c2ecf20Sopenharmony_ci		if (ret)
22358c2ecf20Sopenharmony_ci			goto unroll_vsi_init;
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci		ret = ice_vsi_setup_vector_base(vsi);
22388c2ecf20Sopenharmony_ci		if (ret)
22398c2ecf20Sopenharmony_ci			goto unroll_alloc_q_vector;
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
22428c2ecf20Sopenharmony_ci		if (ret)
22438c2ecf20Sopenharmony_ci			goto unroll_vector_base;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
22468c2ecf20Sopenharmony_ci		if (ret)
22478c2ecf20Sopenharmony_ci			goto unroll_vector_base;
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_ci		/* Always add VLAN ID 0 switch rule by default. This is needed
22508c2ecf20Sopenharmony_ci		 * in order to allow all untagged and 0 tagged priority traffic
22518c2ecf20Sopenharmony_ci		 * if Rx VLAN pruning is enabled. Also there are cases where we
22528c2ecf20Sopenharmony_ci		 * don't get the call to add VLAN 0 via ice_vlan_rx_add_vid()
22538c2ecf20Sopenharmony_ci		 * so this handles those cases (i.e. adding the PF to a bridge
22548c2ecf20Sopenharmony_ci		 * without the 8021q module loaded).
22558c2ecf20Sopenharmony_ci		 */
22568c2ecf20Sopenharmony_ci		ret = ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI);
22578c2ecf20Sopenharmony_ci		if (ret)
22588c2ecf20Sopenharmony_ci			goto unroll_clear_rings;
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci		ice_vsi_map_rings_to_vectors(vsi);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
22638c2ecf20Sopenharmony_ci		if (vsi->type != ICE_VSI_CTRL)
22648c2ecf20Sopenharmony_ci			/* Do not exit if configuring RSS had an issue, at
22658c2ecf20Sopenharmony_ci			 * least receive traffic on first queue. Hence no
22668c2ecf20Sopenharmony_ci			 * need to capture return value
22678c2ecf20Sopenharmony_ci			 */
22688c2ecf20Sopenharmony_ci			if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
22698c2ecf20Sopenharmony_ci				ice_vsi_cfg_rss_lut_key(vsi);
22708c2ecf20Sopenharmony_ci				ice_vsi_set_rss_flow_fld(vsi);
22718c2ecf20Sopenharmony_ci			}
22728c2ecf20Sopenharmony_ci		ice_init_arfs(vsi);
22738c2ecf20Sopenharmony_ci		break;
22748c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
22758c2ecf20Sopenharmony_ci		/* VF driver will take care of creating netdev for this type and
22768c2ecf20Sopenharmony_ci		 * map queues to vectors through Virtchnl, PF driver only
22778c2ecf20Sopenharmony_ci		 * creates a VSI and corresponding structures for bookkeeping
22788c2ecf20Sopenharmony_ci		 * purpose
22798c2ecf20Sopenharmony_ci		 */
22808c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(vsi);
22818c2ecf20Sopenharmony_ci		if (ret)
22828c2ecf20Sopenharmony_ci			goto unroll_vsi_init;
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
22858c2ecf20Sopenharmony_ci		if (ret)
22868c2ecf20Sopenharmony_ci			goto unroll_alloc_q_vector;
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_ci		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
22898c2ecf20Sopenharmony_ci		if (ret)
22908c2ecf20Sopenharmony_ci			goto unroll_vector_base;
22918c2ecf20Sopenharmony_ci
22928c2ecf20Sopenharmony_ci		/* Do not exit if configuring RSS had an issue, at least
22938c2ecf20Sopenharmony_ci		 * receive traffic on first queue. Hence no need to capture
22948c2ecf20Sopenharmony_ci		 * return value
22958c2ecf20Sopenharmony_ci		 */
22968c2ecf20Sopenharmony_ci		if (test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
22978c2ecf20Sopenharmony_ci			ice_vsi_cfg_rss_lut_key(vsi);
22988c2ecf20Sopenharmony_ci			ice_vsi_set_vf_rss_flow_fld(vsi);
22998c2ecf20Sopenharmony_ci		}
23008c2ecf20Sopenharmony_ci		break;
23018c2ecf20Sopenharmony_ci	case ICE_VSI_LB:
23028c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
23038c2ecf20Sopenharmony_ci		if (ret)
23048c2ecf20Sopenharmony_ci			goto unroll_vsi_init;
23058c2ecf20Sopenharmony_ci		break;
23068c2ecf20Sopenharmony_ci	default:
23078c2ecf20Sopenharmony_ci		/* clean up the resources and exit */
23088c2ecf20Sopenharmony_ci		goto unroll_vsi_init;
23098c2ecf20Sopenharmony_ci	}
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci	/* configure VSI nodes based on number of queues and TC's */
23128c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->tc_cfg.numtc; i++)
23138c2ecf20Sopenharmony_ci		max_txqs[i] = vsi->alloc_txq;
23148c2ecf20Sopenharmony_ci
23158c2ecf20Sopenharmony_ci	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
23168c2ecf20Sopenharmony_ci				 max_txqs);
23178c2ecf20Sopenharmony_ci	if (status) {
23188c2ecf20Sopenharmony_ci		dev_err(dev, "VSI %d failed lan queue config, error %s\n",
23198c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
23208c2ecf20Sopenharmony_ci		goto unroll_clear_rings;
23218c2ecf20Sopenharmony_ci	}
23228c2ecf20Sopenharmony_ci
23238c2ecf20Sopenharmony_ci	/* Add switch rule to drop all Tx Flow Control Frames, of look up
23248c2ecf20Sopenharmony_ci	 * type ETHERTYPE from VSIs, and restrict malicious VF from sending
23258c2ecf20Sopenharmony_ci	 * out PAUSE or PFC frames. If enabled, FW can still send FC frames.
23268c2ecf20Sopenharmony_ci	 * The rule is added once for PF VSI in order to create appropriate
23278c2ecf20Sopenharmony_ci	 * recipe, since VSI/VSI list is ignored with drop action...
23288c2ecf20Sopenharmony_ci	 * Also add rules to handle LLDP Tx packets.  Tx LLDP packets need to
23298c2ecf20Sopenharmony_ci	 * be dropped so that VFs cannot send LLDP packets to reconfig DCB
23308c2ecf20Sopenharmony_ci	 * settings in the HW.
23318c2ecf20Sopenharmony_ci	 */
23328c2ecf20Sopenharmony_ci	if (!ice_is_safe_mode(pf))
23338c2ecf20Sopenharmony_ci		if (vsi->type == ICE_VSI_PF) {
23348c2ecf20Sopenharmony_ci			ice_fltr_add_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX,
23358c2ecf20Sopenharmony_ci					 ICE_DROP_PACKET);
23368c2ecf20Sopenharmony_ci			ice_cfg_sw_lldp(vsi, true, true);
23378c2ecf20Sopenharmony_ci		}
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	return vsi;
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ciunroll_clear_rings:
23428c2ecf20Sopenharmony_ci	ice_vsi_clear_rings(vsi);
23438c2ecf20Sopenharmony_ciunroll_vector_base:
23448c2ecf20Sopenharmony_ci	/* reclaim SW interrupts back to the common pool */
23458c2ecf20Sopenharmony_ci	ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
23468c2ecf20Sopenharmony_ci	pf->num_avail_sw_msix += vsi->num_q_vectors;
23478c2ecf20Sopenharmony_ciunroll_alloc_q_vector:
23488c2ecf20Sopenharmony_ci	ice_vsi_free_q_vectors(vsi);
23498c2ecf20Sopenharmony_ciunroll_vsi_init:
23508c2ecf20Sopenharmony_ci	ice_vsi_delete(vsi);
23518c2ecf20Sopenharmony_ciunroll_get_qs:
23528c2ecf20Sopenharmony_ci	ice_vsi_put_qs(vsi);
23538c2ecf20Sopenharmony_ciunroll_vsi_alloc:
23548c2ecf20Sopenharmony_ci	ice_vsi_clear(vsi);
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci	return NULL;
23578c2ecf20Sopenharmony_ci}
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_ci/**
23608c2ecf20Sopenharmony_ci * ice_vsi_release_msix - Clear the queue to Interrupt mapping in HW
23618c2ecf20Sopenharmony_ci * @vsi: the VSI being cleaned up
23628c2ecf20Sopenharmony_ci */
23638c2ecf20Sopenharmony_cistatic void ice_vsi_release_msix(struct ice_vsi *vsi)
23648c2ecf20Sopenharmony_ci{
23658c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
23668c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
23678c2ecf20Sopenharmony_ci	u32 txq = 0;
23688c2ecf20Sopenharmony_ci	u32 rxq = 0;
23698c2ecf20Sopenharmony_ci	int i, q;
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_q_vectors; i++) {
23728c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
23738c2ecf20Sopenharmony_ci		u16 reg_idx = q_vector->reg_idx;
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci		wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0);
23768c2ecf20Sopenharmony_ci		wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0);
23778c2ecf20Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_tx; q++) {
23788c2ecf20Sopenharmony_ci			wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0);
23798c2ecf20Sopenharmony_ci			if (ice_is_xdp_ena_vsi(vsi)) {
23808c2ecf20Sopenharmony_ci				u32 xdp_txq = txq + vsi->num_xdp_txq;
23818c2ecf20Sopenharmony_ci
23828c2ecf20Sopenharmony_ci				wr32(hw, QINT_TQCTL(vsi->txq_map[xdp_txq]), 0);
23838c2ecf20Sopenharmony_ci			}
23848c2ecf20Sopenharmony_ci			txq++;
23858c2ecf20Sopenharmony_ci		}
23868c2ecf20Sopenharmony_ci
23878c2ecf20Sopenharmony_ci		for (q = 0; q < q_vector->num_ring_rx; q++) {
23888c2ecf20Sopenharmony_ci			wr32(hw, QINT_RQCTL(vsi->rxq_map[rxq]), 0);
23898c2ecf20Sopenharmony_ci			rxq++;
23908c2ecf20Sopenharmony_ci		}
23918c2ecf20Sopenharmony_ci	}
23928c2ecf20Sopenharmony_ci
23938c2ecf20Sopenharmony_ci	ice_flush(hw);
23948c2ecf20Sopenharmony_ci}
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci/**
23978c2ecf20Sopenharmony_ci * ice_vsi_free_irq - Free the IRQ association with the OS
23988c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
23998c2ecf20Sopenharmony_ci */
24008c2ecf20Sopenharmony_civoid ice_vsi_free_irq(struct ice_vsi *vsi)
24018c2ecf20Sopenharmony_ci{
24028c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
24038c2ecf20Sopenharmony_ci	int base = vsi->base_vector;
24048c2ecf20Sopenharmony_ci	int i;
24058c2ecf20Sopenharmony_ci
24068c2ecf20Sopenharmony_ci	if (!vsi->q_vectors || !vsi->irqs_ready)
24078c2ecf20Sopenharmony_ci		return;
24088c2ecf20Sopenharmony_ci
24098c2ecf20Sopenharmony_ci	ice_vsi_release_msix(vsi);
24108c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
24118c2ecf20Sopenharmony_ci		return;
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_ci	vsi->irqs_ready = false;
24148c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
24158c2ecf20Sopenharmony_ci		u16 vector = i + base;
24168c2ecf20Sopenharmony_ci		int irq_num;
24178c2ecf20Sopenharmony_ci
24188c2ecf20Sopenharmony_ci		irq_num = pf->msix_entries[vector].vector;
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci		/* free only the irqs that were actually requested */
24218c2ecf20Sopenharmony_ci		if (!vsi->q_vectors[i] ||
24228c2ecf20Sopenharmony_ci		    !(vsi->q_vectors[i]->num_ring_tx ||
24238c2ecf20Sopenharmony_ci		      vsi->q_vectors[i]->num_ring_rx))
24248c2ecf20Sopenharmony_ci			continue;
24258c2ecf20Sopenharmony_ci
24268c2ecf20Sopenharmony_ci		/* clear the affinity notifier in the IRQ descriptor */
24278c2ecf20Sopenharmony_ci		irq_set_affinity_notifier(irq_num, NULL);
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci		/* clear the affinity_mask in the IRQ descriptor */
24308c2ecf20Sopenharmony_ci		irq_set_affinity_hint(irq_num, NULL);
24318c2ecf20Sopenharmony_ci		synchronize_irq(irq_num);
24328c2ecf20Sopenharmony_ci		devm_free_irq(ice_pf_to_dev(pf), irq_num, vsi->q_vectors[i]);
24338c2ecf20Sopenharmony_ci	}
24348c2ecf20Sopenharmony_ci}
24358c2ecf20Sopenharmony_ci
24368c2ecf20Sopenharmony_ci/**
24378c2ecf20Sopenharmony_ci * ice_vsi_free_tx_rings - Free Tx resources for VSI queues
24388c2ecf20Sopenharmony_ci * @vsi: the VSI having resources freed
24398c2ecf20Sopenharmony_ci */
24408c2ecf20Sopenharmony_civoid ice_vsi_free_tx_rings(struct ice_vsi *vsi)
24418c2ecf20Sopenharmony_ci{
24428c2ecf20Sopenharmony_ci	int i;
24438c2ecf20Sopenharmony_ci
24448c2ecf20Sopenharmony_ci	if (!vsi->tx_rings)
24458c2ecf20Sopenharmony_ci		return;
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci	ice_for_each_txq(vsi, i)
24488c2ecf20Sopenharmony_ci		if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc)
24498c2ecf20Sopenharmony_ci			ice_free_tx_ring(vsi->tx_rings[i]);
24508c2ecf20Sopenharmony_ci}
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_ci/**
24538c2ecf20Sopenharmony_ci * ice_vsi_free_rx_rings - Free Rx resources for VSI queues
24548c2ecf20Sopenharmony_ci * @vsi: the VSI having resources freed
24558c2ecf20Sopenharmony_ci */
24568c2ecf20Sopenharmony_civoid ice_vsi_free_rx_rings(struct ice_vsi *vsi)
24578c2ecf20Sopenharmony_ci{
24588c2ecf20Sopenharmony_ci	int i;
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci	if (!vsi->rx_rings)
24618c2ecf20Sopenharmony_ci		return;
24628c2ecf20Sopenharmony_ci
24638c2ecf20Sopenharmony_ci	ice_for_each_rxq(vsi, i)
24648c2ecf20Sopenharmony_ci		if (vsi->rx_rings[i] && vsi->rx_rings[i]->desc)
24658c2ecf20Sopenharmony_ci			ice_free_rx_ring(vsi->rx_rings[i]);
24668c2ecf20Sopenharmony_ci}
24678c2ecf20Sopenharmony_ci
24688c2ecf20Sopenharmony_ci/**
24698c2ecf20Sopenharmony_ci * ice_vsi_close - Shut down a VSI
24708c2ecf20Sopenharmony_ci * @vsi: the VSI being shut down
24718c2ecf20Sopenharmony_ci */
24728c2ecf20Sopenharmony_civoid ice_vsi_close(struct ice_vsi *vsi)
24738c2ecf20Sopenharmony_ci{
24748c2ecf20Sopenharmony_ci	if (!test_and_set_bit(__ICE_DOWN, vsi->state))
24758c2ecf20Sopenharmony_ci		ice_down(vsi);
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_ci	ice_vsi_free_irq(vsi);
24788c2ecf20Sopenharmony_ci	ice_vsi_free_tx_rings(vsi);
24798c2ecf20Sopenharmony_ci	ice_vsi_free_rx_rings(vsi);
24808c2ecf20Sopenharmony_ci}
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ci/**
24838c2ecf20Sopenharmony_ci * ice_ena_vsi - resume a VSI
24848c2ecf20Sopenharmony_ci * @vsi: the VSI being resume
24858c2ecf20Sopenharmony_ci * @locked: is the rtnl_lock already held
24868c2ecf20Sopenharmony_ci */
24878c2ecf20Sopenharmony_ciint ice_ena_vsi(struct ice_vsi *vsi, bool locked)
24888c2ecf20Sopenharmony_ci{
24898c2ecf20Sopenharmony_ci	int err = 0;
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_NEEDS_RESTART, vsi->state))
24928c2ecf20Sopenharmony_ci		return 0;
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	clear_bit(__ICE_NEEDS_RESTART, vsi->state);
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	if (vsi->netdev && vsi->type == ICE_VSI_PF) {
24978c2ecf20Sopenharmony_ci		if (netif_running(vsi->netdev)) {
24988c2ecf20Sopenharmony_ci			if (!locked)
24998c2ecf20Sopenharmony_ci				rtnl_lock();
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci			err = ice_open_internal(vsi->netdev);
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_ci			if (!locked)
25048c2ecf20Sopenharmony_ci				rtnl_unlock();
25058c2ecf20Sopenharmony_ci		}
25068c2ecf20Sopenharmony_ci	} else if (vsi->type == ICE_VSI_CTRL) {
25078c2ecf20Sopenharmony_ci		err = ice_vsi_open_ctrl(vsi);
25088c2ecf20Sopenharmony_ci	}
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	return err;
25118c2ecf20Sopenharmony_ci}
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci/**
25148c2ecf20Sopenharmony_ci * ice_dis_vsi - pause a VSI
25158c2ecf20Sopenharmony_ci * @vsi: the VSI being paused
25168c2ecf20Sopenharmony_ci * @locked: is the rtnl_lock already held
25178c2ecf20Sopenharmony_ci */
25188c2ecf20Sopenharmony_civoid ice_dis_vsi(struct ice_vsi *vsi, bool locked)
25198c2ecf20Sopenharmony_ci{
25208c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, vsi->state))
25218c2ecf20Sopenharmony_ci		return;
25228c2ecf20Sopenharmony_ci
25238c2ecf20Sopenharmony_ci	set_bit(__ICE_NEEDS_RESTART, vsi->state);
25248c2ecf20Sopenharmony_ci
25258c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF && vsi->netdev) {
25268c2ecf20Sopenharmony_ci		if (netif_running(vsi->netdev)) {
25278c2ecf20Sopenharmony_ci			if (!locked)
25288c2ecf20Sopenharmony_ci				rtnl_lock();
25298c2ecf20Sopenharmony_ci
25308c2ecf20Sopenharmony_ci			ice_vsi_close(vsi);
25318c2ecf20Sopenharmony_ci
25328c2ecf20Sopenharmony_ci			if (!locked)
25338c2ecf20Sopenharmony_ci				rtnl_unlock();
25348c2ecf20Sopenharmony_ci		} else {
25358c2ecf20Sopenharmony_ci			ice_vsi_close(vsi);
25368c2ecf20Sopenharmony_ci		}
25378c2ecf20Sopenharmony_ci	} else if (vsi->type == ICE_VSI_CTRL) {
25388c2ecf20Sopenharmony_ci		ice_vsi_close(vsi);
25398c2ecf20Sopenharmony_ci	}
25408c2ecf20Sopenharmony_ci}
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci/**
25438c2ecf20Sopenharmony_ci * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI
25448c2ecf20Sopenharmony_ci * @vsi: the VSI being un-configured
25458c2ecf20Sopenharmony_ci */
25468c2ecf20Sopenharmony_civoid ice_vsi_dis_irq(struct ice_vsi *vsi)
25478c2ecf20Sopenharmony_ci{
25488c2ecf20Sopenharmony_ci	int base = vsi->base_vector;
25498c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
25508c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
25518c2ecf20Sopenharmony_ci	u32 val;
25528c2ecf20Sopenharmony_ci	int i;
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci	/* disable interrupt causation from each queue */
25558c2ecf20Sopenharmony_ci	if (vsi->tx_rings) {
25568c2ecf20Sopenharmony_ci		ice_for_each_txq(vsi, i) {
25578c2ecf20Sopenharmony_ci			if (vsi->tx_rings[i]) {
25588c2ecf20Sopenharmony_ci				u16 reg;
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci				reg = vsi->tx_rings[i]->reg_idx;
25618c2ecf20Sopenharmony_ci				val = rd32(hw, QINT_TQCTL(reg));
25628c2ecf20Sopenharmony_ci				val &= ~QINT_TQCTL_CAUSE_ENA_M;
25638c2ecf20Sopenharmony_ci				wr32(hw, QINT_TQCTL(reg), val);
25648c2ecf20Sopenharmony_ci			}
25658c2ecf20Sopenharmony_ci		}
25668c2ecf20Sopenharmony_ci	}
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci	if (vsi->rx_rings) {
25698c2ecf20Sopenharmony_ci		ice_for_each_rxq(vsi, i) {
25708c2ecf20Sopenharmony_ci			if (vsi->rx_rings[i]) {
25718c2ecf20Sopenharmony_ci				u16 reg;
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ci				reg = vsi->rx_rings[i]->reg_idx;
25748c2ecf20Sopenharmony_ci				val = rd32(hw, QINT_RQCTL(reg));
25758c2ecf20Sopenharmony_ci				val &= ~QINT_RQCTL_CAUSE_ENA_M;
25768c2ecf20Sopenharmony_ci				wr32(hw, QINT_RQCTL(reg), val);
25778c2ecf20Sopenharmony_ci			}
25788c2ecf20Sopenharmony_ci		}
25798c2ecf20Sopenharmony_ci	}
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci	/* disable each interrupt */
25828c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
25838c2ecf20Sopenharmony_ci		if (!vsi->q_vectors[i])
25848c2ecf20Sopenharmony_ci			continue;
25858c2ecf20Sopenharmony_ci		wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0);
25868c2ecf20Sopenharmony_ci	}
25878c2ecf20Sopenharmony_ci
25888c2ecf20Sopenharmony_ci	ice_flush(hw);
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci	/* don't call synchronize_irq() for VF's from the host */
25918c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
25928c2ecf20Sopenharmony_ci		return;
25938c2ecf20Sopenharmony_ci
25948c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i)
25958c2ecf20Sopenharmony_ci		synchronize_irq(pf->msix_entries[i + base].vector);
25968c2ecf20Sopenharmony_ci}
25978c2ecf20Sopenharmony_ci
25988c2ecf20Sopenharmony_ci/**
25998c2ecf20Sopenharmony_ci * ice_napi_del - Remove NAPI handler for the VSI
26008c2ecf20Sopenharmony_ci * @vsi: VSI for which NAPI handler is to be removed
26018c2ecf20Sopenharmony_ci */
26028c2ecf20Sopenharmony_civoid ice_napi_del(struct ice_vsi *vsi)
26038c2ecf20Sopenharmony_ci{
26048c2ecf20Sopenharmony_ci	int v_idx;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	if (!vsi->netdev)
26078c2ecf20Sopenharmony_ci		return;
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, v_idx)
26108c2ecf20Sopenharmony_ci		netif_napi_del(&vsi->q_vectors[v_idx]->napi);
26118c2ecf20Sopenharmony_ci}
26128c2ecf20Sopenharmony_ci
26138c2ecf20Sopenharmony_ci/**
26148c2ecf20Sopenharmony_ci * ice_vsi_release - Delete a VSI and free its resources
26158c2ecf20Sopenharmony_ci * @vsi: the VSI being removed
26168c2ecf20Sopenharmony_ci *
26178c2ecf20Sopenharmony_ci * Returns 0 on success or < 0 on error
26188c2ecf20Sopenharmony_ci */
26198c2ecf20Sopenharmony_ciint ice_vsi_release(struct ice_vsi *vsi)
26208c2ecf20Sopenharmony_ci{
26218c2ecf20Sopenharmony_ci	struct ice_pf *pf;
26228c2ecf20Sopenharmony_ci
26238c2ecf20Sopenharmony_ci	if (!vsi->back)
26248c2ecf20Sopenharmony_ci		return -ENODEV;
26258c2ecf20Sopenharmony_ci	pf = vsi->back;
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ci	/* do not unregister while driver is in the reset recovery pending
26288c2ecf20Sopenharmony_ci	 * state. Since reset/rebuild happens through PF service task workqueue,
26298c2ecf20Sopenharmony_ci	 * it's not a good idea to unregister netdev that is associated to the
26308c2ecf20Sopenharmony_ci	 * PF that is running the work queue items currently. This is done to
26318c2ecf20Sopenharmony_ci	 * avoid check_flush_dependency() warning on this wq
26328c2ecf20Sopenharmony_ci	 */
26338c2ecf20Sopenharmony_ci	if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) {
26348c2ecf20Sopenharmony_ci		unregister_netdev(vsi->netdev);
26358c2ecf20Sopenharmony_ci		ice_devlink_destroy_port(vsi);
26368c2ecf20Sopenharmony_ci	}
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
26398c2ecf20Sopenharmony_ci		ice_rss_clean(vsi);
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci	/* Disable VSI and free resources */
26428c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_LB)
26438c2ecf20Sopenharmony_ci		ice_vsi_dis_irq(vsi);
26448c2ecf20Sopenharmony_ci	ice_vsi_close(vsi);
26458c2ecf20Sopenharmony_ci
26468c2ecf20Sopenharmony_ci	/* SR-IOV determines needed MSIX resources all at once instead of per
26478c2ecf20Sopenharmony_ci	 * VSI since when VFs are spawned we know how many VFs there are and how
26488c2ecf20Sopenharmony_ci	 * many interrupts each VF needs. SR-IOV MSIX resources are also
26498c2ecf20Sopenharmony_ci	 * cleared in the same manner.
26508c2ecf20Sopenharmony_ci	 */
26518c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_VF) {
26528c2ecf20Sopenharmony_ci		/* reclaim SW interrupts back to the common pool */
26538c2ecf20Sopenharmony_ci		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
26548c2ecf20Sopenharmony_ci		pf->num_avail_sw_msix += vsi->num_q_vectors;
26558c2ecf20Sopenharmony_ci	}
26568c2ecf20Sopenharmony_ci
26578c2ecf20Sopenharmony_ci	if (!ice_is_safe_mode(pf)) {
26588c2ecf20Sopenharmony_ci		if (vsi->type == ICE_VSI_PF) {
26598c2ecf20Sopenharmony_ci			ice_fltr_remove_eth(vsi, ETH_P_PAUSE, ICE_FLTR_TX,
26608c2ecf20Sopenharmony_ci					    ICE_DROP_PACKET);
26618c2ecf20Sopenharmony_ci			ice_cfg_sw_lldp(vsi, true, false);
26628c2ecf20Sopenharmony_ci			/* The Rx rule will only exist to remove if the LLDP FW
26638c2ecf20Sopenharmony_ci			 * engine is currently stopped
26648c2ecf20Sopenharmony_ci			 */
26658c2ecf20Sopenharmony_ci			if (!test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
26668c2ecf20Sopenharmony_ci				ice_cfg_sw_lldp(vsi, false, false);
26678c2ecf20Sopenharmony_ci		}
26688c2ecf20Sopenharmony_ci	}
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi))
26718c2ecf20Sopenharmony_ci		ice_clear_dflt_vsi(pf->first_sw);
26728c2ecf20Sopenharmony_ci	ice_fltr_remove_all(vsi);
26738c2ecf20Sopenharmony_ci	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
26748c2ecf20Sopenharmony_ci	ice_vsi_delete(vsi);
26758c2ecf20Sopenharmony_ci	ice_vsi_free_q_vectors(vsi);
26768c2ecf20Sopenharmony_ci
26778c2ecf20Sopenharmony_ci	/* make sure unregister_netdev() was called by checking __ICE_DOWN */
26788c2ecf20Sopenharmony_ci	if (vsi->netdev && test_bit(__ICE_DOWN, vsi->state)) {
26798c2ecf20Sopenharmony_ci		free_netdev(vsi->netdev);
26808c2ecf20Sopenharmony_ci		vsi->netdev = NULL;
26818c2ecf20Sopenharmony_ci	}
26828c2ecf20Sopenharmony_ci
26838c2ecf20Sopenharmony_ci	ice_vsi_clear_rings(vsi);
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci	ice_vsi_put_qs(vsi);
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ci	/* retain SW VSI data structure since it is needed to unregister and
26888c2ecf20Sopenharmony_ci	 * free VSI netdev when PF is not in reset recovery pending state,\
26898c2ecf20Sopenharmony_ci	 * for ex: during rmmod.
26908c2ecf20Sopenharmony_ci	 */
26918c2ecf20Sopenharmony_ci	if (!ice_is_reset_in_progress(pf->state))
26928c2ecf20Sopenharmony_ci		ice_vsi_clear(vsi);
26938c2ecf20Sopenharmony_ci
26948c2ecf20Sopenharmony_ci	return 0;
26958c2ecf20Sopenharmony_ci}
26968c2ecf20Sopenharmony_ci
26978c2ecf20Sopenharmony_ci/**
26988c2ecf20Sopenharmony_ci * ice_vsi_rebuild_update_coalesce_intrl - set interrupt rate limit for a q_vector
26998c2ecf20Sopenharmony_ci * @q_vector: pointer to q_vector which is being updated
27008c2ecf20Sopenharmony_ci * @stored_intrl_setting: original INTRL setting
27018c2ecf20Sopenharmony_ci *
27028c2ecf20Sopenharmony_ci * Set coalesce param in q_vector and update these parameters in HW.
27038c2ecf20Sopenharmony_ci */
27048c2ecf20Sopenharmony_cistatic void
27058c2ecf20Sopenharmony_ciice_vsi_rebuild_update_coalesce_intrl(struct ice_q_vector *q_vector,
27068c2ecf20Sopenharmony_ci				      u16 stored_intrl_setting)
27078c2ecf20Sopenharmony_ci{
27088c2ecf20Sopenharmony_ci	struct ice_hw *hw = &q_vector->vsi->back->hw;
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ci	q_vector->intrl = stored_intrl_setting;
27118c2ecf20Sopenharmony_ci	wr32(hw, GLINT_RATE(q_vector->reg_idx),
27128c2ecf20Sopenharmony_ci	     ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
27138c2ecf20Sopenharmony_ci}
27148c2ecf20Sopenharmony_ci
27158c2ecf20Sopenharmony_ci/**
27168c2ecf20Sopenharmony_ci * ice_vsi_rebuild_update_coalesce_itr - set coalesce for a q_vector
27178c2ecf20Sopenharmony_ci * @q_vector: pointer to q_vector which is being updated
27188c2ecf20Sopenharmony_ci * @rc: pointer to ring container
27198c2ecf20Sopenharmony_ci * @stored_itr_setting: original ITR setting
27208c2ecf20Sopenharmony_ci *
27218c2ecf20Sopenharmony_ci * Set coalesce param in q_vector and update these parameters in HW.
27228c2ecf20Sopenharmony_ci */
27238c2ecf20Sopenharmony_cistatic void
27248c2ecf20Sopenharmony_ciice_vsi_rebuild_update_coalesce_itr(struct ice_q_vector *q_vector,
27258c2ecf20Sopenharmony_ci				    struct ice_ring_container *rc,
27268c2ecf20Sopenharmony_ci				    u16 stored_itr_setting)
27278c2ecf20Sopenharmony_ci{
27288c2ecf20Sopenharmony_ci	struct ice_hw *hw = &q_vector->vsi->back->hw;
27298c2ecf20Sopenharmony_ci
27308c2ecf20Sopenharmony_ci	rc->itr_setting = stored_itr_setting;
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci	/* dynamic ITR values will be updated during Tx/Rx */
27338c2ecf20Sopenharmony_ci	if (!ITR_IS_DYNAMIC(rc->itr_setting))
27348c2ecf20Sopenharmony_ci		wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx),
27358c2ecf20Sopenharmony_ci		     ITR_REG_ALIGN(rc->itr_setting) >> ICE_ITR_GRAN_S);
27368c2ecf20Sopenharmony_ci}
27378c2ecf20Sopenharmony_ci
27388c2ecf20Sopenharmony_ci/**
27398c2ecf20Sopenharmony_ci * ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
27408c2ecf20Sopenharmony_ci * @vsi: VSI connected with q_vectors
27418c2ecf20Sopenharmony_ci * @coalesce: array of struct with stored coalesce
27428c2ecf20Sopenharmony_ci *
27438c2ecf20Sopenharmony_ci * Returns array size.
27448c2ecf20Sopenharmony_ci */
27458c2ecf20Sopenharmony_cistatic int
27468c2ecf20Sopenharmony_ciice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
27478c2ecf20Sopenharmony_ci			     struct ice_coalesce_stored *coalesce)
27488c2ecf20Sopenharmony_ci{
27498c2ecf20Sopenharmony_ci	int i;
27508c2ecf20Sopenharmony_ci
27518c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i) {
27528c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[i];
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci		coalesce[i].itr_tx = q_vector->tx.itr_setting;
27558c2ecf20Sopenharmony_ci		coalesce[i].itr_rx = q_vector->rx.itr_setting;
27568c2ecf20Sopenharmony_ci		coalesce[i].intrl = q_vector->intrl;
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ci		if (i < vsi->num_txq)
27598c2ecf20Sopenharmony_ci			coalesce[i].tx_valid = true;
27608c2ecf20Sopenharmony_ci		if (i < vsi->num_rxq)
27618c2ecf20Sopenharmony_ci			coalesce[i].rx_valid = true;
27628c2ecf20Sopenharmony_ci	}
27638c2ecf20Sopenharmony_ci
27648c2ecf20Sopenharmony_ci	return vsi->num_q_vectors;
27658c2ecf20Sopenharmony_ci}
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci/**
27688c2ecf20Sopenharmony_ci * ice_vsi_rebuild_set_coalesce - set coalesce from earlier saved arrays
27698c2ecf20Sopenharmony_ci * @vsi: VSI connected with q_vectors
27708c2ecf20Sopenharmony_ci * @coalesce: pointer to array of struct with stored coalesce
27718c2ecf20Sopenharmony_ci * @size: size of coalesce array
27728c2ecf20Sopenharmony_ci *
27738c2ecf20Sopenharmony_ci * Before this function, ice_vsi_rebuild_get_coalesce should be called to save
27748c2ecf20Sopenharmony_ci * ITR params in arrays. If size is 0 or coalesce wasn't stored set coalesce
27758c2ecf20Sopenharmony_ci * to default value.
27768c2ecf20Sopenharmony_ci */
27778c2ecf20Sopenharmony_cistatic void
27788c2ecf20Sopenharmony_ciice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
27798c2ecf20Sopenharmony_ci			     struct ice_coalesce_stored *coalesce, int size)
27808c2ecf20Sopenharmony_ci{
27818c2ecf20Sopenharmony_ci	int i;
27828c2ecf20Sopenharmony_ci
27838c2ecf20Sopenharmony_ci	if ((size && !coalesce) || !vsi)
27848c2ecf20Sopenharmony_ci		return;
27858c2ecf20Sopenharmony_ci
27868c2ecf20Sopenharmony_ci	/* There are a couple of cases that have to be handled here:
27878c2ecf20Sopenharmony_ci	 *   1. The case where the number of queue vectors stays the same, but
27888c2ecf20Sopenharmony_ci	 *      the number of Tx or Rx rings changes (the first for loop)
27898c2ecf20Sopenharmony_ci	 *   2. The case where the number of queue vectors increased (the
27908c2ecf20Sopenharmony_ci	 *      second for loop)
27918c2ecf20Sopenharmony_ci	 */
27928c2ecf20Sopenharmony_ci	for (i = 0; i < size && i < vsi->num_q_vectors; i++) {
27938c2ecf20Sopenharmony_ci		/* There are 2 cases to handle here and they are the same for
27948c2ecf20Sopenharmony_ci		 * both Tx and Rx:
27958c2ecf20Sopenharmony_ci		 *   if the entry was valid previously (coalesce[i].[tr]x_valid
27968c2ecf20Sopenharmony_ci		 *   and the loop variable is less than the number of rings
27978c2ecf20Sopenharmony_ci		 *   allocated, then write the previous values
27988c2ecf20Sopenharmony_ci		 *
27998c2ecf20Sopenharmony_ci		 *   if the entry was not valid previously, but the number of
28008c2ecf20Sopenharmony_ci		 *   rings is less than are allocated (this means the number of
28018c2ecf20Sopenharmony_ci		 *   rings increased from previously), then write out the
28028c2ecf20Sopenharmony_ci		 *   values in the first element
28038c2ecf20Sopenharmony_ci		 */
28048c2ecf20Sopenharmony_ci		if (i < vsi->alloc_rxq && coalesce[i].rx_valid)
28058c2ecf20Sopenharmony_ci			ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
28068c2ecf20Sopenharmony_ci							    &vsi->q_vectors[i]->rx,
28078c2ecf20Sopenharmony_ci							    coalesce[i].itr_rx);
28088c2ecf20Sopenharmony_ci		else if (i < vsi->alloc_rxq)
28098c2ecf20Sopenharmony_ci			ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
28108c2ecf20Sopenharmony_ci							    &vsi->q_vectors[i]->rx,
28118c2ecf20Sopenharmony_ci							    coalesce[0].itr_rx);
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_ci		if (i < vsi->alloc_txq && coalesce[i].tx_valid)
28148c2ecf20Sopenharmony_ci			ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
28158c2ecf20Sopenharmony_ci							    &vsi->q_vectors[i]->tx,
28168c2ecf20Sopenharmony_ci							    coalesce[i].itr_tx);
28178c2ecf20Sopenharmony_ci		else if (i < vsi->alloc_txq)
28188c2ecf20Sopenharmony_ci			ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
28198c2ecf20Sopenharmony_ci							    &vsi->q_vectors[i]->tx,
28208c2ecf20Sopenharmony_ci							    coalesce[0].itr_tx);
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_ci		ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i],
28238c2ecf20Sopenharmony_ci						      coalesce[i].intrl);
28248c2ecf20Sopenharmony_ci	}
28258c2ecf20Sopenharmony_ci
28268c2ecf20Sopenharmony_ci	/* the number of queue vectors increased so write whatever is in
28278c2ecf20Sopenharmony_ci	 * the first element
28288c2ecf20Sopenharmony_ci	 */
28298c2ecf20Sopenharmony_ci	for (; i < vsi->num_q_vectors; i++) {
28308c2ecf20Sopenharmony_ci		ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
28318c2ecf20Sopenharmony_ci						    &vsi->q_vectors[i]->tx,
28328c2ecf20Sopenharmony_ci						    coalesce[0].itr_tx);
28338c2ecf20Sopenharmony_ci		ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
28348c2ecf20Sopenharmony_ci						    &vsi->q_vectors[i]->rx,
28358c2ecf20Sopenharmony_ci						    coalesce[0].itr_rx);
28368c2ecf20Sopenharmony_ci		ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i],
28378c2ecf20Sopenharmony_ci						      coalesce[0].intrl);
28388c2ecf20Sopenharmony_ci	}
28398c2ecf20Sopenharmony_ci}
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci/**
28428c2ecf20Sopenharmony_ci * ice_vsi_rebuild - Rebuild VSI after reset
28438c2ecf20Sopenharmony_ci * @vsi: VSI to be rebuild
28448c2ecf20Sopenharmony_ci * @init_vsi: is this an initialization or a reconfigure of the VSI
28458c2ecf20Sopenharmony_ci *
28468c2ecf20Sopenharmony_ci * Returns 0 on success and negative value on failure
28478c2ecf20Sopenharmony_ci */
28488c2ecf20Sopenharmony_ciint ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
28498c2ecf20Sopenharmony_ci{
28508c2ecf20Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
28518c2ecf20Sopenharmony_ci	struct ice_coalesce_stored *coalesce;
28528c2ecf20Sopenharmony_ci	int prev_num_q_vectors = 0;
28538c2ecf20Sopenharmony_ci	struct ice_vf *vf = NULL;
28548c2ecf20Sopenharmony_ci	enum ice_status status;
28558c2ecf20Sopenharmony_ci	struct ice_pf *pf;
28568c2ecf20Sopenharmony_ci	int ret, i;
28578c2ecf20Sopenharmony_ci
28588c2ecf20Sopenharmony_ci	if (!vsi)
28598c2ecf20Sopenharmony_ci		return -EINVAL;
28608c2ecf20Sopenharmony_ci
28618c2ecf20Sopenharmony_ci	pf = vsi->back;
28628c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
28638c2ecf20Sopenharmony_ci		vf = &pf->vf[vsi->vf_id];
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci	coalesce = kcalloc(vsi->num_q_vectors,
28668c2ecf20Sopenharmony_ci			   sizeof(struct ice_coalesce_stored), GFP_KERNEL);
28678c2ecf20Sopenharmony_ci	if (!coalesce)
28688c2ecf20Sopenharmony_ci		return -ENOMEM;
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci	prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
28718c2ecf20Sopenharmony_ci
28728c2ecf20Sopenharmony_ci	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
28738c2ecf20Sopenharmony_ci	ice_vsi_free_q_vectors(vsi);
28748c2ecf20Sopenharmony_ci
28758c2ecf20Sopenharmony_ci	/* SR-IOV determines needed MSIX resources all at once instead of per
28768c2ecf20Sopenharmony_ci	 * VSI since when VFs are spawned we know how many VFs there are and how
28778c2ecf20Sopenharmony_ci	 * many interrupts each VF needs. SR-IOV MSIX resources are also
28788c2ecf20Sopenharmony_ci	 * cleared in the same manner.
28798c2ecf20Sopenharmony_ci	 */
28808c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_VF) {
28818c2ecf20Sopenharmony_ci		/* reclaim SW interrupts back to the common pool */
28828c2ecf20Sopenharmony_ci		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
28838c2ecf20Sopenharmony_ci		pf->num_avail_sw_msix += vsi->num_q_vectors;
28848c2ecf20Sopenharmony_ci		vsi->base_vector = 0;
28858c2ecf20Sopenharmony_ci	}
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	if (ice_is_xdp_ena_vsi(vsi))
28888c2ecf20Sopenharmony_ci		/* return value check can be skipped here, it always returns
28898c2ecf20Sopenharmony_ci		 * 0 if reset is in progress
28908c2ecf20Sopenharmony_ci		 */
28918c2ecf20Sopenharmony_ci		ice_destroy_xdp_rings(vsi);
28928c2ecf20Sopenharmony_ci	ice_vsi_put_qs(vsi);
28938c2ecf20Sopenharmony_ci	ice_vsi_clear_rings(vsi);
28948c2ecf20Sopenharmony_ci	ice_vsi_free_arrays(vsi);
28958c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_VF)
28968c2ecf20Sopenharmony_ci		ice_vsi_set_num_qs(vsi, vf->vf_id);
28978c2ecf20Sopenharmony_ci	else
28988c2ecf20Sopenharmony_ci		ice_vsi_set_num_qs(vsi, ICE_INVAL_VFID);
28998c2ecf20Sopenharmony_ci
29008c2ecf20Sopenharmony_ci	ret = ice_vsi_alloc_arrays(vsi);
29018c2ecf20Sopenharmony_ci	if (ret < 0)
29028c2ecf20Sopenharmony_ci		goto err_vsi;
29038c2ecf20Sopenharmony_ci
29048c2ecf20Sopenharmony_ci	ice_vsi_get_qs(vsi);
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	ice_alloc_fd_res(vsi);
29078c2ecf20Sopenharmony_ci	ice_vsi_set_tc_cfg(vsi);
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	/* Initialize VSI struct elements and create VSI in FW */
29108c2ecf20Sopenharmony_ci	ret = ice_vsi_init(vsi, init_vsi);
29118c2ecf20Sopenharmony_ci	if (ret < 0)
29128c2ecf20Sopenharmony_ci		goto err_vsi;
29138c2ecf20Sopenharmony_ci
29148c2ecf20Sopenharmony_ci	switch (vsi->type) {
29158c2ecf20Sopenharmony_ci	case ICE_VSI_CTRL:
29168c2ecf20Sopenharmony_ci	case ICE_VSI_PF:
29178c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(vsi);
29188c2ecf20Sopenharmony_ci		if (ret)
29198c2ecf20Sopenharmony_ci			goto err_rings;
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci		ret = ice_vsi_setup_vector_base(vsi);
29228c2ecf20Sopenharmony_ci		if (ret)
29238c2ecf20Sopenharmony_ci			goto err_vectors;
29248c2ecf20Sopenharmony_ci
29258c2ecf20Sopenharmony_ci		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
29268c2ecf20Sopenharmony_ci		if (ret)
29278c2ecf20Sopenharmony_ci			goto err_vectors;
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
29308c2ecf20Sopenharmony_ci		if (ret)
29318c2ecf20Sopenharmony_ci			goto err_vectors;
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci		ice_vsi_map_rings_to_vectors(vsi);
29348c2ecf20Sopenharmony_ci		if (ice_is_xdp_ena_vsi(vsi)) {
29358c2ecf20Sopenharmony_ci			vsi->num_xdp_txq = vsi->alloc_rxq;
29368c2ecf20Sopenharmony_ci			ret = ice_prepare_xdp_rings(vsi, vsi->xdp_prog);
29378c2ecf20Sopenharmony_ci			if (ret)
29388c2ecf20Sopenharmony_ci				goto err_vectors;
29398c2ecf20Sopenharmony_ci		}
29408c2ecf20Sopenharmony_ci		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
29418c2ecf20Sopenharmony_ci		if (vsi->type != ICE_VSI_CTRL)
29428c2ecf20Sopenharmony_ci			/* Do not exit if configuring RSS had an issue, at
29438c2ecf20Sopenharmony_ci			 * least receive traffic on first queue. Hence no
29448c2ecf20Sopenharmony_ci			 * need to capture return value
29458c2ecf20Sopenharmony_ci			 */
29468c2ecf20Sopenharmony_ci			if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
29478c2ecf20Sopenharmony_ci				ice_vsi_cfg_rss_lut_key(vsi);
29488c2ecf20Sopenharmony_ci		break;
29498c2ecf20Sopenharmony_ci	case ICE_VSI_VF:
29508c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(vsi);
29518c2ecf20Sopenharmony_ci		if (ret)
29528c2ecf20Sopenharmony_ci			goto err_rings;
29538c2ecf20Sopenharmony_ci
29548c2ecf20Sopenharmony_ci		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
29558c2ecf20Sopenharmony_ci		if (ret)
29568c2ecf20Sopenharmony_ci			goto err_vectors;
29578c2ecf20Sopenharmony_ci
29588c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_rings(vsi);
29598c2ecf20Sopenharmony_ci		if (ret)
29608c2ecf20Sopenharmony_ci			goto err_vectors;
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci		break;
29638c2ecf20Sopenharmony_ci	default:
29648c2ecf20Sopenharmony_ci		break;
29658c2ecf20Sopenharmony_ci	}
29668c2ecf20Sopenharmony_ci
29678c2ecf20Sopenharmony_ci	/* configure VSI nodes based on number of queues and TC's */
29688c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->tc_cfg.numtc; i++) {
29698c2ecf20Sopenharmony_ci		max_txqs[i] = vsi->alloc_txq;
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci		if (ice_is_xdp_ena_vsi(vsi))
29728c2ecf20Sopenharmony_ci			max_txqs[i] += vsi->num_xdp_txq;
29738c2ecf20Sopenharmony_ci	}
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_ci	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
29768c2ecf20Sopenharmony_ci				 max_txqs);
29778c2ecf20Sopenharmony_ci	if (status) {
29788c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "VSI %d failed lan queue config, error %s\n",
29798c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
29808c2ecf20Sopenharmony_ci		if (init_vsi) {
29818c2ecf20Sopenharmony_ci			ret = -EIO;
29828c2ecf20Sopenharmony_ci			goto err_vectors;
29838c2ecf20Sopenharmony_ci		} else {
29848c2ecf20Sopenharmony_ci			return ice_schedule_reset(pf, ICE_RESET_PFR);
29858c2ecf20Sopenharmony_ci		}
29868c2ecf20Sopenharmony_ci	}
29878c2ecf20Sopenharmony_ci	ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors);
29888c2ecf20Sopenharmony_ci	kfree(coalesce);
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci	return 0;
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_cierr_vectors:
29938c2ecf20Sopenharmony_ci	ice_vsi_free_q_vectors(vsi);
29948c2ecf20Sopenharmony_cierr_rings:
29958c2ecf20Sopenharmony_ci	if (vsi->netdev) {
29968c2ecf20Sopenharmony_ci		vsi->current_netdev_flags = 0;
29978c2ecf20Sopenharmony_ci		unregister_netdev(vsi->netdev);
29988c2ecf20Sopenharmony_ci		free_netdev(vsi->netdev);
29998c2ecf20Sopenharmony_ci		vsi->netdev = NULL;
30008c2ecf20Sopenharmony_ci	}
30018c2ecf20Sopenharmony_cierr_vsi:
30028c2ecf20Sopenharmony_ci	ice_vsi_clear(vsi);
30038c2ecf20Sopenharmony_ci	set_bit(__ICE_RESET_FAILED, pf->state);
30048c2ecf20Sopenharmony_ci	kfree(coalesce);
30058c2ecf20Sopenharmony_ci	return ret;
30068c2ecf20Sopenharmony_ci}
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_ci/**
30098c2ecf20Sopenharmony_ci * ice_is_reset_in_progress - check for a reset in progress
30108c2ecf20Sopenharmony_ci * @state: PF state field
30118c2ecf20Sopenharmony_ci */
30128c2ecf20Sopenharmony_cibool ice_is_reset_in_progress(unsigned long *state)
30138c2ecf20Sopenharmony_ci{
30148c2ecf20Sopenharmony_ci	return test_bit(__ICE_RESET_OICR_RECV, state) ||
30158c2ecf20Sopenharmony_ci	       test_bit(__ICE_PFR_REQ, state) ||
30168c2ecf20Sopenharmony_ci	       test_bit(__ICE_CORER_REQ, state) ||
30178c2ecf20Sopenharmony_ci	       test_bit(__ICE_GLOBR_REQ, state);
30188c2ecf20Sopenharmony_ci}
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci#ifdef CONFIG_DCB
30218c2ecf20Sopenharmony_ci/**
30228c2ecf20Sopenharmony_ci * ice_vsi_update_q_map - update our copy of the VSI info with new queue map
30238c2ecf20Sopenharmony_ci * @vsi: VSI being configured
30248c2ecf20Sopenharmony_ci * @ctx: the context buffer returned from AQ VSI update command
30258c2ecf20Sopenharmony_ci */
30268c2ecf20Sopenharmony_cistatic void ice_vsi_update_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctx)
30278c2ecf20Sopenharmony_ci{
30288c2ecf20Sopenharmony_ci	vsi->info.mapping_flags = ctx->info.mapping_flags;
30298c2ecf20Sopenharmony_ci	memcpy(&vsi->info.q_mapping, &ctx->info.q_mapping,
30308c2ecf20Sopenharmony_ci	       sizeof(vsi->info.q_mapping));
30318c2ecf20Sopenharmony_ci	memcpy(&vsi->info.tc_mapping, ctx->info.tc_mapping,
30328c2ecf20Sopenharmony_ci	       sizeof(vsi->info.tc_mapping));
30338c2ecf20Sopenharmony_ci}
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci/**
30368c2ecf20Sopenharmony_ci * ice_vsi_cfg_tc - Configure VSI Tx Sched for given TC map
30378c2ecf20Sopenharmony_ci * @vsi: VSI to be configured
30388c2ecf20Sopenharmony_ci * @ena_tc: TC bitmap
30398c2ecf20Sopenharmony_ci *
30408c2ecf20Sopenharmony_ci * VSI queues expected to be quiesced before calling this function
30418c2ecf20Sopenharmony_ci */
30428c2ecf20Sopenharmony_ciint ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
30438c2ecf20Sopenharmony_ci{
30448c2ecf20Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
30458c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
30468c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctx;
30478c2ecf20Sopenharmony_ci	enum ice_status status;
30488c2ecf20Sopenharmony_ci	struct device *dev;
30498c2ecf20Sopenharmony_ci	int i, ret = 0;
30508c2ecf20Sopenharmony_ci	u8 num_tc = 0;
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci	ice_for_each_traffic_class(i) {
30558c2ecf20Sopenharmony_ci		/* build bitmap of enabled TCs */
30568c2ecf20Sopenharmony_ci		if (ena_tc & BIT(i))
30578c2ecf20Sopenharmony_ci			num_tc++;
30588c2ecf20Sopenharmony_ci		/* populate max_txqs per TC */
30598c2ecf20Sopenharmony_ci		max_txqs[i] = vsi->alloc_txq;
30608c2ecf20Sopenharmony_ci	}
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	vsi->tc_cfg.ena_tc = ena_tc;
30638c2ecf20Sopenharmony_ci	vsi->tc_cfg.numtc = num_tc;
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_ci	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
30668c2ecf20Sopenharmony_ci	if (!ctx)
30678c2ecf20Sopenharmony_ci		return -ENOMEM;
30688c2ecf20Sopenharmony_ci
30698c2ecf20Sopenharmony_ci	ctx->vf_num = 0;
30708c2ecf20Sopenharmony_ci	ctx->info = vsi->info;
30718c2ecf20Sopenharmony_ci
30728c2ecf20Sopenharmony_ci	ice_vsi_setup_q_map(vsi, ctx);
30738c2ecf20Sopenharmony_ci
30748c2ecf20Sopenharmony_ci	/* must to indicate which section of VSI context are being modified */
30758c2ecf20Sopenharmony_ci	ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_RXQ_MAP_VALID);
30768c2ecf20Sopenharmony_ci	status = ice_update_vsi(&pf->hw, vsi->idx, ctx, NULL);
30778c2ecf20Sopenharmony_ci	if (status) {
30788c2ecf20Sopenharmony_ci		dev_info(dev, "Failed VSI Update\n");
30798c2ecf20Sopenharmony_ci		ret = -EIO;
30808c2ecf20Sopenharmony_ci		goto out;
30818c2ecf20Sopenharmony_ci	}
30828c2ecf20Sopenharmony_ci
30838c2ecf20Sopenharmony_ci	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
30848c2ecf20Sopenharmony_ci				 max_txqs);
30858c2ecf20Sopenharmony_ci
30868c2ecf20Sopenharmony_ci	if (status) {
30878c2ecf20Sopenharmony_ci		dev_err(dev, "VSI %d failed TC config, error %s\n",
30888c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
30898c2ecf20Sopenharmony_ci		ret = -EIO;
30908c2ecf20Sopenharmony_ci		goto out;
30918c2ecf20Sopenharmony_ci	}
30928c2ecf20Sopenharmony_ci	ice_vsi_update_q_map(vsi, ctx);
30938c2ecf20Sopenharmony_ci	vsi->info.valid_sections = 0;
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci	ice_vsi_cfg_netdev_tc(vsi, ena_tc);
30968c2ecf20Sopenharmony_ciout:
30978c2ecf20Sopenharmony_ci	kfree(ctx);
30988c2ecf20Sopenharmony_ci	return ret;
30998c2ecf20Sopenharmony_ci}
31008c2ecf20Sopenharmony_ci#endif /* CONFIG_DCB */
31018c2ecf20Sopenharmony_ci
31028c2ecf20Sopenharmony_ci/**
31038c2ecf20Sopenharmony_ci * ice_update_ring_stats - Update ring statistics
31048c2ecf20Sopenharmony_ci * @ring: ring to update
31058c2ecf20Sopenharmony_ci * @cont: used to increment per-vector counters
31068c2ecf20Sopenharmony_ci * @pkts: number of processed packets
31078c2ecf20Sopenharmony_ci * @bytes: number of processed bytes
31088c2ecf20Sopenharmony_ci *
31098c2ecf20Sopenharmony_ci * This function assumes that caller has acquired a u64_stats_sync lock.
31108c2ecf20Sopenharmony_ci */
31118c2ecf20Sopenharmony_cistatic void
31128c2ecf20Sopenharmony_ciice_update_ring_stats(struct ice_ring *ring, struct ice_ring_container *cont,
31138c2ecf20Sopenharmony_ci		      u64 pkts, u64 bytes)
31148c2ecf20Sopenharmony_ci{
31158c2ecf20Sopenharmony_ci	ring->stats.bytes += bytes;
31168c2ecf20Sopenharmony_ci	ring->stats.pkts += pkts;
31178c2ecf20Sopenharmony_ci	cont->total_bytes += bytes;
31188c2ecf20Sopenharmony_ci	cont->total_pkts += pkts;
31198c2ecf20Sopenharmony_ci}
31208c2ecf20Sopenharmony_ci
31218c2ecf20Sopenharmony_ci/**
31228c2ecf20Sopenharmony_ci * ice_update_tx_ring_stats - Update Tx ring specific counters
31238c2ecf20Sopenharmony_ci * @tx_ring: ring to update
31248c2ecf20Sopenharmony_ci * @pkts: number of processed packets
31258c2ecf20Sopenharmony_ci * @bytes: number of processed bytes
31268c2ecf20Sopenharmony_ci */
31278c2ecf20Sopenharmony_civoid ice_update_tx_ring_stats(struct ice_ring *tx_ring, u64 pkts, u64 bytes)
31288c2ecf20Sopenharmony_ci{
31298c2ecf20Sopenharmony_ci	u64_stats_update_begin(&tx_ring->syncp);
31308c2ecf20Sopenharmony_ci	ice_update_ring_stats(tx_ring, &tx_ring->q_vector->tx, pkts, bytes);
31318c2ecf20Sopenharmony_ci	u64_stats_update_end(&tx_ring->syncp);
31328c2ecf20Sopenharmony_ci}
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci/**
31358c2ecf20Sopenharmony_ci * ice_update_rx_ring_stats - Update Rx ring specific counters
31368c2ecf20Sopenharmony_ci * @rx_ring: ring to update
31378c2ecf20Sopenharmony_ci * @pkts: number of processed packets
31388c2ecf20Sopenharmony_ci * @bytes: number of processed bytes
31398c2ecf20Sopenharmony_ci */
31408c2ecf20Sopenharmony_civoid ice_update_rx_ring_stats(struct ice_ring *rx_ring, u64 pkts, u64 bytes)
31418c2ecf20Sopenharmony_ci{
31428c2ecf20Sopenharmony_ci	u64_stats_update_begin(&rx_ring->syncp);
31438c2ecf20Sopenharmony_ci	ice_update_ring_stats(rx_ring, &rx_ring->q_vector->rx, pkts, bytes);
31448c2ecf20Sopenharmony_ci	u64_stats_update_end(&rx_ring->syncp);
31458c2ecf20Sopenharmony_ci}
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_ci/**
31488c2ecf20Sopenharmony_ci * ice_status_to_errno - convert from enum ice_status to Linux errno
31498c2ecf20Sopenharmony_ci * @err: ice_status value to convert
31508c2ecf20Sopenharmony_ci */
31518c2ecf20Sopenharmony_ciint ice_status_to_errno(enum ice_status err)
31528c2ecf20Sopenharmony_ci{
31538c2ecf20Sopenharmony_ci	switch (err) {
31548c2ecf20Sopenharmony_ci	case ICE_SUCCESS:
31558c2ecf20Sopenharmony_ci		return 0;
31568c2ecf20Sopenharmony_ci	case ICE_ERR_DOES_NOT_EXIST:
31578c2ecf20Sopenharmony_ci		return -ENOENT;
31588c2ecf20Sopenharmony_ci	case ICE_ERR_OUT_OF_RANGE:
31598c2ecf20Sopenharmony_ci		return -ENOTTY;
31608c2ecf20Sopenharmony_ci	case ICE_ERR_PARAM:
31618c2ecf20Sopenharmony_ci		return -EINVAL;
31628c2ecf20Sopenharmony_ci	case ICE_ERR_NO_MEMORY:
31638c2ecf20Sopenharmony_ci		return -ENOMEM;
31648c2ecf20Sopenharmony_ci	case ICE_ERR_MAX_LIMIT:
31658c2ecf20Sopenharmony_ci		return -EAGAIN;
31668c2ecf20Sopenharmony_ci	default:
31678c2ecf20Sopenharmony_ci		return -EINVAL;
31688c2ecf20Sopenharmony_ci	}
31698c2ecf20Sopenharmony_ci}
31708c2ecf20Sopenharmony_ci
31718c2ecf20Sopenharmony_ci/**
31728c2ecf20Sopenharmony_ci * ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
31738c2ecf20Sopenharmony_ci * @sw: switch to check if its default forwarding VSI is free
31748c2ecf20Sopenharmony_ci *
31758c2ecf20Sopenharmony_ci * Return true if the default forwarding VSI is already being used, else returns
31768c2ecf20Sopenharmony_ci * false signalling that it's available to use.
31778c2ecf20Sopenharmony_ci */
31788c2ecf20Sopenharmony_cibool ice_is_dflt_vsi_in_use(struct ice_sw *sw)
31798c2ecf20Sopenharmony_ci{
31808c2ecf20Sopenharmony_ci	return (sw->dflt_vsi && sw->dflt_vsi_ena);
31818c2ecf20Sopenharmony_ci}
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci/**
31848c2ecf20Sopenharmony_ci * ice_is_vsi_dflt_vsi - check if the VSI passed in is the default VSI
31858c2ecf20Sopenharmony_ci * @sw: switch for the default forwarding VSI to compare against
31868c2ecf20Sopenharmony_ci * @vsi: VSI to compare against default forwarding VSI
31878c2ecf20Sopenharmony_ci *
31888c2ecf20Sopenharmony_ci * If this VSI passed in is the default forwarding VSI then return true, else
31898c2ecf20Sopenharmony_ci * return false
31908c2ecf20Sopenharmony_ci */
31918c2ecf20Sopenharmony_cibool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
31928c2ecf20Sopenharmony_ci{
31938c2ecf20Sopenharmony_ci	return (sw->dflt_vsi == vsi && sw->dflt_vsi_ena);
31948c2ecf20Sopenharmony_ci}
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_ci/**
31978c2ecf20Sopenharmony_ci * ice_set_dflt_vsi - set the default forwarding VSI
31988c2ecf20Sopenharmony_ci * @sw: switch used to assign the default forwarding VSI
31998c2ecf20Sopenharmony_ci * @vsi: VSI getting set as the default forwarding VSI on the switch
32008c2ecf20Sopenharmony_ci *
32018c2ecf20Sopenharmony_ci * If the VSI passed in is already the default VSI and it's enabled just return
32028c2ecf20Sopenharmony_ci * success.
32038c2ecf20Sopenharmony_ci *
32048c2ecf20Sopenharmony_ci * If there is already a default VSI on the switch and it's enabled then return
32058c2ecf20Sopenharmony_ci * -EEXIST since there can only be one default VSI per switch.
32068c2ecf20Sopenharmony_ci *
32078c2ecf20Sopenharmony_ci *  Otherwise try to set the VSI passed in as the switch's default VSI and
32088c2ecf20Sopenharmony_ci *  return the result.
32098c2ecf20Sopenharmony_ci */
32108c2ecf20Sopenharmony_ciint ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi)
32118c2ecf20Sopenharmony_ci{
32128c2ecf20Sopenharmony_ci	enum ice_status status;
32138c2ecf20Sopenharmony_ci	struct device *dev;
32148c2ecf20Sopenharmony_ci
32158c2ecf20Sopenharmony_ci	if (!sw || !vsi)
32168c2ecf20Sopenharmony_ci		return -EINVAL;
32178c2ecf20Sopenharmony_ci
32188c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(vsi->back);
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ci	/* the VSI passed in is already the default VSI */
32218c2ecf20Sopenharmony_ci	if (ice_is_vsi_dflt_vsi(sw, vsi)) {
32228c2ecf20Sopenharmony_ci		dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n",
32238c2ecf20Sopenharmony_ci			vsi->vsi_num);
32248c2ecf20Sopenharmony_ci		return 0;
32258c2ecf20Sopenharmony_ci	}
32268c2ecf20Sopenharmony_ci
32278c2ecf20Sopenharmony_ci	/* another VSI is already the default VSI for this switch */
32288c2ecf20Sopenharmony_ci	if (ice_is_dflt_vsi_in_use(sw)) {
32298c2ecf20Sopenharmony_ci		dev_err(dev, "Default forwarding VSI %d already in use, disable it and try again\n",
32308c2ecf20Sopenharmony_ci			sw->dflt_vsi->vsi_num);
32318c2ecf20Sopenharmony_ci		return -EEXIST;
32328c2ecf20Sopenharmony_ci	}
32338c2ecf20Sopenharmony_ci
32348c2ecf20Sopenharmony_ci	status = ice_cfg_dflt_vsi(&vsi->back->hw, vsi->idx, true, ICE_FLTR_RX);
32358c2ecf20Sopenharmony_ci	if (status) {
32368c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to set VSI %d as the default forwarding VSI, error %s\n",
32378c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
32388c2ecf20Sopenharmony_ci		return -EIO;
32398c2ecf20Sopenharmony_ci	}
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	sw->dflt_vsi = vsi;
32428c2ecf20Sopenharmony_ci	sw->dflt_vsi_ena = true;
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_ci	return 0;
32458c2ecf20Sopenharmony_ci}
32468c2ecf20Sopenharmony_ci
32478c2ecf20Sopenharmony_ci/**
32488c2ecf20Sopenharmony_ci * ice_clear_dflt_vsi - clear the default forwarding VSI
32498c2ecf20Sopenharmony_ci * @sw: switch used to clear the default VSI
32508c2ecf20Sopenharmony_ci *
32518c2ecf20Sopenharmony_ci * If the switch has no default VSI or it's not enabled then return error.
32528c2ecf20Sopenharmony_ci *
32538c2ecf20Sopenharmony_ci * Otherwise try to clear the default VSI and return the result.
32548c2ecf20Sopenharmony_ci */
32558c2ecf20Sopenharmony_ciint ice_clear_dflt_vsi(struct ice_sw *sw)
32568c2ecf20Sopenharmony_ci{
32578c2ecf20Sopenharmony_ci	struct ice_vsi *dflt_vsi;
32588c2ecf20Sopenharmony_ci	enum ice_status status;
32598c2ecf20Sopenharmony_ci	struct device *dev;
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci	if (!sw)
32628c2ecf20Sopenharmony_ci		return -EINVAL;
32638c2ecf20Sopenharmony_ci
32648c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(sw->pf);
32658c2ecf20Sopenharmony_ci
32668c2ecf20Sopenharmony_ci	dflt_vsi = sw->dflt_vsi;
32678c2ecf20Sopenharmony_ci
32688c2ecf20Sopenharmony_ci	/* there is no default VSI configured */
32698c2ecf20Sopenharmony_ci	if (!ice_is_dflt_vsi_in_use(sw))
32708c2ecf20Sopenharmony_ci		return -ENODEV;
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci	status = ice_cfg_dflt_vsi(&dflt_vsi->back->hw, dflt_vsi->idx, false,
32738c2ecf20Sopenharmony_ci				  ICE_FLTR_RX);
32748c2ecf20Sopenharmony_ci	if (status) {
32758c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to clear the default forwarding VSI %d, error %s\n",
32768c2ecf20Sopenharmony_ci			dflt_vsi->vsi_num, ice_stat_str(status));
32778c2ecf20Sopenharmony_ci		return -EIO;
32788c2ecf20Sopenharmony_ci	}
32798c2ecf20Sopenharmony_ci
32808c2ecf20Sopenharmony_ci	sw->dflt_vsi = NULL;
32818c2ecf20Sopenharmony_ci	sw->dflt_vsi_ena = false;
32828c2ecf20Sopenharmony_ci
32838c2ecf20Sopenharmony_ci	return 0;
32848c2ecf20Sopenharmony_ci}
3285