net/funeth: Tx handling of XDP with fragments.
authorDimitris Michailidis <d.michailidis@fungible.com>
Fri, 29 Jul 2022 07:32:57 +0000 (00:32 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 1 Aug 2022 11:38:57 +0000 (12:38 +0100)
By now all the functions fun_xdp_tx() calls are shared with the skb path
and thus are fragment-capable. Update fun_xdp_tx(), that up to now has
been passing just one buffer, to check for fragments and call
accordingly.  This makes XDP_TX and ndo_xdp_xmit fragment-capable.

Signed-off-by: Dimitris Michailidis <dmichail@fungible.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/fungible/funeth/funeth_tx.c

index 3128db8586ef64ce0466abd09f0f7a375dbdc6fd..706d81e39a54d3b1902e3ec0aafe8f29a75dff52 100644 (file)
@@ -514,21 +514,31 @@ static unsigned int fun_xdpq_clean(struct funeth_txq *q, unsigned int budget)
 
 bool fun_xdp_tx(struct funeth_txq *q, struct xdp_frame *xdpf)
 {
+       unsigned int idx, nfrags = 1, ndesc = 1, tot_len = xdpf->len;
        const struct skb_shared_info *si = NULL;
+       unsigned int lens[MAX_SKB_FRAGS + 1];
+       dma_addr_t dma[MAX_SKB_FRAGS + 1];
        struct fun_eth_tx_req *req;
-       unsigned int idx, len;
-       dma_addr_t dma;
 
        if (fun_txq_avail(q) < FUN_XDP_CLEAN_THRES)
                fun_xdpq_clean(q, FUN_XDP_CLEAN_BATCH);
 
-       if (!unlikely(fun_txq_avail(q))) {
+       if (unlikely(xdp_frame_has_frags(xdpf))) {
+               si = xdp_get_shared_info_from_frame(xdpf);
+               tot_len = xdp_get_frame_len(xdpf);
+               nfrags += si->nr_frags;
+               ndesc = DIV_ROUND_UP((sizeof(*req) + nfrags *
+                                     sizeof(struct fun_dataop_gl)),
+                                    FUNETH_SQE_SIZE);
+       }
+
+       if (unlikely(fun_txq_avail(q) < ndesc)) {
                FUN_QSTAT_INC(q, tx_xdp_full);
                return false;
        }
 
-       if (unlikely(fun_map_pkt(q->dma_dev, si, xdpf->data, xdpf->len, &dma,
-                                &len))) {
+       if (unlikely(fun_map_pkt(q->dma_dev, si, xdpf->data, xdpf->len, dma,
+                                lens))) {
                FUN_QSTAT_INC(q, tx_map_err);
                return false;
        }
@@ -542,19 +552,19 @@ bool fun_xdp_tx(struct funeth_txq *q, struct xdp_frame *xdpf)
        req->repr_idn = 0;
        req->encap_proto = 0;
        fun_eth_offload_init(&req->offload, 0, 0, 0, 0, 0, 0, 0, 0);
-       req->dataop = FUN_DATAOP_HDR_INIT(1, 0, 1, 0, len);
+       req->dataop = FUN_DATAOP_HDR_INIT(nfrags, 0, nfrags, 0, tot_len);
 
-       fun_write_gl(q, req, &dma, &len, 1);
+       fun_write_gl(q, req, dma, lens, nfrags);
 
        q->info[idx].xdpf = xdpf;
 
        u64_stats_update_begin(&q->syncp);
-       q->stats.tx_bytes += len;
+       q->stats.tx_bytes += tot_len;
        q->stats.tx_pkts++;
        u64_stats_update_end(&q->syncp);
 
-       trace_funeth_tx(q, len, idx, 1);
-       q->prod_cnt++;
+       trace_funeth_tx(q, tot_len, idx, nfrags);
+       q->prod_cnt += ndesc;
 
        return true;
 }