[PATCH v3 3/5] wifi: brcmfmac: add PMK programming for firmware roaming offload
Jason Huang <[email protected]>
| Newsgroups | dev.linux.lists.brcm80211,org.kernel.vger.linux-kernel,org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <20260810-upstream-wireless-next-main-jason-11r-support-v1-v3-3-bce4f460ae0b@infineon.com> |
From: Darren Li <[email protected]> FT and OKC roaming offload need PMK material in firmware even when the initial 802.1X exchange is handled by userspace. Add a roaming firmware-supplicant profile state for those connections and allow PMK configuration while firmware FT or OKC state is active. Program the OKC PMK through the okc_info_pmk iovar before setting the regular PMK when firmware reports OKC state. Only select the roaming firmware-supplicant state when firmware advertises FBT or OKC support; devices without those capabilities keep the profile in the userspace supplicant state and do not issue roaming-offload specific iovars on every connect. For FT-PSK with firmware supplicant support, keep the profile in the PSK firmware-supplicant state. Assisted-by: GitHub Copilot CLI:gpt-5.5 Signed-off-by: Darren Li <[email protected]> Signed-off-by: Chung-Hsien Hsu <[email protected]> Signed-off-by: Chi-hsien Lin <[email protected]> Co-developed-by: Carella Chen <[email protected]> Signed-off-by: Carella Chen <[email protected]> Co-developed-by: Shelley Yang <[email protected]> Signed-off-by: Shelley Yang <[email protected]> Signed-off-by: Jason Huang <[email protected]> --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 56 +++++++++++++++++++--- .../broadcom/brcm80211/brcmfmac/cfg80211.h | 4 +- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 872c48806d09..f2916cc9e5fc 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -2112,9 +2112,11 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) struct brcmf_pub *drvr = ifp->drvr; s32 val; s32 err; + s32 okc_enable; const struct brcmf_tlv *rsn_ie; const u8 *ie; u32 ie_len; + bool fwsup_roam; u32 offset; u16 rsn_cap; u32 mfp; @@ -2122,6 +2124,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE; profile->is_ft = false; + profile->is_okc = false; + fwsup_roam = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FBT) || + brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OKC); if (!sme->crypto.n_akm_suites) return 0; @@ -2138,6 +2143,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA_AUTH_UNSPECIFIED; if (sme->want_1x) profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X; + else if (fwsup_roam) + profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM; break; case WLAN_AKM_SUITE_PSK: val = WPA_AUTH_PSK; @@ -2153,11 +2160,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_UNSPECIFIED; if (sme->want_1x) profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X; + else if (fwsup_roam) + profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM; break; case WLAN_AKM_SUITE_8021X_SHA256: val = WPA2_AUTH_1X_SHA256; if (sme->want_1x) profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X; + else if (fwsup_roam) + profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM; break; case WLAN_AKM_SUITE_PSK_SHA256: val = WPA2_AUTH_PSK_SHA256; @@ -2170,10 +2181,16 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) profile->is_ft = true; if (sme->want_1x) profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X; + else if (fwsup_roam) + profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM; break; case WLAN_AKM_SUITE_FT_PSK: val = WPA2_AUTH_PSK | WPA2_AUTH_FT; profile->is_ft = true; + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) + profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK; + else if (fwsup_roam) + profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM; break; case WLAN_AKM_SUITE_WFA_DPP: val = WFA_AUTH_DPP; @@ -2204,8 +2221,22 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X) brcmf_dbg(INFO, "using 1X offload\n"); + + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X || + profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) { + err = brcmf_fil_bsscfg_int_get(ifp, "okc_enable", + &okc_enable); + if (err) { + bphy_err(drvr, "get okc_enable failed (%d)\n", err); + } else { + brcmf_dbg(INFO, "okc_enable (%d)\n", okc_enable); + profile->is_okc = okc_enable; + } + } if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) brcmf_dbg(INFO, "using SAE offload\n"); + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) + brcmf_dbg(INFO, "using roaming offload\n"); if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) goto skip_mfp_config; @@ -2494,13 +2525,14 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, if (sme->crypto.psk && !is_sae_akm && profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { - if (WARN_ON(profile->use_fwsup != - BRCMF_PROFILE_FWSUP_NONE)) { + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_NONE) { + brcmf_dbg(INFO, "using PSK offload\n"); + profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK; + } else if (WARN_ON(profile->use_fwsup != + BRCMF_PROFILE_FWSUP_PSK)) { err = -EINVAL; goto done; } - brcmf_dbg(INFO, "using PSK offload\n"); - profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK; } if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { /* enable firmware supplicant for this interface */ @@ -5953,17 +5985,29 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev, const struct cfg80211_pmk_conf *conf) { struct brcmf_if *ifp; + struct brcmf_pub *drvr; + int ret; brcmf_dbg(TRACE, "enter\n"); - /* expect using firmware supplicant for 1X */ ifp = netdev_priv(dev); - if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X)) + drvr = ifp->drvr; + if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X && + !ifp->vif->profile.is_ft && + !ifp->vif->profile.is_okc)) return -EINVAL; if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN) return -ERANGE; + if (ifp->vif->profile.is_okc) { + ret = brcmf_fil_iovar_data_set(ifp, "okc_info_pmk", + conf->pmk, conf->pmk_len); + if (ret < 0) + bphy_err(drvr, "okc_info_pmk iovar failed: ret=%d\n", + ret); + } + return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 63e534523f51..58f229489836 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -127,7 +127,8 @@ enum brcmf_profile_fwsup { BRCMF_PROFILE_FWSUP_NONE, BRCMF_PROFILE_FWSUP_PSK, BRCMF_PROFILE_FWSUP_1X, - BRCMF_PROFILE_FWSUP_SAE + BRCMF_PROFILE_FWSUP_SAE, + BRCMF_PROFILE_FWSUP_ROAM }; /** @@ -172,6 +173,7 @@ struct brcmf_cfg80211_profile { enum brcmf_profile_fwsup use_fwsup; u16 use_fwauth; bool is_ft; + bool is_okc; }; /** -- 2.25.1