git: 3a35e07fa930 - stable/14 - LinuxKPI: 802.11: add a lchanctx list to lhw
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 18 Apr 2025 14:37:18 UTC
The branch stable/14 has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=3a35e07fa9309a357f9f7d25e86aba6f93c0af84
commit 3a35e07fa9309a357f9f7d25e86aba6f93c0af84
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-04-08 23:05:43 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-04-18 14:36:01 +0000
LinuxKPI: 802.11: add a lchanctx list to lhw
While we are currently only supporting a single VAP (vif) it is
less of a trouble but in order to get locking and rcu accesses
[from drivers] more right add a list for all chanctx_conf we have
for one hw. Use that list in the iterator function to avoid
having to lock the vif but not protecting the chanctx list
(against a parallel removal) due to different locking.
Sponsored by: The FreeBSD Foundation
PR: 280546
Tested by: Oleksandr Kryvulia (shuriku shurik.kiev.ua)
Tested by: Oleg Nauman (oleg.nauman gmail.com) [rtw88]
Differential Revision: https://reviews.freebsd.org/D49734
(cherry picked from commit a8a47a41775b0320606f90b3ac2048bc23494615)
---
sys/compat/linuxkpi/common/src/linux_80211.c | 39 ++++++++++++++++++----------
sys/compat/linuxkpi/common/src/linux_80211.h | 4 +++
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index bd1e60928144..f5f52101d367 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -1756,6 +1756,7 @@ lkpi_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
/* Cleanup. */
rcu_assign_pointer(vif->bss_conf.chanctx_conf, NULL);
lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
+ list_del(&lchanctx->entry);
free(lchanctx, M_LKPI80211);
}
@@ -1942,6 +1943,7 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
goto out;
}
+ list_add_rcu(&lchanctx->entry, &lhw->lchanctx_list);
rcu_assign_pointer(vif->bss_conf.chanctx_conf, chanctx_conf);
/* Assign vif chanctx. */
@@ -1956,6 +1958,7 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int
lkpi_80211_mo_remove_chanctx(hw, chanctx_conf);
rcu_assign_pointer(vif->bss_conf.chanctx_conf, NULL);
lchanctx = CHANCTX_CONF_TO_LCHANCTX(chanctx_conf);
+ list_del(&lchanctx->entry);
free(lchanctx, M_LKPI80211);
goto out;
}
@@ -5469,6 +5472,9 @@ linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops)
TAILQ_INIT(&lhw->scheduled_txqs[ac]);
}
+ /* Chanctx_conf */
+ INIT_LIST_HEAD(&lhw->lchanctx_list);
+
/* Deferred RX path. */
LKPI_80211_LHW_RXQ_LOCK_INIT(lhw);
TASK_INIT(&lhw->rxq_task, 0, lkpi_80211_lhw_rxq_task, lhw);
@@ -5532,6 +5538,22 @@ linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw)
__func__, lhw, mbufq_len(&lhw->rxq)));
LKPI_80211_LHW_RXQ_LOCK_DESTROY(lhw);
+ /* Chanctx_conf. */
+ if (!list_empty_careful(&lhw->lchanctx_list)) {
+ struct lkpi_chanctx *lchanctx, *next;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+
+ list_for_each_entry_safe(lchanctx, next, &lhw->lchanctx_list, entry) {
+ if (lchanctx->added_to_drv) {
+ /* In reality we should panic? */
+ chanctx_conf = &lchanctx->chanctx_conf;
+ lkpi_80211_mo_remove_chanctx(hw, chanctx_conf);
+ }
+ list_del(&lchanctx->entry);
+ free(lchanctx, M_LKPI80211);
+ }
+ }
+
/* Cleanup more of lhw here or in wiphy_free()? */
LKPI_80211_LHW_TXQ_LOCK_DESTROY(lhw);
LKPI_80211_LHW_SCAN_LOCK_DESTROY(lhw);
@@ -5967,8 +5989,6 @@ linuxkpi_ieee80211_iterate_chan_contexts(struct ieee80211_hw *hw,
void *arg)
{
struct lkpi_hw *lhw;
- struct lkpi_vif *lvif;
- struct ieee80211_vif *vif;
struct lkpi_chanctx *lchanctx;
KASSERT(hw != NULL && iterfunc != NULL,
@@ -5976,22 +5996,13 @@ linuxkpi_ieee80211_iterate_chan_contexts(struct ieee80211_hw *hw,
lhw = HW_TO_LHW(hw);
- IMPROVE("lchanctx should be its own list somewhere");
-
- LKPI_80211_LHW_LVIF_LOCK(lhw);
- TAILQ_FOREACH(lvif, &lhw->lvif_head, lvif_entry) {
-
- vif = LVIF_TO_VIF(lvif);
- if (vif->bss_conf.chanctx_conf == NULL) /* XXX-BZ; FIXME see IMPROVE above. */
- continue;
-
- lchanctx = CHANCTX_CONF_TO_LCHANCTX(vif->bss_conf.chanctx_conf);
+ rcu_read_lock();
+ list_for_each_entry_rcu(lchanctx, &lhw->lchanctx_list, entry) {
if (!lchanctx->added_to_drv)
continue;
-
iterfunc(hw, &lchanctx->chanctx_conf, arg);
}
- LKPI_80211_LHW_LVIF_UNLOCK(lhw);
+ rcu_read_unlock();
}
void
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index c01a6cb0cd7c..8bc2a465f76f 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -217,6 +217,7 @@ struct lkpi_hw { /* name it mac80211_sc? */
struct sx lvif_sx;
struct sx sx; /* XXX-BZ Can this be wiphy->mtx in the future? */
+ struct list_head lchanctx_list;
struct mtx txq_mtx;
uint32_t txq_generation[IEEE80211_NUM_ACS];
@@ -284,7 +285,10 @@ struct lkpi_hw { /* name it mac80211_sc? */
#define HW_TO_LHW(_hw) container_of(_hw, struct lkpi_hw, hw)
struct lkpi_chanctx {
+ struct list_head entry;
+
bool added_to_drv; /* Managed by MO */
+
struct ieee80211_chanctx_conf chanctx_conf __aligned(CACHE_LINE_SIZE);
};
#define LCHANCTX_TO_CHANCTX_CONF(_lchanctx) \