18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/**************************************************************************** 38c2ecf20Sopenharmony_ci * Driver for Solarflare network controllers and boards 48c2ecf20Sopenharmony_ci * Copyright 2005-2006 Fen Systems Ltd. 58c2ecf20Sopenharmony_ci * Copyright 2006-2013 Solarflare Communications Inc. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef EFX_EFX_H 98c2ecf20Sopenharmony_ci#define EFX_EFX_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/indirect_call_wrapper.h> 128c2ecf20Sopenharmony_ci#include "net_driver.h" 138c2ecf20Sopenharmony_ci#include "ef100_rx.h" 148c2ecf20Sopenharmony_ci#include "ef100_tx.h" 158c2ecf20Sopenharmony_ci#include "filter.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciint efx_net_open(struct net_device *net_dev); 188c2ecf20Sopenharmony_ciint efx_net_stop(struct net_device *net_dev); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* TX */ 218c2ecf20Sopenharmony_civoid efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue); 228c2ecf20Sopenharmony_cinetdev_tx_t efx_hard_start_xmit(struct sk_buff *skb, 238c2ecf20Sopenharmony_ci struct net_device *net_dev); 248c2ecf20Sopenharmony_cinetdev_tx_t __efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); 258c2ecf20Sopenharmony_cistatic inline netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci return INDIRECT_CALL_2(tx_queue->efx->type->tx_enqueue, 288c2ecf20Sopenharmony_ci ef100_enqueue_skb, __efx_enqueue_skb, 298c2ecf20Sopenharmony_ci tx_queue, skb); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_civoid efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); 328c2ecf20Sopenharmony_civoid efx_xmit_done_single(struct efx_tx_queue *tx_queue); 338c2ecf20Sopenharmony_ciint efx_setup_tc(struct net_device *net_dev, enum tc_setup_type type, 348c2ecf20Sopenharmony_ci void *type_data); 358c2ecf20Sopenharmony_ciextern unsigned int efx_piobuf_size; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* RX */ 388c2ecf20Sopenharmony_civoid __efx_rx_packet(struct efx_channel *channel); 398c2ecf20Sopenharmony_civoid efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, 408c2ecf20Sopenharmony_ci unsigned int n_frags, unsigned int len, u16 flags); 418c2ecf20Sopenharmony_cistatic inline void efx_rx_flush_packet(struct efx_channel *channel) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci if (channel->rx_pkt_n_frags) 448c2ecf20Sopenharmony_ci INDIRECT_CALL_2(channel->efx->type->rx_packet, 458c2ecf20Sopenharmony_ci __ef100_rx_packet, __efx_rx_packet, 468c2ecf20Sopenharmony_ci channel); 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_cistatic inline bool efx_rx_buf_hash_valid(struct efx_nic *efx, const u8 *prefix) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci if (efx->type->rx_buf_hash_valid) 518c2ecf20Sopenharmony_ci return INDIRECT_CALL_1(efx->type->rx_buf_hash_valid, 528c2ecf20Sopenharmony_ci ef100_rx_buf_hash_valid, 538c2ecf20Sopenharmony_ci prefix); 548c2ecf20Sopenharmony_ci return true; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* Maximum number of TCP segments we support for soft-TSO */ 588c2ecf20Sopenharmony_ci#define EFX_TSO_MAX_SEGS 100 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* The smallest [rt]xq_entries that the driver supports. RX minimum 618c2ecf20Sopenharmony_ci * is a bit arbitrary. For TX, we must have space for at least 2 628c2ecf20Sopenharmony_ci * TSO skbs. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ci#define EFX_RXQ_MIN_ENT 128U 658c2ecf20Sopenharmony_ci#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* All EF10 architecture NICs steal one bit of the DMAQ size for various 688c2ecf20Sopenharmony_ci * other purposes when counting TxQ entries, so we halve the queue size. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci#define EFX_TXQ_MAX_ENT(efx) (EFX_WORKAROUND_EF10(efx) ? \ 718c2ecf20Sopenharmony_ci EFX_MAX_DMAQ_SIZE / 2 : EFX_MAX_DMAQ_SIZE) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic inline bool efx_rss_enabled(struct efx_nic *efx) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci return efx->rss_spread > 1; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* Filters */ 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/** 818c2ecf20Sopenharmony_ci * efx_filter_insert_filter - add or replace a filter 828c2ecf20Sopenharmony_ci * @efx: NIC in which to insert the filter 838c2ecf20Sopenharmony_ci * @spec: Specification for the filter 848c2ecf20Sopenharmony_ci * @replace_equal: Flag for whether the specified filter may replace an 858c2ecf20Sopenharmony_ci * existing filter with equal priority 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci * On success, return the filter ID. 888c2ecf20Sopenharmony_ci * On failure, return a negative error code. 898c2ecf20Sopenharmony_ci * 908c2ecf20Sopenharmony_ci * If existing filters have equal match values to the new filter spec, 918c2ecf20Sopenharmony_ci * then the new filter might replace them or the function might fail, 928c2ecf20Sopenharmony_ci * as follows. 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * 1. If the existing filters have lower priority, or @replace_equal 958c2ecf20Sopenharmony_ci * is set and they have equal priority, replace them. 968c2ecf20Sopenharmony_ci * 978c2ecf20Sopenharmony_ci * 2. If the existing filters have higher priority, return -%EPERM. 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * 3. If !efx_filter_is_mc_recipient(@spec), or the NIC does not 1008c2ecf20Sopenharmony_ci * support delivery to multiple recipients, return -%EEXIST. 1018c2ecf20Sopenharmony_ci * 1028c2ecf20Sopenharmony_ci * This implies that filters for multiple multicast recipients must 1038c2ecf20Sopenharmony_ci * all be inserted with the same priority and @replace_equal = %false. 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_cistatic inline s32 efx_filter_insert_filter(struct efx_nic *efx, 1068c2ecf20Sopenharmony_ci struct efx_filter_spec *spec, 1078c2ecf20Sopenharmony_ci bool replace_equal) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci return efx->type->filter_insert(efx, spec, replace_equal); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/** 1138c2ecf20Sopenharmony_ci * efx_filter_remove_id_safe - remove a filter by ID, carefully 1148c2ecf20Sopenharmony_ci * @efx: NIC from which to remove the filter 1158c2ecf20Sopenharmony_ci * @priority: Priority of filter, as passed to @efx_filter_insert_filter 1168c2ecf20Sopenharmony_ci * @filter_id: ID of filter, as returned by @efx_filter_insert_filter 1178c2ecf20Sopenharmony_ci * 1188c2ecf20Sopenharmony_ci * This function will range-check @filter_id, so it is safe to call 1198c2ecf20Sopenharmony_ci * with a value passed from userland. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_cistatic inline int efx_filter_remove_id_safe(struct efx_nic *efx, 1228c2ecf20Sopenharmony_ci enum efx_filter_priority priority, 1238c2ecf20Sopenharmony_ci u32 filter_id) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return efx->type->filter_remove_safe(efx, priority, filter_id); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/** 1298c2ecf20Sopenharmony_ci * efx_filter_get_filter_safe - retrieve a filter by ID, carefully 1308c2ecf20Sopenharmony_ci * @efx: NIC from which to remove the filter 1318c2ecf20Sopenharmony_ci * @priority: Priority of filter, as passed to @efx_filter_insert_filter 1328c2ecf20Sopenharmony_ci * @filter_id: ID of filter, as returned by @efx_filter_insert_filter 1338c2ecf20Sopenharmony_ci * @spec: Buffer in which to store filter specification 1348c2ecf20Sopenharmony_ci * 1358c2ecf20Sopenharmony_ci * This function will range-check @filter_id, so it is safe to call 1368c2ecf20Sopenharmony_ci * with a value passed from userland. 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_cistatic inline int 1398c2ecf20Sopenharmony_ciefx_filter_get_filter_safe(struct efx_nic *efx, 1408c2ecf20Sopenharmony_ci enum efx_filter_priority priority, 1418c2ecf20Sopenharmony_ci u32 filter_id, struct efx_filter_spec *spec) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci return efx->type->filter_get_safe(efx, priority, filter_id, spec); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic inline u32 efx_filter_count_rx_used(struct efx_nic *efx, 1478c2ecf20Sopenharmony_ci enum efx_filter_priority priority) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci return efx->type->filter_count_rx_used(efx, priority); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_cistatic inline u32 efx_filter_get_rx_id_limit(struct efx_nic *efx) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci return efx->type->filter_get_rx_id_limit(efx); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_cistatic inline s32 efx_filter_get_rx_ids(struct efx_nic *efx, 1568c2ecf20Sopenharmony_ci enum efx_filter_priority priority, 1578c2ecf20Sopenharmony_ci u32 *buf, u32 size) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci return efx->type->filter_get_rx_ids(efx, priority, buf, size); 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/* RSS contexts */ 1638c2ecf20Sopenharmony_cistatic inline bool efx_rss_active(struct efx_rss_context *ctx) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci return ctx->context_id != EFX_MCDI_RSS_CONTEXT_INVALID; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/* Ethtool support */ 1698c2ecf20Sopenharmony_ciextern const struct ethtool_ops efx_ethtool_ops; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/* Global */ 1728c2ecf20Sopenharmony_ciunsigned int efx_usecs_to_ticks(struct efx_nic *efx, unsigned int usecs); 1738c2ecf20Sopenharmony_ciunsigned int efx_ticks_to_usecs(struct efx_nic *efx, unsigned int ticks); 1748c2ecf20Sopenharmony_ciint efx_init_irq_moderation(struct efx_nic *efx, unsigned int tx_usecs, 1758c2ecf20Sopenharmony_ci unsigned int rx_usecs, bool rx_adaptive, 1768c2ecf20Sopenharmony_ci bool rx_may_override_tx); 1778c2ecf20Sopenharmony_civoid efx_get_irq_moderation(struct efx_nic *efx, unsigned int *tx_usecs, 1788c2ecf20Sopenharmony_ci unsigned int *rx_usecs, bool *rx_adaptive); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/* Update the generic software stats in the passed stats array */ 1818c2ecf20Sopenharmony_civoid efx_update_sw_stats(struct efx_nic *efx, u64 *stats); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci/* MTD */ 1848c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_MTD 1858c2ecf20Sopenharmony_ciint efx_mtd_add(struct efx_nic *efx, struct efx_mtd_partition *parts, 1868c2ecf20Sopenharmony_ci size_t n_parts, size_t sizeof_part); 1878c2ecf20Sopenharmony_cistatic inline int efx_mtd_probe(struct efx_nic *efx) 1888c2ecf20Sopenharmony_ci{ 1898c2ecf20Sopenharmony_ci return efx->type->mtd_probe(efx); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_civoid efx_mtd_rename(struct efx_nic *efx); 1928c2ecf20Sopenharmony_civoid efx_mtd_remove(struct efx_nic *efx); 1938c2ecf20Sopenharmony_ci#else 1948c2ecf20Sopenharmony_cistatic inline int efx_mtd_probe(struct efx_nic *efx) { return 0; } 1958c2ecf20Sopenharmony_cistatic inline void efx_mtd_rename(struct efx_nic *efx) {} 1968c2ecf20Sopenharmony_cistatic inline void efx_mtd_remove(struct efx_nic *efx) {} 1978c2ecf20Sopenharmony_ci#endif 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#ifdef CONFIG_SFC_SRIOV 2008c2ecf20Sopenharmony_cistatic inline unsigned int efx_vf_size(struct efx_nic *efx) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci return 1 << efx->vi_scale; 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci#endif 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic inline void efx_device_detach_sync(struct efx_nic *efx) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct net_device *dev = efx->net_dev; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Lock/freeze all TX queues so that we can be sure the 2118c2ecf20Sopenharmony_ci * TX scheduler is stopped when we're done and before 2128c2ecf20Sopenharmony_ci * netif_device_present() becomes false. 2138c2ecf20Sopenharmony_ci */ 2148c2ecf20Sopenharmony_ci netif_tx_lock_bh(dev); 2158c2ecf20Sopenharmony_ci netif_device_detach(dev); 2168c2ecf20Sopenharmony_ci netif_tx_unlock_bh(dev); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic inline void efx_device_attach_if_not_resetting(struct efx_nic *efx) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci if ((efx->state != STATE_DISABLED) && !efx->reset_pending) 2228c2ecf20Sopenharmony_ci netif_device_attach(efx->net_dev); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic inline bool efx_rwsem_assert_write_locked(struct rw_semaphore *sem) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci if (WARN_ON(down_read_trylock(sem))) { 2288c2ecf20Sopenharmony_ci up_read(sem); 2298c2ecf20Sopenharmony_ci return false; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci return true; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ciint efx_xdp_tx_buffers(struct efx_nic *efx, int n, struct xdp_frame **xdpfs, 2358c2ecf20Sopenharmony_ci bool flush); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci#endif /* EFX_EFX_H */ 238