1db37bc17SDimitris Michailidis /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2db37bc17SDimitris Michailidis
3db37bc17SDimitris Michailidis #ifndef _FUNETH_TXRX_H
4db37bc17SDimitris Michailidis #define _FUNETH_TXRX_H
5db37bc17SDimitris Michailidis
6db37bc17SDimitris Michailidis #include <linux/netdevice.h>
7db37bc17SDimitris Michailidis #include <linux/u64_stats_sync.h>
8*92272ec4SJakub Kicinski #include <net/xdp.h>
9db37bc17SDimitris Michailidis
10db37bc17SDimitris Michailidis /* Tx descriptor size */
11db37bc17SDimitris Michailidis #define FUNETH_SQE_SIZE 64U
12db37bc17SDimitris Michailidis
13db37bc17SDimitris Michailidis /* Size of device headers per Tx packet */
14db37bc17SDimitris Michailidis #define FUNETH_FUNOS_HDR_SZ (sizeof(struct fun_eth_tx_req))
15db37bc17SDimitris Michailidis
16db37bc17SDimitris Michailidis /* Number of gather list entries per Tx descriptor */
17db37bc17SDimitris Michailidis #define FUNETH_GLE_PER_DESC (FUNETH_SQE_SIZE / sizeof(struct fun_dataop_gl))
18db37bc17SDimitris Michailidis
19db37bc17SDimitris Michailidis /* Max gather list size in bytes for an sk_buff. */
20db37bc17SDimitris Michailidis #define FUNETH_MAX_GL_SZ ((MAX_SKB_FRAGS + 1) * sizeof(struct fun_dataop_gl))
21db37bc17SDimitris Michailidis
22db37bc17SDimitris Michailidis #if IS_ENABLED(CONFIG_TLS_DEVICE)
23db37bc17SDimitris Michailidis # define FUNETH_TLS_SZ sizeof(struct fun_eth_tls)
24db37bc17SDimitris Michailidis #else
25db37bc17SDimitris Michailidis # define FUNETH_TLS_SZ 0
26db37bc17SDimitris Michailidis #endif
27db37bc17SDimitris Michailidis
28db37bc17SDimitris Michailidis /* Max number of Tx descriptors for an sk_buff using a gather list. */
29db37bc17SDimitris Michailidis #define FUNETH_MAX_GL_DESC \
30db37bc17SDimitris Michailidis DIV_ROUND_UP((FUNETH_FUNOS_HDR_SZ + FUNETH_MAX_GL_SZ + FUNETH_TLS_SZ), \
31db37bc17SDimitris Michailidis FUNETH_SQE_SIZE)
32db37bc17SDimitris Michailidis
33db37bc17SDimitris Michailidis /* Max number of Tx descriptors for any packet. */
34db37bc17SDimitris Michailidis #define FUNETH_MAX_PKT_DESC FUNETH_MAX_GL_DESC
35db37bc17SDimitris Michailidis
36db37bc17SDimitris Michailidis /* Rx CQ descriptor size. */
37db37bc17SDimitris Michailidis #define FUNETH_CQE_SIZE 64U
38db37bc17SDimitris Michailidis
39db37bc17SDimitris Michailidis /* Offset of cqe_info within a CQE. */
40db37bc17SDimitris Michailidis #define FUNETH_CQE_INFO_OFFSET (FUNETH_CQE_SIZE - sizeof(struct fun_cqe_info))
41db37bc17SDimitris Michailidis
42db37bc17SDimitris Michailidis /* Construct the IRQ portion of a CQ doorbell. The resulting value arms the
43db37bc17SDimitris Michailidis * interrupt with the supplied time delay and packet count moderation settings.
44db37bc17SDimitris Michailidis */
45db37bc17SDimitris Michailidis #define FUN_IRQ_CQ_DB(usec, pkts) \
46db37bc17SDimitris Michailidis (FUN_DB_IRQ_ARM_F | ((usec) << FUN_DB_INTCOAL_USEC_S) | \
47db37bc17SDimitris Michailidis ((pkts) << FUN_DB_INTCOAL_ENTRIES_S))
48db37bc17SDimitris Michailidis
49db37bc17SDimitris Michailidis /* As above for SQ doorbells. */
50db37bc17SDimitris Michailidis #define FUN_IRQ_SQ_DB(usec, pkts) \
51db37bc17SDimitris Michailidis (FUN_DB_IRQ_ARM_F | \
52db37bc17SDimitris Michailidis ((usec) << FUN_DB_INTCOAL_USEC_S) | \
53db37bc17SDimitris Michailidis ((pkts) << FUN_DB_INTCOAL_ENTRIES_S))
54db37bc17SDimitris Michailidis
55db37bc17SDimitris Michailidis /* Per packet tailroom. Present only for 1-frag packets. */
56db37bc17SDimitris Michailidis #define FUN_RX_TAILROOM SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
57db37bc17SDimitris Michailidis
58db37bc17SDimitris Michailidis /* Per packet headroom for XDP. Preferred over XDP_PACKET_HEADROOM to
59db37bc17SDimitris Michailidis * accommodate two packets per buffer for 4K pages and 1500B MTUs.
60db37bc17SDimitris Michailidis */
61db37bc17SDimitris Michailidis #define FUN_XDP_HEADROOM 192
62db37bc17SDimitris Michailidis
63db37bc17SDimitris Michailidis /* Initialization state of a queue. */
64db37bc17SDimitris Michailidis enum {
65db37bc17SDimitris Michailidis FUN_QSTATE_DESTROYED, /* what queue? */
66db37bc17SDimitris Michailidis FUN_QSTATE_INIT_SW, /* exists in SW, not on the device */
67db37bc17SDimitris Michailidis FUN_QSTATE_INIT_FULL, /* exists both in SW and on device */
68db37bc17SDimitris Michailidis };
69db37bc17SDimitris Michailidis
70db37bc17SDimitris Michailidis /* Initialization state of an interrupt. */
71db37bc17SDimitris Michailidis enum {
72db37bc17SDimitris Michailidis FUN_IRQ_INIT, /* initialized and in the XArray but inactive */
73db37bc17SDimitris Michailidis FUN_IRQ_REQUESTED, /* request_irq() done */
74db37bc17SDimitris Michailidis FUN_IRQ_ENABLED, /* processing enabled */
75db37bc17SDimitris Michailidis FUN_IRQ_DISABLED, /* processing disabled */
76db37bc17SDimitris Michailidis };
77db37bc17SDimitris Michailidis
78db37bc17SDimitris Michailidis struct bpf_prog;
79db37bc17SDimitris Michailidis
80db37bc17SDimitris Michailidis struct funeth_txq_stats { /* per Tx queue SW counters */
81db37bc17SDimitris Michailidis u64 tx_pkts; /* # of Tx packets */
82db37bc17SDimitris Michailidis u64 tx_bytes; /* total bytes of Tx packets */
83db37bc17SDimitris Michailidis u64 tx_cso; /* # of packets with checksum offload */
84db37bc17SDimitris Michailidis u64 tx_tso; /* # of non-encapsulated TSO super-packets */
85db37bc17SDimitris Michailidis u64 tx_encap_tso; /* # of encapsulated TSO super-packets */
866ce1df88SDimitris Michailidis u64 tx_uso; /* # of non-encapsulated UDP LSO super-packets */
87db37bc17SDimitris Michailidis u64 tx_more; /* # of DBs elided due to xmit_more */
88db37bc17SDimitris Michailidis u64 tx_nstops; /* # of times the queue has stopped */
89db37bc17SDimitris Michailidis u64 tx_nrestarts; /* # of times the queue has restarted */
90db37bc17SDimitris Michailidis u64 tx_map_err; /* # of packets dropped due to DMA mapping errors */
91db37bc17SDimitris Michailidis u64 tx_xdp_full; /* # of XDP packets that could not be enqueued */
92db37bc17SDimitris Michailidis u64 tx_tls_pkts; /* # of Tx TLS packets offloaded to HW */
93db37bc17SDimitris Michailidis u64 tx_tls_bytes; /* Tx bytes of HW-handled TLS payload */
94db37bc17SDimitris Michailidis u64 tx_tls_fallback; /* attempted Tx TLS offloads punted to SW */
95db37bc17SDimitris Michailidis u64 tx_tls_drops; /* attempted Tx TLS offloads dropped */
96db37bc17SDimitris Michailidis };
97db37bc17SDimitris Michailidis
98db37bc17SDimitris Michailidis struct funeth_tx_info { /* per Tx descriptor state */
99db37bc17SDimitris Michailidis union {
10051a83391SDimitris Michailidis struct sk_buff *skb; /* associated packet (sk_buff path) */
10151a83391SDimitris Michailidis struct xdp_frame *xdpf; /* associated XDP frame (XDP path) */
102db37bc17SDimitris Michailidis };
103db37bc17SDimitris Michailidis };
104db37bc17SDimitris Michailidis
105db37bc17SDimitris Michailidis struct funeth_txq {
106db37bc17SDimitris Michailidis /* RO cacheline of frequently accessed data */
107db37bc17SDimitris Michailidis u32 mask; /* queue depth - 1 */
108db37bc17SDimitris Michailidis u32 hw_qid; /* device ID of the queue */
109db37bc17SDimitris Michailidis void *desc; /* base address of descriptor ring */
110db37bc17SDimitris Michailidis struct funeth_tx_info *info;
111db37bc17SDimitris Michailidis struct device *dma_dev; /* device for DMA mappings */
112db37bc17SDimitris Michailidis volatile __be64 *hw_wb; /* HW write-back location */
113db37bc17SDimitris Michailidis u32 __iomem *db; /* SQ doorbell register address */
114db37bc17SDimitris Michailidis struct netdev_queue *ndq;
115db37bc17SDimitris Michailidis dma_addr_t dma_addr; /* DMA address of descriptor ring */
116db37bc17SDimitris Michailidis /* producer R/W cacheline */
117db37bc17SDimitris Michailidis u16 qidx; /* queue index within net_device */
118db37bc17SDimitris Michailidis u16 ethid;
119db37bc17SDimitris Michailidis u32 prod_cnt; /* producer counter */
120db37bc17SDimitris Michailidis struct funeth_txq_stats stats;
121db37bc17SDimitris Michailidis /* shared R/W cacheline, primarily accessed by consumer */
122db37bc17SDimitris Michailidis u32 irq_db_val; /* value written to IRQ doorbell */
123db37bc17SDimitris Michailidis u32 cons_cnt; /* consumer (cleanup) counter */
124db37bc17SDimitris Michailidis struct net_device *netdev;
125db37bc17SDimitris Michailidis struct fun_irq *irq;
126db37bc17SDimitris Michailidis int numa_node;
127db37bc17SDimitris Michailidis u8 init_state; /* queue initialization state */
128db37bc17SDimitris Michailidis struct u64_stats_sync syncp;
129db37bc17SDimitris Michailidis };
130db37bc17SDimitris Michailidis
131db37bc17SDimitris Michailidis struct funeth_rxq_stats { /* per Rx queue SW counters */
132db37bc17SDimitris Michailidis u64 rx_pkts; /* # of received packets, including SW drops */
133db37bc17SDimitris Michailidis u64 rx_bytes; /* total size of received packets */
134db37bc17SDimitris Michailidis u64 rx_cso; /* # of packets with checksum offload */
135db37bc17SDimitris Michailidis u64 rx_bufs; /* total # of Rx buffers provided to device */
136db37bc17SDimitris Michailidis u64 gro_pkts; /* # of GRO superpackets */
137db37bc17SDimitris Michailidis u64 gro_merged; /* # of pkts merged into existing GRO superpackets */
138db37bc17SDimitris Michailidis u64 rx_page_alloc; /* # of page allocations for Rx buffers */
139db37bc17SDimitris Michailidis u64 rx_budget; /* NAPI iterations that exhausted their budget */
140db37bc17SDimitris Michailidis u64 rx_mem_drops; /* # of packets dropped due to memory shortage */
141db37bc17SDimitris Michailidis u64 rx_map_err; /* # of page DMA mapping errors */
142db37bc17SDimitris Michailidis u64 xdp_drops; /* XDP_DROPped packets */
143db37bc17SDimitris Michailidis u64 xdp_tx; /* successful XDP transmits */
144db37bc17SDimitris Michailidis u64 xdp_redir; /* successful XDP redirects */
145db37bc17SDimitris Michailidis u64 xdp_err; /* packets dropped due to XDP errors */
146db37bc17SDimitris Michailidis };
147db37bc17SDimitris Michailidis
148db37bc17SDimitris Michailidis struct funeth_rxbuf { /* per Rx buffer state */
149db37bc17SDimitris Michailidis struct page *page; /* associated page */
150db37bc17SDimitris Michailidis dma_addr_t dma_addr; /* DMA address of page start */
151db37bc17SDimitris Michailidis int pg_refs; /* page refs held by driver */
152db37bc17SDimitris Michailidis int node; /* page node, or -1 if it is PF_MEMALLOC */
153db37bc17SDimitris Michailidis };
154db37bc17SDimitris Michailidis
155db37bc17SDimitris Michailidis struct funeth_rx_cache { /* cache of DMA-mapped previously used buffers */
156db37bc17SDimitris Michailidis struct funeth_rxbuf *bufs; /* base of Rx buffer state ring */
157db37bc17SDimitris Michailidis unsigned int prod_cnt; /* producer counter */
158db37bc17SDimitris Michailidis unsigned int cons_cnt; /* consumer counter */
159db37bc17SDimitris Michailidis unsigned int mask; /* depth - 1 */
160db37bc17SDimitris Michailidis };
161db37bc17SDimitris Michailidis
162db37bc17SDimitris Michailidis /* An Rx queue consists of a CQ and an SQ used to provide Rx buffers. */
163db37bc17SDimitris Michailidis struct funeth_rxq {
164db37bc17SDimitris Michailidis struct net_device *netdev;
165db37bc17SDimitris Michailidis struct napi_struct *napi;
166db37bc17SDimitris Michailidis struct device *dma_dev; /* device for DMA mappings */
167db37bc17SDimitris Michailidis void *cqes; /* base of CQ descriptor ring */
168db37bc17SDimitris Michailidis const void *next_cqe_info; /* fun_cqe_info of next CQE */
169db37bc17SDimitris Michailidis u32 __iomem *cq_db; /* CQ doorbell register address */
170db37bc17SDimitris Michailidis unsigned int cq_head; /* CQ head index */
171db37bc17SDimitris Michailidis unsigned int cq_mask; /* CQ depth - 1 */
172db37bc17SDimitris Michailidis u16 phase; /* CQ phase tag */
173db37bc17SDimitris Michailidis u16 qidx; /* queue index within net_device */
174db37bc17SDimitris Michailidis unsigned int irq_db_val; /* IRQ info for CQ doorbell */
175db37bc17SDimitris Michailidis struct fun_eprq_rqbuf *rqes; /* base of RQ descriptor ring */
176db37bc17SDimitris Michailidis struct funeth_rxbuf *bufs; /* base of Rx buffer state ring */
177db37bc17SDimitris Michailidis struct funeth_rxbuf *cur_buf; /* currently active buffer */
178db37bc17SDimitris Michailidis u32 __iomem *rq_db; /* RQ doorbell register address */
179db37bc17SDimitris Michailidis unsigned int rq_cons; /* RQ consumer counter */
180db37bc17SDimitris Michailidis unsigned int rq_mask; /* RQ depth - 1 */
181db37bc17SDimitris Michailidis unsigned int buf_offset; /* offset of next pkt in head buffer */
182db37bc17SDimitris Michailidis u8 xdp_flush; /* XDP flush types needed at NAPI end */
183db37bc17SDimitris Michailidis u8 init_state; /* queue initialization state */
184db37bc17SDimitris Michailidis u16 headroom; /* per packet headroom */
185db37bc17SDimitris Michailidis unsigned int rq_cons_db; /* value of rq_cons at last RQ db */
186db37bc17SDimitris Michailidis unsigned int rq_db_thres; /* # of new buffers needed to write RQ db */
187db37bc17SDimitris Michailidis struct funeth_rxbuf spare_buf; /* spare for next buffer replacement */
188db37bc17SDimitris Michailidis struct funeth_rx_cache cache; /* used buffer cache */
189db37bc17SDimitris Michailidis struct bpf_prog *xdp_prog; /* optional XDP BPF program */
190db37bc17SDimitris Michailidis struct funeth_rxq_stats stats;
191db37bc17SDimitris Michailidis dma_addr_t cq_dma_addr; /* DMA address of CQE ring */
192db37bc17SDimitris Michailidis dma_addr_t rq_dma_addr; /* DMA address of RQE ring */
193db37bc17SDimitris Michailidis u16 irq_cnt;
194db37bc17SDimitris Michailidis u32 hw_cqid; /* device ID of the queue's CQ */
195db37bc17SDimitris Michailidis u32 hw_sqid; /* device ID of the queue's SQ */
196db37bc17SDimitris Michailidis int numa_node;
197db37bc17SDimitris Michailidis struct u64_stats_sync syncp;
198db37bc17SDimitris Michailidis struct xdp_rxq_info xdp_rxq;
199db37bc17SDimitris Michailidis };
200db37bc17SDimitris Michailidis
201db37bc17SDimitris Michailidis #define FUN_QSTAT_INC(q, counter) \
202db37bc17SDimitris Michailidis do { \
203db37bc17SDimitris Michailidis u64_stats_update_begin(&(q)->syncp); \
204db37bc17SDimitris Michailidis (q)->stats.counter++; \
205db37bc17SDimitris Michailidis u64_stats_update_end(&(q)->syncp); \
206db37bc17SDimitris Michailidis } while (0)
207db37bc17SDimitris Michailidis
208db37bc17SDimitris Michailidis #define FUN_QSTAT_READ(q, seq, stats_copy) \
209db37bc17SDimitris Michailidis do { \
210068c38adSThomas Gleixner seq = u64_stats_fetch_begin(&(q)->syncp); \
211db37bc17SDimitris Michailidis stats_copy = (q)->stats; \
212068c38adSThomas Gleixner } while (u64_stats_fetch_retry(&(q)->syncp, (seq)))
213db37bc17SDimitris Michailidis
214db37bc17SDimitris Michailidis #define FUN_INT_NAME_LEN (IFNAMSIZ + 16)
215db37bc17SDimitris Michailidis
216db37bc17SDimitris Michailidis struct fun_irq {
217db37bc17SDimitris Michailidis struct napi_struct napi;
218db37bc17SDimitris Michailidis struct funeth_txq *txq;
219db37bc17SDimitris Michailidis struct funeth_rxq *rxq;
220db37bc17SDimitris Michailidis u8 state;
221db37bc17SDimitris Michailidis u16 irq_idx; /* index of MSI-X interrupt */
222db37bc17SDimitris Michailidis int irq; /* Linux IRQ vector */
223db37bc17SDimitris Michailidis cpumask_t affinity_mask; /* IRQ affinity */
224db37bc17SDimitris Michailidis struct irq_affinity_notify aff_notify;
225db37bc17SDimitris Michailidis char name[FUN_INT_NAME_LEN];
226db37bc17SDimitris Michailidis } ____cacheline_internodealigned_in_smp;
227db37bc17SDimitris Michailidis
228db37bc17SDimitris Michailidis /* Return the start address of the idx-th Tx descriptor. */
fun_tx_desc_addr(const struct funeth_txq * q,unsigned int idx)229db37bc17SDimitris Michailidis static inline void *fun_tx_desc_addr(const struct funeth_txq *q,
230db37bc17SDimitris Michailidis unsigned int idx)
231db37bc17SDimitris Michailidis {
232db37bc17SDimitris Michailidis return q->desc + idx * FUNETH_SQE_SIZE;
233db37bc17SDimitris Michailidis }
234db37bc17SDimitris Michailidis
fun_txq_wr_db(const struct funeth_txq * q)235db37bc17SDimitris Michailidis static inline void fun_txq_wr_db(const struct funeth_txq *q)
236db37bc17SDimitris Michailidis {
237db37bc17SDimitris Michailidis unsigned int tail = q->prod_cnt & q->mask;
238db37bc17SDimitris Michailidis
239db37bc17SDimitris Michailidis writel(tail, q->db);
240db37bc17SDimitris Michailidis }
241db37bc17SDimitris Michailidis
fun_irq_node(const struct fun_irq * p)242db37bc17SDimitris Michailidis static inline int fun_irq_node(const struct fun_irq *p)
243db37bc17SDimitris Michailidis {
244cdba2490SDimitris Michailidis return cpu_to_mem(cpumask_first(&p->affinity_mask));
245db37bc17SDimitris Michailidis }
246db37bc17SDimitris Michailidis
247db37bc17SDimitris Michailidis int fun_rxq_napi_poll(struct napi_struct *napi, int budget);
248db37bc17SDimitris Michailidis int fun_txq_napi_poll(struct napi_struct *napi, int budget);
249db37bc17SDimitris Michailidis netdev_tx_t fun_start_xmit(struct sk_buff *skb, struct net_device *netdev);
25051a83391SDimitris Michailidis bool fun_xdp_tx(struct funeth_txq *q, struct xdp_frame *xdpf);
251db37bc17SDimitris Michailidis int fun_xdp_xmit_frames(struct net_device *dev, int n,
252db37bc17SDimitris Michailidis struct xdp_frame **frames, u32 flags);
253db37bc17SDimitris Michailidis
254db37bc17SDimitris Michailidis int funeth_txq_create(struct net_device *dev, unsigned int qidx,
255db37bc17SDimitris Michailidis unsigned int ndesc, struct fun_irq *irq, int state,
256db37bc17SDimitris Michailidis struct funeth_txq **qp);
257db37bc17SDimitris Michailidis int fun_txq_create_dev(struct funeth_txq *q, struct fun_irq *irq);
258db37bc17SDimitris Michailidis struct funeth_txq *funeth_txq_free(struct funeth_txq *q, int state);
259db37bc17SDimitris Michailidis int funeth_rxq_create(struct net_device *dev, unsigned int qidx,
260db37bc17SDimitris Michailidis unsigned int ncqe, unsigned int nrqe, struct fun_irq *irq,
261db37bc17SDimitris Michailidis int state, struct funeth_rxq **qp);
262db37bc17SDimitris Michailidis int fun_rxq_create_dev(struct funeth_rxq *q, struct fun_irq *irq);
263db37bc17SDimitris Michailidis struct funeth_rxq *funeth_rxq_free(struct funeth_rxq *q, int state);
264db37bc17SDimitris Michailidis int fun_rxq_set_bpf(struct funeth_rxq *q, struct bpf_prog *prog);
265db37bc17SDimitris Michailidis
266db37bc17SDimitris Michailidis #endif /* _FUNETH_TXRX_H */
267