git: 9919c1a8ebd7 - main - firewire: extract shared helpers from fwe and fwip

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Fri, 19 Jun 2026 19:01:31 UTC
The branch main has been updated by adrian:

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

commit 9919c1a8ebd7da0aa86c6475446a7af255ecb17a
Author:     Abdelkader Boudih <freebsd@seuros.com>
AuthorDate: 2026-06-19 19:01:12 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
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 <freebsd@seuros.com>
+ *
+ * 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;