18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* Atlantic Network Driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2014-2019 aQuantia Corporation 58c2ecf20Sopenharmony_ci * Copyright (C) 2019-2020 Marvell International Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* File aq_ring.h: Declaration of functions for Rx/Tx rings. */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef AQ_RING_H 118c2ecf20Sopenharmony_ci#define AQ_RING_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "aq_common.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistruct page; 168c2ecf20Sopenharmony_cistruct aq_nic_cfg_s; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct aq_rxpage { 198c2ecf20Sopenharmony_ci struct page *page; 208c2ecf20Sopenharmony_ci dma_addr_t daddr; 218c2ecf20Sopenharmony_ci unsigned int order; 228c2ecf20Sopenharmony_ci unsigned int pg_off; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* TxC SOP DX EOP 268c2ecf20Sopenharmony_ci * +----------+----------+----------+----------- 278c2ecf20Sopenharmony_ci * 8bytes|len l3,l4 | pa | pa | pa 288c2ecf20Sopenharmony_ci * +----------+----------+----------+----------- 298c2ecf20Sopenharmony_ci * 4/8bytes|len pkt |len pkt | | skb 308c2ecf20Sopenharmony_ci * +----------+----------+----------+----------- 318c2ecf20Sopenharmony_ci * 4/8bytes|is_gso |len,flags |len |len,is_eop 328c2ecf20Sopenharmony_ci * +----------+----------+----------+----------- 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * This aq_ring_buff_s doesn't have endianness dependency. 358c2ecf20Sopenharmony_ci * It is __packed for cache line optimizations. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_cistruct __packed aq_ring_buff_s { 388c2ecf20Sopenharmony_ci union { 398c2ecf20Sopenharmony_ci /* RX/TX */ 408c2ecf20Sopenharmony_ci dma_addr_t pa; 418c2ecf20Sopenharmony_ci /* RX */ 428c2ecf20Sopenharmony_ci struct { 438c2ecf20Sopenharmony_ci u32 rss_hash; 448c2ecf20Sopenharmony_ci u16 next; 458c2ecf20Sopenharmony_ci u8 is_hash_l4; 468c2ecf20Sopenharmony_ci u8 rsvd1; 478c2ecf20Sopenharmony_ci struct aq_rxpage rxdata; 488c2ecf20Sopenharmony_ci u16 vlan_rx_tag; 498c2ecf20Sopenharmony_ci }; 508c2ecf20Sopenharmony_ci /* EOP */ 518c2ecf20Sopenharmony_ci struct { 528c2ecf20Sopenharmony_ci dma_addr_t pa_eop; 538c2ecf20Sopenharmony_ci struct sk_buff *skb; 548c2ecf20Sopenharmony_ci }; 558c2ecf20Sopenharmony_ci /* TxC */ 568c2ecf20Sopenharmony_ci struct { 578c2ecf20Sopenharmony_ci u32 mss; 588c2ecf20Sopenharmony_ci u8 len_l2; 598c2ecf20Sopenharmony_ci u8 len_l3; 608c2ecf20Sopenharmony_ci u8 len_l4; 618c2ecf20Sopenharmony_ci u8 is_ipv6:1; 628c2ecf20Sopenharmony_ci u8 rsvd2:7; 638c2ecf20Sopenharmony_ci u32 len_pkt; 648c2ecf20Sopenharmony_ci u16 vlan_tx_tag; 658c2ecf20Sopenharmony_ci }; 668c2ecf20Sopenharmony_ci }; 678c2ecf20Sopenharmony_ci union { 688c2ecf20Sopenharmony_ci struct { 698c2ecf20Sopenharmony_ci u32 len:16; 708c2ecf20Sopenharmony_ci u32 is_ip_cso:1; 718c2ecf20Sopenharmony_ci u32 is_udp_cso:1; 728c2ecf20Sopenharmony_ci u32 is_tcp_cso:1; 738c2ecf20Sopenharmony_ci u32 is_cso_err:1; 748c2ecf20Sopenharmony_ci u32 is_sop:1; 758c2ecf20Sopenharmony_ci u32 is_eop:1; 768c2ecf20Sopenharmony_ci u32 is_gso_tcp:1; 778c2ecf20Sopenharmony_ci u32 is_gso_udp:1; 788c2ecf20Sopenharmony_ci u32 is_mapped:1; 798c2ecf20Sopenharmony_ci u32 is_cleaned:1; 808c2ecf20Sopenharmony_ci u32 is_error:1; 818c2ecf20Sopenharmony_ci u32 is_vlan:1; 828c2ecf20Sopenharmony_ci u32 is_lro:1; 838c2ecf20Sopenharmony_ci u32 rsvd3:3; 848c2ecf20Sopenharmony_ci u16 eop_index; 858c2ecf20Sopenharmony_ci u16 rsvd4; 868c2ecf20Sopenharmony_ci }; 878c2ecf20Sopenharmony_ci u64 flags; 888c2ecf20Sopenharmony_ci }; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct aq_ring_stats_rx_s { 928c2ecf20Sopenharmony_ci struct u64_stats_sync syncp; /* must be first */ 938c2ecf20Sopenharmony_ci u64 errors; 948c2ecf20Sopenharmony_ci u64 packets; 958c2ecf20Sopenharmony_ci u64 bytes; 968c2ecf20Sopenharmony_ci u64 lro_packets; 978c2ecf20Sopenharmony_ci u64 jumbo_packets; 988c2ecf20Sopenharmony_ci u64 alloc_fails; 998c2ecf20Sopenharmony_ci u64 skb_alloc_fails; 1008c2ecf20Sopenharmony_ci u64 polls; 1018c2ecf20Sopenharmony_ci u64 pg_losts; 1028c2ecf20Sopenharmony_ci u64 pg_flips; 1038c2ecf20Sopenharmony_ci u64 pg_reuses; 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistruct aq_ring_stats_tx_s { 1078c2ecf20Sopenharmony_ci struct u64_stats_sync syncp; /* must be first */ 1088c2ecf20Sopenharmony_ci u64 errors; 1098c2ecf20Sopenharmony_ci u64 packets; 1108c2ecf20Sopenharmony_ci u64 bytes; 1118c2ecf20Sopenharmony_ci u64 queue_restarts; 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ciunion aq_ring_stats_s { 1158c2ecf20Sopenharmony_ci struct aq_ring_stats_rx_s rx; 1168c2ecf20Sopenharmony_ci struct aq_ring_stats_tx_s tx; 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cienum atl_ring_type { 1208c2ecf20Sopenharmony_ci ATL_RING_TX, 1218c2ecf20Sopenharmony_ci ATL_RING_RX, 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct aq_ring_s { 1258c2ecf20Sopenharmony_ci struct aq_ring_buff_s *buff_ring; 1268c2ecf20Sopenharmony_ci u8 *dx_ring; /* descriptors ring, dma shared mem */ 1278c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic; 1288c2ecf20Sopenharmony_ci unsigned int idx; /* for HW layer registers operations */ 1298c2ecf20Sopenharmony_ci unsigned int hw_head; 1308c2ecf20Sopenharmony_ci unsigned int sw_head; 1318c2ecf20Sopenharmony_ci unsigned int sw_tail; 1328c2ecf20Sopenharmony_ci unsigned int size; /* descriptors number */ 1338c2ecf20Sopenharmony_ci unsigned int dx_size; /* TX or RX descriptor size, */ 1348c2ecf20Sopenharmony_ci /* stored here for fater math */ 1358c2ecf20Sopenharmony_ci unsigned int page_order; 1368c2ecf20Sopenharmony_ci union aq_ring_stats_s stats; 1378c2ecf20Sopenharmony_ci dma_addr_t dx_ring_pa; 1388c2ecf20Sopenharmony_ci enum atl_ring_type ring_type; 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistruct aq_ring_param_s { 1428c2ecf20Sopenharmony_ci unsigned int vec_idx; 1438c2ecf20Sopenharmony_ci unsigned int cpu; 1448c2ecf20Sopenharmony_ci cpumask_t affinity_mask; 1458c2ecf20Sopenharmony_ci}; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic inline void *aq_buf_vaddr(struct aq_rxpage *rxpage) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci return page_to_virt(rxpage->page) + rxpage->pg_off; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic inline dma_addr_t aq_buf_daddr(struct aq_rxpage *rxpage) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci return rxpage->daddr + rxpage->pg_off; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic inline unsigned int aq_ring_next_dx(struct aq_ring_s *self, 1588c2ecf20Sopenharmony_ci unsigned int dx) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci return (++dx >= self->size) ? 0U : dx; 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic inline unsigned int aq_ring_avail_dx(struct aq_ring_s *self) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci return (((self->sw_tail >= self->sw_head)) ? 1668c2ecf20Sopenharmony_ci (self->size - 1) - self->sw_tail + self->sw_head : 1678c2ecf20Sopenharmony_ci self->sw_head - self->sw_tail - 1); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistruct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self, 1718c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic, 1728c2ecf20Sopenharmony_ci unsigned int idx, 1738c2ecf20Sopenharmony_ci struct aq_nic_cfg_s *aq_nic_cfg); 1748c2ecf20Sopenharmony_cistruct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, 1758c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic, 1768c2ecf20Sopenharmony_ci unsigned int idx, 1778c2ecf20Sopenharmony_ci struct aq_nic_cfg_s *aq_nic_cfg); 1788c2ecf20Sopenharmony_ciint aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type); 1798c2ecf20Sopenharmony_civoid aq_ring_rx_deinit(struct aq_ring_s *self); 1808c2ecf20Sopenharmony_civoid aq_ring_free(struct aq_ring_s *self); 1818c2ecf20Sopenharmony_civoid aq_ring_update_queue_state(struct aq_ring_s *ring); 1828c2ecf20Sopenharmony_civoid aq_ring_queue_wake(struct aq_ring_s *ring); 1838c2ecf20Sopenharmony_civoid aq_ring_queue_stop(struct aq_ring_s *ring); 1848c2ecf20Sopenharmony_cibool aq_ring_tx_clean(struct aq_ring_s *self); 1858c2ecf20Sopenharmony_ciint aq_ring_rx_clean(struct aq_ring_s *self, 1868c2ecf20Sopenharmony_ci struct napi_struct *napi, 1878c2ecf20Sopenharmony_ci int *work_done, 1888c2ecf20Sopenharmony_ci int budget); 1898c2ecf20Sopenharmony_ciint aq_ring_rx_fill(struct aq_ring_s *self); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistruct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self, 1928c2ecf20Sopenharmony_ci struct aq_nic_s *aq_nic, unsigned int idx, 1938c2ecf20Sopenharmony_ci unsigned int size, unsigned int dx_size); 1948c2ecf20Sopenharmony_civoid aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ciunsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci#endif /* AQ_RING_H */ 199