18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/****************************************************************************
38c2ecf20Sopenharmony_ci * Driver for Solarflare network controllers and boards
48c2ecf20Sopenharmony_ci * Copyright 2012-2013 Solarflare Communications Inc.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "net_driver.h"
88c2ecf20Sopenharmony_ci#include "rx_common.h"
98c2ecf20Sopenharmony_ci#include "tx_common.h"
108c2ecf20Sopenharmony_ci#include "ef10_regs.h"
118c2ecf20Sopenharmony_ci#include "io.h"
128c2ecf20Sopenharmony_ci#include "mcdi.h"
138c2ecf20Sopenharmony_ci#include "mcdi_pcol.h"
148c2ecf20Sopenharmony_ci#include "mcdi_port.h"
158c2ecf20Sopenharmony_ci#include "mcdi_port_common.h"
168c2ecf20Sopenharmony_ci#include "mcdi_functions.h"
178c2ecf20Sopenharmony_ci#include "nic.h"
188c2ecf20Sopenharmony_ci#include "mcdi_filters.h"
198c2ecf20Sopenharmony_ci#include "workarounds.h"
208c2ecf20Sopenharmony_ci#include "selftest.h"
218c2ecf20Sopenharmony_ci#include "ef10_sriov.h"
228c2ecf20Sopenharmony_ci#include <linux/in.h>
238c2ecf20Sopenharmony_ci#include <linux/jhash.h>
248c2ecf20Sopenharmony_ci#include <linux/wait.h>
258c2ecf20Sopenharmony_ci#include <linux/workqueue.h>
268c2ecf20Sopenharmony_ci#include <net/udp_tunnel.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* Hardware control for EF10 architecture including 'Huntington'. */
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#define EFX_EF10_DRVGEN_EV		7
318c2ecf20Sopenharmony_cienum {
328c2ecf20Sopenharmony_ci	EFX_EF10_TEST = 1,
338c2ecf20Sopenharmony_ci	EFX_EF10_REFILL,
348c2ecf20Sopenharmony_ci};
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* VLAN list entry */
378c2ecf20Sopenharmony_cistruct efx_ef10_vlan {
388c2ecf20Sopenharmony_ci	struct list_head list;
398c2ecf20Sopenharmony_ci	u16 vid;
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic int efx_ef10_set_udp_tnl_ports(struct efx_nic *efx, bool unloading);
438c2ecf20Sopenharmony_cistatic const struct udp_tunnel_nic_info efx_ef10_udp_tunnels;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic int efx_ef10_get_warm_boot_count(struct efx_nic *efx)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	efx_dword_t reg;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	efx_readd(efx, &reg, ER_DZ_BIU_MC_SFT_STATUS);
508c2ecf20Sopenharmony_ci	return EFX_DWORD_FIELD(reg, EFX_WORD_1) == 0xb007 ?
518c2ecf20Sopenharmony_ci		EFX_DWORD_FIELD(reg, EFX_WORD_0) : -EIO;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* On all EF10s up to and including SFC9220 (Medford1), all PFs use BAR 0 for
558c2ecf20Sopenharmony_ci * I/O space and BAR 2(&3) for memory.  On SFC9250 (Medford2), there is no I/O
568c2ecf20Sopenharmony_ci * bar; PFs use BAR 0/1 for memory.
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_cistatic unsigned int efx_ef10_pf_mem_bar(struct efx_nic *efx)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	switch (efx->pci_dev->device) {
618c2ecf20Sopenharmony_ci	case 0x0b03: /* SFC9250 PF */
628c2ecf20Sopenharmony_ci		return 0;
638c2ecf20Sopenharmony_ci	default:
648c2ecf20Sopenharmony_ci		return 2;
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/* All VFs use BAR 0/1 for memory */
698c2ecf20Sopenharmony_cistatic unsigned int efx_ef10_vf_mem_bar(struct efx_nic *efx)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	return 0;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic unsigned int efx_ef10_mem_map_size(struct efx_nic *efx)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	int bar;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	bar = efx->type->mem_bar(efx);
798c2ecf20Sopenharmony_ci	return resource_size(&efx->pci_dev->resource[bar]);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic bool efx_ef10_is_vf(struct efx_nic *efx)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	return efx->type->is_vf;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
888c2ecf20Sopenharmony_cistatic int efx_ef10_get_vf_index(struct efx_nic *efx)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_FUNCTION_INFO_OUT_LEN);
918c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
928c2ecf20Sopenharmony_ci	size_t outlen;
938c2ecf20Sopenharmony_ci	int rc;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_GET_FUNCTION_INFO, NULL, 0, outbuf,
968c2ecf20Sopenharmony_ci			  sizeof(outbuf), &outlen);
978c2ecf20Sopenharmony_ci	if (rc)
988c2ecf20Sopenharmony_ci		return rc;
998c2ecf20Sopenharmony_ci	if (outlen < sizeof(outbuf))
1008c2ecf20Sopenharmony_ci		return -EIO;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	nic_data->vf_index = MCDI_DWORD(outbuf, GET_FUNCTION_INFO_OUT_VF);
1038c2ecf20Sopenharmony_ci	return 0;
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci#endif
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistatic int efx_ef10_init_datapath_caps(struct efx_nic *efx)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CAPABILITIES_V4_OUT_LEN);
1108c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
1118c2ecf20Sopenharmony_ci	size_t outlen;
1128c2ecf20Sopenharmony_ci	int rc;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_GET_CAPABILITIES_IN_LEN != 0);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_GET_CAPABILITIES, NULL, 0,
1178c2ecf20Sopenharmony_ci			  outbuf, sizeof(outbuf), &outlen);
1188c2ecf20Sopenharmony_ci	if (rc)
1198c2ecf20Sopenharmony_ci		return rc;
1208c2ecf20Sopenharmony_ci	if (outlen < MC_CMD_GET_CAPABILITIES_OUT_LEN) {
1218c2ecf20Sopenharmony_ci		netif_err(efx, drv, efx->net_dev,
1228c2ecf20Sopenharmony_ci			  "unable to read datapath firmware capabilities\n");
1238c2ecf20Sopenharmony_ci		return -EIO;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	nic_data->datapath_caps =
1278c2ecf20Sopenharmony_ci		MCDI_DWORD(outbuf, GET_CAPABILITIES_OUT_FLAGS1);
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	if (outlen >= MC_CMD_GET_CAPABILITIES_V2_OUT_LEN) {
1308c2ecf20Sopenharmony_ci		nic_data->datapath_caps2 = MCDI_DWORD(outbuf,
1318c2ecf20Sopenharmony_ci				GET_CAPABILITIES_V2_OUT_FLAGS2);
1328c2ecf20Sopenharmony_ci		nic_data->piobuf_size = MCDI_WORD(outbuf,
1338c2ecf20Sopenharmony_ci				GET_CAPABILITIES_V2_OUT_SIZE_PIO_BUFF);
1348c2ecf20Sopenharmony_ci	} else {
1358c2ecf20Sopenharmony_ci		nic_data->datapath_caps2 = 0;
1368c2ecf20Sopenharmony_ci		nic_data->piobuf_size = ER_DZ_TX_PIOBUF_SIZE;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	/* record the DPCPU firmware IDs to determine VEB vswitching support.
1408c2ecf20Sopenharmony_ci	 */
1418c2ecf20Sopenharmony_ci	nic_data->rx_dpcpu_fw_id =
1428c2ecf20Sopenharmony_ci		MCDI_WORD(outbuf, GET_CAPABILITIES_OUT_RX_DPCPU_FW_ID);
1438c2ecf20Sopenharmony_ci	nic_data->tx_dpcpu_fw_id =
1448c2ecf20Sopenharmony_ci		MCDI_WORD(outbuf, GET_CAPABILITIES_OUT_TX_DPCPU_FW_ID);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	if (!(nic_data->datapath_caps &
1478c2ecf20Sopenharmony_ci	      (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14_LBN))) {
1488c2ecf20Sopenharmony_ci		netif_err(efx, probe, efx->net_dev,
1498c2ecf20Sopenharmony_ci			  "current firmware does not support an RX prefix\n");
1508c2ecf20Sopenharmony_ci		return -ENODEV;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	if (outlen >= MC_CMD_GET_CAPABILITIES_V3_OUT_LEN) {
1548c2ecf20Sopenharmony_ci		u8 vi_window_mode = MCDI_BYTE(outbuf,
1558c2ecf20Sopenharmony_ci				GET_CAPABILITIES_V3_OUT_VI_WINDOW_MODE);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci		rc = efx_mcdi_window_mode_to_stride(efx, vi_window_mode);
1588c2ecf20Sopenharmony_ci		if (rc)
1598c2ecf20Sopenharmony_ci			return rc;
1608c2ecf20Sopenharmony_ci	} else {
1618c2ecf20Sopenharmony_ci		/* keep default VI stride */
1628c2ecf20Sopenharmony_ci		netif_dbg(efx, probe, efx->net_dev,
1638c2ecf20Sopenharmony_ci			  "firmware did not report VI window mode, assuming vi_stride = %u\n",
1648c2ecf20Sopenharmony_ci			  efx->vi_stride);
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (outlen >= MC_CMD_GET_CAPABILITIES_V4_OUT_LEN) {
1688c2ecf20Sopenharmony_ci		efx->num_mac_stats = MCDI_WORD(outbuf,
1698c2ecf20Sopenharmony_ci				GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS);
1708c2ecf20Sopenharmony_ci		netif_dbg(efx, probe, efx->net_dev,
1718c2ecf20Sopenharmony_ci			  "firmware reports num_mac_stats = %u\n",
1728c2ecf20Sopenharmony_ci			  efx->num_mac_stats);
1738c2ecf20Sopenharmony_ci	} else {
1748c2ecf20Sopenharmony_ci		/* leave num_mac_stats as the default value, MC_CMD_MAC_NSTATS */
1758c2ecf20Sopenharmony_ci		netif_dbg(efx, probe, efx->net_dev,
1768c2ecf20Sopenharmony_ci			  "firmware did not report num_mac_stats, assuming %u\n",
1778c2ecf20Sopenharmony_ci			  efx->num_mac_stats);
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	return 0;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_cistatic void efx_ef10_read_licensed_features(struct efx_nic *efx)
1848c2ecf20Sopenharmony_ci{
1858c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_LICENSING_V3_IN_LEN);
1868c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_LICENSING_V3_OUT_LEN);
1878c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
1888c2ecf20Sopenharmony_ci	size_t outlen;
1898c2ecf20Sopenharmony_ci	int rc;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, LICENSING_V3_IN_OP,
1928c2ecf20Sopenharmony_ci		       MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
1938c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_LICENSING_V3, inbuf, sizeof(inbuf),
1948c2ecf20Sopenharmony_ci				outbuf, sizeof(outbuf), &outlen);
1958c2ecf20Sopenharmony_ci	if (rc || (outlen < MC_CMD_LICENSING_V3_OUT_LEN))
1968c2ecf20Sopenharmony_ci		return;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	nic_data->licensed_features = MCDI_QWORD(outbuf,
1998c2ecf20Sopenharmony_ci					 LICENSING_V3_OUT_LICENSED_FEATURES);
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic int efx_ef10_get_sysclk_freq(struct efx_nic *efx)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_CLOCK_OUT_LEN);
2058c2ecf20Sopenharmony_ci	int rc;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_GET_CLOCK, NULL, 0,
2088c2ecf20Sopenharmony_ci			  outbuf, sizeof(outbuf), NULL);
2098c2ecf20Sopenharmony_ci	if (rc)
2108c2ecf20Sopenharmony_ci		return rc;
2118c2ecf20Sopenharmony_ci	rc = MCDI_DWORD(outbuf, GET_CLOCK_OUT_SYS_FREQ);
2128c2ecf20Sopenharmony_ci	return rc > 0 ? rc : -ERANGE;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic int efx_ef10_get_timer_workarounds(struct efx_nic *efx)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
2188c2ecf20Sopenharmony_ci	unsigned int implemented;
2198c2ecf20Sopenharmony_ci	unsigned int enabled;
2208c2ecf20Sopenharmony_ci	int rc;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	nic_data->workaround_35388 = false;
2238c2ecf20Sopenharmony_ci	nic_data->workaround_61265 = false;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (rc == -ENOSYS) {
2288c2ecf20Sopenharmony_ci		/* Firmware without GET_WORKAROUNDS - not a problem. */
2298c2ecf20Sopenharmony_ci		rc = 0;
2308c2ecf20Sopenharmony_ci	} else if (rc == 0) {
2318c2ecf20Sopenharmony_ci		/* Bug61265 workaround is always enabled if implemented. */
2328c2ecf20Sopenharmony_ci		if (enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG61265)
2338c2ecf20Sopenharmony_ci			nic_data->workaround_61265 = true;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci		if (enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388) {
2368c2ecf20Sopenharmony_ci			nic_data->workaround_35388 = true;
2378c2ecf20Sopenharmony_ci		} else if (implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG35388) {
2388c2ecf20Sopenharmony_ci			/* Workaround is implemented but not enabled.
2398c2ecf20Sopenharmony_ci			 * Try to enable it.
2408c2ecf20Sopenharmony_ci			 */
2418c2ecf20Sopenharmony_ci			rc = efx_mcdi_set_workaround(efx,
2428c2ecf20Sopenharmony_ci						     MC_CMD_WORKAROUND_BUG35388,
2438c2ecf20Sopenharmony_ci						     true, NULL);
2448c2ecf20Sopenharmony_ci			if (rc == 0)
2458c2ecf20Sopenharmony_ci				nic_data->workaround_35388 = true;
2468c2ecf20Sopenharmony_ci			/* If we failed to set the workaround just carry on. */
2478c2ecf20Sopenharmony_ci			rc = 0;
2488c2ecf20Sopenharmony_ci		}
2498c2ecf20Sopenharmony_ci	}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	netif_dbg(efx, probe, efx->net_dev,
2528c2ecf20Sopenharmony_ci		  "workaround for bug 35388 is %sabled\n",
2538c2ecf20Sopenharmony_ci		  nic_data->workaround_35388 ? "en" : "dis");
2548c2ecf20Sopenharmony_ci	netif_dbg(efx, probe, efx->net_dev,
2558c2ecf20Sopenharmony_ci		  "workaround for bug 61265 is %sabled\n",
2568c2ecf20Sopenharmony_ci		  nic_data->workaround_61265 ? "en" : "dis");
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return rc;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistatic void efx_ef10_process_timer_config(struct efx_nic *efx,
2628c2ecf20Sopenharmony_ci					  const efx_dword_t *data)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	unsigned int max_count;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	if (EFX_EF10_WORKAROUND_61265(efx)) {
2678c2ecf20Sopenharmony_ci		efx->timer_quantum_ns = MCDI_DWORD(data,
2688c2ecf20Sopenharmony_ci			GET_EVQ_TMR_PROPERTIES_OUT_MCDI_TMR_STEP_NS);
2698c2ecf20Sopenharmony_ci		efx->timer_max_ns = MCDI_DWORD(data,
2708c2ecf20Sopenharmony_ci			GET_EVQ_TMR_PROPERTIES_OUT_MCDI_TMR_MAX_NS);
2718c2ecf20Sopenharmony_ci	} else if (EFX_EF10_WORKAROUND_35388(efx)) {
2728c2ecf20Sopenharmony_ci		efx->timer_quantum_ns = MCDI_DWORD(data,
2738c2ecf20Sopenharmony_ci			GET_EVQ_TMR_PROPERTIES_OUT_BUG35388_TMR_NS_PER_COUNT);
2748c2ecf20Sopenharmony_ci		max_count = MCDI_DWORD(data,
2758c2ecf20Sopenharmony_ci			GET_EVQ_TMR_PROPERTIES_OUT_BUG35388_TMR_MAX_COUNT);
2768c2ecf20Sopenharmony_ci		efx->timer_max_ns = max_count * efx->timer_quantum_ns;
2778c2ecf20Sopenharmony_ci	} else {
2788c2ecf20Sopenharmony_ci		efx->timer_quantum_ns = MCDI_DWORD(data,
2798c2ecf20Sopenharmony_ci			GET_EVQ_TMR_PROPERTIES_OUT_TMR_REG_NS_PER_COUNT);
2808c2ecf20Sopenharmony_ci		max_count = MCDI_DWORD(data,
2818c2ecf20Sopenharmony_ci			GET_EVQ_TMR_PROPERTIES_OUT_TMR_REG_MAX_COUNT);
2828c2ecf20Sopenharmony_ci		efx->timer_max_ns = max_count * efx->timer_quantum_ns;
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	netif_dbg(efx, probe, efx->net_dev,
2868c2ecf20Sopenharmony_ci		  "got timer properties from MC: quantum %u ns; max %u ns\n",
2878c2ecf20Sopenharmony_ci		  efx->timer_quantum_ns, efx->timer_max_ns);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic int efx_ef10_get_timer_config(struct efx_nic *efx)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_LEN);
2938c2ecf20Sopenharmony_ci	int rc;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	rc = efx_ef10_get_timer_workarounds(efx);
2968c2ecf20Sopenharmony_ci	if (rc)
2978c2ecf20Sopenharmony_ci		return rc;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_GET_EVQ_TMR_PROPERTIES, NULL, 0,
3008c2ecf20Sopenharmony_ci				outbuf, sizeof(outbuf), NULL);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	if (rc == 0) {
3038c2ecf20Sopenharmony_ci		efx_ef10_process_timer_config(efx, outbuf);
3048c2ecf20Sopenharmony_ci	} else if (rc == -ENOSYS || rc == -EPERM) {
3058c2ecf20Sopenharmony_ci		/* Not available - fall back to Huntington defaults. */
3068c2ecf20Sopenharmony_ci		unsigned int quantum;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci		rc = efx_ef10_get_sysclk_freq(efx);
3098c2ecf20Sopenharmony_ci		if (rc < 0)
3108c2ecf20Sopenharmony_ci			return rc;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci		quantum = 1536000 / rc; /* 1536 cycles */
3138c2ecf20Sopenharmony_ci		efx->timer_quantum_ns = quantum;
3148c2ecf20Sopenharmony_ci		efx->timer_max_ns = efx->type->timer_period_max * quantum;
3158c2ecf20Sopenharmony_ci		rc = 0;
3168c2ecf20Sopenharmony_ci	} else {
3178c2ecf20Sopenharmony_ci		efx_mcdi_display_error(efx, MC_CMD_GET_EVQ_TMR_PROPERTIES,
3188c2ecf20Sopenharmony_ci				       MC_CMD_GET_EVQ_TMR_PROPERTIES_OUT_LEN,
3198c2ecf20Sopenharmony_ci				       NULL, 0, rc);
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	return rc;
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic int efx_ef10_get_mac_address_pf(struct efx_nic *efx, u8 *mac_address)
3268c2ecf20Sopenharmony_ci{
3278c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_MAC_ADDRESSES_OUT_LEN);
3288c2ecf20Sopenharmony_ci	size_t outlen;
3298c2ecf20Sopenharmony_ci	int rc;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_GET_MAC_ADDRESSES_IN_LEN != 0);
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_GET_MAC_ADDRESSES, NULL, 0,
3348c2ecf20Sopenharmony_ci			  outbuf, sizeof(outbuf), &outlen);
3358c2ecf20Sopenharmony_ci	if (rc)
3368c2ecf20Sopenharmony_ci		return rc;
3378c2ecf20Sopenharmony_ci	if (outlen < MC_CMD_GET_MAC_ADDRESSES_OUT_LEN)
3388c2ecf20Sopenharmony_ci		return -EIO;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	ether_addr_copy(mac_address,
3418c2ecf20Sopenharmony_ci			MCDI_PTR(outbuf, GET_MAC_ADDRESSES_OUT_MAC_ADDR_BASE));
3428c2ecf20Sopenharmony_ci	return 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic int efx_ef10_get_mac_address_vf(struct efx_nic *efx, u8 *mac_address)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_GET_MAC_ADDRESSES_IN_LEN);
3488c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMAX);
3498c2ecf20Sopenharmony_ci	size_t outlen;
3508c2ecf20Sopenharmony_ci	int num_addrs, rc;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, VPORT_GET_MAC_ADDRESSES_IN_VPORT_ID,
3538c2ecf20Sopenharmony_ci		       EVB_PORT_ID_ASSIGNED);
3548c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_VPORT_GET_MAC_ADDRESSES, inbuf,
3558c2ecf20Sopenharmony_ci			  sizeof(inbuf), outbuf, sizeof(outbuf), &outlen);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	if (rc)
3588c2ecf20Sopenharmony_ci		return rc;
3598c2ecf20Sopenharmony_ci	if (outlen < MC_CMD_VPORT_GET_MAC_ADDRESSES_OUT_LENMIN)
3608c2ecf20Sopenharmony_ci		return -EIO;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	num_addrs = MCDI_DWORD(outbuf,
3638c2ecf20Sopenharmony_ci			       VPORT_GET_MAC_ADDRESSES_OUT_MACADDR_COUNT);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	WARN_ON(num_addrs != 1);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	ether_addr_copy(mac_address,
3688c2ecf20Sopenharmony_ci			MCDI_PTR(outbuf, VPORT_GET_MAC_ADDRESSES_OUT_MACADDR));
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	return 0;
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic ssize_t efx_ef10_show_link_control_flag(struct device *dev,
3748c2ecf20Sopenharmony_ci					       struct device_attribute *attr,
3758c2ecf20Sopenharmony_ci					       char *buf)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	struct efx_nic *efx = dev_get_drvdata(dev);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n",
3808c2ecf20Sopenharmony_ci		       ((efx->mcdi->fn_flags) &
3818c2ecf20Sopenharmony_ci			(1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL))
3828c2ecf20Sopenharmony_ci		       ? 1 : 0);
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic ssize_t efx_ef10_show_primary_flag(struct device *dev,
3868c2ecf20Sopenharmony_ci					  struct device_attribute *attr,
3878c2ecf20Sopenharmony_ci					  char *buf)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	struct efx_nic *efx = dev_get_drvdata(dev);
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n",
3928c2ecf20Sopenharmony_ci		       ((efx->mcdi->fn_flags) &
3938c2ecf20Sopenharmony_ci			(1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_PRIMARY))
3948c2ecf20Sopenharmony_ci		       ? 1 : 0);
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic struct efx_ef10_vlan *efx_ef10_find_vlan(struct efx_nic *efx, u16 vid)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
4008c2ecf20Sopenharmony_ci	struct efx_ef10_vlan *vlan;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	WARN_ON(!mutex_is_locked(&nic_data->vlan_lock));
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	list_for_each_entry(vlan, &nic_data->vlan_list, list) {
4058c2ecf20Sopenharmony_ci		if (vlan->vid == vid)
4068c2ecf20Sopenharmony_ci			return vlan;
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	return NULL;
4108c2ecf20Sopenharmony_ci}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistatic int efx_ef10_add_vlan(struct efx_nic *efx, u16 vid)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
4158c2ecf20Sopenharmony_ci	struct efx_ef10_vlan *vlan;
4168c2ecf20Sopenharmony_ci	int rc;
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->vlan_lock);
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	vlan = efx_ef10_find_vlan(efx, vid);
4218c2ecf20Sopenharmony_ci	if (vlan) {
4228c2ecf20Sopenharmony_ci		/* We add VID 0 on init. 8021q adds it on module init
4238c2ecf20Sopenharmony_ci		 * for all interfaces with VLAN filtring feature.
4248c2ecf20Sopenharmony_ci		 */
4258c2ecf20Sopenharmony_ci		if (vid == 0)
4268c2ecf20Sopenharmony_ci			goto done_unlock;
4278c2ecf20Sopenharmony_ci		netif_warn(efx, drv, efx->net_dev,
4288c2ecf20Sopenharmony_ci			   "VLAN %u already added\n", vid);
4298c2ecf20Sopenharmony_ci		rc = -EALREADY;
4308c2ecf20Sopenharmony_ci		goto fail_exist;
4318c2ecf20Sopenharmony_ci	}
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	rc = -ENOMEM;
4348c2ecf20Sopenharmony_ci	vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
4358c2ecf20Sopenharmony_ci	if (!vlan)
4368c2ecf20Sopenharmony_ci		goto fail_alloc;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	vlan->vid = vid;
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	list_add_tail(&vlan->list, &nic_data->vlan_list);
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	if (efx->filter_state) {
4438c2ecf20Sopenharmony_ci		mutex_lock(&efx->mac_lock);
4448c2ecf20Sopenharmony_ci		down_write(&efx->filter_sem);
4458c2ecf20Sopenharmony_ci		rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
4468c2ecf20Sopenharmony_ci		up_write(&efx->filter_sem);
4478c2ecf20Sopenharmony_ci		mutex_unlock(&efx->mac_lock);
4488c2ecf20Sopenharmony_ci		if (rc)
4498c2ecf20Sopenharmony_ci			goto fail_filter_add_vlan;
4508c2ecf20Sopenharmony_ci	}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_cidone_unlock:
4538c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->vlan_lock);
4548c2ecf20Sopenharmony_ci	return 0;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_cifail_filter_add_vlan:
4578c2ecf20Sopenharmony_ci	list_del(&vlan->list);
4588c2ecf20Sopenharmony_ci	kfree(vlan);
4598c2ecf20Sopenharmony_cifail_alloc:
4608c2ecf20Sopenharmony_cifail_exist:
4618c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->vlan_lock);
4628c2ecf20Sopenharmony_ci	return rc;
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cistatic void efx_ef10_del_vlan_internal(struct efx_nic *efx,
4668c2ecf20Sopenharmony_ci				       struct efx_ef10_vlan *vlan)
4678c2ecf20Sopenharmony_ci{
4688c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	WARN_ON(!mutex_is_locked(&nic_data->vlan_lock));
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	if (efx->filter_state) {
4738c2ecf20Sopenharmony_ci		down_write(&efx->filter_sem);
4748c2ecf20Sopenharmony_ci		efx_mcdi_filter_del_vlan(efx, vlan->vid);
4758c2ecf20Sopenharmony_ci		up_write(&efx->filter_sem);
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	list_del(&vlan->list);
4798c2ecf20Sopenharmony_ci	kfree(vlan);
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_cistatic int efx_ef10_del_vlan(struct efx_nic *efx, u16 vid)
4838c2ecf20Sopenharmony_ci{
4848c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
4858c2ecf20Sopenharmony_ci	struct efx_ef10_vlan *vlan;
4868c2ecf20Sopenharmony_ci	int rc = 0;
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	/* 8021q removes VID 0 on module unload for all interfaces
4898c2ecf20Sopenharmony_ci	 * with VLAN filtering feature. We need to keep it to receive
4908c2ecf20Sopenharmony_ci	 * untagged traffic.
4918c2ecf20Sopenharmony_ci	 */
4928c2ecf20Sopenharmony_ci	if (vid == 0)
4938c2ecf20Sopenharmony_ci		return 0;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->vlan_lock);
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	vlan = efx_ef10_find_vlan(efx, vid);
4988c2ecf20Sopenharmony_ci	if (!vlan) {
4998c2ecf20Sopenharmony_ci		netif_err(efx, drv, efx->net_dev,
5008c2ecf20Sopenharmony_ci			  "VLAN %u to be deleted not found\n", vid);
5018c2ecf20Sopenharmony_ci		rc = -ENOENT;
5028c2ecf20Sopenharmony_ci	} else {
5038c2ecf20Sopenharmony_ci		efx_ef10_del_vlan_internal(efx, vlan);
5048c2ecf20Sopenharmony_ci	}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->vlan_lock);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	return rc;
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic void efx_ef10_cleanup_vlans(struct efx_nic *efx)
5128c2ecf20Sopenharmony_ci{
5138c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
5148c2ecf20Sopenharmony_ci	struct efx_ef10_vlan *vlan, *next_vlan;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->vlan_lock);
5178c2ecf20Sopenharmony_ci	list_for_each_entry_safe(vlan, next_vlan, &nic_data->vlan_list, list)
5188c2ecf20Sopenharmony_ci		efx_ef10_del_vlan_internal(efx, vlan);
5198c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->vlan_lock);
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_cistatic DEVICE_ATTR(link_control_flag, 0444, efx_ef10_show_link_control_flag,
5238c2ecf20Sopenharmony_ci		   NULL);
5248c2ecf20Sopenharmony_cistatic DEVICE_ATTR(primary_flag, 0444, efx_ef10_show_primary_flag, NULL);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_cistatic int efx_ef10_probe(struct efx_nic *efx)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data;
5298c2ecf20Sopenharmony_ci	int i, rc;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL);
5328c2ecf20Sopenharmony_ci	if (!nic_data)
5338c2ecf20Sopenharmony_ci		return -ENOMEM;
5348c2ecf20Sopenharmony_ci	efx->nic_data = nic_data;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	/* we assume later that we can copy from this buffer in dwords */
5378c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MCDI_CTL_SDU_LEN_MAX_V2 % 4);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	rc = efx_nic_alloc_buffer(efx, &nic_data->mcdi_buf,
5408c2ecf20Sopenharmony_ci				  8 + MCDI_CTL_SDU_LEN_MAX_V2, GFP_KERNEL);
5418c2ecf20Sopenharmony_ci	if (rc)
5428c2ecf20Sopenharmony_ci		goto fail1;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	/* Get the MC's warm boot count.  In case it's rebooting right
5458c2ecf20Sopenharmony_ci	 * now, be prepared to retry.
5468c2ecf20Sopenharmony_ci	 */
5478c2ecf20Sopenharmony_ci	i = 0;
5488c2ecf20Sopenharmony_ci	for (;;) {
5498c2ecf20Sopenharmony_ci		rc = efx_ef10_get_warm_boot_count(efx);
5508c2ecf20Sopenharmony_ci		if (rc >= 0)
5518c2ecf20Sopenharmony_ci			break;
5528c2ecf20Sopenharmony_ci		if (++i == 5)
5538c2ecf20Sopenharmony_ci			goto fail2;
5548c2ecf20Sopenharmony_ci		ssleep(1);
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci	nic_data->warm_boot_count = rc;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	/* In case we're recovering from a crash (kexec), we want to
5598c2ecf20Sopenharmony_ci	 * cancel any outstanding request by the previous user of this
5608c2ecf20Sopenharmony_ci	 * function.  We send a special message using the least
5618c2ecf20Sopenharmony_ci	 * significant bits of the 'high' (doorbell) register.
5628c2ecf20Sopenharmony_ci	 */
5638c2ecf20Sopenharmony_ci	_efx_writed(efx, cpu_to_le32(1), ER_DZ_MC_DB_HWRD);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	rc = efx_mcdi_init(efx);
5668c2ecf20Sopenharmony_ci	if (rc)
5678c2ecf20Sopenharmony_ci		goto fail2;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	mutex_init(&nic_data->udp_tunnels_lock);
5708c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(nic_data->udp_tunnels); ++i)
5718c2ecf20Sopenharmony_ci		nic_data->udp_tunnels[i].type =
5728c2ecf20Sopenharmony_ci			TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	/* Reset (most) configuration for this function */
5758c2ecf20Sopenharmony_ci	rc = efx_mcdi_reset(efx, RESET_TYPE_ALL);
5768c2ecf20Sopenharmony_ci	if (rc)
5778c2ecf20Sopenharmony_ci		goto fail3;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	/* Enable event logging */
5808c2ecf20Sopenharmony_ci	rc = efx_mcdi_log_ctrl(efx, true, false, 0);
5818c2ecf20Sopenharmony_ci	if (rc)
5828c2ecf20Sopenharmony_ci		goto fail3;
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	rc = device_create_file(&efx->pci_dev->dev,
5858c2ecf20Sopenharmony_ci				&dev_attr_link_control_flag);
5868c2ecf20Sopenharmony_ci	if (rc)
5878c2ecf20Sopenharmony_ci		goto fail3;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	rc = device_create_file(&efx->pci_dev->dev, &dev_attr_primary_flag);
5908c2ecf20Sopenharmony_ci	if (rc)
5918c2ecf20Sopenharmony_ci		goto fail4;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	rc = efx_get_pf_index(efx, &nic_data->pf_index);
5948c2ecf20Sopenharmony_ci	if (rc)
5958c2ecf20Sopenharmony_ci		goto fail5;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	rc = efx_ef10_init_datapath_caps(efx);
5988c2ecf20Sopenharmony_ci	if (rc < 0)
5998c2ecf20Sopenharmony_ci		goto fail5;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	efx_ef10_read_licensed_features(efx);
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	/* We can have one VI for each vi_stride-byte region.
6048c2ecf20Sopenharmony_ci	 * However, until we use TX option descriptors we need up to four
6058c2ecf20Sopenharmony_ci	 * TX queues per channel for different checksumming combinations.
6068c2ecf20Sopenharmony_ci	 */
6078c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
6088c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))
6098c2ecf20Sopenharmony_ci		efx->tx_queues_per_channel = 4;
6108c2ecf20Sopenharmony_ci	else
6118c2ecf20Sopenharmony_ci		efx->tx_queues_per_channel = 2;
6128c2ecf20Sopenharmony_ci	efx->max_vis = efx_ef10_mem_map_size(efx) / efx->vi_stride;
6138c2ecf20Sopenharmony_ci	if (!efx->max_vis) {
6148c2ecf20Sopenharmony_ci		netif_err(efx, drv, efx->net_dev, "error determining max VIs\n");
6158c2ecf20Sopenharmony_ci		rc = -EIO;
6168c2ecf20Sopenharmony_ci		goto fail5;
6178c2ecf20Sopenharmony_ci	}
6188c2ecf20Sopenharmony_ci	efx->max_channels = min_t(unsigned int, EFX_MAX_CHANNELS,
6198c2ecf20Sopenharmony_ci				  efx->max_vis / efx->tx_queues_per_channel);
6208c2ecf20Sopenharmony_ci	efx->max_tx_channels = efx->max_channels;
6218c2ecf20Sopenharmony_ci	if (WARN_ON(efx->max_channels == 0)) {
6228c2ecf20Sopenharmony_ci		rc = -EIO;
6238c2ecf20Sopenharmony_ci		goto fail5;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	efx->rx_packet_len_offset =
6278c2ecf20Sopenharmony_ci		ES_DZ_RX_PREFIX_PKTLEN_OFST - ES_DZ_RX_PREFIX_SIZE;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
6308c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_INCLUDE_FCS_LBN))
6318c2ecf20Sopenharmony_ci		efx->net_dev->hw_features |= NETIF_F_RXFCS;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	rc = efx_mcdi_port_get_number(efx);
6348c2ecf20Sopenharmony_ci	if (rc < 0)
6358c2ecf20Sopenharmony_ci		goto fail5;
6368c2ecf20Sopenharmony_ci	efx->port_num = rc;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	rc = efx->type->get_mac_address(efx, efx->net_dev->perm_addr);
6398c2ecf20Sopenharmony_ci	if (rc)
6408c2ecf20Sopenharmony_ci		goto fail5;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	rc = efx_ef10_get_timer_config(efx);
6438c2ecf20Sopenharmony_ci	if (rc < 0)
6448c2ecf20Sopenharmony_ci		goto fail5;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	rc = efx_mcdi_mon_probe(efx);
6478c2ecf20Sopenharmony_ci	if (rc && rc != -EPERM)
6488c2ecf20Sopenharmony_ci		goto fail5;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	efx_ptp_defer_probe_with_channel(efx);
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
6538c2ecf20Sopenharmony_ci	if ((efx->pci_dev->physfn) && (!efx->pci_dev->is_physfn)) {
6548c2ecf20Sopenharmony_ci		struct pci_dev *pci_dev_pf = efx->pci_dev->physfn;
6558c2ecf20Sopenharmony_ci		struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci		efx_pf->type->get_mac_address(efx_pf, nic_data->port_id);
6588c2ecf20Sopenharmony_ci	} else
6598c2ecf20Sopenharmony_ci#endif
6608c2ecf20Sopenharmony_ci		ether_addr_copy(nic_data->port_id, efx->net_dev->perm_addr);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&nic_data->vlan_list);
6638c2ecf20Sopenharmony_ci	mutex_init(&nic_data->vlan_lock);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	/* Add unspecified VID to support VLAN filtering being disabled */
6668c2ecf20Sopenharmony_ci	rc = efx_ef10_add_vlan(efx, EFX_FILTER_VID_UNSPEC);
6678c2ecf20Sopenharmony_ci	if (rc)
6688c2ecf20Sopenharmony_ci		goto fail_add_vid_unspec;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	/* If VLAN filtering is enabled, we need VID 0 to get untagged
6718c2ecf20Sopenharmony_ci	 * traffic.  It is added automatically if 8021q module is loaded,
6728c2ecf20Sopenharmony_ci	 * but we can't rely on it since module may be not loaded.
6738c2ecf20Sopenharmony_ci	 */
6748c2ecf20Sopenharmony_ci	rc = efx_ef10_add_vlan(efx, 0);
6758c2ecf20Sopenharmony_ci	if (rc)
6768c2ecf20Sopenharmony_ci		goto fail_add_vid_0;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
6798c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN) &&
6808c2ecf20Sopenharmony_ci	    efx->mcdi->fn_flags &
6818c2ecf20Sopenharmony_ci	    (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_TRUSTED))
6828c2ecf20Sopenharmony_ci		efx->net_dev->udp_tunnel_nic_info = &efx_ef10_udp_tunnels;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	return 0;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_cifail_add_vid_0:
6878c2ecf20Sopenharmony_ci	efx_ef10_cleanup_vlans(efx);
6888c2ecf20Sopenharmony_cifail_add_vid_unspec:
6898c2ecf20Sopenharmony_ci	mutex_destroy(&nic_data->vlan_lock);
6908c2ecf20Sopenharmony_ci	efx_ptp_remove(efx);
6918c2ecf20Sopenharmony_ci	efx_mcdi_mon_remove(efx);
6928c2ecf20Sopenharmony_cifail5:
6938c2ecf20Sopenharmony_ci	device_remove_file(&efx->pci_dev->dev, &dev_attr_primary_flag);
6948c2ecf20Sopenharmony_cifail4:
6958c2ecf20Sopenharmony_ci	device_remove_file(&efx->pci_dev->dev, &dev_attr_link_control_flag);
6968c2ecf20Sopenharmony_cifail3:
6978c2ecf20Sopenharmony_ci	efx_mcdi_detach(efx);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->udp_tunnels_lock);
7008c2ecf20Sopenharmony_ci	memset(nic_data->udp_tunnels, 0, sizeof(nic_data->udp_tunnels));
7018c2ecf20Sopenharmony_ci	(void)efx_ef10_set_udp_tnl_ports(efx, true);
7028c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->udp_tunnels_lock);
7038c2ecf20Sopenharmony_ci	mutex_destroy(&nic_data->udp_tunnels_lock);
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	efx_mcdi_fini(efx);
7068c2ecf20Sopenharmony_cifail2:
7078c2ecf20Sopenharmony_ci	efx_nic_free_buffer(efx, &nic_data->mcdi_buf);
7088c2ecf20Sopenharmony_cifail1:
7098c2ecf20Sopenharmony_ci	kfree(nic_data);
7108c2ecf20Sopenharmony_ci	efx->nic_data = NULL;
7118c2ecf20Sopenharmony_ci	return rc;
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci#ifdef EFX_USE_PIO
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_cistatic void efx_ef10_free_piobufs(struct efx_nic *efx)
7178c2ecf20Sopenharmony_ci{
7188c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
7198c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_FREE_PIOBUF_IN_LEN);
7208c2ecf20Sopenharmony_ci	unsigned int i;
7218c2ecf20Sopenharmony_ci	int rc;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_FREE_PIOBUF_OUT_LEN != 0);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	for (i = 0; i < nic_data->n_piobufs; i++) {
7268c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, FREE_PIOBUF_IN_PIOBUF_HANDLE,
7278c2ecf20Sopenharmony_ci			       nic_data->piobuf_handle[i]);
7288c2ecf20Sopenharmony_ci		rc = efx_mcdi_rpc(efx, MC_CMD_FREE_PIOBUF, inbuf, sizeof(inbuf),
7298c2ecf20Sopenharmony_ci				  NULL, 0, NULL);
7308c2ecf20Sopenharmony_ci		WARN_ON(rc);
7318c2ecf20Sopenharmony_ci	}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	nic_data->n_piobufs = 0;
7348c2ecf20Sopenharmony_ci}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_cistatic int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
7398c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_ALLOC_PIOBUF_OUT_LEN);
7408c2ecf20Sopenharmony_ci	unsigned int i;
7418c2ecf20Sopenharmony_ci	size_t outlen;
7428c2ecf20Sopenharmony_ci	int rc = 0;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_ALLOC_PIOBUF_IN_LEN != 0);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
7478c2ecf20Sopenharmony_ci		rc = efx_mcdi_rpc_quiet(efx, MC_CMD_ALLOC_PIOBUF, NULL, 0,
7488c2ecf20Sopenharmony_ci					outbuf, sizeof(outbuf), &outlen);
7498c2ecf20Sopenharmony_ci		if (rc) {
7508c2ecf20Sopenharmony_ci			/* Don't display the MC error if we didn't have space
7518c2ecf20Sopenharmony_ci			 * for a VF.
7528c2ecf20Sopenharmony_ci			 */
7538c2ecf20Sopenharmony_ci			if (!(efx_ef10_is_vf(efx) && rc == -ENOSPC))
7548c2ecf20Sopenharmony_ci				efx_mcdi_display_error(efx, MC_CMD_ALLOC_PIOBUF,
7558c2ecf20Sopenharmony_ci						       0, outbuf, outlen, rc);
7568c2ecf20Sopenharmony_ci			break;
7578c2ecf20Sopenharmony_ci		}
7588c2ecf20Sopenharmony_ci		if (outlen < MC_CMD_ALLOC_PIOBUF_OUT_LEN) {
7598c2ecf20Sopenharmony_ci			rc = -EIO;
7608c2ecf20Sopenharmony_ci			break;
7618c2ecf20Sopenharmony_ci		}
7628c2ecf20Sopenharmony_ci		nic_data->piobuf_handle[i] =
7638c2ecf20Sopenharmony_ci			MCDI_DWORD(outbuf, ALLOC_PIOBUF_OUT_PIOBUF_HANDLE);
7648c2ecf20Sopenharmony_ci		netif_dbg(efx, probe, efx->net_dev,
7658c2ecf20Sopenharmony_ci			  "allocated PIO buffer %u handle %x\n", i,
7668c2ecf20Sopenharmony_ci			  nic_data->piobuf_handle[i]);
7678c2ecf20Sopenharmony_ci	}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci	nic_data->n_piobufs = i;
7708c2ecf20Sopenharmony_ci	if (rc)
7718c2ecf20Sopenharmony_ci		efx_ef10_free_piobufs(efx);
7728c2ecf20Sopenharmony_ci	return rc;
7738c2ecf20Sopenharmony_ci}
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_cistatic int efx_ef10_link_piobufs(struct efx_nic *efx)
7768c2ecf20Sopenharmony_ci{
7778c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
7788c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_LINK_PIOBUF_IN_LEN);
7798c2ecf20Sopenharmony_ci	struct efx_channel *channel;
7808c2ecf20Sopenharmony_ci	struct efx_tx_queue *tx_queue;
7818c2ecf20Sopenharmony_ci	unsigned int offset, index;
7828c2ecf20Sopenharmony_ci	int rc;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_LINK_PIOBUF_OUT_LEN != 0);
7858c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_UNLINK_PIOBUF_OUT_LEN != 0);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	/* Link a buffer to each VI in the write-combining mapping */
7888c2ecf20Sopenharmony_ci	for (index = 0; index < nic_data->n_piobufs; ++index) {
7898c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_PIOBUF_HANDLE,
7908c2ecf20Sopenharmony_ci			       nic_data->piobuf_handle[index]);
7918c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, LINK_PIOBUF_IN_TXQ_INSTANCE,
7928c2ecf20Sopenharmony_ci			       nic_data->pio_write_vi_base + index);
7938c2ecf20Sopenharmony_ci		rc = efx_mcdi_rpc(efx, MC_CMD_LINK_PIOBUF,
7948c2ecf20Sopenharmony_ci				  inbuf, MC_CMD_LINK_PIOBUF_IN_LEN,
7958c2ecf20Sopenharmony_ci				  NULL, 0, NULL);
7968c2ecf20Sopenharmony_ci		if (rc) {
7978c2ecf20Sopenharmony_ci			netif_err(efx, drv, efx->net_dev,
7988c2ecf20Sopenharmony_ci				  "failed to link VI %u to PIO buffer %u (%d)\n",
7998c2ecf20Sopenharmony_ci				  nic_data->pio_write_vi_base + index, index,
8008c2ecf20Sopenharmony_ci				  rc);
8018c2ecf20Sopenharmony_ci			goto fail;
8028c2ecf20Sopenharmony_ci		}
8038c2ecf20Sopenharmony_ci		netif_dbg(efx, probe, efx->net_dev,
8048c2ecf20Sopenharmony_ci			  "linked VI %u to PIO buffer %u\n",
8058c2ecf20Sopenharmony_ci			  nic_data->pio_write_vi_base + index, index);
8068c2ecf20Sopenharmony_ci	}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	/* Link a buffer to each TX queue */
8098c2ecf20Sopenharmony_ci	efx_for_each_channel(channel, efx) {
8108c2ecf20Sopenharmony_ci		/* Extra channels, even those with TXQs (PTP), do not require
8118c2ecf20Sopenharmony_ci		 * PIO resources.
8128c2ecf20Sopenharmony_ci		 */
8138c2ecf20Sopenharmony_ci		if (!channel->type->want_pio ||
8148c2ecf20Sopenharmony_ci		    channel->channel >= efx->xdp_channel_offset)
8158c2ecf20Sopenharmony_ci			continue;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci		efx_for_each_channel_tx_queue(tx_queue, channel) {
8188c2ecf20Sopenharmony_ci			/* We assign the PIO buffers to queues in
8198c2ecf20Sopenharmony_ci			 * reverse order to allow for the following
8208c2ecf20Sopenharmony_ci			 * special case.
8218c2ecf20Sopenharmony_ci			 */
8228c2ecf20Sopenharmony_ci			offset = ((efx->tx_channel_offset + efx->n_tx_channels -
8238c2ecf20Sopenharmony_ci				   tx_queue->channel->channel - 1) *
8248c2ecf20Sopenharmony_ci				  efx_piobuf_size);
8258c2ecf20Sopenharmony_ci			index = offset / nic_data->piobuf_size;
8268c2ecf20Sopenharmony_ci			offset = offset % nic_data->piobuf_size;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci			/* When the host page size is 4K, the first
8298c2ecf20Sopenharmony_ci			 * host page in the WC mapping may be within
8308c2ecf20Sopenharmony_ci			 * the same VI page as the last TX queue.  We
8318c2ecf20Sopenharmony_ci			 * can only link one buffer to each VI.
8328c2ecf20Sopenharmony_ci			 */
8338c2ecf20Sopenharmony_ci			if (tx_queue->queue == nic_data->pio_write_vi_base) {
8348c2ecf20Sopenharmony_ci				BUG_ON(index != 0);
8358c2ecf20Sopenharmony_ci				rc = 0;
8368c2ecf20Sopenharmony_ci			} else {
8378c2ecf20Sopenharmony_ci				MCDI_SET_DWORD(inbuf,
8388c2ecf20Sopenharmony_ci					       LINK_PIOBUF_IN_PIOBUF_HANDLE,
8398c2ecf20Sopenharmony_ci					       nic_data->piobuf_handle[index]);
8408c2ecf20Sopenharmony_ci				MCDI_SET_DWORD(inbuf,
8418c2ecf20Sopenharmony_ci					       LINK_PIOBUF_IN_TXQ_INSTANCE,
8428c2ecf20Sopenharmony_ci					       tx_queue->queue);
8438c2ecf20Sopenharmony_ci				rc = efx_mcdi_rpc(efx, MC_CMD_LINK_PIOBUF,
8448c2ecf20Sopenharmony_ci						  inbuf, MC_CMD_LINK_PIOBUF_IN_LEN,
8458c2ecf20Sopenharmony_ci						  NULL, 0, NULL);
8468c2ecf20Sopenharmony_ci			}
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci			if (rc) {
8498c2ecf20Sopenharmony_ci				/* This is non-fatal; the TX path just
8508c2ecf20Sopenharmony_ci				 * won't use PIO for this queue
8518c2ecf20Sopenharmony_ci				 */
8528c2ecf20Sopenharmony_ci				netif_err(efx, drv, efx->net_dev,
8538c2ecf20Sopenharmony_ci					  "failed to link VI %u to PIO buffer %u (%d)\n",
8548c2ecf20Sopenharmony_ci					  tx_queue->queue, index, rc);
8558c2ecf20Sopenharmony_ci				tx_queue->piobuf = NULL;
8568c2ecf20Sopenharmony_ci			} else {
8578c2ecf20Sopenharmony_ci				tx_queue->piobuf =
8588c2ecf20Sopenharmony_ci					nic_data->pio_write_base +
8598c2ecf20Sopenharmony_ci					index * efx->vi_stride + offset;
8608c2ecf20Sopenharmony_ci				tx_queue->piobuf_offset = offset;
8618c2ecf20Sopenharmony_ci				netif_dbg(efx, probe, efx->net_dev,
8628c2ecf20Sopenharmony_ci					  "linked VI %u to PIO buffer %u offset %x addr %p\n",
8638c2ecf20Sopenharmony_ci					  tx_queue->queue, index,
8648c2ecf20Sopenharmony_ci					  tx_queue->piobuf_offset,
8658c2ecf20Sopenharmony_ci					  tx_queue->piobuf);
8668c2ecf20Sopenharmony_ci			}
8678c2ecf20Sopenharmony_ci		}
8688c2ecf20Sopenharmony_ci	}
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	return 0;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cifail:
8738c2ecf20Sopenharmony_ci	/* inbuf was defined for MC_CMD_LINK_PIOBUF.  We can use the same
8748c2ecf20Sopenharmony_ci	 * buffer for MC_CMD_UNLINK_PIOBUF because it's shorter.
8758c2ecf20Sopenharmony_ci	 */
8768c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_LINK_PIOBUF_IN_LEN < MC_CMD_UNLINK_PIOBUF_IN_LEN);
8778c2ecf20Sopenharmony_ci	while (index--) {
8788c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, UNLINK_PIOBUF_IN_TXQ_INSTANCE,
8798c2ecf20Sopenharmony_ci			       nic_data->pio_write_vi_base + index);
8808c2ecf20Sopenharmony_ci		efx_mcdi_rpc(efx, MC_CMD_UNLINK_PIOBUF,
8818c2ecf20Sopenharmony_ci			     inbuf, MC_CMD_UNLINK_PIOBUF_IN_LEN,
8828c2ecf20Sopenharmony_ci			     NULL, 0, NULL);
8838c2ecf20Sopenharmony_ci	}
8848c2ecf20Sopenharmony_ci	return rc;
8858c2ecf20Sopenharmony_ci}
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_cistatic void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
8888c2ecf20Sopenharmony_ci{
8898c2ecf20Sopenharmony_ci	struct efx_channel *channel;
8908c2ecf20Sopenharmony_ci	struct efx_tx_queue *tx_queue;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	/* All our existing PIO buffers went away */
8938c2ecf20Sopenharmony_ci	efx_for_each_channel(channel, efx)
8948c2ecf20Sopenharmony_ci		efx_for_each_channel_tx_queue(tx_queue, channel)
8958c2ecf20Sopenharmony_ci			tx_queue->piobuf = NULL;
8968c2ecf20Sopenharmony_ci}
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci#else /* !EFX_USE_PIO */
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_cistatic int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	return n == 0 ? 0 : -ENOBUFS;
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic int efx_ef10_link_piobufs(struct efx_nic *efx)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	return 0;
9088c2ecf20Sopenharmony_ci}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_cistatic void efx_ef10_free_piobufs(struct efx_nic *efx)
9118c2ecf20Sopenharmony_ci{
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_cistatic void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci#endif /* EFX_USE_PIO */
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_cistatic void efx_ef10_remove(struct efx_nic *efx)
9218c2ecf20Sopenharmony_ci{
9228c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
9238c2ecf20Sopenharmony_ci	int rc;
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
9268c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data_pf;
9278c2ecf20Sopenharmony_ci	struct pci_dev *pci_dev_pf;
9288c2ecf20Sopenharmony_ci	struct efx_nic *efx_pf;
9298c2ecf20Sopenharmony_ci	struct ef10_vf *vf;
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	if (efx->pci_dev->is_virtfn) {
9328c2ecf20Sopenharmony_ci		pci_dev_pf = efx->pci_dev->physfn;
9338c2ecf20Sopenharmony_ci		if (pci_dev_pf) {
9348c2ecf20Sopenharmony_ci			efx_pf = pci_get_drvdata(pci_dev_pf);
9358c2ecf20Sopenharmony_ci			nic_data_pf = efx_pf->nic_data;
9368c2ecf20Sopenharmony_ci			vf = nic_data_pf->vf + nic_data->vf_index;
9378c2ecf20Sopenharmony_ci			vf->efx = NULL;
9388c2ecf20Sopenharmony_ci		} else
9398c2ecf20Sopenharmony_ci			netif_info(efx, drv, efx->net_dev,
9408c2ecf20Sopenharmony_ci				   "Could not get the PF id from VF\n");
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci#endif
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	efx_ef10_cleanup_vlans(efx);
9458c2ecf20Sopenharmony_ci	mutex_destroy(&nic_data->vlan_lock);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	efx_ptp_remove(efx);
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	efx_mcdi_mon_remove(efx);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	efx_mcdi_rx_free_indir_table(efx);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci	if (nic_data->wc_membase)
9548c2ecf20Sopenharmony_ci		iounmap(nic_data->wc_membase);
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	rc = efx_mcdi_free_vis(efx);
9578c2ecf20Sopenharmony_ci	WARN_ON(rc != 0);
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	if (!nic_data->must_restore_piobufs)
9608c2ecf20Sopenharmony_ci		efx_ef10_free_piobufs(efx);
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci	device_remove_file(&efx->pci_dev->dev, &dev_attr_primary_flag);
9638c2ecf20Sopenharmony_ci	device_remove_file(&efx->pci_dev->dev, &dev_attr_link_control_flag);
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_ci	efx_mcdi_detach(efx);
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	memset(nic_data->udp_tunnels, 0, sizeof(nic_data->udp_tunnels));
9688c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->udp_tunnels_lock);
9698c2ecf20Sopenharmony_ci	(void)efx_ef10_set_udp_tnl_ports(efx, true);
9708c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->udp_tunnels_lock);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	mutex_destroy(&nic_data->udp_tunnels_lock);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	efx_mcdi_fini(efx);
9758c2ecf20Sopenharmony_ci	efx_nic_free_buffer(efx, &nic_data->mcdi_buf);
9768c2ecf20Sopenharmony_ci	kfree(nic_data);
9778c2ecf20Sopenharmony_ci}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_cistatic int efx_ef10_probe_pf(struct efx_nic *efx)
9808c2ecf20Sopenharmony_ci{
9818c2ecf20Sopenharmony_ci	return efx_ef10_probe(efx);
9828c2ecf20Sopenharmony_ci}
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ciint efx_ef10_vadaptor_query(struct efx_nic *efx, unsigned int port_id,
9858c2ecf20Sopenharmony_ci			    u32 *port_flags, u32 *vadaptor_flags,
9868c2ecf20Sopenharmony_ci			    unsigned int *vlan_tags)
9878c2ecf20Sopenharmony_ci{
9888c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
9898c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_QUERY_IN_LEN);
9908c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_VADAPTOR_QUERY_OUT_LEN);
9918c2ecf20Sopenharmony_ci	size_t outlen;
9928c2ecf20Sopenharmony_ci	int rc;
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
9958c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_VADAPTOR_QUERY_LBN)) {
9968c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, VADAPTOR_QUERY_IN_UPSTREAM_PORT_ID,
9978c2ecf20Sopenharmony_ci			       port_id);
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci		rc = efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_QUERY, inbuf, sizeof(inbuf),
10008c2ecf20Sopenharmony_ci				  outbuf, sizeof(outbuf), &outlen);
10018c2ecf20Sopenharmony_ci		if (rc)
10028c2ecf20Sopenharmony_ci			return rc;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		if (outlen < sizeof(outbuf)) {
10058c2ecf20Sopenharmony_ci			rc = -EIO;
10068c2ecf20Sopenharmony_ci			return rc;
10078c2ecf20Sopenharmony_ci		}
10088c2ecf20Sopenharmony_ci	}
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	if (port_flags)
10118c2ecf20Sopenharmony_ci		*port_flags = MCDI_DWORD(outbuf, VADAPTOR_QUERY_OUT_PORT_FLAGS);
10128c2ecf20Sopenharmony_ci	if (vadaptor_flags)
10138c2ecf20Sopenharmony_ci		*vadaptor_flags =
10148c2ecf20Sopenharmony_ci			MCDI_DWORD(outbuf, VADAPTOR_QUERY_OUT_VADAPTOR_FLAGS);
10158c2ecf20Sopenharmony_ci	if (vlan_tags)
10168c2ecf20Sopenharmony_ci		*vlan_tags =
10178c2ecf20Sopenharmony_ci			MCDI_DWORD(outbuf,
10188c2ecf20Sopenharmony_ci				   VADAPTOR_QUERY_OUT_NUM_AVAILABLE_VLAN_TAGS);
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	return 0;
10218c2ecf20Sopenharmony_ci}
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ciint efx_ef10_vadaptor_alloc(struct efx_nic *efx, unsigned int port_id)
10248c2ecf20Sopenharmony_ci{
10258c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_ALLOC_IN_LEN);
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, VADAPTOR_ALLOC_IN_UPSTREAM_PORT_ID, port_id);
10288c2ecf20Sopenharmony_ci	return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_ALLOC, inbuf, sizeof(inbuf),
10298c2ecf20Sopenharmony_ci			    NULL, 0, NULL);
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ciint efx_ef10_vadaptor_free(struct efx_nic *efx, unsigned int port_id)
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_FREE_IN_LEN);
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, VADAPTOR_FREE_IN_UPSTREAM_PORT_ID, port_id);
10378c2ecf20Sopenharmony_ci	return efx_mcdi_rpc(efx, MC_CMD_VADAPTOR_FREE, inbuf, sizeof(inbuf),
10388c2ecf20Sopenharmony_ci			    NULL, 0, NULL);
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ciint efx_ef10_vport_add_mac(struct efx_nic *efx,
10428c2ecf20Sopenharmony_ci			   unsigned int port_id, u8 *mac)
10438c2ecf20Sopenharmony_ci{
10448c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_ADD_MAC_ADDRESS_IN_LEN);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, VPORT_ADD_MAC_ADDRESS_IN_VPORT_ID, port_id);
10478c2ecf20Sopenharmony_ci	ether_addr_copy(MCDI_PTR(inbuf, VPORT_ADD_MAC_ADDRESS_IN_MACADDR), mac);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	return efx_mcdi_rpc(efx, MC_CMD_VPORT_ADD_MAC_ADDRESS, inbuf,
10508c2ecf20Sopenharmony_ci			    sizeof(inbuf), NULL, 0, NULL);
10518c2ecf20Sopenharmony_ci}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ciint efx_ef10_vport_del_mac(struct efx_nic *efx,
10548c2ecf20Sopenharmony_ci			   unsigned int port_id, u8 *mac)
10558c2ecf20Sopenharmony_ci{
10568c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VPORT_DEL_MAC_ADDRESS_IN_LEN);
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, VPORT_DEL_MAC_ADDRESS_IN_VPORT_ID, port_id);
10598c2ecf20Sopenharmony_ci	ether_addr_copy(MCDI_PTR(inbuf, VPORT_DEL_MAC_ADDRESS_IN_MACADDR), mac);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	return efx_mcdi_rpc(efx, MC_CMD_VPORT_DEL_MAC_ADDRESS, inbuf,
10628c2ecf20Sopenharmony_ci			    sizeof(inbuf), NULL, 0, NULL);
10638c2ecf20Sopenharmony_ci}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
10668c2ecf20Sopenharmony_cistatic int efx_ef10_probe_vf(struct efx_nic *efx)
10678c2ecf20Sopenharmony_ci{
10688c2ecf20Sopenharmony_ci	int rc;
10698c2ecf20Sopenharmony_ci	struct pci_dev *pci_dev_pf;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	/* If the parent PF has no VF data structure, it doesn't know about this
10728c2ecf20Sopenharmony_ci	 * VF so fail probe.  The VF needs to be re-created.  This can happen
10738c2ecf20Sopenharmony_ci	 * if the PF driver is unloaded while the VF is assigned to a guest.
10748c2ecf20Sopenharmony_ci	 */
10758c2ecf20Sopenharmony_ci	pci_dev_pf = efx->pci_dev->physfn;
10768c2ecf20Sopenharmony_ci	if (pci_dev_pf) {
10778c2ecf20Sopenharmony_ci		struct efx_nic *efx_pf = pci_get_drvdata(pci_dev_pf);
10788c2ecf20Sopenharmony_ci		struct efx_ef10_nic_data *nic_data_pf = efx_pf->nic_data;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci		if (!nic_data_pf->vf) {
10818c2ecf20Sopenharmony_ci			netif_info(efx, drv, efx->net_dev,
10828c2ecf20Sopenharmony_ci				   "The VF cannot link to its parent PF; "
10838c2ecf20Sopenharmony_ci				   "please destroy and re-create the VF\n");
10848c2ecf20Sopenharmony_ci			return -EBUSY;
10858c2ecf20Sopenharmony_ci		}
10868c2ecf20Sopenharmony_ci	}
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	rc = efx_ef10_probe(efx);
10898c2ecf20Sopenharmony_ci	if (rc)
10908c2ecf20Sopenharmony_ci		return rc;
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	rc = efx_ef10_get_vf_index(efx);
10938c2ecf20Sopenharmony_ci	if (rc)
10948c2ecf20Sopenharmony_ci		goto fail;
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	if (efx->pci_dev->is_virtfn) {
10978c2ecf20Sopenharmony_ci		if (efx->pci_dev->physfn) {
10988c2ecf20Sopenharmony_ci			struct efx_nic *efx_pf =
10998c2ecf20Sopenharmony_ci				pci_get_drvdata(efx->pci_dev->physfn);
11008c2ecf20Sopenharmony_ci			struct efx_ef10_nic_data *nic_data_p = efx_pf->nic_data;
11018c2ecf20Sopenharmony_ci			struct efx_ef10_nic_data *nic_data = efx->nic_data;
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci			nic_data_p->vf[nic_data->vf_index].efx = efx;
11048c2ecf20Sopenharmony_ci			nic_data_p->vf[nic_data->vf_index].pci_dev =
11058c2ecf20Sopenharmony_ci				efx->pci_dev;
11068c2ecf20Sopenharmony_ci		} else
11078c2ecf20Sopenharmony_ci			netif_info(efx, drv, efx->net_dev,
11088c2ecf20Sopenharmony_ci				   "Could not get the PF id from VF\n");
11098c2ecf20Sopenharmony_ci	}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	return 0;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_cifail:
11148c2ecf20Sopenharmony_ci	efx_ef10_remove(efx);
11158c2ecf20Sopenharmony_ci	return rc;
11168c2ecf20Sopenharmony_ci}
11178c2ecf20Sopenharmony_ci#else
11188c2ecf20Sopenharmony_cistatic int efx_ef10_probe_vf(struct efx_nic *efx __attribute__ ((unused)))
11198c2ecf20Sopenharmony_ci{
11208c2ecf20Sopenharmony_ci	return 0;
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci#endif
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_cistatic int efx_ef10_alloc_vis(struct efx_nic *efx,
11258c2ecf20Sopenharmony_ci			      unsigned int min_vis, unsigned int max_vis)
11268c2ecf20Sopenharmony_ci{
11278c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	return efx_mcdi_alloc_vis(efx, min_vis, max_vis, &nic_data->vi_base,
11308c2ecf20Sopenharmony_ci				  &nic_data->n_allocated_vis);
11318c2ecf20Sopenharmony_ci}
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci/* Note that the failure path of this function does not free
11348c2ecf20Sopenharmony_ci * resources, as this will be done by efx_ef10_remove().
11358c2ecf20Sopenharmony_ci */
11368c2ecf20Sopenharmony_cistatic int efx_ef10_dimension_resources(struct efx_nic *efx)
11378c2ecf20Sopenharmony_ci{
11388c2ecf20Sopenharmony_ci	unsigned int min_vis = max_t(unsigned int, efx->tx_queues_per_channel,
11398c2ecf20Sopenharmony_ci				     efx_separate_tx_channels ? 2 : 1);
11408c2ecf20Sopenharmony_ci	unsigned int channel_vis, pio_write_vi_base, max_vis;
11418c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
11428c2ecf20Sopenharmony_ci	unsigned int uc_mem_map_size, wc_mem_map_size;
11438c2ecf20Sopenharmony_ci	void __iomem *membase;
11448c2ecf20Sopenharmony_ci	int rc;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	channel_vis = max(efx->n_channels,
11478c2ecf20Sopenharmony_ci			  ((efx->n_tx_channels + efx->n_extra_tx_channels) *
11488c2ecf20Sopenharmony_ci			   efx->tx_queues_per_channel) +
11498c2ecf20Sopenharmony_ci			   efx->n_xdp_channels * efx->xdp_tx_per_channel);
11508c2ecf20Sopenharmony_ci	if (efx->max_vis && efx->max_vis < channel_vis) {
11518c2ecf20Sopenharmony_ci		netif_dbg(efx, drv, efx->net_dev,
11528c2ecf20Sopenharmony_ci			  "Reducing channel VIs from %u to %u\n",
11538c2ecf20Sopenharmony_ci			  channel_vis, efx->max_vis);
11548c2ecf20Sopenharmony_ci		channel_vis = efx->max_vis;
11558c2ecf20Sopenharmony_ci	}
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci#ifdef EFX_USE_PIO
11588c2ecf20Sopenharmony_ci	/* Try to allocate PIO buffers if wanted and if the full
11598c2ecf20Sopenharmony_ci	 * number of PIO buffers would be sufficient to allocate one
11608c2ecf20Sopenharmony_ci	 * copy-buffer per TX channel.  Failure is non-fatal, as there
11618c2ecf20Sopenharmony_ci	 * are only a small number of PIO buffers shared between all
11628c2ecf20Sopenharmony_ci	 * functions of the controller.
11638c2ecf20Sopenharmony_ci	 */
11648c2ecf20Sopenharmony_ci	if (efx_piobuf_size != 0 &&
11658c2ecf20Sopenharmony_ci	    nic_data->piobuf_size / efx_piobuf_size * EF10_TX_PIOBUF_COUNT >=
11668c2ecf20Sopenharmony_ci	    efx->n_tx_channels) {
11678c2ecf20Sopenharmony_ci		unsigned int n_piobufs =
11688c2ecf20Sopenharmony_ci			DIV_ROUND_UP(efx->n_tx_channels,
11698c2ecf20Sopenharmony_ci				     nic_data->piobuf_size / efx_piobuf_size);
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci		rc = efx_ef10_alloc_piobufs(efx, n_piobufs);
11728c2ecf20Sopenharmony_ci		if (rc == -ENOSPC)
11738c2ecf20Sopenharmony_ci			netif_dbg(efx, probe, efx->net_dev,
11748c2ecf20Sopenharmony_ci				  "out of PIO buffers; cannot allocate more\n");
11758c2ecf20Sopenharmony_ci		else if (rc == -EPERM)
11768c2ecf20Sopenharmony_ci			netif_dbg(efx, probe, efx->net_dev,
11778c2ecf20Sopenharmony_ci				  "not permitted to allocate PIO buffers\n");
11788c2ecf20Sopenharmony_ci		else if (rc)
11798c2ecf20Sopenharmony_ci			netif_err(efx, probe, efx->net_dev,
11808c2ecf20Sopenharmony_ci				  "failed to allocate PIO buffers (%d)\n", rc);
11818c2ecf20Sopenharmony_ci		else
11828c2ecf20Sopenharmony_ci			netif_dbg(efx, probe, efx->net_dev,
11838c2ecf20Sopenharmony_ci				  "allocated %u PIO buffers\n", n_piobufs);
11848c2ecf20Sopenharmony_ci	}
11858c2ecf20Sopenharmony_ci#else
11868c2ecf20Sopenharmony_ci	nic_data->n_piobufs = 0;
11878c2ecf20Sopenharmony_ci#endif
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	/* PIO buffers should be mapped with write-combining enabled,
11908c2ecf20Sopenharmony_ci	 * and we want to make single UC and WC mappings rather than
11918c2ecf20Sopenharmony_ci	 * several of each (in fact that's the only option if host
11928c2ecf20Sopenharmony_ci	 * page size is >4K).  So we may allocate some extra VIs just
11938c2ecf20Sopenharmony_ci	 * for writing PIO buffers through.
11948c2ecf20Sopenharmony_ci	 *
11958c2ecf20Sopenharmony_ci	 * The UC mapping contains (channel_vis - 1) complete VIs and the
11968c2ecf20Sopenharmony_ci	 * first 4K of the next VI.  Then the WC mapping begins with
11978c2ecf20Sopenharmony_ci	 * the remainder of this last VI.
11988c2ecf20Sopenharmony_ci	 */
11998c2ecf20Sopenharmony_ci	uc_mem_map_size = PAGE_ALIGN((channel_vis - 1) * efx->vi_stride +
12008c2ecf20Sopenharmony_ci				     ER_DZ_TX_PIOBUF);
12018c2ecf20Sopenharmony_ci	if (nic_data->n_piobufs) {
12028c2ecf20Sopenharmony_ci		/* pio_write_vi_base rounds down to give the number of complete
12038c2ecf20Sopenharmony_ci		 * VIs inside the UC mapping.
12048c2ecf20Sopenharmony_ci		 */
12058c2ecf20Sopenharmony_ci		pio_write_vi_base = uc_mem_map_size / efx->vi_stride;
12068c2ecf20Sopenharmony_ci		wc_mem_map_size = (PAGE_ALIGN((pio_write_vi_base +
12078c2ecf20Sopenharmony_ci					       nic_data->n_piobufs) *
12088c2ecf20Sopenharmony_ci					      efx->vi_stride) -
12098c2ecf20Sopenharmony_ci				   uc_mem_map_size);
12108c2ecf20Sopenharmony_ci		max_vis = pio_write_vi_base + nic_data->n_piobufs;
12118c2ecf20Sopenharmony_ci	} else {
12128c2ecf20Sopenharmony_ci		pio_write_vi_base = 0;
12138c2ecf20Sopenharmony_ci		wc_mem_map_size = 0;
12148c2ecf20Sopenharmony_ci		max_vis = channel_vis;
12158c2ecf20Sopenharmony_ci	}
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	/* In case the last attached driver failed to free VIs, do it now */
12188c2ecf20Sopenharmony_ci	rc = efx_mcdi_free_vis(efx);
12198c2ecf20Sopenharmony_ci	if (rc != 0)
12208c2ecf20Sopenharmony_ci		return rc;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	rc = efx_ef10_alloc_vis(efx, min_vis, max_vis);
12238c2ecf20Sopenharmony_ci	if (rc != 0)
12248c2ecf20Sopenharmony_ci		return rc;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	if (nic_data->n_allocated_vis < channel_vis) {
12278c2ecf20Sopenharmony_ci		netif_info(efx, drv, efx->net_dev,
12288c2ecf20Sopenharmony_ci			   "Could not allocate enough VIs to satisfy RSS"
12298c2ecf20Sopenharmony_ci			   " requirements. Performance may not be optimal.\n");
12308c2ecf20Sopenharmony_ci		/* We didn't get the VIs to populate our channels.
12318c2ecf20Sopenharmony_ci		 * We could keep what we got but then we'd have more
12328c2ecf20Sopenharmony_ci		 * interrupts than we need.
12338c2ecf20Sopenharmony_ci		 * Instead calculate new max_channels and restart
12348c2ecf20Sopenharmony_ci		 */
12358c2ecf20Sopenharmony_ci		efx->max_channels = nic_data->n_allocated_vis;
12368c2ecf20Sopenharmony_ci		efx->max_tx_channels =
12378c2ecf20Sopenharmony_ci			nic_data->n_allocated_vis / efx->tx_queues_per_channel;
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci		efx_mcdi_free_vis(efx);
12408c2ecf20Sopenharmony_ci		return -EAGAIN;
12418c2ecf20Sopenharmony_ci	}
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	/* If we didn't get enough VIs to map all the PIO buffers, free the
12448c2ecf20Sopenharmony_ci	 * PIO buffers
12458c2ecf20Sopenharmony_ci	 */
12468c2ecf20Sopenharmony_ci	if (nic_data->n_piobufs &&
12478c2ecf20Sopenharmony_ci	    nic_data->n_allocated_vis <
12488c2ecf20Sopenharmony_ci	    pio_write_vi_base + nic_data->n_piobufs) {
12498c2ecf20Sopenharmony_ci		netif_dbg(efx, probe, efx->net_dev,
12508c2ecf20Sopenharmony_ci			  "%u VIs are not sufficient to map %u PIO buffers\n",
12518c2ecf20Sopenharmony_ci			  nic_data->n_allocated_vis, nic_data->n_piobufs);
12528c2ecf20Sopenharmony_ci		efx_ef10_free_piobufs(efx);
12538c2ecf20Sopenharmony_ci	}
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	/* Shrink the original UC mapping of the memory BAR */
12568c2ecf20Sopenharmony_ci	membase = ioremap(efx->membase_phys, uc_mem_map_size);
12578c2ecf20Sopenharmony_ci	if (!membase) {
12588c2ecf20Sopenharmony_ci		netif_err(efx, probe, efx->net_dev,
12598c2ecf20Sopenharmony_ci			  "could not shrink memory BAR to %x\n",
12608c2ecf20Sopenharmony_ci			  uc_mem_map_size);
12618c2ecf20Sopenharmony_ci		return -ENOMEM;
12628c2ecf20Sopenharmony_ci	}
12638c2ecf20Sopenharmony_ci	iounmap(efx->membase);
12648c2ecf20Sopenharmony_ci	efx->membase = membase;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	/* Set up the WC mapping if needed */
12678c2ecf20Sopenharmony_ci	if (wc_mem_map_size) {
12688c2ecf20Sopenharmony_ci		nic_data->wc_membase = ioremap_wc(efx->membase_phys +
12698c2ecf20Sopenharmony_ci						  uc_mem_map_size,
12708c2ecf20Sopenharmony_ci						  wc_mem_map_size);
12718c2ecf20Sopenharmony_ci		if (!nic_data->wc_membase) {
12728c2ecf20Sopenharmony_ci			netif_err(efx, probe, efx->net_dev,
12738c2ecf20Sopenharmony_ci				  "could not allocate WC mapping of size %x\n",
12748c2ecf20Sopenharmony_ci				  wc_mem_map_size);
12758c2ecf20Sopenharmony_ci			return -ENOMEM;
12768c2ecf20Sopenharmony_ci		}
12778c2ecf20Sopenharmony_ci		nic_data->pio_write_vi_base = pio_write_vi_base;
12788c2ecf20Sopenharmony_ci		nic_data->pio_write_base =
12798c2ecf20Sopenharmony_ci			nic_data->wc_membase +
12808c2ecf20Sopenharmony_ci			(pio_write_vi_base * efx->vi_stride + ER_DZ_TX_PIOBUF -
12818c2ecf20Sopenharmony_ci			 uc_mem_map_size);
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci		rc = efx_ef10_link_piobufs(efx);
12848c2ecf20Sopenharmony_ci		if (rc)
12858c2ecf20Sopenharmony_ci			efx_ef10_free_piobufs(efx);
12868c2ecf20Sopenharmony_ci	}
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	netif_dbg(efx, probe, efx->net_dev,
12898c2ecf20Sopenharmony_ci		  "memory BAR at %pa (virtual %p+%x UC, %p+%x WC)\n",
12908c2ecf20Sopenharmony_ci		  &efx->membase_phys, efx->membase, uc_mem_map_size,
12918c2ecf20Sopenharmony_ci		  nic_data->wc_membase, wc_mem_map_size);
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	return 0;
12948c2ecf20Sopenharmony_ci}
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_cistatic void efx_ef10_fini_nic(struct efx_nic *efx)
12978c2ecf20Sopenharmony_ci{
12988c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	spin_lock_bh(&efx->stats_lock);
13018c2ecf20Sopenharmony_ci	kfree(nic_data->mc_stats);
13028c2ecf20Sopenharmony_ci	nic_data->mc_stats = NULL;
13038c2ecf20Sopenharmony_ci	spin_unlock_bh(&efx->stats_lock);
13048c2ecf20Sopenharmony_ci}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_cistatic int efx_ef10_init_nic(struct efx_nic *efx)
13078c2ecf20Sopenharmony_ci{
13088c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
13098c2ecf20Sopenharmony_ci	struct net_device *net_dev = efx->net_dev;
13108c2ecf20Sopenharmony_ci	netdev_features_t tun_feats, tso_feats;
13118c2ecf20Sopenharmony_ci	int rc;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	if (nic_data->must_check_datapath_caps) {
13148c2ecf20Sopenharmony_ci		rc = efx_ef10_init_datapath_caps(efx);
13158c2ecf20Sopenharmony_ci		if (rc)
13168c2ecf20Sopenharmony_ci			return rc;
13178c2ecf20Sopenharmony_ci		nic_data->must_check_datapath_caps = false;
13188c2ecf20Sopenharmony_ci	}
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	if (efx->must_realloc_vis) {
13218c2ecf20Sopenharmony_ci		/* We cannot let the number of VIs change now */
13228c2ecf20Sopenharmony_ci		rc = efx_ef10_alloc_vis(efx, nic_data->n_allocated_vis,
13238c2ecf20Sopenharmony_ci					nic_data->n_allocated_vis);
13248c2ecf20Sopenharmony_ci		if (rc)
13258c2ecf20Sopenharmony_ci			return rc;
13268c2ecf20Sopenharmony_ci		efx->must_realloc_vis = false;
13278c2ecf20Sopenharmony_ci	}
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	nic_data->mc_stats = kmalloc(efx->num_mac_stats * sizeof(__le64),
13308c2ecf20Sopenharmony_ci				     GFP_KERNEL);
13318c2ecf20Sopenharmony_ci	if (!nic_data->mc_stats)
13328c2ecf20Sopenharmony_ci		return -ENOMEM;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	if (nic_data->must_restore_piobufs && nic_data->n_piobufs) {
13358c2ecf20Sopenharmony_ci		rc = efx_ef10_alloc_piobufs(efx, nic_data->n_piobufs);
13368c2ecf20Sopenharmony_ci		if (rc == 0) {
13378c2ecf20Sopenharmony_ci			rc = efx_ef10_link_piobufs(efx);
13388c2ecf20Sopenharmony_ci			if (rc)
13398c2ecf20Sopenharmony_ci				efx_ef10_free_piobufs(efx);
13408c2ecf20Sopenharmony_ci		}
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci		/* Log an error on failure, but this is non-fatal.
13438c2ecf20Sopenharmony_ci		 * Permission errors are less important - we've presumably
13448c2ecf20Sopenharmony_ci		 * had the PIO buffer licence removed.
13458c2ecf20Sopenharmony_ci		 */
13468c2ecf20Sopenharmony_ci		if (rc == -EPERM)
13478c2ecf20Sopenharmony_ci			netif_dbg(efx, drv, efx->net_dev,
13488c2ecf20Sopenharmony_ci				  "not permitted to restore PIO buffers\n");
13498c2ecf20Sopenharmony_ci		else if (rc)
13508c2ecf20Sopenharmony_ci			netif_err(efx, drv, efx->net_dev,
13518c2ecf20Sopenharmony_ci				  "failed to restore PIO buffers (%d)\n", rc);
13528c2ecf20Sopenharmony_ci		nic_data->must_restore_piobufs = false;
13538c2ecf20Sopenharmony_ci	}
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	/* encap features might change during reset if fw variant changed */
13568c2ecf20Sopenharmony_ci	if (efx_has_cap(efx, VXLAN_NVGRE) && !efx_ef10_is_vf(efx))
13578c2ecf20Sopenharmony_ci		net_dev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
13588c2ecf20Sopenharmony_ci	else
13598c2ecf20Sopenharmony_ci		net_dev->hw_enc_features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	tun_feats = NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_GRE |
13628c2ecf20Sopenharmony_ci		    NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_GSO_GRE_CSUM;
13638c2ecf20Sopenharmony_ci	tso_feats = NETIF_F_TSO | NETIF_F_TSO6;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	if (efx_has_cap(efx, TX_TSO_V2_ENCAP)) {
13668c2ecf20Sopenharmony_ci		/* If this is first nic_init, or if it is a reset and a new fw
13678c2ecf20Sopenharmony_ci		 * variant has added new features, enable them by default.
13688c2ecf20Sopenharmony_ci		 * If the features are not new, maintain their current value.
13698c2ecf20Sopenharmony_ci		 */
13708c2ecf20Sopenharmony_ci		if (!(net_dev->hw_features & tun_feats))
13718c2ecf20Sopenharmony_ci			net_dev->features |= tun_feats;
13728c2ecf20Sopenharmony_ci		net_dev->hw_enc_features |= tun_feats | tso_feats;
13738c2ecf20Sopenharmony_ci		net_dev->hw_features |= tun_feats;
13748c2ecf20Sopenharmony_ci	} else {
13758c2ecf20Sopenharmony_ci		net_dev->hw_enc_features &= ~(tun_feats | tso_feats);
13768c2ecf20Sopenharmony_ci		net_dev->hw_features &= ~tun_feats;
13778c2ecf20Sopenharmony_ci		net_dev->features &= ~tun_feats;
13788c2ecf20Sopenharmony_ci	}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	/* don't fail init if RSS setup doesn't work */
13818c2ecf20Sopenharmony_ci	rc = efx->type->rx_push_rss_config(efx, false,
13828c2ecf20Sopenharmony_ci					   efx->rss_context.rx_indir_table, NULL);
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	return 0;
13858c2ecf20Sopenharmony_ci}
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_cistatic void efx_ef10_table_reset_mc_allocations(struct efx_nic *efx)
13888c2ecf20Sopenharmony_ci{
13898c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
13908c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
13918c2ecf20Sopenharmony_ci	unsigned int i;
13928c2ecf20Sopenharmony_ci#endif
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	/* All our allocations have been reset */
13958c2ecf20Sopenharmony_ci	efx->must_realloc_vis = true;
13968c2ecf20Sopenharmony_ci	efx_mcdi_filter_table_reset_mc_allocations(efx);
13978c2ecf20Sopenharmony_ci	nic_data->must_restore_piobufs = true;
13988c2ecf20Sopenharmony_ci	efx_ef10_forget_old_piobufs(efx);
13998c2ecf20Sopenharmony_ci	efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	/* Driver-created vswitches and vports must be re-created */
14028c2ecf20Sopenharmony_ci	nic_data->must_probe_vswitching = true;
14038c2ecf20Sopenharmony_ci	efx->vport_id = EVB_PORT_ID_ASSIGNED;
14048c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
14058c2ecf20Sopenharmony_ci	if (nic_data->vf)
14068c2ecf20Sopenharmony_ci		for (i = 0; i < efx->vf_count; i++)
14078c2ecf20Sopenharmony_ci			nic_data->vf[i].vport_id = 0;
14088c2ecf20Sopenharmony_ci#endif
14098c2ecf20Sopenharmony_ci}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_cistatic enum reset_type efx_ef10_map_reset_reason(enum reset_type reason)
14128c2ecf20Sopenharmony_ci{
14138c2ecf20Sopenharmony_ci	if (reason == RESET_TYPE_MC_FAILURE)
14148c2ecf20Sopenharmony_ci		return RESET_TYPE_DATAPATH;
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	return efx_mcdi_map_reset_reason(reason);
14178c2ecf20Sopenharmony_ci}
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_cistatic int efx_ef10_map_reset_flags(u32 *flags)
14208c2ecf20Sopenharmony_ci{
14218c2ecf20Sopenharmony_ci	enum {
14228c2ecf20Sopenharmony_ci		EF10_RESET_PORT = ((ETH_RESET_MAC | ETH_RESET_PHY) <<
14238c2ecf20Sopenharmony_ci				   ETH_RESET_SHARED_SHIFT),
14248c2ecf20Sopenharmony_ci		EF10_RESET_MC = ((ETH_RESET_DMA | ETH_RESET_FILTER |
14258c2ecf20Sopenharmony_ci				  ETH_RESET_OFFLOAD | ETH_RESET_MAC |
14268c2ecf20Sopenharmony_ci				  ETH_RESET_PHY | ETH_RESET_MGMT) <<
14278c2ecf20Sopenharmony_ci				 ETH_RESET_SHARED_SHIFT)
14288c2ecf20Sopenharmony_ci	};
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	/* We assume for now that our PCI function is permitted to
14318c2ecf20Sopenharmony_ci	 * reset everything.
14328c2ecf20Sopenharmony_ci	 */
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	if ((*flags & EF10_RESET_MC) == EF10_RESET_MC) {
14358c2ecf20Sopenharmony_ci		*flags &= ~EF10_RESET_MC;
14368c2ecf20Sopenharmony_ci		return RESET_TYPE_WORLD;
14378c2ecf20Sopenharmony_ci	}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	if ((*flags & EF10_RESET_PORT) == EF10_RESET_PORT) {
14408c2ecf20Sopenharmony_ci		*flags &= ~EF10_RESET_PORT;
14418c2ecf20Sopenharmony_ci		return RESET_TYPE_ALL;
14428c2ecf20Sopenharmony_ci	}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	/* no invisible reset implemented */
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	return -EINVAL;
14478c2ecf20Sopenharmony_ci}
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_cistatic int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type)
14508c2ecf20Sopenharmony_ci{
14518c2ecf20Sopenharmony_ci	int rc = efx_mcdi_reset(efx, reset_type);
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	/* Unprivileged functions return -EPERM, but need to return success
14548c2ecf20Sopenharmony_ci	 * here so that the datapath is brought back up.
14558c2ecf20Sopenharmony_ci	 */
14568c2ecf20Sopenharmony_ci	if (reset_type == RESET_TYPE_WORLD && rc == -EPERM)
14578c2ecf20Sopenharmony_ci		rc = 0;
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	/* If it was a port reset, trigger reallocation of MC resources.
14608c2ecf20Sopenharmony_ci	 * Note that on an MC reset nothing needs to be done now because we'll
14618c2ecf20Sopenharmony_ci	 * detect the MC reset later and handle it then.
14628c2ecf20Sopenharmony_ci	 * For an FLR, we never get an MC reset event, but the MC has reset all
14638c2ecf20Sopenharmony_ci	 * resources assigned to us, so we have to trigger reallocation now.
14648c2ecf20Sopenharmony_ci	 */
14658c2ecf20Sopenharmony_ci	if ((reset_type == RESET_TYPE_ALL ||
14668c2ecf20Sopenharmony_ci	     reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc)
14678c2ecf20Sopenharmony_ci		efx_ef10_table_reset_mc_allocations(efx);
14688c2ecf20Sopenharmony_ci	return rc;
14698c2ecf20Sopenharmony_ci}
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci#define EF10_DMA_STAT(ext_name, mcdi_name)			\
14728c2ecf20Sopenharmony_ci	[EF10_STAT_ ## ext_name] =				\
14738c2ecf20Sopenharmony_ci	{ #ext_name, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
14748c2ecf20Sopenharmony_ci#define EF10_DMA_INVIS_STAT(int_name, mcdi_name)		\
14758c2ecf20Sopenharmony_ci	[EF10_STAT_ ## int_name] =				\
14768c2ecf20Sopenharmony_ci	{ NULL, 64, 8 * MC_CMD_MAC_ ## mcdi_name }
14778c2ecf20Sopenharmony_ci#define EF10_OTHER_STAT(ext_name)				\
14788c2ecf20Sopenharmony_ci	[EF10_STAT_ ## ext_name] = { #ext_name, 0, 0 }
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_cistatic const struct efx_hw_stat_desc efx_ef10_stat_desc[EF10_STAT_COUNT] = {
14818c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_bytes, TX_BYTES),
14828c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_packets, TX_PKTS),
14838c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_pause, TX_PAUSE_PKTS),
14848c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_control, TX_CONTROL_PKTS),
14858c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_unicast, TX_UNICAST_PKTS),
14868c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_multicast, TX_MULTICAST_PKTS),
14878c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_broadcast, TX_BROADCAST_PKTS),
14888c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_lt64, TX_LT64_PKTS),
14898c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_64, TX_64_PKTS),
14908c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_65_to_127, TX_65_TO_127_PKTS),
14918c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_128_to_255, TX_128_TO_255_PKTS),
14928c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_256_to_511, TX_256_TO_511_PKTS),
14938c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_512_to_1023, TX_512_TO_1023_PKTS),
14948c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_1024_to_15xx, TX_1024_TO_15XX_PKTS),
14958c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_tx_15xx_to_jumbo, TX_15XX_TO_JUMBO_PKTS),
14968c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_bytes, RX_BYTES),
14978c2ecf20Sopenharmony_ci	EF10_DMA_INVIS_STAT(port_rx_bytes_minus_good_bytes, RX_BAD_BYTES),
14988c2ecf20Sopenharmony_ci	EF10_OTHER_STAT(port_rx_good_bytes),
14998c2ecf20Sopenharmony_ci	EF10_OTHER_STAT(port_rx_bad_bytes),
15008c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_packets, RX_PKTS),
15018c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_good, RX_GOOD_PKTS),
15028c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_bad, RX_BAD_FCS_PKTS),
15038c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pause, RX_PAUSE_PKTS),
15048c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_control, RX_CONTROL_PKTS),
15058c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_unicast, RX_UNICAST_PKTS),
15068c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_multicast, RX_MULTICAST_PKTS),
15078c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_broadcast, RX_BROADCAST_PKTS),
15088c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_lt64, RX_UNDERSIZE_PKTS),
15098c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_64, RX_64_PKTS),
15108c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_65_to_127, RX_65_TO_127_PKTS),
15118c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_128_to_255, RX_128_TO_255_PKTS),
15128c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_256_to_511, RX_256_TO_511_PKTS),
15138c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_512_to_1023, RX_512_TO_1023_PKTS),
15148c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_1024_to_15xx, RX_1024_TO_15XX_PKTS),
15158c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_15xx_to_jumbo, RX_15XX_TO_JUMBO_PKTS),
15168c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_gtjumbo, RX_GTJUMBO_PKTS),
15178c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_bad_gtjumbo, RX_JABBER_PKTS),
15188c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_overflow, RX_OVERFLOW_PKTS),
15198c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_align_error, RX_ALIGN_ERROR_PKTS),
15208c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_length_error, RX_LENGTH_ERROR_PKTS),
15218c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_nodesc_drops, RX_NODESC_DROPS),
15228c2ecf20Sopenharmony_ci	EFX_GENERIC_SW_STAT(rx_nodesc_trunc),
15238c2ecf20Sopenharmony_ci	EFX_GENERIC_SW_STAT(rx_noskb_drops),
15248c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_trunc_bb_overflow, PM_TRUNC_BB_OVERFLOW),
15258c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_discard_bb_overflow, PM_DISCARD_BB_OVERFLOW),
15268c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_trunc_vfifo_full, PM_TRUNC_VFIFO_FULL),
15278c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_discard_vfifo_full, PM_DISCARD_VFIFO_FULL),
15288c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_trunc_qbb, PM_TRUNC_QBB),
15298c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_discard_qbb, PM_DISCARD_QBB),
15308c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_pm_discard_mapping, PM_DISCARD_MAPPING),
15318c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_dp_q_disabled_packets, RXDP_Q_DISABLED_PKTS),
15328c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_dp_di_dropped_packets, RXDP_DI_DROPPED_PKTS),
15338c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_dp_streaming_packets, RXDP_STREAMING_PKTS),
15348c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_dp_hlb_fetch, RXDP_HLB_FETCH_CONDITIONS),
15358c2ecf20Sopenharmony_ci	EF10_DMA_STAT(port_rx_dp_hlb_wait, RXDP_HLB_WAIT_CONDITIONS),
15368c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_unicast, VADAPTER_RX_UNICAST_PACKETS),
15378c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_unicast_bytes, VADAPTER_RX_UNICAST_BYTES),
15388c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_multicast, VADAPTER_RX_MULTICAST_PACKETS),
15398c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_multicast_bytes, VADAPTER_RX_MULTICAST_BYTES),
15408c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_broadcast, VADAPTER_RX_BROADCAST_PACKETS),
15418c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_broadcast_bytes, VADAPTER_RX_BROADCAST_BYTES),
15428c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_bad, VADAPTER_RX_BAD_PACKETS),
15438c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_bad_bytes, VADAPTER_RX_BAD_BYTES),
15448c2ecf20Sopenharmony_ci	EF10_DMA_STAT(rx_overflow, VADAPTER_RX_OVERFLOW),
15458c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_unicast, VADAPTER_TX_UNICAST_PACKETS),
15468c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_unicast_bytes, VADAPTER_TX_UNICAST_BYTES),
15478c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_multicast, VADAPTER_TX_MULTICAST_PACKETS),
15488c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_multicast_bytes, VADAPTER_TX_MULTICAST_BYTES),
15498c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_broadcast, VADAPTER_TX_BROADCAST_PACKETS),
15508c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_broadcast_bytes, VADAPTER_TX_BROADCAST_BYTES),
15518c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_bad, VADAPTER_TX_BAD_PACKETS),
15528c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_bad_bytes, VADAPTER_TX_BAD_BYTES),
15538c2ecf20Sopenharmony_ci	EF10_DMA_STAT(tx_overflow, VADAPTER_TX_OVERFLOW),
15548c2ecf20Sopenharmony_ci	EF10_DMA_STAT(fec_uncorrected_errors, FEC_UNCORRECTED_ERRORS),
15558c2ecf20Sopenharmony_ci	EF10_DMA_STAT(fec_corrected_errors, FEC_CORRECTED_ERRORS),
15568c2ecf20Sopenharmony_ci	EF10_DMA_STAT(fec_corrected_symbols_lane0, FEC_CORRECTED_SYMBOLS_LANE0),
15578c2ecf20Sopenharmony_ci	EF10_DMA_STAT(fec_corrected_symbols_lane1, FEC_CORRECTED_SYMBOLS_LANE1),
15588c2ecf20Sopenharmony_ci	EF10_DMA_STAT(fec_corrected_symbols_lane2, FEC_CORRECTED_SYMBOLS_LANE2),
15598c2ecf20Sopenharmony_ci	EF10_DMA_STAT(fec_corrected_symbols_lane3, FEC_CORRECTED_SYMBOLS_LANE3),
15608c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_vi_busy_fallback, CTPIO_VI_BUSY_FALLBACK),
15618c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_long_write_success, CTPIO_LONG_WRITE_SUCCESS),
15628c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_missing_dbell_fail, CTPIO_MISSING_DBELL_FAIL),
15638c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_overflow_fail, CTPIO_OVERFLOW_FAIL),
15648c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_underflow_fail, CTPIO_UNDERFLOW_FAIL),
15658c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_timeout_fail, CTPIO_TIMEOUT_FAIL),
15668c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_noncontig_wr_fail, CTPIO_NONCONTIG_WR_FAIL),
15678c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_frm_clobber_fail, CTPIO_FRM_CLOBBER_FAIL),
15688c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_invalid_wr_fail, CTPIO_INVALID_WR_FAIL),
15698c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_vi_clobber_fallback, CTPIO_VI_CLOBBER_FALLBACK),
15708c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_unqualified_fallback, CTPIO_UNQUALIFIED_FALLBACK),
15718c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_runt_fallback, CTPIO_RUNT_FALLBACK),
15728c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_success, CTPIO_SUCCESS),
15738c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_fallback, CTPIO_FALLBACK),
15748c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_poison, CTPIO_POISON),
15758c2ecf20Sopenharmony_ci	EF10_DMA_STAT(ctpio_erase, CTPIO_ERASE),
15768c2ecf20Sopenharmony_ci};
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci#define HUNT_COMMON_STAT_MASK ((1ULL << EF10_STAT_port_tx_bytes) |	\
15798c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_tx_packets) |	\
15808c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_tx_pause) |	\
15818c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_tx_unicast) |	\
15828c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_tx_multicast) |	\
15838c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_tx_broadcast) |	\
15848c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_bytes) |	\
15858c2ecf20Sopenharmony_ci			       (1ULL <<                                 \
15868c2ecf20Sopenharmony_ci				EF10_STAT_port_rx_bytes_minus_good_bytes) | \
15878c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_good_bytes) |	\
15888c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_bad_bytes) |	\
15898c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_packets) |	\
15908c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_good) |	\
15918c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_bad) |	\
15928c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_pause) |	\
15938c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_control) |	\
15948c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_unicast) |	\
15958c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_multicast) |	\
15968c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_broadcast) |	\
15978c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_lt64) |	\
15988c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_64) |		\
15998c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_65_to_127) |	\
16008c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_128_to_255) |	\
16018c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_256_to_511) |	\
16028c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_512_to_1023) |\
16038c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_1024_to_15xx) |\
16048c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_15xx_to_jumbo) |\
16058c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_gtjumbo) |	\
16068c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_bad_gtjumbo) |\
16078c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_overflow) |	\
16088c2ecf20Sopenharmony_ci			       (1ULL << EF10_STAT_port_rx_nodesc_drops) |\
16098c2ecf20Sopenharmony_ci			       (1ULL << GENERIC_STAT_rx_nodesc_trunc) |	\
16108c2ecf20Sopenharmony_ci			       (1ULL << GENERIC_STAT_rx_noskb_drops))
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci/* On 7000 series NICs, these statistics are only provided by the 10G MAC.
16138c2ecf20Sopenharmony_ci * For a 10G/40G switchable port we do not expose these because they might
16148c2ecf20Sopenharmony_ci * not include all the packets they should.
16158c2ecf20Sopenharmony_ci * On 8000 series NICs these statistics are always provided.
16168c2ecf20Sopenharmony_ci */
16178c2ecf20Sopenharmony_ci#define HUNT_10G_ONLY_STAT_MASK ((1ULL << EF10_STAT_port_tx_control) |	\
16188c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_lt64) |	\
16198c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_64) |	\
16208c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_65_to_127) |\
16218c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_128_to_255) |\
16228c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_256_to_511) |\
16238c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_512_to_1023) |\
16248c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_1024_to_15xx) |\
16258c2ecf20Sopenharmony_ci				 (1ULL << EF10_STAT_port_tx_15xx_to_jumbo))
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci/* These statistics are only provided by the 40G MAC.  For a 10G/40G
16288c2ecf20Sopenharmony_ci * switchable port we do expose these because the errors will otherwise
16298c2ecf20Sopenharmony_ci * be silent.
16308c2ecf20Sopenharmony_ci */
16318c2ecf20Sopenharmony_ci#define HUNT_40G_EXTRA_STAT_MASK ((1ULL << EF10_STAT_port_rx_align_error) |\
16328c2ecf20Sopenharmony_ci				  (1ULL << EF10_STAT_port_rx_length_error))
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci/* These statistics are only provided if the firmware supports the
16358c2ecf20Sopenharmony_ci * capability PM_AND_RXDP_COUNTERS.
16368c2ecf20Sopenharmony_ci */
16378c2ecf20Sopenharmony_ci#define HUNT_PM_AND_RXDP_STAT_MASK (					\
16388c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_trunc_bb_overflow) |		\
16398c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_discard_bb_overflow) |		\
16408c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_trunc_vfifo_full) |		\
16418c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_discard_vfifo_full) |		\
16428c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_trunc_qbb) |			\
16438c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_discard_qbb) |			\
16448c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_pm_discard_mapping) |		\
16458c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_dp_q_disabled_packets) |		\
16468c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_dp_di_dropped_packets) |		\
16478c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_dp_streaming_packets) |		\
16488c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_dp_hlb_fetch) |			\
16498c2ecf20Sopenharmony_ci	(1ULL << EF10_STAT_port_rx_dp_hlb_wait))
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci/* These statistics are only provided if the NIC supports MC_CMD_MAC_STATS_V2,
16528c2ecf20Sopenharmony_ci * indicated by returning a value >= MC_CMD_MAC_NSTATS_V2 in
16538c2ecf20Sopenharmony_ci * MC_CMD_GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS.
16548c2ecf20Sopenharmony_ci * These bits are in the second u64 of the raw mask.
16558c2ecf20Sopenharmony_ci */
16568c2ecf20Sopenharmony_ci#define EF10_FEC_STAT_MASK (						\
16578c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_fec_uncorrected_errors - 64)) |		\
16588c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_fec_corrected_errors - 64)) |		\
16598c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_fec_corrected_symbols_lane0 - 64)) |	\
16608c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_fec_corrected_symbols_lane1 - 64)) |	\
16618c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_fec_corrected_symbols_lane2 - 64)) |	\
16628c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_fec_corrected_symbols_lane3 - 64)))
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci/* These statistics are only provided if the NIC supports MC_CMD_MAC_STATS_V3,
16658c2ecf20Sopenharmony_ci * indicated by returning a value >= MC_CMD_MAC_NSTATS_V3 in
16668c2ecf20Sopenharmony_ci * MC_CMD_GET_CAPABILITIES_V4_OUT_MAC_STATS_NUM_STATS.
16678c2ecf20Sopenharmony_ci * These bits are in the second u64 of the raw mask.
16688c2ecf20Sopenharmony_ci */
16698c2ecf20Sopenharmony_ci#define EF10_CTPIO_STAT_MASK (						\
16708c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_vi_busy_fallback - 64)) |		\
16718c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_long_write_success - 64)) |		\
16728c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_missing_dbell_fail - 64)) |		\
16738c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_overflow_fail - 64)) |		\
16748c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_underflow_fail - 64)) |		\
16758c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_timeout_fail - 64)) |			\
16768c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_noncontig_wr_fail - 64)) |		\
16778c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_frm_clobber_fail - 64)) |		\
16788c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_invalid_wr_fail - 64)) |		\
16798c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_vi_clobber_fallback - 64)) |		\
16808c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_unqualified_fallback - 64)) |		\
16818c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_runt_fallback - 64)) |		\
16828c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_success - 64)) |			\
16838c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_fallback - 64)) |			\
16848c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_poison - 64)) |			\
16858c2ecf20Sopenharmony_ci	(1ULL << (EF10_STAT_ctpio_erase - 64)))
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_cistatic u64 efx_ef10_raw_stat_mask(struct efx_nic *efx)
16888c2ecf20Sopenharmony_ci{
16898c2ecf20Sopenharmony_ci	u64 raw_mask = HUNT_COMMON_STAT_MASK;
16908c2ecf20Sopenharmony_ci	u32 port_caps = efx_mcdi_phy_get_caps(efx);
16918c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci	if (!(efx->mcdi->fn_flags &
16948c2ecf20Sopenharmony_ci	      1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_LINKCTRL))
16958c2ecf20Sopenharmony_ci		return 0;
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	if (port_caps & (1 << MC_CMD_PHY_CAP_40000FDX_LBN)) {
16988c2ecf20Sopenharmony_ci		raw_mask |= HUNT_40G_EXTRA_STAT_MASK;
16998c2ecf20Sopenharmony_ci		/* 8000 series have everything even at 40G */
17008c2ecf20Sopenharmony_ci		if (nic_data->datapath_caps2 &
17018c2ecf20Sopenharmony_ci		    (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_MAC_STATS_40G_TX_SIZE_BINS_LBN))
17028c2ecf20Sopenharmony_ci			raw_mask |= HUNT_10G_ONLY_STAT_MASK;
17038c2ecf20Sopenharmony_ci	} else {
17048c2ecf20Sopenharmony_ci		raw_mask |= HUNT_10G_ONLY_STAT_MASK;
17058c2ecf20Sopenharmony_ci	}
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
17088c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_PM_AND_RXDP_COUNTERS_LBN))
17098c2ecf20Sopenharmony_ci		raw_mask |= HUNT_PM_AND_RXDP_STAT_MASK;
17108c2ecf20Sopenharmony_ci
17118c2ecf20Sopenharmony_ci	return raw_mask;
17128c2ecf20Sopenharmony_ci}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_cistatic void efx_ef10_get_stat_mask(struct efx_nic *efx, unsigned long *mask)
17158c2ecf20Sopenharmony_ci{
17168c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
17178c2ecf20Sopenharmony_ci	u64 raw_mask[2];
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	raw_mask[0] = efx_ef10_raw_stat_mask(efx);
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	/* Only show vadaptor stats when EVB capability is present */
17228c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
17238c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_EVB_LBN)) {
17248c2ecf20Sopenharmony_ci		raw_mask[0] |= ~((1ULL << EF10_STAT_rx_unicast) - 1);
17258c2ecf20Sopenharmony_ci		raw_mask[1] = (1ULL << (EF10_STAT_V1_COUNT - 64)) - 1;
17268c2ecf20Sopenharmony_ci	} else {
17278c2ecf20Sopenharmony_ci		raw_mask[1] = 0;
17288c2ecf20Sopenharmony_ci	}
17298c2ecf20Sopenharmony_ci	/* Only show FEC stats when NIC supports MC_CMD_MAC_STATS_V2 */
17308c2ecf20Sopenharmony_ci	if (efx->num_mac_stats >= MC_CMD_MAC_NSTATS_V2)
17318c2ecf20Sopenharmony_ci		raw_mask[1] |= EF10_FEC_STAT_MASK;
17328c2ecf20Sopenharmony_ci
17338c2ecf20Sopenharmony_ci	/* CTPIO stats appear in V3. Only show them on devices that actually
17348c2ecf20Sopenharmony_ci	 * support CTPIO. Although this driver doesn't use CTPIO others might,
17358c2ecf20Sopenharmony_ci	 * and we may be reporting the stats for the underlying port.
17368c2ecf20Sopenharmony_ci	 */
17378c2ecf20Sopenharmony_ci	if (efx->num_mac_stats >= MC_CMD_MAC_NSTATS_V3 &&
17388c2ecf20Sopenharmony_ci	    (nic_data->datapath_caps2 &
17398c2ecf20Sopenharmony_ci	     (1 << MC_CMD_GET_CAPABILITIES_V4_OUT_CTPIO_LBN)))
17408c2ecf20Sopenharmony_ci		raw_mask[1] |= EF10_CTPIO_STAT_MASK;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 64
17438c2ecf20Sopenharmony_ci	BUILD_BUG_ON(BITS_TO_LONGS(EF10_STAT_COUNT) != 2);
17448c2ecf20Sopenharmony_ci	mask[0] = raw_mask[0];
17458c2ecf20Sopenharmony_ci	mask[1] = raw_mask[1];
17468c2ecf20Sopenharmony_ci#else
17478c2ecf20Sopenharmony_ci	BUILD_BUG_ON(BITS_TO_LONGS(EF10_STAT_COUNT) != 3);
17488c2ecf20Sopenharmony_ci	mask[0] = raw_mask[0] & 0xffffffff;
17498c2ecf20Sopenharmony_ci	mask[1] = raw_mask[0] >> 32;
17508c2ecf20Sopenharmony_ci	mask[2] = raw_mask[1] & 0xffffffff;
17518c2ecf20Sopenharmony_ci#endif
17528c2ecf20Sopenharmony_ci}
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_cistatic size_t efx_ef10_describe_stats(struct efx_nic *efx, u8 *names)
17558c2ecf20Sopenharmony_ci{
17568c2ecf20Sopenharmony_ci	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	efx_ef10_get_stat_mask(efx, mask);
17598c2ecf20Sopenharmony_ci	return efx_nic_describe_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
17608c2ecf20Sopenharmony_ci				      mask, names);
17618c2ecf20Sopenharmony_ci}
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_cistatic size_t efx_ef10_update_stats_common(struct efx_nic *efx, u64 *full_stats,
17648c2ecf20Sopenharmony_ci					   struct rtnl_link_stats64 *core_stats)
17658c2ecf20Sopenharmony_ci{
17668c2ecf20Sopenharmony_ci	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
17678c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
17688c2ecf20Sopenharmony_ci	u64 *stats = nic_data->stats;
17698c2ecf20Sopenharmony_ci	size_t stats_count = 0, index;
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	efx_ef10_get_stat_mask(efx, mask);
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	if (full_stats) {
17748c2ecf20Sopenharmony_ci		for_each_set_bit(index, mask, EF10_STAT_COUNT) {
17758c2ecf20Sopenharmony_ci			if (efx_ef10_stat_desc[index].name) {
17768c2ecf20Sopenharmony_ci				*full_stats++ = stats[index];
17778c2ecf20Sopenharmony_ci				++stats_count;
17788c2ecf20Sopenharmony_ci			}
17798c2ecf20Sopenharmony_ci		}
17808c2ecf20Sopenharmony_ci	}
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	if (!core_stats)
17838c2ecf20Sopenharmony_ci		return stats_count;
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
17868c2ecf20Sopenharmony_ci			1 << MC_CMD_GET_CAPABILITIES_OUT_EVB_LBN) {
17878c2ecf20Sopenharmony_ci		/* Use vadaptor stats. */
17888c2ecf20Sopenharmony_ci		core_stats->rx_packets = stats[EF10_STAT_rx_unicast] +
17898c2ecf20Sopenharmony_ci					 stats[EF10_STAT_rx_multicast] +
17908c2ecf20Sopenharmony_ci					 stats[EF10_STAT_rx_broadcast];
17918c2ecf20Sopenharmony_ci		core_stats->tx_packets = stats[EF10_STAT_tx_unicast] +
17928c2ecf20Sopenharmony_ci					 stats[EF10_STAT_tx_multicast] +
17938c2ecf20Sopenharmony_ci					 stats[EF10_STAT_tx_broadcast];
17948c2ecf20Sopenharmony_ci		core_stats->rx_bytes = stats[EF10_STAT_rx_unicast_bytes] +
17958c2ecf20Sopenharmony_ci				       stats[EF10_STAT_rx_multicast_bytes] +
17968c2ecf20Sopenharmony_ci				       stats[EF10_STAT_rx_broadcast_bytes];
17978c2ecf20Sopenharmony_ci		core_stats->tx_bytes = stats[EF10_STAT_tx_unicast_bytes] +
17988c2ecf20Sopenharmony_ci				       stats[EF10_STAT_tx_multicast_bytes] +
17998c2ecf20Sopenharmony_ci				       stats[EF10_STAT_tx_broadcast_bytes];
18008c2ecf20Sopenharmony_ci		core_stats->rx_dropped = stats[GENERIC_STAT_rx_nodesc_trunc] +
18018c2ecf20Sopenharmony_ci					 stats[GENERIC_STAT_rx_noskb_drops];
18028c2ecf20Sopenharmony_ci		core_stats->multicast = stats[EF10_STAT_rx_multicast];
18038c2ecf20Sopenharmony_ci		core_stats->rx_crc_errors = stats[EF10_STAT_rx_bad];
18048c2ecf20Sopenharmony_ci		core_stats->rx_fifo_errors = stats[EF10_STAT_rx_overflow];
18058c2ecf20Sopenharmony_ci		core_stats->rx_errors = core_stats->rx_crc_errors;
18068c2ecf20Sopenharmony_ci		core_stats->tx_errors = stats[EF10_STAT_tx_bad];
18078c2ecf20Sopenharmony_ci	} else {
18088c2ecf20Sopenharmony_ci		/* Use port stats. */
18098c2ecf20Sopenharmony_ci		core_stats->rx_packets = stats[EF10_STAT_port_rx_packets];
18108c2ecf20Sopenharmony_ci		core_stats->tx_packets = stats[EF10_STAT_port_tx_packets];
18118c2ecf20Sopenharmony_ci		core_stats->rx_bytes = stats[EF10_STAT_port_rx_bytes];
18128c2ecf20Sopenharmony_ci		core_stats->tx_bytes = stats[EF10_STAT_port_tx_bytes];
18138c2ecf20Sopenharmony_ci		core_stats->rx_dropped = stats[EF10_STAT_port_rx_nodesc_drops] +
18148c2ecf20Sopenharmony_ci					 stats[GENERIC_STAT_rx_nodesc_trunc] +
18158c2ecf20Sopenharmony_ci					 stats[GENERIC_STAT_rx_noskb_drops];
18168c2ecf20Sopenharmony_ci		core_stats->multicast = stats[EF10_STAT_port_rx_multicast];
18178c2ecf20Sopenharmony_ci		core_stats->rx_length_errors =
18188c2ecf20Sopenharmony_ci				stats[EF10_STAT_port_rx_gtjumbo] +
18198c2ecf20Sopenharmony_ci				stats[EF10_STAT_port_rx_length_error];
18208c2ecf20Sopenharmony_ci		core_stats->rx_crc_errors = stats[EF10_STAT_port_rx_bad];
18218c2ecf20Sopenharmony_ci		core_stats->rx_frame_errors =
18228c2ecf20Sopenharmony_ci				stats[EF10_STAT_port_rx_align_error];
18238c2ecf20Sopenharmony_ci		core_stats->rx_fifo_errors = stats[EF10_STAT_port_rx_overflow];
18248c2ecf20Sopenharmony_ci		core_stats->rx_errors = (core_stats->rx_length_errors +
18258c2ecf20Sopenharmony_ci					 core_stats->rx_crc_errors +
18268c2ecf20Sopenharmony_ci					 core_stats->rx_frame_errors);
18278c2ecf20Sopenharmony_ci	}
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	return stats_count;
18308c2ecf20Sopenharmony_ci}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_cistatic size_t efx_ef10_update_stats_pf(struct efx_nic *efx, u64 *full_stats,
18338c2ecf20Sopenharmony_ci				       struct rtnl_link_stats64 *core_stats)
18348c2ecf20Sopenharmony_ci{
18358c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
18368c2ecf20Sopenharmony_ci	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
18378c2ecf20Sopenharmony_ci	u64 *stats = nic_data->stats;
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci	efx_ef10_get_stat_mask(efx, mask);
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci	/* If NIC was fini'd (probably resetting), then we can't read
18428c2ecf20Sopenharmony_ci	 * updated stats right now.
18438c2ecf20Sopenharmony_ci	 */
18448c2ecf20Sopenharmony_ci	if (nic_data->mc_stats) {
18458c2ecf20Sopenharmony_ci		efx_nic_copy_stats(efx, nic_data->mc_stats);
18468c2ecf20Sopenharmony_ci		efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT,
18478c2ecf20Sopenharmony_ci				     mask, stats, nic_data->mc_stats, false);
18488c2ecf20Sopenharmony_ci	}
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	/* Update derived statistics */
18518c2ecf20Sopenharmony_ci	efx_nic_fix_nodesc_drop_stat(efx,
18528c2ecf20Sopenharmony_ci				     &stats[EF10_STAT_port_rx_nodesc_drops]);
18538c2ecf20Sopenharmony_ci	/* MC Firmware reads RX_BYTES and RX_GOOD_BYTES from the MAC.
18548c2ecf20Sopenharmony_ci	 * It then calculates RX_BAD_BYTES and DMAs it to us with RX_BYTES.
18558c2ecf20Sopenharmony_ci	 * We report these as port_rx_ stats. We are not given RX_GOOD_BYTES.
18568c2ecf20Sopenharmony_ci	 * Here we calculate port_rx_good_bytes.
18578c2ecf20Sopenharmony_ci	 */
18588c2ecf20Sopenharmony_ci	stats[EF10_STAT_port_rx_good_bytes] =
18598c2ecf20Sopenharmony_ci		stats[EF10_STAT_port_rx_bytes] -
18608c2ecf20Sopenharmony_ci		stats[EF10_STAT_port_rx_bytes_minus_good_bytes];
18618c2ecf20Sopenharmony_ci
18628c2ecf20Sopenharmony_ci	/* The asynchronous reads used to calculate RX_BAD_BYTES in
18638c2ecf20Sopenharmony_ci	 * MC Firmware are done such that we should not see an increase in
18648c2ecf20Sopenharmony_ci	 * RX_BAD_BYTES when a good packet has arrived. Unfortunately this
18658c2ecf20Sopenharmony_ci	 * does mean that the stat can decrease at times. Here we do not
18668c2ecf20Sopenharmony_ci	 * update the stat unless it has increased or has gone to zero
18678c2ecf20Sopenharmony_ci	 * (In the case of the NIC rebooting).
18688c2ecf20Sopenharmony_ci	 * Please see Bug 33781 for a discussion of why things work this way.
18698c2ecf20Sopenharmony_ci	 */
18708c2ecf20Sopenharmony_ci	efx_update_diff_stat(&stats[EF10_STAT_port_rx_bad_bytes],
18718c2ecf20Sopenharmony_ci			     stats[EF10_STAT_port_rx_bytes_minus_good_bytes]);
18728c2ecf20Sopenharmony_ci	efx_update_sw_stats(efx, stats);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
18758c2ecf20Sopenharmony_ci}
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_cistatic int efx_ef10_try_update_nic_stats_vf(struct efx_nic *efx)
18788c2ecf20Sopenharmony_ci	__must_hold(&efx->stats_lock)
18798c2ecf20Sopenharmony_ci{
18808c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
18818c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
18828c2ecf20Sopenharmony_ci	DECLARE_BITMAP(mask, EF10_STAT_COUNT);
18838c2ecf20Sopenharmony_ci	__le64 generation_start, generation_end;
18848c2ecf20Sopenharmony_ci	u64 *stats = nic_data->stats;
18858c2ecf20Sopenharmony_ci	u32 dma_len = efx->num_mac_stats * sizeof(u64);
18868c2ecf20Sopenharmony_ci	struct efx_buffer stats_buf;
18878c2ecf20Sopenharmony_ci	__le64 *dma_stats;
18888c2ecf20Sopenharmony_ci	int rc;
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci	spin_unlock_bh(&efx->stats_lock);
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci	efx_ef10_get_stat_mask(efx, mask);
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci	rc = efx_nic_alloc_buffer(efx, &stats_buf, dma_len, GFP_KERNEL);
18958c2ecf20Sopenharmony_ci	if (rc) {
18968c2ecf20Sopenharmony_ci		spin_lock_bh(&efx->stats_lock);
18978c2ecf20Sopenharmony_ci		return rc;
18988c2ecf20Sopenharmony_ci	}
18998c2ecf20Sopenharmony_ci
19008c2ecf20Sopenharmony_ci	dma_stats = stats_buf.addr;
19018c2ecf20Sopenharmony_ci	dma_stats[efx->num_mac_stats - 1] = EFX_MC_STATS_GENERATION_INVALID;
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, stats_buf.dma_addr);
19048c2ecf20Sopenharmony_ci	MCDI_POPULATE_DWORD_1(inbuf, MAC_STATS_IN_CMD,
19058c2ecf20Sopenharmony_ci			      MAC_STATS_IN_DMA, 1);
19068c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
19078c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_PORT_ID, EVB_PORT_ID_ASSIGNED);
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
19108c2ecf20Sopenharmony_ci				NULL, 0, NULL);
19118c2ecf20Sopenharmony_ci	spin_lock_bh(&efx->stats_lock);
19128c2ecf20Sopenharmony_ci	if (rc) {
19138c2ecf20Sopenharmony_ci		/* Expect ENOENT if DMA queues have not been set up */
19148c2ecf20Sopenharmony_ci		if (rc != -ENOENT || atomic_read(&efx->active_queues))
19158c2ecf20Sopenharmony_ci			efx_mcdi_display_error(efx, MC_CMD_MAC_STATS,
19168c2ecf20Sopenharmony_ci					       sizeof(inbuf), NULL, 0, rc);
19178c2ecf20Sopenharmony_ci		goto out;
19188c2ecf20Sopenharmony_ci	}
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	generation_end = dma_stats[efx->num_mac_stats - 1];
19218c2ecf20Sopenharmony_ci	if (generation_end == EFX_MC_STATS_GENERATION_INVALID) {
19228c2ecf20Sopenharmony_ci		WARN_ON_ONCE(1);
19238c2ecf20Sopenharmony_ci		goto out;
19248c2ecf20Sopenharmony_ci	}
19258c2ecf20Sopenharmony_ci	rmb();
19268c2ecf20Sopenharmony_ci	efx_nic_update_stats(efx_ef10_stat_desc, EF10_STAT_COUNT, mask,
19278c2ecf20Sopenharmony_ci			     stats, stats_buf.addr, false);
19288c2ecf20Sopenharmony_ci	rmb();
19298c2ecf20Sopenharmony_ci	generation_start = dma_stats[MC_CMD_MAC_GENERATION_START];
19308c2ecf20Sopenharmony_ci	if (generation_end != generation_start) {
19318c2ecf20Sopenharmony_ci		rc = -EAGAIN;
19328c2ecf20Sopenharmony_ci		goto out;
19338c2ecf20Sopenharmony_ci	}
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci	efx_update_sw_stats(efx, stats);
19368c2ecf20Sopenharmony_ciout:
19378c2ecf20Sopenharmony_ci	/* releasing a DMA coherent buffer with BH disabled can panic */
19388c2ecf20Sopenharmony_ci	spin_unlock_bh(&efx->stats_lock);
19398c2ecf20Sopenharmony_ci	efx_nic_free_buffer(efx, &stats_buf);
19408c2ecf20Sopenharmony_ci	spin_lock_bh(&efx->stats_lock);
19418c2ecf20Sopenharmony_ci	return rc;
19428c2ecf20Sopenharmony_ci}
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_cistatic size_t efx_ef10_update_stats_vf(struct efx_nic *efx, u64 *full_stats,
19458c2ecf20Sopenharmony_ci				       struct rtnl_link_stats64 *core_stats)
19468c2ecf20Sopenharmony_ci{
19478c2ecf20Sopenharmony_ci	if (efx_ef10_try_update_nic_stats_vf(efx))
19488c2ecf20Sopenharmony_ci		return 0;
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
19518c2ecf20Sopenharmony_ci}
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_cistatic size_t efx_ef10_update_stats_atomic_vf(struct efx_nic *efx, u64 *full_stats,
19548c2ecf20Sopenharmony_ci					      struct rtnl_link_stats64 *core_stats)
19558c2ecf20Sopenharmony_ci{
19568c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci	/* In atomic context, cannot update HW stats.  Just update the
19598c2ecf20Sopenharmony_ci	 * software stats and return so the caller can continue.
19608c2ecf20Sopenharmony_ci	 */
19618c2ecf20Sopenharmony_ci	efx_update_sw_stats(efx, nic_data->stats);
19628c2ecf20Sopenharmony_ci	return efx_ef10_update_stats_common(efx, full_stats, core_stats);
19638c2ecf20Sopenharmony_ci}
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_cistatic void efx_ef10_push_irq_moderation(struct efx_channel *channel)
19668c2ecf20Sopenharmony_ci{
19678c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
19688c2ecf20Sopenharmony_ci	unsigned int mode, usecs;
19698c2ecf20Sopenharmony_ci	efx_dword_t timer_cmd;
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci	if (channel->irq_moderation_us) {
19728c2ecf20Sopenharmony_ci		mode = 3;
19738c2ecf20Sopenharmony_ci		usecs = channel->irq_moderation_us;
19748c2ecf20Sopenharmony_ci	} else {
19758c2ecf20Sopenharmony_ci		mode = 0;
19768c2ecf20Sopenharmony_ci		usecs = 0;
19778c2ecf20Sopenharmony_ci	}
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci	if (EFX_EF10_WORKAROUND_61265(efx)) {
19808c2ecf20Sopenharmony_ci		MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_EVQ_TMR_IN_LEN);
19818c2ecf20Sopenharmony_ci		unsigned int ns = usecs * 1000;
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_INSTANCE,
19848c2ecf20Sopenharmony_ci			       channel->channel);
19858c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_TMR_LOAD_REQ_NS, ns);
19868c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_TMR_RELOAD_REQ_NS, ns);
19878c2ecf20Sopenharmony_ci		MCDI_SET_DWORD(inbuf, SET_EVQ_TMR_IN_TMR_MODE, mode);
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci		efx_mcdi_rpc_async(efx, MC_CMD_SET_EVQ_TMR,
19908c2ecf20Sopenharmony_ci				   inbuf, sizeof(inbuf), 0, NULL, 0);
19918c2ecf20Sopenharmony_ci	} else if (EFX_EF10_WORKAROUND_35388(efx)) {
19928c2ecf20Sopenharmony_ci		unsigned int ticks = efx_usecs_to_ticks(efx, usecs);
19938c2ecf20Sopenharmony_ci
19948c2ecf20Sopenharmony_ci		EFX_POPULATE_DWORD_3(timer_cmd, ERF_DD_EVQ_IND_TIMER_FLAGS,
19958c2ecf20Sopenharmony_ci				     EFE_DD_EVQ_IND_TIMER_FLAGS,
19968c2ecf20Sopenharmony_ci				     ERF_DD_EVQ_IND_TIMER_MODE, mode,
19978c2ecf20Sopenharmony_ci				     ERF_DD_EVQ_IND_TIMER_VAL, ticks);
19988c2ecf20Sopenharmony_ci		efx_writed_page(efx, &timer_cmd, ER_DD_EVQ_INDIRECT,
19998c2ecf20Sopenharmony_ci				channel->channel);
20008c2ecf20Sopenharmony_ci	} else {
20018c2ecf20Sopenharmony_ci		unsigned int ticks = efx_usecs_to_ticks(efx, usecs);
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_ci		EFX_POPULATE_DWORD_3(timer_cmd, ERF_DZ_TC_TIMER_MODE, mode,
20048c2ecf20Sopenharmony_ci				     ERF_DZ_TC_TIMER_VAL, ticks,
20058c2ecf20Sopenharmony_ci				     ERF_FZ_TC_TMR_REL_VAL, ticks);
20068c2ecf20Sopenharmony_ci		efx_writed_page(efx, &timer_cmd, ER_DZ_EVQ_TMR,
20078c2ecf20Sopenharmony_ci				channel->channel);
20088c2ecf20Sopenharmony_ci	}
20098c2ecf20Sopenharmony_ci}
20108c2ecf20Sopenharmony_ci
20118c2ecf20Sopenharmony_cistatic void efx_ef10_get_wol_vf(struct efx_nic *efx,
20128c2ecf20Sopenharmony_ci				struct ethtool_wolinfo *wol) {}
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_cistatic int efx_ef10_set_wol_vf(struct efx_nic *efx, u32 type)
20158c2ecf20Sopenharmony_ci{
20168c2ecf20Sopenharmony_ci	return -EOPNOTSUPP;
20178c2ecf20Sopenharmony_ci}
20188c2ecf20Sopenharmony_ci
20198c2ecf20Sopenharmony_cistatic void efx_ef10_get_wol(struct efx_nic *efx, struct ethtool_wolinfo *wol)
20208c2ecf20Sopenharmony_ci{
20218c2ecf20Sopenharmony_ci	wol->supported = 0;
20228c2ecf20Sopenharmony_ci	wol->wolopts = 0;
20238c2ecf20Sopenharmony_ci	memset(&wol->sopass, 0, sizeof(wol->sopass));
20248c2ecf20Sopenharmony_ci}
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_cistatic int efx_ef10_set_wol(struct efx_nic *efx, u32 type)
20278c2ecf20Sopenharmony_ci{
20288c2ecf20Sopenharmony_ci	if (type != 0)
20298c2ecf20Sopenharmony_ci		return -EINVAL;
20308c2ecf20Sopenharmony_ci	return 0;
20318c2ecf20Sopenharmony_ci}
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_cistatic void efx_ef10_mcdi_request(struct efx_nic *efx,
20348c2ecf20Sopenharmony_ci				  const efx_dword_t *hdr, size_t hdr_len,
20358c2ecf20Sopenharmony_ci				  const efx_dword_t *sdu, size_t sdu_len)
20368c2ecf20Sopenharmony_ci{
20378c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
20388c2ecf20Sopenharmony_ci	u8 *pdu = nic_data->mcdi_buf.addr;
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_ci	memcpy(pdu, hdr, hdr_len);
20418c2ecf20Sopenharmony_ci	memcpy(pdu + hdr_len, sdu, sdu_len);
20428c2ecf20Sopenharmony_ci	wmb();
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	/* The hardware provides 'low' and 'high' (doorbell) registers
20458c2ecf20Sopenharmony_ci	 * for passing the 64-bit address of an MCDI request to
20468c2ecf20Sopenharmony_ci	 * firmware.  However the dwords are swapped by firmware.  The
20478c2ecf20Sopenharmony_ci	 * least significant bits of the doorbell are then 0 for all
20488c2ecf20Sopenharmony_ci	 * MCDI requests due to alignment.
20498c2ecf20Sopenharmony_ci	 */
20508c2ecf20Sopenharmony_ci	_efx_writed(efx, cpu_to_le32((u64)nic_data->mcdi_buf.dma_addr >> 32),
20518c2ecf20Sopenharmony_ci		    ER_DZ_MC_DB_LWRD);
20528c2ecf20Sopenharmony_ci	_efx_writed(efx, cpu_to_le32((u32)nic_data->mcdi_buf.dma_addr),
20538c2ecf20Sopenharmony_ci		    ER_DZ_MC_DB_HWRD);
20548c2ecf20Sopenharmony_ci}
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_cistatic bool efx_ef10_mcdi_poll_response(struct efx_nic *efx)
20578c2ecf20Sopenharmony_ci{
20588c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
20598c2ecf20Sopenharmony_ci	const efx_dword_t hdr = *(const efx_dword_t *)nic_data->mcdi_buf.addr;
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci	rmb();
20628c2ecf20Sopenharmony_ci	return EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE);
20638c2ecf20Sopenharmony_ci}
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_cistatic void
20668c2ecf20Sopenharmony_ciefx_ef10_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf,
20678c2ecf20Sopenharmony_ci			    size_t offset, size_t outlen)
20688c2ecf20Sopenharmony_ci{
20698c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
20708c2ecf20Sopenharmony_ci	const u8 *pdu = nic_data->mcdi_buf.addr;
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci	memcpy(outbuf, pdu + offset, outlen);
20738c2ecf20Sopenharmony_ci}
20748c2ecf20Sopenharmony_ci
20758c2ecf20Sopenharmony_cistatic void efx_ef10_mcdi_reboot_detected(struct efx_nic *efx)
20768c2ecf20Sopenharmony_ci{
20778c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci	/* All our allocations have been reset */
20808c2ecf20Sopenharmony_ci	efx_ef10_table_reset_mc_allocations(efx);
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci	/* The datapath firmware might have been changed */
20838c2ecf20Sopenharmony_ci	nic_data->must_check_datapath_caps = true;
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	/* MAC statistics have been cleared on the NIC; clear the local
20868c2ecf20Sopenharmony_ci	 * statistic that we update with efx_update_diff_stat().
20878c2ecf20Sopenharmony_ci	 */
20888c2ecf20Sopenharmony_ci	nic_data->stats[EF10_STAT_port_rx_bad_bytes] = 0;
20898c2ecf20Sopenharmony_ci}
20908c2ecf20Sopenharmony_ci
20918c2ecf20Sopenharmony_cistatic int efx_ef10_mcdi_poll_reboot(struct efx_nic *efx)
20928c2ecf20Sopenharmony_ci{
20938c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
20948c2ecf20Sopenharmony_ci	int rc;
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	rc = efx_ef10_get_warm_boot_count(efx);
20978c2ecf20Sopenharmony_ci	if (rc < 0) {
20988c2ecf20Sopenharmony_ci		/* The firmware is presumably in the process of
20998c2ecf20Sopenharmony_ci		 * rebooting.  However, we are supposed to report each
21008c2ecf20Sopenharmony_ci		 * reboot just once, so we must only do that once we
21018c2ecf20Sopenharmony_ci		 * can read and store the updated warm boot count.
21028c2ecf20Sopenharmony_ci		 */
21038c2ecf20Sopenharmony_ci		return 0;
21048c2ecf20Sopenharmony_ci	}
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	if (rc == nic_data->warm_boot_count)
21078c2ecf20Sopenharmony_ci		return 0;
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	nic_data->warm_boot_count = rc;
21108c2ecf20Sopenharmony_ci	efx_ef10_mcdi_reboot_detected(efx);
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci	return -EIO;
21138c2ecf20Sopenharmony_ci}
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci/* Handle an MSI interrupt
21168c2ecf20Sopenharmony_ci *
21178c2ecf20Sopenharmony_ci * Handle an MSI hardware interrupt.  This routine schedules event
21188c2ecf20Sopenharmony_ci * queue processing.  No interrupt acknowledgement cycle is necessary.
21198c2ecf20Sopenharmony_ci * Also, we never need to check that the interrupt is for us, since
21208c2ecf20Sopenharmony_ci * MSI interrupts cannot be shared.
21218c2ecf20Sopenharmony_ci */
21228c2ecf20Sopenharmony_cistatic irqreturn_t efx_ef10_msi_interrupt(int irq, void *dev_id)
21238c2ecf20Sopenharmony_ci{
21248c2ecf20Sopenharmony_ci	struct efx_msi_context *context = dev_id;
21258c2ecf20Sopenharmony_ci	struct efx_nic *efx = context->efx;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	netif_vdbg(efx, intr, efx->net_dev,
21288c2ecf20Sopenharmony_ci		   "IRQ %d on CPU %d\n", irq, raw_smp_processor_id());
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci	if (likely(READ_ONCE(efx->irq_soft_enabled))) {
21318c2ecf20Sopenharmony_ci		/* Note test interrupts */
21328c2ecf20Sopenharmony_ci		if (context->index == efx->irq_level)
21338c2ecf20Sopenharmony_ci			efx->last_irq_cpu = raw_smp_processor_id();
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci		/* Schedule processing of the channel */
21368c2ecf20Sopenharmony_ci		efx_schedule_channel_irq(efx->channel[context->index]);
21378c2ecf20Sopenharmony_ci	}
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
21408c2ecf20Sopenharmony_ci}
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_cistatic irqreturn_t efx_ef10_legacy_interrupt(int irq, void *dev_id)
21438c2ecf20Sopenharmony_ci{
21448c2ecf20Sopenharmony_ci	struct efx_nic *efx = dev_id;
21458c2ecf20Sopenharmony_ci	bool soft_enabled = READ_ONCE(efx->irq_soft_enabled);
21468c2ecf20Sopenharmony_ci	struct efx_channel *channel;
21478c2ecf20Sopenharmony_ci	efx_dword_t reg;
21488c2ecf20Sopenharmony_ci	u32 queues;
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	/* Read the ISR which also ACKs the interrupts */
21518c2ecf20Sopenharmony_ci	efx_readd(efx, &reg, ER_DZ_BIU_INT_ISR);
21528c2ecf20Sopenharmony_ci	queues = EFX_DWORD_FIELD(reg, ERF_DZ_ISR_REG);
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	if (queues == 0)
21558c2ecf20Sopenharmony_ci		return IRQ_NONE;
21568c2ecf20Sopenharmony_ci
21578c2ecf20Sopenharmony_ci	if (likely(soft_enabled)) {
21588c2ecf20Sopenharmony_ci		/* Note test interrupts */
21598c2ecf20Sopenharmony_ci		if (queues & (1U << efx->irq_level))
21608c2ecf20Sopenharmony_ci			efx->last_irq_cpu = raw_smp_processor_id();
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci		efx_for_each_channel(channel, efx) {
21638c2ecf20Sopenharmony_ci			if (queues & 1)
21648c2ecf20Sopenharmony_ci				efx_schedule_channel_irq(channel);
21658c2ecf20Sopenharmony_ci			queues >>= 1;
21668c2ecf20Sopenharmony_ci		}
21678c2ecf20Sopenharmony_ci	}
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	netif_vdbg(efx, intr, efx->net_dev,
21708c2ecf20Sopenharmony_ci		   "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n",
21718c2ecf20Sopenharmony_ci		   irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg));
21728c2ecf20Sopenharmony_ci
21738c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
21748c2ecf20Sopenharmony_ci}
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_cistatic int efx_ef10_irq_test_generate(struct efx_nic *efx)
21778c2ecf20Sopenharmony_ci{
21788c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_TRIGGER_INTERRUPT_IN_LEN);
21798c2ecf20Sopenharmony_ci
21808c2ecf20Sopenharmony_ci	if (efx_mcdi_set_workaround(efx, MC_CMD_WORKAROUND_BUG41750, true,
21818c2ecf20Sopenharmony_ci				    NULL) == 0)
21828c2ecf20Sopenharmony_ci		return -ENOTSUPP;
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_TRIGGER_INTERRUPT_OUT_LEN != 0);
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, TRIGGER_INTERRUPT_IN_INTR_LEVEL, efx->irq_level);
21878c2ecf20Sopenharmony_ci	return efx_mcdi_rpc(efx, MC_CMD_TRIGGER_INTERRUPT,
21888c2ecf20Sopenharmony_ci			    inbuf, sizeof(inbuf), NULL, 0, NULL);
21898c2ecf20Sopenharmony_ci}
21908c2ecf20Sopenharmony_ci
21918c2ecf20Sopenharmony_cistatic int efx_ef10_tx_probe(struct efx_tx_queue *tx_queue)
21928c2ecf20Sopenharmony_ci{
21938c2ecf20Sopenharmony_ci	/* low two bits of label are what we want for type */
21948c2ecf20Sopenharmony_ci	BUILD_BUG_ON((EFX_TXQ_TYPE_OUTER_CSUM | EFX_TXQ_TYPE_INNER_CSUM) != 3);
21958c2ecf20Sopenharmony_ci	tx_queue->type = tx_queue->label & 3;
21968c2ecf20Sopenharmony_ci	return efx_nic_alloc_buffer(tx_queue->efx, &tx_queue->txd.buf,
21978c2ecf20Sopenharmony_ci				    (tx_queue->ptr_mask + 1) *
21988c2ecf20Sopenharmony_ci				    sizeof(efx_qword_t),
21998c2ecf20Sopenharmony_ci				    GFP_KERNEL);
22008c2ecf20Sopenharmony_ci}
22018c2ecf20Sopenharmony_ci
22028c2ecf20Sopenharmony_ci/* This writes to the TX_DESC_WPTR and also pushes data */
22038c2ecf20Sopenharmony_cistatic inline void efx_ef10_push_tx_desc(struct efx_tx_queue *tx_queue,
22048c2ecf20Sopenharmony_ci					 const efx_qword_t *txd)
22058c2ecf20Sopenharmony_ci{
22068c2ecf20Sopenharmony_ci	unsigned int write_ptr;
22078c2ecf20Sopenharmony_ci	efx_oword_t reg;
22088c2ecf20Sopenharmony_ci
22098c2ecf20Sopenharmony_ci	write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
22108c2ecf20Sopenharmony_ci	EFX_POPULATE_OWORD_1(reg, ERF_DZ_TX_DESC_WPTR, write_ptr);
22118c2ecf20Sopenharmony_ci	reg.qword[0] = *txd;
22128c2ecf20Sopenharmony_ci	efx_writeo_page(tx_queue->efx, &reg,
22138c2ecf20Sopenharmony_ci			ER_DZ_TX_DESC_UPD, tx_queue->queue);
22148c2ecf20Sopenharmony_ci}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_ci/* Add Firmware-Assisted TSO v2 option descriptors to a queue.
22178c2ecf20Sopenharmony_ci */
22188c2ecf20Sopenharmony_ciint efx_ef10_tx_tso_desc(struct efx_tx_queue *tx_queue, struct sk_buff *skb,
22198c2ecf20Sopenharmony_ci			 bool *data_mapped)
22208c2ecf20Sopenharmony_ci{
22218c2ecf20Sopenharmony_ci	struct efx_tx_buffer *buffer;
22228c2ecf20Sopenharmony_ci	u16 inner_ipv4_id = 0;
22238c2ecf20Sopenharmony_ci	u16 outer_ipv4_id = 0;
22248c2ecf20Sopenharmony_ci	struct tcphdr *tcp;
22258c2ecf20Sopenharmony_ci	struct iphdr *ip;
22268c2ecf20Sopenharmony_ci	u16 ip_tot_len;
22278c2ecf20Sopenharmony_ci	u32 seqnum;
22288c2ecf20Sopenharmony_ci	u32 mss;
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci	EFX_WARN_ON_ONCE_PARANOID(tx_queue->tso_version != 2);
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci	mss = skb_shinfo(skb)->gso_size;
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci	if (unlikely(mss < 4)) {
22358c2ecf20Sopenharmony_ci		WARN_ONCE(1, "MSS of %u is too small for TSO v2\n", mss);
22368c2ecf20Sopenharmony_ci		return -EINVAL;
22378c2ecf20Sopenharmony_ci	}
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	if (skb->encapsulation) {
22408c2ecf20Sopenharmony_ci		if (!tx_queue->tso_encap)
22418c2ecf20Sopenharmony_ci			return -EINVAL;
22428c2ecf20Sopenharmony_ci		ip = ip_hdr(skb);
22438c2ecf20Sopenharmony_ci		if (ip->version == 4)
22448c2ecf20Sopenharmony_ci			outer_ipv4_id = ntohs(ip->id);
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci		ip = inner_ip_hdr(skb);
22478c2ecf20Sopenharmony_ci		tcp = inner_tcp_hdr(skb);
22488c2ecf20Sopenharmony_ci	} else {
22498c2ecf20Sopenharmony_ci		ip = ip_hdr(skb);
22508c2ecf20Sopenharmony_ci		tcp = tcp_hdr(skb);
22518c2ecf20Sopenharmony_ci	}
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	/* 8000-series EF10 hardware requires that IP Total Length be
22548c2ecf20Sopenharmony_ci	 * greater than or equal to the value it will have in each segment
22558c2ecf20Sopenharmony_ci	 * (which is at most mss + 208 + TCP header length), but also less
22568c2ecf20Sopenharmony_ci	 * than (0x10000 - inner_network_header).  Otherwise the TCP
22578c2ecf20Sopenharmony_ci	 * checksum calculation will be broken for encapsulated packets.
22588c2ecf20Sopenharmony_ci	 * We fill in ip->tot_len with 0xff30, which should satisfy the
22598c2ecf20Sopenharmony_ci	 * first requirement unless the MSS is ridiculously large (which
22608c2ecf20Sopenharmony_ci	 * should be impossible as the driver max MTU is 9216); it is
22618c2ecf20Sopenharmony_ci	 * guaranteed to satisfy the second as we only attempt TSO if
22628c2ecf20Sopenharmony_ci	 * inner_network_header <= 208.
22638c2ecf20Sopenharmony_ci	 */
22648c2ecf20Sopenharmony_ci	ip_tot_len = 0x10000 - EFX_TSO2_MAX_HDRLEN;
22658c2ecf20Sopenharmony_ci	EFX_WARN_ON_ONCE_PARANOID(mss + EFX_TSO2_MAX_HDRLEN +
22668c2ecf20Sopenharmony_ci				  (tcp->doff << 2u) > ip_tot_len);
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci	if (ip->version == 4) {
22698c2ecf20Sopenharmony_ci		ip->tot_len = htons(ip_tot_len);
22708c2ecf20Sopenharmony_ci		ip->check = 0;
22718c2ecf20Sopenharmony_ci		inner_ipv4_id = ntohs(ip->id);
22728c2ecf20Sopenharmony_ci	} else {
22738c2ecf20Sopenharmony_ci		((struct ipv6hdr *)ip)->payload_len = htons(ip_tot_len);
22748c2ecf20Sopenharmony_ci	}
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci	seqnum = ntohl(tcp->seq);
22778c2ecf20Sopenharmony_ci
22788c2ecf20Sopenharmony_ci	buffer = efx_tx_queue_get_insert_buffer(tx_queue);
22798c2ecf20Sopenharmony_ci
22808c2ecf20Sopenharmony_ci	buffer->flags = EFX_TX_BUF_OPTION;
22818c2ecf20Sopenharmony_ci	buffer->len = 0;
22828c2ecf20Sopenharmony_ci	buffer->unmap_len = 0;
22838c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_5(buffer->option,
22848c2ecf20Sopenharmony_ci			ESF_DZ_TX_DESC_IS_OPT, 1,
22858c2ecf20Sopenharmony_ci			ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_TSO,
22868c2ecf20Sopenharmony_ci			ESF_DZ_TX_TSO_OPTION_TYPE,
22878c2ecf20Sopenharmony_ci			ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
22888c2ecf20Sopenharmony_ci			ESF_DZ_TX_TSO_IP_ID, inner_ipv4_id,
22898c2ecf20Sopenharmony_ci			ESF_DZ_TX_TSO_TCP_SEQNO, seqnum
22908c2ecf20Sopenharmony_ci			);
22918c2ecf20Sopenharmony_ci	++tx_queue->insert_count;
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	buffer = efx_tx_queue_get_insert_buffer(tx_queue);
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci	buffer->flags = EFX_TX_BUF_OPTION;
22968c2ecf20Sopenharmony_ci	buffer->len = 0;
22978c2ecf20Sopenharmony_ci	buffer->unmap_len = 0;
22988c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_5(buffer->option,
22998c2ecf20Sopenharmony_ci			ESF_DZ_TX_DESC_IS_OPT, 1,
23008c2ecf20Sopenharmony_ci			ESF_DZ_TX_OPTION_TYPE, ESE_DZ_TX_OPTION_DESC_TSO,
23018c2ecf20Sopenharmony_ci			ESF_DZ_TX_TSO_OPTION_TYPE,
23028c2ecf20Sopenharmony_ci			ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
23038c2ecf20Sopenharmony_ci			ESF_DZ_TX_TSO_OUTER_IPID, outer_ipv4_id,
23048c2ecf20Sopenharmony_ci			ESF_DZ_TX_TSO_TCP_MSS, mss
23058c2ecf20Sopenharmony_ci			);
23068c2ecf20Sopenharmony_ci	++tx_queue->insert_count;
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	return 0;
23098c2ecf20Sopenharmony_ci}
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_cistatic u32 efx_ef10_tso_versions(struct efx_nic *efx)
23128c2ecf20Sopenharmony_ci{
23138c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
23148c2ecf20Sopenharmony_ci	u32 tso_versions = 0;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps &
23178c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_TX_TSO_LBN))
23188c2ecf20Sopenharmony_ci		tso_versions |= BIT(1);
23198c2ecf20Sopenharmony_ci	if (nic_data->datapath_caps2 &
23208c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_V2_OUT_TX_TSO_V2_LBN))
23218c2ecf20Sopenharmony_ci		tso_versions |= BIT(2);
23228c2ecf20Sopenharmony_ci	return tso_versions;
23238c2ecf20Sopenharmony_ci}
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_cistatic void efx_ef10_tx_init(struct efx_tx_queue *tx_queue)
23268c2ecf20Sopenharmony_ci{
23278c2ecf20Sopenharmony_ci	bool csum_offload = tx_queue->type & EFX_TXQ_TYPE_OUTER_CSUM;
23288c2ecf20Sopenharmony_ci	bool inner_csum = tx_queue->type & EFX_TXQ_TYPE_INNER_CSUM;
23298c2ecf20Sopenharmony_ci	struct efx_channel *channel = tx_queue->channel;
23308c2ecf20Sopenharmony_ci	struct efx_nic *efx = tx_queue->efx;
23318c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data;
23328c2ecf20Sopenharmony_ci	efx_qword_t *txd;
23338c2ecf20Sopenharmony_ci	int rc;
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_ci	nic_data = efx->nic_data;
23368c2ecf20Sopenharmony_ci
23378c2ecf20Sopenharmony_ci	/* Only attempt to enable TX timestamping if we have the license for it,
23388c2ecf20Sopenharmony_ci	 * otherwise TXQ init will fail
23398c2ecf20Sopenharmony_ci	 */
23408c2ecf20Sopenharmony_ci	if (!(nic_data->licensed_features &
23418c2ecf20Sopenharmony_ci	      (1 << LICENSED_V3_FEATURES_TX_TIMESTAMPS_LBN))) {
23428c2ecf20Sopenharmony_ci		tx_queue->timestamping = false;
23438c2ecf20Sopenharmony_ci		/* Disable sync events on this channel. */
23448c2ecf20Sopenharmony_ci		if (efx->type->ptp_set_ts_sync_events)
23458c2ecf20Sopenharmony_ci			efx->type->ptp_set_ts_sync_events(efx, false, false);
23468c2ecf20Sopenharmony_ci	}
23478c2ecf20Sopenharmony_ci
23488c2ecf20Sopenharmony_ci	/* TSOv2 is a limited resource that can only be configured on a limited
23498c2ecf20Sopenharmony_ci	 * number of queues. TSO without checksum offload is not really a thing,
23508c2ecf20Sopenharmony_ci	 * so we only enable it for those queues.
23518c2ecf20Sopenharmony_ci	 * TSOv2 cannot be used with Hardware timestamping, and is never needed
23528c2ecf20Sopenharmony_ci	 * for XDP tx.
23538c2ecf20Sopenharmony_ci	 */
23548c2ecf20Sopenharmony_ci	if (efx_has_cap(efx, TX_TSO_V2)) {
23558c2ecf20Sopenharmony_ci		if ((csum_offload || inner_csum) &&
23568c2ecf20Sopenharmony_ci		    !tx_queue->timestamping && !tx_queue->xdp_tx) {
23578c2ecf20Sopenharmony_ci			tx_queue->tso_version = 2;
23588c2ecf20Sopenharmony_ci			netif_dbg(efx, hw, efx->net_dev, "Using TSOv2 for channel %u\n",
23598c2ecf20Sopenharmony_ci				  channel->channel);
23608c2ecf20Sopenharmony_ci		}
23618c2ecf20Sopenharmony_ci	} else if (efx_has_cap(efx, TX_TSO)) {
23628c2ecf20Sopenharmony_ci		tx_queue->tso_version = 1;
23638c2ecf20Sopenharmony_ci	}
23648c2ecf20Sopenharmony_ci
23658c2ecf20Sopenharmony_ci	rc = efx_mcdi_tx_init(tx_queue);
23668c2ecf20Sopenharmony_ci	if (rc)
23678c2ecf20Sopenharmony_ci		goto fail;
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci	/* A previous user of this TX queue might have set us up the
23708c2ecf20Sopenharmony_ci	 * bomb by writing a descriptor to the TX push collector but
23718c2ecf20Sopenharmony_ci	 * not the doorbell.  (Each collector belongs to a port, not a
23728c2ecf20Sopenharmony_ci	 * queue or function, so cannot easily be reset.)  We must
23738c2ecf20Sopenharmony_ci	 * attempt to push a no-op descriptor in its place.
23748c2ecf20Sopenharmony_ci	 */
23758c2ecf20Sopenharmony_ci	tx_queue->buffer[0].flags = EFX_TX_BUF_OPTION;
23768c2ecf20Sopenharmony_ci	tx_queue->insert_count = 1;
23778c2ecf20Sopenharmony_ci	txd = efx_tx_desc(tx_queue, 0);
23788c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_7(*txd,
23798c2ecf20Sopenharmony_ci			     ESF_DZ_TX_DESC_IS_OPT, true,
23808c2ecf20Sopenharmony_ci			     ESF_DZ_TX_OPTION_TYPE,
23818c2ecf20Sopenharmony_ci			     ESE_DZ_TX_OPTION_DESC_CRC_CSUM,
23828c2ecf20Sopenharmony_ci			     ESF_DZ_TX_OPTION_UDP_TCP_CSUM, csum_offload,
23838c2ecf20Sopenharmony_ci			     ESF_DZ_TX_OPTION_IP_CSUM, csum_offload && tx_queue->tso_version != 2,
23848c2ecf20Sopenharmony_ci			     ESF_DZ_TX_OPTION_INNER_UDP_TCP_CSUM, inner_csum,
23858c2ecf20Sopenharmony_ci			     ESF_DZ_TX_OPTION_INNER_IP_CSUM, inner_csum && tx_queue->tso_version != 2,
23868c2ecf20Sopenharmony_ci			     ESF_DZ_TX_TIMESTAMP, tx_queue->timestamping);
23878c2ecf20Sopenharmony_ci	tx_queue->write_count = 1;
23888c2ecf20Sopenharmony_ci
23898c2ecf20Sopenharmony_ci	if (tx_queue->tso_version == 2 && efx_has_cap(efx, TX_TSO_V2_ENCAP))
23908c2ecf20Sopenharmony_ci		tx_queue->tso_encap = true;
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci	wmb();
23938c2ecf20Sopenharmony_ci	efx_ef10_push_tx_desc(tx_queue, txd);
23948c2ecf20Sopenharmony_ci
23958c2ecf20Sopenharmony_ci	return;
23968c2ecf20Sopenharmony_ci
23978c2ecf20Sopenharmony_cifail:
23988c2ecf20Sopenharmony_ci	netdev_WARN(efx->net_dev, "failed to initialise TXQ %d\n",
23998c2ecf20Sopenharmony_ci		    tx_queue->queue);
24008c2ecf20Sopenharmony_ci}
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
24038c2ecf20Sopenharmony_cistatic inline void efx_ef10_notify_tx_desc(struct efx_tx_queue *tx_queue)
24048c2ecf20Sopenharmony_ci{
24058c2ecf20Sopenharmony_ci	unsigned int write_ptr;
24068c2ecf20Sopenharmony_ci	efx_dword_t reg;
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
24098c2ecf20Sopenharmony_ci	EFX_POPULATE_DWORD_1(reg, ERF_DZ_TX_DESC_WPTR_DWORD, write_ptr);
24108c2ecf20Sopenharmony_ci	efx_writed_page(tx_queue->efx, &reg,
24118c2ecf20Sopenharmony_ci			ER_DZ_TX_DESC_UPD_DWORD, tx_queue->queue);
24128c2ecf20Sopenharmony_ci}
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci#define EFX_EF10_MAX_TX_DESCRIPTOR_LEN 0x3fff
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_cistatic unsigned int efx_ef10_tx_limit_len(struct efx_tx_queue *tx_queue,
24178c2ecf20Sopenharmony_ci					  dma_addr_t dma_addr, unsigned int len)
24188c2ecf20Sopenharmony_ci{
24198c2ecf20Sopenharmony_ci	if (len > EFX_EF10_MAX_TX_DESCRIPTOR_LEN) {
24208c2ecf20Sopenharmony_ci		/* If we need to break across multiple descriptors we should
24218c2ecf20Sopenharmony_ci		 * stop at a page boundary. This assumes the length limit is
24228c2ecf20Sopenharmony_ci		 * greater than the page size.
24238c2ecf20Sopenharmony_ci		 */
24248c2ecf20Sopenharmony_ci		dma_addr_t end = dma_addr + EFX_EF10_MAX_TX_DESCRIPTOR_LEN;
24258c2ecf20Sopenharmony_ci
24268c2ecf20Sopenharmony_ci		BUILD_BUG_ON(EFX_EF10_MAX_TX_DESCRIPTOR_LEN < EFX_PAGE_SIZE);
24278c2ecf20Sopenharmony_ci		len = (end & (~(EFX_PAGE_SIZE - 1))) - dma_addr;
24288c2ecf20Sopenharmony_ci	}
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_ci	return len;
24318c2ecf20Sopenharmony_ci}
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_cistatic void efx_ef10_tx_write(struct efx_tx_queue *tx_queue)
24348c2ecf20Sopenharmony_ci{
24358c2ecf20Sopenharmony_ci	unsigned int old_write_count = tx_queue->write_count;
24368c2ecf20Sopenharmony_ci	struct efx_tx_buffer *buffer;
24378c2ecf20Sopenharmony_ci	unsigned int write_ptr;
24388c2ecf20Sopenharmony_ci	efx_qword_t *txd;
24398c2ecf20Sopenharmony_ci
24408c2ecf20Sopenharmony_ci	tx_queue->xmit_pending = false;
24418c2ecf20Sopenharmony_ci	if (unlikely(tx_queue->write_count == tx_queue->insert_count))
24428c2ecf20Sopenharmony_ci		return;
24438c2ecf20Sopenharmony_ci
24448c2ecf20Sopenharmony_ci	do {
24458c2ecf20Sopenharmony_ci		write_ptr = tx_queue->write_count & tx_queue->ptr_mask;
24468c2ecf20Sopenharmony_ci		buffer = &tx_queue->buffer[write_ptr];
24478c2ecf20Sopenharmony_ci		txd = efx_tx_desc(tx_queue, write_ptr);
24488c2ecf20Sopenharmony_ci		++tx_queue->write_count;
24498c2ecf20Sopenharmony_ci
24508c2ecf20Sopenharmony_ci		/* Create TX descriptor ring entry */
24518c2ecf20Sopenharmony_ci		if (buffer->flags & EFX_TX_BUF_OPTION) {
24528c2ecf20Sopenharmony_ci			*txd = buffer->option;
24538c2ecf20Sopenharmony_ci			if (EFX_QWORD_FIELD(*txd, ESF_DZ_TX_OPTION_TYPE) == 1)
24548c2ecf20Sopenharmony_ci				/* PIO descriptor */
24558c2ecf20Sopenharmony_ci				tx_queue->packet_write_count = tx_queue->write_count;
24568c2ecf20Sopenharmony_ci		} else {
24578c2ecf20Sopenharmony_ci			tx_queue->packet_write_count = tx_queue->write_count;
24588c2ecf20Sopenharmony_ci			BUILD_BUG_ON(EFX_TX_BUF_CONT != 1);
24598c2ecf20Sopenharmony_ci			EFX_POPULATE_QWORD_3(
24608c2ecf20Sopenharmony_ci				*txd,
24618c2ecf20Sopenharmony_ci				ESF_DZ_TX_KER_CONT,
24628c2ecf20Sopenharmony_ci				buffer->flags & EFX_TX_BUF_CONT,
24638c2ecf20Sopenharmony_ci				ESF_DZ_TX_KER_BYTE_CNT, buffer->len,
24648c2ecf20Sopenharmony_ci				ESF_DZ_TX_KER_BUF_ADDR, buffer->dma_addr);
24658c2ecf20Sopenharmony_ci		}
24668c2ecf20Sopenharmony_ci	} while (tx_queue->write_count != tx_queue->insert_count);
24678c2ecf20Sopenharmony_ci
24688c2ecf20Sopenharmony_ci	wmb(); /* Ensure descriptors are written before they are fetched */
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci	if (efx_nic_may_push_tx_desc(tx_queue, old_write_count)) {
24718c2ecf20Sopenharmony_ci		txd = efx_tx_desc(tx_queue,
24728c2ecf20Sopenharmony_ci				  old_write_count & tx_queue->ptr_mask);
24738c2ecf20Sopenharmony_ci		efx_ef10_push_tx_desc(tx_queue, txd);
24748c2ecf20Sopenharmony_ci		++tx_queue->pushes;
24758c2ecf20Sopenharmony_ci	} else {
24768c2ecf20Sopenharmony_ci		efx_ef10_notify_tx_desc(tx_queue);
24778c2ecf20Sopenharmony_ci	}
24788c2ecf20Sopenharmony_ci}
24798c2ecf20Sopenharmony_ci
24808c2ecf20Sopenharmony_cistatic int efx_ef10_probe_multicast_chaining(struct efx_nic *efx)
24818c2ecf20Sopenharmony_ci{
24828c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
24838c2ecf20Sopenharmony_ci	unsigned int enabled, implemented;
24848c2ecf20Sopenharmony_ci	bool want_workaround_26807;
24858c2ecf20Sopenharmony_ci	int rc;
24868c2ecf20Sopenharmony_ci
24878c2ecf20Sopenharmony_ci	rc = efx_mcdi_get_workarounds(efx, &implemented, &enabled);
24888c2ecf20Sopenharmony_ci	if (rc == -ENOSYS) {
24898c2ecf20Sopenharmony_ci		/* GET_WORKAROUNDS was implemented before this workaround,
24908c2ecf20Sopenharmony_ci		 * thus it must be unavailable in this firmware.
24918c2ecf20Sopenharmony_ci		 */
24928c2ecf20Sopenharmony_ci		nic_data->workaround_26807 = false;
24938c2ecf20Sopenharmony_ci		return 0;
24948c2ecf20Sopenharmony_ci	}
24958c2ecf20Sopenharmony_ci	if (rc)
24968c2ecf20Sopenharmony_ci		return rc;
24978c2ecf20Sopenharmony_ci	want_workaround_26807 =
24988c2ecf20Sopenharmony_ci		implemented & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807;
24998c2ecf20Sopenharmony_ci	nic_data->workaround_26807 =
25008c2ecf20Sopenharmony_ci		!!(enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807);
25018c2ecf20Sopenharmony_ci
25028c2ecf20Sopenharmony_ci	if (want_workaround_26807 && !nic_data->workaround_26807) {
25038c2ecf20Sopenharmony_ci		unsigned int flags;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci		rc = efx_mcdi_set_workaround(efx,
25068c2ecf20Sopenharmony_ci					     MC_CMD_WORKAROUND_BUG26807,
25078c2ecf20Sopenharmony_ci					     true, &flags);
25088c2ecf20Sopenharmony_ci		if (!rc) {
25098c2ecf20Sopenharmony_ci			if (flags &
25108c2ecf20Sopenharmony_ci			    1 << MC_CMD_WORKAROUND_EXT_OUT_FLR_DONE_LBN) {
25118c2ecf20Sopenharmony_ci				netif_info(efx, drv, efx->net_dev,
25128c2ecf20Sopenharmony_ci					   "other functions on NIC have been reset\n");
25138c2ecf20Sopenharmony_ci
25148c2ecf20Sopenharmony_ci				/* With MCFW v4.6.x and earlier, the
25158c2ecf20Sopenharmony_ci				 * boot count will have incremented,
25168c2ecf20Sopenharmony_ci				 * so re-read the warm_boot_count
25178c2ecf20Sopenharmony_ci				 * value now to ensure this function
25188c2ecf20Sopenharmony_ci				 * doesn't think it has changed next
25198c2ecf20Sopenharmony_ci				 * time it checks.
25208c2ecf20Sopenharmony_ci				 */
25218c2ecf20Sopenharmony_ci				rc = efx_ef10_get_warm_boot_count(efx);
25228c2ecf20Sopenharmony_ci				if (rc >= 0) {
25238c2ecf20Sopenharmony_ci					nic_data->warm_boot_count = rc;
25248c2ecf20Sopenharmony_ci					rc = 0;
25258c2ecf20Sopenharmony_ci				}
25268c2ecf20Sopenharmony_ci			}
25278c2ecf20Sopenharmony_ci			nic_data->workaround_26807 = true;
25288c2ecf20Sopenharmony_ci		} else if (rc == -EPERM) {
25298c2ecf20Sopenharmony_ci			rc = 0;
25308c2ecf20Sopenharmony_ci		}
25318c2ecf20Sopenharmony_ci	}
25328c2ecf20Sopenharmony_ci	return rc;
25338c2ecf20Sopenharmony_ci}
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_cistatic int efx_ef10_filter_table_probe(struct efx_nic *efx)
25368c2ecf20Sopenharmony_ci{
25378c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
25388c2ecf20Sopenharmony_ci	int rc = efx_ef10_probe_multicast_chaining(efx);
25398c2ecf20Sopenharmony_ci	struct efx_mcdi_filter_vlan *vlan;
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_ci	if (rc)
25428c2ecf20Sopenharmony_ci		return rc;
25438c2ecf20Sopenharmony_ci	rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807);
25448c2ecf20Sopenharmony_ci
25458c2ecf20Sopenharmony_ci	if (rc)
25468c2ecf20Sopenharmony_ci		return rc;
25478c2ecf20Sopenharmony_ci
25488c2ecf20Sopenharmony_ci	list_for_each_entry(vlan, &nic_data->vlan_list, list) {
25498c2ecf20Sopenharmony_ci		rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
25508c2ecf20Sopenharmony_ci		if (rc)
25518c2ecf20Sopenharmony_ci			goto fail_add_vlan;
25528c2ecf20Sopenharmony_ci	}
25538c2ecf20Sopenharmony_ci	return 0;
25548c2ecf20Sopenharmony_ci
25558c2ecf20Sopenharmony_cifail_add_vlan:
25568c2ecf20Sopenharmony_ci	efx_mcdi_filter_table_remove(efx);
25578c2ecf20Sopenharmony_ci	return rc;
25588c2ecf20Sopenharmony_ci}
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci/* This creates an entry in the RX descriptor queue */
25618c2ecf20Sopenharmony_cistatic inline void
25628c2ecf20Sopenharmony_ciefx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
25638c2ecf20Sopenharmony_ci{
25648c2ecf20Sopenharmony_ci	struct efx_rx_buffer *rx_buf;
25658c2ecf20Sopenharmony_ci	efx_qword_t *rxd;
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ci	rxd = efx_rx_desc(rx_queue, index);
25688c2ecf20Sopenharmony_ci	rx_buf = efx_rx_buffer(rx_queue, index);
25698c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_2(*rxd,
25708c2ecf20Sopenharmony_ci			     ESF_DZ_RX_KER_BYTE_CNT, rx_buf->len,
25718c2ecf20Sopenharmony_ci			     ESF_DZ_RX_KER_BUF_ADDR, rx_buf->dma_addr);
25728c2ecf20Sopenharmony_ci}
25738c2ecf20Sopenharmony_ci
25748c2ecf20Sopenharmony_cistatic void efx_ef10_rx_write(struct efx_rx_queue *rx_queue)
25758c2ecf20Sopenharmony_ci{
25768c2ecf20Sopenharmony_ci	struct efx_nic *efx = rx_queue->efx;
25778c2ecf20Sopenharmony_ci	unsigned int write_count;
25788c2ecf20Sopenharmony_ci	efx_dword_t reg;
25798c2ecf20Sopenharmony_ci
25808c2ecf20Sopenharmony_ci	/* Firmware requires that RX_DESC_WPTR be a multiple of 8 */
25818c2ecf20Sopenharmony_ci	write_count = rx_queue->added_count & ~7;
25828c2ecf20Sopenharmony_ci	if (rx_queue->notified_count == write_count)
25838c2ecf20Sopenharmony_ci		return;
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_ci	do
25868c2ecf20Sopenharmony_ci		efx_ef10_build_rx_desc(
25878c2ecf20Sopenharmony_ci			rx_queue,
25888c2ecf20Sopenharmony_ci			rx_queue->notified_count & rx_queue->ptr_mask);
25898c2ecf20Sopenharmony_ci	while (++rx_queue->notified_count != write_count);
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	wmb();
25928c2ecf20Sopenharmony_ci	EFX_POPULATE_DWORD_1(reg, ERF_DZ_RX_DESC_WPTR,
25938c2ecf20Sopenharmony_ci			     write_count & rx_queue->ptr_mask);
25948c2ecf20Sopenharmony_ci	efx_writed_page(efx, &reg, ER_DZ_RX_DESC_UPD,
25958c2ecf20Sopenharmony_ci			efx_rx_queue_index(rx_queue));
25968c2ecf20Sopenharmony_ci}
25978c2ecf20Sopenharmony_ci
25988c2ecf20Sopenharmony_cistatic efx_mcdi_async_completer efx_ef10_rx_defer_refill_complete;
25998c2ecf20Sopenharmony_ci
26008c2ecf20Sopenharmony_cistatic void efx_ef10_rx_defer_refill(struct efx_rx_queue *rx_queue)
26018c2ecf20Sopenharmony_ci{
26028c2ecf20Sopenharmony_ci	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
26038c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_DRIVER_EVENT_IN_LEN);
26048c2ecf20Sopenharmony_ci	efx_qword_t event;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_2(event,
26078c2ecf20Sopenharmony_ci			     ESF_DZ_EV_CODE, EFX_EF10_DRVGEN_EV,
26088c2ecf20Sopenharmony_ci			     ESF_DZ_EV_DATA, EFX_EF10_REFILL);
26098c2ecf20Sopenharmony_ci
26108c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, DRIVER_EVENT_IN_EVQ, channel->channel);
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci	/* MCDI_SET_QWORD is not appropriate here since EFX_POPULATE_* has
26138c2ecf20Sopenharmony_ci	 * already swapped the data to little-endian order.
26148c2ecf20Sopenharmony_ci	 */
26158c2ecf20Sopenharmony_ci	memcpy(MCDI_PTR(inbuf, DRIVER_EVENT_IN_DATA), &event.u64[0],
26168c2ecf20Sopenharmony_ci	       sizeof(efx_qword_t));
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ci	efx_mcdi_rpc_async(channel->efx, MC_CMD_DRIVER_EVENT,
26198c2ecf20Sopenharmony_ci			   inbuf, sizeof(inbuf), 0,
26208c2ecf20Sopenharmony_ci			   efx_ef10_rx_defer_refill_complete, 0);
26218c2ecf20Sopenharmony_ci}
26228c2ecf20Sopenharmony_ci
26238c2ecf20Sopenharmony_cistatic void
26248c2ecf20Sopenharmony_ciefx_ef10_rx_defer_refill_complete(struct efx_nic *efx, unsigned long cookie,
26258c2ecf20Sopenharmony_ci				  int rc, efx_dword_t *outbuf,
26268c2ecf20Sopenharmony_ci				  size_t outlen_actual)
26278c2ecf20Sopenharmony_ci{
26288c2ecf20Sopenharmony_ci	/* nothing to do */
26298c2ecf20Sopenharmony_ci}
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_cistatic int efx_ef10_ev_init(struct efx_channel *channel)
26328c2ecf20Sopenharmony_ci{
26338c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
26348c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data;
26358c2ecf20Sopenharmony_ci	bool use_v2, cut_thru;
26368c2ecf20Sopenharmony_ci
26378c2ecf20Sopenharmony_ci	nic_data = efx->nic_data;
26388c2ecf20Sopenharmony_ci	use_v2 = nic_data->datapath_caps2 &
26398c2ecf20Sopenharmony_ci			    1 << MC_CMD_GET_CAPABILITIES_V2_OUT_INIT_EVQ_V2_LBN;
26408c2ecf20Sopenharmony_ci	cut_thru = !(nic_data->datapath_caps &
26418c2ecf20Sopenharmony_ci			      1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN);
26428c2ecf20Sopenharmony_ci	return efx_mcdi_ev_init(channel, cut_thru, use_v2);
26438c2ecf20Sopenharmony_ci}
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_cistatic void efx_ef10_handle_rx_wrong_queue(struct efx_rx_queue *rx_queue,
26468c2ecf20Sopenharmony_ci					   unsigned int rx_queue_label)
26478c2ecf20Sopenharmony_ci{
26488c2ecf20Sopenharmony_ci	struct efx_nic *efx = rx_queue->efx;
26498c2ecf20Sopenharmony_ci
26508c2ecf20Sopenharmony_ci	netif_info(efx, hw, efx->net_dev,
26518c2ecf20Sopenharmony_ci		   "rx event arrived on queue %d labeled as queue %u\n",
26528c2ecf20Sopenharmony_ci		   efx_rx_queue_index(rx_queue), rx_queue_label);
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci	efx_schedule_reset(efx, RESET_TYPE_DISABLE);
26558c2ecf20Sopenharmony_ci}
26568c2ecf20Sopenharmony_ci
26578c2ecf20Sopenharmony_cistatic void
26588c2ecf20Sopenharmony_ciefx_ef10_handle_rx_bad_lbits(struct efx_rx_queue *rx_queue,
26598c2ecf20Sopenharmony_ci			     unsigned int actual, unsigned int expected)
26608c2ecf20Sopenharmony_ci{
26618c2ecf20Sopenharmony_ci	unsigned int dropped = (actual - expected) & rx_queue->ptr_mask;
26628c2ecf20Sopenharmony_ci	struct efx_nic *efx = rx_queue->efx;
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_ci	netif_info(efx, hw, efx->net_dev,
26658c2ecf20Sopenharmony_ci		   "dropped %d events (index=%d expected=%d)\n",
26668c2ecf20Sopenharmony_ci		   dropped, actual, expected);
26678c2ecf20Sopenharmony_ci
26688c2ecf20Sopenharmony_ci	efx_schedule_reset(efx, RESET_TYPE_DISABLE);
26698c2ecf20Sopenharmony_ci}
26708c2ecf20Sopenharmony_ci
26718c2ecf20Sopenharmony_ci/* partially received RX was aborted. clean up. */
26728c2ecf20Sopenharmony_cistatic void efx_ef10_handle_rx_abort(struct efx_rx_queue *rx_queue)
26738c2ecf20Sopenharmony_ci{
26748c2ecf20Sopenharmony_ci	unsigned int rx_desc_ptr;
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ci	netif_dbg(rx_queue->efx, hw, rx_queue->efx->net_dev,
26778c2ecf20Sopenharmony_ci		  "scattered RX aborted (dropping %u buffers)\n",
26788c2ecf20Sopenharmony_ci		  rx_queue->scatter_n);
26798c2ecf20Sopenharmony_ci
26808c2ecf20Sopenharmony_ci	rx_desc_ptr = rx_queue->removed_count & rx_queue->ptr_mask;
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci	efx_rx_packet(rx_queue, rx_desc_ptr, rx_queue->scatter_n,
26838c2ecf20Sopenharmony_ci		      0, EFX_RX_PKT_DISCARD);
26848c2ecf20Sopenharmony_ci
26858c2ecf20Sopenharmony_ci	rx_queue->removed_count += rx_queue->scatter_n;
26868c2ecf20Sopenharmony_ci	rx_queue->scatter_n = 0;
26878c2ecf20Sopenharmony_ci	rx_queue->scatter_len = 0;
26888c2ecf20Sopenharmony_ci	++efx_rx_queue_channel(rx_queue)->n_rx_nodesc_trunc;
26898c2ecf20Sopenharmony_ci}
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_cistatic u16 efx_ef10_handle_rx_event_errors(struct efx_channel *channel,
26928c2ecf20Sopenharmony_ci					   unsigned int n_packets,
26938c2ecf20Sopenharmony_ci					   unsigned int rx_encap_hdr,
26948c2ecf20Sopenharmony_ci					   unsigned int rx_l3_class,
26958c2ecf20Sopenharmony_ci					   unsigned int rx_l4_class,
26968c2ecf20Sopenharmony_ci					   const efx_qword_t *event)
26978c2ecf20Sopenharmony_ci{
26988c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
26998c2ecf20Sopenharmony_ci	bool handled = false;
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci	if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_ECRC_ERR)) {
27028c2ecf20Sopenharmony_ci		if (!(efx->net_dev->features & NETIF_F_RXALL)) {
27038c2ecf20Sopenharmony_ci			if (!efx->loopback_selftest)
27048c2ecf20Sopenharmony_ci				channel->n_rx_eth_crc_err += n_packets;
27058c2ecf20Sopenharmony_ci			return EFX_RX_PKT_DISCARD;
27068c2ecf20Sopenharmony_ci		}
27078c2ecf20Sopenharmony_ci		handled = true;
27088c2ecf20Sopenharmony_ci	}
27098c2ecf20Sopenharmony_ci	if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_IPCKSUM_ERR)) {
27108c2ecf20Sopenharmony_ci		if (unlikely(rx_encap_hdr != ESE_EZ_ENCAP_HDR_VXLAN &&
27118c2ecf20Sopenharmony_ci			     rx_l3_class != ESE_DZ_L3_CLASS_IP4 &&
27128c2ecf20Sopenharmony_ci			     rx_l3_class != ESE_DZ_L3_CLASS_IP4_FRAG &&
27138c2ecf20Sopenharmony_ci			     rx_l3_class != ESE_DZ_L3_CLASS_IP6 &&
27148c2ecf20Sopenharmony_ci			     rx_l3_class != ESE_DZ_L3_CLASS_IP6_FRAG))
27158c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
27168c2ecf20Sopenharmony_ci				    "invalid class for RX_IPCKSUM_ERR: event="
27178c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
27188c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
27198c2ecf20Sopenharmony_ci		if (!efx->loopback_selftest)
27208c2ecf20Sopenharmony_ci			*(rx_encap_hdr ?
27218c2ecf20Sopenharmony_ci			  &channel->n_rx_outer_ip_hdr_chksum_err :
27228c2ecf20Sopenharmony_ci			  &channel->n_rx_ip_hdr_chksum_err) += n_packets;
27238c2ecf20Sopenharmony_ci		return 0;
27248c2ecf20Sopenharmony_ci	}
27258c2ecf20Sopenharmony_ci	if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_TCPUDP_CKSUM_ERR)) {
27268c2ecf20Sopenharmony_ci		if (unlikely(rx_encap_hdr != ESE_EZ_ENCAP_HDR_VXLAN &&
27278c2ecf20Sopenharmony_ci			     ((rx_l3_class != ESE_DZ_L3_CLASS_IP4 &&
27288c2ecf20Sopenharmony_ci			       rx_l3_class != ESE_DZ_L3_CLASS_IP6) ||
27298c2ecf20Sopenharmony_ci			      (rx_l4_class != ESE_FZ_L4_CLASS_TCP &&
27308c2ecf20Sopenharmony_ci			       rx_l4_class != ESE_FZ_L4_CLASS_UDP))))
27318c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
27328c2ecf20Sopenharmony_ci				    "invalid class for RX_TCPUDP_CKSUM_ERR: event="
27338c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
27348c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
27358c2ecf20Sopenharmony_ci		if (!efx->loopback_selftest)
27368c2ecf20Sopenharmony_ci			*(rx_encap_hdr ?
27378c2ecf20Sopenharmony_ci			  &channel->n_rx_outer_tcp_udp_chksum_err :
27388c2ecf20Sopenharmony_ci			  &channel->n_rx_tcp_udp_chksum_err) += n_packets;
27398c2ecf20Sopenharmony_ci		return 0;
27408c2ecf20Sopenharmony_ci	}
27418c2ecf20Sopenharmony_ci	if (EFX_QWORD_FIELD(*event, ESF_EZ_RX_IP_INNER_CHKSUM_ERR)) {
27428c2ecf20Sopenharmony_ci		if (unlikely(!rx_encap_hdr))
27438c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
27448c2ecf20Sopenharmony_ci				    "invalid encapsulation type for RX_IP_INNER_CHKSUM_ERR: event="
27458c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
27468c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
27478c2ecf20Sopenharmony_ci		else if (unlikely(rx_l3_class != ESE_DZ_L3_CLASS_IP4 &&
27488c2ecf20Sopenharmony_ci				  rx_l3_class != ESE_DZ_L3_CLASS_IP4_FRAG &&
27498c2ecf20Sopenharmony_ci				  rx_l3_class != ESE_DZ_L3_CLASS_IP6 &&
27508c2ecf20Sopenharmony_ci				  rx_l3_class != ESE_DZ_L3_CLASS_IP6_FRAG))
27518c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
27528c2ecf20Sopenharmony_ci				    "invalid class for RX_IP_INNER_CHKSUM_ERR: event="
27538c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
27548c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
27558c2ecf20Sopenharmony_ci		if (!efx->loopback_selftest)
27568c2ecf20Sopenharmony_ci			channel->n_rx_inner_ip_hdr_chksum_err += n_packets;
27578c2ecf20Sopenharmony_ci		return 0;
27588c2ecf20Sopenharmony_ci	}
27598c2ecf20Sopenharmony_ci	if (EFX_QWORD_FIELD(*event, ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR)) {
27608c2ecf20Sopenharmony_ci		if (unlikely(!rx_encap_hdr))
27618c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
27628c2ecf20Sopenharmony_ci				    "invalid encapsulation type for RX_TCP_UDP_INNER_CHKSUM_ERR: event="
27638c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
27648c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
27658c2ecf20Sopenharmony_ci		else if (unlikely((rx_l3_class != ESE_DZ_L3_CLASS_IP4 &&
27668c2ecf20Sopenharmony_ci				   rx_l3_class != ESE_DZ_L3_CLASS_IP6) ||
27678c2ecf20Sopenharmony_ci				  (rx_l4_class != ESE_FZ_L4_CLASS_TCP &&
27688c2ecf20Sopenharmony_ci				   rx_l4_class != ESE_FZ_L4_CLASS_UDP)))
27698c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
27708c2ecf20Sopenharmony_ci				    "invalid class for RX_TCP_UDP_INNER_CHKSUM_ERR: event="
27718c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
27728c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
27738c2ecf20Sopenharmony_ci		if (!efx->loopback_selftest)
27748c2ecf20Sopenharmony_ci			channel->n_rx_inner_tcp_udp_chksum_err += n_packets;
27758c2ecf20Sopenharmony_ci		return 0;
27768c2ecf20Sopenharmony_ci	}
27778c2ecf20Sopenharmony_ci
27788c2ecf20Sopenharmony_ci	WARN_ON(!handled); /* No error bits were recognised */
27798c2ecf20Sopenharmony_ci	return 0;
27808c2ecf20Sopenharmony_ci}
27818c2ecf20Sopenharmony_ci
27828c2ecf20Sopenharmony_cistatic int efx_ef10_handle_rx_event(struct efx_channel *channel,
27838c2ecf20Sopenharmony_ci				    const efx_qword_t *event)
27848c2ecf20Sopenharmony_ci{
27858c2ecf20Sopenharmony_ci	unsigned int rx_bytes, next_ptr_lbits, rx_queue_label;
27868c2ecf20Sopenharmony_ci	unsigned int rx_l3_class, rx_l4_class, rx_encap_hdr;
27878c2ecf20Sopenharmony_ci	unsigned int n_descs, n_packets, i;
27888c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
27898c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
27908c2ecf20Sopenharmony_ci	struct efx_rx_queue *rx_queue;
27918c2ecf20Sopenharmony_ci	efx_qword_t errors;
27928c2ecf20Sopenharmony_ci	bool rx_cont;
27938c2ecf20Sopenharmony_ci	u16 flags = 0;
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	if (unlikely(READ_ONCE(efx->reset_pending)))
27968c2ecf20Sopenharmony_ci		return 0;
27978c2ecf20Sopenharmony_ci
27988c2ecf20Sopenharmony_ci	/* Basic packet information */
27998c2ecf20Sopenharmony_ci	rx_bytes = EFX_QWORD_FIELD(*event, ESF_DZ_RX_BYTES);
28008c2ecf20Sopenharmony_ci	next_ptr_lbits = EFX_QWORD_FIELD(*event, ESF_DZ_RX_DSC_PTR_LBITS);
28018c2ecf20Sopenharmony_ci	rx_queue_label = EFX_QWORD_FIELD(*event, ESF_DZ_RX_QLABEL);
28028c2ecf20Sopenharmony_ci	rx_l3_class = EFX_QWORD_FIELD(*event, ESF_DZ_RX_L3_CLASS);
28038c2ecf20Sopenharmony_ci	rx_l4_class = EFX_QWORD_FIELD(*event, ESF_FZ_RX_L4_CLASS);
28048c2ecf20Sopenharmony_ci	rx_cont = EFX_QWORD_FIELD(*event, ESF_DZ_RX_CONT);
28058c2ecf20Sopenharmony_ci	rx_encap_hdr =
28068c2ecf20Sopenharmony_ci		nic_data->datapath_caps &
28078c2ecf20Sopenharmony_ci			(1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN) ?
28088c2ecf20Sopenharmony_ci		EFX_QWORD_FIELD(*event, ESF_EZ_RX_ENCAP_HDR) :
28098c2ecf20Sopenharmony_ci		ESE_EZ_ENCAP_HDR_NONE;
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	if (EFX_QWORD_FIELD(*event, ESF_DZ_RX_DROP_EVENT))
28128c2ecf20Sopenharmony_ci		netdev_WARN(efx->net_dev, "saw RX_DROP_EVENT: event="
28138c2ecf20Sopenharmony_ci			    EFX_QWORD_FMT "\n",
28148c2ecf20Sopenharmony_ci			    EFX_QWORD_VAL(*event));
28158c2ecf20Sopenharmony_ci
28168c2ecf20Sopenharmony_ci	rx_queue = efx_channel_get_rx_queue(channel);
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_ci	if (unlikely(rx_queue_label != efx_rx_queue_index(rx_queue)))
28198c2ecf20Sopenharmony_ci		efx_ef10_handle_rx_wrong_queue(rx_queue, rx_queue_label);
28208c2ecf20Sopenharmony_ci
28218c2ecf20Sopenharmony_ci	n_descs = ((next_ptr_lbits - rx_queue->removed_count) &
28228c2ecf20Sopenharmony_ci		   ((1 << ESF_DZ_RX_DSC_PTR_LBITS_WIDTH) - 1));
28238c2ecf20Sopenharmony_ci
28248c2ecf20Sopenharmony_ci	if (n_descs != rx_queue->scatter_n + 1) {
28258c2ecf20Sopenharmony_ci		struct efx_ef10_nic_data *nic_data = efx->nic_data;
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci		/* detect rx abort */
28288c2ecf20Sopenharmony_ci		if (unlikely(n_descs == rx_queue->scatter_n)) {
28298c2ecf20Sopenharmony_ci			if (rx_queue->scatter_n == 0 || rx_bytes != 0)
28308c2ecf20Sopenharmony_ci				netdev_WARN(efx->net_dev,
28318c2ecf20Sopenharmony_ci					    "invalid RX abort: scatter_n=%u event="
28328c2ecf20Sopenharmony_ci					    EFX_QWORD_FMT "\n",
28338c2ecf20Sopenharmony_ci					    rx_queue->scatter_n,
28348c2ecf20Sopenharmony_ci					    EFX_QWORD_VAL(*event));
28358c2ecf20Sopenharmony_ci			efx_ef10_handle_rx_abort(rx_queue);
28368c2ecf20Sopenharmony_ci			return 0;
28378c2ecf20Sopenharmony_ci		}
28388c2ecf20Sopenharmony_ci
28398c2ecf20Sopenharmony_ci		/* Check that RX completion merging is valid, i.e.
28408c2ecf20Sopenharmony_ci		 * the current firmware supports it and this is a
28418c2ecf20Sopenharmony_ci		 * non-scattered packet.
28428c2ecf20Sopenharmony_ci		 */
28438c2ecf20Sopenharmony_ci		if (!(nic_data->datapath_caps &
28448c2ecf20Sopenharmony_ci		      (1 << MC_CMD_GET_CAPABILITIES_OUT_RX_BATCHING_LBN)) ||
28458c2ecf20Sopenharmony_ci		    rx_queue->scatter_n != 0 || rx_cont) {
28468c2ecf20Sopenharmony_ci			efx_ef10_handle_rx_bad_lbits(
28478c2ecf20Sopenharmony_ci				rx_queue, next_ptr_lbits,
28488c2ecf20Sopenharmony_ci				(rx_queue->removed_count +
28498c2ecf20Sopenharmony_ci				 rx_queue->scatter_n + 1) &
28508c2ecf20Sopenharmony_ci				((1 << ESF_DZ_RX_DSC_PTR_LBITS_WIDTH) - 1));
28518c2ecf20Sopenharmony_ci			return 0;
28528c2ecf20Sopenharmony_ci		}
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci		/* Merged completion for multiple non-scattered packets */
28558c2ecf20Sopenharmony_ci		rx_queue->scatter_n = 1;
28568c2ecf20Sopenharmony_ci		rx_queue->scatter_len = 0;
28578c2ecf20Sopenharmony_ci		n_packets = n_descs;
28588c2ecf20Sopenharmony_ci		++channel->n_rx_merge_events;
28598c2ecf20Sopenharmony_ci		channel->n_rx_merge_packets += n_packets;
28608c2ecf20Sopenharmony_ci		flags |= EFX_RX_PKT_PREFIX_LEN;
28618c2ecf20Sopenharmony_ci	} else {
28628c2ecf20Sopenharmony_ci		++rx_queue->scatter_n;
28638c2ecf20Sopenharmony_ci		rx_queue->scatter_len += rx_bytes;
28648c2ecf20Sopenharmony_ci		if (rx_cont)
28658c2ecf20Sopenharmony_ci			return 0;
28668c2ecf20Sopenharmony_ci		n_packets = 1;
28678c2ecf20Sopenharmony_ci	}
28688c2ecf20Sopenharmony_ci
28698c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_5(errors, ESF_DZ_RX_ECRC_ERR, 1,
28708c2ecf20Sopenharmony_ci				     ESF_DZ_RX_IPCKSUM_ERR, 1,
28718c2ecf20Sopenharmony_ci				     ESF_DZ_RX_TCPUDP_CKSUM_ERR, 1,
28728c2ecf20Sopenharmony_ci				     ESF_EZ_RX_IP_INNER_CHKSUM_ERR, 1,
28738c2ecf20Sopenharmony_ci				     ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR, 1);
28748c2ecf20Sopenharmony_ci	EFX_AND_QWORD(errors, *event, errors);
28758c2ecf20Sopenharmony_ci	if (unlikely(!EFX_QWORD_IS_ZERO(errors))) {
28768c2ecf20Sopenharmony_ci		flags |= efx_ef10_handle_rx_event_errors(channel, n_packets,
28778c2ecf20Sopenharmony_ci							 rx_encap_hdr,
28788c2ecf20Sopenharmony_ci							 rx_l3_class, rx_l4_class,
28798c2ecf20Sopenharmony_ci							 event);
28808c2ecf20Sopenharmony_ci	} else {
28818c2ecf20Sopenharmony_ci		bool tcpudp = rx_l4_class == ESE_FZ_L4_CLASS_TCP ||
28828c2ecf20Sopenharmony_ci			      rx_l4_class == ESE_FZ_L4_CLASS_UDP;
28838c2ecf20Sopenharmony_ci
28848c2ecf20Sopenharmony_ci		switch (rx_encap_hdr) {
28858c2ecf20Sopenharmony_ci		case ESE_EZ_ENCAP_HDR_VXLAN: /* VxLAN or GENEVE */
28868c2ecf20Sopenharmony_ci			flags |= EFX_RX_PKT_CSUMMED; /* outer UDP csum */
28878c2ecf20Sopenharmony_ci			if (tcpudp)
28888c2ecf20Sopenharmony_ci				flags |= EFX_RX_PKT_CSUM_LEVEL; /* inner L4 */
28898c2ecf20Sopenharmony_ci			break;
28908c2ecf20Sopenharmony_ci		case ESE_EZ_ENCAP_HDR_GRE:
28918c2ecf20Sopenharmony_ci		case ESE_EZ_ENCAP_HDR_NONE:
28928c2ecf20Sopenharmony_ci			if (tcpudp)
28938c2ecf20Sopenharmony_ci				flags |= EFX_RX_PKT_CSUMMED;
28948c2ecf20Sopenharmony_ci			break;
28958c2ecf20Sopenharmony_ci		default:
28968c2ecf20Sopenharmony_ci			netdev_WARN(efx->net_dev,
28978c2ecf20Sopenharmony_ci				    "unknown encapsulation type: event="
28988c2ecf20Sopenharmony_ci				    EFX_QWORD_FMT "\n",
28998c2ecf20Sopenharmony_ci				    EFX_QWORD_VAL(*event));
29008c2ecf20Sopenharmony_ci		}
29018c2ecf20Sopenharmony_ci	}
29028c2ecf20Sopenharmony_ci
29038c2ecf20Sopenharmony_ci	if (rx_l4_class == ESE_FZ_L4_CLASS_TCP)
29048c2ecf20Sopenharmony_ci		flags |= EFX_RX_PKT_TCP;
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	channel->irq_mod_score += 2 * n_packets;
29078c2ecf20Sopenharmony_ci
29088c2ecf20Sopenharmony_ci	/* Handle received packet(s) */
29098c2ecf20Sopenharmony_ci	for (i = 0; i < n_packets; i++) {
29108c2ecf20Sopenharmony_ci		efx_rx_packet(rx_queue,
29118c2ecf20Sopenharmony_ci			      rx_queue->removed_count & rx_queue->ptr_mask,
29128c2ecf20Sopenharmony_ci			      rx_queue->scatter_n, rx_queue->scatter_len,
29138c2ecf20Sopenharmony_ci			      flags);
29148c2ecf20Sopenharmony_ci		rx_queue->removed_count += rx_queue->scatter_n;
29158c2ecf20Sopenharmony_ci	}
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	rx_queue->scatter_n = 0;
29188c2ecf20Sopenharmony_ci	rx_queue->scatter_len = 0;
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_ci	return n_packets;
29218c2ecf20Sopenharmony_ci}
29228c2ecf20Sopenharmony_ci
29238c2ecf20Sopenharmony_cistatic u32 efx_ef10_extract_event_ts(efx_qword_t *event)
29248c2ecf20Sopenharmony_ci{
29258c2ecf20Sopenharmony_ci	u32 tstamp;
29268c2ecf20Sopenharmony_ci
29278c2ecf20Sopenharmony_ci	tstamp = EFX_QWORD_FIELD(*event, TX_TIMESTAMP_EVENT_TSTAMP_DATA_HI);
29288c2ecf20Sopenharmony_ci	tstamp <<= 16;
29298c2ecf20Sopenharmony_ci	tstamp |= EFX_QWORD_FIELD(*event, TX_TIMESTAMP_EVENT_TSTAMP_DATA_LO);
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	return tstamp;
29328c2ecf20Sopenharmony_ci}
29338c2ecf20Sopenharmony_ci
29348c2ecf20Sopenharmony_cistatic void
29358c2ecf20Sopenharmony_ciefx_ef10_handle_tx_event(struct efx_channel *channel, efx_qword_t *event)
29368c2ecf20Sopenharmony_ci{
29378c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
29388c2ecf20Sopenharmony_ci	struct efx_tx_queue *tx_queue;
29398c2ecf20Sopenharmony_ci	unsigned int tx_ev_desc_ptr;
29408c2ecf20Sopenharmony_ci	unsigned int tx_ev_q_label;
29418c2ecf20Sopenharmony_ci	unsigned int tx_ev_type;
29428c2ecf20Sopenharmony_ci	u64 ts_part;
29438c2ecf20Sopenharmony_ci
29448c2ecf20Sopenharmony_ci	if (unlikely(READ_ONCE(efx->reset_pending)))
29458c2ecf20Sopenharmony_ci		return;
29468c2ecf20Sopenharmony_ci
29478c2ecf20Sopenharmony_ci	if (unlikely(EFX_QWORD_FIELD(*event, ESF_DZ_TX_DROP_EVENT)))
29488c2ecf20Sopenharmony_ci		return;
29498c2ecf20Sopenharmony_ci
29508c2ecf20Sopenharmony_ci	/* Get the transmit queue */
29518c2ecf20Sopenharmony_ci	tx_ev_q_label = EFX_QWORD_FIELD(*event, ESF_DZ_TX_QLABEL);
29528c2ecf20Sopenharmony_ci	tx_queue = channel->tx_queue + (tx_ev_q_label % EFX_MAX_TXQ_PER_CHANNEL);
29538c2ecf20Sopenharmony_ci
29548c2ecf20Sopenharmony_ci	if (!tx_queue->timestamping) {
29558c2ecf20Sopenharmony_ci		/* Transmit completion */
29568c2ecf20Sopenharmony_ci		tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, ESF_DZ_TX_DESCR_INDX);
29578c2ecf20Sopenharmony_ci		efx_xmit_done(tx_queue, tx_ev_desc_ptr & tx_queue->ptr_mask);
29588c2ecf20Sopenharmony_ci		return;
29598c2ecf20Sopenharmony_ci	}
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_ci	/* Transmit timestamps are only available for 8XXX series. They result
29628c2ecf20Sopenharmony_ci	 * in up to three events per packet. These occur in order, and are:
29638c2ecf20Sopenharmony_ci	 *  - the normal completion event (may be omitted)
29648c2ecf20Sopenharmony_ci	 *  - the low part of the timestamp
29658c2ecf20Sopenharmony_ci	 *  - the high part of the timestamp
29668c2ecf20Sopenharmony_ci	 *
29678c2ecf20Sopenharmony_ci	 * It's possible for multiple completion events to appear before the
29688c2ecf20Sopenharmony_ci	 * corresponding timestamps. So we can for example get:
29698c2ecf20Sopenharmony_ci	 *  COMP N
29708c2ecf20Sopenharmony_ci	 *  COMP N+1
29718c2ecf20Sopenharmony_ci	 *  TS_LO N
29728c2ecf20Sopenharmony_ci	 *  TS_HI N
29738c2ecf20Sopenharmony_ci	 *  TS_LO N+1
29748c2ecf20Sopenharmony_ci	 *  TS_HI N+1
29758c2ecf20Sopenharmony_ci	 *
29768c2ecf20Sopenharmony_ci	 * In addition it's also possible for the adjacent completions to be
29778c2ecf20Sopenharmony_ci	 * merged, so we may not see COMP N above. As such, the completion
29788c2ecf20Sopenharmony_ci	 * events are not very useful here.
29798c2ecf20Sopenharmony_ci	 *
29808c2ecf20Sopenharmony_ci	 * Each part of the timestamp is itself split across two 16 bit
29818c2ecf20Sopenharmony_ci	 * fields in the event.
29828c2ecf20Sopenharmony_ci	 */
29838c2ecf20Sopenharmony_ci	tx_ev_type = EFX_QWORD_FIELD(*event, ESF_EZ_TX_SOFT1);
29848c2ecf20Sopenharmony_ci
29858c2ecf20Sopenharmony_ci	switch (tx_ev_type) {
29868c2ecf20Sopenharmony_ci	case TX_TIMESTAMP_EVENT_TX_EV_COMPLETION:
29878c2ecf20Sopenharmony_ci		/* Ignore this event - see above. */
29888c2ecf20Sopenharmony_ci		break;
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci	case TX_TIMESTAMP_EVENT_TX_EV_TSTAMP_LO:
29918c2ecf20Sopenharmony_ci		ts_part = efx_ef10_extract_event_ts(event);
29928c2ecf20Sopenharmony_ci		tx_queue->completed_timestamp_minor = ts_part;
29938c2ecf20Sopenharmony_ci		break;
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci	case TX_TIMESTAMP_EVENT_TX_EV_TSTAMP_HI:
29968c2ecf20Sopenharmony_ci		ts_part = efx_ef10_extract_event_ts(event);
29978c2ecf20Sopenharmony_ci		tx_queue->completed_timestamp_major = ts_part;
29988c2ecf20Sopenharmony_ci
29998c2ecf20Sopenharmony_ci		efx_xmit_done_single(tx_queue);
30008c2ecf20Sopenharmony_ci		break;
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci	default:
30038c2ecf20Sopenharmony_ci		netif_err(efx, hw, efx->net_dev,
30048c2ecf20Sopenharmony_ci			  "channel %d unknown tx event type %d (data "
30058c2ecf20Sopenharmony_ci			  EFX_QWORD_FMT ")\n",
30068c2ecf20Sopenharmony_ci			  channel->channel, tx_ev_type,
30078c2ecf20Sopenharmony_ci			  EFX_QWORD_VAL(*event));
30088c2ecf20Sopenharmony_ci		break;
30098c2ecf20Sopenharmony_ci	}
30108c2ecf20Sopenharmony_ci}
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_cistatic void
30138c2ecf20Sopenharmony_ciefx_ef10_handle_driver_event(struct efx_channel *channel, efx_qword_t *event)
30148c2ecf20Sopenharmony_ci{
30158c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
30168c2ecf20Sopenharmony_ci	int subcode;
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_ci	subcode = EFX_QWORD_FIELD(*event, ESF_DZ_DRV_SUB_CODE);
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_ci	switch (subcode) {
30218c2ecf20Sopenharmony_ci	case ESE_DZ_DRV_TIMER_EV:
30228c2ecf20Sopenharmony_ci	case ESE_DZ_DRV_WAKE_UP_EV:
30238c2ecf20Sopenharmony_ci		break;
30248c2ecf20Sopenharmony_ci	case ESE_DZ_DRV_START_UP_EV:
30258c2ecf20Sopenharmony_ci		/* event queue init complete. ok. */
30268c2ecf20Sopenharmony_ci		break;
30278c2ecf20Sopenharmony_ci	default:
30288c2ecf20Sopenharmony_ci		netif_err(efx, hw, efx->net_dev,
30298c2ecf20Sopenharmony_ci			  "channel %d unknown driver event type %d"
30308c2ecf20Sopenharmony_ci			  " (data " EFX_QWORD_FMT ")\n",
30318c2ecf20Sopenharmony_ci			  channel->channel, subcode,
30328c2ecf20Sopenharmony_ci			  EFX_QWORD_VAL(*event));
30338c2ecf20Sopenharmony_ci
30348c2ecf20Sopenharmony_ci	}
30358c2ecf20Sopenharmony_ci}
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_cistatic void efx_ef10_handle_driver_generated_event(struct efx_channel *channel,
30388c2ecf20Sopenharmony_ci						   efx_qword_t *event)
30398c2ecf20Sopenharmony_ci{
30408c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
30418c2ecf20Sopenharmony_ci	u32 subcode;
30428c2ecf20Sopenharmony_ci
30438c2ecf20Sopenharmony_ci	subcode = EFX_QWORD_FIELD(*event, EFX_DWORD_0);
30448c2ecf20Sopenharmony_ci
30458c2ecf20Sopenharmony_ci	switch (subcode) {
30468c2ecf20Sopenharmony_ci	case EFX_EF10_TEST:
30478c2ecf20Sopenharmony_ci		channel->event_test_cpu = raw_smp_processor_id();
30488c2ecf20Sopenharmony_ci		break;
30498c2ecf20Sopenharmony_ci	case EFX_EF10_REFILL:
30508c2ecf20Sopenharmony_ci		/* The queue must be empty, so we won't receive any rx
30518c2ecf20Sopenharmony_ci		 * events, so efx_process_channel() won't refill the
30528c2ecf20Sopenharmony_ci		 * queue. Refill it here
30538c2ecf20Sopenharmony_ci		 */
30548c2ecf20Sopenharmony_ci		efx_fast_push_rx_descriptors(&channel->rx_queue, true);
30558c2ecf20Sopenharmony_ci		break;
30568c2ecf20Sopenharmony_ci	default:
30578c2ecf20Sopenharmony_ci		netif_err(efx, hw, efx->net_dev,
30588c2ecf20Sopenharmony_ci			  "channel %d unknown driver event type %u"
30598c2ecf20Sopenharmony_ci			  " (data " EFX_QWORD_FMT ")\n",
30608c2ecf20Sopenharmony_ci			  channel->channel, (unsigned) subcode,
30618c2ecf20Sopenharmony_ci			  EFX_QWORD_VAL(*event));
30628c2ecf20Sopenharmony_ci	}
30638c2ecf20Sopenharmony_ci}
30648c2ecf20Sopenharmony_ci
30658c2ecf20Sopenharmony_cistatic int efx_ef10_ev_process(struct efx_channel *channel, int quota)
30668c2ecf20Sopenharmony_ci{
30678c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
30688c2ecf20Sopenharmony_ci	efx_qword_t event, *p_event;
30698c2ecf20Sopenharmony_ci	unsigned int read_ptr;
30708c2ecf20Sopenharmony_ci	int ev_code;
30718c2ecf20Sopenharmony_ci	int spent = 0;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci	if (quota <= 0)
30748c2ecf20Sopenharmony_ci		return spent;
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_ci	read_ptr = channel->eventq_read_ptr;
30778c2ecf20Sopenharmony_ci
30788c2ecf20Sopenharmony_ci	for (;;) {
30798c2ecf20Sopenharmony_ci		p_event = efx_event(channel, read_ptr);
30808c2ecf20Sopenharmony_ci		event = *p_event;
30818c2ecf20Sopenharmony_ci
30828c2ecf20Sopenharmony_ci		if (!efx_event_present(&event))
30838c2ecf20Sopenharmony_ci			break;
30848c2ecf20Sopenharmony_ci
30858c2ecf20Sopenharmony_ci		EFX_SET_QWORD(*p_event);
30868c2ecf20Sopenharmony_ci
30878c2ecf20Sopenharmony_ci		++read_ptr;
30888c2ecf20Sopenharmony_ci
30898c2ecf20Sopenharmony_ci		ev_code = EFX_QWORD_FIELD(event, ESF_DZ_EV_CODE);
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_ci		netif_vdbg(efx, drv, efx->net_dev,
30928c2ecf20Sopenharmony_ci			   "processing event on %d " EFX_QWORD_FMT "\n",
30938c2ecf20Sopenharmony_ci			   channel->channel, EFX_QWORD_VAL(event));
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_ci		switch (ev_code) {
30968c2ecf20Sopenharmony_ci		case ESE_DZ_EV_CODE_MCDI_EV:
30978c2ecf20Sopenharmony_ci			efx_mcdi_process_event(channel, &event);
30988c2ecf20Sopenharmony_ci			break;
30998c2ecf20Sopenharmony_ci		case ESE_DZ_EV_CODE_RX_EV:
31008c2ecf20Sopenharmony_ci			spent += efx_ef10_handle_rx_event(channel, &event);
31018c2ecf20Sopenharmony_ci			if (spent >= quota) {
31028c2ecf20Sopenharmony_ci				/* XXX can we split a merged event to
31038c2ecf20Sopenharmony_ci				 * avoid going over-quota?
31048c2ecf20Sopenharmony_ci				 */
31058c2ecf20Sopenharmony_ci				spent = quota;
31068c2ecf20Sopenharmony_ci				goto out;
31078c2ecf20Sopenharmony_ci			}
31088c2ecf20Sopenharmony_ci			break;
31098c2ecf20Sopenharmony_ci		case ESE_DZ_EV_CODE_TX_EV:
31108c2ecf20Sopenharmony_ci			efx_ef10_handle_tx_event(channel, &event);
31118c2ecf20Sopenharmony_ci			break;
31128c2ecf20Sopenharmony_ci		case ESE_DZ_EV_CODE_DRIVER_EV:
31138c2ecf20Sopenharmony_ci			efx_ef10_handle_driver_event(channel, &event);
31148c2ecf20Sopenharmony_ci			if (++spent == quota)
31158c2ecf20Sopenharmony_ci				goto out;
31168c2ecf20Sopenharmony_ci			break;
31178c2ecf20Sopenharmony_ci		case EFX_EF10_DRVGEN_EV:
31188c2ecf20Sopenharmony_ci			efx_ef10_handle_driver_generated_event(channel, &event);
31198c2ecf20Sopenharmony_ci			break;
31208c2ecf20Sopenharmony_ci		default:
31218c2ecf20Sopenharmony_ci			netif_err(efx, hw, efx->net_dev,
31228c2ecf20Sopenharmony_ci				  "channel %d unknown event type %d"
31238c2ecf20Sopenharmony_ci				  " (data " EFX_QWORD_FMT ")\n",
31248c2ecf20Sopenharmony_ci				  channel->channel, ev_code,
31258c2ecf20Sopenharmony_ci				  EFX_QWORD_VAL(event));
31268c2ecf20Sopenharmony_ci		}
31278c2ecf20Sopenharmony_ci	}
31288c2ecf20Sopenharmony_ci
31298c2ecf20Sopenharmony_ciout:
31308c2ecf20Sopenharmony_ci	channel->eventq_read_ptr = read_ptr;
31318c2ecf20Sopenharmony_ci	return spent;
31328c2ecf20Sopenharmony_ci}
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_cistatic void efx_ef10_ev_read_ack(struct efx_channel *channel)
31358c2ecf20Sopenharmony_ci{
31368c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
31378c2ecf20Sopenharmony_ci	efx_dword_t rptr;
31388c2ecf20Sopenharmony_ci
31398c2ecf20Sopenharmony_ci	if (EFX_EF10_WORKAROUND_35388(efx)) {
31408c2ecf20Sopenharmony_ci		BUILD_BUG_ON(EFX_MIN_EVQ_SIZE <
31418c2ecf20Sopenharmony_ci			     (1 << ERF_DD_EVQ_IND_RPTR_WIDTH));
31428c2ecf20Sopenharmony_ci		BUILD_BUG_ON(EFX_MAX_EVQ_SIZE >
31438c2ecf20Sopenharmony_ci			     (1 << 2 * ERF_DD_EVQ_IND_RPTR_WIDTH));
31448c2ecf20Sopenharmony_ci
31458c2ecf20Sopenharmony_ci		EFX_POPULATE_DWORD_2(rptr, ERF_DD_EVQ_IND_RPTR_FLAGS,
31468c2ecf20Sopenharmony_ci				     EFE_DD_EVQ_IND_RPTR_FLAGS_HIGH,
31478c2ecf20Sopenharmony_ci				     ERF_DD_EVQ_IND_RPTR,
31488c2ecf20Sopenharmony_ci				     (channel->eventq_read_ptr &
31498c2ecf20Sopenharmony_ci				      channel->eventq_mask) >>
31508c2ecf20Sopenharmony_ci				     ERF_DD_EVQ_IND_RPTR_WIDTH);
31518c2ecf20Sopenharmony_ci		efx_writed_page(efx, &rptr, ER_DD_EVQ_INDIRECT,
31528c2ecf20Sopenharmony_ci				channel->channel);
31538c2ecf20Sopenharmony_ci		EFX_POPULATE_DWORD_2(rptr, ERF_DD_EVQ_IND_RPTR_FLAGS,
31548c2ecf20Sopenharmony_ci				     EFE_DD_EVQ_IND_RPTR_FLAGS_LOW,
31558c2ecf20Sopenharmony_ci				     ERF_DD_EVQ_IND_RPTR,
31568c2ecf20Sopenharmony_ci				     channel->eventq_read_ptr &
31578c2ecf20Sopenharmony_ci				     ((1 << ERF_DD_EVQ_IND_RPTR_WIDTH) - 1));
31588c2ecf20Sopenharmony_ci		efx_writed_page(efx, &rptr, ER_DD_EVQ_INDIRECT,
31598c2ecf20Sopenharmony_ci				channel->channel);
31608c2ecf20Sopenharmony_ci	} else {
31618c2ecf20Sopenharmony_ci		EFX_POPULATE_DWORD_1(rptr, ERF_DZ_EVQ_RPTR,
31628c2ecf20Sopenharmony_ci				     channel->eventq_read_ptr &
31638c2ecf20Sopenharmony_ci				     channel->eventq_mask);
31648c2ecf20Sopenharmony_ci		efx_writed_page(efx, &rptr, ER_DZ_EVQ_RPTR, channel->channel);
31658c2ecf20Sopenharmony_ci	}
31668c2ecf20Sopenharmony_ci}
31678c2ecf20Sopenharmony_ci
31688c2ecf20Sopenharmony_cistatic void efx_ef10_ev_test_generate(struct efx_channel *channel)
31698c2ecf20Sopenharmony_ci{
31708c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_DRIVER_EVENT_IN_LEN);
31718c2ecf20Sopenharmony_ci	struct efx_nic *efx = channel->efx;
31728c2ecf20Sopenharmony_ci	efx_qword_t event;
31738c2ecf20Sopenharmony_ci	int rc;
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	EFX_POPULATE_QWORD_2(event,
31768c2ecf20Sopenharmony_ci			     ESF_DZ_EV_CODE, EFX_EF10_DRVGEN_EV,
31778c2ecf20Sopenharmony_ci			     ESF_DZ_EV_DATA, EFX_EF10_TEST);
31788c2ecf20Sopenharmony_ci
31798c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, DRIVER_EVENT_IN_EVQ, channel->channel);
31808c2ecf20Sopenharmony_ci
31818c2ecf20Sopenharmony_ci	/* MCDI_SET_QWORD is not appropriate here since EFX_POPULATE_* has
31828c2ecf20Sopenharmony_ci	 * already swapped the data to little-endian order.
31838c2ecf20Sopenharmony_ci	 */
31848c2ecf20Sopenharmony_ci	memcpy(MCDI_PTR(inbuf, DRIVER_EVENT_IN_DATA), &event.u64[0],
31858c2ecf20Sopenharmony_ci	       sizeof(efx_qword_t));
31868c2ecf20Sopenharmony_ci
31878c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_DRIVER_EVENT, inbuf, sizeof(inbuf),
31888c2ecf20Sopenharmony_ci			  NULL, 0, NULL);
31898c2ecf20Sopenharmony_ci	if (rc != 0)
31908c2ecf20Sopenharmony_ci		goto fail;
31918c2ecf20Sopenharmony_ci
31928c2ecf20Sopenharmony_ci	return;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_cifail:
31958c2ecf20Sopenharmony_ci	WARN_ON(true);
31968c2ecf20Sopenharmony_ci	netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
31978c2ecf20Sopenharmony_ci}
31988c2ecf20Sopenharmony_ci
31998c2ecf20Sopenharmony_cistatic void efx_ef10_prepare_flr(struct efx_nic *efx)
32008c2ecf20Sopenharmony_ci{
32018c2ecf20Sopenharmony_ci	atomic_set(&efx->active_queues, 0);
32028c2ecf20Sopenharmony_ci}
32038c2ecf20Sopenharmony_ci
32048c2ecf20Sopenharmony_cistatic int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
32058c2ecf20Sopenharmony_ci{
32068c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
32078c2ecf20Sopenharmony_ci	u8 mac_old[ETH_ALEN];
32088c2ecf20Sopenharmony_ci	int rc, rc2;
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_ci	/* Only reconfigure a PF-created vport */
32118c2ecf20Sopenharmony_ci	if (is_zero_ether_addr(nic_data->vport_mac))
32128c2ecf20Sopenharmony_ci		return 0;
32138c2ecf20Sopenharmony_ci
32148c2ecf20Sopenharmony_ci	efx_device_detach_sync(efx);
32158c2ecf20Sopenharmony_ci	efx_net_stop(efx->net_dev);
32168c2ecf20Sopenharmony_ci	down_write(&efx->filter_sem);
32178c2ecf20Sopenharmony_ci	efx_mcdi_filter_table_remove(efx);
32188c2ecf20Sopenharmony_ci	up_write(&efx->filter_sem);
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ci	rc = efx_ef10_vadaptor_free(efx, efx->vport_id);
32218c2ecf20Sopenharmony_ci	if (rc)
32228c2ecf20Sopenharmony_ci		goto restore_filters;
32238c2ecf20Sopenharmony_ci
32248c2ecf20Sopenharmony_ci	ether_addr_copy(mac_old, nic_data->vport_mac);
32258c2ecf20Sopenharmony_ci	rc = efx_ef10_vport_del_mac(efx, efx->vport_id,
32268c2ecf20Sopenharmony_ci				    nic_data->vport_mac);
32278c2ecf20Sopenharmony_ci	if (rc)
32288c2ecf20Sopenharmony_ci		goto restore_vadaptor;
32298c2ecf20Sopenharmony_ci
32308c2ecf20Sopenharmony_ci	rc = efx_ef10_vport_add_mac(efx, efx->vport_id,
32318c2ecf20Sopenharmony_ci				    efx->net_dev->dev_addr);
32328c2ecf20Sopenharmony_ci	if (!rc) {
32338c2ecf20Sopenharmony_ci		ether_addr_copy(nic_data->vport_mac, efx->net_dev->dev_addr);
32348c2ecf20Sopenharmony_ci	} else {
32358c2ecf20Sopenharmony_ci		rc2 = efx_ef10_vport_add_mac(efx, efx->vport_id, mac_old);
32368c2ecf20Sopenharmony_ci		if (rc2) {
32378c2ecf20Sopenharmony_ci			/* Failed to add original MAC, so clear vport_mac */
32388c2ecf20Sopenharmony_ci			eth_zero_addr(nic_data->vport_mac);
32398c2ecf20Sopenharmony_ci			goto reset_nic;
32408c2ecf20Sopenharmony_ci		}
32418c2ecf20Sopenharmony_ci	}
32428c2ecf20Sopenharmony_ci
32438c2ecf20Sopenharmony_cirestore_vadaptor:
32448c2ecf20Sopenharmony_ci	rc2 = efx_ef10_vadaptor_alloc(efx, efx->vport_id);
32458c2ecf20Sopenharmony_ci	if (rc2)
32468c2ecf20Sopenharmony_ci		goto reset_nic;
32478c2ecf20Sopenharmony_cirestore_filters:
32488c2ecf20Sopenharmony_ci	down_write(&efx->filter_sem);
32498c2ecf20Sopenharmony_ci	rc2 = efx_ef10_filter_table_probe(efx);
32508c2ecf20Sopenharmony_ci	up_write(&efx->filter_sem);
32518c2ecf20Sopenharmony_ci	if (rc2)
32528c2ecf20Sopenharmony_ci		goto reset_nic;
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci	rc2 = efx_net_open(efx->net_dev);
32558c2ecf20Sopenharmony_ci	if (rc2)
32568c2ecf20Sopenharmony_ci		goto reset_nic;
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_ci	efx_device_attach_if_not_resetting(efx);
32598c2ecf20Sopenharmony_ci
32608c2ecf20Sopenharmony_ci	return rc;
32618c2ecf20Sopenharmony_ci
32628c2ecf20Sopenharmony_cireset_nic:
32638c2ecf20Sopenharmony_ci	netif_err(efx, drv, efx->net_dev,
32648c2ecf20Sopenharmony_ci		  "Failed to restore when changing MAC address - scheduling reset\n");
32658c2ecf20Sopenharmony_ci	efx_schedule_reset(efx, RESET_TYPE_DATAPATH);
32668c2ecf20Sopenharmony_ci
32678c2ecf20Sopenharmony_ci	return rc ? rc : rc2;
32688c2ecf20Sopenharmony_ci}
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_cistatic int efx_ef10_set_mac_address(struct efx_nic *efx)
32718c2ecf20Sopenharmony_ci{
32728c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_VADAPTOR_SET_MAC_IN_LEN);
32738c2ecf20Sopenharmony_ci	bool was_enabled = efx->port_enabled;
32748c2ecf20Sopenharmony_ci	int rc;
32758c2ecf20Sopenharmony_ci
32768c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
32778c2ecf20Sopenharmony_ci	/* If this function is a VF and we have access to the parent PF,
32788c2ecf20Sopenharmony_ci	 * then use the PF control path to attempt to change the VF MAC address.
32798c2ecf20Sopenharmony_ci	 */
32808c2ecf20Sopenharmony_ci	if (efx->pci_dev->is_virtfn && efx->pci_dev->physfn) {
32818c2ecf20Sopenharmony_ci		struct efx_nic *efx_pf = pci_get_drvdata(efx->pci_dev->physfn);
32828c2ecf20Sopenharmony_ci		struct efx_ef10_nic_data *nic_data = efx->nic_data;
32838c2ecf20Sopenharmony_ci		u8 mac[ETH_ALEN];
32848c2ecf20Sopenharmony_ci
32858c2ecf20Sopenharmony_ci		/* net_dev->dev_addr can be zeroed by efx_net_stop in
32868c2ecf20Sopenharmony_ci		 * efx_ef10_sriov_set_vf_mac, so pass in a copy.
32878c2ecf20Sopenharmony_ci		 */
32888c2ecf20Sopenharmony_ci		ether_addr_copy(mac, efx->net_dev->dev_addr);
32898c2ecf20Sopenharmony_ci
32908c2ecf20Sopenharmony_ci		rc = efx_ef10_sriov_set_vf_mac(efx_pf, nic_data->vf_index, mac);
32918c2ecf20Sopenharmony_ci		if (!rc)
32928c2ecf20Sopenharmony_ci			return 0;
32938c2ecf20Sopenharmony_ci
32948c2ecf20Sopenharmony_ci		netif_dbg(efx, drv, efx->net_dev,
32958c2ecf20Sopenharmony_ci			  "Updating VF mac via PF failed (%d), setting directly\n",
32968c2ecf20Sopenharmony_ci			  rc);
32978c2ecf20Sopenharmony_ci	}
32988c2ecf20Sopenharmony_ci#endif
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_ci	efx_device_detach_sync(efx);
33018c2ecf20Sopenharmony_ci	efx_net_stop(efx->net_dev);
33028c2ecf20Sopenharmony_ci
33038c2ecf20Sopenharmony_ci	mutex_lock(&efx->mac_lock);
33048c2ecf20Sopenharmony_ci	down_write(&efx->filter_sem);
33058c2ecf20Sopenharmony_ci	efx_mcdi_filter_table_remove(efx);
33068c2ecf20Sopenharmony_ci
33078c2ecf20Sopenharmony_ci	ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR),
33088c2ecf20Sopenharmony_ci			efx->net_dev->dev_addr);
33098c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, VADAPTOR_SET_MAC_IN_UPSTREAM_PORT_ID,
33108c2ecf20Sopenharmony_ci		       efx->vport_id);
33118c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_VADAPTOR_SET_MAC, inbuf,
33128c2ecf20Sopenharmony_ci				sizeof(inbuf), NULL, 0, NULL);
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	efx_ef10_filter_table_probe(efx);
33158c2ecf20Sopenharmony_ci	up_write(&efx->filter_sem);
33168c2ecf20Sopenharmony_ci	mutex_unlock(&efx->mac_lock);
33178c2ecf20Sopenharmony_ci
33188c2ecf20Sopenharmony_ci	if (was_enabled)
33198c2ecf20Sopenharmony_ci		efx_net_open(efx->net_dev);
33208c2ecf20Sopenharmony_ci	efx_device_attach_if_not_resetting(efx);
33218c2ecf20Sopenharmony_ci
33228c2ecf20Sopenharmony_ci	if (rc == -EPERM) {
33238c2ecf20Sopenharmony_ci		netif_err(efx, drv, efx->net_dev,
33248c2ecf20Sopenharmony_ci			  "Cannot change MAC address; use sfboot to enable"
33258c2ecf20Sopenharmony_ci			  " mac-spoofing on this interface\n");
33268c2ecf20Sopenharmony_ci	} else if (rc == -ENOSYS && !efx_ef10_is_vf(efx)) {
33278c2ecf20Sopenharmony_ci		/* If the active MCFW does not support MC_CMD_VADAPTOR_SET_MAC
33288c2ecf20Sopenharmony_ci		 * fall-back to the method of changing the MAC address on the
33298c2ecf20Sopenharmony_ci		 * vport.  This only applies to PFs because such versions of
33308c2ecf20Sopenharmony_ci		 * MCFW do not support VFs.
33318c2ecf20Sopenharmony_ci		 */
33328c2ecf20Sopenharmony_ci		rc = efx_ef10_vport_set_mac_address(efx);
33338c2ecf20Sopenharmony_ci	} else if (rc) {
33348c2ecf20Sopenharmony_ci		efx_mcdi_display_error(efx, MC_CMD_VADAPTOR_SET_MAC,
33358c2ecf20Sopenharmony_ci				       sizeof(inbuf), NULL, 0, rc);
33368c2ecf20Sopenharmony_ci	}
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_ci	return rc;
33398c2ecf20Sopenharmony_ci}
33408c2ecf20Sopenharmony_ci
33418c2ecf20Sopenharmony_cistatic int efx_ef10_mac_reconfigure(struct efx_nic *efx, bool mtu_only)
33428c2ecf20Sopenharmony_ci{
33438c2ecf20Sopenharmony_ci	WARN_ON(!mutex_is_locked(&efx->mac_lock));
33448c2ecf20Sopenharmony_ci
33458c2ecf20Sopenharmony_ci	efx_mcdi_filter_sync_rx_mode(efx);
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	if (mtu_only && efx_has_cap(efx, SET_MAC_ENHANCED))
33488c2ecf20Sopenharmony_ci		return efx_mcdi_set_mtu(efx);
33498c2ecf20Sopenharmony_ci	return efx_mcdi_set_mac(efx);
33508c2ecf20Sopenharmony_ci}
33518c2ecf20Sopenharmony_ci
33528c2ecf20Sopenharmony_cistatic int efx_ef10_start_bist(struct efx_nic *efx, u32 bist_type)
33538c2ecf20Sopenharmony_ci{
33548c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_type);
33578c2ecf20Sopenharmony_ci	return efx_mcdi_rpc(efx, MC_CMD_START_BIST, inbuf, sizeof(inbuf),
33588c2ecf20Sopenharmony_ci			    NULL, 0, NULL);
33598c2ecf20Sopenharmony_ci}
33608c2ecf20Sopenharmony_ci
33618c2ecf20Sopenharmony_ci/* MC BISTs follow a different poll mechanism to phy BISTs.
33628c2ecf20Sopenharmony_ci * The BIST is done in the poll handler on the MC, and the MCDI command
33638c2ecf20Sopenharmony_ci * will block until the BIST is done.
33648c2ecf20Sopenharmony_ci */
33658c2ecf20Sopenharmony_cistatic int efx_ef10_poll_bist(struct efx_nic *efx)
33668c2ecf20Sopenharmony_ci{
33678c2ecf20Sopenharmony_ci	int rc;
33688c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_LEN);
33698c2ecf20Sopenharmony_ci	size_t outlen;
33708c2ecf20Sopenharmony_ci	u32 result;
33718c2ecf20Sopenharmony_ci
33728c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0,
33738c2ecf20Sopenharmony_ci			   outbuf, sizeof(outbuf), &outlen);
33748c2ecf20Sopenharmony_ci	if (rc != 0)
33758c2ecf20Sopenharmony_ci		return rc;
33768c2ecf20Sopenharmony_ci
33778c2ecf20Sopenharmony_ci	if (outlen < MC_CMD_POLL_BIST_OUT_LEN)
33788c2ecf20Sopenharmony_ci		return -EIO;
33798c2ecf20Sopenharmony_ci
33808c2ecf20Sopenharmony_ci	result = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT);
33818c2ecf20Sopenharmony_ci	switch (result) {
33828c2ecf20Sopenharmony_ci	case MC_CMD_POLL_BIST_PASSED:
33838c2ecf20Sopenharmony_ci		netif_dbg(efx, hw, efx->net_dev, "BIST passed.\n");
33848c2ecf20Sopenharmony_ci		return 0;
33858c2ecf20Sopenharmony_ci	case MC_CMD_POLL_BIST_TIMEOUT:
33868c2ecf20Sopenharmony_ci		netif_err(efx, hw, efx->net_dev, "BIST timed out\n");
33878c2ecf20Sopenharmony_ci		return -EIO;
33888c2ecf20Sopenharmony_ci	case MC_CMD_POLL_BIST_FAILED:
33898c2ecf20Sopenharmony_ci		netif_err(efx, hw, efx->net_dev, "BIST failed.\n");
33908c2ecf20Sopenharmony_ci		return -EIO;
33918c2ecf20Sopenharmony_ci	default:
33928c2ecf20Sopenharmony_ci		netif_err(efx, hw, efx->net_dev,
33938c2ecf20Sopenharmony_ci			  "BIST returned unknown result %u", result);
33948c2ecf20Sopenharmony_ci		return -EIO;
33958c2ecf20Sopenharmony_ci	}
33968c2ecf20Sopenharmony_ci}
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_cistatic int efx_ef10_run_bist(struct efx_nic *efx, u32 bist_type)
33998c2ecf20Sopenharmony_ci{
34008c2ecf20Sopenharmony_ci	int rc;
34018c2ecf20Sopenharmony_ci
34028c2ecf20Sopenharmony_ci	netif_dbg(efx, drv, efx->net_dev, "starting BIST type %u\n", bist_type);
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	rc = efx_ef10_start_bist(efx, bist_type);
34058c2ecf20Sopenharmony_ci	if (rc != 0)
34068c2ecf20Sopenharmony_ci		return rc;
34078c2ecf20Sopenharmony_ci
34088c2ecf20Sopenharmony_ci	return efx_ef10_poll_bist(efx);
34098c2ecf20Sopenharmony_ci}
34108c2ecf20Sopenharmony_ci
34118c2ecf20Sopenharmony_cistatic int
34128c2ecf20Sopenharmony_ciefx_ef10_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
34138c2ecf20Sopenharmony_ci{
34148c2ecf20Sopenharmony_ci	int rc, rc2;
34158c2ecf20Sopenharmony_ci
34168c2ecf20Sopenharmony_ci	efx_reset_down(efx, RESET_TYPE_WORLD);
34178c2ecf20Sopenharmony_ci
34188c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_ENABLE_OFFLINE_BIST,
34198c2ecf20Sopenharmony_ci			  NULL, 0, NULL, 0, NULL);
34208c2ecf20Sopenharmony_ci	if (rc != 0)
34218c2ecf20Sopenharmony_ci		goto out;
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ci	tests->memory = efx_ef10_run_bist(efx, MC_CMD_MC_MEM_BIST) ? -1 : 1;
34248c2ecf20Sopenharmony_ci	tests->registers = efx_ef10_run_bist(efx, MC_CMD_REG_BIST) ? -1 : 1;
34258c2ecf20Sopenharmony_ci
34268c2ecf20Sopenharmony_ci	rc = efx_mcdi_reset(efx, RESET_TYPE_WORLD);
34278c2ecf20Sopenharmony_ci
34288c2ecf20Sopenharmony_ciout:
34298c2ecf20Sopenharmony_ci	if (rc == -EPERM)
34308c2ecf20Sopenharmony_ci		rc = 0;
34318c2ecf20Sopenharmony_ci	rc2 = efx_reset_up(efx, RESET_TYPE_WORLD, rc == 0);
34328c2ecf20Sopenharmony_ci	return rc ? rc : rc2;
34338c2ecf20Sopenharmony_ci}
34348c2ecf20Sopenharmony_ci
34358c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_MTD
34368c2ecf20Sopenharmony_ci
34378c2ecf20Sopenharmony_cistruct efx_ef10_nvram_type_info {
34388c2ecf20Sopenharmony_ci	u16 type, type_mask;
34398c2ecf20Sopenharmony_ci	u8 port;
34408c2ecf20Sopenharmony_ci	const char *name;
34418c2ecf20Sopenharmony_ci};
34428c2ecf20Sopenharmony_ci
34438c2ecf20Sopenharmony_cistatic const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = {
34448c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_MC_FIRMWARE,	   0,    0, "sfc_mcfw" },
34458c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_MC_FIRMWARE_BACKUP, 0,    0, "sfc_mcfw_backup" },
34468c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_EXPANSION_ROM,	   0,    0, "sfc_exp_rom" },
34478c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_STATIC_CONFIG,	   0,    0, "sfc_static_cfg" },
34488c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,	   0,    0, "sfc_dynamic_cfg" },
34498c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT0, 0,   0, "sfc_exp_rom_cfg" },
34508c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT1, 0,   1, "sfc_exp_rom_cfg" },
34518c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT2, 0,   2, "sfc_exp_rom_cfg" },
34528c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_EXPROM_CONFIG_PORT3, 0,   3, "sfc_exp_rom_cfg" },
34538c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_LICENSE,		   0,    0, "sfc_license" },
34548c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_PHY_MIN,		   0xff, 0, "sfc_phy_fw" },
34558c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_MUM_FIRMWARE,	   0,    0, "sfc_mumfw" },
34568c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_EXPANSION_UEFI,	   0,    0, "sfc_uefi" },
34578c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS, 0,    0, "sfc_dynamic_cfg_dflt" },
34588c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS, 0,    0, "sfc_exp_rom_cfg_dflt" },
34598c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_STATUS,		   0,    0, "sfc_status" },
34608c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_BUNDLE,		   0,    0, "sfc_bundle" },
34618c2ecf20Sopenharmony_ci	{ NVRAM_PARTITION_TYPE_BUNDLE_METADATA,	   0,    0, "sfc_bundle_metadata" },
34628c2ecf20Sopenharmony_ci};
34638c2ecf20Sopenharmony_ci#define EF10_NVRAM_PARTITION_COUNT	ARRAY_SIZE(efx_ef10_nvram_types)
34648c2ecf20Sopenharmony_ci
34658c2ecf20Sopenharmony_cistatic int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
34668c2ecf20Sopenharmony_ci					struct efx_mcdi_mtd_partition *part,
34678c2ecf20Sopenharmony_ci					unsigned int type,
34688c2ecf20Sopenharmony_ci					unsigned long *found)
34698c2ecf20Sopenharmony_ci{
34708c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
34718c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_METADATA_OUT_LENMAX);
34728c2ecf20Sopenharmony_ci	const struct efx_ef10_nvram_type_info *info;
34738c2ecf20Sopenharmony_ci	size_t size, erase_size, outlen;
34748c2ecf20Sopenharmony_ci	int type_idx = 0;
34758c2ecf20Sopenharmony_ci	bool protected;
34768c2ecf20Sopenharmony_ci	int rc;
34778c2ecf20Sopenharmony_ci
34788c2ecf20Sopenharmony_ci	for (type_idx = 0; ; type_idx++) {
34798c2ecf20Sopenharmony_ci		if (type_idx == EF10_NVRAM_PARTITION_COUNT)
34808c2ecf20Sopenharmony_ci			return -ENODEV;
34818c2ecf20Sopenharmony_ci		info = efx_ef10_nvram_types + type_idx;
34828c2ecf20Sopenharmony_ci		if ((type & ~info->type_mask) == info->type)
34838c2ecf20Sopenharmony_ci			break;
34848c2ecf20Sopenharmony_ci	}
34858c2ecf20Sopenharmony_ci	if (info->port != efx_port_num(efx))
34868c2ecf20Sopenharmony_ci		return -ENODEV;
34878c2ecf20Sopenharmony_ci
34888c2ecf20Sopenharmony_ci	rc = efx_mcdi_nvram_info(efx, type, &size, &erase_size, &protected);
34898c2ecf20Sopenharmony_ci	if (rc)
34908c2ecf20Sopenharmony_ci		return rc;
34918c2ecf20Sopenharmony_ci	if (protected &&
34928c2ecf20Sopenharmony_ci	    (type != NVRAM_PARTITION_TYPE_DYNCONFIG_DEFAULTS &&
34938c2ecf20Sopenharmony_ci	     type != NVRAM_PARTITION_TYPE_ROMCONFIG_DEFAULTS))
34948c2ecf20Sopenharmony_ci		/* Hide protected partitions that don't provide defaults. */
34958c2ecf20Sopenharmony_ci		return -ENODEV;
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_ci	if (protected)
34988c2ecf20Sopenharmony_ci		/* Protected partitions are read only. */
34998c2ecf20Sopenharmony_ci		erase_size = 0;
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci	/* If we've already exposed a partition of this type, hide this
35028c2ecf20Sopenharmony_ci	 * duplicate.  All operations on MTDs are keyed by the type anyway,
35038c2ecf20Sopenharmony_ci	 * so we can't act on the duplicate.
35048c2ecf20Sopenharmony_ci	 */
35058c2ecf20Sopenharmony_ci	if (__test_and_set_bit(type_idx, found))
35068c2ecf20Sopenharmony_ci		return -EEXIST;
35078c2ecf20Sopenharmony_ci
35088c2ecf20Sopenharmony_ci	part->nvram_type = type;
35098c2ecf20Sopenharmony_ci
35108c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
35118c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_METADATA, inbuf, sizeof(inbuf),
35128c2ecf20Sopenharmony_ci			  outbuf, sizeof(outbuf), &outlen);
35138c2ecf20Sopenharmony_ci	if (rc)
35148c2ecf20Sopenharmony_ci		return rc;
35158c2ecf20Sopenharmony_ci	if (outlen < MC_CMD_NVRAM_METADATA_OUT_LENMIN)
35168c2ecf20Sopenharmony_ci		return -EIO;
35178c2ecf20Sopenharmony_ci	if (MCDI_DWORD(outbuf, NVRAM_METADATA_OUT_FLAGS) &
35188c2ecf20Sopenharmony_ci	    (1 << MC_CMD_NVRAM_METADATA_OUT_SUBTYPE_VALID_LBN))
35198c2ecf20Sopenharmony_ci		part->fw_subtype = MCDI_DWORD(outbuf,
35208c2ecf20Sopenharmony_ci					      NVRAM_METADATA_OUT_SUBTYPE);
35218c2ecf20Sopenharmony_ci
35228c2ecf20Sopenharmony_ci	part->common.dev_type_name = "EF10 NVRAM manager";
35238c2ecf20Sopenharmony_ci	part->common.type_name = info->name;
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ci	part->common.mtd.type = MTD_NORFLASH;
35268c2ecf20Sopenharmony_ci	part->common.mtd.flags = MTD_CAP_NORFLASH;
35278c2ecf20Sopenharmony_ci	part->common.mtd.size = size;
35288c2ecf20Sopenharmony_ci	part->common.mtd.erasesize = erase_size;
35298c2ecf20Sopenharmony_ci	/* sfc_status is read-only */
35308c2ecf20Sopenharmony_ci	if (!erase_size)
35318c2ecf20Sopenharmony_ci		part->common.mtd.flags |= MTD_NO_ERASE;
35328c2ecf20Sopenharmony_ci
35338c2ecf20Sopenharmony_ci	return 0;
35348c2ecf20Sopenharmony_ci}
35358c2ecf20Sopenharmony_ci
35368c2ecf20Sopenharmony_cistatic int efx_ef10_mtd_probe(struct efx_nic *efx)
35378c2ecf20Sopenharmony_ci{
35388c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
35398c2ecf20Sopenharmony_ci	DECLARE_BITMAP(found, EF10_NVRAM_PARTITION_COUNT) = { 0 };
35408c2ecf20Sopenharmony_ci	struct efx_mcdi_mtd_partition *parts;
35418c2ecf20Sopenharmony_ci	size_t outlen, n_parts_total, i, n_parts;
35428c2ecf20Sopenharmony_ci	unsigned int type;
35438c2ecf20Sopenharmony_ci	int rc;
35448c2ecf20Sopenharmony_ci
35458c2ecf20Sopenharmony_ci	ASSERT_RTNL();
35468c2ecf20Sopenharmony_ci
35478c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_NVRAM_PARTITIONS_IN_LEN != 0);
35488c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(efx, MC_CMD_NVRAM_PARTITIONS, NULL, 0,
35498c2ecf20Sopenharmony_ci			  outbuf, sizeof(outbuf), &outlen);
35508c2ecf20Sopenharmony_ci	if (rc)
35518c2ecf20Sopenharmony_ci		return rc;
35528c2ecf20Sopenharmony_ci	if (outlen < MC_CMD_NVRAM_PARTITIONS_OUT_LENMIN)
35538c2ecf20Sopenharmony_ci		return -EIO;
35548c2ecf20Sopenharmony_ci
35558c2ecf20Sopenharmony_ci	n_parts_total = MCDI_DWORD(outbuf, NVRAM_PARTITIONS_OUT_NUM_PARTITIONS);
35568c2ecf20Sopenharmony_ci	if (n_parts_total >
35578c2ecf20Sopenharmony_ci	    MCDI_VAR_ARRAY_LEN(outlen, NVRAM_PARTITIONS_OUT_TYPE_ID))
35588c2ecf20Sopenharmony_ci		return -EIO;
35598c2ecf20Sopenharmony_ci
35608c2ecf20Sopenharmony_ci	parts = kcalloc(n_parts_total, sizeof(*parts), GFP_KERNEL);
35618c2ecf20Sopenharmony_ci	if (!parts)
35628c2ecf20Sopenharmony_ci		return -ENOMEM;
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ci	n_parts = 0;
35658c2ecf20Sopenharmony_ci	for (i = 0; i < n_parts_total; i++) {
35668c2ecf20Sopenharmony_ci		type = MCDI_ARRAY_DWORD(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID,
35678c2ecf20Sopenharmony_ci					i);
35688c2ecf20Sopenharmony_ci		rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type,
35698c2ecf20Sopenharmony_ci						  found);
35708c2ecf20Sopenharmony_ci		if (rc == -EEXIST || rc == -ENODEV)
35718c2ecf20Sopenharmony_ci			continue;
35728c2ecf20Sopenharmony_ci		if (rc)
35738c2ecf20Sopenharmony_ci			goto fail;
35748c2ecf20Sopenharmony_ci		n_parts++;
35758c2ecf20Sopenharmony_ci	}
35768c2ecf20Sopenharmony_ci
35778c2ecf20Sopenharmony_ci	if (!n_parts) {
35788c2ecf20Sopenharmony_ci		kfree(parts);
35798c2ecf20Sopenharmony_ci		return 0;
35808c2ecf20Sopenharmony_ci	}
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci	rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
35838c2ecf20Sopenharmony_cifail:
35848c2ecf20Sopenharmony_ci	if (rc)
35858c2ecf20Sopenharmony_ci		kfree(parts);
35868c2ecf20Sopenharmony_ci	return rc;
35878c2ecf20Sopenharmony_ci}
35888c2ecf20Sopenharmony_ci
35898c2ecf20Sopenharmony_ci#endif /* CONFIG_SFC_MTD */
35908c2ecf20Sopenharmony_ci
35918c2ecf20Sopenharmony_cistatic void efx_ef10_ptp_write_host_time(struct efx_nic *efx, u32 host_time)
35928c2ecf20Sopenharmony_ci{
35938c2ecf20Sopenharmony_ci	_efx_writed(efx, cpu_to_le32(host_time), ER_DZ_MC_DB_LWRD);
35948c2ecf20Sopenharmony_ci}
35958c2ecf20Sopenharmony_ci
35968c2ecf20Sopenharmony_cistatic void efx_ef10_ptp_write_host_time_vf(struct efx_nic *efx,
35978c2ecf20Sopenharmony_ci					    u32 host_time) {}
35988c2ecf20Sopenharmony_ci
35998c2ecf20Sopenharmony_cistatic int efx_ef10_rx_enable_timestamping(struct efx_channel *channel,
36008c2ecf20Sopenharmony_ci					   bool temp)
36018c2ecf20Sopenharmony_ci{
36028c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_SUBSCRIBE_LEN);
36038c2ecf20Sopenharmony_ci	int rc;
36048c2ecf20Sopenharmony_ci
36058c2ecf20Sopenharmony_ci	if (channel->sync_events_state == SYNC_EVENTS_REQUESTED ||
36068c2ecf20Sopenharmony_ci	    channel->sync_events_state == SYNC_EVENTS_VALID ||
36078c2ecf20Sopenharmony_ci	    (temp && channel->sync_events_state == SYNC_EVENTS_DISABLED))
36088c2ecf20Sopenharmony_ci		return 0;
36098c2ecf20Sopenharmony_ci	channel->sync_events_state = SYNC_EVENTS_REQUESTED;
36108c2ecf20Sopenharmony_ci
36118c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_SUBSCRIBE);
36128c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
36138c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_SUBSCRIBE_QUEUE,
36148c2ecf20Sopenharmony_ci		       channel->channel);
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP,
36178c2ecf20Sopenharmony_ci			  inbuf, sizeof(inbuf), NULL, 0, NULL);
36188c2ecf20Sopenharmony_ci
36198c2ecf20Sopenharmony_ci	if (rc != 0)
36208c2ecf20Sopenharmony_ci		channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT :
36218c2ecf20Sopenharmony_ci						    SYNC_EVENTS_DISABLED;
36228c2ecf20Sopenharmony_ci
36238c2ecf20Sopenharmony_ci	return rc;
36248c2ecf20Sopenharmony_ci}
36258c2ecf20Sopenharmony_ci
36268c2ecf20Sopenharmony_cistatic int efx_ef10_rx_disable_timestamping(struct efx_channel *channel,
36278c2ecf20Sopenharmony_ci					    bool temp)
36288c2ecf20Sopenharmony_ci{
36298c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_LEN);
36308c2ecf20Sopenharmony_ci	int rc;
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_ci	if (channel->sync_events_state == SYNC_EVENTS_DISABLED ||
36338c2ecf20Sopenharmony_ci	    (temp && channel->sync_events_state == SYNC_EVENTS_QUIESCENT))
36348c2ecf20Sopenharmony_ci		return 0;
36358c2ecf20Sopenharmony_ci	if (channel->sync_events_state == SYNC_EVENTS_QUIESCENT) {
36368c2ecf20Sopenharmony_ci		channel->sync_events_state = SYNC_EVENTS_DISABLED;
36378c2ecf20Sopenharmony_ci		return 0;
36388c2ecf20Sopenharmony_ci	}
36398c2ecf20Sopenharmony_ci	channel->sync_events_state = temp ? SYNC_EVENTS_QUIESCENT :
36408c2ecf20Sopenharmony_ci					    SYNC_EVENTS_DISABLED;
36418c2ecf20Sopenharmony_ci
36428c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_TIME_EVENT_UNSUBSCRIBE);
36438c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
36448c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_CONTROL,
36458c2ecf20Sopenharmony_ci		       MC_CMD_PTP_IN_TIME_EVENT_UNSUBSCRIBE_SINGLE);
36468c2ecf20Sopenharmony_ci	MCDI_SET_DWORD(inbuf, PTP_IN_TIME_EVENT_UNSUBSCRIBE_QUEUE,
36478c2ecf20Sopenharmony_ci		       channel->channel);
36488c2ecf20Sopenharmony_ci
36498c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc(channel->efx, MC_CMD_PTP,
36508c2ecf20Sopenharmony_ci			  inbuf, sizeof(inbuf), NULL, 0, NULL);
36518c2ecf20Sopenharmony_ci
36528c2ecf20Sopenharmony_ci	return rc;
36538c2ecf20Sopenharmony_ci}
36548c2ecf20Sopenharmony_ci
36558c2ecf20Sopenharmony_cistatic int efx_ef10_ptp_set_ts_sync_events(struct efx_nic *efx, bool en,
36568c2ecf20Sopenharmony_ci					   bool temp)
36578c2ecf20Sopenharmony_ci{
36588c2ecf20Sopenharmony_ci	int (*set)(struct efx_channel *channel, bool temp);
36598c2ecf20Sopenharmony_ci	struct efx_channel *channel;
36608c2ecf20Sopenharmony_ci
36618c2ecf20Sopenharmony_ci	set = en ?
36628c2ecf20Sopenharmony_ci	      efx_ef10_rx_enable_timestamping :
36638c2ecf20Sopenharmony_ci	      efx_ef10_rx_disable_timestamping;
36648c2ecf20Sopenharmony_ci
36658c2ecf20Sopenharmony_ci	channel = efx_ptp_channel(efx);
36668c2ecf20Sopenharmony_ci	if (channel) {
36678c2ecf20Sopenharmony_ci		int rc = set(channel, temp);
36688c2ecf20Sopenharmony_ci		if (en && rc != 0) {
36698c2ecf20Sopenharmony_ci			efx_ef10_ptp_set_ts_sync_events(efx, false, temp);
36708c2ecf20Sopenharmony_ci			return rc;
36718c2ecf20Sopenharmony_ci		}
36728c2ecf20Sopenharmony_ci	}
36738c2ecf20Sopenharmony_ci
36748c2ecf20Sopenharmony_ci	return 0;
36758c2ecf20Sopenharmony_ci}
36768c2ecf20Sopenharmony_ci
36778c2ecf20Sopenharmony_cistatic int efx_ef10_ptp_set_ts_config_vf(struct efx_nic *efx,
36788c2ecf20Sopenharmony_ci					 struct hwtstamp_config *init)
36798c2ecf20Sopenharmony_ci{
36808c2ecf20Sopenharmony_ci	return -EOPNOTSUPP;
36818c2ecf20Sopenharmony_ci}
36828c2ecf20Sopenharmony_ci
36838c2ecf20Sopenharmony_cistatic int efx_ef10_ptp_set_ts_config(struct efx_nic *efx,
36848c2ecf20Sopenharmony_ci				      struct hwtstamp_config *init)
36858c2ecf20Sopenharmony_ci{
36868c2ecf20Sopenharmony_ci	int rc;
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci	switch (init->rx_filter) {
36898c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_NONE:
36908c2ecf20Sopenharmony_ci		efx_ef10_ptp_set_ts_sync_events(efx, false, false);
36918c2ecf20Sopenharmony_ci		/* if TX timestamping is still requested then leave PTP on */
36928c2ecf20Sopenharmony_ci		return efx_ptp_change_mode(efx,
36938c2ecf20Sopenharmony_ci					   init->tx_type != HWTSTAMP_TX_OFF, 0);
36948c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_ALL:
36958c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
36968c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
36978c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
36988c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
36998c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
37008c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
37018c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
37028c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
37038c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
37048c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_EVENT:
37058c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_SYNC:
37068c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
37078c2ecf20Sopenharmony_ci	case HWTSTAMP_FILTER_NTP_ALL:
37088c2ecf20Sopenharmony_ci		init->rx_filter = HWTSTAMP_FILTER_ALL;
37098c2ecf20Sopenharmony_ci		rc = efx_ptp_change_mode(efx, true, 0);
37108c2ecf20Sopenharmony_ci		if (!rc)
37118c2ecf20Sopenharmony_ci			rc = efx_ef10_ptp_set_ts_sync_events(efx, true, false);
37128c2ecf20Sopenharmony_ci		if (rc)
37138c2ecf20Sopenharmony_ci			efx_ptp_change_mode(efx, false, 0);
37148c2ecf20Sopenharmony_ci		return rc;
37158c2ecf20Sopenharmony_ci	default:
37168c2ecf20Sopenharmony_ci		return -ERANGE;
37178c2ecf20Sopenharmony_ci	}
37188c2ecf20Sopenharmony_ci}
37198c2ecf20Sopenharmony_ci
37208c2ecf20Sopenharmony_cistatic int efx_ef10_get_phys_port_id(struct efx_nic *efx,
37218c2ecf20Sopenharmony_ci				     struct netdev_phys_item_id *ppid)
37228c2ecf20Sopenharmony_ci{
37238c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
37248c2ecf20Sopenharmony_ci
37258c2ecf20Sopenharmony_ci	if (!is_valid_ether_addr(nic_data->port_id))
37268c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
37278c2ecf20Sopenharmony_ci
37288c2ecf20Sopenharmony_ci	ppid->id_len = ETH_ALEN;
37298c2ecf20Sopenharmony_ci	memcpy(ppid->id, nic_data->port_id, ppid->id_len);
37308c2ecf20Sopenharmony_ci
37318c2ecf20Sopenharmony_ci	return 0;
37328c2ecf20Sopenharmony_ci}
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_cistatic int efx_ef10_vlan_rx_add_vid(struct efx_nic *efx, __be16 proto, u16 vid)
37358c2ecf20Sopenharmony_ci{
37368c2ecf20Sopenharmony_ci	if (proto != htons(ETH_P_8021Q))
37378c2ecf20Sopenharmony_ci		return -EINVAL;
37388c2ecf20Sopenharmony_ci
37398c2ecf20Sopenharmony_ci	return efx_ef10_add_vlan(efx, vid);
37408c2ecf20Sopenharmony_ci}
37418c2ecf20Sopenharmony_ci
37428c2ecf20Sopenharmony_cistatic int efx_ef10_vlan_rx_kill_vid(struct efx_nic *efx, __be16 proto, u16 vid)
37438c2ecf20Sopenharmony_ci{
37448c2ecf20Sopenharmony_ci	if (proto != htons(ETH_P_8021Q))
37458c2ecf20Sopenharmony_ci		return -EINVAL;
37468c2ecf20Sopenharmony_ci
37478c2ecf20Sopenharmony_ci	return efx_ef10_del_vlan(efx, vid);
37488c2ecf20Sopenharmony_ci}
37498c2ecf20Sopenharmony_ci
37508c2ecf20Sopenharmony_ci/* We rely on the MCDI wiping out our TX rings if it made any changes to the
37518c2ecf20Sopenharmony_ci * ports table, ensuring that any TSO descriptors that were made on a now-
37528c2ecf20Sopenharmony_ci * removed tunnel port will be blown away and won't break things when we try
37538c2ecf20Sopenharmony_ci * to transmit them using the new ports table.
37548c2ecf20Sopenharmony_ci */
37558c2ecf20Sopenharmony_cistatic int efx_ef10_set_udp_tnl_ports(struct efx_nic *efx, bool unloading)
37568c2ecf20Sopenharmony_ci{
37578c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
37588c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX);
37598c2ecf20Sopenharmony_ci	MCDI_DECLARE_BUF(outbuf, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN);
37608c2ecf20Sopenharmony_ci	bool will_reset = false;
37618c2ecf20Sopenharmony_ci	size_t num_entries = 0;
37628c2ecf20Sopenharmony_ci	size_t inlen, outlen;
37638c2ecf20Sopenharmony_ci	size_t i;
37648c2ecf20Sopenharmony_ci	int rc;
37658c2ecf20Sopenharmony_ci	efx_dword_t flags_and_num_entries;
37668c2ecf20Sopenharmony_ci
37678c2ecf20Sopenharmony_ci	WARN_ON(!mutex_is_locked(&nic_data->udp_tunnels_lock));
37688c2ecf20Sopenharmony_ci
37698c2ecf20Sopenharmony_ci	nic_data->udp_tunnels_dirty = false;
37708c2ecf20Sopenharmony_ci
37718c2ecf20Sopenharmony_ci	if (!(nic_data->datapath_caps &
37728c2ecf20Sopenharmony_ci	    (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN))) {
37738c2ecf20Sopenharmony_ci		efx_device_attach_if_not_resetting(efx);
37748c2ecf20Sopenharmony_ci		return 0;
37758c2ecf20Sopenharmony_ci	}
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci	BUILD_BUG_ON(ARRAY_SIZE(nic_data->udp_tunnels) >
37788c2ecf20Sopenharmony_ci		     MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(nic_data->udp_tunnels); ++i) {
37818c2ecf20Sopenharmony_ci		if (nic_data->udp_tunnels[i].type !=
37828c2ecf20Sopenharmony_ci		    TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID) {
37838c2ecf20Sopenharmony_ci			efx_dword_t entry;
37848c2ecf20Sopenharmony_ci
37858c2ecf20Sopenharmony_ci			EFX_POPULATE_DWORD_2(entry,
37868c2ecf20Sopenharmony_ci				TUNNEL_ENCAP_UDP_PORT_ENTRY_UDP_PORT,
37878c2ecf20Sopenharmony_ci					ntohs(nic_data->udp_tunnels[i].port),
37888c2ecf20Sopenharmony_ci				TUNNEL_ENCAP_UDP_PORT_ENTRY_PROTOCOL,
37898c2ecf20Sopenharmony_ci					nic_data->udp_tunnels[i].type);
37908c2ecf20Sopenharmony_ci			*_MCDI_ARRAY_DWORD(inbuf,
37918c2ecf20Sopenharmony_ci				SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES,
37928c2ecf20Sopenharmony_ci				num_entries++) = entry;
37938c2ecf20Sopenharmony_ci		}
37948c2ecf20Sopenharmony_ci	}
37958c2ecf20Sopenharmony_ci
37968c2ecf20Sopenharmony_ci	BUILD_BUG_ON((MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES_OFST -
37978c2ecf20Sopenharmony_ci		      MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS_OFST) * 8 !=
37988c2ecf20Sopenharmony_ci		     EFX_WORD_1_LBN);
37998c2ecf20Sopenharmony_ci	BUILD_BUG_ON(MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES_LEN * 8 !=
38008c2ecf20Sopenharmony_ci		     EFX_WORD_1_WIDTH);
38018c2ecf20Sopenharmony_ci	EFX_POPULATE_DWORD_2(flags_and_num_entries,
38028c2ecf20Sopenharmony_ci			     MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING,
38038c2ecf20Sopenharmony_ci				!!unloading,
38048c2ecf20Sopenharmony_ci			     EFX_WORD_1, num_entries);
38058c2ecf20Sopenharmony_ci	*_MCDI_DWORD(inbuf, SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS) =
38068c2ecf20Sopenharmony_ci		flags_and_num_entries;
38078c2ecf20Sopenharmony_ci
38088c2ecf20Sopenharmony_ci	inlen = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LEN(num_entries);
38098c2ecf20Sopenharmony_ci
38108c2ecf20Sopenharmony_ci	rc = efx_mcdi_rpc_quiet(efx, MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS,
38118c2ecf20Sopenharmony_ci				inbuf, inlen, outbuf, sizeof(outbuf), &outlen);
38128c2ecf20Sopenharmony_ci	if (rc == -EIO) {
38138c2ecf20Sopenharmony_ci		/* Most likely the MC rebooted due to another function also
38148c2ecf20Sopenharmony_ci		 * setting its tunnel port list. Mark the tunnel port list as
38158c2ecf20Sopenharmony_ci		 * dirty, so it will be pushed upon coming up from the reboot.
38168c2ecf20Sopenharmony_ci		 */
38178c2ecf20Sopenharmony_ci		nic_data->udp_tunnels_dirty = true;
38188c2ecf20Sopenharmony_ci		return 0;
38198c2ecf20Sopenharmony_ci	}
38208c2ecf20Sopenharmony_ci
38218c2ecf20Sopenharmony_ci	if (rc) {
38228c2ecf20Sopenharmony_ci		/* expected not available on unprivileged functions */
38238c2ecf20Sopenharmony_ci		if (rc != -EPERM)
38248c2ecf20Sopenharmony_ci			netif_warn(efx, drv, efx->net_dev,
38258c2ecf20Sopenharmony_ci				   "Unable to set UDP tunnel ports; rc=%d.\n", rc);
38268c2ecf20Sopenharmony_ci	} else if (MCDI_DWORD(outbuf, SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS) &
38278c2ecf20Sopenharmony_ci		   (1 << MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING_LBN)) {
38288c2ecf20Sopenharmony_ci		netif_info(efx, drv, efx->net_dev,
38298c2ecf20Sopenharmony_ci			   "Rebooting MC due to UDP tunnel port list change\n");
38308c2ecf20Sopenharmony_ci		will_reset = true;
38318c2ecf20Sopenharmony_ci		if (unloading)
38328c2ecf20Sopenharmony_ci			/* Delay for the MC reset to complete. This will make
38338c2ecf20Sopenharmony_ci			 * unloading other functions a bit smoother. This is a
38348c2ecf20Sopenharmony_ci			 * race, but the other unload will work whichever way
38358c2ecf20Sopenharmony_ci			 * it goes, this just avoids an unnecessary error
38368c2ecf20Sopenharmony_ci			 * message.
38378c2ecf20Sopenharmony_ci			 */
38388c2ecf20Sopenharmony_ci			msleep(100);
38398c2ecf20Sopenharmony_ci	}
38408c2ecf20Sopenharmony_ci	if (!will_reset && !unloading) {
38418c2ecf20Sopenharmony_ci		/* The caller will have detached, relying on the MC reset to
38428c2ecf20Sopenharmony_ci		 * trigger a re-attach.  Since there won't be an MC reset, we
38438c2ecf20Sopenharmony_ci		 * have to do the attach ourselves.
38448c2ecf20Sopenharmony_ci		 */
38458c2ecf20Sopenharmony_ci		efx_device_attach_if_not_resetting(efx);
38468c2ecf20Sopenharmony_ci	}
38478c2ecf20Sopenharmony_ci
38488c2ecf20Sopenharmony_ci	return rc;
38498c2ecf20Sopenharmony_ci}
38508c2ecf20Sopenharmony_ci
38518c2ecf20Sopenharmony_cistatic int efx_ef10_udp_tnl_push_ports(struct efx_nic *efx)
38528c2ecf20Sopenharmony_ci{
38538c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
38548c2ecf20Sopenharmony_ci	int rc = 0;
38558c2ecf20Sopenharmony_ci
38568c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->udp_tunnels_lock);
38578c2ecf20Sopenharmony_ci	if (nic_data->udp_tunnels_dirty) {
38588c2ecf20Sopenharmony_ci		/* Make sure all TX are stopped while we modify the table, else
38598c2ecf20Sopenharmony_ci		 * we might race against an efx_features_check().
38608c2ecf20Sopenharmony_ci		 */
38618c2ecf20Sopenharmony_ci		efx_device_detach_sync(efx);
38628c2ecf20Sopenharmony_ci		rc = efx_ef10_set_udp_tnl_ports(efx, false);
38638c2ecf20Sopenharmony_ci	}
38648c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->udp_tunnels_lock);
38658c2ecf20Sopenharmony_ci	return rc;
38668c2ecf20Sopenharmony_ci}
38678c2ecf20Sopenharmony_ci
38688c2ecf20Sopenharmony_cistatic int efx_ef10_udp_tnl_set_port(struct net_device *dev,
38698c2ecf20Sopenharmony_ci				     unsigned int table, unsigned int entry,
38708c2ecf20Sopenharmony_ci				     struct udp_tunnel_info *ti)
38718c2ecf20Sopenharmony_ci{
38728c2ecf20Sopenharmony_ci	struct efx_nic *efx = netdev_priv(dev);
38738c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data;
38748c2ecf20Sopenharmony_ci	int efx_tunnel_type, rc;
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	if (ti->type == UDP_TUNNEL_TYPE_VXLAN)
38778c2ecf20Sopenharmony_ci		efx_tunnel_type = TUNNEL_ENCAP_UDP_PORT_ENTRY_VXLAN;
38788c2ecf20Sopenharmony_ci	else
38798c2ecf20Sopenharmony_ci		efx_tunnel_type = TUNNEL_ENCAP_UDP_PORT_ENTRY_GENEVE;
38808c2ecf20Sopenharmony_ci
38818c2ecf20Sopenharmony_ci	nic_data = efx->nic_data;
38828c2ecf20Sopenharmony_ci	if (!(nic_data->datapath_caps &
38838c2ecf20Sopenharmony_ci	      (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN)))
38848c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
38858c2ecf20Sopenharmony_ci
38868c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->udp_tunnels_lock);
38878c2ecf20Sopenharmony_ci	/* Make sure all TX are stopped while we add to the table, else we
38888c2ecf20Sopenharmony_ci	 * might race against an efx_features_check().
38898c2ecf20Sopenharmony_ci	 */
38908c2ecf20Sopenharmony_ci	efx_device_detach_sync(efx);
38918c2ecf20Sopenharmony_ci	nic_data->udp_tunnels[entry].type = efx_tunnel_type;
38928c2ecf20Sopenharmony_ci	nic_data->udp_tunnels[entry].port = ti->port;
38938c2ecf20Sopenharmony_ci	rc = efx_ef10_set_udp_tnl_ports(efx, false);
38948c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->udp_tunnels_lock);
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_ci	return rc;
38978c2ecf20Sopenharmony_ci}
38988c2ecf20Sopenharmony_ci
38998c2ecf20Sopenharmony_ci/* Called under the TX lock with the TX queue running, hence no-one can be
39008c2ecf20Sopenharmony_ci * in the middle of updating the UDP tunnels table.  However, they could
39018c2ecf20Sopenharmony_ci * have tried and failed the MCDI, in which case they'll have set the dirty
39028c2ecf20Sopenharmony_ci * flag before dropping their locks.
39038c2ecf20Sopenharmony_ci */
39048c2ecf20Sopenharmony_cistatic bool efx_ef10_udp_tnl_has_port(struct efx_nic *efx, __be16 port)
39058c2ecf20Sopenharmony_ci{
39068c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
39078c2ecf20Sopenharmony_ci	size_t i;
39088c2ecf20Sopenharmony_ci
39098c2ecf20Sopenharmony_ci	if (!(nic_data->datapath_caps &
39108c2ecf20Sopenharmony_ci	      (1 << MC_CMD_GET_CAPABILITIES_OUT_VXLAN_NVGRE_LBN)))
39118c2ecf20Sopenharmony_ci		return false;
39128c2ecf20Sopenharmony_ci
39138c2ecf20Sopenharmony_ci	if (nic_data->udp_tunnels_dirty)
39148c2ecf20Sopenharmony_ci		/* SW table may not match HW state, so just assume we can't
39158c2ecf20Sopenharmony_ci		 * use any UDP tunnel offloads.
39168c2ecf20Sopenharmony_ci		 */
39178c2ecf20Sopenharmony_ci		return false;
39188c2ecf20Sopenharmony_ci
39198c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(nic_data->udp_tunnels); ++i)
39208c2ecf20Sopenharmony_ci		if (nic_data->udp_tunnels[i].type !=
39218c2ecf20Sopenharmony_ci		    TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID &&
39228c2ecf20Sopenharmony_ci		    nic_data->udp_tunnels[i].port == port)
39238c2ecf20Sopenharmony_ci			return true;
39248c2ecf20Sopenharmony_ci
39258c2ecf20Sopenharmony_ci	return false;
39268c2ecf20Sopenharmony_ci}
39278c2ecf20Sopenharmony_ci
39288c2ecf20Sopenharmony_cistatic int efx_ef10_udp_tnl_unset_port(struct net_device *dev,
39298c2ecf20Sopenharmony_ci				       unsigned int table, unsigned int entry,
39308c2ecf20Sopenharmony_ci				       struct udp_tunnel_info *ti)
39318c2ecf20Sopenharmony_ci{
39328c2ecf20Sopenharmony_ci	struct efx_nic *efx = netdev_priv(dev);
39338c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data;
39348c2ecf20Sopenharmony_ci	int rc;
39358c2ecf20Sopenharmony_ci
39368c2ecf20Sopenharmony_ci	nic_data = efx->nic_data;
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci	mutex_lock(&nic_data->udp_tunnels_lock);
39398c2ecf20Sopenharmony_ci	/* Make sure all TX are stopped while we remove from the table, else we
39408c2ecf20Sopenharmony_ci	 * might race against an efx_features_check().
39418c2ecf20Sopenharmony_ci	 */
39428c2ecf20Sopenharmony_ci	efx_device_detach_sync(efx);
39438c2ecf20Sopenharmony_ci	nic_data->udp_tunnels[entry].type = TUNNEL_ENCAP_UDP_PORT_ENTRY_INVALID;
39448c2ecf20Sopenharmony_ci	nic_data->udp_tunnels[entry].port = 0;
39458c2ecf20Sopenharmony_ci	rc = efx_ef10_set_udp_tnl_ports(efx, false);
39468c2ecf20Sopenharmony_ci	mutex_unlock(&nic_data->udp_tunnels_lock);
39478c2ecf20Sopenharmony_ci
39488c2ecf20Sopenharmony_ci	return rc;
39498c2ecf20Sopenharmony_ci}
39508c2ecf20Sopenharmony_ci
39518c2ecf20Sopenharmony_cistatic const struct udp_tunnel_nic_info efx_ef10_udp_tunnels = {
39528c2ecf20Sopenharmony_ci	.set_port	= efx_ef10_udp_tnl_set_port,
39538c2ecf20Sopenharmony_ci	.unset_port	= efx_ef10_udp_tnl_unset_port,
39548c2ecf20Sopenharmony_ci	.flags          = UDP_TUNNEL_NIC_INFO_MAY_SLEEP,
39558c2ecf20Sopenharmony_ci	.tables         = {
39568c2ecf20Sopenharmony_ci		{
39578c2ecf20Sopenharmony_ci			.n_entries = 16,
39588c2ecf20Sopenharmony_ci			.tunnel_types = UDP_TUNNEL_TYPE_VXLAN |
39598c2ecf20Sopenharmony_ci					UDP_TUNNEL_TYPE_GENEVE,
39608c2ecf20Sopenharmony_ci		},
39618c2ecf20Sopenharmony_ci	},
39628c2ecf20Sopenharmony_ci};
39638c2ecf20Sopenharmony_ci
39648c2ecf20Sopenharmony_ci/* EF10 may have multiple datapath firmware variants within a
39658c2ecf20Sopenharmony_ci * single version.  Report which variants are running.
39668c2ecf20Sopenharmony_ci */
39678c2ecf20Sopenharmony_cistatic size_t efx_ef10_print_additional_fwver(struct efx_nic *efx, char *buf,
39688c2ecf20Sopenharmony_ci					      size_t len)
39698c2ecf20Sopenharmony_ci{
39708c2ecf20Sopenharmony_ci	struct efx_ef10_nic_data *nic_data = efx->nic_data;
39718c2ecf20Sopenharmony_ci
39728c2ecf20Sopenharmony_ci	return scnprintf(buf, len, " rx%x tx%x",
39738c2ecf20Sopenharmony_ci			 nic_data->rx_dpcpu_fw_id,
39748c2ecf20Sopenharmony_ci			 nic_data->tx_dpcpu_fw_id);
39758c2ecf20Sopenharmony_ci}
39768c2ecf20Sopenharmony_ci
39778c2ecf20Sopenharmony_cistatic unsigned int ef10_check_caps(const struct efx_nic *efx,
39788c2ecf20Sopenharmony_ci				    u8 flag,
39798c2ecf20Sopenharmony_ci				    u32 offset)
39808c2ecf20Sopenharmony_ci{
39818c2ecf20Sopenharmony_ci	const struct efx_ef10_nic_data *nic_data = efx->nic_data;
39828c2ecf20Sopenharmony_ci
39838c2ecf20Sopenharmony_ci	switch (offset) {
39848c2ecf20Sopenharmony_ci	case(MC_CMD_GET_CAPABILITIES_V4_OUT_FLAGS1_OFST):
39858c2ecf20Sopenharmony_ci		return nic_data->datapath_caps & BIT_ULL(flag);
39868c2ecf20Sopenharmony_ci	case(MC_CMD_GET_CAPABILITIES_V4_OUT_FLAGS2_OFST):
39878c2ecf20Sopenharmony_ci		return nic_data->datapath_caps2 & BIT_ULL(flag);
39888c2ecf20Sopenharmony_ci	default:
39898c2ecf20Sopenharmony_ci		return 0;
39908c2ecf20Sopenharmony_ci	}
39918c2ecf20Sopenharmony_ci}
39928c2ecf20Sopenharmony_ci
39938c2ecf20Sopenharmony_ci#define EF10_OFFLOAD_FEATURES		\
39948c2ecf20Sopenharmony_ci	(NETIF_F_IP_CSUM |		\
39958c2ecf20Sopenharmony_ci	 NETIF_F_HW_VLAN_CTAG_FILTER |	\
39968c2ecf20Sopenharmony_ci	 NETIF_F_IPV6_CSUM |		\
39978c2ecf20Sopenharmony_ci	 NETIF_F_RXHASH |		\
39988c2ecf20Sopenharmony_ci	 NETIF_F_NTUPLE |		\
39998c2ecf20Sopenharmony_ci	 NETIF_F_SG |			\
40008c2ecf20Sopenharmony_ci	 NETIF_F_RXCSUM |		\
40018c2ecf20Sopenharmony_ci	 NETIF_F_RXALL)
40028c2ecf20Sopenharmony_ci
40038c2ecf20Sopenharmony_ciconst struct efx_nic_type efx_hunt_a0_vf_nic_type = {
40048c2ecf20Sopenharmony_ci	.is_vf = true,
40058c2ecf20Sopenharmony_ci	.mem_bar = efx_ef10_vf_mem_bar,
40068c2ecf20Sopenharmony_ci	.mem_map_size = efx_ef10_mem_map_size,
40078c2ecf20Sopenharmony_ci	.probe = efx_ef10_probe_vf,
40088c2ecf20Sopenharmony_ci	.remove = efx_ef10_remove,
40098c2ecf20Sopenharmony_ci	.dimension_resources = efx_ef10_dimension_resources,
40108c2ecf20Sopenharmony_ci	.init = efx_ef10_init_nic,
40118c2ecf20Sopenharmony_ci	.fini = efx_ef10_fini_nic,
40128c2ecf20Sopenharmony_ci	.map_reset_reason = efx_ef10_map_reset_reason,
40138c2ecf20Sopenharmony_ci	.map_reset_flags = efx_ef10_map_reset_flags,
40148c2ecf20Sopenharmony_ci	.reset = efx_ef10_reset,
40158c2ecf20Sopenharmony_ci	.probe_port = efx_mcdi_port_probe,
40168c2ecf20Sopenharmony_ci	.remove_port = efx_mcdi_port_remove,
40178c2ecf20Sopenharmony_ci	.fini_dmaq = efx_fini_dmaq,
40188c2ecf20Sopenharmony_ci	.prepare_flr = efx_ef10_prepare_flr,
40198c2ecf20Sopenharmony_ci	.finish_flr = efx_port_dummy_op_void,
40208c2ecf20Sopenharmony_ci	.describe_stats = efx_ef10_describe_stats,
40218c2ecf20Sopenharmony_ci	.update_stats = efx_ef10_update_stats_vf,
40228c2ecf20Sopenharmony_ci	.update_stats_atomic = efx_ef10_update_stats_atomic_vf,
40238c2ecf20Sopenharmony_ci	.start_stats = efx_port_dummy_op_void,
40248c2ecf20Sopenharmony_ci	.pull_stats = efx_port_dummy_op_void,
40258c2ecf20Sopenharmony_ci	.stop_stats = efx_port_dummy_op_void,
40268c2ecf20Sopenharmony_ci	.push_irq_moderation = efx_ef10_push_irq_moderation,
40278c2ecf20Sopenharmony_ci	.reconfigure_mac = efx_ef10_mac_reconfigure,
40288c2ecf20Sopenharmony_ci	.check_mac_fault = efx_mcdi_mac_check_fault,
40298c2ecf20Sopenharmony_ci	.reconfigure_port = efx_mcdi_port_reconfigure,
40308c2ecf20Sopenharmony_ci	.get_wol = efx_ef10_get_wol_vf,
40318c2ecf20Sopenharmony_ci	.set_wol = efx_ef10_set_wol_vf,
40328c2ecf20Sopenharmony_ci	.resume_wol = efx_port_dummy_op_void,
40338c2ecf20Sopenharmony_ci	.mcdi_request = efx_ef10_mcdi_request,
40348c2ecf20Sopenharmony_ci	.mcdi_poll_response = efx_ef10_mcdi_poll_response,
40358c2ecf20Sopenharmony_ci	.mcdi_read_response = efx_ef10_mcdi_read_response,
40368c2ecf20Sopenharmony_ci	.mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot,
40378c2ecf20Sopenharmony_ci	.mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected,
40388c2ecf20Sopenharmony_ci	.irq_enable_master = efx_port_dummy_op_void,
40398c2ecf20Sopenharmony_ci	.irq_test_generate = efx_ef10_irq_test_generate,
40408c2ecf20Sopenharmony_ci	.irq_disable_non_ev = efx_port_dummy_op_void,
40418c2ecf20Sopenharmony_ci	.irq_handle_msi = efx_ef10_msi_interrupt,
40428c2ecf20Sopenharmony_ci	.irq_handle_legacy = efx_ef10_legacy_interrupt,
40438c2ecf20Sopenharmony_ci	.tx_probe = efx_ef10_tx_probe,
40448c2ecf20Sopenharmony_ci	.tx_init = efx_ef10_tx_init,
40458c2ecf20Sopenharmony_ci	.tx_remove = efx_mcdi_tx_remove,
40468c2ecf20Sopenharmony_ci	.tx_write = efx_ef10_tx_write,
40478c2ecf20Sopenharmony_ci	.tx_limit_len = efx_ef10_tx_limit_len,
40488c2ecf20Sopenharmony_ci	.tx_enqueue = __efx_enqueue_skb,
40498c2ecf20Sopenharmony_ci	.rx_push_rss_config = efx_mcdi_vf_rx_push_rss_config,
40508c2ecf20Sopenharmony_ci	.rx_pull_rss_config = efx_mcdi_rx_pull_rss_config,
40518c2ecf20Sopenharmony_ci	.rx_probe = efx_mcdi_rx_probe,
40528c2ecf20Sopenharmony_ci	.rx_init = efx_mcdi_rx_init,
40538c2ecf20Sopenharmony_ci	.rx_remove = efx_mcdi_rx_remove,
40548c2ecf20Sopenharmony_ci	.rx_write = efx_ef10_rx_write,
40558c2ecf20Sopenharmony_ci	.rx_defer_refill = efx_ef10_rx_defer_refill,
40568c2ecf20Sopenharmony_ci	.rx_packet = __efx_rx_packet,
40578c2ecf20Sopenharmony_ci	.ev_probe = efx_mcdi_ev_probe,
40588c2ecf20Sopenharmony_ci	.ev_init = efx_ef10_ev_init,
40598c2ecf20Sopenharmony_ci	.ev_fini = efx_mcdi_ev_fini,
40608c2ecf20Sopenharmony_ci	.ev_remove = efx_mcdi_ev_remove,
40618c2ecf20Sopenharmony_ci	.ev_process = efx_ef10_ev_process,
40628c2ecf20Sopenharmony_ci	.ev_read_ack = efx_ef10_ev_read_ack,
40638c2ecf20Sopenharmony_ci	.ev_test_generate = efx_ef10_ev_test_generate,
40648c2ecf20Sopenharmony_ci	.filter_table_probe = efx_ef10_filter_table_probe,
40658c2ecf20Sopenharmony_ci	.filter_table_restore = efx_mcdi_filter_table_restore,
40668c2ecf20Sopenharmony_ci	.filter_table_remove = efx_mcdi_filter_table_remove,
40678c2ecf20Sopenharmony_ci	.filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
40688c2ecf20Sopenharmony_ci	.filter_insert = efx_mcdi_filter_insert,
40698c2ecf20Sopenharmony_ci	.filter_remove_safe = efx_mcdi_filter_remove_safe,
40708c2ecf20Sopenharmony_ci	.filter_get_safe = efx_mcdi_filter_get_safe,
40718c2ecf20Sopenharmony_ci	.filter_clear_rx = efx_mcdi_filter_clear_rx,
40728c2ecf20Sopenharmony_ci	.filter_count_rx_used = efx_mcdi_filter_count_rx_used,
40738c2ecf20Sopenharmony_ci	.filter_get_rx_id_limit = efx_mcdi_filter_get_rx_id_limit,
40748c2ecf20Sopenharmony_ci	.filter_get_rx_ids = efx_mcdi_filter_get_rx_ids,
40758c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
40768c2ecf20Sopenharmony_ci	.filter_rfs_expire_one = efx_mcdi_filter_rfs_expire_one,
40778c2ecf20Sopenharmony_ci#endif
40788c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_MTD
40798c2ecf20Sopenharmony_ci	.mtd_probe = efx_port_dummy_op_int,
40808c2ecf20Sopenharmony_ci#endif
40818c2ecf20Sopenharmony_ci	.ptp_write_host_time = efx_ef10_ptp_write_host_time_vf,
40828c2ecf20Sopenharmony_ci	.ptp_set_ts_config = efx_ef10_ptp_set_ts_config_vf,
40838c2ecf20Sopenharmony_ci	.vlan_rx_add_vid = efx_ef10_vlan_rx_add_vid,
40848c2ecf20Sopenharmony_ci	.vlan_rx_kill_vid = efx_ef10_vlan_rx_kill_vid,
40858c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
40868c2ecf20Sopenharmony_ci	.vswitching_probe = efx_ef10_vswitching_probe_vf,
40878c2ecf20Sopenharmony_ci	.vswitching_restore = efx_ef10_vswitching_restore_vf,
40888c2ecf20Sopenharmony_ci	.vswitching_remove = efx_ef10_vswitching_remove_vf,
40898c2ecf20Sopenharmony_ci#endif
40908c2ecf20Sopenharmony_ci	.get_mac_address = efx_ef10_get_mac_address_vf,
40918c2ecf20Sopenharmony_ci	.set_mac_address = efx_ef10_set_mac_address,
40928c2ecf20Sopenharmony_ci
40938c2ecf20Sopenharmony_ci	.get_phys_port_id = efx_ef10_get_phys_port_id,
40948c2ecf20Sopenharmony_ci	.revision = EFX_REV_HUNT_A0,
40958c2ecf20Sopenharmony_ci	.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
40968c2ecf20Sopenharmony_ci	.rx_prefix_size = ES_DZ_RX_PREFIX_SIZE,
40978c2ecf20Sopenharmony_ci	.rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST,
40988c2ecf20Sopenharmony_ci	.rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST,
40998c2ecf20Sopenharmony_ci	.can_rx_scatter = true,
41008c2ecf20Sopenharmony_ci	.always_rx_scatter = true,
41018c2ecf20Sopenharmony_ci	.min_interrupt_mode = EFX_INT_MODE_MSIX,
41028c2ecf20Sopenharmony_ci	.timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH,
41038c2ecf20Sopenharmony_ci	.offload_features = EF10_OFFLOAD_FEATURES,
41048c2ecf20Sopenharmony_ci	.mcdi_max_ver = 2,
41058c2ecf20Sopenharmony_ci	.max_rx_ip_filters = EFX_MCDI_FILTER_TBL_ROWS,
41068c2ecf20Sopenharmony_ci	.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
41078c2ecf20Sopenharmony_ci			    1 << HWTSTAMP_FILTER_ALL,
41088c2ecf20Sopenharmony_ci	.rx_hash_key_size = 40,
41098c2ecf20Sopenharmony_ci	.check_caps = ef10_check_caps,
41108c2ecf20Sopenharmony_ci	.print_additional_fwver = efx_ef10_print_additional_fwver,
41118c2ecf20Sopenharmony_ci	.sensor_event = efx_mcdi_sensor_event,
41128c2ecf20Sopenharmony_ci};
41138c2ecf20Sopenharmony_ci
41148c2ecf20Sopenharmony_ciconst struct efx_nic_type efx_hunt_a0_nic_type = {
41158c2ecf20Sopenharmony_ci	.is_vf = false,
41168c2ecf20Sopenharmony_ci	.mem_bar = efx_ef10_pf_mem_bar,
41178c2ecf20Sopenharmony_ci	.mem_map_size = efx_ef10_mem_map_size,
41188c2ecf20Sopenharmony_ci	.probe = efx_ef10_probe_pf,
41198c2ecf20Sopenharmony_ci	.remove = efx_ef10_remove,
41208c2ecf20Sopenharmony_ci	.dimension_resources = efx_ef10_dimension_resources,
41218c2ecf20Sopenharmony_ci	.init = efx_ef10_init_nic,
41228c2ecf20Sopenharmony_ci	.fini = efx_ef10_fini_nic,
41238c2ecf20Sopenharmony_ci	.map_reset_reason = efx_ef10_map_reset_reason,
41248c2ecf20Sopenharmony_ci	.map_reset_flags = efx_ef10_map_reset_flags,
41258c2ecf20Sopenharmony_ci	.reset = efx_ef10_reset,
41268c2ecf20Sopenharmony_ci	.probe_port = efx_mcdi_port_probe,
41278c2ecf20Sopenharmony_ci	.remove_port = efx_mcdi_port_remove,
41288c2ecf20Sopenharmony_ci	.fini_dmaq = efx_fini_dmaq,
41298c2ecf20Sopenharmony_ci	.prepare_flr = efx_ef10_prepare_flr,
41308c2ecf20Sopenharmony_ci	.finish_flr = efx_port_dummy_op_void,
41318c2ecf20Sopenharmony_ci	.describe_stats = efx_ef10_describe_stats,
41328c2ecf20Sopenharmony_ci	.update_stats = efx_ef10_update_stats_pf,
41338c2ecf20Sopenharmony_ci	.start_stats = efx_mcdi_mac_start_stats,
41348c2ecf20Sopenharmony_ci	.pull_stats = efx_mcdi_mac_pull_stats,
41358c2ecf20Sopenharmony_ci	.stop_stats = efx_mcdi_mac_stop_stats,
41368c2ecf20Sopenharmony_ci	.push_irq_moderation = efx_ef10_push_irq_moderation,
41378c2ecf20Sopenharmony_ci	.reconfigure_mac = efx_ef10_mac_reconfigure,
41388c2ecf20Sopenharmony_ci	.check_mac_fault = efx_mcdi_mac_check_fault,
41398c2ecf20Sopenharmony_ci	.reconfigure_port = efx_mcdi_port_reconfigure,
41408c2ecf20Sopenharmony_ci	.get_wol = efx_ef10_get_wol,
41418c2ecf20Sopenharmony_ci	.set_wol = efx_ef10_set_wol,
41428c2ecf20Sopenharmony_ci	.resume_wol = efx_port_dummy_op_void,
41438c2ecf20Sopenharmony_ci	.test_chip = efx_ef10_test_chip,
41448c2ecf20Sopenharmony_ci	.test_nvram = efx_mcdi_nvram_test_all,
41458c2ecf20Sopenharmony_ci	.mcdi_request = efx_ef10_mcdi_request,
41468c2ecf20Sopenharmony_ci	.mcdi_poll_response = efx_ef10_mcdi_poll_response,
41478c2ecf20Sopenharmony_ci	.mcdi_read_response = efx_ef10_mcdi_read_response,
41488c2ecf20Sopenharmony_ci	.mcdi_poll_reboot = efx_ef10_mcdi_poll_reboot,
41498c2ecf20Sopenharmony_ci	.mcdi_reboot_detected = efx_ef10_mcdi_reboot_detected,
41508c2ecf20Sopenharmony_ci	.irq_enable_master = efx_port_dummy_op_void,
41518c2ecf20Sopenharmony_ci	.irq_test_generate = efx_ef10_irq_test_generate,
41528c2ecf20Sopenharmony_ci	.irq_disable_non_ev = efx_port_dummy_op_void,
41538c2ecf20Sopenharmony_ci	.irq_handle_msi = efx_ef10_msi_interrupt,
41548c2ecf20Sopenharmony_ci	.irq_handle_legacy = efx_ef10_legacy_interrupt,
41558c2ecf20Sopenharmony_ci	.tx_probe = efx_ef10_tx_probe,
41568c2ecf20Sopenharmony_ci	.tx_init = efx_ef10_tx_init,
41578c2ecf20Sopenharmony_ci	.tx_remove = efx_mcdi_tx_remove,
41588c2ecf20Sopenharmony_ci	.tx_write = efx_ef10_tx_write,
41598c2ecf20Sopenharmony_ci	.tx_limit_len = efx_ef10_tx_limit_len,
41608c2ecf20Sopenharmony_ci	.tx_enqueue = __efx_enqueue_skb,
41618c2ecf20Sopenharmony_ci	.rx_push_rss_config = efx_mcdi_pf_rx_push_rss_config,
41628c2ecf20Sopenharmony_ci	.rx_pull_rss_config = efx_mcdi_rx_pull_rss_config,
41638c2ecf20Sopenharmony_ci	.rx_push_rss_context_config = efx_mcdi_rx_push_rss_context_config,
41648c2ecf20Sopenharmony_ci	.rx_pull_rss_context_config = efx_mcdi_rx_pull_rss_context_config,
41658c2ecf20Sopenharmony_ci	.rx_restore_rss_contexts = efx_mcdi_rx_restore_rss_contexts,
41668c2ecf20Sopenharmony_ci	.rx_probe = efx_mcdi_rx_probe,
41678c2ecf20Sopenharmony_ci	.rx_init = efx_mcdi_rx_init,
41688c2ecf20Sopenharmony_ci	.rx_remove = efx_mcdi_rx_remove,
41698c2ecf20Sopenharmony_ci	.rx_write = efx_ef10_rx_write,
41708c2ecf20Sopenharmony_ci	.rx_defer_refill = efx_ef10_rx_defer_refill,
41718c2ecf20Sopenharmony_ci	.rx_packet = __efx_rx_packet,
41728c2ecf20Sopenharmony_ci	.ev_probe = efx_mcdi_ev_probe,
41738c2ecf20Sopenharmony_ci	.ev_init = efx_ef10_ev_init,
41748c2ecf20Sopenharmony_ci	.ev_fini = efx_mcdi_ev_fini,
41758c2ecf20Sopenharmony_ci	.ev_remove = efx_mcdi_ev_remove,
41768c2ecf20Sopenharmony_ci	.ev_process = efx_ef10_ev_process,
41778c2ecf20Sopenharmony_ci	.ev_read_ack = efx_ef10_ev_read_ack,
41788c2ecf20Sopenharmony_ci	.ev_test_generate = efx_ef10_ev_test_generate,
41798c2ecf20Sopenharmony_ci	.filter_table_probe = efx_ef10_filter_table_probe,
41808c2ecf20Sopenharmony_ci	.filter_table_restore = efx_mcdi_filter_table_restore,
41818c2ecf20Sopenharmony_ci	.filter_table_remove = efx_mcdi_filter_table_remove,
41828c2ecf20Sopenharmony_ci	.filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
41838c2ecf20Sopenharmony_ci	.filter_insert = efx_mcdi_filter_insert,
41848c2ecf20Sopenharmony_ci	.filter_remove_safe = efx_mcdi_filter_remove_safe,
41858c2ecf20Sopenharmony_ci	.filter_get_safe = efx_mcdi_filter_get_safe,
41868c2ecf20Sopenharmony_ci	.filter_clear_rx = efx_mcdi_filter_clear_rx,
41878c2ecf20Sopenharmony_ci	.filter_count_rx_used = efx_mcdi_filter_count_rx_used,
41888c2ecf20Sopenharmony_ci	.filter_get_rx_id_limit = efx_mcdi_filter_get_rx_id_limit,
41898c2ecf20Sopenharmony_ci	.filter_get_rx_ids = efx_mcdi_filter_get_rx_ids,
41908c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL
41918c2ecf20Sopenharmony_ci	.filter_rfs_expire_one = efx_mcdi_filter_rfs_expire_one,
41928c2ecf20Sopenharmony_ci#endif
41938c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_MTD
41948c2ecf20Sopenharmony_ci	.mtd_probe = efx_ef10_mtd_probe,
41958c2ecf20Sopenharmony_ci	.mtd_rename = efx_mcdi_mtd_rename,
41968c2ecf20Sopenharmony_ci	.mtd_read = efx_mcdi_mtd_read,
41978c2ecf20Sopenharmony_ci	.mtd_erase = efx_mcdi_mtd_erase,
41988c2ecf20Sopenharmony_ci	.mtd_write = efx_mcdi_mtd_write,
41998c2ecf20Sopenharmony_ci	.mtd_sync = efx_mcdi_mtd_sync,
42008c2ecf20Sopenharmony_ci#endif
42018c2ecf20Sopenharmony_ci	.ptp_write_host_time = efx_ef10_ptp_write_host_time,
42028c2ecf20Sopenharmony_ci	.ptp_set_ts_sync_events = efx_ef10_ptp_set_ts_sync_events,
42038c2ecf20Sopenharmony_ci	.ptp_set_ts_config = efx_ef10_ptp_set_ts_config,
42048c2ecf20Sopenharmony_ci	.vlan_rx_add_vid = efx_ef10_vlan_rx_add_vid,
42058c2ecf20Sopenharmony_ci	.vlan_rx_kill_vid = efx_ef10_vlan_rx_kill_vid,
42068c2ecf20Sopenharmony_ci	.udp_tnl_push_ports = efx_ef10_udp_tnl_push_ports,
42078c2ecf20Sopenharmony_ci	.udp_tnl_has_port = efx_ef10_udp_tnl_has_port,
42088c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV
42098c2ecf20Sopenharmony_ci	.sriov_configure = efx_ef10_sriov_configure,
42108c2ecf20Sopenharmony_ci	.sriov_init = efx_ef10_sriov_init,
42118c2ecf20Sopenharmony_ci	.sriov_fini = efx_ef10_sriov_fini,
42128c2ecf20Sopenharmony_ci	.sriov_wanted = efx_ef10_sriov_wanted,
42138c2ecf20Sopenharmony_ci	.sriov_reset = efx_ef10_sriov_reset,
42148c2ecf20Sopenharmony_ci	.sriov_flr = efx_ef10_sriov_flr,
42158c2ecf20Sopenharmony_ci	.sriov_set_vf_mac = efx_ef10_sriov_set_vf_mac,
42168c2ecf20Sopenharmony_ci	.sriov_set_vf_vlan = efx_ef10_sriov_set_vf_vlan,
42178c2ecf20Sopenharmony_ci	.sriov_set_vf_spoofchk = efx_ef10_sriov_set_vf_spoofchk,
42188c2ecf20Sopenharmony_ci	.sriov_get_vf_config = efx_ef10_sriov_get_vf_config,
42198c2ecf20Sopenharmony_ci	.sriov_set_vf_link_state = efx_ef10_sriov_set_vf_link_state,
42208c2ecf20Sopenharmony_ci	.vswitching_probe = efx_ef10_vswitching_probe_pf,
42218c2ecf20Sopenharmony_ci	.vswitching_restore = efx_ef10_vswitching_restore_pf,
42228c2ecf20Sopenharmony_ci	.vswitching_remove = efx_ef10_vswitching_remove_pf,
42238c2ecf20Sopenharmony_ci#endif
42248c2ecf20Sopenharmony_ci	.get_mac_address = efx_ef10_get_mac_address_pf,
42258c2ecf20Sopenharmony_ci	.set_mac_address = efx_ef10_set_mac_address,
42268c2ecf20Sopenharmony_ci	.tso_versions = efx_ef10_tso_versions,
42278c2ecf20Sopenharmony_ci
42288c2ecf20Sopenharmony_ci	.get_phys_port_id = efx_ef10_get_phys_port_id,
42298c2ecf20Sopenharmony_ci	.revision = EFX_REV_HUNT_A0,
42308c2ecf20Sopenharmony_ci	.max_dma_mask = DMA_BIT_MASK(ESF_DZ_TX_KER_BUF_ADDR_WIDTH),
42318c2ecf20Sopenharmony_ci	.rx_prefix_size = ES_DZ_RX_PREFIX_SIZE,
42328c2ecf20Sopenharmony_ci	.rx_hash_offset = ES_DZ_RX_PREFIX_HASH_OFST,
42338c2ecf20Sopenharmony_ci	.rx_ts_offset = ES_DZ_RX_PREFIX_TSTAMP_OFST,
42348c2ecf20Sopenharmony_ci	.can_rx_scatter = true,
42358c2ecf20Sopenharmony_ci	.always_rx_scatter = true,
42368c2ecf20Sopenharmony_ci	.option_descriptors = true,
42378c2ecf20Sopenharmony_ci	.min_interrupt_mode = EFX_INT_MODE_LEGACY,
42388c2ecf20Sopenharmony_ci	.timer_period_max = 1 << ERF_DD_EVQ_IND_TIMER_VAL_WIDTH,
42398c2ecf20Sopenharmony_ci	.offload_features = EF10_OFFLOAD_FEATURES,
42408c2ecf20Sopenharmony_ci	.mcdi_max_ver = 2,
42418c2ecf20Sopenharmony_ci	.max_rx_ip_filters = EFX_MCDI_FILTER_TBL_ROWS,
42428c2ecf20Sopenharmony_ci	.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
42438c2ecf20Sopenharmony_ci			    1 << HWTSTAMP_FILTER_ALL,
42448c2ecf20Sopenharmony_ci	.rx_hash_key_size = 40,
42458c2ecf20Sopenharmony_ci	.check_caps = ef10_check_caps,
42468c2ecf20Sopenharmony_ci	.print_additional_fwver = efx_ef10_print_additional_fwver,
42478c2ecf20Sopenharmony_ci	.sensor_event = efx_mcdi_sensor_event,
42488c2ecf20Sopenharmony_ci};
4249