git: e3a0b1202bf6 - main - LinuxKPI: 80211 / iwlwifi: improve queue management

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Mon, 05 Sep 2022 21:12:24 UTC
The branch main has been updated by bz:

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

commit e3a0b1202bf63f4b412e02eb6edc0fb1f64313de
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2022-09-05 21:03:03 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2022-09-05 21:03:03 +0000

    LinuxKPI: 80211 / iwlwifi: improve queue management
    
    For one initialise vif->hw_queues later set in lkpi_80211_txq_tx_one()
    for drivers using them.  This may still need slightly more cleanup once
    we get QUEUE_CONTROL-supporting drivers into the tree.
    
    For the other rework and improve how we deal with tid/ac/txq in
    lkpi_80211_txq_tx_one() and cleanup old comments and unused code.
    This seems to reduce (remove) "Invalid TXQ id" reports from iwlwifi.
    (The assumption is that the frame(s) triggering this WARN_ONCE or the
    added FreeBSD specific logging were sent with lkpi_80211_mo_tx()).
    
    Adjust the one logging from e674ddec0b4138274539587fe9336b577ff1242a
    to IWL_DEBUG_TX so that now this is fixed it is also not always logged
    anymore but leave it in case we need to further debug queues in the
    future.
    
    Tested by:      pstef, Kevin Oberman (rkoberman gmail.com)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 83 +++++++++++++---------------
 sys/contrib/dev/iwlwifi/mvm/tx.c             |  2 +-
 2 files changed, 39 insertions(+), 46 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 7f8e07dee048..1eb520b2140f 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -316,6 +316,7 @@ lkpi_nl80211_band_to_net80211_band(enum nl80211_band band)
 	return (0x00);
 }
 
+#if 0
 static enum ieee80211_ac_numbers
 lkpi_ac_net_to_l80211(int ac)
 {
@@ -334,6 +335,7 @@ lkpi_ac_net_to_l80211(int ac)
 		return (IEEE80211_AC_BE);
 	}
 }
+#endif
 
 static enum nl80211_iftype
 lkpi_opmode_to_vif_type(enum ieee80211_opmode opmode)
@@ -2196,7 +2198,7 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
 	struct ieee80211_vif *vif;
 	enum ieee80211_bss_changed changed;
 	size_t len;
-	int error;
+	int error, i;
 
 	if (!TAILQ_EMPTY(&ic->ic_vaps))	/* 1 so far. Add <n> once this works. */
 		return (NULL);
@@ -2252,6 +2254,18 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
 	if (vif->bss_conf.beacon_int < 16)
 		vif->bss_conf.beacon_int = 16;
 #endif
+
+	/* Setup queue defaults; driver may override in (*add_interface). */
+	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+		if (ieee80211_hw_check(hw, QUEUE_CONTROL))
+			vif->hw_queue[i] = IEEE80211_INVAL_HW_QUEUE;
+		else if (hw->queues >= IEEE80211_NUM_ACS)
+			vif->hw_queue[i] = i;
+		else
+			vif->hw_queue[i] = 0;
+	}
+	vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
+
 	IMPROVE();
 
 	error = lkpi_80211_mo_start(hw);
@@ -2967,8 +2981,9 @@ lkpi_80211_txq_tx_one(struct lkpi_sta *lsta, struct mbuf *m)
 	struct ieee80211_tx_control control;
 	struct ieee80211_tx_info *info;
 	struct ieee80211_sta *sta;
+	struct ieee80211_hdr *hdr;
 	void *buf;
-	int ac;
+	uint8_t ac, tid;
 
 	M_ASSERTPKTHDR(m);
 #ifdef LINUXKPI_DEBUG_80211
@@ -3047,10 +3062,15 @@ lkpi_80211_txq_tx_one(struct lkpi_sta *lsta, struct mbuf *m)
 	lvif = VAP_TO_LVIF(ni->ni_vap);
 	vif = LVIF_TO_VIF(lvif);
 
-	/* XXX-BZ review this at some point [4] vs. [8] vs. [16](TID). */
-	ac = M_WME_GETAC(m);
-	skb->priority = WME_AC_TO_TID(ac);
-	ac = lkpi_ac_net_to_l80211(ac);
+	hdr = (void *)skb->data;
+	tid = linuxkpi_ieee80211_get_tid(hdr, true);
+	if (tid == IEEE80211_NONQOS_TID) { /* == IEEE80211_NUM_TIDS */
+		skb->priority = 0;
+		ac = IEEE80211_AC_BE;
+	} else {
+		skb->priority = tid & IEEE80211_QOS_CTL_TID_MASK;
+		ac = tid_to_mac80211_ac[tid & 7];
+	}
 	skb_set_queue_mapping(skb, ac);
 
 	info = IEEE80211_SKB_CB(skb);
@@ -3059,7 +3079,7 @@ lkpi_80211_txq_tx_one(struct lkpi_sta *lsta, struct mbuf *m)
 	if (c == NULL || c == IEEE80211_CHAN_ANYC)
 		c = ic->ic_curchan;
 	info->band = lkpi_net80211_chan_to_nl80211_band(c);
-	info->hw_queue = ac;		/* XXX-BZ is this correct? */
+	info->hw_queue = vif->hw_queue[ac];
 	if (m->m_flags & M_EAPOL)
 		info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
 	info->control.vif = vif;
@@ -3079,50 +3099,23 @@ lkpi_80211_txq_tx_one(struct lkpi_sta *lsta, struct mbuf *m)
 
 	if (sta != NULL) {
 		struct lkpi_txq *ltxq;
-		struct ieee80211_hdr *hdr;
 
-		hdr = (void *)skb->data;
-		if (lsta->added_to_drv &&
-		    !ieee80211_is_data_present(hdr->frame_control)) {
-			if (sta->txq[IEEE80211_NUM_TIDS] != NULL)
+		ltxq = NULL;
+		if (!ieee80211_is_data_present(hdr->frame_control)) {
+			if (vif->type == NL80211_IFTYPE_STATION &&
+			    lsta->added_to_drv &&
+			    sta->txq[IEEE80211_NUM_TIDS] != NULL)
 				ltxq = TXQ_TO_LTXQ(sta->txq[IEEE80211_NUM_TIDS]);
-			else
-				goto ops_tx;
-		} else if (lsta->added_to_drv) {
-			ltxq = TXQ_TO_LTXQ(sta->txq[ac]);	/* XXX-BZ re-check */
-		} else
+		} else if (lsta->added_to_drv &&
+		    sta->txq[skb->priority] != NULL) {
+			ltxq = TXQ_TO_LTXQ(sta->txq[skb->priority]);
+		}
+		if (ltxq == NULL)
 			goto ops_tx;
+
 		KASSERT(ltxq != NULL, ("%s: lsta %p sta %p m %p skb %p "
 		    "ltxq %p != NULL\n", __func__, lsta, sta, m, skb, ltxq));
 
-		/*
-		 * We currently do not use queues but do direct TX.
-		 * The exception to the rule is initial packets, as we cannot
-		 * TX until queues are allocated (at least for iwlwifi).
-		 * So we wake_tx_queue in newstate and register any dequeue
-		 * calls.  In the time until then we queue packets and
-		 * let the driver deal with them.
-		 */
-#if 0
-		if (!ltxq->seen_dequeue) {
-
-			/* Prevent an ordering problem, likely other issues. */
-			while (!skb_queue_empty(&ltxq->skbq)) {
-				struct sk_buff *skb2;
-
-				skb2 = skb_dequeue(&ltxq->skbq);
-				if (skb2 != NULL) {
-					memset(&control, 0, sizeof(control));
-					control.sta = sta;
-					lkpi_80211_mo_tx(hw, &control, skb2);
-				}
-			}
-			goto ops_tx;
-		}
-		if (0 && ltxq->seen_dequeue && skb_queue_empty(&ltxq->skbq))
-			goto ops_tx;
-#endif
-
 		skb_queue_tail(&ltxq->skbq, skb);
 #ifdef LINUXKPI_DEBUG_80211
 		if (linuxkpi_debug_80211 & D80211_TRACE_TX)
diff --git a/sys/contrib/dev/iwlwifi/mvm/tx.c b/sys/contrib/dev/iwlwifi/mvm/tx.c
index 303d9b1e5a02..ac96cff455b1 100644
--- a/sys/contrib/dev/iwlwifi/mvm/tx.c
+++ b/sys/contrib/dev/iwlwifi/mvm/tx.c
@@ -1140,7 +1140,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
 
 	if (WARN_ONCE(txq_id == IWL_MVM_INVALID_QUEUE, "Invalid TXQ id")) {
 #if defined(__FreeBSD__)
-		IWL_ERR(mvm, "fc %#06x sta_id %u tid %u txq_id %u mvm %p "
+		IWL_DEBUG_TX(mvm, "fc %#06x sta_id %u tid %u txq_id %u mvm %p "
 		    "skb %p { len %u } info %p sta %p\n", fc, mvmsta->sta_id,
 		    tid, txq_id, mvm, skb, skb->len, info, sta);
 #endif