git: 9919c1a8ebd7 - main - firewire: extract shared helpers from fwe and fwip
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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;