From 2a25a441e73583e1b8173621bb48d0a4cb6efc1b Mon Sep 17 00:00:00 2001 From: Adesh Kumar Singh Date: Fri, 2 Jun 2023 02:10:27 -0500 Subject: [PATCH 269/296] non-upstream: Add support for pfn autoswitch PFN autoswitch support added Fixes: SWWLAN-146955 Signed-off-by: Adesh Kumar Singh --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 42 +++-- .../broadcom/brcm80211/brcmfmac/cfg80211.h | 3 +- .../broadcom/brcm80211/brcmfmac/pno.c | 158 +++--------------- .../broadcom/brcm80211/brcmfmac/pno.h | 12 +- .../broadcom/brcm80211/brcmfmac/vendor_ifx.c | 30 ++-- 5 files changed, 71 insertions(+), 174 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 411fcc5d695a..dd50568c69de 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -2830,6 +2830,28 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, bool skip_hints = ifp->drvr->settings->fw_ap_select; brcmf_dbg(TRACE, "Enter\n"); + + if (cfg->pfn_enable && cfg->pfn_connection) { + err = brcmf_fil_cmd_data_set(ifp, + BRCMF_C_DISASSOC, NULL, 0); + if (err) { + brcmf_err("BRCMF_C_DISASSOC error:%d\n", err); + return -1; + } + cfg->pfn_connection = 0; + + /* Disable pfn */ + err = brcmf_fil_iovar_int_set(ifp, "pfn", 0); + if (err < 0) { + brcmf_err("pfn disable error:%d\n", err); + } else { + /* clear pfn */ + err = brcmf_fil_iovar_data_set(ifp, "pfnclear", NULL, 0); + if (err) + brcmf_err("pfnclear error:%d\n", err); + } + } + if (!check_vif_up(ifp->vif)) return -EIO; @@ -3037,13 +3059,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, brcmf_set_join_pref(ifp, &sme->bss_select); - if (cfg->pfn_enable) { - err = pfn_save_curr_network(wiphy, ndev, sme); - if (err) { - brcmf_err("pfn: not able to save the curr network:%d\n", err); - } - } - /* The internal supplicant judges to use assoc or reassoc itself. * it is not necessary to specify REASSOC */ @@ -3112,7 +3127,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, cfg80211_disconnected(ndev, reason_code, NULL, 0, true, GFP_KERNEL); if (cfg->pfn_enable) { - memset(&cfg->curr_network, '\0', sizeof(struct network_blob)); + cfg->pfn_connection = 0; pfn_send_network_blob_fw(wiphy, &ifp->vif->wdev); } @@ -7904,15 +7919,6 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, struct cfg80211_connect_resp_params conn_params; brcmf_dbg(TRACE, "Enter cfg->pfn_enable %d\n", cfg->pfn_enable); - if (cfg->pfn_enable) { - if (!completed) { - memset(&cfg->curr_network, '\0', sizeof(struct network_blob)); - pfn_send_network_blob_fw(cfg->wiphy, &ifp->vif->wdev); - } - if (cfg->curr_network.ssid_len) { - pfn_send_network_blob_fw(cfg->wiphy, &ifp->vif->wdev); - } - } if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { @@ -7945,6 +7951,8 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, cfg80211_connect_done(ndev, &conn_params, GFP_KERNEL); brcmf_dbg(CONN, "Report connect result - connection %s\n", completed ? "succeeded" : "failed"); + } else if (cfg->pfn_enable && completed) { + cfg->pfn_connection = 1; } brcmf_dbg(TRACE, "Exit\n"); return 0; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 7e47f5dbf24a..6be4de07e906 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -364,6 +364,7 @@ struct network_blob { }; struct drv_config_pfn_params { + u8 pfn_config; u8 count; struct network_blob *network_blob_data; }; @@ -439,8 +440,8 @@ struct brcmf_cfg80211_info { u8 pm_state; u8 num_softap; u8 pfn_enable; + u8 pfn_connection; struct drv_config_pfn_params pfn_data; - struct network_blob curr_network; }; /** diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index e5cb835855a7..a1a774d9a064 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -613,13 +613,11 @@ int pfn_send_network_blob_fw(struct wiphy *wiphy, brcmf_dbg(TRACE, "Enter\n"); - if (!cfg->curr_network.ssid_len) { - ret = brcmf_fil_cmd_data_set(vif->ifp, - BRCMF_C_DISASSOC, NULL, 0); - if (ret) { - brcmf_err("BRCMF_C_DISASSOC error:%d\n", ret); - return -1; - } + ret = brcmf_fil_cmd_data_set(vif->ifp, + BRCMF_C_DISASSOC, NULL, 0); + if (ret) { + brcmf_err("BRCMF_C_DISASSOC error:%d\n", ret); + return -1; } brcmf_pno_clean(ifp); @@ -629,7 +627,7 @@ int pfn_send_network_blob_fw(struct wiphy *wiphy, return -1; } - if (!cfg->pfn_data.count && !cfg->curr_network.ssid_len) + if (!cfg->pfn_data.count) return 0; pfn_param.version = PFN_VERSION; @@ -642,7 +640,18 @@ int pfn_send_network_blob_fw(struct wiphy *wiphy, pfn_param.mscan = DEFAULT_MSCAN; pfn_param.repeat = DEFAULT_REPEAT; pfn_param.exp = DEFAULT_EXP; - pfn_param.flags |= AUTO_CONNECT_MASK; + + if (cfg->pfn_data.pfn_config == PFN_CONFIG_AUTOCONNECT) { + pfn_param.flags |= AUTO_CONNECT_MASK; + + } else if (cfg->pfn_data.pfn_config == PFN_CONFIG_AUTOSWITCH_LISTORDER) { + pfn_param.flags |= AUTO_NET_SWITCH_MASK; + pfn_param.flags |= (PFN_LIST_ORDER << SORT_CRITERIA_BIT); + + } else if (cfg->pfn_data.pfn_config == PFN_CONFIG_AUTOSWITCH_RSSI) { + pfn_param.flags |= AUTO_NET_SWITCH_MASK; + pfn_param.flags |= (PFN_RSSI << SORT_CRITERIA_BIT); + } pfn_param.version = cpu_to_le32(pfn_param.version); pfn_param.scan_freq = cpu_to_le32(pfn_param.scan_freq); @@ -660,55 +669,10 @@ int pfn_send_network_blob_fw(struct wiphy *wiphy, brcm_pfn_length = (cfg->pfn_data.count) * sizeof(struct brcm_pfn); - if (cfg->curr_network.ssid_len) - brcm_pfn_length += sizeof(struct brcm_pfn); - pfn_list_buffer = (struct brcm_pfn *)kzalloc(brcm_pfn_length, GFP_KERNEL); pssidnet = pfn_list_buffer; network_blob_data = cfg->pfn_data.network_blob_data; - if (cfg->curr_network.ssid_len) { - pssidnet->auth = WLAN_AUTH_OPEN; - pssidnet->wpa_auth = WPA_AUTH_DISABLED; - pssidnet->wsec = WPA_CIPHER_NONE; - pssidnet->infra = WPAS_MODE_IBSS; - pssidnet->flags = 0; - memcpy((char *)pssidnet->ssid.SSID, cfg->curr_network.ssid, - cfg->curr_network.ssid_len); - pssidnet->ssid.SSID_len = cpu_to_le32(cfg->curr_network.ssid_len); - pssidnet->flags = cpu_to_le32(pssidnet->flags); - - if (cfg->curr_network.proto == WPA_PROTO_WPA && - cfg->curr_network.key_mgmt == KEY_MGMT_WPA) { - pssidnet->wpa_auth = WPA_AUTH_PSK; - - } else if (cfg->curr_network.proto == WPA_PROTO_RSN && - cfg->curr_network.key_mgmt == KEY_MGMT_WPA2) { - pssidnet->wpa_auth = WPA2_AUTH_PSK; - - } else if (cfg->curr_network.proto == WPA_PROTO_RSN && - cfg->curr_network.key_mgmt == KEY_MGMT_SAE) { - pssidnet->wpa_auth = WPA3_AUTH_SAE_PSK; - pssidnet->auth = WLAN_AUTH_SAE; - - } else if (cfg->curr_network.proto == WPA_PROTO_RSN && - cfg->curr_network.key_mgmt == KEY_MGMT_OWE) { - pssidnet->wpa_auth = WPA3_AUTH_OWE; - } - - if (cfg->curr_network.pairwise_cipher == BIT(WPA_CIPHER_AES_CCM)) - pssidnet->wsec = AES_ENABLED; - - else if (cfg->curr_network.pairwise_cipher == BIT(WPA_CIPHER_TKIP)) - pssidnet->wsec = TKIP_ENABLED; - - brcmf_dbg(TRACE, "ssid %s key_mgmt %d proto %d wsec %d wpa_auth %d auth %d\n", - cfg->curr_network.ssid, cfg->curr_network.key_mgmt, - cfg->curr_network.proto, pssidnet->wsec, - pssidnet->wpa_auth, pssidnet->auth); - pssidnet++; - } - for (i = 0; i < cfg->pfn_data.count; i++) { /* Default setting, open, no WPA, no WEP and bss */ pssidnet->auth = WLAN_AUTH_OPEN; @@ -721,6 +685,12 @@ int pfn_send_network_blob_fw(struct wiphy *wiphy, pssidnet->ssid.SSID_len = cpu_to_le32(network_blob_data->ssid_len); pssidnet->flags = cpu_to_le32(pssidnet->flags); + if (strlen(network_blob_data->psk)) { + strncpy((char *)pssidnet->psk.key, + network_blob_data->psk, WSEC_MAX_PSK_LEN); + pssidnet->psk.key_len = strlen(network_blob_data->psk); + } + if (network_blob_data->proto == WPA_PROTO_WPA && network_blob_data->key_mgmt == KEY_MGMT_WPA) { pssidnet->wpa_auth = WPA_AUTH_PSK; @@ -767,83 +737,3 @@ int pfn_send_network_blob_fw(struct wiphy *wiphy, brcmf_dbg(TRACE, "Exit\n"); return 0; } - -int pfn_save_curr_network(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_connect_params *sme) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_if *ifp = netdev_priv(ndev); - struct brcmf_pub *drvr = ifp->drvr; - struct network_blob *curr_network; - int ret; - s32 val; - - brcmf_dbg(TRACE, "Enter\n"); - curr_network = &cfg->curr_network; - brcmf_pno_clean(ifp); - - if (sme->ssid_len) - memcpy(curr_network->ssid, sme->ssid, sme->ssid_len); - - curr_network->ssid_len = sme->ssid_len; - ret = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "wpa_auth", &val); - if (ret) { - bphy_err(drvr, "could not get wpa_auth (%d)\n", ret); - return ret; - } - - if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { - switch (sme->crypto.akm_suites[0]) { - case WLAN_AKM_SUITE_8021X: - val = WPA_AUTH_UNSPECIFIED; - curr_network->proto = (WPA_PROTO_RSN | WPA_PROTO_WPA); - curr_network->key_mgmt = KEY_MGMT_WPA_NONE; - break; - case WLAN_AKM_SUITE_PSK: - val = WPA_AUTH_PSK; - curr_network->proto = WPA_PROTO_RSN; - curr_network->key_mgmt = KEY_MGMT_WPA; - break; - default: - bphy_err(drvr, "invalid cipher group (%d)\n", - sme->crypto.cipher_group); - return -EINVAL; - } - } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { - switch (sme->crypto.akm_suites[0]) { - case WLAN_AKM_SUITE_8021X: - val = WPA2_AUTH_UNSPECIFIED; - curr_network->proto = (WPA_PROTO_RSN | WPA_PROTO_WPA); - curr_network->key_mgmt = KEY_MGMT_WPA_NONE; - break; - case WLAN_AKM_SUITE_PSK: - val = WPA2_AUTH_PSK; - curr_network->proto = WPA_PROTO_RSN; - curr_network->key_mgmt = KEY_MGMT_WPA2; - break; - case WLAN_AKM_SUITE_OWE: - val = WPA3_AUTH_OWE; - curr_network->proto = WPA_PROTO_RSN; - curr_network->key_mgmt = KEY_MGMT_OWE; - break; - default: - bphy_err(drvr, "invalid cipher group (%d)\n", - sme->crypto.cipher_group); - return -EINVAL; - } - } else if (val & WPA3_AUTH_SAE_PSK) { - switch (sme->crypto.akm_suites[0]) { - case WLAN_AKM_SUITE_SAE: - val = WPA3_AUTH_SAE_PSK; - curr_network->proto = WPA_PROTO_RSN; - curr_network->key_mgmt = KEY_MGMT_SAE; - break; - default: - bphy_err(drvr, "invalid cipher group (%d)\n", - sme->crypto.cipher_group); - return -EINVAL; - } - } - brcmf_dbg(TRACE, "Exit\n"); - return 0; -} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h index 7040d360cc97..7d4a2c635247 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h @@ -17,6 +17,7 @@ #define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ #define AUTO_CONNECT_MASK 0x0010 +#define AUTO_NET_SWITCH_MASK 0x0002 #define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF #define MAXNUM_SSID_PER_ADD 16 #define WSEC_MIN_PSK_LEN 8 @@ -24,6 +25,7 @@ #define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ #define PFN_VERSION 2 #define PFN_LIST_ORDER 0 +#define PFN_RSSI 1 #define SORT_CRITERIA_BIT 0 #define ENABLE 1 #define IMMEDIATE_SCAN_BIT 3 @@ -34,6 +36,7 @@ #define WPA_AUTH_DISABLED 0x0000 #define PFN_SET 1 #define PFN_UNSET 0 +#define PFN_CONFIG_AND_COUNT_SIZE 2 #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 #define WLAN_AUTH_FT 2 @@ -110,6 +113,12 @@ struct pfn_conn_info { int key_mgmt; }; +enum { + PFN_CONFIG_AUTOCONNECT, + PFN_CONFIG_AUTOSWITCH_LISTORDER, + PFN_CONFIG_AUTOSWITCH_RSSI, +}; + enum wpas_mode { WPAS_MODE_INFRA = 0, WPAS_MODE_IBSS = 1, @@ -182,6 +191,3 @@ u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi, int pfn_send_network_blob_fw(struct wiphy *wiphy, struct wireless_dev *wdev); - -int pfn_save_curr_network(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_connect_params *sme); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c index f025d98f5f3b..159441e29753 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c @@ -1038,20 +1038,20 @@ int ifx_cfg80211_vndr_cmds_config_pfn(struct wiphy *wiphy, { int buflen; struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct drv_config_pfn_params *pfn_data; brcmf_dbg(TRACE, "Enter pfn_enable %d Network_blob count %d\n", cfg->pfn_enable, *((u8 *)data)); - if (!cfg->pfn_enable) - memset(&cfg->curr_network, '\0', sizeof(struct network_blob)); - cfg->pfn_enable = 1; - cfg->pfn_data.count = *((u8 *)data); + pfn_data = (struct drv_config_pfn_params *)data; + cfg->pfn_data.pfn_config = pfn_data->pfn_config; + cfg->pfn_data.count = pfn_data->count; buflen = cfg->pfn_data.count * sizeof(struct network_blob); cfg->pfn_data.network_blob_data = (struct network_blob *)kmalloc(buflen, GFP_KERNEL); memset(cfg->pfn_data.network_blob_data, '\0', buflen); - memcpy(cfg->pfn_data.network_blob_data, (u8 *)data + sizeof(u8), buflen); + memcpy(cfg->pfn_data.network_blob_data, (u8 *)data + PFN_CONFIG_AND_COUNT_SIZE, buflen); pfn_send_network_blob_fw(wiphy, wdev); brcmf_dbg(TRACE, "Exit\n"); return 0; @@ -1104,21 +1104,13 @@ int ifx_cfg80211_vndr_cmds_get_pfn_status(struct wiphy *wiphy, curr_bssid.SNR = bi->SNR; network_blob_data = cfg->pfn_data.network_blob_data; - if (cfg->curr_network.ssid_len) { - if (!strncmp(cfg->curr_network.ssid, bi->SSID, bi->SSID_len)) { - curr_bssid.proto = cfg->curr_network.proto; - curr_bssid.key_mgmt = cfg->curr_network.key_mgmt; - } - - } else { - for (; i < cfg->pfn_data.count && network_blob_data; i++) { - if (!strncmp(network_blob_data->ssid, bi->SSID, bi->SSID_len)) { - curr_bssid.proto = network_blob_data->proto; - curr_bssid.key_mgmt = network_blob_data->key_mgmt; - break; - } - network_blob_data++; + for (; i < cfg->pfn_data.count && network_blob_data; i++) { + if (!strncmp(network_blob_data->ssid, bi->SSID, bi->SSID_len)) { + curr_bssid.proto = network_blob_data->proto; + curr_bssid.key_mgmt = network_blob_data->key_mgmt; + break; } + network_blob_data++; } } if (curr_bssid.SSID_len) -- 2.25.1