From 1b81c7565b077e4f14bb4abacc8ede29a52445ae Mon Sep 17 00:00:00 2001 From: Adesh Kumar Singh Date: Wed, 8 Mar 2023 22:37:22 -0600 Subject: [PATCH 267/296] non-upstream: PFN offload implementation PFN offload support added Signed-off-by: adesh kumar singh --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 22 +- .../broadcom/brcm80211/brcmfmac/cfg80211.h | 18 ++ .../broadcom/brcm80211/brcmfmac/core.c | 3 + .../broadcom/brcm80211/brcmfmac/pno.c | 248 ++++++++++++++++++ .../broadcom/brcm80211/brcmfmac/pno.h | 115 ++++++++ .../broadcom/brcm80211/brcmfmac/vendor.c | 14 + .../broadcom/brcm80211/brcmfmac/vendor_ifx.c | 94 +++++++ .../broadcom/brcm80211/brcmfmac/vendor_ifx.h | 6 +- .../broadcom/brcm80211/include/brcmu_wifi.h | 3 + 9 files changed, 520 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 4cde3aefe659..e6c222610232 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3037,6 +3037,13 @@ 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 */ @@ -3104,6 +3111,11 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &ifp->vif->sme_state); cfg80211_disconnected(ndev, reason_code, NULL, 0, true, GFP_KERNEL); + if (cfg->pfn_enable) { + memset(&cfg->curr_network, '\0', sizeof(struct network_blob)); + pfn_send_network_blob_fw(wiphy, &ifp->vif->wdev); + } + memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); scbval.val = cpu_to_le32(reason_code); err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC, @@ -7891,7 +7903,14 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); struct cfg80211_connect_resp_params conn_params; - brcmf_dbg(TRACE, "Enter\n"); + 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)); + + if (strlen(cfg->curr_network.ssid)) + pfn_send_network_blob_fw(cfg->wiphy, &ifp->vif->wdev); + } if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { @@ -8020,6 +8039,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, } else { brcmf_bss_connect_done(cfg, ndev, e, true); } + brcmf_bss_connect_done(cfg, ndev, e, true); } brcmf_net_setcarrier(ifp, true); } else if (brcmf_is_linkdown(ifp->vif, e)) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index a6e4e196510f..e9b2d981d508 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -352,6 +352,21 @@ struct brcmf_cfg80211_wowl { bool nd_enabled; }; +struct network_blob { + char ssid[32]; + int key_mgmt; + char psk[64]; + char sae_password[64]; + u8 proto; + u8 pairwise_cipher; + u8 frequency; +}; + +struct drv_config_pfn_params { + u8 count; + struct network_blob *network_blob_data; +}; + /** * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface * @@ -422,6 +437,9 @@ struct brcmf_cfg80211_info { u8 ac_priority[MAX_8021D_PRIO]; u8 pm_state; u8 num_softap; + u8 pfn_enable; + struct drv_config_pfn_params pfn_data; + struct network_blob curr_network; }; /** diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index e353103b5102..59bb7cd9373f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -1868,6 +1868,9 @@ void brcmf_detach(struct device *dev) } if (drvr->config) { + if (drvr->config->pfn_data.network_blob_data) + kfree(drvr->config->pfn_data.network_blob_data); + brcmf_p2p_detach(&drvr->config->p2p); brcmf_cfg80211_detach(drvr->config); drvr->config = NULL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c index 05f66ab13bed..a8bb440377d7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c @@ -12,6 +12,8 @@ #include "fwil_types.h" #include "cfg80211.h" #include "pno.h" +#include "vendor_ifx.h" +#include #define BRCMF_PNO_VERSION 2 #define BRCMF_PNO_REPEAT 4 @@ -593,3 +595,249 @@ u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi, mutex_unlock(&pi->req_lock); return bucket_map; } + +int pfn_send_network_blob_fw(struct wiphy *wiphy, + struct wireless_dev *wdev) +{ + int i, ret; + struct brcmf_cfg80211_vif *vif; + struct brcmf_if *ifp; + struct network_blob *network_blob_data; + brcm_pfn_param_t pfn_param; + struct brcm_pfn *pfn_list_buffer, *pssidnet; + int brcm_pfn_length = 0; + + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + ifp = vif->ifp; + + brcmf_dbg(TRACE, "Enter\n"); + brcmf_pno_clean(ifp); + + ret = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1); + if (ret) { + brcmf_err("sup_wpa set error:%d\n", ret); + return -1; + } + + if (!cfg->pfn_data.count && !strlen(cfg->curr_network.ssid)) + return 0; + + pfn_param.version = PFN_VERSION; + pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT | ENABLE << IMMEDIATE_SCAN_BIT); + pfn_param.scan_freq = 30; + pfn_param.slow_freq = 0; + pfn_param.rssi_margin = 10; + pfn_param.lost_network_timeout = 60; + pfn_param.bestn = DEFAULT_BESTN; + pfn_param.mscan = DEFAULT_MSCAN; + pfn_param.repeat = DEFAULT_REPEAT; + pfn_param.exp = DEFAULT_EXP; + pfn_param.flags |= AUTO_CONNECT_MASK; + + pfn_param.version = cpu_to_le32(pfn_param.version); + pfn_param.scan_freq = cpu_to_le32(pfn_param.scan_freq); + pfn_param.lost_network_timeout = cpu_to_le32(pfn_param.lost_network_timeout); + pfn_param.flags = cpu_to_le16(pfn_param.flags); + pfn_param.rssi_margin = cpu_to_le16(pfn_param.rssi_margin); + pfn_param.slow_freq = cpu_to_le32(pfn_param.slow_freq); + + ret = brcmf_fil_iovar_data_set(ifp, "pfn_set", (void *)&pfn_param, + sizeof(brcm_pfn_param_t)); + if (ret) { + brcmf_err("set pfn_set enable error:%d\n", ret); + return -1; + } + + brcm_pfn_length = (cfg->pfn_data.count) * sizeof(struct brcm_pfn); + + if (strlen(cfg->curr_network.ssid)) + 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 (strlen(cfg->curr_network.ssid)) { + 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, + strlen(cfg->curr_network.ssid)); + pssidnet->ssid.SSID_len = cpu_to_le32(strlen(cfg->curr_network.ssid)); + pssidnet->flags = cpu_to_le32(pssidnet->flags); + + if (cfg->curr_network.proto == KEY_MGMT_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; + pssidnet->wpa_auth = WPA_AUTH_DISABLED; + pssidnet->wsec = WPA_CIPHER_NONE; + pssidnet->infra = WPAS_MODE_IBSS; + pssidnet->flags = 0; + memcpy((char *)pssidnet->ssid.SSID, network_blob_data->ssid, + strlen(network_blob_data->ssid)); + pssidnet->ssid.SSID_len = cpu_to_le32(strlen(network_blob_data->ssid)); + pssidnet->flags = cpu_to_le32(pssidnet->flags); + + if (network_blob_data->proto == KEY_MGMT_WPA && + network_blob_data->key_mgmt == KEY_MGMT_WPA) { + pssidnet->wpa_auth = WPA_AUTH_PSK; + pssidnet->wsec = AES_ENABLED; + + } else if (network_blob_data->proto == WPA_PROTO_RSN && + network_blob_data->key_mgmt == KEY_MGMT_WPA2) { + pssidnet->wpa_auth = WPA2_AUTH_PSK; + pssidnet->wsec = AES_ENABLED; + + } else if (network_blob_data->proto == WPA_PROTO_RSN && + network_blob_data->key_mgmt == KEY_MGMT_SAE) { + pssidnet->wpa_auth = WPA3_AUTH_SAE_PSK; + pssidnet->wsec = AES_ENABLED; + pssidnet->auth = WLAN_AUTH_SAE; + + } else if (network_blob_data->proto == WPA_PROTO_RSN && + network_blob_data->key_mgmt == KEY_MGMT_OWE) { + pssidnet->wpa_auth = WPA3_AUTH_OWE; + pssidnet->wsec = AES_ENABLED; + } + + if (network_blob_data->pairwise_cipher == BIT(WPA_CIPHER_AES_CCM)) + pssidnet->wsec = AES_ENABLED; + + else if (network_blob_data->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", + network_blob_data->ssid, network_blob_data->key_mgmt, + network_blob_data->proto, pssidnet->wsec, + pssidnet->wpa_auth, pssidnet->auth); + pssidnet++; + network_blob_data++; + } + + ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", (void *)pfn_list_buffer, brcm_pfn_length); + if (ret) { + brcmf_err("set pfnadd enable error:%d\n", ret); + return -1; + } + ret = brcmf_fil_iovar_int_set(ifp, "pfn", PFN_SET); + if (ret) { + brcmf_err("set pfn error:%d\n", ret); + return -1; + } + kfree(pfn_list_buffer); + 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) + memcpy(curr_network->ssid, sme->ssid, 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 25d406019ac3..7040d360cc97 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.h @@ -10,6 +10,115 @@ #define BRCMF_PNO_SCHED_SCAN_MIN_PERIOD 10 #define BRCMF_PNO_SCHED_SCAN_MAX_PERIOD 508 +#define WPA_CIPHER_NONE 0 /* None */ +#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ +#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ +#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ +#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ + +#define AUTO_CONNECT_MASK 0x0010 +#define BRCMF_PNO_WPA_AUTH_ANY 0xFFFFFFFF +#define MAXNUM_SSID_PER_ADD 16 +#define WSEC_MIN_PSK_LEN 8 +#define WSEC_MAX_PSK_LEN 64 +#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ +#define PFN_VERSION 2 +#define PFN_LIST_ORDER 0 +#define SORT_CRITERIA_BIT 0 +#define ENABLE 1 +#define IMMEDIATE_SCAN_BIT 3 +#define DEFAULT_BESTN 2 +#define DEFAULT_MSCAN 0 +#define DEFAULT_REPEAT 10 +#define DEFAULT_EXP 2 +#define WPA_AUTH_DISABLED 0x0000 +#define PFN_SET 1 +#define PFN_UNSET 0 +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_FT 2 +#define WLAN_AUTH_SAE 3 + +#define KEY_MGMT_WPA 0x00000001 +#define KEY_MGMT_WPA2 0x00000002 +#define KEY_MGMT_WPA_PSK 0x00000004 +#define KEY_MGMT_WPA2_PSK 0x00000008 +#define KEY_MGMT_WPA_NONE 0x00000010 +#define KEY_MGMT_FT 0x00000020 +#define KEY_MGMT_FT_PSK 0x00000040 +#define KEY_MGMT_WAPI_PSK 0x00000080 +#define KEY_MGMT_SUITE_B 0x00000100 +#define KEY_MGMT_SUITE_B_192 0x00000200 +#define KEY_MGMT_OWE 0x00000400 +#define KEY_MGMT_DPP 0x00000800 +#define KEY_MGMT_FILS_SHA256 0x00001000 +#define KEY_MGMT_FILS_SHA384 0x00002000 +#define KEY_MGMT_FT_FILS_SHA256 0x00004000 +#define KEY_MGMT_FT_FILS_SHA384 0x00008000 +#define KEY_MGMT_SAE 0x00010000 +#define KEY_MGMT_802_1X_SHA256 0x00020000 +#define KEY_MGMT_PSK_SHA256 0x00040000 +#define KEY_MGMT_TPK_HANDSHAKE 0x00080000 +#define KEY_MGMT_FT_SAE 0x00100000 +#define KEY_MGMT_FT_802_1X_SHA384 0x00200000 +#define KEY_MGMT_CCKM 0x00400000 +#define KEY_MGMT_OSEN 0x00800000 + +typedef struct brcm_pfn_param { + s32 version; + s32 scan_freq; + s32 lost_network_timeout; + s16 flags; + s16 rssi_margin; + u8 bestn; + u8 mscan; + u8 repeat; + u8 exp; + s32 slow_freq; +} brcm_pfn_param_t; + +typedef struct wsec_pmk { + u16 key_len; + u16 flags; + u8 key[WSEC_MAX_PSK_LEN]; +} wsec_pmk_t; + +typedef struct brcm_ssid { + u32 SSID_len; + u8 SSID[DOT11_MAX_SSID_LEN]; +} brcm_ssid_t; + +struct brcm_pfn { + brcm_ssid_t ssid; /**< ssid name and its length */ + s32 flags; /**< bit2: hidden */ + s32 infra; /**< BSS Vs IBSS */ + s32 auth; /**< Open Vs Closed */ + s32 wpa_auth; /**< WPA type */ + s32 wsec; /**< wsec value */ + wsec_pmk_t psk; /**< Password */ +}; + +struct pfn_conn_info { + u8 SSID_len; + u8 SSID[32]; + u8 BSSID[ETH_ALEN]; + s16 RSSI; + s8 phy_noise; + u16 channel; + s16 SNR; + u8 proto; + int key_mgmt; +}; + +enum wpas_mode { + WPAS_MODE_INFRA = 0, + WPAS_MODE_IBSS = 1, + WPAS_MODE_AP = 2, + WPAS_MODE_P2P_GO = 3, + WPAS_MODE_P2P_GROUP_FORMATION = 4, + WPAS_MODE_MESH = 5, +}; + /* forward declaration */ struct brcmf_pno_info; @@ -70,3 +179,9 @@ u32 brcmf_pno_get_bucket_map(struct brcmf_pno_info *pi, struct brcmf_pno_net_info_le *netinfo); #endif /* _BRCMF_PNO_H */ + +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.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index 03085634e1d1..65adad8bd24a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -357,6 +357,20 @@ const struct wiphy_vendor_command brcmf_vendor_cmds[] = { VENDOR_CMD_RAW_DATA, ifx_cfg80211_vndr_cmds_str) }, + { + IFX_SUBCMD(PFN_CONFIG, + (WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV), + VENDOR_CMD_RAW_DATA, + ifx_cfg80211_vndr_cmds_config_pfn) + }, + { + IFX_SUBCMD(PFN_STATUS, + (WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV), + VENDOR_CMD_RAW_DATA, + ifx_cfg80211_vndr_cmds_get_pfn_status) + }, }; const struct nl80211_vendor_cmd_info brcmf_vendor_events[] = { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c index 82cf1eafbeea..afb6cf71977f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.c @@ -38,6 +38,7 @@ #include "vendor_ifx.h" #include "xtlv.h" #include "twt.h" +#include "pno.h" #include "bus.h" #include #include @@ -1030,3 +1031,96 @@ int ifx_cfg80211_vndr_cmds_str(struct wiphy *wiphy, struct wireless_dev *wdev, return ret; } + +int ifx_cfg80211_vndr_cmds_config_pfn(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int len) +{ + int buflen; + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + + 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); + + if (!cfg->pfn_data.count) + return 0; + + 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); + pfn_send_network_blob_fw(wiphy, wdev); + brcmf_dbg(TRACE, "Exit\n"); + return 0; +} + +int ifx_cfg80211_vndr_cmds_get_pfn_status(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int len) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + u8 *buf = NULL; + struct brcmf_bss_info_le *bi = NULL; + int err = 0, i = 0; + struct brcmf_cfg80211_vif *vif; + struct brcmf_if *ifp; + struct network_blob *curr_network = NULL, *network_blob_data = NULL; + struct brcmu_chan ch; + struct pfn_conn_info curr_bssid; + + brcmf_dbg(TRACE, "Enter\n"); + vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + ifp = vif->ifp; + if (cfg->pfn_enable != 1) + return 0; + buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (!buf) { + err = -ENOMEM; + return 0; + } + + *(u32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, + buf, WL_BSS_INFO_MAX); + if (err) { + brcmf_err("pfn_status buf error:%d\n", err); + return 0; + } + bi = (struct brcmf_bss_info_le *)(buf + 4); + memset(&curr_bssid, '\0', sizeof(struct pfn_conn_info)); + + if (bi->SSID_len > 0) { + memcpy(curr_bssid.SSID, bi->SSID, bi->SSID_len); + memcpy(curr_bssid.BSSID, bi->BSSID, ETH_ALEN); + curr_bssid.SSID_len = bi->SSID_len; + curr_bssid.RSSI = bi->RSSI; + curr_bssid.phy_noise = bi->phy_noise; + ch.chspec = le16_to_cpu(bi->chanspec); + cfg->d11inf.decchspec(&ch); + curr_bssid.channel = ch.control_ch_num; + curr_bssid.SNR = bi->SNR; + + network_blob_data = cfg->pfn_data.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_network = network_blob_data; + 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) + ifx_cfg80211_vndr_send_cmd_reply(wiphy, (void *)&curr_bssid, + sizeof(struct pfn_conn_info)); + kfree(buf); + brcmf_dbg(TRACE, "Exit\n"); + return 0; +} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h index 22a3548237a5..092735823d31 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor_ifx.h @@ -794,6 +794,8 @@ int ifx_vndr_cmdstr_tko(struct wiphy *wiphy, struct wireless_dev *wdev, long *cmd_val); int ifx_cfg80211_vndr_cmds_str(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len); - +int ifx_cfg80211_vndr_cmds_config_pfn(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int len); +int ifx_cfg80211_vndr_cmds_get_pfn_status(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int len); #endif /* IFX_VENDOR_H */ - diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 1023a117696e..f6b019556c5b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h @@ -260,4 +260,7 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define HT_CAP_RX_STBC_NO 0x0 #define HT_CAP_RX_STBC_ONE_STREAM 0x1 +#define WPA_PROTO_WPA BIT(0) +#define WPA_PROTO_RSN BIT(1) + #endif /* _BRCMU_WIFI_H_ */ -- 2.25.1