18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2018, Intel Corporation. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci/* Intel(R) Ethernet Connection E800 Series Linux Driver */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <generated/utsrelease.h>
98c2ecf20Sopenharmony_ci#include <linux/crash_dump.h>
108c2ecf20Sopenharmony_ci#include "ice.h"
118c2ecf20Sopenharmony_ci#include "ice_base.h"
128c2ecf20Sopenharmony_ci#include "ice_lib.h"
138c2ecf20Sopenharmony_ci#include "ice_fltr.h"
148c2ecf20Sopenharmony_ci#include "ice_dcb_lib.h"
158c2ecf20Sopenharmony_ci#include "ice_dcb_nl.h"
168c2ecf20Sopenharmony_ci#include "ice_devlink.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define DRV_SUMMARY	"Intel(R) Ethernet Connection E800 Series Linux Driver"
198c2ecf20Sopenharmony_cistatic const char ice_driver_string[] = DRV_SUMMARY;
208c2ecf20Sopenharmony_cistatic const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation.";
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* DDP Package file located in firmware search paths (e.g. /lib/firmware/) */
238c2ecf20Sopenharmony_ci#define ICE_DDP_PKG_PATH	"intel/ice/ddp/"
248c2ecf20Sopenharmony_ci#define ICE_DDP_PKG_FILE	ICE_DDP_PKG_PATH "ice.pkg"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ciMODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRV_SUMMARY);
288c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
298c2ecf20Sopenharmony_ciMODULE_FIRMWARE(ICE_DDP_PKG_FILE);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic int debug = -1;
328c2ecf20Sopenharmony_cimodule_param(debug, int, 0644);
338c2ecf20Sopenharmony_ci#ifndef CONFIG_DYNAMIC_DEBUG
348c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXXXXX)");
358c2ecf20Sopenharmony_ci#else
368c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)");
378c2ecf20Sopenharmony_ci#endif /* !CONFIG_DYNAMIC_DEBUG */
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_cistatic struct workqueue_struct *ice_wq;
408c2ecf20Sopenharmony_cistatic const struct net_device_ops ice_netdev_safe_mode_ops;
418c2ecf20Sopenharmony_cistatic const struct net_device_ops ice_netdev_ops;
428c2ecf20Sopenharmony_cistatic int ice_vsi_open(struct ice_vsi *vsi);
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type);
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic void ice_vsi_release_all(struct ice_pf *pf);
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/**
498c2ecf20Sopenharmony_ci * ice_get_tx_pending - returns number of Tx descriptors not processed
508c2ecf20Sopenharmony_ci * @ring: the ring of descriptors
518c2ecf20Sopenharmony_ci */
528c2ecf20Sopenharmony_cistatic u16 ice_get_tx_pending(struct ice_ring *ring)
538c2ecf20Sopenharmony_ci{
548c2ecf20Sopenharmony_ci	u16 head, tail;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	head = ring->next_to_clean;
578c2ecf20Sopenharmony_ci	tail = ring->next_to_use;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	if (head != tail)
608c2ecf20Sopenharmony_ci		return (head < tail) ?
618c2ecf20Sopenharmony_ci			tail - head : (tail + ring->count - head);
628c2ecf20Sopenharmony_ci	return 0;
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/**
668c2ecf20Sopenharmony_ci * ice_check_for_hang_subtask - check for and recover hung queues
678c2ecf20Sopenharmony_ci * @pf: pointer to PF struct
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_cistatic void ice_check_for_hang_subtask(struct ice_pf *pf)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = NULL;
728c2ecf20Sopenharmony_ci	struct ice_hw *hw;
738c2ecf20Sopenharmony_ci	unsigned int i;
748c2ecf20Sopenharmony_ci	int packets;
758c2ecf20Sopenharmony_ci	u32 v;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, v)
788c2ecf20Sopenharmony_ci		if (pf->vsi[v] && pf->vsi[v]->type == ICE_VSI_PF) {
798c2ecf20Sopenharmony_ci			vsi = pf->vsi[v];
808c2ecf20Sopenharmony_ci			break;
818c2ecf20Sopenharmony_ci		}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	if (!vsi || test_bit(__ICE_DOWN, vsi->state))
848c2ecf20Sopenharmony_ci		return;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if (!(vsi->netdev && netif_carrier_ok(vsi->netdev)))
878c2ecf20Sopenharmony_ci		return;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	hw = &vsi->back->hw;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_txq; i++) {
928c2ecf20Sopenharmony_ci		struct ice_ring *tx_ring = vsi->tx_rings[i];
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci		if (tx_ring && tx_ring->desc) {
958c2ecf20Sopenharmony_ci			/* If packet counter has not changed the queue is
968c2ecf20Sopenharmony_ci			 * likely stalled, so force an interrupt for this
978c2ecf20Sopenharmony_ci			 * queue.
988c2ecf20Sopenharmony_ci			 *
998c2ecf20Sopenharmony_ci			 * prev_pkt would be negative if there was no
1008c2ecf20Sopenharmony_ci			 * pending work.
1018c2ecf20Sopenharmony_ci			 */
1028c2ecf20Sopenharmony_ci			packets = tx_ring->stats.pkts & INT_MAX;
1038c2ecf20Sopenharmony_ci			if (tx_ring->tx_stats.prev_pkt == packets) {
1048c2ecf20Sopenharmony_ci				/* Trigger sw interrupt to revive the queue */
1058c2ecf20Sopenharmony_ci				ice_trigger_sw_intr(hw, tx_ring->q_vector);
1068c2ecf20Sopenharmony_ci				continue;
1078c2ecf20Sopenharmony_ci			}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci			/* Memory barrier between read of packet count and call
1108c2ecf20Sopenharmony_ci			 * to ice_get_tx_pending()
1118c2ecf20Sopenharmony_ci			 */
1128c2ecf20Sopenharmony_ci			smp_rmb();
1138c2ecf20Sopenharmony_ci			tx_ring->tx_stats.prev_pkt =
1148c2ecf20Sopenharmony_ci			    ice_get_tx_pending(tx_ring) ? packets : -1;
1158c2ecf20Sopenharmony_ci		}
1168c2ecf20Sopenharmony_ci	}
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci/**
1208c2ecf20Sopenharmony_ci * ice_init_mac_fltr - Set initial MAC filters
1218c2ecf20Sopenharmony_ci * @pf: board private structure
1228c2ecf20Sopenharmony_ci *
1238c2ecf20Sopenharmony_ci * Set initial set of MAC filters for PF VSI; configure filters for permanent
1248c2ecf20Sopenharmony_ci * address and broadcast address. If an error is encountered, netdevice will be
1258c2ecf20Sopenharmony_ci * unregistered.
1268c2ecf20Sopenharmony_ci */
1278c2ecf20Sopenharmony_cistatic int ice_init_mac_fltr(struct ice_pf *pf)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	enum ice_status status;
1308c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
1318c2ecf20Sopenharmony_ci	u8 *perm_addr;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	vsi = ice_get_main_vsi(pf);
1348c2ecf20Sopenharmony_ci	if (!vsi)
1358c2ecf20Sopenharmony_ci		return -EINVAL;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	perm_addr = vsi->port_info->mac.perm_addr;
1388c2ecf20Sopenharmony_ci	status = ice_fltr_add_mac_and_broadcast(vsi, perm_addr, ICE_FWD_TO_VSI);
1398c2ecf20Sopenharmony_ci	if (!status)
1408c2ecf20Sopenharmony_ci		return 0;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/* We aren't useful with no MAC filters, so unregister if we
1438c2ecf20Sopenharmony_ci	 * had an error
1448c2ecf20Sopenharmony_ci	 */
1458c2ecf20Sopenharmony_ci	if (vsi->netdev->reg_state == NETREG_REGISTERED) {
1468c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Could not add MAC filters error %s. Unregistering device\n",
1478c2ecf20Sopenharmony_ci			ice_stat_str(status));
1488c2ecf20Sopenharmony_ci		unregister_netdev(vsi->netdev);
1498c2ecf20Sopenharmony_ci		free_netdev(vsi->netdev);
1508c2ecf20Sopenharmony_ci		vsi->netdev = NULL;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	return -EIO;
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci/**
1578c2ecf20Sopenharmony_ci * ice_add_mac_to_sync_list - creates list of MAC addresses to be synced
1588c2ecf20Sopenharmony_ci * @netdev: the net device on which the sync is happening
1598c2ecf20Sopenharmony_ci * @addr: MAC address to sync
1608c2ecf20Sopenharmony_ci *
1618c2ecf20Sopenharmony_ci * This is a callback function which is called by the in kernel device sync
1628c2ecf20Sopenharmony_ci * functions (like __dev_uc_sync, __dev_mc_sync, etc). This function only
1638c2ecf20Sopenharmony_ci * populates the tmp_sync_list, which is later used by ice_add_mac to add the
1648c2ecf20Sopenharmony_ci * MAC filters from the hardware.
1658c2ecf20Sopenharmony_ci */
1668c2ecf20Sopenharmony_cistatic int ice_add_mac_to_sync_list(struct net_device *netdev, const u8 *addr)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
1698c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (ice_fltr_add_mac_to_list(vsi, &vsi->tmp_sync_list, addr,
1728c2ecf20Sopenharmony_ci				     ICE_FWD_TO_VSI))
1738c2ecf20Sopenharmony_ci		return -EINVAL;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	return 0;
1768c2ecf20Sopenharmony_ci}
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci/**
1798c2ecf20Sopenharmony_ci * ice_add_mac_to_unsync_list - creates list of MAC addresses to be unsynced
1808c2ecf20Sopenharmony_ci * @netdev: the net device on which the unsync is happening
1818c2ecf20Sopenharmony_ci * @addr: MAC address to unsync
1828c2ecf20Sopenharmony_ci *
1838c2ecf20Sopenharmony_ci * This is a callback function which is called by the in kernel device unsync
1848c2ecf20Sopenharmony_ci * functions (like __dev_uc_unsync, __dev_mc_unsync, etc). This function only
1858c2ecf20Sopenharmony_ci * populates the tmp_unsync_list, which is later used by ice_remove_mac to
1868c2ecf20Sopenharmony_ci * delete the MAC filters from the hardware.
1878c2ecf20Sopenharmony_ci */
1888c2ecf20Sopenharmony_cistatic int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
1918c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	/* Under some circumstances, we might receive a request to delete our
1948c2ecf20Sopenharmony_ci	 * own device address from our uc list. Because we store the device
1958c2ecf20Sopenharmony_ci	 * address in the VSI's MAC filter list, we need to ignore such
1968c2ecf20Sopenharmony_ci	 * requests and not delete our device address from this list.
1978c2ecf20Sopenharmony_ci	 */
1988c2ecf20Sopenharmony_ci	if (ether_addr_equal(addr, netdev->dev_addr))
1998c2ecf20Sopenharmony_ci		return 0;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	if (ice_fltr_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr,
2028c2ecf20Sopenharmony_ci				     ICE_FWD_TO_VSI))
2038c2ecf20Sopenharmony_ci		return -EINVAL;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci/**
2098c2ecf20Sopenharmony_ci * ice_vsi_fltr_changed - check if filter state changed
2108c2ecf20Sopenharmony_ci * @vsi: VSI to be checked
2118c2ecf20Sopenharmony_ci *
2128c2ecf20Sopenharmony_ci * returns true if filter state has changed, false otherwise.
2138c2ecf20Sopenharmony_ci */
2148c2ecf20Sopenharmony_cistatic bool ice_vsi_fltr_changed(struct ice_vsi *vsi)
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	return test_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags) ||
2178c2ecf20Sopenharmony_ci	       test_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags) ||
2188c2ecf20Sopenharmony_ci	       test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci/**
2228c2ecf20Sopenharmony_ci * ice_cfg_promisc - Enable or disable promiscuous mode for a given PF
2238c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
2248c2ecf20Sopenharmony_ci * @promisc_m: mask of promiscuous config bits
2258c2ecf20Sopenharmony_ci * @set_promisc: enable or disable promisc flag request
2268c2ecf20Sopenharmony_ci *
2278c2ecf20Sopenharmony_ci */
2288c2ecf20Sopenharmony_cistatic int ice_cfg_promisc(struct ice_vsi *vsi, u8 promisc_m, bool set_promisc)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
2318c2ecf20Sopenharmony_ci	enum ice_status status = 0;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_PF)
2348c2ecf20Sopenharmony_ci		return 0;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (vsi->vlan_ena) {
2378c2ecf20Sopenharmony_ci		status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m,
2388c2ecf20Sopenharmony_ci						  set_promisc);
2398c2ecf20Sopenharmony_ci	} else {
2408c2ecf20Sopenharmony_ci		if (set_promisc)
2418c2ecf20Sopenharmony_ci			status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
2428c2ecf20Sopenharmony_ci						     0);
2438c2ecf20Sopenharmony_ci		else
2448c2ecf20Sopenharmony_ci			status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
2458c2ecf20Sopenharmony_ci						       0);
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	if (status)
2498c2ecf20Sopenharmony_ci		return -EIO;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	return 0;
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci/**
2558c2ecf20Sopenharmony_ci * ice_vsi_sync_fltr - Update the VSI filter list to the HW
2568c2ecf20Sopenharmony_ci * @vsi: ptr to the VSI
2578c2ecf20Sopenharmony_ci *
2588c2ecf20Sopenharmony_ci * Push any outstanding VSI filter changes through the AdminQ.
2598c2ecf20Sopenharmony_ci */
2608c2ecf20Sopenharmony_cistatic int ice_vsi_sync_fltr(struct ice_vsi *vsi)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(vsi->back);
2638c2ecf20Sopenharmony_ci	struct net_device *netdev = vsi->netdev;
2648c2ecf20Sopenharmony_ci	bool promisc_forced_on = false;
2658c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
2668c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
2678c2ecf20Sopenharmony_ci	enum ice_status status = 0;
2688c2ecf20Sopenharmony_ci	u32 changed_flags = 0;
2698c2ecf20Sopenharmony_ci	u8 promisc_m;
2708c2ecf20Sopenharmony_ci	int err = 0;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	if (!vsi->netdev)
2738c2ecf20Sopenharmony_ci		return -EINVAL;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	while (test_and_set_bit(__ICE_CFG_BUSY, vsi->state))
2768c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	changed_flags = vsi->current_netdev_flags ^ vsi->netdev->flags;
2798c2ecf20Sopenharmony_ci	vsi->current_netdev_flags = vsi->netdev->flags;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&vsi->tmp_sync_list);
2828c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&vsi->tmp_unsync_list);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	if (ice_vsi_fltr_changed(vsi)) {
2858c2ecf20Sopenharmony_ci		clear_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
2868c2ecf20Sopenharmony_ci		clear_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
2878c2ecf20Sopenharmony_ci		clear_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci		/* grab the netdev's addr_list_lock */
2908c2ecf20Sopenharmony_ci		netif_addr_lock_bh(netdev);
2918c2ecf20Sopenharmony_ci		__dev_uc_sync(netdev, ice_add_mac_to_sync_list,
2928c2ecf20Sopenharmony_ci			      ice_add_mac_to_unsync_list);
2938c2ecf20Sopenharmony_ci		__dev_mc_sync(netdev, ice_add_mac_to_sync_list,
2948c2ecf20Sopenharmony_ci			      ice_add_mac_to_unsync_list);
2958c2ecf20Sopenharmony_ci		/* our temp lists are populated. release lock */
2968c2ecf20Sopenharmony_ci		netif_addr_unlock_bh(netdev);
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	/* Remove MAC addresses in the unsync list */
3008c2ecf20Sopenharmony_ci	status = ice_fltr_remove_mac_list(vsi, &vsi->tmp_unsync_list);
3018c2ecf20Sopenharmony_ci	ice_fltr_free_list(dev, &vsi->tmp_unsync_list);
3028c2ecf20Sopenharmony_ci	if (status) {
3038c2ecf20Sopenharmony_ci		netdev_err(netdev, "Failed to delete MAC filters\n");
3048c2ecf20Sopenharmony_ci		/* if we failed because of alloc failures, just bail */
3058c2ecf20Sopenharmony_ci		if (status == ICE_ERR_NO_MEMORY) {
3068c2ecf20Sopenharmony_ci			err = -ENOMEM;
3078c2ecf20Sopenharmony_ci			goto out;
3088c2ecf20Sopenharmony_ci		}
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/* Add MAC addresses in the sync list */
3128c2ecf20Sopenharmony_ci	status = ice_fltr_add_mac_list(vsi, &vsi->tmp_sync_list);
3138c2ecf20Sopenharmony_ci	ice_fltr_free_list(dev, &vsi->tmp_sync_list);
3148c2ecf20Sopenharmony_ci	/* If filter is added successfully or already exists, do not go into
3158c2ecf20Sopenharmony_ci	 * 'if' condition and report it as error. Instead continue processing
3168c2ecf20Sopenharmony_ci	 * rest of the function.
3178c2ecf20Sopenharmony_ci	 */
3188c2ecf20Sopenharmony_ci	if (status && status != ICE_ERR_ALREADY_EXISTS) {
3198c2ecf20Sopenharmony_ci		netdev_err(netdev, "Failed to add MAC filters\n");
3208c2ecf20Sopenharmony_ci		/* If there is no more space for new umac filters, VSI
3218c2ecf20Sopenharmony_ci		 * should go into promiscuous mode. There should be some
3228c2ecf20Sopenharmony_ci		 * space reserved for promiscuous filters.
3238c2ecf20Sopenharmony_ci		 */
3248c2ecf20Sopenharmony_ci		if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOSPC &&
3258c2ecf20Sopenharmony_ci		    !test_and_set_bit(__ICE_FLTR_OVERFLOW_PROMISC,
3268c2ecf20Sopenharmony_ci				      vsi->state)) {
3278c2ecf20Sopenharmony_ci			promisc_forced_on = true;
3288c2ecf20Sopenharmony_ci			netdev_warn(netdev, "Reached MAC filter limit, forcing promisc mode on VSI %d\n",
3298c2ecf20Sopenharmony_ci				    vsi->vsi_num);
3308c2ecf20Sopenharmony_ci		} else {
3318c2ecf20Sopenharmony_ci			err = -EIO;
3328c2ecf20Sopenharmony_ci			goto out;
3338c2ecf20Sopenharmony_ci		}
3348c2ecf20Sopenharmony_ci	}
3358c2ecf20Sopenharmony_ci	/* check for changes in promiscuous modes */
3368c2ecf20Sopenharmony_ci	if (changed_flags & IFF_ALLMULTI) {
3378c2ecf20Sopenharmony_ci		if (vsi->current_netdev_flags & IFF_ALLMULTI) {
3388c2ecf20Sopenharmony_ci			if (vsi->vlan_ena)
3398c2ecf20Sopenharmony_ci				promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
3408c2ecf20Sopenharmony_ci			else
3418c2ecf20Sopenharmony_ci				promisc_m = ICE_MCAST_PROMISC_BITS;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci			err = ice_cfg_promisc(vsi, promisc_m, true);
3448c2ecf20Sopenharmony_ci			if (err) {
3458c2ecf20Sopenharmony_ci				netdev_err(netdev, "Error setting Multicast promiscuous mode on VSI %i\n",
3468c2ecf20Sopenharmony_ci					   vsi->vsi_num);
3478c2ecf20Sopenharmony_ci				vsi->current_netdev_flags &= ~IFF_ALLMULTI;
3488c2ecf20Sopenharmony_ci				goto out_promisc;
3498c2ecf20Sopenharmony_ci			}
3508c2ecf20Sopenharmony_ci		} else {
3518c2ecf20Sopenharmony_ci			/* !(vsi->current_netdev_flags & IFF_ALLMULTI) */
3528c2ecf20Sopenharmony_ci			if (vsi->vlan_ena)
3538c2ecf20Sopenharmony_ci				promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
3548c2ecf20Sopenharmony_ci			else
3558c2ecf20Sopenharmony_ci				promisc_m = ICE_MCAST_PROMISC_BITS;
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci			err = ice_cfg_promisc(vsi, promisc_m, false);
3588c2ecf20Sopenharmony_ci			if (err) {
3598c2ecf20Sopenharmony_ci				netdev_err(netdev, "Error clearing Multicast promiscuous mode on VSI %i\n",
3608c2ecf20Sopenharmony_ci					   vsi->vsi_num);
3618c2ecf20Sopenharmony_ci				vsi->current_netdev_flags |= IFF_ALLMULTI;
3628c2ecf20Sopenharmony_ci				goto out_promisc;
3638c2ecf20Sopenharmony_ci			}
3648c2ecf20Sopenharmony_ci		}
3658c2ecf20Sopenharmony_ci	}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	if (((changed_flags & IFF_PROMISC) || promisc_forced_on) ||
3688c2ecf20Sopenharmony_ci	    test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) {
3698c2ecf20Sopenharmony_ci		clear_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags);
3708c2ecf20Sopenharmony_ci		if (vsi->current_netdev_flags & IFF_PROMISC) {
3718c2ecf20Sopenharmony_ci			/* Apply Rx filter rule to get traffic from wire */
3728c2ecf20Sopenharmony_ci			if (!ice_is_dflt_vsi_in_use(pf->first_sw)) {
3738c2ecf20Sopenharmony_ci				err = ice_set_dflt_vsi(pf->first_sw, vsi);
3748c2ecf20Sopenharmony_ci				if (err && err != -EEXIST) {
3758c2ecf20Sopenharmony_ci					netdev_err(netdev, "Error %d setting default VSI %i Rx rule\n",
3768c2ecf20Sopenharmony_ci						   err, vsi->vsi_num);
3778c2ecf20Sopenharmony_ci					vsi->current_netdev_flags &=
3788c2ecf20Sopenharmony_ci						~IFF_PROMISC;
3798c2ecf20Sopenharmony_ci					goto out_promisc;
3808c2ecf20Sopenharmony_ci				}
3818c2ecf20Sopenharmony_ci				ice_cfg_vlan_pruning(vsi, false, false);
3828c2ecf20Sopenharmony_ci			}
3838c2ecf20Sopenharmony_ci		} else {
3848c2ecf20Sopenharmony_ci			/* Clear Rx filter to remove traffic from wire */
3858c2ecf20Sopenharmony_ci			if (ice_is_vsi_dflt_vsi(pf->first_sw, vsi)) {
3868c2ecf20Sopenharmony_ci				err = ice_clear_dflt_vsi(pf->first_sw);
3878c2ecf20Sopenharmony_ci				if (err) {
3888c2ecf20Sopenharmony_ci					netdev_err(netdev, "Error %d clearing default VSI %i Rx rule\n",
3898c2ecf20Sopenharmony_ci						   err, vsi->vsi_num);
3908c2ecf20Sopenharmony_ci					vsi->current_netdev_flags |=
3918c2ecf20Sopenharmony_ci						IFF_PROMISC;
3928c2ecf20Sopenharmony_ci					goto out_promisc;
3938c2ecf20Sopenharmony_ci				}
3948c2ecf20Sopenharmony_ci				if (vsi->num_vlan > 1)
3958c2ecf20Sopenharmony_ci					ice_cfg_vlan_pruning(vsi, true, false);
3968c2ecf20Sopenharmony_ci			}
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci	goto exit;
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ciout_promisc:
4028c2ecf20Sopenharmony_ci	set_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags);
4038c2ecf20Sopenharmony_ci	goto exit;
4048c2ecf20Sopenharmony_ciout:
4058c2ecf20Sopenharmony_ci	/* if something went wrong then set the changed flag so we try again */
4068c2ecf20Sopenharmony_ci	set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
4078c2ecf20Sopenharmony_ci	set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
4088c2ecf20Sopenharmony_ciexit:
4098c2ecf20Sopenharmony_ci	clear_bit(__ICE_CFG_BUSY, vsi->state);
4108c2ecf20Sopenharmony_ci	return err;
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci/**
4148c2ecf20Sopenharmony_ci * ice_sync_fltr_subtask - Sync the VSI filter list with HW
4158c2ecf20Sopenharmony_ci * @pf: board private structure
4168c2ecf20Sopenharmony_ci */
4178c2ecf20Sopenharmony_cistatic void ice_sync_fltr_subtask(struct ice_pf *pf)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	int v;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (!pf || !(test_bit(ICE_FLAG_FLTR_SYNC, pf->flags)))
4228c2ecf20Sopenharmony_ci		return;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	clear_bit(ICE_FLAG_FLTR_SYNC, pf->flags);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, v)
4278c2ecf20Sopenharmony_ci		if (pf->vsi[v] && ice_vsi_fltr_changed(pf->vsi[v]) &&
4288c2ecf20Sopenharmony_ci		    ice_vsi_sync_fltr(pf->vsi[v])) {
4298c2ecf20Sopenharmony_ci			/* come back and try again later */
4308c2ecf20Sopenharmony_ci			set_bit(ICE_FLAG_FLTR_SYNC, pf->flags);
4318c2ecf20Sopenharmony_ci			break;
4328c2ecf20Sopenharmony_ci		}
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci/**
4368c2ecf20Sopenharmony_ci * ice_pf_dis_all_vsi - Pause all VSIs on a PF
4378c2ecf20Sopenharmony_ci * @pf: the PF
4388c2ecf20Sopenharmony_ci * @locked: is the rtnl_lock already held
4398c2ecf20Sopenharmony_ci */
4408c2ecf20Sopenharmony_cistatic void ice_pf_dis_all_vsi(struct ice_pf *pf, bool locked)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	int v;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, v)
4458c2ecf20Sopenharmony_ci		if (pf->vsi[v])
4468c2ecf20Sopenharmony_ci			ice_dis_vsi(pf->vsi[v], locked);
4478c2ecf20Sopenharmony_ci}
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci/**
4508c2ecf20Sopenharmony_ci * ice_prepare_for_reset - prep for the core to reset
4518c2ecf20Sopenharmony_ci * @pf: board private structure
4528c2ecf20Sopenharmony_ci *
4538c2ecf20Sopenharmony_ci * Inform or close all dependent features in prep for reset.
4548c2ecf20Sopenharmony_ci */
4558c2ecf20Sopenharmony_cistatic void
4568c2ecf20Sopenharmony_ciice_prepare_for_reset(struct ice_pf *pf)
4578c2ecf20Sopenharmony_ci{
4588c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
4598c2ecf20Sopenharmony_ci	unsigned int i;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	/* already prepared for reset */
4628c2ecf20Sopenharmony_ci	if (test_bit(__ICE_PREPARED_FOR_RESET, pf->state))
4638c2ecf20Sopenharmony_ci		return;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	/* Notify VFs of impending reset */
4668c2ecf20Sopenharmony_ci	if (ice_check_sq_alive(hw, &hw->mailboxq))
4678c2ecf20Sopenharmony_ci		ice_vc_notify_reset(pf);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	/* Disable VFs until reset is completed */
4708c2ecf20Sopenharmony_ci	ice_for_each_vf(pf, i)
4718c2ecf20Sopenharmony_ci		ice_set_vf_state_qs_dis(&pf->vf[i]);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	/* clear SW filtering DB */
4748c2ecf20Sopenharmony_ci	ice_clear_hw_tbls(hw);
4758c2ecf20Sopenharmony_ci	/* disable the VSIs and their queues that are not already DOWN */
4768c2ecf20Sopenharmony_ci	ice_pf_dis_all_vsi(pf, false);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	if (hw->port_info)
4798c2ecf20Sopenharmony_ci		ice_sched_clear_port(hw->port_info);
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	ice_shutdown_all_ctrlq(hw);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	set_bit(__ICE_PREPARED_FOR_RESET, pf->state);
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci/**
4878c2ecf20Sopenharmony_ci * ice_do_reset - Initiate one of many types of resets
4888c2ecf20Sopenharmony_ci * @pf: board private structure
4898c2ecf20Sopenharmony_ci * @reset_type: reset type requested
4908c2ecf20Sopenharmony_ci * before this function was called.
4918c2ecf20Sopenharmony_ci */
4928c2ecf20Sopenharmony_cistatic void ice_do_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
4958c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	dev_dbg(dev, "reset_type 0x%x requested\n", reset_type);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	ice_prepare_for_reset(pf);
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci	/* trigger the reset */
5028c2ecf20Sopenharmony_ci	if (ice_reset(hw, reset_type)) {
5038c2ecf20Sopenharmony_ci		dev_err(dev, "reset %d failed\n", reset_type);
5048c2ecf20Sopenharmony_ci		set_bit(__ICE_RESET_FAILED, pf->state);
5058c2ecf20Sopenharmony_ci		clear_bit(__ICE_RESET_OICR_RECV, pf->state);
5068c2ecf20Sopenharmony_ci		clear_bit(__ICE_PREPARED_FOR_RESET, pf->state);
5078c2ecf20Sopenharmony_ci		clear_bit(__ICE_PFR_REQ, pf->state);
5088c2ecf20Sopenharmony_ci		clear_bit(__ICE_CORER_REQ, pf->state);
5098c2ecf20Sopenharmony_ci		clear_bit(__ICE_GLOBR_REQ, pf->state);
5108c2ecf20Sopenharmony_ci		return;
5118c2ecf20Sopenharmony_ci	}
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	/* PFR is a bit of a special case because it doesn't result in an OICR
5148c2ecf20Sopenharmony_ci	 * interrupt. So for PFR, rebuild after the reset and clear the reset-
5158c2ecf20Sopenharmony_ci	 * associated state bits.
5168c2ecf20Sopenharmony_ci	 */
5178c2ecf20Sopenharmony_ci	if (reset_type == ICE_RESET_PFR) {
5188c2ecf20Sopenharmony_ci		pf->pfr_count++;
5198c2ecf20Sopenharmony_ci		ice_rebuild(pf, reset_type);
5208c2ecf20Sopenharmony_ci		clear_bit(__ICE_PREPARED_FOR_RESET, pf->state);
5218c2ecf20Sopenharmony_ci		clear_bit(__ICE_PFR_REQ, pf->state);
5228c2ecf20Sopenharmony_ci		ice_reset_all_vfs(pf, true);
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci/**
5278c2ecf20Sopenharmony_ci * ice_reset_subtask - Set up for resetting the device and driver
5288c2ecf20Sopenharmony_ci * @pf: board private structure
5298c2ecf20Sopenharmony_ci */
5308c2ecf20Sopenharmony_cistatic void ice_reset_subtask(struct ice_pf *pf)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	enum ice_reset_req reset_type = ICE_RESET_INVAL;
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	/* When a CORER/GLOBR/EMPR is about to happen, the hardware triggers an
5358c2ecf20Sopenharmony_ci	 * OICR interrupt. The OICR handler (ice_misc_intr) determines what type
5368c2ecf20Sopenharmony_ci	 * of reset is pending and sets bits in pf->state indicating the reset
5378c2ecf20Sopenharmony_ci	 * type and __ICE_RESET_OICR_RECV. So, if the latter bit is set
5388c2ecf20Sopenharmony_ci	 * prepare for pending reset if not already (for PF software-initiated
5398c2ecf20Sopenharmony_ci	 * global resets the software should already be prepared for it as
5408c2ecf20Sopenharmony_ci	 * indicated by __ICE_PREPARED_FOR_RESET; for global resets initiated
5418c2ecf20Sopenharmony_ci	 * by firmware or software on other PFs, that bit is not set so prepare
5428c2ecf20Sopenharmony_ci	 * for the reset now), poll for reset done, rebuild and return.
5438c2ecf20Sopenharmony_ci	 */
5448c2ecf20Sopenharmony_ci	if (test_bit(__ICE_RESET_OICR_RECV, pf->state)) {
5458c2ecf20Sopenharmony_ci		/* Perform the largest reset requested */
5468c2ecf20Sopenharmony_ci		if (test_and_clear_bit(__ICE_CORER_RECV, pf->state))
5478c2ecf20Sopenharmony_ci			reset_type = ICE_RESET_CORER;
5488c2ecf20Sopenharmony_ci		if (test_and_clear_bit(__ICE_GLOBR_RECV, pf->state))
5498c2ecf20Sopenharmony_ci			reset_type = ICE_RESET_GLOBR;
5508c2ecf20Sopenharmony_ci		if (test_and_clear_bit(__ICE_EMPR_RECV, pf->state))
5518c2ecf20Sopenharmony_ci			reset_type = ICE_RESET_EMPR;
5528c2ecf20Sopenharmony_ci		/* return if no valid reset type requested */
5538c2ecf20Sopenharmony_ci		if (reset_type == ICE_RESET_INVAL)
5548c2ecf20Sopenharmony_ci			return;
5558c2ecf20Sopenharmony_ci		ice_prepare_for_reset(pf);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci		/* make sure we are ready to rebuild */
5588c2ecf20Sopenharmony_ci		if (ice_check_reset(&pf->hw)) {
5598c2ecf20Sopenharmony_ci			set_bit(__ICE_RESET_FAILED, pf->state);
5608c2ecf20Sopenharmony_ci		} else {
5618c2ecf20Sopenharmony_ci			/* done with reset. start rebuild */
5628c2ecf20Sopenharmony_ci			pf->hw.reset_ongoing = false;
5638c2ecf20Sopenharmony_ci			ice_rebuild(pf, reset_type);
5648c2ecf20Sopenharmony_ci			/* clear bit to resume normal operations, but
5658c2ecf20Sopenharmony_ci			 * ICE_NEEDS_RESTART bit is set in case rebuild failed
5668c2ecf20Sopenharmony_ci			 */
5678c2ecf20Sopenharmony_ci			clear_bit(__ICE_RESET_OICR_RECV, pf->state);
5688c2ecf20Sopenharmony_ci			clear_bit(__ICE_PREPARED_FOR_RESET, pf->state);
5698c2ecf20Sopenharmony_ci			clear_bit(__ICE_PFR_REQ, pf->state);
5708c2ecf20Sopenharmony_ci			clear_bit(__ICE_CORER_REQ, pf->state);
5718c2ecf20Sopenharmony_ci			clear_bit(__ICE_GLOBR_REQ, pf->state);
5728c2ecf20Sopenharmony_ci			ice_reset_all_vfs(pf, true);
5738c2ecf20Sopenharmony_ci		}
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci		return;
5768c2ecf20Sopenharmony_ci	}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	/* No pending resets to finish processing. Check for new resets */
5798c2ecf20Sopenharmony_ci	if (test_bit(__ICE_PFR_REQ, pf->state))
5808c2ecf20Sopenharmony_ci		reset_type = ICE_RESET_PFR;
5818c2ecf20Sopenharmony_ci	if (test_bit(__ICE_CORER_REQ, pf->state))
5828c2ecf20Sopenharmony_ci		reset_type = ICE_RESET_CORER;
5838c2ecf20Sopenharmony_ci	if (test_bit(__ICE_GLOBR_REQ, pf->state))
5848c2ecf20Sopenharmony_ci		reset_type = ICE_RESET_GLOBR;
5858c2ecf20Sopenharmony_ci	/* If no valid reset type requested just return */
5868c2ecf20Sopenharmony_ci	if (reset_type == ICE_RESET_INVAL)
5878c2ecf20Sopenharmony_ci		return;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	/* reset if not already down or busy */
5908c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_DOWN, pf->state) &&
5918c2ecf20Sopenharmony_ci	    !test_bit(__ICE_CFG_BUSY, pf->state)) {
5928c2ecf20Sopenharmony_ci		ice_do_reset(pf, reset_type);
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci/**
5978c2ecf20Sopenharmony_ci * ice_print_topo_conflict - print topology conflict message
5988c2ecf20Sopenharmony_ci * @vsi: the VSI whose topology status is being checked
5998c2ecf20Sopenharmony_ci */
6008c2ecf20Sopenharmony_cistatic void ice_print_topo_conflict(struct ice_vsi *vsi)
6018c2ecf20Sopenharmony_ci{
6028c2ecf20Sopenharmony_ci	switch (vsi->port_info->phy.link_info.topo_media_conflict) {
6038c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_TOPO_CONFLICT:
6048c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_MEDIA_CONFLICT:
6058c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_TOPO_UNREACH_PRT:
6068c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_TOPO_UNDRUTIL_PRT:
6078c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_TOPO_UNDRUTIL_MEDIA:
6088c2ecf20Sopenharmony_ci		netdev_info(vsi->netdev, "Possible mis-configuration of the Ethernet port detected, please use the Intel(R) Ethernet Port Configuration Tool application to address the issue.\n");
6098c2ecf20Sopenharmony_ci		break;
6108c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_TOPO_UNSUPP_MEDIA:
6118c2ecf20Sopenharmony_ci		netdev_info(vsi->netdev, "Rx/Tx is disabled on this device because an unsupported module type was detected. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules.\n");
6128c2ecf20Sopenharmony_ci		break;
6138c2ecf20Sopenharmony_ci	default:
6148c2ecf20Sopenharmony_ci		break;
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci/**
6198c2ecf20Sopenharmony_ci * ice_print_link_msg - print link up or down message
6208c2ecf20Sopenharmony_ci * @vsi: the VSI whose link status is being queried
6218c2ecf20Sopenharmony_ci * @isup: boolean for if the link is now up or down
6228c2ecf20Sopenharmony_ci */
6238c2ecf20Sopenharmony_civoid ice_print_link_msg(struct ice_vsi *vsi, bool isup)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *caps;
6268c2ecf20Sopenharmony_ci	const char *an_advertised;
6278c2ecf20Sopenharmony_ci	enum ice_status status;
6288c2ecf20Sopenharmony_ci	const char *fec_req;
6298c2ecf20Sopenharmony_ci	const char *speed;
6308c2ecf20Sopenharmony_ci	const char *fec;
6318c2ecf20Sopenharmony_ci	const char *fc;
6328c2ecf20Sopenharmony_ci	const char *an;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	if (!vsi)
6358c2ecf20Sopenharmony_ci		return;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	if (vsi->current_isup == isup)
6388c2ecf20Sopenharmony_ci		return;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	vsi->current_isup = isup;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	if (!isup) {
6438c2ecf20Sopenharmony_ci		netdev_info(vsi->netdev, "NIC Link is Down\n");
6448c2ecf20Sopenharmony_ci		return;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	switch (vsi->port_info->phy.link_info.link_speed) {
6488c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_100GB:
6498c2ecf20Sopenharmony_ci		speed = "100 G";
6508c2ecf20Sopenharmony_ci		break;
6518c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_50GB:
6528c2ecf20Sopenharmony_ci		speed = "50 G";
6538c2ecf20Sopenharmony_ci		break;
6548c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_40GB:
6558c2ecf20Sopenharmony_ci		speed = "40 G";
6568c2ecf20Sopenharmony_ci		break;
6578c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_25GB:
6588c2ecf20Sopenharmony_ci		speed = "25 G";
6598c2ecf20Sopenharmony_ci		break;
6608c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_20GB:
6618c2ecf20Sopenharmony_ci		speed = "20 G";
6628c2ecf20Sopenharmony_ci		break;
6638c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_10GB:
6648c2ecf20Sopenharmony_ci		speed = "10 G";
6658c2ecf20Sopenharmony_ci		break;
6668c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_5GB:
6678c2ecf20Sopenharmony_ci		speed = "5 G";
6688c2ecf20Sopenharmony_ci		break;
6698c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_2500MB:
6708c2ecf20Sopenharmony_ci		speed = "2.5 G";
6718c2ecf20Sopenharmony_ci		break;
6728c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_1000MB:
6738c2ecf20Sopenharmony_ci		speed = "1 G";
6748c2ecf20Sopenharmony_ci		break;
6758c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_SPEED_100MB:
6768c2ecf20Sopenharmony_ci		speed = "100 M";
6778c2ecf20Sopenharmony_ci		break;
6788c2ecf20Sopenharmony_ci	default:
6798c2ecf20Sopenharmony_ci		speed = "Unknown";
6808c2ecf20Sopenharmony_ci		break;
6818c2ecf20Sopenharmony_ci	}
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	switch (vsi->port_info->fc.current_mode) {
6848c2ecf20Sopenharmony_ci	case ICE_FC_FULL:
6858c2ecf20Sopenharmony_ci		fc = "Rx/Tx";
6868c2ecf20Sopenharmony_ci		break;
6878c2ecf20Sopenharmony_ci	case ICE_FC_TX_PAUSE:
6888c2ecf20Sopenharmony_ci		fc = "Tx";
6898c2ecf20Sopenharmony_ci		break;
6908c2ecf20Sopenharmony_ci	case ICE_FC_RX_PAUSE:
6918c2ecf20Sopenharmony_ci		fc = "Rx";
6928c2ecf20Sopenharmony_ci		break;
6938c2ecf20Sopenharmony_ci	case ICE_FC_NONE:
6948c2ecf20Sopenharmony_ci		fc = "None";
6958c2ecf20Sopenharmony_ci		break;
6968c2ecf20Sopenharmony_ci	default:
6978c2ecf20Sopenharmony_ci		fc = "Unknown";
6988c2ecf20Sopenharmony_ci		break;
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	/* Get FEC mode based on negotiated link info */
7028c2ecf20Sopenharmony_ci	switch (vsi->port_info->phy.link_info.fec_info) {
7038c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_25G_RS_528_FEC_EN:
7048c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_25G_RS_544_FEC_EN:
7058c2ecf20Sopenharmony_ci		fec = "RS-FEC";
7068c2ecf20Sopenharmony_ci		break;
7078c2ecf20Sopenharmony_ci	case ICE_AQ_LINK_25G_KR_FEC_EN:
7088c2ecf20Sopenharmony_ci		fec = "FC-FEC/BASE-R";
7098c2ecf20Sopenharmony_ci		break;
7108c2ecf20Sopenharmony_ci	default:
7118c2ecf20Sopenharmony_ci		fec = "NONE";
7128c2ecf20Sopenharmony_ci		break;
7138c2ecf20Sopenharmony_ci	}
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	/* check if autoneg completed, might be false due to not supported */
7168c2ecf20Sopenharmony_ci	if (vsi->port_info->phy.link_info.an_info & ICE_AQ_AN_COMPLETED)
7178c2ecf20Sopenharmony_ci		an = "True";
7188c2ecf20Sopenharmony_ci	else
7198c2ecf20Sopenharmony_ci		an = "False";
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	/* Get FEC mode requested based on PHY caps last SW configuration */
7228c2ecf20Sopenharmony_ci	caps = kzalloc(sizeof(*caps), GFP_KERNEL);
7238c2ecf20Sopenharmony_ci	if (!caps) {
7248c2ecf20Sopenharmony_ci		fec_req = "Unknown";
7258c2ecf20Sopenharmony_ci		an_advertised = "Unknown";
7268c2ecf20Sopenharmony_ci		goto done;
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	status = ice_aq_get_phy_caps(vsi->port_info, false,
7308c2ecf20Sopenharmony_ci				     ICE_AQC_REPORT_ACTIVE_CFG, caps, NULL);
7318c2ecf20Sopenharmony_ci	if (status)
7328c2ecf20Sopenharmony_ci		netdev_info(vsi->netdev, "Get phy capability failed.\n");
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	an_advertised = ice_is_phy_caps_an_enabled(caps) ? "On" : "Off";
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	if (caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_528_REQ ||
7378c2ecf20Sopenharmony_ci	    caps->link_fec_options & ICE_AQC_PHY_FEC_25G_RS_544_REQ)
7388c2ecf20Sopenharmony_ci		fec_req = "RS-FEC";
7398c2ecf20Sopenharmony_ci	else if (caps->link_fec_options & ICE_AQC_PHY_FEC_10G_KR_40G_KR4_REQ ||
7408c2ecf20Sopenharmony_ci		 caps->link_fec_options & ICE_AQC_PHY_FEC_25G_KR_REQ)
7418c2ecf20Sopenharmony_ci		fec_req = "FC-FEC/BASE-R";
7428c2ecf20Sopenharmony_ci	else
7438c2ecf20Sopenharmony_ci		fec_req = "NONE";
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	kfree(caps);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_cidone:
7488c2ecf20Sopenharmony_ci	netdev_info(vsi->netdev, "NIC Link is up %sbps Full Duplex, Requested FEC: %s, Negotiated FEC: %s, Autoneg Advertised: %s, Autoneg Negotiated: %s, Flow Control: %s\n",
7498c2ecf20Sopenharmony_ci		    speed, fec_req, fec, an_advertised, an, fc);
7508c2ecf20Sopenharmony_ci	ice_print_topo_conflict(vsi);
7518c2ecf20Sopenharmony_ci}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci/**
7548c2ecf20Sopenharmony_ci * ice_vsi_link_event - update the VSI's netdev
7558c2ecf20Sopenharmony_ci * @vsi: the VSI on which the link event occurred
7568c2ecf20Sopenharmony_ci * @link_up: whether or not the VSI needs to be set up or down
7578c2ecf20Sopenharmony_ci */
7588c2ecf20Sopenharmony_cistatic void ice_vsi_link_event(struct ice_vsi *vsi, bool link_up)
7598c2ecf20Sopenharmony_ci{
7608c2ecf20Sopenharmony_ci	if (!vsi)
7618c2ecf20Sopenharmony_ci		return;
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, vsi->state) || !vsi->netdev)
7648c2ecf20Sopenharmony_ci		return;
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF) {
7678c2ecf20Sopenharmony_ci		if (link_up == netif_carrier_ok(vsi->netdev))
7688c2ecf20Sopenharmony_ci			return;
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci		if (link_up) {
7718c2ecf20Sopenharmony_ci			netif_carrier_on(vsi->netdev);
7728c2ecf20Sopenharmony_ci			netif_tx_wake_all_queues(vsi->netdev);
7738c2ecf20Sopenharmony_ci		} else {
7748c2ecf20Sopenharmony_ci			netif_carrier_off(vsi->netdev);
7758c2ecf20Sopenharmony_ci			netif_tx_stop_all_queues(vsi->netdev);
7768c2ecf20Sopenharmony_ci		}
7778c2ecf20Sopenharmony_ci	}
7788c2ecf20Sopenharmony_ci}
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci/**
7818c2ecf20Sopenharmony_ci * ice_set_dflt_mib - send a default config MIB to the FW
7828c2ecf20Sopenharmony_ci * @pf: private PF struct
7838c2ecf20Sopenharmony_ci *
7848c2ecf20Sopenharmony_ci * This function sends a default configuration MIB to the FW.
7858c2ecf20Sopenharmony_ci *
7868c2ecf20Sopenharmony_ci * If this function errors out at any point, the driver is still able to
7878c2ecf20Sopenharmony_ci * function.  The main impact is that LFC may not operate as expected.
7888c2ecf20Sopenharmony_ci * Therefore an error state in this function should be treated with a DBG
7898c2ecf20Sopenharmony_ci * message and continue on with driver rebuild/reenable.
7908c2ecf20Sopenharmony_ci */
7918c2ecf20Sopenharmony_cistatic void ice_set_dflt_mib(struct ice_pf *pf)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
7948c2ecf20Sopenharmony_ci	u8 mib_type, *buf, *lldpmib = NULL;
7958c2ecf20Sopenharmony_ci	u16 len, typelen, offset = 0;
7968c2ecf20Sopenharmony_ci	struct ice_lldp_org_tlv *tlv;
7978c2ecf20Sopenharmony_ci	struct ice_hw *hw;
7988c2ecf20Sopenharmony_ci	u32 ouisubtype;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	if (!pf) {
8018c2ecf20Sopenharmony_ci		dev_dbg(dev, "%s NULL pf pointer\n", __func__);
8028c2ecf20Sopenharmony_ci		return;
8038c2ecf20Sopenharmony_ci	}
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	hw = &pf->hw;
8068c2ecf20Sopenharmony_ci	mib_type = SET_LOCAL_MIB_TYPE_LOCAL_MIB;
8078c2ecf20Sopenharmony_ci	lldpmib = kzalloc(ICE_LLDPDU_SIZE, GFP_KERNEL);
8088c2ecf20Sopenharmony_ci	if (!lldpmib) {
8098c2ecf20Sopenharmony_ci		dev_dbg(dev, "%s Failed to allocate MIB memory\n",
8108c2ecf20Sopenharmony_ci			__func__);
8118c2ecf20Sopenharmony_ci		return;
8128c2ecf20Sopenharmony_ci	}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	/* Add ETS CFG TLV */
8158c2ecf20Sopenharmony_ci	tlv = (struct ice_lldp_org_tlv *)lldpmib;
8168c2ecf20Sopenharmony_ci	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
8178c2ecf20Sopenharmony_ci		   ICE_IEEE_ETS_TLV_LEN);
8188c2ecf20Sopenharmony_ci	tlv->typelen = htons(typelen);
8198c2ecf20Sopenharmony_ci	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
8208c2ecf20Sopenharmony_ci		      ICE_IEEE_SUBTYPE_ETS_CFG);
8218c2ecf20Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	buf = tlv->tlvinfo;
8248c2ecf20Sopenharmony_ci	buf[0] = 0;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	/* ETS CFG all UPs map to TC 0. Next 4 (1 - 4) Octets = 0.
8278c2ecf20Sopenharmony_ci	 * Octets 5 - 12 are BW values, set octet 5 to 100% BW.
8288c2ecf20Sopenharmony_ci	 * Octets 13 - 20 are TSA values - leave as zeros
8298c2ecf20Sopenharmony_ci	 */
8308c2ecf20Sopenharmony_ci	buf[5] = 0x64;
8318c2ecf20Sopenharmony_ci	len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S;
8328c2ecf20Sopenharmony_ci	offset += len + 2;
8338c2ecf20Sopenharmony_ci	tlv = (struct ice_lldp_org_tlv *)
8348c2ecf20Sopenharmony_ci		((char *)tlv + sizeof(tlv->typelen) + len);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci	/* Add ETS REC TLV */
8378c2ecf20Sopenharmony_ci	buf = tlv->tlvinfo;
8388c2ecf20Sopenharmony_ci	tlv->typelen = htons(typelen);
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
8418c2ecf20Sopenharmony_ci		      ICE_IEEE_SUBTYPE_ETS_REC);
8428c2ecf20Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	/* First octet of buf is reserved
8458c2ecf20Sopenharmony_ci	 * Octets 1 - 4 map UP to TC - all UPs map to zero
8468c2ecf20Sopenharmony_ci	 * Octets 5 - 12 are BW values - set TC 0 to 100%.
8478c2ecf20Sopenharmony_ci	 * Octets 13 - 20 are TSA value - leave as zeros
8488c2ecf20Sopenharmony_ci	 */
8498c2ecf20Sopenharmony_ci	buf[5] = 0x64;
8508c2ecf20Sopenharmony_ci	offset += len + 2;
8518c2ecf20Sopenharmony_ci	tlv = (struct ice_lldp_org_tlv *)
8528c2ecf20Sopenharmony_ci		((char *)tlv + sizeof(tlv->typelen) + len);
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	/* Add PFC CFG TLV */
8558c2ecf20Sopenharmony_ci	typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
8568c2ecf20Sopenharmony_ci		   ICE_IEEE_PFC_TLV_LEN);
8578c2ecf20Sopenharmony_ci	tlv->typelen = htons(typelen);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	ouisubtype = ((ICE_IEEE_8021QAZ_OUI << ICE_LLDP_TLV_OUI_S) |
8608c2ecf20Sopenharmony_ci		      ICE_IEEE_SUBTYPE_PFC_CFG);
8618c2ecf20Sopenharmony_ci	tlv->ouisubtype = htonl(ouisubtype);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	/* Octet 1 left as all zeros - PFC disabled */
8648c2ecf20Sopenharmony_ci	buf[0] = 0x08;
8658c2ecf20Sopenharmony_ci	len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S;
8668c2ecf20Sopenharmony_ci	offset += len + 2;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	if (ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, offset, NULL))
8698c2ecf20Sopenharmony_ci		dev_dbg(dev, "%s Failed to set default LLDP MIB\n", __func__);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	kfree(lldpmib);
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci/**
8758c2ecf20Sopenharmony_ci * ice_link_event - process the link event
8768c2ecf20Sopenharmony_ci * @pf: PF that the link event is associated with
8778c2ecf20Sopenharmony_ci * @pi: port_info for the port that the link event is associated with
8788c2ecf20Sopenharmony_ci * @link_up: true if the physical link is up and false if it is down
8798c2ecf20Sopenharmony_ci * @link_speed: current link speed received from the link event
8808c2ecf20Sopenharmony_ci *
8818c2ecf20Sopenharmony_ci * Returns 0 on success and negative on failure
8828c2ecf20Sopenharmony_ci */
8838c2ecf20Sopenharmony_cistatic int
8848c2ecf20Sopenharmony_ciice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
8858c2ecf20Sopenharmony_ci	       u16 link_speed)
8868c2ecf20Sopenharmony_ci{
8878c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
8888c2ecf20Sopenharmony_ci	struct ice_phy_info *phy_info;
8898c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
8908c2ecf20Sopenharmony_ci	u16 old_link_speed;
8918c2ecf20Sopenharmony_ci	bool old_link;
8928c2ecf20Sopenharmony_ci	int result;
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	phy_info = &pi->phy;
8958c2ecf20Sopenharmony_ci	phy_info->link_info_old = phy_info->link_info;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci	old_link = !!(phy_info->link_info_old.link_info & ICE_AQ_LINK_UP);
8988c2ecf20Sopenharmony_ci	old_link_speed = phy_info->link_info_old.link_speed;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	/* update the link info structures and re-enable link events,
9018c2ecf20Sopenharmony_ci	 * don't bail on failure due to other book keeping needed
9028c2ecf20Sopenharmony_ci	 */
9038c2ecf20Sopenharmony_ci	result = ice_update_link_info(pi);
9048c2ecf20Sopenharmony_ci	if (result)
9058c2ecf20Sopenharmony_ci		dev_dbg(dev, "Failed to update link status and re-enable link events for port %d\n",
9068c2ecf20Sopenharmony_ci			pi->lport);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	/* Check if the link state is up after updating link info, and treat
9098c2ecf20Sopenharmony_ci	 * this event as an UP event since the link is actually UP now.
9108c2ecf20Sopenharmony_ci	 */
9118c2ecf20Sopenharmony_ci	if (phy_info->link_info.link_info & ICE_AQ_LINK_UP)
9128c2ecf20Sopenharmony_ci		link_up = true;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	vsi = ice_get_main_vsi(pf);
9158c2ecf20Sopenharmony_ci	if (!vsi || !vsi->port_info)
9168c2ecf20Sopenharmony_ci		return -EINVAL;
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci	/* turn off PHY if media was removed */
9198c2ecf20Sopenharmony_ci	if (!test_bit(ICE_FLAG_NO_MEDIA, pf->flags) &&
9208c2ecf20Sopenharmony_ci	    !(pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE)) {
9218c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_NO_MEDIA, pf->flags);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci		result = ice_aq_set_link_restart_an(pi, false, NULL);
9248c2ecf20Sopenharmony_ci		if (result) {
9258c2ecf20Sopenharmony_ci			dev_dbg(dev, "Failed to set link down, VSI %d error %d\n",
9268c2ecf20Sopenharmony_ci				vsi->vsi_num, result);
9278c2ecf20Sopenharmony_ci			return result;
9288c2ecf20Sopenharmony_ci		}
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	/* if the old link up/down and speed is the same as the new */
9328c2ecf20Sopenharmony_ci	if (link_up == old_link && link_speed == old_link_speed)
9338c2ecf20Sopenharmony_ci		return result;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci	if (ice_is_dcb_active(pf)) {
9368c2ecf20Sopenharmony_ci		if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
9378c2ecf20Sopenharmony_ci			ice_dcb_rebuild(pf);
9388c2ecf20Sopenharmony_ci	} else {
9398c2ecf20Sopenharmony_ci		if (link_up)
9408c2ecf20Sopenharmony_ci			ice_set_dflt_mib(pf);
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci	ice_vsi_link_event(vsi, link_up);
9438c2ecf20Sopenharmony_ci	ice_print_link_msg(vsi, link_up);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	ice_vc_notify_link_state(pf);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	return result;
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci/**
9518c2ecf20Sopenharmony_ci * ice_watchdog_subtask - periodic tasks not using event driven scheduling
9528c2ecf20Sopenharmony_ci * @pf: board private structure
9538c2ecf20Sopenharmony_ci */
9548c2ecf20Sopenharmony_cistatic void ice_watchdog_subtask(struct ice_pf *pf)
9558c2ecf20Sopenharmony_ci{
9568c2ecf20Sopenharmony_ci	int i;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	/* if interface is down do nothing */
9598c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, pf->state) ||
9608c2ecf20Sopenharmony_ci	    test_bit(__ICE_CFG_BUSY, pf->state))
9618c2ecf20Sopenharmony_ci		return;
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci	/* make sure we don't do these things too often */
9648c2ecf20Sopenharmony_ci	if (time_before(jiffies,
9658c2ecf20Sopenharmony_ci			pf->serv_tmr_prev + pf->serv_tmr_period))
9668c2ecf20Sopenharmony_ci		return;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	pf->serv_tmr_prev = jiffies;
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	/* Update the stats for active netdevs so the network stack
9718c2ecf20Sopenharmony_ci	 * can look at updated numbers whenever it cares to
9728c2ecf20Sopenharmony_ci	 */
9738c2ecf20Sopenharmony_ci	ice_update_pf_stats(pf);
9748c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, i)
9758c2ecf20Sopenharmony_ci		if (pf->vsi[i] && pf->vsi[i]->netdev)
9768c2ecf20Sopenharmony_ci			ice_update_vsi_stats(pf->vsi[i]);
9778c2ecf20Sopenharmony_ci}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci/**
9808c2ecf20Sopenharmony_ci * ice_init_link_events - enable/initialize link events
9818c2ecf20Sopenharmony_ci * @pi: pointer to the port_info instance
9828c2ecf20Sopenharmony_ci *
9838c2ecf20Sopenharmony_ci * Returns -EIO on failure, 0 on success
9848c2ecf20Sopenharmony_ci */
9858c2ecf20Sopenharmony_cistatic int ice_init_link_events(struct ice_port_info *pi)
9868c2ecf20Sopenharmony_ci{
9878c2ecf20Sopenharmony_ci	u16 mask;
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_ci	mask = ~((u16)(ICE_AQ_LINK_EVENT_UPDOWN | ICE_AQ_LINK_EVENT_MEDIA_NA |
9908c2ecf20Sopenharmony_ci		       ICE_AQ_LINK_EVENT_MODULE_QUAL_FAIL));
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	if (ice_aq_set_event_mask(pi->hw, pi->lport, mask, NULL)) {
9938c2ecf20Sopenharmony_ci		dev_dbg(ice_hw_to_dev(pi->hw), "Failed to set link event mask for port %d\n",
9948c2ecf20Sopenharmony_ci			pi->lport);
9958c2ecf20Sopenharmony_ci		return -EIO;
9968c2ecf20Sopenharmony_ci	}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	if (ice_aq_get_link_info(pi, true, NULL, NULL)) {
9998c2ecf20Sopenharmony_ci		dev_dbg(ice_hw_to_dev(pi->hw), "Failed to enable link events for port %d\n",
10008c2ecf20Sopenharmony_ci			pi->lport);
10018c2ecf20Sopenharmony_ci		return -EIO;
10028c2ecf20Sopenharmony_ci	}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	return 0;
10058c2ecf20Sopenharmony_ci}
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_ci/**
10088c2ecf20Sopenharmony_ci * ice_handle_link_event - handle link event via ARQ
10098c2ecf20Sopenharmony_ci * @pf: PF that the link event is associated with
10108c2ecf20Sopenharmony_ci * @event: event structure containing link status info
10118c2ecf20Sopenharmony_ci */
10128c2ecf20Sopenharmony_cistatic int
10138c2ecf20Sopenharmony_ciice_handle_link_event(struct ice_pf *pf, struct ice_rq_event_info *event)
10148c2ecf20Sopenharmony_ci{
10158c2ecf20Sopenharmony_ci	struct ice_aqc_get_link_status_data *link_data;
10168c2ecf20Sopenharmony_ci	struct ice_port_info *port_info;
10178c2ecf20Sopenharmony_ci	int status;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	link_data = (struct ice_aqc_get_link_status_data *)event->msg_buf;
10208c2ecf20Sopenharmony_ci	port_info = pf->hw.port_info;
10218c2ecf20Sopenharmony_ci	if (!port_info)
10228c2ecf20Sopenharmony_ci		return -EINVAL;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	status = ice_link_event(pf, port_info,
10258c2ecf20Sopenharmony_ci				!!(link_data->link_info & ICE_AQ_LINK_UP),
10268c2ecf20Sopenharmony_ci				le16_to_cpu(link_data->link_speed));
10278c2ecf20Sopenharmony_ci	if (status)
10288c2ecf20Sopenharmony_ci		dev_dbg(ice_pf_to_dev(pf), "Could not process link event, error %d\n",
10298c2ecf20Sopenharmony_ci			status);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	return status;
10328c2ecf20Sopenharmony_ci}
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_cienum ice_aq_task_state {
10358c2ecf20Sopenharmony_ci	ICE_AQ_TASK_WAITING = 0,
10368c2ecf20Sopenharmony_ci	ICE_AQ_TASK_COMPLETE,
10378c2ecf20Sopenharmony_ci	ICE_AQ_TASK_CANCELED,
10388c2ecf20Sopenharmony_ci};
10398c2ecf20Sopenharmony_ci
10408c2ecf20Sopenharmony_cistruct ice_aq_task {
10418c2ecf20Sopenharmony_ci	struct hlist_node entry;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	u16 opcode;
10448c2ecf20Sopenharmony_ci	struct ice_rq_event_info *event;
10458c2ecf20Sopenharmony_ci	enum ice_aq_task_state state;
10468c2ecf20Sopenharmony_ci};
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci/**
10498c2ecf20Sopenharmony_ci * ice_wait_for_aq_event - Wait for an AdminQ event from firmware
10508c2ecf20Sopenharmony_ci * @pf: pointer to the PF private structure
10518c2ecf20Sopenharmony_ci * @opcode: the opcode to wait for
10528c2ecf20Sopenharmony_ci * @timeout: how long to wait, in jiffies
10538c2ecf20Sopenharmony_ci * @event: storage for the event info
10548c2ecf20Sopenharmony_ci *
10558c2ecf20Sopenharmony_ci * Waits for a specific AdminQ completion event on the ARQ for a given PF. The
10568c2ecf20Sopenharmony_ci * current thread will be put to sleep until the specified event occurs or
10578c2ecf20Sopenharmony_ci * until the given timeout is reached.
10588c2ecf20Sopenharmony_ci *
10598c2ecf20Sopenharmony_ci * To obtain only the descriptor contents, pass an event without an allocated
10608c2ecf20Sopenharmony_ci * msg_buf. If the complete data buffer is desired, allocate the
10618c2ecf20Sopenharmony_ci * event->msg_buf with enough space ahead of time.
10628c2ecf20Sopenharmony_ci *
10638c2ecf20Sopenharmony_ci * Returns: zero on success, or a negative error code on failure.
10648c2ecf20Sopenharmony_ci */
10658c2ecf20Sopenharmony_ciint ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout,
10668c2ecf20Sopenharmony_ci			  struct ice_rq_event_info *event)
10678c2ecf20Sopenharmony_ci{
10688c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
10698c2ecf20Sopenharmony_ci	struct ice_aq_task *task;
10708c2ecf20Sopenharmony_ci	unsigned long start;
10718c2ecf20Sopenharmony_ci	long ret;
10728c2ecf20Sopenharmony_ci	int err;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	task = kzalloc(sizeof(*task), GFP_KERNEL);
10758c2ecf20Sopenharmony_ci	if (!task)
10768c2ecf20Sopenharmony_ci		return -ENOMEM;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	INIT_HLIST_NODE(&task->entry);
10798c2ecf20Sopenharmony_ci	task->opcode = opcode;
10808c2ecf20Sopenharmony_ci	task->event = event;
10818c2ecf20Sopenharmony_ci	task->state = ICE_AQ_TASK_WAITING;
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	spin_lock_bh(&pf->aq_wait_lock);
10848c2ecf20Sopenharmony_ci	hlist_add_head(&task->entry, &pf->aq_wait_list);
10858c2ecf20Sopenharmony_ci	spin_unlock_bh(&pf->aq_wait_lock);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	start = jiffies;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	ret = wait_event_interruptible_timeout(pf->aq_wait_queue, task->state,
10908c2ecf20Sopenharmony_ci					       timeout);
10918c2ecf20Sopenharmony_ci	switch (task->state) {
10928c2ecf20Sopenharmony_ci	case ICE_AQ_TASK_WAITING:
10938c2ecf20Sopenharmony_ci		err = ret < 0 ? ret : -ETIMEDOUT;
10948c2ecf20Sopenharmony_ci		break;
10958c2ecf20Sopenharmony_ci	case ICE_AQ_TASK_CANCELED:
10968c2ecf20Sopenharmony_ci		err = ret < 0 ? ret : -ECANCELED;
10978c2ecf20Sopenharmony_ci		break;
10988c2ecf20Sopenharmony_ci	case ICE_AQ_TASK_COMPLETE:
10998c2ecf20Sopenharmony_ci		err = ret < 0 ? ret : 0;
11008c2ecf20Sopenharmony_ci		break;
11018c2ecf20Sopenharmony_ci	default:
11028c2ecf20Sopenharmony_ci		WARN(1, "Unexpected AdminQ wait task state %u", task->state);
11038c2ecf20Sopenharmony_ci		err = -EINVAL;
11048c2ecf20Sopenharmony_ci		break;
11058c2ecf20Sopenharmony_ci	}
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	dev_dbg(dev, "Waited %u msecs (max %u msecs) for firmware response to op 0x%04x\n",
11088c2ecf20Sopenharmony_ci		jiffies_to_msecs(jiffies - start),
11098c2ecf20Sopenharmony_ci		jiffies_to_msecs(timeout),
11108c2ecf20Sopenharmony_ci		opcode);
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	spin_lock_bh(&pf->aq_wait_lock);
11138c2ecf20Sopenharmony_ci	hlist_del(&task->entry);
11148c2ecf20Sopenharmony_ci	spin_unlock_bh(&pf->aq_wait_lock);
11158c2ecf20Sopenharmony_ci	kfree(task);
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	return err;
11188c2ecf20Sopenharmony_ci}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci/**
11218c2ecf20Sopenharmony_ci * ice_aq_check_events - Check if any thread is waiting for an AdminQ event
11228c2ecf20Sopenharmony_ci * @pf: pointer to the PF private structure
11238c2ecf20Sopenharmony_ci * @opcode: the opcode of the event
11248c2ecf20Sopenharmony_ci * @event: the event to check
11258c2ecf20Sopenharmony_ci *
11268c2ecf20Sopenharmony_ci * Loops over the current list of pending threads waiting for an AdminQ event.
11278c2ecf20Sopenharmony_ci * For each matching task, copy the contents of the event into the task
11288c2ecf20Sopenharmony_ci * structure and wake up the thread.
11298c2ecf20Sopenharmony_ci *
11308c2ecf20Sopenharmony_ci * If multiple threads wait for the same opcode, they will all be woken up.
11318c2ecf20Sopenharmony_ci *
11328c2ecf20Sopenharmony_ci * Note that event->msg_buf will only be duplicated if the event has a buffer
11338c2ecf20Sopenharmony_ci * with enough space already allocated. Otherwise, only the descriptor and
11348c2ecf20Sopenharmony_ci * message length will be copied.
11358c2ecf20Sopenharmony_ci *
11368c2ecf20Sopenharmony_ci * Returns: true if an event was found, false otherwise
11378c2ecf20Sopenharmony_ci */
11388c2ecf20Sopenharmony_cistatic void ice_aq_check_events(struct ice_pf *pf, u16 opcode,
11398c2ecf20Sopenharmony_ci				struct ice_rq_event_info *event)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	struct ice_rq_event_info *task_ev;
11428c2ecf20Sopenharmony_ci	struct ice_aq_task *task;
11438c2ecf20Sopenharmony_ci	bool found = false;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	spin_lock_bh(&pf->aq_wait_lock);
11468c2ecf20Sopenharmony_ci	hlist_for_each_entry(task, &pf->aq_wait_list, entry) {
11478c2ecf20Sopenharmony_ci		if (task->state || task->opcode != opcode)
11488c2ecf20Sopenharmony_ci			continue;
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci		task_ev = task->event;
11518c2ecf20Sopenharmony_ci		memcpy(&task_ev->desc, &event->desc, sizeof(event->desc));
11528c2ecf20Sopenharmony_ci		task_ev->msg_len = event->msg_len;
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci		/* Only copy the data buffer if a destination was set */
11558c2ecf20Sopenharmony_ci		if (task_ev->msg_buf && task_ev->buf_len >= event->buf_len) {
11568c2ecf20Sopenharmony_ci			memcpy(task_ev->msg_buf, event->msg_buf,
11578c2ecf20Sopenharmony_ci			       event->buf_len);
11588c2ecf20Sopenharmony_ci			task_ev->buf_len = event->buf_len;
11598c2ecf20Sopenharmony_ci		}
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci		task->state = ICE_AQ_TASK_COMPLETE;
11628c2ecf20Sopenharmony_ci		found = true;
11638c2ecf20Sopenharmony_ci	}
11648c2ecf20Sopenharmony_ci	spin_unlock_bh(&pf->aq_wait_lock);
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	if (found)
11678c2ecf20Sopenharmony_ci		wake_up(&pf->aq_wait_queue);
11688c2ecf20Sopenharmony_ci}
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci/**
11718c2ecf20Sopenharmony_ci * ice_aq_cancel_waiting_tasks - Immediately cancel all waiting tasks
11728c2ecf20Sopenharmony_ci * @pf: the PF private structure
11738c2ecf20Sopenharmony_ci *
11748c2ecf20Sopenharmony_ci * Set all waiting tasks to ICE_AQ_TASK_CANCELED, and wake up their threads.
11758c2ecf20Sopenharmony_ci * This will then cause ice_aq_wait_for_event to exit with -ECANCELED.
11768c2ecf20Sopenharmony_ci */
11778c2ecf20Sopenharmony_cistatic void ice_aq_cancel_waiting_tasks(struct ice_pf *pf)
11788c2ecf20Sopenharmony_ci{
11798c2ecf20Sopenharmony_ci	struct ice_aq_task *task;
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	spin_lock_bh(&pf->aq_wait_lock);
11828c2ecf20Sopenharmony_ci	hlist_for_each_entry(task, &pf->aq_wait_list, entry)
11838c2ecf20Sopenharmony_ci		task->state = ICE_AQ_TASK_CANCELED;
11848c2ecf20Sopenharmony_ci	spin_unlock_bh(&pf->aq_wait_lock);
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	wake_up(&pf->aq_wait_queue);
11878c2ecf20Sopenharmony_ci}
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci/**
11908c2ecf20Sopenharmony_ci * __ice_clean_ctrlq - helper function to clean controlq rings
11918c2ecf20Sopenharmony_ci * @pf: ptr to struct ice_pf
11928c2ecf20Sopenharmony_ci * @q_type: specific Control queue type
11938c2ecf20Sopenharmony_ci */
11948c2ecf20Sopenharmony_cistatic int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type)
11958c2ecf20Sopenharmony_ci{
11968c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
11978c2ecf20Sopenharmony_ci	struct ice_rq_event_info event;
11988c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
11998c2ecf20Sopenharmony_ci	struct ice_ctl_q_info *cq;
12008c2ecf20Sopenharmony_ci	u16 pending, i = 0;
12018c2ecf20Sopenharmony_ci	const char *qtype;
12028c2ecf20Sopenharmony_ci	u32 oldval, val;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	/* Do not clean control queue if/when PF reset fails */
12058c2ecf20Sopenharmony_ci	if (test_bit(__ICE_RESET_FAILED, pf->state))
12068c2ecf20Sopenharmony_ci		return 0;
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	switch (q_type) {
12098c2ecf20Sopenharmony_ci	case ICE_CTL_Q_ADMIN:
12108c2ecf20Sopenharmony_ci		cq = &hw->adminq;
12118c2ecf20Sopenharmony_ci		qtype = "Admin";
12128c2ecf20Sopenharmony_ci		break;
12138c2ecf20Sopenharmony_ci	case ICE_CTL_Q_MAILBOX:
12148c2ecf20Sopenharmony_ci		cq = &hw->mailboxq;
12158c2ecf20Sopenharmony_ci		qtype = "Mailbox";
12168c2ecf20Sopenharmony_ci		break;
12178c2ecf20Sopenharmony_ci	default:
12188c2ecf20Sopenharmony_ci		dev_warn(dev, "Unknown control queue type 0x%x\n", q_type);
12198c2ecf20Sopenharmony_ci		return 0;
12208c2ecf20Sopenharmony_ci	}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	/* check for error indications - PF_xx_AxQLEN register layout for
12238c2ecf20Sopenharmony_ci	 * FW/MBX/SB are identical so just use defines for PF_FW_AxQLEN.
12248c2ecf20Sopenharmony_ci	 */
12258c2ecf20Sopenharmony_ci	val = rd32(hw, cq->rq.len);
12268c2ecf20Sopenharmony_ci	if (val & (PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M |
12278c2ecf20Sopenharmony_ci		   PF_FW_ARQLEN_ARQCRIT_M)) {
12288c2ecf20Sopenharmony_ci		oldval = val;
12298c2ecf20Sopenharmony_ci		if (val & PF_FW_ARQLEN_ARQVFE_M)
12308c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Receive Queue VF Error detected\n",
12318c2ecf20Sopenharmony_ci				qtype);
12328c2ecf20Sopenharmony_ci		if (val & PF_FW_ARQLEN_ARQOVFL_M) {
12338c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Receive Queue Overflow Error detected\n",
12348c2ecf20Sopenharmony_ci				qtype);
12358c2ecf20Sopenharmony_ci		}
12368c2ecf20Sopenharmony_ci		if (val & PF_FW_ARQLEN_ARQCRIT_M)
12378c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Receive Queue Critical Error detected\n",
12388c2ecf20Sopenharmony_ci				qtype);
12398c2ecf20Sopenharmony_ci		val &= ~(PF_FW_ARQLEN_ARQVFE_M | PF_FW_ARQLEN_ARQOVFL_M |
12408c2ecf20Sopenharmony_ci			 PF_FW_ARQLEN_ARQCRIT_M);
12418c2ecf20Sopenharmony_ci		if (oldval != val)
12428c2ecf20Sopenharmony_ci			wr32(hw, cq->rq.len, val);
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	val = rd32(hw, cq->sq.len);
12468c2ecf20Sopenharmony_ci	if (val & (PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M |
12478c2ecf20Sopenharmony_ci		   PF_FW_ATQLEN_ATQCRIT_M)) {
12488c2ecf20Sopenharmony_ci		oldval = val;
12498c2ecf20Sopenharmony_ci		if (val & PF_FW_ATQLEN_ATQVFE_M)
12508c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Send Queue VF Error detected\n",
12518c2ecf20Sopenharmony_ci				qtype);
12528c2ecf20Sopenharmony_ci		if (val & PF_FW_ATQLEN_ATQOVFL_M) {
12538c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Send Queue Overflow Error detected\n",
12548c2ecf20Sopenharmony_ci				qtype);
12558c2ecf20Sopenharmony_ci		}
12568c2ecf20Sopenharmony_ci		if (val & PF_FW_ATQLEN_ATQCRIT_M)
12578c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Send Queue Critical Error detected\n",
12588c2ecf20Sopenharmony_ci				qtype);
12598c2ecf20Sopenharmony_ci		val &= ~(PF_FW_ATQLEN_ATQVFE_M | PF_FW_ATQLEN_ATQOVFL_M |
12608c2ecf20Sopenharmony_ci			 PF_FW_ATQLEN_ATQCRIT_M);
12618c2ecf20Sopenharmony_ci		if (oldval != val)
12628c2ecf20Sopenharmony_ci			wr32(hw, cq->sq.len, val);
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci
12658c2ecf20Sopenharmony_ci	event.buf_len = cq->rq_buf_size;
12668c2ecf20Sopenharmony_ci	event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
12678c2ecf20Sopenharmony_ci	if (!event.msg_buf)
12688c2ecf20Sopenharmony_ci		return 0;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	do {
12718c2ecf20Sopenharmony_ci		enum ice_status ret;
12728c2ecf20Sopenharmony_ci		u16 opcode;
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci		ret = ice_clean_rq_elem(hw, cq, &event, &pending);
12758c2ecf20Sopenharmony_ci		if (ret == ICE_ERR_AQ_NO_WORK)
12768c2ecf20Sopenharmony_ci			break;
12778c2ecf20Sopenharmony_ci		if (ret) {
12788c2ecf20Sopenharmony_ci			dev_err(dev, "%s Receive Queue event error %s\n", qtype,
12798c2ecf20Sopenharmony_ci				ice_stat_str(ret));
12808c2ecf20Sopenharmony_ci			break;
12818c2ecf20Sopenharmony_ci		}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci		opcode = le16_to_cpu(event.desc.opcode);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci		/* Notify any thread that might be waiting for this event */
12868c2ecf20Sopenharmony_ci		ice_aq_check_events(pf, opcode, &event);
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci		switch (opcode) {
12898c2ecf20Sopenharmony_ci		case ice_aqc_opc_get_link_status:
12908c2ecf20Sopenharmony_ci			if (ice_handle_link_event(pf, &event))
12918c2ecf20Sopenharmony_ci				dev_err(dev, "Could not handle link event\n");
12928c2ecf20Sopenharmony_ci			break;
12938c2ecf20Sopenharmony_ci		case ice_aqc_opc_event_lan_overflow:
12948c2ecf20Sopenharmony_ci			ice_vf_lan_overflow_event(pf, &event);
12958c2ecf20Sopenharmony_ci			break;
12968c2ecf20Sopenharmony_ci		case ice_mbx_opc_send_msg_to_pf:
12978c2ecf20Sopenharmony_ci			ice_vc_process_vf_msg(pf, &event);
12988c2ecf20Sopenharmony_ci			break;
12998c2ecf20Sopenharmony_ci		case ice_aqc_opc_fw_logging:
13008c2ecf20Sopenharmony_ci			ice_output_fw_log(hw, &event.desc, event.msg_buf);
13018c2ecf20Sopenharmony_ci			break;
13028c2ecf20Sopenharmony_ci		case ice_aqc_opc_lldp_set_mib_change:
13038c2ecf20Sopenharmony_ci			ice_dcb_process_lldp_set_mib_change(pf, &event);
13048c2ecf20Sopenharmony_ci			break;
13058c2ecf20Sopenharmony_ci		default:
13068c2ecf20Sopenharmony_ci			dev_dbg(dev, "%s Receive Queue unknown event 0x%04x ignored\n",
13078c2ecf20Sopenharmony_ci				qtype, opcode);
13088c2ecf20Sopenharmony_ci			break;
13098c2ecf20Sopenharmony_ci		}
13108c2ecf20Sopenharmony_ci	} while (pending && (i++ < ICE_DFLT_IRQ_WORK));
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	kfree(event.msg_buf);
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	return pending && (i == ICE_DFLT_IRQ_WORK);
13158c2ecf20Sopenharmony_ci}
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci/**
13188c2ecf20Sopenharmony_ci * ice_ctrlq_pending - check if there is a difference between ntc and ntu
13198c2ecf20Sopenharmony_ci * @hw: pointer to hardware info
13208c2ecf20Sopenharmony_ci * @cq: control queue information
13218c2ecf20Sopenharmony_ci *
13228c2ecf20Sopenharmony_ci * returns true if there are pending messages in a queue, false if there aren't
13238c2ecf20Sopenharmony_ci */
13248c2ecf20Sopenharmony_cistatic bool ice_ctrlq_pending(struct ice_hw *hw, struct ice_ctl_q_info *cq)
13258c2ecf20Sopenharmony_ci{
13268c2ecf20Sopenharmony_ci	u16 ntu;
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	ntu = (u16)(rd32(hw, cq->rq.head) & cq->rq.head_mask);
13298c2ecf20Sopenharmony_ci	return cq->rq.next_to_clean != ntu;
13308c2ecf20Sopenharmony_ci}
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci/**
13338c2ecf20Sopenharmony_ci * ice_clean_adminq_subtask - clean the AdminQ rings
13348c2ecf20Sopenharmony_ci * @pf: board private structure
13358c2ecf20Sopenharmony_ci */
13368c2ecf20Sopenharmony_cistatic void ice_clean_adminq_subtask(struct ice_pf *pf)
13378c2ecf20Sopenharmony_ci{
13388c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
13418c2ecf20Sopenharmony_ci		return;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	if (__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN))
13448c2ecf20Sopenharmony_ci		return;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	clear_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state);
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_ci	/* There might be a situation where new messages arrive to a control
13498c2ecf20Sopenharmony_ci	 * queue between processing the last message and clearing the
13508c2ecf20Sopenharmony_ci	 * EVENT_PENDING bit. So before exiting, check queue head again (using
13518c2ecf20Sopenharmony_ci	 * ice_ctrlq_pending) and process new messages if any.
13528c2ecf20Sopenharmony_ci	 */
13538c2ecf20Sopenharmony_ci	if (ice_ctrlq_pending(hw, &hw->adminq))
13548c2ecf20Sopenharmony_ci		__ice_clean_ctrlq(pf, ICE_CTL_Q_ADMIN);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	ice_flush(hw);
13578c2ecf20Sopenharmony_ci}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci/**
13608c2ecf20Sopenharmony_ci * ice_clean_mailboxq_subtask - clean the MailboxQ rings
13618c2ecf20Sopenharmony_ci * @pf: board private structure
13628c2ecf20Sopenharmony_ci */
13638c2ecf20Sopenharmony_cistatic void ice_clean_mailboxq_subtask(struct ice_pf *pf)
13648c2ecf20Sopenharmony_ci{
13658c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state))
13688c2ecf20Sopenharmony_ci		return;
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	if (__ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX))
13718c2ecf20Sopenharmony_ci		return;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	clear_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state);
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	if (ice_ctrlq_pending(hw, &hw->mailboxq))
13768c2ecf20Sopenharmony_ci		__ice_clean_ctrlq(pf, ICE_CTL_Q_MAILBOX);
13778c2ecf20Sopenharmony_ci
13788c2ecf20Sopenharmony_ci	ice_flush(hw);
13798c2ecf20Sopenharmony_ci}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_ci/**
13828c2ecf20Sopenharmony_ci * ice_service_task_schedule - schedule the service task to wake up
13838c2ecf20Sopenharmony_ci * @pf: board private structure
13848c2ecf20Sopenharmony_ci *
13858c2ecf20Sopenharmony_ci * If not already scheduled, this puts the task into the work queue.
13868c2ecf20Sopenharmony_ci */
13878c2ecf20Sopenharmony_civoid ice_service_task_schedule(struct ice_pf *pf)
13888c2ecf20Sopenharmony_ci{
13898c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_SERVICE_DIS, pf->state) &&
13908c2ecf20Sopenharmony_ci	    !test_and_set_bit(__ICE_SERVICE_SCHED, pf->state) &&
13918c2ecf20Sopenharmony_ci	    !test_bit(__ICE_NEEDS_RESTART, pf->state))
13928c2ecf20Sopenharmony_ci		queue_work(ice_wq, &pf->serv_task);
13938c2ecf20Sopenharmony_ci}
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci/**
13968c2ecf20Sopenharmony_ci * ice_service_task_complete - finish up the service task
13978c2ecf20Sopenharmony_ci * @pf: board private structure
13988c2ecf20Sopenharmony_ci */
13998c2ecf20Sopenharmony_cistatic void ice_service_task_complete(struct ice_pf *pf)
14008c2ecf20Sopenharmony_ci{
14018c2ecf20Sopenharmony_ci	WARN_ON(!test_bit(__ICE_SERVICE_SCHED, pf->state));
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	/* force memory (pf->state) to sync before next service task */
14048c2ecf20Sopenharmony_ci	smp_mb__before_atomic();
14058c2ecf20Sopenharmony_ci	clear_bit(__ICE_SERVICE_SCHED, pf->state);
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci/**
14098c2ecf20Sopenharmony_ci * ice_service_task_stop - stop service task and cancel works
14108c2ecf20Sopenharmony_ci * @pf: board private structure
14118c2ecf20Sopenharmony_ci *
14128c2ecf20Sopenharmony_ci * Return 0 if the __ICE_SERVICE_DIS bit was not already set,
14138c2ecf20Sopenharmony_ci * 1 otherwise.
14148c2ecf20Sopenharmony_ci */
14158c2ecf20Sopenharmony_cistatic int ice_service_task_stop(struct ice_pf *pf)
14168c2ecf20Sopenharmony_ci{
14178c2ecf20Sopenharmony_ci	int ret;
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	ret = test_and_set_bit(__ICE_SERVICE_DIS, pf->state);
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	if (pf->serv_tmr.function)
14228c2ecf20Sopenharmony_ci		del_timer_sync(&pf->serv_tmr);
14238c2ecf20Sopenharmony_ci	if (pf->serv_task.func)
14248c2ecf20Sopenharmony_ci		cancel_work_sync(&pf->serv_task);
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	clear_bit(__ICE_SERVICE_SCHED, pf->state);
14278c2ecf20Sopenharmony_ci	return ret;
14288c2ecf20Sopenharmony_ci}
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci/**
14318c2ecf20Sopenharmony_ci * ice_service_task_restart - restart service task and schedule works
14328c2ecf20Sopenharmony_ci * @pf: board private structure
14338c2ecf20Sopenharmony_ci *
14348c2ecf20Sopenharmony_ci * This function is needed for suspend and resume works (e.g WoL scenario)
14358c2ecf20Sopenharmony_ci */
14368c2ecf20Sopenharmony_cistatic void ice_service_task_restart(struct ice_pf *pf)
14378c2ecf20Sopenharmony_ci{
14388c2ecf20Sopenharmony_ci	clear_bit(__ICE_SERVICE_DIS, pf->state);
14398c2ecf20Sopenharmony_ci	ice_service_task_schedule(pf);
14408c2ecf20Sopenharmony_ci}
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci/**
14438c2ecf20Sopenharmony_ci * ice_service_timer - timer callback to schedule service task
14448c2ecf20Sopenharmony_ci * @t: pointer to timer_list
14458c2ecf20Sopenharmony_ci */
14468c2ecf20Sopenharmony_cistatic void ice_service_timer(struct timer_list *t)
14478c2ecf20Sopenharmony_ci{
14488c2ecf20Sopenharmony_ci	struct ice_pf *pf = from_timer(pf, t, serv_tmr);
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	mod_timer(&pf->serv_tmr, round_jiffies(pf->serv_tmr_period + jiffies));
14518c2ecf20Sopenharmony_ci	ice_service_task_schedule(pf);
14528c2ecf20Sopenharmony_ci}
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci/**
14558c2ecf20Sopenharmony_ci * ice_handle_mdd_event - handle malicious driver detect event
14568c2ecf20Sopenharmony_ci * @pf: pointer to the PF structure
14578c2ecf20Sopenharmony_ci *
14588c2ecf20Sopenharmony_ci * Called from service task. OICR interrupt handler indicates MDD event.
14598c2ecf20Sopenharmony_ci * VF MDD logging is guarded by net_ratelimit. Additional PF and VF log
14608c2ecf20Sopenharmony_ci * messages are wrapped by netif_msg_[rx|tx]_err. Since VF Rx MDD events
14618c2ecf20Sopenharmony_ci * disable the queue, the PF can be configured to reset the VF using ethtool
14628c2ecf20Sopenharmony_ci * private flag mdd-auto-reset-vf.
14638c2ecf20Sopenharmony_ci */
14648c2ecf20Sopenharmony_cistatic void ice_handle_mdd_event(struct ice_pf *pf)
14658c2ecf20Sopenharmony_ci{
14668c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
14678c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
14688c2ecf20Sopenharmony_ci	unsigned int i;
14698c2ecf20Sopenharmony_ci	u32 reg;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci	if (!test_and_clear_bit(__ICE_MDD_EVENT_PENDING, pf->state)) {
14728c2ecf20Sopenharmony_ci		/* Since the VF MDD event logging is rate limited, check if
14738c2ecf20Sopenharmony_ci		 * there are pending MDD events.
14748c2ecf20Sopenharmony_ci		 */
14758c2ecf20Sopenharmony_ci		ice_print_vfs_mdd_events(pf);
14768c2ecf20Sopenharmony_ci		return;
14778c2ecf20Sopenharmony_ci	}
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	/* find what triggered an MDD event */
14808c2ecf20Sopenharmony_ci	reg = rd32(hw, GL_MDET_TX_PQM);
14818c2ecf20Sopenharmony_ci	if (reg & GL_MDET_TX_PQM_VALID_M) {
14828c2ecf20Sopenharmony_ci		u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >>
14838c2ecf20Sopenharmony_ci				GL_MDET_TX_PQM_PF_NUM_S;
14848c2ecf20Sopenharmony_ci		u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >>
14858c2ecf20Sopenharmony_ci				GL_MDET_TX_PQM_VF_NUM_S;
14868c2ecf20Sopenharmony_ci		u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >>
14878c2ecf20Sopenharmony_ci				GL_MDET_TX_PQM_MAL_TYPE_S;
14888c2ecf20Sopenharmony_ci		u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >>
14898c2ecf20Sopenharmony_ci				GL_MDET_TX_PQM_QNUM_S);
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci		if (netif_msg_tx_err(pf))
14928c2ecf20Sopenharmony_ci			dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
14938c2ecf20Sopenharmony_ci				 event, queue, pf_num, vf_num);
14948c2ecf20Sopenharmony_ci		wr32(hw, GL_MDET_TX_PQM, 0xffffffff);
14958c2ecf20Sopenharmony_ci	}
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	reg = rd32(hw, GL_MDET_TX_TCLAN);
14988c2ecf20Sopenharmony_ci	if (reg & GL_MDET_TX_TCLAN_VALID_M) {
14998c2ecf20Sopenharmony_ci		u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >>
15008c2ecf20Sopenharmony_ci				GL_MDET_TX_TCLAN_PF_NUM_S;
15018c2ecf20Sopenharmony_ci		u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >>
15028c2ecf20Sopenharmony_ci				GL_MDET_TX_TCLAN_VF_NUM_S;
15038c2ecf20Sopenharmony_ci		u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >>
15048c2ecf20Sopenharmony_ci				GL_MDET_TX_TCLAN_MAL_TYPE_S;
15058c2ecf20Sopenharmony_ci		u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >>
15068c2ecf20Sopenharmony_ci				GL_MDET_TX_TCLAN_QNUM_S);
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci		if (netif_msg_tx_err(pf))
15098c2ecf20Sopenharmony_ci			dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
15108c2ecf20Sopenharmony_ci				 event, queue, pf_num, vf_num);
15118c2ecf20Sopenharmony_ci		wr32(hw, GL_MDET_TX_TCLAN, 0xffffffff);
15128c2ecf20Sopenharmony_ci	}
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	reg = rd32(hw, GL_MDET_RX);
15158c2ecf20Sopenharmony_ci	if (reg & GL_MDET_RX_VALID_M) {
15168c2ecf20Sopenharmony_ci		u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >>
15178c2ecf20Sopenharmony_ci				GL_MDET_RX_PF_NUM_S;
15188c2ecf20Sopenharmony_ci		u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >>
15198c2ecf20Sopenharmony_ci				GL_MDET_RX_VF_NUM_S;
15208c2ecf20Sopenharmony_ci		u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >>
15218c2ecf20Sopenharmony_ci				GL_MDET_RX_MAL_TYPE_S;
15228c2ecf20Sopenharmony_ci		u16 queue = ((reg & GL_MDET_RX_QNUM_M) >>
15238c2ecf20Sopenharmony_ci				GL_MDET_RX_QNUM_S);
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci		if (netif_msg_rx_err(pf))
15268c2ecf20Sopenharmony_ci			dev_info(dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n",
15278c2ecf20Sopenharmony_ci				 event, queue, pf_num, vf_num);
15288c2ecf20Sopenharmony_ci		wr32(hw, GL_MDET_RX, 0xffffffff);
15298c2ecf20Sopenharmony_ci	}
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	/* check to see if this PF caused an MDD event */
15328c2ecf20Sopenharmony_ci	reg = rd32(hw, PF_MDET_TX_PQM);
15338c2ecf20Sopenharmony_ci	if (reg & PF_MDET_TX_PQM_VALID_M) {
15348c2ecf20Sopenharmony_ci		wr32(hw, PF_MDET_TX_PQM, 0xFFFF);
15358c2ecf20Sopenharmony_ci		if (netif_msg_tx_err(pf))
15368c2ecf20Sopenharmony_ci			dev_info(dev, "Malicious Driver Detection event TX_PQM detected on PF\n");
15378c2ecf20Sopenharmony_ci	}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_ci	reg = rd32(hw, PF_MDET_TX_TCLAN);
15408c2ecf20Sopenharmony_ci	if (reg & PF_MDET_TX_TCLAN_VALID_M) {
15418c2ecf20Sopenharmony_ci		wr32(hw, PF_MDET_TX_TCLAN, 0xFFFF);
15428c2ecf20Sopenharmony_ci		if (netif_msg_tx_err(pf))
15438c2ecf20Sopenharmony_ci			dev_info(dev, "Malicious Driver Detection event TX_TCLAN detected on PF\n");
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci
15468c2ecf20Sopenharmony_ci	reg = rd32(hw, PF_MDET_RX);
15478c2ecf20Sopenharmony_ci	if (reg & PF_MDET_RX_VALID_M) {
15488c2ecf20Sopenharmony_ci		wr32(hw, PF_MDET_RX, 0xFFFF);
15498c2ecf20Sopenharmony_ci		if (netif_msg_rx_err(pf))
15508c2ecf20Sopenharmony_ci			dev_info(dev, "Malicious Driver Detection event RX detected on PF\n");
15518c2ecf20Sopenharmony_ci	}
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	/* Check to see if one of the VFs caused an MDD event, and then
15548c2ecf20Sopenharmony_ci	 * increment counters and set print pending
15558c2ecf20Sopenharmony_ci	 */
15568c2ecf20Sopenharmony_ci	ice_for_each_vf(pf, i) {
15578c2ecf20Sopenharmony_ci		struct ice_vf *vf = &pf->vf[i];
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci		reg = rd32(hw, VP_MDET_TX_PQM(i));
15608c2ecf20Sopenharmony_ci		if (reg & VP_MDET_TX_PQM_VALID_M) {
15618c2ecf20Sopenharmony_ci			wr32(hw, VP_MDET_TX_PQM(i), 0xFFFF);
15628c2ecf20Sopenharmony_ci			vf->mdd_tx_events.count++;
15638c2ecf20Sopenharmony_ci			set_bit(__ICE_MDD_VF_PRINT_PENDING, pf->state);
15648c2ecf20Sopenharmony_ci			if (netif_msg_tx_err(pf))
15658c2ecf20Sopenharmony_ci				dev_info(dev, "Malicious Driver Detection event TX_PQM detected on VF %d\n",
15668c2ecf20Sopenharmony_ci					 i);
15678c2ecf20Sopenharmony_ci		}
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_ci		reg = rd32(hw, VP_MDET_TX_TCLAN(i));
15708c2ecf20Sopenharmony_ci		if (reg & VP_MDET_TX_TCLAN_VALID_M) {
15718c2ecf20Sopenharmony_ci			wr32(hw, VP_MDET_TX_TCLAN(i), 0xFFFF);
15728c2ecf20Sopenharmony_ci			vf->mdd_tx_events.count++;
15738c2ecf20Sopenharmony_ci			set_bit(__ICE_MDD_VF_PRINT_PENDING, pf->state);
15748c2ecf20Sopenharmony_ci			if (netif_msg_tx_err(pf))
15758c2ecf20Sopenharmony_ci				dev_info(dev, "Malicious Driver Detection event TX_TCLAN detected on VF %d\n",
15768c2ecf20Sopenharmony_ci					 i);
15778c2ecf20Sopenharmony_ci		}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ci		reg = rd32(hw, VP_MDET_TX_TDPU(i));
15808c2ecf20Sopenharmony_ci		if (reg & VP_MDET_TX_TDPU_VALID_M) {
15818c2ecf20Sopenharmony_ci			wr32(hw, VP_MDET_TX_TDPU(i), 0xFFFF);
15828c2ecf20Sopenharmony_ci			vf->mdd_tx_events.count++;
15838c2ecf20Sopenharmony_ci			set_bit(__ICE_MDD_VF_PRINT_PENDING, pf->state);
15848c2ecf20Sopenharmony_ci			if (netif_msg_tx_err(pf))
15858c2ecf20Sopenharmony_ci				dev_info(dev, "Malicious Driver Detection event TX_TDPU detected on VF %d\n",
15868c2ecf20Sopenharmony_ci					 i);
15878c2ecf20Sopenharmony_ci		}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci		reg = rd32(hw, VP_MDET_RX(i));
15908c2ecf20Sopenharmony_ci		if (reg & VP_MDET_RX_VALID_M) {
15918c2ecf20Sopenharmony_ci			wr32(hw, VP_MDET_RX(i), 0xFFFF);
15928c2ecf20Sopenharmony_ci			vf->mdd_rx_events.count++;
15938c2ecf20Sopenharmony_ci			set_bit(__ICE_MDD_VF_PRINT_PENDING, pf->state);
15948c2ecf20Sopenharmony_ci			if (netif_msg_rx_err(pf))
15958c2ecf20Sopenharmony_ci				dev_info(dev, "Malicious Driver Detection event RX detected on VF %d\n",
15968c2ecf20Sopenharmony_ci					 i);
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_ci			/* Since the queue is disabled on VF Rx MDD events, the
15998c2ecf20Sopenharmony_ci			 * PF can be configured to reset the VF through ethtool
16008c2ecf20Sopenharmony_ci			 * private flag mdd-auto-reset-vf.
16018c2ecf20Sopenharmony_ci			 */
16028c2ecf20Sopenharmony_ci			if (test_bit(ICE_FLAG_MDD_AUTO_RESET_VF, pf->flags)) {
16038c2ecf20Sopenharmony_ci				/* VF MDD event counters will be cleared by
16048c2ecf20Sopenharmony_ci				 * reset, so print the event prior to reset.
16058c2ecf20Sopenharmony_ci				 */
16068c2ecf20Sopenharmony_ci				ice_print_vf_rx_mdd_event(vf);
16078c2ecf20Sopenharmony_ci				mutex_lock(&pf->vf[i].cfg_lock);
16088c2ecf20Sopenharmony_ci				ice_reset_vf(&pf->vf[i], false);
16098c2ecf20Sopenharmony_ci				mutex_unlock(&pf->vf[i].cfg_lock);
16108c2ecf20Sopenharmony_ci			}
16118c2ecf20Sopenharmony_ci		}
16128c2ecf20Sopenharmony_ci	}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	ice_print_vfs_mdd_events(pf);
16158c2ecf20Sopenharmony_ci}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_ci/**
16188c2ecf20Sopenharmony_ci * ice_force_phys_link_state - Force the physical link state
16198c2ecf20Sopenharmony_ci * @vsi: VSI to force the physical link state to up/down
16208c2ecf20Sopenharmony_ci * @link_up: true/false indicates to set the physical link to up/down
16218c2ecf20Sopenharmony_ci *
16228c2ecf20Sopenharmony_ci * Force the physical link state by getting the current PHY capabilities from
16238c2ecf20Sopenharmony_ci * hardware and setting the PHY config based on the determined capabilities. If
16248c2ecf20Sopenharmony_ci * link changes a link event will be triggered because both the Enable Automatic
16258c2ecf20Sopenharmony_ci * Link Update and LESM Enable bits are set when setting the PHY capabilities.
16268c2ecf20Sopenharmony_ci *
16278c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
16288c2ecf20Sopenharmony_ci */
16298c2ecf20Sopenharmony_cistatic int ice_force_phys_link_state(struct ice_vsi *vsi, bool link_up)
16308c2ecf20Sopenharmony_ci{
16318c2ecf20Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
16328c2ecf20Sopenharmony_ci	struct ice_aqc_set_phy_cfg_data *cfg;
16338c2ecf20Sopenharmony_ci	struct ice_port_info *pi;
16348c2ecf20Sopenharmony_ci	struct device *dev;
16358c2ecf20Sopenharmony_ci	int retcode;
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	if (!vsi || !vsi->port_info || !vsi->back)
16388c2ecf20Sopenharmony_ci		return -EINVAL;
16398c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_PF)
16408c2ecf20Sopenharmony_ci		return 0;
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(vsi->back);
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci	pi = vsi->port_info;
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
16478c2ecf20Sopenharmony_ci	if (!pcaps)
16488c2ecf20Sopenharmony_ci		return -ENOMEM;
16498c2ecf20Sopenharmony_ci
16508c2ecf20Sopenharmony_ci	retcode = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG, pcaps,
16518c2ecf20Sopenharmony_ci				      NULL);
16528c2ecf20Sopenharmony_ci	if (retcode) {
16538c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to get phy capabilities, VSI %d error %d\n",
16548c2ecf20Sopenharmony_ci			vsi->vsi_num, retcode);
16558c2ecf20Sopenharmony_ci		retcode = -EIO;
16568c2ecf20Sopenharmony_ci		goto out;
16578c2ecf20Sopenharmony_ci	}
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	/* No change in link */
16608c2ecf20Sopenharmony_ci	if (link_up == !!(pcaps->caps & ICE_AQC_PHY_EN_LINK) &&
16618c2ecf20Sopenharmony_ci	    link_up == !!(pi->phy.link_info.link_info & ICE_AQ_LINK_UP))
16628c2ecf20Sopenharmony_ci		goto out;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	/* Use the current user PHY configuration. The current user PHY
16658c2ecf20Sopenharmony_ci	 * configuration is initialized during probe from PHY capabilities
16668c2ecf20Sopenharmony_ci	 * software mode, and updated on set PHY configuration.
16678c2ecf20Sopenharmony_ci	 */
16688c2ecf20Sopenharmony_ci	cfg = kmemdup(&pi->phy.curr_user_phy_cfg, sizeof(*cfg), GFP_KERNEL);
16698c2ecf20Sopenharmony_ci	if (!cfg) {
16708c2ecf20Sopenharmony_ci		retcode = -ENOMEM;
16718c2ecf20Sopenharmony_ci		goto out;
16728c2ecf20Sopenharmony_ci	}
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	cfg->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT;
16758c2ecf20Sopenharmony_ci	if (link_up)
16768c2ecf20Sopenharmony_ci		cfg->caps |= ICE_AQ_PHY_ENA_LINK;
16778c2ecf20Sopenharmony_ci	else
16788c2ecf20Sopenharmony_ci		cfg->caps &= ~ICE_AQ_PHY_ENA_LINK;
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	retcode = ice_aq_set_phy_cfg(&vsi->back->hw, pi, cfg, NULL);
16818c2ecf20Sopenharmony_ci	if (retcode) {
16828c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to set phy config, VSI %d error %d\n",
16838c2ecf20Sopenharmony_ci			vsi->vsi_num, retcode);
16848c2ecf20Sopenharmony_ci		retcode = -EIO;
16858c2ecf20Sopenharmony_ci	}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	kfree(cfg);
16888c2ecf20Sopenharmony_ciout:
16898c2ecf20Sopenharmony_ci	kfree(pcaps);
16908c2ecf20Sopenharmony_ci	return retcode;
16918c2ecf20Sopenharmony_ci}
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci/**
16948c2ecf20Sopenharmony_ci * ice_init_nvm_phy_type - Initialize the NVM PHY type
16958c2ecf20Sopenharmony_ci * @pi: port info structure
16968c2ecf20Sopenharmony_ci *
16978c2ecf20Sopenharmony_ci * Initialize nvm_phy_type_[low|high] for link lenient mode support
16988c2ecf20Sopenharmony_ci */
16998c2ecf20Sopenharmony_cistatic int ice_init_nvm_phy_type(struct ice_port_info *pi)
17008c2ecf20Sopenharmony_ci{
17018c2ecf20Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
17028c2ecf20Sopenharmony_ci	struct ice_pf *pf = pi->hw->back;
17038c2ecf20Sopenharmony_ci	enum ice_status status;
17048c2ecf20Sopenharmony_ci	int err = 0;
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
17078c2ecf20Sopenharmony_ci	if (!pcaps)
17088c2ecf20Sopenharmony_ci		return -ENOMEM;
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA, pcaps,
17118c2ecf20Sopenharmony_ci				     NULL);
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci	if (status) {
17148c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Get PHY capability failed.\n");
17158c2ecf20Sopenharmony_ci		err = -EIO;
17168c2ecf20Sopenharmony_ci		goto out;
17178c2ecf20Sopenharmony_ci	}
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	pf->nvm_phy_type_hi = pcaps->phy_type_high;
17208c2ecf20Sopenharmony_ci	pf->nvm_phy_type_lo = pcaps->phy_type_low;
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ciout:
17238c2ecf20Sopenharmony_ci	kfree(pcaps);
17248c2ecf20Sopenharmony_ci	return err;
17258c2ecf20Sopenharmony_ci}
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci/**
17288c2ecf20Sopenharmony_ci * ice_init_link_dflt_override - Initialize link default override
17298c2ecf20Sopenharmony_ci * @pi: port info structure
17308c2ecf20Sopenharmony_ci *
17318c2ecf20Sopenharmony_ci * Initialize link default override and PHY total port shutdown during probe
17328c2ecf20Sopenharmony_ci */
17338c2ecf20Sopenharmony_cistatic void ice_init_link_dflt_override(struct ice_port_info *pi)
17348c2ecf20Sopenharmony_ci{
17358c2ecf20Sopenharmony_ci	struct ice_link_default_override_tlv *ldo;
17368c2ecf20Sopenharmony_ci	struct ice_pf *pf = pi->hw->back;
17378c2ecf20Sopenharmony_ci
17388c2ecf20Sopenharmony_ci	ldo = &pf->link_dflt_override;
17398c2ecf20Sopenharmony_ci	if (ice_get_link_default_override(ldo, pi))
17408c2ecf20Sopenharmony_ci		return;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	if (!(ldo->options & ICE_LINK_OVERRIDE_PORT_DIS))
17438c2ecf20Sopenharmony_ci		return;
17448c2ecf20Sopenharmony_ci
17458c2ecf20Sopenharmony_ci	/* Enable Total Port Shutdown (override/replace link-down-on-close
17468c2ecf20Sopenharmony_ci	 * ethtool private flag) for ports with Port Disable bit set.
17478c2ecf20Sopenharmony_ci	 */
17488c2ecf20Sopenharmony_ci	set_bit(ICE_FLAG_TOTAL_PORT_SHUTDOWN_ENA, pf->flags);
17498c2ecf20Sopenharmony_ci	set_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags);
17508c2ecf20Sopenharmony_ci}
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci/**
17538c2ecf20Sopenharmony_ci * ice_init_phy_cfg_dflt_override - Initialize PHY cfg default override settings
17548c2ecf20Sopenharmony_ci * @pi: port info structure
17558c2ecf20Sopenharmony_ci *
17568c2ecf20Sopenharmony_ci * If default override is enabled, initialized the user PHY cfg speed and FEC
17578c2ecf20Sopenharmony_ci * settings using the default override mask from the NVM.
17588c2ecf20Sopenharmony_ci *
17598c2ecf20Sopenharmony_ci * The PHY should only be configured with the default override settings the
17608c2ecf20Sopenharmony_ci * first time media is available. The __ICE_LINK_DEFAULT_OVERRIDE_PENDING state
17618c2ecf20Sopenharmony_ci * is used to indicate that the user PHY cfg default override is initialized
17628c2ecf20Sopenharmony_ci * and the PHY has not been configured with the default override settings. The
17638c2ecf20Sopenharmony_ci * state is set here, and cleared in ice_configure_phy the first time the PHY is
17648c2ecf20Sopenharmony_ci * configured.
17658c2ecf20Sopenharmony_ci */
17668c2ecf20Sopenharmony_cistatic void ice_init_phy_cfg_dflt_override(struct ice_port_info *pi)
17678c2ecf20Sopenharmony_ci{
17688c2ecf20Sopenharmony_ci	struct ice_link_default_override_tlv *ldo;
17698c2ecf20Sopenharmony_ci	struct ice_aqc_set_phy_cfg_data *cfg;
17708c2ecf20Sopenharmony_ci	struct ice_phy_info *phy = &pi->phy;
17718c2ecf20Sopenharmony_ci	struct ice_pf *pf = pi->hw->back;
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	ldo = &pf->link_dflt_override;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	/* If link default override is enabled, use to mask NVM PHY capabilities
17768c2ecf20Sopenharmony_ci	 * for speed and FEC default configuration.
17778c2ecf20Sopenharmony_ci	 */
17788c2ecf20Sopenharmony_ci	cfg = &phy->curr_user_phy_cfg;
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	if (ldo->phy_type_low || ldo->phy_type_high) {
17818c2ecf20Sopenharmony_ci		cfg->phy_type_low = pf->nvm_phy_type_lo &
17828c2ecf20Sopenharmony_ci				    cpu_to_le64(ldo->phy_type_low);
17838c2ecf20Sopenharmony_ci		cfg->phy_type_high = pf->nvm_phy_type_hi &
17848c2ecf20Sopenharmony_ci				     cpu_to_le64(ldo->phy_type_high);
17858c2ecf20Sopenharmony_ci	}
17868c2ecf20Sopenharmony_ci	cfg->link_fec_opt = ldo->fec_options;
17878c2ecf20Sopenharmony_ci	phy->curr_user_fec_req = ICE_FEC_AUTO;
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_ci	set_bit(__ICE_LINK_DEFAULT_OVERRIDE_PENDING, pf->state);
17908c2ecf20Sopenharmony_ci}
17918c2ecf20Sopenharmony_ci
17928c2ecf20Sopenharmony_ci/**
17938c2ecf20Sopenharmony_ci * ice_init_phy_user_cfg - Initialize the PHY user configuration
17948c2ecf20Sopenharmony_ci * @pi: port info structure
17958c2ecf20Sopenharmony_ci *
17968c2ecf20Sopenharmony_ci * Initialize the current user PHY configuration, speed, FEC, and FC requested
17978c2ecf20Sopenharmony_ci * mode to default. The PHY defaults are from get PHY capabilities topology
17988c2ecf20Sopenharmony_ci * with media so call when media is first available. An error is returned if
17998c2ecf20Sopenharmony_ci * called when media is not available. The PHY initialization completed state is
18008c2ecf20Sopenharmony_ci * set here.
18018c2ecf20Sopenharmony_ci *
18028c2ecf20Sopenharmony_ci * These configurations are used when setting PHY
18038c2ecf20Sopenharmony_ci * configuration. The user PHY configuration is updated on set PHY
18048c2ecf20Sopenharmony_ci * configuration. Returns 0 on success, negative on failure
18058c2ecf20Sopenharmony_ci */
18068c2ecf20Sopenharmony_cistatic int ice_init_phy_user_cfg(struct ice_port_info *pi)
18078c2ecf20Sopenharmony_ci{
18088c2ecf20Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
18098c2ecf20Sopenharmony_ci	struct ice_phy_info *phy = &pi->phy;
18108c2ecf20Sopenharmony_ci	struct ice_pf *pf = pi->hw->back;
18118c2ecf20Sopenharmony_ci	enum ice_status status;
18128c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
18138c2ecf20Sopenharmony_ci	int err = 0;
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	if (!(phy->link_info.link_info & ICE_AQ_MEDIA_AVAILABLE))
18168c2ecf20Sopenharmony_ci		return -EIO;
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ci	vsi = ice_get_main_vsi(pf);
18198c2ecf20Sopenharmony_ci	if (!vsi)
18208c2ecf20Sopenharmony_ci		return -EINVAL;
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
18238c2ecf20Sopenharmony_ci	if (!pcaps)
18248c2ecf20Sopenharmony_ci		return -ENOMEM;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps,
18278c2ecf20Sopenharmony_ci				     NULL);
18288c2ecf20Sopenharmony_ci	if (status) {
18298c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Get PHY capability failed.\n");
18308c2ecf20Sopenharmony_ci		err = -EIO;
18318c2ecf20Sopenharmony_ci		goto err_out;
18328c2ecf20Sopenharmony_ci	}
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci	ice_copy_phy_caps_to_cfg(pi, pcaps, &pi->phy.curr_user_phy_cfg);
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ci	/* check if lenient mode is supported and enabled */
18378c2ecf20Sopenharmony_ci	if (ice_fw_supports_link_override(&vsi->back->hw) &&
18388c2ecf20Sopenharmony_ci	    !(pcaps->module_compliance_enforcement &
18398c2ecf20Sopenharmony_ci	      ICE_AQC_MOD_ENFORCE_STRICT_MODE)) {
18408c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags);
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci		/* if link default override is enabled, initialize user PHY
18438c2ecf20Sopenharmony_ci		 * configuration with link default override values
18448c2ecf20Sopenharmony_ci		 */
18458c2ecf20Sopenharmony_ci		if (pf->link_dflt_override.options & ICE_LINK_OVERRIDE_EN) {
18468c2ecf20Sopenharmony_ci			ice_init_phy_cfg_dflt_override(pi);
18478c2ecf20Sopenharmony_ci			goto out;
18488c2ecf20Sopenharmony_ci		}
18498c2ecf20Sopenharmony_ci	}
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	/* if link default override is not enabled, initialize PHY using
18528c2ecf20Sopenharmony_ci	 * topology with media
18538c2ecf20Sopenharmony_ci	 */
18548c2ecf20Sopenharmony_ci	phy->curr_user_fec_req = ice_caps_to_fec_mode(pcaps->caps,
18558c2ecf20Sopenharmony_ci						      pcaps->link_fec_options);
18568c2ecf20Sopenharmony_ci	phy->curr_user_fc_req = ice_caps_to_fc_mode(pcaps->caps);
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ciout:
18598c2ecf20Sopenharmony_ci	phy->curr_user_speed_req = ICE_AQ_LINK_SPEED_M;
18608c2ecf20Sopenharmony_ci	set_bit(__ICE_PHY_INIT_COMPLETE, pf->state);
18618c2ecf20Sopenharmony_cierr_out:
18628c2ecf20Sopenharmony_ci	kfree(pcaps);
18638c2ecf20Sopenharmony_ci	return err;
18648c2ecf20Sopenharmony_ci}
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci/**
18678c2ecf20Sopenharmony_ci * ice_configure_phy - configure PHY
18688c2ecf20Sopenharmony_ci * @vsi: VSI of PHY
18698c2ecf20Sopenharmony_ci *
18708c2ecf20Sopenharmony_ci * Set the PHY configuration. If the current PHY configuration is the same as
18718c2ecf20Sopenharmony_ci * the curr_user_phy_cfg, then do nothing to avoid link flap. Otherwise
18728c2ecf20Sopenharmony_ci * configure the based get PHY capabilities for topology with media.
18738c2ecf20Sopenharmony_ci */
18748c2ecf20Sopenharmony_cistatic int ice_configure_phy(struct ice_vsi *vsi)
18758c2ecf20Sopenharmony_ci{
18768c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(vsi->back);
18778c2ecf20Sopenharmony_ci	struct ice_aqc_get_phy_caps_data *pcaps;
18788c2ecf20Sopenharmony_ci	struct ice_aqc_set_phy_cfg_data *cfg;
18798c2ecf20Sopenharmony_ci	struct ice_port_info *pi;
18808c2ecf20Sopenharmony_ci	enum ice_status status;
18818c2ecf20Sopenharmony_ci	int err = 0;
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	pi = vsi->port_info;
18848c2ecf20Sopenharmony_ci	if (!pi)
18858c2ecf20Sopenharmony_ci		return -EINVAL;
18868c2ecf20Sopenharmony_ci
18878c2ecf20Sopenharmony_ci	/* Ensure we have media as we cannot configure a medialess port */
18888c2ecf20Sopenharmony_ci	if (!(pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE))
18898c2ecf20Sopenharmony_ci		return -EPERM;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	ice_print_topo_conflict(vsi);
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_ci	if (vsi->port_info->phy.link_info.topo_media_conflict ==
18948c2ecf20Sopenharmony_ci	    ICE_AQ_LINK_TOPO_UNSUPP_MEDIA)
18958c2ecf20Sopenharmony_ci		return -EPERM;
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags))
18988c2ecf20Sopenharmony_ci		return ice_force_phys_link_state(vsi, true);
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ci	pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
19018c2ecf20Sopenharmony_ci	if (!pcaps)
19028c2ecf20Sopenharmony_ci		return -ENOMEM;
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	/* Get current PHY config */
19058c2ecf20Sopenharmony_ci	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_ACTIVE_CFG, pcaps,
19068c2ecf20Sopenharmony_ci				     NULL);
19078c2ecf20Sopenharmony_ci	if (status) {
19088c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to get PHY configuration, VSI %d error %s\n",
19098c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
19108c2ecf20Sopenharmony_ci		err = -EIO;
19118c2ecf20Sopenharmony_ci		goto done;
19128c2ecf20Sopenharmony_ci	}
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci	/* If PHY enable link is configured and configuration has not changed,
19158c2ecf20Sopenharmony_ci	 * there's nothing to do
19168c2ecf20Sopenharmony_ci	 */
19178c2ecf20Sopenharmony_ci	if (pcaps->caps & ICE_AQC_PHY_EN_LINK &&
19188c2ecf20Sopenharmony_ci	    ice_phy_caps_equals_cfg(pcaps, &pi->phy.curr_user_phy_cfg))
19198c2ecf20Sopenharmony_ci		goto done;
19208c2ecf20Sopenharmony_ci
19218c2ecf20Sopenharmony_ci	/* Use PHY topology as baseline for configuration */
19228c2ecf20Sopenharmony_ci	memset(pcaps, 0, sizeof(*pcaps));
19238c2ecf20Sopenharmony_ci	status = ice_aq_get_phy_caps(pi, false, ICE_AQC_REPORT_TOPO_CAP_MEDIA, pcaps,
19248c2ecf20Sopenharmony_ci				     NULL);
19258c2ecf20Sopenharmony_ci	if (status) {
19268c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to get PHY topology, VSI %d error %s\n",
19278c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
19288c2ecf20Sopenharmony_ci		err = -EIO;
19298c2ecf20Sopenharmony_ci		goto done;
19308c2ecf20Sopenharmony_ci	}
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_ci	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
19338c2ecf20Sopenharmony_ci	if (!cfg) {
19348c2ecf20Sopenharmony_ci		err = -ENOMEM;
19358c2ecf20Sopenharmony_ci		goto done;
19368c2ecf20Sopenharmony_ci	}
19378c2ecf20Sopenharmony_ci
19388c2ecf20Sopenharmony_ci	ice_copy_phy_caps_to_cfg(pi, pcaps, cfg);
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci	/* Speed - If default override pending, use curr_user_phy_cfg set in
19418c2ecf20Sopenharmony_ci	 * ice_init_phy_user_cfg_ldo.
19428c2ecf20Sopenharmony_ci	 */
19438c2ecf20Sopenharmony_ci	if (test_and_clear_bit(__ICE_LINK_DEFAULT_OVERRIDE_PENDING,
19448c2ecf20Sopenharmony_ci			       vsi->back->state)) {
19458c2ecf20Sopenharmony_ci		cfg->phy_type_low = pi->phy.curr_user_phy_cfg.phy_type_low;
19468c2ecf20Sopenharmony_ci		cfg->phy_type_high = pi->phy.curr_user_phy_cfg.phy_type_high;
19478c2ecf20Sopenharmony_ci	} else {
19488c2ecf20Sopenharmony_ci		u64 phy_low = 0, phy_high = 0;
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci		ice_update_phy_type(&phy_low, &phy_high,
19518c2ecf20Sopenharmony_ci				    pi->phy.curr_user_speed_req);
19528c2ecf20Sopenharmony_ci		cfg->phy_type_low = pcaps->phy_type_low & cpu_to_le64(phy_low);
19538c2ecf20Sopenharmony_ci		cfg->phy_type_high = pcaps->phy_type_high &
19548c2ecf20Sopenharmony_ci				     cpu_to_le64(phy_high);
19558c2ecf20Sopenharmony_ci	}
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_ci	/* Can't provide what was requested; use PHY capabilities */
19588c2ecf20Sopenharmony_ci	if (!cfg->phy_type_low && !cfg->phy_type_high) {
19598c2ecf20Sopenharmony_ci		cfg->phy_type_low = pcaps->phy_type_low;
19608c2ecf20Sopenharmony_ci		cfg->phy_type_high = pcaps->phy_type_high;
19618c2ecf20Sopenharmony_ci	}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_ci	/* FEC */
19648c2ecf20Sopenharmony_ci	ice_cfg_phy_fec(pi, cfg, pi->phy.curr_user_fec_req);
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci	/* Can't provide what was requested; use PHY capabilities */
19678c2ecf20Sopenharmony_ci	if (cfg->link_fec_opt !=
19688c2ecf20Sopenharmony_ci	    (cfg->link_fec_opt & pcaps->link_fec_options)) {
19698c2ecf20Sopenharmony_ci		cfg->caps |= pcaps->caps & ICE_AQC_PHY_EN_AUTO_FEC;
19708c2ecf20Sopenharmony_ci		cfg->link_fec_opt = pcaps->link_fec_options;
19718c2ecf20Sopenharmony_ci	}
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci	/* Flow Control - always supported; no need to check against
19748c2ecf20Sopenharmony_ci	 * capabilities
19758c2ecf20Sopenharmony_ci	 */
19768c2ecf20Sopenharmony_ci	ice_cfg_phy_fc(pi, cfg, pi->phy.curr_user_fc_req);
19778c2ecf20Sopenharmony_ci
19788c2ecf20Sopenharmony_ci	/* Enable link and link update */
19798c2ecf20Sopenharmony_ci	cfg->caps |= ICE_AQ_PHY_ENA_AUTO_LINK_UPDT | ICE_AQ_PHY_ENA_LINK;
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	status = ice_aq_set_phy_cfg(&vsi->back->hw, pi, cfg, NULL);
19828c2ecf20Sopenharmony_ci	if (status) {
19838c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to set phy config, VSI %d error %s\n",
19848c2ecf20Sopenharmony_ci			vsi->vsi_num, ice_stat_str(status));
19858c2ecf20Sopenharmony_ci		err = -EIO;
19868c2ecf20Sopenharmony_ci	}
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	kfree(cfg);
19898c2ecf20Sopenharmony_cidone:
19908c2ecf20Sopenharmony_ci	kfree(pcaps);
19918c2ecf20Sopenharmony_ci	return err;
19928c2ecf20Sopenharmony_ci}
19938c2ecf20Sopenharmony_ci
19948c2ecf20Sopenharmony_ci/**
19958c2ecf20Sopenharmony_ci * ice_check_media_subtask - Check for media
19968c2ecf20Sopenharmony_ci * @pf: pointer to PF struct
19978c2ecf20Sopenharmony_ci *
19988c2ecf20Sopenharmony_ci * If media is available, then initialize PHY user configuration if it is not
19998c2ecf20Sopenharmony_ci * been, and configure the PHY if the interface is up.
20008c2ecf20Sopenharmony_ci */
20018c2ecf20Sopenharmony_cistatic void ice_check_media_subtask(struct ice_pf *pf)
20028c2ecf20Sopenharmony_ci{
20038c2ecf20Sopenharmony_ci	struct ice_port_info *pi;
20048c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
20058c2ecf20Sopenharmony_ci	int err;
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_ci	/* No need to check for media if it's already present */
20088c2ecf20Sopenharmony_ci	if (!test_bit(ICE_FLAG_NO_MEDIA, pf->flags))
20098c2ecf20Sopenharmony_ci		return;
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_ci	vsi = ice_get_main_vsi(pf);
20128c2ecf20Sopenharmony_ci	if (!vsi)
20138c2ecf20Sopenharmony_ci		return;
20148c2ecf20Sopenharmony_ci
20158c2ecf20Sopenharmony_ci	/* Refresh link info and check if media is present */
20168c2ecf20Sopenharmony_ci	pi = vsi->port_info;
20178c2ecf20Sopenharmony_ci	err = ice_update_link_info(pi);
20188c2ecf20Sopenharmony_ci	if (err)
20198c2ecf20Sopenharmony_ci		return;
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ci	if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
20228c2ecf20Sopenharmony_ci		if (!test_bit(__ICE_PHY_INIT_COMPLETE, pf->state))
20238c2ecf20Sopenharmony_ci			ice_init_phy_user_cfg(pi);
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci		/* PHY settings are reset on media insertion, reconfigure
20268c2ecf20Sopenharmony_ci		 * PHY to preserve settings.
20278c2ecf20Sopenharmony_ci		 */
20288c2ecf20Sopenharmony_ci		if (test_bit(__ICE_DOWN, vsi->state) &&
20298c2ecf20Sopenharmony_ci		    test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags))
20308c2ecf20Sopenharmony_ci			return;
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci		err = ice_configure_phy(vsi);
20338c2ecf20Sopenharmony_ci		if (!err)
20348c2ecf20Sopenharmony_ci			clear_bit(ICE_FLAG_NO_MEDIA, pf->flags);
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci		/* A Link Status Event will be generated; the event handler
20378c2ecf20Sopenharmony_ci		 * will complete bringing the interface up
20388c2ecf20Sopenharmony_ci		 */
20398c2ecf20Sopenharmony_ci	}
20408c2ecf20Sopenharmony_ci}
20418c2ecf20Sopenharmony_ci
20428c2ecf20Sopenharmony_ci/**
20438c2ecf20Sopenharmony_ci * ice_service_task - manage and run subtasks
20448c2ecf20Sopenharmony_ci * @work: pointer to work_struct contained by the PF struct
20458c2ecf20Sopenharmony_ci */
20468c2ecf20Sopenharmony_cistatic void ice_service_task(struct work_struct *work)
20478c2ecf20Sopenharmony_ci{
20488c2ecf20Sopenharmony_ci	struct ice_pf *pf = container_of(work, struct ice_pf, serv_task);
20498c2ecf20Sopenharmony_ci	unsigned long start_time = jiffies;
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci	/* subtasks */
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	/* process reset requests first */
20548c2ecf20Sopenharmony_ci	ice_reset_subtask(pf);
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	/* bail if a reset/recovery cycle is pending or rebuild failed */
20578c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state) ||
20588c2ecf20Sopenharmony_ci	    test_bit(__ICE_SUSPENDED, pf->state) ||
20598c2ecf20Sopenharmony_ci	    test_bit(__ICE_NEEDS_RESTART, pf->state)) {
20608c2ecf20Sopenharmony_ci		ice_service_task_complete(pf);
20618c2ecf20Sopenharmony_ci		return;
20628c2ecf20Sopenharmony_ci	}
20638c2ecf20Sopenharmony_ci
20648c2ecf20Sopenharmony_ci	ice_clean_adminq_subtask(pf);
20658c2ecf20Sopenharmony_ci	ice_check_media_subtask(pf);
20668c2ecf20Sopenharmony_ci	ice_check_for_hang_subtask(pf);
20678c2ecf20Sopenharmony_ci	ice_sync_fltr_subtask(pf);
20688c2ecf20Sopenharmony_ci	ice_handle_mdd_event(pf);
20698c2ecf20Sopenharmony_ci	ice_watchdog_subtask(pf);
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
20728c2ecf20Sopenharmony_ci		ice_service_task_complete(pf);
20738c2ecf20Sopenharmony_ci		return;
20748c2ecf20Sopenharmony_ci	}
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci	ice_process_vflr_event(pf);
20778c2ecf20Sopenharmony_ci	ice_clean_mailboxq_subtask(pf);
20788c2ecf20Sopenharmony_ci	ice_sync_arfs_fltrs(pf);
20798c2ecf20Sopenharmony_ci	/* Clear __ICE_SERVICE_SCHED flag to allow scheduling next event */
20808c2ecf20Sopenharmony_ci	ice_service_task_complete(pf);
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	/* If the tasks have taken longer than one service timer period
20838c2ecf20Sopenharmony_ci	 * or there is more work to be done, reset the service timer to
20848c2ecf20Sopenharmony_ci	 * schedule the service task now.
20858c2ecf20Sopenharmony_ci	 */
20868c2ecf20Sopenharmony_ci	if (time_after(jiffies, (start_time + pf->serv_tmr_period)) ||
20878c2ecf20Sopenharmony_ci	    test_bit(__ICE_MDD_EVENT_PENDING, pf->state) ||
20888c2ecf20Sopenharmony_ci	    test_bit(__ICE_VFLR_EVENT_PENDING, pf->state) ||
20898c2ecf20Sopenharmony_ci	    test_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state) ||
20908c2ecf20Sopenharmony_ci	    test_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state))
20918c2ecf20Sopenharmony_ci		mod_timer(&pf->serv_tmr, jiffies);
20928c2ecf20Sopenharmony_ci}
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci/**
20958c2ecf20Sopenharmony_ci * ice_set_ctrlq_len - helper function to set controlq length
20968c2ecf20Sopenharmony_ci * @hw: pointer to the HW instance
20978c2ecf20Sopenharmony_ci */
20988c2ecf20Sopenharmony_cistatic void ice_set_ctrlq_len(struct ice_hw *hw)
20998c2ecf20Sopenharmony_ci{
21008c2ecf20Sopenharmony_ci	hw->adminq.num_rq_entries = ICE_AQ_LEN;
21018c2ecf20Sopenharmony_ci	hw->adminq.num_sq_entries = ICE_AQ_LEN;
21028c2ecf20Sopenharmony_ci	hw->adminq.rq_buf_size = ICE_AQ_MAX_BUF_LEN;
21038c2ecf20Sopenharmony_ci	hw->adminq.sq_buf_size = ICE_AQ_MAX_BUF_LEN;
21048c2ecf20Sopenharmony_ci	hw->mailboxq.num_rq_entries = PF_MBX_ARQLEN_ARQLEN_M;
21058c2ecf20Sopenharmony_ci	hw->mailboxq.num_sq_entries = ICE_MBXSQ_LEN;
21068c2ecf20Sopenharmony_ci	hw->mailboxq.rq_buf_size = ICE_MBXQ_MAX_BUF_LEN;
21078c2ecf20Sopenharmony_ci	hw->mailboxq.sq_buf_size = ICE_MBXQ_MAX_BUF_LEN;
21088c2ecf20Sopenharmony_ci}
21098c2ecf20Sopenharmony_ci
21108c2ecf20Sopenharmony_ci/**
21118c2ecf20Sopenharmony_ci * ice_schedule_reset - schedule a reset
21128c2ecf20Sopenharmony_ci * @pf: board private structure
21138c2ecf20Sopenharmony_ci * @reset: reset being requested
21148c2ecf20Sopenharmony_ci */
21158c2ecf20Sopenharmony_ciint ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset)
21168c2ecf20Sopenharmony_ci{
21178c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
21188c2ecf20Sopenharmony_ci
21198c2ecf20Sopenharmony_ci	/* bail out if earlier reset has failed */
21208c2ecf20Sopenharmony_ci	if (test_bit(__ICE_RESET_FAILED, pf->state)) {
21218c2ecf20Sopenharmony_ci		dev_dbg(dev, "earlier reset has failed\n");
21228c2ecf20Sopenharmony_ci		return -EIO;
21238c2ecf20Sopenharmony_ci	}
21248c2ecf20Sopenharmony_ci	/* bail if reset/recovery already in progress */
21258c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state)) {
21268c2ecf20Sopenharmony_ci		dev_dbg(dev, "Reset already in progress\n");
21278c2ecf20Sopenharmony_ci		return -EBUSY;
21288c2ecf20Sopenharmony_ci	}
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci	switch (reset) {
21318c2ecf20Sopenharmony_ci	case ICE_RESET_PFR:
21328c2ecf20Sopenharmony_ci		set_bit(__ICE_PFR_REQ, pf->state);
21338c2ecf20Sopenharmony_ci		break;
21348c2ecf20Sopenharmony_ci	case ICE_RESET_CORER:
21358c2ecf20Sopenharmony_ci		set_bit(__ICE_CORER_REQ, pf->state);
21368c2ecf20Sopenharmony_ci		break;
21378c2ecf20Sopenharmony_ci	case ICE_RESET_GLOBR:
21388c2ecf20Sopenharmony_ci		set_bit(__ICE_GLOBR_REQ, pf->state);
21398c2ecf20Sopenharmony_ci		break;
21408c2ecf20Sopenharmony_ci	default:
21418c2ecf20Sopenharmony_ci		return -EINVAL;
21428c2ecf20Sopenharmony_ci	}
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_ci	ice_service_task_schedule(pf);
21458c2ecf20Sopenharmony_ci	return 0;
21468c2ecf20Sopenharmony_ci}
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci/**
21498c2ecf20Sopenharmony_ci * ice_irq_affinity_notify - Callback for affinity changes
21508c2ecf20Sopenharmony_ci * @notify: context as to what irq was changed
21518c2ecf20Sopenharmony_ci * @mask: the new affinity mask
21528c2ecf20Sopenharmony_ci *
21538c2ecf20Sopenharmony_ci * This is a callback function used by the irq_set_affinity_notifier function
21548c2ecf20Sopenharmony_ci * so that we may register to receive changes to the irq affinity masks.
21558c2ecf20Sopenharmony_ci */
21568c2ecf20Sopenharmony_cistatic void
21578c2ecf20Sopenharmony_ciice_irq_affinity_notify(struct irq_affinity_notify *notify,
21588c2ecf20Sopenharmony_ci			const cpumask_t *mask)
21598c2ecf20Sopenharmony_ci{
21608c2ecf20Sopenharmony_ci	struct ice_q_vector *q_vector =
21618c2ecf20Sopenharmony_ci		container_of(notify, struct ice_q_vector, affinity_notify);
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci	cpumask_copy(&q_vector->affinity_mask, mask);
21648c2ecf20Sopenharmony_ci}
21658c2ecf20Sopenharmony_ci
21668c2ecf20Sopenharmony_ci/**
21678c2ecf20Sopenharmony_ci * ice_irq_affinity_release - Callback for affinity notifier release
21688c2ecf20Sopenharmony_ci * @ref: internal core kernel usage
21698c2ecf20Sopenharmony_ci *
21708c2ecf20Sopenharmony_ci * This is a callback function used by the irq_set_affinity_notifier function
21718c2ecf20Sopenharmony_ci * to inform the current notification subscriber that they will no longer
21728c2ecf20Sopenharmony_ci * receive notifications.
21738c2ecf20Sopenharmony_ci */
21748c2ecf20Sopenharmony_cistatic void ice_irq_affinity_release(struct kref __always_unused *ref) {}
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci/**
21778c2ecf20Sopenharmony_ci * ice_vsi_ena_irq - Enable IRQ for the given VSI
21788c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
21798c2ecf20Sopenharmony_ci */
21808c2ecf20Sopenharmony_cistatic int ice_vsi_ena_irq(struct ice_vsi *vsi)
21818c2ecf20Sopenharmony_ci{
21828c2ecf20Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
21838c2ecf20Sopenharmony_ci	int i;
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, i)
21868c2ecf20Sopenharmony_ci		ice_irq_dynamic_ena(hw, vsi, vsi->q_vectors[i]);
21878c2ecf20Sopenharmony_ci
21888c2ecf20Sopenharmony_ci	ice_flush(hw);
21898c2ecf20Sopenharmony_ci	return 0;
21908c2ecf20Sopenharmony_ci}
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci/**
21938c2ecf20Sopenharmony_ci * ice_vsi_req_irq_msix - get MSI-X vectors from the OS for the VSI
21948c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
21958c2ecf20Sopenharmony_ci * @basename: name for the vector
21968c2ecf20Sopenharmony_ci */
21978c2ecf20Sopenharmony_cistatic int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
21988c2ecf20Sopenharmony_ci{
21998c2ecf20Sopenharmony_ci	int q_vectors = vsi->num_q_vectors;
22008c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
22018c2ecf20Sopenharmony_ci	int base = vsi->base_vector;
22028c2ecf20Sopenharmony_ci	struct device *dev;
22038c2ecf20Sopenharmony_ci	int rx_int_idx = 0;
22048c2ecf20Sopenharmony_ci	int tx_int_idx = 0;
22058c2ecf20Sopenharmony_ci	int vector, err;
22068c2ecf20Sopenharmony_ci	int irq_num;
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
22098c2ecf20Sopenharmony_ci	for (vector = 0; vector < q_vectors; vector++) {
22108c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[vector];
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci		irq_num = pf->msix_entries[base + vector].vector;
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci		if (q_vector->tx.ring && q_vector->rx.ring) {
22158c2ecf20Sopenharmony_ci			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
22168c2ecf20Sopenharmony_ci				 "%s-%s-%d", basename, "TxRx", rx_int_idx++);
22178c2ecf20Sopenharmony_ci			tx_int_idx++;
22188c2ecf20Sopenharmony_ci		} else if (q_vector->rx.ring) {
22198c2ecf20Sopenharmony_ci			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
22208c2ecf20Sopenharmony_ci				 "%s-%s-%d", basename, "rx", rx_int_idx++);
22218c2ecf20Sopenharmony_ci		} else if (q_vector->tx.ring) {
22228c2ecf20Sopenharmony_ci			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
22238c2ecf20Sopenharmony_ci				 "%s-%s-%d", basename, "tx", tx_int_idx++);
22248c2ecf20Sopenharmony_ci		} else {
22258c2ecf20Sopenharmony_ci			/* skip this unused q_vector */
22268c2ecf20Sopenharmony_ci			continue;
22278c2ecf20Sopenharmony_ci		}
22288c2ecf20Sopenharmony_ci		err = devm_request_irq(dev, irq_num, vsi->irq_handler, 0,
22298c2ecf20Sopenharmony_ci				       q_vector->name, q_vector);
22308c2ecf20Sopenharmony_ci		if (err) {
22318c2ecf20Sopenharmony_ci			netdev_err(vsi->netdev, "MSIX request_irq failed, error: %d\n",
22328c2ecf20Sopenharmony_ci				   err);
22338c2ecf20Sopenharmony_ci			goto free_q_irqs;
22348c2ecf20Sopenharmony_ci		}
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci		/* register for affinity change notifications */
22378c2ecf20Sopenharmony_ci		if (!IS_ENABLED(CONFIG_RFS_ACCEL)) {
22388c2ecf20Sopenharmony_ci			struct irq_affinity_notify *affinity_notify;
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci			affinity_notify = &q_vector->affinity_notify;
22418c2ecf20Sopenharmony_ci			affinity_notify->notify = ice_irq_affinity_notify;
22428c2ecf20Sopenharmony_ci			affinity_notify->release = ice_irq_affinity_release;
22438c2ecf20Sopenharmony_ci			irq_set_affinity_notifier(irq_num, affinity_notify);
22448c2ecf20Sopenharmony_ci		}
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci		/* assign the mask for this irq */
22478c2ecf20Sopenharmony_ci		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
22488c2ecf20Sopenharmony_ci	}
22498c2ecf20Sopenharmony_ci
22508c2ecf20Sopenharmony_ci	vsi->irqs_ready = true;
22518c2ecf20Sopenharmony_ci	return 0;
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_cifree_q_irqs:
22548c2ecf20Sopenharmony_ci	while (vector) {
22558c2ecf20Sopenharmony_ci		vector--;
22568c2ecf20Sopenharmony_ci		irq_num = pf->msix_entries[base + vector].vector;
22578c2ecf20Sopenharmony_ci		if (!IS_ENABLED(CONFIG_RFS_ACCEL))
22588c2ecf20Sopenharmony_ci			irq_set_affinity_notifier(irq_num, NULL);
22598c2ecf20Sopenharmony_ci		irq_set_affinity_hint(irq_num, NULL);
22608c2ecf20Sopenharmony_ci		devm_free_irq(dev, irq_num, &vsi->q_vectors[vector]);
22618c2ecf20Sopenharmony_ci	}
22628c2ecf20Sopenharmony_ci	return err;
22638c2ecf20Sopenharmony_ci}
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci/**
22668c2ecf20Sopenharmony_ci * ice_xdp_alloc_setup_rings - Allocate and setup Tx rings for XDP
22678c2ecf20Sopenharmony_ci * @vsi: VSI to setup Tx rings used by XDP
22688c2ecf20Sopenharmony_ci *
22698c2ecf20Sopenharmony_ci * Return 0 on success and negative value on error
22708c2ecf20Sopenharmony_ci */
22718c2ecf20Sopenharmony_cistatic int ice_xdp_alloc_setup_rings(struct ice_vsi *vsi)
22728c2ecf20Sopenharmony_ci{
22738c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(vsi->back);
22748c2ecf20Sopenharmony_ci	int i;
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_xdp_txq; i++) {
22778c2ecf20Sopenharmony_ci		u16 xdp_q_idx = vsi->alloc_txq + i;
22788c2ecf20Sopenharmony_ci		struct ice_ring *xdp_ring;
22798c2ecf20Sopenharmony_ci
22808c2ecf20Sopenharmony_ci		xdp_ring = kzalloc(sizeof(*xdp_ring), GFP_KERNEL);
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci		if (!xdp_ring)
22838c2ecf20Sopenharmony_ci			goto free_xdp_rings;
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci		xdp_ring->q_index = xdp_q_idx;
22868c2ecf20Sopenharmony_ci		xdp_ring->reg_idx = vsi->txq_map[xdp_q_idx];
22878c2ecf20Sopenharmony_ci		xdp_ring->ring_active = false;
22888c2ecf20Sopenharmony_ci		xdp_ring->vsi = vsi;
22898c2ecf20Sopenharmony_ci		xdp_ring->netdev = NULL;
22908c2ecf20Sopenharmony_ci		xdp_ring->dev = dev;
22918c2ecf20Sopenharmony_ci		xdp_ring->count = vsi->num_tx_desc;
22928c2ecf20Sopenharmony_ci		WRITE_ONCE(vsi->xdp_rings[i], xdp_ring);
22938c2ecf20Sopenharmony_ci		if (ice_setup_tx_ring(xdp_ring))
22948c2ecf20Sopenharmony_ci			goto free_xdp_rings;
22958c2ecf20Sopenharmony_ci		ice_set_ring_xdp(xdp_ring);
22968c2ecf20Sopenharmony_ci		xdp_ring->xsk_pool = ice_xsk_pool(xdp_ring);
22978c2ecf20Sopenharmony_ci	}
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_ci	return 0;
23008c2ecf20Sopenharmony_ci
23018c2ecf20Sopenharmony_cifree_xdp_rings:
23028c2ecf20Sopenharmony_ci	for (; i >= 0; i--)
23038c2ecf20Sopenharmony_ci		if (vsi->xdp_rings[i] && vsi->xdp_rings[i]->desc)
23048c2ecf20Sopenharmony_ci			ice_free_tx_ring(vsi->xdp_rings[i]);
23058c2ecf20Sopenharmony_ci	return -ENOMEM;
23068c2ecf20Sopenharmony_ci}
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci/**
23098c2ecf20Sopenharmony_ci * ice_vsi_assign_bpf_prog - set or clear bpf prog pointer on VSI
23108c2ecf20Sopenharmony_ci * @vsi: VSI to set the bpf prog on
23118c2ecf20Sopenharmony_ci * @prog: the bpf prog pointer
23128c2ecf20Sopenharmony_ci */
23138c2ecf20Sopenharmony_cistatic void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)
23148c2ecf20Sopenharmony_ci{
23158c2ecf20Sopenharmony_ci	struct bpf_prog *old_prog;
23168c2ecf20Sopenharmony_ci	int i;
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_ci	old_prog = xchg(&vsi->xdp_prog, prog);
23198c2ecf20Sopenharmony_ci	if (old_prog)
23208c2ecf20Sopenharmony_ci		bpf_prog_put(old_prog);
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci	ice_for_each_rxq(vsi, i)
23238c2ecf20Sopenharmony_ci		WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
23248c2ecf20Sopenharmony_ci}
23258c2ecf20Sopenharmony_ci
23268c2ecf20Sopenharmony_ci/**
23278c2ecf20Sopenharmony_ci * ice_prepare_xdp_rings - Allocate, configure and setup Tx rings for XDP
23288c2ecf20Sopenharmony_ci * @vsi: VSI to bring up Tx rings used by XDP
23298c2ecf20Sopenharmony_ci * @prog: bpf program that will be assigned to VSI
23308c2ecf20Sopenharmony_ci *
23318c2ecf20Sopenharmony_ci * Return 0 on success and negative value on error
23328c2ecf20Sopenharmony_ci */
23338c2ecf20Sopenharmony_ciint ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)
23348c2ecf20Sopenharmony_ci{
23358c2ecf20Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
23368c2ecf20Sopenharmony_ci	int xdp_rings_rem = vsi->num_xdp_txq;
23378c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
23388c2ecf20Sopenharmony_ci	struct ice_qs_cfg xdp_qs_cfg = {
23398c2ecf20Sopenharmony_ci		.qs_mutex = &pf->avail_q_mutex,
23408c2ecf20Sopenharmony_ci		.pf_map = pf->avail_txqs,
23418c2ecf20Sopenharmony_ci		.pf_map_size = pf->max_pf_txqs,
23428c2ecf20Sopenharmony_ci		.q_count = vsi->num_xdp_txq,
23438c2ecf20Sopenharmony_ci		.scatter_count = ICE_MAX_SCATTER_TXQS,
23448c2ecf20Sopenharmony_ci		.vsi_map = vsi->txq_map,
23458c2ecf20Sopenharmony_ci		.vsi_map_offset = vsi->alloc_txq,
23468c2ecf20Sopenharmony_ci		.mapping_mode = ICE_VSI_MAP_CONTIG
23478c2ecf20Sopenharmony_ci	};
23488c2ecf20Sopenharmony_ci	enum ice_status status;
23498c2ecf20Sopenharmony_ci	struct device *dev;
23508c2ecf20Sopenharmony_ci	int i, v_idx;
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
23538c2ecf20Sopenharmony_ci	vsi->xdp_rings = devm_kcalloc(dev, vsi->num_xdp_txq,
23548c2ecf20Sopenharmony_ci				      sizeof(*vsi->xdp_rings), GFP_KERNEL);
23558c2ecf20Sopenharmony_ci	if (!vsi->xdp_rings)
23568c2ecf20Sopenharmony_ci		return -ENOMEM;
23578c2ecf20Sopenharmony_ci
23588c2ecf20Sopenharmony_ci	vsi->xdp_mapping_mode = xdp_qs_cfg.mapping_mode;
23598c2ecf20Sopenharmony_ci	if (__ice_vsi_get_qs(&xdp_qs_cfg))
23608c2ecf20Sopenharmony_ci		goto err_map_xdp;
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_ci	if (ice_xdp_alloc_setup_rings(vsi))
23638c2ecf20Sopenharmony_ci		goto clear_xdp_rings;
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci	/* follow the logic from ice_vsi_map_rings_to_vectors */
23668c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, v_idx) {
23678c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[v_idx];
23688c2ecf20Sopenharmony_ci		int xdp_rings_per_v, q_id, q_base;
23698c2ecf20Sopenharmony_ci
23708c2ecf20Sopenharmony_ci		xdp_rings_per_v = DIV_ROUND_UP(xdp_rings_rem,
23718c2ecf20Sopenharmony_ci					       vsi->num_q_vectors - v_idx);
23728c2ecf20Sopenharmony_ci		q_base = vsi->num_xdp_txq - xdp_rings_rem;
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_ci		for (q_id = q_base; q_id < (q_base + xdp_rings_per_v); q_id++) {
23758c2ecf20Sopenharmony_ci			struct ice_ring *xdp_ring = vsi->xdp_rings[q_id];
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ci			xdp_ring->q_vector = q_vector;
23788c2ecf20Sopenharmony_ci			xdp_ring->next = q_vector->tx.ring;
23798c2ecf20Sopenharmony_ci			q_vector->tx.ring = xdp_ring;
23808c2ecf20Sopenharmony_ci		}
23818c2ecf20Sopenharmony_ci		xdp_rings_rem -= xdp_rings_per_v;
23828c2ecf20Sopenharmony_ci	}
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_ci	/* omit the scheduler update if in reset path; XDP queues will be
23858c2ecf20Sopenharmony_ci	 * taken into account at the end of ice_vsi_rebuild, where
23868c2ecf20Sopenharmony_ci	 * ice_cfg_vsi_lan is being called
23878c2ecf20Sopenharmony_ci	 */
23888c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state))
23898c2ecf20Sopenharmony_ci		return 0;
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	/* tell the Tx scheduler that right now we have
23928c2ecf20Sopenharmony_ci	 * additional queues
23938c2ecf20Sopenharmony_ci	 */
23948c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->tc_cfg.numtc; i++)
23958c2ecf20Sopenharmony_ci		max_txqs[i] = vsi->num_txq + vsi->num_xdp_txq;
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_ci	status = ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
23988c2ecf20Sopenharmony_ci				 max_txqs);
23998c2ecf20Sopenharmony_ci	if (status) {
24008c2ecf20Sopenharmony_ci		dev_err(dev, "Failed VSI LAN queue config for XDP, error: %s\n",
24018c2ecf20Sopenharmony_ci			ice_stat_str(status));
24028c2ecf20Sopenharmony_ci		goto clear_xdp_rings;
24038c2ecf20Sopenharmony_ci	}
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	/* assign the prog only when it's not already present on VSI;
24068c2ecf20Sopenharmony_ci	 * this flow is a subject of both ethtool -L and ndo_bpf flows;
24078c2ecf20Sopenharmony_ci	 * VSI rebuild that happens under ethtool -L can expose us to
24088c2ecf20Sopenharmony_ci	 * the bpf_prog refcount issues as we would be swapping same
24098c2ecf20Sopenharmony_ci	 * bpf_prog pointers from vsi->xdp_prog and calling bpf_prog_put
24108c2ecf20Sopenharmony_ci	 * on it as it would be treated as an 'old_prog'; for ndo_bpf
24118c2ecf20Sopenharmony_ci	 * this is not harmful as dev_xdp_install bumps the refcount
24128c2ecf20Sopenharmony_ci	 * before calling the op exposed by the driver;
24138c2ecf20Sopenharmony_ci	 */
24148c2ecf20Sopenharmony_ci	if (!ice_is_xdp_ena_vsi(vsi))
24158c2ecf20Sopenharmony_ci		ice_vsi_assign_bpf_prog(vsi, prog);
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	return 0;
24188c2ecf20Sopenharmony_ciclear_xdp_rings:
24198c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_xdp_txq; i++)
24208c2ecf20Sopenharmony_ci		if (vsi->xdp_rings[i]) {
24218c2ecf20Sopenharmony_ci			kfree_rcu(vsi->xdp_rings[i], rcu);
24228c2ecf20Sopenharmony_ci			vsi->xdp_rings[i] = NULL;
24238c2ecf20Sopenharmony_ci		}
24248c2ecf20Sopenharmony_ci
24258c2ecf20Sopenharmony_cierr_map_xdp:
24268c2ecf20Sopenharmony_ci	mutex_lock(&pf->avail_q_mutex);
24278c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_xdp_txq; i++) {
24288c2ecf20Sopenharmony_ci		clear_bit(vsi->txq_map[i + vsi->alloc_txq], pf->avail_txqs);
24298c2ecf20Sopenharmony_ci		vsi->txq_map[i + vsi->alloc_txq] = ICE_INVAL_Q_INDEX;
24308c2ecf20Sopenharmony_ci	}
24318c2ecf20Sopenharmony_ci	mutex_unlock(&pf->avail_q_mutex);
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_ci	devm_kfree(dev, vsi->xdp_rings);
24348c2ecf20Sopenharmony_ci	return -ENOMEM;
24358c2ecf20Sopenharmony_ci}
24368c2ecf20Sopenharmony_ci
24378c2ecf20Sopenharmony_ci/**
24388c2ecf20Sopenharmony_ci * ice_destroy_xdp_rings - undo the configuration made by ice_prepare_xdp_rings
24398c2ecf20Sopenharmony_ci * @vsi: VSI to remove XDP rings
24408c2ecf20Sopenharmony_ci *
24418c2ecf20Sopenharmony_ci * Detach XDP rings from irq vectors, clean up the PF bitmap and free
24428c2ecf20Sopenharmony_ci * resources
24438c2ecf20Sopenharmony_ci */
24448c2ecf20Sopenharmony_ciint ice_destroy_xdp_rings(struct ice_vsi *vsi)
24458c2ecf20Sopenharmony_ci{
24468c2ecf20Sopenharmony_ci	u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
24478c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
24488c2ecf20Sopenharmony_ci	int i, v_idx;
24498c2ecf20Sopenharmony_ci
24508c2ecf20Sopenharmony_ci	/* q_vectors are freed in reset path so there's no point in detaching
24518c2ecf20Sopenharmony_ci	 * rings; in case of rebuild being triggered not from reset bits
24528c2ecf20Sopenharmony_ci	 * in pf->state won't be set, so additionally check first q_vector
24538c2ecf20Sopenharmony_ci	 * against NULL
24548c2ecf20Sopenharmony_ci	 */
24558c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state) || !vsi->q_vectors[0])
24568c2ecf20Sopenharmony_ci		goto free_qmap;
24578c2ecf20Sopenharmony_ci
24588c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, v_idx) {
24598c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[v_idx];
24608c2ecf20Sopenharmony_ci		struct ice_ring *ring;
24618c2ecf20Sopenharmony_ci
24628c2ecf20Sopenharmony_ci		ice_for_each_ring(ring, q_vector->tx)
24638c2ecf20Sopenharmony_ci			if (!ring->tx_buf || !ice_ring_is_xdp(ring))
24648c2ecf20Sopenharmony_ci				break;
24658c2ecf20Sopenharmony_ci
24668c2ecf20Sopenharmony_ci		/* restore the value of last node prior to XDP setup */
24678c2ecf20Sopenharmony_ci		q_vector->tx.ring = ring;
24688c2ecf20Sopenharmony_ci	}
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_cifree_qmap:
24718c2ecf20Sopenharmony_ci	mutex_lock(&pf->avail_q_mutex);
24728c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_xdp_txq; i++) {
24738c2ecf20Sopenharmony_ci		clear_bit(vsi->txq_map[i + vsi->alloc_txq], pf->avail_txqs);
24748c2ecf20Sopenharmony_ci		vsi->txq_map[i + vsi->alloc_txq] = ICE_INVAL_Q_INDEX;
24758c2ecf20Sopenharmony_ci	}
24768c2ecf20Sopenharmony_ci	mutex_unlock(&pf->avail_q_mutex);
24778c2ecf20Sopenharmony_ci
24788c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_xdp_txq; i++)
24798c2ecf20Sopenharmony_ci		if (vsi->xdp_rings[i]) {
24808c2ecf20Sopenharmony_ci			if (vsi->xdp_rings[i]->desc) {
24818c2ecf20Sopenharmony_ci				synchronize_rcu();
24828c2ecf20Sopenharmony_ci				ice_free_tx_ring(vsi->xdp_rings[i]);
24838c2ecf20Sopenharmony_ci			}
24848c2ecf20Sopenharmony_ci			kfree_rcu(vsi->xdp_rings[i], rcu);
24858c2ecf20Sopenharmony_ci			vsi->xdp_rings[i] = NULL;
24868c2ecf20Sopenharmony_ci		}
24878c2ecf20Sopenharmony_ci
24888c2ecf20Sopenharmony_ci	devm_kfree(ice_pf_to_dev(pf), vsi->xdp_rings);
24898c2ecf20Sopenharmony_ci	vsi->xdp_rings = NULL;
24908c2ecf20Sopenharmony_ci
24918c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state) || !vsi->q_vectors[0])
24928c2ecf20Sopenharmony_ci		return 0;
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	ice_vsi_assign_bpf_prog(vsi, NULL);
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	/* notify Tx scheduler that we destroyed XDP queues and bring
24978c2ecf20Sopenharmony_ci	 * back the old number of child nodes
24988c2ecf20Sopenharmony_ci	 */
24998c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->tc_cfg.numtc; i++)
25008c2ecf20Sopenharmony_ci		max_txqs[i] = vsi->num_txq;
25018c2ecf20Sopenharmony_ci
25028c2ecf20Sopenharmony_ci	/* change number of XDP Tx queues to 0 */
25038c2ecf20Sopenharmony_ci	vsi->num_xdp_txq = 0;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci	return ice_cfg_vsi_lan(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
25068c2ecf20Sopenharmony_ci			       max_txqs);
25078c2ecf20Sopenharmony_ci}
25088c2ecf20Sopenharmony_ci
25098c2ecf20Sopenharmony_ci/**
25108c2ecf20Sopenharmony_ci * ice_xdp_setup_prog - Add or remove XDP eBPF program
25118c2ecf20Sopenharmony_ci * @vsi: VSI to setup XDP for
25128c2ecf20Sopenharmony_ci * @prog: XDP program
25138c2ecf20Sopenharmony_ci * @extack: netlink extended ack
25148c2ecf20Sopenharmony_ci */
25158c2ecf20Sopenharmony_cistatic int
25168c2ecf20Sopenharmony_ciice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,
25178c2ecf20Sopenharmony_ci		   struct netlink_ext_ack *extack)
25188c2ecf20Sopenharmony_ci{
25198c2ecf20Sopenharmony_ci	int frame_size = vsi->netdev->mtu + ICE_ETH_PKT_HDR_PAD;
25208c2ecf20Sopenharmony_ci	bool if_running = netif_running(vsi->netdev);
25218c2ecf20Sopenharmony_ci	int ret = 0, xdp_ring_err = 0;
25228c2ecf20Sopenharmony_ci
25238c2ecf20Sopenharmony_ci	if (frame_size > vsi->rx_buf_len) {
25248c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(extack, "MTU too large for loading XDP");
25258c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
25268c2ecf20Sopenharmony_ci	}
25278c2ecf20Sopenharmony_ci
25288c2ecf20Sopenharmony_ci	/* need to stop netdev while setting up the program for Rx rings */
25298c2ecf20Sopenharmony_ci	if (if_running && !test_and_set_bit(__ICE_DOWN, vsi->state)) {
25308c2ecf20Sopenharmony_ci		ret = ice_down(vsi);
25318c2ecf20Sopenharmony_ci		if (ret) {
25328c2ecf20Sopenharmony_ci			NL_SET_ERR_MSG_MOD(extack, "Preparing device for XDP attach failed");
25338c2ecf20Sopenharmony_ci			return ret;
25348c2ecf20Sopenharmony_ci		}
25358c2ecf20Sopenharmony_ci	}
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci	if (!ice_is_xdp_ena_vsi(vsi) && prog) {
25388c2ecf20Sopenharmony_ci		vsi->num_xdp_txq = vsi->alloc_rxq;
25398c2ecf20Sopenharmony_ci		xdp_ring_err = ice_prepare_xdp_rings(vsi, prog);
25408c2ecf20Sopenharmony_ci		if (xdp_ring_err)
25418c2ecf20Sopenharmony_ci			NL_SET_ERR_MSG_MOD(extack, "Setting up XDP Tx resources failed");
25428c2ecf20Sopenharmony_ci	} else if (ice_is_xdp_ena_vsi(vsi) && !prog) {
25438c2ecf20Sopenharmony_ci		xdp_ring_err = ice_destroy_xdp_rings(vsi);
25448c2ecf20Sopenharmony_ci		if (xdp_ring_err)
25458c2ecf20Sopenharmony_ci			NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Tx resources failed");
25468c2ecf20Sopenharmony_ci	} else {
25478c2ecf20Sopenharmony_ci		/* safe to call even when prog == vsi->xdp_prog as
25488c2ecf20Sopenharmony_ci		 * dev_xdp_install in net/core/dev.c incremented prog's
25498c2ecf20Sopenharmony_ci		 * refcount so corresponding bpf_prog_put won't cause
25508c2ecf20Sopenharmony_ci		 * underflow
25518c2ecf20Sopenharmony_ci		 */
25528c2ecf20Sopenharmony_ci		ice_vsi_assign_bpf_prog(vsi, prog);
25538c2ecf20Sopenharmony_ci	}
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_ci	if (if_running)
25568c2ecf20Sopenharmony_ci		ret = ice_up(vsi);
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_ci	if (!ret && prog && vsi->xsk_pools) {
25598c2ecf20Sopenharmony_ci		int i;
25608c2ecf20Sopenharmony_ci
25618c2ecf20Sopenharmony_ci		ice_for_each_rxq(vsi, i) {
25628c2ecf20Sopenharmony_ci			struct ice_ring *rx_ring = vsi->rx_rings[i];
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci			if (rx_ring->xsk_pool)
25658c2ecf20Sopenharmony_ci				napi_schedule(&rx_ring->q_vector->napi);
25668c2ecf20Sopenharmony_ci		}
25678c2ecf20Sopenharmony_ci	}
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_ci	return (ret || xdp_ring_err) ? -ENOMEM : 0;
25708c2ecf20Sopenharmony_ci}
25718c2ecf20Sopenharmony_ci
25728c2ecf20Sopenharmony_ci/**
25738c2ecf20Sopenharmony_ci * ice_xdp_safe_mode - XDP handler for safe mode
25748c2ecf20Sopenharmony_ci * @dev: netdevice
25758c2ecf20Sopenharmony_ci * @xdp: XDP command
25768c2ecf20Sopenharmony_ci */
25778c2ecf20Sopenharmony_cistatic int ice_xdp_safe_mode(struct net_device __always_unused *dev,
25788c2ecf20Sopenharmony_ci			     struct netdev_bpf *xdp)
25798c2ecf20Sopenharmony_ci{
25808c2ecf20Sopenharmony_ci	NL_SET_ERR_MSG_MOD(xdp->extack,
25818c2ecf20Sopenharmony_ci			   "Please provide working DDP firmware package in order to use XDP\n"
25828c2ecf20Sopenharmony_ci			   "Refer to Documentation/networking/device_drivers/ethernet/intel/ice.rst");
25838c2ecf20Sopenharmony_ci	return -EOPNOTSUPP;
25848c2ecf20Sopenharmony_ci}
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci/**
25878c2ecf20Sopenharmony_ci * ice_xdp - implements XDP handler
25888c2ecf20Sopenharmony_ci * @dev: netdevice
25898c2ecf20Sopenharmony_ci * @xdp: XDP command
25908c2ecf20Sopenharmony_ci */
25918c2ecf20Sopenharmony_cistatic int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp)
25928c2ecf20Sopenharmony_ci{
25938c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(dev);
25948c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
25958c2ecf20Sopenharmony_ci
25968c2ecf20Sopenharmony_ci	if (vsi->type != ICE_VSI_PF) {
25978c2ecf20Sopenharmony_ci		NL_SET_ERR_MSG_MOD(xdp->extack, "XDP can be loaded only on PF VSI");
25988c2ecf20Sopenharmony_ci		return -EINVAL;
25998c2ecf20Sopenharmony_ci	}
26008c2ecf20Sopenharmony_ci
26018c2ecf20Sopenharmony_ci	switch (xdp->command) {
26028c2ecf20Sopenharmony_ci	case XDP_SETUP_PROG:
26038c2ecf20Sopenharmony_ci		return ice_xdp_setup_prog(vsi, xdp->prog, xdp->extack);
26048c2ecf20Sopenharmony_ci	case XDP_SETUP_XSK_POOL:
26058c2ecf20Sopenharmony_ci		return ice_xsk_pool_setup(vsi, xdp->xsk.pool,
26068c2ecf20Sopenharmony_ci					  xdp->xsk.queue_id);
26078c2ecf20Sopenharmony_ci	default:
26088c2ecf20Sopenharmony_ci		return -EINVAL;
26098c2ecf20Sopenharmony_ci	}
26108c2ecf20Sopenharmony_ci}
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci/**
26138c2ecf20Sopenharmony_ci * ice_ena_misc_vector - enable the non-queue interrupts
26148c2ecf20Sopenharmony_ci * @pf: board private structure
26158c2ecf20Sopenharmony_ci */
26168c2ecf20Sopenharmony_cistatic void ice_ena_misc_vector(struct ice_pf *pf)
26178c2ecf20Sopenharmony_ci{
26188c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
26198c2ecf20Sopenharmony_ci	u32 val;
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci	/* Disable anti-spoof detection interrupt to prevent spurious event
26228c2ecf20Sopenharmony_ci	 * interrupts during a function reset. Anti-spoof functionally is
26238c2ecf20Sopenharmony_ci	 * still supported.
26248c2ecf20Sopenharmony_ci	 */
26258c2ecf20Sopenharmony_ci	val = rd32(hw, GL_MDCK_TX_TDPU);
26268c2ecf20Sopenharmony_ci	val |= GL_MDCK_TX_TDPU_RCU_ANTISPOOF_ITR_DIS_M;
26278c2ecf20Sopenharmony_ci	wr32(hw, GL_MDCK_TX_TDPU, val);
26288c2ecf20Sopenharmony_ci
26298c2ecf20Sopenharmony_ci	/* clear things first */
26308c2ecf20Sopenharmony_ci	wr32(hw, PFINT_OICR_ENA, 0);	/* disable all */
26318c2ecf20Sopenharmony_ci	rd32(hw, PFINT_OICR);		/* read to clear */
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci	val = (PFINT_OICR_ECC_ERR_M |
26348c2ecf20Sopenharmony_ci	       PFINT_OICR_MAL_DETECT_M |
26358c2ecf20Sopenharmony_ci	       PFINT_OICR_GRST_M |
26368c2ecf20Sopenharmony_ci	       PFINT_OICR_PCI_EXCEPTION_M |
26378c2ecf20Sopenharmony_ci	       PFINT_OICR_VFLR_M |
26388c2ecf20Sopenharmony_ci	       PFINT_OICR_HMC_ERR_M |
26398c2ecf20Sopenharmony_ci	       PFINT_OICR_PE_CRITERR_M);
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci	wr32(hw, PFINT_OICR_ENA, val);
26428c2ecf20Sopenharmony_ci
26438c2ecf20Sopenharmony_ci	/* SW_ITR_IDX = 0, but don't change INTENA */
26448c2ecf20Sopenharmony_ci	wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
26458c2ecf20Sopenharmony_ci	     GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
26468c2ecf20Sopenharmony_ci}
26478c2ecf20Sopenharmony_ci
26488c2ecf20Sopenharmony_ci/**
26498c2ecf20Sopenharmony_ci * ice_misc_intr - misc interrupt handler
26508c2ecf20Sopenharmony_ci * @irq: interrupt number
26518c2ecf20Sopenharmony_ci * @data: pointer to a q_vector
26528c2ecf20Sopenharmony_ci */
26538c2ecf20Sopenharmony_cistatic irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
26548c2ecf20Sopenharmony_ci{
26558c2ecf20Sopenharmony_ci	struct ice_pf *pf = (struct ice_pf *)data;
26568c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
26578c2ecf20Sopenharmony_ci	irqreturn_t ret = IRQ_NONE;
26588c2ecf20Sopenharmony_ci	struct device *dev;
26598c2ecf20Sopenharmony_ci	u32 oicr, ena_mask;
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
26628c2ecf20Sopenharmony_ci	set_bit(__ICE_ADMINQ_EVENT_PENDING, pf->state);
26638c2ecf20Sopenharmony_ci	set_bit(__ICE_MAILBOXQ_EVENT_PENDING, pf->state);
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci	oicr = rd32(hw, PFINT_OICR);
26668c2ecf20Sopenharmony_ci	ena_mask = rd32(hw, PFINT_OICR_ENA);
26678c2ecf20Sopenharmony_ci
26688c2ecf20Sopenharmony_ci	if (oicr & PFINT_OICR_SWINT_M) {
26698c2ecf20Sopenharmony_ci		ena_mask &= ~PFINT_OICR_SWINT_M;
26708c2ecf20Sopenharmony_ci		pf->sw_int_count++;
26718c2ecf20Sopenharmony_ci	}
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	if (oicr & PFINT_OICR_MAL_DETECT_M) {
26748c2ecf20Sopenharmony_ci		ena_mask &= ~PFINT_OICR_MAL_DETECT_M;
26758c2ecf20Sopenharmony_ci		set_bit(__ICE_MDD_EVENT_PENDING, pf->state);
26768c2ecf20Sopenharmony_ci	}
26778c2ecf20Sopenharmony_ci	if (oicr & PFINT_OICR_VFLR_M) {
26788c2ecf20Sopenharmony_ci		/* disable any further VFLR event notifications */
26798c2ecf20Sopenharmony_ci		if (test_bit(__ICE_VF_RESETS_DISABLED, pf->state)) {
26808c2ecf20Sopenharmony_ci			u32 reg = rd32(hw, PFINT_OICR_ENA);
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci			reg &= ~PFINT_OICR_VFLR_M;
26838c2ecf20Sopenharmony_ci			wr32(hw, PFINT_OICR_ENA, reg);
26848c2ecf20Sopenharmony_ci		} else {
26858c2ecf20Sopenharmony_ci			ena_mask &= ~PFINT_OICR_VFLR_M;
26868c2ecf20Sopenharmony_ci			set_bit(__ICE_VFLR_EVENT_PENDING, pf->state);
26878c2ecf20Sopenharmony_ci		}
26888c2ecf20Sopenharmony_ci	}
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci	if (oicr & PFINT_OICR_GRST_M) {
26918c2ecf20Sopenharmony_ci		u32 reset;
26928c2ecf20Sopenharmony_ci
26938c2ecf20Sopenharmony_ci		/* we have a reset warning */
26948c2ecf20Sopenharmony_ci		ena_mask &= ~PFINT_OICR_GRST_M;
26958c2ecf20Sopenharmony_ci		reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >>
26968c2ecf20Sopenharmony_ci			GLGEN_RSTAT_RESET_TYPE_S;
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci		if (reset == ICE_RESET_CORER)
26998c2ecf20Sopenharmony_ci			pf->corer_count++;
27008c2ecf20Sopenharmony_ci		else if (reset == ICE_RESET_GLOBR)
27018c2ecf20Sopenharmony_ci			pf->globr_count++;
27028c2ecf20Sopenharmony_ci		else if (reset == ICE_RESET_EMPR)
27038c2ecf20Sopenharmony_ci			pf->empr_count++;
27048c2ecf20Sopenharmony_ci		else
27058c2ecf20Sopenharmony_ci			dev_dbg(dev, "Invalid reset type %d\n", reset);
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_ci		/* If a reset cycle isn't already in progress, we set a bit in
27088c2ecf20Sopenharmony_ci		 * pf->state so that the service task can start a reset/rebuild.
27098c2ecf20Sopenharmony_ci		 * We also make note of which reset happened so that peer
27108c2ecf20Sopenharmony_ci		 * devices/drivers can be informed.
27118c2ecf20Sopenharmony_ci		 */
27128c2ecf20Sopenharmony_ci		if (!test_and_set_bit(__ICE_RESET_OICR_RECV, pf->state)) {
27138c2ecf20Sopenharmony_ci			if (reset == ICE_RESET_CORER)
27148c2ecf20Sopenharmony_ci				set_bit(__ICE_CORER_RECV, pf->state);
27158c2ecf20Sopenharmony_ci			else if (reset == ICE_RESET_GLOBR)
27168c2ecf20Sopenharmony_ci				set_bit(__ICE_GLOBR_RECV, pf->state);
27178c2ecf20Sopenharmony_ci			else
27188c2ecf20Sopenharmony_ci				set_bit(__ICE_EMPR_RECV, pf->state);
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_ci			/* There are couple of different bits at play here.
27218c2ecf20Sopenharmony_ci			 * hw->reset_ongoing indicates whether the hardware is
27228c2ecf20Sopenharmony_ci			 * in reset. This is set to true when a reset interrupt
27238c2ecf20Sopenharmony_ci			 * is received and set back to false after the driver
27248c2ecf20Sopenharmony_ci			 * has determined that the hardware is out of reset.
27258c2ecf20Sopenharmony_ci			 *
27268c2ecf20Sopenharmony_ci			 * __ICE_RESET_OICR_RECV in pf->state indicates
27278c2ecf20Sopenharmony_ci			 * that a post reset rebuild is required before the
27288c2ecf20Sopenharmony_ci			 * driver is operational again. This is set above.
27298c2ecf20Sopenharmony_ci			 *
27308c2ecf20Sopenharmony_ci			 * As this is the start of the reset/rebuild cycle, set
27318c2ecf20Sopenharmony_ci			 * both to indicate that.
27328c2ecf20Sopenharmony_ci			 */
27338c2ecf20Sopenharmony_ci			hw->reset_ongoing = true;
27348c2ecf20Sopenharmony_ci		}
27358c2ecf20Sopenharmony_ci	}
27368c2ecf20Sopenharmony_ci
27378c2ecf20Sopenharmony_ci	if (oicr & PFINT_OICR_HMC_ERR_M) {
27388c2ecf20Sopenharmony_ci		ena_mask &= ~PFINT_OICR_HMC_ERR_M;
27398c2ecf20Sopenharmony_ci		dev_dbg(dev, "HMC Error interrupt - info 0x%x, data 0x%x\n",
27408c2ecf20Sopenharmony_ci			rd32(hw, PFHMC_ERRORINFO),
27418c2ecf20Sopenharmony_ci			rd32(hw, PFHMC_ERRORDATA));
27428c2ecf20Sopenharmony_ci	}
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_ci	/* Report any remaining unexpected interrupts */
27458c2ecf20Sopenharmony_ci	oicr &= ena_mask;
27468c2ecf20Sopenharmony_ci	if (oicr) {
27478c2ecf20Sopenharmony_ci		dev_dbg(dev, "unhandled interrupt oicr=0x%08x\n", oicr);
27488c2ecf20Sopenharmony_ci		/* If a critical error is pending there is no choice but to
27498c2ecf20Sopenharmony_ci		 * reset the device.
27508c2ecf20Sopenharmony_ci		 */
27518c2ecf20Sopenharmony_ci		if (oicr & (PFINT_OICR_PE_CRITERR_M |
27528c2ecf20Sopenharmony_ci			    PFINT_OICR_PCI_EXCEPTION_M |
27538c2ecf20Sopenharmony_ci			    PFINT_OICR_ECC_ERR_M)) {
27548c2ecf20Sopenharmony_ci			set_bit(__ICE_PFR_REQ, pf->state);
27558c2ecf20Sopenharmony_ci			ice_service_task_schedule(pf);
27568c2ecf20Sopenharmony_ci		}
27578c2ecf20Sopenharmony_ci	}
27588c2ecf20Sopenharmony_ci	ret = IRQ_HANDLED;
27598c2ecf20Sopenharmony_ci
27608c2ecf20Sopenharmony_ci	ice_service_task_schedule(pf);
27618c2ecf20Sopenharmony_ci	ice_irq_dynamic_ena(hw, NULL, NULL);
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_ci	return ret;
27648c2ecf20Sopenharmony_ci}
27658c2ecf20Sopenharmony_ci
27668c2ecf20Sopenharmony_ci/**
27678c2ecf20Sopenharmony_ci * ice_dis_ctrlq_interrupts - disable control queue interrupts
27688c2ecf20Sopenharmony_ci * @hw: pointer to HW structure
27698c2ecf20Sopenharmony_ci */
27708c2ecf20Sopenharmony_cistatic void ice_dis_ctrlq_interrupts(struct ice_hw *hw)
27718c2ecf20Sopenharmony_ci{
27728c2ecf20Sopenharmony_ci	/* disable Admin queue Interrupt causes */
27738c2ecf20Sopenharmony_ci	wr32(hw, PFINT_FW_CTL,
27748c2ecf20Sopenharmony_ci	     rd32(hw, PFINT_FW_CTL) & ~PFINT_FW_CTL_CAUSE_ENA_M);
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	/* disable Mailbox queue Interrupt causes */
27778c2ecf20Sopenharmony_ci	wr32(hw, PFINT_MBX_CTL,
27788c2ecf20Sopenharmony_ci	     rd32(hw, PFINT_MBX_CTL) & ~PFINT_MBX_CTL_CAUSE_ENA_M);
27798c2ecf20Sopenharmony_ci
27808c2ecf20Sopenharmony_ci	/* disable Control queue Interrupt causes */
27818c2ecf20Sopenharmony_ci	wr32(hw, PFINT_OICR_CTL,
27828c2ecf20Sopenharmony_ci	     rd32(hw, PFINT_OICR_CTL) & ~PFINT_OICR_CTL_CAUSE_ENA_M);
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci	ice_flush(hw);
27858c2ecf20Sopenharmony_ci}
27868c2ecf20Sopenharmony_ci
27878c2ecf20Sopenharmony_ci/**
27888c2ecf20Sopenharmony_ci * ice_free_irq_msix_misc - Unroll misc vector setup
27898c2ecf20Sopenharmony_ci * @pf: board private structure
27908c2ecf20Sopenharmony_ci */
27918c2ecf20Sopenharmony_cistatic void ice_free_irq_msix_misc(struct ice_pf *pf)
27928c2ecf20Sopenharmony_ci{
27938c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	ice_dis_ctrlq_interrupts(hw);
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci	/* disable OICR interrupt */
27988c2ecf20Sopenharmony_ci	wr32(hw, PFINT_OICR_ENA, 0);
27998c2ecf20Sopenharmony_ci	ice_flush(hw);
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_ci	if (pf->msix_entries) {
28028c2ecf20Sopenharmony_ci		synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
28038c2ecf20Sopenharmony_ci		devm_free_irq(ice_pf_to_dev(pf),
28048c2ecf20Sopenharmony_ci			      pf->msix_entries[pf->oicr_idx].vector, pf);
28058c2ecf20Sopenharmony_ci	}
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	pf->num_avail_sw_msix += 1;
28088c2ecf20Sopenharmony_ci	ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID);
28098c2ecf20Sopenharmony_ci}
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci/**
28128c2ecf20Sopenharmony_ci * ice_ena_ctrlq_interrupts - enable control queue interrupts
28138c2ecf20Sopenharmony_ci * @hw: pointer to HW structure
28148c2ecf20Sopenharmony_ci * @reg_idx: HW vector index to associate the control queue interrupts with
28158c2ecf20Sopenharmony_ci */
28168c2ecf20Sopenharmony_cistatic void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 reg_idx)
28178c2ecf20Sopenharmony_ci{
28188c2ecf20Sopenharmony_ci	u32 val;
28198c2ecf20Sopenharmony_ci
28208c2ecf20Sopenharmony_ci	val = ((reg_idx & PFINT_OICR_CTL_MSIX_INDX_M) |
28218c2ecf20Sopenharmony_ci	       PFINT_OICR_CTL_CAUSE_ENA_M);
28228c2ecf20Sopenharmony_ci	wr32(hw, PFINT_OICR_CTL, val);
28238c2ecf20Sopenharmony_ci
28248c2ecf20Sopenharmony_ci	/* enable Admin queue Interrupt causes */
28258c2ecf20Sopenharmony_ci	val = ((reg_idx & PFINT_FW_CTL_MSIX_INDX_M) |
28268c2ecf20Sopenharmony_ci	       PFINT_FW_CTL_CAUSE_ENA_M);
28278c2ecf20Sopenharmony_ci	wr32(hw, PFINT_FW_CTL, val);
28288c2ecf20Sopenharmony_ci
28298c2ecf20Sopenharmony_ci	/* enable Mailbox queue Interrupt causes */
28308c2ecf20Sopenharmony_ci	val = ((reg_idx & PFINT_MBX_CTL_MSIX_INDX_M) |
28318c2ecf20Sopenharmony_ci	       PFINT_MBX_CTL_CAUSE_ENA_M);
28328c2ecf20Sopenharmony_ci	wr32(hw, PFINT_MBX_CTL, val);
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci	ice_flush(hw);
28358c2ecf20Sopenharmony_ci}
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci/**
28388c2ecf20Sopenharmony_ci * ice_req_irq_msix_misc - Setup the misc vector to handle non queue events
28398c2ecf20Sopenharmony_ci * @pf: board private structure
28408c2ecf20Sopenharmony_ci *
28418c2ecf20Sopenharmony_ci * This sets up the handler for MSIX 0, which is used to manage the
28428c2ecf20Sopenharmony_ci * non-queue interrupts, e.g. AdminQ and errors. This is not used
28438c2ecf20Sopenharmony_ci * when in MSI or Legacy interrupt mode.
28448c2ecf20Sopenharmony_ci */
28458c2ecf20Sopenharmony_cistatic int ice_req_irq_msix_misc(struct ice_pf *pf)
28468c2ecf20Sopenharmony_ci{
28478c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
28488c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
28498c2ecf20Sopenharmony_ci	int oicr_idx, err = 0;
28508c2ecf20Sopenharmony_ci
28518c2ecf20Sopenharmony_ci	if (!pf->int_name[0])
28528c2ecf20Sopenharmony_ci		snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
28538c2ecf20Sopenharmony_ci			 dev_driver_string(dev), dev_name(dev));
28548c2ecf20Sopenharmony_ci
28558c2ecf20Sopenharmony_ci	/* Do not request IRQ but do enable OICR interrupt since settings are
28568c2ecf20Sopenharmony_ci	 * lost during reset. Note that this function is called only during
28578c2ecf20Sopenharmony_ci	 * rebuild path and not while reset is in progress.
28588c2ecf20Sopenharmony_ci	 */
28598c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state))
28608c2ecf20Sopenharmony_ci		goto skip_req_irq;
28618c2ecf20Sopenharmony_ci
28628c2ecf20Sopenharmony_ci	/* reserve one vector in irq_tracker for misc interrupts */
28638c2ecf20Sopenharmony_ci	oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
28648c2ecf20Sopenharmony_ci	if (oicr_idx < 0)
28658c2ecf20Sopenharmony_ci		return oicr_idx;
28668c2ecf20Sopenharmony_ci
28678c2ecf20Sopenharmony_ci	pf->num_avail_sw_msix -= 1;
28688c2ecf20Sopenharmony_ci	pf->oicr_idx = (u16)oicr_idx;
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci	err = devm_request_irq(dev, pf->msix_entries[pf->oicr_idx].vector,
28718c2ecf20Sopenharmony_ci			       ice_misc_intr, 0, pf->int_name, pf);
28728c2ecf20Sopenharmony_ci	if (err) {
28738c2ecf20Sopenharmony_ci		dev_err(dev, "devm_request_irq for %s failed: %d\n",
28748c2ecf20Sopenharmony_ci			pf->int_name, err);
28758c2ecf20Sopenharmony_ci		ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
28768c2ecf20Sopenharmony_ci		pf->num_avail_sw_msix += 1;
28778c2ecf20Sopenharmony_ci		return err;
28788c2ecf20Sopenharmony_ci	}
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ciskip_req_irq:
28818c2ecf20Sopenharmony_ci	ice_ena_misc_vector(pf);
28828c2ecf20Sopenharmony_ci
28838c2ecf20Sopenharmony_ci	ice_ena_ctrlq_interrupts(hw, pf->oicr_idx);
28848c2ecf20Sopenharmony_ci	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx),
28858c2ecf20Sopenharmony_ci	     ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	ice_flush(hw);
28888c2ecf20Sopenharmony_ci	ice_irq_dynamic_ena(hw, NULL, NULL);
28898c2ecf20Sopenharmony_ci
28908c2ecf20Sopenharmony_ci	return 0;
28918c2ecf20Sopenharmony_ci}
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci/**
28948c2ecf20Sopenharmony_ci * ice_napi_add - register NAPI handler for the VSI
28958c2ecf20Sopenharmony_ci * @vsi: VSI for which NAPI handler is to be registered
28968c2ecf20Sopenharmony_ci *
28978c2ecf20Sopenharmony_ci * This function is only called in the driver's load path. Registering the NAPI
28988c2ecf20Sopenharmony_ci * handler is done in ice_vsi_alloc_q_vector() for all other cases (i.e. resume,
28998c2ecf20Sopenharmony_ci * reset/rebuild, etc.)
29008c2ecf20Sopenharmony_ci */
29018c2ecf20Sopenharmony_cistatic void ice_napi_add(struct ice_vsi *vsi)
29028c2ecf20Sopenharmony_ci{
29038c2ecf20Sopenharmony_ci	int v_idx;
29048c2ecf20Sopenharmony_ci
29058c2ecf20Sopenharmony_ci	if (!vsi->netdev)
29068c2ecf20Sopenharmony_ci		return;
29078c2ecf20Sopenharmony_ci
29088c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, v_idx)
29098c2ecf20Sopenharmony_ci		netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi,
29108c2ecf20Sopenharmony_ci			       ice_napi_poll, NAPI_POLL_WEIGHT);
29118c2ecf20Sopenharmony_ci}
29128c2ecf20Sopenharmony_ci
29138c2ecf20Sopenharmony_ci/**
29148c2ecf20Sopenharmony_ci * ice_set_ops - set netdev and ethtools ops for the given netdev
29158c2ecf20Sopenharmony_ci * @netdev: netdev instance
29168c2ecf20Sopenharmony_ci */
29178c2ecf20Sopenharmony_cistatic void ice_set_ops(struct net_device *netdev)
29188c2ecf20Sopenharmony_ci{
29198c2ecf20Sopenharmony_ci	struct ice_pf *pf = ice_netdev_to_pf(netdev);
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
29228c2ecf20Sopenharmony_ci		netdev->netdev_ops = &ice_netdev_safe_mode_ops;
29238c2ecf20Sopenharmony_ci		ice_set_ethtool_safe_mode_ops(netdev);
29248c2ecf20Sopenharmony_ci		return;
29258c2ecf20Sopenharmony_ci	}
29268c2ecf20Sopenharmony_ci
29278c2ecf20Sopenharmony_ci	netdev->netdev_ops = &ice_netdev_ops;
29288c2ecf20Sopenharmony_ci	netdev->udp_tunnel_nic_info = &pf->hw.udp_tunnel_nic;
29298c2ecf20Sopenharmony_ci	ice_set_ethtool_ops(netdev);
29308c2ecf20Sopenharmony_ci}
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci/**
29338c2ecf20Sopenharmony_ci * ice_set_netdev_features - set features for the given netdev
29348c2ecf20Sopenharmony_ci * @netdev: netdev instance
29358c2ecf20Sopenharmony_ci */
29368c2ecf20Sopenharmony_cistatic void ice_set_netdev_features(struct net_device *netdev)
29378c2ecf20Sopenharmony_ci{
29388c2ecf20Sopenharmony_ci	struct ice_pf *pf = ice_netdev_to_pf(netdev);
29398c2ecf20Sopenharmony_ci	netdev_features_t csumo_features;
29408c2ecf20Sopenharmony_ci	netdev_features_t vlano_features;
29418c2ecf20Sopenharmony_ci	netdev_features_t dflt_features;
29428c2ecf20Sopenharmony_ci	netdev_features_t tso_features;
29438c2ecf20Sopenharmony_ci
29448c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
29458c2ecf20Sopenharmony_ci		/* safe mode */
29468c2ecf20Sopenharmony_ci		netdev->features = NETIF_F_SG | NETIF_F_HIGHDMA;
29478c2ecf20Sopenharmony_ci		netdev->hw_features = netdev->features;
29488c2ecf20Sopenharmony_ci		return;
29498c2ecf20Sopenharmony_ci	}
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_ci	dflt_features = NETIF_F_SG	|
29528c2ecf20Sopenharmony_ci			NETIF_F_HIGHDMA	|
29538c2ecf20Sopenharmony_ci			NETIF_F_NTUPLE	|
29548c2ecf20Sopenharmony_ci			NETIF_F_RXHASH;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	csumo_features = NETIF_F_RXCSUM	  |
29578c2ecf20Sopenharmony_ci			 NETIF_F_IP_CSUM  |
29588c2ecf20Sopenharmony_ci			 NETIF_F_SCTP_CRC |
29598c2ecf20Sopenharmony_ci			 NETIF_F_IPV6_CSUM;
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_ci	vlano_features = NETIF_F_HW_VLAN_CTAG_FILTER |
29628c2ecf20Sopenharmony_ci			 NETIF_F_HW_VLAN_CTAG_TX     |
29638c2ecf20Sopenharmony_ci			 NETIF_F_HW_VLAN_CTAG_RX;
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci	tso_features = NETIF_F_TSO			|
29668c2ecf20Sopenharmony_ci		       NETIF_F_TSO_ECN			|
29678c2ecf20Sopenharmony_ci		       NETIF_F_TSO6			|
29688c2ecf20Sopenharmony_ci		       NETIF_F_GSO_GRE			|
29698c2ecf20Sopenharmony_ci		       NETIF_F_GSO_UDP_TUNNEL		|
29708c2ecf20Sopenharmony_ci		       NETIF_F_GSO_GRE_CSUM		|
29718c2ecf20Sopenharmony_ci		       NETIF_F_GSO_UDP_TUNNEL_CSUM	|
29728c2ecf20Sopenharmony_ci		       NETIF_F_GSO_PARTIAL		|
29738c2ecf20Sopenharmony_ci		       NETIF_F_GSO_IPXIP4		|
29748c2ecf20Sopenharmony_ci		       NETIF_F_GSO_IPXIP6		|
29758c2ecf20Sopenharmony_ci		       NETIF_F_GSO_UDP_L4;
29768c2ecf20Sopenharmony_ci
29778c2ecf20Sopenharmony_ci	netdev->gso_partial_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM |
29788c2ecf20Sopenharmony_ci					NETIF_F_GSO_GRE_CSUM;
29798c2ecf20Sopenharmony_ci	/* set features that user can change */
29808c2ecf20Sopenharmony_ci	netdev->hw_features = dflt_features | csumo_features |
29818c2ecf20Sopenharmony_ci			      vlano_features | tso_features;
29828c2ecf20Sopenharmony_ci
29838c2ecf20Sopenharmony_ci	/* add support for HW_CSUM on packets with MPLS header */
29848c2ecf20Sopenharmony_ci	netdev->mpls_features =  NETIF_F_HW_CSUM;
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci	/* enable features */
29878c2ecf20Sopenharmony_ci	netdev->features |= netdev->hw_features;
29888c2ecf20Sopenharmony_ci	/* encap and VLAN devices inherit default, csumo and tso features */
29898c2ecf20Sopenharmony_ci	netdev->hw_enc_features |= dflt_features | csumo_features |
29908c2ecf20Sopenharmony_ci				   tso_features;
29918c2ecf20Sopenharmony_ci	netdev->vlan_features |= dflt_features | csumo_features |
29928c2ecf20Sopenharmony_ci				 tso_features;
29938c2ecf20Sopenharmony_ci}
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci/**
29968c2ecf20Sopenharmony_ci * ice_cfg_netdev - Allocate, configure and register a netdev
29978c2ecf20Sopenharmony_ci * @vsi: the VSI associated with the new netdev
29988c2ecf20Sopenharmony_ci *
29998c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on failure
30008c2ecf20Sopenharmony_ci */
30018c2ecf20Sopenharmony_cistatic int ice_cfg_netdev(struct ice_vsi *vsi)
30028c2ecf20Sopenharmony_ci{
30038c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
30048c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np;
30058c2ecf20Sopenharmony_ci	struct net_device *netdev;
30068c2ecf20Sopenharmony_ci	u8 mac_addr[ETH_ALEN];
30078c2ecf20Sopenharmony_ci	int err;
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_ci	err = ice_devlink_create_port(vsi);
30108c2ecf20Sopenharmony_ci	if (err)
30118c2ecf20Sopenharmony_ci		return err;
30128c2ecf20Sopenharmony_ci
30138c2ecf20Sopenharmony_ci	netdev = alloc_etherdev_mqs(sizeof(*np), vsi->alloc_txq,
30148c2ecf20Sopenharmony_ci				    vsi->alloc_rxq);
30158c2ecf20Sopenharmony_ci	if (!netdev) {
30168c2ecf20Sopenharmony_ci		err = -ENOMEM;
30178c2ecf20Sopenharmony_ci		goto err_destroy_devlink_port;
30188c2ecf20Sopenharmony_ci	}
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci	vsi->netdev = netdev;
30218c2ecf20Sopenharmony_ci	np = netdev_priv(netdev);
30228c2ecf20Sopenharmony_ci	np->vsi = vsi;
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci	ice_set_netdev_features(netdev);
30258c2ecf20Sopenharmony_ci
30268c2ecf20Sopenharmony_ci	ice_set_ops(netdev);
30278c2ecf20Sopenharmony_ci
30288c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF) {
30298c2ecf20Sopenharmony_ci		SET_NETDEV_DEV(netdev, ice_pf_to_dev(pf));
30308c2ecf20Sopenharmony_ci		ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr);
30318c2ecf20Sopenharmony_ci		ether_addr_copy(netdev->dev_addr, mac_addr);
30328c2ecf20Sopenharmony_ci		ether_addr_copy(netdev->perm_addr, mac_addr);
30338c2ecf20Sopenharmony_ci	}
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci	netdev->priv_flags |= IFF_UNICAST_FLT;
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci	/* Setup netdev TC information */
30388c2ecf20Sopenharmony_ci	ice_vsi_cfg_netdev_tc(vsi, vsi->tc_cfg.ena_tc);
30398c2ecf20Sopenharmony_ci
30408c2ecf20Sopenharmony_ci	/* setup watchdog timeout value to be 5 second */
30418c2ecf20Sopenharmony_ci	netdev->watchdog_timeo = 5 * HZ;
30428c2ecf20Sopenharmony_ci
30438c2ecf20Sopenharmony_ci	netdev->min_mtu = ETH_MIN_MTU;
30448c2ecf20Sopenharmony_ci	netdev->max_mtu = ICE_MAX_MTU;
30458c2ecf20Sopenharmony_ci
30468c2ecf20Sopenharmony_ci	err = register_netdev(vsi->netdev);
30478c2ecf20Sopenharmony_ci	if (err)
30488c2ecf20Sopenharmony_ci		goto err_free_netdev;
30498c2ecf20Sopenharmony_ci
30508c2ecf20Sopenharmony_ci	devlink_port_type_eth_set(&vsi->devlink_port, vsi->netdev);
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_ci	netif_carrier_off(vsi->netdev);
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci	/* make sure transmit queues start off as stopped */
30558c2ecf20Sopenharmony_ci	netif_tx_stop_all_queues(vsi->netdev);
30568c2ecf20Sopenharmony_ci
30578c2ecf20Sopenharmony_ci	return 0;
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_cierr_free_netdev:
30608c2ecf20Sopenharmony_ci	free_netdev(vsi->netdev);
30618c2ecf20Sopenharmony_ci	vsi->netdev = NULL;
30628c2ecf20Sopenharmony_cierr_destroy_devlink_port:
30638c2ecf20Sopenharmony_ci	ice_devlink_destroy_port(vsi);
30648c2ecf20Sopenharmony_ci	return err;
30658c2ecf20Sopenharmony_ci}
30668c2ecf20Sopenharmony_ci
30678c2ecf20Sopenharmony_ci/**
30688c2ecf20Sopenharmony_ci * ice_fill_rss_lut - Fill the RSS lookup table with default values
30698c2ecf20Sopenharmony_ci * @lut: Lookup table
30708c2ecf20Sopenharmony_ci * @rss_table_size: Lookup table size
30718c2ecf20Sopenharmony_ci * @rss_size: Range of queue number for hashing
30728c2ecf20Sopenharmony_ci */
30738c2ecf20Sopenharmony_civoid ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size)
30748c2ecf20Sopenharmony_ci{
30758c2ecf20Sopenharmony_ci	u16 i;
30768c2ecf20Sopenharmony_ci
30778c2ecf20Sopenharmony_ci	for (i = 0; i < rss_table_size; i++)
30788c2ecf20Sopenharmony_ci		lut[i] = i % rss_size;
30798c2ecf20Sopenharmony_ci}
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci/**
30828c2ecf20Sopenharmony_ci * ice_pf_vsi_setup - Set up a PF VSI
30838c2ecf20Sopenharmony_ci * @pf: board private structure
30848c2ecf20Sopenharmony_ci * @pi: pointer to the port_info instance
30858c2ecf20Sopenharmony_ci *
30868c2ecf20Sopenharmony_ci * Returns pointer to the successfully allocated VSI software struct
30878c2ecf20Sopenharmony_ci * on success, otherwise returns NULL on failure.
30888c2ecf20Sopenharmony_ci */
30898c2ecf20Sopenharmony_cistatic struct ice_vsi *
30908c2ecf20Sopenharmony_ciice_pf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
30918c2ecf20Sopenharmony_ci{
30928c2ecf20Sopenharmony_ci	return ice_vsi_setup(pf, pi, ICE_VSI_PF, ICE_INVAL_VFID);
30938c2ecf20Sopenharmony_ci}
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci/**
30968c2ecf20Sopenharmony_ci * ice_ctrl_vsi_setup - Set up a control VSI
30978c2ecf20Sopenharmony_ci * @pf: board private structure
30988c2ecf20Sopenharmony_ci * @pi: pointer to the port_info instance
30998c2ecf20Sopenharmony_ci *
31008c2ecf20Sopenharmony_ci * Returns pointer to the successfully allocated VSI software struct
31018c2ecf20Sopenharmony_ci * on success, otherwise returns NULL on failure.
31028c2ecf20Sopenharmony_ci */
31038c2ecf20Sopenharmony_cistatic struct ice_vsi *
31048c2ecf20Sopenharmony_ciice_ctrl_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
31058c2ecf20Sopenharmony_ci{
31068c2ecf20Sopenharmony_ci	return ice_vsi_setup(pf, pi, ICE_VSI_CTRL, ICE_INVAL_VFID);
31078c2ecf20Sopenharmony_ci}
31088c2ecf20Sopenharmony_ci
31098c2ecf20Sopenharmony_ci/**
31108c2ecf20Sopenharmony_ci * ice_lb_vsi_setup - Set up a loopback VSI
31118c2ecf20Sopenharmony_ci * @pf: board private structure
31128c2ecf20Sopenharmony_ci * @pi: pointer to the port_info instance
31138c2ecf20Sopenharmony_ci *
31148c2ecf20Sopenharmony_ci * Returns pointer to the successfully allocated VSI software struct
31158c2ecf20Sopenharmony_ci * on success, otherwise returns NULL on failure.
31168c2ecf20Sopenharmony_ci */
31178c2ecf20Sopenharmony_cistruct ice_vsi *
31188c2ecf20Sopenharmony_ciice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi)
31198c2ecf20Sopenharmony_ci{
31208c2ecf20Sopenharmony_ci	return ice_vsi_setup(pf, pi, ICE_VSI_LB, ICE_INVAL_VFID);
31218c2ecf20Sopenharmony_ci}
31228c2ecf20Sopenharmony_ci
31238c2ecf20Sopenharmony_ci/**
31248c2ecf20Sopenharmony_ci * ice_vlan_rx_add_vid - Add a VLAN ID filter to HW offload
31258c2ecf20Sopenharmony_ci * @netdev: network interface to be adjusted
31268c2ecf20Sopenharmony_ci * @proto: unused protocol
31278c2ecf20Sopenharmony_ci * @vid: VLAN ID to be added
31288c2ecf20Sopenharmony_ci *
31298c2ecf20Sopenharmony_ci * net_device_ops implementation for adding VLAN IDs
31308c2ecf20Sopenharmony_ci */
31318c2ecf20Sopenharmony_cistatic int
31328c2ecf20Sopenharmony_ciice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
31338c2ecf20Sopenharmony_ci		    u16 vid)
31348c2ecf20Sopenharmony_ci{
31358c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
31368c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
31378c2ecf20Sopenharmony_ci	int ret;
31388c2ecf20Sopenharmony_ci
31398c2ecf20Sopenharmony_ci	if (vid >= VLAN_N_VID) {
31408c2ecf20Sopenharmony_ci		netdev_err(netdev, "VLAN id requested %d is out of range %d\n",
31418c2ecf20Sopenharmony_ci			   vid, VLAN_N_VID);
31428c2ecf20Sopenharmony_ci		return -EINVAL;
31438c2ecf20Sopenharmony_ci	}
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci	if (vsi->info.pvid)
31468c2ecf20Sopenharmony_ci		return -EINVAL;
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_ci	/* VLAN 0 is added by default during load/reset */
31498c2ecf20Sopenharmony_ci	if (!vid)
31508c2ecf20Sopenharmony_ci		return 0;
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci	/* Enable VLAN pruning when a VLAN other than 0 is added */
31538c2ecf20Sopenharmony_ci	if (!ice_vsi_is_vlan_pruning_ena(vsi)) {
31548c2ecf20Sopenharmony_ci		ret = ice_cfg_vlan_pruning(vsi, true, false);
31558c2ecf20Sopenharmony_ci		if (ret)
31568c2ecf20Sopenharmony_ci			return ret;
31578c2ecf20Sopenharmony_ci	}
31588c2ecf20Sopenharmony_ci
31598c2ecf20Sopenharmony_ci	/* Add a switch rule for this VLAN ID so its corresponding VLAN tagged
31608c2ecf20Sopenharmony_ci	 * packets aren't pruned by the device's internal switch on Rx
31618c2ecf20Sopenharmony_ci	 */
31628c2ecf20Sopenharmony_ci	ret = ice_vsi_add_vlan(vsi, vid, ICE_FWD_TO_VSI);
31638c2ecf20Sopenharmony_ci	if (!ret) {
31648c2ecf20Sopenharmony_ci		vsi->vlan_ena = true;
31658c2ecf20Sopenharmony_ci		set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
31668c2ecf20Sopenharmony_ci	}
31678c2ecf20Sopenharmony_ci
31688c2ecf20Sopenharmony_ci	return ret;
31698c2ecf20Sopenharmony_ci}
31708c2ecf20Sopenharmony_ci
31718c2ecf20Sopenharmony_ci/**
31728c2ecf20Sopenharmony_ci * ice_vlan_rx_kill_vid - Remove a VLAN ID filter from HW offload
31738c2ecf20Sopenharmony_ci * @netdev: network interface to be adjusted
31748c2ecf20Sopenharmony_ci * @proto: unused protocol
31758c2ecf20Sopenharmony_ci * @vid: VLAN ID to be removed
31768c2ecf20Sopenharmony_ci *
31778c2ecf20Sopenharmony_ci * net_device_ops implementation for removing VLAN IDs
31788c2ecf20Sopenharmony_ci */
31798c2ecf20Sopenharmony_cistatic int
31808c2ecf20Sopenharmony_ciice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
31818c2ecf20Sopenharmony_ci		     u16 vid)
31828c2ecf20Sopenharmony_ci{
31838c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
31848c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
31858c2ecf20Sopenharmony_ci	int ret;
31868c2ecf20Sopenharmony_ci
31878c2ecf20Sopenharmony_ci	if (vsi->info.pvid)
31888c2ecf20Sopenharmony_ci		return -EINVAL;
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	/* don't allow removal of VLAN 0 */
31918c2ecf20Sopenharmony_ci	if (!vid)
31928c2ecf20Sopenharmony_ci		return 0;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
31958c2ecf20Sopenharmony_ci	 * information
31968c2ecf20Sopenharmony_ci	 */
31978c2ecf20Sopenharmony_ci	ret = ice_vsi_kill_vlan(vsi, vid);
31988c2ecf20Sopenharmony_ci	if (ret)
31998c2ecf20Sopenharmony_ci		return ret;
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_ci	/* Disable pruning when VLAN 0 is the only VLAN rule */
32028c2ecf20Sopenharmony_ci	if (vsi->num_vlan == 1 && ice_vsi_is_vlan_pruning_ena(vsi))
32038c2ecf20Sopenharmony_ci		ret = ice_cfg_vlan_pruning(vsi, false, false);
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	vsi->vlan_ena = false;
32068c2ecf20Sopenharmony_ci	set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
32078c2ecf20Sopenharmony_ci	return ret;
32088c2ecf20Sopenharmony_ci}
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_ci/**
32118c2ecf20Sopenharmony_ci * ice_setup_pf_sw - Setup the HW switch on startup or after reset
32128c2ecf20Sopenharmony_ci * @pf: board private structure
32138c2ecf20Sopenharmony_ci *
32148c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on failure
32158c2ecf20Sopenharmony_ci */
32168c2ecf20Sopenharmony_cistatic int ice_setup_pf_sw(struct ice_pf *pf)
32178c2ecf20Sopenharmony_ci{
32188c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
32198c2ecf20Sopenharmony_ci	int status = 0;
32208c2ecf20Sopenharmony_ci
32218c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state))
32228c2ecf20Sopenharmony_ci		return -EBUSY;
32238c2ecf20Sopenharmony_ci
32248c2ecf20Sopenharmony_ci	vsi = ice_pf_vsi_setup(pf, pf->hw.port_info);
32258c2ecf20Sopenharmony_ci	if (!vsi)
32268c2ecf20Sopenharmony_ci		return -ENOMEM;
32278c2ecf20Sopenharmony_ci
32288c2ecf20Sopenharmony_ci	status = ice_cfg_netdev(vsi);
32298c2ecf20Sopenharmony_ci	if (status) {
32308c2ecf20Sopenharmony_ci		status = -ENODEV;
32318c2ecf20Sopenharmony_ci		goto unroll_vsi_setup;
32328c2ecf20Sopenharmony_ci	}
32338c2ecf20Sopenharmony_ci	/* netdev has to be configured before setting frame size */
32348c2ecf20Sopenharmony_ci	ice_vsi_cfg_frame_size(vsi);
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci	/* Setup DCB netlink interface */
32378c2ecf20Sopenharmony_ci	ice_dcbnl_setup(vsi);
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	/* registering the NAPI handler requires both the queues and
32408c2ecf20Sopenharmony_ci	 * netdev to be created, which are done in ice_pf_vsi_setup()
32418c2ecf20Sopenharmony_ci	 * and ice_cfg_netdev() respectively
32428c2ecf20Sopenharmony_ci	 */
32438c2ecf20Sopenharmony_ci	ice_napi_add(vsi);
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_ci	status = ice_set_cpu_rx_rmap(vsi);
32468c2ecf20Sopenharmony_ci	if (status) {
32478c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(pf), "Failed to set CPU Rx map VSI %d error %d\n",
32488c2ecf20Sopenharmony_ci			vsi->vsi_num, status);
32498c2ecf20Sopenharmony_ci		status = -EINVAL;
32508c2ecf20Sopenharmony_ci		goto unroll_napi_add;
32518c2ecf20Sopenharmony_ci	}
32528c2ecf20Sopenharmony_ci	status = ice_init_mac_fltr(pf);
32538c2ecf20Sopenharmony_ci	if (status)
32548c2ecf20Sopenharmony_ci		goto free_cpu_rx_map;
32558c2ecf20Sopenharmony_ci
32568c2ecf20Sopenharmony_ci	return status;
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_cifree_cpu_rx_map:
32598c2ecf20Sopenharmony_ci	ice_free_cpu_rx_rmap(vsi);
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ciunroll_napi_add:
32628c2ecf20Sopenharmony_ci	if (vsi) {
32638c2ecf20Sopenharmony_ci		ice_napi_del(vsi);
32648c2ecf20Sopenharmony_ci		if (vsi->netdev) {
32658c2ecf20Sopenharmony_ci			if (vsi->netdev->reg_state == NETREG_REGISTERED)
32668c2ecf20Sopenharmony_ci				unregister_netdev(vsi->netdev);
32678c2ecf20Sopenharmony_ci			free_netdev(vsi->netdev);
32688c2ecf20Sopenharmony_ci			vsi->netdev = NULL;
32698c2ecf20Sopenharmony_ci		}
32708c2ecf20Sopenharmony_ci	}
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ciunroll_vsi_setup:
32738c2ecf20Sopenharmony_ci	ice_vsi_release(vsi);
32748c2ecf20Sopenharmony_ci	return status;
32758c2ecf20Sopenharmony_ci}
32768c2ecf20Sopenharmony_ci
32778c2ecf20Sopenharmony_ci/**
32788c2ecf20Sopenharmony_ci * ice_get_avail_q_count - Get count of queues in use
32798c2ecf20Sopenharmony_ci * @pf_qmap: bitmap to get queue use count from
32808c2ecf20Sopenharmony_ci * @lock: pointer to a mutex that protects access to pf_qmap
32818c2ecf20Sopenharmony_ci * @size: size of the bitmap
32828c2ecf20Sopenharmony_ci */
32838c2ecf20Sopenharmony_cistatic u16
32848c2ecf20Sopenharmony_ciice_get_avail_q_count(unsigned long *pf_qmap, struct mutex *lock, u16 size)
32858c2ecf20Sopenharmony_ci{
32868c2ecf20Sopenharmony_ci	unsigned long bit;
32878c2ecf20Sopenharmony_ci	u16 count = 0;
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci	mutex_lock(lock);
32908c2ecf20Sopenharmony_ci	for_each_clear_bit(bit, pf_qmap, size)
32918c2ecf20Sopenharmony_ci		count++;
32928c2ecf20Sopenharmony_ci	mutex_unlock(lock);
32938c2ecf20Sopenharmony_ci
32948c2ecf20Sopenharmony_ci	return count;
32958c2ecf20Sopenharmony_ci}
32968c2ecf20Sopenharmony_ci
32978c2ecf20Sopenharmony_ci/**
32988c2ecf20Sopenharmony_ci * ice_get_avail_txq_count - Get count of Tx queues in use
32998c2ecf20Sopenharmony_ci * @pf: pointer to an ice_pf instance
33008c2ecf20Sopenharmony_ci */
33018c2ecf20Sopenharmony_ciu16 ice_get_avail_txq_count(struct ice_pf *pf)
33028c2ecf20Sopenharmony_ci{
33038c2ecf20Sopenharmony_ci	return ice_get_avail_q_count(pf->avail_txqs, &pf->avail_q_mutex,
33048c2ecf20Sopenharmony_ci				     pf->max_pf_txqs);
33058c2ecf20Sopenharmony_ci}
33068c2ecf20Sopenharmony_ci
33078c2ecf20Sopenharmony_ci/**
33088c2ecf20Sopenharmony_ci * ice_get_avail_rxq_count - Get count of Rx queues in use
33098c2ecf20Sopenharmony_ci * @pf: pointer to an ice_pf instance
33108c2ecf20Sopenharmony_ci */
33118c2ecf20Sopenharmony_ciu16 ice_get_avail_rxq_count(struct ice_pf *pf)
33128c2ecf20Sopenharmony_ci{
33138c2ecf20Sopenharmony_ci	return ice_get_avail_q_count(pf->avail_rxqs, &pf->avail_q_mutex,
33148c2ecf20Sopenharmony_ci				     pf->max_pf_rxqs);
33158c2ecf20Sopenharmony_ci}
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci/**
33188c2ecf20Sopenharmony_ci * ice_deinit_pf - Unrolls initialziations done by ice_init_pf
33198c2ecf20Sopenharmony_ci * @pf: board private structure to initialize
33208c2ecf20Sopenharmony_ci */
33218c2ecf20Sopenharmony_cistatic void ice_deinit_pf(struct ice_pf *pf)
33228c2ecf20Sopenharmony_ci{
33238c2ecf20Sopenharmony_ci	ice_service_task_stop(pf);
33248c2ecf20Sopenharmony_ci	mutex_destroy(&pf->sw_mutex);
33258c2ecf20Sopenharmony_ci	mutex_destroy(&pf->tc_mutex);
33268c2ecf20Sopenharmony_ci	mutex_destroy(&pf->avail_q_mutex);
33278c2ecf20Sopenharmony_ci
33288c2ecf20Sopenharmony_ci	if (pf->avail_txqs) {
33298c2ecf20Sopenharmony_ci		bitmap_free(pf->avail_txqs);
33308c2ecf20Sopenharmony_ci		pf->avail_txqs = NULL;
33318c2ecf20Sopenharmony_ci	}
33328c2ecf20Sopenharmony_ci
33338c2ecf20Sopenharmony_ci	if (pf->avail_rxqs) {
33348c2ecf20Sopenharmony_ci		bitmap_free(pf->avail_rxqs);
33358c2ecf20Sopenharmony_ci		pf->avail_rxqs = NULL;
33368c2ecf20Sopenharmony_ci	}
33378c2ecf20Sopenharmony_ci}
33388c2ecf20Sopenharmony_ci
33398c2ecf20Sopenharmony_ci/**
33408c2ecf20Sopenharmony_ci * ice_set_pf_caps - set PFs capability flags
33418c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
33428c2ecf20Sopenharmony_ci */
33438c2ecf20Sopenharmony_cistatic void ice_set_pf_caps(struct ice_pf *pf)
33448c2ecf20Sopenharmony_ci{
33458c2ecf20Sopenharmony_ci	struct ice_hw_func_caps *func_caps = &pf->hw.func_caps;
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	clear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
33488c2ecf20Sopenharmony_ci	if (func_caps->common_cap.dcb)
33498c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
33508c2ecf20Sopenharmony_ci	clear_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
33518c2ecf20Sopenharmony_ci	if (func_caps->common_cap.sr_iov_1_1) {
33528c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_SRIOV_CAPABLE, pf->flags);
33538c2ecf20Sopenharmony_ci		pf->num_vfs_supported = min_t(int, func_caps->num_allocd_vfs,
33548c2ecf20Sopenharmony_ci					      ICE_MAX_VF_COUNT);
33558c2ecf20Sopenharmony_ci	}
33568c2ecf20Sopenharmony_ci	clear_bit(ICE_FLAG_RSS_ENA, pf->flags);
33578c2ecf20Sopenharmony_ci	if (func_caps->common_cap.rss_table_size)
33588c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_RSS_ENA, pf->flags);
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_ci	clear_bit(ICE_FLAG_FD_ENA, pf->flags);
33618c2ecf20Sopenharmony_ci	if (func_caps->fd_fltr_guar > 0 || func_caps->fd_fltr_best_effort > 0) {
33628c2ecf20Sopenharmony_ci		u16 unused;
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci		/* ctrl_vsi_idx will be set to a valid value when flow director
33658c2ecf20Sopenharmony_ci		 * is setup by ice_init_fdir
33668c2ecf20Sopenharmony_ci		 */
33678c2ecf20Sopenharmony_ci		pf->ctrl_vsi_idx = ICE_NO_VSI;
33688c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_FD_ENA, pf->flags);
33698c2ecf20Sopenharmony_ci		/* force guaranteed filter pool for PF */
33708c2ecf20Sopenharmony_ci		ice_alloc_fd_guar_item(&pf->hw, &unused,
33718c2ecf20Sopenharmony_ci				       func_caps->fd_fltr_guar);
33728c2ecf20Sopenharmony_ci		/* force shared filter pool for PF */
33738c2ecf20Sopenharmony_ci		ice_alloc_fd_shrd_item(&pf->hw, &unused,
33748c2ecf20Sopenharmony_ci				       func_caps->fd_fltr_best_effort);
33758c2ecf20Sopenharmony_ci	}
33768c2ecf20Sopenharmony_ci
33778c2ecf20Sopenharmony_ci	pf->max_pf_txqs = func_caps->common_cap.num_txq;
33788c2ecf20Sopenharmony_ci	pf->max_pf_rxqs = func_caps->common_cap.num_rxq;
33798c2ecf20Sopenharmony_ci}
33808c2ecf20Sopenharmony_ci
33818c2ecf20Sopenharmony_ci/**
33828c2ecf20Sopenharmony_ci * ice_init_pf - Initialize general software structures (struct ice_pf)
33838c2ecf20Sopenharmony_ci * @pf: board private structure to initialize
33848c2ecf20Sopenharmony_ci */
33858c2ecf20Sopenharmony_cistatic int ice_init_pf(struct ice_pf *pf)
33868c2ecf20Sopenharmony_ci{
33878c2ecf20Sopenharmony_ci	ice_set_pf_caps(pf);
33888c2ecf20Sopenharmony_ci
33898c2ecf20Sopenharmony_ci	mutex_init(&pf->sw_mutex);
33908c2ecf20Sopenharmony_ci	mutex_init(&pf->tc_mutex);
33918c2ecf20Sopenharmony_ci
33928c2ecf20Sopenharmony_ci	INIT_HLIST_HEAD(&pf->aq_wait_list);
33938c2ecf20Sopenharmony_ci	spin_lock_init(&pf->aq_wait_lock);
33948c2ecf20Sopenharmony_ci	init_waitqueue_head(&pf->aq_wait_queue);
33958c2ecf20Sopenharmony_ci
33968c2ecf20Sopenharmony_ci	/* setup service timer and periodic service task */
33978c2ecf20Sopenharmony_ci	timer_setup(&pf->serv_tmr, ice_service_timer, 0);
33988c2ecf20Sopenharmony_ci	pf->serv_tmr_period = HZ;
33998c2ecf20Sopenharmony_ci	INIT_WORK(&pf->serv_task, ice_service_task);
34008c2ecf20Sopenharmony_ci	clear_bit(__ICE_SERVICE_SCHED, pf->state);
34018c2ecf20Sopenharmony_ci
34028c2ecf20Sopenharmony_ci	mutex_init(&pf->avail_q_mutex);
34038c2ecf20Sopenharmony_ci	pf->avail_txqs = bitmap_zalloc(pf->max_pf_txqs, GFP_KERNEL);
34048c2ecf20Sopenharmony_ci	if (!pf->avail_txqs)
34058c2ecf20Sopenharmony_ci		return -ENOMEM;
34068c2ecf20Sopenharmony_ci
34078c2ecf20Sopenharmony_ci	pf->avail_rxqs = bitmap_zalloc(pf->max_pf_rxqs, GFP_KERNEL);
34088c2ecf20Sopenharmony_ci	if (!pf->avail_rxqs) {
34098c2ecf20Sopenharmony_ci		bitmap_free(pf->avail_txqs);
34108c2ecf20Sopenharmony_ci		pf->avail_txqs = NULL;
34118c2ecf20Sopenharmony_ci		return -ENOMEM;
34128c2ecf20Sopenharmony_ci	}
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_ci	return 0;
34158c2ecf20Sopenharmony_ci}
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci/**
34188c2ecf20Sopenharmony_ci * ice_ena_msix_range - Request a range of MSIX vectors from the OS
34198c2ecf20Sopenharmony_ci * @pf: board private structure
34208c2ecf20Sopenharmony_ci *
34218c2ecf20Sopenharmony_ci * compute the number of MSIX vectors required (v_budget) and request from
34228c2ecf20Sopenharmony_ci * the OS. Return the number of vectors reserved or negative on failure
34238c2ecf20Sopenharmony_ci */
34248c2ecf20Sopenharmony_cistatic int ice_ena_msix_range(struct ice_pf *pf)
34258c2ecf20Sopenharmony_ci{
34268c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
34278c2ecf20Sopenharmony_ci	int v_left, v_actual, v_budget = 0;
34288c2ecf20Sopenharmony_ci	int needed, err, i;
34298c2ecf20Sopenharmony_ci
34308c2ecf20Sopenharmony_ci	v_left = pf->hw.func_caps.common_cap.num_msix_vectors;
34318c2ecf20Sopenharmony_ci
34328c2ecf20Sopenharmony_ci	/* reserve one vector for miscellaneous handler */
34338c2ecf20Sopenharmony_ci	needed = 1;
34348c2ecf20Sopenharmony_ci	if (v_left < needed)
34358c2ecf20Sopenharmony_ci		goto no_hw_vecs_left_err;
34368c2ecf20Sopenharmony_ci	v_budget += needed;
34378c2ecf20Sopenharmony_ci	v_left -= needed;
34388c2ecf20Sopenharmony_ci
34398c2ecf20Sopenharmony_ci	/* reserve vectors for LAN traffic */
34408c2ecf20Sopenharmony_ci	needed = min_t(int, num_online_cpus(), v_left);
34418c2ecf20Sopenharmony_ci	if (v_left < needed)
34428c2ecf20Sopenharmony_ci		goto no_hw_vecs_left_err;
34438c2ecf20Sopenharmony_ci	pf->num_lan_msix = needed;
34448c2ecf20Sopenharmony_ci	v_budget += needed;
34458c2ecf20Sopenharmony_ci	v_left -= needed;
34468c2ecf20Sopenharmony_ci
34478c2ecf20Sopenharmony_ci	/* reserve one vector for flow director */
34488c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {
34498c2ecf20Sopenharmony_ci		needed = ICE_FDIR_MSIX;
34508c2ecf20Sopenharmony_ci		if (v_left < needed)
34518c2ecf20Sopenharmony_ci			goto no_hw_vecs_left_err;
34528c2ecf20Sopenharmony_ci		v_budget += needed;
34538c2ecf20Sopenharmony_ci		v_left -= needed;
34548c2ecf20Sopenharmony_ci	}
34558c2ecf20Sopenharmony_ci
34568c2ecf20Sopenharmony_ci	pf->msix_entries = devm_kcalloc(dev, v_budget,
34578c2ecf20Sopenharmony_ci					sizeof(*pf->msix_entries), GFP_KERNEL);
34588c2ecf20Sopenharmony_ci
34598c2ecf20Sopenharmony_ci	if (!pf->msix_entries) {
34608c2ecf20Sopenharmony_ci		err = -ENOMEM;
34618c2ecf20Sopenharmony_ci		goto exit_err;
34628c2ecf20Sopenharmony_ci	}
34638c2ecf20Sopenharmony_ci
34648c2ecf20Sopenharmony_ci	for (i = 0; i < v_budget; i++)
34658c2ecf20Sopenharmony_ci		pf->msix_entries[i].entry = i;
34668c2ecf20Sopenharmony_ci
34678c2ecf20Sopenharmony_ci	/* actually reserve the vectors */
34688c2ecf20Sopenharmony_ci	v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries,
34698c2ecf20Sopenharmony_ci					 ICE_MIN_MSIX, v_budget);
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_ci	if (v_actual < 0) {
34728c2ecf20Sopenharmony_ci		dev_err(dev, "unable to reserve MSI-X vectors\n");
34738c2ecf20Sopenharmony_ci		err = v_actual;
34748c2ecf20Sopenharmony_ci		goto msix_err;
34758c2ecf20Sopenharmony_ci	}
34768c2ecf20Sopenharmony_ci
34778c2ecf20Sopenharmony_ci	if (v_actual < v_budget) {
34788c2ecf20Sopenharmony_ci		dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n",
34798c2ecf20Sopenharmony_ci			 v_budget, v_actual);
34808c2ecf20Sopenharmony_ci
34818c2ecf20Sopenharmony_ci		if (v_actual < ICE_MIN_MSIX) {
34828c2ecf20Sopenharmony_ci			/* error if we can't get minimum vectors */
34838c2ecf20Sopenharmony_ci			pci_disable_msix(pf->pdev);
34848c2ecf20Sopenharmony_ci			err = -ERANGE;
34858c2ecf20Sopenharmony_ci			goto msix_err;
34868c2ecf20Sopenharmony_ci		} else {
34878c2ecf20Sopenharmony_ci			pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX;
34888c2ecf20Sopenharmony_ci		}
34898c2ecf20Sopenharmony_ci	}
34908c2ecf20Sopenharmony_ci
34918c2ecf20Sopenharmony_ci	return v_actual;
34928c2ecf20Sopenharmony_ci
34938c2ecf20Sopenharmony_cimsix_err:
34948c2ecf20Sopenharmony_ci	devm_kfree(dev, pf->msix_entries);
34958c2ecf20Sopenharmony_ci	goto exit_err;
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_cino_hw_vecs_left_err:
34988c2ecf20Sopenharmony_ci	dev_err(dev, "not enough device MSI-X vectors. requested = %d, available = %d\n",
34998c2ecf20Sopenharmony_ci		needed, v_left);
35008c2ecf20Sopenharmony_ci	err = -ERANGE;
35018c2ecf20Sopenharmony_ciexit_err:
35028c2ecf20Sopenharmony_ci	pf->num_lan_msix = 0;
35038c2ecf20Sopenharmony_ci	return err;
35048c2ecf20Sopenharmony_ci}
35058c2ecf20Sopenharmony_ci
35068c2ecf20Sopenharmony_ci/**
35078c2ecf20Sopenharmony_ci * ice_dis_msix - Disable MSI-X interrupt setup in OS
35088c2ecf20Sopenharmony_ci * @pf: board private structure
35098c2ecf20Sopenharmony_ci */
35108c2ecf20Sopenharmony_cistatic void ice_dis_msix(struct ice_pf *pf)
35118c2ecf20Sopenharmony_ci{
35128c2ecf20Sopenharmony_ci	pci_disable_msix(pf->pdev);
35138c2ecf20Sopenharmony_ci	devm_kfree(ice_pf_to_dev(pf), pf->msix_entries);
35148c2ecf20Sopenharmony_ci	pf->msix_entries = NULL;
35158c2ecf20Sopenharmony_ci}
35168c2ecf20Sopenharmony_ci
35178c2ecf20Sopenharmony_ci/**
35188c2ecf20Sopenharmony_ci * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme
35198c2ecf20Sopenharmony_ci * @pf: board private structure
35208c2ecf20Sopenharmony_ci */
35218c2ecf20Sopenharmony_cistatic void ice_clear_interrupt_scheme(struct ice_pf *pf)
35228c2ecf20Sopenharmony_ci{
35238c2ecf20Sopenharmony_ci	ice_dis_msix(pf);
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ci	if (pf->irq_tracker) {
35268c2ecf20Sopenharmony_ci		devm_kfree(ice_pf_to_dev(pf), pf->irq_tracker);
35278c2ecf20Sopenharmony_ci		pf->irq_tracker = NULL;
35288c2ecf20Sopenharmony_ci	}
35298c2ecf20Sopenharmony_ci}
35308c2ecf20Sopenharmony_ci
35318c2ecf20Sopenharmony_ci/**
35328c2ecf20Sopenharmony_ci * ice_init_interrupt_scheme - Determine proper interrupt scheme
35338c2ecf20Sopenharmony_ci * @pf: board private structure to initialize
35348c2ecf20Sopenharmony_ci */
35358c2ecf20Sopenharmony_cistatic int ice_init_interrupt_scheme(struct ice_pf *pf)
35368c2ecf20Sopenharmony_ci{
35378c2ecf20Sopenharmony_ci	int vectors;
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci	vectors = ice_ena_msix_range(pf);
35408c2ecf20Sopenharmony_ci
35418c2ecf20Sopenharmony_ci	if (vectors < 0)
35428c2ecf20Sopenharmony_ci		return vectors;
35438c2ecf20Sopenharmony_ci
35448c2ecf20Sopenharmony_ci	/* set up vector assignment tracking */
35458c2ecf20Sopenharmony_ci	pf->irq_tracker =
35468c2ecf20Sopenharmony_ci		devm_kzalloc(ice_pf_to_dev(pf), sizeof(*pf->irq_tracker) +
35478c2ecf20Sopenharmony_ci			     (sizeof(u16) * vectors), GFP_KERNEL);
35488c2ecf20Sopenharmony_ci	if (!pf->irq_tracker) {
35498c2ecf20Sopenharmony_ci		ice_dis_msix(pf);
35508c2ecf20Sopenharmony_ci		return -ENOMEM;
35518c2ecf20Sopenharmony_ci	}
35528c2ecf20Sopenharmony_ci
35538c2ecf20Sopenharmony_ci	/* populate SW interrupts pool with number of OS granted IRQs. */
35548c2ecf20Sopenharmony_ci	pf->num_avail_sw_msix = (u16)vectors;
35558c2ecf20Sopenharmony_ci	pf->irq_tracker->num_entries = (u16)vectors;
35568c2ecf20Sopenharmony_ci	pf->irq_tracker->end = pf->irq_tracker->num_entries;
35578c2ecf20Sopenharmony_ci
35588c2ecf20Sopenharmony_ci	return 0;
35598c2ecf20Sopenharmony_ci}
35608c2ecf20Sopenharmony_ci
35618c2ecf20Sopenharmony_ci/**
35628c2ecf20Sopenharmony_ci * ice_is_wol_supported - check if WoL is supported
35638c2ecf20Sopenharmony_ci * @hw: pointer to hardware info
35648c2ecf20Sopenharmony_ci *
35658c2ecf20Sopenharmony_ci * Check if WoL is supported based on the HW configuration.
35668c2ecf20Sopenharmony_ci * Returns true if NVM supports and enables WoL for this port, false otherwise
35678c2ecf20Sopenharmony_ci */
35688c2ecf20Sopenharmony_cibool ice_is_wol_supported(struct ice_hw *hw)
35698c2ecf20Sopenharmony_ci{
35708c2ecf20Sopenharmony_ci	u16 wol_ctrl;
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci	/* A bit set to 1 in the NVM Software Reserved Word 2 (WoL control
35738c2ecf20Sopenharmony_ci	 * word) indicates WoL is not supported on the corresponding PF ID.
35748c2ecf20Sopenharmony_ci	 */
35758c2ecf20Sopenharmony_ci	if (ice_read_sr_word(hw, ICE_SR_NVM_WOL_CFG, &wol_ctrl))
35768c2ecf20Sopenharmony_ci		return false;
35778c2ecf20Sopenharmony_ci
35788c2ecf20Sopenharmony_ci	return !(BIT(hw->port_info->lport) & wol_ctrl);
35798c2ecf20Sopenharmony_ci}
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci/**
35828c2ecf20Sopenharmony_ci * ice_vsi_recfg_qs - Change the number of queues on a VSI
35838c2ecf20Sopenharmony_ci * @vsi: VSI being changed
35848c2ecf20Sopenharmony_ci * @new_rx: new number of Rx queues
35858c2ecf20Sopenharmony_ci * @new_tx: new number of Tx queues
35868c2ecf20Sopenharmony_ci *
35878c2ecf20Sopenharmony_ci * Only change the number of queues if new_tx, or new_rx is non-0.
35888c2ecf20Sopenharmony_ci *
35898c2ecf20Sopenharmony_ci * Returns 0 on success.
35908c2ecf20Sopenharmony_ci */
35918c2ecf20Sopenharmony_ciint ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx)
35928c2ecf20Sopenharmony_ci{
35938c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
35948c2ecf20Sopenharmony_ci	int err = 0, timeout = 50;
35958c2ecf20Sopenharmony_ci
35968c2ecf20Sopenharmony_ci	if (!new_rx && !new_tx)
35978c2ecf20Sopenharmony_ci		return -EINVAL;
35988c2ecf20Sopenharmony_ci
35998c2ecf20Sopenharmony_ci	while (test_and_set_bit(__ICE_CFG_BUSY, pf->state)) {
36008c2ecf20Sopenharmony_ci		timeout--;
36018c2ecf20Sopenharmony_ci		if (!timeout)
36028c2ecf20Sopenharmony_ci			return -EBUSY;
36038c2ecf20Sopenharmony_ci		usleep_range(1000, 2000);
36048c2ecf20Sopenharmony_ci	}
36058c2ecf20Sopenharmony_ci
36068c2ecf20Sopenharmony_ci	if (new_tx)
36078c2ecf20Sopenharmony_ci		vsi->req_txq = (u16)new_tx;
36088c2ecf20Sopenharmony_ci	if (new_rx)
36098c2ecf20Sopenharmony_ci		vsi->req_rxq = (u16)new_rx;
36108c2ecf20Sopenharmony_ci
36118c2ecf20Sopenharmony_ci	/* set for the next time the netdev is started */
36128c2ecf20Sopenharmony_ci	if (!netif_running(vsi->netdev)) {
36138c2ecf20Sopenharmony_ci		ice_vsi_rebuild(vsi, false);
36148c2ecf20Sopenharmony_ci		dev_dbg(ice_pf_to_dev(pf), "Link is down, queue count change happens when link is brought up\n");
36158c2ecf20Sopenharmony_ci		goto done;
36168c2ecf20Sopenharmony_ci	}
36178c2ecf20Sopenharmony_ci
36188c2ecf20Sopenharmony_ci	ice_vsi_close(vsi);
36198c2ecf20Sopenharmony_ci	ice_vsi_rebuild(vsi, false);
36208c2ecf20Sopenharmony_ci	ice_pf_dcb_recfg(pf);
36218c2ecf20Sopenharmony_ci	ice_vsi_open(vsi);
36228c2ecf20Sopenharmony_cidone:
36238c2ecf20Sopenharmony_ci	clear_bit(__ICE_CFG_BUSY, pf->state);
36248c2ecf20Sopenharmony_ci	return err;
36258c2ecf20Sopenharmony_ci}
36268c2ecf20Sopenharmony_ci
36278c2ecf20Sopenharmony_ci/**
36288c2ecf20Sopenharmony_ci * ice_set_safe_mode_vlan_cfg - configure PF VSI to allow all VLANs in safe mode
36298c2ecf20Sopenharmony_ci * @pf: PF to configure
36308c2ecf20Sopenharmony_ci *
36318c2ecf20Sopenharmony_ci * No VLAN offloads/filtering are advertised in safe mode so make sure the PF
36328c2ecf20Sopenharmony_ci * VSI can still Tx/Rx VLAN tagged packets.
36338c2ecf20Sopenharmony_ci */
36348c2ecf20Sopenharmony_cistatic void ice_set_safe_mode_vlan_cfg(struct ice_pf *pf)
36358c2ecf20Sopenharmony_ci{
36368c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = ice_get_main_vsi(pf);
36378c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
36388c2ecf20Sopenharmony_ci	enum ice_status status;
36398c2ecf20Sopenharmony_ci	struct ice_hw *hw;
36408c2ecf20Sopenharmony_ci
36418c2ecf20Sopenharmony_ci	if (!vsi)
36428c2ecf20Sopenharmony_ci		return;
36438c2ecf20Sopenharmony_ci
36448c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
36458c2ecf20Sopenharmony_ci	if (!ctxt)
36468c2ecf20Sopenharmony_ci		return;
36478c2ecf20Sopenharmony_ci
36488c2ecf20Sopenharmony_ci	hw = &pf->hw;
36498c2ecf20Sopenharmony_ci	ctxt->info = vsi->info;
36508c2ecf20Sopenharmony_ci
36518c2ecf20Sopenharmony_ci	ctxt->info.valid_sections =
36528c2ecf20Sopenharmony_ci		cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID |
36538c2ecf20Sopenharmony_ci			    ICE_AQ_VSI_PROP_SECURITY_VALID |
36548c2ecf20Sopenharmony_ci			    ICE_AQ_VSI_PROP_SW_VALID);
36558c2ecf20Sopenharmony_ci
36568c2ecf20Sopenharmony_ci	/* disable VLAN anti-spoof */
36578c2ecf20Sopenharmony_ci	ctxt->info.sec_flags &= ~(ICE_AQ_VSI_SEC_TX_VLAN_PRUNE_ENA <<
36588c2ecf20Sopenharmony_ci				  ICE_AQ_VSI_SEC_TX_PRUNE_ENA_S);
36598c2ecf20Sopenharmony_ci
36608c2ecf20Sopenharmony_ci	/* disable VLAN pruning and keep all other settings */
36618c2ecf20Sopenharmony_ci	ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
36628c2ecf20Sopenharmony_ci
36638c2ecf20Sopenharmony_ci	/* allow all VLANs on Tx and don't strip on Rx */
36648c2ecf20Sopenharmony_ci	ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL |
36658c2ecf20Sopenharmony_ci		ICE_AQ_VSI_VLAN_EMOD_NOTHING;
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
36688c2ecf20Sopenharmony_ci	if (status) {
36698c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Failed to update VSI for safe mode VLANs, err %s aq_err %s\n",
36708c2ecf20Sopenharmony_ci			ice_stat_str(status),
36718c2ecf20Sopenharmony_ci			ice_aq_str(hw->adminq.sq_last_status));
36728c2ecf20Sopenharmony_ci	} else {
36738c2ecf20Sopenharmony_ci		vsi->info.sec_flags = ctxt->info.sec_flags;
36748c2ecf20Sopenharmony_ci		vsi->info.sw_flags2 = ctxt->info.sw_flags2;
36758c2ecf20Sopenharmony_ci		vsi->info.vlan_flags = ctxt->info.vlan_flags;
36768c2ecf20Sopenharmony_ci	}
36778c2ecf20Sopenharmony_ci
36788c2ecf20Sopenharmony_ci	kfree(ctxt);
36798c2ecf20Sopenharmony_ci}
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci/**
36828c2ecf20Sopenharmony_ci * ice_log_pkg_init - log result of DDP package load
36838c2ecf20Sopenharmony_ci * @hw: pointer to hardware info
36848c2ecf20Sopenharmony_ci * @status: status of package load
36858c2ecf20Sopenharmony_ci */
36868c2ecf20Sopenharmony_cistatic void
36878c2ecf20Sopenharmony_ciice_log_pkg_init(struct ice_hw *hw, enum ice_status *status)
36888c2ecf20Sopenharmony_ci{
36898c2ecf20Sopenharmony_ci	struct ice_pf *pf = (struct ice_pf *)hw->back;
36908c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
36918c2ecf20Sopenharmony_ci
36928c2ecf20Sopenharmony_ci	switch (*status) {
36938c2ecf20Sopenharmony_ci	case ICE_SUCCESS:
36948c2ecf20Sopenharmony_ci		/* The package download AdminQ command returned success because
36958c2ecf20Sopenharmony_ci		 * this download succeeded or ICE_ERR_AQ_NO_WORK since there is
36968c2ecf20Sopenharmony_ci		 * already a package loaded on the device.
36978c2ecf20Sopenharmony_ci		 */
36988c2ecf20Sopenharmony_ci		if (hw->pkg_ver.major == hw->active_pkg_ver.major &&
36998c2ecf20Sopenharmony_ci		    hw->pkg_ver.minor == hw->active_pkg_ver.minor &&
37008c2ecf20Sopenharmony_ci		    hw->pkg_ver.update == hw->active_pkg_ver.update &&
37018c2ecf20Sopenharmony_ci		    hw->pkg_ver.draft == hw->active_pkg_ver.draft &&
37028c2ecf20Sopenharmony_ci		    !memcmp(hw->pkg_name, hw->active_pkg_name,
37038c2ecf20Sopenharmony_ci			    sizeof(hw->pkg_name))) {
37048c2ecf20Sopenharmony_ci			if (hw->pkg_dwnld_status == ICE_AQ_RC_EEXIST)
37058c2ecf20Sopenharmony_ci				dev_info(dev, "DDP package already present on device: %s version %d.%d.%d.%d\n",
37068c2ecf20Sopenharmony_ci					 hw->active_pkg_name,
37078c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.major,
37088c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.minor,
37098c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.update,
37108c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.draft);
37118c2ecf20Sopenharmony_ci			else
37128c2ecf20Sopenharmony_ci				dev_info(dev, "The DDP package was successfully loaded: %s version %d.%d.%d.%d\n",
37138c2ecf20Sopenharmony_ci					 hw->active_pkg_name,
37148c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.major,
37158c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.minor,
37168c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.update,
37178c2ecf20Sopenharmony_ci					 hw->active_pkg_ver.draft);
37188c2ecf20Sopenharmony_ci		} else if (hw->active_pkg_ver.major != ICE_PKG_SUPP_VER_MAJ ||
37198c2ecf20Sopenharmony_ci			   hw->active_pkg_ver.minor != ICE_PKG_SUPP_VER_MNR) {
37208c2ecf20Sopenharmony_ci			dev_err(dev, "The device has a DDP package that is not supported by the driver.  The device has package '%s' version %d.%d.x.x.  The driver requires version %d.%d.x.x.  Entering Safe Mode.\n",
37218c2ecf20Sopenharmony_ci				hw->active_pkg_name,
37228c2ecf20Sopenharmony_ci				hw->active_pkg_ver.major,
37238c2ecf20Sopenharmony_ci				hw->active_pkg_ver.minor,
37248c2ecf20Sopenharmony_ci				ICE_PKG_SUPP_VER_MAJ, ICE_PKG_SUPP_VER_MNR);
37258c2ecf20Sopenharmony_ci			*status = ICE_ERR_NOT_SUPPORTED;
37268c2ecf20Sopenharmony_ci		} else if (hw->active_pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
37278c2ecf20Sopenharmony_ci			   hw->active_pkg_ver.minor == ICE_PKG_SUPP_VER_MNR) {
37288c2ecf20Sopenharmony_ci			dev_info(dev, "The driver could not load the DDP package file because a compatible DDP package is already present on the device.  The device has package '%s' version %d.%d.%d.%d.  The package file found by the driver: '%s' version %d.%d.%d.%d.\n",
37298c2ecf20Sopenharmony_ci				 hw->active_pkg_name,
37308c2ecf20Sopenharmony_ci				 hw->active_pkg_ver.major,
37318c2ecf20Sopenharmony_ci				 hw->active_pkg_ver.minor,
37328c2ecf20Sopenharmony_ci				 hw->active_pkg_ver.update,
37338c2ecf20Sopenharmony_ci				 hw->active_pkg_ver.draft,
37348c2ecf20Sopenharmony_ci				 hw->pkg_name,
37358c2ecf20Sopenharmony_ci				 hw->pkg_ver.major,
37368c2ecf20Sopenharmony_ci				 hw->pkg_ver.minor,
37378c2ecf20Sopenharmony_ci				 hw->pkg_ver.update,
37388c2ecf20Sopenharmony_ci				 hw->pkg_ver.draft);
37398c2ecf20Sopenharmony_ci		} else {
37408c2ecf20Sopenharmony_ci			dev_err(dev, "An unknown error occurred when loading the DDP package, please reboot the system.  If the problem persists, update the NVM.  Entering Safe Mode.\n");
37418c2ecf20Sopenharmony_ci			*status = ICE_ERR_NOT_SUPPORTED;
37428c2ecf20Sopenharmony_ci		}
37438c2ecf20Sopenharmony_ci		break;
37448c2ecf20Sopenharmony_ci	case ICE_ERR_FW_DDP_MISMATCH:
37458c2ecf20Sopenharmony_ci		dev_err(dev, "The firmware loaded on the device is not compatible with the DDP package.  Please update the device's NVM.  Entering safe mode.\n");
37468c2ecf20Sopenharmony_ci		break;
37478c2ecf20Sopenharmony_ci	case ICE_ERR_BUF_TOO_SHORT:
37488c2ecf20Sopenharmony_ci	case ICE_ERR_CFG:
37498c2ecf20Sopenharmony_ci		dev_err(dev, "The DDP package file is invalid. Entering Safe Mode.\n");
37508c2ecf20Sopenharmony_ci		break;
37518c2ecf20Sopenharmony_ci	case ICE_ERR_NOT_SUPPORTED:
37528c2ecf20Sopenharmony_ci		/* Package File version not supported */
37538c2ecf20Sopenharmony_ci		if (hw->pkg_ver.major > ICE_PKG_SUPP_VER_MAJ ||
37548c2ecf20Sopenharmony_ci		    (hw->pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
37558c2ecf20Sopenharmony_ci		     hw->pkg_ver.minor > ICE_PKG_SUPP_VER_MNR))
37568c2ecf20Sopenharmony_ci			dev_err(dev, "The DDP package file version is higher than the driver supports.  Please use an updated driver.  Entering Safe Mode.\n");
37578c2ecf20Sopenharmony_ci		else if (hw->pkg_ver.major < ICE_PKG_SUPP_VER_MAJ ||
37588c2ecf20Sopenharmony_ci			 (hw->pkg_ver.major == ICE_PKG_SUPP_VER_MAJ &&
37598c2ecf20Sopenharmony_ci			  hw->pkg_ver.minor < ICE_PKG_SUPP_VER_MNR))
37608c2ecf20Sopenharmony_ci			dev_err(dev, "The DDP package file version is lower than the driver supports.  The driver requires version %d.%d.x.x.  Please use an updated DDP Package file.  Entering Safe Mode.\n",
37618c2ecf20Sopenharmony_ci				ICE_PKG_SUPP_VER_MAJ, ICE_PKG_SUPP_VER_MNR);
37628c2ecf20Sopenharmony_ci		break;
37638c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_ERROR:
37648c2ecf20Sopenharmony_ci		switch (hw->pkg_dwnld_status) {
37658c2ecf20Sopenharmony_ci		case ICE_AQ_RC_ENOSEC:
37668c2ecf20Sopenharmony_ci		case ICE_AQ_RC_EBADSIG:
37678c2ecf20Sopenharmony_ci			dev_err(dev, "The DDP package could not be loaded because its signature is not valid.  Please use a valid DDP Package.  Entering Safe Mode.\n");
37688c2ecf20Sopenharmony_ci			return;
37698c2ecf20Sopenharmony_ci		case ICE_AQ_RC_ESVN:
37708c2ecf20Sopenharmony_ci			dev_err(dev, "The DDP Package could not be loaded because its security revision is too low.  Please use an updated DDP Package.  Entering Safe Mode.\n");
37718c2ecf20Sopenharmony_ci			return;
37728c2ecf20Sopenharmony_ci		case ICE_AQ_RC_EBADMAN:
37738c2ecf20Sopenharmony_ci		case ICE_AQ_RC_EBADBUF:
37748c2ecf20Sopenharmony_ci			dev_err(dev, "An error occurred on the device while loading the DDP package.  The device will be reset.\n");
37758c2ecf20Sopenharmony_ci			/* poll for reset to complete */
37768c2ecf20Sopenharmony_ci			if (ice_check_reset(hw))
37778c2ecf20Sopenharmony_ci				dev_err(dev, "Error resetting device. Please reload the driver\n");
37788c2ecf20Sopenharmony_ci			return;
37798c2ecf20Sopenharmony_ci		default:
37808c2ecf20Sopenharmony_ci			break;
37818c2ecf20Sopenharmony_ci		}
37828c2ecf20Sopenharmony_ci		fallthrough;
37838c2ecf20Sopenharmony_ci	default:
37848c2ecf20Sopenharmony_ci		dev_err(dev, "An unknown error (%d) occurred when loading the DDP package.  Entering Safe Mode.\n",
37858c2ecf20Sopenharmony_ci			*status);
37868c2ecf20Sopenharmony_ci		break;
37878c2ecf20Sopenharmony_ci	}
37888c2ecf20Sopenharmony_ci}
37898c2ecf20Sopenharmony_ci
37908c2ecf20Sopenharmony_ci/**
37918c2ecf20Sopenharmony_ci * ice_load_pkg - load/reload the DDP Package file
37928c2ecf20Sopenharmony_ci * @firmware: firmware structure when firmware requested or NULL for reload
37938c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
37948c2ecf20Sopenharmony_ci *
37958c2ecf20Sopenharmony_ci * Called on probe and post CORER/GLOBR rebuild to load DDP Package and
37968c2ecf20Sopenharmony_ci * initialize HW tables.
37978c2ecf20Sopenharmony_ci */
37988c2ecf20Sopenharmony_cistatic void
37998c2ecf20Sopenharmony_ciice_load_pkg(const struct firmware *firmware, struct ice_pf *pf)
38008c2ecf20Sopenharmony_ci{
38018c2ecf20Sopenharmony_ci	enum ice_status status = ICE_ERR_PARAM;
38028c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
38038c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
38048c2ecf20Sopenharmony_ci
38058c2ecf20Sopenharmony_ci	/* Load DDP Package */
38068c2ecf20Sopenharmony_ci	if (firmware && !hw->pkg_copy) {
38078c2ecf20Sopenharmony_ci		status = ice_copy_and_init_pkg(hw, firmware->data,
38088c2ecf20Sopenharmony_ci					       firmware->size);
38098c2ecf20Sopenharmony_ci		ice_log_pkg_init(hw, &status);
38108c2ecf20Sopenharmony_ci	} else if (!firmware && hw->pkg_copy) {
38118c2ecf20Sopenharmony_ci		/* Reload package during rebuild after CORER/GLOBR reset */
38128c2ecf20Sopenharmony_ci		status = ice_init_pkg(hw, hw->pkg_copy, hw->pkg_size);
38138c2ecf20Sopenharmony_ci		ice_log_pkg_init(hw, &status);
38148c2ecf20Sopenharmony_ci	} else {
38158c2ecf20Sopenharmony_ci		dev_err(dev, "The DDP package file failed to load. Entering Safe Mode.\n");
38168c2ecf20Sopenharmony_ci	}
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_ci	if (status) {
38198c2ecf20Sopenharmony_ci		/* Safe Mode */
38208c2ecf20Sopenharmony_ci		clear_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
38218c2ecf20Sopenharmony_ci		return;
38228c2ecf20Sopenharmony_ci	}
38238c2ecf20Sopenharmony_ci
38248c2ecf20Sopenharmony_ci	/* Successful download package is the precondition for advanced
38258c2ecf20Sopenharmony_ci	 * features, hence setting the ICE_FLAG_ADV_FEATURES flag
38268c2ecf20Sopenharmony_ci	 */
38278c2ecf20Sopenharmony_ci	set_bit(ICE_FLAG_ADV_FEATURES, pf->flags);
38288c2ecf20Sopenharmony_ci}
38298c2ecf20Sopenharmony_ci
38308c2ecf20Sopenharmony_ci/**
38318c2ecf20Sopenharmony_ci * ice_verify_cacheline_size - verify driver's assumption of 64 Byte cache lines
38328c2ecf20Sopenharmony_ci * @pf: pointer to the PF structure
38338c2ecf20Sopenharmony_ci *
38348c2ecf20Sopenharmony_ci * There is no error returned here because the driver should be able to handle
38358c2ecf20Sopenharmony_ci * 128 Byte cache lines, so we only print a warning in case issues are seen,
38368c2ecf20Sopenharmony_ci * specifically with Tx.
38378c2ecf20Sopenharmony_ci */
38388c2ecf20Sopenharmony_cistatic void ice_verify_cacheline_size(struct ice_pf *pf)
38398c2ecf20Sopenharmony_ci{
38408c2ecf20Sopenharmony_ci	if (rd32(&pf->hw, GLPCI_CNF2) & GLPCI_CNF2_CACHELINE_SIZE_M)
38418c2ecf20Sopenharmony_ci		dev_warn(ice_pf_to_dev(pf), "%d Byte cache line assumption is invalid, driver may have Tx timeouts!\n",
38428c2ecf20Sopenharmony_ci			 ICE_CACHE_LINE_BYTES);
38438c2ecf20Sopenharmony_ci}
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci/**
38468c2ecf20Sopenharmony_ci * ice_send_version - update firmware with driver version
38478c2ecf20Sopenharmony_ci * @pf: PF struct
38488c2ecf20Sopenharmony_ci *
38498c2ecf20Sopenharmony_ci * Returns ICE_SUCCESS on success, else error code
38508c2ecf20Sopenharmony_ci */
38518c2ecf20Sopenharmony_cistatic enum ice_status ice_send_version(struct ice_pf *pf)
38528c2ecf20Sopenharmony_ci{
38538c2ecf20Sopenharmony_ci	struct ice_driver_ver dv;
38548c2ecf20Sopenharmony_ci
38558c2ecf20Sopenharmony_ci	dv.major_ver = 0xff;
38568c2ecf20Sopenharmony_ci	dv.minor_ver = 0xff;
38578c2ecf20Sopenharmony_ci	dv.build_ver = 0xff;
38588c2ecf20Sopenharmony_ci	dv.subbuild_ver = 0;
38598c2ecf20Sopenharmony_ci	strscpy((char *)dv.driver_string, UTS_RELEASE,
38608c2ecf20Sopenharmony_ci		sizeof(dv.driver_string));
38618c2ecf20Sopenharmony_ci	return ice_aq_send_driver_ver(&pf->hw, &dv, NULL);
38628c2ecf20Sopenharmony_ci}
38638c2ecf20Sopenharmony_ci
38648c2ecf20Sopenharmony_ci/**
38658c2ecf20Sopenharmony_ci * ice_init_fdir - Initialize flow director VSI and configuration
38668c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
38678c2ecf20Sopenharmony_ci *
38688c2ecf20Sopenharmony_ci * returns 0 on success, negative on error
38698c2ecf20Sopenharmony_ci */
38708c2ecf20Sopenharmony_cistatic int ice_init_fdir(struct ice_pf *pf)
38718c2ecf20Sopenharmony_ci{
38728c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
38738c2ecf20Sopenharmony_ci	struct ice_vsi *ctrl_vsi;
38748c2ecf20Sopenharmony_ci	int err;
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	/* Side Band Flow Director needs to have a control VSI.
38778c2ecf20Sopenharmony_ci	 * Allocate it and store it in the PF.
38788c2ecf20Sopenharmony_ci	 */
38798c2ecf20Sopenharmony_ci	ctrl_vsi = ice_ctrl_vsi_setup(pf, pf->hw.port_info);
38808c2ecf20Sopenharmony_ci	if (!ctrl_vsi) {
38818c2ecf20Sopenharmony_ci		dev_dbg(dev, "could not create control VSI\n");
38828c2ecf20Sopenharmony_ci		return -ENOMEM;
38838c2ecf20Sopenharmony_ci	}
38848c2ecf20Sopenharmony_ci
38858c2ecf20Sopenharmony_ci	err = ice_vsi_open_ctrl(ctrl_vsi);
38868c2ecf20Sopenharmony_ci	if (err) {
38878c2ecf20Sopenharmony_ci		dev_dbg(dev, "could not open control VSI\n");
38888c2ecf20Sopenharmony_ci		goto err_vsi_open;
38898c2ecf20Sopenharmony_ci	}
38908c2ecf20Sopenharmony_ci
38918c2ecf20Sopenharmony_ci	mutex_init(&pf->hw.fdir_fltr_lock);
38928c2ecf20Sopenharmony_ci
38938c2ecf20Sopenharmony_ci	err = ice_fdir_create_dflt_rules(pf);
38948c2ecf20Sopenharmony_ci	if (err)
38958c2ecf20Sopenharmony_ci		goto err_fdir_rule;
38968c2ecf20Sopenharmony_ci
38978c2ecf20Sopenharmony_ci	return 0;
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_cierr_fdir_rule:
39008c2ecf20Sopenharmony_ci	ice_fdir_release_flows(&pf->hw);
39018c2ecf20Sopenharmony_ci	ice_vsi_close(ctrl_vsi);
39028c2ecf20Sopenharmony_cierr_vsi_open:
39038c2ecf20Sopenharmony_ci	ice_vsi_release(ctrl_vsi);
39048c2ecf20Sopenharmony_ci	if (pf->ctrl_vsi_idx != ICE_NO_VSI) {
39058c2ecf20Sopenharmony_ci		pf->vsi[pf->ctrl_vsi_idx] = NULL;
39068c2ecf20Sopenharmony_ci		pf->ctrl_vsi_idx = ICE_NO_VSI;
39078c2ecf20Sopenharmony_ci	}
39088c2ecf20Sopenharmony_ci	return err;
39098c2ecf20Sopenharmony_ci}
39108c2ecf20Sopenharmony_ci
39118c2ecf20Sopenharmony_ci/**
39128c2ecf20Sopenharmony_ci * ice_get_opt_fw_name - return optional firmware file name or NULL
39138c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
39148c2ecf20Sopenharmony_ci */
39158c2ecf20Sopenharmony_cistatic char *ice_get_opt_fw_name(struct ice_pf *pf)
39168c2ecf20Sopenharmony_ci{
39178c2ecf20Sopenharmony_ci	/* Optional firmware name same as default with additional dash
39188c2ecf20Sopenharmony_ci	 * followed by a EUI-64 identifier (PCIe Device Serial Number)
39198c2ecf20Sopenharmony_ci	 */
39208c2ecf20Sopenharmony_ci	struct pci_dev *pdev = pf->pdev;
39218c2ecf20Sopenharmony_ci	char *opt_fw_filename;
39228c2ecf20Sopenharmony_ci	u64 dsn;
39238c2ecf20Sopenharmony_ci
39248c2ecf20Sopenharmony_ci	/* Determine the name of the optional file using the DSN (two
39258c2ecf20Sopenharmony_ci	 * dwords following the start of the DSN Capability).
39268c2ecf20Sopenharmony_ci	 */
39278c2ecf20Sopenharmony_ci	dsn = pci_get_dsn(pdev);
39288c2ecf20Sopenharmony_ci	if (!dsn)
39298c2ecf20Sopenharmony_ci		return NULL;
39308c2ecf20Sopenharmony_ci
39318c2ecf20Sopenharmony_ci	opt_fw_filename = kzalloc(NAME_MAX, GFP_KERNEL);
39328c2ecf20Sopenharmony_ci	if (!opt_fw_filename)
39338c2ecf20Sopenharmony_ci		return NULL;
39348c2ecf20Sopenharmony_ci
39358c2ecf20Sopenharmony_ci	snprintf(opt_fw_filename, NAME_MAX, "%sice-%016llx.pkg",
39368c2ecf20Sopenharmony_ci		 ICE_DDP_PKG_PATH, dsn);
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci	return opt_fw_filename;
39398c2ecf20Sopenharmony_ci}
39408c2ecf20Sopenharmony_ci
39418c2ecf20Sopenharmony_ci/**
39428c2ecf20Sopenharmony_ci * ice_request_fw - Device initialization routine
39438c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
39448c2ecf20Sopenharmony_ci */
39458c2ecf20Sopenharmony_cistatic void ice_request_fw(struct ice_pf *pf)
39468c2ecf20Sopenharmony_ci{
39478c2ecf20Sopenharmony_ci	char *opt_fw_filename = ice_get_opt_fw_name(pf);
39488c2ecf20Sopenharmony_ci	const struct firmware *firmware = NULL;
39498c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
39508c2ecf20Sopenharmony_ci	int err = 0;
39518c2ecf20Sopenharmony_ci
39528c2ecf20Sopenharmony_ci	/* optional device-specific DDP (if present) overrides the default DDP
39538c2ecf20Sopenharmony_ci	 * package file. kernel logs a debug message if the file doesn't exist,
39548c2ecf20Sopenharmony_ci	 * and warning messages for other errors.
39558c2ecf20Sopenharmony_ci	 */
39568c2ecf20Sopenharmony_ci	if (opt_fw_filename) {
39578c2ecf20Sopenharmony_ci		err = firmware_request_nowarn(&firmware, opt_fw_filename, dev);
39588c2ecf20Sopenharmony_ci		if (err) {
39598c2ecf20Sopenharmony_ci			kfree(opt_fw_filename);
39608c2ecf20Sopenharmony_ci			goto dflt_pkg_load;
39618c2ecf20Sopenharmony_ci		}
39628c2ecf20Sopenharmony_ci
39638c2ecf20Sopenharmony_ci		/* request for firmware was successful. Download to device */
39648c2ecf20Sopenharmony_ci		ice_load_pkg(firmware, pf);
39658c2ecf20Sopenharmony_ci		kfree(opt_fw_filename);
39668c2ecf20Sopenharmony_ci		release_firmware(firmware);
39678c2ecf20Sopenharmony_ci		return;
39688c2ecf20Sopenharmony_ci	}
39698c2ecf20Sopenharmony_ci
39708c2ecf20Sopenharmony_cidflt_pkg_load:
39718c2ecf20Sopenharmony_ci	err = request_firmware(&firmware, ICE_DDP_PKG_FILE, dev);
39728c2ecf20Sopenharmony_ci	if (err) {
39738c2ecf20Sopenharmony_ci		dev_err(dev, "The DDP package file was not found or could not be read. Entering Safe Mode\n");
39748c2ecf20Sopenharmony_ci		return;
39758c2ecf20Sopenharmony_ci	}
39768c2ecf20Sopenharmony_ci
39778c2ecf20Sopenharmony_ci	/* request for firmware was successful. Download to device */
39788c2ecf20Sopenharmony_ci	ice_load_pkg(firmware, pf);
39798c2ecf20Sopenharmony_ci	release_firmware(firmware);
39808c2ecf20Sopenharmony_ci}
39818c2ecf20Sopenharmony_ci
39828c2ecf20Sopenharmony_ci/**
39838c2ecf20Sopenharmony_ci * ice_print_wake_reason - show the wake up cause in the log
39848c2ecf20Sopenharmony_ci * @pf: pointer to the PF struct
39858c2ecf20Sopenharmony_ci */
39868c2ecf20Sopenharmony_cistatic void ice_print_wake_reason(struct ice_pf *pf)
39878c2ecf20Sopenharmony_ci{
39888c2ecf20Sopenharmony_ci	u32 wus = pf->wakeup_reason;
39898c2ecf20Sopenharmony_ci	const char *wake_str;
39908c2ecf20Sopenharmony_ci
39918c2ecf20Sopenharmony_ci	/* if no wake event, nothing to print */
39928c2ecf20Sopenharmony_ci	if (!wus)
39938c2ecf20Sopenharmony_ci		return;
39948c2ecf20Sopenharmony_ci
39958c2ecf20Sopenharmony_ci	if (wus & PFPM_WUS_LNKC_M)
39968c2ecf20Sopenharmony_ci		wake_str = "Link\n";
39978c2ecf20Sopenharmony_ci	else if (wus & PFPM_WUS_MAG_M)
39988c2ecf20Sopenharmony_ci		wake_str = "Magic Packet\n";
39998c2ecf20Sopenharmony_ci	else if (wus & PFPM_WUS_MNG_M)
40008c2ecf20Sopenharmony_ci		wake_str = "Management\n";
40018c2ecf20Sopenharmony_ci	else if (wus & PFPM_WUS_FW_RST_WK_M)
40028c2ecf20Sopenharmony_ci		wake_str = "Firmware Reset\n";
40038c2ecf20Sopenharmony_ci	else
40048c2ecf20Sopenharmony_ci		wake_str = "Unknown\n";
40058c2ecf20Sopenharmony_ci
40068c2ecf20Sopenharmony_ci	dev_info(ice_pf_to_dev(pf), "Wake reason: %s", wake_str);
40078c2ecf20Sopenharmony_ci}
40088c2ecf20Sopenharmony_ci
40098c2ecf20Sopenharmony_ci/**
40108c2ecf20Sopenharmony_ci * ice_probe - Device initialization routine
40118c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
40128c2ecf20Sopenharmony_ci * @ent: entry in ice_pci_tbl
40138c2ecf20Sopenharmony_ci *
40148c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
40158c2ecf20Sopenharmony_ci */
40168c2ecf20Sopenharmony_cistatic int
40178c2ecf20Sopenharmony_ciice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
40188c2ecf20Sopenharmony_ci{
40198c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
40208c2ecf20Sopenharmony_ci	struct ice_pf *pf;
40218c2ecf20Sopenharmony_ci	struct ice_hw *hw;
40228c2ecf20Sopenharmony_ci	int i, err;
40238c2ecf20Sopenharmony_ci
40248c2ecf20Sopenharmony_ci	if (pdev->is_virtfn) {
40258c2ecf20Sopenharmony_ci		dev_err(dev, "can't probe a virtual function\n");
40268c2ecf20Sopenharmony_ci		return -EINVAL;
40278c2ecf20Sopenharmony_ci	}
40288c2ecf20Sopenharmony_ci
40298c2ecf20Sopenharmony_ci	/* when under a kdump kernel initiate a reset before enabling the
40308c2ecf20Sopenharmony_ci	 * device in order to clear out any pending DMA transactions. These
40318c2ecf20Sopenharmony_ci	 * transactions can cause some systems to machine check when doing
40328c2ecf20Sopenharmony_ci	 * the pcim_enable_device() below.
40338c2ecf20Sopenharmony_ci	 */
40348c2ecf20Sopenharmony_ci	if (is_kdump_kernel()) {
40358c2ecf20Sopenharmony_ci		pci_save_state(pdev);
40368c2ecf20Sopenharmony_ci		pci_clear_master(pdev);
40378c2ecf20Sopenharmony_ci		err = pcie_flr(pdev);
40388c2ecf20Sopenharmony_ci		if (err)
40398c2ecf20Sopenharmony_ci			return err;
40408c2ecf20Sopenharmony_ci		pci_restore_state(pdev);
40418c2ecf20Sopenharmony_ci	}
40428c2ecf20Sopenharmony_ci
40438c2ecf20Sopenharmony_ci	/* this driver uses devres, see
40448c2ecf20Sopenharmony_ci	 * Documentation/driver-api/driver-model/devres.rst
40458c2ecf20Sopenharmony_ci	 */
40468c2ecf20Sopenharmony_ci	err = pcim_enable_device(pdev);
40478c2ecf20Sopenharmony_ci	if (err)
40488c2ecf20Sopenharmony_ci		return err;
40498c2ecf20Sopenharmony_ci
40508c2ecf20Sopenharmony_ci	err = pcim_iomap_regions(pdev, BIT(ICE_BAR0), pci_name(pdev));
40518c2ecf20Sopenharmony_ci	if (err) {
40528c2ecf20Sopenharmony_ci		dev_err(dev, "BAR0 I/O map error %d\n", err);
40538c2ecf20Sopenharmony_ci		return err;
40548c2ecf20Sopenharmony_ci	}
40558c2ecf20Sopenharmony_ci
40568c2ecf20Sopenharmony_ci	pf = ice_allocate_pf(dev);
40578c2ecf20Sopenharmony_ci	if (!pf)
40588c2ecf20Sopenharmony_ci		return -ENOMEM;
40598c2ecf20Sopenharmony_ci
40608c2ecf20Sopenharmony_ci	/* set up for high or low DMA */
40618c2ecf20Sopenharmony_ci	err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
40628c2ecf20Sopenharmony_ci	if (err)
40638c2ecf20Sopenharmony_ci		err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
40648c2ecf20Sopenharmony_ci	if (err) {
40658c2ecf20Sopenharmony_ci		dev_err(dev, "DMA configuration failed: 0x%x\n", err);
40668c2ecf20Sopenharmony_ci		return err;
40678c2ecf20Sopenharmony_ci	}
40688c2ecf20Sopenharmony_ci
40698c2ecf20Sopenharmony_ci	pci_enable_pcie_error_reporting(pdev);
40708c2ecf20Sopenharmony_ci	pci_set_master(pdev);
40718c2ecf20Sopenharmony_ci
40728c2ecf20Sopenharmony_ci	pf->pdev = pdev;
40738c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, pf);
40748c2ecf20Sopenharmony_ci	set_bit(__ICE_DOWN, pf->state);
40758c2ecf20Sopenharmony_ci	/* Disable service task until DOWN bit is cleared */
40768c2ecf20Sopenharmony_ci	set_bit(__ICE_SERVICE_DIS, pf->state);
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	hw = &pf->hw;
40798c2ecf20Sopenharmony_ci	hw->hw_addr = pcim_iomap_table(pdev)[ICE_BAR0];
40808c2ecf20Sopenharmony_ci	pci_save_state(pdev);
40818c2ecf20Sopenharmony_ci
40828c2ecf20Sopenharmony_ci	hw->back = pf;
40838c2ecf20Sopenharmony_ci	hw->vendor_id = pdev->vendor;
40848c2ecf20Sopenharmony_ci	hw->device_id = pdev->device;
40858c2ecf20Sopenharmony_ci	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
40868c2ecf20Sopenharmony_ci	hw->subsystem_vendor_id = pdev->subsystem_vendor;
40878c2ecf20Sopenharmony_ci	hw->subsystem_device_id = pdev->subsystem_device;
40888c2ecf20Sopenharmony_ci	hw->bus.device = PCI_SLOT(pdev->devfn);
40898c2ecf20Sopenharmony_ci	hw->bus.func = PCI_FUNC(pdev->devfn);
40908c2ecf20Sopenharmony_ci	ice_set_ctrlq_len(hw);
40918c2ecf20Sopenharmony_ci
40928c2ecf20Sopenharmony_ci	pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci	err = ice_devlink_register(pf);
40958c2ecf20Sopenharmony_ci	if (err) {
40968c2ecf20Sopenharmony_ci		dev_err(dev, "ice_devlink_register failed: %d\n", err);
40978c2ecf20Sopenharmony_ci		goto err_exit_unroll;
40988c2ecf20Sopenharmony_ci	}
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci#ifndef CONFIG_DYNAMIC_DEBUG
41018c2ecf20Sopenharmony_ci	if (debug < -1)
41028c2ecf20Sopenharmony_ci		hw->debug_mask = debug;
41038c2ecf20Sopenharmony_ci#endif
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_ci	err = ice_init_hw(hw);
41068c2ecf20Sopenharmony_ci	if (err) {
41078c2ecf20Sopenharmony_ci		dev_err(dev, "ice_init_hw failed: %d\n", err);
41088c2ecf20Sopenharmony_ci		err = -EIO;
41098c2ecf20Sopenharmony_ci		goto err_exit_unroll;
41108c2ecf20Sopenharmony_ci	}
41118c2ecf20Sopenharmony_ci
41128c2ecf20Sopenharmony_ci	ice_request_fw(pf);
41138c2ecf20Sopenharmony_ci
41148c2ecf20Sopenharmony_ci	/* if ice_request_fw fails, ICE_FLAG_ADV_FEATURES bit won't be
41158c2ecf20Sopenharmony_ci	 * set in pf->state, which will cause ice_is_safe_mode to return
41168c2ecf20Sopenharmony_ci	 * true
41178c2ecf20Sopenharmony_ci	 */
41188c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
41198c2ecf20Sopenharmony_ci		dev_err(dev, "Package download failed. Advanced features disabled - Device now in Safe Mode\n");
41208c2ecf20Sopenharmony_ci		/* we already got function/device capabilities but these don't
41218c2ecf20Sopenharmony_ci		 * reflect what the driver needs to do in safe mode. Instead of
41228c2ecf20Sopenharmony_ci		 * adding conditional logic everywhere to ignore these
41238c2ecf20Sopenharmony_ci		 * device/function capabilities, override them.
41248c2ecf20Sopenharmony_ci		 */
41258c2ecf20Sopenharmony_ci		ice_set_safe_mode_caps(hw);
41268c2ecf20Sopenharmony_ci	}
41278c2ecf20Sopenharmony_ci
41288c2ecf20Sopenharmony_ci	err = ice_init_pf(pf);
41298c2ecf20Sopenharmony_ci	if (err) {
41308c2ecf20Sopenharmony_ci		dev_err(dev, "ice_init_pf failed: %d\n", err);
41318c2ecf20Sopenharmony_ci		goto err_init_pf_unroll;
41328c2ecf20Sopenharmony_ci	}
41338c2ecf20Sopenharmony_ci
41348c2ecf20Sopenharmony_ci	ice_devlink_init_regions(pf);
41358c2ecf20Sopenharmony_ci
41368c2ecf20Sopenharmony_ci	pf->hw.udp_tunnel_nic.set_port = ice_udp_tunnel_set_port;
41378c2ecf20Sopenharmony_ci	pf->hw.udp_tunnel_nic.unset_port = ice_udp_tunnel_unset_port;
41388c2ecf20Sopenharmony_ci	pf->hw.udp_tunnel_nic.flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP;
41398c2ecf20Sopenharmony_ci	pf->hw.udp_tunnel_nic.shared = &pf->hw.udp_tunnel_shared;
41408c2ecf20Sopenharmony_ci	i = 0;
41418c2ecf20Sopenharmony_ci	if (pf->hw.tnl.valid_count[TNL_VXLAN]) {
41428c2ecf20Sopenharmony_ci		pf->hw.udp_tunnel_nic.tables[i].n_entries =
41438c2ecf20Sopenharmony_ci			pf->hw.tnl.valid_count[TNL_VXLAN];
41448c2ecf20Sopenharmony_ci		pf->hw.udp_tunnel_nic.tables[i].tunnel_types =
41458c2ecf20Sopenharmony_ci			UDP_TUNNEL_TYPE_VXLAN;
41468c2ecf20Sopenharmony_ci		i++;
41478c2ecf20Sopenharmony_ci	}
41488c2ecf20Sopenharmony_ci	if (pf->hw.tnl.valid_count[TNL_GENEVE]) {
41498c2ecf20Sopenharmony_ci		pf->hw.udp_tunnel_nic.tables[i].n_entries =
41508c2ecf20Sopenharmony_ci			pf->hw.tnl.valid_count[TNL_GENEVE];
41518c2ecf20Sopenharmony_ci		pf->hw.udp_tunnel_nic.tables[i].tunnel_types =
41528c2ecf20Sopenharmony_ci			UDP_TUNNEL_TYPE_GENEVE;
41538c2ecf20Sopenharmony_ci		i++;
41548c2ecf20Sopenharmony_ci	}
41558c2ecf20Sopenharmony_ci
41568c2ecf20Sopenharmony_ci	pf->num_alloc_vsi = hw->func_caps.guar_num_vsi;
41578c2ecf20Sopenharmony_ci	if (!pf->num_alloc_vsi) {
41588c2ecf20Sopenharmony_ci		err = -EIO;
41598c2ecf20Sopenharmony_ci		goto err_init_pf_unroll;
41608c2ecf20Sopenharmony_ci	}
41618c2ecf20Sopenharmony_ci	if (pf->num_alloc_vsi > UDP_TUNNEL_NIC_MAX_SHARING_DEVICES) {
41628c2ecf20Sopenharmony_ci		dev_warn(&pf->pdev->dev,
41638c2ecf20Sopenharmony_ci			 "limiting the VSI count due to UDP tunnel limitation %d > %d\n",
41648c2ecf20Sopenharmony_ci			 pf->num_alloc_vsi, UDP_TUNNEL_NIC_MAX_SHARING_DEVICES);
41658c2ecf20Sopenharmony_ci		pf->num_alloc_vsi = UDP_TUNNEL_NIC_MAX_SHARING_DEVICES;
41668c2ecf20Sopenharmony_ci	}
41678c2ecf20Sopenharmony_ci
41688c2ecf20Sopenharmony_ci	pf->vsi = devm_kcalloc(dev, pf->num_alloc_vsi, sizeof(*pf->vsi),
41698c2ecf20Sopenharmony_ci			       GFP_KERNEL);
41708c2ecf20Sopenharmony_ci	if (!pf->vsi) {
41718c2ecf20Sopenharmony_ci		err = -ENOMEM;
41728c2ecf20Sopenharmony_ci		goto err_init_pf_unroll;
41738c2ecf20Sopenharmony_ci	}
41748c2ecf20Sopenharmony_ci
41758c2ecf20Sopenharmony_ci	err = ice_init_interrupt_scheme(pf);
41768c2ecf20Sopenharmony_ci	if (err) {
41778c2ecf20Sopenharmony_ci		dev_err(dev, "ice_init_interrupt_scheme failed: %d\n", err);
41788c2ecf20Sopenharmony_ci		err = -EIO;
41798c2ecf20Sopenharmony_ci		goto err_init_vsi_unroll;
41808c2ecf20Sopenharmony_ci	}
41818c2ecf20Sopenharmony_ci
41828c2ecf20Sopenharmony_ci	/* In case of MSIX we are going to setup the misc vector right here
41838c2ecf20Sopenharmony_ci	 * to handle admin queue events etc. In case of legacy and MSI
41848c2ecf20Sopenharmony_ci	 * the misc functionality and queue processing is combined in
41858c2ecf20Sopenharmony_ci	 * the same vector and that gets setup at open.
41868c2ecf20Sopenharmony_ci	 */
41878c2ecf20Sopenharmony_ci	err = ice_req_irq_msix_misc(pf);
41888c2ecf20Sopenharmony_ci	if (err) {
41898c2ecf20Sopenharmony_ci		dev_err(dev, "setup of misc vector failed: %d\n", err);
41908c2ecf20Sopenharmony_ci		goto err_init_interrupt_unroll;
41918c2ecf20Sopenharmony_ci	}
41928c2ecf20Sopenharmony_ci
41938c2ecf20Sopenharmony_ci	/* create switch struct for the switch element created by FW on boot */
41948c2ecf20Sopenharmony_ci	pf->first_sw = devm_kzalloc(dev, sizeof(*pf->first_sw), GFP_KERNEL);
41958c2ecf20Sopenharmony_ci	if (!pf->first_sw) {
41968c2ecf20Sopenharmony_ci		err = -ENOMEM;
41978c2ecf20Sopenharmony_ci		goto err_msix_misc_unroll;
41988c2ecf20Sopenharmony_ci	}
41998c2ecf20Sopenharmony_ci
42008c2ecf20Sopenharmony_ci	if (hw->evb_veb)
42018c2ecf20Sopenharmony_ci		pf->first_sw->bridge_mode = BRIDGE_MODE_VEB;
42028c2ecf20Sopenharmony_ci	else
42038c2ecf20Sopenharmony_ci		pf->first_sw->bridge_mode = BRIDGE_MODE_VEPA;
42048c2ecf20Sopenharmony_ci
42058c2ecf20Sopenharmony_ci	pf->first_sw->pf = pf;
42068c2ecf20Sopenharmony_ci
42078c2ecf20Sopenharmony_ci	/* record the sw_id available for later use */
42088c2ecf20Sopenharmony_ci	pf->first_sw->sw_id = hw->port_info->sw_id;
42098c2ecf20Sopenharmony_ci
42108c2ecf20Sopenharmony_ci	err = ice_setup_pf_sw(pf);
42118c2ecf20Sopenharmony_ci	if (err) {
42128c2ecf20Sopenharmony_ci		dev_err(dev, "probe failed due to setup PF switch: %d\n", err);
42138c2ecf20Sopenharmony_ci		goto err_alloc_sw_unroll;
42148c2ecf20Sopenharmony_ci	}
42158c2ecf20Sopenharmony_ci
42168c2ecf20Sopenharmony_ci	clear_bit(__ICE_SERVICE_DIS, pf->state);
42178c2ecf20Sopenharmony_ci
42188c2ecf20Sopenharmony_ci	/* tell the firmware we are up */
42198c2ecf20Sopenharmony_ci	err = ice_send_version(pf);
42208c2ecf20Sopenharmony_ci	if (err) {
42218c2ecf20Sopenharmony_ci		dev_err(dev, "probe failed sending driver version %s. error: %d\n",
42228c2ecf20Sopenharmony_ci			UTS_RELEASE, err);
42238c2ecf20Sopenharmony_ci		goto err_send_version_unroll;
42248c2ecf20Sopenharmony_ci	}
42258c2ecf20Sopenharmony_ci
42268c2ecf20Sopenharmony_ci	/* since everything is good, start the service timer */
42278c2ecf20Sopenharmony_ci	mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
42288c2ecf20Sopenharmony_ci
42298c2ecf20Sopenharmony_ci	err = ice_init_link_events(pf->hw.port_info);
42308c2ecf20Sopenharmony_ci	if (err) {
42318c2ecf20Sopenharmony_ci		dev_err(dev, "ice_init_link_events failed: %d\n", err);
42328c2ecf20Sopenharmony_ci		goto err_send_version_unroll;
42338c2ecf20Sopenharmony_ci	}
42348c2ecf20Sopenharmony_ci
42358c2ecf20Sopenharmony_ci	/* not a fatal error if this fails */
42368c2ecf20Sopenharmony_ci	err = ice_init_nvm_phy_type(pf->hw.port_info);
42378c2ecf20Sopenharmony_ci	if (err)
42388c2ecf20Sopenharmony_ci		dev_err(dev, "ice_init_nvm_phy_type failed: %d\n", err);
42398c2ecf20Sopenharmony_ci
42408c2ecf20Sopenharmony_ci	/* not a fatal error if this fails */
42418c2ecf20Sopenharmony_ci	err = ice_update_link_info(pf->hw.port_info);
42428c2ecf20Sopenharmony_ci	if (err)
42438c2ecf20Sopenharmony_ci		dev_err(dev, "ice_update_link_info failed: %d\n", err);
42448c2ecf20Sopenharmony_ci
42458c2ecf20Sopenharmony_ci	ice_init_link_dflt_override(pf->hw.port_info);
42468c2ecf20Sopenharmony_ci
42478c2ecf20Sopenharmony_ci	/* if media available, initialize PHY settings */
42488c2ecf20Sopenharmony_ci	if (pf->hw.port_info->phy.link_info.link_info &
42498c2ecf20Sopenharmony_ci	    ICE_AQ_MEDIA_AVAILABLE) {
42508c2ecf20Sopenharmony_ci		/* not a fatal error if this fails */
42518c2ecf20Sopenharmony_ci		err = ice_init_phy_user_cfg(pf->hw.port_info);
42528c2ecf20Sopenharmony_ci		if (err)
42538c2ecf20Sopenharmony_ci			dev_err(dev, "ice_init_phy_user_cfg failed: %d\n", err);
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci		if (!test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags)) {
42568c2ecf20Sopenharmony_ci			struct ice_vsi *vsi = ice_get_main_vsi(pf);
42578c2ecf20Sopenharmony_ci
42588c2ecf20Sopenharmony_ci			if (vsi)
42598c2ecf20Sopenharmony_ci				ice_configure_phy(vsi);
42608c2ecf20Sopenharmony_ci		}
42618c2ecf20Sopenharmony_ci	} else {
42628c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_NO_MEDIA, pf->flags);
42638c2ecf20Sopenharmony_ci	}
42648c2ecf20Sopenharmony_ci
42658c2ecf20Sopenharmony_ci	ice_verify_cacheline_size(pf);
42668c2ecf20Sopenharmony_ci
42678c2ecf20Sopenharmony_ci	/* Save wakeup reason register for later use */
42688c2ecf20Sopenharmony_ci	pf->wakeup_reason = rd32(hw, PFPM_WUS);
42698c2ecf20Sopenharmony_ci
42708c2ecf20Sopenharmony_ci	/* check for a power management event */
42718c2ecf20Sopenharmony_ci	ice_print_wake_reason(pf);
42728c2ecf20Sopenharmony_ci
42738c2ecf20Sopenharmony_ci	/* clear wake status, all bits */
42748c2ecf20Sopenharmony_ci	wr32(hw, PFPM_WUS, U32_MAX);
42758c2ecf20Sopenharmony_ci
42768c2ecf20Sopenharmony_ci	/* Disable WoL at init, wait for user to enable */
42778c2ecf20Sopenharmony_ci	device_set_wakeup_enable(dev, false);
42788c2ecf20Sopenharmony_ci
42798c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(pf)) {
42808c2ecf20Sopenharmony_ci		ice_set_safe_mode_vlan_cfg(pf);
42818c2ecf20Sopenharmony_ci		goto probe_done;
42828c2ecf20Sopenharmony_ci	}
42838c2ecf20Sopenharmony_ci
42848c2ecf20Sopenharmony_ci	/* initialize DDP driven features */
42858c2ecf20Sopenharmony_ci
42868c2ecf20Sopenharmony_ci	/* Note: Flow director init failure is non-fatal to load */
42878c2ecf20Sopenharmony_ci	if (ice_init_fdir(pf))
42888c2ecf20Sopenharmony_ci		dev_err(dev, "could not initialize flow director\n");
42898c2ecf20Sopenharmony_ci
42908c2ecf20Sopenharmony_ci	/* Note: DCB init failure is non-fatal to load */
42918c2ecf20Sopenharmony_ci	if (ice_init_pf_dcb(pf, false)) {
42928c2ecf20Sopenharmony_ci		clear_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
42938c2ecf20Sopenharmony_ci		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
42948c2ecf20Sopenharmony_ci	} else {
42958c2ecf20Sopenharmony_ci		ice_cfg_lldp_mib_change(&pf->hw, true);
42968c2ecf20Sopenharmony_ci	}
42978c2ecf20Sopenharmony_ci
42988c2ecf20Sopenharmony_ci	/* print PCI link speed and width */
42998c2ecf20Sopenharmony_ci	pcie_print_link_status(pf->pdev);
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ciprobe_done:
43028c2ecf20Sopenharmony_ci	/* ready to go, so clear down state bit */
43038c2ecf20Sopenharmony_ci	clear_bit(__ICE_DOWN, pf->state);
43048c2ecf20Sopenharmony_ci	return 0;
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_cierr_send_version_unroll:
43078c2ecf20Sopenharmony_ci	ice_vsi_release_all(pf);
43088c2ecf20Sopenharmony_cierr_alloc_sw_unroll:
43098c2ecf20Sopenharmony_ci	set_bit(__ICE_SERVICE_DIS, pf->state);
43108c2ecf20Sopenharmony_ci	set_bit(__ICE_DOWN, pf->state);
43118c2ecf20Sopenharmony_ci	devm_kfree(dev, pf->first_sw);
43128c2ecf20Sopenharmony_cierr_msix_misc_unroll:
43138c2ecf20Sopenharmony_ci	ice_free_irq_msix_misc(pf);
43148c2ecf20Sopenharmony_cierr_init_interrupt_unroll:
43158c2ecf20Sopenharmony_ci	ice_clear_interrupt_scheme(pf);
43168c2ecf20Sopenharmony_cierr_init_vsi_unroll:
43178c2ecf20Sopenharmony_ci	devm_kfree(dev, pf->vsi);
43188c2ecf20Sopenharmony_cierr_init_pf_unroll:
43198c2ecf20Sopenharmony_ci	ice_deinit_pf(pf);
43208c2ecf20Sopenharmony_ci	ice_devlink_destroy_regions(pf);
43218c2ecf20Sopenharmony_ci	ice_deinit_hw(hw);
43228c2ecf20Sopenharmony_cierr_exit_unroll:
43238c2ecf20Sopenharmony_ci	ice_devlink_unregister(pf);
43248c2ecf20Sopenharmony_ci	pci_disable_pcie_error_reporting(pdev);
43258c2ecf20Sopenharmony_ci	pci_disable_device(pdev);
43268c2ecf20Sopenharmony_ci	return err;
43278c2ecf20Sopenharmony_ci}
43288c2ecf20Sopenharmony_ci
43298c2ecf20Sopenharmony_ci/**
43308c2ecf20Sopenharmony_ci * ice_set_wake - enable or disable Wake on LAN
43318c2ecf20Sopenharmony_ci * @pf: pointer to the PF struct
43328c2ecf20Sopenharmony_ci *
43338c2ecf20Sopenharmony_ci * Simple helper for WoL control
43348c2ecf20Sopenharmony_ci */
43358c2ecf20Sopenharmony_cistatic void ice_set_wake(struct ice_pf *pf)
43368c2ecf20Sopenharmony_ci{
43378c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
43388c2ecf20Sopenharmony_ci	bool wol = pf->wol_ena;
43398c2ecf20Sopenharmony_ci
43408c2ecf20Sopenharmony_ci	/* clear wake state, otherwise new wake events won't fire */
43418c2ecf20Sopenharmony_ci	wr32(hw, PFPM_WUS, U32_MAX);
43428c2ecf20Sopenharmony_ci
43438c2ecf20Sopenharmony_ci	/* enable / disable APM wake up, no RMW needed */
43448c2ecf20Sopenharmony_ci	wr32(hw, PFPM_APM, wol ? PFPM_APM_APME_M : 0);
43458c2ecf20Sopenharmony_ci
43468c2ecf20Sopenharmony_ci	/* set magic packet filter enabled */
43478c2ecf20Sopenharmony_ci	wr32(hw, PFPM_WUFC, wol ? PFPM_WUFC_MAG_M : 0);
43488c2ecf20Sopenharmony_ci}
43498c2ecf20Sopenharmony_ci
43508c2ecf20Sopenharmony_ci/**
43518c2ecf20Sopenharmony_ci * ice_setup_magic_mc_wake - setup device to wake on multicast magic packet
43528c2ecf20Sopenharmony_ci * @pf: pointer to the PF struct
43538c2ecf20Sopenharmony_ci *
43548c2ecf20Sopenharmony_ci * Issue firmware command to enable multicast magic wake, making
43558c2ecf20Sopenharmony_ci * sure that any locally administered address (LAA) is used for
43568c2ecf20Sopenharmony_ci * wake, and that PF reset doesn't undo the LAA.
43578c2ecf20Sopenharmony_ci */
43588c2ecf20Sopenharmony_cistatic void ice_setup_mc_magic_wake(struct ice_pf *pf)
43598c2ecf20Sopenharmony_ci{
43608c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
43618c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
43628c2ecf20Sopenharmony_ci	enum ice_status status;
43638c2ecf20Sopenharmony_ci	u8 mac_addr[ETH_ALEN];
43648c2ecf20Sopenharmony_ci	struct ice_vsi *vsi;
43658c2ecf20Sopenharmony_ci	u8 flags;
43668c2ecf20Sopenharmony_ci
43678c2ecf20Sopenharmony_ci	if (!pf->wol_ena)
43688c2ecf20Sopenharmony_ci		return;
43698c2ecf20Sopenharmony_ci
43708c2ecf20Sopenharmony_ci	vsi = ice_get_main_vsi(pf);
43718c2ecf20Sopenharmony_ci	if (!vsi)
43728c2ecf20Sopenharmony_ci		return;
43738c2ecf20Sopenharmony_ci
43748c2ecf20Sopenharmony_ci	/* Get current MAC address in case it's an LAA */
43758c2ecf20Sopenharmony_ci	if (vsi->netdev)
43768c2ecf20Sopenharmony_ci		ether_addr_copy(mac_addr, vsi->netdev->dev_addr);
43778c2ecf20Sopenharmony_ci	else
43788c2ecf20Sopenharmony_ci		ether_addr_copy(mac_addr, vsi->port_info->mac.perm_addr);
43798c2ecf20Sopenharmony_ci
43808c2ecf20Sopenharmony_ci	flags = ICE_AQC_MAN_MAC_WR_MC_MAG_EN |
43818c2ecf20Sopenharmony_ci		ICE_AQC_MAN_MAC_UPDATE_LAA_WOL |
43828c2ecf20Sopenharmony_ci		ICE_AQC_MAN_MAC_WR_WOL_LAA_PFR_KEEP;
43838c2ecf20Sopenharmony_ci
43848c2ecf20Sopenharmony_ci	status = ice_aq_manage_mac_write(hw, mac_addr, flags, NULL);
43858c2ecf20Sopenharmony_ci	if (status)
43868c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to enable Multicast Magic Packet wake, err %s aq_err %s\n",
43878c2ecf20Sopenharmony_ci			ice_stat_str(status),
43888c2ecf20Sopenharmony_ci			ice_aq_str(hw->adminq.sq_last_status));
43898c2ecf20Sopenharmony_ci}
43908c2ecf20Sopenharmony_ci
43918c2ecf20Sopenharmony_ci/**
43928c2ecf20Sopenharmony_ci * ice_remove - Device removal routine
43938c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
43948c2ecf20Sopenharmony_ci */
43958c2ecf20Sopenharmony_cistatic void ice_remove(struct pci_dev *pdev)
43968c2ecf20Sopenharmony_ci{
43978c2ecf20Sopenharmony_ci	struct ice_pf *pf = pci_get_drvdata(pdev);
43988c2ecf20Sopenharmony_ci	int i;
43998c2ecf20Sopenharmony_ci
44008c2ecf20Sopenharmony_ci	for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
44018c2ecf20Sopenharmony_ci		if (!ice_is_reset_in_progress(pf->state))
44028c2ecf20Sopenharmony_ci			break;
44038c2ecf20Sopenharmony_ci		msleep(100);
44048c2ecf20Sopenharmony_ci	}
44058c2ecf20Sopenharmony_ci
44068c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) {
44078c2ecf20Sopenharmony_ci		set_bit(__ICE_VF_RESETS_DISABLED, pf->state);
44088c2ecf20Sopenharmony_ci		ice_free_vfs(pf);
44098c2ecf20Sopenharmony_ci	}
44108c2ecf20Sopenharmony_ci
44118c2ecf20Sopenharmony_ci	set_bit(__ICE_DOWN, pf->state);
44128c2ecf20Sopenharmony_ci	ice_service_task_stop(pf);
44138c2ecf20Sopenharmony_ci
44148c2ecf20Sopenharmony_ci	ice_aq_cancel_waiting_tasks(pf);
44158c2ecf20Sopenharmony_ci
44168c2ecf20Sopenharmony_ci	mutex_destroy(&(&pf->hw)->fdir_fltr_lock);
44178c2ecf20Sopenharmony_ci	if (!ice_is_safe_mode(pf))
44188c2ecf20Sopenharmony_ci		ice_remove_arfs(pf);
44198c2ecf20Sopenharmony_ci	ice_setup_mc_magic_wake(pf);
44208c2ecf20Sopenharmony_ci	ice_vsi_release_all(pf);
44218c2ecf20Sopenharmony_ci	ice_set_wake(pf);
44228c2ecf20Sopenharmony_ci	ice_free_irq_msix_misc(pf);
44238c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, i) {
44248c2ecf20Sopenharmony_ci		if (!pf->vsi[i])
44258c2ecf20Sopenharmony_ci			continue;
44268c2ecf20Sopenharmony_ci		ice_vsi_free_q_vectors(pf->vsi[i]);
44278c2ecf20Sopenharmony_ci	}
44288c2ecf20Sopenharmony_ci	ice_deinit_pf(pf);
44298c2ecf20Sopenharmony_ci	ice_devlink_destroy_regions(pf);
44308c2ecf20Sopenharmony_ci	ice_deinit_hw(&pf->hw);
44318c2ecf20Sopenharmony_ci	ice_devlink_unregister(pf);
44328c2ecf20Sopenharmony_ci
44338c2ecf20Sopenharmony_ci	/* Issue a PFR as part of the prescribed driver unload flow.  Do not
44348c2ecf20Sopenharmony_ci	 * do it via ice_schedule_reset() since there is no need to rebuild
44358c2ecf20Sopenharmony_ci	 * and the service task is already stopped.
44368c2ecf20Sopenharmony_ci	 */
44378c2ecf20Sopenharmony_ci	ice_reset(&pf->hw, ICE_RESET_PFR);
44388c2ecf20Sopenharmony_ci	pci_wait_for_pending_transaction(pdev);
44398c2ecf20Sopenharmony_ci	ice_clear_interrupt_scheme(pf);
44408c2ecf20Sopenharmony_ci	pci_disable_pcie_error_reporting(pdev);
44418c2ecf20Sopenharmony_ci	pci_disable_device(pdev);
44428c2ecf20Sopenharmony_ci}
44438c2ecf20Sopenharmony_ci
44448c2ecf20Sopenharmony_ci/**
44458c2ecf20Sopenharmony_ci * ice_shutdown - PCI callback for shutting down device
44468c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
44478c2ecf20Sopenharmony_ci */
44488c2ecf20Sopenharmony_cistatic void ice_shutdown(struct pci_dev *pdev)
44498c2ecf20Sopenharmony_ci{
44508c2ecf20Sopenharmony_ci	struct ice_pf *pf = pci_get_drvdata(pdev);
44518c2ecf20Sopenharmony_ci
44528c2ecf20Sopenharmony_ci	ice_remove(pdev);
44538c2ecf20Sopenharmony_ci
44548c2ecf20Sopenharmony_ci	if (system_state == SYSTEM_POWER_OFF) {
44558c2ecf20Sopenharmony_ci		pci_wake_from_d3(pdev, pf->wol_ena);
44568c2ecf20Sopenharmony_ci		pci_set_power_state(pdev, PCI_D3hot);
44578c2ecf20Sopenharmony_ci	}
44588c2ecf20Sopenharmony_ci}
44598c2ecf20Sopenharmony_ci
44608c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
44618c2ecf20Sopenharmony_ci/**
44628c2ecf20Sopenharmony_ci * ice_prepare_for_shutdown - prep for PCI shutdown
44638c2ecf20Sopenharmony_ci * @pf: board private structure
44648c2ecf20Sopenharmony_ci *
44658c2ecf20Sopenharmony_ci * Inform or close all dependent features in prep for PCI device shutdown
44668c2ecf20Sopenharmony_ci */
44678c2ecf20Sopenharmony_cistatic void ice_prepare_for_shutdown(struct ice_pf *pf)
44688c2ecf20Sopenharmony_ci{
44698c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
44708c2ecf20Sopenharmony_ci	u32 v;
44718c2ecf20Sopenharmony_ci
44728c2ecf20Sopenharmony_ci	/* Notify VFs of impending reset */
44738c2ecf20Sopenharmony_ci	if (ice_check_sq_alive(hw, &hw->mailboxq))
44748c2ecf20Sopenharmony_ci		ice_vc_notify_reset(pf);
44758c2ecf20Sopenharmony_ci
44768c2ecf20Sopenharmony_ci	dev_dbg(ice_pf_to_dev(pf), "Tearing down internal switch for shutdown\n");
44778c2ecf20Sopenharmony_ci
44788c2ecf20Sopenharmony_ci	/* disable the VSIs and their queues that are not already DOWN */
44798c2ecf20Sopenharmony_ci	ice_pf_dis_all_vsi(pf, false);
44808c2ecf20Sopenharmony_ci
44818c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, v)
44828c2ecf20Sopenharmony_ci		if (pf->vsi[v])
44838c2ecf20Sopenharmony_ci			pf->vsi[v]->vsi_num = 0;
44848c2ecf20Sopenharmony_ci
44858c2ecf20Sopenharmony_ci	ice_shutdown_all_ctrlq(hw);
44868c2ecf20Sopenharmony_ci}
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_ci/**
44898c2ecf20Sopenharmony_ci * ice_reinit_interrupt_scheme - Reinitialize interrupt scheme
44908c2ecf20Sopenharmony_ci * @pf: board private structure to reinitialize
44918c2ecf20Sopenharmony_ci *
44928c2ecf20Sopenharmony_ci * This routine reinitialize interrupt scheme that was cleared during
44938c2ecf20Sopenharmony_ci * power management suspend callback.
44948c2ecf20Sopenharmony_ci *
44958c2ecf20Sopenharmony_ci * This should be called during resume routine to re-allocate the q_vectors
44968c2ecf20Sopenharmony_ci * and reacquire interrupts.
44978c2ecf20Sopenharmony_ci */
44988c2ecf20Sopenharmony_cistatic int ice_reinit_interrupt_scheme(struct ice_pf *pf)
44998c2ecf20Sopenharmony_ci{
45008c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
45018c2ecf20Sopenharmony_ci	int ret, v;
45028c2ecf20Sopenharmony_ci
45038c2ecf20Sopenharmony_ci	/* Since we clear MSIX flag during suspend, we need to
45048c2ecf20Sopenharmony_ci	 * set it back during resume...
45058c2ecf20Sopenharmony_ci	 */
45068c2ecf20Sopenharmony_ci
45078c2ecf20Sopenharmony_ci	ret = ice_init_interrupt_scheme(pf);
45088c2ecf20Sopenharmony_ci	if (ret) {
45098c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to re-initialize interrupt %d\n", ret);
45108c2ecf20Sopenharmony_ci		return ret;
45118c2ecf20Sopenharmony_ci	}
45128c2ecf20Sopenharmony_ci
45138c2ecf20Sopenharmony_ci	/* Remap vectors and rings, after successful re-init interrupts */
45148c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, v) {
45158c2ecf20Sopenharmony_ci		if (!pf->vsi[v])
45168c2ecf20Sopenharmony_ci			continue;
45178c2ecf20Sopenharmony_ci
45188c2ecf20Sopenharmony_ci		ret = ice_vsi_alloc_q_vectors(pf->vsi[v]);
45198c2ecf20Sopenharmony_ci		if (ret)
45208c2ecf20Sopenharmony_ci			goto err_reinit;
45218c2ecf20Sopenharmony_ci		ice_vsi_map_rings_to_vectors(pf->vsi[v]);
45228c2ecf20Sopenharmony_ci	}
45238c2ecf20Sopenharmony_ci
45248c2ecf20Sopenharmony_ci	ret = ice_req_irq_msix_misc(pf);
45258c2ecf20Sopenharmony_ci	if (ret) {
45268c2ecf20Sopenharmony_ci		dev_err(dev, "Setting up misc vector failed after device suspend %d\n",
45278c2ecf20Sopenharmony_ci			ret);
45288c2ecf20Sopenharmony_ci		goto err_reinit;
45298c2ecf20Sopenharmony_ci	}
45308c2ecf20Sopenharmony_ci
45318c2ecf20Sopenharmony_ci	return 0;
45328c2ecf20Sopenharmony_ci
45338c2ecf20Sopenharmony_cierr_reinit:
45348c2ecf20Sopenharmony_ci	while (v--)
45358c2ecf20Sopenharmony_ci		if (pf->vsi[v])
45368c2ecf20Sopenharmony_ci			ice_vsi_free_q_vectors(pf->vsi[v]);
45378c2ecf20Sopenharmony_ci
45388c2ecf20Sopenharmony_ci	return ret;
45398c2ecf20Sopenharmony_ci}
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_ci/**
45428c2ecf20Sopenharmony_ci * ice_suspend
45438c2ecf20Sopenharmony_ci * @dev: generic device information structure
45448c2ecf20Sopenharmony_ci *
45458c2ecf20Sopenharmony_ci * Power Management callback to quiesce the device and prepare
45468c2ecf20Sopenharmony_ci * for D3 transition.
45478c2ecf20Sopenharmony_ci */
45488c2ecf20Sopenharmony_cistatic int __maybe_unused ice_suspend(struct device *dev)
45498c2ecf20Sopenharmony_ci{
45508c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev);
45518c2ecf20Sopenharmony_ci	struct ice_pf *pf;
45528c2ecf20Sopenharmony_ci	int disabled, v;
45538c2ecf20Sopenharmony_ci
45548c2ecf20Sopenharmony_ci	pf = pci_get_drvdata(pdev);
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci	if (!ice_pf_state_is_nominal(pf)) {
45578c2ecf20Sopenharmony_ci		dev_err(dev, "Device is not ready, no need to suspend it\n");
45588c2ecf20Sopenharmony_ci		return -EBUSY;
45598c2ecf20Sopenharmony_ci	}
45608c2ecf20Sopenharmony_ci
45618c2ecf20Sopenharmony_ci	/* Stop watchdog tasks until resume completion.
45628c2ecf20Sopenharmony_ci	 * Even though it is most likely that the service task is
45638c2ecf20Sopenharmony_ci	 * disabled if the device is suspended or down, the service task's
45648c2ecf20Sopenharmony_ci	 * state is controlled by a different state bit, and we should
45658c2ecf20Sopenharmony_ci	 * store and honor whatever state that bit is in at this point.
45668c2ecf20Sopenharmony_ci	 */
45678c2ecf20Sopenharmony_ci	disabled = ice_service_task_stop(pf);
45688c2ecf20Sopenharmony_ci
45698c2ecf20Sopenharmony_ci	/* Already suspended?, then there is nothing to do */
45708c2ecf20Sopenharmony_ci	if (test_and_set_bit(__ICE_SUSPENDED, pf->state)) {
45718c2ecf20Sopenharmony_ci		if (!disabled)
45728c2ecf20Sopenharmony_ci			ice_service_task_restart(pf);
45738c2ecf20Sopenharmony_ci		return 0;
45748c2ecf20Sopenharmony_ci	}
45758c2ecf20Sopenharmony_ci
45768c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, pf->state) ||
45778c2ecf20Sopenharmony_ci	    ice_is_reset_in_progress(pf->state)) {
45788c2ecf20Sopenharmony_ci		dev_err(dev, "can't suspend device in reset or already down\n");
45798c2ecf20Sopenharmony_ci		if (!disabled)
45808c2ecf20Sopenharmony_ci			ice_service_task_restart(pf);
45818c2ecf20Sopenharmony_ci		return 0;
45828c2ecf20Sopenharmony_ci	}
45838c2ecf20Sopenharmony_ci
45848c2ecf20Sopenharmony_ci	ice_setup_mc_magic_wake(pf);
45858c2ecf20Sopenharmony_ci
45868c2ecf20Sopenharmony_ci	ice_prepare_for_shutdown(pf);
45878c2ecf20Sopenharmony_ci
45888c2ecf20Sopenharmony_ci	ice_set_wake(pf);
45898c2ecf20Sopenharmony_ci
45908c2ecf20Sopenharmony_ci	/* Free vectors, clear the interrupt scheme and release IRQs
45918c2ecf20Sopenharmony_ci	 * for proper hibernation, especially with large number of CPUs.
45928c2ecf20Sopenharmony_ci	 * Otherwise hibernation might fail when mapping all the vectors back
45938c2ecf20Sopenharmony_ci	 * to CPU0.
45948c2ecf20Sopenharmony_ci	 */
45958c2ecf20Sopenharmony_ci	ice_free_irq_msix_misc(pf);
45968c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, v) {
45978c2ecf20Sopenharmony_ci		if (!pf->vsi[v])
45988c2ecf20Sopenharmony_ci			continue;
45998c2ecf20Sopenharmony_ci		ice_vsi_free_q_vectors(pf->vsi[v]);
46008c2ecf20Sopenharmony_ci	}
46018c2ecf20Sopenharmony_ci	ice_free_cpu_rx_rmap(ice_get_main_vsi(pf));
46028c2ecf20Sopenharmony_ci	ice_clear_interrupt_scheme(pf);
46038c2ecf20Sopenharmony_ci
46048c2ecf20Sopenharmony_ci	pci_save_state(pdev);
46058c2ecf20Sopenharmony_ci	pci_wake_from_d3(pdev, pf->wol_ena);
46068c2ecf20Sopenharmony_ci	pci_set_power_state(pdev, PCI_D3hot);
46078c2ecf20Sopenharmony_ci	return 0;
46088c2ecf20Sopenharmony_ci}
46098c2ecf20Sopenharmony_ci
46108c2ecf20Sopenharmony_ci/**
46118c2ecf20Sopenharmony_ci * ice_resume - PM callback for waking up from D3
46128c2ecf20Sopenharmony_ci * @dev: generic device information structure
46138c2ecf20Sopenharmony_ci */
46148c2ecf20Sopenharmony_cistatic int __maybe_unused ice_resume(struct device *dev)
46158c2ecf20Sopenharmony_ci{
46168c2ecf20Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev);
46178c2ecf20Sopenharmony_ci	enum ice_reset_req reset_type;
46188c2ecf20Sopenharmony_ci	struct ice_pf *pf;
46198c2ecf20Sopenharmony_ci	struct ice_hw *hw;
46208c2ecf20Sopenharmony_ci	int ret;
46218c2ecf20Sopenharmony_ci
46228c2ecf20Sopenharmony_ci	pci_set_power_state(pdev, PCI_D0);
46238c2ecf20Sopenharmony_ci	pci_restore_state(pdev);
46248c2ecf20Sopenharmony_ci	pci_save_state(pdev);
46258c2ecf20Sopenharmony_ci
46268c2ecf20Sopenharmony_ci	if (!pci_device_is_present(pdev))
46278c2ecf20Sopenharmony_ci		return -ENODEV;
46288c2ecf20Sopenharmony_ci
46298c2ecf20Sopenharmony_ci	ret = pci_enable_device_mem(pdev);
46308c2ecf20Sopenharmony_ci	if (ret) {
46318c2ecf20Sopenharmony_ci		dev_err(dev, "Cannot enable device after suspend\n");
46328c2ecf20Sopenharmony_ci		return ret;
46338c2ecf20Sopenharmony_ci	}
46348c2ecf20Sopenharmony_ci
46358c2ecf20Sopenharmony_ci	pf = pci_get_drvdata(pdev);
46368c2ecf20Sopenharmony_ci	hw = &pf->hw;
46378c2ecf20Sopenharmony_ci
46388c2ecf20Sopenharmony_ci	pf->wakeup_reason = rd32(hw, PFPM_WUS);
46398c2ecf20Sopenharmony_ci	ice_print_wake_reason(pf);
46408c2ecf20Sopenharmony_ci
46418c2ecf20Sopenharmony_ci	/* We cleared the interrupt scheme when we suspended, so we need to
46428c2ecf20Sopenharmony_ci	 * restore it now to resume device functionality.
46438c2ecf20Sopenharmony_ci	 */
46448c2ecf20Sopenharmony_ci	ret = ice_reinit_interrupt_scheme(pf);
46458c2ecf20Sopenharmony_ci	if (ret)
46468c2ecf20Sopenharmony_ci		dev_err(dev, "Cannot restore interrupt scheme: %d\n", ret);
46478c2ecf20Sopenharmony_ci
46488c2ecf20Sopenharmony_ci	clear_bit(__ICE_DOWN, pf->state);
46498c2ecf20Sopenharmony_ci	/* Now perform PF reset and rebuild */
46508c2ecf20Sopenharmony_ci	reset_type = ICE_RESET_PFR;
46518c2ecf20Sopenharmony_ci	/* re-enable service task for reset, but allow reset to schedule it */
46528c2ecf20Sopenharmony_ci	clear_bit(__ICE_SERVICE_DIS, pf->state);
46538c2ecf20Sopenharmony_ci
46548c2ecf20Sopenharmony_ci	if (ice_schedule_reset(pf, reset_type))
46558c2ecf20Sopenharmony_ci		dev_err(dev, "Reset during resume failed.\n");
46568c2ecf20Sopenharmony_ci
46578c2ecf20Sopenharmony_ci	clear_bit(__ICE_SUSPENDED, pf->state);
46588c2ecf20Sopenharmony_ci	ice_service_task_restart(pf);
46598c2ecf20Sopenharmony_ci
46608c2ecf20Sopenharmony_ci	/* Restart the service task */
46618c2ecf20Sopenharmony_ci	mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
46628c2ecf20Sopenharmony_ci
46638c2ecf20Sopenharmony_ci	return 0;
46648c2ecf20Sopenharmony_ci}
46658c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
46668c2ecf20Sopenharmony_ci
46678c2ecf20Sopenharmony_ci/**
46688c2ecf20Sopenharmony_ci * ice_pci_err_detected - warning that PCI error has been detected
46698c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
46708c2ecf20Sopenharmony_ci * @err: the type of PCI error
46718c2ecf20Sopenharmony_ci *
46728c2ecf20Sopenharmony_ci * Called to warn that something happened on the PCI bus and the error handling
46738c2ecf20Sopenharmony_ci * is in progress.  Allows the driver to gracefully prepare/handle PCI errors.
46748c2ecf20Sopenharmony_ci */
46758c2ecf20Sopenharmony_cistatic pci_ers_result_t
46768c2ecf20Sopenharmony_ciice_pci_err_detected(struct pci_dev *pdev, pci_channel_state_t err)
46778c2ecf20Sopenharmony_ci{
46788c2ecf20Sopenharmony_ci	struct ice_pf *pf = pci_get_drvdata(pdev);
46798c2ecf20Sopenharmony_ci
46808c2ecf20Sopenharmony_ci	if (!pf) {
46818c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "%s: unrecoverable device error %d\n",
46828c2ecf20Sopenharmony_ci			__func__, err);
46838c2ecf20Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
46848c2ecf20Sopenharmony_ci	}
46858c2ecf20Sopenharmony_ci
46868c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_SUSPENDED, pf->state)) {
46878c2ecf20Sopenharmony_ci		ice_service_task_stop(pf);
46888c2ecf20Sopenharmony_ci
46898c2ecf20Sopenharmony_ci		if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) {
46908c2ecf20Sopenharmony_ci			set_bit(__ICE_PFR_REQ, pf->state);
46918c2ecf20Sopenharmony_ci			ice_prepare_for_reset(pf);
46928c2ecf20Sopenharmony_ci		}
46938c2ecf20Sopenharmony_ci	}
46948c2ecf20Sopenharmony_ci
46958c2ecf20Sopenharmony_ci	return PCI_ERS_RESULT_NEED_RESET;
46968c2ecf20Sopenharmony_ci}
46978c2ecf20Sopenharmony_ci
46988c2ecf20Sopenharmony_ci/**
46998c2ecf20Sopenharmony_ci * ice_pci_err_slot_reset - a PCI slot reset has just happened
47008c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
47018c2ecf20Sopenharmony_ci *
47028c2ecf20Sopenharmony_ci * Called to determine if the driver can recover from the PCI slot reset by
47038c2ecf20Sopenharmony_ci * using a register read to determine if the device is recoverable.
47048c2ecf20Sopenharmony_ci */
47058c2ecf20Sopenharmony_cistatic pci_ers_result_t ice_pci_err_slot_reset(struct pci_dev *pdev)
47068c2ecf20Sopenharmony_ci{
47078c2ecf20Sopenharmony_ci	struct ice_pf *pf = pci_get_drvdata(pdev);
47088c2ecf20Sopenharmony_ci	pci_ers_result_t result;
47098c2ecf20Sopenharmony_ci	int err;
47108c2ecf20Sopenharmony_ci	u32 reg;
47118c2ecf20Sopenharmony_ci
47128c2ecf20Sopenharmony_ci	err = pci_enable_device_mem(pdev);
47138c2ecf20Sopenharmony_ci	if (err) {
47148c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Cannot re-enable PCI device after reset, error %d\n",
47158c2ecf20Sopenharmony_ci			err);
47168c2ecf20Sopenharmony_ci		result = PCI_ERS_RESULT_DISCONNECT;
47178c2ecf20Sopenharmony_ci	} else {
47188c2ecf20Sopenharmony_ci		pci_set_master(pdev);
47198c2ecf20Sopenharmony_ci		pci_restore_state(pdev);
47208c2ecf20Sopenharmony_ci		pci_save_state(pdev);
47218c2ecf20Sopenharmony_ci		pci_wake_from_d3(pdev, false);
47228c2ecf20Sopenharmony_ci
47238c2ecf20Sopenharmony_ci		/* Check for life */
47248c2ecf20Sopenharmony_ci		reg = rd32(&pf->hw, GLGEN_RTRIG);
47258c2ecf20Sopenharmony_ci		if (!reg)
47268c2ecf20Sopenharmony_ci			result = PCI_ERS_RESULT_RECOVERED;
47278c2ecf20Sopenharmony_ci		else
47288c2ecf20Sopenharmony_ci			result = PCI_ERS_RESULT_DISCONNECT;
47298c2ecf20Sopenharmony_ci	}
47308c2ecf20Sopenharmony_ci
47318c2ecf20Sopenharmony_ci	err = pci_aer_clear_nonfatal_status(pdev);
47328c2ecf20Sopenharmony_ci	if (err)
47338c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "pci_aer_clear_nonfatal_status() failed, error %d\n",
47348c2ecf20Sopenharmony_ci			err);
47358c2ecf20Sopenharmony_ci		/* non-fatal, continue */
47368c2ecf20Sopenharmony_ci
47378c2ecf20Sopenharmony_ci	return result;
47388c2ecf20Sopenharmony_ci}
47398c2ecf20Sopenharmony_ci
47408c2ecf20Sopenharmony_ci/**
47418c2ecf20Sopenharmony_ci * ice_pci_err_resume - restart operations after PCI error recovery
47428c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
47438c2ecf20Sopenharmony_ci *
47448c2ecf20Sopenharmony_ci * Called to allow the driver to bring things back up after PCI error and/or
47458c2ecf20Sopenharmony_ci * reset recovery have finished
47468c2ecf20Sopenharmony_ci */
47478c2ecf20Sopenharmony_cistatic void ice_pci_err_resume(struct pci_dev *pdev)
47488c2ecf20Sopenharmony_ci{
47498c2ecf20Sopenharmony_ci	struct ice_pf *pf = pci_get_drvdata(pdev);
47508c2ecf20Sopenharmony_ci
47518c2ecf20Sopenharmony_ci	if (!pf) {
47528c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "%s failed, device is unrecoverable\n",
47538c2ecf20Sopenharmony_ci			__func__);
47548c2ecf20Sopenharmony_ci		return;
47558c2ecf20Sopenharmony_ci	}
47568c2ecf20Sopenharmony_ci
47578c2ecf20Sopenharmony_ci	if (test_bit(__ICE_SUSPENDED, pf->state)) {
47588c2ecf20Sopenharmony_ci		dev_dbg(&pdev->dev, "%s failed to resume normal operations!\n",
47598c2ecf20Sopenharmony_ci			__func__);
47608c2ecf20Sopenharmony_ci		return;
47618c2ecf20Sopenharmony_ci	}
47628c2ecf20Sopenharmony_ci
47638c2ecf20Sopenharmony_ci	ice_restore_all_vfs_msi_state(pdev);
47648c2ecf20Sopenharmony_ci
47658c2ecf20Sopenharmony_ci	ice_do_reset(pf, ICE_RESET_PFR);
47668c2ecf20Sopenharmony_ci	ice_service_task_restart(pf);
47678c2ecf20Sopenharmony_ci	mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
47688c2ecf20Sopenharmony_ci}
47698c2ecf20Sopenharmony_ci
47708c2ecf20Sopenharmony_ci/**
47718c2ecf20Sopenharmony_ci * ice_pci_err_reset_prepare - prepare device driver for PCI reset
47728c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
47738c2ecf20Sopenharmony_ci */
47748c2ecf20Sopenharmony_cistatic void ice_pci_err_reset_prepare(struct pci_dev *pdev)
47758c2ecf20Sopenharmony_ci{
47768c2ecf20Sopenharmony_ci	struct ice_pf *pf = pci_get_drvdata(pdev);
47778c2ecf20Sopenharmony_ci
47788c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_SUSPENDED, pf->state)) {
47798c2ecf20Sopenharmony_ci		ice_service_task_stop(pf);
47808c2ecf20Sopenharmony_ci
47818c2ecf20Sopenharmony_ci		if (!test_bit(__ICE_PREPARED_FOR_RESET, pf->state)) {
47828c2ecf20Sopenharmony_ci			set_bit(__ICE_PFR_REQ, pf->state);
47838c2ecf20Sopenharmony_ci			ice_prepare_for_reset(pf);
47848c2ecf20Sopenharmony_ci		}
47858c2ecf20Sopenharmony_ci	}
47868c2ecf20Sopenharmony_ci}
47878c2ecf20Sopenharmony_ci
47888c2ecf20Sopenharmony_ci/**
47898c2ecf20Sopenharmony_ci * ice_pci_err_reset_done - PCI reset done, device driver reset can begin
47908c2ecf20Sopenharmony_ci * @pdev: PCI device information struct
47918c2ecf20Sopenharmony_ci */
47928c2ecf20Sopenharmony_cistatic void ice_pci_err_reset_done(struct pci_dev *pdev)
47938c2ecf20Sopenharmony_ci{
47948c2ecf20Sopenharmony_ci	ice_pci_err_resume(pdev);
47958c2ecf20Sopenharmony_ci}
47968c2ecf20Sopenharmony_ci
47978c2ecf20Sopenharmony_ci/* ice_pci_tbl - PCI Device ID Table
47988c2ecf20Sopenharmony_ci *
47998c2ecf20Sopenharmony_ci * Wildcard entries (PCI_ANY_ID) should come last
48008c2ecf20Sopenharmony_ci * Last entry must be all 0s
48018c2ecf20Sopenharmony_ci *
48028c2ecf20Sopenharmony_ci * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
48038c2ecf20Sopenharmony_ci *   Class, Class Mask, private data (not used) }
48048c2ecf20Sopenharmony_ci */
48058c2ecf20Sopenharmony_cistatic const struct pci_device_id ice_pci_tbl[] = {
48068c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_BACKPLANE), 0 },
48078c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_QSFP), 0 },
48088c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_SFP), 0 },
48098c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810_XXV_BACKPLANE), 0 },
48108c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810_XXV_QSFP), 0 },
48118c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810_XXV_SFP), 0 },
48128c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_BACKPLANE), 0 },
48138c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_QSFP), 0 },
48148c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_SFP), 0 },
48158c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_10G_BASE_T), 0 },
48168c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_SGMII), 0 },
48178c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_BACKPLANE), 0 },
48188c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_QSFP), 0 },
48198c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_SFP), 0 },
48208c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_10G_BASE_T), 0 },
48218c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_SGMII), 0 },
48228c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_BACKPLANE), 0 },
48238c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_SFP), 0 },
48248c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_10G_BASE_T), 0 },
48258c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_SGMII), 0 },
48268c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_BACKPLANE), 0 },
48278c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_SFP), 0 },
48288c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_10G_BASE_T), 0 },
48298c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_1GBE), 0 },
48308c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_QSFP), 0 },
48318c2ecf20Sopenharmony_ci	/* required last entry */
48328c2ecf20Sopenharmony_ci	{ 0, }
48338c2ecf20Sopenharmony_ci};
48348c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, ice_pci_tbl);
48358c2ecf20Sopenharmony_ci
48368c2ecf20Sopenharmony_cistatic __maybe_unused SIMPLE_DEV_PM_OPS(ice_pm_ops, ice_suspend, ice_resume);
48378c2ecf20Sopenharmony_ci
48388c2ecf20Sopenharmony_cistatic const struct pci_error_handlers ice_pci_err_handler = {
48398c2ecf20Sopenharmony_ci	.error_detected = ice_pci_err_detected,
48408c2ecf20Sopenharmony_ci	.slot_reset = ice_pci_err_slot_reset,
48418c2ecf20Sopenharmony_ci	.reset_prepare = ice_pci_err_reset_prepare,
48428c2ecf20Sopenharmony_ci	.reset_done = ice_pci_err_reset_done,
48438c2ecf20Sopenharmony_ci	.resume = ice_pci_err_resume
48448c2ecf20Sopenharmony_ci};
48458c2ecf20Sopenharmony_ci
48468c2ecf20Sopenharmony_cistatic struct pci_driver ice_driver = {
48478c2ecf20Sopenharmony_ci	.name = KBUILD_MODNAME,
48488c2ecf20Sopenharmony_ci	.id_table = ice_pci_tbl,
48498c2ecf20Sopenharmony_ci	.probe = ice_probe,
48508c2ecf20Sopenharmony_ci	.remove = ice_remove,
48518c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
48528c2ecf20Sopenharmony_ci	.driver.pm = &ice_pm_ops,
48538c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
48548c2ecf20Sopenharmony_ci	.shutdown = ice_shutdown,
48558c2ecf20Sopenharmony_ci	.sriov_configure = ice_sriov_configure,
48568c2ecf20Sopenharmony_ci	.err_handler = &ice_pci_err_handler
48578c2ecf20Sopenharmony_ci};
48588c2ecf20Sopenharmony_ci
48598c2ecf20Sopenharmony_ci/**
48608c2ecf20Sopenharmony_ci * ice_module_init - Driver registration routine
48618c2ecf20Sopenharmony_ci *
48628c2ecf20Sopenharmony_ci * ice_module_init is the first routine called when the driver is
48638c2ecf20Sopenharmony_ci * loaded. All it does is register with the PCI subsystem.
48648c2ecf20Sopenharmony_ci */
48658c2ecf20Sopenharmony_cistatic int __init ice_module_init(void)
48668c2ecf20Sopenharmony_ci{
48678c2ecf20Sopenharmony_ci	int status;
48688c2ecf20Sopenharmony_ci
48698c2ecf20Sopenharmony_ci	pr_info("%s\n", ice_driver_string);
48708c2ecf20Sopenharmony_ci	pr_info("%s\n", ice_copyright);
48718c2ecf20Sopenharmony_ci
48728c2ecf20Sopenharmony_ci	ice_wq = alloc_workqueue("%s", 0, 0, KBUILD_MODNAME);
48738c2ecf20Sopenharmony_ci	if (!ice_wq) {
48748c2ecf20Sopenharmony_ci		pr_err("Failed to create workqueue\n");
48758c2ecf20Sopenharmony_ci		return -ENOMEM;
48768c2ecf20Sopenharmony_ci	}
48778c2ecf20Sopenharmony_ci
48788c2ecf20Sopenharmony_ci	status = pci_register_driver(&ice_driver);
48798c2ecf20Sopenharmony_ci	if (status) {
48808c2ecf20Sopenharmony_ci		pr_err("failed to register PCI driver, err %d\n", status);
48818c2ecf20Sopenharmony_ci		destroy_workqueue(ice_wq);
48828c2ecf20Sopenharmony_ci	}
48838c2ecf20Sopenharmony_ci
48848c2ecf20Sopenharmony_ci	return status;
48858c2ecf20Sopenharmony_ci}
48868c2ecf20Sopenharmony_cimodule_init(ice_module_init);
48878c2ecf20Sopenharmony_ci
48888c2ecf20Sopenharmony_ci/**
48898c2ecf20Sopenharmony_ci * ice_module_exit - Driver exit cleanup routine
48908c2ecf20Sopenharmony_ci *
48918c2ecf20Sopenharmony_ci * ice_module_exit is called just before the driver is removed
48928c2ecf20Sopenharmony_ci * from memory.
48938c2ecf20Sopenharmony_ci */
48948c2ecf20Sopenharmony_cistatic void __exit ice_module_exit(void)
48958c2ecf20Sopenharmony_ci{
48968c2ecf20Sopenharmony_ci	pci_unregister_driver(&ice_driver);
48978c2ecf20Sopenharmony_ci	destroy_workqueue(ice_wq);
48988c2ecf20Sopenharmony_ci	pr_info("module unloaded\n");
48998c2ecf20Sopenharmony_ci}
49008c2ecf20Sopenharmony_cimodule_exit(ice_module_exit);
49018c2ecf20Sopenharmony_ci
49028c2ecf20Sopenharmony_ci/**
49038c2ecf20Sopenharmony_ci * ice_set_mac_address - NDO callback to set MAC address
49048c2ecf20Sopenharmony_ci * @netdev: network interface device structure
49058c2ecf20Sopenharmony_ci * @pi: pointer to an address structure
49068c2ecf20Sopenharmony_ci *
49078c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
49088c2ecf20Sopenharmony_ci */
49098c2ecf20Sopenharmony_cistatic int ice_set_mac_address(struct net_device *netdev, void *pi)
49108c2ecf20Sopenharmony_ci{
49118c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
49128c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
49138c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
49148c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
49158c2ecf20Sopenharmony_ci	struct sockaddr *addr = pi;
49168c2ecf20Sopenharmony_ci	enum ice_status status;
49178c2ecf20Sopenharmony_ci	u8 old_mac[ETH_ALEN];
49188c2ecf20Sopenharmony_ci	u8 flags = 0;
49198c2ecf20Sopenharmony_ci	int err = 0;
49208c2ecf20Sopenharmony_ci	u8 *mac;
49218c2ecf20Sopenharmony_ci
49228c2ecf20Sopenharmony_ci	mac = (u8 *)addr->sa_data;
49238c2ecf20Sopenharmony_ci
49248c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(mac))
49258c2ecf20Sopenharmony_ci		return -EADDRNOTAVAIL;
49268c2ecf20Sopenharmony_ci
49278c2ecf20Sopenharmony_ci	if (ether_addr_equal(netdev->dev_addr, mac)) {
49288c2ecf20Sopenharmony_ci		netdev_dbg(netdev, "already using mac %pM\n", mac);
49298c2ecf20Sopenharmony_ci		return 0;
49308c2ecf20Sopenharmony_ci	}
49318c2ecf20Sopenharmony_ci
49328c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, pf->state) ||
49338c2ecf20Sopenharmony_ci	    ice_is_reset_in_progress(pf->state)) {
49348c2ecf20Sopenharmony_ci		netdev_err(netdev, "can't set mac %pM. device not ready\n",
49358c2ecf20Sopenharmony_ci			   mac);
49368c2ecf20Sopenharmony_ci		return -EBUSY;
49378c2ecf20Sopenharmony_ci	}
49388c2ecf20Sopenharmony_ci
49398c2ecf20Sopenharmony_ci	netif_addr_lock_bh(netdev);
49408c2ecf20Sopenharmony_ci	ether_addr_copy(old_mac, netdev->dev_addr);
49418c2ecf20Sopenharmony_ci	/* change the netdev's MAC address */
49428c2ecf20Sopenharmony_ci	memcpy(netdev->dev_addr, mac, netdev->addr_len);
49438c2ecf20Sopenharmony_ci	netif_addr_unlock_bh(netdev);
49448c2ecf20Sopenharmony_ci
49458c2ecf20Sopenharmony_ci	/* Clean up old MAC filter. Not an error if old filter doesn't exist */
49468c2ecf20Sopenharmony_ci	status = ice_fltr_remove_mac(vsi, old_mac, ICE_FWD_TO_VSI);
49478c2ecf20Sopenharmony_ci	if (status && status != ICE_ERR_DOES_NOT_EXIST) {
49488c2ecf20Sopenharmony_ci		err = -EADDRNOTAVAIL;
49498c2ecf20Sopenharmony_ci		goto err_update_filters;
49508c2ecf20Sopenharmony_ci	}
49518c2ecf20Sopenharmony_ci
49528c2ecf20Sopenharmony_ci	/* Add filter for new MAC. If filter exists, return success */
49538c2ecf20Sopenharmony_ci	status = ice_fltr_add_mac(vsi, mac, ICE_FWD_TO_VSI);
49548c2ecf20Sopenharmony_ci	if (status == ICE_ERR_ALREADY_EXISTS)
49558c2ecf20Sopenharmony_ci		/* Although this MAC filter is already present in hardware it's
49568c2ecf20Sopenharmony_ci		 * possible in some cases (e.g. bonding) that dev_addr was
49578c2ecf20Sopenharmony_ci		 * modified outside of the driver and needs to be restored back
49588c2ecf20Sopenharmony_ci		 * to this value.
49598c2ecf20Sopenharmony_ci		 */
49608c2ecf20Sopenharmony_ci		netdev_dbg(netdev, "filter for MAC %pM already exists\n", mac);
49618c2ecf20Sopenharmony_ci	else if (status)
49628c2ecf20Sopenharmony_ci		/* error if the new filter addition failed */
49638c2ecf20Sopenharmony_ci		err = -EADDRNOTAVAIL;
49648c2ecf20Sopenharmony_ci
49658c2ecf20Sopenharmony_cierr_update_filters:
49668c2ecf20Sopenharmony_ci	if (err) {
49678c2ecf20Sopenharmony_ci		netdev_err(netdev, "can't set MAC %pM. filter update failed\n",
49688c2ecf20Sopenharmony_ci			   mac);
49698c2ecf20Sopenharmony_ci		netif_addr_lock_bh(netdev);
49708c2ecf20Sopenharmony_ci		ether_addr_copy(netdev->dev_addr, old_mac);
49718c2ecf20Sopenharmony_ci		netif_addr_unlock_bh(netdev);
49728c2ecf20Sopenharmony_ci		return err;
49738c2ecf20Sopenharmony_ci	}
49748c2ecf20Sopenharmony_ci
49758c2ecf20Sopenharmony_ci	netdev_dbg(vsi->netdev, "updated MAC address to %pM\n",
49768c2ecf20Sopenharmony_ci		   netdev->dev_addr);
49778c2ecf20Sopenharmony_ci
49788c2ecf20Sopenharmony_ci	/* write new MAC address to the firmware */
49798c2ecf20Sopenharmony_ci	flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL;
49808c2ecf20Sopenharmony_ci	status = ice_aq_manage_mac_write(hw, mac, flags, NULL);
49818c2ecf20Sopenharmony_ci	if (status) {
49828c2ecf20Sopenharmony_ci		netdev_err(netdev, "can't set MAC %pM. write to firmware failed error %s\n",
49838c2ecf20Sopenharmony_ci			   mac, ice_stat_str(status));
49848c2ecf20Sopenharmony_ci	}
49858c2ecf20Sopenharmony_ci	return 0;
49868c2ecf20Sopenharmony_ci}
49878c2ecf20Sopenharmony_ci
49888c2ecf20Sopenharmony_ci/**
49898c2ecf20Sopenharmony_ci * ice_set_rx_mode - NDO callback to set the netdev filters
49908c2ecf20Sopenharmony_ci * @netdev: network interface device structure
49918c2ecf20Sopenharmony_ci */
49928c2ecf20Sopenharmony_cistatic void ice_set_rx_mode(struct net_device *netdev)
49938c2ecf20Sopenharmony_ci{
49948c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
49958c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
49968c2ecf20Sopenharmony_ci
49978c2ecf20Sopenharmony_ci	if (!vsi)
49988c2ecf20Sopenharmony_ci		return;
49998c2ecf20Sopenharmony_ci
50008c2ecf20Sopenharmony_ci	/* Set the flags to synchronize filters
50018c2ecf20Sopenharmony_ci	 * ndo_set_rx_mode may be triggered even without a change in netdev
50028c2ecf20Sopenharmony_ci	 * flags
50038c2ecf20Sopenharmony_ci	 */
50048c2ecf20Sopenharmony_ci	set_bit(ICE_VSI_FLAG_UMAC_FLTR_CHANGED, vsi->flags);
50058c2ecf20Sopenharmony_ci	set_bit(ICE_VSI_FLAG_MMAC_FLTR_CHANGED, vsi->flags);
50068c2ecf20Sopenharmony_ci	set_bit(ICE_FLAG_FLTR_SYNC, vsi->back->flags);
50078c2ecf20Sopenharmony_ci
50088c2ecf20Sopenharmony_ci	/* schedule our worker thread which will take care of
50098c2ecf20Sopenharmony_ci	 * applying the new filter changes
50108c2ecf20Sopenharmony_ci	 */
50118c2ecf20Sopenharmony_ci	ice_service_task_schedule(vsi->back);
50128c2ecf20Sopenharmony_ci}
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_ci/**
50158c2ecf20Sopenharmony_ci * ice_set_tx_maxrate - NDO callback to set the maximum per-queue bitrate
50168c2ecf20Sopenharmony_ci * @netdev: network interface device structure
50178c2ecf20Sopenharmony_ci * @queue_index: Queue ID
50188c2ecf20Sopenharmony_ci * @maxrate: maximum bandwidth in Mbps
50198c2ecf20Sopenharmony_ci */
50208c2ecf20Sopenharmony_cistatic int
50218c2ecf20Sopenharmony_ciice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
50228c2ecf20Sopenharmony_ci{
50238c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
50248c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
50258c2ecf20Sopenharmony_ci	enum ice_status status;
50268c2ecf20Sopenharmony_ci	u16 q_handle;
50278c2ecf20Sopenharmony_ci	u8 tc;
50288c2ecf20Sopenharmony_ci
50298c2ecf20Sopenharmony_ci	/* Validate maxrate requested is within permitted range */
50308c2ecf20Sopenharmony_ci	if (maxrate && (maxrate > (ICE_SCHED_MAX_BW / 1000))) {
50318c2ecf20Sopenharmony_ci		netdev_err(netdev, "Invalid max rate %d specified for the queue %d\n",
50328c2ecf20Sopenharmony_ci			   maxrate, queue_index);
50338c2ecf20Sopenharmony_ci		return -EINVAL;
50348c2ecf20Sopenharmony_ci	}
50358c2ecf20Sopenharmony_ci
50368c2ecf20Sopenharmony_ci	q_handle = vsi->tx_rings[queue_index]->q_handle;
50378c2ecf20Sopenharmony_ci	tc = ice_dcb_get_tc(vsi, queue_index);
50388c2ecf20Sopenharmony_ci
50398c2ecf20Sopenharmony_ci	/* Set BW back to default, when user set maxrate to 0 */
50408c2ecf20Sopenharmony_ci	if (!maxrate)
50418c2ecf20Sopenharmony_ci		status = ice_cfg_q_bw_dflt_lmt(vsi->port_info, vsi->idx, tc,
50428c2ecf20Sopenharmony_ci					       q_handle, ICE_MAX_BW);
50438c2ecf20Sopenharmony_ci	else
50448c2ecf20Sopenharmony_ci		status = ice_cfg_q_bw_lmt(vsi->port_info, vsi->idx, tc,
50458c2ecf20Sopenharmony_ci					  q_handle, ICE_MAX_BW, maxrate * 1000);
50468c2ecf20Sopenharmony_ci	if (status) {
50478c2ecf20Sopenharmony_ci		netdev_err(netdev, "Unable to set Tx max rate, error %s\n",
50488c2ecf20Sopenharmony_ci			   ice_stat_str(status));
50498c2ecf20Sopenharmony_ci		return -EIO;
50508c2ecf20Sopenharmony_ci	}
50518c2ecf20Sopenharmony_ci
50528c2ecf20Sopenharmony_ci	return 0;
50538c2ecf20Sopenharmony_ci}
50548c2ecf20Sopenharmony_ci
50558c2ecf20Sopenharmony_ci/**
50568c2ecf20Sopenharmony_ci * ice_fdb_add - add an entry to the hardware database
50578c2ecf20Sopenharmony_ci * @ndm: the input from the stack
50588c2ecf20Sopenharmony_ci * @tb: pointer to array of nladdr (unused)
50598c2ecf20Sopenharmony_ci * @dev: the net device pointer
50608c2ecf20Sopenharmony_ci * @addr: the MAC address entry being added
50618c2ecf20Sopenharmony_ci * @vid: VLAN ID
50628c2ecf20Sopenharmony_ci * @flags: instructions from stack about fdb operation
50638c2ecf20Sopenharmony_ci * @extack: netlink extended ack
50648c2ecf20Sopenharmony_ci */
50658c2ecf20Sopenharmony_cistatic int
50668c2ecf20Sopenharmony_ciice_fdb_add(struct ndmsg *ndm, struct nlattr __always_unused *tb[],
50678c2ecf20Sopenharmony_ci	    struct net_device *dev, const unsigned char *addr, u16 vid,
50688c2ecf20Sopenharmony_ci	    u16 flags, struct netlink_ext_ack __always_unused *extack)
50698c2ecf20Sopenharmony_ci{
50708c2ecf20Sopenharmony_ci	int err;
50718c2ecf20Sopenharmony_ci
50728c2ecf20Sopenharmony_ci	if (vid) {
50738c2ecf20Sopenharmony_ci		netdev_err(dev, "VLANs aren't supported yet for dev_uc|mc_add()\n");
50748c2ecf20Sopenharmony_ci		return -EINVAL;
50758c2ecf20Sopenharmony_ci	}
50768c2ecf20Sopenharmony_ci	if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
50778c2ecf20Sopenharmony_ci		netdev_err(dev, "FDB only supports static addresses\n");
50788c2ecf20Sopenharmony_ci		return -EINVAL;
50798c2ecf20Sopenharmony_ci	}
50808c2ecf20Sopenharmony_ci
50818c2ecf20Sopenharmony_ci	if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr))
50828c2ecf20Sopenharmony_ci		err = dev_uc_add_excl(dev, addr);
50838c2ecf20Sopenharmony_ci	else if (is_multicast_ether_addr(addr))
50848c2ecf20Sopenharmony_ci		err = dev_mc_add_excl(dev, addr);
50858c2ecf20Sopenharmony_ci	else
50868c2ecf20Sopenharmony_ci		err = -EINVAL;
50878c2ecf20Sopenharmony_ci
50888c2ecf20Sopenharmony_ci	/* Only return duplicate errors if NLM_F_EXCL is set */
50898c2ecf20Sopenharmony_ci	if (err == -EEXIST && !(flags & NLM_F_EXCL))
50908c2ecf20Sopenharmony_ci		err = 0;
50918c2ecf20Sopenharmony_ci
50928c2ecf20Sopenharmony_ci	return err;
50938c2ecf20Sopenharmony_ci}
50948c2ecf20Sopenharmony_ci
50958c2ecf20Sopenharmony_ci/**
50968c2ecf20Sopenharmony_ci * ice_fdb_del - delete an entry from the hardware database
50978c2ecf20Sopenharmony_ci * @ndm: the input from the stack
50988c2ecf20Sopenharmony_ci * @tb: pointer to array of nladdr (unused)
50998c2ecf20Sopenharmony_ci * @dev: the net device pointer
51008c2ecf20Sopenharmony_ci * @addr: the MAC address entry being added
51018c2ecf20Sopenharmony_ci * @vid: VLAN ID
51028c2ecf20Sopenharmony_ci */
51038c2ecf20Sopenharmony_cistatic int
51048c2ecf20Sopenharmony_ciice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
51058c2ecf20Sopenharmony_ci	    struct net_device *dev, const unsigned char *addr,
51068c2ecf20Sopenharmony_ci	    __always_unused u16 vid)
51078c2ecf20Sopenharmony_ci{
51088c2ecf20Sopenharmony_ci	int err;
51098c2ecf20Sopenharmony_ci
51108c2ecf20Sopenharmony_ci	if (ndm->ndm_state & NUD_PERMANENT) {
51118c2ecf20Sopenharmony_ci		netdev_err(dev, "FDB only supports static addresses\n");
51128c2ecf20Sopenharmony_ci		return -EINVAL;
51138c2ecf20Sopenharmony_ci	}
51148c2ecf20Sopenharmony_ci
51158c2ecf20Sopenharmony_ci	if (is_unicast_ether_addr(addr))
51168c2ecf20Sopenharmony_ci		err = dev_uc_del(dev, addr);
51178c2ecf20Sopenharmony_ci	else if (is_multicast_ether_addr(addr))
51188c2ecf20Sopenharmony_ci		err = dev_mc_del(dev, addr);
51198c2ecf20Sopenharmony_ci	else
51208c2ecf20Sopenharmony_ci		err = -EINVAL;
51218c2ecf20Sopenharmony_ci
51228c2ecf20Sopenharmony_ci	return err;
51238c2ecf20Sopenharmony_ci}
51248c2ecf20Sopenharmony_ci
51258c2ecf20Sopenharmony_ci/**
51268c2ecf20Sopenharmony_ci * ice_set_features - set the netdev feature flags
51278c2ecf20Sopenharmony_ci * @netdev: ptr to the netdev being adjusted
51288c2ecf20Sopenharmony_ci * @features: the feature set that the stack is suggesting
51298c2ecf20Sopenharmony_ci */
51308c2ecf20Sopenharmony_cistatic int
51318c2ecf20Sopenharmony_ciice_set_features(struct net_device *netdev, netdev_features_t features)
51328c2ecf20Sopenharmony_ci{
51338c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
51348c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
51358c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
51368c2ecf20Sopenharmony_ci	int ret = 0;
51378c2ecf20Sopenharmony_ci
51388c2ecf20Sopenharmony_ci	/* Don't set any netdev advanced features with device in Safe Mode */
51398c2ecf20Sopenharmony_ci	if (ice_is_safe_mode(vsi->back)) {
51408c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Device is in Safe Mode - not enabling advanced netdev features\n");
51418c2ecf20Sopenharmony_ci		return ret;
51428c2ecf20Sopenharmony_ci	}
51438c2ecf20Sopenharmony_ci
51448c2ecf20Sopenharmony_ci	/* Do not change setting during reset */
51458c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state)) {
51468c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "Device is resetting, changing advanced netdev features temporarily unavailable.\n");
51478c2ecf20Sopenharmony_ci		return -EBUSY;
51488c2ecf20Sopenharmony_ci	}
51498c2ecf20Sopenharmony_ci
51508c2ecf20Sopenharmony_ci	/* Multiple features can be changed in one call so keep features in
51518c2ecf20Sopenharmony_ci	 * separate if/else statements to guarantee each feature is checked
51528c2ecf20Sopenharmony_ci	 */
51538c2ecf20Sopenharmony_ci	if (features & NETIF_F_RXHASH && !(netdev->features & NETIF_F_RXHASH))
51548c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_rss_lut(vsi, true);
51558c2ecf20Sopenharmony_ci	else if (!(features & NETIF_F_RXHASH) &&
51568c2ecf20Sopenharmony_ci		 netdev->features & NETIF_F_RXHASH)
51578c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_rss_lut(vsi, false);
51588c2ecf20Sopenharmony_ci
51598c2ecf20Sopenharmony_ci	if ((features & NETIF_F_HW_VLAN_CTAG_RX) &&
51608c2ecf20Sopenharmony_ci	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
51618c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_vlan_stripping(vsi, true);
51628c2ecf20Sopenharmony_ci	else if (!(features & NETIF_F_HW_VLAN_CTAG_RX) &&
51638c2ecf20Sopenharmony_ci		 (netdev->features & NETIF_F_HW_VLAN_CTAG_RX))
51648c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_vlan_stripping(vsi, false);
51658c2ecf20Sopenharmony_ci
51668c2ecf20Sopenharmony_ci	if ((features & NETIF_F_HW_VLAN_CTAG_TX) &&
51678c2ecf20Sopenharmony_ci	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
51688c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_vlan_insertion(vsi);
51698c2ecf20Sopenharmony_ci	else if (!(features & NETIF_F_HW_VLAN_CTAG_TX) &&
51708c2ecf20Sopenharmony_ci		 (netdev->features & NETIF_F_HW_VLAN_CTAG_TX))
51718c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_vlan_insertion(vsi);
51728c2ecf20Sopenharmony_ci
51738c2ecf20Sopenharmony_ci	if ((features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
51748c2ecf20Sopenharmony_ci	    !(netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
51758c2ecf20Sopenharmony_ci		ret = ice_cfg_vlan_pruning(vsi, true, false);
51768c2ecf20Sopenharmony_ci	else if (!(features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
51778c2ecf20Sopenharmony_ci		 (netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
51788c2ecf20Sopenharmony_ci		ret = ice_cfg_vlan_pruning(vsi, false, false);
51798c2ecf20Sopenharmony_ci
51808c2ecf20Sopenharmony_ci	if ((features & NETIF_F_NTUPLE) &&
51818c2ecf20Sopenharmony_ci	    !(netdev->features & NETIF_F_NTUPLE)) {
51828c2ecf20Sopenharmony_ci		ice_vsi_manage_fdir(vsi, true);
51838c2ecf20Sopenharmony_ci		ice_init_arfs(vsi);
51848c2ecf20Sopenharmony_ci	} else if (!(features & NETIF_F_NTUPLE) &&
51858c2ecf20Sopenharmony_ci		 (netdev->features & NETIF_F_NTUPLE)) {
51868c2ecf20Sopenharmony_ci		ice_vsi_manage_fdir(vsi, false);
51878c2ecf20Sopenharmony_ci		ice_clear_arfs(vsi);
51888c2ecf20Sopenharmony_ci	}
51898c2ecf20Sopenharmony_ci
51908c2ecf20Sopenharmony_ci	return ret;
51918c2ecf20Sopenharmony_ci}
51928c2ecf20Sopenharmony_ci
51938c2ecf20Sopenharmony_ci/**
51948c2ecf20Sopenharmony_ci * ice_vsi_vlan_setup - Setup VLAN offload properties on a VSI
51958c2ecf20Sopenharmony_ci * @vsi: VSI to setup VLAN properties for
51968c2ecf20Sopenharmony_ci */
51978c2ecf20Sopenharmony_cistatic int ice_vsi_vlan_setup(struct ice_vsi *vsi)
51988c2ecf20Sopenharmony_ci{
51998c2ecf20Sopenharmony_ci	int ret = 0;
52008c2ecf20Sopenharmony_ci
52018c2ecf20Sopenharmony_ci	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
52028c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_vlan_stripping(vsi, true);
52038c2ecf20Sopenharmony_ci	if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)
52048c2ecf20Sopenharmony_ci		ret = ice_vsi_manage_vlan_insertion(vsi);
52058c2ecf20Sopenharmony_ci
52068c2ecf20Sopenharmony_ci	return ret;
52078c2ecf20Sopenharmony_ci}
52088c2ecf20Sopenharmony_ci
52098c2ecf20Sopenharmony_ci/**
52108c2ecf20Sopenharmony_ci * ice_vsi_cfg - Setup the VSI
52118c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
52128c2ecf20Sopenharmony_ci *
52138c2ecf20Sopenharmony_ci * Return 0 on success and negative value on error
52148c2ecf20Sopenharmony_ci */
52158c2ecf20Sopenharmony_ciint ice_vsi_cfg(struct ice_vsi *vsi)
52168c2ecf20Sopenharmony_ci{
52178c2ecf20Sopenharmony_ci	int err;
52188c2ecf20Sopenharmony_ci
52198c2ecf20Sopenharmony_ci	if (vsi->netdev && vsi->type == ICE_VSI_PF) {
52208c2ecf20Sopenharmony_ci		ice_set_rx_mode(vsi->netdev);
52218c2ecf20Sopenharmony_ci
52228c2ecf20Sopenharmony_ci		err = ice_vsi_vlan_setup(vsi);
52238c2ecf20Sopenharmony_ci		if (err)
52248c2ecf20Sopenharmony_ci			return err;
52258c2ecf20Sopenharmony_ci	}
52268c2ecf20Sopenharmony_ci	ice_vsi_cfg_dcb_rings(vsi);
52278c2ecf20Sopenharmony_ci
52288c2ecf20Sopenharmony_ci	err = ice_vsi_cfg_lan_txqs(vsi);
52298c2ecf20Sopenharmony_ci	if (!err && ice_is_xdp_ena_vsi(vsi))
52308c2ecf20Sopenharmony_ci		err = ice_vsi_cfg_xdp_txqs(vsi);
52318c2ecf20Sopenharmony_ci	if (!err)
52328c2ecf20Sopenharmony_ci		err = ice_vsi_cfg_rxqs(vsi);
52338c2ecf20Sopenharmony_ci
52348c2ecf20Sopenharmony_ci	return err;
52358c2ecf20Sopenharmony_ci}
52368c2ecf20Sopenharmony_ci
52378c2ecf20Sopenharmony_ci/**
52388c2ecf20Sopenharmony_ci * ice_napi_enable_all - Enable NAPI for all q_vectors in the VSI
52398c2ecf20Sopenharmony_ci * @vsi: the VSI being configured
52408c2ecf20Sopenharmony_ci */
52418c2ecf20Sopenharmony_cistatic void ice_napi_enable_all(struct ice_vsi *vsi)
52428c2ecf20Sopenharmony_ci{
52438c2ecf20Sopenharmony_ci	int q_idx;
52448c2ecf20Sopenharmony_ci
52458c2ecf20Sopenharmony_ci	if (!vsi->netdev)
52468c2ecf20Sopenharmony_ci		return;
52478c2ecf20Sopenharmony_ci
52488c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, q_idx) {
52498c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[q_idx];
52508c2ecf20Sopenharmony_ci
52518c2ecf20Sopenharmony_ci		if (q_vector->rx.ring || q_vector->tx.ring)
52528c2ecf20Sopenharmony_ci			napi_enable(&q_vector->napi);
52538c2ecf20Sopenharmony_ci	}
52548c2ecf20Sopenharmony_ci}
52558c2ecf20Sopenharmony_ci
52568c2ecf20Sopenharmony_ci/**
52578c2ecf20Sopenharmony_ci * ice_up_complete - Finish the last steps of bringing up a connection
52588c2ecf20Sopenharmony_ci * @vsi: The VSI being configured
52598c2ecf20Sopenharmony_ci *
52608c2ecf20Sopenharmony_ci * Return 0 on success and negative value on error
52618c2ecf20Sopenharmony_ci */
52628c2ecf20Sopenharmony_cistatic int ice_up_complete(struct ice_vsi *vsi)
52638c2ecf20Sopenharmony_ci{
52648c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
52658c2ecf20Sopenharmony_ci	int err;
52668c2ecf20Sopenharmony_ci
52678c2ecf20Sopenharmony_ci	ice_vsi_cfg_msix(vsi);
52688c2ecf20Sopenharmony_ci
52698c2ecf20Sopenharmony_ci	/* Enable only Rx rings, Tx rings were enabled by the FW when the
52708c2ecf20Sopenharmony_ci	 * Tx queue group list was configured and the context bits were
52718c2ecf20Sopenharmony_ci	 * programmed using ice_vsi_cfg_txqs
52728c2ecf20Sopenharmony_ci	 */
52738c2ecf20Sopenharmony_ci	err = ice_vsi_start_all_rx_rings(vsi);
52748c2ecf20Sopenharmony_ci	if (err)
52758c2ecf20Sopenharmony_ci		return err;
52768c2ecf20Sopenharmony_ci
52778c2ecf20Sopenharmony_ci	clear_bit(__ICE_DOWN, vsi->state);
52788c2ecf20Sopenharmony_ci	ice_napi_enable_all(vsi);
52798c2ecf20Sopenharmony_ci	ice_vsi_ena_irq(vsi);
52808c2ecf20Sopenharmony_ci
52818c2ecf20Sopenharmony_ci	if (vsi->port_info &&
52828c2ecf20Sopenharmony_ci	    (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
52838c2ecf20Sopenharmony_ci	    vsi->netdev && vsi->type == ICE_VSI_PF) {
52848c2ecf20Sopenharmony_ci		ice_print_link_msg(vsi, true);
52858c2ecf20Sopenharmony_ci		netif_tx_start_all_queues(vsi->netdev);
52868c2ecf20Sopenharmony_ci		netif_carrier_on(vsi->netdev);
52878c2ecf20Sopenharmony_ci	}
52888c2ecf20Sopenharmony_ci
52898c2ecf20Sopenharmony_ci	/* Perform an initial read of the statistics registers now to
52908c2ecf20Sopenharmony_ci	 * set the baseline so counters are ready when interface is up
52918c2ecf20Sopenharmony_ci	 */
52928c2ecf20Sopenharmony_ci	ice_update_eth_stats(vsi);
52938c2ecf20Sopenharmony_ci
52948c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF)
52958c2ecf20Sopenharmony_ci		ice_service_task_schedule(pf);
52968c2ecf20Sopenharmony_ci
52978c2ecf20Sopenharmony_ci	return 0;
52988c2ecf20Sopenharmony_ci}
52998c2ecf20Sopenharmony_ci
53008c2ecf20Sopenharmony_ci/**
53018c2ecf20Sopenharmony_ci * ice_up - Bring the connection back up after being down
53028c2ecf20Sopenharmony_ci * @vsi: VSI being configured
53038c2ecf20Sopenharmony_ci */
53048c2ecf20Sopenharmony_ciint ice_up(struct ice_vsi *vsi)
53058c2ecf20Sopenharmony_ci{
53068c2ecf20Sopenharmony_ci	int err;
53078c2ecf20Sopenharmony_ci
53088c2ecf20Sopenharmony_ci	err = ice_vsi_cfg(vsi);
53098c2ecf20Sopenharmony_ci	if (!err)
53108c2ecf20Sopenharmony_ci		err = ice_up_complete(vsi);
53118c2ecf20Sopenharmony_ci
53128c2ecf20Sopenharmony_ci	return err;
53138c2ecf20Sopenharmony_ci}
53148c2ecf20Sopenharmony_ci
53158c2ecf20Sopenharmony_ci/**
53168c2ecf20Sopenharmony_ci * ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring
53178c2ecf20Sopenharmony_ci * @ring: Tx or Rx ring to read stats from
53188c2ecf20Sopenharmony_ci * @pkts: packets stats counter
53198c2ecf20Sopenharmony_ci * @bytes: bytes stats counter
53208c2ecf20Sopenharmony_ci *
53218c2ecf20Sopenharmony_ci * This function fetches stats from the ring considering the atomic operations
53228c2ecf20Sopenharmony_ci * that needs to be performed to read u64 values in 32 bit machine.
53238c2ecf20Sopenharmony_ci */
53248c2ecf20Sopenharmony_cistatic void
53258c2ecf20Sopenharmony_ciice_fetch_u64_stats_per_ring(struct ice_ring *ring, u64 *pkts, u64 *bytes)
53268c2ecf20Sopenharmony_ci{
53278c2ecf20Sopenharmony_ci	unsigned int start;
53288c2ecf20Sopenharmony_ci	*pkts = 0;
53298c2ecf20Sopenharmony_ci	*bytes = 0;
53308c2ecf20Sopenharmony_ci
53318c2ecf20Sopenharmony_ci	if (!ring)
53328c2ecf20Sopenharmony_ci		return;
53338c2ecf20Sopenharmony_ci	do {
53348c2ecf20Sopenharmony_ci		start = u64_stats_fetch_begin_irq(&ring->syncp);
53358c2ecf20Sopenharmony_ci		*pkts = ring->stats.pkts;
53368c2ecf20Sopenharmony_ci		*bytes = ring->stats.bytes;
53378c2ecf20Sopenharmony_ci	} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
53388c2ecf20Sopenharmony_ci}
53398c2ecf20Sopenharmony_ci
53408c2ecf20Sopenharmony_ci/**
53418c2ecf20Sopenharmony_ci * ice_update_vsi_tx_ring_stats - Update VSI Tx ring stats counters
53428c2ecf20Sopenharmony_ci * @vsi: the VSI to be updated
53438c2ecf20Sopenharmony_ci * @rings: rings to work on
53448c2ecf20Sopenharmony_ci * @count: number of rings
53458c2ecf20Sopenharmony_ci */
53468c2ecf20Sopenharmony_cistatic void
53478c2ecf20Sopenharmony_ciice_update_vsi_tx_ring_stats(struct ice_vsi *vsi, struct ice_ring **rings,
53488c2ecf20Sopenharmony_ci			     u16 count)
53498c2ecf20Sopenharmony_ci{
53508c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
53518c2ecf20Sopenharmony_ci	u16 i;
53528c2ecf20Sopenharmony_ci
53538c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
53548c2ecf20Sopenharmony_ci		struct ice_ring *ring;
53558c2ecf20Sopenharmony_ci		u64 pkts, bytes;
53568c2ecf20Sopenharmony_ci
53578c2ecf20Sopenharmony_ci		ring = READ_ONCE(rings[i]);
53588c2ecf20Sopenharmony_ci		ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
53598c2ecf20Sopenharmony_ci		vsi_stats->tx_packets += pkts;
53608c2ecf20Sopenharmony_ci		vsi_stats->tx_bytes += bytes;
53618c2ecf20Sopenharmony_ci		vsi->tx_restart += ring->tx_stats.restart_q;
53628c2ecf20Sopenharmony_ci		vsi->tx_busy += ring->tx_stats.tx_busy;
53638c2ecf20Sopenharmony_ci		vsi->tx_linearize += ring->tx_stats.tx_linearize;
53648c2ecf20Sopenharmony_ci	}
53658c2ecf20Sopenharmony_ci}
53668c2ecf20Sopenharmony_ci
53678c2ecf20Sopenharmony_ci/**
53688c2ecf20Sopenharmony_ci * ice_update_vsi_ring_stats - Update VSI stats counters
53698c2ecf20Sopenharmony_ci * @vsi: the VSI to be updated
53708c2ecf20Sopenharmony_ci */
53718c2ecf20Sopenharmony_cistatic void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
53728c2ecf20Sopenharmony_ci{
53738c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 *vsi_stats = &vsi->net_stats;
53748c2ecf20Sopenharmony_ci	struct ice_ring *ring;
53758c2ecf20Sopenharmony_ci	u64 pkts, bytes;
53768c2ecf20Sopenharmony_ci	int i;
53778c2ecf20Sopenharmony_ci
53788c2ecf20Sopenharmony_ci	/* reset netdev stats */
53798c2ecf20Sopenharmony_ci	vsi_stats->tx_packets = 0;
53808c2ecf20Sopenharmony_ci	vsi_stats->tx_bytes = 0;
53818c2ecf20Sopenharmony_ci	vsi_stats->rx_packets = 0;
53828c2ecf20Sopenharmony_ci	vsi_stats->rx_bytes = 0;
53838c2ecf20Sopenharmony_ci
53848c2ecf20Sopenharmony_ci	/* reset non-netdev (extended) stats */
53858c2ecf20Sopenharmony_ci	vsi->tx_restart = 0;
53868c2ecf20Sopenharmony_ci	vsi->tx_busy = 0;
53878c2ecf20Sopenharmony_ci	vsi->tx_linearize = 0;
53888c2ecf20Sopenharmony_ci	vsi->rx_buf_failed = 0;
53898c2ecf20Sopenharmony_ci	vsi->rx_page_failed = 0;
53908c2ecf20Sopenharmony_ci	vsi->rx_gro_dropped = 0;
53918c2ecf20Sopenharmony_ci
53928c2ecf20Sopenharmony_ci	rcu_read_lock();
53938c2ecf20Sopenharmony_ci
53948c2ecf20Sopenharmony_ci	/* update Tx rings counters */
53958c2ecf20Sopenharmony_ci	ice_update_vsi_tx_ring_stats(vsi, vsi->tx_rings, vsi->num_txq);
53968c2ecf20Sopenharmony_ci
53978c2ecf20Sopenharmony_ci	/* update Rx rings counters */
53988c2ecf20Sopenharmony_ci	ice_for_each_rxq(vsi, i) {
53998c2ecf20Sopenharmony_ci		ring = READ_ONCE(vsi->rx_rings[i]);
54008c2ecf20Sopenharmony_ci		ice_fetch_u64_stats_per_ring(ring, &pkts, &bytes);
54018c2ecf20Sopenharmony_ci		vsi_stats->rx_packets += pkts;
54028c2ecf20Sopenharmony_ci		vsi_stats->rx_bytes += bytes;
54038c2ecf20Sopenharmony_ci		vsi->rx_buf_failed += ring->rx_stats.alloc_buf_failed;
54048c2ecf20Sopenharmony_ci		vsi->rx_page_failed += ring->rx_stats.alloc_page_failed;
54058c2ecf20Sopenharmony_ci		vsi->rx_gro_dropped += ring->rx_stats.gro_dropped;
54068c2ecf20Sopenharmony_ci	}
54078c2ecf20Sopenharmony_ci
54088c2ecf20Sopenharmony_ci	/* update XDP Tx rings counters */
54098c2ecf20Sopenharmony_ci	if (ice_is_xdp_ena_vsi(vsi))
54108c2ecf20Sopenharmony_ci		ice_update_vsi_tx_ring_stats(vsi, vsi->xdp_rings,
54118c2ecf20Sopenharmony_ci					     vsi->num_xdp_txq);
54128c2ecf20Sopenharmony_ci
54138c2ecf20Sopenharmony_ci	rcu_read_unlock();
54148c2ecf20Sopenharmony_ci}
54158c2ecf20Sopenharmony_ci
54168c2ecf20Sopenharmony_ci/**
54178c2ecf20Sopenharmony_ci * ice_update_vsi_stats - Update VSI stats counters
54188c2ecf20Sopenharmony_ci * @vsi: the VSI to be updated
54198c2ecf20Sopenharmony_ci */
54208c2ecf20Sopenharmony_civoid ice_update_vsi_stats(struct ice_vsi *vsi)
54218c2ecf20Sopenharmony_ci{
54228c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 *cur_ns = &vsi->net_stats;
54238c2ecf20Sopenharmony_ci	struct ice_eth_stats *cur_es = &vsi->eth_stats;
54248c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
54258c2ecf20Sopenharmony_ci
54268c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, vsi->state) ||
54278c2ecf20Sopenharmony_ci	    test_bit(__ICE_CFG_BUSY, pf->state))
54288c2ecf20Sopenharmony_ci		return;
54298c2ecf20Sopenharmony_ci
54308c2ecf20Sopenharmony_ci	/* get stats as recorded by Tx/Rx rings */
54318c2ecf20Sopenharmony_ci	ice_update_vsi_ring_stats(vsi);
54328c2ecf20Sopenharmony_ci
54338c2ecf20Sopenharmony_ci	/* get VSI stats as recorded by the hardware */
54348c2ecf20Sopenharmony_ci	ice_update_eth_stats(vsi);
54358c2ecf20Sopenharmony_ci
54368c2ecf20Sopenharmony_ci	cur_ns->tx_errors = cur_es->tx_errors;
54378c2ecf20Sopenharmony_ci	cur_ns->rx_dropped = cur_es->rx_discards + vsi->rx_gro_dropped;
54388c2ecf20Sopenharmony_ci	cur_ns->tx_dropped = cur_es->tx_discards;
54398c2ecf20Sopenharmony_ci	cur_ns->multicast = cur_es->rx_multicast;
54408c2ecf20Sopenharmony_ci
54418c2ecf20Sopenharmony_ci	/* update some more netdev stats if this is main VSI */
54428c2ecf20Sopenharmony_ci	if (vsi->type == ICE_VSI_PF) {
54438c2ecf20Sopenharmony_ci		cur_ns->rx_crc_errors = pf->stats.crc_errors;
54448c2ecf20Sopenharmony_ci		cur_ns->rx_errors = pf->stats.crc_errors +
54458c2ecf20Sopenharmony_ci				    pf->stats.illegal_bytes +
54468c2ecf20Sopenharmony_ci				    pf->stats.rx_len_errors +
54478c2ecf20Sopenharmony_ci				    pf->stats.rx_undersize +
54488c2ecf20Sopenharmony_ci				    pf->hw_csum_rx_error +
54498c2ecf20Sopenharmony_ci				    pf->stats.rx_jabber +
54508c2ecf20Sopenharmony_ci				    pf->stats.rx_fragments +
54518c2ecf20Sopenharmony_ci				    pf->stats.rx_oversize;
54528c2ecf20Sopenharmony_ci		cur_ns->rx_length_errors = pf->stats.rx_len_errors;
54538c2ecf20Sopenharmony_ci		/* record drops from the port level */
54548c2ecf20Sopenharmony_ci		cur_ns->rx_missed_errors = pf->stats.eth.rx_discards;
54558c2ecf20Sopenharmony_ci	}
54568c2ecf20Sopenharmony_ci}
54578c2ecf20Sopenharmony_ci
54588c2ecf20Sopenharmony_ci/**
54598c2ecf20Sopenharmony_ci * ice_update_pf_stats - Update PF port stats counters
54608c2ecf20Sopenharmony_ci * @pf: PF whose stats needs to be updated
54618c2ecf20Sopenharmony_ci */
54628c2ecf20Sopenharmony_civoid ice_update_pf_stats(struct ice_pf *pf)
54638c2ecf20Sopenharmony_ci{
54648c2ecf20Sopenharmony_ci	struct ice_hw_port_stats *prev_ps, *cur_ps;
54658c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
54668c2ecf20Sopenharmony_ci	u16 fd_ctr_base;
54678c2ecf20Sopenharmony_ci	u8 port;
54688c2ecf20Sopenharmony_ci
54698c2ecf20Sopenharmony_ci	port = hw->port_info->lport;
54708c2ecf20Sopenharmony_ci	prev_ps = &pf->stats_prev;
54718c2ecf20Sopenharmony_ci	cur_ps = &pf->stats;
54728c2ecf20Sopenharmony_ci
54738c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_GORCL(port), pf->stat_prev_loaded,
54748c2ecf20Sopenharmony_ci			  &prev_ps->eth.rx_bytes,
54758c2ecf20Sopenharmony_ci			  &cur_ps->eth.rx_bytes);
54768c2ecf20Sopenharmony_ci
54778c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_UPRCL(port), pf->stat_prev_loaded,
54788c2ecf20Sopenharmony_ci			  &prev_ps->eth.rx_unicast,
54798c2ecf20Sopenharmony_ci			  &cur_ps->eth.rx_unicast);
54808c2ecf20Sopenharmony_ci
54818c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_MPRCL(port), pf->stat_prev_loaded,
54828c2ecf20Sopenharmony_ci			  &prev_ps->eth.rx_multicast,
54838c2ecf20Sopenharmony_ci			  &cur_ps->eth.rx_multicast);
54848c2ecf20Sopenharmony_ci
54858c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_BPRCL(port), pf->stat_prev_loaded,
54868c2ecf20Sopenharmony_ci			  &prev_ps->eth.rx_broadcast,
54878c2ecf20Sopenharmony_ci			  &cur_ps->eth.rx_broadcast);
54888c2ecf20Sopenharmony_ci
54898c2ecf20Sopenharmony_ci	ice_stat_update32(hw, PRTRPB_RDPC, pf->stat_prev_loaded,
54908c2ecf20Sopenharmony_ci			  &prev_ps->eth.rx_discards,
54918c2ecf20Sopenharmony_ci			  &cur_ps->eth.rx_discards);
54928c2ecf20Sopenharmony_ci
54938c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_GOTCL(port), pf->stat_prev_loaded,
54948c2ecf20Sopenharmony_ci			  &prev_ps->eth.tx_bytes,
54958c2ecf20Sopenharmony_ci			  &cur_ps->eth.tx_bytes);
54968c2ecf20Sopenharmony_ci
54978c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_UPTCL(port), pf->stat_prev_loaded,
54988c2ecf20Sopenharmony_ci			  &prev_ps->eth.tx_unicast,
54998c2ecf20Sopenharmony_ci			  &cur_ps->eth.tx_unicast);
55008c2ecf20Sopenharmony_ci
55018c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_MPTCL(port), pf->stat_prev_loaded,
55028c2ecf20Sopenharmony_ci			  &prev_ps->eth.tx_multicast,
55038c2ecf20Sopenharmony_ci			  &cur_ps->eth.tx_multicast);
55048c2ecf20Sopenharmony_ci
55058c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_BPTCL(port), pf->stat_prev_loaded,
55068c2ecf20Sopenharmony_ci			  &prev_ps->eth.tx_broadcast,
55078c2ecf20Sopenharmony_ci			  &cur_ps->eth.tx_broadcast);
55088c2ecf20Sopenharmony_ci
55098c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_TDOLD(port), pf->stat_prev_loaded,
55108c2ecf20Sopenharmony_ci			  &prev_ps->tx_dropped_link_down,
55118c2ecf20Sopenharmony_ci			  &cur_ps->tx_dropped_link_down);
55128c2ecf20Sopenharmony_ci
55138c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC64L(port), pf->stat_prev_loaded,
55148c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_64, &cur_ps->rx_size_64);
55158c2ecf20Sopenharmony_ci
55168c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC127L(port), pf->stat_prev_loaded,
55178c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_127, &cur_ps->rx_size_127);
55188c2ecf20Sopenharmony_ci
55198c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC255L(port), pf->stat_prev_loaded,
55208c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_255, &cur_ps->rx_size_255);
55218c2ecf20Sopenharmony_ci
55228c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC511L(port), pf->stat_prev_loaded,
55238c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_511, &cur_ps->rx_size_511);
55248c2ecf20Sopenharmony_ci
55258c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC1023L(port), pf->stat_prev_loaded,
55268c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_1023, &cur_ps->rx_size_1023);
55278c2ecf20Sopenharmony_ci
55288c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC1522L(port), pf->stat_prev_loaded,
55298c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_1522, &cur_ps->rx_size_1522);
55308c2ecf20Sopenharmony_ci
55318c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PRC9522L(port), pf->stat_prev_loaded,
55328c2ecf20Sopenharmony_ci			  &prev_ps->rx_size_big, &cur_ps->rx_size_big);
55338c2ecf20Sopenharmony_ci
55348c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC64L(port), pf->stat_prev_loaded,
55358c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_64, &cur_ps->tx_size_64);
55368c2ecf20Sopenharmony_ci
55378c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC127L(port), pf->stat_prev_loaded,
55388c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_127, &cur_ps->tx_size_127);
55398c2ecf20Sopenharmony_ci
55408c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC255L(port), pf->stat_prev_loaded,
55418c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_255, &cur_ps->tx_size_255);
55428c2ecf20Sopenharmony_ci
55438c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC511L(port), pf->stat_prev_loaded,
55448c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_511, &cur_ps->tx_size_511);
55458c2ecf20Sopenharmony_ci
55468c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC1023L(port), pf->stat_prev_loaded,
55478c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_1023, &cur_ps->tx_size_1023);
55488c2ecf20Sopenharmony_ci
55498c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC1522L(port), pf->stat_prev_loaded,
55508c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_1522, &cur_ps->tx_size_1522);
55518c2ecf20Sopenharmony_ci
55528c2ecf20Sopenharmony_ci	ice_stat_update40(hw, GLPRT_PTC9522L(port), pf->stat_prev_loaded,
55538c2ecf20Sopenharmony_ci			  &prev_ps->tx_size_big, &cur_ps->tx_size_big);
55548c2ecf20Sopenharmony_ci
55558c2ecf20Sopenharmony_ci	fd_ctr_base = hw->fd_ctr_base;
55568c2ecf20Sopenharmony_ci
55578c2ecf20Sopenharmony_ci	ice_stat_update40(hw,
55588c2ecf20Sopenharmony_ci			  GLSTAT_FD_CNT0L(ICE_FD_SB_STAT_IDX(fd_ctr_base)),
55598c2ecf20Sopenharmony_ci			  pf->stat_prev_loaded, &prev_ps->fd_sb_match,
55608c2ecf20Sopenharmony_ci			  &cur_ps->fd_sb_match);
55618c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_LXONRXC(port), pf->stat_prev_loaded,
55628c2ecf20Sopenharmony_ci			  &prev_ps->link_xon_rx, &cur_ps->link_xon_rx);
55638c2ecf20Sopenharmony_ci
55648c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_LXOFFRXC(port), pf->stat_prev_loaded,
55658c2ecf20Sopenharmony_ci			  &prev_ps->link_xoff_rx, &cur_ps->link_xoff_rx);
55668c2ecf20Sopenharmony_ci
55678c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_LXONTXC(port), pf->stat_prev_loaded,
55688c2ecf20Sopenharmony_ci			  &prev_ps->link_xon_tx, &cur_ps->link_xon_tx);
55698c2ecf20Sopenharmony_ci
55708c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_LXOFFTXC(port), pf->stat_prev_loaded,
55718c2ecf20Sopenharmony_ci			  &prev_ps->link_xoff_tx, &cur_ps->link_xoff_tx);
55728c2ecf20Sopenharmony_ci
55738c2ecf20Sopenharmony_ci	ice_update_dcb_stats(pf);
55748c2ecf20Sopenharmony_ci
55758c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_CRCERRS(port), pf->stat_prev_loaded,
55768c2ecf20Sopenharmony_ci			  &prev_ps->crc_errors, &cur_ps->crc_errors);
55778c2ecf20Sopenharmony_ci
55788c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_ILLERRC(port), pf->stat_prev_loaded,
55798c2ecf20Sopenharmony_ci			  &prev_ps->illegal_bytes, &cur_ps->illegal_bytes);
55808c2ecf20Sopenharmony_ci
55818c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_MLFC(port), pf->stat_prev_loaded,
55828c2ecf20Sopenharmony_ci			  &prev_ps->mac_local_faults,
55838c2ecf20Sopenharmony_ci			  &cur_ps->mac_local_faults);
55848c2ecf20Sopenharmony_ci
55858c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_MRFC(port), pf->stat_prev_loaded,
55868c2ecf20Sopenharmony_ci			  &prev_ps->mac_remote_faults,
55878c2ecf20Sopenharmony_ci			  &cur_ps->mac_remote_faults);
55888c2ecf20Sopenharmony_ci
55898c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_RLEC(port), pf->stat_prev_loaded,
55908c2ecf20Sopenharmony_ci			  &prev_ps->rx_len_errors, &cur_ps->rx_len_errors);
55918c2ecf20Sopenharmony_ci
55928c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_RUC(port), pf->stat_prev_loaded,
55938c2ecf20Sopenharmony_ci			  &prev_ps->rx_undersize, &cur_ps->rx_undersize);
55948c2ecf20Sopenharmony_ci
55958c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_RFC(port), pf->stat_prev_loaded,
55968c2ecf20Sopenharmony_ci			  &prev_ps->rx_fragments, &cur_ps->rx_fragments);
55978c2ecf20Sopenharmony_ci
55988c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_ROC(port), pf->stat_prev_loaded,
55998c2ecf20Sopenharmony_ci			  &prev_ps->rx_oversize, &cur_ps->rx_oversize);
56008c2ecf20Sopenharmony_ci
56018c2ecf20Sopenharmony_ci	ice_stat_update32(hw, GLPRT_RJC(port), pf->stat_prev_loaded,
56028c2ecf20Sopenharmony_ci			  &prev_ps->rx_jabber, &cur_ps->rx_jabber);
56038c2ecf20Sopenharmony_ci
56048c2ecf20Sopenharmony_ci	cur_ps->fd_sb_status = test_bit(ICE_FLAG_FD_ENA, pf->flags) ? 1 : 0;
56058c2ecf20Sopenharmony_ci
56068c2ecf20Sopenharmony_ci	pf->stat_prev_loaded = true;
56078c2ecf20Sopenharmony_ci}
56088c2ecf20Sopenharmony_ci
56098c2ecf20Sopenharmony_ci/**
56108c2ecf20Sopenharmony_ci * ice_get_stats64 - get statistics for network device structure
56118c2ecf20Sopenharmony_ci * @netdev: network interface device structure
56128c2ecf20Sopenharmony_ci * @stats: main device statistics structure
56138c2ecf20Sopenharmony_ci */
56148c2ecf20Sopenharmony_cistatic
56158c2ecf20Sopenharmony_civoid ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
56168c2ecf20Sopenharmony_ci{
56178c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
56188c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 *vsi_stats;
56198c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
56208c2ecf20Sopenharmony_ci
56218c2ecf20Sopenharmony_ci	vsi_stats = &vsi->net_stats;
56228c2ecf20Sopenharmony_ci
56238c2ecf20Sopenharmony_ci	if (!vsi->num_txq || !vsi->num_rxq)
56248c2ecf20Sopenharmony_ci		return;
56258c2ecf20Sopenharmony_ci
56268c2ecf20Sopenharmony_ci	/* netdev packet/byte stats come from ring counter. These are obtained
56278c2ecf20Sopenharmony_ci	 * by summing up ring counters (done by ice_update_vsi_ring_stats).
56288c2ecf20Sopenharmony_ci	 * But, only call the update routine and read the registers if VSI is
56298c2ecf20Sopenharmony_ci	 * not down.
56308c2ecf20Sopenharmony_ci	 */
56318c2ecf20Sopenharmony_ci	if (!test_bit(__ICE_DOWN, vsi->state))
56328c2ecf20Sopenharmony_ci		ice_update_vsi_ring_stats(vsi);
56338c2ecf20Sopenharmony_ci	stats->tx_packets = vsi_stats->tx_packets;
56348c2ecf20Sopenharmony_ci	stats->tx_bytes = vsi_stats->tx_bytes;
56358c2ecf20Sopenharmony_ci	stats->rx_packets = vsi_stats->rx_packets;
56368c2ecf20Sopenharmony_ci	stats->rx_bytes = vsi_stats->rx_bytes;
56378c2ecf20Sopenharmony_ci
56388c2ecf20Sopenharmony_ci	/* The rest of the stats can be read from the hardware but instead we
56398c2ecf20Sopenharmony_ci	 * just return values that the watchdog task has already obtained from
56408c2ecf20Sopenharmony_ci	 * the hardware.
56418c2ecf20Sopenharmony_ci	 */
56428c2ecf20Sopenharmony_ci	stats->multicast = vsi_stats->multicast;
56438c2ecf20Sopenharmony_ci	stats->tx_errors = vsi_stats->tx_errors;
56448c2ecf20Sopenharmony_ci	stats->tx_dropped = vsi_stats->tx_dropped;
56458c2ecf20Sopenharmony_ci	stats->rx_errors = vsi_stats->rx_errors;
56468c2ecf20Sopenharmony_ci	stats->rx_dropped = vsi_stats->rx_dropped;
56478c2ecf20Sopenharmony_ci	stats->rx_crc_errors = vsi_stats->rx_crc_errors;
56488c2ecf20Sopenharmony_ci	stats->rx_length_errors = vsi_stats->rx_length_errors;
56498c2ecf20Sopenharmony_ci}
56508c2ecf20Sopenharmony_ci
56518c2ecf20Sopenharmony_ci/**
56528c2ecf20Sopenharmony_ci * ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI
56538c2ecf20Sopenharmony_ci * @vsi: VSI having NAPI disabled
56548c2ecf20Sopenharmony_ci */
56558c2ecf20Sopenharmony_cistatic void ice_napi_disable_all(struct ice_vsi *vsi)
56568c2ecf20Sopenharmony_ci{
56578c2ecf20Sopenharmony_ci	int q_idx;
56588c2ecf20Sopenharmony_ci
56598c2ecf20Sopenharmony_ci	if (!vsi->netdev)
56608c2ecf20Sopenharmony_ci		return;
56618c2ecf20Sopenharmony_ci
56628c2ecf20Sopenharmony_ci	ice_for_each_q_vector(vsi, q_idx) {
56638c2ecf20Sopenharmony_ci		struct ice_q_vector *q_vector = vsi->q_vectors[q_idx];
56648c2ecf20Sopenharmony_ci
56658c2ecf20Sopenharmony_ci		if (q_vector->rx.ring || q_vector->tx.ring)
56668c2ecf20Sopenharmony_ci			napi_disable(&q_vector->napi);
56678c2ecf20Sopenharmony_ci	}
56688c2ecf20Sopenharmony_ci}
56698c2ecf20Sopenharmony_ci
56708c2ecf20Sopenharmony_ci/**
56718c2ecf20Sopenharmony_ci * ice_down - Shutdown the connection
56728c2ecf20Sopenharmony_ci * @vsi: The VSI being stopped
56738c2ecf20Sopenharmony_ci */
56748c2ecf20Sopenharmony_ciint ice_down(struct ice_vsi *vsi)
56758c2ecf20Sopenharmony_ci{
56768c2ecf20Sopenharmony_ci	int i, tx_err, rx_err, link_err = 0;
56778c2ecf20Sopenharmony_ci
56788c2ecf20Sopenharmony_ci	/* Caller of this function is expected to set the
56798c2ecf20Sopenharmony_ci	 * vsi->state __ICE_DOWN bit
56808c2ecf20Sopenharmony_ci	 */
56818c2ecf20Sopenharmony_ci	if (vsi->netdev) {
56828c2ecf20Sopenharmony_ci		netif_carrier_off(vsi->netdev);
56838c2ecf20Sopenharmony_ci		netif_tx_disable(vsi->netdev);
56848c2ecf20Sopenharmony_ci	}
56858c2ecf20Sopenharmony_ci
56868c2ecf20Sopenharmony_ci	ice_vsi_dis_irq(vsi);
56878c2ecf20Sopenharmony_ci
56888c2ecf20Sopenharmony_ci	tx_err = ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0);
56898c2ecf20Sopenharmony_ci	if (tx_err)
56908c2ecf20Sopenharmony_ci		netdev_err(vsi->netdev, "Failed stop Tx rings, VSI %d error %d\n",
56918c2ecf20Sopenharmony_ci			   vsi->vsi_num, tx_err);
56928c2ecf20Sopenharmony_ci	if (!tx_err && ice_is_xdp_ena_vsi(vsi)) {
56938c2ecf20Sopenharmony_ci		tx_err = ice_vsi_stop_xdp_tx_rings(vsi);
56948c2ecf20Sopenharmony_ci		if (tx_err)
56958c2ecf20Sopenharmony_ci			netdev_err(vsi->netdev, "Failed stop XDP rings, VSI %d error %d\n",
56968c2ecf20Sopenharmony_ci				   vsi->vsi_num, tx_err);
56978c2ecf20Sopenharmony_ci	}
56988c2ecf20Sopenharmony_ci
56998c2ecf20Sopenharmony_ci	rx_err = ice_vsi_stop_all_rx_rings(vsi);
57008c2ecf20Sopenharmony_ci	if (rx_err)
57018c2ecf20Sopenharmony_ci		netdev_err(vsi->netdev, "Failed stop Rx rings, VSI %d error %d\n",
57028c2ecf20Sopenharmony_ci			   vsi->vsi_num, rx_err);
57038c2ecf20Sopenharmony_ci
57048c2ecf20Sopenharmony_ci	ice_napi_disable_all(vsi);
57058c2ecf20Sopenharmony_ci
57068c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, vsi->back->flags)) {
57078c2ecf20Sopenharmony_ci		link_err = ice_force_phys_link_state(vsi, false);
57088c2ecf20Sopenharmony_ci		if (link_err)
57098c2ecf20Sopenharmony_ci			netdev_err(vsi->netdev, "Failed to set physical link down, VSI %d error %d\n",
57108c2ecf20Sopenharmony_ci				   vsi->vsi_num, link_err);
57118c2ecf20Sopenharmony_ci	}
57128c2ecf20Sopenharmony_ci
57138c2ecf20Sopenharmony_ci	ice_for_each_txq(vsi, i)
57148c2ecf20Sopenharmony_ci		ice_clean_tx_ring(vsi->tx_rings[i]);
57158c2ecf20Sopenharmony_ci
57168c2ecf20Sopenharmony_ci	ice_for_each_rxq(vsi, i)
57178c2ecf20Sopenharmony_ci		ice_clean_rx_ring(vsi->rx_rings[i]);
57188c2ecf20Sopenharmony_ci
57198c2ecf20Sopenharmony_ci	if (tx_err || rx_err || link_err) {
57208c2ecf20Sopenharmony_ci		netdev_err(vsi->netdev, "Failed to close VSI 0x%04X on switch 0x%04X\n",
57218c2ecf20Sopenharmony_ci			   vsi->vsi_num, vsi->vsw->sw_id);
57228c2ecf20Sopenharmony_ci		return -EIO;
57238c2ecf20Sopenharmony_ci	}
57248c2ecf20Sopenharmony_ci
57258c2ecf20Sopenharmony_ci	return 0;
57268c2ecf20Sopenharmony_ci}
57278c2ecf20Sopenharmony_ci
57288c2ecf20Sopenharmony_ci/**
57298c2ecf20Sopenharmony_ci * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources
57308c2ecf20Sopenharmony_ci * @vsi: VSI having resources allocated
57318c2ecf20Sopenharmony_ci *
57328c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure
57338c2ecf20Sopenharmony_ci */
57348c2ecf20Sopenharmony_ciint ice_vsi_setup_tx_rings(struct ice_vsi *vsi)
57358c2ecf20Sopenharmony_ci{
57368c2ecf20Sopenharmony_ci	int i, err = 0;
57378c2ecf20Sopenharmony_ci
57388c2ecf20Sopenharmony_ci	if (!vsi->num_txq) {
57398c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "VSI %d has 0 Tx queues\n",
57408c2ecf20Sopenharmony_ci			vsi->vsi_num);
57418c2ecf20Sopenharmony_ci		return -EINVAL;
57428c2ecf20Sopenharmony_ci	}
57438c2ecf20Sopenharmony_ci
57448c2ecf20Sopenharmony_ci	ice_for_each_txq(vsi, i) {
57458c2ecf20Sopenharmony_ci		struct ice_ring *ring = vsi->tx_rings[i];
57468c2ecf20Sopenharmony_ci
57478c2ecf20Sopenharmony_ci		if (!ring)
57488c2ecf20Sopenharmony_ci			return -EINVAL;
57498c2ecf20Sopenharmony_ci
57508c2ecf20Sopenharmony_ci		ring->netdev = vsi->netdev;
57518c2ecf20Sopenharmony_ci		err = ice_setup_tx_ring(ring);
57528c2ecf20Sopenharmony_ci		if (err)
57538c2ecf20Sopenharmony_ci			break;
57548c2ecf20Sopenharmony_ci	}
57558c2ecf20Sopenharmony_ci
57568c2ecf20Sopenharmony_ci	return err;
57578c2ecf20Sopenharmony_ci}
57588c2ecf20Sopenharmony_ci
57598c2ecf20Sopenharmony_ci/**
57608c2ecf20Sopenharmony_ci * ice_vsi_setup_rx_rings - Allocate VSI Rx queue resources
57618c2ecf20Sopenharmony_ci * @vsi: VSI having resources allocated
57628c2ecf20Sopenharmony_ci *
57638c2ecf20Sopenharmony_ci * Return 0 on success, negative on failure
57648c2ecf20Sopenharmony_ci */
57658c2ecf20Sopenharmony_ciint ice_vsi_setup_rx_rings(struct ice_vsi *vsi)
57668c2ecf20Sopenharmony_ci{
57678c2ecf20Sopenharmony_ci	int i, err = 0;
57688c2ecf20Sopenharmony_ci
57698c2ecf20Sopenharmony_ci	if (!vsi->num_rxq) {
57708c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "VSI %d has 0 Rx queues\n",
57718c2ecf20Sopenharmony_ci			vsi->vsi_num);
57728c2ecf20Sopenharmony_ci		return -EINVAL;
57738c2ecf20Sopenharmony_ci	}
57748c2ecf20Sopenharmony_ci
57758c2ecf20Sopenharmony_ci	ice_for_each_rxq(vsi, i) {
57768c2ecf20Sopenharmony_ci		struct ice_ring *ring = vsi->rx_rings[i];
57778c2ecf20Sopenharmony_ci
57788c2ecf20Sopenharmony_ci		if (!ring)
57798c2ecf20Sopenharmony_ci			return -EINVAL;
57808c2ecf20Sopenharmony_ci
57818c2ecf20Sopenharmony_ci		ring->netdev = vsi->netdev;
57828c2ecf20Sopenharmony_ci		err = ice_setup_rx_ring(ring);
57838c2ecf20Sopenharmony_ci		if (err)
57848c2ecf20Sopenharmony_ci			break;
57858c2ecf20Sopenharmony_ci	}
57868c2ecf20Sopenharmony_ci
57878c2ecf20Sopenharmony_ci	return err;
57888c2ecf20Sopenharmony_ci}
57898c2ecf20Sopenharmony_ci
57908c2ecf20Sopenharmony_ci/**
57918c2ecf20Sopenharmony_ci * ice_vsi_open_ctrl - open control VSI for use
57928c2ecf20Sopenharmony_ci * @vsi: the VSI to open
57938c2ecf20Sopenharmony_ci *
57948c2ecf20Sopenharmony_ci * Initialization of the Control VSI
57958c2ecf20Sopenharmony_ci *
57968c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on error
57978c2ecf20Sopenharmony_ci */
57988c2ecf20Sopenharmony_ciint ice_vsi_open_ctrl(struct ice_vsi *vsi)
57998c2ecf20Sopenharmony_ci{
58008c2ecf20Sopenharmony_ci	char int_name[ICE_INT_NAME_STR_LEN];
58018c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
58028c2ecf20Sopenharmony_ci	struct device *dev;
58038c2ecf20Sopenharmony_ci	int err;
58048c2ecf20Sopenharmony_ci
58058c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
58068c2ecf20Sopenharmony_ci	/* allocate descriptors */
58078c2ecf20Sopenharmony_ci	err = ice_vsi_setup_tx_rings(vsi);
58088c2ecf20Sopenharmony_ci	if (err)
58098c2ecf20Sopenharmony_ci		goto err_setup_tx;
58108c2ecf20Sopenharmony_ci
58118c2ecf20Sopenharmony_ci	err = ice_vsi_setup_rx_rings(vsi);
58128c2ecf20Sopenharmony_ci	if (err)
58138c2ecf20Sopenharmony_ci		goto err_setup_rx;
58148c2ecf20Sopenharmony_ci
58158c2ecf20Sopenharmony_ci	err = ice_vsi_cfg(vsi);
58168c2ecf20Sopenharmony_ci	if (err)
58178c2ecf20Sopenharmony_ci		goto err_setup_rx;
58188c2ecf20Sopenharmony_ci
58198c2ecf20Sopenharmony_ci	snprintf(int_name, sizeof(int_name) - 1, "%s-%s:ctrl",
58208c2ecf20Sopenharmony_ci		 dev_driver_string(dev), dev_name(dev));
58218c2ecf20Sopenharmony_ci	err = ice_vsi_req_irq_msix(vsi, int_name);
58228c2ecf20Sopenharmony_ci	if (err)
58238c2ecf20Sopenharmony_ci		goto err_setup_rx;
58248c2ecf20Sopenharmony_ci
58258c2ecf20Sopenharmony_ci	ice_vsi_cfg_msix(vsi);
58268c2ecf20Sopenharmony_ci
58278c2ecf20Sopenharmony_ci	err = ice_vsi_start_all_rx_rings(vsi);
58288c2ecf20Sopenharmony_ci	if (err)
58298c2ecf20Sopenharmony_ci		goto err_up_complete;
58308c2ecf20Sopenharmony_ci
58318c2ecf20Sopenharmony_ci	clear_bit(__ICE_DOWN, vsi->state);
58328c2ecf20Sopenharmony_ci	ice_vsi_ena_irq(vsi);
58338c2ecf20Sopenharmony_ci
58348c2ecf20Sopenharmony_ci	return 0;
58358c2ecf20Sopenharmony_ci
58368c2ecf20Sopenharmony_cierr_up_complete:
58378c2ecf20Sopenharmony_ci	ice_down(vsi);
58388c2ecf20Sopenharmony_cierr_setup_rx:
58398c2ecf20Sopenharmony_ci	ice_vsi_free_rx_rings(vsi);
58408c2ecf20Sopenharmony_cierr_setup_tx:
58418c2ecf20Sopenharmony_ci	ice_vsi_free_tx_rings(vsi);
58428c2ecf20Sopenharmony_ci
58438c2ecf20Sopenharmony_ci	return err;
58448c2ecf20Sopenharmony_ci}
58458c2ecf20Sopenharmony_ci
58468c2ecf20Sopenharmony_ci/**
58478c2ecf20Sopenharmony_ci * ice_vsi_open - Called when a network interface is made active
58488c2ecf20Sopenharmony_ci * @vsi: the VSI to open
58498c2ecf20Sopenharmony_ci *
58508c2ecf20Sopenharmony_ci * Initialization of the VSI
58518c2ecf20Sopenharmony_ci *
58528c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on error
58538c2ecf20Sopenharmony_ci */
58548c2ecf20Sopenharmony_cistatic int ice_vsi_open(struct ice_vsi *vsi)
58558c2ecf20Sopenharmony_ci{
58568c2ecf20Sopenharmony_ci	char int_name[ICE_INT_NAME_STR_LEN];
58578c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
58588c2ecf20Sopenharmony_ci	int err;
58598c2ecf20Sopenharmony_ci
58608c2ecf20Sopenharmony_ci	/* allocate descriptors */
58618c2ecf20Sopenharmony_ci	err = ice_vsi_setup_tx_rings(vsi);
58628c2ecf20Sopenharmony_ci	if (err)
58638c2ecf20Sopenharmony_ci		goto err_setup_tx;
58648c2ecf20Sopenharmony_ci
58658c2ecf20Sopenharmony_ci	err = ice_vsi_setup_rx_rings(vsi);
58668c2ecf20Sopenharmony_ci	if (err)
58678c2ecf20Sopenharmony_ci		goto err_setup_rx;
58688c2ecf20Sopenharmony_ci
58698c2ecf20Sopenharmony_ci	err = ice_vsi_cfg(vsi);
58708c2ecf20Sopenharmony_ci	if (err)
58718c2ecf20Sopenharmony_ci		goto err_setup_rx;
58728c2ecf20Sopenharmony_ci
58738c2ecf20Sopenharmony_ci	snprintf(int_name, sizeof(int_name) - 1, "%s-%s",
58748c2ecf20Sopenharmony_ci		 dev_driver_string(ice_pf_to_dev(pf)), vsi->netdev->name);
58758c2ecf20Sopenharmony_ci	err = ice_vsi_req_irq_msix(vsi, int_name);
58768c2ecf20Sopenharmony_ci	if (err)
58778c2ecf20Sopenharmony_ci		goto err_setup_rx;
58788c2ecf20Sopenharmony_ci
58798c2ecf20Sopenharmony_ci	/* Notify the stack of the actual queue counts. */
58808c2ecf20Sopenharmony_ci	err = netif_set_real_num_tx_queues(vsi->netdev, vsi->num_txq);
58818c2ecf20Sopenharmony_ci	if (err)
58828c2ecf20Sopenharmony_ci		goto err_set_qs;
58838c2ecf20Sopenharmony_ci
58848c2ecf20Sopenharmony_ci	err = netif_set_real_num_rx_queues(vsi->netdev, vsi->num_rxq);
58858c2ecf20Sopenharmony_ci	if (err)
58868c2ecf20Sopenharmony_ci		goto err_set_qs;
58878c2ecf20Sopenharmony_ci
58888c2ecf20Sopenharmony_ci	err = ice_up_complete(vsi);
58898c2ecf20Sopenharmony_ci	if (err)
58908c2ecf20Sopenharmony_ci		goto err_up_complete;
58918c2ecf20Sopenharmony_ci
58928c2ecf20Sopenharmony_ci	return 0;
58938c2ecf20Sopenharmony_ci
58948c2ecf20Sopenharmony_cierr_up_complete:
58958c2ecf20Sopenharmony_ci	ice_down(vsi);
58968c2ecf20Sopenharmony_cierr_set_qs:
58978c2ecf20Sopenharmony_ci	ice_vsi_free_irq(vsi);
58988c2ecf20Sopenharmony_cierr_setup_rx:
58998c2ecf20Sopenharmony_ci	ice_vsi_free_rx_rings(vsi);
59008c2ecf20Sopenharmony_cierr_setup_tx:
59018c2ecf20Sopenharmony_ci	ice_vsi_free_tx_rings(vsi);
59028c2ecf20Sopenharmony_ci
59038c2ecf20Sopenharmony_ci	return err;
59048c2ecf20Sopenharmony_ci}
59058c2ecf20Sopenharmony_ci
59068c2ecf20Sopenharmony_ci/**
59078c2ecf20Sopenharmony_ci * ice_vsi_release_all - Delete all VSIs
59088c2ecf20Sopenharmony_ci * @pf: PF from which all VSIs are being removed
59098c2ecf20Sopenharmony_ci */
59108c2ecf20Sopenharmony_cistatic void ice_vsi_release_all(struct ice_pf *pf)
59118c2ecf20Sopenharmony_ci{
59128c2ecf20Sopenharmony_ci	int err, i;
59138c2ecf20Sopenharmony_ci
59148c2ecf20Sopenharmony_ci	if (!pf->vsi)
59158c2ecf20Sopenharmony_ci		return;
59168c2ecf20Sopenharmony_ci
59178c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, i) {
59188c2ecf20Sopenharmony_ci		if (!pf->vsi[i])
59198c2ecf20Sopenharmony_ci			continue;
59208c2ecf20Sopenharmony_ci
59218c2ecf20Sopenharmony_ci		err = ice_vsi_release(pf->vsi[i]);
59228c2ecf20Sopenharmony_ci		if (err)
59238c2ecf20Sopenharmony_ci			dev_dbg(ice_pf_to_dev(pf), "Failed to release pf->vsi[%d], err %d, vsi_num = %d\n",
59248c2ecf20Sopenharmony_ci				i, err, pf->vsi[i]->vsi_num);
59258c2ecf20Sopenharmony_ci	}
59268c2ecf20Sopenharmony_ci}
59278c2ecf20Sopenharmony_ci
59288c2ecf20Sopenharmony_ci/**
59298c2ecf20Sopenharmony_ci * ice_vsi_rebuild_by_type - Rebuild VSI of a given type
59308c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
59318c2ecf20Sopenharmony_ci * @type: VSI type to rebuild
59328c2ecf20Sopenharmony_ci *
59338c2ecf20Sopenharmony_ci * Iterates through the pf->vsi array and rebuilds VSIs of the requested type
59348c2ecf20Sopenharmony_ci */
59358c2ecf20Sopenharmony_cistatic int ice_vsi_rebuild_by_type(struct ice_pf *pf, enum ice_vsi_type type)
59368c2ecf20Sopenharmony_ci{
59378c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
59388c2ecf20Sopenharmony_ci	enum ice_status status;
59398c2ecf20Sopenharmony_ci	int i, err;
59408c2ecf20Sopenharmony_ci
59418c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, i) {
59428c2ecf20Sopenharmony_ci		struct ice_vsi *vsi = pf->vsi[i];
59438c2ecf20Sopenharmony_ci
59448c2ecf20Sopenharmony_ci		if (!vsi || vsi->type != type)
59458c2ecf20Sopenharmony_ci			continue;
59468c2ecf20Sopenharmony_ci
59478c2ecf20Sopenharmony_ci		/* rebuild the VSI */
59488c2ecf20Sopenharmony_ci		err = ice_vsi_rebuild(vsi, true);
59498c2ecf20Sopenharmony_ci		if (err) {
59508c2ecf20Sopenharmony_ci			dev_err(dev, "rebuild VSI failed, err %d, VSI index %d, type %s\n",
59518c2ecf20Sopenharmony_ci				err, vsi->idx, ice_vsi_type_str(type));
59528c2ecf20Sopenharmony_ci			return err;
59538c2ecf20Sopenharmony_ci		}
59548c2ecf20Sopenharmony_ci
59558c2ecf20Sopenharmony_ci		/* replay filters for the VSI */
59568c2ecf20Sopenharmony_ci		status = ice_replay_vsi(&pf->hw, vsi->idx);
59578c2ecf20Sopenharmony_ci		if (status) {
59588c2ecf20Sopenharmony_ci			dev_err(dev, "replay VSI failed, status %s, VSI index %d, type %s\n",
59598c2ecf20Sopenharmony_ci				ice_stat_str(status), vsi->idx,
59608c2ecf20Sopenharmony_ci				ice_vsi_type_str(type));
59618c2ecf20Sopenharmony_ci			return -EIO;
59628c2ecf20Sopenharmony_ci		}
59638c2ecf20Sopenharmony_ci
59648c2ecf20Sopenharmony_ci		/* Re-map HW VSI number, using VSI handle that has been
59658c2ecf20Sopenharmony_ci		 * previously validated in ice_replay_vsi() call above
59668c2ecf20Sopenharmony_ci		 */
59678c2ecf20Sopenharmony_ci		vsi->vsi_num = ice_get_hw_vsi_num(&pf->hw, vsi->idx);
59688c2ecf20Sopenharmony_ci
59698c2ecf20Sopenharmony_ci		/* enable the VSI */
59708c2ecf20Sopenharmony_ci		err = ice_ena_vsi(vsi, false);
59718c2ecf20Sopenharmony_ci		if (err) {
59728c2ecf20Sopenharmony_ci			dev_err(dev, "enable VSI failed, err %d, VSI index %d, type %s\n",
59738c2ecf20Sopenharmony_ci				err, vsi->idx, ice_vsi_type_str(type));
59748c2ecf20Sopenharmony_ci			return err;
59758c2ecf20Sopenharmony_ci		}
59768c2ecf20Sopenharmony_ci
59778c2ecf20Sopenharmony_ci		dev_info(dev, "VSI rebuilt. VSI index %d, type %s\n", vsi->idx,
59788c2ecf20Sopenharmony_ci			 ice_vsi_type_str(type));
59798c2ecf20Sopenharmony_ci	}
59808c2ecf20Sopenharmony_ci
59818c2ecf20Sopenharmony_ci	return 0;
59828c2ecf20Sopenharmony_ci}
59838c2ecf20Sopenharmony_ci
59848c2ecf20Sopenharmony_ci/**
59858c2ecf20Sopenharmony_ci * ice_update_pf_netdev_link - Update PF netdev link status
59868c2ecf20Sopenharmony_ci * @pf: pointer to the PF instance
59878c2ecf20Sopenharmony_ci */
59888c2ecf20Sopenharmony_cistatic void ice_update_pf_netdev_link(struct ice_pf *pf)
59898c2ecf20Sopenharmony_ci{
59908c2ecf20Sopenharmony_ci	bool link_up;
59918c2ecf20Sopenharmony_ci	int i;
59928c2ecf20Sopenharmony_ci
59938c2ecf20Sopenharmony_ci	ice_for_each_vsi(pf, i) {
59948c2ecf20Sopenharmony_ci		struct ice_vsi *vsi = pf->vsi[i];
59958c2ecf20Sopenharmony_ci
59968c2ecf20Sopenharmony_ci		if (!vsi || vsi->type != ICE_VSI_PF)
59978c2ecf20Sopenharmony_ci			return;
59988c2ecf20Sopenharmony_ci
59998c2ecf20Sopenharmony_ci		ice_get_link_status(pf->vsi[i]->port_info, &link_up);
60008c2ecf20Sopenharmony_ci		if (link_up) {
60018c2ecf20Sopenharmony_ci			netif_carrier_on(pf->vsi[i]->netdev);
60028c2ecf20Sopenharmony_ci			netif_tx_wake_all_queues(pf->vsi[i]->netdev);
60038c2ecf20Sopenharmony_ci		} else {
60048c2ecf20Sopenharmony_ci			netif_carrier_off(pf->vsi[i]->netdev);
60058c2ecf20Sopenharmony_ci			netif_tx_stop_all_queues(pf->vsi[i]->netdev);
60068c2ecf20Sopenharmony_ci		}
60078c2ecf20Sopenharmony_ci	}
60088c2ecf20Sopenharmony_ci}
60098c2ecf20Sopenharmony_ci
60108c2ecf20Sopenharmony_ci/**
60118c2ecf20Sopenharmony_ci * ice_rebuild - rebuild after reset
60128c2ecf20Sopenharmony_ci * @pf: PF to rebuild
60138c2ecf20Sopenharmony_ci * @reset_type: type of reset
60148c2ecf20Sopenharmony_ci *
60158c2ecf20Sopenharmony_ci * Do not rebuild VF VSI in this flow because that is already handled via
60168c2ecf20Sopenharmony_ci * ice_reset_all_vfs(). This is because requirements for resetting a VF after a
60178c2ecf20Sopenharmony_ci * PFR/CORER/GLOBER/etc. are different than the normal flow. Also, we don't want
60188c2ecf20Sopenharmony_ci * to reset/rebuild all the VF VSI twice.
60198c2ecf20Sopenharmony_ci */
60208c2ecf20Sopenharmony_cistatic void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
60218c2ecf20Sopenharmony_ci{
60228c2ecf20Sopenharmony_ci	struct device *dev = ice_pf_to_dev(pf);
60238c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
60248c2ecf20Sopenharmony_ci	enum ice_status ret;
60258c2ecf20Sopenharmony_ci	int err;
60268c2ecf20Sopenharmony_ci
60278c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, pf->state))
60288c2ecf20Sopenharmony_ci		goto clear_recovery;
60298c2ecf20Sopenharmony_ci
60308c2ecf20Sopenharmony_ci	dev_dbg(dev, "rebuilding PF after reset_type=%d\n", reset_type);
60318c2ecf20Sopenharmony_ci
60328c2ecf20Sopenharmony_ci	ret = ice_init_all_ctrlq(hw);
60338c2ecf20Sopenharmony_ci	if (ret) {
60348c2ecf20Sopenharmony_ci		dev_err(dev, "control queues init failed %s\n",
60358c2ecf20Sopenharmony_ci			ice_stat_str(ret));
60368c2ecf20Sopenharmony_ci		goto err_init_ctrlq;
60378c2ecf20Sopenharmony_ci	}
60388c2ecf20Sopenharmony_ci
60398c2ecf20Sopenharmony_ci	/* if DDP was previously loaded successfully */
60408c2ecf20Sopenharmony_ci	if (!ice_is_safe_mode(pf)) {
60418c2ecf20Sopenharmony_ci		/* reload the SW DB of filter tables */
60428c2ecf20Sopenharmony_ci		if (reset_type == ICE_RESET_PFR)
60438c2ecf20Sopenharmony_ci			ice_fill_blk_tbls(hw);
60448c2ecf20Sopenharmony_ci		else
60458c2ecf20Sopenharmony_ci			/* Reload DDP Package after CORER/GLOBR reset */
60468c2ecf20Sopenharmony_ci			ice_load_pkg(NULL, pf);
60478c2ecf20Sopenharmony_ci	}
60488c2ecf20Sopenharmony_ci
60498c2ecf20Sopenharmony_ci	ret = ice_clear_pf_cfg(hw);
60508c2ecf20Sopenharmony_ci	if (ret) {
60518c2ecf20Sopenharmony_ci		dev_err(dev, "clear PF configuration failed %s\n",
60528c2ecf20Sopenharmony_ci			ice_stat_str(ret));
60538c2ecf20Sopenharmony_ci		goto err_init_ctrlq;
60548c2ecf20Sopenharmony_ci	}
60558c2ecf20Sopenharmony_ci
60568c2ecf20Sopenharmony_ci	if (pf->first_sw->dflt_vsi_ena)
60578c2ecf20Sopenharmony_ci		dev_info(dev, "Clearing default VSI, re-enable after reset completes\n");
60588c2ecf20Sopenharmony_ci	/* clear the default VSI configuration if it exists */
60598c2ecf20Sopenharmony_ci	pf->first_sw->dflt_vsi = NULL;
60608c2ecf20Sopenharmony_ci	pf->first_sw->dflt_vsi_ena = false;
60618c2ecf20Sopenharmony_ci
60628c2ecf20Sopenharmony_ci	ice_clear_pxe_mode(hw);
60638c2ecf20Sopenharmony_ci
60648c2ecf20Sopenharmony_ci	ret = ice_get_caps(hw);
60658c2ecf20Sopenharmony_ci	if (ret) {
60668c2ecf20Sopenharmony_ci		dev_err(dev, "ice_get_caps failed %s\n", ice_stat_str(ret));
60678c2ecf20Sopenharmony_ci		goto err_init_ctrlq;
60688c2ecf20Sopenharmony_ci	}
60698c2ecf20Sopenharmony_ci
60708c2ecf20Sopenharmony_ci	ret = ice_aq_set_mac_cfg(hw, ICE_AQ_SET_MAC_FRAME_SIZE_MAX, NULL);
60718c2ecf20Sopenharmony_ci	if (ret) {
60728c2ecf20Sopenharmony_ci		dev_err(dev, "set_mac_cfg failed %s\n", ice_stat_str(ret));
60738c2ecf20Sopenharmony_ci		goto err_init_ctrlq;
60748c2ecf20Sopenharmony_ci	}
60758c2ecf20Sopenharmony_ci
60768c2ecf20Sopenharmony_ci	err = ice_sched_init_port(hw->port_info);
60778c2ecf20Sopenharmony_ci	if (err)
60788c2ecf20Sopenharmony_ci		goto err_sched_init_port;
60798c2ecf20Sopenharmony_ci
60808c2ecf20Sopenharmony_ci	/* start misc vector */
60818c2ecf20Sopenharmony_ci	err = ice_req_irq_msix_misc(pf);
60828c2ecf20Sopenharmony_ci	if (err) {
60838c2ecf20Sopenharmony_ci		dev_err(dev, "misc vector setup failed: %d\n", err);
60848c2ecf20Sopenharmony_ci		goto err_sched_init_port;
60858c2ecf20Sopenharmony_ci	}
60868c2ecf20Sopenharmony_ci
60878c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {
60888c2ecf20Sopenharmony_ci		wr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M);
60898c2ecf20Sopenharmony_ci		if (!rd32(hw, PFQF_FD_SIZE)) {
60908c2ecf20Sopenharmony_ci			u16 unused, guar, b_effort;
60918c2ecf20Sopenharmony_ci
60928c2ecf20Sopenharmony_ci			guar = hw->func_caps.fd_fltr_guar;
60938c2ecf20Sopenharmony_ci			b_effort = hw->func_caps.fd_fltr_best_effort;
60948c2ecf20Sopenharmony_ci
60958c2ecf20Sopenharmony_ci			/* force guaranteed filter pool for PF */
60968c2ecf20Sopenharmony_ci			ice_alloc_fd_guar_item(hw, &unused, guar);
60978c2ecf20Sopenharmony_ci			/* force shared filter pool for PF */
60988c2ecf20Sopenharmony_ci			ice_alloc_fd_shrd_item(hw, &unused, b_effort);
60998c2ecf20Sopenharmony_ci		}
61008c2ecf20Sopenharmony_ci	}
61018c2ecf20Sopenharmony_ci
61028c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
61038c2ecf20Sopenharmony_ci		ice_dcb_rebuild(pf);
61048c2ecf20Sopenharmony_ci
61058c2ecf20Sopenharmony_ci	/* rebuild PF VSI */
61068c2ecf20Sopenharmony_ci	err = ice_vsi_rebuild_by_type(pf, ICE_VSI_PF);
61078c2ecf20Sopenharmony_ci	if (err) {
61088c2ecf20Sopenharmony_ci		dev_err(dev, "PF VSI rebuild failed: %d\n", err);
61098c2ecf20Sopenharmony_ci		goto err_vsi_rebuild;
61108c2ecf20Sopenharmony_ci	}
61118c2ecf20Sopenharmony_ci
61128c2ecf20Sopenharmony_ci	/* If Flow Director is active */
61138c2ecf20Sopenharmony_ci	if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {
61148c2ecf20Sopenharmony_ci		err = ice_vsi_rebuild_by_type(pf, ICE_VSI_CTRL);
61158c2ecf20Sopenharmony_ci		if (err) {
61168c2ecf20Sopenharmony_ci			dev_err(dev, "control VSI rebuild failed: %d\n", err);
61178c2ecf20Sopenharmony_ci			goto err_vsi_rebuild;
61188c2ecf20Sopenharmony_ci		}
61198c2ecf20Sopenharmony_ci
61208c2ecf20Sopenharmony_ci		/* replay HW Flow Director recipes */
61218c2ecf20Sopenharmony_ci		if (hw->fdir_prof)
61228c2ecf20Sopenharmony_ci			ice_fdir_replay_flows(hw);
61238c2ecf20Sopenharmony_ci
61248c2ecf20Sopenharmony_ci		/* replay Flow Director filters */
61258c2ecf20Sopenharmony_ci		ice_fdir_replay_fltrs(pf);
61268c2ecf20Sopenharmony_ci
61278c2ecf20Sopenharmony_ci		ice_rebuild_arfs(pf);
61288c2ecf20Sopenharmony_ci	}
61298c2ecf20Sopenharmony_ci
61308c2ecf20Sopenharmony_ci	ice_update_pf_netdev_link(pf);
61318c2ecf20Sopenharmony_ci
61328c2ecf20Sopenharmony_ci	/* tell the firmware we are up */
61338c2ecf20Sopenharmony_ci	ret = ice_send_version(pf);
61348c2ecf20Sopenharmony_ci	if (ret) {
61358c2ecf20Sopenharmony_ci		dev_err(dev, "Rebuild failed due to error sending driver version: %s\n",
61368c2ecf20Sopenharmony_ci			ice_stat_str(ret));
61378c2ecf20Sopenharmony_ci		goto err_vsi_rebuild;
61388c2ecf20Sopenharmony_ci	}
61398c2ecf20Sopenharmony_ci
61408c2ecf20Sopenharmony_ci	ice_replay_post(hw);
61418c2ecf20Sopenharmony_ci
61428c2ecf20Sopenharmony_ci	/* if we get here, reset flow is successful */
61438c2ecf20Sopenharmony_ci	clear_bit(__ICE_RESET_FAILED, pf->state);
61448c2ecf20Sopenharmony_ci	return;
61458c2ecf20Sopenharmony_ci
61468c2ecf20Sopenharmony_cierr_vsi_rebuild:
61478c2ecf20Sopenharmony_cierr_sched_init_port:
61488c2ecf20Sopenharmony_ci	ice_sched_cleanup_all(hw);
61498c2ecf20Sopenharmony_cierr_init_ctrlq:
61508c2ecf20Sopenharmony_ci	ice_shutdown_all_ctrlq(hw);
61518c2ecf20Sopenharmony_ci	set_bit(__ICE_RESET_FAILED, pf->state);
61528c2ecf20Sopenharmony_ciclear_recovery:
61538c2ecf20Sopenharmony_ci	/* set this bit in PF state to control service task scheduling */
61548c2ecf20Sopenharmony_ci	set_bit(__ICE_NEEDS_RESTART, pf->state);
61558c2ecf20Sopenharmony_ci	dev_err(dev, "Rebuild failed, unload and reload driver\n");
61568c2ecf20Sopenharmony_ci}
61578c2ecf20Sopenharmony_ci
61588c2ecf20Sopenharmony_ci/**
61598c2ecf20Sopenharmony_ci * ice_max_xdp_frame_size - returns the maximum allowed frame size for XDP
61608c2ecf20Sopenharmony_ci * @vsi: Pointer to VSI structure
61618c2ecf20Sopenharmony_ci */
61628c2ecf20Sopenharmony_cistatic int ice_max_xdp_frame_size(struct ice_vsi *vsi)
61638c2ecf20Sopenharmony_ci{
61648c2ecf20Sopenharmony_ci	if (PAGE_SIZE >= 8192 || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags))
61658c2ecf20Sopenharmony_ci		return ICE_RXBUF_2048 - XDP_PACKET_HEADROOM;
61668c2ecf20Sopenharmony_ci	else
61678c2ecf20Sopenharmony_ci		return ICE_RXBUF_3072;
61688c2ecf20Sopenharmony_ci}
61698c2ecf20Sopenharmony_ci
61708c2ecf20Sopenharmony_ci/**
61718c2ecf20Sopenharmony_ci * ice_change_mtu - NDO callback to change the MTU
61728c2ecf20Sopenharmony_ci * @netdev: network interface device structure
61738c2ecf20Sopenharmony_ci * @new_mtu: new value for maximum frame size
61748c2ecf20Sopenharmony_ci *
61758c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
61768c2ecf20Sopenharmony_ci */
61778c2ecf20Sopenharmony_cistatic int ice_change_mtu(struct net_device *netdev, int new_mtu)
61788c2ecf20Sopenharmony_ci{
61798c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
61808c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
61818c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
61828c2ecf20Sopenharmony_ci	u8 count = 0;
61838c2ecf20Sopenharmony_ci
61848c2ecf20Sopenharmony_ci	if (new_mtu == (int)netdev->mtu) {
61858c2ecf20Sopenharmony_ci		netdev_warn(netdev, "MTU is already %u\n", netdev->mtu);
61868c2ecf20Sopenharmony_ci		return 0;
61878c2ecf20Sopenharmony_ci	}
61888c2ecf20Sopenharmony_ci
61898c2ecf20Sopenharmony_ci	if (ice_is_xdp_ena_vsi(vsi)) {
61908c2ecf20Sopenharmony_ci		int frame_size = ice_max_xdp_frame_size(vsi);
61918c2ecf20Sopenharmony_ci
61928c2ecf20Sopenharmony_ci		if (new_mtu + ICE_ETH_PKT_HDR_PAD > frame_size) {
61938c2ecf20Sopenharmony_ci			netdev_err(netdev, "max MTU for XDP usage is %d\n",
61948c2ecf20Sopenharmony_ci				   frame_size - ICE_ETH_PKT_HDR_PAD);
61958c2ecf20Sopenharmony_ci			return -EINVAL;
61968c2ecf20Sopenharmony_ci		}
61978c2ecf20Sopenharmony_ci	}
61988c2ecf20Sopenharmony_ci
61998c2ecf20Sopenharmony_ci	if (new_mtu < (int)netdev->min_mtu) {
62008c2ecf20Sopenharmony_ci		netdev_err(netdev, "new MTU invalid. min_mtu is %d\n",
62018c2ecf20Sopenharmony_ci			   netdev->min_mtu);
62028c2ecf20Sopenharmony_ci		return -EINVAL;
62038c2ecf20Sopenharmony_ci	} else if (new_mtu > (int)netdev->max_mtu) {
62048c2ecf20Sopenharmony_ci		netdev_err(netdev, "new MTU invalid. max_mtu is %d\n",
62058c2ecf20Sopenharmony_ci			   netdev->min_mtu);
62068c2ecf20Sopenharmony_ci		return -EINVAL;
62078c2ecf20Sopenharmony_ci	}
62088c2ecf20Sopenharmony_ci	/* if a reset is in progress, wait for some time for it to complete */
62098c2ecf20Sopenharmony_ci	do {
62108c2ecf20Sopenharmony_ci		if (ice_is_reset_in_progress(pf->state)) {
62118c2ecf20Sopenharmony_ci			count++;
62128c2ecf20Sopenharmony_ci			usleep_range(1000, 2000);
62138c2ecf20Sopenharmony_ci		} else {
62148c2ecf20Sopenharmony_ci			break;
62158c2ecf20Sopenharmony_ci		}
62168c2ecf20Sopenharmony_ci
62178c2ecf20Sopenharmony_ci	} while (count < 100);
62188c2ecf20Sopenharmony_ci
62198c2ecf20Sopenharmony_ci	if (count == 100) {
62208c2ecf20Sopenharmony_ci		netdev_err(netdev, "can't change MTU. Device is busy\n");
62218c2ecf20Sopenharmony_ci		return -EBUSY;
62228c2ecf20Sopenharmony_ci	}
62238c2ecf20Sopenharmony_ci
62248c2ecf20Sopenharmony_ci	netdev->mtu = (unsigned int)new_mtu;
62258c2ecf20Sopenharmony_ci
62268c2ecf20Sopenharmony_ci	/* if VSI is up, bring it down and then back up */
62278c2ecf20Sopenharmony_ci	if (!test_and_set_bit(__ICE_DOWN, vsi->state)) {
62288c2ecf20Sopenharmony_ci		int err;
62298c2ecf20Sopenharmony_ci
62308c2ecf20Sopenharmony_ci		err = ice_down(vsi);
62318c2ecf20Sopenharmony_ci		if (err) {
62328c2ecf20Sopenharmony_ci			netdev_err(netdev, "change MTU if_up err %d\n", err);
62338c2ecf20Sopenharmony_ci			return err;
62348c2ecf20Sopenharmony_ci		}
62358c2ecf20Sopenharmony_ci
62368c2ecf20Sopenharmony_ci		err = ice_up(vsi);
62378c2ecf20Sopenharmony_ci		if (err) {
62388c2ecf20Sopenharmony_ci			netdev_err(netdev, "change MTU if_up err %d\n", err);
62398c2ecf20Sopenharmony_ci			return err;
62408c2ecf20Sopenharmony_ci		}
62418c2ecf20Sopenharmony_ci	}
62428c2ecf20Sopenharmony_ci
62438c2ecf20Sopenharmony_ci	netdev_dbg(netdev, "changed MTU to %d\n", new_mtu);
62448c2ecf20Sopenharmony_ci	return 0;
62458c2ecf20Sopenharmony_ci}
62468c2ecf20Sopenharmony_ci
62478c2ecf20Sopenharmony_ci/**
62488c2ecf20Sopenharmony_ci * ice_aq_str - convert AQ err code to a string
62498c2ecf20Sopenharmony_ci * @aq_err: the AQ error code to convert
62508c2ecf20Sopenharmony_ci */
62518c2ecf20Sopenharmony_ciconst char *ice_aq_str(enum ice_aq_err aq_err)
62528c2ecf20Sopenharmony_ci{
62538c2ecf20Sopenharmony_ci	switch (aq_err) {
62548c2ecf20Sopenharmony_ci	case ICE_AQ_RC_OK:
62558c2ecf20Sopenharmony_ci		return "OK";
62568c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EPERM:
62578c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EPERM";
62588c2ecf20Sopenharmony_ci	case ICE_AQ_RC_ENOENT:
62598c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_ENOENT";
62608c2ecf20Sopenharmony_ci	case ICE_AQ_RC_ENOMEM:
62618c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_ENOMEM";
62628c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EBUSY:
62638c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EBUSY";
62648c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EEXIST:
62658c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EEXIST";
62668c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EINVAL:
62678c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EINVAL";
62688c2ecf20Sopenharmony_ci	case ICE_AQ_RC_ENOSPC:
62698c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_ENOSPC";
62708c2ecf20Sopenharmony_ci	case ICE_AQ_RC_ENOSYS:
62718c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_ENOSYS";
62728c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EMODE:
62738c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EMODE";
62748c2ecf20Sopenharmony_ci	case ICE_AQ_RC_ENOSEC:
62758c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_ENOSEC";
62768c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EBADSIG:
62778c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EBADSIG";
62788c2ecf20Sopenharmony_ci	case ICE_AQ_RC_ESVN:
62798c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_ESVN";
62808c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EBADMAN:
62818c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EBADMAN";
62828c2ecf20Sopenharmony_ci	case ICE_AQ_RC_EBADBUF:
62838c2ecf20Sopenharmony_ci		return "ICE_AQ_RC_EBADBUF";
62848c2ecf20Sopenharmony_ci	}
62858c2ecf20Sopenharmony_ci
62868c2ecf20Sopenharmony_ci	return "ICE_AQ_RC_UNKNOWN";
62878c2ecf20Sopenharmony_ci}
62888c2ecf20Sopenharmony_ci
62898c2ecf20Sopenharmony_ci/**
62908c2ecf20Sopenharmony_ci * ice_stat_str - convert status err code to a string
62918c2ecf20Sopenharmony_ci * @stat_err: the status error code to convert
62928c2ecf20Sopenharmony_ci */
62938c2ecf20Sopenharmony_ciconst char *ice_stat_str(enum ice_status stat_err)
62948c2ecf20Sopenharmony_ci{
62958c2ecf20Sopenharmony_ci	switch (stat_err) {
62968c2ecf20Sopenharmony_ci	case ICE_SUCCESS:
62978c2ecf20Sopenharmony_ci		return "OK";
62988c2ecf20Sopenharmony_ci	case ICE_ERR_PARAM:
62998c2ecf20Sopenharmony_ci		return "ICE_ERR_PARAM";
63008c2ecf20Sopenharmony_ci	case ICE_ERR_NOT_IMPL:
63018c2ecf20Sopenharmony_ci		return "ICE_ERR_NOT_IMPL";
63028c2ecf20Sopenharmony_ci	case ICE_ERR_NOT_READY:
63038c2ecf20Sopenharmony_ci		return "ICE_ERR_NOT_READY";
63048c2ecf20Sopenharmony_ci	case ICE_ERR_NOT_SUPPORTED:
63058c2ecf20Sopenharmony_ci		return "ICE_ERR_NOT_SUPPORTED";
63068c2ecf20Sopenharmony_ci	case ICE_ERR_BAD_PTR:
63078c2ecf20Sopenharmony_ci		return "ICE_ERR_BAD_PTR";
63088c2ecf20Sopenharmony_ci	case ICE_ERR_INVAL_SIZE:
63098c2ecf20Sopenharmony_ci		return "ICE_ERR_INVAL_SIZE";
63108c2ecf20Sopenharmony_ci	case ICE_ERR_DEVICE_NOT_SUPPORTED:
63118c2ecf20Sopenharmony_ci		return "ICE_ERR_DEVICE_NOT_SUPPORTED";
63128c2ecf20Sopenharmony_ci	case ICE_ERR_RESET_FAILED:
63138c2ecf20Sopenharmony_ci		return "ICE_ERR_RESET_FAILED";
63148c2ecf20Sopenharmony_ci	case ICE_ERR_FW_API_VER:
63158c2ecf20Sopenharmony_ci		return "ICE_ERR_FW_API_VER";
63168c2ecf20Sopenharmony_ci	case ICE_ERR_NO_MEMORY:
63178c2ecf20Sopenharmony_ci		return "ICE_ERR_NO_MEMORY";
63188c2ecf20Sopenharmony_ci	case ICE_ERR_CFG:
63198c2ecf20Sopenharmony_ci		return "ICE_ERR_CFG";
63208c2ecf20Sopenharmony_ci	case ICE_ERR_OUT_OF_RANGE:
63218c2ecf20Sopenharmony_ci		return "ICE_ERR_OUT_OF_RANGE";
63228c2ecf20Sopenharmony_ci	case ICE_ERR_ALREADY_EXISTS:
63238c2ecf20Sopenharmony_ci		return "ICE_ERR_ALREADY_EXISTS";
63248c2ecf20Sopenharmony_ci	case ICE_ERR_NVM_CHECKSUM:
63258c2ecf20Sopenharmony_ci		return "ICE_ERR_NVM_CHECKSUM";
63268c2ecf20Sopenharmony_ci	case ICE_ERR_BUF_TOO_SHORT:
63278c2ecf20Sopenharmony_ci		return "ICE_ERR_BUF_TOO_SHORT";
63288c2ecf20Sopenharmony_ci	case ICE_ERR_NVM_BLANK_MODE:
63298c2ecf20Sopenharmony_ci		return "ICE_ERR_NVM_BLANK_MODE";
63308c2ecf20Sopenharmony_ci	case ICE_ERR_IN_USE:
63318c2ecf20Sopenharmony_ci		return "ICE_ERR_IN_USE";
63328c2ecf20Sopenharmony_ci	case ICE_ERR_MAX_LIMIT:
63338c2ecf20Sopenharmony_ci		return "ICE_ERR_MAX_LIMIT";
63348c2ecf20Sopenharmony_ci	case ICE_ERR_RESET_ONGOING:
63358c2ecf20Sopenharmony_ci		return "ICE_ERR_RESET_ONGOING";
63368c2ecf20Sopenharmony_ci	case ICE_ERR_HW_TABLE:
63378c2ecf20Sopenharmony_ci		return "ICE_ERR_HW_TABLE";
63388c2ecf20Sopenharmony_ci	case ICE_ERR_DOES_NOT_EXIST:
63398c2ecf20Sopenharmony_ci		return "ICE_ERR_DOES_NOT_EXIST";
63408c2ecf20Sopenharmony_ci	case ICE_ERR_FW_DDP_MISMATCH:
63418c2ecf20Sopenharmony_ci		return "ICE_ERR_FW_DDP_MISMATCH";
63428c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_ERROR:
63438c2ecf20Sopenharmony_ci		return "ICE_ERR_AQ_ERROR";
63448c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_TIMEOUT:
63458c2ecf20Sopenharmony_ci		return "ICE_ERR_AQ_TIMEOUT";
63468c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_FULL:
63478c2ecf20Sopenharmony_ci		return "ICE_ERR_AQ_FULL";
63488c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_NO_WORK:
63498c2ecf20Sopenharmony_ci		return "ICE_ERR_AQ_NO_WORK";
63508c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_EMPTY:
63518c2ecf20Sopenharmony_ci		return "ICE_ERR_AQ_EMPTY";
63528c2ecf20Sopenharmony_ci	case ICE_ERR_AQ_FW_CRITICAL:
63538c2ecf20Sopenharmony_ci		return "ICE_ERR_AQ_FW_CRITICAL";
63548c2ecf20Sopenharmony_ci	}
63558c2ecf20Sopenharmony_ci
63568c2ecf20Sopenharmony_ci	return "ICE_ERR_UNKNOWN";
63578c2ecf20Sopenharmony_ci}
63588c2ecf20Sopenharmony_ci
63598c2ecf20Sopenharmony_ci/**
63608c2ecf20Sopenharmony_ci * ice_set_rss - Set RSS keys and lut
63618c2ecf20Sopenharmony_ci * @vsi: Pointer to VSI structure
63628c2ecf20Sopenharmony_ci * @seed: RSS hash seed
63638c2ecf20Sopenharmony_ci * @lut: Lookup table
63648c2ecf20Sopenharmony_ci * @lut_size: Lookup table size
63658c2ecf20Sopenharmony_ci *
63668c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
63678c2ecf20Sopenharmony_ci */
63688c2ecf20Sopenharmony_ciint ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
63698c2ecf20Sopenharmony_ci{
63708c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
63718c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
63728c2ecf20Sopenharmony_ci	enum ice_status status;
63738c2ecf20Sopenharmony_ci	struct device *dev;
63748c2ecf20Sopenharmony_ci
63758c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
63768c2ecf20Sopenharmony_ci	if (seed) {
63778c2ecf20Sopenharmony_ci		struct ice_aqc_get_set_rss_keys *buf =
63788c2ecf20Sopenharmony_ci				  (struct ice_aqc_get_set_rss_keys *)seed;
63798c2ecf20Sopenharmony_ci
63808c2ecf20Sopenharmony_ci		status = ice_aq_set_rss_key(hw, vsi->idx, buf);
63818c2ecf20Sopenharmony_ci
63828c2ecf20Sopenharmony_ci		if (status) {
63838c2ecf20Sopenharmony_ci			dev_err(dev, "Cannot set RSS key, err %s aq_err %s\n",
63848c2ecf20Sopenharmony_ci				ice_stat_str(status),
63858c2ecf20Sopenharmony_ci				ice_aq_str(hw->adminq.sq_last_status));
63868c2ecf20Sopenharmony_ci			return -EIO;
63878c2ecf20Sopenharmony_ci		}
63888c2ecf20Sopenharmony_ci	}
63898c2ecf20Sopenharmony_ci
63908c2ecf20Sopenharmony_ci	if (lut) {
63918c2ecf20Sopenharmony_ci		status = ice_aq_set_rss_lut(hw, vsi->idx, vsi->rss_lut_type,
63928c2ecf20Sopenharmony_ci					    lut, lut_size);
63938c2ecf20Sopenharmony_ci		if (status) {
63948c2ecf20Sopenharmony_ci			dev_err(dev, "Cannot set RSS lut, err %s aq_err %s\n",
63958c2ecf20Sopenharmony_ci				ice_stat_str(status),
63968c2ecf20Sopenharmony_ci				ice_aq_str(hw->adminq.sq_last_status));
63978c2ecf20Sopenharmony_ci			return -EIO;
63988c2ecf20Sopenharmony_ci		}
63998c2ecf20Sopenharmony_ci	}
64008c2ecf20Sopenharmony_ci
64018c2ecf20Sopenharmony_ci	return 0;
64028c2ecf20Sopenharmony_ci}
64038c2ecf20Sopenharmony_ci
64048c2ecf20Sopenharmony_ci/**
64058c2ecf20Sopenharmony_ci * ice_get_rss - Get RSS keys and lut
64068c2ecf20Sopenharmony_ci * @vsi: Pointer to VSI structure
64078c2ecf20Sopenharmony_ci * @seed: Buffer to store the keys
64088c2ecf20Sopenharmony_ci * @lut: Buffer to store the lookup table entries
64098c2ecf20Sopenharmony_ci * @lut_size: Size of buffer to store the lookup table entries
64108c2ecf20Sopenharmony_ci *
64118c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
64128c2ecf20Sopenharmony_ci */
64138c2ecf20Sopenharmony_ciint ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size)
64148c2ecf20Sopenharmony_ci{
64158c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
64168c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
64178c2ecf20Sopenharmony_ci	enum ice_status status;
64188c2ecf20Sopenharmony_ci	struct device *dev;
64198c2ecf20Sopenharmony_ci
64208c2ecf20Sopenharmony_ci	dev = ice_pf_to_dev(pf);
64218c2ecf20Sopenharmony_ci	if (seed) {
64228c2ecf20Sopenharmony_ci		struct ice_aqc_get_set_rss_keys *buf =
64238c2ecf20Sopenharmony_ci				  (struct ice_aqc_get_set_rss_keys *)seed;
64248c2ecf20Sopenharmony_ci
64258c2ecf20Sopenharmony_ci		status = ice_aq_get_rss_key(hw, vsi->idx, buf);
64268c2ecf20Sopenharmony_ci		if (status) {
64278c2ecf20Sopenharmony_ci			dev_err(dev, "Cannot get RSS key, err %s aq_err %s\n",
64288c2ecf20Sopenharmony_ci				ice_stat_str(status),
64298c2ecf20Sopenharmony_ci				ice_aq_str(hw->adminq.sq_last_status));
64308c2ecf20Sopenharmony_ci			return -EIO;
64318c2ecf20Sopenharmony_ci		}
64328c2ecf20Sopenharmony_ci	}
64338c2ecf20Sopenharmony_ci
64348c2ecf20Sopenharmony_ci	if (lut) {
64358c2ecf20Sopenharmony_ci		status = ice_aq_get_rss_lut(hw, vsi->idx, vsi->rss_lut_type,
64368c2ecf20Sopenharmony_ci					    lut, lut_size);
64378c2ecf20Sopenharmony_ci		if (status) {
64388c2ecf20Sopenharmony_ci			dev_err(dev, "Cannot get RSS lut, err %s aq_err %s\n",
64398c2ecf20Sopenharmony_ci				ice_stat_str(status),
64408c2ecf20Sopenharmony_ci				ice_aq_str(hw->adminq.sq_last_status));
64418c2ecf20Sopenharmony_ci			return -EIO;
64428c2ecf20Sopenharmony_ci		}
64438c2ecf20Sopenharmony_ci	}
64448c2ecf20Sopenharmony_ci
64458c2ecf20Sopenharmony_ci	return 0;
64468c2ecf20Sopenharmony_ci}
64478c2ecf20Sopenharmony_ci
64488c2ecf20Sopenharmony_ci/**
64498c2ecf20Sopenharmony_ci * ice_bridge_getlink - Get the hardware bridge mode
64508c2ecf20Sopenharmony_ci * @skb: skb buff
64518c2ecf20Sopenharmony_ci * @pid: process ID
64528c2ecf20Sopenharmony_ci * @seq: RTNL message seq
64538c2ecf20Sopenharmony_ci * @dev: the netdev being configured
64548c2ecf20Sopenharmony_ci * @filter_mask: filter mask passed in
64558c2ecf20Sopenharmony_ci * @nlflags: netlink flags passed in
64568c2ecf20Sopenharmony_ci *
64578c2ecf20Sopenharmony_ci * Return the bridge mode (VEB/VEPA)
64588c2ecf20Sopenharmony_ci */
64598c2ecf20Sopenharmony_cistatic int
64608c2ecf20Sopenharmony_ciice_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
64618c2ecf20Sopenharmony_ci		   struct net_device *dev, u32 filter_mask, int nlflags)
64628c2ecf20Sopenharmony_ci{
64638c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(dev);
64648c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
64658c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
64668c2ecf20Sopenharmony_ci	u16 bmode;
64678c2ecf20Sopenharmony_ci
64688c2ecf20Sopenharmony_ci	bmode = pf->first_sw->bridge_mode;
64698c2ecf20Sopenharmony_ci
64708c2ecf20Sopenharmony_ci	return ndo_dflt_bridge_getlink(skb, pid, seq, dev, bmode, 0, 0, nlflags,
64718c2ecf20Sopenharmony_ci				       filter_mask, NULL);
64728c2ecf20Sopenharmony_ci}
64738c2ecf20Sopenharmony_ci
64748c2ecf20Sopenharmony_ci/**
64758c2ecf20Sopenharmony_ci * ice_vsi_update_bridge_mode - Update VSI for switching bridge mode (VEB/VEPA)
64768c2ecf20Sopenharmony_ci * @vsi: Pointer to VSI structure
64778c2ecf20Sopenharmony_ci * @bmode: Hardware bridge mode (VEB/VEPA)
64788c2ecf20Sopenharmony_ci *
64798c2ecf20Sopenharmony_ci * Returns 0 on success, negative on failure
64808c2ecf20Sopenharmony_ci */
64818c2ecf20Sopenharmony_cistatic int ice_vsi_update_bridge_mode(struct ice_vsi *vsi, u16 bmode)
64828c2ecf20Sopenharmony_ci{
64838c2ecf20Sopenharmony_ci	struct ice_aqc_vsi_props *vsi_props;
64848c2ecf20Sopenharmony_ci	struct ice_hw *hw = &vsi->back->hw;
64858c2ecf20Sopenharmony_ci	struct ice_vsi_ctx *ctxt;
64868c2ecf20Sopenharmony_ci	enum ice_status status;
64878c2ecf20Sopenharmony_ci	int ret = 0;
64888c2ecf20Sopenharmony_ci
64898c2ecf20Sopenharmony_ci	vsi_props = &vsi->info;
64908c2ecf20Sopenharmony_ci
64918c2ecf20Sopenharmony_ci	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
64928c2ecf20Sopenharmony_ci	if (!ctxt)
64938c2ecf20Sopenharmony_ci		return -ENOMEM;
64948c2ecf20Sopenharmony_ci
64958c2ecf20Sopenharmony_ci	ctxt->info = vsi->info;
64968c2ecf20Sopenharmony_ci
64978c2ecf20Sopenharmony_ci	if (bmode == BRIDGE_MODE_VEB)
64988c2ecf20Sopenharmony_ci		/* change from VEPA to VEB mode */
64998c2ecf20Sopenharmony_ci		ctxt->info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
65008c2ecf20Sopenharmony_ci	else
65018c2ecf20Sopenharmony_ci		/* change from VEB to VEPA mode */
65028c2ecf20Sopenharmony_ci		ctxt->info.sw_flags &= ~ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
65038c2ecf20Sopenharmony_ci	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);
65048c2ecf20Sopenharmony_ci
65058c2ecf20Sopenharmony_ci	status = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
65068c2ecf20Sopenharmony_ci	if (status) {
65078c2ecf20Sopenharmony_ci		dev_err(ice_pf_to_dev(vsi->back), "update VSI for bridge mode failed, bmode = %d err %s aq_err %s\n",
65088c2ecf20Sopenharmony_ci			bmode, ice_stat_str(status),
65098c2ecf20Sopenharmony_ci			ice_aq_str(hw->adminq.sq_last_status));
65108c2ecf20Sopenharmony_ci		ret = -EIO;
65118c2ecf20Sopenharmony_ci		goto out;
65128c2ecf20Sopenharmony_ci	}
65138c2ecf20Sopenharmony_ci	/* Update sw flags for book keeping */
65148c2ecf20Sopenharmony_ci	vsi_props->sw_flags = ctxt->info.sw_flags;
65158c2ecf20Sopenharmony_ci
65168c2ecf20Sopenharmony_ciout:
65178c2ecf20Sopenharmony_ci	kfree(ctxt);
65188c2ecf20Sopenharmony_ci	return ret;
65198c2ecf20Sopenharmony_ci}
65208c2ecf20Sopenharmony_ci
65218c2ecf20Sopenharmony_ci/**
65228c2ecf20Sopenharmony_ci * ice_bridge_setlink - Set the hardware bridge mode
65238c2ecf20Sopenharmony_ci * @dev: the netdev being configured
65248c2ecf20Sopenharmony_ci * @nlh: RTNL message
65258c2ecf20Sopenharmony_ci * @flags: bridge setlink flags
65268c2ecf20Sopenharmony_ci * @extack: netlink extended ack
65278c2ecf20Sopenharmony_ci *
65288c2ecf20Sopenharmony_ci * Sets the bridge mode (VEB/VEPA) of the switch to which the netdev (VSI) is
65298c2ecf20Sopenharmony_ci * hooked up to. Iterates through the PF VSI list and sets the loopback mode (if
65308c2ecf20Sopenharmony_ci * not already set for all VSIs connected to this switch. And also update the
65318c2ecf20Sopenharmony_ci * unicast switch filter rules for the corresponding switch of the netdev.
65328c2ecf20Sopenharmony_ci */
65338c2ecf20Sopenharmony_cistatic int
65348c2ecf20Sopenharmony_ciice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
65358c2ecf20Sopenharmony_ci		   u16 __always_unused flags,
65368c2ecf20Sopenharmony_ci		   struct netlink_ext_ack __always_unused *extack)
65378c2ecf20Sopenharmony_ci{
65388c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(dev);
65398c2ecf20Sopenharmony_ci	struct ice_pf *pf = np->vsi->back;
65408c2ecf20Sopenharmony_ci	struct nlattr *attr, *br_spec;
65418c2ecf20Sopenharmony_ci	struct ice_hw *hw = &pf->hw;
65428c2ecf20Sopenharmony_ci	enum ice_status status;
65438c2ecf20Sopenharmony_ci	struct ice_sw *pf_sw;
65448c2ecf20Sopenharmony_ci	int rem, v, err = 0;
65458c2ecf20Sopenharmony_ci
65468c2ecf20Sopenharmony_ci	pf_sw = pf->first_sw;
65478c2ecf20Sopenharmony_ci	/* find the attribute in the netlink message */
65488c2ecf20Sopenharmony_ci	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
65498c2ecf20Sopenharmony_ci
65508c2ecf20Sopenharmony_ci	nla_for_each_nested(attr, br_spec, rem) {
65518c2ecf20Sopenharmony_ci		__u16 mode;
65528c2ecf20Sopenharmony_ci
65538c2ecf20Sopenharmony_ci		if (nla_type(attr) != IFLA_BRIDGE_MODE)
65548c2ecf20Sopenharmony_ci			continue;
65558c2ecf20Sopenharmony_ci		mode = nla_get_u16(attr);
65568c2ecf20Sopenharmony_ci		if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB)
65578c2ecf20Sopenharmony_ci			return -EINVAL;
65588c2ecf20Sopenharmony_ci		/* Continue  if bridge mode is not being flipped */
65598c2ecf20Sopenharmony_ci		if (mode == pf_sw->bridge_mode)
65608c2ecf20Sopenharmony_ci			continue;
65618c2ecf20Sopenharmony_ci		/* Iterates through the PF VSI list and update the loopback
65628c2ecf20Sopenharmony_ci		 * mode of the VSI
65638c2ecf20Sopenharmony_ci		 */
65648c2ecf20Sopenharmony_ci		ice_for_each_vsi(pf, v) {
65658c2ecf20Sopenharmony_ci			if (!pf->vsi[v])
65668c2ecf20Sopenharmony_ci				continue;
65678c2ecf20Sopenharmony_ci			err = ice_vsi_update_bridge_mode(pf->vsi[v], mode);
65688c2ecf20Sopenharmony_ci			if (err)
65698c2ecf20Sopenharmony_ci				return err;
65708c2ecf20Sopenharmony_ci		}
65718c2ecf20Sopenharmony_ci
65728c2ecf20Sopenharmony_ci		hw->evb_veb = (mode == BRIDGE_MODE_VEB);
65738c2ecf20Sopenharmony_ci		/* Update the unicast switch filter rules for the corresponding
65748c2ecf20Sopenharmony_ci		 * switch of the netdev
65758c2ecf20Sopenharmony_ci		 */
65768c2ecf20Sopenharmony_ci		status = ice_update_sw_rule_bridge_mode(hw);
65778c2ecf20Sopenharmony_ci		if (status) {
65788c2ecf20Sopenharmony_ci			netdev_err(dev, "switch rule update failed, mode = %d err %s aq_err %s\n",
65798c2ecf20Sopenharmony_ci				   mode, ice_stat_str(status),
65808c2ecf20Sopenharmony_ci				   ice_aq_str(hw->adminq.sq_last_status));
65818c2ecf20Sopenharmony_ci			/* revert hw->evb_veb */
65828c2ecf20Sopenharmony_ci			hw->evb_veb = (pf_sw->bridge_mode == BRIDGE_MODE_VEB);
65838c2ecf20Sopenharmony_ci			return -EIO;
65848c2ecf20Sopenharmony_ci		}
65858c2ecf20Sopenharmony_ci
65868c2ecf20Sopenharmony_ci		pf_sw->bridge_mode = mode;
65878c2ecf20Sopenharmony_ci	}
65888c2ecf20Sopenharmony_ci
65898c2ecf20Sopenharmony_ci	return 0;
65908c2ecf20Sopenharmony_ci}
65918c2ecf20Sopenharmony_ci
65928c2ecf20Sopenharmony_ci/**
65938c2ecf20Sopenharmony_ci * ice_tx_timeout - Respond to a Tx Hang
65948c2ecf20Sopenharmony_ci * @netdev: network interface device structure
65958c2ecf20Sopenharmony_ci * @txqueue: Tx queue
65968c2ecf20Sopenharmony_ci */
65978c2ecf20Sopenharmony_cistatic void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue)
65988c2ecf20Sopenharmony_ci{
65998c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
66008c2ecf20Sopenharmony_ci	struct ice_ring *tx_ring = NULL;
66018c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
66028c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
66038c2ecf20Sopenharmony_ci	u32 i;
66048c2ecf20Sopenharmony_ci
66058c2ecf20Sopenharmony_ci	pf->tx_timeout_count++;
66068c2ecf20Sopenharmony_ci
66078c2ecf20Sopenharmony_ci	/* Check if PFC is enabled for the TC to which the queue belongs
66088c2ecf20Sopenharmony_ci	 * to. If yes then Tx timeout is not caused by a hung queue, no
66098c2ecf20Sopenharmony_ci	 * need to reset and rebuild
66108c2ecf20Sopenharmony_ci	 */
66118c2ecf20Sopenharmony_ci	if (ice_is_pfc_causing_hung_q(pf, txqueue)) {
66128c2ecf20Sopenharmony_ci		dev_info(ice_pf_to_dev(pf), "Fake Tx hang detected on queue %u, timeout caused by PFC storm\n",
66138c2ecf20Sopenharmony_ci			 txqueue);
66148c2ecf20Sopenharmony_ci		return;
66158c2ecf20Sopenharmony_ci	}
66168c2ecf20Sopenharmony_ci
66178c2ecf20Sopenharmony_ci	/* now that we have an index, find the tx_ring struct */
66188c2ecf20Sopenharmony_ci	for (i = 0; i < vsi->num_txq; i++)
66198c2ecf20Sopenharmony_ci		if (vsi->tx_rings[i] && vsi->tx_rings[i]->desc)
66208c2ecf20Sopenharmony_ci			if (txqueue == vsi->tx_rings[i]->q_index) {
66218c2ecf20Sopenharmony_ci				tx_ring = vsi->tx_rings[i];
66228c2ecf20Sopenharmony_ci				break;
66238c2ecf20Sopenharmony_ci			}
66248c2ecf20Sopenharmony_ci
66258c2ecf20Sopenharmony_ci	/* Reset recovery level if enough time has elapsed after last timeout.
66268c2ecf20Sopenharmony_ci	 * Also ensure no new reset action happens before next timeout period.
66278c2ecf20Sopenharmony_ci	 */
66288c2ecf20Sopenharmony_ci	if (time_after(jiffies, (pf->tx_timeout_last_recovery + HZ * 20)))
66298c2ecf20Sopenharmony_ci		pf->tx_timeout_recovery_level = 1;
66308c2ecf20Sopenharmony_ci	else if (time_before(jiffies, (pf->tx_timeout_last_recovery +
66318c2ecf20Sopenharmony_ci				       netdev->watchdog_timeo)))
66328c2ecf20Sopenharmony_ci		return;
66338c2ecf20Sopenharmony_ci
66348c2ecf20Sopenharmony_ci	if (tx_ring) {
66358c2ecf20Sopenharmony_ci		struct ice_hw *hw = &pf->hw;
66368c2ecf20Sopenharmony_ci		u32 head, val = 0;
66378c2ecf20Sopenharmony_ci
66388c2ecf20Sopenharmony_ci		head = (rd32(hw, QTX_COMM_HEAD(vsi->txq_map[txqueue])) &
66398c2ecf20Sopenharmony_ci			QTX_COMM_HEAD_HEAD_M) >> QTX_COMM_HEAD_HEAD_S;
66408c2ecf20Sopenharmony_ci		/* Read interrupt register */
66418c2ecf20Sopenharmony_ci		val = rd32(hw, GLINT_DYN_CTL(tx_ring->q_vector->reg_idx));
66428c2ecf20Sopenharmony_ci
66438c2ecf20Sopenharmony_ci		netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %u, NTC: 0x%x, HW_HEAD: 0x%x, NTU: 0x%x, INT: 0x%x\n",
66448c2ecf20Sopenharmony_ci			    vsi->vsi_num, txqueue, tx_ring->next_to_clean,
66458c2ecf20Sopenharmony_ci			    head, tx_ring->next_to_use, val);
66468c2ecf20Sopenharmony_ci	}
66478c2ecf20Sopenharmony_ci
66488c2ecf20Sopenharmony_ci	pf->tx_timeout_last_recovery = jiffies;
66498c2ecf20Sopenharmony_ci	netdev_info(netdev, "tx_timeout recovery level %d, txqueue %u\n",
66508c2ecf20Sopenharmony_ci		    pf->tx_timeout_recovery_level, txqueue);
66518c2ecf20Sopenharmony_ci
66528c2ecf20Sopenharmony_ci	switch (pf->tx_timeout_recovery_level) {
66538c2ecf20Sopenharmony_ci	case 1:
66548c2ecf20Sopenharmony_ci		set_bit(__ICE_PFR_REQ, pf->state);
66558c2ecf20Sopenharmony_ci		break;
66568c2ecf20Sopenharmony_ci	case 2:
66578c2ecf20Sopenharmony_ci		set_bit(__ICE_CORER_REQ, pf->state);
66588c2ecf20Sopenharmony_ci		break;
66598c2ecf20Sopenharmony_ci	case 3:
66608c2ecf20Sopenharmony_ci		set_bit(__ICE_GLOBR_REQ, pf->state);
66618c2ecf20Sopenharmony_ci		break;
66628c2ecf20Sopenharmony_ci	default:
66638c2ecf20Sopenharmony_ci		netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in unrecoverable state.\n");
66648c2ecf20Sopenharmony_ci		set_bit(__ICE_DOWN, pf->state);
66658c2ecf20Sopenharmony_ci		set_bit(__ICE_NEEDS_RESTART, vsi->state);
66668c2ecf20Sopenharmony_ci		set_bit(__ICE_SERVICE_DIS, pf->state);
66678c2ecf20Sopenharmony_ci		break;
66688c2ecf20Sopenharmony_ci	}
66698c2ecf20Sopenharmony_ci
66708c2ecf20Sopenharmony_ci	ice_service_task_schedule(pf);
66718c2ecf20Sopenharmony_ci	pf->tx_timeout_recovery_level++;
66728c2ecf20Sopenharmony_ci}
66738c2ecf20Sopenharmony_ci
66748c2ecf20Sopenharmony_ci/**
66758c2ecf20Sopenharmony_ci * ice_open - Called when a network interface becomes active
66768c2ecf20Sopenharmony_ci * @netdev: network interface device structure
66778c2ecf20Sopenharmony_ci *
66788c2ecf20Sopenharmony_ci * The open entry point is called when a network interface is made
66798c2ecf20Sopenharmony_ci * active by the system (IFF_UP). At this point all resources needed
66808c2ecf20Sopenharmony_ci * for transmit and receive operations are allocated, the interrupt
66818c2ecf20Sopenharmony_ci * handler is registered with the OS, the netdev watchdog is enabled,
66828c2ecf20Sopenharmony_ci * and the stack is notified that the interface is ready.
66838c2ecf20Sopenharmony_ci *
66848c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on failure
66858c2ecf20Sopenharmony_ci */
66868c2ecf20Sopenharmony_ciint ice_open(struct net_device *netdev)
66878c2ecf20Sopenharmony_ci{
66888c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
66898c2ecf20Sopenharmony_ci	struct ice_pf *pf = np->vsi->back;
66908c2ecf20Sopenharmony_ci
66918c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state)) {
66928c2ecf20Sopenharmony_ci		netdev_err(netdev, "can't open net device while reset is in progress");
66938c2ecf20Sopenharmony_ci		return -EBUSY;
66948c2ecf20Sopenharmony_ci	}
66958c2ecf20Sopenharmony_ci
66968c2ecf20Sopenharmony_ci	return ice_open_internal(netdev);
66978c2ecf20Sopenharmony_ci}
66988c2ecf20Sopenharmony_ci
66998c2ecf20Sopenharmony_ci/**
67008c2ecf20Sopenharmony_ci * ice_open_internal - Called when a network interface becomes active
67018c2ecf20Sopenharmony_ci * @netdev: network interface device structure
67028c2ecf20Sopenharmony_ci *
67038c2ecf20Sopenharmony_ci * Internal ice_open implementation. Should not be used directly except for ice_open and reset
67048c2ecf20Sopenharmony_ci * handling routine
67058c2ecf20Sopenharmony_ci *
67068c2ecf20Sopenharmony_ci * Returns 0 on success, negative value on failure
67078c2ecf20Sopenharmony_ci */
67088c2ecf20Sopenharmony_ciint ice_open_internal(struct net_device *netdev)
67098c2ecf20Sopenharmony_ci{
67108c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
67118c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
67128c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
67138c2ecf20Sopenharmony_ci	struct ice_port_info *pi;
67148c2ecf20Sopenharmony_ci	int err;
67158c2ecf20Sopenharmony_ci
67168c2ecf20Sopenharmony_ci	if (test_bit(__ICE_NEEDS_RESTART, pf->state)) {
67178c2ecf20Sopenharmony_ci		netdev_err(netdev, "driver needs to be unloaded and reloaded\n");
67188c2ecf20Sopenharmony_ci		return -EIO;
67198c2ecf20Sopenharmony_ci	}
67208c2ecf20Sopenharmony_ci
67218c2ecf20Sopenharmony_ci	if (test_bit(__ICE_DOWN, pf->state)) {
67228c2ecf20Sopenharmony_ci		netdev_err(netdev, "device is not ready yet\n");
67238c2ecf20Sopenharmony_ci		return -EBUSY;
67248c2ecf20Sopenharmony_ci	}
67258c2ecf20Sopenharmony_ci
67268c2ecf20Sopenharmony_ci	netif_carrier_off(netdev);
67278c2ecf20Sopenharmony_ci
67288c2ecf20Sopenharmony_ci	pi = vsi->port_info;
67298c2ecf20Sopenharmony_ci	err = ice_update_link_info(pi);
67308c2ecf20Sopenharmony_ci	if (err) {
67318c2ecf20Sopenharmony_ci		netdev_err(netdev, "Failed to get link info, error %d\n",
67328c2ecf20Sopenharmony_ci			   err);
67338c2ecf20Sopenharmony_ci		return err;
67348c2ecf20Sopenharmony_ci	}
67358c2ecf20Sopenharmony_ci
67368c2ecf20Sopenharmony_ci	/* Set PHY if there is media, otherwise, turn off PHY */
67378c2ecf20Sopenharmony_ci	if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) {
67388c2ecf20Sopenharmony_ci		clear_bit(ICE_FLAG_NO_MEDIA, pf->flags);
67398c2ecf20Sopenharmony_ci		if (!test_bit(__ICE_PHY_INIT_COMPLETE, pf->state)) {
67408c2ecf20Sopenharmony_ci			err = ice_init_phy_user_cfg(pi);
67418c2ecf20Sopenharmony_ci			if (err) {
67428c2ecf20Sopenharmony_ci				netdev_err(netdev, "Failed to initialize PHY settings, error %d\n",
67438c2ecf20Sopenharmony_ci					   err);
67448c2ecf20Sopenharmony_ci				return err;
67458c2ecf20Sopenharmony_ci			}
67468c2ecf20Sopenharmony_ci		}
67478c2ecf20Sopenharmony_ci
67488c2ecf20Sopenharmony_ci		err = ice_configure_phy(vsi);
67498c2ecf20Sopenharmony_ci		if (err) {
67508c2ecf20Sopenharmony_ci			netdev_err(netdev, "Failed to set physical link up, error %d\n",
67518c2ecf20Sopenharmony_ci				   err);
67528c2ecf20Sopenharmony_ci			return err;
67538c2ecf20Sopenharmony_ci		}
67548c2ecf20Sopenharmony_ci	} else {
67558c2ecf20Sopenharmony_ci		set_bit(ICE_FLAG_NO_MEDIA, pf->flags);
67568c2ecf20Sopenharmony_ci		err = ice_aq_set_link_restart_an(pi, false, NULL);
67578c2ecf20Sopenharmony_ci		if (err) {
67588c2ecf20Sopenharmony_ci			netdev_err(netdev, "Failed to set PHY state, VSI %d error %d\n",
67598c2ecf20Sopenharmony_ci				   vsi->vsi_num, err);
67608c2ecf20Sopenharmony_ci			return err;
67618c2ecf20Sopenharmony_ci		}
67628c2ecf20Sopenharmony_ci	}
67638c2ecf20Sopenharmony_ci
67648c2ecf20Sopenharmony_ci	err = ice_vsi_open(vsi);
67658c2ecf20Sopenharmony_ci	if (err)
67668c2ecf20Sopenharmony_ci		netdev_err(netdev, "Failed to open VSI 0x%04X on switch 0x%04X\n",
67678c2ecf20Sopenharmony_ci			   vsi->vsi_num, vsi->vsw->sw_id);
67688c2ecf20Sopenharmony_ci
67698c2ecf20Sopenharmony_ci	/* Update existing tunnels information */
67708c2ecf20Sopenharmony_ci	udp_tunnel_get_rx_info(netdev);
67718c2ecf20Sopenharmony_ci
67728c2ecf20Sopenharmony_ci	return err;
67738c2ecf20Sopenharmony_ci}
67748c2ecf20Sopenharmony_ci
67758c2ecf20Sopenharmony_ci/**
67768c2ecf20Sopenharmony_ci * ice_stop - Disables a network interface
67778c2ecf20Sopenharmony_ci * @netdev: network interface device structure
67788c2ecf20Sopenharmony_ci *
67798c2ecf20Sopenharmony_ci * The stop entry point is called when an interface is de-activated by the OS,
67808c2ecf20Sopenharmony_ci * and the netdevice enters the DOWN state. The hardware is still under the
67818c2ecf20Sopenharmony_ci * driver's control, but the netdev interface is disabled.
67828c2ecf20Sopenharmony_ci *
67838c2ecf20Sopenharmony_ci * Returns success only - not allowed to fail
67848c2ecf20Sopenharmony_ci */
67858c2ecf20Sopenharmony_ciint ice_stop(struct net_device *netdev)
67868c2ecf20Sopenharmony_ci{
67878c2ecf20Sopenharmony_ci	struct ice_netdev_priv *np = netdev_priv(netdev);
67888c2ecf20Sopenharmony_ci	struct ice_vsi *vsi = np->vsi;
67898c2ecf20Sopenharmony_ci	struct ice_pf *pf = vsi->back;
67908c2ecf20Sopenharmony_ci
67918c2ecf20Sopenharmony_ci	if (ice_is_reset_in_progress(pf->state)) {
67928c2ecf20Sopenharmony_ci		netdev_err(netdev, "can't stop net device while reset is in progress");
67938c2ecf20Sopenharmony_ci		return -EBUSY;
67948c2ecf20Sopenharmony_ci	}
67958c2ecf20Sopenharmony_ci
67968c2ecf20Sopenharmony_ci	ice_vsi_close(vsi);
67978c2ecf20Sopenharmony_ci
67988c2ecf20Sopenharmony_ci	return 0;
67998c2ecf20Sopenharmony_ci}
68008c2ecf20Sopenharmony_ci
68018c2ecf20Sopenharmony_ci/**
68028c2ecf20Sopenharmony_ci * ice_features_check - Validate encapsulated packet conforms to limits
68038c2ecf20Sopenharmony_ci * @skb: skb buffer
68048c2ecf20Sopenharmony_ci * @netdev: This port's netdev
68058c2ecf20Sopenharmony_ci * @features: Offload features that the stack believes apply
68068c2ecf20Sopenharmony_ci */
68078c2ecf20Sopenharmony_cistatic netdev_features_t
68088c2ecf20Sopenharmony_ciice_features_check(struct sk_buff *skb,
68098c2ecf20Sopenharmony_ci		   struct net_device __always_unused *netdev,
68108c2ecf20Sopenharmony_ci		   netdev_features_t features)
68118c2ecf20Sopenharmony_ci{
68128c2ecf20Sopenharmony_ci	size_t len;
68138c2ecf20Sopenharmony_ci
68148c2ecf20Sopenharmony_ci	/* No point in doing any of this if neither checksum nor GSO are
68158c2ecf20Sopenharmony_ci	 * being requested for this frame. We can rule out both by just
68168c2ecf20Sopenharmony_ci	 * checking for CHECKSUM_PARTIAL
68178c2ecf20Sopenharmony_ci	 */
68188c2ecf20Sopenharmony_ci	if (skb->ip_summed != CHECKSUM_PARTIAL)
68198c2ecf20Sopenharmony_ci		return features;
68208c2ecf20Sopenharmony_ci
68218c2ecf20Sopenharmony_ci	/* We cannot support GSO if the MSS is going to be less than
68228c2ecf20Sopenharmony_ci	 * 64 bytes. If it is then we need to drop support for GSO.
68238c2ecf20Sopenharmony_ci	 */
68248c2ecf20Sopenharmony_ci	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
68258c2ecf20Sopenharmony_ci		features &= ~NETIF_F_GSO_MASK;
68268c2ecf20Sopenharmony_ci
68278c2ecf20Sopenharmony_ci	len = skb_network_header(skb) - skb->data;
68288c2ecf20Sopenharmony_ci	if (len > ICE_TXD_MACLEN_MAX || len & 0x1)
68298c2ecf20Sopenharmony_ci		goto out_rm_features;
68308c2ecf20Sopenharmony_ci
68318c2ecf20Sopenharmony_ci	len = skb_transport_header(skb) - skb_network_header(skb);
68328c2ecf20Sopenharmony_ci	if (len > ICE_TXD_IPLEN_MAX || len & 0x1)
68338c2ecf20Sopenharmony_ci		goto out_rm_features;
68348c2ecf20Sopenharmony_ci
68358c2ecf20Sopenharmony_ci	if (skb->encapsulation) {
68368c2ecf20Sopenharmony_ci		len = skb_inner_network_header(skb) - skb_transport_header(skb);
68378c2ecf20Sopenharmony_ci		if (len > ICE_TXD_L4LEN_MAX || len & 0x1)
68388c2ecf20Sopenharmony_ci			goto out_rm_features;
68398c2ecf20Sopenharmony_ci
68408c2ecf20Sopenharmony_ci		len = skb_inner_transport_header(skb) -
68418c2ecf20Sopenharmony_ci		      skb_inner_network_header(skb);
68428c2ecf20Sopenharmony_ci		if (len > ICE_TXD_IPLEN_MAX || len & 0x1)
68438c2ecf20Sopenharmony_ci			goto out_rm_features;
68448c2ecf20Sopenharmony_ci	}
68458c2ecf20Sopenharmony_ci
68468c2ecf20Sopenharmony_ci	return features;
68478c2ecf20Sopenharmony_ciout_rm_features:
68488c2ecf20Sopenharmony_ci	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
68498c2ecf20Sopenharmony_ci}
68508c2ecf20Sopenharmony_ci
68518c2ecf20Sopenharmony_cistatic const struct net_device_ops ice_netdev_safe_mode_ops = {
68528c2ecf20Sopenharmony_ci	.ndo_open = ice_open,
68538c2ecf20Sopenharmony_ci	.ndo_stop = ice_stop,
68548c2ecf20Sopenharmony_ci	.ndo_start_xmit = ice_start_xmit,
68558c2ecf20Sopenharmony_ci	.ndo_set_mac_address = ice_set_mac_address,
68568c2ecf20Sopenharmony_ci	.ndo_validate_addr = eth_validate_addr,
68578c2ecf20Sopenharmony_ci	.ndo_change_mtu = ice_change_mtu,
68588c2ecf20Sopenharmony_ci	.ndo_get_stats64 = ice_get_stats64,
68598c2ecf20Sopenharmony_ci	.ndo_tx_timeout = ice_tx_timeout,
68608c2ecf20Sopenharmony_ci	.ndo_bpf = ice_xdp_safe_mode,
68618c2ecf20Sopenharmony_ci};
68628c2ecf20Sopenharmony_ci
68638c2ecf20Sopenharmony_cistatic const struct net_device_ops ice_netdev_ops = {
68648c2ecf20Sopenharmony_ci	.ndo_open = ice_open,
68658c2ecf20Sopenharmony_ci	.ndo_stop = ice_stop,
68668c2ecf20Sopenharmony_ci	.ndo_start_xmit = ice_start_xmit,
68678c2ecf20Sopenharmony_ci	.ndo_features_check = ice_features_check,
68688c2ecf20Sopenharmony_ci	.ndo_set_rx_mode = ice_set_rx_mode,
68698c2ecf20Sopenharmony_ci	.ndo_set_mac_address = ice_set_mac_address,
68708c2ecf20Sopenharmony_ci	.ndo_validate_addr = eth_validate_addr,
68718c2ecf20Sopenharmony_ci	.ndo_change_mtu = ice_change_mtu,
68728c2ecf20Sopenharmony_ci	.ndo_get_stats64 = ice_get_stats64,
68738c2ecf20Sopenharmony_ci	.ndo_set_tx_maxrate = ice_set_tx_maxrate,
68748c2ecf20Sopenharmony_ci	.ndo_set_vf_spoofchk = ice_set_vf_spoofchk,
68758c2ecf20Sopenharmony_ci	.ndo_set_vf_mac = ice_set_vf_mac,
68768c2ecf20Sopenharmony_ci	.ndo_get_vf_config = ice_get_vf_cfg,
68778c2ecf20Sopenharmony_ci	.ndo_set_vf_trust = ice_set_vf_trust,
68788c2ecf20Sopenharmony_ci	.ndo_set_vf_vlan = ice_set_vf_port_vlan,
68798c2ecf20Sopenharmony_ci	.ndo_set_vf_link_state = ice_set_vf_link_state,
68808c2ecf20Sopenharmony_ci	.ndo_get_vf_stats = ice_get_vf_stats,
68818c2ecf20Sopenharmony_ci	.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
68828c2ecf20Sopenharmony_ci	.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
68838c2ecf20Sopenharmony_ci	.ndo_set_features = ice_set_features,
68848c2ecf20Sopenharmony_ci	.ndo_bridge_getlink = ice_bridge_getlink,
68858c2ecf20Sopenharmony_ci	.ndo_bridge_setlink = ice_bridge_setlink,
68868c2ecf20Sopenharmony_ci	.ndo_fdb_add = ice_fdb_add,
68878c2ecf20Sopenharmony_ci	.ndo_fdb_del = ice_fdb_del,
68888c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
68898c2ecf20Sopenharmony_ci	.ndo_rx_flow_steer = ice_rx_flow_steer,
68908c2ecf20Sopenharmony_ci#endif
68918c2ecf20Sopenharmony_ci	.ndo_tx_timeout = ice_tx_timeout,
68928c2ecf20Sopenharmony_ci	.ndo_bpf = ice_xdp,
68938c2ecf20Sopenharmony_ci	.ndo_xdp_xmit = ice_xdp_xmit,
68948c2ecf20Sopenharmony_ci	.ndo_xsk_wakeup = ice_xsk_wakeup,
68958c2ecf20Sopenharmony_ci	.ndo_udp_tunnel_add = udp_tunnel_nic_add_port,
68968c2ecf20Sopenharmony_ci	.ndo_udp_tunnel_del = udp_tunnel_nic_del_port,
68978c2ecf20Sopenharmony_ci};
6898