The branch main has been updated by adrian:

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

commit 9919c1a8ebd7da0aa86c6475446a7af255ecb17a
Author:     Abdelkader Boudih <[email protected]>
AuthorDate: 2026-06-19 19:01:12 +0000
Commit:     Adrian Chadd <[email protected]>
CommitDate: 2026-06-19 19:01:12 +0000

    firewire: extract shared helpers from fwe and fwip
    
    Add fw_net.h with common inline helpers used by both if_fwe and
    if_fwip: ISO chunk init, TX xfer allocation, xferlist free,
    send queue drain, and DEVICE_POLLING ioctl handling.
    
    Reviewed by:    imp
    Differential Revision:  https://reviews.freebsd.org/D57615
---
 sys/dev/firewire/fw_net.h  | 109 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/firewire/if_fwe.c  |  56 +++++------------------
 sys/dev/firewire/if_fwip.c |  62 +++++---------------------
 3 files changed, 130 insertions(+), 97 deletions(-)

diff --git a/sys/dev/firewire/fw_net.h b/sys/dev/firewire/fw_net.h
new file mode 100644
index 000000000000..84495a9bc0a9
--- /dev/null
+++ b/sys/dev/firewire/fw_net.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2026 Abdelkader Boudih <[email protected]>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _DEV_FIREWIRE_FW_NET_H_
+#define _DEV_FIREWIRE_FW_NET_H_
+
+/*
+ * Allocate mbuf clusters for isochronous receive bulk transfers
+ * and insert them into the free queue.
+ */
+static __inline void
+fw_net_init_iso_chunks(struct fw_xferq *xferq)
+{
+       struct mbuf *m;
+       int i;
+
+       for (i = 0; i < xferq->bnchunk; i++) {
+               m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
+               xferq->bulkxfer[i].mbuf = m;
+               m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
+               STAILQ_INSERT_TAIL(&xferq->stfree, &xferq->bulkxfer[i], link);
+       }
+}
+
+/*
+ * Allocate a single TX xfer with speed, callback, and softc pre-filled.
+ */
+static __inline struct fw_xfer *
+fw_net_alloc_txfer(struct firewire_comm *fc, int speed,
+    void *sc, void (*hand)(struct fw_xfer *),
+    struct malloc_type *mtype)
+{
+       struct fw_xfer *xfer;
+
+       xfer = fw_xfer_alloc(mtype);
+       if (xfer == NULL)
+               return (NULL);
+       xfer->send.spd = speed;
+       xfer->fc = fc;
+       xfer->sc = (caddr_t)sc;
+       xfer->hand = hand;
+       return (xfer);
+}
+
+/*
+ * Free all xfers on a STAILQ list.
+ */
+#define        FW_NET_FREE_XFERLIST(head) do {                                 
\
+       struct fw_xfer *_xfer, *_next;                                  \
+       for (_xfer = STAILQ_FIRST(head); _xfer != NULL;         \
+           _xfer = _next) {                                            \
+               _next = STAILQ_NEXT(_xfer, link);                       \
+               fw_xfer_free(_xfer);                                    \
+       }                                                               \
+} while (0)
+
+/*
+ * Drain the send queue, counting each dropped packet as an output error.
+ */
+static __inline void
+fw_net_drain_sendq(if_t ifp)
+{
+       struct mbuf *m;
+
+       do {
+               m = if_dequeue(ifp);
+               if (m != NULL)
+                       m_freem(m);
+               if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+       } while (m != NULL);
+}
+
+/*
+ * Handle SIOCSIFCAP for DEVICE_POLLING.
+ * Returns 0 if handled (caller should return), -1 if not a polling request.
+ */
+#ifdef DEVICE_POLLING
+static __inline int
+fw_net_poll_ioctl(if_t ifp, struct ifreq *ifr,
+    struct firewire_comm *fc, poll_handler_t *poll_fn)
+{
+       int error;
+
+       if (ifr->ifr_reqcap & IFCAP_POLLING &&
+           !(if_getcapenable(ifp) & IFCAP_POLLING)) {
+               error = ether_poll_register(poll_fn, ifp);
+               if (error)
+                       return (error);
+               /* Disable interrupts */
+               fc->set_intr(fc, 0);
+               if_setcapenablebit(ifp, IFCAP_POLLING, 0);
+               return (0);
+       }
+       if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+           if_getcapenable(ifp) & IFCAP_POLLING) {
+               error = ether_poll_deregister(ifp);
+               /* Enable interrupts. */
+               fc->set_intr(fc, 1);
+               if_setcapenablebit(ifp, 0, IFCAP_POLLING);
+               return (error);
+       }
+       return (-1);
+}
+#endif /* DEVICE_POLLING */
+
+#endif /* !_DEV_FIREWIRE_FW_NET_H_ */
diff --git a/sys/dev/firewire/if_fwe.c b/sys/dev/firewire/if_fwe.c
index 5d7299b4acf8..c8bfc439e166 100644
--- a/sys/dev/firewire/if_fwe.c
+++ b/sys/dev/firewire/if_fwe.c
@@ -62,6 +62,7 @@
 #include <dev/firewire/firewire.h>
 #include <dev/firewire/firewirereg.h>
 #include <dev/firewire/if_fwevar.h>
+#include <dev/firewire/fw_net.h>
 
 #define FWEDEBUG       if (fwedebug) if_printf
 #define TX_MAX_QUEUE   (FWMAXQUEUE - 1)
@@ -206,7 +207,6 @@ fwe_stop(struct fwe_softc *fwe)
        struct firewire_comm *fc;
        struct fw_xferq *xferq;
        if_t ifp = fwe->eth_softc.ifp;
-       struct fw_xfer *xfer, *next;
        int i;
 
        fc = fwe->fd.fc;
@@ -225,11 +225,7 @@ fwe_stop(struct fwe_softc *fwe)
                        m_freem(xferq->bulkxfer[i].mbuf);
                free(xferq->bulkxfer, M_FWE);
 
-               for (xfer = STAILQ_FIRST(&fwe->xferlist); xfer != NULL;
-                                       xfer = next) {
-                       next = STAILQ_NEXT(xfer, link);
-                       fw_xfer_free(xfer);
-               }
+               FW_NET_FREE_XFERLIST(&fwe->xferlist);
                STAILQ_INIT(&fwe->xferlist);
 
                xferq->bulkxfer =  NULL;
@@ -272,7 +268,6 @@ fwe_init(void *arg)
        if_t ifp = fwe->eth_softc.ifp;
        struct fw_xferq *xferq;
        struct fw_xfer *xfer;
-       struct mbuf *m;
        int i;
 
        FWEDEBUG(ifp, "initializing\n");
@@ -307,22 +302,13 @@ fwe_init(void *arg)
                STAILQ_INIT(&xferq->stfree);
                STAILQ_INIT(&xferq->stdma);
                xferq->stproc = NULL;
-               for (i = 0; i < xferq->bnchunk; i++) {
-                       m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
-                       xferq->bulkxfer[i].mbuf = m;
-                       m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
-                       STAILQ_INSERT_TAIL(&xferq->stfree,
-                                       &xferq->bulkxfer[i], link);
-               }
+               fw_net_init_iso_chunks(xferq);
                STAILQ_INIT(&fwe->xferlist);
                for (i = 0; i < TX_MAX_QUEUE; i++) {
-                       xfer = fw_xfer_alloc(M_FWE);
+                       xfer = fw_net_alloc_txfer(fwe->fd.fc, tx_speed,
+                           fwe, fwe_output_callback, M_FWE);
                        if (xfer == NULL)
                                break;
-                       xfer->send.spd = tx_speed;
-                       xfer->fc = fwe->fd.fc;
-                       xfer->sc = (caddr_t)fwe;
-                       xfer->hand = fwe_output_callback;
                        STAILQ_INSERT_TAIL(&fwe->xferlist, xfer, link);
                }
        } else
@@ -379,26 +365,11 @@ fwe_ioctl(if_t ifp, u_long cmd, caddr_t data)
 #ifdef DEVICE_POLLING
                    {
                        struct ifreq *ifr = (struct ifreq *) data;
-                       struct firewire_comm *fc = fwe->fd.fc;
-
-                       if (ifr->ifr_reqcap & IFCAP_POLLING &&
-                           !(if_getcapenable(ifp) & IFCAP_POLLING)) {
-                               error = ether_poll_register(fwe_poll, ifp);
-                               if (error)
-                                       return (error);
-                               /* Disable interrupts */
-                               fc->set_intr(fc, 0);
-                               if_setcapenablebit(ifp, IFCAP_POLLING, 0);
-                               return (error);
-                       }
-                       if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
-                           if_getcapenable(ifp) & IFCAP_POLLING) {
-                               error = ether_poll_deregister(ifp);
-                               /* Enable interrupts. */
-                               fc->set_intr(fc, 1);
-                               if_setcapenablebit(ifp, 0, IFCAP_POLLING);
+
+                       error = fw_net_poll_ioctl(ifp, ifr,
+                           fwe->fd.fc, fwe_poll);
+                       if (error >= 0)
                                return (error);
-                       }
                    }
 #endif /* DEVICE_POLLING */
                        break;
@@ -448,17 +419,10 @@ fwe_start(if_t ifp)
        FWEDEBUG(ifp, "starting\n");
 
        if (fwe->dma_ch < 0) {
-               struct mbuf     *m = NULL;
-
                FWEDEBUG(ifp, "not ready\n");
 
                s = splimp();
-               do {
-                       m = if_dequeue(ifp);
-                       if (m != NULL)
-                               m_freem(m);
-                       if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-               } while (m != NULL);
+               fw_net_drain_sendq(ifp);
                splx(s);
 
                return;
diff --git a/sys/dev/firewire/if_fwip.c b/sys/dev/firewire/if_fwip.c
index 42f0c6f53743..0f37ce6a8e41 100644
--- a/sys/dev/firewire/if_fwip.c
+++ b/sys/dev/firewire/if_fwip.c
@@ -65,6 +65,7 @@
 #include <dev/firewire/firewirereg.h>
 #include <dev/firewire/iec13213.h>
 #include <dev/firewire/if_fwipvar.h>
+#include <dev/firewire/fw_net.h>
 
 /*
  * We really need a mechanism for allocating regions in the FIFO
@@ -206,7 +207,6 @@ fwip_stop(struct fwip_softc *fwip)
        struct firewire_comm *fc;
        struct fw_xferq *xferq;
        if_t ifp = fwip->fw_softc.fwip_ifp;
-       struct fw_xfer *xfer, *next;
        int i;
 
        fc = fwip->fd.fc;
@@ -226,17 +226,8 @@ fwip_stop(struct fwip_softc *fwip)
                free(xferq->bulkxfer, M_FWIP);
 
                fw_bindremove(fc, &fwip->fwb);
-               for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL;
-                                       xfer = next) {
-                       next = STAILQ_NEXT(xfer, link);
-                       fw_xfer_free(xfer);
-               }
-
-               for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL;
-                                       xfer = next) {
-                       next = STAILQ_NEXT(xfer, link);
-                       fw_xfer_free(xfer);
-               }
+               FW_NET_FREE_XFERLIST(&fwip->fwb.xferlist);
+               FW_NET_FREE_XFERLIST(&fwip->xferlist);
                STAILQ_INIT(&fwip->xferlist);
 
                xferq->bulkxfer =  NULL;
@@ -311,13 +302,7 @@ fwip_init(void *arg)
                STAILQ_INIT(&xferq->stfree);
                STAILQ_INIT(&xferq->stdma);
                xferq->stproc = NULL;
-               for (i = 0; i < xferq->bnchunk; i++) {
-                       m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
-                       xferq->bulkxfer[i].mbuf = m;
-                       m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
-                       STAILQ_INSERT_TAIL(&xferq->stfree,
-                                       &xferq->bulkxfer[i], link);
-               }
+               fw_net_init_iso_chunks(xferq);
 
                fwip->fwb.start = INET_FIFO;
                fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */
@@ -341,13 +326,10 @@ fwip_init(void *arg)
 
                STAILQ_INIT(&fwip->xferlist);
                for (i = 0; i < TX_MAX_QUEUE; i++) {
-                       xfer = fw_xfer_alloc(M_FWIP);
+                       xfer = fw_net_alloc_txfer(fwip->fd.fc, tx_speed,
+                           fwip, fwip_output_callback, M_FWIP);
                        if (xfer == NULL)
                                break;
-                       xfer->send.spd = tx_speed;
-                       xfer->fc = fwip->fd.fc;
-                       xfer->sc = (caddr_t)fwip;
-                       xfer->hand = fwip_output_callback;
                        STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
                }
        } else
@@ -394,26 +376,11 @@ fwip_ioctl(if_t ifp, u_long cmd, caddr_t data)
 #ifdef DEVICE_POLLING
            {
                struct ifreq *ifr = (struct ifreq *) data;
-               struct firewire_comm *fc = fwip->fd.fc;
-
-               if (ifr->ifr_reqcap & IFCAP_POLLING &&
-                   !(if_getcapenable(ifp) & IFCAP_POLLING)) {
-                       error = ether_poll_register(fwip_poll, ifp);
-                       if (error)
-                               return (error);
-                       /* Disable interrupts */
-                       fc->set_intr(fc, 0);
-                       if_setcapenablebit(ifp, IFCAP_POLLING, 0);
-                       return (error);
-               }
-               if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
-                   if_getcapenable(ifp) & IFCAP_POLLING) {
-                       error = ether_poll_deregister(ifp);
-                       /* Enable interrupts. */
-                       fc->set_intr(fc, 1);
-                       if_setcapenablebit(ifp, 0, IFCAP_POLLING);
+
+               error = fw_net_poll_ioctl(ifp, ifr,
+                   fwip->fd.fc, fwip_poll);
+               if (error >= 0)
                        return (error);
-               }
            }
 #endif /* DEVICE_POLLING */
                break;
@@ -495,17 +462,10 @@ fwip_start(if_t ifp)
        FWIPDEBUG(ifp, "starting\n");
 
        if (fwip->dma_ch < 0) {
-               struct mbuf     *m = NULL;
-
                FWIPDEBUG(ifp, "not ready\n");
 
                s = splimp();
-               do {
-                       m = if_dequeue(ifp);
-                       if (m != NULL)
-                               m_freem(m);
-                       if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-               } while (m != NULL);
+               fw_net_drain_sendq(ifp);
                splx(s);
 
                return;

Reply via email to