* [PATCH v2] wifi: brcmfmac: add DPP support and fix fw-supplicant/P2P interop [not found] <20260603035722.145894-1-Jason.Huang2@infineon.com> @ 2026-06-04 3:42 ` Jason Huang 2026-07-08 3:58 ` [PATCH v3] wifi: brcmfmac: add DPP support Jason Huang 0 siblings, 1 reply; 10+ messages in thread From: Jason Huang @ 2026-06-04 3:42 UTC (permalink / raw) To: linux-wireless Cc: brcm80211, brcm80211-dev-list.pdl, linux-kernel, Kurt Lee, Jason Huang From: Kurt Lee <kurt.lee@cypress.com> Add DPP support in brcmfmac and include follow-up fixes needed for reliable operation with mixed security setups. Main changes: - add DPP AKM handling in key-mgmt and RSN parsing - map DPP to WFA_AUTH_DPP and allow it in MFP-required checks - recognize DPP public action frames in the P2P TX path - pass the transmitting vif explicitly for action frame TX - track the correct ROC wdev for remain-on-channel expiry - gate sup_wpa iovar usage by firmware FWSUP capability - avoid stale fw supplicant state that can break DPP/EAPOL handling - add missing NULL checks in P2P abort/search-channel paths Together these changes enable DPP while preventing regressions when switching between DPP and non-DPP encrypted connections. Changes in v2: - Fix the kernel test robot warning by removing the unused action_frame_len variable. - Use upstream WLAN_AKM_SUITE_WFA_DPP and WLAN_OUI_* constants instead of adding local DPP/P2P definitions. - Use get_unaligned_be24() and get_unaligned_be32() for OUI and AKM suite parsing. - Gate sup_wpa handling on BRCMF_FEAT_FWSUP. - Avoid stale firmware supplicant state when switching between DPP and non-DPP encrypted connections. - Preserve SAE password handling while avoiding incorrect PSK offload selection. - Track remain-on-channel completion with the correct wireless_dev. - Add NULL checks in P2P abort/search-channel paths. Signed-off-by: Kurt Lee <kurt.lee@cypress.com> Signed-off-by: Jason Huang <jason.huang2@infineon.com> --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 157 +++++++++++------- .../broadcom/brcm80211/brcmfmac/p2p.c | 70 ++++++-- .../broadcom/brcm80211/brcmfmac/p2p.h | 1 + .../broadcom/brcm80211/include/brcmu_wifi.h | 2 + 4 files changed, 151 insertions(+), 79 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 0b55d445895f..3df7af710a5f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/module.h> +#include <linux/unaligned.h> #include <linux/vmalloc.h> #include <net/cfg80211.h> #include <net/netlink.h> @@ -2174,6 +2175,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_PSK | WPA2_AUTH_FT; profile->is_ft = true; break; + case WLAN_AKM_SUITE_WFA_DPP: + val = WFA_AUTH_DPP; + break; default: bphy_err(drvr, "invalid akm suite (%d)\n", sme->crypto.akm_suites[0]); @@ -2483,43 +2487,56 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - if (sme->crypto.psk && - profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { - if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) { - 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 */ - err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); - if (err < 0) { - bphy_err(drvr, "failed to enable fw supplicant\n"); - goto done; + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) { + u32 akm = sme->crypto.n_akm_suites ? sme->crypto.akm_suites[0] : 0; + bool is_sae_akm = akm == WLAN_AKM_SUITE_SAE || + akm == WLAN_AKM_SUITE_FT_OVER_SAE; + + if (sme->crypto.psk) { + if (is_sae_akm && + profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { + profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE; + } else if (!is_sae_akm && + profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { + if (WARN_ON(profile->use_fwsup != + BRCMF_PROFILE_FWSUP_NONE)) { + err = -EINVAL; + goto done; + } + brcmf_dbg(INFO, "using PSK offload\n"); + profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK; + } + } else { + profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE; } - } - - if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) - err = brcmf_set_pmk(ifp, sme->crypto.psk, - BRCMF_WSEC_MAX_PSK_LEN); - else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) { - /* clean up user-space RSNE */ - err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0); - if (err) { - bphy_err(drvr, "failed to clean up user-space RSNE\n"); - goto done; + if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { + /* enable firmware supplicant for this interface */ + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); + if (err < 0) { + bphy_err(drvr, "failed to enable fw supplicant\n"); + goto done; + } + } else { + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0); } - err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); - if (!err && sme->crypto.psk) + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) err = brcmf_set_pmk(ifp, sme->crypto.psk, BRCMF_WSEC_MAX_PSK_LEN); + else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE && + (sme->crypto.sae_pwd && brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE))) { + /* clean up user-space RSNE */ + if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) { + bphy_err(drvr, "failed to clean up user-space RSNE\n"); + goto done; + } + err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); + if (!err && sme->crypto.psk) + err = brcmf_set_pmk(ifp, sme->crypto.psk, + BRCMF_WSEC_MAX_PSK_LEN); + } + if (err) + goto done; } - if (err) - goto done; - /* Join with specific BSSID and cached SSID * If SSID is zero join based on BSSID only */ @@ -4538,6 +4555,11 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0); } +static bool brcmf_valid_dpp_suite(u8 *oui) +{ + return get_unaligned_be32(oui) == WLAN_AKM_SUITE_WFA_DPP; +} + static s32 brcmf_configure_wpaie(struct brcmf_if *ifp, const struct brcmf_vs_tlv *wpa_ie, @@ -4651,42 +4673,47 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, goto exit; } for (i = 0; i < count; i++) { - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + if (brcmf_valid_dpp_suite(&data[offset])) { + wpa_auth |= WFA_AUTH_DPP; + offset += TLV_OUI_LEN; + } else if (brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + offset += TLV_OUI_LEN; + switch (data[offset]) { + case RSN_AKM_NONE: + brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); + wpa_auth |= WPA_AUTH_NONE; + break; + case RSN_AKM_UNSPECIFIED: + brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); + is_rsn_ie ? + (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : + (wpa_auth |= WPA_AUTH_UNSPECIFIED); + break; + case RSN_AKM_PSK: + brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); + is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : + (wpa_auth |= WPA_AUTH_PSK); + break; + case RSN_AKM_SHA256_PSK: + brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); + wpa_auth |= WPA2_AUTH_PSK_SHA256; + break; + case RSN_AKM_SHA256_1X: + brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); + wpa_auth |= WPA2_AUTH_1X_SHA256; + break; + case RSN_AKM_SAE: + brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); + wpa_auth |= WPA3_AUTH_SAE_PSK; + break; + default: + bphy_err(drvr, "Invalid key mgmt info\n"); + } + } else { err = -EINVAL; bphy_err(drvr, "invalid OUI\n"); goto exit; } - offset += TLV_OUI_LEN; - switch (data[offset]) { - case RSN_AKM_NONE: - brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); - wpa_auth |= WPA_AUTH_NONE; - break; - case RSN_AKM_UNSPECIFIED: - brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : - (wpa_auth |= WPA_AUTH_UNSPECIFIED); - break; - case RSN_AKM_PSK: - brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : - (wpa_auth |= WPA_AUTH_PSK); - break; - case RSN_AKM_SHA256_PSK: - brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); - wpa_auth |= WPA2_AUTH_PSK_SHA256; - break; - case RSN_AKM_SHA256_1X: - brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); - wpa_auth |= WPA2_AUTH_1X_SHA256; - break; - case RSN_AKM_SAE: - brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); - wpa_auth |= WPA3_AUTH_SAE_PSK; - break; - default: - bphy_err(drvr, "Invalid key mgmt info\n"); - } offset++; } @@ -4706,10 +4733,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, */ if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 | WPA2_AUTH_1X_SHA256 | + WFA_AUTH_DPP | WPA3_AUTH_SAE_PSK))) { err = -EINVAL; goto exit; } + /* Firmware has requirement that WPA2_AUTH_PSK/ * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI * is to be included in the rsn ie. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 92c16a317328..db942e7eff18 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -6,6 +6,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> +#include <linux/unaligned.h> #include <net/cfg80211.h> #include <brcmu_wifi.h> @@ -44,9 +45,6 @@ #define BRCMF_SCB_TIMEOUT_VALUE 20 -#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */ -#define P2P_PUB_AF_CATEGORY 0x04 -#define P2P_PUB_AF_ACTION 0x09 #define P2P_AF_CATEGORY 0x7f #define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */ #define P2P_OUI_LEN 3 /* P2P OUI length */ @@ -143,10 +141,10 @@ struct brcmf_p2p_scan_le { /** * struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame * - * @category: P2P_PUB_AF_CATEGORY - * @action: P2P_PUB_AF_ACTION + * @category: WLAN_CATEGORY_PUBLIC + * @action: WLAN_PUB_ACTION_VENDOR_SPECIFIC * @oui: P2P_OUI - * @oui_type: OUI type - P2P_VER + * @oui_type: OUI type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI subtype - P2P_TYPE_* * @dialog_token: nonzero, identifies req/rsp transaction * @elts: Variable length information elements. @@ -166,7 +164,7 @@ struct brcmf_p2p_pub_act_frame { * * @category: P2P_AF_CATEGORY * @oui: OUI - P2P_OUI - * @type: OUI Type - P2P_VER + * @type: OUI Type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI Subtype - P2P_AF_* * @dialog_token: nonzero, identifies req/resp tranaction * @elts: Variable length information elements. @@ -228,10 +226,38 @@ static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len) if (frame_len < sizeof(*pact_frm)) return false; - if (pact_frm->category == P2P_PUB_AF_CATEGORY && - pact_frm->action == P2P_PUB_AF_ACTION && - pact_frm->oui_type == P2P_VER && - memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_P2P && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) + return true; + + return false; +} + +/** + * brcmf_p2p_is_dpp_pub_action() - true if dpp public type frame. + * + * @frame: action frame data. + * @frame_len: length of action frame data. + * + * Determine if action frame is dpp public action type + */ +static bool brcmf_p2p_is_dpp_pub_action(void *frame, u32 frame_len) +{ + struct brcmf_p2p_pub_act_frame *pact_frm; + + if (!frame) + return false; + + pact_frm = (struct brcmf_p2p_pub_act_frame *)frame; + if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1) + return false; + + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_DPP && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) return true; return false; @@ -257,7 +283,7 @@ static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len) return false; if (act_frm->category == P2P_AF_CATEGORY && - act_frm->type == P2P_VER && + act_frm->type == WLAN_OUI_TYPE_WFA_P2P && memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) return true; @@ -993,6 +1019,8 @@ int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, if (err) goto exit; + p2p->remain_on_channel_wdev = wdev; + memcpy(&p2p->remain_on_channel, channel, sizeof(*channel)); *cookie = p2p->remain_on_channel_cookie; cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL); @@ -1016,6 +1044,7 @@ int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp, { struct brcmf_cfg80211_info *cfg = ifp->drvr->config; struct brcmf_p2p_info *p2p = &cfg->p2p; + struct wireless_dev *wdev = p2p->remain_on_channel_wdev; brcmf_dbg(TRACE, "Enter\n"); if (test_and_clear_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, @@ -1028,10 +1057,16 @@ int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp, complete(&p2p->wait_next_af); } - cfg80211_remain_on_channel_expired(&ifp->vif->wdev, + wdev = p2p->remain_on_channel_wdev ? + p2p->remain_on_channel_wdev : + &ifp->vif->wdev; + + cfg80211_remain_on_channel_expired(wdev, p2p->remain_on_channel_cookie, &p2p->remain_on_channel, GFP_KERNEL); + p2p->remain_on_channel_wdev = NULL; + } return 0; } @@ -1283,6 +1318,9 @@ static s32 brcmf_p2p_abort_action_frame(struct brcmf_cfg80211_info *cfg) brcmf_dbg(TRACE, "Enter\n"); vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; + if (!vif) + vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; + err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val, sizeof(s32)); if (err) @@ -1782,7 +1820,9 @@ bool brcmf_p2p_send_action_frame(struct brcmf_if *ifp, goto exit; } } else if (brcmf_p2p_is_p2p_action(action_frame->data, - action_frame_len)) { + action_frame_len) || + brcmf_p2p_is_dpp_pub_action(action_frame->data, + action_frame_len)) { /* do not configure anything. it will be */ /* sent with a default configuration */ } else { @@ -1819,6 +1859,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_if *ifp, /* validate channel and p2p ies */ if (config_af_params.search_channel && IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) && + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { afx_hdl = &p2p->afx_hdl; afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel); @@ -2504,7 +2545,6 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced) pri_ifp = brcmf_get_ifp(cfg->pub, 0); p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; - init_completion(&p2p->send_af_done); if (p2pdev_forced) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h index 9f3f01ade2b7..ae159b9aef90 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h @@ -138,6 +138,7 @@ struct brcmf_p2p_info { bool block_gon_req_tx; bool p2pdev_dynamically; bool wait_for_offchan_complete; + struct wireless_dev *remain_on_channel_wdev; }; s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced); diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 7552bdb91991..c465208c4331 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h @@ -233,6 +233,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */ +#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */ + #define DOT11_DEFAULT_RTS_LEN 2347 #define DOT11_DEFAULT_FRAG_LEN 2346 base-commit: 6aded6c10490d5b24325e46f22b327876b669f72 -- 2.25.1 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3] wifi: brcmfmac: add DPP support 2026-06-04 3:42 ` [PATCH v2] wifi: brcmfmac: add DPP support and fix fw-supplicant/P2P interop Jason Huang @ 2026-07-08 3:58 ` Jason Huang 2026-07-08 7:12 ` [PATCH v4] " Jason Huang 0 siblings, 1 reply; 10+ messages in thread From: Jason Huang @ 2026-07-08 3:58 UTC (permalink / raw) To: linux-wireless Cc: brcm80211, brcm80211-dev-list.pdl, linux-kernel, arend.vanspriel, Jason Huang, Kurt Lee, Copilot From: Jason Huang <jason.huang2@infineon.com> Add DPP AKM handling and RSN parsing support. Map DPP to the firmware wpa_auth value and recognize DPP public action frames in the P2P action-frame TX path. Allow non-P2P public action frames such as DPP to use the primary vif when a P2P device vif is not present. Guard P2P-device IE access for the same case. Gate sup_wpa programming on firmware supplicant capability. Disable it only when the selected connection mode does not use firmware supplicant. This keeps pure SAE and 802.1X firmware-supplicant paths intact while avoiding stale firmware supplicant state for DPP. Signed-off-by: Kurt Lee <kurt.lee@cypress.com> Signed-off-by: Jason Huang <jason.huang2@infineon.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 151 ++++++++++-------- .../broadcom/brcm80211/brcmfmac/p2p.c | 59 +++++-- .../broadcom/brcm80211/include/brcmu_wifi.h | 2 + 3 files changed, 134 insertions(+), 78 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 4b70845e1a26..d61c3e03a106 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/module.h> +#include <linux/unaligned.h> #include <linux/vmalloc.h> #include <net/cfg80211.h> #include <net/netlink.h> @@ -2154,6 +2155,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_PSK | WPA2_AUTH_FT; profile->is_ft = true; break; + case WLAN_AKM_SUITE_WFA_DPP: + val = WFA_AUTH_DPP; + break; default: bphy_err(drvr, "invalid akm suite (%d)\n", sme->crypto.akm_suites[0]); @@ -2466,43 +2470,50 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - if (sme->crypto.psk && - profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { - if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) { - 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 */ - err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); - if (err < 0) { - bphy_err(drvr, "failed to enable fw supplicant\n"); - goto done; + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) { + u32 akm = sme->crypto.n_akm_suites ? sme->crypto.akm_suites[0] : 0; + bool is_sae_akm = akm == WLAN_AKM_SUITE_SAE || + akm == WLAN_AKM_SUITE_FT_OVER_SAE; + + if (sme->crypto.psk && !is_sae_akm && + profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { + if (WARN_ON(profile->use_fwsup != + BRCMF_PROFILE_FWSUP_NONE)) { + 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_PSK) - err = brcmf_set_pmk(ifp, sme->crypto.psk, - BRCMF_WSEC_MAX_PSK_LEN); - else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) { - /* clean up user-space RSNE */ - err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0); - if (err) { - bphy_err(drvr, "failed to clean up user-space RSNE\n"); - goto done; + if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { + /* enable firmware supplicant for this interface */ + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); + if (err < 0) { + bphy_err(drvr, "failed to enable fw supplicant\n"); + goto done; + } + } else { + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0); } - err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); - if (!err && sme->crypto.psk) + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) err = brcmf_set_pmk(ifp, sme->crypto.psk, BRCMF_WSEC_MAX_PSK_LEN); + else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE && + sme->crypto.sae_pwd && + brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE)) { + /* clean up user-space RSNE */ + if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) { + bphy_err(drvr, "failed to clean up user-space RSNE\n"); + goto done; + } + err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); + if (!err && sme->crypto.psk) + err = brcmf_set_pmk(ifp, sme->crypto.psk, + BRCMF_WSEC_MAX_PSK_LEN); + } + if (err) + goto done; } - if (err) - goto done; - /* Join with specific BSSID and cached SSID * If SSID is zero join based on BSSID only */ @@ -4519,6 +4530,11 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0); } +static bool brcmf_valid_dpp_suite(u8 *oui) +{ + return get_unaligned_be32(oui) == WLAN_AKM_SUITE_WFA_DPP; +} + static s32 brcmf_configure_wpaie(struct brcmf_if *ifp, const struct brcmf_vs_tlv *wpa_ie, @@ -4632,42 +4648,47 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, goto exit; } for (i = 0; i < count; i++) { - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + if (brcmf_valid_dpp_suite(&data[offset])) { + wpa_auth |= WFA_AUTH_DPP; + offset += TLV_OUI_LEN; + } else if (brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + offset += TLV_OUI_LEN; + switch (data[offset]) { + case RSN_AKM_NONE: + brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); + wpa_auth |= WPA_AUTH_NONE; + break; + case RSN_AKM_UNSPECIFIED: + brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); + is_rsn_ie ? + (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : + (wpa_auth |= WPA_AUTH_UNSPECIFIED); + break; + case RSN_AKM_PSK: + brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); + is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : + (wpa_auth |= WPA_AUTH_PSK); + break; + case RSN_AKM_SHA256_PSK: + brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); + wpa_auth |= WPA2_AUTH_PSK_SHA256; + break; + case RSN_AKM_SHA256_1X: + brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); + wpa_auth |= WPA2_AUTH_1X_SHA256; + break; + case RSN_AKM_SAE: + brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); + wpa_auth |= WPA3_AUTH_SAE_PSK; + break; + default: + bphy_err(drvr, "Invalid key mgmt info\n"); + } + } else { err = -EINVAL; bphy_err(drvr, "invalid OUI\n"); goto exit; } - offset += TLV_OUI_LEN; - switch (data[offset]) { - case RSN_AKM_NONE: - brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); - wpa_auth |= WPA_AUTH_NONE; - break; - case RSN_AKM_UNSPECIFIED: - brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : - (wpa_auth |= WPA_AUTH_UNSPECIFIED); - break; - case RSN_AKM_PSK: - brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : - (wpa_auth |= WPA_AUTH_PSK); - break; - case RSN_AKM_SHA256_PSK: - brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); - wpa_auth |= WPA2_AUTH_PSK_SHA256; - break; - case RSN_AKM_SHA256_1X: - brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); - wpa_auth |= WPA2_AUTH_1X_SHA256; - break; - case RSN_AKM_SAE: - brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); - wpa_auth |= WPA3_AUTH_SAE_PSK; - break; - default: - bphy_err(drvr, "Invalid key mgmt info\n"); - } offset++; } @@ -4687,10 +4708,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, */ if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 | WPA2_AUTH_1X_SHA256 | + WFA_AUTH_DPP | WPA3_AUTH_SAE_PSK))) { err = -EINVAL; goto exit; } + /* Firmware has requirement that WPA2_AUTH_PSK/ * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI * is to be included in the rsn ie. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 6e0c90f4718b..2c1f52ed5138 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -6,6 +6,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> +#include <linux/unaligned.h> #include <net/cfg80211.h> #include <brcmu_wifi.h> @@ -44,9 +45,6 @@ #define BRCMF_SCB_TIMEOUT_VALUE 20 -#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */ -#define P2P_PUB_AF_CATEGORY 0x04 -#define P2P_PUB_AF_ACTION 0x09 #define P2P_AF_CATEGORY 0x7f #define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */ #define P2P_OUI_LEN 3 /* P2P OUI length */ @@ -143,10 +141,10 @@ struct brcmf_p2p_scan_le { /** * struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame * - * @category: P2P_PUB_AF_CATEGORY - * @action: P2P_PUB_AF_ACTION + * @category: WLAN_CATEGORY_PUBLIC + * @action: WLAN_PUB_ACTION_VENDOR_SPECIFIC * @oui: P2P_OUI - * @oui_type: OUI type - P2P_VER + * @oui_type: OUI type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI subtype - P2P_TYPE_* * @dialog_token: nonzero, identifies req/rsp transaction * @elts: Variable length information elements. @@ -166,7 +164,7 @@ struct brcmf_p2p_pub_act_frame { * * @category: P2P_AF_CATEGORY * @oui: OUI - P2P_OUI - * @type: OUI Type - P2P_VER + * @type: OUI Type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI Subtype - P2P_AF_* * @dialog_token: nonzero, identifies req/resp tranaction * @elts: Variable length information elements. @@ -228,10 +226,38 @@ static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len) if (frame_len < sizeof(*pact_frm)) return false; - if (pact_frm->category == P2P_PUB_AF_CATEGORY && - pact_frm->action == P2P_PUB_AF_ACTION && - pact_frm->oui_type == P2P_VER && - memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_P2P && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) + return true; + + return false; +} + +/** + * brcmf_p2p_is_dpp_pub_action() - true if dpp public type frame. + * + * @frame: action frame data. + * @frame_len: length of action frame data. + * + * Determine if action frame is dpp public action type + */ +static bool brcmf_p2p_is_dpp_pub_action(void *frame, u32 frame_len) +{ + struct brcmf_p2p_pub_act_frame *pact_frm; + + if (!frame) + return false; + + pact_frm = (struct brcmf_p2p_pub_act_frame *)frame; + if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1) + return false; + + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_DPP && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) return true; return false; @@ -257,7 +283,7 @@ static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len) return false; if (act_frm->category == P2P_AF_CATEGORY && - act_frm->type == P2P_VER && + act_frm->type == WLAN_OUI_TYPE_WFA_P2P && memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) return true; @@ -1281,6 +1307,9 @@ static s32 brcmf_p2p_abort_action_frame(struct brcmf_cfg80211_info *cfg) brcmf_dbg(TRACE, "Enter\n"); vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; + if (!vif) + vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; + err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val, sizeof(s32)); if (err) @@ -1789,7 +1818,9 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, goto exit; } } else if (brcmf_p2p_is_p2p_action(action_frame->data, - action_frame_len)) { + action_frame_len) || + brcmf_p2p_is_dpp_pub_action(action_frame->data, + action_frame_len)) { /* do not configure anything. it will be */ /* sent with a default configuration */ } else { @@ -1826,6 +1857,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, /* validate channel and p2p ies */ if (config_af_params.search_channel && IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) && + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { afx_hdl = &p2p->afx_hdl; afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel); @@ -2543,4 +2575,3 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) /* just set it all to zero */ memset(p2p, 0, sizeof(*p2p)); } - diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 7552bdb91991..c465208c4331 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h @@ -233,6 +233,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */ +#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */ + #define DOT11_DEFAULT_RTS_LEN 2347 #define DOT11_DEFAULT_FRAG_LEN 2346 base-commit: 3737936e2be920977aea7d9f7eb8cb4468d700d7 -- 2.25.1 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v4] wifi: brcmfmac: add DPP support 2026-07-08 3:58 ` [PATCH v3] wifi: brcmfmac: add DPP support Jason Huang @ 2026-07-08 7:12 ` Jason Huang 2026-07-12 22:33 ` Arend van Spriel 2026-07-15 8:47 ` [PATCH v5] " Jason Huang 0 siblings, 2 replies; 10+ messages in thread From: Jason Huang @ 2026-07-08 7:12 UTC (permalink / raw) To: linux-wireless Cc: brcm80211, brcm80211-dev-list.pdl, linux-kernel, arend.vanspriel, Jason Huang, Kurt Lee From: Jason Huang <jason.huang2@infineon.com> Add DPP AKM handling and RSN parsing support. Map DPP to the firmware wpa_auth value and recognize DPP public action frames in the P2P action-frame TX path. Allow non-P2P public action frames such as DPP to use the primary vif when a P2P device vif is not present. Guard P2P-device IE access for the same case. Gate sup_wpa programming on firmware supplicant capability. Disable it only when the selected connection mode does not use firmware supplicant. This keeps pure SAE and 802.1X firmware-supplicant paths intact while avoiding stale firmware supplicant state for DPP. Signed-off-by: Kurt Lee <kurt.lee@cypress.com> Signed-off-by: Jason Huang <jason.huang2@infineon.com> --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 151 ++++++++++-------- .../broadcom/brcm80211/brcmfmac/p2p.c | 59 +++++-- .../broadcom/brcm80211/include/brcmu_wifi.h | 2 + 3 files changed, 134 insertions(+), 78 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 4b70845e1a26..d61c3e03a106 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/module.h> +#include <linux/unaligned.h> #include <linux/vmalloc.h> #include <net/cfg80211.h> #include <net/netlink.h> @@ -2154,6 +2155,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_PSK | WPA2_AUTH_FT; profile->is_ft = true; break; + case WLAN_AKM_SUITE_WFA_DPP: + val = WFA_AUTH_DPP; + break; default: bphy_err(drvr, "invalid akm suite (%d)\n", sme->crypto.akm_suites[0]); @@ -2466,43 +2470,50 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - if (sme->crypto.psk && - profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { - if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) { - 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 */ - err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); - if (err < 0) { - bphy_err(drvr, "failed to enable fw supplicant\n"); - goto done; + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) { + u32 akm = sme->crypto.n_akm_suites ? sme->crypto.akm_suites[0] : 0; + bool is_sae_akm = akm == WLAN_AKM_SUITE_SAE || + akm == WLAN_AKM_SUITE_FT_OVER_SAE; + + if (sme->crypto.psk && !is_sae_akm && + profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { + if (WARN_ON(profile->use_fwsup != + BRCMF_PROFILE_FWSUP_NONE)) { + 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_PSK) - err = brcmf_set_pmk(ifp, sme->crypto.psk, - BRCMF_WSEC_MAX_PSK_LEN); - else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) { - /* clean up user-space RSNE */ - err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0); - if (err) { - bphy_err(drvr, "failed to clean up user-space RSNE\n"); - goto done; + if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { + /* enable firmware supplicant for this interface */ + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); + if (err < 0) { + bphy_err(drvr, "failed to enable fw supplicant\n"); + goto done; + } + } else { + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0); } - err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); - if (!err && sme->crypto.psk) + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) err = brcmf_set_pmk(ifp, sme->crypto.psk, BRCMF_WSEC_MAX_PSK_LEN); + else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE && + sme->crypto.sae_pwd && + brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE)) { + /* clean up user-space RSNE */ + if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) { + bphy_err(drvr, "failed to clean up user-space RSNE\n"); + goto done; + } + err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); + if (!err && sme->crypto.psk) + err = brcmf_set_pmk(ifp, sme->crypto.psk, + BRCMF_WSEC_MAX_PSK_LEN); + } + if (err) + goto done; } - if (err) - goto done; - /* Join with specific BSSID and cached SSID * If SSID is zero join based on BSSID only */ @@ -4519,6 +4530,11 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0); } +static bool brcmf_valid_dpp_suite(u8 *oui) +{ + return get_unaligned_be32(oui) == WLAN_AKM_SUITE_WFA_DPP; +} + static s32 brcmf_configure_wpaie(struct brcmf_if *ifp, const struct brcmf_vs_tlv *wpa_ie, @@ -4632,42 +4648,47 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, goto exit; } for (i = 0; i < count; i++) { - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + if (brcmf_valid_dpp_suite(&data[offset])) { + wpa_auth |= WFA_AUTH_DPP; + offset += TLV_OUI_LEN; + } else if (brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + offset += TLV_OUI_LEN; + switch (data[offset]) { + case RSN_AKM_NONE: + brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); + wpa_auth |= WPA_AUTH_NONE; + break; + case RSN_AKM_UNSPECIFIED: + brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); + is_rsn_ie ? + (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : + (wpa_auth |= WPA_AUTH_UNSPECIFIED); + break; + case RSN_AKM_PSK: + brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); + is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : + (wpa_auth |= WPA_AUTH_PSK); + break; + case RSN_AKM_SHA256_PSK: + brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); + wpa_auth |= WPA2_AUTH_PSK_SHA256; + break; + case RSN_AKM_SHA256_1X: + brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); + wpa_auth |= WPA2_AUTH_1X_SHA256; + break; + case RSN_AKM_SAE: + brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); + wpa_auth |= WPA3_AUTH_SAE_PSK; + break; + default: + bphy_err(drvr, "Invalid key mgmt info\n"); + } + } else { err = -EINVAL; bphy_err(drvr, "invalid OUI\n"); goto exit; } - offset += TLV_OUI_LEN; - switch (data[offset]) { - case RSN_AKM_NONE: - brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); - wpa_auth |= WPA_AUTH_NONE; - break; - case RSN_AKM_UNSPECIFIED: - brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : - (wpa_auth |= WPA_AUTH_UNSPECIFIED); - break; - case RSN_AKM_PSK: - brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : - (wpa_auth |= WPA_AUTH_PSK); - break; - case RSN_AKM_SHA256_PSK: - brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); - wpa_auth |= WPA2_AUTH_PSK_SHA256; - break; - case RSN_AKM_SHA256_1X: - brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); - wpa_auth |= WPA2_AUTH_1X_SHA256; - break; - case RSN_AKM_SAE: - brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); - wpa_auth |= WPA3_AUTH_SAE_PSK; - break; - default: - bphy_err(drvr, "Invalid key mgmt info\n"); - } offset++; } @@ -4687,10 +4708,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, */ if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 | WPA2_AUTH_1X_SHA256 | + WFA_AUTH_DPP | WPA3_AUTH_SAE_PSK))) { err = -EINVAL; goto exit; } + /* Firmware has requirement that WPA2_AUTH_PSK/ * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI * is to be included in the rsn ie. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 6e0c90f4718b..2c1f52ed5138 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -6,6 +6,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> +#include <linux/unaligned.h> #include <net/cfg80211.h> #include <brcmu_wifi.h> @@ -44,9 +45,6 @@ #define BRCMF_SCB_TIMEOUT_VALUE 20 -#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */ -#define P2P_PUB_AF_CATEGORY 0x04 -#define P2P_PUB_AF_ACTION 0x09 #define P2P_AF_CATEGORY 0x7f #define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */ #define P2P_OUI_LEN 3 /* P2P OUI length */ @@ -143,10 +141,10 @@ struct brcmf_p2p_scan_le { /** * struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame * - * @category: P2P_PUB_AF_CATEGORY - * @action: P2P_PUB_AF_ACTION + * @category: WLAN_CATEGORY_PUBLIC + * @action: WLAN_PUB_ACTION_VENDOR_SPECIFIC * @oui: P2P_OUI - * @oui_type: OUI type - P2P_VER + * @oui_type: OUI type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI subtype - P2P_TYPE_* * @dialog_token: nonzero, identifies req/rsp transaction * @elts: Variable length information elements. @@ -166,7 +164,7 @@ struct brcmf_p2p_pub_act_frame { * * @category: P2P_AF_CATEGORY * @oui: OUI - P2P_OUI - * @type: OUI Type - P2P_VER + * @type: OUI Type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI Subtype - P2P_AF_* * @dialog_token: nonzero, identifies req/resp tranaction * @elts: Variable length information elements. @@ -228,10 +226,38 @@ static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len) if (frame_len < sizeof(*pact_frm)) return false; - if (pact_frm->category == P2P_PUB_AF_CATEGORY && - pact_frm->action == P2P_PUB_AF_ACTION && - pact_frm->oui_type == P2P_VER && - memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_P2P && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) + return true; + + return false; +} + +/** + * brcmf_p2p_is_dpp_pub_action() - true if dpp public type frame. + * + * @frame: action frame data. + * @frame_len: length of action frame data. + * + * Determine if action frame is dpp public action type + */ +static bool brcmf_p2p_is_dpp_pub_action(void *frame, u32 frame_len) +{ + struct brcmf_p2p_pub_act_frame *pact_frm; + + if (!frame) + return false; + + pact_frm = (struct brcmf_p2p_pub_act_frame *)frame; + if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1) + return false; + + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_DPP && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) return true; return false; @@ -257,7 +283,7 @@ static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len) return false; if (act_frm->category == P2P_AF_CATEGORY && - act_frm->type == P2P_VER && + act_frm->type == WLAN_OUI_TYPE_WFA_P2P && memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) return true; @@ -1281,6 +1307,9 @@ static s32 brcmf_p2p_abort_action_frame(struct brcmf_cfg80211_info *cfg) brcmf_dbg(TRACE, "Enter\n"); vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; + if (!vif) + vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; + err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe_abort", &int_val, sizeof(s32)); if (err) @@ -1789,7 +1818,9 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, goto exit; } } else if (brcmf_p2p_is_p2p_action(action_frame->data, - action_frame_len)) { + action_frame_len) || + brcmf_p2p_is_dpp_pub_action(action_frame->data, + action_frame_len)) { /* do not configure anything. it will be */ /* sent with a default configuration */ } else { @@ -1826,6 +1857,7 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, /* validate channel and p2p ies */ if (config_af_params.search_channel && IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) && + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { afx_hdl = &p2p->afx_hdl; afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel); @@ -2543,4 +2575,3 @@ void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) /* just set it all to zero */ memset(p2p, 0, sizeof(*p2p)); } - diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 7552bdb91991..c465208c4331 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h @@ -233,6 +233,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */ +#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */ + #define DOT11_DEFAULT_RTS_LEN 2347 #define DOT11_DEFAULT_FRAG_LEN 2346 base-commit: 3737936e2be920977aea7d9f7eb8cb4468d700d7 -- 2.25.1 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] wifi: brcmfmac: add DPP support 2026-07-08 7:12 ` [PATCH v4] " Jason Huang @ 2026-07-12 22:33 ` Arend van Spriel 2026-07-15 9:22 ` HungTsung Huang 2026-07-15 8:47 ` [PATCH v5] " Jason Huang 1 sibling, 1 reply; 10+ messages in thread From: Arend van Spriel @ 2026-07-12 22:33 UTC (permalink / raw) To: Jason Huang Cc: arend.vanspriel, brcm80211-dev-list.pdl, brcm80211, linux-kernel, linux-wireless, Kurt Lee On Wed, 8 Jul 2026 15:12:30 +0800, Jason Huang wrote: > Add DPP AKM handling and RSN parsing support. Map DPP to the > firmware wpa_auth value and recognize DPP public action frames in the > P2P action-frame TX path. [...] > + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && > p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { [...] > --- > .../broadcom/brcm80211/brcmfmac/cfg80211.c | 151 ++++++++++-------- > .../broadcom/brcm80211/brcmfmac/p2p.c | 59 +++++-- > .../broadcom/brcm80211/include/brcmu_wifi.h | 2 + In the v2 review I asked to split the P2P device vif bug fix into a separate patch with a Fixes: tag for stable backport. The null guard and the fallback vif in brcmf_p2p_abort_action_frame() are both pre-existing P2P bugs that should be split out and submitted as a standalone patch so they can be backported to stable independently of the DPP feature. Please also add a changelog below the --- line describing what changed since v3. Note that the P2P device vif fixes are pre-existing bugs that need to go to the wireless tree for stable backport, separate from the DPP feature which targets wireless-next. Regards, Arend ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] wifi: brcmfmac: add DPP support 2026-07-12 22:33 ` Arend van Spriel @ 2026-07-15 9:22 ` HungTsung Huang 2026-07-15 18:46 ` Arend van Spriel 2026-07-20 18:48 ` Arend van Spriel 0 siblings, 2 replies; 10+ messages in thread From: HungTsung Huang @ 2026-07-15 9:22 UTC (permalink / raw) To: Arend van Spriel Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel Hi Arend, Thanks for the clarification. Could you please confirm whether it is OK to submit the standalone P2P fix to wireless in parallel to wireless-next origin/main? My understanding is that the P2P fix does not need to wait for the DPP support patch to be accepted, since it fixes pre-existing bugs and the DPP patch no longer depends on it. The reason I added: > > + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && > > p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { was that DPP public action frames can be sent through the primary interface without a P2P device vif being created. The existing peer channel search path assumed the P2P device vif was always available before accessing saved Probe Request IEs, which could dereference a NULL vif in that case. However, I agree this is a pre-existing P2P bug rather than part of DPP support, so I moved it into the standalone P2P fix patch. Regards, Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] wifi: brcmfmac: add DPP support 2026-07-15 9:22 ` HungTsung Huang @ 2026-07-15 18:46 ` Arend van Spriel 2026-07-20 18:48 ` Arend van Spriel 1 sibling, 0 replies; 10+ messages in thread From: Arend van Spriel @ 2026-07-15 18:46 UTC (permalink / raw) To: HungTsung Huang Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel, Johannes Berg On 15/07/2026 11:22, HungTsung Huang wrote: > Hi Arend, > > Thanks for the clarification. > > Could you please confirm whether it is OK to submit the standalone P2P fix > to wireless in parallel to wireless-next origin/main? My understanding is > that the P2P fix does not need to wait for the DPP support patch to be > accepted, since it fixes pre-existing bugs and the DPP patch no longer > depends on it. Yes. You can submit the P2P fix in parallel. I am not sure if wireless-next is rebased against wireless in a release cycle. Maybe this kind of scenario is a reason to do so. > The reason I added: >>> + p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif && >>> p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { > > was that DPP public action frames can be sent through the primary interface > without a P2P device vif being created. The existing peer channel search path > assumed the P2P device vif was always available before accessing saved > Probe Request IEs, which could dereference a NULL vif in that case. However, > I agree this is a pre-existing P2P bug rather than part of DPP support, so I > moved it into the standalone P2P fix patch. Thanks. Regards, Arend ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v4] wifi: brcmfmac: add DPP support 2026-07-15 9:22 ` HungTsung Huang 2026-07-15 18:46 ` Arend van Spriel @ 2026-07-20 18:48 ` Arend van Spriel 1 sibling, 0 replies; 10+ messages in thread From: Arend van Spriel @ 2026-07-20 18:48 UTC (permalink / raw) To: HungTsung Huang Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel On 15/07/2026 11:22, HungTsung Huang wrote: > I agree this is a pre-existing P2P bug rather than part of DPP support, so I > moved it into the standalone P2P fix patch. Hi Jason, I must have missed the "standalone P2P fix patch". Can you provide a reference or submit the patch against the wireless tree if not already done so. Thanks, Arend ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v5] wifi: brcmfmac: add DPP support 2026-07-08 7:12 ` [PATCH v4] " Jason Huang 2026-07-12 22:33 ` Arend van Spriel @ 2026-07-15 8:47 ` Jason Huang 2026-07-20 19:48 ` Arend van Spriel 1 sibling, 1 reply; 10+ messages in thread From: Jason Huang @ 2026-07-15 8:47 UTC (permalink / raw) To: linux-wireless Cc: brcm80211, brcm80211-dev-list.pdl, linux-kernel, arend.vanspriel, Jason Huang, Kurt Lee From: Jason Huang <jason.huang2@infineon.com> Add DPP AKM handling and RSN parsing support. Map DPP to the firmware wpa_auth value and recognize DPP public action frames in the P2P action-frame TX path. Gate sup_wpa programming on firmware supplicant capability. Disable it only when the selected connection mode does not use firmware supplicant. This keeps pure SAE and 802.1X firmware-supplicant paths intact while avoiding stale firmware supplicant state for DPP. Signed-off-by: Kurt Lee <kurt.lee@cypress.com> Signed-off-by: Jason Huang <jason.huang2@infineon.com> --- Changes since v4: - Drop the pre-existing P2P device vif fixes; they are now a standalone wireless patch. - Keep this patch limited to DPP AKM/RSN parsing and DPP public action frame handling. .../broadcom/brcm80211/brcmfmac/cfg80211.c | 151 ++++++++++-------- .../broadcom/brcm80211/brcmfmac/p2p.c | 54 +++++-- .../broadcom/brcm80211/include/brcmu_wifi.h | 2 + 3 files changed, 130 insertions(+), 77 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 4b70845e1a26..d61c3e03a106 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -8,6 +8,7 @@ #include <linux/kernel.h> #include <linux/etherdevice.h> #include <linux/module.h> +#include <linux/unaligned.h> #include <linux/vmalloc.h> #include <net/cfg80211.h> #include <net/netlink.h> @@ -2154,6 +2155,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WPA2_AUTH_PSK | WPA2_AUTH_FT; profile->is_ft = true; break; + case WLAN_AKM_SUITE_WFA_DPP: + val = WFA_AUTH_DPP; + break; default: bphy_err(drvr, "invalid akm suite (%d)\n", sme->crypto.akm_suites[0]); @@ -2466,43 +2470,50 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - if (sme->crypto.psk && - profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { - if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) { - 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 */ - err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); - if (err < 0) { - bphy_err(drvr, "failed to enable fw supplicant\n"); - goto done; + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) { + u32 akm = sme->crypto.n_akm_suites ? sme->crypto.akm_suites[0] : 0; + bool is_sae_akm = akm == WLAN_AKM_SUITE_SAE || + akm == WLAN_AKM_SUITE_FT_OVER_SAE; + + if (sme->crypto.psk && !is_sae_akm && + profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { + if (WARN_ON(profile->use_fwsup != + BRCMF_PROFILE_FWSUP_NONE)) { + 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_PSK) - err = brcmf_set_pmk(ifp, sme->crypto.psk, - BRCMF_WSEC_MAX_PSK_LEN); - else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) { - /* clean up user-space RSNE */ - err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0); - if (err) { - bphy_err(drvr, "failed to clean up user-space RSNE\n"); - goto done; + if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) { + /* enable firmware supplicant for this interface */ + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); + if (err < 0) { + bphy_err(drvr, "failed to enable fw supplicant\n"); + goto done; + } + } else { + err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0); } - err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); - if (!err && sme->crypto.psk) + if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) err = brcmf_set_pmk(ifp, sme->crypto.psk, BRCMF_WSEC_MAX_PSK_LEN); + else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE && + sme->crypto.sae_pwd && + brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE)) { + /* clean up user-space RSNE */ + if (brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0)) { + bphy_err(drvr, "failed to clean up user-space RSNE\n"); + goto done; + } + err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto); + if (!err && sme->crypto.psk) + err = brcmf_set_pmk(ifp, sme->crypto.psk, + BRCMF_WSEC_MAX_PSK_LEN); + } + if (err) + goto done; } - if (err) - goto done; - /* Join with specific BSSID and cached SSID * If SSID is zero join based on BSSID only */ @@ -4519,6 +4530,11 @@ static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0); } +static bool brcmf_valid_dpp_suite(u8 *oui) +{ + return get_unaligned_be32(oui) == WLAN_AKM_SUITE_WFA_DPP; +} + static s32 brcmf_configure_wpaie(struct brcmf_if *ifp, const struct brcmf_vs_tlv *wpa_ie, @@ -4632,42 +4648,47 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, goto exit; } for (i = 0; i < count; i++) { - if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + if (brcmf_valid_dpp_suite(&data[offset])) { + wpa_auth |= WFA_AUTH_DPP; + offset += TLV_OUI_LEN; + } else if (brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + offset += TLV_OUI_LEN; + switch (data[offset]) { + case RSN_AKM_NONE: + brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); + wpa_auth |= WPA_AUTH_NONE; + break; + case RSN_AKM_UNSPECIFIED: + brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); + is_rsn_ie ? + (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : + (wpa_auth |= WPA_AUTH_UNSPECIFIED); + break; + case RSN_AKM_PSK: + brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); + is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : + (wpa_auth |= WPA_AUTH_PSK); + break; + case RSN_AKM_SHA256_PSK: + brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); + wpa_auth |= WPA2_AUTH_PSK_SHA256; + break; + case RSN_AKM_SHA256_1X: + brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); + wpa_auth |= WPA2_AUTH_1X_SHA256; + break; + case RSN_AKM_SAE: + brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); + wpa_auth |= WPA3_AUTH_SAE_PSK; + break; + default: + bphy_err(drvr, "Invalid key mgmt info\n"); + } + } else { err = -EINVAL; bphy_err(drvr, "invalid OUI\n"); goto exit; } - offset += TLV_OUI_LEN; - switch (data[offset]) { - case RSN_AKM_NONE: - brcmf_dbg(TRACE, "RSN_AKM_NONE\n"); - wpa_auth |= WPA_AUTH_NONE; - break; - case RSN_AKM_UNSPECIFIED: - brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : - (wpa_auth |= WPA_AUTH_UNSPECIFIED); - break; - case RSN_AKM_PSK: - brcmf_dbg(TRACE, "RSN_AKM_PSK\n"); - is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : - (wpa_auth |= WPA_AUTH_PSK); - break; - case RSN_AKM_SHA256_PSK: - brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n"); - wpa_auth |= WPA2_AUTH_PSK_SHA256; - break; - case RSN_AKM_SHA256_1X: - brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n"); - wpa_auth |= WPA2_AUTH_1X_SHA256; - break; - case RSN_AKM_SAE: - brcmf_dbg(TRACE, "RSN_AKM_SAE\n"); - wpa_auth |= WPA3_AUTH_SAE_PSK; - break; - default: - bphy_err(drvr, "Invalid key mgmt info\n"); - } offset++; } @@ -4687,10 +4708,12 @@ brcmf_configure_wpaie(struct brcmf_if *ifp, */ if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 | WPA2_AUTH_1X_SHA256 | + WFA_AUTH_DPP | WPA3_AUTH_SAE_PSK))) { err = -EINVAL; goto exit; } + /* Firmware has requirement that WPA2_AUTH_PSK/ * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI * is to be included in the rsn ie. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 6e0c90f4718b..58a9738e81ac 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -6,6 +6,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> +#include <linux/unaligned.h> #include <net/cfg80211.h> #include <brcmu_wifi.h> @@ -44,9 +45,6 @@ #define BRCMF_SCB_TIMEOUT_VALUE 20 -#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */ -#define P2P_PUB_AF_CATEGORY 0x04 -#define P2P_PUB_AF_ACTION 0x09 #define P2P_AF_CATEGORY 0x7f #define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */ #define P2P_OUI_LEN 3 /* P2P OUI length */ @@ -143,10 +141,10 @@ struct brcmf_p2p_scan_le { /** * struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame * - * @category: P2P_PUB_AF_CATEGORY - * @action: P2P_PUB_AF_ACTION + * @category: WLAN_CATEGORY_PUBLIC + * @action: WLAN_PUB_ACTION_VENDOR_SPECIFIC * @oui: P2P_OUI - * @oui_type: OUI type - P2P_VER + * @oui_type: OUI type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI subtype - P2P_TYPE_* * @dialog_token: nonzero, identifies req/rsp transaction * @elts: Variable length information elements. @@ -166,7 +164,7 @@ struct brcmf_p2p_pub_act_frame { * * @category: P2P_AF_CATEGORY * @oui: OUI - P2P_OUI - * @type: OUI Type - P2P_VER + * @type: OUI Type - WLAN_OUI_TYPE_WFA_P2P * @subtype: OUI Subtype - P2P_AF_* * @dialog_token: nonzero, identifies req/resp tranaction * @elts: Variable length information elements. @@ -228,10 +226,38 @@ static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len) if (frame_len < sizeof(*pact_frm)) return false; - if (pact_frm->category == P2P_PUB_AF_CATEGORY && - pact_frm->action == P2P_PUB_AF_ACTION && - pact_frm->oui_type == P2P_VER && - memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_P2P && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) + return true; + + return false; +} + +/** + * brcmf_p2p_is_dpp_pub_action() - true if dpp public type frame. + * + * @frame: action frame data. + * @frame_len: length of action frame data. + * + * Determine if action frame is dpp public action type + */ +static bool brcmf_p2p_is_dpp_pub_action(void *frame, u32 frame_len) +{ + struct brcmf_p2p_pub_act_frame *pact_frm; + + if (!frame) + return false; + + pact_frm = (struct brcmf_p2p_pub_act_frame *)frame; + if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1) + return false; + + if (pact_frm->category == WLAN_CATEGORY_PUBLIC && + pact_frm->action == WLAN_PUB_ACTION_VENDOR_SPECIFIC && + pact_frm->oui_type == WLAN_OUI_TYPE_WFA_DPP && + get_unaligned_be24(pact_frm->oui) == WLAN_OUI_WFA) return true; return false; @@ -257,7 +283,7 @@ static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len) return false; if (act_frm->category == P2P_AF_CATEGORY && - act_frm->type == P2P_VER && + act_frm->type == WLAN_OUI_TYPE_WFA_P2P && memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) return true; @@ -1789,7 +1815,9 @@ bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, goto exit; } } else if (brcmf_p2p_is_p2p_action(action_frame->data, - action_frame_len)) { + action_frame_len) || + brcmf_p2p_is_dpp_pub_action(action_frame->data, + action_frame_len)) { /* do not configure anything. it will be */ /* sent with a default configuration */ } else { diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 7552bdb91991..c465208c4331 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h @@ -233,6 +233,8 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */ +#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */ + #define DOT11_DEFAULT_RTS_LEN 2347 #define DOT11_DEFAULT_FRAG_LEN 2346 base-commit: 3737936e2be920977aea7d9f7eb8cb4468d700d7 -- 2.25.1 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5] wifi: brcmfmac: add DPP support 2026-07-15 8:47 ` [PATCH v5] " Jason Huang @ 2026-07-20 19:48 ` Arend van Spriel 2026-07-23 5:22 ` HungTsung Huang 0 siblings, 1 reply; 10+ messages in thread From: Arend van Spriel @ 2026-07-20 19:48 UTC (permalink / raw) To: linux-wireless Cc: Arend van Spriel, brcm80211, brcm80211-dev-list.pdl, linux-kernel, Jason Huang, Kurt Lee On Wed, 15 Jul 2026, Jason Huang wrote: > [PATCH v5] wifi: brcmfmac: add DPP support > > Add DPP AKM handling and RSN parsing support ... > > Changes since v4: > - Drop the pre-existing P2P device vif fixes; they are now a standalone > wireless patch. The DPP code looks good. The P2P fixes have been removed as requested and the changelog is present. Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com> This ack is conditional on the standalone P2P device vif guard patch being submitted. When you post it, please reply here with the lore.kernel.org link so I can track it. Regards, Arend ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v5] wifi: brcmfmac: add DPP support 2026-07-20 19:48 ` Arend van Spriel @ 2026-07-23 5:22 ` HungTsung Huang 0 siblings, 0 replies; 10+ messages in thread From: HungTsung Huang @ 2026-07-23 5:22 UTC (permalink / raw) To: Arend van Spriel, y Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel, Kurt Lee Hi Arend, Thank you for the Acked-by. As requested, the standalone P2P device vif guard patch has been submitted. Here is the official Linux mailing list link so you can track it. https://patchwork.kernel.org/project/linux-wireless/patch/20260722082608.412472-1-Jason.Huang2@infineon.com/ Best regards, Jason On Mon, Jul 20, 2026 at 09:48:56PM +0200, Arend van Spriel wrote: > Caution: This e-mail originated outside Infineon Technologies. Please be cautious when sharing information or opening attachments especially from unknown senders. Refer to our intranet guide<https://intranet-content.infineon.com/explore/aboutinfineon/rules/informationsecurity/ug/SocialEngineering/Pages/SocialEngineeringElements_en.aspx> to help you identify Phishing email. > > > > On Wed, 15 Jul 2026, Jason Huang wrote: > > > [PATCH v5] wifi: brcmfmac: add DPP support > > > > Add DPP AKM handling and RSN parsing support ... > > > > Changes since v4: > > - Drop the pre-existing P2P device vif fixes; they are now a standalone > > wireless patch. > > The DPP code looks good. The P2P fixes have been removed as requested and > the changelog is present. > > Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com> > > This ack is conditional on the standalone P2P device vif guard patch being > submitted. When you post it, please reply here with the lore.kernel.org > link so I can track it. > > Regards, > Arend ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-07-23 5:22 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20260603035722.145894-1-Jason.Huang2@infineon.com>
2026-06-04 3:42 ` [PATCH v2] wifi: brcmfmac: add DPP support and fix fw-supplicant/P2P interop Jason Huang
2026-07-08 3:58 ` [PATCH v3] wifi: brcmfmac: add DPP support Jason Huang
2026-07-08 7:12 ` [PATCH v4] " Jason Huang
2026-07-12 22:33 ` Arend van Spriel
2026-07-15 9:22 ` HungTsung Huang
2026-07-15 18:46 ` Arend van Spriel
2026-07-20 18:48 ` Arend van Spriel
2026-07-15 8:47 ` [PATCH v5] " Jason Huang
2026-07-20 19:48 ` Arend van Spriel
2026-07-23 5:22 ` HungTsung Huang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®