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, ®, 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, ®, 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, ®, 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, ®, 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, ®, 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