git: a27b3695d123 - stable/14 - LinuxKPI: 802.11: improvements to (*ampdu_action)() callers

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Thu, 14 Nov 2024 01:53:57 UTC
The branch stable/14 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=a27b3695d12300bd458e0d9efc0780f095691204

commit a27b3695d12300bd458e0d9efc0780f095691204
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2024-01-27 13:24:27 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2024-11-14 01:53:12 +0000

    LinuxKPI: 802.11: improvements to (*ampdu_action)() callers
    
    Annotate lkpi_ic_recv_action(), lkpi_ic_send_action(), and
    lkpi_ic_ampdu_enable() with HT specifc debug logging as we only hook
    them up currently for debug tracing but later should not need them
    anymore.
    
    Start the implementation for lkpi_ic_addba_request(),
    lkpi_ic_addba_response(), and lkpi_ic_addba_stop().
    
    Improve the implementation of lkpi_ic_ampdu_rx_start() and
    lkpi_ic_ampdu_rx_stop().
    
    Sponsored by:   The FreeBSD Foundation (commit)
    
    (cherry picked from commit 310743c4ccc545d58401cb9fb7761432e12a9fb5)
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 206 +++++++++++++++++++++++++--
 1 file changed, 192 insertions(+), 14 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 1a07ef0a82fe..2bb0c2ab113c 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -3992,7 +3992,7 @@ lkpi_ic_recv_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
 	ic = ni->ni_ic;
 	lhw = ic->ic_softc;
 
-	IMPROVE_HT();
+	IMPROVE_HT("recv_action called; nothing to do in lkpi; make debugging");
 
 	return (lhw->ic_recv_action(ni, wh, frm, efrm));
 }
@@ -4006,7 +4006,7 @@ lkpi_ic_send_action(struct ieee80211_node *ni, int category, int action, void *s
 	ic = ni->ni_ic;
 	lhw = ic->ic_softc;
 
-	IMPROVE_HT();
+	IMPROVE_HT("send_action called; nothing to do in lkpi; make debugging");
 
 	return (lhw->ic_send_action(ni, category, action, sa));
 }
@@ -4021,52 +4021,207 @@ lkpi_ic_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
 	ic = ni->ni_ic;
 	lhw = ic->ic_softc;
 
-	IMPROVE_HT();
+	IMPROVE_HT("ieee80211_ampdu_enable called; nothing to do in lkpi for now; make debugging");
 
 	return (lhw->ic_ampdu_enable(ni, tap));
 }
 
+/*
+ * (*ic_addba_request)() is called by ieee80211_ampdu_request() before
+ * calling send_action(CAT_BA, BA_ADDBA_REQUEST).
+ *
+ * NB: returns 0 on ERROR!
+ */
 static int
 lkpi_ic_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
     int dialogtoken, int baparamset, int batimeout)
 {
 	struct ieee80211com *ic;
 	struct lkpi_hw *lhw;
+	struct ieee80211_hw *hw;
+	struct ieee80211vap *vap;
+	struct lkpi_vif *lvif;
+	struct ieee80211_vif *vif;
+	struct lkpi_sta *lsta;
+	struct ieee80211_sta *sta;
+	struct ieee80211_ampdu_params params = { };
+	int error;
 
 	ic = ni->ni_ic;
 	lhw = ic->ic_softc;
+	hw = LHW_TO_HW(lhw);
+	vap = ni->ni_vap;
+	lvif = VAP_TO_LVIF(vap);
+	vif = LVIF_TO_VIF(lvif);
+	lsta = ni->ni_drv_data;
+	sta = LSTA_TO_STA(lsta);
 
-	IMPROVE_HT();
+	if (!lsta->added_to_drv) {
+		ic_printf(ic, "%s: lsta %p ni %p, sta %p not added to firmware\n",
+		    __func__, lsta, ni, sta);
+		return (0);
+	}
+
+	params.sta = sta;
+	params.action = IEEE80211_AMPDU_TX_START;
+	/* Keep 0 here! */
+	params.buf_size = 0;
+	params.timeout = 0;
+	params.ssn = tap->txa_start & (IEEE80211_SEQ_RANGE-1);
+	params.tid = tap->txa_tid;
+	params.amsdu = false;
+
+	IEEE80211_UNLOCK(ic);
+	LKPI_80211_LHW_LOCK(lhw);
+	error = lkpi_80211_mo_ampdu_action(hw, vif, &params);
+	LKPI_80211_LHW_UNLOCK(lhw);
+	IEEE80211_LOCK(ic);
+	if (error != 0) {
+		ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p tap %p\n",
+		    __func__, error, ni, tap);
+		return (0);
+	}
 
 	return (lhw->ic_addba_request(ni, tap, dialogtoken, baparamset, batimeout));
 }
 
+/*
+ * (*ic_addba_response)() is called from ht_recv_action_ba_addba_response()
+ * and calls the default ieee80211_addba_response() which always returns 1.
+ *
+ * NB: No error checking in net80211!
+ * Staying with 0 is an error.
+ */
 static int
 lkpi_ic_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
     int status, int baparamset, int batimeout)
 {
 	struct ieee80211com *ic;
 	struct lkpi_hw *lhw;
+	struct ieee80211_hw *hw;
+	struct ieee80211vap *vap;
+	struct lkpi_vif *lvif;
+	struct ieee80211_vif *vif;
+	struct lkpi_sta *lsta;
+	struct ieee80211_sta *sta;
+	struct ieee80211_ampdu_params params = { };
+	int error;
 
 	ic = ni->ni_ic;
 	lhw = ic->ic_softc;
+	hw = LHW_TO_HW(lhw);
+	vap = ni->ni_vap;
+	lvif = VAP_TO_LVIF(vap);
+	vif = LVIF_TO_VIF(lvif);
+	lsta = ni->ni_drv_data;
+	sta = LSTA_TO_STA(lsta);
 
-	IMPROVE_HT();
+	if (!lsta->added_to_drv) {
+		ic_printf(ic, "%s: lsta %p ni %p, sta %p not added to firmware\n",
+		    __func__, lsta, ni, sta);
+		return (0);
+	}
+
+	if (status == IEEE80211_STATUS_SUCCESS) {
+		params.sta = sta;
+		params.action = IEEE80211_AMPDU_TX_OPERATIONAL;
+		params.buf_size = tap->txa_wnd;
+		params.timeout = 0;
+		params.ssn = 0;
+		params.tid = tap->txa_tid;
+		if ((tap->txa_flags & IEEE80211_AGGR_AMSDU) != 0)
+			params.amsdu = true;
+		else
+			params.amsdu = false;
+	} else {
+		/* We need to free the allocated resources. */
+		params.sta = sta;
+		switch (status) {
+			/* params.action = FLUSH, FLUSH_CONT */
+		default:
+			params.action = IEEE80211_AMPDU_TX_STOP_CONT;
+			break;
+		}
+		params.buf_size = 0;
+		params.timeout = 0;
+		params.ssn = 0;
+		params.tid = tap->txa_tid;
+		params.amsdu = false;
+	}
+
+	IEEE80211_UNLOCK(ic);
+	LKPI_80211_LHW_LOCK(lhw);
+	error = lkpi_80211_mo_ampdu_action(hw, vif, &params);
+	LKPI_80211_LHW_UNLOCK(lhw);
+	IEEE80211_LOCK(ic);
+	if (error != 0) {
+		ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p tap %p\n",
+		    __func__, error, ni, tap);
+		return (0);
+	}
+
+	IMPROVE_HT("who unleashes the TXQ? and when?, do we need to ni->ni_txseqs[tid] = tap->txa_start & 0xfff;");
 
 	return (lhw->ic_addba_response(ni, tap, status, baparamset, batimeout));
 }
 
+/*
+ * (*ic_addba_stop)() is called from ampdu_tx_stop(), ht_recv_action_ba_delba(),
+ * and ieee80211_ampdu_stop() and calls the default ieee80211_addba_stop().
+ */
 static void
 lkpi_ic_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
 {
 	struct ieee80211com *ic;
 	struct lkpi_hw *lhw;
+	struct ieee80211_hw *hw;
+	struct ieee80211vap *vap;
+	struct lkpi_vif *lvif;
+	struct ieee80211_vif *vif;
+	struct lkpi_sta *lsta;
+	struct ieee80211_sta *sta;
+	struct ieee80211_ampdu_params params = { };
+	int error;
 
 	ic = ni->ni_ic;
 	lhw = ic->ic_softc;
+	hw = LHW_TO_HW(lhw);
+	vap = ni->ni_vap;
+	lvif = VAP_TO_LVIF(vap);
+	vif = LVIF_TO_VIF(lvif);
+	lsta = ni->ni_drv_data;
+	sta = LSTA_TO_STA(lsta);
 
-	IMPROVE_HT();
+	if (!lsta->added_to_drv) {
+		ic_printf(ic, "%s: lsta %p ni %p, sta %p not added to firmware\n",
+		    __func__, lsta, ni, sta);
+		goto n80211;
+	}
 
+	/* We need to free the allocated resources. */
+	params.sta = sta;
+	IMPROVE("net80211 does not provide a reason to us");
+	params.action = IEEE80211_AMPDU_TX_STOP_CONT; /* params.action = FLUSH, FLUSH_CONT */
+	params.buf_size = 0;
+	params.timeout = 0;
+	params.ssn = 0;
+	params.tid = tap->txa_tid;
+	params.amsdu = false;
+
+	IEEE80211_UNLOCK(ic);
+	LKPI_80211_LHW_LOCK(lhw);
+	error = lkpi_80211_mo_ampdu_action(hw, vif, &params);
+	LKPI_80211_LHW_UNLOCK(lhw);
+	IEEE80211_LOCK(ic);
+	if (error != 0) {
+		ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p tap %p\n",
+		    __func__, error, ni, tap);
+		goto n80211;
+	}
+
+	IMPROVE_HT("anyting else?");
+
+n80211:
 	lhw->ic_addba_stop(ni, tap);
 }
 
@@ -4110,8 +4265,8 @@ lkpi_ic_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap
 	struct lkpi_vif *lvif;
 	struct ieee80211_vif *vif;
 	struct lkpi_sta *lsta;
-        struct ieee80211_sta *sta;
-	struct ieee80211_ampdu_params params;
+	struct ieee80211_sta *sta;
+	struct ieee80211_ampdu_params params = { };
 	int error;
 
 	ic = ni->ni_ic;
@@ -4123,6 +4278,14 @@ lkpi_ic_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap
 	lsta = ni->ni_drv_data;
 	sta = LSTA_TO_STA(lsta);
 
+	IEEE80211_UNLOCK_ASSERT(ic);
+
+	if (!lsta->added_to_drv) {
+		ic_printf(ic, "%s: lsta %p ni %p vap %p, sta %p not added to firmware\n",
+		    __func__, lsta, ni, vap, sta);
+		return (-ENXIO);
+	}
+
 	params.sta = sta;
 	params.action = IEEE80211_AMPDU_RX_START;
 	params.buf_size = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_BUFSIZ);
@@ -4130,22 +4293,33 @@ lkpi_ic_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap
 		params.buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
 	else
 		params.buf_size = min(params.buf_size, IEEE80211_MAX_AMPDU_BUF_HT);
-	if (params.buf_size > hw->max_rx_aggregation_subframes)
+	if (hw->max_rx_aggregation_subframes > 0 &&
+	    params.buf_size > hw->max_rx_aggregation_subframes)
 		params.buf_size = hw->max_rx_aggregation_subframes;
 	params.timeout = le16toh(batimeout);
 	params.ssn = _IEEE80211_MASKSHIFT(le16toh(baseqctl), IEEE80211_BASEQ_START);
 	params.tid = _IEEE80211_MASKSHIFT(le16toh(baparamset), IEEE80211_BAPS_TID);
-	params.amsdu = false;
 
-	IMPROVE_HT("Do we need to distinguish based on SUPPORTS_REORDERING_BUFFER?");
+	/* Based on net80211::ampdu_rx_start(). */
+	if ((vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU) &&
+	    (_IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU)))
+		params.amsdu = true;
+	else
+		params.amsdu = false;
 
-	/* This may call kalloc.  Make sure we can sleep. */
+	LKPI_80211_LHW_LOCK(lhw);
 	error = lkpi_80211_mo_ampdu_action(hw, vif, &params);
+	LKPI_80211_LHW_UNLOCK(lhw);
 	if (error != 0) {
 		ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p rap %p\n",
 		    __func__, error, ni, rap);
 		return (error);
 	}
+
+	if (!ieee80211_hw_check(hw, SUPPORTS_REORDERING_BUFFER)) {
+		IMPROVE("%s: TODO: SUPPORTS_REORDERING_BUFFER not set; check net80211\n", __func__);
+	}
+
 	IMPROVE_HT("net80211 is missing the error check on return and assumes success");
 
 	error = lhw->ic_ampdu_rx_start(ni, rap, baparamset, batimeout, baseqctl);
@@ -4162,8 +4336,8 @@ lkpi_ic_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
 	struct lkpi_vif *lvif;
 	struct ieee80211_vif *vif;
 	struct lkpi_sta *lsta;
-        struct ieee80211_sta *sta;
-	struct ieee80211_ampdu_params params;
+	struct ieee80211_sta *sta;
+	struct ieee80211_ampdu_params params = { };
 	int error;
 	uint8_t tid;
 
@@ -4203,7 +4377,11 @@ lkpi_ic_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
 	params.tid = tid;
 	params.amsdu = false;
 
+	// IEEE80211_UNLOCK(ic);
+	LKPI_80211_LHW_LOCK(lhw);
 	error = lkpi_80211_mo_ampdu_action(hw, vif, &params);
+	LKPI_80211_LHW_UNLOCK(lhw);
+	// IEEE80211_LOCK(ic);
 	if (error != 0)
 		ic_printf(ic, "%s: mo_ampdu_action returned %d. ni %p rap %p\n",
 		    __func__, error, ni, rap);