The branch main has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e2a2a7581c9663a08b8d92a34040d6fcdfc20816

commit e2a2a7581c9663a08b8d92a34040d6fcdfc20816
Author:     John Baldwin <j...@freebsd.org>
AuthorDate: 2025-09-11 21:10:39 +0000
Commit:     John Baldwin <j...@freebsd.org>
CommitDate: 2025-09-11 21:10:39 +0000

    cxgbe tom: Support sending "raw" WR mbufs on plain TCP and TLS sockets
    
    This is intended to support control work requests that manipulate
    connection state but do not transmit data.  Raw WRs are transmitted
    immediately if possible, otherwise they are queued to an mbufq in the
    toe pcb until sufficient credits are available.  Raw WRs take
    precendence over transmitting socket data.
    
    Reviewed by:    np
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D47761
---
 sys/dev/cxgbe/tom/t4_cpl_io.c | 85 +++++++++++++++++++++++++++++++++++++++++++
 sys/dev/cxgbe/tom/t4_tls.c    | 13 +++++++
 sys/dev/cxgbe/tom/t4_tom.h    |  2 +
 3 files changed, 100 insertions(+)

diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 9ecb4aeee939..a7b4162db3b5 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -619,6 +619,48 @@ write_tx_sgl(void *dst, struct mbuf *start, struct mbuf 
*stop, int nsegs, int n)
            __func__, nsegs, start, stop));
 }
 
+bool
+t4_push_raw_wr(struct adapter *sc, struct toepcb *toep, struct mbuf *m)
+{
+#ifdef INVARIANTS
+       struct inpcb *inp = toep->inp;
+#endif
+       struct wrqe *wr;
+       struct ofld_tx_sdesc *txsd;
+       u_int credits, plen;
+
+       INP_WLOCK_ASSERT(inp);
+       MPASS(mbuf_raw_wr(m));
+       plen = m->m_pkthdr.len;
+       credits = howmany(plen, 16);
+       if (credits > toep->tx_credits)
+               return (false);
+
+       wr = alloc_wrqe(roundup2(plen, 16), &toep->ofld_txq->wrq);
+       if (wr == NULL)
+               return (false);
+
+       m_copydata(m, 0, plen, wrtod(wr));
+       m_freem(m);
+
+       toep->tx_credits -= credits;
+       if (toep->tx_credits < MIN_OFLD_TX_CREDITS)
+               toep->flags |= TPF_TX_SUSPENDED;
+
+       KASSERT(toep->txsd_avail > 0, ("%s: no txsd", __func__));
+       KASSERT(credits <= MAX_OFLD_TX_SDESC_CREDITS,
+           ("%s: tx_credits %u too large", __func__, credits));
+       txsd = &toep->txsd[toep->txsd_pidx];
+       txsd->plen = 0;
+       txsd->tx_credits = credits;
+       if (__predict_false(++toep->txsd_pidx == toep->txsd_total))
+               toep->txsd_pidx = 0;
+       toep->txsd_avail--;
+
+       t4_wrq_tx(sc, wr);
+       return (true);
+}
+
 /*
  * Max number of SGL entries an offload tx work request can have.  This is 41
  * (1 + 40) for a full 512B work request.
@@ -651,6 +693,7 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, int 
drop)
        struct tcpcb *tp = intotcpcb(inp);
        struct socket *so = inp->inp_socket;
        struct sockbuf *sb = &so->so_snd;
+       struct mbufq *pduq = &toep->ulp_pduq;
        int tx_credits, shove, compl, sowwakeup;
        struct ofld_tx_sdesc *txsd;
        bool nomap_mbuf_seen;
@@ -695,6 +738,19 @@ t4_push_frames(struct adapter *sc, struct toepcb *toep, 
int drop)
                max_imm = max_imm_payload(tx_credits, 0);
                max_nsegs = max_dsgl_nsegs(tx_credits, 0);
 
+               if (__predict_false((sndptr = mbufq_first(pduq)) != NULL)) {
+                       if (!t4_push_raw_wr(sc, toep, sndptr)) {
+                               toep->flags |= TPF_TX_SUSPENDED;
+                               return;
+                       }
+
+                       m = mbufq_dequeue(pduq);
+                       MPASS(m == sndptr);
+
+                       txsd = &toep->txsd[toep->txsd_pidx];
+                       continue;
+               }
+
                SOCKBUF_LOCK(sb);
                sowwakeup = drop;
                if (drop) {
@@ -1253,6 +1309,35 @@ t4_push_data(struct adapter *sc, struct toepcb *toep, 
int drop)
                t4_push_frames(sc, toep, drop);
 }
 
+void
+t4_raw_wr_tx(struct adapter *sc, struct toepcb *toep, struct mbuf *m)
+{
+#ifdef INVARIANTS
+       struct inpcb *inp = toep->inp;
+#endif
+
+       INP_WLOCK_ASSERT(inp);
+
+       /*
+        * If there are other raw WRs enqueued, enqueue to preserve
+        * FIFO ordering.
+        */
+       if (!mbufq_empty(&toep->ulp_pduq)) {
+               mbufq_enqueue(&toep->ulp_pduq, m);
+               return;
+       }
+
+       /*
+        * Cannot call t4_push_data here as that will lock so_snd and
+        * some callers of this run in rx handlers with so_rcv locked.
+        * Instead, just try to transmit this WR.
+        */
+       if (!t4_push_raw_wr(sc, toep, m)) {
+               mbufq_enqueue(&toep->ulp_pduq, m);
+               toep->flags |= TPF_TX_SUSPENDED;
+       }
+}
+
 int
 t4_tod_output(struct toedev *tod, struct tcpcb *tp)
 {
diff --git a/sys/dev/cxgbe/tom/t4_tls.c b/sys/dev/cxgbe/tom/t4_tls.c
index 857832aafa5c..3dd3c28e3a86 100644
--- a/sys/dev/cxgbe/tom/t4_tls.c
+++ b/sys/dev/cxgbe/tom/t4_tls.c
@@ -496,6 +496,7 @@ t4_push_ktls(struct adapter *sc, struct toepcb *toep, int 
drop)
        struct tcpcb *tp = intotcpcb(inp);
        struct socket *so = inp->inp_socket;
        struct sockbuf *sb = &so->so_snd;
+       struct mbufq *pduq = &toep->ulp_pduq;
        int tls_size, tx_credits, shove, sowwakeup;
        struct ofld_tx_sdesc *txsd;
        char *buf;
@@ -538,6 +539,18 @@ t4_push_ktls(struct adapter *sc, struct toepcb *toep, int 
drop)
        for (;;) {
                tx_credits = min(toep->tx_credits, MAX_OFLD_TX_CREDITS);
 
+               if (__predict_false((m = mbufq_first(pduq)) != NULL)) {
+                       if (!t4_push_raw_wr(sc, toep, m)) {
+                               toep->flags |= TPF_TX_SUSPENDED;
+                               return;
+                       }
+
+                       (void)mbufq_dequeue(pduq);
+
+                       txsd = &toep->txsd[toep->txsd_pidx];
+                       continue;
+               }
+
                SOCKBUF_LOCK(sb);
                sowwakeup = drop;
                if (drop) {
diff --git a/sys/dev/cxgbe/tom/t4_tom.h b/sys/dev/cxgbe/tom/t4_tom.h
index 3b2243aeb69f..3dfa24a33f85 100644
--- a/sys/dev/cxgbe/tom/t4_tom.h
+++ b/sys/dev/cxgbe/tom/t4_tom.h
@@ -529,6 +529,8 @@ int t4_send_rst(struct toedev *, struct tcpcb *);
 void t4_set_tcb_field(struct adapter *, struct sge_wrq *, struct toepcb *,
     uint16_t, uint64_t, uint64_t, int, int);
 void t4_push_pdus(struct adapter *, struct toepcb *, int);
+bool t4_push_raw_wr(struct adapter *, struct toepcb *, struct mbuf *);
+void t4_raw_wr_tx(struct adapter *, struct toepcb *, struct mbuf *);
 
 /* t4_ddp.c */
 int t4_init_ppod_region(struct ppod_region *, struct t4_range *, u_int,

Reply via email to