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;
