Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
Re: sys/qwz: shutdown firmware after autoconf
To:
Marcus Glocker <marcus@nazgul.ch>
Cc:
tech@openbsd.org
Date:
Mon, 01 Jun 2026 22:45:43 +0200

Download raw body.

Thread
On Mon, 01 Jun 2026 22:27:27 +0200,
Marcus Glocker <marcus@nazgul.ch> wrote:
> 
> On Mon, Jun 01, 2026 at 09:50:48PM +0200, Kirill A. Korinsky wrote:
> 
> > tech@,
> > 
> > seems that I had figured out why we need a hack to keep qwz running after
> > autoconf.
> > 
> > So, here I reset pending MHI transfers and the command ring queue counter
> > during shutdown, and remove fw_initialized so the next ifconfig up performs
> > a full firmware boot.
> > 
> > Thoughts? Ok?
> 
> I just gave it a quick spin, but it re-introduces the issue I faced
> before on a NWID switch attempt:
> 
> ifconfig: SIOCS80211NWID: Resource temporarily unavailable
> ifconfig: qwz0: SIOCS80211WPAPSK: Resource temporarily unavailable
> 
> ***
> 
> qwz0: tx credits timeout
> qwz0: failed to send WMI_PDEV_SET_PARAM cmd
> qwz0: failed to enable MESH MCAST ENABLE for pdev 0: 35
> qwz0: tx credits timeout
> qwz0: failed to send WMI_PDEV_SET_PARAM cmd
> qwz0: failed to enable MESH MCAST ENABLE for pdev 0: 35
> qwz0: tx credits timeout
> qwz0: failed to send WMI_PDEV_SET_PARAM cmd
> qwz0: failed to enable MESH MCAST ENABLE for pdev 0: 35
> qwz0: tx credits timeout
> qwz0: failed to send WMI_PDEV_SET_PARAM cmd
> qwz0: failed to enable MESH MCAST ENABLE for pdev 0: 35
>

Does switch from NWID/AP really work on your device?

On my machine I can connect only to one AP per boot. Anything else is ended
with "Resource temporarily unavailable"

> > Index: sys/dev/ic/qwz.c
> > ===================================================================
> > RCS file: /home/cvs/src/sys/dev/ic/qwz.c,v
> > diff -u -p -r1.38 qwz.c
> > --- sys/dev/ic/qwz.c	26 May 2026 14:55:16 -0000	1.38
> > +++ sys/dev/ic/qwz.c	1 Jun 2026 19:26:04 -0000
> > @@ -159,6 +159,7 @@ int qwz_wmi_vdev_install_key(struct qwz_
> >  int qwz_dp_peer_rx_pn_replay_config(struct qwz_softc *, struct qwz_vif *,
> >      struct ieee80211_node *, struct ieee80211_key *, int);
> >  void qwz_setkey_clear(struct qwz_softc *);
> > +void qwz_vif_free_all(struct qwz_softc *);
> >  
> >  int qwz_scan(struct qwz_softc *);
> >  void qwz_scan_abort(struct qwz_softc *);
> > @@ -185,20 +186,6 @@ qwz_init(struct ifnet *ifp)
> >  	struct qwz_softc *sc = ifp->if_softc;
> >  	struct ieee80211com *ic = &sc->sc_ic;
> >  
> > -	/* Firmware stays running across ifconfig down/up; only re-scan. */
> > -	if (sc->fw_initialized) {
> > -		ic->ic_state = IEEE80211_S_INIT;
> > -		sc->ns_nstate = IEEE80211_S_INIT;
> > -		sc->scan.state = ATH12K_SCAN_IDLE;
> > -		if (ifp->if_flags & IFF_UP) {
> > -			refcnt_init(&sc->task_refs);
> > -			ifq_clr_oactive(&ifp->if_snd);
> > -			ifp->if_flags |= IFF_RUNNING;
> > -			ieee80211_begin_scan(ifp);
> > -		}
> > -		return 0;
> > -	}
> > -
> >  	sc->fw_mode = ATH12K_FIRMWARE_MODE_NORMAL;
> >  	/*
> >  	 * There are several known hardware/software crypto issues
> > @@ -300,7 +287,6 @@ qwz_init(struct ifnet *ifp)
> >  		ieee80211_begin_scan(ifp);
> >  	}
> >  
> > -	sc->fw_initialized = 1;
> >  	return 0;
> >  }
> >  
> > @@ -370,12 +356,10 @@ qwz_stop(struct ifnet *ifp)
> >  	sc->scan.state = ATH12K_SCAN_IDLE;
> >  	sc->vdev_id_11d_scan = QWZ_11D_INVALID_VDEV_ID;
> >  
> > -	/*
> > -	 * Firmware stays running across ifconfig down/up; the chip is
> > -	 * only released on driver detach.  Do not clear pdevs_active
> > -	 * or call qwz_core_deinit() here.
> > -	 */
> > +	sc->pdevs_active = 0;
> >  
> > +	qwz_core_deinit(sc);
> > +	qwz_vif_free_all(sc);
> >  	splx(s);
> >  }
> >  
> > @@ -18703,8 +18687,6 @@ qwz_core_deinit(struct qwz_softc *sc)
> >  
> >  	hal->num_shadow_reg_configured = 0;
> >  
> > -	sc->fw_initialized = 0;
> > -
> >  	splx(s);
> >  }
> >  
> > @@ -21787,6 +21769,18 @@ qwz_vif_free(struct qwz_softc *sc, struc
> >  	}
> >  
> >  	free(arvif, M_DEVBUF, sizeof(*arvif));
> > +}
> > +
> > +void
> > +qwz_vif_free_all(struct qwz_softc *sc)
> > +{
> > +	struct qwz_vif *arvif;
> > +
> > +	while (!TAILQ_EMPTY(&sc->vif_list)) {
> > +		arvif = TAILQ_FIRST(&sc->vif_list);
> > +		TAILQ_REMOVE(&sc->vif_list, arvif, entry);
> > +		qwz_vif_free(sc, arvif);
> > +	}
> >  }
> >  
> >  struct qwz_vif *
> > Index: sys/dev/ic/qwzvar.h
> > ===================================================================
> > RCS file: /home/cvs/src/sys/dev/ic/qwzvar.h,v
> > diff -u -p -r1.18 qwzvar.h
> > --- sys/dev/ic/qwzvar.h	26 May 2026 14:55:16 -0000	1.18
> > +++ sys/dev/ic/qwzvar.h	1 Jun 2026 19:26:14 -0000
> > @@ -1971,7 +1971,6 @@ struct qwz_softc {
> >  	struct qwz_survey_info	survey[IEEE80211_CHAN_MAX];
> >  
> >  	int			attached;
> > -	int			fw_initialized;
> >  	struct {
> >  		u_char *data;
> >  		size_t size;
> > Index: sys/dev/pci/if_qwz_pci.c
> > ===================================================================
> > RCS file: /home/cvs/src/sys/dev/pci/if_qwz_pci.c,v
> > diff -u -p -r1.13 if_qwz_pci.c
> > --- sys/dev/pci/if_qwz_pci.c	26 May 2026 14:55:16 -0000	1.13
> > +++ sys/dev/pci/if_qwz_pci.c	1 Jun 2026 19:30:15 -0000
> > @@ -430,6 +430,7 @@ void	qwz_mhi_init_xfer_rings(struct qwz_
> >  void	qwz_mhi_init_event_rings(struct qwz_pci_softc *);
> >  void	qwz_mhi_init_cmd_ring(struct qwz_pci_softc *);
> >  void	qwz_mhi_init_dev_ctxt(struct qwz_pci_softc *);
> > +void	qwz_mhi_reset_xfer_rings(struct qwz_pci_softc *);
> >  int	qwz_mhi_send_cmd(struct qwz_pci_softc *psc, uint32_t, uint32_t);
> >  void *	qwz_pci_xfer_ring_get_elem(struct qwz_pci_xfer_ring *, uint64_t);
> >  struct qwz_xfer_data *qwz_pci_xfer_ring_get_data(struct qwz_pci_xfer_ring *,
> > @@ -2445,6 +2446,7 @@ qwz_mhi_init_cmd_ring(struct qwz_pci_sof
> >  	len = ring->size;
> >  
> >  	ring->rp = ring->wp = paddr;
> > +	ring->queued = 0;
> >  
> >  	c = (struct qwz_mhi_cmd_ctxt *)QWZ_DMA_KVA(psc->cmd_ctxt);
> >  	c->rbase = htole64(paddr);
> > @@ -2464,6 +2466,58 @@ qwz_mhi_init_dev_ctxt(struct qwz_pci_sof
> >  	qwz_mhi_init_cmd_ring(psc);
> >  }
> >  
> > +void
> > +qwz_mhi_reset_xfer_rings(struct qwz_pci_softc *psc)
> > +{
> > +	struct qwz_softc *sc = &psc->sc_sc;
> > +	struct qwz_pci_xfer_ring *ring;
> > +	struct qwz_xfer_data *xfer;
> > +	uint64_t paddr;
> > +	int i, j;
> > +
> > +	for (i = 0; i < nitems(psc->xfer_rings); i++) {
> > +		ring = &psc->xfer_rings[i];
> > +		if (ring->dmamem == NULL)
> > +			continue;
> > +
> > +		for (j = 0; j < ring->num_elements; j++) {
> > +			xfer = &ring->data[j];
> > +			if (ring->mhi_chan_direction == MHI_CHAN_TYPE_OUTBOUND) {
> > +				if (xfer->m == NULL)
> > +					continue;
> > +				bus_dmamap_sync(sc->sc_dmat, xfer->map, 0,
> > +				    xfer->map->dm_mapsize,
> > +				    BUS_DMASYNC_POSTWRITE);
> > +				bus_dmamap_unload(sc->sc_dmat, xfer->map);
> > +				m_freem(xfer->m);
> > +				xfer->m = NULL;
> > +			} else if (xfer->m != NULL) {
> > +				bus_dmamap_sync(sc->sc_dmat, xfer->map, 0,
> > +				    QWZ_PCI_XFER_MAX_DATA_SIZE,
> > +				    BUS_DMASYNC_POSTREAD);
> > +				xfer->m->m_len = xfer->m->m_pkthdr.len =
> > +				    QWZ_PCI_XFER_MAX_DATA_SIZE;
> > +				bus_dmamap_sync(sc->sc_dmat, xfer->map, 0,
> > +				    QWZ_PCI_XFER_MAX_DATA_SIZE,
> > +				    BUS_DMASYNC_PREREAD);
> > +			}
> > +		}
> > +
> > +		paddr = QWZ_DMA_DVA(ring->dmamem);
> > +		ring->rp = ring->wp = paddr;
> > +		ring->queued = 0;
> > +		ring->cmd_status = MHI_EV_CC_INVALID;
> > +		if (ring->chan_ctxt != NULL) {
> > +			ring->chan_ctxt->rp = htole64(paddr);
> > +			ring->chan_ctxt->wp = htole64(paddr);
> > +		}
> > +	}
> > +
> > +	if (psc->chan_ctxt != NULL)
> > +		bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(psc->chan_ctxt), 0,
> > +		    QWZ_DMA_LEN(psc->chan_ctxt), BUS_DMASYNC_PREWRITE);
> > +}
> > +
> >  void *
> >  qwz_pci_cmd_ring_get_elem(struct qwz_pci_cmd_ring *ring, uint64_t ptr)
> >  {
> > @@ -2847,6 +2901,7 @@ void
> >  qwz_mhi_stop(struct qwz_softc *sc)
> >  {
> >  	qwz_mhi_reset_device(sc, 1);
> > +	qwz_mhi_reset_xfer_rings((struct qwz_pci_softc *)sc);
> >  }
> >  
> >  int
> > 
> > 
> > 
> > -- 
> > wbr, Kirill
> > 

-- 
wbr, Kirill