Download raw body.
sys/qwz: shutdown firmware after autoconf
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
sys/qwz: shutdown firmware after autoconf