net/funeth: Unify skb/XDP Tx packet unmapping.
[linux-2.6-microblaze.git] / drivers / net / ethernet / fungible / funeth / funeth_tx.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2
3 #include <linux/dma-mapping.h>
4 #include <linux/ip.h>
5 #include <linux/pci.h>
6 #include <linux/skbuff.h>
7 #include <linux/tcp.h>
8 #include <uapi/linux/udp.h>
9 #include "funeth.h"
10 #include "funeth_ktls.h"
11 #include "funeth_txrx.h"
12 #include "funeth_trace.h"
13 #include "fun_queue.h"
14
15 #define FUN_XDP_CLEAN_THRES 32
16 #define FUN_XDP_CLEAN_BATCH 16
17
18 /* DMA-map a packet and return the (length, DMA_address) pairs for its
19  * segments. If a mapping error occurs -ENOMEM is returned.
20  */
21 static int map_skb(const struct sk_buff *skb, struct device *dev,
22                    dma_addr_t *addr, unsigned int *len)
23 {
24         const struct skb_shared_info *si;
25         const skb_frag_t *fp, *end;
26
27         *len = skb_headlen(skb);
28         *addr = dma_map_single(dev, skb->data, *len, DMA_TO_DEVICE);
29         if (dma_mapping_error(dev, *addr))
30                 return -ENOMEM;
31
32         si = skb_shinfo(skb);
33         end = &si->frags[si->nr_frags];
34
35         for (fp = si->frags; fp < end; fp++) {
36                 *++len = skb_frag_size(fp);
37                 *++addr = skb_frag_dma_map(dev, fp, 0, *len, DMA_TO_DEVICE);
38                 if (dma_mapping_error(dev, *addr))
39                         goto unwind;
40         }
41         return 0;
42
43 unwind:
44         while (fp-- > si->frags)
45                 dma_unmap_page(dev, *--addr, skb_frag_size(fp), DMA_TO_DEVICE);
46
47         dma_unmap_single(dev, addr[-1], skb_headlen(skb), DMA_TO_DEVICE);
48         return -ENOMEM;
49 }
50
51 /* Return the address just past the end of a Tx queue's descriptor ring.
52  * It exploits the fact that the HW writeback area is just after the end
53  * of the descriptor ring.
54  */
55 static void *txq_end(const struct funeth_txq *q)
56 {
57         return (void *)q->hw_wb;
58 }
59
60 /* Return the amount of space within a Tx ring from the given address to the
61  * end.
62  */
63 static unsigned int txq_to_end(const struct funeth_txq *q, void *p)
64 {
65         return txq_end(q) - p;
66 }
67
68 /* Return the number of Tx descriptors occupied by a Tx request. */
69 static unsigned int tx_req_ndesc(const struct fun_eth_tx_req *req)
70 {
71         return DIV_ROUND_UP(req->len8, FUNETH_SQE_SIZE / 8);
72 }
73
74 static __be16 tcp_hdr_doff_flags(const struct tcphdr *th)
75 {
76         return *(__be16 *)&tcp_flag_word(th);
77 }
78
79 static struct sk_buff *fun_tls_tx(struct sk_buff *skb, struct funeth_txq *q,
80                                   unsigned int *tls_len)
81 {
82 #if IS_ENABLED(CONFIG_TLS_DEVICE)
83         const struct fun_ktls_tx_ctx *tls_ctx;
84         u32 datalen, seq;
85
86         datalen = skb->len - skb_tcp_all_headers(skb);
87         if (!datalen)
88                 return skb;
89
90         if (likely(!tls_offload_tx_resync_pending(skb->sk))) {
91                 seq = ntohl(tcp_hdr(skb)->seq);
92                 tls_ctx = tls_driver_ctx(skb->sk, TLS_OFFLOAD_CTX_DIR_TX);
93
94                 if (likely(tls_ctx->next_seq == seq)) {
95                         *tls_len = datalen;
96                         return skb;
97                 }
98                 if (seq - tls_ctx->next_seq < U32_MAX / 4) {
99                         tls_offload_tx_resync_request(skb->sk, seq,
100                                                       tls_ctx->next_seq);
101                 }
102         }
103
104         FUN_QSTAT_INC(q, tx_tls_fallback);
105         skb = tls_encrypt_skb(skb);
106         if (!skb)
107                 FUN_QSTAT_INC(q, tx_tls_drops);
108
109         return skb;
110 #else
111         return NULL;
112 #endif
113 }
114
115 /* Write as many descriptors as needed for the supplied skb starting at the
116  * current producer location. The caller has made certain enough descriptors
117  * are available.
118  *
119  * Returns the number of descriptors written, 0 on error.
120  */
121 static unsigned int write_pkt_desc(struct sk_buff *skb, struct funeth_txq *q,
122                                    unsigned int tls_len)
123 {
124         unsigned int extra_bytes = 0, extra_pkts = 0;
125         unsigned int idx = q->prod_cnt & q->mask;
126         const struct skb_shared_info *shinfo;
127         unsigned int lens[MAX_SKB_FRAGS + 1];
128         dma_addr_t addrs[MAX_SKB_FRAGS + 1];
129         struct fun_eth_tx_req *req;
130         struct fun_dataop_gl *gle;
131         const struct tcphdr *th;
132         unsigned int ngle, i;
133         unsigned int l4_hlen;
134         u16 flags;
135
136         if (unlikely(map_skb(skb, q->dma_dev, addrs, lens))) {
137                 FUN_QSTAT_INC(q, tx_map_err);
138                 return 0;
139         }
140
141         req = fun_tx_desc_addr(q, idx);
142         req->op = FUN_ETH_OP_TX;
143         req->len8 = 0;
144         req->flags = 0;
145         req->suboff8 = offsetof(struct fun_eth_tx_req, dataop);
146         req->repr_idn = 0;
147         req->encap_proto = 0;
148
149         shinfo = skb_shinfo(skb);
150         if (likely(shinfo->gso_size)) {
151                 if (skb->encapsulation) {
152                         u16 ol4_ofst;
153
154                         flags = FUN_ETH_OUTER_EN | FUN_ETH_INNER_LSO |
155                                 FUN_ETH_UPDATE_INNER_L4_CKSUM |
156                                 FUN_ETH_UPDATE_OUTER_L3_LEN;
157                         if (shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
158                                                 SKB_GSO_UDP_TUNNEL_CSUM)) {
159                                 flags |= FUN_ETH_UPDATE_OUTER_L4_LEN |
160                                          FUN_ETH_OUTER_UDP;
161                                 if (shinfo->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
162                                         flags |= FUN_ETH_UPDATE_OUTER_L4_CKSUM;
163                                 ol4_ofst = skb_transport_offset(skb);
164                         } else {
165                                 ol4_ofst = skb_inner_network_offset(skb);
166                         }
167
168                         if (ip_hdr(skb)->version == 4)
169                                 flags |= FUN_ETH_UPDATE_OUTER_L3_CKSUM;
170                         else
171                                 flags |= FUN_ETH_OUTER_IPV6;
172
173                         if (skb->inner_network_header) {
174                                 if (inner_ip_hdr(skb)->version == 4)
175                                         flags |= FUN_ETH_UPDATE_INNER_L3_CKSUM |
176                                                  FUN_ETH_UPDATE_INNER_L3_LEN;
177                                 else
178                                         flags |= FUN_ETH_INNER_IPV6 |
179                                                  FUN_ETH_UPDATE_INNER_L3_LEN;
180                         }
181                         th = inner_tcp_hdr(skb);
182                         l4_hlen = __tcp_hdrlen(th);
183                         fun_eth_offload_init(&req->offload, flags,
184                                              shinfo->gso_size,
185                                              tcp_hdr_doff_flags(th), 0,
186                                              skb_inner_network_offset(skb),
187                                              skb_inner_transport_offset(skb),
188                                              skb_network_offset(skb), ol4_ofst);
189                         FUN_QSTAT_INC(q, tx_encap_tso);
190                 } else if (shinfo->gso_type & SKB_GSO_UDP_L4) {
191                         flags = FUN_ETH_INNER_LSO | FUN_ETH_INNER_UDP |
192                                 FUN_ETH_UPDATE_INNER_L4_CKSUM |
193                                 FUN_ETH_UPDATE_INNER_L4_LEN |
194                                 FUN_ETH_UPDATE_INNER_L3_LEN;
195
196                         if (ip_hdr(skb)->version == 4)
197                                 flags |= FUN_ETH_UPDATE_INNER_L3_CKSUM;
198                         else
199                                 flags |= FUN_ETH_INNER_IPV6;
200
201                         l4_hlen = sizeof(struct udphdr);
202                         fun_eth_offload_init(&req->offload, flags,
203                                              shinfo->gso_size,
204                                              cpu_to_be16(l4_hlen << 10), 0,
205                                              skb_network_offset(skb),
206                                              skb_transport_offset(skb), 0, 0);
207                         FUN_QSTAT_INC(q, tx_uso);
208                 } else {
209                         /* HW considers one set of headers as inner */
210                         flags = FUN_ETH_INNER_LSO |
211                                 FUN_ETH_UPDATE_INNER_L4_CKSUM |
212                                 FUN_ETH_UPDATE_INNER_L3_LEN;
213                         if (shinfo->gso_type & SKB_GSO_TCPV6)
214                                 flags |= FUN_ETH_INNER_IPV6;
215                         else
216                                 flags |= FUN_ETH_UPDATE_INNER_L3_CKSUM;
217                         th = tcp_hdr(skb);
218                         l4_hlen = __tcp_hdrlen(th);
219                         fun_eth_offload_init(&req->offload, flags,
220                                              shinfo->gso_size,
221                                              tcp_hdr_doff_flags(th), 0,
222                                              skb_network_offset(skb),
223                                              skb_transport_offset(skb), 0, 0);
224                         FUN_QSTAT_INC(q, tx_tso);
225                 }
226
227                 u64_stats_update_begin(&q->syncp);
228                 q->stats.tx_cso += shinfo->gso_segs;
229                 u64_stats_update_end(&q->syncp);
230
231                 extra_pkts = shinfo->gso_segs - 1;
232                 extra_bytes = (be16_to_cpu(req->offload.inner_l4_off) +
233                                l4_hlen) * extra_pkts;
234         } else if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
235                 flags = FUN_ETH_UPDATE_INNER_L4_CKSUM;
236                 if (skb->csum_offset == offsetof(struct udphdr, check))
237                         flags |= FUN_ETH_INNER_UDP;
238                 fun_eth_offload_init(&req->offload, flags, 0, 0, 0, 0,
239                                      skb_checksum_start_offset(skb), 0, 0);
240                 FUN_QSTAT_INC(q, tx_cso);
241         } else {
242                 fun_eth_offload_init(&req->offload, 0, 0, 0, 0, 0, 0, 0, 0);
243         }
244
245         ngle = shinfo->nr_frags + 1;
246         req->len8 = (sizeof(*req) + ngle * sizeof(*gle)) / 8;
247         req->dataop = FUN_DATAOP_HDR_INIT(ngle, 0, ngle, 0, skb->len);
248
249         for (i = 0, gle = (struct fun_dataop_gl *)req->dataop.imm;
250              i < ngle && txq_to_end(q, gle); i++, gle++)
251                 fun_dataop_gl_init(gle, 0, 0, lens[i], addrs[i]);
252
253         if (txq_to_end(q, gle) == 0) {
254                 gle = (struct fun_dataop_gl *)q->desc;
255                 for ( ; i < ngle; i++, gle++)
256                         fun_dataop_gl_init(gle, 0, 0, lens[i], addrs[i]);
257         }
258
259         if (IS_ENABLED(CONFIG_TLS_DEVICE) && unlikely(tls_len)) {
260                 struct fun_eth_tls *tls = (struct fun_eth_tls *)gle;
261                 struct fun_ktls_tx_ctx *tls_ctx;
262
263                 req->len8 += FUNETH_TLS_SZ / 8;
264                 req->flags = cpu_to_be16(FUN_ETH_TX_TLS);
265
266                 tls_ctx = tls_driver_ctx(skb->sk, TLS_OFFLOAD_CTX_DIR_TX);
267                 tls->tlsid = tls_ctx->tlsid;
268                 tls_ctx->next_seq += tls_len;
269
270                 u64_stats_update_begin(&q->syncp);
271                 q->stats.tx_tls_bytes += tls_len;
272                 q->stats.tx_tls_pkts += 1 + extra_pkts;
273                 u64_stats_update_end(&q->syncp);
274         }
275
276         u64_stats_update_begin(&q->syncp);
277         q->stats.tx_bytes += skb->len + extra_bytes;
278         q->stats.tx_pkts += 1 + extra_pkts;
279         u64_stats_update_end(&q->syncp);
280
281         q->info[idx].skb = skb;
282
283         trace_funeth_tx(q, skb->len, idx, req->dataop.ngather);
284         return tx_req_ndesc(req);
285 }
286
287 /* Return the number of available descriptors of a Tx queue.
288  * HW assumes head==tail means the ring is empty so we need to keep one
289  * descriptor unused.
290  */
291 static unsigned int fun_txq_avail(const struct funeth_txq *q)
292 {
293         return q->mask - q->prod_cnt + q->cons_cnt;
294 }
295
296 /* Stop a queue if it can't handle another worst-case packet. */
297 static void fun_tx_check_stop(struct funeth_txq *q)
298 {
299         if (likely(fun_txq_avail(q) >= FUNETH_MAX_PKT_DESC))
300                 return;
301
302         netif_tx_stop_queue(q->ndq);
303
304         /* NAPI reclaim is freeing packets in parallel with us and we may race.
305          * We have stopped the queue but check again after synchronizing with
306          * reclaim.
307          */
308         smp_mb();
309         if (likely(fun_txq_avail(q) < FUNETH_MAX_PKT_DESC))
310                 FUN_QSTAT_INC(q, tx_nstops);
311         else
312                 netif_tx_start_queue(q->ndq);
313 }
314
315 /* Return true if a queue has enough space to restart. Current condition is
316  * that the queue must be >= 1/4 empty.
317  */
318 static bool fun_txq_may_restart(struct funeth_txq *q)
319 {
320         return fun_txq_avail(q) >= q->mask / 4;
321 }
322
323 netdev_tx_t fun_start_xmit(struct sk_buff *skb, struct net_device *netdev)
324 {
325         struct funeth_priv *fp = netdev_priv(netdev);
326         unsigned int qid = skb_get_queue_mapping(skb);
327         struct funeth_txq *q = fp->txqs[qid];
328         unsigned int tls_len = 0;
329         unsigned int ndesc;
330
331         if (IS_ENABLED(CONFIG_TLS_DEVICE) && skb->sk &&
332             tls_is_sk_tx_device_offloaded(skb->sk)) {
333                 skb = fun_tls_tx(skb, q, &tls_len);
334                 if (unlikely(!skb))
335                         goto dropped;
336         }
337
338         ndesc = write_pkt_desc(skb, q, tls_len);
339         if (unlikely(!ndesc)) {
340                 dev_kfree_skb_any(skb);
341                 goto dropped;
342         }
343
344         q->prod_cnt += ndesc;
345         fun_tx_check_stop(q);
346
347         skb_tx_timestamp(skb);
348
349         if (__netdev_tx_sent_queue(q->ndq, skb->len, netdev_xmit_more()))
350                 fun_txq_wr_db(q);
351         else
352                 FUN_QSTAT_INC(q, tx_more);
353
354         return NETDEV_TX_OK;
355
356 dropped:
357         /* A dropped packet may be the last one in a xmit_more train,
358          * ring the doorbell just in case.
359          */
360         if (!netdev_xmit_more())
361                 fun_txq_wr_db(q);
362         return NETDEV_TX_OK;
363 }
364
365 /* Return a Tx queue's HW head index written back to host memory. */
366 static u16 txq_hw_head(const struct funeth_txq *q)
367 {
368         return (u16)be64_to_cpu(*q->hw_wb);
369 }
370
371 /* Unmap the Tx packet starting at the given descriptor index and
372  * return the number of Tx descriptors it occupied.
373  */
374 static unsigned int fun_unmap_pkt(const struct funeth_txq *q, unsigned int idx)
375 {
376         const struct fun_eth_tx_req *req = fun_tx_desc_addr(q, idx);
377         unsigned int ngle = req->dataop.ngather;
378         struct fun_dataop_gl *gle;
379
380         if (ngle) {
381                 gle = (struct fun_dataop_gl *)req->dataop.imm;
382                 dma_unmap_single(q->dma_dev, be64_to_cpu(gle->sgl_data),
383                                  be32_to_cpu(gle->sgl_len), DMA_TO_DEVICE);
384
385                 for (gle++; --ngle && txq_to_end(q, gle); gle++)
386                         dma_unmap_page(q->dma_dev, be64_to_cpu(gle->sgl_data),
387                                        be32_to_cpu(gle->sgl_len),
388                                        DMA_TO_DEVICE);
389
390                 for (gle = (struct fun_dataop_gl *)q->desc; ngle; ngle--, gle++)
391                         dma_unmap_page(q->dma_dev, be64_to_cpu(gle->sgl_data),
392                                        be32_to_cpu(gle->sgl_len),
393                                        DMA_TO_DEVICE);
394         }
395
396         return tx_req_ndesc(req);
397 }
398
399 /* Reclaim completed Tx descriptors and free their packets. Restart a stopped
400  * queue if we freed enough descriptors.
401  *
402  * Return true if we exhausted the budget while there is more work to be done.
403  */
404 static bool fun_txq_reclaim(struct funeth_txq *q, int budget)
405 {
406         unsigned int npkts = 0, nbytes = 0, ndesc = 0;
407         unsigned int head, limit, reclaim_idx;
408
409         /* budget may be 0, e.g., netpoll */
410         limit = budget ? budget : UINT_MAX;
411
412         for (head = txq_hw_head(q), reclaim_idx = q->cons_cnt & q->mask;
413              head != reclaim_idx && npkts < limit; head = txq_hw_head(q)) {
414                 /* The HW head is continually updated, ensure we don't read
415                  * descriptor state before the head tells us to reclaim it.
416                  * On the enqueue side the doorbell is an implicit write
417                  * barrier.
418                  */
419                 rmb();
420
421                 do {
422                         unsigned int pkt_desc = fun_unmap_pkt(q, reclaim_idx);
423                         struct sk_buff *skb = q->info[reclaim_idx].skb;
424
425                         trace_funeth_tx_free(q, reclaim_idx, pkt_desc, head);
426
427                         nbytes += skb->len;
428                         napi_consume_skb(skb, budget);
429                         ndesc += pkt_desc;
430                         reclaim_idx = (reclaim_idx + pkt_desc) & q->mask;
431                         npkts++;
432                 } while (reclaim_idx != head && npkts < limit);
433         }
434
435         q->cons_cnt += ndesc;
436         netdev_tx_completed_queue(q->ndq, npkts, nbytes);
437         smp_mb(); /* pairs with the one in fun_tx_check_stop() */
438
439         if (unlikely(netif_tx_queue_stopped(q->ndq) &&
440                      fun_txq_may_restart(q))) {
441                 netif_tx_wake_queue(q->ndq);
442                 FUN_QSTAT_INC(q, tx_nrestarts);
443         }
444
445         return reclaim_idx != head;
446 }
447
448 /* The NAPI handler for Tx queues. */
449 int fun_txq_napi_poll(struct napi_struct *napi, int budget)
450 {
451         struct fun_irq *irq = container_of(napi, struct fun_irq, napi);
452         struct funeth_txq *q = irq->txq;
453         unsigned int db_val;
454
455         if (fun_txq_reclaim(q, budget))
456                 return budget;               /* exhausted budget */
457
458         napi_complete(napi);                 /* exhausted pending work */
459         db_val = READ_ONCE(q->irq_db_val) | (q->cons_cnt & q->mask);
460         writel(db_val, q->db);
461         return 0;
462 }
463
464 /* Reclaim up to @budget completed Tx packets from a TX XDP queue. */
465 static unsigned int fun_xdpq_clean(struct funeth_txq *q, unsigned int budget)
466 {
467         unsigned int npkts = 0, ndesc = 0, head, reclaim_idx;
468
469         for (head = txq_hw_head(q), reclaim_idx = q->cons_cnt & q->mask;
470              head != reclaim_idx && npkts < budget; head = txq_hw_head(q)) {
471                 /* The HW head is continually updated, ensure we don't read
472                  * descriptor state before the head tells us to reclaim it.
473                  * On the enqueue side the doorbell is an implicit write
474                  * barrier.
475                  */
476                 rmb();
477
478                 do {
479                         unsigned int pkt_desc = fun_unmap_pkt(q, reclaim_idx);
480
481                         xdp_return_frame(q->info[reclaim_idx].xdpf);
482
483                         trace_funeth_tx_free(q, reclaim_idx, pkt_desc, head);
484
485                         reclaim_idx = (reclaim_idx + pkt_desc) & q->mask;
486                         ndesc += pkt_desc;
487                         npkts++;
488                 } while (reclaim_idx != head && npkts < budget);
489         }
490
491         q->cons_cnt += ndesc;
492         return npkts;
493 }
494
495 bool fun_xdp_tx(struct funeth_txq *q, struct xdp_frame *xdpf)
496 {
497         struct fun_eth_tx_req *req;
498         struct fun_dataop_gl *gle;
499         unsigned int idx, len;
500         dma_addr_t dma;
501
502         if (fun_txq_avail(q) < FUN_XDP_CLEAN_THRES)
503                 fun_xdpq_clean(q, FUN_XDP_CLEAN_BATCH);
504
505         if (!unlikely(fun_txq_avail(q))) {
506                 FUN_QSTAT_INC(q, tx_xdp_full);
507                 return false;
508         }
509
510         len = xdpf->len;
511         dma = dma_map_single(q->dma_dev, xdpf->data, len, DMA_TO_DEVICE);
512         if (unlikely(dma_mapping_error(q->dma_dev, dma))) {
513                 FUN_QSTAT_INC(q, tx_map_err);
514                 return false;
515         }
516
517         idx = q->prod_cnt & q->mask;
518         req = fun_tx_desc_addr(q, idx);
519         req->op = FUN_ETH_OP_TX;
520         req->len8 = (sizeof(*req) + sizeof(*gle)) / 8;
521         req->flags = 0;
522         req->suboff8 = offsetof(struct fun_eth_tx_req, dataop);
523         req->repr_idn = 0;
524         req->encap_proto = 0;
525         fun_eth_offload_init(&req->offload, 0, 0, 0, 0, 0, 0, 0, 0);
526         req->dataop = FUN_DATAOP_HDR_INIT(1, 0, 1, 0, len);
527
528         gle = (struct fun_dataop_gl *)req->dataop.imm;
529         fun_dataop_gl_init(gle, 0, 0, len, dma);
530
531         q->info[idx].xdpf = xdpf;
532
533         u64_stats_update_begin(&q->syncp);
534         q->stats.tx_bytes += len;
535         q->stats.tx_pkts++;
536         u64_stats_update_end(&q->syncp);
537
538         trace_funeth_tx(q, len, idx, 1);
539         q->prod_cnt++;
540
541         return true;
542 }
543
544 int fun_xdp_xmit_frames(struct net_device *dev, int n,
545                         struct xdp_frame **frames, u32 flags)
546 {
547         struct funeth_priv *fp = netdev_priv(dev);
548         struct funeth_txq *q, **xdpqs;
549         int i, q_idx;
550
551         if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
552                 return -EINVAL;
553
554         xdpqs = rcu_dereference_bh(fp->xdpqs);
555         if (unlikely(!xdpqs))
556                 return -ENETDOWN;
557
558         q_idx = smp_processor_id();
559         if (unlikely(q_idx >= fp->num_xdpqs))
560                 return -ENXIO;
561
562         for (q = xdpqs[q_idx], i = 0; i < n; i++)
563                 if (!fun_xdp_tx(q, frames[i]))
564                         break;
565
566         if (unlikely(flags & XDP_XMIT_FLUSH))
567                 fun_txq_wr_db(q);
568         return i;
569 }
570
571 /* Purge a Tx queue of any queued packets. Should be called once HW access
572  * to the packets has been revoked, e.g., after the queue has been disabled.
573  */
574 static void fun_txq_purge(struct funeth_txq *q)
575 {
576         while (q->cons_cnt != q->prod_cnt) {
577                 unsigned int idx = q->cons_cnt & q->mask;
578
579                 q->cons_cnt += fun_unmap_pkt(q, idx);
580                 dev_kfree_skb_any(q->info[idx].skb);
581         }
582         netdev_tx_reset_queue(q->ndq);
583 }
584
585 static void fun_xdpq_purge(struct funeth_txq *q)
586 {
587         while (q->cons_cnt != q->prod_cnt) {
588                 unsigned int idx = q->cons_cnt & q->mask;
589
590                 q->cons_cnt += fun_unmap_pkt(q, idx);
591                 xdp_return_frame(q->info[idx].xdpf);
592         }
593 }
594
595 /* Create a Tx queue, allocating all the host resources needed. */
596 static struct funeth_txq *fun_txq_create_sw(struct net_device *dev,
597                                             unsigned int qidx,
598                                             unsigned int ndesc,
599                                             struct fun_irq *irq)
600 {
601         struct funeth_priv *fp = netdev_priv(dev);
602         struct funeth_txq *q;
603         int numa_node;
604
605         if (irq)
606                 numa_node = fun_irq_node(irq); /* skb Tx queue */
607         else
608                 numa_node = cpu_to_node(qidx); /* XDP Tx queue */
609
610         q = kzalloc_node(sizeof(*q), GFP_KERNEL, numa_node);
611         if (!q)
612                 goto err;
613
614         q->dma_dev = &fp->pdev->dev;
615         q->desc = fun_alloc_ring_mem(q->dma_dev, ndesc, FUNETH_SQE_SIZE,
616                                      sizeof(*q->info), true, numa_node,
617                                      &q->dma_addr, (void **)&q->info,
618                                      &q->hw_wb);
619         if (!q->desc)
620                 goto free_q;
621
622         q->netdev = dev;
623         q->mask = ndesc - 1;
624         q->qidx = qidx;
625         q->numa_node = numa_node;
626         u64_stats_init(&q->syncp);
627         q->init_state = FUN_QSTATE_INIT_SW;
628         return q;
629
630 free_q:
631         kfree(q);
632 err:
633         netdev_err(dev, "Can't allocate memory for %s queue %u\n",
634                    irq ? "Tx" : "XDP", qidx);
635         return NULL;
636 }
637
638 static void fun_txq_free_sw(struct funeth_txq *q)
639 {
640         struct funeth_priv *fp = netdev_priv(q->netdev);
641
642         fun_free_ring_mem(q->dma_dev, q->mask + 1, FUNETH_SQE_SIZE, true,
643                           q->desc, q->dma_addr, q->info);
644
645         fp->tx_packets += q->stats.tx_pkts;
646         fp->tx_bytes   += q->stats.tx_bytes;
647         fp->tx_dropped += q->stats.tx_map_err;
648
649         kfree(q);
650 }
651
652 /* Allocate the device portion of a Tx queue. */
653 int fun_txq_create_dev(struct funeth_txq *q, struct fun_irq *irq)
654 {
655         struct funeth_priv *fp = netdev_priv(q->netdev);
656         unsigned int irq_idx, ndesc = q->mask + 1;
657         int err;
658
659         q->irq = irq;
660         *q->hw_wb = 0;
661         q->prod_cnt = 0;
662         q->cons_cnt = 0;
663         irq_idx = irq ? irq->irq_idx : 0;
664
665         err = fun_sq_create(fp->fdev,
666                             FUN_ADMIN_EPSQ_CREATE_FLAG_HEAD_WB_ADDRESS |
667                             FUN_ADMIN_RES_CREATE_FLAG_ALLOCATOR, 0,
668                             FUN_HCI_ID_INVALID, ilog2(FUNETH_SQE_SIZE), ndesc,
669                             q->dma_addr, fp->tx_coal_count, fp->tx_coal_usec,
670                             irq_idx, 0, fp->fdev->kern_end_qid, 0,
671                             &q->hw_qid, &q->db);
672         if (err)
673                 goto out;
674
675         err = fun_create_and_bind_tx(fp, q->hw_qid);
676         if (err < 0)
677                 goto free_devq;
678         q->ethid = err;
679
680         if (irq) {
681                 irq->txq = q;
682                 q->ndq = netdev_get_tx_queue(q->netdev, q->qidx);
683                 q->irq_db_val = FUN_IRQ_SQ_DB(fp->tx_coal_usec,
684                                               fp->tx_coal_count);
685                 writel(q->irq_db_val, q->db);
686         }
687
688         q->init_state = FUN_QSTATE_INIT_FULL;
689         netif_info(fp, ifup, q->netdev,
690                    "%s queue %u, depth %u, HW qid %u, IRQ idx %u, eth id %u, node %d\n",
691                    irq ? "Tx" : "XDP", q->qidx, ndesc, q->hw_qid, irq_idx,
692                    q->ethid, q->numa_node);
693         return 0;
694
695 free_devq:
696         fun_destroy_sq(fp->fdev, q->hw_qid);
697 out:
698         netdev_err(q->netdev,
699                    "Failed to create %s queue %u on device, error %d\n",
700                    irq ? "Tx" : "XDP", q->qidx, err);
701         return err;
702 }
703
704 static void fun_txq_free_dev(struct funeth_txq *q)
705 {
706         struct funeth_priv *fp = netdev_priv(q->netdev);
707
708         if (q->init_state < FUN_QSTATE_INIT_FULL)
709                 return;
710
711         netif_info(fp, ifdown, q->netdev,
712                    "Freeing %s queue %u (id %u), IRQ %u, ethid %u\n",
713                    q->irq ? "Tx" : "XDP", q->qidx, q->hw_qid,
714                    q->irq ? q->irq->irq_idx : 0, q->ethid);
715
716         fun_destroy_sq(fp->fdev, q->hw_qid);
717         fun_res_destroy(fp->fdev, FUN_ADMIN_OP_ETH, 0, q->ethid);
718
719         if (q->irq) {
720                 q->irq->txq = NULL;
721                 fun_txq_purge(q);
722         } else {
723                 fun_xdpq_purge(q);
724         }
725
726         q->init_state = FUN_QSTATE_INIT_SW;
727 }
728
729 /* Create or advance a Tx queue, allocating all the host and device resources
730  * needed to reach the target state.
731  */
732 int funeth_txq_create(struct net_device *dev, unsigned int qidx,
733                       unsigned int ndesc, struct fun_irq *irq, int state,
734                       struct funeth_txq **qp)
735 {
736         struct funeth_txq *q = *qp;
737         int err;
738
739         if (!q)
740                 q = fun_txq_create_sw(dev, qidx, ndesc, irq);
741         if (!q)
742                 return -ENOMEM;
743
744         if (q->init_state >= state)
745                 goto out;
746
747         err = fun_txq_create_dev(q, irq);
748         if (err) {
749                 if (!*qp)
750                         fun_txq_free_sw(q);
751                 return err;
752         }
753
754 out:
755         *qp = q;
756         return 0;
757 }
758
759 /* Free Tx queue resources until it reaches the target state.
760  * The queue must be already disconnected from the stack.
761  */
762 struct funeth_txq *funeth_txq_free(struct funeth_txq *q, int state)
763 {
764         if (state < FUN_QSTATE_INIT_FULL)
765                 fun_txq_free_dev(q);
766
767         if (state == FUN_QSTATE_DESTROYED) {
768                 fun_txq_free_sw(q);
769                 q = NULL;
770         }
771
772         return q;
773 }