From nobody Thu Feb 22 22:49:19 2024 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4TgpH424xJz5BbCJ; Thu, 22 Feb 2024 22:49:20 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4TgpH36hPnz4GBn; Thu, 22 Feb 2024 22:49:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708642159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ibA8Ca8V+2OE850wgNogmc1I1r8zXCJg3i1AonV6ULg=; b=gMnGuqmgoW4NX1qUpT/oFPOWp7iPP1zRwIGmJNpsOkX4PCiMYNBgZuTzV6aPuvC5ideQGb NPqo/6K2xfkfzj3dJhAHwoXBbZGiww3Ph5N9owiwtist728Cx8uNNybLnMvJrspUmWAcH4 BZ6Mwmp9iwlKmdgL/53uoMjybP0bhykPR3thLiNc/ZdBP5wYRF5Fx6o8UWaAJkcvGHR/zB rakMEgL46TW1BWpYWi1/Ggdgm5PyC4FMlKLsBgG0m0YD3fUK9MNGSDs4APdl3wXMCmUnHG BdpSwRHvj76zFCzHaETSOin/BuUJ5IU4cEPx+wXG7tdQpjXQD9sZtI97JGl9sg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708642159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=ibA8Ca8V+2OE850wgNogmc1I1r8zXCJg3i1AonV6ULg=; b=QsPcJRzI+azsRp7wt9YMtTrwZi2VNpgWpu55W/IwZsFqeaFUESQ1RoDx7n45ocWTjRQXQk VsRVII3T12Sl7PoPJU88PGX/xjcq/P7ax3aIE1+0lDLjyBolQ/leS546KAq8JQUkcMHO5l vtRSoDNIeeHfqXd3LsDI/6sCdY+ihWOlqsQ/du/7En7Um2JtUmJuDRAOmxb2mZQauWCUba 9aEbr2GqEvF6RquJWPTWlz1MOLieuNQ/X/LhpI1C5EBagl0JdACur8nbHRlJNENIEOPIgI cYwwaesKpomfyi6fs0EwywyRiS1FVKBPclqCHPWDoYMA8xzZ0L4+lJWNMMxe3w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1708642159; a=rsa-sha256; cv=none; b=JcRt3NBNDtkDHttKbd7n2lxkkyu2cnMj/RfKUOKRJxED6e4PXXoQzj+tHcGAcFfGLsd+bU I+gCMttNvzrEJmESpLbQaZmFVrwXevXAQkSmqGg7OHOPcP0IrBaZdPInh6kDSysQSjvtX+ RCpQ4WNG5nM+PTic2HqrXOPAd4+z+c63IfoY8pNsg5n44p/lAIIsOmcnCjzSMUfOlfYxVq gJGfJga/KOP/Zxm/iISewdg29e7I/bxM8REG99/85jT8ZTM+j+zCewTPGU2JbALLYw1bPG VmetG4M2tW9UNN9ljX23qAialIyDYhegcd/pbzE/u++UfneZxwOXjgMIRgaMDw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4TgpH35n3szqcf; Thu, 22 Feb 2024 22:49:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 41MMnJIU060610; Thu, 22 Feb 2024 22:49:19 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 41MMnJMO060607; Thu, 22 Feb 2024 22:49:19 GMT (envelope-from git) Date: Thu, 22 Feb 2024 22:49:19 GMT Message-Id: <202402222249.41MMnJMO060607@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 759a996d610d - main - LinuxKPI: 802.11: implement a deferred RX path List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bz X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 759a996d610d9354aac5c48a6bdc9cedcba2f48b Auto-Submitted: auto-generated The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=759a996d610d9354aac5c48a6bdc9cedcba2f48b commit 759a996d610d9354aac5c48a6bdc9cedcba2f48b Author: Bjoern A. Zeeb AuthorDate: 2024-02-12 16:03:13 +0000 Commit: Bjoern A. Zeeb CommitDate: 2024-02-22 22:46:48 +0000 LinuxKPI: 802.11: implement a deferred RX path Some calls, e.g., action frames cause us to call through all the way down to firmware from the RX path without any deferral in net80211. For LinuxKPI and iwlwifi this goes (with omissions) like this: lkpi_napi_task -> linuxkpi_ieee80211_rx -> ieee80211_input_mimo -> sta_input -> ht_recv_action_ba_addba_request -> lkpi_ic_ampdu_rx_start -> iwl_mvm_mac_ampdu_action -> iwl_trans_txq_send_hcmd. At that point we are waiting for an interrupt from the firmware but given the lkpi_napi_task has not finished (and may have more to dispatch based on budget and what was received) we will not see the new interrupt/fw response. With no answer from the firmware, the software timeout in the driver kills the command and the firmware and issues a complete restart. Implement the deferred RX path in LinuxKPI for the moment. At a later point we should carefully shift this into net80211. This fixes the hangs for (*ic_ampdu_rx_start)() calls with iwlwifi. MFC after: 3 days PR: 276083 Reviewed by: cc Differential Revision: https://reviews.freebsd.org/D43968 --- sys/compat/linuxkpi/common/src/linux_80211.c | 134 ++++++++++++++++++++++++--- sys/compat/linuxkpi/common/src/linux_80211.h | 31 +++++++ 2 files changed, 154 insertions(+), 11 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index 6ed5722ab998..ced2f2dc8cca 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -144,6 +144,7 @@ const struct cfg80211_ops linuxkpi_mac80211cfgops = { static struct lkpi_sta *lkpi_find_lsta_by_ni(struct lkpi_vif *, struct ieee80211_node *); static void lkpi_80211_txq_task(void *, int); +static void lkpi_80211_lhw_rxq_task(void *, int); static void lkpi_ieee80211_free_skb_mbuf(void *); #ifdef LKPI_80211_WME static int lkpi_wme_update(struct lkpi_hw *, struct ieee80211vap *, bool); @@ -4271,6 +4272,12 @@ linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops) TAILQ_INIT(&lhw->scheduled_txqs[ac]); } + /* Deferred RX path. */ + LKPI_80211_LHW_RXQ_LOCK_INIT(lhw); + TASK_INIT(&lhw->rxq_task, 0, lkpi_80211_lhw_rxq_task, lhw); + mbufq_init(&lhw->rxq, IFQ_MAXLEN); + lhw->rxq_stopped = false; + /* * XXX-BZ TODO make sure there is a "_null" function to all ops * not initialized. @@ -4296,11 +4303,42 @@ void linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw) { struct lkpi_hw *lhw; + struct mbuf *m; lhw = HW_TO_LHW(hw); free(lhw->ic, M_LKPI80211); lhw->ic = NULL; + /* + * Drain the deferred RX path. + */ + LKPI_80211_LHW_RXQ_LOCK(lhw); + lhw->rxq_stopped = true; + LKPI_80211_LHW_RXQ_UNLOCK(lhw); + + /* Drain taskq, won't be restarted due to rxq_stopped being set. */ + while (taskqueue_cancel(taskqueue_thread, &lhw->rxq_task, NULL) != 0) + taskqueue_drain(taskqueue_thread, &lhw->rxq_task); + + /* Flush mbufq (make sure to release ni refs!). */ + m = mbufq_dequeue(&lhw->rxq); + while (m != NULL) { + struct m_tag *mtag; + + mtag = m_tag_locate(m, MTAG_ABI_LKPI80211, LKPI80211_TAG_RXNI, NULL); + if (mtag != NULL) { + struct lkpi_80211_tag_rxni *rxni; + + rxni = (struct lkpi_80211_tag_rxni *)(mtag + 1); + ieee80211_free_node(rxni->ni); + } + m_freem(m); + m = mbufq_dequeue(&lhw->rxq); + } + KASSERT(mbufq_empty(&lhw->rxq), ("%s: lhw %p has rxq len %d != 0\n", + __func__, lhw, mbufq_len(&lhw->rxq))); + LKPI_80211_LHW_RXQ_LOCK_DESTROY(lhw); + /* Cleanup more of lhw here or in wiphy_free()? */ LKPI_80211_LHW_TXQ_LOCK_DESTROY(lhw); LKPI_80211_LHW_SCAN_LOCK_DESTROY(lhw); @@ -4795,6 +4833,66 @@ linuxkpi_ieee80211_scan_completed(struct ieee80211_hw *hw, return; } +static void +lkpi_80211_lhw_rxq_rx_one(struct lkpi_hw *lhw, struct mbuf *m) +{ + struct ieee80211_node *ni; + struct m_tag *mtag; + int ok; + + ni = NULL; + mtag = m_tag_locate(m, MTAG_ABI_LKPI80211, LKPI80211_TAG_RXNI, NULL); + if (mtag != NULL) { + struct lkpi_80211_tag_rxni *rxni; + + rxni = (struct lkpi_80211_tag_rxni *)(mtag + 1); + ni = rxni->ni; + } + + if (ni != NULL) { + ok = ieee80211_input_mimo(ni, m); + ieee80211_free_node(ni); /* Release the reference. */ + if (ok < 0) + m_freem(m); + } else { + ok = ieee80211_input_mimo_all(lhw->ic, m); + /* mbuf got consumed. */ + } + +#ifdef LINUXKPI_DEBUG_80211 + if (linuxkpi_debug_80211 & D80211_TRACE_RX) + printf("TRACE %s: handled frame type %#0x\n", __func__, ok); +#endif +} + +static void +lkpi_80211_lhw_rxq_task(void *ctx, int pending) +{ + struct lkpi_hw *lhw; + struct mbufq mq; + struct mbuf *m; + + lhw = ctx; + +#ifdef LINUXKPI_DEBUG_80211 + if (linuxkpi_debug_80211 & D80211_TRACE_RX) + printf("%s:%d lhw %p pending %d mbuf_qlen %d\n", + __func__, __LINE__, lhw, pending, mbufq_len(&lhw->rxq)); +#endif + + mbufq_init(&mq, IFQ_MAXLEN); + + LKPI_80211_LHW_RXQ_LOCK(lhw); + mbufq_concat(&mq, &lhw->rxq); + LKPI_80211_LHW_RXQ_UNLOCK(lhw); + + m = mbufq_dequeue(&mq); + while (m != NULL) { + lkpi_80211_lhw_rxq_rx_one(lhw, m); + m = mbufq_dequeue(&mq); + } +} + /* For %list see comment towards the end of the function. */ void linuxkpi_ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, @@ -5018,20 +5116,34 @@ skip_device_ts: } #endif + /* + * Attach meta-information to the mbuf for the deferred RX path. + * Currently this is best-effort. Should we need to be hard, + * drop the frame and goto err; + */ if (ni != NULL) { - ok = ieee80211_input_mimo(ni, m); - ieee80211_free_node(ni); - if (ok < 0) - m_freem(m); - } else { - ok = ieee80211_input_mimo_all(ic, m); - /* mbuf got consumed. */ + struct m_tag *mtag; + struct lkpi_80211_tag_rxni *rxni; + + mtag = m_tag_alloc(MTAG_ABI_LKPI80211, LKPI80211_TAG_RXNI, + sizeof(*rxni), IEEE80211_M_NOWAIT); + if (mtag != NULL) { + rxni = (struct lkpi_80211_tag_rxni *)(mtag + 1); + rxni->ni = ni; /* We hold a reference. */ + m_tag_prepend(m, mtag); + } } -#ifdef LINUXKPI_DEBUG_80211 - if (linuxkpi_debug_80211 & D80211_TRACE_RX) - printf("TRACE %s: handled frame type %#0x\n", __func__, ok); -#endif + LKPI_80211_LHW_RXQ_LOCK(lhw); + if (lhw->rxq_stopped) { + LKPI_80211_LHW_RXQ_UNLOCK(lhw); + m_freem(m); + goto err; + } + + mbufq_enqueue(&lhw->rxq, m); + taskqueue_enqueue(taskqueue_thread, &lhw->rxq_task); + LKPI_80211_LHW_RXQ_UNLOCK(lhw); IMPROVE(); diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index d25614de56dc..b0156a5ade3f 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -76,6 +76,18 @@ if (linuxkpi_debug_80211 & D80211_TRACE_MODE_HT) \ printf("%s:%d: XXX LKPI80211 IMPROVE_HT\n", __func__, __LINE__) +#define MTAG_ABI_LKPI80211 1707696513 /* LinuxKPI 802.11 KBI */ + +/* + * Deferred RX path. + * We need to pass *ni along (and possibly more in the future so + * we use a struct right from the start. + */ +#define LKPI80211_TAG_RXNI 0 /* deferred RX path */ +struct lkpi_80211_tag_rxni { + struct ieee80211_node *ni; /* MUST hold a reference to it. */ +}; + struct lkpi_radiotap_tx_hdr { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; @@ -192,6 +204,11 @@ struct lkpi_hw { /* name it mac80211_sc? */ uint32_t txq_generation[IEEE80211_NUM_ACS]; TAILQ_HEAD(, lkpi_txq) scheduled_txqs[IEEE80211_NUM_ACS]; + /* Deferred RX path. */ + struct task rxq_task; + struct mbufq rxq; + struct mtx rxq_mtx; + /* Scan functions we overload to handle depending on scan mode. */ void (*ic_scan_curchan)(struct ieee80211_scan_state *, unsigned long); @@ -240,6 +257,7 @@ struct lkpi_hw { /* name it mac80211_sc? */ bool update_mc; bool update_wme; + bool rxq_stopped; /* Must be last! */ struct ieee80211_hw hw __aligned(CACHE_LINE_SIZE); @@ -304,6 +322,19 @@ struct lkpi_wiphy { #define LKPI_80211_LHW_TXQ_UNLOCK_ASSERT(_lhw) \ mtx_assert(&(_lhw)->txq_mtx, MA_NOTOWNED) +#define LKPI_80211_LHW_RXQ_LOCK_INIT(_lhw) \ + mtx_init(&(_lhw)->rxq_mtx, "lhw-rxq", NULL, MTX_DEF | MTX_RECURSE); +#define LKPI_80211_LHW_RXQ_LOCK_DESTROY(_lhw) \ + mtx_destroy(&(_lhw)->rxq_mtx); +#define LKPI_80211_LHW_RXQ_LOCK(_lhw) \ + mtx_lock(&(_lhw)->rxq_mtx) +#define LKPI_80211_LHW_RXQ_UNLOCK(_lhw) \ + mtx_unlock(&(_lhw)->rxq_mtx) +#define LKPI_80211_LHW_RXQ_LOCK_ASSERT(_lhw) \ + mtx_assert(&(_lhw)->rxq_mtx, MA_OWNED) +#define LKPI_80211_LHW_RXQ_UNLOCK_ASSERT(_lhw) \ + mtx_assert(&(_lhw)->rxq_mtx, MA_NOTOWNED) + #define LKPI_80211_LHW_LVIF_LOCK(_lhw) sx_xlock(&(_lhw)->lvif_sx) #define LKPI_80211_LHW_LVIF_UNLOCK(_lhw) sx_xunlock(&(_lhw)->lvif_sx)