From nobody Mon Feb 19 08:08:02 2024 X-Original-To: dev-commits-src-all@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 4TdZsb1xv6z5B2sQ; Mon, 19 Feb 2024 08:08:03 +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 4TdZsb0Kgwz4KnH; Mon, 19 Feb 2024 08:08:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708330083; 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=KCSQLThYFO4YaPBjuowUZyeANP3C0/Oa4OX9iepEnFw=; b=I9T8kpE0WvXiIqoU544NsVIZxaf6yR0OQv3t9FAhjCcx/8XXBxg/eWAenUFns9tLDKc+/7 i/2nu4UrwzWfc0PTWCCkGDr5QrQ1PP9BqA67M+XULlYkCGZWTL+p+J+uDS0om630TRhKEq nw+lVoGJjvGYyuSNjHikUZY7b+Y2sVGX+ZiIsIqwHnni3JsuZDz9nL1Ea6gQBFEbd7fTJ2 QjUamEp+myUXHd2mF+JKwPa/fbimzlCjgLIZdVNdEXg3mWCuEOR5PLCykBuimwmV5TGI4F Zqw50g8PLlHpSX5LRC5XHPEg3PZcBVfeB2BE7AroDmJRmRbPk/85XEr5x9/M5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708330083; 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=KCSQLThYFO4YaPBjuowUZyeANP3C0/Oa4OX9iepEnFw=; b=pMav8NRIFnWthbhT03oHh70cYUYDqSv9ZKtXYoVhuYppD4FlHpXAaQ/B3aLkRUMKbFlFaE eulMrsaH8vwqH3+SOQWMLbnYRnSeFnMZC41d62tT/3yqLbo5+8tj988Tvx/ziBF1qCj+Zf PmxkJOliLdgnnPeNAGkBVwwqeTINCkUGLKSFV0lCCknC8hXyxG8H+6Dm2qlzWhsCuxIIBK qBFrUVgRaHSM81isPHyXXXIchYoVDhIARGFdBPDlc4HboULoJlBJtLTC8wnnCi5AgoBWbt O2w7Wuuxe2MP34Sc3r8Uq6ipEJdiP9lTkuSNSuYkhj2e31krmEtM4NOcpl/4IA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1708330083; a=rsa-sha256; cv=none; b=PvVZFPnCX59hzixWO79a5Oay1LpCqmm1vAU8BGAaZG47GsT1h59xLD+BobRa3CGq/OZqbG FgiHCC6vO21rfwSSbJgxGPy/XqVvqUQWsJE31cRcy6Z6U7jvdZ7fdVe/Ucp8oMf6nOvxU7 HA/0iWkwVK/tzip/qyc2ZbJSzqMnS5bRX1+gwKzN8iUR88jVZmUJS0oiPHUv/9oh034vTN 2jTRsgg+rW02fSYAe2+cUb0tEKdJQuv6fnWQyFLB2EmpcZprkaNCuY4XuqW/t2+TOwDIVw AH8VRVbDZ/NX7dgREGgsVokOPaxY/LGVWePSDY771GSxT1Whzjb4OOHKJ39A5g== 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 4TdZsZ6WRrzR85; Mon, 19 Feb 2024 08:08:02 +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 41J882W7016449; Mon, 19 Feb 2024 08:08:02 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 41J882fa016446; Mon, 19 Feb 2024 08:08:02 GMT (envelope-from git) Date: Mon, 19 Feb 2024 08:08:02 GMT Message-Id: <202402190808.41J882fa016446@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: "Bjoern A. Zeeb" Subject: git: 184ccc414686 - stable/13 - LinuxKPI: 802.11: band-aid for invalid state changes after (*iv_update_bss) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@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/stable/13 X-Git-Reftype: branch X-Git-Commit: 184ccc414686ea32c64f063c081c7cc1adeae7c3 Auto-Submitted: auto-generated The branch stable/13 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=184ccc414686ea32c64f063c081c7cc1adeae7c3 commit 184ccc414686ea32c64f063c081c7cc1adeae7c3 Author: Bjoern A. Zeeb AuthorDate: 2024-02-03 16:33:56 +0000 Commit: Bjoern A. Zeeb CommitDate: 2024-02-19 08:02:02 +0000 LinuxKPI: 802.11: band-aid for invalid state changes after (*iv_update_bss) With firmware based solutions we cannot just jump from an active session to a new iv_bss node without tearing down state for the old and bringing up the new node. This likely used to work on softmac based cards/drivers where one could essentially set the state and fire at will. We track (*iv_update_bss) calls from net80211 and set a local flag that we are out of synch and do not allow any further operations up the state machine until we hit INIT or SCAN. That means someone will take the state down, clean up firmware state and then we can join again and build up state. Apparently this problem has been "known" for a while as native iwm(4) and others have similar workarounds (though less strict) and can be equally pestered into bad states. For LinuxKPI all the KASSERTs just massively brought this problem out. The solution will be some rewrites in net80211. Until then, try to keep us more stable at least and not die on second join1() calls triggered by service netif start wlan0 and similar. PR: 271979, 271988, 275255, 263613, 274003 Sponsored by: The FreeBSD Foundation (2023, partial) Reviewed by: cc Differential Revision: https://reviews.freebsd.org/D43725 (cherry picked from commit 2ac8a2189ac6707f48f77ef2e36baf696a0d2f40) --- sys/compat/linuxkpi/common/src/linux_80211.c | 309 +++++++++++++++++++-------- sys/compat/linuxkpi/common/src/linux_80211.h | 2 + 2 files changed, 216 insertions(+), 95 deletions(-) diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c index b71deedb12b8..b1c3b5c32ded 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -611,6 +611,7 @@ lkpi_find_lkpi80211_chan(struct lkpi_hw *lhw, return (NULL); } +#if 0 static struct linuxkpi_ieee80211_channel * lkpi_get_lkpi80211_chan(struct ieee80211com *ic, struct ieee80211_node *ni) { @@ -635,6 +636,7 @@ lkpi_get_lkpi80211_chan(struct ieee80211com *ic, struct ieee80211_node *ni) return (chan); } +#endif struct linuxkpi_ieee80211_channel * linuxkpi_ieee80211_get_channel(struct wiphy *wiphy, uint32_t freq) @@ -1040,19 +1042,37 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int uint32_t changed; int error; - chan = lkpi_get_lkpi80211_chan(vap->iv_ic, vap->iv_bss); + /* + * In here we use vap->iv_bss until lvif->lvif_bss is set. + * For all later (STATE >= AUTH) functions we need to use the lvif + * cache which will be tracked even through (*iv_update_bss)(). + */ + + if (vap->iv_bss == NULL) { + ic_printf(vap->iv_ic, "%s: no iv_bss for vap %p\n", __func__, vap); + return (EINVAL); + } + ni = ieee80211_ref_node(vap->iv_bss); + if (ni->ni_chan == NULL || ni->ni_chan == IEEE80211_CHAN_ANYC) { + ic_printf(vap->iv_ic, "%s: no channel set for iv_bss ni %p " + "on vap %p\n", __func__, ni, vap); + ieee80211_free_node(ni); + return (EINVAL); + } + + lhw = vap->iv_ic->ic_softc; + chan = lkpi_find_lkpi80211_chan(lhw, ni->ni_chan); if (chan == NULL) { - ic_printf(vap->iv_ic, "%s: failed to get channel\n", __func__); + ic_printf(vap->iv_ic, "%s: failed to get LKPI channel from " + "iv_bss ni %p on vap %p\n", __func__, ni, vap); + ieee80211_free_node(ni); return (ESRCH); } - lhw = vap->iv_ic->ic_softc; hw = LHW_TO_HW(lhw); lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - ni = ieee80211_ref_node(vap->iv_bss); - IEEE80211_UNLOCK(vap->iv_ic); LKPI_80211_LHW_LOCK(lhw); @@ -1077,6 +1097,8 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int conf->def.center_freq1 = chan->center_freq; conf->def.center_freq2 = 0; IMPROVE("Check vht_cap from band not just chan?"); + KASSERT(ni->ni_chan != NULL && ni->ni_chan != IEEE80211_CHAN_ANYC, + ("%s:%d: ni %p ni_chan %p\n", __func__, __LINE__, ni, ni->ni_chan)); #ifdef LKPI_80211_HT if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { @@ -1187,6 +1209,8 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int * workflow so live with this. It is a compat layer after all. */ if (ni->ni_drv_data == NULL) { + ic_printf(vap->iv_ic, "%s:%d: lkpi_lsta_alloc to be called: " + "ni %p lsta %p\n", __func__, __LINE__, ni, ni->ni_drv_data); lsta = lkpi_lsta_alloc(vap, ni->ni_macaddr, hw, ni); if (lsta == NULL) { error = ENOMEM; @@ -1199,8 +1223,22 @@ lkpi_sta_scan_to_auth(struct ieee80211vap *vap, enum ieee80211_state nstate, int lsta = ni->ni_drv_data; } - /* Insert the [l]sta into the list of known stations. */ LKPI_80211_LVIF_LOCK(lvif); + /* XXX-BZ KASSERT later? */ + /* XXX-BZ this should have caught the upper lkpi_lsta_alloc() too! */ + if (lvif->lvif_bss_synched || lvif->lvif_bss != NULL) + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d, ni %p lsta %p\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched, ni, lsta); + + /* Reference the ni for this cache of lsta. */ + ieee80211_ref_node(vap->iv_bss); + lvif->lvif_bss = lsta; + lvif->lvif_bss_synched = true; + + /* Insert the [l]sta into the list of known stations. */ TAILQ_INSERT_TAIL(&lvif->lsta_head, lsta, lsta_entry); LKPI_80211_LVIF_UNLOCK(lvif); @@ -1272,9 +1310,23 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - /* Keep ni around. */ - ni = ieee80211_ref_node(vap->iv_bss); - lsta = ni->ni_drv_data; + LKPI_80211_LVIF_LOCK(lvif); +#ifdef LINUXKPI_DEBUG_80211 + /* XXX-BZ KASSERT later; state going down so no action. */ + if (lvif->lvif_bss == NULL) + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p " + "lvif %p vap %p\n", __func__, + lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap)); + ni = lsta->ni; /* Reference held for lvif_bss. */ sta = LSTA_TO_STA(lsta); lkpi_lsta_dump(lsta, ni, __func__, __LINE__); @@ -1324,6 +1376,13 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int lkpi_lsta_dump(lsta, ni, __func__, __LINE__); + LKPI_80211_LVIF_LOCK(lvif); + /* Remove ni reference for this cache of lsta. */ + lvif->lvif_bss = NULL; + lvif->lvif_bss_synched = false; + LKPI_80211_LVIF_UNLOCK(lvif); + ieee80211_free_node(ni); /* was lvif->lvif_bss->ni */ + lkpi_lsta_remove(lsta, lvif); /* conf_tx */ @@ -1347,8 +1406,6 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum ieee80211_state nstate, int out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); - if (ni != NULL) - ieee80211_free_node(ni); return (error); } @@ -1370,7 +1427,6 @@ lkpi_sta_auth_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, in struct ieee80211_hw *hw; struct lkpi_vif *lvif; struct ieee80211_vif *vif; - struct ieee80211_node *ni; struct lkpi_sta *lsta; struct ieee80211_prep_tx_info prep_tx_info; int error; @@ -1382,15 +1438,30 @@ lkpi_sta_auth_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, in IEEE80211_UNLOCK(vap->iv_ic); LKPI_80211_LHW_LOCK(lhw); - ni = NULL; + + LKPI_80211_LVIF_LOCK(lvif); + /* XXX-BZ KASSERT later? */ + if (!lvif->lvif_bss_synched || lvif->lvif_bss == NULL) { +#ifdef LINUXKPI_DEBUG_80211 + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + error = ENOTRECOVERABLE; + LKPI_80211_LVIF_UNLOCK(lvif); + goto out; + } + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + + KASSERT(lsta != NULL, ("%s: lsta %p\n", __func__, lsta)); /* Finish auth. */ IMPROVE("event callback"); /* Update sta_state (NONE to AUTH). */ - ni = ieee80211_ref_node(vap->iv_bss); - lsta = ni->ni_drv_data; - KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni)); KASSERT(lsta->state == IEEE80211_STA_NONE, ("%s: lsta %p state not " "NONE: %#x\n", __func__, lsta, lsta->state)); error = lkpi_80211_mo_sta_state(hw, vif, lsta, IEEE80211_STA_AUTH); @@ -1434,8 +1505,6 @@ lkpi_sta_auth_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, in out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); - if (ni != NULL) - ieee80211_free_node(ni); return (error); } @@ -1447,20 +1516,37 @@ lkpi_sta_a_to_a(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) struct ieee80211_hw *hw; struct lkpi_vif *lvif; struct ieee80211_vif *vif; - struct ieee80211_node *ni; struct lkpi_sta *lsta; struct ieee80211_prep_tx_info prep_tx_info; + int error; lhw = vap->iv_ic->ic_softc; hw = LHW_TO_HW(lhw); lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - ni = ieee80211_ref_node(vap->iv_bss); - IEEE80211_UNLOCK(vap->iv_ic); LKPI_80211_LHW_LOCK(lhw); - lsta = ni->ni_drv_data; + + LKPI_80211_LVIF_LOCK(lvif); + /* XXX-BZ KASSERT later? */ + if (!lvif->lvif_bss_synched || lvif->lvif_bss == NULL) { +#ifdef LINUXKPI_DEBUG_80211 + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + LKPI_80211_LVIF_UNLOCK(lvif); + error = ENOTRECOVERABLE; + goto out; + } + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + + KASSERT(lsta != NULL, ("%s: lsta %p! lvif %p vap %p\n", __func__, + lsta, lvif, vap)); IMPROVE("event callback?"); @@ -1482,12 +1568,12 @@ lkpi_sta_a_to_a(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) lsta->in_mgd = true; } + error = 0; +out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); - if (ni != NULL) - ieee80211_free_node(ni); - return (0); + return (error); } static int @@ -1509,16 +1595,30 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - /* Keep ni around. */ - ni = ieee80211_ref_node(vap->iv_bss); - lsta = ni->ni_drv_data; + IEEE80211_UNLOCK(vap->iv_ic); + LKPI_80211_LHW_LOCK(lhw); + + LKPI_80211_LVIF_LOCK(lvif); +#ifdef LINUXKPI_DEBUG_80211 + /* XXX-BZ KASSERT later; state going down so no action. */ + if (lvif->lvif_bss == NULL) + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p " + "lvif %p vap %p\n", __func__, + lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap)); + + ni = lsta->ni; /* Reference held for lvif_bss. */ sta = LSTA_TO_STA(lsta); lkpi_lsta_dump(lsta, ni, __func__, __LINE__); - IEEE80211_UNLOCK(vap->iv_ic); - LKPI_80211_LHW_LOCK(lhw); - /* flush, drop. */ lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), true); @@ -1614,6 +1714,13 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum ieee80211_state nstate, i bss_changed |= BSS_CHANGED_BSSID; lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + LKPI_80211_LVIF_LOCK(lvif); + /* Remove ni reference for this cache of lsta. */ + lvif->lvif_bss = NULL; + lvif->lvif_bss_synched = false; + LKPI_80211_LVIF_UNLOCK(lvif); + ieee80211_free_node(ni); /* was lvif->lvif_bss->ni */ + lkpi_lsta_remove(lsta, lvif); /* conf_tx */ @@ -1639,8 +1746,6 @@ out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); outni: - if (ni != NULL) - ieee80211_free_node(ni); return (error); } @@ -1698,16 +1803,34 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int IEEE80211_UNLOCK(vap->iv_ic); LKPI_80211_LHW_LOCK(lhw); - ni = NULL; + + LKPI_80211_LVIF_LOCK(lvif); + /* XXX-BZ KASSERT later? */ + if (!lvif->lvif_bss_synched || lvif->lvif_bss == NULL) { +#ifdef LINUXKPI_DEBUG_80211 + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + LKPI_80211_LVIF_UNLOCK(lvif); + error = ENOTRECOVERABLE; + goto out; + } + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p " + "lvif %p vap %p\n", __func__, + lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap)); + + ni = lsta->ni; /* Reference held for lvif_bss. */ IMPROVE("ponder some of this moved to ic_newassoc, scan_assoc_success, " "and to lesser extend ieee80211_notify_node_join"); /* Finish assoc. */ /* Update sta_state (AUTH to ASSOC) and set aid. */ - ni = ieee80211_ref_node(vap->iv_bss); - lsta = ni->ni_drv_data; - KASSERT(lsta != NULL, ("%s: ni %p lsta is NULL\n", __func__, ni)); KASSERT(lsta->state == IEEE80211_STA_AUTH, ("%s: lsta %p state not " "AUTH: %#x\n", __func__, lsta, lsta->state)); sta = LSTA_TO_STA(lsta); @@ -1820,8 +1943,6 @@ lkpi_sta_assoc_to_run(struct ieee80211vap *vap, enum ieee80211_state nstate, int out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); - if (ni != NULL) - ieee80211_free_node(ni); return (error); } @@ -1857,9 +1978,23 @@ lkpi_sta_run_to_assoc(struct ieee80211vap *vap, enum ieee80211_state nstate, int lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - /* Keep ni around. */ - ni = ieee80211_ref_node(vap->iv_bss); - lsta = ni->ni_drv_data; + LKPI_80211_LVIF_LOCK(lvif); +#ifdef LINUXKPI_DEBUG_80211 + /* XXX-BZ KASSERT later; state going down so no action. */ + if (lvif->lvif_bss == NULL) + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p " + "lvif %p vap %p\n", __func__, + lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap)); + + ni = lsta->ni; /* Reference held for lvif_bss. */ sta = LSTA_TO_STA(lsta); lkpi_lsta_dump(lsta, ni, __func__, __LINE__); @@ -1955,8 +2090,6 @@ out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); outni: - if (ni != NULL) - ieee80211_free_node(ni); return (error); } @@ -1979,16 +2112,30 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - /* Keep ni around. */ - ni = ieee80211_ref_node(vap->iv_bss); - lsta = ni->ni_drv_data; + IEEE80211_UNLOCK(vap->iv_ic); + LKPI_80211_LHW_LOCK(lhw); + + LKPI_80211_LVIF_LOCK(lvif); +#ifdef LINUXKPI_DEBUG_80211 + /* XXX-BZ KASSERT later; state going down so no action. */ + if (lvif->lvif_bss == NULL) + ic_printf(vap->iv_ic, "%s:%d: lvif %p vap %p iv_bss %p lvif_bss %p " + "lvif_bss->ni %p synched %d\n", __func__, __LINE__, + lvif, vap, vap->iv_bss, lvif->lvif_bss, + (lvif->lvif_bss != NULL) ? lvif->lvif_bss->ni : NULL, + lvif->lvif_bss_synched); +#endif + lsta = lvif->lvif_bss; + LKPI_80211_LVIF_UNLOCK(lvif); + KASSERT(lsta != NULL && lsta->ni != NULL, ("%s: lsta %p ni %p " + "lvif %p vap %p\n", __func__, + lsta, (lsta != NULL) ? lsta->ni : NULL, lvif, vap)); + + ni = lsta->ni; /* Reference held for lvif_bss. */ sta = LSTA_TO_STA(lsta); lkpi_lsta_dump(lsta, ni, __func__, __LINE__); - IEEE80211_UNLOCK(vap->iv_ic); - LKPI_80211_LHW_LOCK(lhw); - /* flush, drop. */ lkpi_80211_mo_flush(hw, vif, nitems(sta->txq), true); @@ -2108,6 +2255,13 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum ieee80211_state nstate, int bss_changed |= BSS_CHANGED_BSSID; lkpi_80211_mo_bss_info_changed(hw, vif, &vif->bss_conf, bss_changed); + LKPI_80211_LVIF_LOCK(lvif); + /* Remove ni reference for this cache of lsta. */ + lvif->lvif_bss = NULL; + lvif->lvif_bss_synched = false; + LKPI_80211_LVIF_UNLOCK(lvif); + ieee80211_free_node(ni); /* was lvif->lvif_bss->ni */ + lkpi_lsta_remove(lsta, lvif); /* conf_tx */ @@ -2133,8 +2287,6 @@ out: LKPI_80211_LHW_UNLOCK(lhw); IEEE80211_LOCK(vap->iv_ic); outni: - if (ni != NULL) - ieee80211_free_node(ni); return (error); } @@ -2307,53 +2459,18 @@ static struct ieee80211_node * lkpi_iv_update_bss(struct ieee80211vap *vap, struct ieee80211_node *ni) { struct lkpi_vif *lvif; - struct ieee80211_node *obss; - struct lkpi_sta *lsta; - struct ieee80211_sta *sta; - - obss = vap->iv_bss; - -#ifdef LINUXKPI_DEBUG_80211 - if (linuxkpi_debug_80211 & D80211_TRACE) - ic_printf(vap->iv_ic, "%s: obss %p ni_drv_data %p " - "ni %p ni_drv_data %p\n", __func__, - obss, (obss != NULL) ? obss->ni_drv_data : NULL, - ni, (ni != NULL) ? ni->ni_drv_data : NULL); -#endif + struct ieee80211_node *rni; - /* Nothing to copy from. Just return. */ - if (obss == NULL || obss->ni_drv_data == NULL) - goto out; - - /* Nothing to copy to. Just return. */ - IMPROVE("clearing the obss might still be needed?"); - if (ni == NULL) - goto out; + IEEE80211_LOCK_ASSERT(vap->iv_ic); - /* Nothing changed? panic? */ - if (obss == ni) - goto out; + lvif = VAP_TO_LVIF(vap); - lsta = obss->ni_drv_data; - obss->ni_drv_data = ni->ni_drv_data; - ni->ni_drv_data = lsta; - if (lsta != NULL) { - lsta->ni = ni; - sta = LSTA_TO_STA(lsta); - IEEE80211_ADDR_COPY(sta->addr, lsta->ni->ni_macaddr); - IEEE80211_ADDR_COPY(sta->deflink.addr, sta->addr); - } - lsta = obss->ni_drv_data; - if (lsta != NULL) { - lsta->ni = obss; - sta = LSTA_TO_STA(lsta); - IEEE80211_ADDR_COPY(sta->addr, lsta->ni->ni_macaddr); - IEEE80211_ADDR_COPY(sta->deflink.addr, sta->addr); - } + LKPI_80211_LVIF_LOCK(lvif); + lvif->lvif_bss_synched = false; + LKPI_80211_LVIF_UNLOCK(lvif); -out: - lvif = VAP_TO_LVIF(vap); - return (lvif->iv_update_bss(vap, ni)); + rni = lvif->iv_update_bss(vap, ni); + return (rni); } #ifdef LKPI_80211_WME @@ -2474,6 +2591,8 @@ lkpi_ic_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], lvif = malloc(len, M_80211_VAP, M_WAITOK | M_ZERO); mtx_init(&lvif->mtx, "lvif", NULL, MTX_DEF); TAILQ_INIT(&lvif->lsta_head); + lvif->lvif_bss = NULL; + lvif->lvif_bss_synched = false; vap = LVIF_TO_VAP(lvif); vif = LVIF_TO_VIF(lvif); diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h index c9ac19321ab3..4aeca414973c 100644 --- a/sys/compat/linuxkpi/common/src/linux_80211.h +++ b/sys/compat/linuxkpi/common/src/linux_80211.h @@ -156,6 +156,8 @@ struct lkpi_vif { struct ieee80211_node * (*iv_update_bss)(struct ieee80211vap *, struct ieee80211_node *); TAILQ_HEAD(, lkpi_sta) lsta_head; + struct lkpi_sta *lvif_bss; + bool lvif_bss_synched; bool added_to_drv; /* Driver knows; i.e. we called add_interface(). */ bool hw_queue_stopped[IEEE80211_NUM_ACS];