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