From: Kirill A. Korinsky Subject: Re: sys/qwz: shutdown firmware after autoconf To: Marcus Glocker Cc: tech@openbsd.org Date: Mon, 01 Jun 2026 22:45:43 +0200 On Mon, 01 Jun 2026 22:27:27 +0200, Marcus Glocker 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