Index | Thread | Search

From:
Marcus Glocker <marcus@nazgul.ch>
Subject:
Re: sys/qwz: shutdown firmware after autoconf
To:
"Kirill A. Korinsky" <kirill@korins.ky>
Cc:
tech@openbsd.org
Date:
Mon, 1 Jun 2026 22:27:27 +0200

Download raw body.

Thread
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
>