brintos

brintos / linux-shallow public Read only

0
0
Text · 228.3 KiB · 349aa34 Raw
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, &params);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, &params);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(&params_le->ssid_le, &params_v2_le->ssid_le,1051	       sizeof(params_le->ssid_le));1052	memcpy(&params_le->bssid, &params_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(&params_le->channel_list[0],1074	       &params_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(&params_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, &params_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						     &params_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(&params_v2_le, &params_le);1200			err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,1201						     &params_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, &params->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(&params->params_v2_le, &params_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						       &params->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(&params, 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, &params);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", &gtk_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