On Wed, Sep 23, 2026 at 06:38:21PM +0200, Peter Hessler wrote:
> On 2026 Sep 23 (Wed) at 10:25:52 +0200 (+0200), Stefan Sperling wrote:
> :On Tue, Sep 22, 2026 at 04:17:55PM +0200, BESSOT Jean-Michel wrote:
> :> Hello
> :>
> :> I do not have network this time but it pass most of the time with those
> :> errors in dmesg.
> :>
> :> Sorry for the bug, i send the dmesg.
> :>
> :> Bye
> :>
> :
> :Can you please try this patch and let me know whether it helps?
> :
> :See
> https://lore.kernel.org/lkml/[email protected]/
> :
>
> OK
Looking at this again, I believe the diff below might be better.
There are many more places where we read or write SRNG descriptors in
memory shared with the device. All these places are surrounded with
the access_begin() and access_end() helpers. Adding DMA syncs there
should ensure that host and device will always get a coherent view
of memory, not just in the particular case fixed in the Linux patch.
Also handle the potential empty packet case a bit better. The Linux
patch is correct in that erroring out early here is bad. It leaves the
ring data structures in an incosistent state. The sw_index counter won't
be updated which means we will be looking at the wrong rx_data pointer
when receiving the next packet.
Does this help with the issues on arm64? ok?
M sys/dev/ic/qwx.c | 10+ 8-
1 file changed, 10 insertions(+), 8 deletions(-)
commit - 37e1413d351ba93bef8686ca531e826712a1b8c4
commit + d59fa2d30f82dbe2ae57563f3ffa4c842e03b60b
blob - f0483d385f461ec6b982d3b34b847b1cb8214ce5
blob + cd972c70046b3b582f2dffc9a528feaca2c7243e
--- sys/dev/ic/qwx.c
+++ sys/dev/ic/qwx.c
@@ -9817,6 +9817,9 @@ qwx_hal_srng_access_begin(struct qwx_softc *sc, struct
} else {
srng->u.dst_ring.cached_hp =
*(volatile uint32_t *)srng->u.dst_ring.hp_addr;
+
+ bus_dmamap_sync(sc->sc_dmat, QWX_DMA_MAP(sc->hal.rdpmem), 0,
+ QWX_DMA_LEN(sc->hal.rdpmem), BUS_DMASYNC_POSTREAD);
}
}
@@ -9826,12 +9829,14 @@ qwx_hal_srng_access_end(struct qwx_softc *sc, struct h
#ifdef notyet
lockdep_assert_held(&srng->lock);
#endif
- /* TODO: See if we need a write memory barrier here */
if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
/* For LMAC rings, ring pointer updates are done through FW and
* hence written to a shared memory location that is read by FW
*/
if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
+ bus_dmamap_sync(sc->sc_dmat,
QWX_DMA_MAP(sc->hal.wrpmem), 0,
+ QWX_DMA_LEN(sc->hal.wrpmem), BUS_DMASYNC_POSTWRITE);
+
srng->u.src_ring.last_tp =
*(volatile uint32_t *)srng->u.src_ring.tp_addr;
*srng->u.src_ring.hp_addr = srng->u.src_ring.hp;
@@ -23017,10 +23022,6 @@ qwx_ce_completed_recv_next(struct qwx_ce_pipe *pipe,
}
*nbytes = qwx_hal_ce_dst_status_get_length(desc);
- if (*nbytes == 0) {
- ret = EIO;
- goto err;
- }
if (per_transfer_contextp) {
*per_transfer_contextp =
@@ -23044,6 +23045,8 @@ int
qwx_ce_recv_process_cb(struct qwx_ce_pipe *pipe)
{
struct qwx_softc *sc = pipe->sc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
struct mbuf *m;
struct mbuf_list ml = MBUF_LIST_INITIALIZER();
void *transfer_context;
@@ -23059,9 +23062,8 @@ qwx_ce_recv_process_cb(struct qwx_ce_pipe *pipe)
rx_data->m = NULL;
max_nbytes = m->m_pkthdr.len;
- if (max_nbytes < nbytes) {
- printf("%s: received more than expected (nbytes %d, "
- "max %d)", __func__, nbytes, max_nbytes);
+ if (nbytes == 0 || max_nbytes < nbytes) {
+ ifp->if_ierrors++;
m_freem(m);
continue;
}