8442 lines · c
1// SPDX-License-Identifier: ISC2/*3 * Copyright (c) 2010 Broadcom Corporation4 */5 6/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */7 8#include <linux/kernel.h>9#include <linux/etherdevice.h>10#include <linux/module.h>11#include <linux/vmalloc.h>12#include <net/cfg80211.h>13#include <net/netlink.h>14#include <uapi/linux/if_arp.h>15 16#include <brcmu_utils.h>17#include <defs.h>18#include <brcmu_wifi.h>19#include <brcm_hw_ids.h>20#include "core.h"21#include "debug.h"22#include "tracepoint.h"23#include "fwil_types.h"24#include "p2p.h"25#include "btcoex.h"26#include "pno.h"27#include "fwsignal.h"28#include "cfg80211.h"29#include "feature.h"30#include "fwil.h"31#include "proto.h"32#include "vendor.h"33#include "bus.h"34#include "common.h"35#include "fwvid.h"36 37#define BRCMF_SCAN_IE_LEN_MAX 204838 39#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */40#define WPA_OUI_TYPE 141#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */42#define WME_OUI_TYPE 243#define WPS_OUI_TYPE 444 45#define VS_IE_FIXED_HDR_LEN 646#define WPA_IE_VERSION_LEN 247#define WPA_IE_MIN_OUI_LEN 448#define WPA_IE_SUITE_COUNT_LEN 249 50#define WPA_CIPHER_NONE 0 /* None */51#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */52#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */53#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */54#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */55 56#define RSN_AKM_NONE 0 /* None (IBSS) */57#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */58#define RSN_AKM_PSK 2 /* Pre-shared Key */59#define RSN_AKM_SHA256_1X 5 /* SHA256, 802.1X */60#define RSN_AKM_SHA256_PSK 6 /* SHA256, Pre-shared Key */61#define RSN_AKM_SAE 8 /* SAE */62#define RSN_CAP_LEN 2 /* Length of RSN capabilities */63#define RSN_CAP_PTK_REPLAY_CNTR_MASK (BIT(2) | BIT(3))64#define RSN_CAP_MFPR_MASK BIT(6)65#define RSN_CAP_MFPC_MASK BIT(7)66#define RSN_PMKID_COUNT_LEN 267 68#define VNDR_IE_CMD_LEN 4 /* length of the set command69 * string :"add", "del" (+ NUL)70 */71#define VNDR_IE_COUNT_OFFSET 472#define VNDR_IE_PKTFLAG_OFFSET 873#define VNDR_IE_VSIE_OFFSET 1274#define VNDR_IE_HDR_SIZE 1275#define VNDR_IE_PARSE_LIMIT 576 77#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */78#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */79 80#define BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 32081#define BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 40082#define BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS 2083 84#define BRCMF_SCAN_CHANNEL_TIME 4085#define BRCMF_SCAN_UNASSOC_TIME 4086#define BRCMF_SCAN_PASSIVE_TIME 12087 88#define BRCMF_ND_INFO_TIMEOUT msecs_to_jiffies(2000)89 90#define BRCMF_PS_MAX_TIMEOUT_MS 200091 92/* Dump obss definitions */93#define ACS_MSRMNT_DELAY 8094#define CHAN_NOISE_DUMMY (-80)95#define OBSS_TOKEN_IDX 1596#define IBSS_TOKEN_IDX 1597#define TX_TOKEN_IDX 1498#define CTG_TOKEN_IDX 1399#define PKT_TOKEN_IDX 15100#define IDLE_TOKEN_IDX 12101 102#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \103 (sizeof(struct brcmf_assoc_params_le) - sizeof(u16))104 105#define BRCMF_MAX_CHANSPEC_LIST \106 (BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1)107 108struct brcmf_dump_survey {109 u32 obss;110 u32 ibss;111 u32 no_ctg;112 u32 no_pckt;113 u32 tx;114 u32 idle;115};116 117struct cca_stats_n_flags {118 u32 msrmnt_time; /* Time for Measurement (msec) */119 u32 msrmnt_done; /* flag set when measurement complete */120 char buf[1];121};122 123struct cca_msrmnt_query {124 u32 msrmnt_query;125 u32 time_req;126};127 128static bool check_vif_up(struct brcmf_cfg80211_vif *vif)129{130 if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {131 brcmf_dbg(INFO, "device is not ready : status (%lu)\n",132 vif->sme_state);133 return false;134 }135 return true;136}137 138#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)139#define RATETAB_ENT(_rateid, _flags) \140 { \141 .bitrate = RATE_TO_BASE100KBPS(_rateid), \142 .hw_value = (_rateid), \143 .flags = (_flags), \144 }145 146static struct ieee80211_rate __wl_rates[] = {147 RATETAB_ENT(BRCM_RATE_1M, 0),148 RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),149 RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),150 RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),151 RATETAB_ENT(BRCM_RATE_6M, 0),152 RATETAB_ENT(BRCM_RATE_9M, 0),153 RATETAB_ENT(BRCM_RATE_12M, 0),154 RATETAB_ENT(BRCM_RATE_18M, 0),155 RATETAB_ENT(BRCM_RATE_24M, 0),156 RATETAB_ENT(BRCM_RATE_36M, 0),157 RATETAB_ENT(BRCM_RATE_48M, 0),158 RATETAB_ENT(BRCM_RATE_54M, 0),159};160 161#define wl_g_rates (__wl_rates + 0)162#define wl_g_rates_size ARRAY_SIZE(__wl_rates)163#define wl_a_rates (__wl_rates + 4)164#define wl_a_rates_size (wl_g_rates_size - 4)165 166#define CHAN2G(_channel, _freq) { \167 .band = NL80211_BAND_2GHZ, \168 .center_freq = (_freq), \169 .hw_value = (_channel), \170 .max_antenna_gain = 0, \171 .max_power = 30, \172}173 174#define CHAN5G(_channel) { \175 .band = NL80211_BAND_5GHZ, \176 .center_freq = 5000 + (5 * (_channel)), \177 .hw_value = (_channel), \178 .max_antenna_gain = 0, \179 .max_power = 30, \180}181 182static struct ieee80211_channel __wl_2ghz_channels[] = {183 CHAN2G(1, 2412), CHAN2G(2, 2417), CHAN2G(3, 2422), CHAN2G(4, 2427),184 CHAN2G(5, 2432), CHAN2G(6, 2437), CHAN2G(7, 2442), CHAN2G(8, 2447),185 CHAN2G(9, 2452), CHAN2G(10, 2457), CHAN2G(11, 2462), CHAN2G(12, 2467),186 CHAN2G(13, 2472), CHAN2G(14, 2484)187};188 189static struct ieee80211_channel __wl_5ghz_channels[] = {190 CHAN5G(34), CHAN5G(36), CHAN5G(38), CHAN5G(40), CHAN5G(42),191 CHAN5G(44), CHAN5G(46), CHAN5G(48), CHAN5G(52), CHAN5G(56),192 CHAN5G(60), CHAN5G(64), CHAN5G(100), CHAN5G(104), CHAN5G(108),193 CHAN5G(112), CHAN5G(116), CHAN5G(120), CHAN5G(124), CHAN5G(128),194 CHAN5G(132), CHAN5G(136), CHAN5G(140), CHAN5G(144), CHAN5G(149),195 CHAN5G(153), CHAN5G(157), CHAN5G(161), CHAN5G(165)196};197 198/* Band templates duplicated per wiphy. The channel info199 * above is added to the band during setup.200 */201static const struct ieee80211_supported_band __wl_band_2ghz = {202 .band = NL80211_BAND_2GHZ,203 .bitrates = wl_g_rates,204 .n_bitrates = wl_g_rates_size,205};206 207static const struct ieee80211_supported_band __wl_band_5ghz = {208 .band = NL80211_BAND_5GHZ,209 .bitrates = wl_a_rates,210 .n_bitrates = wl_a_rates_size,211};212 213/* This is to override regulatory domains defined in cfg80211 module (reg.c)214 * By default world regulatory domain defined in reg.c puts the flags215 * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165).216 * With respect to these flags, wpa_supplicant doesn't * start p2p217 * operations on 5GHz channels. All the changes in world regulatory218 * domain are to be done here.219 */220static const struct ieee80211_regdomain brcmf_regdom = {221 .n_reg_rules = 4,222 .alpha2 = "99",223 .reg_rules = {224 /* IEEE 802.11b/g, channels 1..11 */225 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),226 /* If any */227 /* IEEE 802.11 channel 14 - Only JP enables228 * this and for 802.11b only229 */230 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),231 /* IEEE 802.11a, channel 36..64 */232 REG_RULE(5150-10, 5350+10, 160, 6, 20, 0),233 /* IEEE 802.11a, channel 100..165 */234 REG_RULE(5470-10, 5850+10, 160, 6, 20, 0), }235};236 237/* Note: brcmf_cipher_suites is an array of int defining which cipher suites238 * are supported. A pointer to this array and the number of entries is passed239 * on to upper layers. AES_CMAC defines whether or not the driver supports MFP.240 * So the cipher suite AES_CMAC has to be the last one in the array, and when241 * device does not support MFP then the number of suites will be decreased by 1242 */243static const u32 brcmf_cipher_suites[] = {244 WLAN_CIPHER_SUITE_WEP40,245 WLAN_CIPHER_SUITE_WEP104,246 WLAN_CIPHER_SUITE_TKIP,247 WLAN_CIPHER_SUITE_CCMP,248 /* Keep as last entry: */249 WLAN_CIPHER_SUITE_AES_CMAC250};251 252/* Vendor specific ie. id = 221, oui and type defines exact ie */253struct brcmf_vs_tlv {254 u8 id;255 u8 len;256 u8 oui[3];257 u8 oui_type;258};259 260struct parsed_vndr_ie_info {261 u8 *ie_ptr;262 u32 ie_len; /* total length including id & length field */263 struct brcmf_vs_tlv vndrie;264};265 266struct parsed_vndr_ies {267 u32 count;268 struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];269};270 271#define WL_INTERFACE_CREATE_VER_1 1272#define WL_INTERFACE_CREATE_VER_2 2273#define WL_INTERFACE_CREATE_VER_3 3274#define WL_INTERFACE_CREATE_VER_MAX WL_INTERFACE_CREATE_VER_3275 276#define WL_INTERFACE_MAC_DONT_USE 0x0277#define WL_INTERFACE_MAC_USE 0x2278 279#define WL_INTERFACE_CREATE_STA 0x0280#define WL_INTERFACE_CREATE_AP 0x1281 282struct wl_interface_create_v1 {283 u16 ver; /* structure version */284 u32 flags; /* flags for operation */285 u8 mac_addr[ETH_ALEN]; /* MAC address */286 u32 wlc_index; /* optional for wlc index */287};288 289struct wl_interface_create_v2 {290 u16 ver; /* structure version */291 u8 pad1[2];292 u32 flags; /* flags for operation */293 u8 mac_addr[ETH_ALEN]; /* MAC address */294 u8 iftype; /* type of interface created */295 u8 pad2;296 u32 wlc_index; /* optional for wlc index */297};298 299struct wl_interface_create_v3 {300 u16 ver; /* structure version */301 u16 len; /* length of structure + data */302 u16 fixed_len; /* length of structure */303 u8 iftype; /* type of interface created */304 u8 wlc_index; /* optional for wlc index */305 u32 flags; /* flags for operation */306 u8 mac_addr[ETH_ALEN]; /* MAC address */307 u8 bssid[ETH_ALEN]; /* optional for BSSID */308 u8 if_index; /* interface index request */309 u8 pad[3];310 u8 data[]; /* Optional for specific data */311};312 313static u8 nl80211_band_to_fwil(enum nl80211_band band)314{315 switch (band) {316 case NL80211_BAND_2GHZ:317 return WLC_BAND_2G;318 case NL80211_BAND_5GHZ:319 return WLC_BAND_5G;320 default:321 WARN_ON(1);322 break;323 }324 return 0;325}326 327static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,328 struct cfg80211_chan_def *ch)329{330 struct brcmu_chan ch_inf;331 s32 primary_offset;332 333 brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",334 ch->chan->center_freq, ch->center_freq1, ch->width);335 ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);336 primary_offset = ch->chan->center_freq - ch->center_freq1;337 switch (ch->width) {338 case NL80211_CHAN_WIDTH_20:339 case NL80211_CHAN_WIDTH_20_NOHT:340 ch_inf.bw = BRCMU_CHAN_BW_20;341 WARN_ON(primary_offset != 0);342 break;343 case NL80211_CHAN_WIDTH_40:344 ch_inf.bw = BRCMU_CHAN_BW_40;345 if (primary_offset > 0)346 ch_inf.sb = BRCMU_CHAN_SB_U;347 else348 ch_inf.sb = BRCMU_CHAN_SB_L;349 break;350 case NL80211_CHAN_WIDTH_80:351 ch_inf.bw = BRCMU_CHAN_BW_80;352 if (primary_offset == -30)353 ch_inf.sb = BRCMU_CHAN_SB_LL;354 else if (primary_offset == -10)355 ch_inf.sb = BRCMU_CHAN_SB_LU;356 else if (primary_offset == 10)357 ch_inf.sb = BRCMU_CHAN_SB_UL;358 else359 ch_inf.sb = BRCMU_CHAN_SB_UU;360 break;361 case NL80211_CHAN_WIDTH_160:362 ch_inf.bw = BRCMU_CHAN_BW_160;363 if (primary_offset == -70)364 ch_inf.sb = BRCMU_CHAN_SB_LLL;365 else if (primary_offset == -50)366 ch_inf.sb = BRCMU_CHAN_SB_LLU;367 else if (primary_offset == -30)368 ch_inf.sb = BRCMU_CHAN_SB_LUL;369 else if (primary_offset == -10)370 ch_inf.sb = BRCMU_CHAN_SB_LUU;371 else if (primary_offset == 10)372 ch_inf.sb = BRCMU_CHAN_SB_ULL;373 else if (primary_offset == 30)374 ch_inf.sb = BRCMU_CHAN_SB_ULU;375 else if (primary_offset == 50)376 ch_inf.sb = BRCMU_CHAN_SB_UUL;377 else378 ch_inf.sb = BRCMU_CHAN_SB_UUU;379 break;380 case NL80211_CHAN_WIDTH_80P80:381 case NL80211_CHAN_WIDTH_5:382 case NL80211_CHAN_WIDTH_10:383 default:384 WARN_ON_ONCE(1);385 }386 switch (ch->chan->band) {387 case NL80211_BAND_2GHZ:388 ch_inf.band = BRCMU_CHAN_BAND_2G;389 break;390 case NL80211_BAND_5GHZ:391 ch_inf.band = BRCMU_CHAN_BAND_5G;392 break;393 case NL80211_BAND_60GHZ:394 default:395 WARN_ON_ONCE(1);396 }397 d11inf->encchspec(&ch_inf);398 399 brcmf_dbg(TRACE, "chanspec: 0x%x\n", ch_inf.chspec);400 return ch_inf.chspec;401}402 403u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,404 struct ieee80211_channel *ch)405{406 struct brcmu_chan ch_inf;407 408 ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq);409 ch_inf.bw = BRCMU_CHAN_BW_20;410 d11inf->encchspec(&ch_inf);411 412 return ch_inf.chspec;413}414 415/* Traverse a string of 1-byte tag/1-byte length/variable-length value416 * triples, returning a pointer to the substring whose first element417 * matches tag418 */419static const struct brcmf_tlv *420brcmf_parse_tlvs(const void *buf, int buflen, uint key)421{422 const struct brcmf_tlv *elt = buf;423 int totlen = buflen;424 425 /* find tagged parameter */426 while (totlen >= TLV_HDR_LEN) {427 int len = elt->len;428 429 /* validate remaining totlen */430 if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN)))431 return elt;432 433 elt = (struct brcmf_tlv *)((u8 *)elt + (len + TLV_HDR_LEN));434 totlen -= (len + TLV_HDR_LEN);435 }436 437 return NULL;438}439 440/* Is any of the tlvs the expected entry? If441 * not update the tlvs buffer pointer/length.442 */443static bool444brcmf_tlv_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len,445 const u8 *oui, u32 oui_len, u8 type)446{447 /* If the contents match the OUI and the type */448 if (ie[TLV_LEN_OFF] >= oui_len + 1 &&449 !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&450 type == ie[TLV_BODY_OFF + oui_len]) {451 return true;452 }453 454 if (tlvs == NULL)455 return false;456 /* point to the next ie */457 ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;458 /* calculate the length of the rest of the buffer */459 *tlvs_len -= (int)(ie - *tlvs);460 /* update the pointer to the start of the buffer */461 *tlvs = ie;462 463 return false;464}465 466static struct brcmf_vs_tlv *467brcmf_find_wpaie(const u8 *parse, u32 len)468{469 const struct brcmf_tlv *ie;470 471 while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {472 if (brcmf_tlv_has_ie((const u8 *)ie, &parse, &len,473 WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE))474 return (struct brcmf_vs_tlv *)ie;475 }476 return NULL;477}478 479static struct brcmf_vs_tlv *480brcmf_find_wpsie(const u8 *parse, u32 len)481{482 const struct brcmf_tlv *ie;483 484 while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) {485 if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len,486 WPA_OUI, TLV_OUI_LEN, WPS_OUI_TYPE))487 return (struct brcmf_vs_tlv *)ie;488 }489 return NULL;490}491 492static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,493 struct brcmf_cfg80211_vif *vif,494 enum nl80211_iftype new_type)495{496 struct brcmf_cfg80211_vif *pos;497 bool check_combos = false;498 int ret = 0;499 struct iface_combination_params params = {500 .num_different_channels = 1,501 };502 503 list_for_each_entry(pos, &cfg->vif_list, list)504 if (pos == vif) {505 params.iftype_num[new_type]++;506 } else {507 /* concurrent interfaces so need check combinations */508 check_combos = true;509 params.iftype_num[pos->wdev.iftype]++;510 }511 512 if (check_combos)513 ret = cfg80211_check_combinations(cfg->wiphy, ¶ms);514 515 return ret;516}517 518static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,519 enum nl80211_iftype new_type)520{521 struct brcmf_cfg80211_vif *pos;522 struct iface_combination_params params = {523 .num_different_channels = 1,524 };525 526 list_for_each_entry(pos, &cfg->vif_list, list)527 params.iftype_num[pos->wdev.iftype]++;528 529 params.iftype_num[new_type]++;530 return cfg80211_check_combinations(cfg->wiphy, ¶ms);531}532 533static void convert_key_from_CPU(struct brcmf_wsec_key *key,534 struct brcmf_wsec_key_le *key_le)535{536 key_le->index = cpu_to_le32(key->index);537 key_le->len = cpu_to_le32(key->len);538 key_le->algo = cpu_to_le32(key->algo);539 key_le->flags = cpu_to_le32(key->flags);540 key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);541 key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);542 key_le->iv_initialized = cpu_to_le32(key->iv_initialized);543 memcpy(key_le->data, key->data, sizeof(key->data));544 memcpy(key_le->ea, key->ea, sizeof(key->ea));545}546 547static int548send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)549{550 struct brcmf_pub *drvr = ifp->drvr;551 int err;552 struct brcmf_wsec_key_le key_le;553 554 convert_key_from_CPU(key, &key_le);555 556 brcmf_netdev_wait_pend8021x(ifp);557 558 err = brcmf_fil_bsscfg_data_set(ifp, "wsec_key", &key_le,559 sizeof(key_le));560 561 if (err)562 bphy_err(drvr, "wsec_key error (%d)\n", err);563 return err;564}565 566static void567brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)568{569 struct brcmf_cfg80211_vif *vif;570 struct brcmf_if *ifp;571 572 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);573 ifp = vif->ifp;574 575 if ((wdev->iftype == NL80211_IFTYPE_ADHOC) ||576 (wdev->iftype == NL80211_IFTYPE_AP) ||577 (wdev->iftype == NL80211_IFTYPE_P2P_GO))578 brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,579 ADDR_DIRECT);580 else581 brcmf_proto_configure_addr_mode(ifp->drvr, ifp->ifidx,582 ADDR_INDIRECT);583}584 585static int brcmf_get_first_free_bsscfgidx(struct brcmf_pub *drvr)586{587 int bsscfgidx;588 589 for (bsscfgidx = 0; bsscfgidx < BRCMF_MAX_IFS; bsscfgidx++) {590 /* bsscfgidx 1 is reserved for legacy P2P */591 if (bsscfgidx == 1)592 continue;593 if (!drvr->iflist[bsscfgidx])594 return bsscfgidx;595 }596 597 return -ENOMEM;598}599 600static void brcmf_set_vif_sta_macaddr(struct brcmf_if *ifp, u8 *mac_addr)601{602 u8 mac_idx = ifp->drvr->sta_mac_idx;603 604 /* set difference MAC address with locally administered bit */605 memcpy(mac_addr, ifp->mac_addr, ETH_ALEN);606 mac_addr[0] |= 0x02;607 mac_addr[3] ^= mac_idx ? 0xC0 : 0xA0;608 mac_idx++;609 mac_idx = mac_idx % 2;610 ifp->drvr->sta_mac_idx = mac_idx;611}612 613static int brcmf_cfg80211_request_sta_if(struct brcmf_if *ifp, u8 *macaddr)614{615 struct wl_interface_create_v1 iface_v1;616 struct wl_interface_create_v2 iface_v2;617 struct wl_interface_create_v3 iface_v3;618 u32 iface_create_ver;619 int err;620 621 /* interface_create version 1 */622 memset(&iface_v1, 0, sizeof(iface_v1));623 iface_v1.ver = WL_INTERFACE_CREATE_VER_1;624 iface_v1.flags = WL_INTERFACE_CREATE_STA |625 WL_INTERFACE_MAC_USE;626 if (!is_zero_ether_addr(macaddr))627 memcpy(iface_v1.mac_addr, macaddr, ETH_ALEN);628 else629 brcmf_set_vif_sta_macaddr(ifp, iface_v1.mac_addr);630 631 err = brcmf_fil_iovar_data_get(ifp, "interface_create",632 &iface_v1,633 sizeof(iface_v1));634 if (err) {635 brcmf_info("failed to create interface(v1), err=%d\n",636 err);637 } else {638 brcmf_dbg(INFO, "interface created(v1)\n");639 return 0;640 }641 642 /* interface_create version 2 */643 memset(&iface_v2, 0, sizeof(iface_v2));644 iface_v2.ver = WL_INTERFACE_CREATE_VER_2;645 iface_v2.flags = WL_INTERFACE_MAC_USE;646 iface_v2.iftype = WL_INTERFACE_CREATE_STA;647 if (!is_zero_ether_addr(macaddr))648 memcpy(iface_v2.mac_addr, macaddr, ETH_ALEN);649 else650 brcmf_set_vif_sta_macaddr(ifp, iface_v2.mac_addr);651 652 err = brcmf_fil_iovar_data_get(ifp, "interface_create",653 &iface_v2,654 sizeof(iface_v2));655 if (err) {656 brcmf_info("failed to create interface(v2), err=%d\n",657 err);658 } else {659 brcmf_dbg(INFO, "interface created(v2)\n");660 return 0;661 }662 663 /* interface_create version 3+ */664 /* get supported version from firmware side */665 iface_create_ver = 0;666 err = brcmf_fil_bsscfg_int_query(ifp, "interface_create",667 &iface_create_ver);668 if (err) {669 brcmf_err("fail to get supported version, err=%d\n", err);670 return -EOPNOTSUPP;671 }672 673 switch (iface_create_ver) {674 case WL_INTERFACE_CREATE_VER_3:675 memset(&iface_v3, 0, sizeof(iface_v3));676 iface_v3.ver = WL_INTERFACE_CREATE_VER_3;677 iface_v3.flags = WL_INTERFACE_MAC_USE;678 iface_v3.iftype = WL_INTERFACE_CREATE_STA;679 if (!is_zero_ether_addr(macaddr))680 memcpy(iface_v3.mac_addr, macaddr, ETH_ALEN);681 else682 brcmf_set_vif_sta_macaddr(ifp, iface_v3.mac_addr);683 684 err = brcmf_fil_iovar_data_get(ifp, "interface_create",685 &iface_v3,686 sizeof(iface_v3));687 688 if (!err)689 brcmf_dbg(INFO, "interface created(v3)\n");690 break;691 default:692 brcmf_err("not support interface create(v%d)\n",693 iface_create_ver);694 err = -EOPNOTSUPP;695 break;696 }697 698 if (err) {699 brcmf_info("station interface creation failed (%d)\n",700 err);701 return -EIO;702 }703 704 return 0;705}706 707static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)708{709 struct wl_interface_create_v1 iface_v1;710 struct wl_interface_create_v2 iface_v2;711 struct wl_interface_create_v3 iface_v3;712 u32 iface_create_ver;713 struct brcmf_pub *drvr = ifp->drvr;714 struct brcmf_mbss_ssid_le mbss_ssid_le;715 int bsscfgidx;716 int err;717 718 /* interface_create version 1 */719 memset(&iface_v1, 0, sizeof(iface_v1));720 iface_v1.ver = WL_INTERFACE_CREATE_VER_1;721 iface_v1.flags = WL_INTERFACE_CREATE_AP |722 WL_INTERFACE_MAC_USE;723 724 brcmf_set_vif_sta_macaddr(ifp, iface_v1.mac_addr);725 726 err = brcmf_fil_iovar_data_get(ifp, "interface_create",727 &iface_v1,728 sizeof(iface_v1));729 if (err) {730 brcmf_info("failed to create interface(v1), err=%d\n",731 err);732 } else {733 brcmf_dbg(INFO, "interface created(v1)\n");734 return 0;735 }736 737 /* interface_create version 2 */738 memset(&iface_v2, 0, sizeof(iface_v2));739 iface_v2.ver = WL_INTERFACE_CREATE_VER_2;740 iface_v2.flags = WL_INTERFACE_MAC_USE;741 iface_v2.iftype = WL_INTERFACE_CREATE_AP;742 743 brcmf_set_vif_sta_macaddr(ifp, iface_v2.mac_addr);744 745 err = brcmf_fil_iovar_data_get(ifp, "interface_create",746 &iface_v2,747 sizeof(iface_v2));748 if (err) {749 brcmf_info("failed to create interface(v2), err=%d\n",750 err);751 } else {752 brcmf_dbg(INFO, "interface created(v2)\n");753 return 0;754 }755 756 /* interface_create version 3+ */757 /* get supported version from firmware side */758 iface_create_ver = 0;759 err = brcmf_fil_bsscfg_int_query(ifp, "interface_create",760 &iface_create_ver);761 if (err) {762 brcmf_err("fail to get supported version, err=%d\n", err);763 return -EOPNOTSUPP;764 }765 766 switch (iface_create_ver) {767 case WL_INTERFACE_CREATE_VER_3:768 memset(&iface_v3, 0, sizeof(iface_v3));769 iface_v3.ver = WL_INTERFACE_CREATE_VER_3;770 iface_v3.flags = WL_INTERFACE_MAC_USE;771 iface_v3.iftype = WL_INTERFACE_CREATE_AP;772 brcmf_set_vif_sta_macaddr(ifp, iface_v3.mac_addr);773 774 err = brcmf_fil_iovar_data_get(ifp, "interface_create",775 &iface_v3,776 sizeof(iface_v3));777 778 if (!err)779 brcmf_dbg(INFO, "interface created(v3)\n");780 break;781 default:782 brcmf_err("not support interface create(v%d)\n",783 iface_create_ver);784 err = -EOPNOTSUPP;785 break;786 }787 788 if (err) {789 brcmf_info("Does not support interface_create (%d)\n",790 err);791 memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));792 bsscfgidx = brcmf_get_first_free_bsscfgidx(ifp->drvr);793 if (bsscfgidx < 0)794 return bsscfgidx;795 796 mbss_ssid_le.bsscfgidx = cpu_to_le32(bsscfgidx);797 mbss_ssid_le.SSID_len = cpu_to_le32(5);798 sprintf(mbss_ssid_le.SSID, "ssid%d", bsscfgidx);799 800 err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,801 sizeof(mbss_ssid_le));802 803 if (err < 0)804 bphy_err(drvr, "setting ssid failed %d\n", err);805 }806 807 return err;808}809 810/**811 * brcmf_apsta_add_vif() - create a new AP or STA virtual interface812 *813 * @wiphy: wiphy device of new interface.814 * @name: name of the new interface.815 * @params: contains mac address for AP or STA device.816 * @type: interface type.817 */818static819struct wireless_dev *brcmf_apsta_add_vif(struct wiphy *wiphy, const char *name,820 struct vif_params *params,821 enum nl80211_iftype type)822{823 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);824 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));825 struct brcmf_pub *drvr = cfg->pub;826 struct brcmf_cfg80211_vif *vif;827 int err;828 829 if (type != NL80211_IFTYPE_STATION && type != NL80211_IFTYPE_AP)830 return ERR_PTR(-EINVAL);831 832 if (brcmf_cfg80211_vif_event_armed(cfg))833 return ERR_PTR(-EBUSY);834 835 brcmf_dbg(INFO, "Adding vif \"%s\"\n", name);836 837 vif = brcmf_alloc_vif(cfg, type);838 if (IS_ERR(vif))839 return (struct wireless_dev *)vif;840 841 brcmf_cfg80211_arm_vif_event(cfg, vif);842 843 if (type == NL80211_IFTYPE_STATION)844 err = brcmf_cfg80211_request_sta_if(ifp, params->macaddr);845 else846 err = brcmf_cfg80211_request_ap_if(ifp);847 if (err) {848 brcmf_cfg80211_arm_vif_event(cfg, NULL);849 goto fail;850 }851 852 /* wait for firmware event */853 err = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_ADD,854 BRCMF_VIF_EVENT_TIMEOUT);855 brcmf_cfg80211_arm_vif_event(cfg, NULL);856 if (!err) {857 bphy_err(drvr, "timeout occurred\n");858 err = -EIO;859 goto fail;860 }861 862 /* interface created in firmware */863 ifp = vif->ifp;864 if (!ifp) {865 bphy_err(drvr, "no if pointer provided\n");866 err = -ENOENT;867 goto fail;868 }869 870 strscpy(ifp->ndev->name, name, sizeof(ifp->ndev->name));871 err = brcmf_net_attach(ifp, true);872 if (err) {873 bphy_err(drvr, "Registering netdevice failed\n");874 free_netdev(ifp->ndev);875 goto fail;876 }877 878 return &ifp->vif->wdev;879 880fail:881 brcmf_free_vif(vif);882 return ERR_PTR(err);883}884 885static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)886{887 enum nl80211_iftype iftype;888 889 iftype = vif->wdev.iftype;890 return iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO;891}892 893static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif)894{895 return vif->wdev.iftype == NL80211_IFTYPE_ADHOC;896}897 898/**899 * brcmf_mon_add_vif() - create monitor mode virtual interface900 *901 * @wiphy: wiphy device of new interface.902 * @name: name of the new interface.903 */904static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy,905 const char *name)906{907 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);908 struct brcmf_cfg80211_vif *vif;909 struct net_device *ndev;910 struct brcmf_if *ifp;911 int err;912 913 if (cfg->pub->mon_if) {914 err = -EEXIST;915 goto err_out;916 }917 918 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_MONITOR);919 if (IS_ERR(vif)) {920 err = PTR_ERR(vif);921 goto err_out;922 }923 924 ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, ether_setup);925 if (!ndev) {926 err = -ENOMEM;927 goto err_free_vif;928 }929 ndev->type = ARPHRD_IEEE80211_RADIOTAP;930 ndev->ieee80211_ptr = &vif->wdev;931 ndev->needs_free_netdev = true;932 ndev->priv_destructor = brcmf_cfg80211_free_netdev;933 SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));934 935 ifp = netdev_priv(ndev);936 ifp->vif = vif;937 ifp->ndev = ndev;938 ifp->drvr = cfg->pub;939 940 vif->ifp = ifp;941 vif->wdev.netdev = ndev;942 943 err = brcmf_net_mon_attach(ifp);944 if (err) {945 brcmf_err("Failed to attach %s device\n", ndev->name);946 free_netdev(ndev);947 goto err_free_vif;948 }949 950 cfg->pub->mon_if = ifp;951 952 return &vif->wdev;953 954err_free_vif:955 brcmf_free_vif(vif);956err_out:957 return ERR_PTR(err);958}959 960static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)961{962 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);963 struct net_device *ndev = wdev->netdev;964 965 ndev->netdev_ops->ndo_stop(ndev);966 967 brcmf_net_detach(ndev, true);968 969 cfg->pub->mon_if = NULL;970 971 return 0;972}973 974static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,975 const char *name,976 unsigned char name_assign_type,977 enum nl80211_iftype type,978 struct vif_params *params)979{980 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);981 struct brcmf_pub *drvr = cfg->pub;982 struct wireless_dev *wdev;983 int err;984 985 brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);986 err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);987 if (err) {988 bphy_err(drvr, "iface validation failed: err=%d\n", err);989 return ERR_PTR(err);990 }991 switch (type) {992 case NL80211_IFTYPE_ADHOC:993 case NL80211_IFTYPE_AP_VLAN:994 case NL80211_IFTYPE_WDS:995 case NL80211_IFTYPE_MESH_POINT:996 return ERR_PTR(-EOPNOTSUPP);997 case NL80211_IFTYPE_MONITOR:998 return brcmf_mon_add_vif(wiphy, name);999 case NL80211_IFTYPE_STATION:1000 case NL80211_IFTYPE_AP:1001 wdev = brcmf_apsta_add_vif(wiphy, name, params, type);1002 break;1003 case NL80211_IFTYPE_P2P_CLIENT:1004 case NL80211_IFTYPE_P2P_GO:1005 case NL80211_IFTYPE_P2P_DEVICE:1006 wdev = brcmf_p2p_add_vif(wiphy, name, name_assign_type, type, params);1007 break;1008 case NL80211_IFTYPE_UNSPECIFIED:1009 default:1010 return ERR_PTR(-EINVAL);1011 }1012 1013 if (IS_ERR(wdev))1014 bphy_err(drvr, "add iface %s type %d failed: err=%d\n", name,1015 type, (int)PTR_ERR(wdev));1016 else1017 brcmf_cfg80211_update_proto_addr_mode(wdev);1018 1019 return wdev;1020}1021 1022static void brcmf_scan_config_mpc(struct brcmf_if *ifp, int mpc)1023{1024 if (brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_NEED_MPC))1025 brcmf_set_mpc(ifp, mpc);1026}1027 1028void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)1029{1030 struct brcmf_pub *drvr = ifp->drvr;1031 s32 err = 0;1032 1033 if (check_vif_up(ifp->vif)) {1034 err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);1035 if (err) {1036 bphy_err(drvr, "fail to set mpc\n");1037 return;1038 }1039 brcmf_dbg(INFO, "MPC : %d\n", mpc);1040 }1041}1042 1043static void brcmf_scan_params_v2_to_v1(struct brcmf_scan_params_v2_le *params_v2_le,1044 struct brcmf_scan_params_le *params_le)1045{1046 size_t params_size;1047 u32 ch;1048 int n_channels, n_ssids;1049 1050 memcpy(¶ms_le->ssid_le, ¶ms_v2_le->ssid_le,1051 sizeof(params_le->ssid_le));1052 memcpy(¶ms_le->bssid, ¶ms_v2_le->bssid,1053 sizeof(params_le->bssid));1054 1055 params_le->bss_type = params_v2_le->bss_type;1056 params_le->scan_type = le32_to_cpu(params_v2_le->scan_type);1057 params_le->nprobes = params_v2_le->nprobes;1058 params_le->active_time = params_v2_le->active_time;1059 params_le->passive_time = params_v2_le->passive_time;1060 params_le->home_time = params_v2_le->home_time;1061 params_le->channel_num = params_v2_le->channel_num;1062 1063 ch = le32_to_cpu(params_v2_le->channel_num);1064 n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK;1065 n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT;1066 1067 params_size = sizeof(u16) * n_channels;1068 if (n_ssids > 0) {1069 params_size = roundup(params_size, sizeof(u32));1070 params_size += sizeof(struct brcmf_ssid_le) * n_ssids;1071 }1072 1073 memcpy(¶ms_le->channel_list[0],1074 ¶ms_v2_le->channel_list[0], params_size);1075}1076 1077static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,1078 struct brcmf_scan_params_v2_le *params_le,1079 struct cfg80211_scan_request *request)1080{1081 u32 n_ssids;1082 u32 n_channels;1083 s32 i;1084 s32 offset;1085 u16 chanspec;1086 char *ptr;1087 int length;1088 struct brcmf_ssid_le ssid_le;1089 1090 eth_broadcast_addr(params_le->bssid);1091 1092 length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;1093 1094 params_le->version = cpu_to_le16(BRCMF_SCAN_PARAMS_VERSION_V2);1095 params_le->bss_type = DOT11_BSSTYPE_ANY;1096 params_le->scan_type = cpu_to_le32(BRCMF_SCANTYPE_ACTIVE);1097 params_le->channel_num = 0;1098 params_le->nprobes = cpu_to_le32(-1);1099 params_le->active_time = cpu_to_le32(-1);1100 params_le->passive_time = cpu_to_le32(-1);1101 params_le->home_time = cpu_to_le32(-1);1102 memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le));1103 1104 /* Scan abort */1105 if (!request) {1106 length += sizeof(u16);1107 params_le->channel_num = cpu_to_le32(1);1108 params_le->channel_list[0] = cpu_to_le16(-1);1109 params_le->length = cpu_to_le16(length);1110 return;1111 }1112 1113 n_ssids = request->n_ssids;1114 n_channels = request->n_channels;1115 1116 /* Copy channel array if applicable */1117 brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",1118 n_channels);1119 if (n_channels > 0) {1120 length += roundup(sizeof(u16) * n_channels, sizeof(u32));1121 for (i = 0; i < n_channels; i++) {1122 chanspec = channel_to_chanspec(&cfg->d11inf,1123 request->channels[i]);1124 brcmf_dbg(SCAN, "Chan : %d, Channel spec: %x\n",1125 request->channels[i]->hw_value, chanspec);1126 params_le->channel_list[i] = cpu_to_le16(chanspec);1127 }1128 } else {1129 brcmf_dbg(SCAN, "Scanning all channels\n");1130 }1131 1132 /* Copy ssid array if applicable */1133 brcmf_dbg(SCAN, "### List of SSIDs to scan ### %d\n", n_ssids);1134 if (n_ssids > 0) {1135 offset = offsetof(struct brcmf_scan_params_v2_le, channel_list) +1136 n_channels * sizeof(u16);1137 offset = roundup(offset, sizeof(u32));1138 length += sizeof(ssid_le) * n_ssids;1139 ptr = (char *)params_le + offset;1140 for (i = 0; i < n_ssids; i++) {1141 memset(&ssid_le, 0, sizeof(ssid_le));1142 ssid_le.SSID_len =1143 cpu_to_le32(request->ssids[i].ssid_len);1144 memcpy(ssid_le.SSID, request->ssids[i].ssid,1145 request->ssids[i].ssid_len);1146 if (!ssid_le.SSID_len)1147 brcmf_dbg(SCAN, "%d: Broadcast scan\n", i);1148 else1149 brcmf_dbg(SCAN, "%d: scan for %.32s size=%d\n",1150 i, ssid_le.SSID, ssid_le.SSID_len);1151 memcpy(ptr, &ssid_le, sizeof(ssid_le));1152 ptr += sizeof(ssid_le);1153 }1154 } else {1155 brcmf_dbg(SCAN, "Performing passive scan\n");1156 params_le->scan_type = cpu_to_le32(BRCMF_SCANTYPE_PASSIVE);1157 }1158 params_le->length = cpu_to_le16(length);1159 /* Adding mask to channel numbers */1160 params_le->channel_num =1161 cpu_to_le32((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT) |1162 (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));1163}1164 1165s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,1166 struct brcmf_if *ifp, bool aborted,1167 bool fw_abort)1168{1169 struct brcmf_pub *drvr = cfg->pub;1170 struct brcmf_scan_params_v2_le params_v2_le;1171 struct cfg80211_scan_request *scan_request;1172 u64 reqid;1173 u32 bucket;1174 s32 err = 0;1175 1176 brcmf_dbg(SCAN, "Enter\n");1177 1178 /* clear scan request, because the FW abort can cause a second call */1179 /* to this functon and might cause a double cfg80211_scan_done */1180 scan_request = cfg->scan_request;1181 cfg->scan_request = NULL;1182 1183 timer_delete_sync(&cfg->escan_timeout);1184 1185 if (fw_abort) {1186 /* Do a scan abort to stop the driver's scan engine */1187 brcmf_dbg(SCAN, "ABORT scan in firmware\n");1188 1189 brcmf_escan_prep(cfg, ¶ms_v2_le, NULL);1190 1191 /* E-Scan (or anyother type) can be aborted by SCAN */1192 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {1193 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,1194 ¶ms_v2_le,1195 sizeof(params_v2_le));1196 } else {1197 struct brcmf_scan_params_le params_le;1198 1199 brcmf_scan_params_v2_to_v1(¶ms_v2_le, ¶ms_le);1200 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,1201 ¶ms_le,1202 sizeof(params_le));1203 }1204 1205 if (err)1206 bphy_err(drvr, "Scan abort failed\n");1207 }1208 1209 brcmf_scan_config_mpc(ifp, 1);1210 1211 /*1212 * e-scan can be initiated internally1213 * which takes precedence.1214 */1215 if (cfg->int_escan_map) {1216 brcmf_dbg(SCAN, "scheduled scan completed (%x)\n",1217 cfg->int_escan_map);1218 while (cfg->int_escan_map) {1219 bucket = __ffs(cfg->int_escan_map);1220 cfg->int_escan_map &= ~BIT(bucket);1221 reqid = brcmf_pno_find_reqid_by_bucket(cfg->pno,1222 bucket);1223 if (!aborted) {1224 brcmf_dbg(SCAN, "report results: reqid=%llu\n",1225 reqid);1226 cfg80211_sched_scan_results(cfg_to_wiphy(cfg),1227 reqid);1228 }1229 }1230 } else if (scan_request) {1231 struct cfg80211_scan_info info = {1232 .aborted = aborted,1233 };1234 1235 brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",1236 aborted ? "Aborted" : "Done");1237 cfg80211_scan_done(scan_request, &info);1238 }1239 if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))1240 brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");1241 1242 return err;1243}1244 1245static int brcmf_cfg80211_del_apsta_iface(struct wiphy *wiphy,1246 struct wireless_dev *wdev)1247{1248 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);1249 struct net_device *ndev = wdev->netdev;1250 struct brcmf_if *ifp = netdev_priv(ndev);1251 struct brcmf_pub *drvr = cfg->pub;1252 int ret;1253 int err;1254 1255 brcmf_cfg80211_arm_vif_event(cfg, ifp->vif);1256 1257 err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0);1258 if (err) {1259 bphy_err(drvr, "interface_remove failed %d\n", err);1260 goto err_unarm;1261 }1262 1263 /* wait for firmware event */1264 ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,1265 BRCMF_VIF_EVENT_TIMEOUT);1266 if (!ret) {1267 bphy_err(drvr, "timeout occurred\n");1268 err = -EIO;1269 goto err_unarm;1270 }1271 1272 brcmf_remove_interface(ifp, true);1273 1274err_unarm:1275 brcmf_cfg80211_arm_vif_event(cfg, NULL);1276 return err;1277}1278 1279static1280int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)1281{1282 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);1283 struct net_device *ndev = wdev->netdev;1284 1285 if (ndev && ndev == cfg_to_ndev(cfg))1286 return -ENOTSUPP;1287 1288 /* vif event pending in firmware */1289 if (brcmf_cfg80211_vif_event_armed(cfg))1290 return -EBUSY;1291 1292 if (ndev) {1293 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&1294 cfg->escan_info.ifp == netdev_priv(ndev))1295 brcmf_notify_escan_complete(cfg, netdev_priv(ndev),1296 true, true);1297 1298 brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);1299 }1300 1301 switch (wdev->iftype) {1302 case NL80211_IFTYPE_ADHOC:1303 case NL80211_IFTYPE_AP_VLAN:1304 case NL80211_IFTYPE_WDS:1305 case NL80211_IFTYPE_MESH_POINT:1306 return -EOPNOTSUPP;1307 case NL80211_IFTYPE_MONITOR:1308 return brcmf_mon_del_vif(wiphy, wdev);1309 case NL80211_IFTYPE_STATION:1310 case NL80211_IFTYPE_AP:1311 return brcmf_cfg80211_del_apsta_iface(wiphy, wdev);1312 case NL80211_IFTYPE_P2P_CLIENT:1313 case NL80211_IFTYPE_P2P_GO:1314 case NL80211_IFTYPE_P2P_DEVICE:1315 return brcmf_p2p_del_vif(wiphy, wdev);1316 case NL80211_IFTYPE_UNSPECIFIED:1317 default:1318 return -EINVAL;1319 }1320 return -EOPNOTSUPP;1321}1322 1323static s321324brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,1325 enum nl80211_iftype type,1326 struct vif_params *params)1327{1328 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);1329 struct brcmf_if *ifp = netdev_priv(ndev);1330 struct brcmf_cfg80211_vif *vif = ifp->vif;1331 struct brcmf_pub *drvr = cfg->pub;1332 s32 infra = 0;1333 s32 ap = 0;1334 s32 err = 0;1335 1336 brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, type=%d\n", ifp->bsscfgidx,1337 type);1338 1339 /* WAR: There are a number of p2p interface related problems which1340 * need to be handled initially (before doing the validate).1341 * wpa_supplicant tends to do iface changes on p2p device/client/go1342 * which are not always possible/allowed. However we need to return1343 * OK otherwise the wpa_supplicant wont start. The situation differs1344 * on configuration and setup (p2pon=1 module param). The first check1345 * is to see if the request is a change to station for p2p iface.1346 */1347 if ((type == NL80211_IFTYPE_STATION) &&1348 ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) ||1349 (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) ||1350 (vif->wdev.iftype == NL80211_IFTYPE_P2P_DEVICE))) {1351 brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n");1352 /* Now depending on whether module param p2pon=1 was used the1353 * response needs to be either 0 or EOPNOTSUPP. The reason is1354 * that if p2pon=1 is used, but a newer supplicant is used then1355 * we should return an error, as this combination wont work.1356 * In other situations 0 is returned and supplicant will start1357 * normally. It will give a trace in cfg80211, but it is the1358 * only way to get it working. Unfortunately this will result1359 * in situation where we wont support new supplicant in1360 * combination with module param p2pon=1, but that is the way1361 * it is. If the user tries this then unloading of driver might1362 * fail/lock.1363 */1364 if (cfg->p2p.p2pdev_dynamically)1365 return -EOPNOTSUPP;1366 else1367 return 0;1368 }1369 err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type);1370 if (err) {1371 bphy_err(drvr, "iface validation failed: err=%d\n", err);1372 return err;1373 }1374 switch (type) {1375 case NL80211_IFTYPE_MONITOR:1376 case NL80211_IFTYPE_WDS:1377 bphy_err(drvr, "type (%d) : currently we do not support this type\n",1378 type);1379 return -EOPNOTSUPP;1380 case NL80211_IFTYPE_ADHOC:1381 infra = 0;1382 break;1383 case NL80211_IFTYPE_STATION:1384 infra = 1;1385 break;1386 case NL80211_IFTYPE_AP:1387 case NL80211_IFTYPE_P2P_GO:1388 ap = 1;1389 break;1390 default:1391 err = -EINVAL;1392 goto done;1393 }1394 1395 if (ap) {1396 if (type == NL80211_IFTYPE_P2P_GO) {1397 brcmf_dbg(INFO, "IF Type = P2P GO\n");1398 err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO);1399 }1400 if (!err) {1401 brcmf_dbg(INFO, "IF Type = AP\n");1402 }1403 } else {1404 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra);1405 if (err) {1406 bphy_err(drvr, "WLC_SET_INFRA error (%d)\n", err);1407 err = -EAGAIN;1408 goto done;1409 }1410 brcmf_dbg(INFO, "IF Type = %s\n", brcmf_is_ibssmode(vif) ?1411 "Adhoc" : "Infra");1412 }1413 ndev->ieee80211_ptr->iftype = type;1414 1415 brcmf_cfg80211_update_proto_addr_mode(&vif->wdev);1416 1417done:1418 brcmf_dbg(TRACE, "Exit\n");1419 1420 return err;1421}1422 1423static s321424brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,1425 struct cfg80211_scan_request *request)1426{1427 struct brcmf_pub *drvr = cfg->pub;1428 s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +1429 offsetof(struct brcmf_escan_params_le, params_v2_le);1430 struct brcmf_escan_params_le *params;1431 s32 err = 0;1432 1433 brcmf_dbg(SCAN, "E-SCAN START\n");1434 1435 if (request != NULL) {1436 /* Allocate space for populating ssids in struct */1437 params_size += sizeof(u32) * ((request->n_channels + 1) / 2);1438 1439 /* Allocate space for populating ssids in struct */1440 params_size += sizeof(struct brcmf_ssid_le) * request->n_ssids;1441 }1442 1443 params = kzalloc(params_size, GFP_KERNEL);1444 if (!params) {1445 err = -ENOMEM;1446 goto exit;1447 }1448 BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);1449 brcmf_escan_prep(cfg, ¶ms->params_v2_le, request);1450 1451 params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION_V2);1452 1453 if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_V2)) {1454 struct brcmf_escan_params_le *params_v1;1455 1456 params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE;1457 params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE;1458 params_v1 = kzalloc(params_size, GFP_KERNEL);1459 if (!params_v1) {1460 err = -ENOMEM;1461 goto exit_params;1462 }1463 params_v1->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);1464 brcmf_scan_params_v2_to_v1(¶ms->params_v2_le, ¶ms_v1->params_le);1465 kfree(params);1466 params = params_v1;1467 }1468 1469 params->action = cpu_to_le16(WL_ESCAN_ACTION_START);1470 params->sync_id = cpu_to_le16(0x1234);1471 1472 err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size);1473 if (err) {1474 if (err == -EBUSY)1475 brcmf_dbg(INFO, "system busy : escan canceled\n");1476 else1477 bphy_err(drvr, "error (%d)\n", err);1478 }1479 1480exit_params:1481 kfree(params);1482exit:1483 return err;1484}1485 1486static s321487brcmf_do_escan(struct brcmf_if *ifp, struct cfg80211_scan_request *request)1488{1489 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;1490 s32 err;1491 struct brcmf_scan_results *results;1492 struct escan_info *escan = &cfg->escan_info;1493 1494 brcmf_dbg(SCAN, "Enter\n");1495 escan->ifp = ifp;1496 escan->wiphy = cfg->wiphy;1497 escan->escan_state = WL_ESCAN_STATE_SCANNING;1498 1499 brcmf_scan_config_mpc(ifp, 0);1500 results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;1501 results->version = 0;1502 results->count = 0;1503 results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;1504 1505 err = escan->run(cfg, ifp, request);1506 if (err)1507 brcmf_scan_config_mpc(ifp, 1);1508 return err;1509}1510 1511static s321512brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)1513{1514 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);1515 struct brcmf_pub *drvr = cfg->pub;1516 struct brcmf_cfg80211_vif *vif;1517 s32 err = 0;1518 1519 brcmf_dbg(TRACE, "Enter\n");1520 vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);1521 if (!check_vif_up(vif))1522 return -EIO;1523 1524 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {1525 bphy_err(drvr, "Scanning already: status (%lu)\n",1526 cfg->scan_status);1527 return -EAGAIN;1528 }1529 if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) {1530 bphy_err(drvr, "Scanning being aborted: status (%lu)\n",1531 cfg->scan_status);1532 return -EAGAIN;1533 }1534 if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {1535 bphy_err(drvr, "Scanning suppressed: status (%lu)\n",1536 cfg->scan_status);1537 return -EAGAIN;1538 }1539 if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {1540 bphy_err(drvr, "Connecting: status (%lu)\n", vif->sme_state);1541 return -EAGAIN;1542 }1543 1544 /* If scan req comes for p2p0, send it over primary I/F */1545 if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)1546 vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;1547 1548 brcmf_dbg(SCAN, "START ESCAN\n");1549 1550 cfg->scan_request = request;1551 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);1552 1553 cfg->escan_info.run = brcmf_run_escan;1554 err = brcmf_p2p_scan_prep(wiphy, request, vif);1555 if (err)1556 goto scan_out;1557 1558 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,1559 request->ie, request->ie_len);1560 if (err)1561 goto scan_out;1562 1563 err = brcmf_do_escan(vif->ifp, request);1564 if (err)1565 goto scan_out;1566 1567 /* Arm scan timeout timer */1568 mod_timer(&cfg->escan_timeout,1569 jiffies + msecs_to_jiffies(BRCMF_ESCAN_TIMER_INTERVAL_MS));1570 1571 return 0;1572 1573scan_out:1574 bphy_err(drvr, "scan error (%d)\n", err);1575 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);1576 cfg->scan_request = NULL;1577 return err;1578}1579 1580static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)1581{1582 struct brcmf_if *ifp = netdev_priv(ndev);1583 struct brcmf_pub *drvr = ifp->drvr;1584 s32 err = 0;1585 1586 err = brcmf_fil_iovar_int_set(ifp, "rtsthresh", rts_threshold);1587 if (err)1588 bphy_err(drvr, "Error (%d)\n", err);1589 1590 return err;1591}1592 1593static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)1594{1595 struct brcmf_if *ifp = netdev_priv(ndev);1596 struct brcmf_pub *drvr = ifp->drvr;1597 s32 err = 0;1598 1599 err = brcmf_fil_iovar_int_set(ifp, "fragthresh",1600 frag_threshold);1601 if (err)1602 bphy_err(drvr, "Error (%d)\n", err);1603 1604 return err;1605}1606 1607static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)1608{1609 struct brcmf_if *ifp = netdev_priv(ndev);1610 struct brcmf_pub *drvr = ifp->drvr;1611 s32 err = 0;1612 u32 cmd = (l ? BRCMF_C_SET_LRL : BRCMF_C_SET_SRL);1613 1614 err = brcmf_fil_cmd_int_set(ifp, cmd, retry);1615 if (err) {1616 bphy_err(drvr, "cmd (%d) , error (%d)\n", cmd, err);1617 return err;1618 }1619 return err;1620}1621 1622static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)1623{1624 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);1625 struct net_device *ndev = cfg_to_ndev(cfg);1626 struct brcmf_if *ifp = netdev_priv(ndev);1627 s32 err = 0;1628 1629 brcmf_dbg(TRACE, "Enter\n");1630 if (!check_vif_up(ifp->vif))1631 return -EIO;1632 1633 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&1634 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {1635 cfg->conf->rts_threshold = wiphy->rts_threshold;1636 err = brcmf_set_rts(ndev, cfg->conf->rts_threshold);1637 if (!err)1638 goto done;1639 }1640 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&1641 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {1642 cfg->conf->frag_threshold = wiphy->frag_threshold;1643 err = brcmf_set_frag(ndev, cfg->conf->frag_threshold);1644 if (!err)1645 goto done;1646 }1647 if (changed & WIPHY_PARAM_RETRY_LONG1648 && (cfg->conf->retry_long != wiphy->retry_long)) {1649 cfg->conf->retry_long = wiphy->retry_long;1650 err = brcmf_set_retry(ndev, cfg->conf->retry_long, true);1651 if (!err)1652 goto done;1653 }1654 if (changed & WIPHY_PARAM_RETRY_SHORT1655 && (cfg->conf->retry_short != wiphy->retry_short)) {1656 cfg->conf->retry_short = wiphy->retry_short;1657 err = brcmf_set_retry(ndev, cfg->conf->retry_short, false);1658 if (!err)1659 goto done;1660 }1661 1662done:1663 brcmf_dbg(TRACE, "Exit\n");1664 return err;1665}1666 1667static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)1668{1669 memset(prof, 0, sizeof(*prof));1670}1671 1672static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)1673{1674 u16 reason;1675 1676 switch (e->event_code) {1677 case BRCMF_E_DEAUTH:1678 case BRCMF_E_DEAUTH_IND:1679 case BRCMF_E_DISASSOC_IND:1680 reason = e->reason;1681 break;1682 case BRCMF_E_LINK:1683 default:1684 reason = 0;1685 break;1686 }1687 return reason;1688}1689 1690int brcmf_set_wsec(struct brcmf_if *ifp, const u8 *key, u16 key_len, u16 flags)1691{1692 struct brcmf_pub *drvr = ifp->drvr;1693 struct brcmf_wsec_pmk_le pmk;1694 int err;1695 1696 if (key_len > sizeof(pmk.key)) {1697 bphy_err(drvr, "key must be less than %zu bytes\n",1698 sizeof(pmk.key));1699 return -EINVAL;1700 }1701 1702 memset(&pmk, 0, sizeof(pmk));1703 1704 /* pass key material directly */1705 pmk.key_len = cpu_to_le16(key_len);1706 pmk.flags = cpu_to_le16(flags);1707 memcpy(pmk.key, key, key_len);1708 1709 /* store key material in firmware */1710 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,1711 &pmk, sizeof(pmk));1712 if (err < 0)1713 bphy_err(drvr, "failed to change PSK in firmware (len=%u)\n",1714 key_len);1715 1716 return err;1717}1718BRCMF_EXPORT_SYMBOL_GPL(brcmf_set_wsec);1719 1720static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)1721{1722 return brcmf_set_wsec(ifp, pmk_data, pmk_len, 0);1723}1724 1725static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason,1726 bool locally_generated)1727{1728 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);1729 struct brcmf_pub *drvr = cfg->pub;1730 bool bus_up = drvr->bus_if->state == BRCMF_BUS_UP;1731 s32 err = 0;1732 1733 brcmf_dbg(TRACE, "Enter\n");1734 1735 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {1736 if (bus_up) {1737 brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n");1738 err = brcmf_fil_cmd_data_set(vif->ifp,1739 BRCMF_C_DISASSOC, NULL, 0);1740 if (err)1741 bphy_err(drvr, "WLC_DISASSOC failed (%d)\n",1742 err);1743 }1744 1745 if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) ||1746 (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT))1747 cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,1748 locally_generated, GFP_KERNEL);1749 }1750 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);1751 clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);1752 clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);1753 clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);1754 brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);1755 if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {1756 if (bus_up)1757 brcmf_set_pmk(vif->ifp, NULL, 0);1758 vif->profile.use_fwsup = BRCMF_PROFILE_FWSUP_NONE;1759 }1760 brcmf_dbg(TRACE, "Exit\n");1761}1762 1763static s321764brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,1765 struct cfg80211_ibss_params *params)1766{1767 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);1768 struct brcmf_if *ifp = netdev_priv(ndev);1769 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;1770 struct brcmf_pub *drvr = cfg->pub;1771 struct brcmf_join_params join_params;1772 size_t join_params_size = 0;1773 s32 err = 0;1774 s32 wsec = 0;1775 s32 bcnprd;1776 u16 chanspec;1777 u32 ssid_len;1778 1779 brcmf_dbg(TRACE, "Enter\n");1780 if (!check_vif_up(ifp->vif))1781 return -EIO;1782 1783 if (params->ssid)1784 brcmf_dbg(CONN, "SSID: %s\n", params->ssid);1785 else {1786 brcmf_dbg(CONN, "SSID: NULL, Not supported\n");1787 return -EOPNOTSUPP;1788 }1789 1790 set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);1791 1792 if (params->bssid)1793 brcmf_dbg(CONN, "BSSID: %pM\n", params->bssid);1794 else1795 brcmf_dbg(CONN, "No BSSID specified\n");1796 1797 if (params->chandef.chan)1798 brcmf_dbg(CONN, "channel: %d\n",1799 params->chandef.chan->center_freq);1800 else1801 brcmf_dbg(CONN, "no channel specified\n");1802 1803 if (params->channel_fixed)1804 brcmf_dbg(CONN, "fixed channel required\n");1805 else1806 brcmf_dbg(CONN, "no fixed channel required\n");1807 1808 if (params->ie && params->ie_len)1809 brcmf_dbg(CONN, "ie len: %d\n", params->ie_len);1810 else1811 brcmf_dbg(CONN, "no ie specified\n");1812 1813 if (params->beacon_interval)1814 brcmf_dbg(CONN, "beacon interval: %d\n",1815 params->beacon_interval);1816 else1817 brcmf_dbg(CONN, "no beacon interval specified\n");1818 1819 if (params->basic_rates)1820 brcmf_dbg(CONN, "basic rates: %08X\n", params->basic_rates);1821 else1822 brcmf_dbg(CONN, "no basic rates specified\n");1823 1824 if (params->privacy)1825 brcmf_dbg(CONN, "privacy required\n");1826 else1827 brcmf_dbg(CONN, "no privacy required\n");1828 1829 /* Configure Privacy for starter */1830 if (params->privacy)1831 wsec |= WEP_ENABLED;1832 1833 err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec);1834 if (err) {1835 bphy_err(drvr, "wsec failed (%d)\n", err);1836 goto done;1837 }1838 1839 /* Configure Beacon Interval for starter */1840 if (params->beacon_interval)1841 bcnprd = params->beacon_interval;1842 else1843 bcnprd = 100;1844 1845 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, bcnprd);1846 if (err) {1847 bphy_err(drvr, "WLC_SET_BCNPRD failed (%d)\n", err);1848 goto done;1849 }1850 1851 /* Configure required join parameter */1852 memset(&join_params, 0, sizeof(struct brcmf_join_params));1853 1854 /* SSID */1855 ssid_len = min_t(u32, params->ssid_len, IEEE80211_MAX_SSID_LEN);1856 memcpy(join_params.ssid_le.SSID, params->ssid, ssid_len);1857 join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);1858 join_params_size = sizeof(join_params.ssid_le);1859 1860 /* BSSID */1861 if (params->bssid) {1862 memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);1863 join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;1864 memcpy(profile->bssid, params->bssid, ETH_ALEN);1865 } else {1866 eth_broadcast_addr(join_params.params_le.bssid);1867 eth_zero_addr(profile->bssid);1868 }1869 1870 /* Channel */1871 if (params->chandef.chan) {1872 u32 target_channel;1873 1874 cfg->channel =1875 ieee80211_frequency_to_channel(1876 params->chandef.chan->center_freq);1877 if (params->channel_fixed) {1878 /* adding chanspec */1879 chanspec = chandef_to_chanspec(&cfg->d11inf,1880 ¶ms->chandef);1881 join_params.params_le.chanspec_list[0] =1882 cpu_to_le16(chanspec);1883 join_params.params_le.chanspec_num = cpu_to_le32(1);1884 join_params_size += sizeof(join_params.params_le);1885 }1886 1887 /* set channel for starter */1888 target_channel = cfg->channel;1889 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_CHANNEL,1890 target_channel);1891 if (err) {1892 bphy_err(drvr, "WLC_SET_CHANNEL failed (%d)\n", err);1893 goto done;1894 }1895 } else1896 cfg->channel = 0;1897 1898 cfg->ibss_starter = false;1899 1900 1901 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,1902 &join_params, join_params_size);1903 if (err) {1904 bphy_err(drvr, "WLC_SET_SSID failed (%d)\n", err);1905 goto done;1906 }1907 1908done:1909 if (err)1910 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);1911 brcmf_dbg(TRACE, "Exit\n");1912 return err;1913}1914 1915static s321916brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)1917{1918 struct brcmf_if *ifp = netdev_priv(ndev);1919 1920 brcmf_dbg(TRACE, "Enter\n");1921 if (!check_vif_up(ifp->vif)) {1922 /* When driver is being unloaded, it can end up here. If an1923 * error is returned then later on a debug trace in the wireless1924 * core module will be printed. To avoid this 0 is returned.1925 */1926 return 0;1927 }1928 1929 brcmf_link_down(ifp->vif, WLAN_REASON_DEAUTH_LEAVING, true);1930 brcmf_net_setcarrier(ifp, false);1931 1932 brcmf_dbg(TRACE, "Exit\n");1933 1934 return 0;1935}1936 1937static s32 brcmf_set_wpa_version(struct net_device *ndev,1938 struct cfg80211_connect_params *sme)1939{1940 struct brcmf_if *ifp = netdev_priv(ndev);1941 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);1942 struct brcmf_pub *drvr = ifp->drvr;1943 struct brcmf_cfg80211_security *sec;1944 s32 val = 0;1945 s32 err = 0;1946 1947 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)1948 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;1949 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)1950 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;1951 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)1952 val = WPA3_AUTH_SAE_PSK;1953 else1954 val = WPA_AUTH_DISABLED;1955 brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);1956 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);1957 if (err) {1958 bphy_err(drvr, "set wpa_auth failed (%d)\n", err);1959 return err;1960 }1961 sec = &profile->sec;1962 sec->wpa_versions = sme->crypto.wpa_versions;1963 return err;1964}1965 1966static s32 brcmf_set_auth_type(struct net_device *ndev,1967 struct cfg80211_connect_params *sme)1968{1969 struct brcmf_if *ifp = netdev_priv(ndev);1970 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);1971 struct brcmf_pub *drvr = ifp->drvr;1972 struct brcmf_cfg80211_security *sec;1973 s32 val = 0;1974 s32 err = 0;1975 1976 switch (sme->auth_type) {1977 case NL80211_AUTHTYPE_OPEN_SYSTEM:1978 val = 0;1979 brcmf_dbg(CONN, "open system\n");1980 break;1981 case NL80211_AUTHTYPE_SHARED_KEY:1982 val = 1;1983 brcmf_dbg(CONN, "shared key\n");1984 break;1985 case NL80211_AUTHTYPE_SAE:1986 val = 3;1987 brcmf_dbg(CONN, "SAE authentication\n");1988 break;1989 default:1990 val = 2;1991 brcmf_dbg(CONN, "automatic, auth type (%d)\n", sme->auth_type);1992 break;1993 }1994 1995 err = brcmf_fil_bsscfg_int_set(ifp, "auth", val);1996 if (err) {1997 bphy_err(drvr, "set auth failed (%d)\n", err);1998 return err;1999 }2000 sec = &profile->sec;2001 sec->auth_type = sme->auth_type;2002 return err;2003}2004 2005static s322006brcmf_set_wsec_mode(struct net_device *ndev,2007 struct cfg80211_connect_params *sme)2008{2009 struct brcmf_if *ifp = netdev_priv(ndev);2010 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);2011 struct brcmf_pub *drvr = ifp->drvr;2012 struct brcmf_cfg80211_security *sec;2013 s32 pval = 0;2014 s32 gval = 0;2015 s32 wsec;2016 s32 err = 0;2017 2018 if (sme->crypto.n_ciphers_pairwise) {2019 switch (sme->crypto.ciphers_pairwise[0]) {2020 case WLAN_CIPHER_SUITE_WEP40:2021 case WLAN_CIPHER_SUITE_WEP104:2022 pval = WEP_ENABLED;2023 break;2024 case WLAN_CIPHER_SUITE_TKIP:2025 pval = TKIP_ENABLED;2026 break;2027 case WLAN_CIPHER_SUITE_CCMP:2028 pval = AES_ENABLED;2029 break;2030 case WLAN_CIPHER_SUITE_AES_CMAC:2031 pval = AES_ENABLED;2032 break;2033 default:2034 bphy_err(drvr, "invalid cipher pairwise (%d)\n",2035 sme->crypto.ciphers_pairwise[0]);2036 return -EINVAL;2037 }2038 }2039 if (sme->crypto.cipher_group) {2040 switch (sme->crypto.cipher_group) {2041 case WLAN_CIPHER_SUITE_WEP40:2042 case WLAN_CIPHER_SUITE_WEP104:2043 gval = WEP_ENABLED;2044 break;2045 case WLAN_CIPHER_SUITE_TKIP:2046 gval = TKIP_ENABLED;2047 break;2048 case WLAN_CIPHER_SUITE_CCMP:2049 gval = AES_ENABLED;2050 break;2051 case WLAN_CIPHER_SUITE_AES_CMAC:2052 gval = AES_ENABLED;2053 break;2054 default:2055 bphy_err(drvr, "invalid cipher group (%d)\n",2056 sme->crypto.cipher_group);2057 return -EINVAL;2058 }2059 }2060 2061 brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);2062 /* In case of privacy, but no security and WPS then simulate */2063 /* setting AES. WPS-2.0 allows no security */2064 if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval &&2065 sme->privacy)2066 pval = AES_ENABLED;2067 2068 wsec = pval | gval;2069 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);2070 if (err) {2071 bphy_err(drvr, "error (%d)\n", err);2072 return err;2073 }2074 2075 sec = &profile->sec;2076 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];2077 sec->cipher_group = sme->crypto.cipher_group;2078 2079 return err;2080}2081 2082static s322083brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)2084{2085 struct brcmf_if *ifp = netdev_priv(ndev);2086 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;2087 struct brcmf_pub *drvr = ifp->drvr;2088 s32 val;2089 s32 err;2090 const struct brcmf_tlv *rsn_ie;2091 const u8 *ie;2092 u32 ie_len;2093 u32 offset;2094 u16 rsn_cap;2095 u32 mfp;2096 u16 count;2097 2098 profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;2099 profile->is_ft = false;2100 2101 if (!sme->crypto.n_akm_suites)2102 return 0;2103 2104 err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev),2105 "wpa_auth", &val);2106 if (err) {2107 bphy_err(drvr, "could not get wpa_auth (%d)\n", err);2108 return err;2109 }2110 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {2111 switch (sme->crypto.akm_suites[0]) {2112 case WLAN_AKM_SUITE_8021X:2113 val = WPA_AUTH_UNSPECIFIED;2114 if (sme->want_1x)2115 profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;2116 break;2117 case WLAN_AKM_SUITE_PSK:2118 val = WPA_AUTH_PSK;2119 break;2120 default:2121 bphy_err(drvr, "invalid akm suite (%d)\n",2122 sme->crypto.akm_suites[0]);2123 return -EINVAL;2124 }2125 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {2126 switch (sme->crypto.akm_suites[0]) {2127 case WLAN_AKM_SUITE_8021X:2128 val = WPA2_AUTH_UNSPECIFIED;2129 if (sme->want_1x)2130 profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;2131 break;2132 case WLAN_AKM_SUITE_8021X_SHA256:2133 val = WPA2_AUTH_1X_SHA256;2134 if (sme->want_1x)2135 profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;2136 break;2137 case WLAN_AKM_SUITE_PSK_SHA256:2138 val = WPA2_AUTH_PSK_SHA256;2139 break;2140 case WLAN_AKM_SUITE_PSK:2141 val = WPA2_AUTH_PSK;2142 break;2143 case WLAN_AKM_SUITE_FT_8021X:2144 val = WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT;2145 profile->is_ft = true;2146 if (sme->want_1x)2147 profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;2148 break;2149 case WLAN_AKM_SUITE_FT_PSK:2150 val = WPA2_AUTH_PSK | WPA2_AUTH_FT;2151 profile->is_ft = true;2152 break;2153 default:2154 bphy_err(drvr, "invalid akm suite (%d)\n",2155 sme->crypto.akm_suites[0]);2156 return -EINVAL;2157 }2158 } else if (val & WPA3_AUTH_SAE_PSK) {2159 switch (sme->crypto.akm_suites[0]) {2160 case WLAN_AKM_SUITE_SAE:2161 val = WPA3_AUTH_SAE_PSK;2162 if (sme->crypto.sae_pwd) {2163 brcmf_dbg(INFO, "using SAE offload\n");2164 profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;2165 }2166 break;2167 case WLAN_AKM_SUITE_FT_OVER_SAE:2168 val = WPA3_AUTH_SAE_PSK | WPA2_AUTH_FT;2169 profile->is_ft = true;2170 if (sme->crypto.sae_pwd) {2171 brcmf_dbg(INFO, "using SAE offload\n");2172 profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;2173 }2174 break;2175 default:2176 bphy_err(drvr, "invalid akm suite (%d)\n",2177 sme->crypto.akm_suites[0]);2178 return -EINVAL;2179 }2180 }2181 2182 if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)2183 brcmf_dbg(INFO, "using 1X offload\n");2184 2185 if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))2186 goto skip_mfp_config;2187 /* The MFP mode (1 or 2) needs to be determined, parse IEs. The2188 * IE will not be verified, just a quick search for MFP config2189 */2190 rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie, sme->ie_len,2191 WLAN_EID_RSN);2192 if (!rsn_ie)2193 goto skip_mfp_config;2194 ie = (const u8 *)rsn_ie;2195 ie_len = rsn_ie->len + TLV_HDR_LEN;2196 /* Skip unicast suite */2197 offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;2198 if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)2199 goto skip_mfp_config;2200 /* Skip multicast suite */2201 count = ie[offset] + (ie[offset + 1] << 8);2202 offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);2203 if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)2204 goto skip_mfp_config;2205 /* Skip auth key management suite(s) */2206 count = ie[offset] + (ie[offset + 1] << 8);2207 offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);2208 if (offset + WPA_IE_SUITE_COUNT_LEN > ie_len)2209 goto skip_mfp_config;2210 /* Ready to read capabilities */2211 mfp = BRCMF_MFP_NONE;2212 rsn_cap = ie[offset] + (ie[offset + 1] << 8);2213 if (rsn_cap & RSN_CAP_MFPR_MASK)2214 mfp = BRCMF_MFP_REQUIRED;2215 else if (rsn_cap & RSN_CAP_MFPC_MASK)2216 mfp = BRCMF_MFP_CAPABLE;2217 brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);2218 2219skip_mfp_config:2220 brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);2221 err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);2222 if (err) {2223 bphy_err(drvr, "could not set wpa_auth (%d)\n", err);2224 return err;2225 }2226 2227 return err;2228}2229 2230static s322231brcmf_set_sharedkey(struct net_device *ndev,2232 struct cfg80211_connect_params *sme)2233{2234 struct brcmf_if *ifp = netdev_priv(ndev);2235 struct brcmf_pub *drvr = ifp->drvr;2236 struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev);2237 struct brcmf_cfg80211_security *sec;2238 struct brcmf_wsec_key key;2239 s32 val;2240 s32 err = 0;2241 2242 brcmf_dbg(CONN, "key len (%d)\n", sme->key_len);2243 2244 if (sme->key_len == 0)2245 return 0;2246 2247 sec = &profile->sec;2248 brcmf_dbg(CONN, "wpa_versions 0x%x cipher_pairwise 0x%x\n",2249 sec->wpa_versions, sec->cipher_pairwise);2250 2251 if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2 |2252 NL80211_WPA_VERSION_3))2253 return 0;2254 2255 if (!(sec->cipher_pairwise &2256 (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)))2257 return 0;2258 2259 memset(&key, 0, sizeof(key));2260 key.len = (u32) sme->key_len;2261 key.index = (u32) sme->key_idx;2262 if (key.len > sizeof(key.data)) {2263 bphy_err(drvr, "Too long key length (%u)\n", key.len);2264 return -EINVAL;2265 }2266 memcpy(key.data, sme->key, key.len);2267 key.flags = BRCMF_PRIMARY_KEY;2268 switch (sec->cipher_pairwise) {2269 case WLAN_CIPHER_SUITE_WEP40:2270 key.algo = CRYPTO_ALGO_WEP1;2271 break;2272 case WLAN_CIPHER_SUITE_WEP104:2273 key.algo = CRYPTO_ALGO_WEP128;2274 break;2275 default:2276 bphy_err(drvr, "Invalid algorithm (%d)\n",2277 sme->crypto.ciphers_pairwise[0]);2278 return -EINVAL;2279 }2280 /* Set the new key/index */2281 brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",2282 key.len, key.index, key.algo);2283 brcmf_dbg(CONN, "key \"%s\"\n", key.data);2284 err = send_key_to_dongle(ifp, &key);2285 if (err)2286 return err;2287 2288 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {2289 brcmf_dbg(CONN, "set auth_type to shared key\n");2290 val = WL_AUTH_SHARED_KEY; /* shared key */2291 err = brcmf_fil_bsscfg_int_set(ifp, "auth", val);2292 if (err)2293 bphy_err(drvr, "set auth failed (%d)\n", err);2294 }2295 return err;2296}2297 2298static2299enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp,2300 enum nl80211_auth_type type)2301{2302 if (type == NL80211_AUTHTYPE_AUTOMATIC &&2303 brcmf_feat_is_quirk_enabled(ifp, BRCMF_FEAT_QUIRK_AUTO_AUTH)) {2304 brcmf_dbg(CONN, "WAR: use OPEN instead of AUTO\n");2305 type = NL80211_AUTHTYPE_OPEN_SYSTEM;2306 }2307 return type;2308}2309 2310static void brcmf_set_join_pref(struct brcmf_if *ifp,2311 struct cfg80211_bss_selection *bss_select)2312{2313 struct brcmf_pub *drvr = ifp->drvr;2314 struct brcmf_join_pref_params join_pref_params[2];2315 enum nl80211_band band;2316 int err, i = 0;2317 2318 join_pref_params[i].len = 2;2319 join_pref_params[i].rssi_gain = 0;2320 2321 if (bss_select->behaviour != NL80211_BSS_SELECT_ATTR_BAND_PREF)2322 brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_ASSOC_PREFER, WLC_BAND_AUTO);2323 2324 switch (bss_select->behaviour) {2325 case __NL80211_BSS_SELECT_ATTR_INVALID:2326 brcmf_c_set_joinpref_default(ifp);2327 return;2328 case NL80211_BSS_SELECT_ATTR_BAND_PREF:2329 join_pref_params[i].type = BRCMF_JOIN_PREF_BAND;2330 band = bss_select->param.band_pref;2331 join_pref_params[i].band = nl80211_band_to_fwil(band);2332 i++;2333 break;2334 case NL80211_BSS_SELECT_ATTR_RSSI_ADJUST:2335 join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI_DELTA;2336 band = bss_select->param.adjust.band;2337 join_pref_params[i].band = nl80211_band_to_fwil(band);2338 join_pref_params[i].rssi_gain = bss_select->param.adjust.delta;2339 i++;2340 break;2341 case NL80211_BSS_SELECT_ATTR_RSSI:2342 default:2343 break;2344 }2345 join_pref_params[i].type = BRCMF_JOIN_PREF_RSSI;2346 join_pref_params[i].len = 2;2347 join_pref_params[i].rssi_gain = 0;2348 join_pref_params[i].band = 0;2349 err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,2350 sizeof(join_pref_params));2351 if (err)2352 bphy_err(drvr, "Set join_pref error (%d)\n", err);2353}2354 2355static s322356brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,2357 struct cfg80211_connect_params *sme)2358{2359 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);2360 struct brcmf_if *ifp = netdev_priv(ndev);2361 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;2362 struct ieee80211_channel *chan = sme->channel;2363 struct brcmf_pub *drvr = ifp->drvr;2364 struct brcmf_join_params join_params;2365 size_t join_params_size;2366 const struct brcmf_tlv *rsn_ie;2367 const struct brcmf_vs_tlv *wpa_ie;2368 const void *ie;2369 u32 ie_len;2370 struct brcmf_ext_join_params_le *ext_join_params;2371 u16 chanspec;2372 s32 err = 0;2373 u32 ssid_len;2374 2375 brcmf_dbg(TRACE, "Enter\n");2376 if (!check_vif_up(ifp->vif))2377 return -EIO;2378 2379 if (!sme->ssid) {2380 bphy_err(drvr, "Invalid ssid\n");2381 return -EOPNOTSUPP;2382 }2383 2384 if (sme->channel_hint)2385 chan = sme->channel_hint;2386 2387 if (sme->bssid_hint)2388 sme->bssid = sme->bssid_hint;2389 2390 if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) {2391 /* A normal (non P2P) connection request setup. */2392 ie = NULL;2393 ie_len = 0;2394 /* find the WPA_IE */2395 wpa_ie = brcmf_find_wpaie((u8 *)sme->ie, sme->ie_len);2396 if (wpa_ie) {2397 ie = wpa_ie;2398 ie_len = wpa_ie->len + TLV_HDR_LEN;2399 } else {2400 /* find the RSN_IE */2401 rsn_ie = brcmf_parse_tlvs((const u8 *)sme->ie,2402 sme->ie_len,2403 WLAN_EID_RSN);2404 if (rsn_ie) {2405 ie = rsn_ie;2406 ie_len = rsn_ie->len + TLV_HDR_LEN;2407 }2408 }2409 brcmf_fil_iovar_data_set(ifp, "wpaie", ie, ie_len);2410 }2411 2412 err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,2413 sme->ie, sme->ie_len);2414 if (err)2415 bphy_err(drvr, "Set Assoc REQ IE Failed\n");2416 else2417 brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");2418 2419 set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);2420 2421 if (chan) {2422 cfg->channel =2423 ieee80211_frequency_to_channel(chan->center_freq);2424 chanspec = channel_to_chanspec(&cfg->d11inf, chan);2425 brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n",2426 cfg->channel, chan->center_freq, chanspec);2427 } else {2428 cfg->channel = 0;2429 chanspec = 0;2430 }2431 2432 brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);2433 2434 err = brcmf_set_wpa_version(ndev, sme);2435 if (err) {2436 bphy_err(drvr, "wl_set_wpa_version failed (%d)\n", err);2437 goto done;2438 }2439 2440 sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type);2441 err = brcmf_set_auth_type(ndev, sme);2442 if (err) {2443 bphy_err(drvr, "wl_set_auth_type failed (%d)\n", err);2444 goto done;2445 }2446 2447 err = brcmf_set_wsec_mode(ndev, sme);2448 if (err) {2449 bphy_err(drvr, "wl_set_set_cipher failed (%d)\n", err);2450 goto done;2451 }2452 2453 err = brcmf_set_key_mgmt(ndev, sme);2454 if (err) {2455 bphy_err(drvr, "wl_set_key_mgmt failed (%d)\n", err);2456 goto done;2457 }2458 2459 err = brcmf_set_sharedkey(ndev, sme);2460 if (err) {2461 bphy_err(drvr, "brcmf_set_sharedkey failed (%d)\n", err);2462 goto done;2463 }2464 2465 if (sme->crypto.psk &&2466 profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {2467 if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {2468 err = -EINVAL;2469 goto done;2470 }2471 brcmf_dbg(INFO, "using PSK offload\n");2472 profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;2473 }2474 2475 if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {2476 /* enable firmware supplicant for this interface */2477 err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);2478 if (err < 0) {2479 bphy_err(drvr, "failed to enable fw supplicant\n");2480 goto done;2481 }2482 }2483 2484 if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK)2485 err = brcmf_set_pmk(ifp, sme->crypto.psk,2486 BRCMF_WSEC_MAX_PSK_LEN);2487 else if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE) {2488 /* clean up user-space RSNE */2489 err = brcmf_fil_iovar_data_set(ifp, "wpaie", NULL, 0);2490 if (err) {2491 bphy_err(drvr, "failed to clean up user-space RSNE\n");2492 goto done;2493 }2494 err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto);2495 if (!err && sme->crypto.psk)2496 err = brcmf_set_pmk(ifp, sme->crypto.psk,2497 BRCMF_WSEC_MAX_PSK_LEN);2498 }2499 if (err)2500 goto done;2501 2502 /* Join with specific BSSID and cached SSID2503 * If SSID is zero join based on BSSID only2504 */2505 join_params_size = offsetof(struct brcmf_ext_join_params_le, assoc_le) +2506 offsetof(struct brcmf_assoc_params_le, chanspec_list);2507 if (cfg->channel)2508 join_params_size += sizeof(u16);2509 ext_join_params = kzalloc(sizeof(*ext_join_params), GFP_KERNEL);2510 if (ext_join_params == NULL) {2511 err = -ENOMEM;2512 goto done;2513 }2514 ssid_len = min_t(u32, sme->ssid_len, IEEE80211_MAX_SSID_LEN);2515 ext_join_params->ssid_le.SSID_len = cpu_to_le32(ssid_len);2516 memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, ssid_len);2517 if (ssid_len < IEEE80211_MAX_SSID_LEN)2518 brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n",2519 ext_join_params->ssid_le.SSID, ssid_len);2520 2521 /* Set up join scan parameters */2522 ext_join_params->scan_le.scan_type = -1;2523 ext_join_params->scan_le.home_time = cpu_to_le32(-1);2524 2525 if (sme->bssid)2526 memcpy(&ext_join_params->assoc_le.bssid, sme->bssid, ETH_ALEN);2527 else2528 eth_broadcast_addr(ext_join_params->assoc_le.bssid);2529 2530 if (cfg->channel) {2531 ext_join_params->assoc_le.chanspec_num = cpu_to_le32(1);2532 2533 ext_join_params->assoc_le.chanspec_list[0] =2534 cpu_to_le16(chanspec);2535 /* Increase dwell time to receive probe response or detect2536 * beacon from target AP at a noisy air only during connect2537 * command.2538 */2539 ext_join_params->scan_le.active_time =2540 cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS);2541 ext_join_params->scan_le.passive_time =2542 cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS);2543 /* To sync with presence period of VSDB GO send probe request2544 * more frequently. Probe request will be stopped when it gets2545 * probe response from target AP/GO.2546 */2547 ext_join_params->scan_le.nprobes =2548 cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS /2549 BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS);2550 } else {2551 ext_join_params->scan_le.active_time = cpu_to_le32(-1);2552 ext_join_params->scan_le.passive_time = cpu_to_le32(-1);2553 ext_join_params->scan_le.nprobes = cpu_to_le32(-1);2554 }2555 2556 brcmf_set_join_pref(ifp, &sme->bss_select);2557 2558 err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params,2559 join_params_size);2560 kfree(ext_join_params);2561 if (!err)2562 /* This is it. join command worked, we are done */2563 goto done;2564 2565 /* join command failed, fallback to set ssid */2566 memset(&join_params, 0, sizeof(join_params));2567 join_params_size = sizeof(join_params.ssid_le);2568 2569 memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid_len);2570 join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);2571 2572 if (sme->bssid)2573 memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);2574 else2575 eth_broadcast_addr(join_params.params_le.bssid);2576 2577 if (cfg->channel) {2578 join_params.params_le.chanspec_list[0] = cpu_to_le16(chanspec);2579 join_params.params_le.chanspec_num = cpu_to_le32(1);2580 join_params_size += sizeof(join_params.params_le);2581 }2582 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,2583 &join_params, join_params_size);2584 if (err)2585 bphy_err(drvr, "BRCMF_C_SET_SSID failed (%d)\n", err);2586 2587done:2588 if (err)2589 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);2590 brcmf_dbg(TRACE, "Exit\n");2591 return err;2592}2593 2594static s322595brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,2596 u16 reason_code)2597{2598 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);2599 struct brcmf_if *ifp = netdev_priv(ndev);2600 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;2601 struct brcmf_pub *drvr = cfg->pub;2602 struct brcmf_scb_val_le scbval;2603 s32 err = 0;2604 2605 brcmf_dbg(TRACE, "Enter. Reason code = %d\n", reason_code);2606 if (!check_vif_up(ifp->vif))2607 return -EIO;2608 2609 clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);2610 clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);2611 clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &ifp->vif->sme_state);2612 clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &ifp->vif->sme_state);2613 cfg80211_disconnected(ndev, reason_code, NULL, 0, true, GFP_KERNEL);2614 2615 memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);2616 scbval.val = cpu_to_le32(reason_code);2617 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC,2618 &scbval, sizeof(scbval));2619 if (err)2620 bphy_err(drvr, "error (%d)\n", err);2621 2622 brcmf_dbg(TRACE, "Exit\n");2623 return err;2624}2625 2626static s322627brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,2628 enum nl80211_tx_power_setting type, s32 mbm)2629{2630 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);2631 struct net_device *ndev = cfg_to_ndev(cfg);2632 struct brcmf_if *ifp = netdev_priv(ndev);2633 struct brcmf_pub *drvr = cfg->pub;2634 s32 err;2635 s32 disable;2636 u32 qdbm = 127;2637 2638 brcmf_dbg(TRACE, "Enter %d %d\n", type, mbm);2639 if (!check_vif_up(ifp->vif))2640 return -EIO;2641 2642 switch (type) {2643 case NL80211_TX_POWER_AUTOMATIC:2644 break;2645 case NL80211_TX_POWER_LIMITED:2646 case NL80211_TX_POWER_FIXED:2647 if (mbm < 0) {2648 bphy_err(drvr, "TX_POWER_FIXED - dbm is negative\n");2649 err = -EINVAL;2650 goto done;2651 }2652 qdbm = MBM_TO_DBM(4 * mbm);2653 if (qdbm > 127)2654 qdbm = 127;2655 qdbm |= WL_TXPWR_OVERRIDE;2656 break;2657 default:2658 bphy_err(drvr, "Unsupported type %d\n", type);2659 err = -EINVAL;2660 goto done;2661 }2662 /* Make sure radio is off or on as far as software is concerned */2663 disable = WL_RADIO_SW_DISABLE << 16;2664 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable);2665 if (err)2666 bphy_err(drvr, "WLC_SET_RADIO error (%d)\n", err);2667 2668 err = brcmf_fil_iovar_int_set(ifp, "qtxpower", qdbm);2669 if (err)2670 bphy_err(drvr, "qtxpower error (%d)\n", err);2671 2672done:2673 brcmf_dbg(TRACE, "Exit %d (qdbm)\n", qdbm & ~WL_TXPWR_OVERRIDE);2674 return err;2675}2676 2677static s322678brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,2679 s32 *dbm)2680{2681 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);2682 struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);2683 struct brcmf_pub *drvr = cfg->pub;2684 s32 qdbm;2685 s32 err;2686 2687 brcmf_dbg(TRACE, "Enter\n");2688 if (!check_vif_up(vif))2689 return -EIO;2690 2691 err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm);2692 if (err) {2693 bphy_err(drvr, "error (%d)\n", err);2694 goto done;2695 }2696 *dbm = (qdbm & ~WL_TXPWR_OVERRIDE) / 4;2697 2698done:2699 brcmf_dbg(TRACE, "Exit (0x%x %d)\n", qdbm, *dbm);2700 return err;2701}2702 2703static s322704brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,2705 int link_id, u8 key_idx, bool unicast,2706 bool multicast)2707{2708 struct brcmf_if *ifp = netdev_priv(ndev);2709 struct brcmf_pub *drvr = ifp->drvr;2710 u32 index;2711 u32 wsec;2712 s32 err = 0;2713 2714 brcmf_dbg(TRACE, "Enter\n");2715 brcmf_dbg(CONN, "key index (%d)\n", key_idx);2716 if (!check_vif_up(ifp->vif))2717 return -EIO;2718 2719 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);2720 if (err) {2721 bphy_err(drvr, "WLC_GET_WSEC error (%d)\n", err);2722 goto done;2723 }2724 2725 if (wsec & WEP_ENABLED) {2726 /* Just select a new current key */2727 index = key_idx;2728 err = brcmf_fil_cmd_int_set(ifp,2729 BRCMF_C_SET_KEY_PRIMARY, index);2730 if (err)2731 bphy_err(drvr, "error (%d)\n", err);2732 }2733done:2734 brcmf_dbg(TRACE, "Exit\n");2735 return err;2736}2737 2738static s322739brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,2740 int link_id, u8 key_idx, bool pairwise,2741 const u8 *mac_addr)2742{2743 struct brcmf_if *ifp = netdev_priv(ndev);2744 struct brcmf_wsec_key *key;2745 s32 err;2746 2747 brcmf_dbg(TRACE, "Enter\n");2748 brcmf_dbg(CONN, "key index (%d)\n", key_idx);2749 2750 if (!check_vif_up(ifp->vif))2751 return -EIO;2752 2753 if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {2754 /* we ignore this key index in this case */2755 return -EINVAL;2756 }2757 2758 key = &ifp->vif->profile.key[key_idx];2759 2760 if (key->algo == CRYPTO_ALGO_OFF) {2761 brcmf_dbg(CONN, "Ignore clearing of (never configured) key\n");2762 return -EINVAL;2763 }2764 2765 memset(key, 0, sizeof(*key));2766 key->index = (u32)key_idx;2767 key->flags = BRCMF_PRIMARY_KEY;2768 2769 /* Clear the key/index */2770 err = send_key_to_dongle(ifp, key);2771 2772 brcmf_dbg(TRACE, "Exit\n");2773 return err;2774}2775 2776static s322777brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,2778 int link_id, u8 key_idx, bool pairwise,2779 const u8 *mac_addr, struct key_params *params)2780{2781 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);2782 struct brcmf_if *ifp = netdev_priv(ndev);2783 struct brcmf_pub *drvr = cfg->pub;2784 struct brcmf_wsec_key *key;2785 s32 val;2786 s32 wsec;2787 s32 err;2788 u8 keybuf[8];2789 bool ext_key;2790 2791 brcmf_dbg(TRACE, "Enter\n");2792 brcmf_dbg(CONN, "key index (%d)\n", key_idx);2793 if (!check_vif_up(ifp->vif))2794 return -EIO;2795 2796 if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {2797 /* we ignore this key index in this case */2798 bphy_err(drvr, "invalid key index (%d)\n", key_idx);2799 return -EINVAL;2800 }2801 2802 if (params->key_len == 0)2803 return brcmf_cfg80211_del_key(wiphy, ndev, -1, key_idx,2804 pairwise, mac_addr);2805 2806 if (params->key_len > sizeof(key->data)) {2807 bphy_err(drvr, "Too long key length (%u)\n", params->key_len);2808 return -EINVAL;2809 }2810 2811 ext_key = false;2812 if (mac_addr && (params->cipher != WLAN_CIPHER_SUITE_WEP40) &&2813 (params->cipher != WLAN_CIPHER_SUITE_WEP104)) {2814 brcmf_dbg(TRACE, "Ext key, mac %pM", mac_addr);2815 ext_key = true;2816 }2817 2818 key = &ifp->vif->profile.key[key_idx];2819 memset(key, 0, sizeof(*key));2820 if ((ext_key) && (!is_multicast_ether_addr(mac_addr)))2821 memcpy((char *)&key->ea, (void *)mac_addr, ETH_ALEN);2822 key->len = params->key_len;2823 key->index = key_idx;2824 memcpy(key->data, params->key, key->len);2825 if (!ext_key)2826 key->flags = BRCMF_PRIMARY_KEY;2827 2828 if (params->seq && params->seq_len == 6) {2829 /* rx iv */2830 u8 *ivptr;2831 2832 ivptr = (u8 *)params->seq;2833 key->rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |2834 (ivptr[3] << 8) | ivptr[2];2835 key->rxiv.lo = (ivptr[1] << 8) | ivptr[0];2836 key->iv_initialized = true;2837 }2838 2839 switch (params->cipher) {2840 case WLAN_CIPHER_SUITE_WEP40:2841 key->algo = CRYPTO_ALGO_WEP1;2842 val = WEP_ENABLED;2843 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");2844 break;2845 case WLAN_CIPHER_SUITE_WEP104:2846 key->algo = CRYPTO_ALGO_WEP128;2847 val = WEP_ENABLED;2848 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");2849 break;2850 case WLAN_CIPHER_SUITE_TKIP:2851 if (!brcmf_is_apmode(ifp->vif)) {2852 brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");2853 memcpy(keybuf, &key->data[24], sizeof(keybuf));2854 memcpy(&key->data[24], &key->data[16], sizeof(keybuf));2855 memcpy(&key->data[16], keybuf, sizeof(keybuf));2856 }2857 key->algo = CRYPTO_ALGO_TKIP;2858 val = TKIP_ENABLED;2859 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");2860 break;2861 case WLAN_CIPHER_SUITE_AES_CMAC:2862 key->algo = CRYPTO_ALGO_AES_CCM;2863 val = AES_ENABLED;2864 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");2865 break;2866 case WLAN_CIPHER_SUITE_CCMP:2867 key->algo = CRYPTO_ALGO_AES_CCM;2868 val = AES_ENABLED;2869 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");2870 break;2871 default:2872 bphy_err(drvr, "Invalid cipher (0x%x)\n", params->cipher);2873 err = -EINVAL;2874 goto done;2875 }2876 2877 err = send_key_to_dongle(ifp, key);2878 if (ext_key || err)2879 goto done;2880 2881 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);2882 if (err) {2883 bphy_err(drvr, "get wsec error (%d)\n", err);2884 goto done;2885 }2886 wsec |= val;2887 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);2888 if (err) {2889 bphy_err(drvr, "set wsec error (%d)\n", err);2890 goto done;2891 }2892 2893done:2894 brcmf_dbg(TRACE, "Exit\n");2895 return err;2896}2897 2898static s322899brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,2900 int link_id, u8 key_idx, bool pairwise,2901 const u8 *mac_addr, void *cookie,2902 void (*callback)(void *cookie,2903 struct key_params *params))2904{2905 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);2906 struct key_params params;2907 struct brcmf_if *ifp = netdev_priv(ndev);2908 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;2909 struct brcmf_pub *drvr = cfg->pub;2910 struct brcmf_cfg80211_security *sec;2911 s32 wsec;2912 s32 err = 0;2913 2914 brcmf_dbg(TRACE, "Enter\n");2915 brcmf_dbg(CONN, "key index (%d)\n", key_idx);2916 if (!check_vif_up(ifp->vif))2917 return -EIO;2918 2919 memset(¶ms, 0, sizeof(params));2920 2921 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);2922 if (err) {2923 bphy_err(drvr, "WLC_GET_WSEC error (%d)\n", err);2924 /* Ignore this error, may happen during DISASSOC */2925 err = -EAGAIN;2926 goto done;2927 }2928 if (wsec & WEP_ENABLED) {2929 sec = &profile->sec;2930 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {2931 params.cipher = WLAN_CIPHER_SUITE_WEP40;2932 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");2933 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {2934 params.cipher = WLAN_CIPHER_SUITE_WEP104;2935 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");2936 }2937 } else if (wsec & TKIP_ENABLED) {2938 params.cipher = WLAN_CIPHER_SUITE_TKIP;2939 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");2940 } else if (wsec & AES_ENABLED) {2941 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;2942 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");2943 } else {2944 bphy_err(drvr, "Invalid algo (0x%x)\n", wsec);2945 err = -EINVAL;2946 goto done;2947 }2948 callback(cookie, ¶ms);2949 2950done:2951 brcmf_dbg(TRACE, "Exit\n");2952 return err;2953}2954 2955static s322956brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,2957 struct net_device *ndev, int link_id,2958 u8 key_idx)2959{2960 struct brcmf_if *ifp = netdev_priv(ndev);2961 2962 brcmf_dbg(TRACE, "Enter key_idx %d\n", key_idx);2963 2964 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))2965 return 0;2966 2967 brcmf_dbg(INFO, "Not supported\n");2968 2969 return -EOPNOTSUPP;2970}2971 2972static void2973brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)2974{2975 struct brcmf_pub *drvr = ifp->drvr;2976 s32 err;2977 u8 key_idx;2978 struct brcmf_wsec_key *key;2979 s32 wsec;2980 2981 for (key_idx = 0; key_idx < BRCMF_MAX_DEFAULT_KEYS; key_idx++) {2982 key = &ifp->vif->profile.key[key_idx];2983 if ((key->algo == CRYPTO_ALGO_WEP1) ||2984 (key->algo == CRYPTO_ALGO_WEP128))2985 break;2986 }2987 if (key_idx == BRCMF_MAX_DEFAULT_KEYS)2988 return;2989 2990 err = send_key_to_dongle(ifp, key);2991 if (err) {2992 bphy_err(drvr, "Setting WEP key failed (%d)\n", err);2993 return;2994 }2995 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);2996 if (err) {2997 bphy_err(drvr, "get wsec error (%d)\n", err);2998 return;2999 }3000 wsec |= WEP_ENABLED;3001 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);3002 if (err)3003 bphy_err(drvr, "set wsec error (%d)\n", err);3004}3005 3006static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)3007{3008 struct nl80211_sta_flag_update *sfu;3009 3010 brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);3011 si->filled |= BIT_ULL(NL80211_STA_INFO_STA_FLAGS);3012 sfu = &si->sta_flags;3013 sfu->mask = BIT(NL80211_STA_FLAG_WME) |3014 BIT(NL80211_STA_FLAG_AUTHENTICATED) |3015 BIT(NL80211_STA_FLAG_ASSOCIATED) |3016 BIT(NL80211_STA_FLAG_AUTHORIZED);3017 if (fw_sta_flags & BRCMF_STA_WME)3018 sfu->set |= BIT(NL80211_STA_FLAG_WME);3019 if (fw_sta_flags & BRCMF_STA_AUTHE)3020 sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);3021 if (fw_sta_flags & BRCMF_STA_ASSOC)3022 sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);3023 if (fw_sta_flags & BRCMF_STA_AUTHO)3024 sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);3025}3026 3027static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)3028{3029 struct brcmf_pub *drvr = ifp->drvr;3030 struct {3031 __le32 len;3032 struct brcmf_bss_info_le bss_le;3033 } *buf;3034 u16 capability;3035 int err;3036 3037 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);3038 if (!buf)3039 return;3040 3041 buf->len = cpu_to_le32(WL_BSS_INFO_MAX);3042 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,3043 WL_BSS_INFO_MAX);3044 if (err) {3045 bphy_err(drvr, "Failed to get bss info (%d)\n", err);3046 goto out_kfree;3047 }3048 si->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM);3049 si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);3050 si->bss_param.dtim_period = buf->bss_le.dtim_period;3051 capability = le16_to_cpu(buf->bss_le.capability);3052 if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)3053 si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;3054 if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)3055 si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;3056 if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)3057 si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;3058 3059out_kfree:3060 kfree(buf);3061}3062 3063static s323064brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,3065 struct station_info *sinfo)3066{3067 struct brcmf_pub *drvr = ifp->drvr;3068 struct brcmf_scb_val_le scbval;3069 struct brcmf_pktcnt_le pktcnt;3070 s32 err;3071 u32 rate;3072 u32 rssi;3073 3074 /* Get the current tx rate */3075 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);3076 if (err < 0) {3077 bphy_err(drvr, "BRCMF_C_GET_RATE error (%d)\n", err);3078 return err;3079 }3080 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);3081 sinfo->txrate.legacy = rate * 5;3082 3083 memset(&scbval, 0, sizeof(scbval));3084 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scbval,3085 sizeof(scbval));3086 if (err) {3087 bphy_err(drvr, "BRCMF_C_GET_RSSI error (%d)\n", err);3088 return err;3089 }3090 rssi = le32_to_cpu(scbval.val);3091 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);3092 sinfo->signal = rssi;3093 3094 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_GET_PKTCNTS, &pktcnt,3095 sizeof(pktcnt));3096 if (err) {3097 bphy_err(drvr, "BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err);3098 return err;3099 }3100 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS) |3101 BIT_ULL(NL80211_STA_INFO_RX_DROP_MISC) |3102 BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |3103 BIT_ULL(NL80211_STA_INFO_TX_FAILED);3104 sinfo->rx_packets = le32_to_cpu(pktcnt.rx_good_pkt);3105 sinfo->rx_dropped_misc = le32_to_cpu(pktcnt.rx_bad_pkt);3106 sinfo->tx_packets = le32_to_cpu(pktcnt.tx_good_pkt);3107 sinfo->tx_failed = le32_to_cpu(pktcnt.tx_bad_pkt);3108 3109 return 0;3110}3111 3112static s323113brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,3114 const u8 *mac, struct station_info *sinfo)3115{3116 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);3117 struct brcmf_if *ifp = netdev_priv(ndev);3118 struct brcmf_pub *drvr = cfg->pub;3119 struct brcmf_scb_val_le scb_val;3120 s32 err = 0;3121 struct brcmf_sta_info_le sta_info_le;3122 u32 sta_flags;3123 u32 is_tdls_peer;3124 s32 total_rssi_avg = 0;3125 s32 total_rssi = 0;3126 s32 count_rssi = 0;3127 int rssi;3128 u32 i;3129 3130 brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);3131 if (!check_vif_up(ifp->vif))3132 return -EIO;3133 3134 if (brcmf_is_ibssmode(ifp->vif))3135 return brcmf_cfg80211_get_station_ibss(ifp, sinfo);3136 3137 memset(&sta_info_le, 0, sizeof(sta_info_le));3138 memcpy(&sta_info_le, mac, ETH_ALEN);3139 err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",3140 &sta_info_le,3141 sizeof(sta_info_le));3142 is_tdls_peer = !err;3143 if (err) {3144 err = brcmf_fil_iovar_data_get(ifp, "sta_info",3145 &sta_info_le,3146 sizeof(sta_info_le));3147 if (err < 0) {3148 bphy_err(drvr, "GET STA INFO failed, %d\n", err);3149 goto done;3150 }3151 }3152 brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));3153 sinfo->filled = BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);3154 sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;3155 sta_flags = le32_to_cpu(sta_info_le.flags);3156 brcmf_convert_sta_flags(sta_flags, sinfo);3157 sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);3158 if (is_tdls_peer)3159 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);3160 else3161 sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);3162 if (sta_flags & BRCMF_STA_ASSOC) {3163 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CONNECTED_TIME);3164 sinfo->connected_time = le32_to_cpu(sta_info_le.in);3165 brcmf_fill_bss_param(ifp, sinfo);3166 }3167 if (sta_flags & BRCMF_STA_SCBSTATS) {3168 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);3169 sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);3170 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);3171 sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);3172 sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);3173 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_PACKETS);3174 sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);3175 sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);3176 if (sinfo->tx_packets) {3177 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);3178 sinfo->txrate.legacy =3179 le32_to_cpu(sta_info_le.tx_rate) / 100;3180 }3181 if (sinfo->rx_packets) {3182 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE);3183 sinfo->rxrate.legacy =3184 le32_to_cpu(sta_info_le.rx_rate) / 100;3185 }3186 if (le16_to_cpu(sta_info_le.ver) >= 4) {3187 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BYTES);3188 sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);3189 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);3190 sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);3191 }3192 for (i = 0; i < BRCMF_ANT_MAX; i++) {3193 if (sta_info_le.rssi[i] == 0 ||3194 sta_info_le.rx_lastpkt_rssi[i] == 0)3195 continue;3196 sinfo->chains |= BIT(count_rssi);3197 sinfo->chain_signal[count_rssi] =3198 sta_info_le.rx_lastpkt_rssi[i];3199 sinfo->chain_signal_avg[count_rssi] =3200 sta_info_le.rssi[i];3201 total_rssi += sta_info_le.rx_lastpkt_rssi[i];3202 total_rssi_avg += sta_info_le.rssi[i];3203 count_rssi++;3204 }3205 if (count_rssi) {3206 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);3207 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);3208 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);3209 sinfo->filled |=3210 BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);3211 sinfo->signal = total_rssi / count_rssi;3212 sinfo->signal_avg = total_rssi_avg / count_rssi;3213 } else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,3214 &ifp->vif->sme_state)) {3215 memset(&scb_val, 0, sizeof(scb_val));3216 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,3217 &scb_val, sizeof(scb_val));3218 if (err) {3219 bphy_err(drvr, "Could not get rssi (%d)\n",3220 err);3221 goto done;3222 } else {3223 rssi = le32_to_cpu(scb_val.val);3224 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);3225 sinfo->signal = rssi;3226 brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);3227 }3228 }3229 }3230done:3231 brcmf_dbg(TRACE, "Exit\n");3232 return err;3233}3234 3235static int3236brcmf_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *ndev,3237 int idx, u8 *mac, struct station_info *sinfo)3238{3239 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);3240 struct brcmf_if *ifp = netdev_priv(ndev);3241 struct brcmf_pub *drvr = cfg->pub;3242 s32 err;3243 3244 brcmf_dbg(TRACE, "Enter, idx %d\n", idx);3245 3246 if (idx == 0) {3247 cfg->assoclist.count = cpu_to_le32(BRCMF_MAX_ASSOCLIST);3248 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_ASSOCLIST,3249 &cfg->assoclist,3250 sizeof(cfg->assoclist));3251 if (err) {3252 /* GET_ASSOCLIST unsupported by firmware of older chips */3253 if (err == -EBADE)3254 bphy_info_once(drvr, "BRCMF_C_GET_ASSOCLIST unsupported\n");3255 else3256 bphy_err(drvr, "BRCMF_C_GET_ASSOCLIST failed, err=%d\n",3257 err);3258 3259 cfg->assoclist.count = 0;3260 return -EOPNOTSUPP;3261 }3262 }3263 if (idx < le32_to_cpu(cfg->assoclist.count)) {3264 memcpy(mac, cfg->assoclist.mac[idx], ETH_ALEN);3265 return brcmf_cfg80211_get_station(wiphy, ndev, mac, sinfo);3266 }3267 return -ENOENT;3268}3269 3270static s323271brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,3272 bool enabled, s32 timeout)3273{3274 s32 pm;3275 s32 err = 0;3276 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);3277 struct brcmf_if *ifp = netdev_priv(ndev);3278 struct brcmf_pub *drvr = cfg->pub;3279 3280 brcmf_dbg(TRACE, "Enter\n");3281 3282 /*3283 * Powersave enable/disable request is coming from the3284 * cfg80211 even before the interface is up. In that3285 * scenario, driver will be storing the power save3286 * preference in cfg struct to apply this to3287 * FW later while initializing the dongle3288 */3289 cfg->pwr_save = enabled;3290 if (!check_vif_up(ifp->vif)) {3291 3292 brcmf_dbg(INFO, "Device is not ready, storing the value in cfg_info struct\n");3293 goto done;3294 }3295 3296 pm = enabled ? PM_FAST : PM_OFF;3297 /* Do not enable the power save after assoc if it is a p2p interface */3298 if (ifp->vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) {3299 brcmf_dbg(INFO, "Do not enable power save for P2P clients\n");3300 pm = PM_OFF;3301 }3302 brcmf_dbg(INFO, "power save %s\n", (pm ? "enabled" : "disabled"));3303 3304 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm);3305 if (err) {3306 if (err == -ENODEV)3307 bphy_err(drvr, "net_device is not ready yet\n");3308 else3309 bphy_err(drvr, "error (%d)\n", err);3310 }3311 3312 err = brcmf_fil_iovar_int_set(ifp, "pm2_sleep_ret",3313 min_t(u32, timeout, BRCMF_PS_MAX_TIMEOUT_MS));3314 if (err)3315 bphy_err(drvr, "Unable to set pm timeout, (%d)\n", err);3316 3317done:3318 brcmf_dbg(TRACE, "Exit\n");3319 return err;3320}3321 3322static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,3323 struct brcmf_bss_info_le *bi)3324{3325 struct wiphy *wiphy = cfg_to_wiphy(cfg);3326 struct brcmf_pub *drvr = cfg->pub;3327 struct cfg80211_bss *bss;3328 enum nl80211_band band;3329 struct brcmu_chan ch;3330 u16 channel;3331 u32 freq;3332 u16 notify_capability;3333 u16 notify_interval;3334 u8 *notify_ie;3335 size_t notify_ielen;3336 struct cfg80211_inform_bss bss_data = {};3337 3338 if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {3339 bphy_err(drvr, "Bss info is larger than buffer. Discarding\n");3340 return -EINVAL;3341 }3342 3343 if (!bi->ctl_ch) {3344 ch.chspec = le16_to_cpu(bi->chanspec);3345 cfg->d11inf.decchspec(&ch);3346 bi->ctl_ch = ch.control_ch_num;3347 }3348 channel = bi->ctl_ch;3349 3350 if (channel <= CH_MAX_2G_CHANNEL)3351 band = NL80211_BAND_2GHZ;3352 else3353 band = NL80211_BAND_5GHZ;3354 3355 freq = ieee80211_channel_to_frequency(channel, band);3356 bss_data.chan = ieee80211_get_channel(wiphy, freq);3357 bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());3358 3359 notify_capability = le16_to_cpu(bi->capability);3360 notify_interval = le16_to_cpu(bi->beacon_period);3361 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);3362 notify_ielen = le32_to_cpu(bi->ie_length);3363 bss_data.signal = (s16)le16_to_cpu(bi->RSSI) * 100;3364 3365 brcmf_dbg(CONN, "bssid: %pM\n", bi->BSSID);3366 brcmf_dbg(CONN, "Channel: %d(%d)\n", channel, freq);3367 brcmf_dbg(CONN, "Capability: %X\n", notify_capability);3368 brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);3369 brcmf_dbg(CONN, "Signal: %d\n", bss_data.signal);3370 3371 bss = cfg80211_inform_bss_data(wiphy, &bss_data,3372 CFG80211_BSS_FTYPE_UNKNOWN,3373 (const u8 *)bi->BSSID,3374 0, notify_capability,3375 notify_interval, notify_ie,3376 notify_ielen, GFP_KERNEL);3377 3378 if (!bss)3379 return -ENOMEM;3380 3381 cfg80211_put_bss(wiphy, bss);3382 3383 return 0;3384}3385 3386static struct brcmf_bss_info_le *3387next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)3388{3389 if (bss == NULL)3390 return list->bss_info_le;3391 return (struct brcmf_bss_info_le *)((unsigned long)bss +3392 le32_to_cpu(bss->length));3393}3394 3395static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)3396{3397 struct brcmf_pub *drvr = cfg->pub;3398 struct brcmf_scan_results *bss_list;3399 struct brcmf_bss_info_le *bi = NULL; /* must be initialized */3400 s32 err = 0;3401 int i;3402 3403 bss_list = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;3404 if (bss_list->count != 0 &&3405 bss_list->version != BRCMF_BSS_INFO_VERSION) {3406 bphy_err(drvr, "Version %d != WL_BSS_INFO_VERSION\n",3407 bss_list->version);3408 return -EOPNOTSUPP;3409 }3410 brcmf_dbg(SCAN, "scanned AP count (%d)\n", bss_list->count);3411 for (i = 0; i < bss_list->count; i++) {3412 bi = next_bss_le(bss_list, bi);3413 err = brcmf_inform_single_bss(cfg, bi);3414 if (err)3415 break;3416 }3417 return err;3418}3419 3420static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,3421 struct net_device *ndev, const u8 *bssid)3422{3423 struct wiphy *wiphy = cfg_to_wiphy(cfg);3424 struct brcmf_pub *drvr = cfg->pub;3425 struct ieee80211_channel *notify_channel;3426 struct brcmf_bss_info_le *bi = NULL;3427 struct ieee80211_supported_band *band;3428 struct cfg80211_bss *bss;3429 struct brcmu_chan ch;3430 u8 *buf = NULL;3431 s32 err = 0;3432 u32 freq;3433 u16 notify_capability;3434 u16 notify_interval;3435 u8 *notify_ie;3436 size_t notify_ielen;3437 s32 notify_signal;3438 3439 brcmf_dbg(TRACE, "Enter\n");3440 3441 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);3442 if (buf == NULL) {3443 err = -ENOMEM;3444 goto CleanUp;3445 }3446 3447 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);3448 3449 err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO,3450 buf, WL_BSS_INFO_MAX);3451 if (err) {3452 bphy_err(drvr, "WLC_GET_BSS_INFO failed: %d\n", err);3453 goto CleanUp;3454 }3455 3456 bi = (struct brcmf_bss_info_le *)(buf + 4);3457 3458 ch.chspec = le16_to_cpu(bi->chanspec);3459 cfg->d11inf.decchspec(&ch);3460 3461 if (ch.band == BRCMU_CHAN_BAND_2G)3462 band = wiphy->bands[NL80211_BAND_2GHZ];3463 else3464 band = wiphy->bands[NL80211_BAND_5GHZ];3465 3466 freq = ieee80211_channel_to_frequency(ch.control_ch_num, band->band);3467 cfg->channel = freq;3468 notify_channel = ieee80211_get_channel(wiphy, freq);3469 3470 notify_capability = le16_to_cpu(bi->capability);3471 notify_interval = le16_to_cpu(bi->beacon_period);3472 notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);3473 notify_ielen = le32_to_cpu(bi->ie_length);3474 notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;3475 3476 brcmf_dbg(CONN, "channel: %d(%d)\n", ch.control_ch_num, freq);3477 brcmf_dbg(CONN, "capability: %X\n", notify_capability);3478 brcmf_dbg(CONN, "beacon interval: %d\n", notify_interval);3479 brcmf_dbg(CONN, "signal: %d\n", notify_signal);3480 3481 bss = cfg80211_inform_bss(wiphy, notify_channel,3482 CFG80211_BSS_FTYPE_UNKNOWN, bssid, 0,3483 notify_capability, notify_interval,3484 notify_ie, notify_ielen, notify_signal,3485 GFP_KERNEL);3486 3487 if (!bss) {3488 err = -ENOMEM;3489 goto CleanUp;3490 }3491 3492 cfg80211_put_bss(wiphy, bss);3493 3494CleanUp:3495 3496 kfree(buf);3497 3498 brcmf_dbg(TRACE, "Exit\n");3499 3500 return err;3501}3502 3503static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,3504 struct brcmf_if *ifp)3505{3506 struct brcmf_pub *drvr = cfg->pub;3507 struct brcmf_bss_info_le *bi = NULL;3508 s32 err = 0;3509 3510 brcmf_dbg(TRACE, "Enter\n");3511 if (brcmf_is_ibssmode(ifp->vif))3512 return err;3513 3514 *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);3515 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,3516 cfg->extra_buf, WL_EXTRA_BUF_MAX);3517 if (err) {3518 bphy_err(drvr, "Could not get bss info %d\n", err);3519 goto update_bss_info_out;3520 }3521 bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4);3522 err = brcmf_inform_single_bss(cfg, bi);3523 3524update_bss_info_out:3525 brcmf_dbg(TRACE, "Exit");3526 return err;3527}3528 3529void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg)3530{3531 struct escan_info *escan = &cfg->escan_info;3532 3533 set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);3534 if (cfg->int_escan_map || cfg->scan_request) {3535 escan->escan_state = WL_ESCAN_STATE_IDLE;3536 brcmf_notify_escan_complete(cfg, escan->ifp, true, true);3537 }3538 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);3539 clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);3540}3541 3542static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)3543{3544 struct brcmf_cfg80211_info *cfg =3545 container_of(work, struct brcmf_cfg80211_info,3546 escan_timeout_work);3547 3548 brcmf_inform_bss(cfg);3549 brcmf_notify_escan_complete(cfg, cfg->escan_info.ifp, true, true);3550}3551 3552static void brcmf_escan_timeout(struct timer_list *t)3553{3554 struct brcmf_cfg80211_info *cfg =3555 from_timer(cfg, t, escan_timeout);3556 struct brcmf_pub *drvr = cfg->pub;3557 3558 if (cfg->int_escan_map || cfg->scan_request) {3559 bphy_err(drvr, "timer expired\n");3560 schedule_work(&cfg->escan_timeout_work);3561 }3562}3563 3564static s323565brcmf_compare_update_same_bss(struct brcmf_cfg80211_info *cfg,3566 struct brcmf_bss_info_le *bss,3567 struct brcmf_bss_info_le *bss_info_le)3568{3569 struct brcmu_chan ch_bss, ch_bss_info_le;3570 3571 ch_bss.chspec = le16_to_cpu(bss->chanspec);3572 cfg->d11inf.decchspec(&ch_bss);3573 ch_bss_info_le.chspec = le16_to_cpu(bss_info_le->chanspec);3574 cfg->d11inf.decchspec(&ch_bss_info_le);3575 3576 if (!memcmp(&bss_info_le->BSSID, &bss->BSSID, ETH_ALEN) &&3577 ch_bss.band == ch_bss_info_le.band &&3578 bss_info_le->SSID_len == bss->SSID_len &&3579 !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {3580 if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) ==3581 (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL)) {3582 s16 bss_rssi = le16_to_cpu(bss->RSSI);3583 s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);3584 3585 /* preserve max RSSI if the measurements are3586 * both on-channel or both off-channel3587 */3588 if (bss_info_rssi > bss_rssi)3589 bss->RSSI = bss_info_le->RSSI;3590 } else if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) &&3591 (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == 0) {3592 /* preserve the on-channel rssi measurement3593 * if the new measurement is off channel3594 */3595 bss->RSSI = bss_info_le->RSSI;3596 bss->flags |= BRCMF_BSS_RSSI_ON_CHANNEL;3597 }3598 return 1;3599 }3600 return 0;3601}3602 3603static s323604brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,3605 const struct brcmf_event_msg *e, void *data)3606{3607 struct brcmf_pub *drvr = ifp->drvr;3608 struct brcmf_cfg80211_info *cfg = drvr->config;3609 s32 status;3610 struct brcmf_escan_result_le *escan_result_le;3611 u32 escan_buflen;3612 struct brcmf_bss_info_le *bss_info_le;3613 struct brcmf_bss_info_le *bss = NULL;3614 u32 bi_length;3615 struct brcmf_scan_results *list;3616 u32 i;3617 bool aborted;3618 3619 status = e->status;3620 3621 if (status == BRCMF_E_STATUS_ABORT)3622 goto exit;3623 3624 if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {3625 bphy_err(drvr, "scan not ready, bsscfgidx=%d\n",3626 ifp->bsscfgidx);3627 return -EPERM;3628 }3629 3630 if (status == BRCMF_E_STATUS_PARTIAL) {3631 brcmf_dbg(SCAN, "ESCAN Partial result\n");3632 if (e->datalen < sizeof(*escan_result_le)) {3633 bphy_err(drvr, "invalid event data length\n");3634 goto exit;3635 }3636 escan_result_le = (struct brcmf_escan_result_le *) data;3637 if (!escan_result_le) {3638 bphy_err(drvr, "Invalid escan result (NULL pointer)\n");3639 goto exit;3640 }3641 escan_buflen = le32_to_cpu(escan_result_le->buflen);3642 if (escan_buflen > BRCMF_ESCAN_BUF_SIZE ||3643 escan_buflen > e->datalen ||3644 escan_buflen < sizeof(*escan_result_le)) {3645 bphy_err(drvr, "Invalid escan buffer length: %d\n",3646 escan_buflen);3647 goto exit;3648 }3649 if (le16_to_cpu(escan_result_le->bss_count) != 1) {3650 bphy_err(drvr, "Invalid bss_count %d: ignoring\n",3651 escan_result_le->bss_count);3652 goto exit;3653 }3654 bss_info_le = &escan_result_le->bss_info_le;3655 3656 if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le))3657 goto exit;3658 3659 if (!cfg->int_escan_map && !cfg->scan_request) {3660 brcmf_dbg(SCAN, "result without cfg80211 request\n");3661 goto exit;3662 }3663 3664 bi_length = le32_to_cpu(bss_info_le->length);3665 if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) {3666 bphy_err(drvr, "Ignoring invalid bss_info length: %d\n",3667 bi_length);3668 goto exit;3669 }3670 3671 if (!(cfg_to_wiphy(cfg)->interface_modes &3672 BIT(NL80211_IFTYPE_ADHOC))) {3673 if (le16_to_cpu(bss_info_le->capability) &3674 WLAN_CAPABILITY_IBSS) {3675 bphy_err(drvr, "Ignoring IBSS result\n");3676 goto exit;3677 }3678 }3679 3680 list = (struct brcmf_scan_results *)3681 cfg->escan_info.escan_buf;3682 if (bi_length > BRCMF_ESCAN_BUF_SIZE - list->buflen) {3683 bphy_err(drvr, "Buffer is too small: ignoring\n");3684 goto exit;3685 }3686 3687 for (i = 0; i < list->count; i++) {3688 bss = bss ? (struct brcmf_bss_info_le *)3689 ((unsigned char *)bss +3690 le32_to_cpu(bss->length)) : list->bss_info_le;3691 if (brcmf_compare_update_same_bss(cfg, bss,3692 bss_info_le))3693 goto exit;3694 }3695 memcpy(&cfg->escan_info.escan_buf[list->buflen], bss_info_le,3696 bi_length);3697 list->version = le32_to_cpu(bss_info_le->version);3698 list->buflen += bi_length;3699 list->count++;3700 } else {3701 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;3702 if (brcmf_p2p_scan_finding_common_channel(cfg, NULL))3703 goto exit;3704 if (cfg->int_escan_map || cfg->scan_request) {3705 brcmf_inform_bss(cfg);3706 aborted = status != BRCMF_E_STATUS_SUCCESS;3707 brcmf_notify_escan_complete(cfg, ifp, aborted, false);3708 } else3709 brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n",3710 status);3711 }3712exit:3713 return 0;3714}3715 3716static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg)3717{3718 brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT,3719 brcmf_cfg80211_escan_handler);3720 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;3721 /* Init scan_timeout timer */3722 timer_setup(&cfg->escan_timeout, brcmf_escan_timeout, 0);3723 INIT_WORK(&cfg->escan_timeout_work,3724 brcmf_cfg80211_escan_timeout_worker);3725}3726 3727static struct cfg80211_scan_request *3728brcmf_alloc_internal_escan_request(struct wiphy *wiphy, u32 n_netinfo) {3729 struct cfg80211_scan_request *req;3730 size_t req_size;3731 3732 req_size = sizeof(*req) +3733 n_netinfo * sizeof(req->channels[0]) +3734 n_netinfo * sizeof(*req->ssids);3735 3736 req = kzalloc(req_size, GFP_KERNEL);3737 if (req) {3738 req->wiphy = wiphy;3739 req->ssids = (void *)(&req->channels[0]) +3740 n_netinfo * sizeof(req->channels[0]);3741 }3742 return req;3743}3744 3745static int brcmf_internal_escan_add_info(struct cfg80211_scan_request *req,3746 u8 *ssid, u8 ssid_len, u8 channel)3747{3748 struct ieee80211_channel *chan;3749 enum nl80211_band band;3750 int freq, i;3751 3752 if (channel <= CH_MAX_2G_CHANNEL)3753 band = NL80211_BAND_2GHZ;3754 else3755 band = NL80211_BAND_5GHZ;3756 3757 freq = ieee80211_channel_to_frequency(channel, band);3758 if (!freq)3759 return -EINVAL;3760 3761 chan = ieee80211_get_channel(req->wiphy, freq);3762 if (!chan)3763 return -EINVAL;3764 3765 for (i = 0; i < req->n_channels; i++) {3766 if (req->channels[i] == chan)3767 break;3768 }3769 if (i == req->n_channels) {3770 req->n_channels++;3771 req->channels[i] = chan;3772 }3773 3774 for (i = 0; i < req->n_ssids; i++) {3775 if (req->ssids[i].ssid_len == ssid_len &&3776 !memcmp(req->ssids[i].ssid, ssid, ssid_len))3777 break;3778 }3779 if (i == req->n_ssids) {3780 memcpy(req->ssids[req->n_ssids].ssid, ssid, ssid_len);3781 req->ssids[req->n_ssids++].ssid_len = ssid_len;3782 }3783 return 0;3784}3785 3786static int brcmf_start_internal_escan(struct brcmf_if *ifp, u32 fwmap,3787 struct cfg80211_scan_request *request)3788{3789 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;3790 int err;3791 3792 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {3793 if (cfg->int_escan_map)3794 brcmf_dbg(SCAN, "aborting internal scan: map=%u\n",3795 cfg->int_escan_map);3796 /* Abort any on-going scan */3797 brcmf_abort_scanning(cfg);3798 }3799 3800 brcmf_dbg(SCAN, "start internal scan: map=%u\n", fwmap);3801 set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);3802 cfg->escan_info.run = brcmf_run_escan;3803 err = brcmf_do_escan(ifp, request);3804 if (err) {3805 clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);3806 return err;3807 }3808 cfg->int_escan_map = fwmap;3809 return 0;3810}3811 3812static struct brcmf_pno_net_info_le *3813brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)3814{3815 struct brcmf_pno_scanresults_v2_le *pfn_v2;3816 struct brcmf_pno_net_info_le *netinfo;3817 3818 switch (pfn_v1->version) {3819 default:3820 WARN_ON(1);3821 fallthrough;3822 case cpu_to_le32(1):3823 netinfo = (struct brcmf_pno_net_info_le *)(pfn_v1 + 1);3824 break;3825 case cpu_to_le32(2):3826 pfn_v2 = (struct brcmf_pno_scanresults_v2_le *)pfn_v1;3827 netinfo = (struct brcmf_pno_net_info_le *)(pfn_v2 + 1);3828 break;3829 }3830 3831 return netinfo;3832}3833 3834/* PFN result doesn't have all the info which are required by the supplicant3835 * (For e.g IEs) Do a target Escan so that sched scan results are reported3836 * via wl_inform_single_bss in the required format. Escan does require the3837 * scan request in the form of cfg80211_scan_request. For timebeing, create3838 * cfg80211_scan_request one out of the received PNO event.3839 */3840static s323841brcmf_notify_sched_scan_results(struct brcmf_if *ifp,3842 const struct brcmf_event_msg *e, void *data)3843{3844 struct brcmf_pub *drvr = ifp->drvr;3845 struct brcmf_cfg80211_info *cfg = drvr->config;3846 struct brcmf_pno_net_info_le *netinfo, *netinfo_start;3847 struct cfg80211_scan_request *request = NULL;3848 struct wiphy *wiphy = cfg_to_wiphy(cfg);3849 int i, err = 0;3850 struct brcmf_pno_scanresults_le *pfn_result;3851 u32 bucket_map;3852 u32 result_count;3853 u32 status;3854 u32 datalen;3855 3856 brcmf_dbg(SCAN, "Enter\n");3857 3858 if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {3859 brcmf_dbg(SCAN, "Event data to small. Ignore\n");3860 return 0;3861 }3862 3863 if (e->event_code == BRCMF_E_PFN_NET_LOST) {3864 brcmf_dbg(SCAN, "PFN NET LOST event. Do Nothing\n");3865 return 0;3866 }3867 3868 pfn_result = (struct brcmf_pno_scanresults_le *)data;3869 result_count = le32_to_cpu(pfn_result->count);3870 status = le32_to_cpu(pfn_result->status);3871 3872 /* PFN event is limited to fit 512 bytes so we may get3873 * multiple NET_FOUND events. For now place a warning here.3874 */3875 WARN_ON(status != BRCMF_PNO_SCAN_COMPLETE);3876 brcmf_dbg(SCAN, "PFN NET FOUND event. count: %d\n", result_count);3877 if (!result_count) {3878 bphy_err(drvr, "FALSE PNO Event. (pfn_count == 0)\n");3879 goto out_err;3880 }3881 3882 netinfo_start = brcmf_get_netinfo_array(pfn_result);3883 datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result);3884 if (datalen < result_count * sizeof(*netinfo)) {3885 bphy_err(drvr, "insufficient event data\n");3886 goto out_err;3887 }3888 3889 request = brcmf_alloc_internal_escan_request(wiphy,3890 result_count);3891 if (!request) {3892 err = -ENOMEM;3893 goto out_err;3894 }3895 3896 bucket_map = 0;3897 for (i = 0; i < result_count; i++) {3898 netinfo = &netinfo_start[i];3899 3900 if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)3901 netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;3902 brcmf_dbg(SCAN, "SSID:%.32s Channel:%d\n",3903 netinfo->SSID, netinfo->channel);3904 bucket_map |= brcmf_pno_get_bucket_map(cfg->pno, netinfo);3905 err = brcmf_internal_escan_add_info(request,3906 netinfo->SSID,3907 netinfo->SSID_len,3908 netinfo->channel);3909 if (err)3910 goto out_err;3911 }3912 3913 if (!bucket_map)3914 goto free_req;3915 3916 err = brcmf_start_internal_escan(ifp, bucket_map, request);3917 if (!err)3918 goto free_req;3919 3920out_err:3921 cfg80211_sched_scan_stopped(wiphy, 0);3922free_req:3923 kfree(request);3924 return err;3925}3926 3927static int3928brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,3929 struct net_device *ndev,3930 struct cfg80211_sched_scan_request *req)3931{3932 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);3933 struct brcmf_if *ifp = netdev_priv(ndev);3934 struct brcmf_pub *drvr = cfg->pub;3935 3936 brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",3937 req->n_match_sets, req->n_ssids);3938 3939 if (test_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status)) {3940 bphy_err(drvr, "Scanning suppressed: status=%lu\n",3941 cfg->scan_status);3942 return -EAGAIN;3943 }3944 3945 if (req->n_match_sets <= 0) {3946 brcmf_dbg(SCAN, "invalid number of matchsets specified: %d\n",3947 req->n_match_sets);3948 return -EINVAL;3949 }3950 3951 return brcmf_pno_start_sched_scan(ifp, req);3952}3953 3954static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,3955 struct net_device *ndev, u64 reqid)3956{3957 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);3958 struct brcmf_if *ifp = netdev_priv(ndev);3959 3960 brcmf_dbg(SCAN, "enter\n");3961 brcmf_pno_stop_sched_scan(ifp, reqid);3962 if (cfg->int_escan_map)3963 brcmf_notify_escan_complete(cfg, ifp, true, true);3964 return 0;3965}3966 3967static __always_inline void brcmf_delay(u32 ms)3968{3969 if (ms < 1000 / HZ) {3970 cond_resched();3971 mdelay(ms);3972 } else {3973 msleep(ms);3974 }3975}3976 3977static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],3978 u8 *pattern, u32 patternsize, u8 *mask,3979 u32 packet_offset)3980{3981 struct brcmf_fil_wowl_pattern_le *filter;3982 u32 masksize;3983 u32 patternoffset;3984 u8 *buf;3985 u32 bufsize;3986 s32 ret;3987 3988 masksize = (patternsize + 7) / 8;3989 patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize;3990 3991 bufsize = sizeof(*filter) + patternsize + masksize;3992 buf = kzalloc(bufsize, GFP_KERNEL);3993 if (!buf)3994 return -ENOMEM;3995 filter = (struct brcmf_fil_wowl_pattern_le *)buf;3996 3997 memcpy(filter->cmd, cmd, 4);3998 filter->masksize = cpu_to_le32(masksize);3999 filter->offset = cpu_to_le32(packet_offset);4000 filter->patternoffset = cpu_to_le32(patternoffset);4001 filter->patternsize = cpu_to_le32(patternsize);4002 filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP);4003 4004 if ((mask) && (masksize))4005 memcpy(buf + sizeof(*filter), mask, masksize);4006 if ((pattern) && (patternsize))4007 memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize);4008 4009 ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize);4010 4011 kfree(buf);4012 return ret;4013}4014 4015static s324016brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,4017 void *data)4018{4019 struct brcmf_pub *drvr = ifp->drvr;4020 struct brcmf_cfg80211_info *cfg = drvr->config;4021 struct brcmf_pno_scanresults_le *pfn_result;4022 struct brcmf_pno_net_info_le *netinfo;4023 4024 brcmf_dbg(SCAN, "Enter\n");4025 4026 if (e->datalen < (sizeof(*pfn_result) + sizeof(*netinfo))) {4027 brcmf_dbg(SCAN, "Event data to small. Ignore\n");4028 return 0;4029 }4030 4031 pfn_result = (struct brcmf_pno_scanresults_le *)data;4032 4033 if (e->event_code == BRCMF_E_PFN_NET_LOST) {4034 brcmf_dbg(SCAN, "PFN NET LOST event. Ignore\n");4035 return 0;4036 }4037 4038 if (le32_to_cpu(pfn_result->count) < 1) {4039 bphy_err(drvr, "Invalid result count, expected 1 (%d)\n",4040 le32_to_cpu(pfn_result->count));4041 return -EINVAL;4042 }4043 4044 netinfo = brcmf_get_netinfo_array(pfn_result);4045 if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)4046 netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;4047 memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);4048 cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;4049 cfg->wowl.nd->n_channels = 1;4050 cfg->wowl.nd->channels[0] =4051 ieee80211_channel_to_frequency(netinfo->channel,4052 netinfo->channel <= CH_MAX_2G_CHANNEL ?4053 NL80211_BAND_2GHZ : NL80211_BAND_5GHZ);4054 cfg->wowl.nd_info->n_matches = 1;4055 cfg->wowl.nd_info->matches[0] = cfg->wowl.nd;4056 4057 /* Inform (the resume task) that the net detect information was recvd */4058 cfg->wowl.nd_data_completed = true;4059 wake_up(&cfg->wowl.nd_data_wait);4060 4061 return 0;4062}4063 4064#ifdef CONFIG_PM4065 4066static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)4067{4068 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);4069 struct brcmf_pub *drvr = cfg->pub;4070 struct brcmf_wowl_wakeind_le wake_ind_le;4071 struct cfg80211_wowlan_wakeup wakeup_data;4072 struct cfg80211_wowlan_wakeup *wakeup;4073 u32 wakeind;4074 s32 err;4075 long time_left;4076 4077 err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le,4078 sizeof(wake_ind_le));4079 if (err) {4080 bphy_err(drvr, "Get wowl_wakeind failed, err = %d\n", err);4081 return;4082 }4083 4084 wakeind = le32_to_cpu(wake_ind_le.ucode_wakeind);4085 if (wakeind & (BRCMF_WOWL_MAGIC | BRCMF_WOWL_DIS | BRCMF_WOWL_BCN |4086 BRCMF_WOWL_RETR | BRCMF_WOWL_NET |4087 BRCMF_WOWL_PFN_FOUND)) {4088 wakeup = &wakeup_data;4089 memset(&wakeup_data, 0, sizeof(wakeup_data));4090 wakeup_data.pattern_idx = -1;4091 4092 if (wakeind & BRCMF_WOWL_MAGIC) {4093 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_MAGIC\n");4094 wakeup_data.magic_pkt = true;4095 }4096 if (wakeind & BRCMF_WOWL_DIS) {4097 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_DIS\n");4098 wakeup_data.disconnect = true;4099 }4100 if (wakeind & BRCMF_WOWL_BCN) {4101 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_BCN\n");4102 wakeup_data.disconnect = true;4103 }4104 if (wakeind & BRCMF_WOWL_RETR) {4105 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_RETR\n");4106 wakeup_data.disconnect = true;4107 }4108 if (wakeind & BRCMF_WOWL_NET) {4109 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_NET\n");4110 /* For now always map to pattern 0, no API to get4111 * correct information available at the moment.4112 */4113 wakeup_data.pattern_idx = 0;4114 }4115 if (wakeind & BRCMF_WOWL_PFN_FOUND) {4116 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_PFN_FOUND\n");4117 time_left = wait_event_timeout(cfg->wowl.nd_data_wait,4118 cfg->wowl.nd_data_completed,4119 BRCMF_ND_INFO_TIMEOUT);4120 if (!time_left)4121 bphy_err(drvr, "No result for wowl net detect\n");4122 else4123 wakeup_data.net_detect = cfg->wowl.nd_info;4124 }4125 if (wakeind & BRCMF_WOWL_GTK_FAILURE) {4126 brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_GTK_FAILURE\n");4127 wakeup_data.gtk_rekey_failure = true;4128 }4129 } else {4130 wakeup = NULL;4131 }4132 cfg80211_report_wowlan_wakeup(&ifp->vif->wdev, wakeup, GFP_KERNEL);4133}4134 4135#else4136 4137static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)4138{4139}4140 4141#endif /* CONFIG_PM */4142 4143static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)4144{4145 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);4146 struct net_device *ndev = cfg_to_ndev(cfg);4147 struct brcmf_if *ifp = netdev_priv(ndev);4148 4149 brcmf_dbg(TRACE, "Enter\n");4150 4151 if (cfg->wowl.active) {4152 brcmf_report_wowl_wakeind(wiphy, ifp);4153 brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);4154 brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);4155 if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND))4156 brcmf_configure_arp_nd_offload(ifp, true);4157 brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,4158 cfg->wowl.pre_pmmode);4159 cfg->wowl.active = false;4160 if (cfg->wowl.nd_enabled) {4161 brcmf_cfg80211_sched_scan_stop(cfg->wiphy, ifp->ndev, 0);4162 brcmf_fweh_unregister(cfg->pub, BRCMF_E_PFN_NET_FOUND);4163 brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,4164 brcmf_notify_sched_scan_results);4165 cfg->wowl.nd_enabled = false;4166 }4167 }4168 return 0;4169}4170 4171static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,4172 struct brcmf_if *ifp,4173 struct cfg80211_wowlan *wowl)4174{4175 u32 wowl_config;4176 struct brcmf_wowl_wakeind_le wowl_wakeind;4177 u32 i;4178 4179 brcmf_dbg(TRACE, "Suspend, wowl config.\n");4180 4181 if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ARP_ND))4182 brcmf_configure_arp_nd_offload(ifp, false);4183 brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->wowl.pre_pmmode);4184 brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);4185 4186 wowl_config = 0;4187 if (wowl->disconnect)4188 wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR;4189 if (wowl->magic_pkt)4190 wowl_config |= BRCMF_WOWL_MAGIC;4191 if ((wowl->patterns) && (wowl->n_patterns)) {4192 wowl_config |= BRCMF_WOWL_NET;4193 for (i = 0; i < wowl->n_patterns; i++) {4194 brcmf_config_wowl_pattern(ifp, "add",4195 (u8 *)wowl->patterns[i].pattern,4196 wowl->patterns[i].pattern_len,4197 (u8 *)wowl->patterns[i].mask,4198 wowl->patterns[i].pkt_offset);4199 }4200 }4201 if (wowl->nd_config) {4202 brcmf_cfg80211_sched_scan_start(cfg->wiphy, ifp->ndev,4203 wowl->nd_config);4204 wowl_config |= BRCMF_WOWL_PFN_FOUND;4205 4206 cfg->wowl.nd_data_completed = false;4207 cfg->wowl.nd_enabled = true;4208 /* Now reroute the event for PFN to the wowl function. */4209 brcmf_fweh_unregister(cfg->pub, BRCMF_E_PFN_NET_FOUND);4210 brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,4211 brcmf_wowl_nd_results);4212 }4213 if (wowl->gtk_rekey_failure)4214 wowl_config |= BRCMF_WOWL_GTK_FAILURE;4215 if (!test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))4216 wowl_config |= BRCMF_WOWL_UNASSOC;4217 4218 memcpy(&wowl_wakeind, "clear", 6);4219 brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", &wowl_wakeind,4220 sizeof(wowl_wakeind));4221 brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);4222 brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);4223 brcmf_bus_wowl_config(cfg->pub->bus_if, true);4224 cfg->wowl.active = true;4225}4226 4227static int brcmf_keepalive_start(struct brcmf_if *ifp, unsigned int interval)4228{4229 struct brcmf_mkeep_alive_pkt_le kalive = {0};4230 int ret = 0;4231 4232 /* Configure Null function/data keepalive */4233 kalive.version = cpu_to_le16(1);4234 kalive.period_msec = cpu_to_le32(interval * MSEC_PER_SEC);4235 kalive.len_bytes = cpu_to_le16(0);4236 kalive.keep_alive_id = 0;4237 4238 ret = brcmf_fil_iovar_data_set(ifp, "mkeep_alive", &kalive, sizeof(kalive));4239 if (ret)4240 brcmf_err("keep-alive packet config failed, ret=%d\n", ret);4241 4242 return ret;4243}4244 4245static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,4246 struct cfg80211_wowlan *wowl)4247{4248 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);4249 struct net_device *ndev = cfg_to_ndev(cfg);4250 struct brcmf_if *ifp = netdev_priv(ndev);4251 struct brcmf_cfg80211_vif *vif;4252 4253 brcmf_dbg(TRACE, "Enter\n");4254 4255 /* if the primary net_device is not READY there is nothing4256 * we can do but pray resume goes smoothly.4257 */4258 if (!check_vif_up(ifp->vif))4259 goto exit;4260 4261 /* Stop scheduled scan */4262 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO))4263 brcmf_cfg80211_sched_scan_stop(wiphy, ndev, 0);4264 4265 /* end any scanning */4266 if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))4267 brcmf_abort_scanning(cfg);4268 4269 if (wowl == NULL) {4270 brcmf_bus_wowl_config(cfg->pub->bus_if, false);4271 list_for_each_entry(vif, &cfg->vif_list, list) {4272 if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state))4273 continue;4274 /* While going to suspend if associated with AP4275 * disassociate from AP to save power while system is4276 * in suspended state4277 */4278 brcmf_link_down(vif, WLAN_REASON_UNSPECIFIED, true);4279 /* Make sure WPA_Supplicant receives all the event4280 * generated due to DISASSOC call to the fw to keep4281 * the state fw and WPA_Supplicant state consistent4282 */4283 brcmf_delay(500);4284 }4285 /* Configure MPC */4286 brcmf_set_mpc(ifp, 1);4287 4288 } else {4289 /* Configure WOWL paramaters */4290 brcmf_configure_wowl(cfg, ifp, wowl);4291 4292 /* Prevent disassociation due to inactivity with keep-alive */4293 brcmf_keepalive_start(ifp, 30);4294 }4295 4296exit:4297 brcmf_dbg(TRACE, "Exit\n");4298 /* clear any scanning activity */4299 cfg->scan_status = 0;4300 return 0;4301}4302 4303static s324304brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,4305 bool alive)4306{4307 struct brcmf_pmk_op_v3_le *pmk_op;4308 int length = offsetof(struct brcmf_pmk_op_v3_le, pmk);4309 int ret;4310 4311 pmk_op = kzalloc(sizeof(*pmk_op), GFP_KERNEL);4312 if (!pmk_op)4313 return -ENOMEM;4314 4315 pmk_op->version = cpu_to_le16(BRCMF_PMKSA_VER_3);4316 4317 if (!pmksa) {4318 /* Flush operation, operate on entire list */4319 pmk_op->count = cpu_to_le16(0);4320 } else {4321 /* Single PMK operation */4322 pmk_op->count = cpu_to_le16(1);4323 length += sizeof(struct brcmf_pmksa_v3);4324 if (pmksa->bssid)4325 memcpy(pmk_op->pmk[0].bssid, pmksa->bssid, ETH_ALEN);4326 if (pmksa->pmkid) {4327 memcpy(pmk_op->pmk[0].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);4328 pmk_op->pmk[0].pmkid_len = WLAN_PMKID_LEN;4329 }4330 if (pmksa->ssid && pmksa->ssid_len) {4331 memcpy(pmk_op->pmk[0].ssid.SSID, pmksa->ssid, pmksa->ssid_len);4332 pmk_op->pmk[0].ssid.SSID_len = pmksa->ssid_len;4333 }4334 pmk_op->pmk[0].time_left = cpu_to_le32(alive ? BRCMF_PMKSA_NO_EXPIRY : 0);4335 }4336 4337 pmk_op->length = cpu_to_le16(length);4338 4339 ret = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_op, sizeof(*pmk_op));4340 kfree(pmk_op);4341 return ret;4342}4343 4344static __used s324345brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)4346{4347 struct brcmf_pmk_list_le *pmk_list;4348 int i;4349 u32 npmk;4350 4351 pmk_list = &cfg->pmk_list;4352 npmk = le32_to_cpu(pmk_list->npmk);4353 4354 brcmf_dbg(CONN, "No of elements %d\n", npmk);4355 for (i = 0; i < npmk; i++)4356 brcmf_dbg(CONN, "PMK[%d]: %pM\n", i, &pmk_list->pmk[i].bssid);4357 4358 return brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_list,4359 sizeof(*pmk_list));4360}4361 4362static s324363brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,4364 struct cfg80211_pmksa *pmksa)4365{4366 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);4367 struct brcmf_if *ifp = netdev_priv(ndev);4368 struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];4369 struct brcmf_pub *drvr = cfg->pub;4370 s32 err;4371 u32 npmk, i;4372 4373 brcmf_dbg(TRACE, "Enter\n");4374 if (!check_vif_up(ifp->vif))4375 return -EIO;4376 4377 brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmksa->bssid);4378 brcmf_dbg(CONN, "%*ph\n", WLAN_PMKID_LEN, pmksa->pmkid);4379 4380 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))4381 return brcmf_pmksa_v3_op(ifp, pmksa, true);4382 4383 /* TODO: implement PMKID_V2 */4384 4385 npmk = le32_to_cpu(cfg->pmk_list.npmk);4386 for (i = 0; i < npmk; i++)4387 if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))4388 break;4389 if (i < BRCMF_MAXPMKID) {4390 memcpy(pmk[i].bssid, pmksa->bssid, ETH_ALEN);4391 memcpy(pmk[i].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);4392 if (i == npmk) {4393 npmk++;4394 cfg->pmk_list.npmk = cpu_to_le32(npmk);4395 }4396 } else {4397 bphy_err(drvr, "Too many PMKSA entries cached %d\n", npmk);4398 return -EINVAL;4399 }4400 4401 err = brcmf_update_pmklist(cfg, ifp);4402 4403 brcmf_dbg(TRACE, "Exit\n");4404 return err;4405}4406 4407static s324408brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,4409 struct cfg80211_pmksa *pmksa)4410{4411 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);4412 struct brcmf_if *ifp = netdev_priv(ndev);4413 struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];4414 struct brcmf_pub *drvr = cfg->pub;4415 s32 err;4416 u32 npmk, i;4417 4418 brcmf_dbg(TRACE, "Enter\n");4419 if (!check_vif_up(ifp->vif))4420 return -EIO;4421 4422 brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", pmksa->bssid);4423 4424 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))4425 return brcmf_pmksa_v3_op(ifp, pmksa, false);4426 4427 /* TODO: implement PMKID_V2 */4428 4429 npmk = le32_to_cpu(cfg->pmk_list.npmk);4430 for (i = 0; i < npmk; i++)4431 if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))4432 break;4433 4434 if ((npmk > 0) && (i < npmk)) {4435 for (; i < (npmk - 1); i++) {4436 memcpy(&pmk[i].bssid, &pmk[i + 1].bssid, ETH_ALEN);4437 memcpy(&pmk[i].pmkid, &pmk[i + 1].pmkid,4438 WLAN_PMKID_LEN);4439 }4440 memset(&pmk[i], 0, sizeof(*pmk));4441 cfg->pmk_list.npmk = cpu_to_le32(npmk - 1);4442 } else {4443 bphy_err(drvr, "Cache entry not found\n");4444 return -EINVAL;4445 }4446 4447 err = brcmf_update_pmklist(cfg, ifp);4448 4449 brcmf_dbg(TRACE, "Exit\n");4450 return err;4451 4452}4453 4454static s324455brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)4456{4457 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);4458 struct brcmf_if *ifp = netdev_priv(ndev);4459 s32 err;4460 4461 brcmf_dbg(TRACE, "Enter\n");4462 if (!check_vif_up(ifp->vif))4463 return -EIO;4464 4465 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))4466 return brcmf_pmksa_v3_op(ifp, NULL, false);4467 4468 /* TODO: implement PMKID_V2 */4469 4470 memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));4471 err = brcmf_update_pmklist(cfg, ifp);4472 4473 brcmf_dbg(TRACE, "Exit\n");4474 return err;4475 4476}4477 4478static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp)4479{4480 struct brcmf_pub *drvr = ifp->drvr;4481 s32 err;4482 s32 wpa_val;4483 4484 /* set auth */4485 err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0);4486 if (err < 0) {4487 bphy_err(drvr, "auth error %d\n", err);4488 return err;4489 }4490 /* set wsec */4491 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0);4492 if (err < 0) {4493 bphy_err(drvr, "wsec error %d\n", err);4494 return err;4495 }4496 /* set upper-layer auth */4497 if (brcmf_is_ibssmode(ifp->vif))4498 wpa_val = WPA_AUTH_NONE;4499 else4500 wpa_val = WPA_AUTH_DISABLED;4501 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_val);4502 if (err < 0) {4503 bphy_err(drvr, "wpa_auth error %d\n", err);4504 return err;4505 }4506 4507 return 0;4508}4509 4510static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie)4511{4512 if (is_rsn_ie)4513 return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0);4514 4515 return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0);4516}4517 4518static s324519brcmf_configure_wpaie(struct brcmf_if *ifp,4520 const struct brcmf_vs_tlv *wpa_ie,4521 bool is_rsn_ie)4522{4523 struct brcmf_pub *drvr = ifp->drvr;4524 u32 auth = 0; /* d11 open authentication */4525 u16 count;4526 s32 err = 0;4527 s32 len;4528 u32 i;4529 u32 wsec;4530 u32 pval = 0;4531 u32 gval = 0;4532 u32 wpa_auth = 0;4533 u32 offset;4534 u8 *data;4535 u16 rsn_cap;4536 u32 wme_bss_disable;4537 u32 mfp;4538 4539 brcmf_dbg(TRACE, "Enter\n");4540 if (wpa_ie == NULL)4541 goto exit;4542 4543 len = wpa_ie->len + TLV_HDR_LEN;4544 data = (u8 *)wpa_ie;4545 offset = TLV_HDR_LEN;4546 if (!is_rsn_ie)4547 offset += VS_IE_FIXED_HDR_LEN;4548 else4549 offset += WPA_IE_VERSION_LEN;4550 4551 /* check for multicast cipher suite */4552 if (offset + WPA_IE_MIN_OUI_LEN > len) {4553 err = -EINVAL;4554 bphy_err(drvr, "no multicast cipher suite\n");4555 goto exit;4556 }4557 4558 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {4559 err = -EINVAL;4560 bphy_err(drvr, "invalid OUI\n");4561 goto exit;4562 }4563 offset += TLV_OUI_LEN;4564 4565 /* pick up multicast cipher */4566 switch (data[offset]) {4567 case WPA_CIPHER_NONE:4568 gval = 0;4569 break;4570 case WPA_CIPHER_WEP_40:4571 case WPA_CIPHER_WEP_104:4572 gval = WEP_ENABLED;4573 break;4574 case WPA_CIPHER_TKIP:4575 gval = TKIP_ENABLED;4576 break;4577 case WPA_CIPHER_AES_CCM:4578 gval = AES_ENABLED;4579 break;4580 default:4581 err = -EINVAL;4582 bphy_err(drvr, "Invalid multi cast cipher info\n");4583 goto exit;4584 }4585 4586 offset++;4587 /* walk thru unicast cipher list and pick up what we recognize */4588 count = data[offset] + (data[offset + 1] << 8);4589 offset += WPA_IE_SUITE_COUNT_LEN;4590 /* Check for unicast suite(s) */4591 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {4592 err = -EINVAL;4593 bphy_err(drvr, "no unicast cipher suite\n");4594 goto exit;4595 }4596 for (i = 0; i < count; i++) {4597 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {4598 err = -EINVAL;4599 bphy_err(drvr, "invalid OUI\n");4600 goto exit;4601 }4602 offset += TLV_OUI_LEN;4603 switch (data[offset]) {4604 case WPA_CIPHER_NONE:4605 break;4606 case WPA_CIPHER_WEP_40:4607 case WPA_CIPHER_WEP_104:4608 pval |= WEP_ENABLED;4609 break;4610 case WPA_CIPHER_TKIP:4611 pval |= TKIP_ENABLED;4612 break;4613 case WPA_CIPHER_AES_CCM:4614 pval |= AES_ENABLED;4615 break;4616 default:4617 bphy_err(drvr, "Invalid unicast security info\n");4618 }4619 offset++;4620 }4621 /* walk thru auth management suite list and pick up what we recognize */4622 count = data[offset] + (data[offset + 1] << 8);4623 offset += WPA_IE_SUITE_COUNT_LEN;4624 /* Check for auth key management suite(s) */4625 if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) {4626 err = -EINVAL;4627 bphy_err(drvr, "no auth key mgmt suite\n");4628 goto exit;4629 }4630 for (i = 0; i < count; i++) {4631 if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) {4632 err = -EINVAL;4633 bphy_err(drvr, "invalid OUI\n");4634 goto exit;4635 }4636 offset += TLV_OUI_LEN;4637 switch (data[offset]) {4638 case RSN_AKM_NONE:4639 brcmf_dbg(TRACE, "RSN_AKM_NONE\n");4640 wpa_auth |= WPA_AUTH_NONE;4641 break;4642 case RSN_AKM_UNSPECIFIED:4643 brcmf_dbg(TRACE, "RSN_AKM_UNSPECIFIED\n");4644 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) :4645 (wpa_auth |= WPA_AUTH_UNSPECIFIED);4646 break;4647 case RSN_AKM_PSK:4648 brcmf_dbg(TRACE, "RSN_AKM_PSK\n");4649 is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) :4650 (wpa_auth |= WPA_AUTH_PSK);4651 break;4652 case RSN_AKM_SHA256_PSK:4653 brcmf_dbg(TRACE, "RSN_AKM_MFP_PSK\n");4654 wpa_auth |= WPA2_AUTH_PSK_SHA256;4655 break;4656 case RSN_AKM_SHA256_1X:4657 brcmf_dbg(TRACE, "RSN_AKM_MFP_1X\n");4658 wpa_auth |= WPA2_AUTH_1X_SHA256;4659 break;4660 case RSN_AKM_SAE:4661 brcmf_dbg(TRACE, "RSN_AKM_SAE\n");4662 wpa_auth |= WPA3_AUTH_SAE_PSK;4663 break;4664 default:4665 bphy_err(drvr, "Invalid key mgmt info\n");4666 }4667 offset++;4668 }4669 4670 mfp = BRCMF_MFP_NONE;4671 if (is_rsn_ie) {4672 wme_bss_disable = 1;4673 if ((offset + RSN_CAP_LEN) <= len) {4674 rsn_cap = data[offset] + (data[offset + 1] << 8);4675 if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK)4676 wme_bss_disable = 0;4677 if (rsn_cap & RSN_CAP_MFPR_MASK) {4678 brcmf_dbg(TRACE, "MFP Required\n");4679 mfp = BRCMF_MFP_REQUIRED;4680 /* Firmware only supports mfp required in4681 * combination with WPA2_AUTH_PSK_SHA256,4682 * WPA2_AUTH_1X_SHA256, or WPA3_AUTH_SAE_PSK.4683 */4684 if (!(wpa_auth & (WPA2_AUTH_PSK_SHA256 |4685 WPA2_AUTH_1X_SHA256 |4686 WPA3_AUTH_SAE_PSK))) {4687 err = -EINVAL;4688 goto exit;4689 }4690 /* Firmware has requirement that WPA2_AUTH_PSK/4691 * WPA2_AUTH_UNSPECIFIED be set, if SHA256 OUI4692 * is to be included in the rsn ie.4693 */4694 if (wpa_auth & WPA2_AUTH_PSK_SHA256)4695 wpa_auth |= WPA2_AUTH_PSK;4696 else if (wpa_auth & WPA2_AUTH_1X_SHA256)4697 wpa_auth |= WPA2_AUTH_UNSPECIFIED;4698 } else if (rsn_cap & RSN_CAP_MFPC_MASK) {4699 brcmf_dbg(TRACE, "MFP Capable\n");4700 mfp = BRCMF_MFP_CAPABLE;4701 }4702 }4703 offset += RSN_CAP_LEN;4704 /* set wme_bss_disable to sync RSN Capabilities */4705 err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable",4706 wme_bss_disable);4707 if (err < 0) {4708 bphy_err(drvr, "wme_bss_disable error %d\n", err);4709 goto exit;4710 }4711 4712 /* Skip PMKID cnt as it is know to be 0 for AP. */4713 offset += RSN_PMKID_COUNT_LEN;4714 4715 /* See if there is BIP wpa suite left for MFP */4716 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP) &&4717 ((offset + WPA_IE_MIN_OUI_LEN) <= len)) {4718 err = brcmf_fil_bsscfg_data_set(ifp, "bip",4719 &data[offset],4720 WPA_IE_MIN_OUI_LEN);4721 if (err < 0) {4722 bphy_err(drvr, "bip error %d\n", err);4723 goto exit;4724 }4725 }4726 }4727 /* FOR WPS , set SES_OW_ENABLED */4728 wsec = (pval | gval | SES_OW_ENABLED);4729 4730 /* set auth */4731 err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth);4732 if (err < 0) {4733 bphy_err(drvr, "auth error %d\n", err);4734 goto exit;4735 }4736 /* set wsec */4737 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);4738 if (err < 0) {4739 bphy_err(drvr, "wsec error %d\n", err);4740 goto exit;4741 }4742 /* Configure MFP, this needs to go after wsec otherwise the wsec command4743 * will overwrite the values set by MFP4744 */4745 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP)) {4746 err = brcmf_fil_bsscfg_int_set(ifp, "mfp", mfp);4747 if (err < 0) {4748 bphy_err(drvr, "mfp error %d\n", err);4749 goto exit;4750 }4751 }4752 /* set upper-layer auth */4753 err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth);4754 if (err < 0) {4755 bphy_err(drvr, "wpa_auth error %d\n", err);4756 goto exit;4757 }4758 4759exit:4760 return err;4761}4762 4763static s324764brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len,4765 struct parsed_vndr_ies *vndr_ies)4766{4767 struct brcmf_vs_tlv *vndrie;4768 struct brcmf_tlv *ie;4769 struct parsed_vndr_ie_info *parsed_info;4770 s32 remaining_len;4771 4772 remaining_len = (s32)vndr_ie_len;4773 memset(vndr_ies, 0, sizeof(*vndr_ies));4774 4775 ie = (struct brcmf_tlv *)vndr_ie_buf;4776 while (ie) {4777 if (ie->id != WLAN_EID_VENDOR_SPECIFIC)4778 goto next;4779 vndrie = (struct brcmf_vs_tlv *)ie;4780 /* len should be bigger than OUI length + one */4781 if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) {4782 brcmf_err("invalid vndr ie. length is too small %d\n",4783 vndrie->len);4784 goto next;4785 }4786 /* if wpa or wme ie, do not add ie */4787 if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) &&4788 ((vndrie->oui_type == WPA_OUI_TYPE) ||4789 (vndrie->oui_type == WME_OUI_TYPE))) {4790 brcmf_dbg(TRACE, "Found WPA/WME oui. Do not add it\n");4791 goto next;4792 }4793 4794 parsed_info = &vndr_ies->ie_info[vndr_ies->count];4795 4796 /* save vndr ie information */4797 parsed_info->ie_ptr = (char *)vndrie;4798 parsed_info->ie_len = vndrie->len + TLV_HDR_LEN;4799 memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie));4800 4801 vndr_ies->count++;4802 4803 brcmf_dbg(TRACE, "** OUI %3ph, type 0x%02x\n",4804 parsed_info->vndrie.oui,4805 parsed_info->vndrie.oui_type);4806 4807 if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT)4808 break;4809next:4810 remaining_len -= (ie->len + TLV_HDR_LEN);4811 if (remaining_len <= TLV_HDR_LEN)4812 ie = NULL;4813 else4814 ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len +4815 TLV_HDR_LEN);4816 }4817 return 0;4818}4819 4820static u324821brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)4822{4823 strscpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN);4824 4825 put_unaligned_le32(1, &iebuf[VNDR_IE_COUNT_OFFSET]);4826 4827 put_unaligned_le32(pktflag, &iebuf[VNDR_IE_PKTFLAG_OFFSET]);4828 4829 memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);4830 4831 return ie_len + VNDR_IE_HDR_SIZE;4832}4833 4834s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,4835 const u8 *vndr_ie_buf, u32 vndr_ie_len)4836{4837 struct brcmf_pub *drvr;4838 struct brcmf_if *ifp;4839 struct vif_saved_ie *saved_ie;4840 s32 err = 0;4841 u8 *iovar_ie_buf;4842 u8 *curr_ie_buf;4843 u8 *mgmt_ie_buf = NULL;4844 int mgmt_ie_buf_len;4845 u32 *mgmt_ie_len;4846 u32 del_add_ie_buf_len = 0;4847 u32 total_ie_buf_len = 0;4848 u32 parsed_ie_buf_len = 0;4849 struct parsed_vndr_ies old_vndr_ies;4850 struct parsed_vndr_ies new_vndr_ies;4851 struct parsed_vndr_ie_info *vndrie_info;4852 s32 i;4853 u8 *ptr;4854 int remained_buf_len;4855 4856 if (!vif)4857 return -ENODEV;4858 ifp = vif->ifp;4859 drvr = ifp->drvr;4860 saved_ie = &vif->saved_ie;4861 4862 brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx,4863 pktflag);4864 iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);4865 if (!iovar_ie_buf)4866 return -ENOMEM;4867 curr_ie_buf = iovar_ie_buf;4868 switch (pktflag) {4869 case BRCMF_VNDR_IE_PRBREQ_FLAG:4870 mgmt_ie_buf = saved_ie->probe_req_ie;4871 mgmt_ie_len = &saved_ie->probe_req_ie_len;4872 mgmt_ie_buf_len = sizeof(saved_ie->probe_req_ie);4873 break;4874 case BRCMF_VNDR_IE_PRBRSP_FLAG:4875 mgmt_ie_buf = saved_ie->probe_res_ie;4876 mgmt_ie_len = &saved_ie->probe_res_ie_len;4877 mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie);4878 break;4879 case BRCMF_VNDR_IE_BEACON_FLAG:4880 mgmt_ie_buf = saved_ie->beacon_ie;4881 mgmt_ie_len = &saved_ie->beacon_ie_len;4882 mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie);4883 break;4884 case BRCMF_VNDR_IE_ASSOCREQ_FLAG:4885 mgmt_ie_buf = saved_ie->assoc_req_ie;4886 mgmt_ie_len = &saved_ie->assoc_req_ie_len;4887 mgmt_ie_buf_len = sizeof(saved_ie->assoc_req_ie);4888 break;4889 case BRCMF_VNDR_IE_ASSOCRSP_FLAG:4890 mgmt_ie_buf = saved_ie->assoc_res_ie;4891 mgmt_ie_len = &saved_ie->assoc_res_ie_len;4892 mgmt_ie_buf_len = sizeof(saved_ie->assoc_res_ie);4893 break;4894 default:4895 err = -EPERM;4896 bphy_err(drvr, "not suitable type\n");4897 goto exit;4898 }4899 4900 if (vndr_ie_len > mgmt_ie_buf_len) {4901 err = -ENOMEM;4902 bphy_err(drvr, "extra IE size too big\n");4903 goto exit;4904 }4905 4906 /* parse and save new vndr_ie in curr_ie_buff before comparing it */4907 if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) {4908 ptr = curr_ie_buf;4909 brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies);4910 for (i = 0; i < new_vndr_ies.count; i++) {4911 vndrie_info = &new_vndr_ies.ie_info[i];4912 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,4913 vndrie_info->ie_len);4914 parsed_ie_buf_len += vndrie_info->ie_len;4915 }4916 }4917 4918 if (mgmt_ie_buf && *mgmt_ie_len) {4919 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&4920 (memcmp(mgmt_ie_buf, curr_ie_buf,4921 parsed_ie_buf_len) == 0)) {4922 brcmf_dbg(TRACE, "Previous mgmt IE equals to current IE\n");4923 goto exit;4924 }4925 4926 /* parse old vndr_ie */4927 brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies);4928 4929 /* make a command to delete old ie */4930 for (i = 0; i < old_vndr_ies.count; i++) {4931 vndrie_info = &old_vndr_ies.ie_info[i];4932 4933 brcmf_dbg(TRACE, "DEL ID : %d, Len: %d , OUI:%3ph\n",4934 vndrie_info->vndrie.id,4935 vndrie_info->vndrie.len,4936 vndrie_info->vndrie.oui);4937 4938 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,4939 vndrie_info->ie_ptr,4940 vndrie_info->ie_len,4941 "del");4942 curr_ie_buf += del_add_ie_buf_len;4943 total_ie_buf_len += del_add_ie_buf_len;4944 }4945 }4946 4947 *mgmt_ie_len = 0;4948 /* Add if there is any extra IE */4949 if (mgmt_ie_buf && parsed_ie_buf_len) {4950 ptr = mgmt_ie_buf;4951 4952 remained_buf_len = mgmt_ie_buf_len;4953 4954 /* make a command to add new ie */4955 for (i = 0; i < new_vndr_ies.count; i++) {4956 vndrie_info = &new_vndr_ies.ie_info[i];4957 4958 /* verify remained buf size before copy data */4959 if (remained_buf_len < (vndrie_info->vndrie.len +4960 VNDR_IE_VSIE_OFFSET)) {4961 bphy_err(drvr, "no space in mgmt_ie_buf: len left %d",4962 remained_buf_len);4963 break;4964 }4965 remained_buf_len -= (vndrie_info->ie_len +4966 VNDR_IE_VSIE_OFFSET);4967 4968 brcmf_dbg(TRACE, "ADDED ID : %d, Len: %d, OUI:%3ph\n",4969 vndrie_info->vndrie.id,4970 vndrie_info->vndrie.len,4971 vndrie_info->vndrie.oui);4972 4973 del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag,4974 vndrie_info->ie_ptr,4975 vndrie_info->ie_len,4976 "add");4977 4978 /* save the parsed IE in wl struct */4979 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,4980 vndrie_info->ie_len);4981 *mgmt_ie_len += vndrie_info->ie_len;4982 4983 curr_ie_buf += del_add_ie_buf_len;4984 total_ie_buf_len += del_add_ie_buf_len;4985 }4986 }4987 if (total_ie_buf_len) {4988 err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf,4989 total_ie_buf_len);4990 if (err)4991 bphy_err(drvr, "vndr ie set error : %d\n", err);4992 }4993 4994exit:4995 kfree(iovar_ie_buf);4996 return err;4997}4998 4999s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)5000{5001 static const s32 pktflags[] = {5002 BRCMF_VNDR_IE_PRBREQ_FLAG,5003 BRCMF_VNDR_IE_PRBRSP_FLAG,5004 BRCMF_VNDR_IE_BEACON_FLAG5005 };5006 int i;5007 5008 for (i = 0; i < ARRAY_SIZE(pktflags); i++)5009 brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);5010 5011 memset(&vif->saved_ie, 0, sizeof(vif->saved_ie));5012 return 0;5013}5014 5015static s325016brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,5017 struct cfg80211_beacon_data *beacon)5018{5019 struct brcmf_pub *drvr = vif->ifp->drvr;5020 s32 err;5021 5022 /* Set Beacon IEs to FW */5023 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG,5024 beacon->tail, beacon->tail_len);5025 if (err) {5026 bphy_err(drvr, "Set Beacon IE Failed\n");5027 return err;5028 }5029 brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n");5030 5031 /* Set Probe Response IEs to FW */5032 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBRSP_FLAG,5033 beacon->proberesp_ies,5034 beacon->proberesp_ies_len);5035 if (err)5036 bphy_err(drvr, "Set Probe Resp IE Failed\n");5037 else5038 brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n");5039 5040 /* Set Assoc Response IEs to FW */5041 err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_ASSOCRSP_FLAG,5042 beacon->assocresp_ies,5043 beacon->assocresp_ies_len);5044 if (err)5045 brcmf_err("Set Assoc Resp IE Failed\n");5046 else5047 brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc Resp\n");5048 5049 return err;5050}5051 5052static s325053brcmf_parse_configure_security(struct brcmf_if *ifp,5054 struct cfg80211_ap_settings *settings,5055 enum nl80211_iftype dev_role)5056{5057 const struct brcmf_tlv *rsn_ie;5058 const struct brcmf_vs_tlv *wpa_ie;5059 s32 err = 0;5060 5061 /* find the RSN_IE */5062 rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,5063 settings->beacon.tail_len, WLAN_EID_RSN);5064 5065 /* find the WPA_IE */5066 wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,5067 settings->beacon.tail_len);5068 5069 if (wpa_ie || rsn_ie) {5070 brcmf_dbg(TRACE, "WPA(2) IE is found\n");5071 if (wpa_ie) {5072 /* WPA IE */5073 err = brcmf_configure_wpaie(ifp, wpa_ie, false);5074 if (err < 0)5075 return err;5076 } else {5077 struct brcmf_vs_tlv *tmp_ie;5078 5079 tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;5080 5081 /* RSN IE */5082 err = brcmf_configure_wpaie(ifp, tmp_ie, true);5083 if (err < 0)5084 return err;5085 }5086 } else {5087 brcmf_dbg(TRACE, "No WPA(2) IEs found\n");5088 brcmf_configure_opensecurity(ifp);5089 }5090 5091 return err;5092}5093 5094static s325095brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,5096 struct cfg80211_ap_settings *settings)5097{5098 s32 ie_offset;5099 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5100 struct brcmf_if *ifp = netdev_priv(ndev);5101 struct brcmf_pub *drvr = cfg->pub;5102 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;5103 struct cfg80211_crypto_settings *crypto = &settings->crypto;5104 const struct brcmf_tlv *ssid_ie;5105 const struct brcmf_tlv *country_ie;5106 struct brcmf_ssid_le ssid_le;5107 s32 err = -EPERM;5108 struct brcmf_join_params join_params;5109 enum nl80211_iftype dev_role;5110 struct brcmf_fil_bss_enable_le bss_enable;5111 u16 chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);5112 bool mbss;5113 int is_11d;5114 bool supports_11d;5115 bool closednet;5116 5117 brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",5118 settings->chandef.chan->hw_value,5119 settings->chandef.center_freq1, settings->chandef.width,5120 settings->beacon_interval, settings->dtim_period);5121 brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",5122 settings->ssid, settings->ssid_len, settings->auth_type,5123 settings->inactivity_timeout);5124 dev_role = ifp->vif->wdev.iftype;5125 mbss = ifp->vif->mbss;5126 5127 /* store current 11d setting */5128 if (brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY,5129 &ifp->vif->is_11d)) {5130 is_11d = supports_11d = false;5131 } else {5132 country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,5133 settings->beacon.tail_len,5134 WLAN_EID_COUNTRY);5135 is_11d = country_ie ? 1 : 0;5136 supports_11d = true;5137 }5138 5139 memset(&ssid_le, 0, sizeof(ssid_le));5140 if (settings->ssid == NULL || settings->ssid_len == 0) {5141 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;5142 ssid_ie = brcmf_parse_tlvs(5143 (u8 *)&settings->beacon.head[ie_offset],5144 settings->beacon.head_len - ie_offset,5145 WLAN_EID_SSID);5146 if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN)5147 return -EINVAL;5148 5149 memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len);5150 ssid_le.SSID_len = cpu_to_le32(ssid_ie->len);5151 brcmf_dbg(TRACE, "SSID is (%s) in Head\n", ssid_le.SSID);5152 } else {5153 memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len);5154 ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);5155 }5156 5157 if (!mbss) {5158 brcmf_set_mpc(ifp, 0);5159 brcmf_configure_arp_nd_offload(ifp, false);5160 }5161 5162 /* Parameters shared by all radio interfaces */5163 if (!mbss) {5164 if ((supports_11d) && (is_11d != ifp->vif->is_11d)) {5165 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,5166 is_11d);5167 if (err < 0) {5168 bphy_err(drvr, "Regulatory Set Error, %d\n",5169 err);5170 goto exit;5171 }5172 }5173 if (settings->beacon_interval) {5174 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,5175 settings->beacon_interval);5176 if (err < 0) {5177 bphy_err(drvr, "Beacon Interval Set Error, %d\n",5178 err);5179 goto exit;5180 }5181 }5182 if (settings->dtim_period) {5183 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,5184 settings->dtim_period);5185 if (err < 0) {5186 bphy_err(drvr, "DTIM Interval Set Error, %d\n",5187 err);5188 goto exit;5189 }5190 }5191 5192 if ((dev_role == NL80211_IFTYPE_AP) &&5193 ((ifp->ifidx == 0) ||5194 (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB) &&5195 !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)))) {5196 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);5197 if (err < 0) {5198 bphy_err(drvr, "BRCMF_C_DOWN error %d\n",5199 err);5200 goto exit;5201 }5202 brcmf_fil_iovar_int_set(ifp, "apsta", 0);5203 }5204 5205 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);5206 if (err < 0) {5207 bphy_err(drvr, "SET INFRA error %d\n", err);5208 goto exit;5209 }5210 } else if (WARN_ON(supports_11d && (is_11d != ifp->vif->is_11d))) {5211 /* Multiple-BSS should use same 11d configuration */5212 err = -EINVAL;5213 goto exit;5214 }5215 5216 /* Interface specific setup */5217 if (dev_role == NL80211_IFTYPE_AP) {5218 if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))5219 brcmf_fil_iovar_int_set(ifp, "mbss", 1);5220 5221 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);5222 if (err < 0) {5223 bphy_err(drvr, "setting AP mode failed %d\n",5224 err);5225 goto exit;5226 }5227 if (!mbss) {5228 /* Firmware 10.x requires setting channel after enabling5229 * AP and before bringing interface up.5230 */5231 err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);5232 if (err < 0) {5233 bphy_err(drvr, "Set Channel failed: chspec=%d, %d\n",5234 chanspec, err);5235 goto exit;5236 }5237 }5238 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);5239 if (err < 0) {5240 bphy_err(drvr, "BRCMF_C_UP error (%d)\n", err);5241 goto exit;5242 }5243 5244 if (crypto->psk) {5245 brcmf_dbg(INFO, "using PSK offload\n");5246 profile->use_fwauth |= BIT(BRCMF_PROFILE_FWAUTH_PSK);5247 err = brcmf_set_pmk(ifp, crypto->psk,5248 BRCMF_WSEC_MAX_PSK_LEN);5249 if (err < 0)5250 goto exit;5251 }5252 if (crypto->sae_pwd) {5253 brcmf_dbg(INFO, "using SAE offload\n");5254 profile->use_fwauth |= BIT(BRCMF_PROFILE_FWAUTH_SAE);5255 err = brcmf_fwvid_set_sae_password(ifp, crypto);5256 if (err < 0)5257 goto exit;5258 }5259 if (profile->use_fwauth == 0)5260 profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);5261 5262 err = brcmf_parse_configure_security(ifp, settings,5263 NL80211_IFTYPE_AP);5264 if (err < 0) {5265 bphy_err(drvr, "brcmf_parse_configure_security error\n");5266 goto exit;5267 }5268 5269 /* On DOWN the firmware removes the WEP keys, reconfigure5270 * them if they were set.5271 */5272 brcmf_cfg80211_reconfigure_wep(ifp);5273 5274 memset(&join_params, 0, sizeof(join_params));5275 /* join parameters starts with ssid */5276 memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le));5277 /* create softap */5278 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,5279 &join_params, sizeof(join_params));5280 if (err < 0) {5281 bphy_err(drvr, "SET SSID error (%d)\n", err);5282 goto exit;5283 }5284 5285 closednet =5286 (settings->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);5287 err = brcmf_fil_iovar_int_set(ifp, "closednet", closednet);5288 if (err) {5289 bphy_err(drvr, "%s closednet error (%d)\n",5290 (closednet ? "enabled" : "disabled"),5291 err);5292 goto exit;5293 }5294 5295 brcmf_dbg(TRACE, "AP mode configuration complete\n");5296 } else if (dev_role == NL80211_IFTYPE_P2P_GO) {5297 err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);5298 if (err < 0) {5299 bphy_err(drvr, "Set Channel failed: chspec=%d, %d\n",5300 chanspec, err);5301 goto exit;5302 }5303 5304 err = brcmf_parse_configure_security(ifp, settings,5305 NL80211_IFTYPE_P2P_GO);5306 if (err < 0) {5307 brcmf_err("brcmf_parse_configure_security error\n");5308 goto exit;5309 }5310 5311 err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,5312 sizeof(ssid_le));5313 if (err < 0) {5314 bphy_err(drvr, "setting ssid failed %d\n", err);5315 goto exit;5316 }5317 bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);5318 bss_enable.enable = cpu_to_le32(1);5319 err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,5320 sizeof(bss_enable));5321 if (err < 0) {5322 bphy_err(drvr, "bss_enable config failed %d\n", err);5323 goto exit;5324 }5325 5326 brcmf_dbg(TRACE, "GO mode configuration complete\n");5327 } else {5328 WARN_ON(1);5329 }5330 5331 brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);5332 set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);5333 brcmf_net_setcarrier(ifp, true);5334 5335exit:5336 if ((err) && (!mbss)) {5337 brcmf_set_mpc(ifp, 1);5338 brcmf_configure_arp_nd_offload(ifp, true);5339 }5340 return err;5341}5342 5343static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev,5344 unsigned int link_id)5345{5346 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5347 struct brcmf_if *ifp = netdev_priv(ndev);5348 struct brcmf_pub *drvr = cfg->pub;5349 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;5350 s32 err;5351 struct brcmf_fil_bss_enable_le bss_enable;5352 struct brcmf_join_params join_params;5353 5354 brcmf_dbg(TRACE, "Enter\n");5355 5356 if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) {5357 /* Due to most likely deauths outstanding we sleep */5358 /* first to make sure they get processed by fw. */5359 msleep(400);5360 5361 if (profile->use_fwauth != BIT(BRCMF_PROFILE_FWAUTH_NONE)) {5362 struct cfg80211_crypto_settings crypto = {};5363 5364 if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_PSK))5365 brcmf_set_pmk(ifp, NULL, 0);5366 if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_SAE))5367 brcmf_fwvid_set_sae_password(ifp, &crypto);5368 profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);5369 }5370 5371 if (ifp->vif->mbss) {5372 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);5373 return err;5374 }5375 5376 /* First BSS doesn't get a full reset */5377 if (ifp->bsscfgidx == 0)5378 brcmf_fil_iovar_int_set(ifp, "closednet", 0);5379 5380 memset(&join_params, 0, sizeof(join_params));5381 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,5382 &join_params, sizeof(join_params));5383 if (err < 0)5384 bphy_err(drvr, "SET SSID error (%d)\n", err);5385 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);5386 if (err < 0)5387 bphy_err(drvr, "BRCMF_C_DOWN error %d\n", err);5388 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);5389 if (err < 0)5390 bphy_err(drvr, "setting AP mode failed %d\n", err);5391 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))5392 brcmf_fil_iovar_int_set(ifp, "mbss", 0);5393 brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,5394 ifp->vif->is_11d);5395 /* Bring device back up so it can be used again */5396 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);5397 if (err < 0)5398 bphy_err(drvr, "BRCMF_C_UP error %d\n", err);5399 5400 brcmf_vif_clear_mgmt_ies(ifp->vif);5401 } else {5402 bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);5403 bss_enable.enable = cpu_to_le32(0);5404 err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,5405 sizeof(bss_enable));5406 if (err < 0)5407 bphy_err(drvr, "bss_enable config failed %d\n", err);5408 }5409 brcmf_set_mpc(ifp, 1);5410 brcmf_configure_arp_nd_offload(ifp, true);5411 clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);5412 brcmf_net_setcarrier(ifp, false);5413 5414 return err;5415}5416 5417static s325418brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,5419 struct cfg80211_ap_update *info)5420{5421 struct brcmf_if *ifp = netdev_priv(ndev);5422 5423 brcmf_dbg(TRACE, "Enter\n");5424 5425 return brcmf_config_ap_mgmt_ie(ifp->vif, &info->beacon);5426}5427 5428static int5429brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,5430 struct station_del_parameters *params)5431{5432 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5433 struct brcmf_pub *drvr = cfg->pub;5434 struct brcmf_scb_val_le scbval;5435 struct brcmf_if *ifp = netdev_priv(ndev);5436 s32 err;5437 5438 if (!params->mac)5439 return -EFAULT;5440 5441 brcmf_dbg(TRACE, "Enter %pM\n", params->mac);5442 5443 if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)5444 ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;5445 if (!check_vif_up(ifp->vif))5446 return -EIO;5447 5448 memcpy(&scbval.ea, params->mac, ETH_ALEN);5449 scbval.val = cpu_to_le32(params->reason_code);5450 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,5451 &scbval, sizeof(scbval));5452 if (err)5453 bphy_err(drvr, "SCB_DEAUTHENTICATE_FOR_REASON failed %d\n",5454 err);5455 5456 brcmf_dbg(TRACE, "Exit\n");5457 return err;5458}5459 5460static int5461brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,5462 const u8 *mac, struct station_parameters *params)5463{5464 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5465 struct brcmf_pub *drvr = cfg->pub;5466 struct brcmf_if *ifp = netdev_priv(ndev);5467 s32 err;5468 5469 brcmf_dbg(TRACE, "Enter, MAC %pM, mask 0x%04x set 0x%04x\n", mac,5470 params->sta_flags_mask, params->sta_flags_set);5471 5472 /* Ignore all 00 MAC */5473 if (is_zero_ether_addr(mac))5474 return 0;5475 5476 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))5477 return 0;5478 5479 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))5480 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_AUTHORIZE,5481 (void *)mac, ETH_ALEN);5482 else5483 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE,5484 (void *)mac, ETH_ALEN);5485 if (err < 0)5486 bphy_err(drvr, "Setting SCB (de-)authorize failed, %d\n", err);5487 5488 return err;5489}5490 5491static void5492brcmf_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,5493 struct wireless_dev *wdev,5494 struct mgmt_frame_regs *upd)5495{5496 struct brcmf_cfg80211_vif *vif;5497 5498 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);5499 5500 vif->mgmt_rx_reg = upd->interface_stypes;5501}5502 5503 5504static int5505brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,5506 struct cfg80211_mgmt_tx_params *params, u64 *cookie)5507{5508 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5509 struct ieee80211_channel *chan = params->chan;5510 struct brcmf_pub *drvr = cfg->pub;5511 const u8 *buf = params->buf;5512 size_t len = params->len;5513 const struct ieee80211_mgmt *mgmt;5514 struct brcmf_cfg80211_vif *vif;5515 s32 err = 0;5516 s32 ie_offset;5517 s32 ie_len;5518 struct brcmf_fil_action_frame_le *action_frame;5519 struct brcmf_fil_af_params_le *af_params;5520 bool ack;5521 s32 chan_nr;5522 u32 freq;5523 5524 brcmf_dbg(TRACE, "Enter\n");5525 5526 *cookie = 0;5527 5528 mgmt = (const struct ieee80211_mgmt *)buf;5529 5530 if (!ieee80211_is_mgmt(mgmt->frame_control)) {5531 bphy_err(drvr, "Driver only allows MGMT packet type\n");5532 return -EPERM;5533 }5534 5535 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);5536 5537 if (ieee80211_is_probe_resp(mgmt->frame_control)) {5538 /* Right now the only reason to get a probe response */5539 /* is for p2p listen response or for p2p GO from */5540 /* wpa_supplicant. Unfortunately the probe is send */5541 /* on primary ndev, while dongle wants it on the p2p */5542 /* vif. Since this is only reason for a probe */5543 /* response to be sent, the vif is taken from cfg. */5544 /* If ever desired to send proberesp for non p2p */5545 /* response then data should be checked for */5546 /* "DIRECT-". Note in future supplicant will take */5547 /* dedicated p2p wdev to do this and then this 'hack'*/5548 /* is not needed anymore. */5549 ie_offset = DOT11_MGMT_HDR_LEN +5550 DOT11_BCN_PRB_FIXED_LEN;5551 ie_len = len - ie_offset;5552 if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif)5553 vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;5554 err = brcmf_vif_set_mgmt_ie(vif,5555 BRCMF_VNDR_IE_PRBRSP_FLAG,5556 &buf[ie_offset],5557 ie_len);5558 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,5559 GFP_KERNEL);5560 } else if (ieee80211_is_action(mgmt->frame_control)) {5561 if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {5562 bphy_err(drvr, "invalid action frame length\n");5563 err = -EINVAL;5564 goto exit;5565 }5566 af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);5567 if (af_params == NULL) {5568 bphy_err(drvr, "unable to allocate frame\n");5569 err = -ENOMEM;5570 goto exit;5571 }5572 action_frame = &af_params->action_frame;5573 /* Add the packet Id */5574 action_frame->packet_id = cpu_to_le32(*cookie);5575 /* Add BSSID */5576 memcpy(&action_frame->da[0], &mgmt->da[0], ETH_ALEN);5577 memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN);5578 /* Add the length exepted for 802.11 header */5579 action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);5580 /* Add the channel. Use the one specified as parameter if any or5581 * the current one (got from the firmware) otherwise5582 */5583 if (chan)5584 freq = chan->center_freq;5585 else5586 brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL,5587 &freq);5588 chan_nr = ieee80211_frequency_to_channel(freq);5589 af_params->channel = cpu_to_le32(chan_nr);5590 af_params->dwell_time = cpu_to_le32(params->wait);5591 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN],5592 le16_to_cpu(action_frame->len));5593 5594 brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n",5595 *cookie, le16_to_cpu(action_frame->len), freq);5596 5597 ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg),5598 af_params);5599 5600 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack,5601 GFP_KERNEL);5602 kfree(af_params);5603 } else {5604 brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control);5605 brcmf_dbg_hex_dump(true, buf, len, "payload, len=%zu\n", len);5606 }5607 5608exit:5609 return err;5610}5611 5612static int brcmf_cfg80211_set_cqm_rssi_range_config(struct wiphy *wiphy,5613 struct net_device *ndev,5614 s32 rssi_low, s32 rssi_high)5615{5616 struct brcmf_cfg80211_vif *vif;5617 struct brcmf_if *ifp;5618 int err = 0;5619 5620 brcmf_dbg(TRACE, "low=%d high=%d", rssi_low, rssi_high);5621 5622 ifp = netdev_priv(ndev);5623 vif = ifp->vif;5624 5625 if (rssi_low != vif->cqm_rssi_low || rssi_high != vif->cqm_rssi_high) {5626 /* The firmware will send an event when the RSSI is less than or5627 * equal to a configured level and the previous RSSI event was5628 * less than or equal to a different level. Set a third level5629 * so that we also detect the transition from rssi <= rssi_high5630 * to rssi > rssi_high.5631 */5632 struct brcmf_rssi_event_le config = {5633 .rate_limit_msec = cpu_to_le32(0),5634 .rssi_level_num = 3,5635 .rssi_levels = {5636 clamp_val(rssi_low, S8_MIN, S8_MAX - 2),5637 clamp_val(rssi_high, S8_MIN + 1, S8_MAX - 1),5638 S8_MAX,5639 },5640 };5641 5642 err = brcmf_fil_iovar_data_set(ifp, "rssi_event", &config,5643 sizeof(config));5644 if (err) {5645 err = -EINVAL;5646 } else {5647 vif->cqm_rssi_low = rssi_low;5648 vif->cqm_rssi_high = rssi_high;5649 }5650 }5651 5652 return err;5653}5654 5655static int5656brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,5657 struct wireless_dev *wdev,5658 u64 cookie)5659{5660 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5661 struct brcmf_pub *drvr = cfg->pub;5662 struct brcmf_cfg80211_vif *vif;5663 int err = 0;5664 5665 brcmf_dbg(TRACE, "Enter p2p listen cancel\n");5666 5667 vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif;5668 if (vif == NULL) {5669 bphy_err(drvr, "No p2p device available for probe response\n");5670 err = -ENODEV;5671 goto exit;5672 }5673 brcmf_p2p_cancel_remain_on_channel(vif->ifp);5674exit:5675 return err;5676}5677 5678static int brcmf_cfg80211_get_channel(struct wiphy *wiphy,5679 struct wireless_dev *wdev,5680 unsigned int link_id,5681 struct cfg80211_chan_def *chandef)5682{5683 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5684 struct net_device *ndev = wdev->netdev;5685 struct brcmf_pub *drvr = cfg->pub;5686 struct brcmu_chan ch;5687 enum nl80211_band band = 0;5688 enum nl80211_chan_width width = 0;5689 u32 chanspec;5690 int freq, err;5691 5692 if (!ndev || drvr->bus_if->state != BRCMF_BUS_UP)5693 return -ENODEV;5694 5695 err = brcmf_fil_iovar_int_get(netdev_priv(ndev), "chanspec", &chanspec);5696 if (err) {5697 bphy_err(drvr, "chanspec failed (%d)\n", err);5698 return err;5699 }5700 5701 ch.chspec = chanspec;5702 cfg->d11inf.decchspec(&ch);5703 5704 switch (ch.band) {5705 case BRCMU_CHAN_BAND_2G:5706 band = NL80211_BAND_2GHZ;5707 break;5708 case BRCMU_CHAN_BAND_5G:5709 band = NL80211_BAND_5GHZ;5710 break;5711 }5712 5713 switch (ch.bw) {5714 case BRCMU_CHAN_BW_80:5715 width = NL80211_CHAN_WIDTH_80;5716 break;5717 case BRCMU_CHAN_BW_40:5718 width = NL80211_CHAN_WIDTH_40;5719 break;5720 case BRCMU_CHAN_BW_20:5721 width = NL80211_CHAN_WIDTH_20;5722 break;5723 case BRCMU_CHAN_BW_80P80:5724 width = NL80211_CHAN_WIDTH_80P80;5725 break;5726 case BRCMU_CHAN_BW_160:5727 width = NL80211_CHAN_WIDTH_160;5728 break;5729 }5730 5731 freq = ieee80211_channel_to_frequency(ch.control_ch_num, band);5732 chandef->chan = ieee80211_get_channel(wiphy, freq);5733 chandef->width = width;5734 chandef->center_freq1 = ieee80211_channel_to_frequency(ch.chnum, band);5735 chandef->center_freq2 = 0;5736 5737 return 0;5738}5739 5740static int brcmf_cfg80211_crit_proto_start(struct wiphy *wiphy,5741 struct wireless_dev *wdev,5742 enum nl80211_crit_proto_id proto,5743 u16 duration)5744{5745 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5746 struct brcmf_cfg80211_vif *vif;5747 5748 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);5749 5750 /* only DHCP support for now */5751 if (proto != NL80211_CRIT_PROTO_DHCP)5752 return -EINVAL;5753 5754 /* suppress and abort scanning */5755 set_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);5756 brcmf_abort_scanning(cfg);5757 5758 return brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_DISABLED, duration);5759}5760 5761static void brcmf_cfg80211_crit_proto_stop(struct wiphy *wiphy,5762 struct wireless_dev *wdev)5763{5764 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5765 struct brcmf_cfg80211_vif *vif;5766 5767 vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);5768 5769 brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);5770 clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);5771}5772 5773static s325774brcmf_notify_tdls_peer_event(struct brcmf_if *ifp,5775 const struct brcmf_event_msg *e, void *data)5776{5777 switch (e->reason) {5778 case BRCMF_E_REASON_TDLS_PEER_DISCOVERED:5779 brcmf_dbg(TRACE, "TDLS Peer Discovered\n");5780 break;5781 case BRCMF_E_REASON_TDLS_PEER_CONNECTED:5782 brcmf_dbg(TRACE, "TDLS Peer Connected\n");5783 brcmf_proto_add_tdls_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);5784 break;5785 case BRCMF_E_REASON_TDLS_PEER_DISCONNECTED:5786 brcmf_dbg(TRACE, "TDLS Peer Disconnected\n");5787 brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);5788 break;5789 }5790 5791 return 0;5792}5793 5794static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)5795{5796 int ret;5797 5798 switch (oper) {5799 case NL80211_TDLS_DISCOVERY_REQ:5800 ret = BRCMF_TDLS_MANUAL_EP_DISCOVERY;5801 break;5802 case NL80211_TDLS_SETUP:5803 ret = BRCMF_TDLS_MANUAL_EP_CREATE;5804 break;5805 case NL80211_TDLS_TEARDOWN:5806 ret = BRCMF_TDLS_MANUAL_EP_DELETE;5807 break;5808 default:5809 brcmf_err("unsupported operation: %d\n", oper);5810 ret = -EOPNOTSUPP;5811 }5812 return ret;5813}5814 5815static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,5816 struct net_device *ndev, const u8 *peer,5817 enum nl80211_tdls_operation oper)5818{5819 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5820 struct brcmf_pub *drvr = cfg->pub;5821 struct brcmf_if *ifp;5822 struct brcmf_tdls_iovar_le info;5823 int ret = 0;5824 5825 ret = brcmf_convert_nl80211_tdls_oper(oper);5826 if (ret < 0)5827 return ret;5828 5829 ifp = netdev_priv(ndev);5830 memset(&info, 0, sizeof(info));5831 info.mode = (u8)ret;5832 if (peer)5833 memcpy(info.ea, peer, ETH_ALEN);5834 5835 ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint",5836 &info, sizeof(info));5837 if (ret < 0)5838 bphy_err(drvr, "tdls_endpoint iovar failed: ret=%d\n", ret);5839 5840 return ret;5841}5842 5843static int5844brcmf_cfg80211_update_conn_params(struct wiphy *wiphy,5845 struct net_device *ndev,5846 struct cfg80211_connect_params *sme,5847 u32 changed)5848{5849 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5850 struct brcmf_pub *drvr = cfg->pub;5851 struct brcmf_if *ifp;5852 int err;5853 5854 if (!(changed & UPDATE_ASSOC_IES))5855 return 0;5856 5857 ifp = netdev_priv(ndev);5858 err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,5859 sme->ie, sme->ie_len);5860 if (err)5861 bphy_err(drvr, "Set Assoc REQ IE Failed\n");5862 else5863 brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");5864 5865 return err;5866}5867 5868#ifdef CONFIG_PM5869static int5870brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,5871 struct cfg80211_gtk_rekey_data *gtk)5872{5873 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);5874 struct brcmf_pub *drvr = cfg->pub;5875 struct brcmf_if *ifp = netdev_priv(ndev);5876 struct brcmf_gtk_keyinfo_le gtk_le;5877 int ret;5878 5879 brcmf_dbg(TRACE, "Enter, bssidx=%d\n", ifp->bsscfgidx);5880 5881 memcpy(gtk_le.kck, gtk->kck, sizeof(gtk_le.kck));5882 memcpy(gtk_le.kek, gtk->kek, sizeof(gtk_le.kek));5883 memcpy(gtk_le.replay_counter, gtk->replay_ctr,5884 sizeof(gtk_le.replay_counter));5885 5886 ret = brcmf_fil_iovar_data_set(ifp, "gtk_key_info", >k_le,5887 sizeof(gtk_le));5888 if (ret < 0)5889 bphy_err(drvr, "gtk_key_info iovar failed: ret=%d\n", ret);5890 5891 return ret;5892}5893#endif5894 5895static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,5896 const struct cfg80211_pmk_conf *conf)5897{5898 struct brcmf_if *ifp;5899 5900 brcmf_dbg(TRACE, "enter\n");5901 5902 /* expect using firmware supplicant for 1X */5903 ifp = netdev_priv(dev);5904 if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))5905 return -EINVAL;5906 5907 if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)5908 return -ERANGE;5909 5910 return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);5911}5912 5913static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,5914 const u8 *aa)5915{5916 struct brcmf_if *ifp;5917 5918 brcmf_dbg(TRACE, "enter\n");5919 ifp = netdev_priv(dev);5920 if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))5921 return -EINVAL;5922 5923 return brcmf_set_pmk(ifp, NULL, 0);5924}5925 5926static struct cfg80211_ops brcmf_cfg80211_ops = {5927 .add_virtual_intf = brcmf_cfg80211_add_iface,5928 .del_virtual_intf = brcmf_cfg80211_del_iface,5929 .change_virtual_intf = brcmf_cfg80211_change_iface,5930 .scan = brcmf_cfg80211_scan,5931 .set_wiphy_params = brcmf_cfg80211_set_wiphy_params,5932 .join_ibss = brcmf_cfg80211_join_ibss,5933 .leave_ibss = brcmf_cfg80211_leave_ibss,5934 .get_station = brcmf_cfg80211_get_station,5935 .dump_station = brcmf_cfg80211_dump_station,5936 .set_tx_power = brcmf_cfg80211_set_tx_power,5937 .get_tx_power = brcmf_cfg80211_get_tx_power,5938 .add_key = brcmf_cfg80211_add_key,5939 .del_key = brcmf_cfg80211_del_key,5940 .get_key = brcmf_cfg80211_get_key,5941 .set_default_key = brcmf_cfg80211_config_default_key,5942 .set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,5943 .set_power_mgmt = brcmf_cfg80211_set_power_mgmt,5944 .connect = brcmf_cfg80211_connect,5945 .disconnect = brcmf_cfg80211_disconnect,5946 .suspend = brcmf_cfg80211_suspend,5947 .resume = brcmf_cfg80211_resume,5948 .set_pmksa = brcmf_cfg80211_set_pmksa,5949 .del_pmksa = brcmf_cfg80211_del_pmksa,5950 .flush_pmksa = brcmf_cfg80211_flush_pmksa,5951 .start_ap = brcmf_cfg80211_start_ap,5952 .stop_ap = brcmf_cfg80211_stop_ap,5953 .change_beacon = brcmf_cfg80211_change_beacon,5954 .del_station = brcmf_cfg80211_del_station,5955 .change_station = brcmf_cfg80211_change_station,5956 .sched_scan_start = brcmf_cfg80211_sched_scan_start,5957 .sched_scan_stop = brcmf_cfg80211_sched_scan_stop,5958 .update_mgmt_frame_registrations =5959 brcmf_cfg80211_update_mgmt_frame_registrations,5960 .mgmt_tx = brcmf_cfg80211_mgmt_tx,5961 .set_cqm_rssi_range_config = brcmf_cfg80211_set_cqm_rssi_range_config,5962 .remain_on_channel = brcmf_p2p_remain_on_channel,5963 .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel,5964 .get_channel = brcmf_cfg80211_get_channel,5965 .start_p2p_device = brcmf_p2p_start_device,5966 .stop_p2p_device = brcmf_p2p_stop_device,5967 .crit_proto_start = brcmf_cfg80211_crit_proto_start,5968 .crit_proto_stop = brcmf_cfg80211_crit_proto_stop,5969 .tdls_oper = brcmf_cfg80211_tdls_oper,5970 .update_connect_params = brcmf_cfg80211_update_conn_params,5971 .set_pmk = brcmf_cfg80211_set_pmk,5972 .del_pmk = brcmf_cfg80211_del_pmk,5973};5974 5975struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings)5976{5977 struct cfg80211_ops *ops;5978 5979 ops = kmemdup(&brcmf_cfg80211_ops, sizeof(brcmf_cfg80211_ops),5980 GFP_KERNEL);5981 5982 if (ops && settings->roamoff)5983 ops->update_connect_params = NULL;5984 5985 return ops;5986}5987 5988struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,5989 enum nl80211_iftype type)5990{5991 struct brcmf_cfg80211_vif *vif_walk;5992 struct brcmf_cfg80211_vif *vif;5993 bool mbss;5994 struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);5995 5996 brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",5997 sizeof(*vif));5998 vif = kzalloc(sizeof(*vif), GFP_KERNEL);5999 if (!vif)6000 return ERR_PTR(-ENOMEM);6001 6002 vif->wdev.wiphy = cfg->wiphy;6003 vif->wdev.iftype = type;6004 6005 brcmf_init_prof(&vif->profile);6006 6007 if (type == NL80211_IFTYPE_AP &&6008 brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {6009 mbss = false;6010 list_for_each_entry(vif_walk, &cfg->vif_list, list) {6011 if (vif_walk->wdev.iftype == NL80211_IFTYPE_AP) {6012 mbss = true;6013 break;6014 }6015 }6016 vif->mbss = mbss;6017 }6018 6019 list_add_tail(&vif->list, &cfg->vif_list);6020 return vif;6021}6022 6023void brcmf_free_vif(struct brcmf_cfg80211_vif *vif)6024{6025 list_del(&vif->list);6026 kfree(vif);6027}6028 6029void brcmf_cfg80211_free_netdev(struct net_device *ndev)6030{6031 struct brcmf_cfg80211_vif *vif;6032 struct brcmf_if *ifp;6033 6034 ifp = netdev_priv(ndev);6035 vif = ifp->vif;6036 6037 if (vif)6038 brcmf_free_vif(vif);6039}6040 6041static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,6042 const struct brcmf_event_msg *e)6043{6044 u32 event = e->event_code;6045 u32 status = e->status;6046 6047 if ((vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK ||6048 vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_SAE) &&6049 event == BRCMF_E_PSK_SUP &&6050 status == BRCMF_E_STATUS_FWSUP_COMPLETED)6051 set_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);6052 if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {6053 brcmf_dbg(CONN, "Processing set ssid\n");6054 memcpy(vif->profile.bssid, e->addr, ETH_ALEN);6055 if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_PSK &&6056 vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_SAE)6057 return true;6058 6059 set_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);6060 }6061 6062 if (test_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state) &&6063 test_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state)) {6064 clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);6065 clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);6066 return true;6067 }6068 return false;6069}6070 6071static bool brcmf_is_linkdown(struct brcmf_cfg80211_vif *vif,6072 const struct brcmf_event_msg *e)6073{6074 u32 event = e->event_code;6075 u16 flags = e->flags;6076 6077 if ((event == BRCMF_E_DEAUTH) || (event == BRCMF_E_DEAUTH_IND) ||6078 (event == BRCMF_E_DISASSOC_IND) ||6079 ((event == BRCMF_E_LINK) && (!(flags & BRCMF_EVENT_MSG_LINK)))) {6080 brcmf_dbg(CONN, "Processing link down\n");6081 clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);6082 clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);6083 return true;6084 }6085 return false;6086}6087 6088static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,6089 const struct brcmf_event_msg *e)6090{6091 u32 event = e->event_code;6092 u32 status = e->status;6093 6094 if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {6095 brcmf_dbg(CONN, "Processing Link %s & no network found\n",6096 e->flags & BRCMF_EVENT_MSG_LINK ? "up" : "down");6097 return true;6098 }6099 6100 if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {6101 brcmf_dbg(CONN, "Processing connecting & no network found\n");6102 return true;6103 }6104 6105 if (event == BRCMF_E_PSK_SUP &&6106 status != BRCMF_E_STATUS_FWSUP_COMPLETED) {6107 brcmf_dbg(CONN, "Processing failed supplicant state: %u\n",6108 status);6109 return true;6110 }6111 6112 return false;6113}6114 6115static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)6116{6117 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);6118 6119 kfree(conn_info->req_ie);6120 conn_info->req_ie = NULL;6121 conn_info->req_ie_len = 0;6122 kfree(conn_info->resp_ie);6123 conn_info->resp_ie = NULL;6124 conn_info->resp_ie_len = 0;6125}6126 6127u8 brcmf_map_prio_to_prec(void *config, u8 prio)6128{6129 struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)config;6130 6131 if (!cfg)6132 return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ?6133 (prio ^ 2) : prio;6134 6135 /* For those AC(s) with ACM flag set to 1, convert its 4-level priority6136 * to an 8-level precedence which is the same as BE's6137 */6138 if (prio > PRIO_8021D_EE &&6139 cfg->ac_priority[prio] == cfg->ac_priority[PRIO_8021D_BE])6140 return cfg->ac_priority[prio] * 2;6141 6142 /* Conversion of 4-level priority to 8-level precedence */6143 if (prio == PRIO_8021D_BE || prio == PRIO_8021D_BK ||6144 prio == PRIO_8021D_CL || prio == PRIO_8021D_VO)6145 return cfg->ac_priority[prio] * 2;6146 else6147 return cfg->ac_priority[prio] * 2 + 1;6148}6149 6150u8 brcmf_map_prio_to_aci(void *config, u8 prio)6151{6152 /* Prio here refers to the 802.1d priority in range of 0 to 7.6153 * ACI here refers to the WLAN AC Index in range of 0 to 3.6154 * This function will return ACI corresponding to input prio.6155 */6156 struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)config;6157 6158 if (cfg)6159 return cfg->ac_priority[prio];6160 6161 return prio;6162}6163 6164static void brcmf_init_wmm_prio(u8 *priority)6165{6166 /* Initialize AC priority array to default6167 * 802.1d priority as per following table:6168 * 802.1d prio 0,3 maps to BE6169 * 802.1d prio 1,2 maps to BK6170 * 802.1d prio 4,5 maps to VI6171 * 802.1d prio 6,7 maps to VO6172 */6173 priority[0] = BRCMF_FWS_FIFO_AC_BE;6174 priority[3] = BRCMF_FWS_FIFO_AC_BE;6175 priority[1] = BRCMF_FWS_FIFO_AC_BK;6176 priority[2] = BRCMF_FWS_FIFO_AC_BK;6177 priority[4] = BRCMF_FWS_FIFO_AC_VI;6178 priority[5] = BRCMF_FWS_FIFO_AC_VI;6179 priority[6] = BRCMF_FWS_FIFO_AC_VO;6180 priority[7] = BRCMF_FWS_FIFO_AC_VO;6181}6182 6183static void brcmf_wifi_prioritize_acparams(const6184 struct brcmf_cfg80211_edcf_acparam *acp, u8 *priority)6185{6186 u8 aci;6187 u8 aifsn;6188 u8 ecwmin;6189 u8 ecwmax;6190 u8 acm;6191 u8 ranking_basis[EDCF_AC_COUNT];6192 u8 aci_prio[EDCF_AC_COUNT]; /* AC_BE, AC_BK, AC_VI, AC_VO */6193 u8 index;6194 6195 for (aci = 0; aci < EDCF_AC_COUNT; aci++, acp++) {6196 aifsn = acp->ACI & EDCF_AIFSN_MASK;6197 acm = (acp->ACI & EDCF_ACM_MASK) ? 1 : 0;6198 ecwmin = acp->ECW & EDCF_ECWMIN_MASK;6199 ecwmax = (acp->ECW & EDCF_ECWMAX_MASK) >> EDCF_ECWMAX_SHIFT;6200 brcmf_dbg(CONN, "ACI %d aifsn %d acm %d ecwmin %d ecwmax %d\n",6201 aci, aifsn, acm, ecwmin, ecwmax);6202 /* Default AC_VO will be the lowest ranking value */6203 ranking_basis[aci] = aifsn + ecwmin + ecwmax;6204 /* Initialise priority starting at 0 (AC_BE) */6205 aci_prio[aci] = 0;6206 6207 /* If ACM is set, STA can't use this AC as per 802.11.6208 * Change the ranking to BE6209 */6210 if (aci != AC_BE && aci != AC_BK && acm == 1)6211 ranking_basis[aci] = ranking_basis[AC_BE];6212 }6213 6214 /* Ranking method which works for AC priority6215 * swapping when values for cwmin, cwmax and aifsn are varied6216 * Compare each aci_prio against each other aci_prio6217 */6218 for (aci = 0; aci < EDCF_AC_COUNT; aci++) {6219 for (index = 0; index < EDCF_AC_COUNT; index++) {6220 if (index != aci) {6221 /* Smaller ranking value has higher priority,6222 * so increment priority for each ACI which has6223 * a higher ranking value6224 */6225 if (ranking_basis[aci] < ranking_basis[index])6226 aci_prio[aci]++;6227 }6228 }6229 }6230 6231 /* By now, aci_prio[] will be in range of 0 to 3.6232 * Use ACI prio to get the new priority value for6233 * each 802.1d traffic type, in this range.6234 */6235 if (!(aci_prio[AC_BE] == aci_prio[AC_BK] &&6236 aci_prio[AC_BK] == aci_prio[AC_VI] &&6237 aci_prio[AC_VI] == aci_prio[AC_VO])) {6238 /* 802.1d 0,3 maps to BE */6239 priority[0] = aci_prio[AC_BE];6240 priority[3] = aci_prio[AC_BE];6241 6242 /* 802.1d 1,2 maps to BK */6243 priority[1] = aci_prio[AC_BK];6244 priority[2] = aci_prio[AC_BK];6245 6246 /* 802.1d 4,5 maps to VO */6247 priority[4] = aci_prio[AC_VI];6248 priority[5] = aci_prio[AC_VI];6249 6250 /* 802.1d 6,7 maps to VO */6251 priority[6] = aci_prio[AC_VO];6252 priority[7] = aci_prio[AC_VO];6253 } else {6254 /* Initialize to default priority */6255 brcmf_init_wmm_prio(priority);6256 }6257 6258 brcmf_dbg(CONN, "Adj prio BE 0->%d, BK 1->%d, BK 2->%d, BE 3->%d\n",6259 priority[0], priority[1], priority[2], priority[3]);6260 6261 brcmf_dbg(CONN, "Adj prio VI 4->%d, VI 5->%d, VO 6->%d, VO 7->%d\n",6262 priority[4], priority[5], priority[6], priority[7]);6263}6264 6265static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,6266 struct brcmf_if *ifp)6267{6268 struct brcmf_pub *drvr = cfg->pub;6269 struct brcmf_cfg80211_assoc_ielen_le *assoc_info;6270 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);6271 struct brcmf_cfg80211_edcf_acparam edcf_acparam_info[EDCF_AC_COUNT];6272 u32 req_len;6273 u32 resp_len;6274 s32 err = 0;6275 6276 brcmf_clear_assoc_ies(cfg);6277 6278 err = brcmf_fil_iovar_data_get(ifp, "assoc_info",6279 cfg->extra_buf, WL_ASSOC_INFO_MAX);6280 if (err) {6281 bphy_err(drvr, "could not get assoc info (%d)\n", err);6282 return err;6283 }6284 assoc_info =6285 (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;6286 req_len = le32_to_cpu(assoc_info->req_len);6287 resp_len = le32_to_cpu(assoc_info->resp_len);6288 if (req_len > WL_EXTRA_BUF_MAX || resp_len > WL_EXTRA_BUF_MAX) {6289 bphy_err(drvr, "invalid lengths in assoc info: req %u resp %u\n",6290 req_len, resp_len);6291 return -EINVAL;6292 }6293 if (req_len) {6294 err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",6295 cfg->extra_buf,6296 WL_ASSOC_INFO_MAX);6297 if (err) {6298 bphy_err(drvr, "could not get assoc req (%d)\n", err);6299 return err;6300 }6301 conn_info->req_ie_len = req_len;6302 conn_info->req_ie =6303 kmemdup(cfg->extra_buf, conn_info->req_ie_len,6304 GFP_KERNEL);6305 if (!conn_info->req_ie)6306 conn_info->req_ie_len = 0;6307 } else {6308 conn_info->req_ie_len = 0;6309 conn_info->req_ie = NULL;6310 }6311 if (resp_len) {6312 err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies",6313 cfg->extra_buf,6314 WL_ASSOC_INFO_MAX);6315 if (err) {6316 bphy_err(drvr, "could not get assoc resp (%d)\n", err);6317 return err;6318 }6319 conn_info->resp_ie_len = resp_len;6320 conn_info->resp_ie =6321 kmemdup(cfg->extra_buf, conn_info->resp_ie_len,6322 GFP_KERNEL);6323 if (!conn_info->resp_ie)6324 conn_info->resp_ie_len = 0;6325 6326 err = brcmf_fil_iovar_data_get(ifp, "wme_ac_sta",6327 edcf_acparam_info,6328 sizeof(edcf_acparam_info));6329 if (err) {6330 brcmf_err("could not get wme_ac_sta (%d)\n", err);6331 return err;6332 }6333 6334 brcmf_wifi_prioritize_acparams(edcf_acparam_info,6335 cfg->ac_priority);6336 } else {6337 conn_info->resp_ie_len = 0;6338 conn_info->resp_ie = NULL;6339 }6340 brcmf_dbg(CONN, "req len (%d) resp len (%d)\n",6341 conn_info->req_ie_len, conn_info->resp_ie_len);6342 6343 return err;6344}6345 6346static s326347brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,6348 struct net_device *ndev,6349 const struct brcmf_event_msg *e)6350{6351 struct brcmf_if *ifp = netdev_priv(ndev);6352 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;6353 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);6354 struct wiphy *wiphy = cfg_to_wiphy(cfg);6355 struct ieee80211_channel *notify_channel = NULL;6356 struct ieee80211_supported_band *band;6357 struct brcmf_bss_info_le *bi;6358 struct brcmu_chan ch;6359 struct cfg80211_roam_info roam_info = {};6360 u32 freq;6361 s32 err = 0;6362 u8 *buf;6363 6364 brcmf_dbg(TRACE, "Enter\n");6365 6366 brcmf_get_assoc_ies(cfg, ifp);6367 memcpy(profile->bssid, e->addr, ETH_ALEN);6368 brcmf_update_bss_info(cfg, ifp);6369 6370 buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);6371 if (buf == NULL) {6372 err = -ENOMEM;6373 goto done;6374 }6375 6376 /* data sent to dongle has to be little endian */6377 *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);6378 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,6379 buf, WL_BSS_INFO_MAX);6380 6381 if (err)6382 goto done;6383 6384 bi = (struct brcmf_bss_info_le *)(buf + 4);6385 ch.chspec = le16_to_cpu(bi->chanspec);6386 cfg->d11inf.decchspec(&ch);6387 6388 if (ch.band == BRCMU_CHAN_BAND_2G)6389 band = wiphy->bands[NL80211_BAND_2GHZ];6390 else6391 band = wiphy->bands[NL80211_BAND_5GHZ];6392 6393 freq = ieee80211_channel_to_frequency(ch.control_ch_num, band->band);6394 notify_channel = ieee80211_get_channel(wiphy, freq);6395 6396done:6397 kfree(buf);6398 6399 roam_info.links[0].channel = notify_channel;6400 roam_info.links[0].bssid = profile->bssid;6401 roam_info.req_ie = conn_info->req_ie;6402 roam_info.req_ie_len = conn_info->req_ie_len;6403 roam_info.resp_ie = conn_info->resp_ie;6404 roam_info.resp_ie_len = conn_info->resp_ie_len;6405 6406 cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);6407 brcmf_dbg(CONN, "Report roaming result\n");6408 6409 if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {6410 cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);6411 brcmf_dbg(CONN, "Report port authorized\n");6412 }6413 6414 set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);6415 brcmf_dbg(TRACE, "Exit\n");6416 return err;6417}6418 6419static s326420brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,6421 struct net_device *ndev, const struct brcmf_event_msg *e,6422 bool completed)6423{6424 struct brcmf_if *ifp = netdev_priv(ndev);6425 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;6426 struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);6427 struct cfg80211_connect_resp_params conn_params;6428 6429 brcmf_dbg(TRACE, "Enter\n");6430 6431 if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,6432 &ifp->vif->sme_state)) {6433 memset(&conn_params, 0, sizeof(conn_params));6434 if (completed) {6435 brcmf_get_assoc_ies(cfg, ifp);6436 brcmf_update_bss_info(cfg, ifp);6437 set_bit(BRCMF_VIF_STATUS_CONNECTED,6438 &ifp->vif->sme_state);6439 conn_params.status = WLAN_STATUS_SUCCESS;6440 } else {6441 clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS,6442 &ifp->vif->sme_state);6443 clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS,6444 &ifp->vif->sme_state);6445 conn_params.status = WLAN_STATUS_AUTH_TIMEOUT;6446 }6447 conn_params.links[0].bssid = profile->bssid;6448 conn_params.req_ie = conn_info->req_ie;6449 conn_params.req_ie_len = conn_info->req_ie_len;6450 conn_params.resp_ie = conn_info->resp_ie;6451 conn_params.resp_ie_len = conn_info->resp_ie_len;6452 cfg80211_connect_done(ndev, &conn_params, GFP_KERNEL);6453 brcmf_dbg(CONN, "Report connect result - connection %s\n",6454 completed ? "succeeded" : "failed");6455 }6456 brcmf_dbg(TRACE, "Exit\n");6457 return 0;6458}6459 6460static s326461brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,6462 struct net_device *ndev,6463 const struct brcmf_event_msg *e, void *data)6464{6465 struct brcmf_pub *drvr = cfg->pub;6466 static int generation;6467 u32 event = e->event_code;6468 u32 reason = e->reason;6469 struct station_info *sinfo;6470 6471 brcmf_dbg(CONN, "event %s (%u), reason %d\n",6472 brcmf_fweh_event_name(event), event, reason);6473 if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&6474 ndev != cfg_to_ndev(cfg)) {6475 brcmf_dbg(CONN, "AP mode link down\n");6476 complete(&cfg->vif_disabled);6477 return 0;6478 }6479 6480 if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&6481 (reason == BRCMF_E_STATUS_SUCCESS)) {6482 if (!data) {6483 bphy_err(drvr, "No IEs present in ASSOC/REASSOC_IND\n");6484 return -EINVAL;6485 }6486 6487 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);6488 if (!sinfo)6489 return -ENOMEM;6490 6491 sinfo->assoc_req_ies = data;6492 sinfo->assoc_req_ies_len = e->datalen;6493 generation++;6494 sinfo->generation = generation;6495 cfg80211_new_sta(ndev, e->addr, sinfo, GFP_KERNEL);6496 6497 kfree(sinfo);6498 } else if ((event == BRCMF_E_DISASSOC_IND) ||6499 (event == BRCMF_E_DEAUTH_IND) ||6500 (event == BRCMF_E_DEAUTH)) {6501 cfg80211_del_sta(ndev, e->addr, GFP_KERNEL);6502 }6503 return 0;6504}6505 6506static s326507brcmf_notify_connect_status(struct brcmf_if *ifp,6508 const struct brcmf_event_msg *e, void *data)6509{6510 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;6511 struct net_device *ndev = ifp->ndev;6512 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;6513 struct ieee80211_channel *chan;6514 s32 err = 0;6515 6516 if ((e->event_code == BRCMF_E_DEAUTH) ||6517 (e->event_code == BRCMF_E_DEAUTH_IND) ||6518 (e->event_code == BRCMF_E_DISASSOC_IND) ||6519 ((e->event_code == BRCMF_E_LINK) && (!e->flags))) {6520 brcmf_proto_delete_peer(ifp->drvr, ifp->ifidx, (u8 *)e->addr);6521 }6522 6523 if (brcmf_is_apmode(ifp->vif)) {6524 err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);6525 } else if (brcmf_is_linkup(ifp->vif, e)) {6526 brcmf_dbg(CONN, "Linkup\n");6527 if (brcmf_is_ibssmode(ifp->vif)) {6528 brcmf_inform_ibss(cfg, ndev, e->addr);6529 chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);6530 memcpy(profile->bssid, e->addr, ETH_ALEN);6531 cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);6532 clear_bit(BRCMF_VIF_STATUS_CONNECTING,6533 &ifp->vif->sme_state);6534 set_bit(BRCMF_VIF_STATUS_CONNECTED,6535 &ifp->vif->sme_state);6536 } else6537 brcmf_bss_connect_done(cfg, ndev, e, true);6538 brcmf_net_setcarrier(ifp, true);6539 } else if (brcmf_is_linkdown(ifp->vif, e)) {6540 brcmf_dbg(CONN, "Linkdown\n");6541 if (!brcmf_is_ibssmode(ifp->vif) &&6542 (test_bit(BRCMF_VIF_STATUS_CONNECTED,6543 &ifp->vif->sme_state) ||6544 test_bit(BRCMF_VIF_STATUS_CONNECTING,6545 &ifp->vif->sme_state))) {6546 if (test_bit(BRCMF_VIF_STATUS_CONNECTED,6547 &ifp->vif->sme_state) &&6548 memcmp(profile->bssid, e->addr, ETH_ALEN))6549 return err;6550 6551 brcmf_bss_connect_done(cfg, ndev, e, false);6552 brcmf_link_down(ifp->vif,6553 brcmf_map_fw_linkdown_reason(e),6554 e->event_code &6555 (BRCMF_E_DEAUTH_IND |6556 BRCMF_E_DISASSOC_IND)6557 ? false : true);6558 brcmf_init_prof(ndev_to_prof(ndev));6559 if (ndev != cfg_to_ndev(cfg))6560 complete(&cfg->vif_disabled);6561 brcmf_net_setcarrier(ifp, false);6562 }6563 } else if (brcmf_is_nonetwork(cfg, e)) {6564 if (brcmf_is_ibssmode(ifp->vif))6565 clear_bit(BRCMF_VIF_STATUS_CONNECTING,6566 &ifp->vif->sme_state);6567 else6568 brcmf_bss_connect_done(cfg, ndev, e, false);6569 }6570 6571 return err;6572}6573 6574static s326575brcmf_notify_roaming_status(struct brcmf_if *ifp,6576 const struct brcmf_event_msg *e, void *data)6577{6578 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;6579 u32 event = e->event_code;6580 u32 status = e->status;6581 6582 if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {6583 if (test_bit(BRCMF_VIF_STATUS_CONNECTED,6584 &ifp->vif->sme_state)) {6585 brcmf_bss_roaming_done(cfg, ifp->ndev, e);6586 } else {6587 brcmf_bss_connect_done(cfg, ifp->ndev, e, true);6588 brcmf_net_setcarrier(ifp, true);6589 }6590 }6591 6592 return 0;6593}6594 6595static s326596brcmf_notify_mic_status(struct brcmf_if *ifp,6597 const struct brcmf_event_msg *e, void *data)6598{6599 u16 flags = e->flags;6600 enum nl80211_key_type key_type;6601 6602 if (flags & BRCMF_EVENT_MSG_GROUP)6603 key_type = NL80211_KEYTYPE_GROUP;6604 else6605 key_type = NL80211_KEYTYPE_PAIRWISE;6606 6607 cfg80211_michael_mic_failure(ifp->ndev, (u8 *)&e->addr, key_type, -1,6608 NULL, GFP_KERNEL);6609 6610 return 0;6611}6612 6613static s32 brcmf_notify_rssi(struct brcmf_if *ifp,6614 const struct brcmf_event_msg *e, void *data)6615{6616 struct brcmf_cfg80211_vif *vif = ifp->vif;6617 struct brcmf_rssi_be *info = data;6618 s32 rssi, snr = 0, noise = 0;6619 s32 low, high, last;6620 6621 if (e->datalen >= sizeof(*info)) {6622 rssi = be32_to_cpu(info->rssi);6623 snr = be32_to_cpu(info->snr);6624 noise = be32_to_cpu(info->noise);6625 } else if (e->datalen >= sizeof(rssi)) {6626 rssi = be32_to_cpu(*(__be32 *)data);6627 } else {6628 brcmf_err("insufficient RSSI event data\n");6629 return 0;6630 }6631 6632 low = vif->cqm_rssi_low;6633 high = vif->cqm_rssi_high;6634 last = vif->cqm_rssi_last;6635 6636 brcmf_dbg(TRACE, "rssi=%d snr=%d noise=%d low=%d high=%d last=%d\n",6637 rssi, snr, noise, low, high, last);6638 6639 vif->cqm_rssi_last = rssi;6640 6641 if (rssi <= low || rssi == 0) {6642 brcmf_dbg(INFO, "LOW rssi=%d\n", rssi);6643 cfg80211_cqm_rssi_notify(ifp->ndev,6644 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,6645 rssi, GFP_KERNEL);6646 } else if (rssi > high) {6647 brcmf_dbg(INFO, "HIGH rssi=%d\n", rssi);6648 cfg80211_cqm_rssi_notify(ifp->ndev,6649 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,6650 rssi, GFP_KERNEL);6651 }6652 6653 return 0;6654}6655 6656static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,6657 const struct brcmf_event_msg *e, void *data)6658{6659 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;6660 struct brcmf_if_event *ifevent = (struct brcmf_if_event *)data;6661 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;6662 struct brcmf_cfg80211_vif *vif;6663 6664 brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfgidx %u\n",6665 ifevent->action, ifevent->flags, ifevent->ifidx,6666 ifevent->bsscfgidx);6667 6668 spin_lock(&event->vif_event_lock);6669 event->action = ifevent->action;6670 vif = event->vif;6671 6672 switch (ifevent->action) {6673 case BRCMF_E_IF_ADD:6674 /* waiting process may have timed out */6675 if (!cfg->vif_event.vif) {6676 spin_unlock(&event->vif_event_lock);6677 return -EBADF;6678 }6679 6680 ifp->vif = vif;6681 vif->ifp = ifp;6682 if (ifp->ndev) {6683 vif->wdev.netdev = ifp->ndev;6684 ifp->ndev->ieee80211_ptr = &vif->wdev;6685 SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy));6686 }6687 spin_unlock(&event->vif_event_lock);6688 wake_up(&event->vif_wq);6689 return 0;6690 6691 case BRCMF_E_IF_DEL:6692 spin_unlock(&event->vif_event_lock);6693 /* event may not be upon user request */6694 if (brcmf_cfg80211_vif_event_armed(cfg))6695 wake_up(&event->vif_wq);6696 return 0;6697 6698 case BRCMF_E_IF_CHANGE:6699 spin_unlock(&event->vif_event_lock);6700 wake_up(&event->vif_wq);6701 return 0;6702 6703 default:6704 spin_unlock(&event->vif_event_lock);6705 break;6706 }6707 return -EINVAL;6708}6709 6710static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)6711{6712 conf->frag_threshold = (u32)-1;6713 conf->rts_threshold = (u32)-1;6714 conf->retry_short = (u32)-1;6715 conf->retry_long = (u32)-1;6716}6717 6718static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)6719{6720 brcmf_fweh_register(cfg->pub, BRCMF_E_LINK,6721 brcmf_notify_connect_status);6722 brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH_IND,6723 brcmf_notify_connect_status);6724 brcmf_fweh_register(cfg->pub, BRCMF_E_DEAUTH,6725 brcmf_notify_connect_status);6726 brcmf_fweh_register(cfg->pub, BRCMF_E_DISASSOC_IND,6727 brcmf_notify_connect_status);6728 brcmf_fweh_register(cfg->pub, BRCMF_E_ASSOC_IND,6729 brcmf_notify_connect_status);6730 brcmf_fweh_register(cfg->pub, BRCMF_E_REASSOC_IND,6731 brcmf_notify_connect_status);6732 brcmf_fweh_register(cfg->pub, BRCMF_E_ROAM,6733 brcmf_notify_roaming_status);6734 brcmf_fweh_register(cfg->pub, BRCMF_E_MIC_ERROR,6735 brcmf_notify_mic_status);6736 brcmf_fweh_register(cfg->pub, BRCMF_E_SET_SSID,6737 brcmf_notify_connect_status);6738 brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND,6739 brcmf_notify_sched_scan_results);6740 brcmf_fweh_register(cfg->pub, BRCMF_E_IF,6741 brcmf_notify_vif_event);6742 brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_PROBEREQ_MSG,6743 brcmf_p2p_notify_rx_mgmt_p2p_probereq);6744 brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE,6745 brcmf_p2p_notify_listen_complete);6746 brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX,6747 brcmf_p2p_notify_action_frame_rx);6748 brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_COMPLETE,6749 brcmf_p2p_notify_action_tx_complete);6750 brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,6751 brcmf_p2p_notify_action_tx_complete);6752 brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,6753 brcmf_notify_connect_status);6754 brcmf_fweh_register(cfg->pub, BRCMF_E_RSSI, brcmf_notify_rssi);6755}6756 6757static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)6758{6759 kfree(cfg->conf);6760 cfg->conf = NULL;6761 kfree(cfg->extra_buf);6762 cfg->extra_buf = NULL;6763 kfree(cfg->wowl.nd);6764 cfg->wowl.nd = NULL;6765 kfree(cfg->wowl.nd_info);6766 cfg->wowl.nd_info = NULL;6767 kfree(cfg->escan_info.escan_buf);6768 cfg->escan_info.escan_buf = NULL;6769}6770 6771static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)6772{6773 cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL);6774 if (!cfg->conf)6775 goto init_priv_mem_out;6776 cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);6777 if (!cfg->extra_buf)6778 goto init_priv_mem_out;6779 cfg->wowl.nd = kzalloc(sizeof(*cfg->wowl.nd) + sizeof(u32), GFP_KERNEL);6780 if (!cfg->wowl.nd)6781 goto init_priv_mem_out;6782 cfg->wowl.nd_info = kzalloc(sizeof(*cfg->wowl.nd_info) +6783 sizeof(struct cfg80211_wowlan_nd_match *),6784 GFP_KERNEL);6785 if (!cfg->wowl.nd_info)6786 goto init_priv_mem_out;6787 cfg->escan_info.escan_buf = kzalloc(BRCMF_ESCAN_BUF_SIZE, GFP_KERNEL);6788 if (!cfg->escan_info.escan_buf)6789 goto init_priv_mem_out;6790 6791 return 0;6792 6793init_priv_mem_out:6794 brcmf_deinit_priv_mem(cfg);6795 6796 return -ENOMEM;6797}6798 6799static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)6800{6801 s32 err = 0;6802 6803 cfg->scan_request = NULL;6804 cfg->pwr_save = true;6805 cfg->dongle_up = false; /* dongle is not up yet */6806 err = brcmf_init_priv_mem(cfg);6807 if (err)6808 return err;6809 brcmf_register_event_handlers(cfg);6810 mutex_init(&cfg->usr_sync);6811 brcmf_init_escan(cfg);6812 brcmf_init_conf(cfg->conf);6813 brcmf_init_wmm_prio(cfg->ac_priority);6814 init_completion(&cfg->vif_disabled);6815 return err;6816}6817 6818static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)6819{6820 cfg->dongle_up = false; /* dongle down */6821 brcmf_abort_scanning(cfg);6822 brcmf_deinit_priv_mem(cfg);6823 brcmf_clear_assoc_ies(cfg);6824}6825 6826static void init_vif_event(struct brcmf_cfg80211_vif_event *event)6827{6828 init_waitqueue_head(&event->vif_wq);6829 spin_lock_init(&event->vif_event_lock);6830}6831 6832static s32 brcmf_dongle_roam(struct brcmf_if *ifp)6833{6834 struct brcmf_pub *drvr = ifp->drvr;6835 s32 err;6836 u32 bcn_timeout;6837 __le32 roamtrigger[2];6838 __le32 roam_delta[2];6839 6840 /* Configure beacon timeout value based upon roaming setting */6841 if (ifp->drvr->settings->roamoff)6842 bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;6843 else6844 bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;6845 err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);6846 if (err) {6847 bphy_err(drvr, "bcn_timeout error (%d)\n", err);6848 goto roam_setup_done;6849 }6850 6851 /* Enable/Disable built-in roaming to allow supplicant to take care of6852 * roaming.6853 */6854 brcmf_dbg(INFO, "Internal Roaming = %s\n",6855 ifp->drvr->settings->roamoff ? "Off" : "On");6856 err = brcmf_fil_iovar_int_set(ifp, "roam_off",6857 ifp->drvr->settings->roamoff);6858 if (err) {6859 bphy_err(drvr, "roam_off error (%d)\n", err);6860 goto roam_setup_done;6861 }6862 6863 roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);6864 roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);6865 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER,6866 (void *)roamtrigger, sizeof(roamtrigger));6867 if (err)6868 bphy_err(drvr, "WLC_SET_ROAM_TRIGGER error (%d)\n", err);6869 6870 roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);6871 roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);6872 err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA,6873 (void *)roam_delta, sizeof(roam_delta));6874 if (err)6875 bphy_err(drvr, "WLC_SET_ROAM_DELTA error (%d)\n", err);6876 6877 return 0;6878 6879roam_setup_done:6880 return err;6881}6882 6883static s326884brcmf_dongle_scantime(struct brcmf_if *ifp)6885{6886 struct brcmf_pub *drvr = ifp->drvr;6887 s32 err = 0;6888 6889 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,6890 BRCMF_SCAN_CHANNEL_TIME);6891 if (err) {6892 bphy_err(drvr, "Scan assoc time error (%d)\n", err);6893 goto dongle_scantime_out;6894 }6895 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,6896 BRCMF_SCAN_UNASSOC_TIME);6897 if (err) {6898 bphy_err(drvr, "Scan unassoc time error (%d)\n", err);6899 goto dongle_scantime_out;6900 }6901 6902 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,6903 BRCMF_SCAN_PASSIVE_TIME);6904 if (err) {6905 bphy_err(drvr, "Scan passive time error (%d)\n", err);6906 goto dongle_scantime_out;6907 }6908 6909dongle_scantime_out:6910 return err;6911}6912 6913static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel,6914 struct brcmu_chan *ch)6915{6916 u32 ht40_flag;6917 6918 ht40_flag = channel->flags & IEEE80211_CHAN_NO_HT40;6919 if (ch->sb == BRCMU_CHAN_SB_U) {6920 if (ht40_flag == IEEE80211_CHAN_NO_HT40)6921 channel->flags &= ~IEEE80211_CHAN_NO_HT40;6922 channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;6923 } else {6924 /* It should be one of6925 * IEEE80211_CHAN_NO_HT40 or6926 * IEEE80211_CHAN_NO_HT40PLUS6927 */6928 channel->flags &= ~IEEE80211_CHAN_NO_HT40;6929 if (ht40_flag == IEEE80211_CHAN_NO_HT40)6930 channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;6931 }6932}6933 6934static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,6935 u32 bw_cap[])6936{6937 struct wiphy *wiphy = cfg_to_wiphy(cfg);6938 struct brcmf_pub *drvr = cfg->pub;6939 struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);6940 struct ieee80211_supported_band *band;6941 struct ieee80211_channel *channel;6942 struct brcmf_chanspec_list *list;6943 struct brcmu_chan ch;6944 int err;6945 u8 *pbuf;6946 u32 i, j;6947 u32 total;6948 u32 chaninfo;6949 6950 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);6951 6952 if (pbuf == NULL)6953 return -ENOMEM;6954 6955 list = (struct brcmf_chanspec_list *)pbuf;6956 6957 err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,6958 BRCMF_DCMD_MEDLEN);6959 if (err) {6960 bphy_err(drvr, "get chanspecs error (%d)\n", err);6961 goto fail_pbuf;6962 }6963 6964 band = wiphy->bands[NL80211_BAND_2GHZ];6965 if (band)6966 for (i = 0; i < band->n_channels; i++)6967 band->channels[i].flags = IEEE80211_CHAN_DISABLED;6968 band = wiphy->bands[NL80211_BAND_5GHZ];6969 if (band)6970 for (i = 0; i < band->n_channels; i++)6971 band->channels[i].flags = IEEE80211_CHAN_DISABLED;6972 6973 total = le32_to_cpu(list->count);6974 if (total > BRCMF_MAX_CHANSPEC_LIST) {6975 bphy_err(drvr, "Invalid count of channel Spec. (%u)\n",6976 total);6977 err = -EINVAL;6978 goto fail_pbuf;6979 }6980 6981 for (i = 0; i < total; i++) {6982 ch.chspec = (u16)le32_to_cpu(list->element[i]);6983 cfg->d11inf.decchspec(&ch);6984 6985 if (ch.band == BRCMU_CHAN_BAND_2G) {6986 band = wiphy->bands[NL80211_BAND_2GHZ];6987 } else if (ch.band == BRCMU_CHAN_BAND_5G) {6988 band = wiphy->bands[NL80211_BAND_5GHZ];6989 } else {6990 bphy_err(drvr, "Invalid channel Spec. 0x%x.\n",6991 ch.chspec);6992 continue;6993 }6994 if (!band)6995 continue;6996 if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) &&6997 ch.bw == BRCMU_CHAN_BW_40)6998 continue;6999 if (!(bw_cap[band->band] & WLC_BW_80MHZ_BIT) &&7000 ch.bw == BRCMU_CHAN_BW_80)7001 continue;7002 7003 channel = NULL;7004 for (j = 0; j < band->n_channels; j++) {7005 if (band->channels[j].hw_value == ch.control_ch_num) {7006 channel = &band->channels[j];7007 break;7008 }7009 }7010 if (!channel) {7011 /* It seems firmware supports some channel we never7012 * considered. Something new in IEEE standard?7013 */7014 bphy_err(drvr, "Ignoring unexpected firmware channel %d\n",7015 ch.control_ch_num);7016 continue;7017 }7018 7019 if (channel->orig_flags & IEEE80211_CHAN_DISABLED)7020 continue;7021 7022 /* assuming the chanspecs order is HT20,7023 * HT40 upper, HT40 lower, and VHT80.7024 */7025 switch (ch.bw) {7026 case BRCMU_CHAN_BW_160:7027 channel->flags &= ~IEEE80211_CHAN_NO_160MHZ;7028 break;7029 case BRCMU_CHAN_BW_80:7030 channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;7031 break;7032 case BRCMU_CHAN_BW_40:7033 brcmf_update_bw40_channel_flag(channel, &ch);7034 break;7035 default:7036 wiphy_warn(wiphy, "Firmware reported unsupported bandwidth %d\n",7037 ch.bw);7038 fallthrough;7039 case BRCMU_CHAN_BW_20:7040 /* enable the channel and disable other bandwidths7041 * for now as mentioned order assure they are enabled7042 * for subsequent chanspecs.7043 */7044 channel->flags = IEEE80211_CHAN_NO_HT40 |7045 IEEE80211_CHAN_NO_80MHZ |7046 IEEE80211_CHAN_NO_160MHZ;7047 ch.bw = BRCMU_CHAN_BW_20;7048 cfg->d11inf.encchspec(&ch);7049 chaninfo = ch.chspec;7050 err = brcmf_fil_bsscfg_int_query(ifp, "per_chan_info",7051 &chaninfo);7052 if (!err) {7053 if (chaninfo & WL_CHAN_RADAR)7054 channel->flags |=7055 (IEEE80211_CHAN_RADAR |7056 IEEE80211_CHAN_NO_IR);7057 if (chaninfo & WL_CHAN_PASSIVE)7058 channel->flags |=7059 IEEE80211_CHAN_NO_IR;7060 }7061 }7062 }7063 7064fail_pbuf:7065 kfree(pbuf);7066 return err;7067}7068 7069static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)7070{7071 struct brcmf_pub *drvr = cfg->pub;7072 struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);7073 struct ieee80211_supported_band *band;7074 struct brcmf_fil_bwcap_le band_bwcap;7075 struct brcmf_chanspec_list *list;7076 u8 *pbuf;7077 u32 val;7078 int err;7079 struct brcmu_chan ch;7080 u32 num_chan;7081 int i, j;7082 7083 /* verify support for bw_cap command */7084 val = WLC_BAND_5G;7085 err = brcmf_fil_iovar_int_query(ifp, "bw_cap", &val);7086 7087 if (!err) {7088 /* only set 2G bandwidth using bw_cap command */7089 band_bwcap.band = cpu_to_le32(WLC_BAND_2G);7090 band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);7091 err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,7092 sizeof(band_bwcap));7093 } else {7094 brcmf_dbg(INFO, "fallback to mimo_bw_cap\n");7095 val = WLC_N_BW_40ALL;7096 err = brcmf_fil_iovar_int_set(ifp, "mimo_bw_cap", val);7097 }7098 7099 if (!err) {7100 /* update channel info in 2G band */7101 pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);7102 7103 if (pbuf == NULL)7104 return -ENOMEM;7105 7106 ch.band = BRCMU_CHAN_BAND_2G;7107 ch.bw = BRCMU_CHAN_BW_40;7108 ch.sb = BRCMU_CHAN_SB_NONE;7109 ch.chnum = 0;7110 cfg->d11inf.encchspec(&ch);7111 7112 /* pass encoded chanspec in query */7113 *(__le16 *)pbuf = cpu_to_le16(ch.chspec);7114 7115 err = brcmf_fil_iovar_data_get(ifp, "chanspecs", pbuf,7116 BRCMF_DCMD_MEDLEN);7117 if (err) {7118 bphy_err(drvr, "get chanspecs error (%d)\n", err);7119 kfree(pbuf);7120 return err;7121 }7122 7123 band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ];7124 list = (struct brcmf_chanspec_list *)pbuf;7125 num_chan = le32_to_cpu(list->count);7126 if (num_chan > BRCMF_MAX_CHANSPEC_LIST) {7127 bphy_err(drvr, "Invalid count of channel Spec. (%u)\n",7128 num_chan);7129 kfree(pbuf);7130 return -EINVAL;7131 }7132 7133 for (i = 0; i < num_chan; i++) {7134 ch.chspec = (u16)le32_to_cpu(list->element[i]);7135 cfg->d11inf.decchspec(&ch);7136 if (WARN_ON(ch.band != BRCMU_CHAN_BAND_2G))7137 continue;7138 if (WARN_ON(ch.bw != BRCMU_CHAN_BW_40))7139 continue;7140 for (j = 0; j < band->n_channels; j++) {7141 if (band->channels[j].hw_value == ch.control_ch_num)7142 break;7143 }7144 if (WARN_ON(j == band->n_channels))7145 continue;7146 7147 brcmf_update_bw40_channel_flag(&band->channels[j], &ch);7148 }7149 kfree(pbuf);7150 }7151 return err;7152}7153 7154static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])7155{7156 struct brcmf_pub *drvr = ifp->drvr;7157 u32 band, mimo_bwcap;7158 int err;7159 7160 band = WLC_BAND_2G;7161 err = brcmf_fil_iovar_int_query(ifp, "bw_cap", &band);7162 if (!err) {7163 bw_cap[NL80211_BAND_2GHZ] = band;7164 band = WLC_BAND_5G;7165 err = brcmf_fil_iovar_int_query(ifp, "bw_cap", &band);7166 if (!err) {7167 bw_cap[NL80211_BAND_5GHZ] = band;7168 return;7169 }7170 WARN_ON(1);7171 return;7172 }7173 brcmf_dbg(INFO, "fallback to mimo_bw_cap info\n");7174 err = brcmf_fil_iovar_int_get(ifp, "mimo_bw_cap", &mimo_bwcap);7175 if (err)7176 /* assume 20MHz if firmware does not give a clue */7177 mimo_bwcap = WLC_N_BW_20ALL;7178 7179 switch (mimo_bwcap) {7180 case WLC_N_BW_40ALL:7181 bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT;7182 fallthrough;7183 case WLC_N_BW_20IN2G_40IN5G:7184 bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT;7185 fallthrough;7186 case WLC_N_BW_20ALL:7187 bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;7188 bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;7189 break;7190 default:7191 bphy_err(drvr, "invalid mimo_bw_cap value\n");7192 }7193}7194 7195static void brcmf_update_ht_cap(struct ieee80211_supported_band *band,7196 u32 bw_cap[2], u32 nchain)7197{7198 band->ht_cap.ht_supported = true;7199 if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {7200 band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;7201 band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;7202 }7203 band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;7204 band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;7205 band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;7206 band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;7207 memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);7208 band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;7209}7210 7211static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)7212{7213 u16 mcs_map;7214 int i;7215 7216 for (i = 0, mcs_map = 0xFFFF; i < nchain; i++)7217 mcs_map = (mcs_map << 2) | supp;7218 7219 return cpu_to_le16(mcs_map);7220}7221 7222static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,7223 u32 bw_cap[2], u32 nchain, u32 txstreams,7224 u32 txbf_bfe_cap, u32 txbf_bfr_cap)7225{7226 __le16 mcs_map;7227 7228 /* not allowed in 2.4G band */7229 if (band->band == NL80211_BAND_2GHZ)7230 return;7231 7232 band->vht_cap.vht_supported = true;7233 /* 80MHz is mandatory */7234 band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;7235 if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) {7236 band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;7237 band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;7238 }7239 /* all support 256-QAM */7240 mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);7241 band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;7242 band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;7243 7244 /* Beamforming support information */7245 if (txbf_bfe_cap & BRCMF_TXBF_SU_BFE_CAP)7246 band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;7247 if (txbf_bfe_cap & BRCMF_TXBF_MU_BFE_CAP)7248 band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;7249 if (txbf_bfr_cap & BRCMF_TXBF_SU_BFR_CAP)7250 band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;7251 if (txbf_bfr_cap & BRCMF_TXBF_MU_BFR_CAP)7252 band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;7253 7254 if ((txbf_bfe_cap || txbf_bfr_cap) && (txstreams > 1)) {7255 band->vht_cap.cap |=7256 (2 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);7257 band->vht_cap.cap |= ((txstreams - 1) <<7258 IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);7259 band->vht_cap.cap |=7260 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;7261 }7262}7263 7264static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)7265{7266 struct brcmf_pub *drvr = cfg->pub;7267 struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);7268 struct wiphy *wiphy = cfg_to_wiphy(cfg);7269 u32 nmode;7270 u32 vhtmode = 0;7271 u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };7272 u32 rxchain;7273 u32 nchain;7274 int err;7275 s32 i;7276 struct ieee80211_supported_band *band;7277 u32 txstreams = 0;7278 u32 txbf_bfe_cap = 0;7279 u32 txbf_bfr_cap = 0;7280 7281 (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);7282 err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);7283 if (err) {7284 bphy_err(drvr, "nmode error (%d)\n", err);7285 } else {7286 brcmf_get_bwcap(ifp, bw_cap);7287 }7288 brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",7289 nmode, vhtmode, bw_cap[NL80211_BAND_2GHZ],7290 bw_cap[NL80211_BAND_5GHZ]);7291 7292 err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);7293 if (err) {7294 /* rxchain unsupported by firmware of older chips */7295 if (err == -EBADE)7296 bphy_info_once(drvr, "rxchain unsupported\n");7297 else7298 bphy_err(drvr, "rxchain error (%d)\n", err);7299 7300 nchain = 1;7301 } else {7302 for (nchain = 0; rxchain; nchain++)7303 rxchain = rxchain & (rxchain - 1);7304 }7305 brcmf_dbg(INFO, "nchain=%d\n", nchain);7306 7307 err = brcmf_construct_chaninfo(cfg, bw_cap);7308 if (err) {7309 bphy_err(drvr, "brcmf_construct_chaninfo failed (%d)\n", err);7310 return err;7311 }7312 7313 if (vhtmode) {7314 (void)brcmf_fil_iovar_int_get(ifp, "txstreams", &txstreams);7315 (void)brcmf_fil_iovar_int_get(ifp, "txbf_bfe_cap",7316 &txbf_bfe_cap);7317 (void)brcmf_fil_iovar_int_get(ifp, "txbf_bfr_cap",7318 &txbf_bfr_cap);7319 }7320 7321 for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {7322 band = wiphy->bands[i];7323 if (band == NULL)7324 continue;7325 7326 if (nmode)7327 brcmf_update_ht_cap(band, bw_cap, nchain);7328 if (vhtmode)7329 brcmf_update_vht_cap(band, bw_cap, nchain, txstreams,7330 txbf_bfe_cap, txbf_bfr_cap);7331 }7332 7333 return 0;7334}7335 7336static const struct ieee80211_txrx_stypes7337brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {7338 [NL80211_IFTYPE_STATION] = {7339 .tx = 0xffff,7340 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |7341 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)7342 },7343 [NL80211_IFTYPE_P2P_CLIENT] = {7344 .tx = 0xffff,7345 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |7346 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)7347 },7348 [NL80211_IFTYPE_P2P_GO] = {7349 .tx = 0xffff,7350 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |7351 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |7352 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |7353 BIT(IEEE80211_STYPE_DISASSOC >> 4) |7354 BIT(IEEE80211_STYPE_AUTH >> 4) |7355 BIT(IEEE80211_STYPE_DEAUTH >> 4) |7356 BIT(IEEE80211_STYPE_ACTION >> 4)7357 },7358 [NL80211_IFTYPE_P2P_DEVICE] = {7359 .tx = 0xffff,7360 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |7361 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)7362 },7363 [NL80211_IFTYPE_AP] = {7364 .tx = 0xffff,7365 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |7366 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |7367 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |7368 BIT(IEEE80211_STYPE_DISASSOC >> 4) |7369 BIT(IEEE80211_STYPE_AUTH >> 4) |7370 BIT(IEEE80211_STYPE_DEAUTH >> 4) |7371 BIT(IEEE80211_STYPE_ACTION >> 4)7372 }7373};7374 7375/**7376 * brcmf_setup_ifmodes() - determine interface modes and combinations.7377 *7378 * @wiphy: wiphy object.7379 * @ifp: interface object needed for feat module api.7380 *7381 * The interface modes and combinations are determined dynamically here7382 * based on firmware functionality.7383 *7384 * no p2p and no mbss:7385 *7386 * #STA <= 1, #AP <= 1, channels = 1, 2 total7387 *7388 * no p2p and mbss:7389 *7390 * #STA <= 1, #AP <= 1, channels = 1, 2 total7391 * #AP <= 4, matching BI, channels = 1, 4 total7392 *7393 * no p2p and rsdb:7394 * #STA <= 1, #AP <= 2, channels = 2, 4 total7395 *7396 * p2p, no mchan, and mbss:7397 *7398 * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total7399 * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total7400 * #AP <= 4, matching BI, channels = 1, 4 total7401 *7402 * p2p, mchan, and mbss:7403 *7404 * #STA <= 2, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total7405 * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total7406 * #AP <= 4, matching BI, channels = 1, 4 total7407 *7408 * p2p, rsdb, and no mbss:7409 * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 2, AP <= 2,7410 * channels = 2, 4 total7411 */7412static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)7413{7414 struct ieee80211_iface_combination *combo = NULL;7415 struct ieee80211_iface_limit *c0_limits = NULL;7416 struct ieee80211_iface_limit *p2p_limits = NULL;7417 struct ieee80211_iface_limit *mbss_limits = NULL;7418 bool mon_flag, mbss, p2p, rsdb, mchan;7419 int i, c, n_combos, n_limits;7420 7421 mon_flag = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FLAG);7422 mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);7423 p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);7424 rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB);7425 mchan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN);7426 7427 n_combos = 1 + !!(p2p && !rsdb) + !!mbss;7428 combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL);7429 if (!combo)7430 goto err;7431 7432 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |7433 BIT(NL80211_IFTYPE_ADHOC) |7434 BIT(NL80211_IFTYPE_AP);7435 if (mon_flag)7436 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);7437 if (p2p)7438 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |7439 BIT(NL80211_IFTYPE_P2P_GO) |7440 BIT(NL80211_IFTYPE_P2P_DEVICE);7441 7442 c = 0;7443 i = 0;7444 n_limits = 1 + mon_flag + (p2p ? 2 : 0) + (rsdb || !p2p);7445 c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL);7446 if (!c0_limits)7447 goto err;7448 7449 combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan));7450 c0_limits[i].max = 1 + (p2p && mchan);7451 c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);7452 if (mon_flag) {7453 c0_limits[i].max = 1;7454 c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR);7455 }7456 if (p2p) {7457 c0_limits[i].max = 1;7458 c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);7459 c0_limits[i].max = 1 + rsdb;7460 c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |7461 BIT(NL80211_IFTYPE_P2P_GO);7462 }7463 if (p2p && rsdb) {7464 c0_limits[i].max = 2;7465 c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);7466 combo[c].max_interfaces = 4;7467 } else if (p2p) {7468 combo[c].max_interfaces = i;7469 } else if (rsdb) {7470 c0_limits[i].max = 2;7471 c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);7472 combo[c].max_interfaces = 3;7473 } else {7474 c0_limits[i].max = 1;7475 c0_limits[i++].types = BIT(NL80211_IFTYPE_AP);7476 combo[c].max_interfaces = i;7477 }7478 combo[c].n_limits = i;7479 combo[c].limits = c0_limits;7480 7481 if (p2p && !rsdb) {7482 c++;7483 i = 0;7484 p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL);7485 if (!p2p_limits)7486 goto err;7487 p2p_limits[i].max = 1;7488 p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION);7489 p2p_limits[i].max = 1;7490 p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP);7491 p2p_limits[i].max = 1;7492 p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT);7493 p2p_limits[i].max = 1;7494 p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);7495 combo[c].num_different_channels = 1;7496 combo[c].max_interfaces = i;7497 combo[c].n_limits = i;7498 combo[c].limits = p2p_limits;7499 }7500 7501 if (mbss) {7502 c++;7503 i = 0;7504 n_limits = 1 + mon_flag;7505 mbss_limits = kcalloc(n_limits, sizeof(*mbss_limits),7506 GFP_KERNEL);7507 if (!mbss_limits)7508 goto err;7509 mbss_limits[i].max = 4;7510 mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP);7511 if (mon_flag) {7512 mbss_limits[i].max = 1;7513 mbss_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR);7514 }7515 combo[c].beacon_int_infra_match = true;7516 combo[c].num_different_channels = 1;7517 combo[c].max_interfaces = 4 + mon_flag;7518 combo[c].n_limits = i;7519 combo[c].limits = mbss_limits;7520 }7521 7522 wiphy->n_iface_combinations = n_combos;7523 wiphy->iface_combinations = combo;7524 return 0;7525 7526err:7527 kfree(c0_limits);7528 kfree(p2p_limits);7529 kfree(mbss_limits);7530 kfree(combo);7531 return -ENOMEM;7532}7533 7534#ifdef CONFIG_PM7535static const struct wiphy_wowlan_support brcmf_wowlan_support = {7536 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,7537 .n_patterns = BRCMF_WOWL_MAXPATTERNS,7538 .pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE,7539 .pattern_min_len = 1,7540 .max_pkt_offset = 1500,7541};7542#endif7543 7544static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp)7545{7546#ifdef CONFIG_PM7547 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);7548 struct brcmf_pub *drvr = cfg->pub;7549 struct wiphy_wowlan_support *wowl;7550 7551 wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support),7552 GFP_KERNEL);7553 if (!wowl) {7554 bphy_err(drvr, "only support basic wowlan features\n");7555 wiphy->wowlan = &brcmf_wowlan_support;7556 return;7557 }7558 7559 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {7560 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {7561 wowl->flags |= WIPHY_WOWLAN_NET_DETECT;7562 wowl->max_nd_match_sets = BRCMF_PNO_MAX_PFN_COUNT;7563 init_waitqueue_head(&cfg->wowl.nd_data_wait);7564 }7565 }7566 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {7567 wowl->flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;7568 wowl->flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;7569 }7570 7571 wiphy->wowlan = wowl;7572#endif7573}7574 7575static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)7576{7577 struct brcmf_pub *drvr = ifp->drvr;7578 const struct ieee80211_iface_combination *combo;7579 struct ieee80211_supported_band *band;7580 u16 max_interfaces = 0;7581 bool gscan;7582 __le32 bandlist[3];7583 u32 n_bands;7584 int err, i;7585 7586 wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;7587 wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;7588 wiphy->max_num_pmkids = BRCMF_MAXPMKID;7589 7590 err = brcmf_setup_ifmodes(wiphy, ifp);7591 if (err)7592 return err;7593 7594 for (i = 0, combo = wiphy->iface_combinations;7595 i < wiphy->n_iface_combinations; i++, combo++) {7596 max_interfaces = max(max_interfaces, combo->max_interfaces);7597 }7598 7599 for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses);7600 i++) {7601 u8 *addr = drvr->addresses[i].addr;7602 7603 memcpy(addr, drvr->mac, ETH_ALEN);7604 if (i) {7605 addr[0] |= BIT(1);7606 addr[ETH_ALEN - 1] ^= i;7607 }7608 }7609 wiphy->addresses = drvr->addresses;7610 wiphy->n_addresses = i;7611 7612 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;7613 wiphy->cipher_suites = brcmf_cipher_suites;7614 wiphy->n_cipher_suites = ARRAY_SIZE(brcmf_cipher_suites);7615 if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))7616 wiphy->n_cipher_suites--;7617 wiphy->bss_select_support = BIT(NL80211_BSS_SELECT_ATTR_RSSI) |7618 BIT(NL80211_BSS_SELECT_ATTR_BAND_PREF) |7619 BIT(NL80211_BSS_SELECT_ATTR_RSSI_ADJUST);7620 7621 wiphy->flags |= WIPHY_FLAG_NETNS_OK |7622 WIPHY_FLAG_PS_ON_BY_DEFAULT |7623 WIPHY_FLAG_HAVE_AP_SME |7624 WIPHY_FLAG_OFFCHAN_TX |7625 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;7626 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))7627 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;7628 if (!ifp->drvr->settings->roamoff)7629 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;7630 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {7631 wiphy_ext_feature_set(wiphy,7632 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK);7633 wiphy_ext_feature_set(wiphy,7634 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X);7635 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE))7636 wiphy_ext_feature_set(wiphy,7637 NL80211_EXT_FEATURE_SAE_OFFLOAD);7638 }7639 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWAUTH)) {7640 wiphy_ext_feature_set(wiphy,7641 NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK);7642 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SAE))7643 wiphy_ext_feature_set(wiphy,7644 NL80211_EXT_FEATURE_SAE_OFFLOAD_AP);7645 }7646 wiphy->mgmt_stypes = brcmf_txrx_stypes;7647 wiphy->max_remain_on_channel_duration = 5000;7648 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {7649 gscan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GSCAN);7650 brcmf_pno_wiphy_params(wiphy, gscan);7651 }7652 /* vendor commands/events support */7653 wiphy->vendor_commands = brcmf_vendor_cmds;7654 wiphy->n_vendor_commands = BRCMF_VNDR_CMDS_LAST - 1;7655 7656 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL))7657 brcmf_wiphy_wowl_params(wiphy, ifp);7658 err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist,7659 sizeof(bandlist));7660 if (err) {7661 bphy_err(drvr, "could not obtain band info: err=%d\n", err);7662 return err;7663 }7664 /* first entry in bandlist is number of bands */7665 n_bands = le32_to_cpu(bandlist[0]);7666 for (i = 1; i <= n_bands && i < ARRAY_SIZE(bandlist); i++) {7667 if (bandlist[i] == cpu_to_le32(WLC_BAND_2G)) {7668 band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz),7669 GFP_KERNEL);7670 if (!band)7671 return -ENOMEM;7672 7673 band->channels = kmemdup(&__wl_2ghz_channels,7674 sizeof(__wl_2ghz_channels),7675 GFP_KERNEL);7676 if (!band->channels) {7677 kfree(band);7678 return -ENOMEM;7679 }7680 7681 band->n_channels = ARRAY_SIZE(__wl_2ghz_channels);7682 wiphy->bands[NL80211_BAND_2GHZ] = band;7683 }7684 if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) {7685 band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz),7686 GFP_KERNEL);7687 if (!band)7688 return -ENOMEM;7689 7690 band->channels = kmemdup(&__wl_5ghz_channels,7691 sizeof(__wl_5ghz_channels),7692 GFP_KERNEL);7693 if (!band->channels) {7694 kfree(band);7695 return -ENOMEM;7696 }7697 7698 band->n_channels = ARRAY_SIZE(__wl_5ghz_channels);7699 wiphy->bands[NL80211_BAND_5GHZ] = band;7700 }7701 }7702 7703 if (wiphy->bands[NL80211_BAND_5GHZ] &&7704 brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DOT11H))7705 wiphy_ext_feature_set(wiphy,7706 NL80211_EXT_FEATURE_DFS_OFFLOAD);7707 7708 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);7709 7710 wiphy_read_of_freq_limits(wiphy);7711 7712 return 0;7713}7714 7715static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)7716{7717 struct brcmf_pub *drvr = cfg->pub;7718 struct net_device *ndev;7719 struct wireless_dev *wdev;7720 struct brcmf_if *ifp;7721 s32 power_mode;7722 s32 err = 0;7723 7724 if (cfg->dongle_up)7725 return err;7726 7727 ndev = cfg_to_ndev(cfg);7728 wdev = ndev->ieee80211_ptr;7729 ifp = netdev_priv(ndev);7730 7731 /* make sure RF is ready for work */7732 brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);7733 7734 brcmf_dongle_scantime(ifp);7735 7736 power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;7737 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);7738 if (err)7739 goto default_conf_out;7740 brcmf_dbg(INFO, "power save set to %s\n",7741 (power_mode ? "enabled" : "disabled"));7742 7743 err = brcmf_dongle_roam(ifp);7744 if (err)7745 goto default_conf_out;7746 err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,7747 NULL);7748 if (err)7749 goto default_conf_out;7750 7751 brcmf_configure_arp_nd_offload(ifp, true);7752 7753 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1);7754 if (err) {7755 bphy_err(drvr, "failed to set frameburst mode\n");7756 goto default_conf_out;7757 }7758 7759 cfg->dongle_up = true;7760default_conf_out:7761 7762 return err;7763 7764}7765 7766static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)7767{7768 set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);7769 7770 return brcmf_config_dongle(ifp->drvr->config);7771}7772 7773static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)7774{7775 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;7776 7777 /*7778 * While going down, if associated with AP disassociate7779 * from AP to save power7780 */7781 if (check_vif_up(ifp->vif)) {7782 brcmf_link_down(ifp->vif, WLAN_REASON_UNSPECIFIED, true);7783 7784 /* Make sure WPA_Supplicant receives all the event7785 generated due to DISASSOC call to the fw to keep7786 the state fw and WPA_Supplicant state consistent7787 */7788 brcmf_delay(500);7789 }7790 7791 brcmf_abort_scanning(cfg);7792 clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);7793 7794 return 0;7795}7796 7797s32 brcmf_cfg80211_up(struct net_device *ndev)7798{7799 struct brcmf_if *ifp = netdev_priv(ndev);7800 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;7801 s32 err = 0;7802 7803 mutex_lock(&cfg->usr_sync);7804 err = __brcmf_cfg80211_up(ifp);7805 mutex_unlock(&cfg->usr_sync);7806 7807 return err;7808}7809 7810s32 brcmf_cfg80211_down(struct net_device *ndev)7811{7812 struct brcmf_if *ifp = netdev_priv(ndev);7813 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;7814 s32 err = 0;7815 7816 mutex_lock(&cfg->usr_sync);7817 err = __brcmf_cfg80211_down(ifp);7818 mutex_unlock(&cfg->usr_sync);7819 7820 return err;7821}7822 7823enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp)7824{7825 struct wireless_dev *wdev = &ifp->vif->wdev;7826 7827 return wdev->iftype;7828}7829 7830bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,7831 unsigned long state)7832{7833 struct brcmf_cfg80211_vif *vif;7834 7835 list_for_each_entry(vif, &cfg->vif_list, list) {7836 if (test_bit(state, &vif->sme_state))7837 return true;7838 }7839 return false;7840}7841 7842static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event,7843 u8 action)7844{7845 u8 evt_action;7846 7847 spin_lock(&event->vif_event_lock);7848 evt_action = event->action;7849 spin_unlock(&event->vif_event_lock);7850 return evt_action == action;7851}7852 7853void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,7854 struct brcmf_cfg80211_vif *vif)7855{7856 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;7857 7858 spin_lock(&event->vif_event_lock);7859 event->vif = vif;7860 event->action = 0;7861 spin_unlock(&event->vif_event_lock);7862}7863 7864bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg)7865{7866 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;7867 bool armed;7868 7869 spin_lock(&event->vif_event_lock);7870 armed = event->vif != NULL;7871 spin_unlock(&event->vif_event_lock);7872 7873 return armed;7874}7875 7876int brcmf_cfg80211_wait_vif_event(struct brcmf_cfg80211_info *cfg,7877 u8 action, ulong timeout)7878{7879 struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;7880 7881 return wait_event_timeout(event->vif_wq,7882 vif_event_equals(event, action), timeout);7883}7884 7885static bool brmcf_use_iso3166_ccode_fallback(struct brcmf_pub *drvr)7886{7887 if (drvr->settings->trivial_ccode_map)7888 return true;7889 7890 switch (drvr->bus_if->chip) {7891 case BRCM_CC_43430_CHIP_ID:7892 case BRCM_CC_4345_CHIP_ID:7893 case BRCM_CC_4356_CHIP_ID:7894 case BRCM_CC_43602_CHIP_ID:7895 return true;7896 default:7897 return false;7898 }7899}7900 7901static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2],7902 struct brcmf_fil_country_le *ccreq)7903{7904 struct brcmfmac_pd_cc *country_codes;7905 struct brcmfmac_pd_cc_entry *cc;7906 s32 found_index;7907 int i;7908 7909 if ((alpha2[0] == ccreq->country_abbrev[0]) &&7910 (alpha2[1] == ccreq->country_abbrev[1])) {7911 brcmf_dbg(TRACE, "Country code already set\n");7912 return -EAGAIN;7913 }7914 7915 country_codes = drvr->settings->country_codes;7916 if (!country_codes) {7917 if (brmcf_use_iso3166_ccode_fallback(drvr)) {7918 brcmf_dbg(TRACE, "No country codes configured for device, using ISO3166 code and 0 rev\n");7919 memset(ccreq, 0, sizeof(*ccreq));7920 ccreq->country_abbrev[0] = alpha2[0];7921 ccreq->country_abbrev[1] = alpha2[1];7922 ccreq->ccode[0] = alpha2[0];7923 ccreq->ccode[1] = alpha2[1];7924 return 0;7925 }7926 7927 brcmf_dbg(TRACE, "No country codes configured for device\n");7928 return -EINVAL;7929 }7930 7931 found_index = -1;7932 for (i = 0; i < country_codes->table_size; i++) {7933 cc = &country_codes->table[i];7934 if ((cc->iso3166[0] == '\0') && (found_index == -1))7935 found_index = i;7936 if ((cc->iso3166[0] == alpha2[0]) &&7937 (cc->iso3166[1] == alpha2[1])) {7938 found_index = i;7939 break;7940 }7941 }7942 if (found_index == -1) {7943 brcmf_dbg(TRACE, "No country code match found\n");7944 return -EINVAL;7945 }7946 memset(ccreq, 0, sizeof(*ccreq));7947 ccreq->rev = cpu_to_le32(country_codes->table[found_index].rev);7948 memcpy(ccreq->ccode, country_codes->table[found_index].cc,7949 BRCMF_COUNTRY_BUF_SZ);7950 ccreq->country_abbrev[0] = alpha2[0];7951 ccreq->country_abbrev[1] = alpha2[1];7952 ccreq->country_abbrev[2] = 0;7953 7954 return 0;7955}7956 7957static int7958brcmf_parse_dump_obss(char *buf, struct brcmf_dump_survey *survey)7959{7960 int i;7961 char *token;7962 char delim[] = "\n ";7963 unsigned long val;7964 int err = 0;7965 7966 token = strsep(&buf, delim);7967 while (token) {7968 if (!strcmp(token, "OBSS")) {7969 for (i = 0; i < OBSS_TOKEN_IDX; i++)7970 token = strsep(&buf, delim);7971 err = kstrtoul(token, 10, &val);7972 if (err)7973 break;7974 survey->obss = val;7975 }7976 7977 if (!strcmp(token, "IBSS")) {7978 for (i = 0; i < IBSS_TOKEN_IDX; i++)7979 token = strsep(&buf, delim);7980 err = kstrtoul(token, 10, &val);7981 if (err)7982 break;7983 survey->ibss = val;7984 }7985 7986 if (!strcmp(token, "TXDur")) {7987 for (i = 0; i < TX_TOKEN_IDX; i++)7988 token = strsep(&buf, delim);7989 err = kstrtoul(token, 10, &val);7990 if (err)7991 break;7992 survey->tx = val;7993 }7994 7995 if (!strcmp(token, "Category")) {7996 for (i = 0; i < CTG_TOKEN_IDX; i++)7997 token = strsep(&buf, delim);7998 err = kstrtoul(token, 10, &val);7999 if (err)8000 break;8001 survey->no_ctg = val;8002 }8003 8004 if (!strcmp(token, "Packet")) {8005 for (i = 0; i < PKT_TOKEN_IDX; i++)8006 token = strsep(&buf, delim);8007 err = kstrtoul(token, 10, &val);8008 if (err)8009 break;8010 survey->no_pckt = val;8011 }8012 8013 if (!strcmp(token, "Opp(time):")) {8014 for (i = 0; i < IDLE_TOKEN_IDX; i++)8015 token = strsep(&buf, delim);8016 err = kstrtoul(token, 10, &val);8017 if (err)8018 break;8019 survey->idle = val;8020 }8021 8022 token = strsep(&buf, delim);8023 }8024 8025 return err;8026}8027 8028static int8029brcmf_dump_obss(struct brcmf_if *ifp, struct cca_msrmnt_query req,8030 struct brcmf_dump_survey *survey)8031{8032 struct cca_stats_n_flags *results;8033 char *buf;8034 int err;8035 8036 buf = kzalloc(sizeof(char) * BRCMF_DCMD_MEDLEN, GFP_KERNEL);8037 if (!buf)8038 return -ENOMEM;8039 8040 memcpy(buf, &req, sizeof(struct cca_msrmnt_query));8041 err = brcmf_fil_iovar_data_get(ifp, "dump_obss",8042 buf, BRCMF_DCMD_MEDLEN);8043 if (err) {8044 brcmf_err("dump_obss error (%d)\n", err);8045 err = -EINVAL;8046 goto exit;8047 }8048 results = (struct cca_stats_n_flags *)(buf);8049 8050 if (req.msrmnt_query)8051 brcmf_parse_dump_obss(results->buf, survey);8052 8053exit:8054 kfree(buf);8055 return err;8056}8057 8058static s328059brcmf_set_channel(struct brcmf_cfg80211_info *cfg, struct ieee80211_channel *chan)8060{8061 u16 chspec = 0;8062 int err = 0;8063 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));8064 8065 if (chan->flags & IEEE80211_CHAN_DISABLED)8066 return -EINVAL;8067 8068 /* set_channel */8069 chspec = channel_to_chanspec(&cfg->d11inf, chan);8070 if (chspec != INVCHANSPEC) {8071 err = brcmf_fil_iovar_int_set(ifp, "chanspec", chspec);8072 if (err) {8073 brcmf_err("set chanspec 0x%04x fail, reason %d\n", chspec, err);8074 err = -EINVAL;8075 }8076 } else {8077 brcmf_err("failed to convert host chanspec to fw chanspec\n");8078 err = -EINVAL;8079 }8080 8081 return err;8082}8083 8084static int8085brcmf_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,8086 int idx, struct survey_info *info)8087{8088 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);8089 struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));8090 struct brcmf_dump_survey survey = {};8091 struct ieee80211_supported_band *band;8092 enum nl80211_band band_id;8093 struct cca_msrmnt_query req;8094 u32 noise;8095 int err;8096 8097 brcmf_dbg(TRACE, "Enter: channel idx=%d\n", idx);8098 8099 /* Do not run survey when VIF in CONNECTING / CONNECTED states */8100 if ((test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) ||8101 (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state))) {8102 return -EBUSY;8103 }8104 8105 for (band_id = 0; band_id < NUM_NL80211_BANDS; band_id++) {8106 band = wiphy->bands[band_id];8107 if (!band)8108 continue;8109 if (idx >= band->n_channels) {8110 idx -= band->n_channels;8111 continue;8112 }8113 8114 info->channel = &band->channels[idx];8115 break;8116 }8117 if (band_id == NUM_NL80211_BANDS)8118 return -ENOENT;8119 8120 /* Setting current channel to the requested channel */8121 info->filled = 0;8122 if (brcmf_set_channel(cfg, info->channel))8123 return 0;8124 8125 /* Disable mpc */8126 brcmf_set_mpc(ifp, 0);8127 8128 /* Set interface up, explicitly. */8129 err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);8130 if (err) {8131 brcmf_err("set interface up failed, err = %d\n", err);8132 goto exit;8133 }8134 8135 /* Get noise value */8136 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PHY_NOISE, &noise);8137 if (err) {8138 brcmf_err("Get Phy Noise failed, use dummy value\n");8139 noise = CHAN_NOISE_DUMMY;8140 }8141 8142 /* Start Measurement for obss stats on current channel */8143 req.msrmnt_query = 0;8144 req.time_req = ACS_MSRMNT_DELAY;8145 err = brcmf_dump_obss(ifp, req, &survey);8146 if (err)8147 goto exit;8148 8149 /* Add 10 ms for IOVAR completion */8150 msleep(ACS_MSRMNT_DELAY + 10);8151 8152 /* Issue IOVAR to collect measurement results */8153 req.msrmnt_query = 1;8154 err = brcmf_dump_obss(ifp, req, &survey);8155 if (err)8156 goto exit;8157 8158 info->noise = noise;8159 info->time = ACS_MSRMNT_DELAY;8160 info->time_busy = ACS_MSRMNT_DELAY - survey.idle;8161 info->time_rx = survey.obss + survey.ibss + survey.no_ctg +8162 survey.no_pckt;8163 info->time_tx = survey.tx;8164 info->filled = SURVEY_INFO_NOISE_DBM | SURVEY_INFO_TIME |8165 SURVEY_INFO_TIME_BUSY | SURVEY_INFO_TIME_RX |8166 SURVEY_INFO_TIME_TX;8167 8168 brcmf_dbg(INFO, "OBSS dump: channel %d: survey duration %d\n",8169 ieee80211_frequency_to_channel(info->channel->center_freq),8170 ACS_MSRMNT_DELAY);8171 brcmf_dbg(INFO, "noise(%d) busy(%llu) rx(%llu) tx(%llu)\n",8172 info->noise, info->time_busy, info->time_rx, info->time_tx);8173 8174exit:8175 if (!brcmf_is_apmode(ifp->vif))8176 brcmf_set_mpc(ifp, 1);8177 return err;8178}8179 8180static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,8181 struct regulatory_request *req)8182{8183 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);8184 struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);8185 struct brcmf_pub *drvr = cfg->pub;8186 struct brcmf_fil_country_le ccreq;8187 s32 err;8188 int i;8189 8190 /* The country code gets set to "00" by default at boot, ignore */8191 if (req->alpha2[0] == '0' && req->alpha2[1] == '0')8192 return;8193 8194 /* ignore non-ISO3166 country codes */8195 for (i = 0; i < 2; i++)8196 if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {8197 bphy_err(drvr, "not an ISO3166 code (0x%02x 0x%02x)\n",8198 req->alpha2[0], req->alpha2[1]);8199 return;8200 }8201 8202 brcmf_dbg(TRACE, "Enter: initiator=%d, alpha=%c%c\n", req->initiator,8203 req->alpha2[0], req->alpha2[1]);8204 8205 err = brcmf_fil_iovar_data_get(ifp, "country", &ccreq, sizeof(ccreq));8206 if (err) {8207 bphy_err(drvr, "Country code iovar returned err = %d\n", err);8208 return;8209 }8210 8211 err = brcmf_translate_country_code(ifp->drvr, req->alpha2, &ccreq);8212 if (err)8213 return;8214 8215 err = brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));8216 if (err) {8217 bphy_err(drvr, "Firmware rejected country setting\n");8218 return;8219 }8220 brcmf_setup_wiphybands(cfg);8221}8222 8223static void brcmf_free_wiphy(struct wiphy *wiphy)8224{8225 int i;8226 8227 if (!wiphy)8228 return;8229 8230 if (wiphy->iface_combinations) {8231 for (i = 0; i < wiphy->n_iface_combinations; i++)8232 kfree(wiphy->iface_combinations[i].limits);8233 }8234 kfree(wiphy->iface_combinations);8235 if (wiphy->bands[NL80211_BAND_2GHZ]) {8236 kfree(wiphy->bands[NL80211_BAND_2GHZ]->channels);8237 kfree(wiphy->bands[NL80211_BAND_2GHZ]);8238 }8239 if (wiphy->bands[NL80211_BAND_5GHZ]) {8240 kfree(wiphy->bands[NL80211_BAND_5GHZ]->channels);8241 kfree(wiphy->bands[NL80211_BAND_5GHZ]);8242 }8243#if IS_ENABLED(CONFIG_PM)8244 if (wiphy->wowlan != &brcmf_wowlan_support)8245 kfree(wiphy->wowlan);8246#endif8247}8248 8249struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,8250 struct cfg80211_ops *ops,8251 bool p2pdev_forced)8252{8253 struct wiphy *wiphy = drvr->wiphy;8254 struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;8255 struct brcmf_cfg80211_info *cfg;8256 struct brcmf_cfg80211_vif *vif;8257 struct brcmf_if *ifp;8258 s32 err = 0;8259 s32 io_type;8260 u16 *cap = NULL;8261 8262 if (!ndev) {8263 bphy_err(drvr, "ndev is invalid\n");8264 return NULL;8265 }8266 8267 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);8268 if (!cfg) {8269 bphy_err(drvr, "Could not allocate wiphy device\n");8270 return NULL;8271 }8272 8273 cfg->wiphy = wiphy;8274 cfg->pub = drvr;8275 init_vif_event(&cfg->vif_event);8276 INIT_LIST_HEAD(&cfg->vif_list);8277 8278 vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION);8279 if (IS_ERR(vif))8280 goto wiphy_out;8281 8282 ifp = netdev_priv(ndev);8283 vif->ifp = ifp;8284 vif->wdev.netdev = ndev;8285 ndev->ieee80211_ptr = &vif->wdev;8286 SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));8287 8288 err = wl_init_priv(cfg);8289 if (err) {8290 bphy_err(drvr, "Failed to init iwm_priv (%d)\n", err);8291 brcmf_free_vif(vif);8292 goto wiphy_out;8293 }8294 ifp->vif = vif;8295 8296 /* determine d11 io type before wiphy setup */8297 err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION, &io_type);8298 if (err) {8299 bphy_err(drvr, "Failed to get D11 version (%d)\n", err);8300 goto priv_out;8301 }8302 cfg->d11inf.io_type = (u8)io_type;8303 brcmu_d11_attach(&cfg->d11inf);8304 8305 /* regulatory notifer below needs access to cfg so8306 * assign it now.8307 */8308 drvr->config = cfg;8309 8310 err = brcmf_setup_wiphy(wiphy, ifp);8311 if (err < 0)8312 goto priv_out;8313 8314 brcmf_dbg(INFO, "Registering custom regulatory\n");8315 wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;8316 wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;8317 wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);8318 8319 /* firmware defaults to 40MHz disabled in 2G band. We signal8320 * cfg80211 here that we do and have it decide we can enable8321 * it. But first check if device does support 2G operation.8322 */8323 if (wiphy->bands[NL80211_BAND_2GHZ]) {8324 cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap;8325 *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;8326 }8327#ifdef CONFIG_PM8328 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))8329 ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;8330#endif8331 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_DUMP_OBSS))8332 ops->dump_survey = brcmf_cfg80211_dump_survey;8333 8334 err = wiphy_register(wiphy);8335 if (err < 0) {8336 bphy_err(drvr, "Could not register wiphy device (%d)\n", err);8337 goto priv_out;8338 }8339 8340 err = brcmf_setup_wiphybands(cfg);8341 if (err) {8342 bphy_err(drvr, "Setting wiphy bands failed (%d)\n", err);8343 goto wiphy_unreg_out;8344 }8345 8346 /* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),8347 * setup 40MHz in 2GHz band and enable OBSS scanning.8348 */8349 if (cap && (*cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) {8350 err = brcmf_enable_bw40_2g(cfg);8351 if (!err)8352 err = brcmf_fil_iovar_int_set(ifp, "obss_coex",8353 BRCMF_OBSS_COEX_AUTO);8354 else8355 *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;8356 }8357 8358 err = brcmf_fweh_activate_events(ifp);8359 if (err) {8360 bphy_err(drvr, "FWEH activation failed (%d)\n", err);8361 goto wiphy_unreg_out;8362 }8363 8364 err = brcmf_p2p_attach(cfg, p2pdev_forced);8365 if (err) {8366 bphy_err(drvr, "P2P initialisation failed (%d)\n", err);8367 goto wiphy_unreg_out;8368 }8369 err = brcmf_btcoex_attach(cfg);8370 if (err) {8371 bphy_err(drvr, "BT-coex initialisation failed (%d)\n", err);8372 brcmf_p2p_detach(&cfg->p2p);8373 goto wiphy_unreg_out;8374 }8375 err = brcmf_pno_attach(cfg);8376 if (err) {8377 bphy_err(drvr, "PNO initialisation failed (%d)\n", err);8378 brcmf_btcoex_detach(cfg);8379 brcmf_p2p_detach(&cfg->p2p);8380 goto wiphy_unreg_out;8381 }8382 8383 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) {8384 err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);8385 if (err) {8386 brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);8387 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;8388 } else {8389 brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,8390 brcmf_notify_tdls_peer_event);8391 }8392 }8393 8394 /* (re-) activate FWEH event handling */8395 err = brcmf_fweh_activate_events(ifp);8396 if (err) {8397 bphy_err(drvr, "FWEH activation failed (%d)\n", err);8398 goto detach;8399 }8400 8401 /* Fill in some of the advertised nl80211 supported features */8402 if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) {8403 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;8404#ifdef CONFIG_PM8405 if (wiphy->wowlan &&8406 wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT)8407 wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;8408#endif8409 }8410 8411 return cfg;8412 8413detach:8414 brcmf_pno_detach(cfg);8415 brcmf_btcoex_detach(cfg);8416 brcmf_p2p_detach(&cfg->p2p);8417wiphy_unreg_out:8418 wiphy_unregister(cfg->wiphy);8419priv_out:8420 wl_deinit_priv(cfg);8421 brcmf_free_vif(vif);8422 ifp->vif = NULL;8423wiphy_out:8424 brcmf_free_wiphy(wiphy);8425 kfree(cfg);8426 return NULL;8427}8428 8429void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)8430{8431 if (!cfg)8432 return;8433 8434 brcmf_pno_detach(cfg);8435 brcmf_btcoex_detach(cfg);8436 wiphy_unregister(cfg->wiphy);8437 wl_deinit_priv(cfg);8438 cancel_work_sync(&cfg->escan_timeout_work);8439 brcmf_free_wiphy(cfg->wiphy);8440 kfree(cfg);8441}8442