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 EF4_NIC_H 98c2ecf20Sopenharmony_ci#define EF4_NIC_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/net_tstamp.h> 128c2ecf20Sopenharmony_ci#include <linux/i2c-algo-bit.h> 138c2ecf20Sopenharmony_ci#include "net_driver.h" 148c2ecf20Sopenharmony_ci#include "efx.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cienum { 178c2ecf20Sopenharmony_ci EF4_REV_FALCON_A0 = 0, 188c2ecf20Sopenharmony_ci EF4_REV_FALCON_A1 = 1, 198c2ecf20Sopenharmony_ci EF4_REV_FALCON_B0 = 2, 208c2ecf20Sopenharmony_ci}; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic inline int ef4_nic_rev(struct ef4_nic *efx) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci return efx->type->revision; 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciu32 ef4_farch_fpga_ver(struct ef4_nic *efx); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* NIC has two interlinked PCI functions for the same port. */ 308c2ecf20Sopenharmony_cistatic inline bool ef4_nic_is_dual_func(struct ef4_nic *efx) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci return ef4_nic_rev(efx) < EF4_REV_FALCON_B0; 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* Read the current event from the event queue */ 368c2ecf20Sopenharmony_cistatic inline ef4_qword_t *ef4_event(struct ef4_channel *channel, 378c2ecf20Sopenharmony_ci unsigned int index) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci return ((ef4_qword_t *) (channel->eventq.buf.addr)) + 408c2ecf20Sopenharmony_ci (index & channel->eventq_mask); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* See if an event is present 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * We check both the high and low dword of the event for all ones. We 468c2ecf20Sopenharmony_ci * wrote all ones when we cleared the event, and no valid event can 478c2ecf20Sopenharmony_ci * have all ones in either its high or low dwords. This approach is 488c2ecf20Sopenharmony_ci * robust against reordering. 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * Note that using a single 64-bit comparison is incorrect; even 518c2ecf20Sopenharmony_ci * though the CPU read will be atomic, the DMA write may not be. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_cistatic inline int ef4_event_present(ef4_qword_t *event) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci return !(EF4_DWORD_IS_ALL_ONES(event->dword[0]) | 568c2ecf20Sopenharmony_ci EF4_DWORD_IS_ALL_ONES(event->dword[1])); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* Returns a pointer to the specified transmit descriptor in the TX 608c2ecf20Sopenharmony_ci * descriptor queue belonging to the specified channel. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_cistatic inline ef4_qword_t * 638c2ecf20Sopenharmony_cief4_tx_desc(struct ef4_tx_queue *tx_queue, unsigned int index) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci return ((ef4_qword_t *) (tx_queue->txd.buf.addr)) + index; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Get partner of a TX queue, seen as part of the same net core queue */ 698c2ecf20Sopenharmony_cistatic inline struct ef4_tx_queue *ef4_tx_queue_partner(struct ef4_tx_queue *tx_queue) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci if (tx_queue->queue & EF4_TXQ_TYPE_OFFLOAD) 728c2ecf20Sopenharmony_ci return tx_queue - EF4_TXQ_TYPE_OFFLOAD; 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci return tx_queue + EF4_TXQ_TYPE_OFFLOAD; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* Report whether this TX queue would be empty for the given write_count. 788c2ecf20Sopenharmony_ci * May return false negative. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_cistatic inline bool __ef4_nic_tx_is_empty(struct ef4_tx_queue *tx_queue, 818c2ecf20Sopenharmony_ci unsigned int write_count) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci unsigned int empty_read_count = READ_ONCE(tx_queue->empty_read_count); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci if (empty_read_count == 0) 868c2ecf20Sopenharmony_ci return false; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci return ((empty_read_count ^ write_count) & ~EF4_EMPTY_COUNT_VALID) == 0; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* Decide whether to push a TX descriptor to the NIC vs merely writing 928c2ecf20Sopenharmony_ci * the doorbell. This can reduce latency when we are adding a single 938c2ecf20Sopenharmony_ci * descriptor to an empty queue, but is otherwise pointless. Further, 948c2ecf20Sopenharmony_ci * Falcon and Siena have hardware bugs (SF bug 33851) that may be 958c2ecf20Sopenharmony_ci * triggered if we don't check this. 968c2ecf20Sopenharmony_ci * We use the write_count used for the last doorbell push, to get the 978c2ecf20Sopenharmony_ci * NIC's view of the tx queue. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_cistatic inline bool ef4_nic_may_push_tx_desc(struct ef4_tx_queue *tx_queue, 1008c2ecf20Sopenharmony_ci unsigned int write_count) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci bool was_empty = __ef4_nic_tx_is_empty(tx_queue, write_count); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci tx_queue->empty_read_count = 0; 1058c2ecf20Sopenharmony_ci return was_empty && tx_queue->write_count - write_count == 1; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* Returns a pointer to the specified descriptor in the RX descriptor queue */ 1098c2ecf20Sopenharmony_cistatic inline ef4_qword_t * 1108c2ecf20Sopenharmony_cief4_rx_desc(struct ef4_rx_queue *rx_queue, unsigned int index) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci return ((ef4_qword_t *) (rx_queue->rxd.buf.addr)) + index; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cienum { 1168c2ecf20Sopenharmony_ci PHY_TYPE_NONE = 0, 1178c2ecf20Sopenharmony_ci PHY_TYPE_TXC43128 = 1, 1188c2ecf20Sopenharmony_ci PHY_TYPE_88E1111 = 2, 1198c2ecf20Sopenharmony_ci PHY_TYPE_SFX7101 = 3, 1208c2ecf20Sopenharmony_ci PHY_TYPE_QT2022C2 = 4, 1218c2ecf20Sopenharmony_ci PHY_TYPE_PM8358 = 6, 1228c2ecf20Sopenharmony_ci PHY_TYPE_SFT9001A = 8, 1238c2ecf20Sopenharmony_ci PHY_TYPE_QT2025C = 9, 1248c2ecf20Sopenharmony_ci PHY_TYPE_SFT9001B = 10, 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#define FALCON_XMAC_LOOPBACKS \ 1288c2ecf20Sopenharmony_ci ((1 << LOOPBACK_XGMII) | \ 1298c2ecf20Sopenharmony_ci (1 << LOOPBACK_XGXS) | \ 1308c2ecf20Sopenharmony_ci (1 << LOOPBACK_XAUI)) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* Alignment of PCIe DMA boundaries (4KB) */ 1338c2ecf20Sopenharmony_ci#define EF4_PAGE_SIZE 4096 1348c2ecf20Sopenharmony_ci/* Size and alignment of buffer table entries (same) */ 1358c2ecf20Sopenharmony_ci#define EF4_BUF_SIZE EF4_PAGE_SIZE 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* NIC-generic software stats */ 1388c2ecf20Sopenharmony_cienum { 1398c2ecf20Sopenharmony_ci GENERIC_STAT_rx_noskb_drops, 1408c2ecf20Sopenharmony_ci GENERIC_STAT_rx_nodesc_trunc, 1418c2ecf20Sopenharmony_ci GENERIC_STAT_COUNT 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/** 1458c2ecf20Sopenharmony_ci * struct falcon_board_type - board operations and type information 1468c2ecf20Sopenharmony_ci * @id: Board type id, as found in NVRAM 1478c2ecf20Sopenharmony_ci * @init: Allocate resources and initialise peripheral hardware 1488c2ecf20Sopenharmony_ci * @init_phy: Do board-specific PHY initialisation 1498c2ecf20Sopenharmony_ci * @fini: Shut down hardware and free resources 1508c2ecf20Sopenharmony_ci * @set_id_led: Set state of identifying LED or revert to automatic function 1518c2ecf20Sopenharmony_ci * @monitor: Board-specific health check function 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_cistruct falcon_board_type { 1548c2ecf20Sopenharmony_ci u8 id; 1558c2ecf20Sopenharmony_ci int (*init) (struct ef4_nic *nic); 1568c2ecf20Sopenharmony_ci void (*init_phy) (struct ef4_nic *efx); 1578c2ecf20Sopenharmony_ci void (*fini) (struct ef4_nic *nic); 1588c2ecf20Sopenharmony_ci void (*set_id_led) (struct ef4_nic *efx, enum ef4_led_mode mode); 1598c2ecf20Sopenharmony_ci int (*monitor) (struct ef4_nic *nic); 1608c2ecf20Sopenharmony_ci}; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci/** 1638c2ecf20Sopenharmony_ci * struct falcon_board - board information 1648c2ecf20Sopenharmony_ci * @type: Type of board 1658c2ecf20Sopenharmony_ci * @major: Major rev. ('A', 'B' ...) 1668c2ecf20Sopenharmony_ci * @minor: Minor rev. (0, 1, ...) 1678c2ecf20Sopenharmony_ci * @i2c_adap: I2C adapter for on-board peripherals 1688c2ecf20Sopenharmony_ci * @i2c_data: Data for bit-banging algorithm 1698c2ecf20Sopenharmony_ci * @hwmon_client: I2C client for hardware monitor 1708c2ecf20Sopenharmony_ci * @ioexp_client: I2C client for power/port control 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_cistruct falcon_board { 1738c2ecf20Sopenharmony_ci const struct falcon_board_type *type; 1748c2ecf20Sopenharmony_ci int major; 1758c2ecf20Sopenharmony_ci int minor; 1768c2ecf20Sopenharmony_ci struct i2c_adapter i2c_adap; 1778c2ecf20Sopenharmony_ci struct i2c_algo_bit_data i2c_data; 1788c2ecf20Sopenharmony_ci struct i2c_client *hwmon_client, *ioexp_client; 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/** 1828c2ecf20Sopenharmony_ci * struct falcon_spi_device - a Falcon SPI (Serial Peripheral Interface) device 1838c2ecf20Sopenharmony_ci * @device_id: Controller's id for the device 1848c2ecf20Sopenharmony_ci * @size: Size (in bytes) 1858c2ecf20Sopenharmony_ci * @addr_len: Number of address bytes in read/write commands 1868c2ecf20Sopenharmony_ci * @munge_address: Flag whether addresses should be munged. 1878c2ecf20Sopenharmony_ci * Some devices with 9-bit addresses (e.g. AT25040A EEPROM) 1888c2ecf20Sopenharmony_ci * use bit 3 of the command byte as address bit A8, rather 1898c2ecf20Sopenharmony_ci * than having a two-byte address. If this flag is set, then 1908c2ecf20Sopenharmony_ci * commands should be munged in this way. 1918c2ecf20Sopenharmony_ci * @erase_command: Erase command (or 0 if sector erase not needed). 1928c2ecf20Sopenharmony_ci * @erase_size: Erase sector size (in bytes) 1938c2ecf20Sopenharmony_ci * Erase commands affect sectors with this size and alignment. 1948c2ecf20Sopenharmony_ci * This must be a power of two. 1958c2ecf20Sopenharmony_ci * @block_size: Write block size (in bytes). 1968c2ecf20Sopenharmony_ci * Write commands are limited to blocks with this size and alignment. 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_cistruct falcon_spi_device { 1998c2ecf20Sopenharmony_ci int device_id; 2008c2ecf20Sopenharmony_ci unsigned int size; 2018c2ecf20Sopenharmony_ci unsigned int addr_len; 2028c2ecf20Sopenharmony_ci unsigned int munge_address:1; 2038c2ecf20Sopenharmony_ci u8 erase_command; 2048c2ecf20Sopenharmony_ci unsigned int erase_size; 2058c2ecf20Sopenharmony_ci unsigned int block_size; 2068c2ecf20Sopenharmony_ci}; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline bool falcon_spi_present(const struct falcon_spi_device *spi) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci return spi->size != 0; 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cienum { 2148c2ecf20Sopenharmony_ci FALCON_STAT_tx_bytes = GENERIC_STAT_COUNT, 2158c2ecf20Sopenharmony_ci FALCON_STAT_tx_packets, 2168c2ecf20Sopenharmony_ci FALCON_STAT_tx_pause, 2178c2ecf20Sopenharmony_ci FALCON_STAT_tx_control, 2188c2ecf20Sopenharmony_ci FALCON_STAT_tx_unicast, 2198c2ecf20Sopenharmony_ci FALCON_STAT_tx_multicast, 2208c2ecf20Sopenharmony_ci FALCON_STAT_tx_broadcast, 2218c2ecf20Sopenharmony_ci FALCON_STAT_tx_lt64, 2228c2ecf20Sopenharmony_ci FALCON_STAT_tx_64, 2238c2ecf20Sopenharmony_ci FALCON_STAT_tx_65_to_127, 2248c2ecf20Sopenharmony_ci FALCON_STAT_tx_128_to_255, 2258c2ecf20Sopenharmony_ci FALCON_STAT_tx_256_to_511, 2268c2ecf20Sopenharmony_ci FALCON_STAT_tx_512_to_1023, 2278c2ecf20Sopenharmony_ci FALCON_STAT_tx_1024_to_15xx, 2288c2ecf20Sopenharmony_ci FALCON_STAT_tx_15xx_to_jumbo, 2298c2ecf20Sopenharmony_ci FALCON_STAT_tx_gtjumbo, 2308c2ecf20Sopenharmony_ci FALCON_STAT_tx_non_tcpudp, 2318c2ecf20Sopenharmony_ci FALCON_STAT_tx_mac_src_error, 2328c2ecf20Sopenharmony_ci FALCON_STAT_tx_ip_src_error, 2338c2ecf20Sopenharmony_ci FALCON_STAT_rx_bytes, 2348c2ecf20Sopenharmony_ci FALCON_STAT_rx_good_bytes, 2358c2ecf20Sopenharmony_ci FALCON_STAT_rx_bad_bytes, 2368c2ecf20Sopenharmony_ci FALCON_STAT_rx_packets, 2378c2ecf20Sopenharmony_ci FALCON_STAT_rx_good, 2388c2ecf20Sopenharmony_ci FALCON_STAT_rx_bad, 2398c2ecf20Sopenharmony_ci FALCON_STAT_rx_pause, 2408c2ecf20Sopenharmony_ci FALCON_STAT_rx_control, 2418c2ecf20Sopenharmony_ci FALCON_STAT_rx_unicast, 2428c2ecf20Sopenharmony_ci FALCON_STAT_rx_multicast, 2438c2ecf20Sopenharmony_ci FALCON_STAT_rx_broadcast, 2448c2ecf20Sopenharmony_ci FALCON_STAT_rx_lt64, 2458c2ecf20Sopenharmony_ci FALCON_STAT_rx_64, 2468c2ecf20Sopenharmony_ci FALCON_STAT_rx_65_to_127, 2478c2ecf20Sopenharmony_ci FALCON_STAT_rx_128_to_255, 2488c2ecf20Sopenharmony_ci FALCON_STAT_rx_256_to_511, 2498c2ecf20Sopenharmony_ci FALCON_STAT_rx_512_to_1023, 2508c2ecf20Sopenharmony_ci FALCON_STAT_rx_1024_to_15xx, 2518c2ecf20Sopenharmony_ci FALCON_STAT_rx_15xx_to_jumbo, 2528c2ecf20Sopenharmony_ci FALCON_STAT_rx_gtjumbo, 2538c2ecf20Sopenharmony_ci FALCON_STAT_rx_bad_lt64, 2548c2ecf20Sopenharmony_ci FALCON_STAT_rx_bad_gtjumbo, 2558c2ecf20Sopenharmony_ci FALCON_STAT_rx_overflow, 2568c2ecf20Sopenharmony_ci FALCON_STAT_rx_symbol_error, 2578c2ecf20Sopenharmony_ci FALCON_STAT_rx_align_error, 2588c2ecf20Sopenharmony_ci FALCON_STAT_rx_length_error, 2598c2ecf20Sopenharmony_ci FALCON_STAT_rx_internal_error, 2608c2ecf20Sopenharmony_ci FALCON_STAT_rx_nodesc_drop_cnt, 2618c2ecf20Sopenharmony_ci FALCON_STAT_COUNT 2628c2ecf20Sopenharmony_ci}; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/** 2658c2ecf20Sopenharmony_ci * struct falcon_nic_data - Falcon NIC state 2668c2ecf20Sopenharmony_ci * @pci_dev2: Secondary function of Falcon A 2678c2ecf20Sopenharmony_ci * @efx: ef4_nic pointer 2688c2ecf20Sopenharmony_ci * @board: Board state and functions 2698c2ecf20Sopenharmony_ci * @stats: Hardware statistics 2708c2ecf20Sopenharmony_ci * @stats_disable_count: Nest count for disabling statistics fetches 2718c2ecf20Sopenharmony_ci * @stats_pending: Is there a pending DMA of MAC statistics. 2728c2ecf20Sopenharmony_ci * @stats_timer: A timer for regularly fetching MAC statistics. 2738c2ecf20Sopenharmony_ci * @spi_flash: SPI flash device 2748c2ecf20Sopenharmony_ci * @spi_eeprom: SPI EEPROM device 2758c2ecf20Sopenharmony_ci * @spi_lock: SPI bus lock 2768c2ecf20Sopenharmony_ci * @mdio_lock: MDIO bus lock 2778c2ecf20Sopenharmony_ci * @xmac_poll_required: XMAC link state needs polling 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_cistruct falcon_nic_data { 2808c2ecf20Sopenharmony_ci struct pci_dev *pci_dev2; 2818c2ecf20Sopenharmony_ci struct ef4_nic *efx; 2828c2ecf20Sopenharmony_ci struct falcon_board board; 2838c2ecf20Sopenharmony_ci u64 stats[FALCON_STAT_COUNT]; 2848c2ecf20Sopenharmony_ci unsigned int stats_disable_count; 2858c2ecf20Sopenharmony_ci bool stats_pending; 2868c2ecf20Sopenharmony_ci struct timer_list stats_timer; 2878c2ecf20Sopenharmony_ci struct falcon_spi_device spi_flash; 2888c2ecf20Sopenharmony_ci struct falcon_spi_device spi_eeprom; 2898c2ecf20Sopenharmony_ci struct mutex spi_lock; 2908c2ecf20Sopenharmony_ci struct mutex mdio_lock; 2918c2ecf20Sopenharmony_ci bool xmac_poll_required; 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic inline struct falcon_board *falcon_board(struct ef4_nic *efx) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct falcon_nic_data *data = efx->nic_data; 2978c2ecf20Sopenharmony_ci return &data->board; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistruct ethtool_ts_info; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ciextern const struct ef4_nic_type falcon_a1_nic_type; 3038c2ecf20Sopenharmony_ciextern const struct ef4_nic_type falcon_b0_nic_type; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci/************************************************************************** 3068c2ecf20Sopenharmony_ci * 3078c2ecf20Sopenharmony_ci * Externs 3088c2ecf20Sopenharmony_ci * 3098c2ecf20Sopenharmony_ci ************************************************************************** 3108c2ecf20Sopenharmony_ci */ 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ciint falcon_probe_board(struct ef4_nic *efx, u16 revision_info); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/* TX data path */ 3158c2ecf20Sopenharmony_cistatic inline int ef4_nic_probe_tx(struct ef4_tx_queue *tx_queue) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci return tx_queue->efx->type->tx_probe(tx_queue); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_cistatic inline void ef4_nic_init_tx(struct ef4_tx_queue *tx_queue) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci tx_queue->efx->type->tx_init(tx_queue); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_cistatic inline void ef4_nic_remove_tx(struct ef4_tx_queue *tx_queue) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci tx_queue->efx->type->tx_remove(tx_queue); 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_cistatic inline void ef4_nic_push_buffers(struct ef4_tx_queue *tx_queue) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci tx_queue->efx->type->tx_write(tx_queue); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci/* RX data path */ 3338c2ecf20Sopenharmony_cistatic inline int ef4_nic_probe_rx(struct ef4_rx_queue *rx_queue) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci return rx_queue->efx->type->rx_probe(rx_queue); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_cistatic inline void ef4_nic_init_rx(struct ef4_rx_queue *rx_queue) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci rx_queue->efx->type->rx_init(rx_queue); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_cistatic inline void ef4_nic_remove_rx(struct ef4_rx_queue *rx_queue) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci rx_queue->efx->type->rx_remove(rx_queue); 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_cistatic inline void ef4_nic_notify_rx_desc(struct ef4_rx_queue *rx_queue) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci rx_queue->efx->type->rx_write(rx_queue); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_cistatic inline void ef4_nic_generate_fill_event(struct ef4_rx_queue *rx_queue) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci rx_queue->efx->type->rx_defer_refill(rx_queue); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci/* Event data path */ 3558c2ecf20Sopenharmony_cistatic inline int ef4_nic_probe_eventq(struct ef4_channel *channel) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci return channel->efx->type->ev_probe(channel); 3588c2ecf20Sopenharmony_ci} 3598c2ecf20Sopenharmony_cistatic inline int ef4_nic_init_eventq(struct ef4_channel *channel) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci return channel->efx->type->ev_init(channel); 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_cistatic inline void ef4_nic_fini_eventq(struct ef4_channel *channel) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci channel->efx->type->ev_fini(channel); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_cistatic inline void ef4_nic_remove_eventq(struct ef4_channel *channel) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci channel->efx->type->ev_remove(channel); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_cistatic inline int 3728c2ecf20Sopenharmony_cief4_nic_process_eventq(struct ef4_channel *channel, int quota) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci return channel->efx->type->ev_process(channel, quota); 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_cistatic inline void ef4_nic_eventq_read_ack(struct ef4_channel *channel) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci channel->efx->type->ev_read_ack(channel); 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_civoid ef4_nic_event_test_start(struct ef4_channel *channel); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/* queue operations */ 3838c2ecf20Sopenharmony_ciint ef4_farch_tx_probe(struct ef4_tx_queue *tx_queue); 3848c2ecf20Sopenharmony_civoid ef4_farch_tx_init(struct ef4_tx_queue *tx_queue); 3858c2ecf20Sopenharmony_civoid ef4_farch_tx_fini(struct ef4_tx_queue *tx_queue); 3868c2ecf20Sopenharmony_civoid ef4_farch_tx_remove(struct ef4_tx_queue *tx_queue); 3878c2ecf20Sopenharmony_civoid ef4_farch_tx_write(struct ef4_tx_queue *tx_queue); 3888c2ecf20Sopenharmony_ciunsigned int ef4_farch_tx_limit_len(struct ef4_tx_queue *tx_queue, 3898c2ecf20Sopenharmony_ci dma_addr_t dma_addr, unsigned int len); 3908c2ecf20Sopenharmony_ciint ef4_farch_rx_probe(struct ef4_rx_queue *rx_queue); 3918c2ecf20Sopenharmony_civoid ef4_farch_rx_init(struct ef4_rx_queue *rx_queue); 3928c2ecf20Sopenharmony_civoid ef4_farch_rx_fini(struct ef4_rx_queue *rx_queue); 3938c2ecf20Sopenharmony_civoid ef4_farch_rx_remove(struct ef4_rx_queue *rx_queue); 3948c2ecf20Sopenharmony_civoid ef4_farch_rx_write(struct ef4_rx_queue *rx_queue); 3958c2ecf20Sopenharmony_civoid ef4_farch_rx_defer_refill(struct ef4_rx_queue *rx_queue); 3968c2ecf20Sopenharmony_ciint ef4_farch_ev_probe(struct ef4_channel *channel); 3978c2ecf20Sopenharmony_ciint ef4_farch_ev_init(struct ef4_channel *channel); 3988c2ecf20Sopenharmony_civoid ef4_farch_ev_fini(struct ef4_channel *channel); 3998c2ecf20Sopenharmony_civoid ef4_farch_ev_remove(struct ef4_channel *channel); 4008c2ecf20Sopenharmony_ciint ef4_farch_ev_process(struct ef4_channel *channel, int quota); 4018c2ecf20Sopenharmony_civoid ef4_farch_ev_read_ack(struct ef4_channel *channel); 4028c2ecf20Sopenharmony_civoid ef4_farch_ev_test_generate(struct ef4_channel *channel); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci/* filter operations */ 4058c2ecf20Sopenharmony_ciint ef4_farch_filter_table_probe(struct ef4_nic *efx); 4068c2ecf20Sopenharmony_civoid ef4_farch_filter_table_restore(struct ef4_nic *efx); 4078c2ecf20Sopenharmony_civoid ef4_farch_filter_table_remove(struct ef4_nic *efx); 4088c2ecf20Sopenharmony_civoid ef4_farch_filter_update_rx_scatter(struct ef4_nic *efx); 4098c2ecf20Sopenharmony_cis32 ef4_farch_filter_insert(struct ef4_nic *efx, struct ef4_filter_spec *spec, 4108c2ecf20Sopenharmony_ci bool replace); 4118c2ecf20Sopenharmony_ciint ef4_farch_filter_remove_safe(struct ef4_nic *efx, 4128c2ecf20Sopenharmony_ci enum ef4_filter_priority priority, 4138c2ecf20Sopenharmony_ci u32 filter_id); 4148c2ecf20Sopenharmony_ciint ef4_farch_filter_get_safe(struct ef4_nic *efx, 4158c2ecf20Sopenharmony_ci enum ef4_filter_priority priority, u32 filter_id, 4168c2ecf20Sopenharmony_ci struct ef4_filter_spec *); 4178c2ecf20Sopenharmony_ciint ef4_farch_filter_clear_rx(struct ef4_nic *efx, 4188c2ecf20Sopenharmony_ci enum ef4_filter_priority priority); 4198c2ecf20Sopenharmony_ciu32 ef4_farch_filter_count_rx_used(struct ef4_nic *efx, 4208c2ecf20Sopenharmony_ci enum ef4_filter_priority priority); 4218c2ecf20Sopenharmony_ciu32 ef4_farch_filter_get_rx_id_limit(struct ef4_nic *efx); 4228c2ecf20Sopenharmony_cis32 ef4_farch_filter_get_rx_ids(struct ef4_nic *efx, 4238c2ecf20Sopenharmony_ci enum ef4_filter_priority priority, u32 *buf, 4248c2ecf20Sopenharmony_ci u32 size); 4258c2ecf20Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL 4268c2ecf20Sopenharmony_cis32 ef4_farch_filter_rfs_insert(struct ef4_nic *efx, 4278c2ecf20Sopenharmony_ci struct ef4_filter_spec *spec); 4288c2ecf20Sopenharmony_cibool ef4_farch_filter_rfs_expire_one(struct ef4_nic *efx, u32 flow_id, 4298c2ecf20Sopenharmony_ci unsigned int index); 4308c2ecf20Sopenharmony_ci#endif 4318c2ecf20Sopenharmony_civoid ef4_farch_filter_sync_rx_mode(struct ef4_nic *efx); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_cibool ef4_nic_event_present(struct ef4_channel *channel); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/* Some statistics are computed as A - B where A and B each increase 4368c2ecf20Sopenharmony_ci * linearly with some hardware counter(s) and the counters are read 4378c2ecf20Sopenharmony_ci * asynchronously. If the counters contributing to B are always read 4388c2ecf20Sopenharmony_ci * after those contributing to A, the computed value may be lower than 4398c2ecf20Sopenharmony_ci * the true value by some variable amount, and may decrease between 4408c2ecf20Sopenharmony_ci * subsequent computations. 4418c2ecf20Sopenharmony_ci * 4428c2ecf20Sopenharmony_ci * We should never allow statistics to decrease or to exceed the true 4438c2ecf20Sopenharmony_ci * value. Since the computed value will never be greater than the 4448c2ecf20Sopenharmony_ci * true value, we can achieve this by only storing the computed value 4458c2ecf20Sopenharmony_ci * when it increases. 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_cistatic inline void ef4_update_diff_stat(u64 *stat, u64 diff) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci if ((s64)(diff - *stat) > 0) 4508c2ecf20Sopenharmony_ci *stat = diff; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci/* Interrupts */ 4548c2ecf20Sopenharmony_ciint ef4_nic_init_interrupt(struct ef4_nic *efx); 4558c2ecf20Sopenharmony_ciint ef4_nic_irq_test_start(struct ef4_nic *efx); 4568c2ecf20Sopenharmony_civoid ef4_nic_fini_interrupt(struct ef4_nic *efx); 4578c2ecf20Sopenharmony_civoid ef4_farch_irq_enable_master(struct ef4_nic *efx); 4588c2ecf20Sopenharmony_ciint ef4_farch_irq_test_generate(struct ef4_nic *efx); 4598c2ecf20Sopenharmony_civoid ef4_farch_irq_disable_master(struct ef4_nic *efx); 4608c2ecf20Sopenharmony_ciirqreturn_t ef4_farch_msi_interrupt(int irq, void *dev_id); 4618c2ecf20Sopenharmony_ciirqreturn_t ef4_farch_legacy_interrupt(int irq, void *dev_id); 4628c2ecf20Sopenharmony_ciirqreturn_t ef4_farch_fatal_interrupt(struct ef4_nic *efx); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic inline int ef4_nic_event_test_irq_cpu(struct ef4_channel *channel) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci return READ_ONCE(channel->event_test_cpu); 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_cistatic inline int ef4_nic_irq_test_irq_cpu(struct ef4_nic *efx) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci return READ_ONCE(efx->last_irq_cpu); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/* Global Resources */ 4748c2ecf20Sopenharmony_ciint ef4_nic_flush_queues(struct ef4_nic *efx); 4758c2ecf20Sopenharmony_ciint ef4_farch_fini_dmaq(struct ef4_nic *efx); 4768c2ecf20Sopenharmony_civoid ef4_farch_finish_flr(struct ef4_nic *efx); 4778c2ecf20Sopenharmony_civoid falcon_start_nic_stats(struct ef4_nic *efx); 4788c2ecf20Sopenharmony_civoid falcon_stop_nic_stats(struct ef4_nic *efx); 4798c2ecf20Sopenharmony_ciint falcon_reset_xaui(struct ef4_nic *efx); 4808c2ecf20Sopenharmony_civoid ef4_farch_dimension_resources(struct ef4_nic *efx, unsigned sram_lim_qw); 4818c2ecf20Sopenharmony_civoid ef4_farch_init_common(struct ef4_nic *efx); 4828c2ecf20Sopenharmony_civoid ef4_farch_rx_push_indir_table(struct ef4_nic *efx); 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ciint ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer, 4858c2ecf20Sopenharmony_ci unsigned int len, gfp_t gfp_flags); 4868c2ecf20Sopenharmony_civoid ef4_nic_free_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci/* Tests */ 4898c2ecf20Sopenharmony_cistruct ef4_farch_register_test { 4908c2ecf20Sopenharmony_ci unsigned address; 4918c2ecf20Sopenharmony_ci ef4_oword_t mask; 4928c2ecf20Sopenharmony_ci}; 4938c2ecf20Sopenharmony_ciint ef4_farch_test_registers(struct ef4_nic *efx, 4948c2ecf20Sopenharmony_ci const struct ef4_farch_register_test *regs, 4958c2ecf20Sopenharmony_ci size_t n_regs); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_cisize_t ef4_nic_get_regs_len(struct ef4_nic *efx); 4988c2ecf20Sopenharmony_civoid ef4_nic_get_regs(struct ef4_nic *efx, void *buf); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_cisize_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count, 5018c2ecf20Sopenharmony_ci const unsigned long *mask, u8 *names); 5028c2ecf20Sopenharmony_civoid ef4_nic_update_stats(const struct ef4_hw_stat_desc *desc, size_t count, 5038c2ecf20Sopenharmony_ci const unsigned long *mask, u64 *stats, 5048c2ecf20Sopenharmony_ci const void *dma_buf, bool accumulate); 5058c2ecf20Sopenharmony_civoid ef4_nic_fix_nodesc_drop_stat(struct ef4_nic *efx, u64 *stat); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci#define EF4_MAX_FLUSH_TIME 5000 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_civoid ef4_farch_generate_event(struct ef4_nic *efx, unsigned int evq, 5108c2ecf20Sopenharmony_ci ef4_qword_t *event); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci#endif /* EF4_NIC_H */ 513