Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: sys/qwz: add AMPDU callbacks
To:
tech@openbsd.org
Date:
Tue, 26 May 2026 15:46:50 +0200

Download raw body.

Thread
On Tue, May 26, 2026 at 03:24:05PM +0200, Kirill A. Korinsky wrote:
> tech@,
> 
> here I added the same BlockAck task and AMPDU callback plumbing used by qwx.
> 
> This wires net80211 ADDBA/DELBA handling into the existing qwz RX
> TID/reorder setup code, while leaving TX aggregation to firmware as qwx.

> Ok?

Looks good to me! ok.
 
> Index: sys/dev/ic/qwz.c
> ===================================================================
> RCS file: /home/cvs/src/sys/dev/ic/qwz.c,v
> diff -u -p -r1.36 qwz.c
> --- sys/dev/ic/qwz.c	25 May 2026 20:33:58 -0000	1.36
> +++ sys/dev/ic/qwz.c	26 May 2026 13:11:21 -0000
> @@ -345,6 +345,7 @@ qwz_stop(struct ifnet *ifp)
>  	task_del(systq, &sc->init_task);
>  	qwz_del_task(sc, sc->sc_nswq, &sc->newstate_task);
>  	qwz_del_task(sc, systq, &sc->setkey_task);
> +	qwz_del_task(sc, systq, &sc->ba_task);
>  	refcnt_finalize(&sc->task_refs, "qwzstop");
>  
>  	qwz_setkey_clear(sc);
> @@ -868,9 +869,7 @@ qwz_newstate(struct ieee80211com *ic, en
>  	    nstate != IEEE80211_S_AUTH)
>  		return 0;
>  	if (ic->ic_state == IEEE80211_S_RUN) {
> -#if 0
>  		qwz_del_task(sc, systq, &sc->ba_task);
> -#endif
>  		qwz_del_task(sc, systq, &sc->setkey_task);
>  		qwz_setkey_clear(sc);
>  #if 0
> @@ -24432,6 +24431,116 @@ qwz_peer_assoc_prepare(struct qwz_softc 
>  	/* TODO: amsdu_disable req? */
>  }
>  
> +void
> +qwz_rx_agg_start(struct qwz_softc *sc, struct ieee80211_node *ni, uint8_t tid,
> +    uint16_t ssn, uint16_t winsize)
> +{
> +	struct ieee80211com *ic = &sc->sc_ic;
> +	struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
> +	uint8_t pdev_id = 0; /* XXX derive pdev ID somehow */
> +	enum hal_pn_type pn_type;
> +
> +	if (!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, sc->sc_flags) &&
> +	    (ic->ic_flags & IEEE80211_F_RSNON))
> +		pn_type = HAL_PN_TYPE_WPA;
> +	else
> +		pn_type = HAL_PN_TYPE_NONE;
> +
> +	if (qwz_peer_rx_tid_setup(sc, ni, arvif->vdev_id, pdev_id, tid,
> +	    winsize, ssn, pn_type))
> +		ieee80211_addba_req_refuse(ic, ni, tid);
> +	else
> +		ieee80211_addba_req_accept(ic, ni, tid);
> +}
> +
> +void
> +qwz_rx_agg_stop(struct qwz_softc *sc, struct ieee80211_node *ni, uint8_t tid)
> +{
> +	struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
> +	uint8_t pdev_id = 0; /* XXX derive pdev ID somehow */
> +	struct qwz_node *nq = (struct qwz_node *)ni;
> +	struct ath12k_peer *peer = &nq->peer;
> +	uint64_t paddr;
> +	int ret;
> +
> +	if (peer->peer_id == HAL_INVALID_PEERID)
> +		return;
> +
> +	if (!peer->rx_tid[tid].active)
> +		return;
> +
> +	ret = qwz_peer_rx_tid_reo_update(sc, peer, &peer->rx_tid[tid],
> +	    1, 0, 0);
> +	if (ret) {
> +		printf("%s: failed to update reo for rx tid %d: %d\n",
> +		    sc->sc_dev.dv_xname, tid, ret);
> +	}
> +
> +	paddr = peer->rx_tid[tid].paddr;
> +	ret = qwz_wmi_peer_rx_reorder_queue_setup(sc, arvif->vdev_id, pdev_id,
> +	    ni->ni_macaddr, paddr, tid, 1, 1);
> +	if (ret) {
> +		printf("%s: failed to send wmi to delete rx tid %d\n",
> +		    sc->sc_dev.dv_xname, ret);
> +	}
> +}
> +
> +void
> +qwz_ba_task(void *arg)
> +{
> +	struct qwz_softc *sc = arg;
> +	struct ieee80211com *ic = &sc->sc_ic;
> +	struct ieee80211_node *ni = ic->ic_bss;
> +	int s = splnet();
> +	int tid;
> +
> +	for (tid = 0; tid < IEEE80211_NUM_TID; tid++) {
> +		if (test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags))
> +			break;
> +		if (sc->ba_rx.start_tidmask & (1 << tid)) {
> +			struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
> +			qwz_rx_agg_start(sc, ni, tid, ba->ba_winstart,
> +			    ba->ba_winsize);
> +			sc->ba_rx.start_tidmask &= ~(1 << tid);
> +		} else if (sc->ba_rx.stop_tidmask & (1 << tid)) {
> +			qwz_rx_agg_stop(sc, ni, tid);
> +			sc->ba_rx.stop_tidmask &= ~(1 << tid);
> +		}
> +	}
> +
> +	refcnt_rele_wake(&sc->task_refs);
> +	splx(s);
> +}
> +
> +int
> +qwz_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
> +    uint8_t tid)
> +{
> +	struct qwz_softc *sc = ic->ic_softc;
> +
> +	sc->ba_rx.start_tidmask |= (1 << tid);
> +	qwz_add_task(sc, systq, &sc->ba_task);
> +	return EBUSY;
> +}
> +
> +void
> +qwz_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni,
> +    uint8_t tid)
> +{
> +	struct qwz_softc *sc = ic->ic_softc;
> +
> +	sc->ba_rx.stop_tidmask |= (1 << tid);
> +	qwz_add_task(sc, systq, &sc->ba_task);
> +}
> +
> +int
> +qwz_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni,
> +    uint8_t tid)
> +{
> +	/* Firmware handles Tx aggregation internally. */
> +	return 0;
> +}
> +
>  int
>  qwz_run(struct qwz_softc *sc)
>  {
> @@ -24608,6 +24717,7 @@ qwz_attach(struct qwz_softc *sc)
>  	task_set(&sc->init_task, qwz_init_task, sc);
>  	task_set(&sc->newstate_task, qwz_newstate_task, sc);
>  	task_set(&sc->setkey_task, qwz_setkey_task, sc);
> +	task_set(&sc->ba_task, qwz_ba_task, sc);
>  	timeout_set_proc(&sc->scan.timeout, qwz_scan_timeout, sc);
>  #if NBPFILTER > 0
>  	qwz_radiotap_attach(sc);
> Index: sys/dev/ic/qwzvar.h
> ===================================================================
> RCS file: /home/cvs/src/sys/dev/ic/qwzvar.h,v
> diff -u -p -r1.17 qwzvar.h
> --- sys/dev/ic/qwzvar.h	19 May 2026 04:17:51 -0000	1.17
> +++ sys/dev/ic/qwzvar.h	26 May 2026 13:10:36 -0000
> @@ -1910,6 +1910,11 @@ struct qwz_setkey_task_arg {
>  #define QWZ_DEL_KEY	2
>  };
>  
> +struct qwz_ba_task_data {
> +	uint32_t		start_tidmask;
> +	uint32_t		stop_tidmask;
> +};
> +
>  struct qwz_softc {
>  	struct device			sc_dev;
>  	struct ieee80211com		sc_ic;
> @@ -1944,6 +1949,10 @@ struct qwz_softc {
>  	int install_key_done;
>  	int install_key_status;
>  
> +	/* Task for firmware BlockAck setup/teardown and its arguments. */
> +	struct task		ba_task;
> +	struct qwz_ba_task_data	ba_rx;
> +
>  	enum ath12k_11d_state	state_11d;
>  	int			completed_11d_scan;
>  	uint32_t		vdev_id_11d_scan;
> @@ -2161,6 +2170,12 @@ int	qwz_set_key(struct ieee80211com *, s
>      struct ieee80211_key *);
>  void	qwz_delete_key(struct ieee80211com *, struct ieee80211_node *,
>      struct ieee80211_key *);
> +int	qwz_ampdu_rx_start(struct ieee80211com *, struct ieee80211_node *,
> +	    uint8_t);
> +void	qwz_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *,
> +	    uint8_t);
> +int	qwz_ampdu_tx_start(struct ieee80211com *, struct ieee80211_node *,
> +	    uint8_t);
>  
>  void	qwz_qrtr_recv_msg(struct qwz_softc *, struct mbuf *);
>  
> 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.11 if_qwz_pci.c
> --- sys/dev/pci/if_qwz_pci.c	18 May 2026 13:47:32 -0000	1.11
> +++ sys/dev/pci/if_qwz_pci.c	26 May 2026 13:10:36 -0000
> @@ -1007,6 +1007,10 @@ qwz_pci_attach(struct device *parent, st
>  	ic->ic_updateedca = qwz_updateedca;
>  	ic->ic_updatedtim = qwz_updatedtim;
>  #endif
> +	ic->ic_ampdu_rx_start = qwz_ampdu_rx_start;
> +	ic->ic_ampdu_rx_stop = qwz_ampdu_rx_stop;
> +	ic->ic_ampdu_tx_start = qwz_ampdu_tx_start;
> +	ic->ic_ampdu_tx_stop = NULL;
>  	/*
>  	 * We cannot read the MAC address without loading the
>  	 * firmware from disk. Postpone until mountroot is done.
> 
> 
> -- 
> wbr, Kirill
> 
>