1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /* Atlantic Network Driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2014-2019 aQuantia Corporation
5*4882a593Smuzhiyun * Copyright (C) 2019-2020 Marvell International Ltd.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun /* File aq_ring.h: Declaration of functions for Rx/Tx rings. */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #ifndef AQ_RING_H
11*4882a593Smuzhiyun #define AQ_RING_H
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include "aq_common.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun struct page;
16*4882a593Smuzhiyun struct aq_nic_cfg_s;
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun struct aq_rxpage {
19*4882a593Smuzhiyun struct page *page;
20*4882a593Smuzhiyun dma_addr_t daddr;
21*4882a593Smuzhiyun unsigned int order;
22*4882a593Smuzhiyun unsigned int pg_off;
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun /* TxC SOP DX EOP
26*4882a593Smuzhiyun * +----------+----------+----------+-----------
27*4882a593Smuzhiyun * 8bytes|len l3,l4 | pa | pa | pa
28*4882a593Smuzhiyun * +----------+----------+----------+-----------
29*4882a593Smuzhiyun * 4/8bytes|len pkt |len pkt | | skb
30*4882a593Smuzhiyun * +----------+----------+----------+-----------
31*4882a593Smuzhiyun * 4/8bytes|is_gso |len,flags |len |len,is_eop
32*4882a593Smuzhiyun * +----------+----------+----------+-----------
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * This aq_ring_buff_s doesn't have endianness dependency.
35*4882a593Smuzhiyun * It is __packed for cache line optimizations.
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun struct __packed aq_ring_buff_s {
38*4882a593Smuzhiyun union {
39*4882a593Smuzhiyun /* RX/TX */
40*4882a593Smuzhiyun dma_addr_t pa;
41*4882a593Smuzhiyun /* RX */
42*4882a593Smuzhiyun struct {
43*4882a593Smuzhiyun u32 rss_hash;
44*4882a593Smuzhiyun u16 next;
45*4882a593Smuzhiyun u8 is_hash_l4;
46*4882a593Smuzhiyun u8 rsvd1;
47*4882a593Smuzhiyun struct aq_rxpage rxdata;
48*4882a593Smuzhiyun u16 vlan_rx_tag;
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun /* EOP */
51*4882a593Smuzhiyun struct {
52*4882a593Smuzhiyun dma_addr_t pa_eop;
53*4882a593Smuzhiyun struct sk_buff *skb;
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun /* TxC */
56*4882a593Smuzhiyun struct {
57*4882a593Smuzhiyun u32 mss;
58*4882a593Smuzhiyun u8 len_l2;
59*4882a593Smuzhiyun u8 len_l3;
60*4882a593Smuzhiyun u8 len_l4;
61*4882a593Smuzhiyun u8 is_ipv6:1;
62*4882a593Smuzhiyun u8 rsvd2:7;
63*4882a593Smuzhiyun u32 len_pkt;
64*4882a593Smuzhiyun u16 vlan_tx_tag;
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun union {
68*4882a593Smuzhiyun struct {
69*4882a593Smuzhiyun u32 len:16;
70*4882a593Smuzhiyun u32 is_ip_cso:1;
71*4882a593Smuzhiyun u32 is_udp_cso:1;
72*4882a593Smuzhiyun u32 is_tcp_cso:1;
73*4882a593Smuzhiyun u32 is_cso_err:1;
74*4882a593Smuzhiyun u32 is_sop:1;
75*4882a593Smuzhiyun u32 is_eop:1;
76*4882a593Smuzhiyun u32 is_gso_tcp:1;
77*4882a593Smuzhiyun u32 is_gso_udp:1;
78*4882a593Smuzhiyun u32 is_mapped:1;
79*4882a593Smuzhiyun u32 is_cleaned:1;
80*4882a593Smuzhiyun u32 is_error:1;
81*4882a593Smuzhiyun u32 is_vlan:1;
82*4882a593Smuzhiyun u32 is_lro:1;
83*4882a593Smuzhiyun u32 rsvd3:3;
84*4882a593Smuzhiyun u16 eop_index;
85*4882a593Smuzhiyun u16 rsvd4;
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun u64 flags;
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun struct aq_ring_stats_rx_s {
92*4882a593Smuzhiyun struct u64_stats_sync syncp; /* must be first */
93*4882a593Smuzhiyun u64 errors;
94*4882a593Smuzhiyun u64 packets;
95*4882a593Smuzhiyun u64 bytes;
96*4882a593Smuzhiyun u64 lro_packets;
97*4882a593Smuzhiyun u64 jumbo_packets;
98*4882a593Smuzhiyun u64 alloc_fails;
99*4882a593Smuzhiyun u64 skb_alloc_fails;
100*4882a593Smuzhiyun u64 polls;
101*4882a593Smuzhiyun u64 pg_losts;
102*4882a593Smuzhiyun u64 pg_flips;
103*4882a593Smuzhiyun u64 pg_reuses;
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun struct aq_ring_stats_tx_s {
107*4882a593Smuzhiyun struct u64_stats_sync syncp; /* must be first */
108*4882a593Smuzhiyun u64 errors;
109*4882a593Smuzhiyun u64 packets;
110*4882a593Smuzhiyun u64 bytes;
111*4882a593Smuzhiyun u64 queue_restarts;
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun union aq_ring_stats_s {
115*4882a593Smuzhiyun struct aq_ring_stats_rx_s rx;
116*4882a593Smuzhiyun struct aq_ring_stats_tx_s tx;
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun enum atl_ring_type {
120*4882a593Smuzhiyun ATL_RING_TX,
121*4882a593Smuzhiyun ATL_RING_RX,
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun struct aq_ring_s {
125*4882a593Smuzhiyun struct aq_ring_buff_s *buff_ring;
126*4882a593Smuzhiyun u8 *dx_ring; /* descriptors ring, dma shared mem */
127*4882a593Smuzhiyun struct aq_nic_s *aq_nic;
128*4882a593Smuzhiyun unsigned int idx; /* for HW layer registers operations */
129*4882a593Smuzhiyun unsigned int hw_head;
130*4882a593Smuzhiyun unsigned int sw_head;
131*4882a593Smuzhiyun unsigned int sw_tail;
132*4882a593Smuzhiyun unsigned int size; /* descriptors number */
133*4882a593Smuzhiyun unsigned int dx_size; /* TX or RX descriptor size, */
134*4882a593Smuzhiyun /* stored here for fater math */
135*4882a593Smuzhiyun unsigned int page_order;
136*4882a593Smuzhiyun union aq_ring_stats_s stats;
137*4882a593Smuzhiyun dma_addr_t dx_ring_pa;
138*4882a593Smuzhiyun enum atl_ring_type ring_type;
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun struct aq_ring_param_s {
142*4882a593Smuzhiyun unsigned int vec_idx;
143*4882a593Smuzhiyun unsigned int cpu;
144*4882a593Smuzhiyun cpumask_t affinity_mask;
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun
aq_buf_vaddr(struct aq_rxpage * rxpage)147*4882a593Smuzhiyun static inline void *aq_buf_vaddr(struct aq_rxpage *rxpage)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun return page_to_virt(rxpage->page) + rxpage->pg_off;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
aq_buf_daddr(struct aq_rxpage * rxpage)152*4882a593Smuzhiyun static inline dma_addr_t aq_buf_daddr(struct aq_rxpage *rxpage)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun return rxpage->daddr + rxpage->pg_off;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
aq_ring_next_dx(struct aq_ring_s * self,unsigned int dx)157*4882a593Smuzhiyun static inline unsigned int aq_ring_next_dx(struct aq_ring_s *self,
158*4882a593Smuzhiyun unsigned int dx)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun return (++dx >= self->size) ? 0U : dx;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
aq_ring_avail_dx(struct aq_ring_s * self)163*4882a593Smuzhiyun static inline unsigned int aq_ring_avail_dx(struct aq_ring_s *self)
164*4882a593Smuzhiyun {
165*4882a593Smuzhiyun return (((self->sw_tail >= self->sw_head)) ?
166*4882a593Smuzhiyun (self->size - 1) - self->sw_tail + self->sw_head :
167*4882a593Smuzhiyun self->sw_head - self->sw_tail - 1);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self,
171*4882a593Smuzhiyun struct aq_nic_s *aq_nic,
172*4882a593Smuzhiyun unsigned int idx,
173*4882a593Smuzhiyun struct aq_nic_cfg_s *aq_nic_cfg);
174*4882a593Smuzhiyun struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
175*4882a593Smuzhiyun struct aq_nic_s *aq_nic,
176*4882a593Smuzhiyun unsigned int idx,
177*4882a593Smuzhiyun struct aq_nic_cfg_s *aq_nic_cfg);
178*4882a593Smuzhiyun int aq_ring_init(struct aq_ring_s *self, const enum atl_ring_type ring_type);
179*4882a593Smuzhiyun void aq_ring_rx_deinit(struct aq_ring_s *self);
180*4882a593Smuzhiyun void aq_ring_free(struct aq_ring_s *self);
181*4882a593Smuzhiyun void aq_ring_update_queue_state(struct aq_ring_s *ring);
182*4882a593Smuzhiyun void aq_ring_queue_wake(struct aq_ring_s *ring);
183*4882a593Smuzhiyun void aq_ring_queue_stop(struct aq_ring_s *ring);
184*4882a593Smuzhiyun bool aq_ring_tx_clean(struct aq_ring_s *self);
185*4882a593Smuzhiyun int aq_ring_rx_clean(struct aq_ring_s *self,
186*4882a593Smuzhiyun struct napi_struct *napi,
187*4882a593Smuzhiyun int *work_done,
188*4882a593Smuzhiyun int budget);
189*4882a593Smuzhiyun int aq_ring_rx_fill(struct aq_ring_s *self);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self,
192*4882a593Smuzhiyun struct aq_nic_s *aq_nic, unsigned int idx,
193*4882a593Smuzhiyun unsigned int size, unsigned int dx_size);
194*4882a593Smuzhiyun void aq_ring_hwts_rx_clean(struct aq_ring_s *self, struct aq_nic_s *aq_nic);
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data);
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun #endif /* AQ_RING_H */
199