brcmf_feat_firmware_capabilities() looks for each capability with strnstr() in the space separated reply of the "cap" iovar, so a capability matches inside a longer one. The Apple firmware for the BCM4364 lists "hp2p" but not "p2p": ... evt_ext lpr_scan bkoff_evt hp2p rng_reseed arpoe The driver still sets BRCMF_FEAT_P2P and advertises the P2P interface types. wpa_supplicant then creates a P2P device, which fails because the firmware rejects p2p_disc and p2p_da_override with BCME_UNSUPPORTED: brcmf_p2p_set_firmware: failed to update device address ret -52 brcmf_p2p_create_p2pdev: set p2p_disc error brcmf_cfg80211_add_iface: add iface p2p-dev-wlp3s0 type 10 failed: err=-52 Split the reply at spaces and compare whole words. The trailing spaces in "sae", which kept it from matching "sae-ap" and "sae_ext", and in "fbt" can go. Fixes: ec64241c9fd2 ("brcmfmac: obtain feature info using 'cap' firmware command") Reported-by: Aditya Garg Closes: https://lore.kernel.org/all/MA0P287MB021718EE92FC809CB2BB0F82B8BD2@MA0P287MB0217.INDP287.PROD.OUTLOOK.COM/ Tested-by: Yossef Osman Tested-by: Aditya Garg Signed-off-by: Andre Eikmeyer --- .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index cc19e5e7ebf..b324eb53a69 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -42,10 +42,10 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = { { BRCMF_FEAT_MONITOR_FLAG, "rtap" }, { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" }, { BRCMF_FEAT_DOT11H, "802.11h" }, - { BRCMF_FEAT_SAE, "sae " }, + { BRCMF_FEAT_SAE, "sae" }, { BRCMF_FEAT_FWAUTH, "idauth" }, { BRCMF_FEAT_SAE_EXT, "sae_ext" }, - { BRCMF_FEAT_FBT, "fbt " }, + { BRCMF_FEAT_FBT, "fbt" }, { BRCMF_FEAT_OKC, "okc" }, }; @@ -231,6 +231,7 @@ static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp) { struct brcmf_pub *drvr = ifp->drvr; char caps[MAX_CAPS_BUFFER_SIZE]; + char *cap, *next; enum brcmf_feat_id id; int i, err; @@ -240,10 +241,15 @@ static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp) return; } + caps[sizeof(caps) - 1] = '\0'; brcmf_dbg(INFO, "[ %s]\n", caps); - for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) { - if (strnstr(caps, brcmf_fwcap_map[i].fwcap_id, sizeof(caps))) { + /* Match whole words, "hp2p" must not enable P2P */ + next = caps; + while ((cap = strsep(&next, "\n "))) { + for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) { + if (strcmp(cap, brcmf_fwcap_map[i].fwcap_id)) + continue; id = brcmf_fwcap_map[i].feature; brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);