sys/qwz: shutdown firmware after autoconf

Kirill A. Korinsky <[email protected]>
Newsgroups gmane.os.openbsd.tech
Message-ID <[email protected]>
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?

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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.