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