git: 9a45c3ca8501 - main - LinuxKPI: 802.11: deal with the error paths for lkpi_xmit()

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Mon, 14 Apr 2025 14:07:39 UTC
The branch main has been updated by bz:

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

commit 9a45c3ca850110c5871742fadbf7355c1085c725
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-04-13 16:59:56 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-04-14 14:06:50 +0000

    LinuxKPI: 802.11: deal with the error paths for lkpi_xmit()
    
    Rename lkpi_ic_raw_xmit() to lkpi_xmit() as we need a wrapper to add
    an extra argument as (*ic_raw_xmit) and (*ic_transmit) have different
    invariants.  Based on the caller free the mbuf in the error case or
    not to satisfy the requirements of the caller.  For more information
    see the comment in the code.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 38 ++++++++++++++++++----------
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 73e1e7b1e1ad..fbbaf860c233 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -4514,9 +4514,20 @@ lkpi_ic_node_free(struct ieee80211_node *ni)
 		lhw->ic_node_free(ni);
 }
 
+/*
+ * lkpi_xmit() called from both the (*ic_raw_xmit) as well as the (*ic_transmit)
+ * call path.
+ * Unfortunately they have slightly different invariants.  See
+ * ieee80211_raw_output() and ieee80211_parent_xmitpkt().
+ * Both take care of the ni reference in case of error, and otherwise during
+ * the callback after transmit.
+ * The difference is that in case of error (*ic_raw_xmit) needs us to release
+ * the mbuf, while (*ic_transmit) will free the mbuf itself.
+ */
 static int
-lkpi_ic_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
-        const struct ieee80211_bpf_params *params __unused)
+lkpi_xmit(struct ieee80211_node *ni, struct mbuf *m,
+    const struct ieee80211_bpf_params *params __unused,
+    bool freem)
 {
 	struct lkpi_sta *lsta;
 	int error;
@@ -4534,11 +4545,8 @@ lkpi_ic_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
 	if (!lsta->txq_ready) {
 #endif
 		LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
-		/*
-		 * Free the mbuf (do NOT release ni ref for the m_pkthdr.rcvif!
-		 * ieee80211_raw_output() does that in case of error).
-		 */
-		m_free(m);
+		if (freem)
+			m_free(m);
 		return (ENETDOWN);
 	}
 
@@ -4546,11 +4554,8 @@ lkpi_ic_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
 	error = mbufq_enqueue(&lsta->txq, m);
 	if (error != 0) {
 		LKPI_80211_LSTA_TXQ_UNLOCK(lsta);
-		/*
-		 * Free the mbuf (do NOT release ni ref for the m_pkthdr.rcvif!
-		 * ieee80211_raw_output() does that in case of error).
-		 */
-		m_free(m);
+		if (freem)
+			m_free(m);
 #ifdef LINUXKPI_DEBUG_80211
 		if (linuxkpi_debug_80211 & D80211_TRACE_TX)
 			ic_printf(ni->ni_ic, "%s: mbufq_enqueue failed: %d\n",
@@ -4571,6 +4576,13 @@ lkpi_ic_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
 	return (0);
 }
 
+static int
+lkpi_ic_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
+        const struct ieee80211_bpf_params *params __unused)
+{
+	return (lkpi_xmit(ni, m, NULL, true));
+}
+
 #ifdef LKPI_80211_HW_CRYPTO
 static int
 lkpi_hw_crypto_prepare(struct lkpi_sta *lsta, struct ieee80211_key *k,
@@ -4929,7 +4941,7 @@ lkpi_ic_transmit(struct ieee80211com *ic, struct mbuf *m)
 	struct ieee80211_node *ni;
 
 	ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
-	return (lkpi_ic_raw_xmit(ni, m, NULL));
+	return (lkpi_xmit(ni, m, NULL, false));
 }
 
 #ifdef LKPI_80211_HT