brintos

brintos / linux-shallow public Read only

0
0
Text · 135.6 KiB · fca3eea Raw
4932 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * NXP Wireless LAN device driver: CFG802114 *5 * Copyright 2011-2020 NXP6 */7 8#include "cfg80211.h"9#include "main.h"10#include "11n.h"11#include "wmm.h"12 13static char *reg_alpha2;14module_param(reg_alpha2, charp, 0);15 16static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {17	{18		.max = MWIFIEX_MAX_BSS_NUM,19		.types = BIT(NL80211_IFTYPE_STATION) |20				   BIT(NL80211_IFTYPE_P2P_GO) |21				   BIT(NL80211_IFTYPE_P2P_CLIENT) |22				   BIT(NL80211_IFTYPE_AP),23	},24};25 26static const struct ieee80211_iface_combination27mwifiex_iface_comb_ap_sta = {28	.limits = mwifiex_ap_sta_limits,29	.num_different_channels = 1,30	.n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),31	.max_interfaces = MWIFIEX_MAX_BSS_NUM,32	.beacon_int_infra_match = true,33	.radar_detect_widths =	BIT(NL80211_CHAN_WIDTH_20_NOHT) |34				BIT(NL80211_CHAN_WIDTH_20) |35				BIT(NL80211_CHAN_WIDTH_40),36};37 38static const struct ieee80211_iface_combination39mwifiex_iface_comb_ap_sta_vht = {40	.limits = mwifiex_ap_sta_limits,41	.num_different_channels = 1,42	.n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),43	.max_interfaces = MWIFIEX_MAX_BSS_NUM,44	.beacon_int_infra_match = true,45	.radar_detect_widths =	BIT(NL80211_CHAN_WIDTH_20_NOHT) |46				BIT(NL80211_CHAN_WIDTH_20) |47				BIT(NL80211_CHAN_WIDTH_40) |48				BIT(NL80211_CHAN_WIDTH_80),49};50 51static const struct52ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {53	.limits = mwifiex_ap_sta_limits,54	.num_different_channels = 2,55	.n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),56	.max_interfaces = MWIFIEX_MAX_BSS_NUM,57	.beacon_int_infra_match = true,58};59 60/*61 * This function maps the nl802.11 channel type into driver channel type.62 *63 * The mapping is as follows -64 *      NL80211_CHAN_NO_HT     -> IEEE80211_HT_PARAM_CHA_SEC_NONE65 *      NL80211_CHAN_HT20      -> IEEE80211_HT_PARAM_CHA_SEC_NONE66 *      NL80211_CHAN_HT40PLUS  -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE67 *      NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW68 *      Others                 -> IEEE80211_HT_PARAM_CHA_SEC_NONE69 */70u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)71{72	switch (chan_type) {73	case NL80211_CHAN_NO_HT:74	case NL80211_CHAN_HT20:75		return IEEE80211_HT_PARAM_CHA_SEC_NONE;76	case NL80211_CHAN_HT40PLUS:77		return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;78	case NL80211_CHAN_HT40MINUS:79		return IEEE80211_HT_PARAM_CHA_SEC_BELOW;80	default:81		return IEEE80211_HT_PARAM_CHA_SEC_NONE;82	}83}84 85/* This function maps IEEE HT secondary channel type to NL80211 channel type86 */87u8 mwifiex_get_chan_type(struct mwifiex_private *priv)88{89	struct mwifiex_channel_band channel_band;90	int ret;91 92	ret = mwifiex_get_chan_info(priv, &channel_band);93 94	if (!ret) {95		switch (channel_band.band_config.chan_width) {96		case CHAN_BW_20MHZ:97			if (IS_11N_ENABLED(priv))98				return NL80211_CHAN_HT20;99			else100				return NL80211_CHAN_NO_HT;101		case CHAN_BW_40MHZ:102			if (channel_band.band_config.chan2_offset ==103			    SEC_CHAN_ABOVE)104				return NL80211_CHAN_HT40PLUS;105			else106				return NL80211_CHAN_HT40MINUS;107		default:108			return NL80211_CHAN_HT20;109		}110	}111 112	return NL80211_CHAN_HT20;113}114 115/*116 * This function checks whether WEP is set.117 */118static int119mwifiex_is_alg_wep(u32 cipher)120{121	switch (cipher) {122	case WLAN_CIPHER_SUITE_WEP40:123	case WLAN_CIPHER_SUITE_WEP104:124		return 1;125	default:126		break;127	}128 129	return 0;130}131 132/*133 * This function retrieves the private structure from kernel wiphy structure.134 */135static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)136{137	return (void *) (*(unsigned long *) wiphy_priv(wiphy));138}139 140/*141 * CFG802.11 operation handler to delete a network key.142 */143static int144mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,145			 int link_id, u8 key_index, bool pairwise,146			 const u8 *mac_addr)147{148	struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);149	static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};150	const u8 *peer_mac = pairwise ? mac_addr : bc_mac;151 152	if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {153		mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");154		return -EFAULT;155	}156 157	mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");158	return 0;159}160 161/*162 * This function forms an skb for management frame.163 */164static int165mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)166{167	u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};168	u16 pkt_len;169	u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;170 171	pkt_len = len + ETH_ALEN;172 173	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +174		    MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));175	memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));176 177	memcpy(skb_push(skb, sizeof(tx_control)),178	       &tx_control, sizeof(tx_control));179 180	memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));181 182	/* Add packet data and address4 */183	skb_put_data(skb, buf, sizeof(struct ieee80211_hdr_3addr));184	skb_put_data(skb, addr, ETH_ALEN);185	skb_put_data(skb, buf + sizeof(struct ieee80211_hdr_3addr),186		     len - sizeof(struct ieee80211_hdr_3addr));187 188	skb->priority = LOW_PRIO_TID;189	__net_timestamp(skb);190 191	return 0;192}193 194/*195 * CFG802.11 operation handler to transmit a management frame.196 */197static int198mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,199			 struct cfg80211_mgmt_tx_params *params, u64 *cookie)200{201	const u8 *buf = params->buf;202	size_t len = params->len;203	struct sk_buff *skb;204	u16 pkt_len;205	const struct ieee80211_mgmt *mgmt;206	struct mwifiex_txinfo *tx_info;207	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);208 209	if (!buf || !len) {210		mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");211		return -EFAULT;212	}213 214	mgmt = (const struct ieee80211_mgmt *)buf;215	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&216	    ieee80211_is_probe_resp(mgmt->frame_control)) {217		/* Since we support offload probe resp, we need to skip probe218		 * resp in AP or GO mode */219		mwifiex_dbg(priv->adapter, INFO,220			    "info: skip to send probe resp in AP or GO mode\n");221		return 0;222	}223 224	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {225		if (ieee80211_is_auth(mgmt->frame_control))226			mwifiex_dbg(priv->adapter, MSG,227				    "auth: send auth to %pM\n", mgmt->da);228		if (ieee80211_is_deauth(mgmt->frame_control))229			mwifiex_dbg(priv->adapter, MSG,230				    "auth: send deauth to %pM\n", mgmt->da);231		if (ieee80211_is_disassoc(mgmt->frame_control))232			mwifiex_dbg(priv->adapter, MSG,233				    "assoc: send disassoc to %pM\n", mgmt->da);234		if (ieee80211_is_assoc_resp(mgmt->frame_control))235			mwifiex_dbg(priv->adapter, MSG,236				    "assoc: send assoc resp to %pM\n",237				    mgmt->da);238		if (ieee80211_is_reassoc_resp(mgmt->frame_control))239			mwifiex_dbg(priv->adapter, MSG,240				    "assoc: send reassoc resp to %pM\n",241				    mgmt->da);242	}243 244	pkt_len = len + ETH_ALEN;245	skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +246			    MWIFIEX_MGMT_FRAME_HEADER_SIZE +247			    pkt_len + sizeof(pkt_len));248 249	if (!skb) {250		mwifiex_dbg(priv->adapter, ERROR,251			    "allocate skb failed for management frame\n");252		return -ENOMEM;253	}254 255	tx_info = MWIFIEX_SKB_TXCB(skb);256	memset(tx_info, 0, sizeof(*tx_info));257	tx_info->bss_num = priv->bss_num;258	tx_info->bss_type = priv->bss_type;259	tx_info->pkt_len = pkt_len;260 261	mwifiex_form_mgmt_frame(skb, buf, len);262	*cookie = get_random_u32() | 1;263 264	if (ieee80211_is_action(mgmt->frame_control))265		skb = mwifiex_clone_skb_for_tx_status(priv,266						      skb,267				MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);268	else269		cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,270					GFP_ATOMIC);271 272	mwifiex_queue_tx_pkt(priv, skb);273 274	mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");275	return 0;276}277 278/*279 * CFG802.11 operation handler to register a mgmt frame.280 */281static void282mwifiex_cfg80211_update_mgmt_frame_registrations(struct wiphy *wiphy,283						 struct wireless_dev *wdev,284						 struct mgmt_frame_regs *upd)285{286	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);287	u32 mask = upd->interface_stypes;288 289	if (mask != priv->mgmt_frame_mask) {290		priv->mgmt_frame_mask = mask;291		if (priv->host_mlme_reg)292			priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;293		mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,294				 HostCmd_ACT_GEN_SET, 0,295				 &priv->mgmt_frame_mask, false);296		mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");297	}298}299 300/*301 * CFG802.11 operation handler to remain on channel.302 */303static int304mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,305				   struct wireless_dev *wdev,306				   struct ieee80211_channel *chan,307				   unsigned int duration, u64 *cookie)308{309	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);310	int ret;311 312	if (!chan || !cookie) {313		mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");314		return -EINVAL;315	}316 317	if (priv->roc_cfg.cookie) {318		mwifiex_dbg(priv->adapter, INFO,319			    "info: ongoing ROC, cookie = 0x%llx\n",320			    priv->roc_cfg.cookie);321		return -EBUSY;322	}323 324	ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,325					 duration);326 327	if (!ret) {328		*cookie = get_random_u32() | 1;329		priv->roc_cfg.cookie = *cookie;330		priv->roc_cfg.chan = *chan;331 332		cfg80211_ready_on_channel(wdev, *cookie, chan,333					  duration, GFP_ATOMIC);334 335		mwifiex_dbg(priv->adapter, INFO,336			    "info: ROC, cookie = 0x%llx\n", *cookie);337	}338 339	return ret;340}341 342/*343 * CFG802.11 operation handler to cancel remain on channel.344 */345static int346mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,347					  struct wireless_dev *wdev, u64 cookie)348{349	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);350	int ret;351 352	if (cookie != priv->roc_cfg.cookie)353		return -ENOENT;354 355	ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,356					 &priv->roc_cfg.chan, 0);357 358	if (!ret) {359		cfg80211_remain_on_channel_expired(wdev, cookie,360						   &priv->roc_cfg.chan,361						   GFP_ATOMIC);362 363		memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));364 365		mwifiex_dbg(priv->adapter, INFO,366			    "info: cancel ROC, cookie = 0x%llx\n", cookie);367	}368 369	return ret;370}371 372/*373 * CFG802.11 operation handler to set Tx power.374 */375static int376mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,377			      struct wireless_dev *wdev,378			      enum nl80211_tx_power_setting type,379			      int mbm)380{381	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);382	struct mwifiex_private *priv;383	struct mwifiex_power_cfg power_cfg;384	int dbm = MBM_TO_DBM(mbm);385 386	switch (type) {387	case NL80211_TX_POWER_FIXED:388		power_cfg.is_power_auto = 0;389		power_cfg.is_power_fixed = 1;390		power_cfg.power_level = dbm;391		break;392	case NL80211_TX_POWER_LIMITED:393		power_cfg.is_power_auto = 0;394		power_cfg.is_power_fixed = 0;395		power_cfg.power_level = dbm;396		break;397	case NL80211_TX_POWER_AUTOMATIC:398		power_cfg.is_power_auto = 1;399		break;400	}401 402	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);403 404	return mwifiex_set_tx_power(priv, &power_cfg);405}406 407/*408 * CFG802.11 operation handler to get Tx power.409 */410static int411mwifiex_cfg80211_get_tx_power(struct wiphy *wiphy,412			      struct wireless_dev *wdev,413			      int *dbm)414{415	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);416	struct mwifiex_private *priv = mwifiex_get_priv(adapter,417							MWIFIEX_BSS_ROLE_ANY);418	int ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR,419				   HostCmd_ACT_GEN_GET, 0, NULL, true);420 421	if (ret < 0)422		return ret;423 424	/* tx_power_level is set in HostCmd_CMD_RF_TX_PWR command handler */425	*dbm = priv->tx_power_level;426 427	return 0;428}429 430/*431 * CFG802.11 operation handler to set Power Save option.432 *433 * The timeout value, if provided, is currently ignored.434 */435static int436mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,437				struct net_device *dev,438				bool enabled, int timeout)439{440	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);441	u32 ps_mode;442 443	if (timeout)444		mwifiex_dbg(priv->adapter, INFO,445			    "info: ignore timeout value for IEEE Power Save\n");446 447	ps_mode = enabled;448 449	return mwifiex_drv_set_power(priv, &ps_mode);450}451 452/*453 * CFG802.11 operation handler to set the default network key.454 */455static int456mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,457				 int link_id, u8 key_index, bool unicast,458				 bool multicast)459{460	struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);461 462	/* Return if WEP key not configured */463	if (!priv->sec_info.wep_enabled)464		return 0;465 466	if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {467		priv->wep_key_curr_index = key_index;468	} else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,469				      NULL, 0)) {470		mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");471		return -EFAULT;472	}473 474	return 0;475}476 477/*478 * CFG802.11 operation handler to add a network key.479 */480static int481mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,482			 int link_id, u8 key_index, bool pairwise,483			 const u8 *mac_addr, struct key_params *params)484{485	struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);486	struct mwifiex_wep_key *wep_key;487	static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};488	const u8 *peer_mac = pairwise ? mac_addr : bc_mac;489 490	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&491	    (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||492	     params->cipher == WLAN_CIPHER_SUITE_WEP104)) {493		if (params->key && params->key_len) {494			wep_key = &priv->wep_key[key_index];495			memset(wep_key, 0, sizeof(struct mwifiex_wep_key));496			memcpy(wep_key->key_material, params->key,497			       params->key_len);498			wep_key->key_index = key_index;499			wep_key->key_length = params->key_len;500			priv->sec_info.wep_enabled = 1;501		}502		return 0;503	}504 505	if (mwifiex_set_encode(priv, params, params->key, params->key_len,506			       key_index, peer_mac, 0)) {507		mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");508		return -EFAULT;509	}510 511	return 0;512}513 514/*515 * CFG802.11 operation handler to set default mgmt key.516 */517static int518mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,519				      struct net_device *netdev,520				      int link_id,521				      u8 key_index)522{523	struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);524	struct mwifiex_ds_encrypt_key encrypt_key;525 526	wiphy_dbg(wiphy, "set default mgmt key, key index=%d\n", key_index);527 528	if (priv->adapter->host_mlme_enabled)529		return 0;530 531	memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));532	encrypt_key.key_len = WLAN_KEY_LEN_CCMP;533	encrypt_key.key_index = key_index;534	encrypt_key.is_igtk_def_key = true;535	eth_broadcast_addr(encrypt_key.mac_addr);536 537	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL,538			     HostCmd_ACT_GEN_SET, true, &encrypt_key, true)) {539		mwifiex_dbg(priv->adapter, ERROR,540			    "Sending KEY_MATERIAL command failed\n");541		return -1;542	}543 544	return 0;545}546 547/*548 * This function sends domain information to the firmware.549 *550 * The following information are passed to the firmware -551 *      - Country codes552 *      - Sub bands (first channel, number of channels, maximum Tx power)553 */554int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)555{556	u8 no_of_triplet = 0;557	struct ieee80211_country_ie_triplet *t;558	u8 no_of_parsed_chan = 0;559	u8 first_chan = 0, next_chan = 0, max_pwr = 0;560	u8 i, flag = 0;561	enum nl80211_band band;562	struct ieee80211_supported_band *sband;563	struct ieee80211_channel *ch;564	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);565	struct mwifiex_private *priv;566	struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;567 568	/* Set country code */569	domain_info->country_code[0] = adapter->country_code[0];570	domain_info->country_code[1] = adapter->country_code[1];571	domain_info->country_code[2] = ' ';572 573	band = mwifiex_band_to_radio_type(adapter->config_bands);574	if (!wiphy->bands[band]) {575		mwifiex_dbg(adapter, ERROR,576			    "11D: setting domain info in FW\n");577		return -1;578	}579 580	sband = wiphy->bands[band];581 582	for (i = 0; i < sband->n_channels ; i++) {583		ch = &sband->channels[i];584		if (ch->flags & IEEE80211_CHAN_DISABLED)585			continue;586 587		if (!flag) {588			flag = 1;589			first_chan = (u32) ch->hw_value;590			next_chan = first_chan;591			max_pwr = ch->max_power;592			no_of_parsed_chan = 1;593			continue;594		}595 596		if (ch->hw_value == next_chan + 1 &&597		    ch->max_power == max_pwr) {598			next_chan++;599			no_of_parsed_chan++;600		} else {601			t = &domain_info->triplet[no_of_triplet];602			t->chans.first_channel = first_chan;603			t->chans.num_channels = no_of_parsed_chan;604			t->chans.max_power = max_pwr;605			no_of_triplet++;606			first_chan = (u32) ch->hw_value;607			next_chan = first_chan;608			max_pwr = ch->max_power;609			no_of_parsed_chan = 1;610		}611	}612 613	if (flag) {614		t = &domain_info->triplet[no_of_triplet];615		t->chans.first_channel = first_chan;616		t->chans.num_channels = no_of_parsed_chan;617		t->chans.max_power = max_pwr;618		no_of_triplet++;619	}620 621	domain_info->no_of_triplet = no_of_triplet;622 623	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);624 625	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,626			     HostCmd_ACT_GEN_SET, 0, NULL, false)) {627		mwifiex_dbg(adapter, INFO,628			    "11D: setting domain info in FW\n");629		return -1;630	}631 632	return 0;633}634 635static void mwifiex_reg_apply_radar_flags(struct wiphy *wiphy)636{637	struct ieee80211_supported_band *sband;638	struct ieee80211_channel *chan;639	unsigned int i;640 641	if (!wiphy->bands[NL80211_BAND_5GHZ])642		return;643	sband = wiphy->bands[NL80211_BAND_5GHZ];644 645	for (i = 0; i < sband->n_channels; i++) {646		chan = &sband->channels[i];647		if ((!(chan->flags & IEEE80211_CHAN_DISABLED)) &&648		    (chan->flags & IEEE80211_CHAN_RADAR))649			chan->flags |= IEEE80211_CHAN_NO_IR;650	}651}652 653/*654 * CFG802.11 regulatory domain callback function.655 *656 * This function is called when the regulatory domain is changed due to the657 * following reasons -658 *      - Set by driver659 *      - Set by system core660 *      - Set by user661 *      - Set bt Country IE662 */663static void mwifiex_reg_notifier(struct wiphy *wiphy,664				 struct regulatory_request *request)665{666	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);667	struct mwifiex_private *priv = mwifiex_get_priv(adapter,668							MWIFIEX_BSS_ROLE_ANY);669	mwifiex_dbg(adapter, INFO,670		    "info: cfg80211 regulatory domain callback for %c%c\n",671		    request->alpha2[0], request->alpha2[1]);672	mwifiex_reg_apply_radar_flags(wiphy);673 674	switch (request->initiator) {675	case NL80211_REGDOM_SET_BY_DRIVER:676	case NL80211_REGDOM_SET_BY_CORE:677	case NL80211_REGDOM_SET_BY_USER:678	case NL80211_REGDOM_SET_BY_COUNTRY_IE:679		break;680	default:681		mwifiex_dbg(adapter, ERROR,682			    "unknown regdom initiator: %d\n",683			    request->initiator);684		return;685	}686 687	/* Don't send world or same regdom info to firmware */688	if (strncmp(request->alpha2, "00", 2) &&689	    strncmp(request->alpha2, adapter->country_code,690		    sizeof(request->alpha2))) {691		memcpy(adapter->country_code, request->alpha2,692		       sizeof(request->alpha2));693		mwifiex_send_domain_info_cmd_fw(wiphy);694		mwifiex_dnld_txpwr_table(priv);695	}696}697 698/*699 * This function sets the fragmentation threshold.700 *701 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE702 * and MWIFIEX_FRAG_MAX_VALUE.703 */704static int705mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)706{707	if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||708	    frag_thr > MWIFIEX_FRAG_MAX_VALUE)709		frag_thr = MWIFIEX_FRAG_MAX_VALUE;710 711	return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,712				HostCmd_ACT_GEN_SET, FRAG_THRESH_I,713				&frag_thr, true);714}715 716/*717 * This function sets the RTS threshold.718 719 * The rts value must lie between MWIFIEX_RTS_MIN_VALUE720 * and MWIFIEX_RTS_MAX_VALUE.721 */722static int723mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)724{725	if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)726		rts_thr = MWIFIEX_RTS_MAX_VALUE;727 728	return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,729				HostCmd_ACT_GEN_SET, RTS_THRESH_I,730				&rts_thr, true);731}732 733/*734 * CFG802.11 operation handler to set wiphy parameters.735 *736 * This function can be used to set the RTS threshold and the737 * Fragmentation threshold of the driver.738 */739static int740mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)741{742	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);743	struct mwifiex_private *priv;744	struct mwifiex_uap_bss_param *bss_cfg;745	int ret;746 747	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);748 749	switch (priv->bss_role) {750	case MWIFIEX_BSS_ROLE_UAP:751		if (priv->bss_started) {752			mwifiex_dbg(adapter, ERROR,753				    "cannot change wiphy params when bss started");754			return -EINVAL;755		}756 757		bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL);758		if (!bss_cfg)759			return -ENOMEM;760 761		mwifiex_set_sys_config_invalid_data(bss_cfg);762 763		if (changed & WIPHY_PARAM_RTS_THRESHOLD)764			bss_cfg->rts_threshold = wiphy->rts_threshold;765		if (changed & WIPHY_PARAM_FRAG_THRESHOLD)766			bss_cfg->frag_threshold = wiphy->frag_threshold;767		if (changed & WIPHY_PARAM_RETRY_LONG)768			bss_cfg->retry_limit = wiphy->retry_long;769 770		ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,771				       HostCmd_ACT_GEN_SET,772				       UAP_BSS_PARAMS_I, bss_cfg,773				       false);774 775		kfree(bss_cfg);776		if (ret) {777			mwifiex_dbg(adapter, ERROR,778				    "Failed to set wiphy phy params\n");779			return ret;780		}781		break;782 783	case MWIFIEX_BSS_ROLE_STA:784		if (priv->media_connected) {785			mwifiex_dbg(adapter, ERROR,786				    "cannot change wiphy params when connected");787			return -EINVAL;788		}789		if (changed & WIPHY_PARAM_RTS_THRESHOLD) {790			ret = mwifiex_set_rts(priv,791					      wiphy->rts_threshold);792			if (ret)793				return ret;794		}795		if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {796			ret = mwifiex_set_frag(priv,797					       wiphy->frag_threshold);798			if (ret)799				return ret;800		}801		break;802	}803 804	return 0;805}806 807static int808mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)809{810	u16 mode = P2P_MODE_DISABLE;811 812	if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,813			     HostCmd_ACT_GEN_SET, 0, &mode, true))814		return -1;815 816	return 0;817}818 819/*820 * This function initializes the functionalities for P2P client.821 * The P2P client initialization sequence is:822 * disable -> device -> client823 */824static int825mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)826{827	u16 mode;828 829	if (mwifiex_cfg80211_deinit_p2p(priv))830		return -1;831 832	mode = P2P_MODE_DEVICE;833	if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,834			     HostCmd_ACT_GEN_SET, 0, &mode, true))835		return -1;836 837	mode = P2P_MODE_CLIENT;838	if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,839			     HostCmd_ACT_GEN_SET, 0, &mode, true))840		return -1;841 842	return 0;843}844 845/*846 * This function initializes the functionalities for P2P GO.847 * The P2P GO initialization sequence is:848 * disable -> device -> GO849 */850static int851mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)852{853	u16 mode;854 855	if (mwifiex_cfg80211_deinit_p2p(priv))856		return -1;857 858	mode = P2P_MODE_DEVICE;859	if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,860			     HostCmd_ACT_GEN_SET, 0, &mode, true))861		return -1;862 863	mode = P2P_MODE_GO;864	if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,865			     HostCmd_ACT_GEN_SET, 0, &mode, true))866		return -1;867 868	return 0;869}870 871static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)872{873	struct mwifiex_adapter *adapter = priv->adapter;874	unsigned long flags;875 876	priv->host_mlme_reg = false;877	priv->mgmt_frame_mask = 0;878	if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,879			     HostCmd_ACT_GEN_SET, 0,880			     &priv->mgmt_frame_mask, false)) {881		mwifiex_dbg(adapter, ERROR,882			    "could not unregister mgmt frame rx\n");883		return -1;884	}885 886	mwifiex_deauthenticate(priv, NULL);887 888	spin_lock_irqsave(&adapter->main_proc_lock, flags);889	adapter->main_locked = true;890	if (adapter->mwifiex_processing) {891		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);892		flush_workqueue(adapter->workqueue);893	} else {894		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);895	}896 897	spin_lock_bh(&adapter->rx_proc_lock);898	adapter->rx_locked = true;899	if (adapter->rx_processing) {900		spin_unlock_bh(&adapter->rx_proc_lock);901		flush_workqueue(adapter->rx_workqueue);902	} else {903	spin_unlock_bh(&adapter->rx_proc_lock);904	}905 906	mwifiex_free_priv(priv);907	priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;908	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;909	priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;910 911	return 0;912}913 914static int915mwifiex_init_new_priv_params(struct mwifiex_private *priv,916			     struct net_device *dev,917			     enum nl80211_iftype type)918{919	struct mwifiex_adapter *adapter = priv->adapter;920	unsigned long flags;921 922	mwifiex_init_priv(priv);923 924	priv->bss_mode = type;925	priv->wdev.iftype = type;926 927	mwifiex_init_priv_params(priv, priv->netdev);928	priv->bss_started = 0;929 930	switch (type) {931	case NL80211_IFTYPE_STATION:932	case NL80211_IFTYPE_ADHOC:933		priv->bss_role = MWIFIEX_BSS_ROLE_STA;934		priv->bss_type = MWIFIEX_BSS_TYPE_STA;935		break;936	case NL80211_IFTYPE_P2P_CLIENT:937		priv->bss_role = MWIFIEX_BSS_ROLE_STA;938		priv->bss_type = MWIFIEX_BSS_TYPE_P2P;939		break;940	case NL80211_IFTYPE_P2P_GO:941		priv->bss_role = MWIFIEX_BSS_ROLE_UAP;942		priv->bss_type = MWIFIEX_BSS_TYPE_P2P;943		break;944	case NL80211_IFTYPE_AP:945		priv->bss_role = MWIFIEX_BSS_ROLE_UAP;946		priv->bss_type = MWIFIEX_BSS_TYPE_UAP;947		break;948	default:949		mwifiex_dbg(adapter, ERROR,950			    "%s: changing to %d not supported\n",951			    dev->name, type);952		return -EOPNOTSUPP;953	}954 955	priv->bss_num = mwifiex_get_unused_bss_num(adapter, priv->bss_type);956 957	spin_lock_irqsave(&adapter->main_proc_lock, flags);958	adapter->main_locked = false;959	spin_unlock_irqrestore(&adapter->main_proc_lock, flags);960 961	spin_lock_bh(&adapter->rx_proc_lock);962	adapter->rx_locked = false;963	spin_unlock_bh(&adapter->rx_proc_lock);964 965	mwifiex_set_mac_address(priv, dev, false, NULL);966 967	return 0;968}969 970static bool971is_vif_type_change_allowed(struct mwifiex_adapter *adapter,972			   enum nl80211_iftype old_iftype,973			   enum nl80211_iftype new_iftype)974{975	switch (old_iftype) {976	case NL80211_IFTYPE_ADHOC:977		switch (new_iftype) {978		case NL80211_IFTYPE_STATION:979			return true;980		case NL80211_IFTYPE_P2P_CLIENT:981		case NL80211_IFTYPE_P2P_GO:982			return adapter->curr_iface_comb.p2p_intf !=983			       adapter->iface_limit.p2p_intf;984		case NL80211_IFTYPE_AP:985			return adapter->curr_iface_comb.uap_intf !=986			       adapter->iface_limit.uap_intf;987		default:988			return false;989		}990 991	case NL80211_IFTYPE_STATION:992		switch (new_iftype) {993		case NL80211_IFTYPE_ADHOC:994			return true;995		case NL80211_IFTYPE_P2P_CLIENT:996		case NL80211_IFTYPE_P2P_GO:997			return adapter->curr_iface_comb.p2p_intf !=998			       adapter->iface_limit.p2p_intf;999		case NL80211_IFTYPE_AP:1000			return adapter->curr_iface_comb.uap_intf !=1001			       adapter->iface_limit.uap_intf;1002		default:1003			return false;1004		}1005 1006	case NL80211_IFTYPE_AP:1007		switch (new_iftype) {1008		case NL80211_IFTYPE_ADHOC:1009		case NL80211_IFTYPE_STATION:1010			return adapter->curr_iface_comb.sta_intf !=1011			       adapter->iface_limit.sta_intf;1012		case NL80211_IFTYPE_P2P_CLIENT:1013		case NL80211_IFTYPE_P2P_GO:1014			return adapter->curr_iface_comb.p2p_intf !=1015			       adapter->iface_limit.p2p_intf;1016		default:1017			return false;1018		}1019 1020	case NL80211_IFTYPE_P2P_CLIENT:1021		switch (new_iftype) {1022		case NL80211_IFTYPE_ADHOC:1023		case NL80211_IFTYPE_STATION:1024			return true;1025		case NL80211_IFTYPE_P2P_GO:1026			return true;1027		case NL80211_IFTYPE_AP:1028			return adapter->curr_iface_comb.uap_intf !=1029			       adapter->iface_limit.uap_intf;1030		default:1031			return false;1032		}1033 1034	case NL80211_IFTYPE_P2P_GO:1035		switch (new_iftype) {1036		case NL80211_IFTYPE_ADHOC:1037		case NL80211_IFTYPE_STATION:1038			return true;1039		case NL80211_IFTYPE_P2P_CLIENT:1040			return true;1041		case NL80211_IFTYPE_AP:1042			return adapter->curr_iface_comb.uap_intf !=1043			       adapter->iface_limit.uap_intf;1044		default:1045			return false;1046		}1047 1048	default:1049		break;1050	}1051 1052	return false;1053}1054 1055static void1056update_vif_type_counter(struct mwifiex_adapter *adapter,1057			enum nl80211_iftype iftype,1058			int change)1059{1060	switch (iftype) {1061	case NL80211_IFTYPE_UNSPECIFIED:1062	case NL80211_IFTYPE_ADHOC:1063	case NL80211_IFTYPE_STATION:1064		adapter->curr_iface_comb.sta_intf += change;1065		break;1066	case NL80211_IFTYPE_AP:1067		adapter->curr_iface_comb.uap_intf += change;1068		break;1069	case NL80211_IFTYPE_P2P_CLIENT:1070	case NL80211_IFTYPE_P2P_GO:1071		adapter->curr_iface_comb.p2p_intf += change;1072		break;1073	default:1074		mwifiex_dbg(adapter, ERROR,1075			    "%s: Unsupported iftype passed: %d\n",1076			    __func__, iftype);1077		break;1078	}1079}1080 1081static int1082mwifiex_change_vif_to_p2p(struct net_device *dev,1083			  enum nl80211_iftype curr_iftype,1084			  enum nl80211_iftype type,1085			  struct vif_params *params)1086{1087	struct mwifiex_private *priv;1088	struct mwifiex_adapter *adapter;1089 1090	priv = mwifiex_netdev_get_priv(dev);1091 1092	if (!priv)1093		return -1;1094 1095	adapter = priv->adapter;1096 1097	mwifiex_dbg(adapter, INFO,1098		    "%s: changing role to p2p\n", dev->name);1099 1100	if (mwifiex_deinit_priv_params(priv))1101		return -1;1102	if (mwifiex_init_new_priv_params(priv, dev, type))1103		return -1;1104 1105	update_vif_type_counter(adapter, curr_iftype, -1);1106	update_vif_type_counter(adapter, type, +1);1107	dev->ieee80211_ptr->iftype = type;1108 1109	switch (type) {1110	case NL80211_IFTYPE_P2P_CLIENT:1111		if (mwifiex_cfg80211_init_p2p_client(priv))1112			return -EFAULT;1113		break;1114	case NL80211_IFTYPE_P2P_GO:1115		if (mwifiex_cfg80211_init_p2p_go(priv))1116			return -EFAULT;1117		break;1118	default:1119		mwifiex_dbg(adapter, ERROR,1120			    "%s: changing to %d not supported\n",1121			    dev->name, type);1122		return -EOPNOTSUPP;1123	}1124 1125	if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1126			     HostCmd_ACT_GEN_SET, 0, NULL, true))1127		return -1;1128 1129	if (mwifiex_sta_init_cmd(priv, false, false))1130		return -1;1131 1132	return 0;1133}1134 1135static int1136mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,1137				enum nl80211_iftype curr_iftype,1138				enum nl80211_iftype type,1139				struct vif_params *params)1140{1141	struct mwifiex_private *priv;1142	struct mwifiex_adapter *adapter;1143 1144	priv = mwifiex_netdev_get_priv(dev);1145 1146	if (!priv)1147		return -1;1148 1149	adapter = priv->adapter;1150 1151	if (type == NL80211_IFTYPE_STATION)1152		mwifiex_dbg(adapter, INFO,1153			    "%s: changing role to station\n", dev->name);1154	else1155		mwifiex_dbg(adapter, INFO,1156			    "%s: changing role to adhoc\n", dev->name);1157 1158	if (mwifiex_deinit_priv_params(priv))1159		return -1;1160	if (mwifiex_init_new_priv_params(priv, dev, type))1161		return -1;1162 1163	update_vif_type_counter(adapter, curr_iftype, -1);1164	update_vif_type_counter(adapter, type, +1);1165	dev->ieee80211_ptr->iftype = type;1166 1167	if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1168			     HostCmd_ACT_GEN_SET, 0, NULL, true))1169		return -1;1170	if (mwifiex_sta_init_cmd(priv, false, false))1171		return -1;1172 1173	return 0;1174}1175 1176static int1177mwifiex_change_vif_to_ap(struct net_device *dev,1178			 enum nl80211_iftype curr_iftype,1179			 enum nl80211_iftype type,1180			 struct vif_params *params)1181{1182	struct mwifiex_private *priv;1183	struct mwifiex_adapter *adapter;1184 1185	priv = mwifiex_netdev_get_priv(dev);1186 1187	if (!priv)1188		return -1;1189 1190	adapter = priv->adapter;1191 1192	mwifiex_dbg(adapter, INFO,1193		    "%s: changing role to AP\n", dev->name);1194 1195	if (mwifiex_deinit_priv_params(priv))1196		return -1;1197	if (mwifiex_init_new_priv_params(priv, dev, type))1198		return -1;1199 1200	update_vif_type_counter(adapter, curr_iftype, -1);1201	update_vif_type_counter(adapter, type, +1);1202	dev->ieee80211_ptr->iftype = type;1203 1204	if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1205			     HostCmd_ACT_GEN_SET, 0, NULL, true))1206		return -1;1207	if (mwifiex_sta_init_cmd(priv, false, false))1208		return -1;1209 1210	return 0;1211}1212/*1213 * CFG802.11 operation handler to change interface type.1214 */1215static int1216mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,1217				     struct net_device *dev,1218				     enum nl80211_iftype type,1219				     struct vif_params *params)1220{1221	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1222	enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;1223 1224	if (priv->scan_request) {1225		mwifiex_dbg(priv->adapter, ERROR,1226			    "change virtual interface: scan in process\n");1227		return -EBUSY;1228	}1229 1230	if (type == NL80211_IFTYPE_UNSPECIFIED) {1231		mwifiex_dbg(priv->adapter, INFO,1232			    "%s: no new type specified, keeping old type %d\n",1233			    dev->name, curr_iftype);1234		return 0;1235	}1236 1237	if (curr_iftype == type) {1238		mwifiex_dbg(priv->adapter, INFO,1239			    "%s: interface already is of type %d\n",1240			    dev->name, curr_iftype);1241		return 0;1242	}1243 1244	if (!is_vif_type_change_allowed(priv->adapter, curr_iftype, type)) {1245		mwifiex_dbg(priv->adapter, ERROR,1246			    "%s: change from type %d to %d is not allowed\n",1247			    dev->name, curr_iftype, type);1248		return -EOPNOTSUPP;1249	}1250 1251	switch (curr_iftype) {1252	case NL80211_IFTYPE_ADHOC:1253		switch (type) {1254		case NL80211_IFTYPE_STATION:1255			priv->bss_mode = type;1256			priv->sec_info.authentication_mode =1257						   NL80211_AUTHTYPE_OPEN_SYSTEM;1258			dev->ieee80211_ptr->iftype = type;1259			mwifiex_deauthenticate(priv, NULL);1260			return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1261						HostCmd_ACT_GEN_SET, 0, NULL,1262						true);1263		case NL80211_IFTYPE_P2P_CLIENT:1264		case NL80211_IFTYPE_P2P_GO:1265			return mwifiex_change_vif_to_p2p(dev, curr_iftype,1266							 type, params);1267		case NL80211_IFTYPE_AP:1268			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1269							params);1270		default:1271			goto errnotsupp;1272		}1273 1274	case NL80211_IFTYPE_STATION:1275		switch (type) {1276		case NL80211_IFTYPE_ADHOC:1277			priv->bss_mode = type;1278			priv->sec_info.authentication_mode =1279						   NL80211_AUTHTYPE_OPEN_SYSTEM;1280			dev->ieee80211_ptr->iftype = type;1281			mwifiex_deauthenticate(priv, NULL);1282			return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,1283						HostCmd_ACT_GEN_SET, 0, NULL,1284						true);1285		case NL80211_IFTYPE_P2P_CLIENT:1286		case NL80211_IFTYPE_P2P_GO:1287			return mwifiex_change_vif_to_p2p(dev, curr_iftype,1288							 type, params);1289		case NL80211_IFTYPE_AP:1290			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1291							params);1292		default:1293			goto errnotsupp;1294		}1295 1296	case NL80211_IFTYPE_AP:1297		switch (type) {1298		case NL80211_IFTYPE_ADHOC:1299		case NL80211_IFTYPE_STATION:1300			return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,1301							       type, params);1302			break;1303		case NL80211_IFTYPE_P2P_CLIENT:1304		case NL80211_IFTYPE_P2P_GO:1305			return mwifiex_change_vif_to_p2p(dev, curr_iftype,1306							 type, params);1307		default:1308			goto errnotsupp;1309		}1310 1311	case NL80211_IFTYPE_P2P_CLIENT:1312		if (mwifiex_cfg80211_deinit_p2p(priv))1313			return -EFAULT;1314 1315		switch (type) {1316		case NL80211_IFTYPE_ADHOC:1317		case NL80211_IFTYPE_STATION:1318			return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,1319							       type, params);1320		case NL80211_IFTYPE_P2P_GO:1321			return mwifiex_change_vif_to_p2p(dev, curr_iftype,1322							 type, params);1323		case NL80211_IFTYPE_AP:1324			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1325							params);1326		default:1327			goto errnotsupp;1328		}1329 1330	case NL80211_IFTYPE_P2P_GO:1331		if (mwifiex_cfg80211_deinit_p2p(priv))1332			return -EFAULT;1333 1334		switch (type) {1335		case NL80211_IFTYPE_ADHOC:1336		case NL80211_IFTYPE_STATION:1337			return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,1338							       type, params);1339		case NL80211_IFTYPE_P2P_CLIENT:1340			return mwifiex_change_vif_to_p2p(dev, curr_iftype,1341							 type, params);1342		case NL80211_IFTYPE_AP:1343			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,1344							params);1345		default:1346			goto errnotsupp;1347		}1348 1349	default:1350		goto errnotsupp;1351	}1352 1353 1354	return 0;1355 1356errnotsupp:1357	mwifiex_dbg(priv->adapter, ERROR,1358		    "unsupported interface type transition: %d to %d\n",1359		    curr_iftype, type);1360	return -EOPNOTSUPP;1361}1362 1363static void1364mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 rateinfo, u8 htinfo,1365		     struct rate_info *rate)1366{1367	struct mwifiex_adapter *adapter = priv->adapter;1368 1369	if (adapter->is_hw_11ac_capable) {1370		/* bit[1-0]: 00=LG 01=HT 10=VHT */1371		if (htinfo & BIT(0)) {1372			/* HT */1373			rate->mcs = rateinfo;1374			rate->flags |= RATE_INFO_FLAGS_MCS;1375		}1376		if (htinfo & BIT(1)) {1377			/* VHT */1378			rate->mcs = rateinfo & 0x0F;1379			rate->flags |= RATE_INFO_FLAGS_VHT_MCS;1380		}1381 1382		if (htinfo & (BIT(1) | BIT(0))) {1383			/* HT or VHT */1384			switch (htinfo & (BIT(3) | BIT(2))) {1385			case 0:1386				rate->bw = RATE_INFO_BW_20;1387				break;1388			case (BIT(2)):1389				rate->bw = RATE_INFO_BW_40;1390				break;1391			case (BIT(3)):1392				rate->bw = RATE_INFO_BW_80;1393				break;1394			case (BIT(3) | BIT(2)):1395				rate->bw = RATE_INFO_BW_160;1396				break;1397			}1398 1399			if (htinfo & BIT(4))1400				rate->flags |= RATE_INFO_FLAGS_SHORT_GI;1401 1402			if ((rateinfo >> 4) == 1)1403				rate->nss = 2;1404			else1405				rate->nss = 1;1406		}1407	} else {1408		/*1409		 * Bit 0 in htinfo indicates that current rate is 11n. Valid1410		 * MCS index values for us are 0 to 15.1411		 */1412		if ((htinfo & BIT(0)) && (rateinfo < 16)) {1413			rate->mcs = rateinfo;1414			rate->flags |= RATE_INFO_FLAGS_MCS;1415			rate->bw = RATE_INFO_BW_20;1416			if (htinfo & BIT(1))1417				rate->bw = RATE_INFO_BW_40;1418			if (htinfo & BIT(2))1419				rate->flags |= RATE_INFO_FLAGS_SHORT_GI;1420		}1421	}1422 1423	/* Decode legacy rates for non-HT. */1424	if (!(htinfo & (BIT(0) | BIT(1)))) {1425		/* Bitrates in multiples of 100kb/s. */1426		static const int legacy_rates[] = {1427			[0] = 10,1428			[1] = 20,1429			[2] = 55,1430			[3] = 110,1431			[4] = 60, /* MWIFIEX_RATE_INDEX_OFDM0 */1432			[5] = 60,1433			[6] = 90,1434			[7] = 120,1435			[8] = 180,1436			[9] = 240,1437			[10] = 360,1438			[11] = 480,1439			[12] = 540,1440		};1441		if (rateinfo < ARRAY_SIZE(legacy_rates))1442			rate->legacy = legacy_rates[rateinfo];1443	}1444}1445 1446/*1447 * This function dumps the station information on a buffer.1448 *1449 * The following information are shown -1450 *      - Total bytes transmitted1451 *      - Total bytes received1452 *      - Total packets transmitted1453 *      - Total packets received1454 *      - Signal quality level1455 *      - Transmission rate1456 */1457static int1458mwifiex_dump_station_info(struct mwifiex_private *priv,1459			  struct mwifiex_sta_node *node,1460			  struct station_info *sinfo)1461{1462	u32 rate;1463 1464	sinfo->filled = BIT_ULL(NL80211_STA_INFO_RX_BYTES) | BIT_ULL(NL80211_STA_INFO_TX_BYTES) |1465			BIT_ULL(NL80211_STA_INFO_RX_PACKETS) | BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |1466			BIT_ULL(NL80211_STA_INFO_TX_BITRATE) |1467			BIT_ULL(NL80211_STA_INFO_SIGNAL) | BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);1468 1469	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {1470		if (!node)1471			return -ENOENT;1472 1473		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) |1474				BIT_ULL(NL80211_STA_INFO_TX_FAILED);1475		sinfo->inactive_time =1476			jiffies_to_msecs(jiffies - node->stats.last_rx);1477 1478		sinfo->signal = node->stats.rssi;1479		sinfo->signal_avg = node->stats.rssi;1480		sinfo->rx_bytes = node->stats.rx_bytes;1481		sinfo->tx_bytes = node->stats.tx_bytes;1482		sinfo->rx_packets = node->stats.rx_packets;1483		sinfo->tx_packets = node->stats.tx_packets;1484		sinfo->tx_failed = node->stats.tx_failed;1485 1486		mwifiex_parse_htinfo(priv, priv->tx_rate,1487				     node->stats.last_tx_htinfo,1488				     &sinfo->txrate);1489		sinfo->txrate.legacy = node->stats.last_tx_rate * 5;1490 1491		return 0;1492	}1493 1494	/* Get signal information from the firmware */1495	if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,1496			     HostCmd_ACT_GEN_GET, 0, NULL, true)) {1497		mwifiex_dbg(priv->adapter, ERROR,1498			    "failed to get signal information\n");1499		return -EFAULT;1500	}1501 1502	if (mwifiex_drv_get_data_rate(priv, &rate)) {1503		mwifiex_dbg(priv->adapter, ERROR,1504			    "getting data rate error\n");1505		return -EFAULT;1506	}1507 1508	/* Get DTIM period information from firmware */1509	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,1510			 HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,1511			 &priv->dtim_period, true);1512 1513	mwifiex_parse_htinfo(priv, priv->tx_rate, priv->tx_htinfo,1514			     &sinfo->txrate);1515 1516	sinfo->signal_avg = priv->bcn_rssi_avg;1517	sinfo->rx_bytes = priv->stats.rx_bytes;1518	sinfo->tx_bytes = priv->stats.tx_bytes;1519	sinfo->rx_packets = priv->stats.rx_packets;1520	sinfo->tx_packets = priv->stats.tx_packets;1521	sinfo->signal = priv->bcn_rssi_avg;1522	/* bit rate is in 500 kb/s units. Convert it to 100kb/s units */1523	sinfo->txrate.legacy = rate * 5;1524 1525	sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);1526	mwifiex_parse_htinfo(priv, priv->rxpd_rate, priv->rxpd_htinfo,1527			     &sinfo->rxrate);1528 1529	if (priv->bss_mode == NL80211_IFTYPE_STATION) {1530		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_BSS_PARAM);1531		sinfo->bss_param.flags = 0;1532		if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &1533						WLAN_CAPABILITY_SHORT_PREAMBLE)1534			sinfo->bss_param.flags |=1535					BSS_PARAM_FLAGS_SHORT_PREAMBLE;1536		if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &1537						WLAN_CAPABILITY_SHORT_SLOT_TIME)1538			sinfo->bss_param.flags |=1539					BSS_PARAM_FLAGS_SHORT_SLOT_TIME;1540		sinfo->bss_param.dtim_period = priv->dtim_period;1541		sinfo->bss_param.beacon_interval =1542			priv->curr_bss_params.bss_descriptor.beacon_period;1543	}1544 1545	return 0;1546}1547 1548/*1549 * CFG802.11 operation handler to get station information.1550 *1551 * This function only works in connected mode, and dumps the1552 * requested station information, if available.1553 */1554static int1555mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,1556			     const u8 *mac, struct station_info *sinfo)1557{1558	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1559 1560	if (!priv->media_connected)1561		return -ENOENT;1562	if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))1563		return -ENOENT;1564 1565	return mwifiex_dump_station_info(priv, NULL, sinfo);1566}1567 1568/*1569 * CFG802.11 operation handler to dump station information.1570 */1571static int1572mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,1573			      int idx, u8 *mac, struct station_info *sinfo)1574{1575	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1576	struct mwifiex_sta_node *node;1577	int i;1578 1579	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&1580	    priv->media_connected && idx == 0) {1581		ether_addr_copy(mac, priv->cfg_bssid);1582		return mwifiex_dump_station_info(priv, NULL, sinfo);1583	} else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {1584		mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,1585				 HostCmd_ACT_GEN_GET, 0, NULL, true);1586 1587		i = 0;1588		list_for_each_entry(node, &priv->sta_list, list) {1589			if (i++ != idx)1590				continue;1591			ether_addr_copy(mac, node->mac_addr);1592			return mwifiex_dump_station_info(priv, node, sinfo);1593		}1594	}1595 1596	return -ENOENT;1597}1598 1599static int1600mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,1601			     int idx, struct survey_info *survey)1602{1603	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1604	struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;1605	enum nl80211_band band;1606 1607	mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);1608 1609	memset(survey, 0, sizeof(struct survey_info));1610 1611	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&1612	    priv->media_connected && idx == 0) {1613			u8 curr_bss_band = priv->curr_bss_params.band;1614			u32 chan = priv->curr_bss_params.bss_descriptor.channel;1615 1616			band = mwifiex_band_to_radio_type(curr_bss_band);1617			survey->channel = ieee80211_get_channel(wiphy,1618				ieee80211_channel_to_frequency(chan, band));1619 1620			if (priv->bcn_nf_last) {1621				survey->filled = SURVEY_INFO_NOISE_DBM;1622				survey->noise = priv->bcn_nf_last;1623			}1624			return 0;1625	}1626 1627	if (idx >= priv->adapter->num_in_chan_stats)1628		return -ENOENT;1629 1630	if (!pchan_stats[idx].cca_scan_dur)1631		return 0;1632 1633	band = pchan_stats[idx].bandcfg;1634	survey->channel = ieee80211_get_channel(wiphy,1635	    ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));1636	survey->filled = SURVEY_INFO_NOISE_DBM |1637			 SURVEY_INFO_TIME |1638			 SURVEY_INFO_TIME_BUSY;1639	survey->noise = pchan_stats[idx].noise;1640	survey->time = pchan_stats[idx].cca_scan_dur;1641	survey->time_busy = pchan_stats[idx].cca_busy_dur;1642 1643	return 0;1644}1645 1646/* Supported rates to be advertised to the cfg80211 */1647static struct ieee80211_rate mwifiex_rates[] = {1648	{.bitrate = 10, .hw_value = 2, },1649	{.bitrate = 20, .hw_value = 4, },1650	{.bitrate = 55, .hw_value = 11, },1651	{.bitrate = 110, .hw_value = 22, },1652	{.bitrate = 60, .hw_value = 12, },1653	{.bitrate = 90, .hw_value = 18, },1654	{.bitrate = 120, .hw_value = 24, },1655	{.bitrate = 180, .hw_value = 36, },1656	{.bitrate = 240, .hw_value = 48, },1657	{.bitrate = 360, .hw_value = 72, },1658	{.bitrate = 480, .hw_value = 96, },1659	{.bitrate = 540, .hw_value = 108, },1660};1661 1662/* Channel definitions to be advertised to cfg80211 */1663static struct ieee80211_channel mwifiex_channels_2ghz[] = {1664	{.center_freq = 2412, .hw_value = 1, },1665	{.center_freq = 2417, .hw_value = 2, },1666	{.center_freq = 2422, .hw_value = 3, },1667	{.center_freq = 2427, .hw_value = 4, },1668	{.center_freq = 2432, .hw_value = 5, },1669	{.center_freq = 2437, .hw_value = 6, },1670	{.center_freq = 2442, .hw_value = 7, },1671	{.center_freq = 2447, .hw_value = 8, },1672	{.center_freq = 2452, .hw_value = 9, },1673	{.center_freq = 2457, .hw_value = 10, },1674	{.center_freq = 2462, .hw_value = 11, },1675	{.center_freq = 2467, .hw_value = 12, },1676	{.center_freq = 2472, .hw_value = 13, },1677	{.center_freq = 2484, .hw_value = 14, },1678};1679 1680static struct ieee80211_supported_band mwifiex_band_2ghz = {1681	.channels = mwifiex_channels_2ghz,1682	.n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),1683	.bitrates = mwifiex_rates,1684	.n_bitrates = ARRAY_SIZE(mwifiex_rates),1685};1686 1687static struct ieee80211_channel mwifiex_channels_5ghz[] = {1688	{.center_freq = 5040, .hw_value = 8, },1689	{.center_freq = 5060, .hw_value = 12, },1690	{.center_freq = 5080, .hw_value = 16, },1691	{.center_freq = 5170, .hw_value = 34, },1692	{.center_freq = 5190, .hw_value = 38, },1693	{.center_freq = 5210, .hw_value = 42, },1694	{.center_freq = 5230, .hw_value = 46, },1695	{.center_freq = 5180, .hw_value = 36, },1696	{.center_freq = 5200, .hw_value = 40, },1697	{.center_freq = 5220, .hw_value = 44, },1698	{.center_freq = 5240, .hw_value = 48, },1699	{.center_freq = 5260, .hw_value = 52, },1700	{.center_freq = 5280, .hw_value = 56, },1701	{.center_freq = 5300, .hw_value = 60, },1702	{.center_freq = 5320, .hw_value = 64, },1703	{.center_freq = 5500, .hw_value = 100, },1704	{.center_freq = 5520, .hw_value = 104, },1705	{.center_freq = 5540, .hw_value = 108, },1706	{.center_freq = 5560, .hw_value = 112, },1707	{.center_freq = 5580, .hw_value = 116, },1708	{.center_freq = 5600, .hw_value = 120, },1709	{.center_freq = 5620, .hw_value = 124, },1710	{.center_freq = 5640, .hw_value = 128, },1711	{.center_freq = 5660, .hw_value = 132, },1712	{.center_freq = 5680, .hw_value = 136, },1713	{.center_freq = 5700, .hw_value = 140, },1714	{.center_freq = 5745, .hw_value = 149, },1715	{.center_freq = 5765, .hw_value = 153, },1716	{.center_freq = 5785, .hw_value = 157, },1717	{.center_freq = 5805, .hw_value = 161, },1718	{.center_freq = 5825, .hw_value = 165, },1719};1720 1721static struct ieee80211_supported_band mwifiex_band_5ghz = {1722	.channels = mwifiex_channels_5ghz,1723	.n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),1724	.bitrates = mwifiex_rates + 4,1725	.n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,1726};1727 1728 1729/* Supported crypto cipher suits to be advertised to cfg80211 */1730static const u32 mwifiex_cipher_suites[] = {1731	WLAN_CIPHER_SUITE_WEP40,1732	WLAN_CIPHER_SUITE_WEP104,1733	WLAN_CIPHER_SUITE_TKIP,1734	WLAN_CIPHER_SUITE_CCMP,1735	WLAN_CIPHER_SUITE_SMS4,1736	WLAN_CIPHER_SUITE_AES_CMAC,1737};1738 1739/* Supported mgmt frame types to be advertised to cfg80211 */1740static const struct ieee80211_txrx_stypes1741mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {1742	[NL80211_IFTYPE_STATION] = {1743		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1744		      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1745		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1746		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1747	},1748	[NL80211_IFTYPE_AP] = {1749		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1750		      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1751		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1752		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1753	},1754	[NL80211_IFTYPE_P2P_CLIENT] = {1755		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1756		      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1757		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1758		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1759	},1760	[NL80211_IFTYPE_P2P_GO] = {1761		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |1762		      BIT(IEEE80211_STYPE_PROBE_RESP >> 4),1763		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |1764		      BIT(IEEE80211_STYPE_PROBE_REQ >> 4),1765	},1766};1767 1768/*1769 * CFG802.11 operation handler for setting bit rates.1770 *1771 * Function configures data rates to firmware using bitrate mask1772 * provided by cfg80211.1773 */1774static int1775mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,1776				  struct net_device *dev,1777				  unsigned int link_id,1778				  const u8 *peer,1779				  const struct cfg80211_bitrate_mask *mask)1780{1781	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1782	u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];1783	enum nl80211_band band;1784	struct mwifiex_adapter *adapter = priv->adapter;1785 1786	if (!priv->media_connected) {1787		mwifiex_dbg(adapter, ERROR,1788			    "Can not set Tx data rate in disconnected state\n");1789		return -EINVAL;1790	}1791 1792	band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);1793 1794	memset(bitmap_rates, 0, sizeof(bitmap_rates));1795 1796	/* Fill HR/DSSS rates. */1797	if (band == NL80211_BAND_2GHZ)1798		bitmap_rates[0] = mask->control[band].legacy & 0x000f;1799 1800	/* Fill OFDM rates */1801	if (band == NL80211_BAND_2GHZ)1802		bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;1803	else1804		bitmap_rates[1] = mask->control[band].legacy;1805 1806	/* Fill HT MCS rates */1807	bitmap_rates[2] = mask->control[band].ht_mcs[0];1808	if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)1809		bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;1810 1811       /* Fill VHT MCS rates */1812	if (adapter->fw_api_ver == MWIFIEX_FW_V15) {1813		bitmap_rates[10] = mask->control[band].vht_mcs[0];1814		if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)1815			bitmap_rates[11] = mask->control[band].vht_mcs[1];1816	}1817 1818	return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,1819				HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);1820}1821 1822/*1823 * CFG802.11 operation handler for connection quality monitoring.1824 *1825 * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI1826 * events to FW.1827 */1828static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,1829						struct net_device *dev,1830						s32 rssi_thold, u32 rssi_hyst)1831{1832	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1833	struct mwifiex_ds_misc_subsc_evt subsc_evt;1834 1835	priv->cqm_rssi_thold = rssi_thold;1836	priv->cqm_rssi_hyst = rssi_hyst;1837 1838	memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));1839	subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;1840 1841	/* Subscribe/unsubscribe low and high rssi events */1842	if (rssi_thold && rssi_hyst) {1843		subsc_evt.action = HostCmd_ACT_BITWISE_SET;1844		subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);1845		subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);1846		subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;1847		subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;1848		return mwifiex_send_cmd(priv,1849					HostCmd_CMD_802_11_SUBSCRIBE_EVENT,1850					0, 0, &subsc_evt, true);1851	} else {1852		subsc_evt.action = HostCmd_ACT_BITWISE_CLR;1853		return mwifiex_send_cmd(priv,1854					HostCmd_CMD_802_11_SUBSCRIBE_EVENT,1855					0, 0, &subsc_evt, true);1856	}1857 1858	return 0;1859}1860 1861/* cfg80211 operation handler for change_beacon.1862 * Function retrieves and sets modified management IEs to FW.1863 */1864static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,1865					  struct net_device *dev,1866					  struct cfg80211_ap_update *params)1867{1868	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1869	struct mwifiex_adapter *adapter = priv->adapter;1870	struct cfg80211_beacon_data *data = &params->beacon;1871 1872	mwifiex_cancel_scan(adapter);1873 1874	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {1875		mwifiex_dbg(priv->adapter, ERROR,1876			    "%s: bss_type mismatched\n", __func__);1877		return -EINVAL;1878	}1879 1880	if (!priv->bss_started) {1881		mwifiex_dbg(priv->adapter, ERROR,1882			    "%s: bss not started\n", __func__);1883		return -EINVAL;1884	}1885 1886	if (mwifiex_set_mgmt_ies(priv, data)) {1887		mwifiex_dbg(priv->adapter, ERROR,1888			    "%s: setting mgmt ies failed\n", __func__);1889		return -EFAULT;1890	}1891 1892	return 0;1893}1894 1895/* cfg80211 operation handler for del_station.1896 * Function deauthenticates station which value is provided in mac parameter.1897 * If mac is NULL/broadcast, all stations in associated station list are1898 * deauthenticated. If bss is not started or there are no stations in1899 * associated stations list, no action is taken.1900 */1901static int1902mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,1903			     struct station_del_parameters *params)1904{1905	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);1906	struct mwifiex_sta_node *sta_node;1907	u8 deauth_mac[ETH_ALEN];1908 1909	if (!priv->bss_started && priv->wdev.links[0].cac_started) {1910		mwifiex_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__);1911		mwifiex_abort_cac(priv);1912	}1913 1914	if (list_empty(&priv->sta_list) || !priv->bss_started)1915		return 0;1916 1917	if (!params->mac || is_broadcast_ether_addr(params->mac))1918		return 0;1919 1920	mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",1921		    __func__, params->mac);1922 1923	eth_zero_addr(deauth_mac);1924 1925	spin_lock_bh(&priv->sta_list_spinlock);1926	sta_node = mwifiex_get_sta_entry(priv, params->mac);1927	if (sta_node)1928		ether_addr_copy(deauth_mac, params->mac);1929	spin_unlock_bh(&priv->sta_list_spinlock);1930 1931	if (is_valid_ether_addr(deauth_mac)) {1932		if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,1933				     HostCmd_ACT_GEN_SET, 0,1934				     deauth_mac, true))1935			return -1;1936	}1937 1938	return 0;1939}1940 1941static int1942mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)1943{1944	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);1945	struct mwifiex_private *priv = mwifiex_get_priv(adapter,1946							MWIFIEX_BSS_ROLE_ANY);1947	struct mwifiex_ds_ant_cfg ant_cfg;1948 1949	if (!tx_ant || !rx_ant)1950		return -EOPNOTSUPP;1951 1952	if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {1953		/* Not a MIMO chip. User should provide specific antenna number1954		 * for Tx/Rx path or enable all antennas for diversity1955		 */1956		if (tx_ant != rx_ant)1957			return -EOPNOTSUPP;1958 1959		if ((tx_ant & (tx_ant - 1)) &&1960		    (tx_ant != BIT(adapter->number_of_antenna) - 1))1961			return -EOPNOTSUPP;1962 1963		if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&1964		    (priv->adapter->number_of_antenna > 1)) {1965			tx_ant = RF_ANTENNA_AUTO;1966			rx_ant = RF_ANTENNA_AUTO;1967		}1968	} else {1969		struct ieee80211_sta_ht_cap *ht_info;1970		int rx_mcs_supp;1971		enum nl80211_band band;1972 1973		if ((tx_ant == 0x1 && rx_ant == 0x1)) {1974			adapter->user_dev_mcs_support = HT_STREAM_1X1;1975			if (adapter->is_hw_11ac_capable)1976				adapter->usr_dot_11ac_mcs_support =1977						MWIFIEX_11AC_MCS_MAP_1X1;1978		} else {1979			adapter->user_dev_mcs_support = HT_STREAM_2X2;1980			if (adapter->is_hw_11ac_capable)1981				adapter->usr_dot_11ac_mcs_support =1982						MWIFIEX_11AC_MCS_MAP_2X2;1983		}1984 1985		for (band = 0; band < NUM_NL80211_BANDS; band++) {1986			if (!adapter->wiphy->bands[band])1987				continue;1988 1989			ht_info = &adapter->wiphy->bands[band]->ht_cap;1990			rx_mcs_supp =1991				GET_RXMCSSUPP(adapter->user_dev_mcs_support);1992			memset(&ht_info->mcs, 0, adapter->number_of_antenna);1993			memset(&ht_info->mcs, 0xff, rx_mcs_supp);1994		}1995	}1996 1997	ant_cfg.tx_ant = tx_ant;1998	ant_cfg.rx_ant = rx_ant;1999 2000	return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,2001				HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);2002}2003 2004static int2005mwifiex_cfg80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)2006{2007	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);2008	struct mwifiex_private *priv = mwifiex_get_priv(adapter,2009							MWIFIEX_BSS_ROLE_ANY);2010	mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,2011			 HostCmd_ACT_GEN_GET, 0, NULL, true);2012 2013	*tx_ant = priv->tx_ant;2014	*rx_ant = priv->rx_ant;2015 2016	return 0;2017}2018 2019/* cfg80211 operation handler for stop ap.2020 * Function stops BSS running at uAP interface.2021 */2022static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,2023				    unsigned int link_id)2024{2025	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2026 2027	mwifiex_abort_cac(priv);2028 2029	if (mwifiex_del_mgmt_ies(priv))2030		mwifiex_dbg(priv->adapter, ERROR,2031			    "Failed to delete mgmt IEs!\n");2032 2033	priv->ap_11n_enabled = 0;2034	memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));2035 2036	if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,2037			     HostCmd_ACT_GEN_SET, 0, NULL, true)) {2038		mwifiex_dbg(priv->adapter, ERROR,2039			    "Failed to stop the BSS\n");2040		return -1;2041	}2042 2043	if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,2044			     HostCmd_ACT_GEN_SET, 0, NULL, true)) {2045		mwifiex_dbg(priv->adapter, ERROR,2046			    "Failed to reset BSS\n");2047		return -1;2048	}2049 2050	if (netif_carrier_ok(priv->netdev))2051		netif_carrier_off(priv->netdev);2052	mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);2053 2054	return 0;2055}2056 2057/* cfg80211 operation handler for start_ap.2058 * Function sets beacon period, DTIM period, SSID and security into2059 * AP config structure.2060 * AP is configured with these settings and BSS is started.2061 */2062static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,2063				     struct net_device *dev,2064				     struct cfg80211_ap_settings *params)2065{2066	struct mwifiex_uap_bss_param *bss_cfg;2067	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2068 2069	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)2070		return -1;2071 2072	bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);2073	if (!bss_cfg)2074		return -ENOMEM;2075 2076	mwifiex_set_sys_config_invalid_data(bss_cfg);2077 2078	memcpy(bss_cfg->mac_addr, priv->curr_addr, ETH_ALEN);2079 2080	if (params->beacon_interval)2081		bss_cfg->beacon_period = params->beacon_interval;2082	if (params->dtim_period)2083		bss_cfg->dtim_period = params->dtim_period;2084 2085	if (params->ssid && params->ssid_len) {2086		memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);2087		bss_cfg->ssid.ssid_len = params->ssid_len;2088	}2089	if (params->inactivity_timeout > 0) {2090		/* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */2091		bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;2092		bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;2093	}2094 2095	switch (params->hidden_ssid) {2096	case NL80211_HIDDEN_SSID_NOT_IN_USE:2097		bss_cfg->bcast_ssid_ctl = 1;2098		break;2099	case NL80211_HIDDEN_SSID_ZERO_LEN:2100		bss_cfg->bcast_ssid_ctl = 0;2101		break;2102	case NL80211_HIDDEN_SSID_ZERO_CONTENTS:2103		bss_cfg->bcast_ssid_ctl = 2;2104		break;2105	default:2106		kfree(bss_cfg);2107		return -EINVAL;2108	}2109 2110	mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);2111	mwifiex_set_uap_rates(bss_cfg, params);2112 2113	if (mwifiex_set_secure_params(priv, bss_cfg, params)) {2114		mwifiex_dbg(priv->adapter, ERROR,2115			    "Failed to parse security parameters!\n");2116		goto out;2117	}2118 2119	mwifiex_set_ht_params(priv, bss_cfg, params);2120 2121	if (priv->adapter->is_hw_11ac_capable) {2122		mwifiex_set_vht_params(priv, bss_cfg, params);2123		mwifiex_set_vht_width(priv, params->chandef.width,2124				      priv->ap_11ac_enabled);2125	}2126 2127	if (priv->ap_11ac_enabled)2128		mwifiex_set_11ac_ba_params(priv);2129	else2130		mwifiex_set_ba_params(priv);2131 2132	mwifiex_set_wmm_params(priv, bss_cfg, params);2133 2134	if (mwifiex_is_11h_active(priv))2135		mwifiex_set_tpc_params(priv, bss_cfg, params);2136 2137	if (mwifiex_is_11h_active(priv) &&2138	    !cfg80211_chandef_dfs_required(wiphy, &params->chandef,2139					   priv->bss_mode)) {2140		mwifiex_dbg(priv->adapter, INFO,2141			    "Disable 11h extensions in FW\n");2142		if (mwifiex_11h_activate(priv, false)) {2143			mwifiex_dbg(priv->adapter, ERROR,2144				    "Failed to disable 11h extensions!!");2145			goto out;2146		}2147		priv->state_11h.is_11h_active = false;2148	}2149 2150	mwifiex_config_uap_11d(priv, &params->beacon);2151 2152	if (mwifiex_config_start_uap(priv, bss_cfg)) {2153		mwifiex_dbg(priv->adapter, ERROR,2154			    "Failed to start AP\n");2155		goto out;2156	}2157 2158	if (mwifiex_set_mgmt_ies(priv, &params->beacon))2159		goto out;2160 2161	if (!netif_carrier_ok(priv->netdev))2162		netif_carrier_on(priv->netdev);2163	mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter);2164 2165	memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));2166	kfree(bss_cfg);2167	return 0;2168 2169out:2170	kfree(bss_cfg);2171	return -1;2172}2173 2174/*2175 * CFG802.11 operation handler for disconnection request.2176 *2177 * This function does not work when there is already a disconnection2178 * procedure going on.2179 */2180static int2181mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,2182			    u16 reason_code)2183{2184	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2185 2186	if (!mwifiex_stop_bg_scan(priv))2187		cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);2188 2189	if (mwifiex_deauthenticate(priv, NULL))2190		return -EFAULT;2191 2192	eth_zero_addr(priv->cfg_bssid);2193	priv->hs2_enabled = false;2194 2195	return 0;2196}2197 2198/*2199 * This function informs the CFG802.11 subsystem of a new IBSS.2200 *2201 * The following information are sent to the CFG802.11 subsystem2202 * to register the new IBSS. If we do not register the new IBSS,2203 * a kernel panic will result.2204 *      - SSID2205 *      - SSID length2206 *      - BSSID2207 *      - Channel2208 */2209static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)2210{2211	struct ieee80211_channel *chan;2212	struct mwifiex_bss_info bss_info;2213	struct cfg80211_bss *bss;2214	int ie_len;2215	u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];2216	enum nl80211_band band;2217 2218	if (mwifiex_get_bss_info(priv, &bss_info))2219		return -1;2220 2221	ie_buf[0] = WLAN_EID_SSID;2222	ie_buf[1] = bss_info.ssid.ssid_len;2223 2224	memcpy(&ie_buf[sizeof(struct ieee_types_header)],2225	       &bss_info.ssid.ssid, bss_info.ssid.ssid_len);2226	ie_len = ie_buf[1] + sizeof(struct ieee_types_header);2227 2228	band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);2229	chan = ieee80211_get_channel(priv->wdev.wiphy,2230			ieee80211_channel_to_frequency(bss_info.bss_chan,2231						       band));2232 2233	bss = cfg80211_inform_bss(priv->wdev.wiphy, chan,2234				  CFG80211_BSS_FTYPE_UNKNOWN,2235				  bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,2236				  0, ie_buf, ie_len, 0, GFP_KERNEL);2237	if (bss) {2238		cfg80211_put_bss(priv->wdev.wiphy, bss);2239		ether_addr_copy(priv->cfg_bssid, bss_info.bssid);2240	}2241 2242	return 0;2243}2244 2245/*2246 * This function connects with a BSS.2247 *2248 * This function handles both Infra and Ad-Hoc modes. It also performs2249 * validity checking on the provided parameters, disconnects from the2250 * current BSS (if any), sets up the association/scan parameters,2251 * including security settings, and performs specific SSID scan before2252 * trying to connect.2253 *2254 * For Infra mode, the function returns failure if the specified SSID2255 * is not found in scan table. However, for Ad-Hoc mode, it can create2256 * the IBSS if it does not exist. On successful completion in either case,2257 * the function notifies the CFG802.11 subsystem of the new BSS connection.2258 */2259static int2260mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,2261		       const u8 *ssid, const u8 *bssid, int mode,2262		       struct ieee80211_channel *channel,2263		       struct cfg80211_connect_params *sme, bool privacy,2264		       struct cfg80211_bss **sel_bss)2265{2266	struct cfg80211_ssid req_ssid;2267	int ret, auth_type = 0;2268	struct cfg80211_bss *bss = NULL;2269	u8 is_scanning_required = 0;2270 2271	memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));2272 2273	req_ssid.ssid_len = ssid_len;2274	if (ssid_len > IEEE80211_MAX_SSID_LEN) {2275		mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");2276		return -EINVAL;2277	}2278 2279	memcpy(req_ssid.ssid, ssid, ssid_len);2280	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {2281		mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");2282		return -EINVAL;2283	}2284 2285	/* As this is new association, clear locally stored2286	 * keys and security related flags */2287	priv->sec_info.wpa_enabled = false;2288	priv->sec_info.wpa2_enabled = false;2289	priv->wep_key_curr_index = 0;2290	priv->sec_info.encryption_mode = 0;2291	priv->sec_info.is_authtype_auto = 0;2292	ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);2293 2294	if (mode == NL80211_IFTYPE_ADHOC) {2295		u16 enable = true;2296 2297		/* set ibss coalescing_status */2298		ret = mwifiex_send_cmd(2299				priv,2300				HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,2301				HostCmd_ACT_GEN_SET, 0, &enable, true);2302		if (ret)2303			return ret;2304 2305		/* "privacy" is set only for ad-hoc mode */2306		if (privacy) {2307			/*2308			 * Keep WLAN_CIPHER_SUITE_WEP104 for now so that2309			 * the firmware can find a matching network from the2310			 * scan. The cfg80211 does not give us the encryption2311			 * mode at this stage so just setting it to WEP here.2312			 */2313			priv->sec_info.encryption_mode =2314					WLAN_CIPHER_SUITE_WEP104;2315			priv->sec_info.authentication_mode =2316					NL80211_AUTHTYPE_OPEN_SYSTEM;2317		}2318 2319		goto done;2320	}2321 2322	/* Now handle infra mode. "sme" is valid for infra mode only */2323	if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {2324		auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;2325		priv->sec_info.is_authtype_auto = 1;2326	} else {2327		auth_type = sme->auth_type;2328	}2329 2330	if (sme->crypto.n_ciphers_pairwise) {2331		priv->sec_info.encryption_mode =2332						sme->crypto.ciphers_pairwise[0];2333		priv->sec_info.authentication_mode = auth_type;2334	}2335 2336	if (sme->crypto.cipher_group) {2337		priv->sec_info.encryption_mode = sme->crypto.cipher_group;2338		priv->sec_info.authentication_mode = auth_type;2339	}2340	if (sme->ie)2341		ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);2342 2343	if (sme->key) {2344		if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {2345			mwifiex_dbg(priv->adapter, INFO,2346				    "info: setting wep encryption\t"2347				    "with key len %d\n", sme->key_len);2348			priv->wep_key_curr_index = sme->key_idx;2349			ret = mwifiex_set_encode(priv, NULL, sme->key,2350						 sme->key_len, sme->key_idx,2351						 NULL, 0);2352		}2353	}2354done:2355	/*2356	 * Scan entries are valid for some time (15 sec). So we can save one2357	 * active scan time if we just try cfg80211_get_bss first. If it fails2358	 * then request scan and cfg80211_get_bss() again for final output.2359	 */2360	while (1) {2361		if (is_scanning_required) {2362			/* Do specific SSID scanning */2363			if (mwifiex_request_scan(priv, &req_ssid)) {2364				mwifiex_dbg(priv->adapter, ERROR, "scan error\n");2365				return -EFAULT;2366			}2367		}2368 2369		/* Find the BSS we want using available scan results */2370		if (mode == NL80211_IFTYPE_ADHOC)2371			bss = cfg80211_get_bss(priv->wdev.wiphy, channel,2372					       bssid, ssid, ssid_len,2373					       IEEE80211_BSS_TYPE_IBSS,2374					       IEEE80211_PRIVACY_ANY);2375		else2376			bss = cfg80211_get_bss(priv->wdev.wiphy, channel,2377					       bssid, ssid, ssid_len,2378					       IEEE80211_BSS_TYPE_ESS,2379					       IEEE80211_PRIVACY_ANY);2380 2381		if (!bss) {2382			if (is_scanning_required) {2383				mwifiex_dbg(priv->adapter, MSG,2384					    "assoc: requested bss not found in scan results\n");2385				break;2386			}2387			is_scanning_required = 1;2388		} else {2389			mwifiex_dbg(priv->adapter, MSG,2390				    "info: trying to associate to bssid %pM\n",2391				    bss->bssid);2392			memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);2393			break;2394		}2395	}2396 2397	if (bss)2398		cfg80211_ref_bss(priv->adapter->wiphy, bss);2399 2400	ret = mwifiex_bss_start(priv, bss, &req_ssid);2401	if (ret)2402		goto cleanup;2403 2404	if (mode == NL80211_IFTYPE_ADHOC) {2405		/* Inform the BSS information to kernel, otherwise2406		 * kernel will give a panic after successful assoc */2407		if (mwifiex_cfg80211_inform_ibss_bss(priv)) {2408			ret = -EFAULT;2409			goto cleanup;2410		}2411	}2412 2413	/* Pass the selected BSS entry to caller. */2414	if (sel_bss) {2415		*sel_bss = bss;2416		bss = NULL;2417	}2418 2419cleanup:2420	if (bss)2421		cfg80211_put_bss(priv->adapter->wiphy, bss);2422	return ret;2423}2424 2425/*2426 * CFG802.11 operation handler for association request.2427 *2428 * This function does not work when the current mode is set to Ad-Hoc, or2429 * when there is already an association procedure going on. The given BSS2430 * information is used to associate.2431 */2432static int2433mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,2434			 struct cfg80211_connect_params *sme)2435{2436	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2437	struct mwifiex_adapter *adapter = priv->adapter;2438	struct cfg80211_bss *bss = NULL;2439	int ret;2440 2441	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {2442		mwifiex_dbg(adapter, ERROR,2443			    "%s: reject infra assoc request in non-STA role\n",2444			    dev->name);2445		return -EINVAL;2446	}2447 2448	if (priv->wdev.connected) {2449		mwifiex_dbg(adapter, ERROR,2450			    "%s: already connected\n", dev->name);2451		return -EALREADY;2452	}2453 2454	if (priv->scan_block)2455		priv->scan_block = false;2456 2457	if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||2458	    test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {2459		mwifiex_dbg(adapter, ERROR,2460			    "%s: Ignore connection.\t"2461			    "Card removed or FW in bad state\n",2462			    dev->name);2463		return -EFAULT;2464	}2465 2466	mwifiex_dbg(adapter, INFO,2467		    "info: Trying to associate to bssid %pM\n", sme->bssid);2468 2469	if (!mwifiex_stop_bg_scan(priv))2470		cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);2471 2472	ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,2473				     priv->bss_mode, sme->channel, sme, 0,2474				     &bss);2475	if (!ret) {2476		cfg80211_connect_bss(priv->netdev, priv->cfg_bssid, bss, NULL,2477				     0, NULL, 0, WLAN_STATUS_SUCCESS,2478				     GFP_KERNEL, NL80211_TIMEOUT_UNSPECIFIED);2479		mwifiex_dbg(priv->adapter, MSG,2480			    "info: associated to bssid %pM successfully\n",2481			    priv->cfg_bssid);2482		if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&2483		    priv->adapter->auto_tdls &&2484		    priv->bss_type == MWIFIEX_BSS_TYPE_STA)2485			mwifiex_setup_auto_tdls_timer(priv);2486	} else {2487		mwifiex_dbg(priv->adapter, ERROR,2488			    "info: association to bssid %pM failed\n",2489			    priv->cfg_bssid);2490		eth_zero_addr(priv->cfg_bssid);2491 2492		if (ret > 0)2493			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,2494						NULL, 0, NULL, 0, ret,2495						GFP_KERNEL);2496		else2497			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,2498						NULL, 0, NULL, 0,2499						WLAN_STATUS_UNSPECIFIED_FAILURE,2500						GFP_KERNEL);2501	}2502 2503	return 0;2504}2505 2506/*2507 * This function sets following parameters for ibss network.2508 *  -  channel2509 *  -  start band2510 *  -  11n flag2511 *  -  secondary channel offset2512 */2513static int mwifiex_set_ibss_params(struct mwifiex_private *priv,2514				   struct cfg80211_ibss_params *params)2515{2516	struct mwifiex_adapter *adapter = priv->adapter;2517	int index = 0, i;2518	u8 config_bands = 0;2519 2520	if (params->chandef.chan->band == NL80211_BAND_2GHZ) {2521		if (!params->basic_rates) {2522			config_bands = BAND_B | BAND_G;2523		} else {2524			for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {2525				/*2526				 * Rates below 6 Mbps in the table are CCK2527				 * rates; 802.11b and from 6 they are OFDM;2528				 * 802.11G2529				 */2530				if (mwifiex_rates[i].bitrate == 60) {2531					index = 1 << i;2532					break;2533				}2534			}2535 2536			if (params->basic_rates < index) {2537				config_bands = BAND_B;2538			} else {2539				config_bands = BAND_G;2540				if (params->basic_rates % index)2541					config_bands |= BAND_B;2542			}2543		}2544 2545		if (cfg80211_get_chandef_type(&params->chandef) !=2546						NL80211_CHAN_NO_HT)2547			config_bands |= BAND_G | BAND_GN;2548	} else {2549		if (cfg80211_get_chandef_type(&params->chandef) ==2550						NL80211_CHAN_NO_HT)2551			config_bands = BAND_A;2552		else2553			config_bands = BAND_AN | BAND_A;2554	}2555 2556	if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {2557		adapter->config_bands = config_bands;2558		adapter->adhoc_start_band = config_bands;2559 2560		if ((config_bands & BAND_GN) || (config_bands & BAND_AN))2561			adapter->adhoc_11n_enabled = true;2562		else2563			adapter->adhoc_11n_enabled = false;2564	}2565 2566	adapter->sec_chan_offset =2567		mwifiex_chan_type_to_sec_chan_offset(2568			cfg80211_get_chandef_type(&params->chandef));2569	priv->adhoc_channel = ieee80211_frequency_to_channel(2570				params->chandef.chan->center_freq);2571 2572	mwifiex_dbg(adapter, INFO,2573		    "info: set ibss band %d, chan %d, chan offset %d\n",2574		    config_bands, priv->adhoc_channel,2575		    adapter->sec_chan_offset);2576 2577	return 0;2578}2579 2580/*2581 * CFG802.11 operation handler to join an IBSS.2582 *2583 * This function does not work in any mode other than Ad-Hoc, or if2584 * a join operation is already in progress.2585 */2586static int2587mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,2588			   struct cfg80211_ibss_params *params)2589{2590	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2591	int ret = 0;2592 2593	if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {2594		mwifiex_dbg(priv->adapter, ERROR,2595			    "request to join ibss received\t"2596			    "when station is not in ibss mode\n");2597		goto done;2598	}2599 2600	mwifiex_dbg(priv->adapter, MSG, "info: trying to join to bssid %pM\n",2601		    params->bssid);2602 2603	mwifiex_set_ibss_params(priv, params);2604 2605	ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,2606				     params->bssid, priv->bss_mode,2607				     params->chandef.chan, NULL,2608				     params->privacy, NULL);2609done:2610	if (!ret) {2611		cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,2612				     params->chandef.chan, GFP_KERNEL);2613		mwifiex_dbg(priv->adapter, MSG,2614			    "info: joined/created adhoc network with bssid\t"2615			    "%pM successfully\n", priv->cfg_bssid);2616	} else {2617		mwifiex_dbg(priv->adapter, ERROR,2618			    "info: failed creating/joining adhoc network\n");2619	}2620 2621	return ret;2622}2623 2624/*2625 * CFG802.11 operation handler to leave an IBSS.2626 *2627 * This function does not work if a leave operation is2628 * already in progress.2629 */2630static int2631mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)2632{2633	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2634 2635	mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",2636		    priv->cfg_bssid);2637	if (mwifiex_deauthenticate(priv, NULL))2638		return -EFAULT;2639 2640	eth_zero_addr(priv->cfg_bssid);2641 2642	return 0;2643}2644 2645/*2646 * CFG802.11 operation handler for scan request.2647 *2648 * This function issues a scan request to the firmware based upon2649 * the user specified scan configuration. On successful completion,2650 * it also informs the results.2651 */2652static int2653mwifiex_cfg80211_scan(struct wiphy *wiphy,2654		      struct cfg80211_scan_request *request)2655{2656	struct net_device *dev = request->wdev->netdev;2657	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2658	int i, offset, ret;2659	struct ieee80211_channel *chan;2660	struct ieee_types_header *ie;2661	struct mwifiex_user_scan_cfg *user_scan_cfg;2662	u8 mac_addr[ETH_ALEN];2663 2664	mwifiex_dbg(priv->adapter, CMD,2665		    "info: received scan request on %s\n", dev->name);2666 2667	/* Block scan request if scan operation or scan cleanup when interface2668	 * is disabled is in process2669	 */2670	if (priv->scan_request || priv->scan_aborting) {2671		mwifiex_dbg(priv->adapter, WARN,2672			    "cmd: Scan already in process..\n");2673		return -EBUSY;2674	}2675 2676	if (!priv->wdev.connected && priv->scan_block)2677		priv->scan_block = false;2678 2679	if (!mwifiex_stop_bg_scan(priv))2680		cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);2681 2682	user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);2683	if (!user_scan_cfg)2684		return -ENOMEM;2685 2686	priv->scan_request = request;2687 2688	if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {2689		get_random_mask_addr(mac_addr, request->mac_addr,2690				     request->mac_addr_mask);2691		ether_addr_copy(request->mac_addr, mac_addr);2692		ether_addr_copy(user_scan_cfg->random_mac, mac_addr);2693	}2694 2695	user_scan_cfg->num_ssids = request->n_ssids;2696	user_scan_cfg->ssid_list = request->ssids;2697 2698	if (request->ie && request->ie_len) {2699		offset = 0;2700		for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {2701			if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)2702				continue;2703			priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;2704			ie = (struct ieee_types_header *)(request->ie + offset);2705			memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);2706			offset += sizeof(*ie) + ie->len;2707 2708			if (offset >= request->ie_len)2709				break;2710		}2711	}2712 2713	for (i = 0; i < min_t(u32, request->n_channels,2714			      MWIFIEX_USER_SCAN_CHAN_MAX); i++) {2715		chan = request->channels[i];2716		user_scan_cfg->chan_list[i].chan_number = chan->hw_value;2717		user_scan_cfg->chan_list[i].radio_type = chan->band;2718 2719		if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)2720			user_scan_cfg->chan_list[i].scan_type =2721						MWIFIEX_SCAN_TYPE_PASSIVE;2722		else2723			user_scan_cfg->chan_list[i].scan_type =2724						MWIFIEX_SCAN_TYPE_ACTIVE;2725 2726		user_scan_cfg->chan_list[i].scan_time = 0;2727	}2728 2729	if (priv->adapter->scan_chan_gap_enabled &&2730	    mwifiex_is_any_intf_active(priv))2731		user_scan_cfg->scan_chan_gap =2732					      priv->adapter->scan_chan_gap_time;2733 2734	ret = mwifiex_scan_networks(priv, user_scan_cfg);2735	kfree(user_scan_cfg);2736	if (ret) {2737		mwifiex_dbg(priv->adapter, ERROR,2738			    "scan failed: %d\n", ret);2739		priv->scan_aborting = false;2740		priv->scan_request = NULL;2741		return ret;2742	}2743 2744	if (request->ie && request->ie_len) {2745		for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {2746			if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {2747				priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;2748				memset(&priv->vs_ie[i].ie, 0,2749				       MWIFIEX_MAX_VSIE_LEN);2750			}2751		}2752	}2753	return 0;2754}2755 2756/* CFG802.11 operation handler for sched_scan_start.2757 *2758 * This function issues a bgscan config request to the firmware based upon2759 * the user specified sched_scan configuration. On successful completion,2760 * firmware will generate BGSCAN_REPORT event, driver should issue bgscan2761 * query command to get sched_scan results from firmware.2762 */2763static int2764mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy,2765				  struct net_device *dev,2766				  struct cfg80211_sched_scan_request *request)2767{2768	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2769	int i, offset;2770	struct ieee80211_channel *chan;2771	struct mwifiex_bg_scan_cfg *bgscan_cfg;2772	struct ieee_types_header *ie;2773 2774	if (!request || (!request->n_ssids && !request->n_match_sets)) {2775		wiphy_err(wiphy, "%s : Invalid Sched_scan parameters",2776			  __func__);2777		return -EINVAL;2778	}2779 2780	wiphy_info(wiphy, "sched_scan start : n_ssids=%d n_match_sets=%d ",2781		   request->n_ssids, request->n_match_sets);2782	wiphy_info(wiphy, "n_channels=%d interval=%d ie_len=%d\n",2783		   request->n_channels, request->scan_plans->interval,2784		   (int)request->ie_len);2785 2786	bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);2787	if (!bgscan_cfg)2788		return -ENOMEM;2789 2790	if (priv->scan_request || priv->scan_aborting)2791		bgscan_cfg->start_later = true;2792 2793	bgscan_cfg->num_ssids = request->n_match_sets;2794	bgscan_cfg->ssid_list = request->match_sets;2795 2796	if (request->ie && request->ie_len) {2797		offset = 0;2798		for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {2799			if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)2800				continue;2801			priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_BGSCAN;2802			ie = (struct ieee_types_header *)(request->ie + offset);2803			memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);2804			offset += sizeof(*ie) + ie->len;2805 2806			if (offset >= request->ie_len)2807				break;2808		}2809	}2810 2811	for (i = 0; i < min_t(u32, request->n_channels,2812			      MWIFIEX_BG_SCAN_CHAN_MAX); i++) {2813		chan = request->channels[i];2814		bgscan_cfg->chan_list[i].chan_number = chan->hw_value;2815		bgscan_cfg->chan_list[i].radio_type = chan->band;2816 2817		if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)2818			bgscan_cfg->chan_list[i].scan_type =2819						MWIFIEX_SCAN_TYPE_PASSIVE;2820		else2821			bgscan_cfg->chan_list[i].scan_type =2822						MWIFIEX_SCAN_TYPE_ACTIVE;2823 2824		bgscan_cfg->chan_list[i].scan_time = 0;2825	}2826 2827	bgscan_cfg->chan_per_scan = min_t(u32, request->n_channels,2828					  MWIFIEX_BG_SCAN_CHAN_MAX);2829 2830	/* Use at least 15 second for per scan cycle */2831	bgscan_cfg->scan_interval = (request->scan_plans->interval >2832				     MWIFIEX_BGSCAN_INTERVAL) ?2833				request->scan_plans->interval :2834				MWIFIEX_BGSCAN_INTERVAL;2835 2836	bgscan_cfg->repeat_count = MWIFIEX_BGSCAN_REPEAT_COUNT;2837	bgscan_cfg->report_condition = MWIFIEX_BGSCAN_SSID_MATCH |2838				MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE;2839	bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;2840	bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;2841	bgscan_cfg->enable = true;2842	if (request->min_rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) {2843		bgscan_cfg->report_condition |= MWIFIEX_BGSCAN_SSID_RSSI_MATCH;2844		bgscan_cfg->rssi_threshold = request->min_rssi_thold;2845	}2846 2847	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,2848			     HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {2849		kfree(bgscan_cfg);2850		return -EFAULT;2851	}2852 2853	priv->sched_scanning = true;2854 2855	kfree(bgscan_cfg);2856	return 0;2857}2858 2859/* CFG802.11 operation handler for sched_scan_stop.2860 *2861 * This function issues a bgscan config command to disable2862 * previous bgscan configuration in the firmware2863 */2864static int mwifiex_cfg80211_sched_scan_stop(struct wiphy *wiphy,2865					    struct net_device *dev, u64 reqid)2866{2867	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);2868 2869	wiphy_info(wiphy, "sched scan stop!");2870	mwifiex_stop_bg_scan(priv);2871 2872	return 0;2873}2874 2875static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,2876				   struct mwifiex_private *priv)2877{2878	struct mwifiex_adapter *adapter = priv->adapter;2879 2880	vht_info->vht_supported = true;2881 2882	vht_info->cap = adapter->hw_dot_11ac_dev_cap;2883	/* Update MCS support for VHT */2884	vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(2885				adapter->hw_dot_11ac_mcs_support & 0xFFFF);2886	vht_info->vht_mcs.rx_highest = 0;2887	vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(2888				adapter->hw_dot_11ac_mcs_support >> 16);2889	vht_info->vht_mcs.tx_highest = 0;2890}2891 2892/*2893 * This function sets up the CFG802.11 specific HT capability fields2894 * with default values.2895 *2896 * The following default values are set -2897 *      - HT Supported = True2898 *      - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K2899 *      - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE2900 *      - HT Capabilities supported by firmware2901 *      - MCS information, Rx mask = 0xff2902 *      - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)2903 */2904static void2905mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,2906		      struct mwifiex_private *priv)2907{2908	int rx_mcs_supp;2909	struct ieee80211_mcs_info mcs_set;2910	u8 *mcs = (u8 *)&mcs_set;2911	struct mwifiex_adapter *adapter = priv->adapter;2912 2913	ht_info->ht_supported = true;2914	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;2915	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;2916 2917	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));2918 2919	/* Fill HT capability information */2920	if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))2921		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;2922	else2923		ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;2924 2925	if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))2926		ht_info->cap |= IEEE80211_HT_CAP_SGI_20;2927	else2928		ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;2929 2930	if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))2931		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;2932	else2933		ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;2934 2935	if (adapter->user_dev_mcs_support == HT_STREAM_2X2)2936		ht_info->cap |= 2 << IEEE80211_HT_CAP_RX_STBC_SHIFT;2937	else2938		ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;2939 2940	if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))2941		ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;2942	else2943		ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;2944 2945	if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))2946		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;2947	else2948		ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;2949 2950	if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))2951		ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;2952	else2953		ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;2954 2955	if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))2956		ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;2957	else2958		ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;2959 2960	ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;2961	ht_info->cap |= IEEE80211_HT_CAP_SM_PS;2962 2963	rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);2964	/* Set MCS for 1x1/2x2 */2965	memset(mcs, 0xff, rx_mcs_supp);2966	/* Clear all the other values */2967	memset(&mcs[rx_mcs_supp], 0,2968	       sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);2969	if (priv->bss_mode == NL80211_IFTYPE_STATION ||2970	    ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))2971		/* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */2972		SETHT_MCS32(mcs_set.rx_mask);2973 2974	memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));2975 2976	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;2977}2978 2979/*2980 *  create a new virtual interface with the given name and name assign type2981 */2982struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,2983					      const char *name,2984					      unsigned char name_assign_type,2985					      enum nl80211_iftype type,2986					      struct vif_params *params)2987{2988	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);2989	struct mwifiex_private *priv;2990	struct net_device *dev;2991	void *mdev_priv;2992	int ret;2993 2994	if (!adapter)2995		return ERR_PTR(-EFAULT);2996 2997	switch (type) {2998	case NL80211_IFTYPE_UNSPECIFIED:2999	case NL80211_IFTYPE_STATION:3000	case NL80211_IFTYPE_ADHOC:3001		if (adapter->curr_iface_comb.sta_intf ==3002		    adapter->iface_limit.sta_intf) {3003			mwifiex_dbg(adapter, ERROR,3004				    "cannot create multiple sta/adhoc ifaces\n");3005			return ERR_PTR(-EINVAL);3006		}3007 3008		priv = mwifiex_get_unused_priv_by_bss_type(3009						adapter, MWIFIEX_BSS_TYPE_STA);3010		if (!priv) {3011			mwifiex_dbg(adapter, ERROR,3012				    "could not get free private struct\n");3013			return ERR_PTR(-EFAULT);3014		}3015 3016		priv->wdev.wiphy = wiphy;3017		priv->wdev.iftype = NL80211_IFTYPE_STATION;3018 3019		if (type == NL80211_IFTYPE_UNSPECIFIED)3020			priv->bss_mode = NL80211_IFTYPE_STATION;3021		else3022			priv->bss_mode = type;3023 3024		priv->bss_type = MWIFIEX_BSS_TYPE_STA;3025		priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;3026		priv->bss_priority = 0;3027		priv->bss_role = MWIFIEX_BSS_ROLE_STA;3028 3029		break;3030	case NL80211_IFTYPE_AP:3031		if (adapter->curr_iface_comb.uap_intf ==3032		    adapter->iface_limit.uap_intf) {3033			mwifiex_dbg(adapter, ERROR,3034				    "cannot create multiple AP ifaces\n");3035			return ERR_PTR(-EINVAL);3036		}3037 3038		priv = mwifiex_get_unused_priv_by_bss_type(3039						adapter, MWIFIEX_BSS_TYPE_UAP);3040		if (!priv) {3041			mwifiex_dbg(adapter, ERROR,3042				    "could not get free private struct\n");3043			return ERR_PTR(-EFAULT);3044		}3045 3046		priv->wdev.wiphy = wiphy;3047		priv->wdev.iftype = NL80211_IFTYPE_AP;3048 3049		priv->bss_type = MWIFIEX_BSS_TYPE_UAP;3050		priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;3051		priv->bss_priority = 0;3052		priv->bss_role = MWIFIEX_BSS_ROLE_UAP;3053		priv->bss_started = 0;3054		priv->bss_mode = type;3055 3056		break;3057	case NL80211_IFTYPE_P2P_CLIENT:3058		if (adapter->curr_iface_comb.p2p_intf ==3059		    adapter->iface_limit.p2p_intf) {3060			mwifiex_dbg(adapter, ERROR,3061				    "cannot create multiple P2P ifaces\n");3062			return ERR_PTR(-EINVAL);3063		}3064 3065		priv = mwifiex_get_unused_priv_by_bss_type(3066						adapter, MWIFIEX_BSS_TYPE_P2P);3067		if (!priv) {3068			mwifiex_dbg(adapter, ERROR,3069				    "could not get free private struct\n");3070			return ERR_PTR(-EFAULT);3071		}3072 3073		priv->wdev.wiphy = wiphy;3074		/* At start-up, wpa_supplicant tries to change the interface3075		 * to NL80211_IFTYPE_STATION if it is not managed mode.3076		 */3077		priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;3078		priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;3079 3080		/* Setting bss_type to P2P tells firmware that this interface3081		 * is receiving P2P peers found during find phase and doing3082		 * action frame handshake.3083		 */3084		priv->bss_type = MWIFIEX_BSS_TYPE_P2P;3085 3086		priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;3087		priv->bss_priority = 0;3088		priv->bss_role = MWIFIEX_BSS_ROLE_STA;3089		priv->bss_started = 0;3090 3091		if (mwifiex_cfg80211_init_p2p_client(priv)) {3092			memset(&priv->wdev, 0, sizeof(priv->wdev));3093			priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;3094			return ERR_PTR(-EFAULT);3095		}3096 3097		break;3098	default:3099		mwifiex_dbg(adapter, ERROR, "type not supported\n");3100		return ERR_PTR(-EINVAL);3101	}3102 3103	dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,3104			       name_assign_type, ether_setup,3105			       IEEE80211_NUM_ACS, 1);3106	if (!dev) {3107		mwifiex_dbg(adapter, ERROR,3108			    "no memory available for netdevice\n");3109		ret = -ENOMEM;3110		goto err_alloc_netdev;3111	}3112 3113	mwifiex_init_priv_params(priv, dev);3114 3115	priv->netdev = dev;3116 3117	if (!adapter->mfg_mode) {3118		mwifiex_set_mac_address(priv, dev, false, NULL);3119 3120		ret = mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,3121				       HostCmd_ACT_GEN_SET, 0, NULL, true);3122		if (ret)3123			goto err_set_bss_mode;3124 3125		ret = mwifiex_sta_init_cmd(priv, false, false);3126		if (ret)3127			goto err_sta_init;3128	}3129 3130	mwifiex_setup_ht_caps(&wiphy->bands[NL80211_BAND_2GHZ]->ht_cap, priv);3131	if (adapter->is_hw_11ac_capable)3132		mwifiex_setup_vht_caps(3133			&wiphy->bands[NL80211_BAND_2GHZ]->vht_cap, priv);3134 3135	if (adapter->config_bands & BAND_A)3136		mwifiex_setup_ht_caps(3137			&wiphy->bands[NL80211_BAND_5GHZ]->ht_cap, priv);3138 3139	if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)3140		mwifiex_setup_vht_caps(3141			&wiphy->bands[NL80211_BAND_5GHZ]->vht_cap, priv);3142 3143	dev_net_set(dev, wiphy_net(wiphy));3144	dev->ieee80211_ptr = &priv->wdev;3145	dev->ieee80211_ptr->iftype = priv->bss_mode;3146	SET_NETDEV_DEV(dev, wiphy_dev(wiphy));3147 3148	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;3149	dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;3150	dev->needed_headroom = MWIFIEX_MIN_DATA_HEADER_LEN;3151	dev->ethtool_ops = &mwifiex_ethtool_ops;3152 3153	mdev_priv = netdev_priv(dev);3154	*((unsigned long *) mdev_priv) = (unsigned long) priv;3155 3156	SET_NETDEV_DEV(dev, adapter->dev);3157 3158	priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",3159						  WQ_HIGHPRI |3160						  WQ_MEM_RECLAIM |3161						  WQ_UNBOUND, 0, name);3162	if (!priv->dfs_cac_workqueue) {3163		mwifiex_dbg(adapter, ERROR, "cannot alloc DFS CAC queue\n");3164		ret = -ENOMEM;3165		goto err_alloc_cac;3166	}3167 3168	INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);3169 3170	priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",3171						      WQ_HIGHPRI | WQ_UNBOUND |3172						      WQ_MEM_RECLAIM, 0, name);3173	if (!priv->dfs_chan_sw_workqueue) {3174		mwifiex_dbg(adapter, ERROR, "cannot alloc DFS channel sw queue\n");3175		ret = -ENOMEM;3176		goto err_alloc_chsw;3177	}3178 3179	INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,3180			  mwifiex_dfs_chan_sw_work_queue);3181 3182	mutex_init(&priv->async_mutex);3183 3184	/* Register network device */3185	if (cfg80211_register_netdevice(dev)) {3186		mwifiex_dbg(adapter, ERROR, "cannot register network device\n");3187		ret = -EFAULT;3188		goto err_reg_netdev;3189	}3190 3191	mwifiex_dbg(adapter, INFO,3192		    "info: %s: Marvell 802.11 Adapter\n", dev->name);3193 3194#ifdef CONFIG_DEBUG_FS3195	mwifiex_dev_debugfs_init(priv);3196#endif3197 3198	update_vif_type_counter(adapter, type, +1);3199 3200	return &priv->wdev;3201 3202err_reg_netdev:3203	destroy_workqueue(priv->dfs_chan_sw_workqueue);3204	priv->dfs_chan_sw_workqueue = NULL;3205err_alloc_chsw:3206	destroy_workqueue(priv->dfs_cac_workqueue);3207	priv->dfs_cac_workqueue = NULL;3208err_alloc_cac:3209	free_netdev(dev);3210	priv->netdev = NULL;3211err_sta_init:3212err_set_bss_mode:3213err_alloc_netdev:3214	memset(&priv->wdev, 0, sizeof(priv->wdev));3215	priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;3216	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;3217	return ERR_PTR(ret);3218}3219EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);3220 3221/*3222 * del_virtual_intf: remove the virtual interface determined by dev3223 */3224int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)3225{3226	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);3227	struct mwifiex_adapter *adapter = priv->adapter;3228	struct sk_buff *skb, *tmp;3229 3230#ifdef CONFIG_DEBUG_FS3231	mwifiex_dev_debugfs_remove(priv);3232#endif3233 3234	if (priv->sched_scanning)3235		priv->sched_scanning = false;3236 3237	mwifiex_stop_net_dev_queue(priv->netdev, adapter);3238 3239	skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) {3240		skb_unlink(skb, &priv->bypass_txq);3241		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);3242	}3243 3244	if (netif_carrier_ok(priv->netdev))3245		netif_carrier_off(priv->netdev);3246 3247	if (wdev->netdev->reg_state == NETREG_REGISTERED)3248		cfg80211_unregister_netdevice(wdev->netdev);3249 3250	if (priv->dfs_cac_workqueue) {3251		destroy_workqueue(priv->dfs_cac_workqueue);3252		priv->dfs_cac_workqueue = NULL;3253	}3254 3255	if (priv->dfs_chan_sw_workqueue) {3256		destroy_workqueue(priv->dfs_chan_sw_workqueue);3257		priv->dfs_chan_sw_workqueue = NULL;3258	}3259	/* Clear the priv in adapter */3260	priv->netdev = NULL;3261 3262	update_vif_type_counter(adapter, priv->bss_mode, -1);3263 3264	priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;3265 3266	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||3267	    GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)3268		kfree(priv->hist_data);3269 3270	return 0;3271}3272EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);3273 3274static bool3275mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,3276			     u8 max_byte_seq)3277{3278	int j, k, valid_byte_cnt = 0;3279	bool dont_care_byte = false;3280 3281	for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {3282		for (k = 0; k < 8; k++) {3283			if (pat->mask[j] & 1 << k) {3284				memcpy(byte_seq + valid_byte_cnt,3285				       &pat->pattern[j * 8 + k], 1);3286				valid_byte_cnt++;3287				if (dont_care_byte)3288					return false;3289			} else {3290				if (valid_byte_cnt)3291					dont_care_byte = true;3292			}3293 3294			/* wildcard bytes record as the offset3295			 * before the valid byte3296			 */3297			if (!valid_byte_cnt && !dont_care_byte)3298				pat->pkt_offset++;3299 3300			if (valid_byte_cnt > max_byte_seq)3301				return false;3302		}3303	}3304 3305	byte_seq[max_byte_seq] = valid_byte_cnt;3306 3307	return true;3308}3309 3310#ifdef CONFIG_PM3311static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,3312					   struct mwifiex_mef_entry *mef_entry)3313{3314	int i, filt_num = 0, num_ipv4 = 0;3315	struct in_device *in_dev;3316	struct in_ifaddr *ifa;3317	__be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR];3318	struct mwifiex_adapter *adapter = priv->adapter;3319 3320	mef_entry->mode = MEF_MODE_HOST_SLEEP;3321	mef_entry->action = MEF_ACTION_AUTO_ARP;3322 3323	/* Enable ARP offload feature */3324	memset(ips, 0, sizeof(ips));3325	for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {3326		if (adapter->priv[i]->netdev) {3327			in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);3328			if (!in_dev)3329				continue;3330			ifa = rtnl_dereference(in_dev->ifa_list);3331			if (!ifa || !ifa->ifa_local)3332				continue;3333			ips[i] = ifa->ifa_local;3334			num_ipv4++;3335		}3336	}3337 3338	for (i = 0; i < num_ipv4; i++) {3339		if (!ips[i])3340			continue;3341		mef_entry->filter[filt_num].repeat = 1;3342		memcpy(mef_entry->filter[filt_num].byte_seq,3343		       (u8 *)&ips[i], sizeof(ips[i]));3344		mef_entry->filter[filt_num].3345			byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =3346			sizeof(ips[i]);3347		mef_entry->filter[filt_num].offset = 46;3348		mef_entry->filter[filt_num].filt_type = TYPE_EQ;3349		if (filt_num) {3350			mef_entry->filter[filt_num].filt_action =3351				TYPE_OR;3352		}3353		filt_num++;3354	}3355 3356	mef_entry->filter[filt_num].repeat = 1;3357	mef_entry->filter[filt_num].byte_seq[0] = 0x08;3358	mef_entry->filter[filt_num].byte_seq[1] = 0x06;3359	mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2;3360	mef_entry->filter[filt_num].offset = 20;3361	mef_entry->filter[filt_num].filt_type = TYPE_EQ;3362	mef_entry->filter[filt_num].filt_action = TYPE_AND;3363}3364 3365static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,3366					struct mwifiex_ds_mef_cfg *mef_cfg,3367					struct mwifiex_mef_entry *mef_entry,3368					struct cfg80211_wowlan *wowlan)3369{3370	int i, filt_num = 0, ret = 0;3371	bool first_pat = true;3372	u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];3373	static const u8 ipv4_mc_mac[] = {0x33, 0x33};3374	static const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};3375 3376	mef_entry->mode = MEF_MODE_HOST_SLEEP;3377	mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;3378 3379	for (i = 0; i < wowlan->n_patterns; i++) {3380		memset(byte_seq, 0, sizeof(byte_seq));3381		if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],3382					byte_seq,3383					MWIFIEX_MEF_MAX_BYTESEQ)) {3384			mwifiex_dbg(priv->adapter, ERROR,3385				    "Pattern not supported\n");3386			return -EOPNOTSUPP;3387		}3388 3389		if (!wowlan->patterns[i].pkt_offset) {3390			if (is_unicast_ether_addr(byte_seq) &&3391			    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {3392				mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;3393				continue;3394			} else if (is_broadcast_ether_addr(byte_seq)) {3395				mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST;3396				continue;3397			} else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&3398				    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||3399				   (!memcmp(byte_seq, ipv6_mc_mac, 3) &&3400				    (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {3401				mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST;3402				continue;3403			}3404		}3405		mef_entry->filter[filt_num].repeat = 1;3406		mef_entry->filter[filt_num].offset =3407			wowlan->patterns[i].pkt_offset;3408		memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,3409				sizeof(byte_seq));3410		mef_entry->filter[filt_num].filt_type = TYPE_EQ;3411 3412		if (first_pat) {3413			first_pat = false;3414			mwifiex_dbg(priv->adapter, INFO, "Wake on patterns\n");3415		} else {3416			mef_entry->filter[filt_num].filt_action = TYPE_AND;3417		}3418 3419		filt_num++;3420	}3421 3422	if (wowlan->magic_pkt) {3423		mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;3424		mef_entry->filter[filt_num].repeat = 16;3425		memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,3426				ETH_ALEN);3427		mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =3428			ETH_ALEN;3429		mef_entry->filter[filt_num].offset = 28;3430		mef_entry->filter[filt_num].filt_type = TYPE_EQ;3431		if (filt_num)3432			mef_entry->filter[filt_num].filt_action = TYPE_OR;3433 3434		filt_num++;3435		mef_entry->filter[filt_num].repeat = 16;3436		memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,3437				ETH_ALEN);3438		mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =3439			ETH_ALEN;3440		mef_entry->filter[filt_num].offset = 56;3441		mef_entry->filter[filt_num].filt_type = TYPE_EQ;3442		mef_entry->filter[filt_num].filt_action = TYPE_OR;3443		mwifiex_dbg(priv->adapter, INFO, "Wake on magic packet\n");3444	}3445	return ret;3446}3447 3448static int mwifiex_set_mef_filter(struct mwifiex_private *priv,3449				  struct cfg80211_wowlan *wowlan)3450{3451	int ret = 0, num_entries = 1;3452	struct mwifiex_ds_mef_cfg mef_cfg;3453	struct mwifiex_mef_entry *mef_entry;3454 3455	if (wowlan->n_patterns || wowlan->magic_pkt)3456		num_entries++;3457 3458	mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL);3459	if (!mef_entry)3460		return -ENOMEM;3461 3462	memset(&mef_cfg, 0, sizeof(mef_cfg));3463	mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST |3464		MWIFIEX_CRITERIA_UNICAST;3465	mef_cfg.num_entries = num_entries;3466	mef_cfg.mef_entry = mef_entry;3467 3468	mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);3469 3470	if (wowlan->n_patterns || wowlan->magic_pkt) {3471		ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,3472						   &mef_entry[1], wowlan);3473		if (ret)3474			goto err;3475	}3476 3477	if (!mef_cfg.criteria)3478		mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |3479			MWIFIEX_CRITERIA_UNICAST |3480			MWIFIEX_CRITERIA_MULTICAST;3481 3482	ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,3483			HostCmd_ACT_GEN_SET, 0,3484			&mef_cfg, true);3485 3486err:3487	kfree(mef_entry);3488	return ret;3489}3490 3491static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,3492				    struct cfg80211_wowlan *wowlan)3493{3494	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3495	struct mwifiex_ds_hs_cfg hs_cfg;3496	int i, ret = 0, retry_num = 10;3497	struct mwifiex_private *priv;3498	struct mwifiex_private *sta_priv =3499			mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);3500 3501	sta_priv->scan_aborting = true;3502	for (i = 0; i < adapter->priv_num; i++) {3503		priv = adapter->priv[i];3504		mwifiex_abort_cac(priv);3505	}3506 3507	mwifiex_cancel_all_pending_cmd(adapter);3508 3509	for (i = 0; i < adapter->priv_num; i++) {3510		priv = adapter->priv[i];3511		if (priv->netdev)3512			netif_device_detach(priv->netdev);3513	}3514 3515	for (i = 0; i < retry_num; i++) {3516		if (!mwifiex_wmm_lists_empty(adapter) ||3517		    !mwifiex_bypass_txlist_empty(adapter) ||3518		    !skb_queue_empty(&adapter->tx_data_q))3519			usleep_range(10000, 15000);3520		else3521			break;3522	}3523 3524	if (!wowlan) {3525		mwifiex_dbg(adapter, INFO,3526			    "None of the WOWLAN triggers enabled\n");3527		ret = 0;3528		goto done;3529	}3530 3531	if (!sta_priv->media_connected && !wowlan->nd_config) {3532		mwifiex_dbg(adapter, ERROR,3533			    "Can not configure WOWLAN in disconnected state\n");3534		ret = 0;3535		goto done;3536	}3537 3538	ret = mwifiex_set_mef_filter(sta_priv, wowlan);3539	if (ret) {3540		mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");3541		goto done;3542	}3543 3544	memset(&hs_cfg, 0, sizeof(hs_cfg));3545	hs_cfg.conditions = le32_to_cpu(adapter->hs_cfg.conditions);3546 3547	if (wowlan->nd_config) {3548		mwifiex_dbg(adapter, INFO, "Wake on net detect\n");3549		hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT;3550		mwifiex_cfg80211_sched_scan_start(wiphy, sta_priv->netdev,3551						  wowlan->nd_config);3552	}3553 3554	if (wowlan->disconnect) {3555		hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT;3556		mwifiex_dbg(sta_priv->adapter, INFO, "Wake on device disconnect\n");3557	}3558 3559	hs_cfg.is_invoke_hostcmd = false;3560	hs_cfg.gpio = adapter->hs_cfg.gpio;3561	hs_cfg.gap = adapter->hs_cfg.gap;3562	ret = mwifiex_set_hs_params(sta_priv, HostCmd_ACT_GEN_SET,3563				    MWIFIEX_SYNC_CMD, &hs_cfg);3564	if (ret)3565		mwifiex_dbg(adapter, ERROR, "Failed to set HS params\n");3566 3567done:3568	sta_priv->scan_aborting = false;3569	return ret;3570}3571 3572static int mwifiex_cfg80211_resume(struct wiphy *wiphy)3573{3574	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3575	struct mwifiex_private *priv;3576	struct mwifiex_ds_wakeup_reason wakeup_reason;3577	struct cfg80211_wowlan_wakeup wakeup_report;3578	int i;3579	bool report_wakeup_reason = true;3580 3581	for (i = 0; i < adapter->priv_num; i++) {3582		priv = adapter->priv[i];3583		if (priv->netdev)3584			netif_device_attach(priv->netdev);3585	}3586 3587	if (!wiphy->wowlan_config)3588		goto done;3589 3590	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);3591	mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD,3592				  &wakeup_reason);3593	memset(&wakeup_report, 0, sizeof(struct cfg80211_wowlan_wakeup));3594 3595	wakeup_report.pattern_idx = -1;3596 3597	switch (wakeup_reason.hs_wakeup_reason) {3598	case NO_HSWAKEUP_REASON:3599		break;3600	case BCAST_DATA_MATCHED:3601		break;3602	case MCAST_DATA_MATCHED:3603		break;3604	case UCAST_DATA_MATCHED:3605		break;3606	case MASKTABLE_EVENT_MATCHED:3607		break;3608	case NON_MASKABLE_EVENT_MATCHED:3609		if (wiphy->wowlan_config->disconnect)3610			wakeup_report.disconnect = true;3611		if (wiphy->wowlan_config->nd_config)3612			wakeup_report.net_detect = adapter->nd_info;3613		break;3614	case NON_MASKABLE_CONDITION_MATCHED:3615		break;3616	case MAGIC_PATTERN_MATCHED:3617		if (wiphy->wowlan_config->magic_pkt)3618			wakeup_report.magic_pkt = true;3619		if (wiphy->wowlan_config->n_patterns)3620			wakeup_report.pattern_idx = 1;3621		break;3622	case GTK_REKEY_FAILURE:3623		if (wiphy->wowlan_config->gtk_rekey_failure)3624			wakeup_report.gtk_rekey_failure = true;3625		break;3626	default:3627		report_wakeup_reason = false;3628		break;3629	}3630 3631	if (report_wakeup_reason)3632		cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report,3633					      GFP_KERNEL);3634 3635done:3636	if (adapter->nd_info) {3637		for (i = 0 ; i < adapter->nd_info->n_matches ; i++)3638			kfree(adapter->nd_info->matches[i]);3639		kfree(adapter->nd_info);3640		adapter->nd_info = NULL;3641	}3642 3643	return 0;3644}3645 3646static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,3647				       bool enabled)3648{3649	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3650 3651	device_set_wakeup_enable(adapter->dev, enabled);3652}3653 3654static int mwifiex_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,3655				  struct cfg80211_gtk_rekey_data *data)3656{3657	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3658 3659	if (!ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))3660		return -EOPNOTSUPP;3661 3662	if (priv->adapter->host_mlme_enabled)3663		return 0;3664 3665	return mwifiex_send_cmd(priv, HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG,3666				HostCmd_ACT_GEN_SET, 0, data, true);3667}3668 3669#endif3670 3671static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)3672{3673	static const u8 ipv4_mc_mac[] = {0x33, 0x33};3674	static const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};3675	static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};3676 3677	if ((byte_seq[0] & 0x01) &&3678	    (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))3679		return PACKET_TYPE_UNICAST;3680	else if (!memcmp(byte_seq, bc_mac, 4))3681		return PACKET_TYPE_BROADCAST;3682	else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&3683		  byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||3684		 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&3685		  byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))3686		return PACKET_TYPE_MULTICAST;3687 3688	return 0;3689}3690 3691static int3692mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,3693				struct cfg80211_coalesce_rules *crule,3694				struct mwifiex_coalesce_rule *mrule)3695{3696	u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];3697	struct filt_field_param *param;3698	int i;3699 3700	mrule->max_coalescing_delay = crule->delay;3701 3702	param = mrule->params;3703 3704	for (i = 0; i < crule->n_patterns; i++) {3705		memset(byte_seq, 0, sizeof(byte_seq));3706		if (!mwifiex_is_pattern_supported(&crule->patterns[i],3707						  byte_seq,3708						MWIFIEX_COALESCE_MAX_BYTESEQ)) {3709			mwifiex_dbg(priv->adapter, ERROR,3710				    "Pattern not supported\n");3711			return -EOPNOTSUPP;3712		}3713 3714		if (!crule->patterns[i].pkt_offset) {3715			u8 pkt_type;3716 3717			pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);3718			if (pkt_type && mrule->pkt_type) {3719				mwifiex_dbg(priv->adapter, ERROR,3720					    "Multiple packet types not allowed\n");3721				return -EOPNOTSUPP;3722			} else if (pkt_type) {3723				mrule->pkt_type = pkt_type;3724				continue;3725			}3726		}3727 3728		if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)3729			param->operation = RECV_FILTER_MATCH_TYPE_EQ;3730		else3731			param->operation = RECV_FILTER_MATCH_TYPE_NE;3732 3733		param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];3734		memcpy(param->operand_byte_stream, byte_seq,3735		       param->operand_len);3736		param->offset = crule->patterns[i].pkt_offset;3737		param++;3738 3739		mrule->num_of_fields++;3740	}3741 3742	if (!mrule->pkt_type) {3743		mwifiex_dbg(priv->adapter, ERROR,3744			    "Packet type can not be determined\n");3745		return -EOPNOTSUPP;3746	}3747 3748	return 0;3749}3750 3751static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,3752					 struct cfg80211_coalesce *coalesce)3753{3754	struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);3755	int i, ret;3756	struct mwifiex_ds_coalesce_cfg coalesce_cfg;3757	struct mwifiex_private *priv =3758			mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);3759 3760	memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));3761	if (!coalesce) {3762		mwifiex_dbg(adapter, WARN,3763			    "Disable coalesce and reset all previous rules\n");3764		return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,3765					HostCmd_ACT_GEN_SET, 0,3766					&coalesce_cfg, true);3767	}3768 3769	coalesce_cfg.num_of_rules = coalesce->n_rules;3770	for (i = 0; i < coalesce->n_rules; i++) {3771		ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],3772						      &coalesce_cfg.rule[i]);3773		if (ret) {3774			mwifiex_dbg(adapter, ERROR,3775				    "Recheck the patterns provided for rule %d\n",3776				i + 1);3777			return ret;3778		}3779	}3780 3781	return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,3782				HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);3783}3784 3785/* cfg80211 ops handler for tdls_mgmt.3786 * Function prepares TDLS action frame packets and forwards them to FW3787 */3788static int3789mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,3790			   const u8 *peer, int link_id, u8 action_code,3791			   u8 dialog_token, u16 status_code,3792			   u32 peer_capability, bool initiator,3793			   const u8 *extra_ies, size_t extra_ies_len)3794{3795	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3796	int ret;3797 3798	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))3799		return -EOPNOTSUPP;3800 3801	/* make sure we are in station mode and connected */3802	if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))3803		return -EOPNOTSUPP;3804 3805	switch (action_code) {3806	case WLAN_TDLS_SETUP_REQUEST:3807		mwifiex_dbg(priv->adapter, MSG,3808			    "Send TDLS Setup Request to %pM status_code=%d\n",3809			    peer, status_code);3810		mwifiex_add_auto_tdls_peer(priv, peer);3811		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3812						   dialog_token, status_code,3813						   extra_ies, extra_ies_len);3814		break;3815	case WLAN_TDLS_SETUP_RESPONSE:3816		mwifiex_add_auto_tdls_peer(priv, peer);3817		mwifiex_dbg(priv->adapter, MSG,3818			    "Send TDLS Setup Response to %pM status_code=%d\n",3819			    peer, status_code);3820		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3821						   dialog_token, status_code,3822						   extra_ies, extra_ies_len);3823		break;3824	case WLAN_TDLS_SETUP_CONFIRM:3825		mwifiex_dbg(priv->adapter, MSG,3826			    "Send TDLS Confirm to %pM status_code=%d\n", peer,3827			    status_code);3828		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3829						   dialog_token, status_code,3830						   extra_ies, extra_ies_len);3831		break;3832	case WLAN_TDLS_TEARDOWN:3833		mwifiex_dbg(priv->adapter, MSG,3834			    "Send TDLS Tear down to %pM\n", peer);3835		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3836						   dialog_token, status_code,3837						   extra_ies, extra_ies_len);3838		break;3839	case WLAN_TDLS_DISCOVERY_REQUEST:3840		mwifiex_dbg(priv->adapter, MSG,3841			    "Send TDLS Discovery Request to %pM\n", peer);3842		ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,3843						   dialog_token, status_code,3844						   extra_ies, extra_ies_len);3845		break;3846	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:3847		mwifiex_dbg(priv->adapter, MSG,3848			    "Send TDLS Discovery Response to %pM\n", peer);3849		ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,3850						   dialog_token, status_code,3851						   extra_ies, extra_ies_len);3852		break;3853	default:3854		mwifiex_dbg(priv->adapter, ERROR,3855			    "Unknown TDLS mgmt/action frame %pM\n", peer);3856		ret = -EINVAL;3857		break;3858	}3859 3860	return ret;3861}3862 3863static int3864mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,3865			   const u8 *peer, enum nl80211_tdls_operation action)3866{3867	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3868 3869	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||3870	    !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))3871		return -EOPNOTSUPP;3872 3873	/* make sure we are in station mode and connected */3874	if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))3875		return -EOPNOTSUPP;3876 3877	mwifiex_dbg(priv->adapter, MSG,3878		    "TDLS peer=%pM, oper=%d\n", peer, action);3879 3880	switch (action) {3881	case NL80211_TDLS_ENABLE_LINK:3882		action = MWIFIEX_TDLS_ENABLE_LINK;3883		break;3884	case NL80211_TDLS_DISABLE_LINK:3885		action = MWIFIEX_TDLS_DISABLE_LINK;3886		break;3887	case NL80211_TDLS_TEARDOWN:3888		/* shouldn't happen!*/3889		mwifiex_dbg(priv->adapter, ERROR,3890			    "tdls_oper: teardown from driver not supported\n");3891		return -EINVAL;3892	case NL80211_TDLS_SETUP:3893		/* shouldn't happen!*/3894		mwifiex_dbg(priv->adapter, ERROR,3895			    "tdls_oper: setup from driver not supported\n");3896		return -EINVAL;3897	case NL80211_TDLS_DISCOVERY_REQ:3898		/* shouldn't happen!*/3899		mwifiex_dbg(priv->adapter, ERROR,3900			    "tdls_oper: discovery from driver not supported\n");3901		return -EINVAL;3902	default:3903		mwifiex_dbg(priv->adapter, ERROR,3904			    "tdls_oper: operation not supported\n");3905		return -EOPNOTSUPP;3906	}3907 3908	return mwifiex_tdls_oper(priv, peer, action);3909}3910 3911static int3912mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,3913				  const u8 *addr, u8 oper_class,3914				  struct cfg80211_chan_def *chandef)3915{3916	struct mwifiex_sta_node *sta_ptr;3917	u16 chan;3918	u8 second_chan_offset, band;3919	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3920 3921	spin_lock_bh(&priv->sta_list_spinlock);3922	sta_ptr = mwifiex_get_sta_entry(priv, addr);3923	if (!sta_ptr) {3924		spin_unlock_bh(&priv->sta_list_spinlock);3925		wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",3926			  __func__, addr);3927		return -ENOENT;3928	}3929 3930	if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &3931	      WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {3932		spin_unlock_bh(&priv->sta_list_spinlock);3933		wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);3934		return -ENOENT;3935	}3936 3937	if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||3938	    sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {3939		spin_unlock_bh(&priv->sta_list_spinlock);3940		wiphy_err(wiphy, "channel switch is running, abort request\n");3941		return -EALREADY;3942	}3943	spin_unlock_bh(&priv->sta_list_spinlock);3944 3945	chan = chandef->chan->hw_value;3946	second_chan_offset = mwifiex_get_sec_chan_offset(chan);3947	band = chandef->chan->band;3948	mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);3949 3950	return 0;3951}3952 3953static void3954mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,3955					 struct net_device *dev,3956					 const u8 *addr)3957{3958	struct mwifiex_sta_node *sta_ptr;3959	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);3960 3961	spin_lock_bh(&priv->sta_list_spinlock);3962	sta_ptr = mwifiex_get_sta_entry(priv, addr);3963	if (!sta_ptr) {3964		spin_unlock_bh(&priv->sta_list_spinlock);3965		wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",3966			  __func__, addr);3967	} else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||3968		     sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||3969		     sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {3970		spin_unlock_bh(&priv->sta_list_spinlock);3971		wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",3972			  addr);3973	} else {3974		spin_unlock_bh(&priv->sta_list_spinlock);3975		mwifiex_stop_tdls_cs(priv, addr);3976	}3977}3978 3979static int3980mwifiex_cfg80211_uap_add_station(struct mwifiex_private *priv, const u8 *mac,3981				 struct station_parameters *params)3982{3983	struct mwifiex_sta_info add_sta;3984	int ret;3985 3986	memcpy(add_sta.peer_mac, mac, ETH_ALEN);3987	add_sta.params = params;3988 3989	ret = mwifiex_send_cmd(priv, HostCmd_CMD_ADD_NEW_STATION,3990			       HostCmd_ACT_ADD_STA, 0, (void *)&add_sta, true);3991 3992	if (!ret) {3993		struct station_info *sinfo;3994 3995		sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);3996		if (!sinfo)3997			return -ENOMEM;3998 3999		cfg80211_new_sta(priv->netdev, mac, sinfo, GFP_KERNEL);4000		kfree(sinfo);4001	}4002 4003	return ret;4004}4005 4006static int4007mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,4008			     const u8 *mac, struct station_parameters *params)4009{4010	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4011 4012	if (priv->adapter->host_mlme_enabled &&4013	    (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP))4014		return mwifiex_cfg80211_uap_add_station(priv, mac, params);4015 4016	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))4017		return -EOPNOTSUPP;4018 4019	/* make sure we are in station mode and connected */4020	if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)4021		return -EOPNOTSUPP;4022 4023	return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);4024}4025 4026static int4027mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,4028				struct cfg80211_csa_settings *params)4029{4030	struct ieee_types_header *chsw_ie;4031	struct ieee80211_channel_sw_ie *channel_sw;4032	int chsw_msec;4033	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4034 4035	if (priv->adapter->scan_processing) {4036		mwifiex_dbg(priv->adapter, ERROR,4037			    "radar detection: scan in process...\n");4038		return -EBUSY;4039	}4040 4041	if (priv->wdev.links[0].cac_started)4042		return -EBUSY;4043 4044	if (cfg80211_chandef_identical(&params->chandef,4045				       &priv->dfs_chandef))4046		return -EINVAL;4047 4048	chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,4049					   params->beacon_csa.tail,4050					   params->beacon_csa.tail_len);4051	if (!chsw_ie) {4052		mwifiex_dbg(priv->adapter, ERROR,4053			    "Could not parse channel switch announcement IE\n");4054		return -EINVAL;4055	}4056 4057	channel_sw = (void *)(chsw_ie + 1);4058	if (channel_sw->mode) {4059		if (netif_carrier_ok(priv->netdev))4060			netif_carrier_off(priv->netdev);4061		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);4062	}4063 4064	if (mwifiex_del_mgmt_ies(priv))4065		mwifiex_dbg(priv->adapter, ERROR,4066			    "Failed to delete mgmt IEs!\n");4067 4068	if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {4069		mwifiex_dbg(priv->adapter, ERROR,4070			    "%s: setting mgmt ies failed\n", __func__);4071		return -EFAULT;4072	}4073 4074	memcpy(&priv->dfs_chandef, &params->chandef, sizeof(priv->dfs_chandef));4075	memcpy(&priv->beacon_after, &params->beacon_after,4076	       sizeof(priv->beacon_after));4077 4078	chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);4079	queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,4080			   msecs_to_jiffies(chsw_msec));4081	return 0;4082}4083 4084static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,4085					struct wireless_dev *wdev,4086					unsigned int link_id,4087					struct cfg80211_chan_def *chandef)4088{4089	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);4090	struct mwifiex_bssdescriptor *curr_bss;4091	struct ieee80211_channel *chan;4092	enum nl80211_channel_type chan_type;4093	enum nl80211_band band;4094	int freq;4095	int ret = -ENODATA;4096 4097	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&4098	    cfg80211_chandef_valid(&priv->bss_chandef)) {4099		*chandef = priv->bss_chandef;4100		ret = 0;4101	} else if (priv->media_connected) {4102		curr_bss = &priv->curr_bss_params.bss_descriptor;4103		band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);4104		freq = ieee80211_channel_to_frequency(curr_bss->channel, band);4105		chan = ieee80211_get_channel(wiphy, freq);4106 4107		if (priv->ht_param_present) {4108			chan_type = mwifiex_get_chan_type(priv);4109			cfg80211_chandef_create(chandef, chan, chan_type);4110		} else {4111			cfg80211_chandef_create(chandef, chan,4112						NL80211_CHAN_NO_HT);4113		}4114		ret = 0;4115	}4116 4117	return ret;4118}4119 4120#ifdef CONFIG_NL80211_TESTMODE4121 4122enum mwifiex_tm_attr {4123	__MWIFIEX_TM_ATTR_INVALID	= 0,4124	MWIFIEX_TM_ATTR_CMD		= 1,4125	MWIFIEX_TM_ATTR_DATA		= 2,4126 4127	/* keep last */4128	__MWIFIEX_TM_ATTR_AFTER_LAST,4129	MWIFIEX_TM_ATTR_MAX		= __MWIFIEX_TM_ATTR_AFTER_LAST - 1,4130};4131 4132static const struct nla_policy mwifiex_tm_policy[MWIFIEX_TM_ATTR_MAX + 1] = {4133	[MWIFIEX_TM_ATTR_CMD]		= { .type = NLA_U32 },4134	[MWIFIEX_TM_ATTR_DATA]		= { .type = NLA_BINARY,4135					    .len = MWIFIEX_SIZE_OF_CMD_BUFFER },4136};4137 4138enum mwifiex_tm_command {4139	MWIFIEX_TM_CMD_HOSTCMD	= 0,4140};4141 4142static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev,4143			  void *data, int len)4144{4145	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);4146	struct mwifiex_ds_misc_cmd *hostcmd;4147	struct nlattr *tb[MWIFIEX_TM_ATTR_MAX + 1];4148	struct sk_buff *skb;4149	int err;4150 4151	if (!priv)4152		return -EINVAL;4153 4154	err = nla_parse_deprecated(tb, MWIFIEX_TM_ATTR_MAX, data, len,4155				   mwifiex_tm_policy, NULL);4156	if (err)4157		return err;4158 4159	if (!tb[MWIFIEX_TM_ATTR_CMD])4160		return -EINVAL;4161 4162	switch (nla_get_u32(tb[MWIFIEX_TM_ATTR_CMD])) {4163	case MWIFIEX_TM_CMD_HOSTCMD:4164		if (!tb[MWIFIEX_TM_ATTR_DATA])4165			return -EINVAL;4166 4167		hostcmd = kzalloc(sizeof(*hostcmd), GFP_KERNEL);4168		if (!hostcmd)4169			return -ENOMEM;4170 4171		hostcmd->len = nla_len(tb[MWIFIEX_TM_ATTR_DATA]);4172		memcpy(hostcmd->cmd, nla_data(tb[MWIFIEX_TM_ATTR_DATA]),4173		       hostcmd->len);4174 4175		if (mwifiex_send_cmd(priv, 0, 0, 0, hostcmd, true)) {4176			dev_err(priv->adapter->dev, "Failed to process hostcmd\n");4177			kfree(hostcmd);4178			return -EFAULT;4179		}4180 4181		/* process hostcmd response*/4182		skb = cfg80211_testmode_alloc_reply_skb(wiphy, hostcmd->len);4183		if (!skb) {4184			kfree(hostcmd);4185			return -ENOMEM;4186		}4187		err = nla_put(skb, MWIFIEX_TM_ATTR_DATA,4188			      hostcmd->len, hostcmd->cmd);4189		if (err) {4190			kfree(hostcmd);4191			kfree_skb(skb);4192			return -EMSGSIZE;4193		}4194 4195		err = cfg80211_testmode_reply(skb);4196		kfree(hostcmd);4197		return err;4198	default:4199		return -EOPNOTSUPP;4200	}4201}4202#endif4203 4204static int4205mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,4206				       struct net_device *dev,4207				       struct cfg80211_chan_def *chandef,4208				       u32 cac_time_ms, int link_id)4209{4210	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4211	struct mwifiex_radar_params radar_params;4212 4213	if (priv->adapter->scan_processing) {4214		mwifiex_dbg(priv->adapter, ERROR,4215			    "radar detection: scan already in process...\n");4216		return -EBUSY;4217	}4218 4219	if (!mwifiex_is_11h_active(priv)) {4220		mwifiex_dbg(priv->adapter, INFO,4221			    "Enable 11h extensions in FW\n");4222		if (mwifiex_11h_activate(priv, true)) {4223			mwifiex_dbg(priv->adapter, ERROR,4224				    "Failed to activate 11h extensions!!");4225			return -1;4226		}4227		priv->state_11h.is_11h_active = true;4228	}4229 4230	memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));4231	radar_params.chandef = chandef;4232	radar_params.cac_time_ms = cac_time_ms;4233 4234	memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));4235 4236	if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,4237			     HostCmd_ACT_GEN_SET, 0, &radar_params, true))4238		return -1;4239 4240	queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,4241			   msecs_to_jiffies(cac_time_ms));4242	return 0;4243}4244 4245static int4246mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,4247				const u8 *mac,4248				struct station_parameters *params)4249{4250	int ret;4251	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4252 4253	if (priv->adapter->host_mlme_enabled &&4254	    (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP))4255		return 0;4256 4257	/* we support change_station handler only for TDLS peers*/4258	if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))4259		return -EOPNOTSUPP;4260 4261	/* make sure we are in station mode and connected */4262	if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)4263		return -EOPNOTSUPP;4264 4265	priv->sta_params = params;4266 4267	ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);4268	priv->sta_params = NULL;4269 4270	return ret;4271}4272 4273static int4274mwifiex_cfg80211_authenticate(struct wiphy *wiphy,4275			      struct net_device *dev,4276			      struct cfg80211_auth_request *req)4277{4278	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4279	struct mwifiex_adapter *adapter = priv->adapter;4280	struct sk_buff *skb;4281	u16 pkt_len, auth_alg;4282	int ret;4283	struct mwifiex_ieee80211_mgmt *mgmt;4284	struct mwifiex_txinfo *tx_info;4285	u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;4286	u8 trans = 1, status_code = 0;4287	u8 *varptr = NULL;4288 4289	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {4290		mwifiex_dbg(priv->adapter, ERROR, "Interface role is AP\n");4291		return -EFAULT;4292	}4293 4294	if (priv->wdev.iftype != NL80211_IFTYPE_STATION) {4295		mwifiex_dbg(priv->adapter, ERROR,4296			    "Interface type is not correct (type %d)\n",4297			    priv->wdev.iftype);4298		return -EINVAL;4299	}4300 4301	if (priv->auth_alg != WLAN_AUTH_SAE &&4302	    (priv->auth_flag & HOST_MLME_AUTH_PENDING)) {4303		mwifiex_dbg(priv->adapter, ERROR, "Pending auth on going\n");4304		return -EBUSY;4305	}4306 4307	if (!priv->host_mlme_reg) {4308		priv->host_mlme_reg = true;4309		priv->mgmt_frame_mask |= HOST_MLME_MGMT_MASK;4310		mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,4311				 HostCmd_ACT_GEN_SET, 0,4312				 &priv->mgmt_frame_mask, false);4313	}4314 4315	switch (req->auth_type) {4316	case NL80211_AUTHTYPE_OPEN_SYSTEM:4317		auth_alg = WLAN_AUTH_OPEN;4318		break;4319	case NL80211_AUTHTYPE_SHARED_KEY:4320		auth_alg = WLAN_AUTH_SHARED_KEY;4321		break;4322	case NL80211_AUTHTYPE_FT:4323		auth_alg = WLAN_AUTH_FT;4324		break;4325	case NL80211_AUTHTYPE_NETWORK_EAP:4326		auth_alg = WLAN_AUTH_LEAP;4327		break;4328	case NL80211_AUTHTYPE_SAE:4329		auth_alg = WLAN_AUTH_SAE;4330		break;4331	default:4332		mwifiex_dbg(priv->adapter, ERROR,4333			    "unsupported auth type=%d\n", req->auth_type);4334		return -EOPNOTSUPP;4335	}4336 4337	if (!priv->auth_flag) {4338		ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET,4339						 req->bss->channel,4340						 AUTH_TX_DEFAULT_WAIT_TIME);4341 4342		if (!ret) {4343			priv->roc_cfg.cookie = get_random_u32() | 1;4344			priv->roc_cfg.chan = *req->bss->channel;4345		} else {4346			return -EFAULT;4347		}4348	}4349 4350	priv->sec_info.authentication_mode = auth_alg;4351 4352	mwifiex_cancel_scan(adapter);4353 4354	pkt_len = (u16)req->ie_len + req->auth_data_len +4355		MWIFIEX_MGMT_HEADER_LEN + MWIFIEX_AUTH_BODY_LEN;4356	if (req->auth_data_len >= 4)4357		pkt_len -= 4;4358 4359	skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +4360			    MWIFIEX_MGMT_FRAME_HEADER_SIZE +4361			    pkt_len + sizeof(pkt_len));4362	if (!skb) {4363		mwifiex_dbg(priv->adapter, ERROR,4364			    "allocate skb failed for management frame\n");4365		return -ENOMEM;4366	}4367 4368	tx_info = MWIFIEX_SKB_TXCB(skb);4369	memset(tx_info, 0, sizeof(*tx_info));4370	tx_info->bss_num = priv->bss_num;4371	tx_info->bss_type = priv->bss_type;4372	tx_info->pkt_len = pkt_len;4373 4374	skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +4375		    MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));4376	memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));4377	memcpy(skb_push(skb, sizeof(tx_control)),4378	       &tx_control, sizeof(tx_control));4379	memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));4380 4381	mgmt = (struct mwifiex_ieee80211_mgmt *)skb_put(skb, pkt_len);4382	memset(mgmt, 0, pkt_len);4383	mgmt->frame_control =4384		cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);4385	memcpy(mgmt->da, req->bss->bssid, ETH_ALEN);4386	memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN);4387	memcpy(mgmt->bssid, req->bss->bssid, ETH_ALEN);4388	eth_broadcast_addr(mgmt->addr4);4389 4390	if (req->auth_data_len >= 4) {4391		if (req->auth_type == NL80211_AUTHTYPE_SAE) {4392			__le16 *pos = (__le16 *)req->auth_data;4393 4394			trans = le16_to_cpu(pos[0]);4395			status_code = le16_to_cpu(pos[1]);4396		}4397		memcpy((u8 *)(&mgmt->auth.variable), req->auth_data + 4,4398		       req->auth_data_len - 4);4399		varptr = (u8 *)&mgmt->auth.variable +4400			 (req->auth_data_len - 4);4401	}4402 4403	mgmt->auth.auth_alg = cpu_to_le16(auth_alg);4404	mgmt->auth.auth_transaction = cpu_to_le16(trans);4405	mgmt->auth.status_code = cpu_to_le16(status_code);4406 4407	if (req->ie && req->ie_len) {4408		if (!varptr)4409			varptr = (u8 *)&mgmt->auth.variable;4410		memcpy((u8 *)varptr, req->ie, req->ie_len);4411	}4412 4413	priv->auth_flag = HOST_MLME_AUTH_PENDING;4414	priv->auth_alg = auth_alg;4415 4416	skb->priority = WMM_HIGHEST_PRIORITY;4417	__net_timestamp(skb);4418 4419	mwifiex_dbg(priv->adapter, MSG,4420		    "auth: send authentication to %pM\n", req->bss->bssid);4421 4422	mwifiex_queue_tx_pkt(priv, skb);4423 4424	return 0;4425}4426 4427static int4428mwifiex_cfg80211_associate(struct wiphy *wiphy, struct net_device *dev,4429			   struct cfg80211_assoc_request *req)4430{4431	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);4432	struct mwifiex_adapter *adapter = priv->adapter;4433	int ret;4434	struct cfg80211_ssid req_ssid;4435	const u8 *ssid_ie;4436 4437	if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {4438		mwifiex_dbg(adapter, ERROR,4439			    "%s: reject infra assoc request in non-STA role\n",4440			    dev->name);4441		return -EINVAL;4442	}4443 4444	if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||4445	    test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {4446		mwifiex_dbg(adapter, ERROR,4447			    "%s: Ignore association.\t"4448			    "Card removed or FW in bad state\n",4449			    dev->name);4450		return -EFAULT;4451	}4452 4453	if (priv->auth_alg == WLAN_AUTH_SAE)4454		priv->auth_flag = HOST_MLME_AUTH_DONE;4455 4456	if (priv->auth_flag && !(priv->auth_flag & HOST_MLME_AUTH_DONE))4457		return -EBUSY;4458 4459	if (priv->roc_cfg.cookie) {4460		ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,4461						 &priv->roc_cfg.chan, 0);4462		if (!ret)4463			memset(&priv->roc_cfg, 0,4464			       sizeof(struct mwifiex_roc_cfg));4465		else4466			return -EFAULT;4467	}4468 4469	if (!mwifiex_stop_bg_scan(priv))4470		cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0);4471 4472	memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));4473	rcu_read_lock();4474	ssid_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);4475 4476	if (!ssid_ie)4477		goto ssid_err;4478 4479	req_ssid.ssid_len = ssid_ie[1];4480	if (req_ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {4481		mwifiex_dbg(adapter, ERROR, "invalid SSID - aborting\n");4482		goto ssid_err;4483	}4484 4485	memcpy(req_ssid.ssid, ssid_ie + 2, req_ssid.ssid_len);4486	if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {4487		mwifiex_dbg(adapter, ERROR, "invalid SSID - aborting\n");4488		goto ssid_err;4489	}4490	rcu_read_unlock();4491 4492	/* As this is new association, clear locally stored4493	 * keys and security related flags4494	 */4495	priv->sec_info.wpa_enabled = false;4496	priv->sec_info.wpa2_enabled = false;4497	priv->wep_key_curr_index = 0;4498	priv->sec_info.encryption_mode = 0;4499	priv->sec_info.is_authtype_auto = 0;4500	if (mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1)) {4501		mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");4502		return -EFAULT;4503	}4504 4505	if (req->crypto.n_ciphers_pairwise)4506		priv->sec_info.encryption_mode =4507			req->crypto.ciphers_pairwise[0];4508 4509	if (req->crypto.cipher_group)4510		priv->sec_info.encryption_mode = req->crypto.cipher_group;4511 4512	if (req->ie)4513		mwifiex_set_gen_ie(priv, req->ie, req->ie_len);4514 4515	memcpy(priv->cfg_bssid, req->bss->bssid, ETH_ALEN);4516 4517	mwifiex_dbg(adapter, MSG,4518		    "assoc: send association to %pM\n", req->bss->bssid);4519 4520	cfg80211_ref_bss(adapter->wiphy, req->bss);4521	ret = mwifiex_bss_start(priv, req->bss, &req_ssid);4522	if (ret) {4523		priv->auth_flag = 0;4524		priv->auth_alg = WLAN_AUTH_NONE;4525		eth_zero_addr(priv->cfg_bssid);4526	}4527 4528	if (priv->assoc_rsp_size) {4529		priv->req_bss = req->bss;4530		adapter->assoc_resp_received = true;4531		queue_work(adapter->host_mlme_workqueue,4532			   &adapter->host_mlme_work);4533	}4534 4535	cfg80211_put_bss(priv->adapter->wiphy, req->bss);4536 4537	return 0;4538 4539ssid_err:4540	rcu_read_unlock();4541	return -EFAULT;4542}4543 4544static int4545mwifiex_cfg80211_deauthenticate(struct wiphy *wiphy,4546				struct net_device *dev,4547				struct cfg80211_deauth_request *req)4548{4549	return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);4550}4551 4552static int4553mwifiex_cfg80211_disassociate(struct wiphy *wiphy,4554			      struct net_device *dev,4555			      struct cfg80211_disassoc_request *req)4556{4557	return mwifiex_cfg80211_disconnect(wiphy, dev, req->reason_code);4558}4559 4560static int4561mwifiex_cfg80211_probe_client(struct wiphy *wiphy,4562			      struct net_device *dev, const u8 *peer,4563			      u64 *cookie)4564{4565	/* hostapd looks for NL80211_CMD_PROBE_CLIENT support; otherwise,4566	 * it requires monitor-mode support (which mwifiex doesn't support).4567	 * Provide fake probe_client support to work around this.4568	 */4569	return -EOPNOTSUPP;4570}4571 4572/* station cfg80211 operations */4573static const struct cfg80211_ops mwifiex_cfg80211_ops = {4574	.add_virtual_intf = mwifiex_add_virtual_intf,4575	.del_virtual_intf = mwifiex_del_virtual_intf,4576	.change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,4577	.scan = mwifiex_cfg80211_scan,4578	.connect = mwifiex_cfg80211_connect,4579	.disconnect = mwifiex_cfg80211_disconnect,4580	.get_station = mwifiex_cfg80211_get_station,4581	.dump_station = mwifiex_cfg80211_dump_station,4582	.dump_survey = mwifiex_cfg80211_dump_survey,4583	.set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,4584	.join_ibss = mwifiex_cfg80211_join_ibss,4585	.leave_ibss = mwifiex_cfg80211_leave_ibss,4586	.add_key = mwifiex_cfg80211_add_key,4587	.del_key = mwifiex_cfg80211_del_key,4588	.set_default_mgmt_key = mwifiex_cfg80211_set_default_mgmt_key,4589	.mgmt_tx = mwifiex_cfg80211_mgmt_tx,4590	.update_mgmt_frame_registrations =4591		mwifiex_cfg80211_update_mgmt_frame_registrations,4592	.remain_on_channel = mwifiex_cfg80211_remain_on_channel,4593	.cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,4594	.set_default_key = mwifiex_cfg80211_set_default_key,4595	.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,4596	.set_tx_power = mwifiex_cfg80211_set_tx_power,4597	.get_tx_power = mwifiex_cfg80211_get_tx_power,4598	.set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,4599	.start_ap = mwifiex_cfg80211_start_ap,4600	.stop_ap = mwifiex_cfg80211_stop_ap,4601	.change_beacon = mwifiex_cfg80211_change_beacon,4602	.set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,4603	.set_antenna = mwifiex_cfg80211_set_antenna,4604	.get_antenna = mwifiex_cfg80211_get_antenna,4605	.del_station = mwifiex_cfg80211_del_station,4606	.sched_scan_start = mwifiex_cfg80211_sched_scan_start,4607	.sched_scan_stop = mwifiex_cfg80211_sched_scan_stop,4608#ifdef CONFIG_PM4609	.suspend = mwifiex_cfg80211_suspend,4610	.resume = mwifiex_cfg80211_resume,4611	.set_wakeup = mwifiex_cfg80211_set_wakeup,4612	.set_rekey_data = mwifiex_set_rekey_data,4613#endif4614	.set_coalesce = mwifiex_cfg80211_set_coalesce,4615	.tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,4616	.tdls_oper = mwifiex_cfg80211_tdls_oper,4617	.tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,4618	.tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,4619	.add_station = mwifiex_cfg80211_add_station,4620	.change_station = mwifiex_cfg80211_change_station,4621	CFG80211_TESTMODE_CMD(mwifiex_tm_cmd)4622	.get_channel = mwifiex_cfg80211_get_channel,4623	.start_radar_detection = mwifiex_cfg80211_start_radar_detection,4624	.channel_switch = mwifiex_cfg80211_channel_switch,4625};4626 4627#ifdef CONFIG_PM4628static const struct wiphy_wowlan_support mwifiex_wowlan_support = {4629	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT |4630		WIPHY_WOWLAN_NET_DETECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |4631		WIPHY_WOWLAN_GTK_REKEY_FAILURE,4632	.n_patterns = MWIFIEX_MEF_MAX_FILTERS,4633	.pattern_min_len = 1,4634	.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,4635	.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,4636	.max_nd_match_sets = MWIFIEX_MAX_ND_MATCH_SETS,4637};4638 4639static const struct wiphy_wowlan_support mwifiex_wowlan_support_no_gtk = {4640	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT |4641		 WIPHY_WOWLAN_NET_DETECT,4642	.n_patterns = MWIFIEX_MEF_MAX_FILTERS,4643	.pattern_min_len = 1,4644	.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,4645	.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,4646	.max_nd_match_sets = MWIFIEX_MAX_ND_MATCH_SETS,4647};4648#endif4649 4650static bool mwifiex_is_valid_alpha2(const char *alpha2)4651{4652	if (!alpha2 || strlen(alpha2) != 2)4653		return false;4654 4655	if (isalpha(alpha2[0]) && isalpha(alpha2[1]))4656		return true;4657 4658	return false;4659}4660 4661static const struct wiphy_coalesce_support mwifiex_coalesce_support = {4662	.n_rules = MWIFIEX_COALESCE_MAX_RULES,4663	.max_delay = MWIFIEX_MAX_COALESCING_DELAY,4664	.n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,4665	.pattern_min_len = 1,4666	.pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,4667	.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,4668};4669 4670int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)4671{4672	u32 n_channels_bg, n_channels_a = 0;4673 4674	n_channels_bg = mwifiex_band_2ghz.n_channels;4675 4676	if (adapter->config_bands & BAND_A)4677		n_channels_a = mwifiex_band_5ghz.n_channels;4678 4679	/* allocate twice the number total channels, since the driver issues an4680	 * additional active scan request for hidden SSIDs on passive channels.4681	 */4682	adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a);4683	adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats),4684						 adapter->num_in_chan_stats));4685 4686	if (!adapter->chan_stats)4687		return -ENOMEM;4688 4689	return 0;4690}4691 4692/*4693 * This function registers the device with CFG802.11 subsystem.4694 *4695 * The function creates the wireless device/wiphy, populates it with4696 * default parameters and handler function pointers, and finally4697 * registers the device.4698 */4699 4700int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)4701{4702	int ret;4703	void *wdev_priv;4704	struct wiphy *wiphy;4705	struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];4706	u8 *country_code;4707	u32 thr, retry;4708	struct cfg80211_ops *ops;4709 4710	ops = devm_kmemdup(adapter->dev, &mwifiex_cfg80211_ops,4711			   sizeof(mwifiex_cfg80211_ops), GFP_KERNEL);4712	if (!ops)4713		return -ENOMEM;4714 4715	/* create a new wiphy for use with cfg80211 */4716	wiphy = wiphy_new(ops, sizeof(struct mwifiex_adapter *));4717	if (!wiphy) {4718		mwifiex_dbg(adapter, ERROR,4719			    "%s: creating new wiphy\n", __func__);4720		return -ENOMEM;4721	}4722	if (adapter->host_mlme_enabled) {4723		ops->auth = mwifiex_cfg80211_authenticate;4724		ops->assoc = mwifiex_cfg80211_associate;4725		ops->deauth = mwifiex_cfg80211_deauthenticate;4726		ops->disassoc = mwifiex_cfg80211_disassociate;4727		ops->disconnect = NULL;4728		ops->connect = NULL;4729		ops->probe_client = mwifiex_cfg80211_probe_client;4730	}4731	wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;4732	wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;4733	if (adapter->host_mlme_enabled) {4734		memcpy(adapter->mwifiex_mgmt_stypes,4735		       mwifiex_mgmt_stypes,4736		       NUM_NL80211_IFTYPES *4737		       sizeof(struct ieee80211_txrx_stypes));4738 4739		adapter->mwifiex_mgmt_stypes[NL80211_IFTYPE_AP].tx = 0xffff;4740		adapter->mwifiex_mgmt_stypes[NL80211_IFTYPE_AP].rx =4741			BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |4742			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |4743			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |4744			BIT(IEEE80211_STYPE_DISASSOC >> 4) |4745			BIT(IEEE80211_STYPE_AUTH >> 4) |4746			BIT(IEEE80211_STYPE_DEAUTH >> 4) |4747			BIT(IEEE80211_STYPE_ACTION >> 4);4748		wiphy->mgmt_stypes = adapter->mwifiex_mgmt_stypes;4749	} else {4750		wiphy->mgmt_stypes = mwifiex_mgmt_stypes;4751	}4752	wiphy->max_remain_on_channel_duration = 5000;4753	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |4754				 BIT(NL80211_IFTYPE_P2P_CLIENT) |4755				 BIT(NL80211_IFTYPE_P2P_GO) |4756				 BIT(NL80211_IFTYPE_AP);4757 4758	wiphy->max_num_akm_suites = CFG80211_MAX_NUM_AKM_SUITES;4759 4760	if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))4761		wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);4762 4763	wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(adapter->dev,4764						       &mwifiex_band_2ghz,4765						       sizeof(mwifiex_band_2ghz),4766						       GFP_KERNEL);4767	if (!wiphy->bands[NL80211_BAND_2GHZ]) {4768		ret = -ENOMEM;4769		goto err;4770	}4771 4772	if (adapter->config_bands & BAND_A) {4773		wiphy->bands[NL80211_BAND_5GHZ] = devm_kmemdup(adapter->dev,4774							       &mwifiex_band_5ghz,4775							       sizeof(mwifiex_band_5ghz),4776							       GFP_KERNEL);4777		if (!wiphy->bands[NL80211_BAND_5GHZ]) {4778			ret = -ENOMEM;4779			goto err;4780		}4781	} else {4782		wiphy->bands[NL80211_BAND_5GHZ] = NULL;4783	}4784 4785	if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))4786		wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;4787	else if (adapter->is_hw_11ac_capable)4788		wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht;4789	else4790		wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;4791	wiphy->n_iface_combinations = 1;4792 4793	if (adapter->max_sta_conn > adapter->max_p2p_conn)4794		wiphy->max_ap_assoc_sta = adapter->max_sta_conn;4795	else4796		wiphy->max_ap_assoc_sta = adapter->max_p2p_conn;4797 4798	/* Initialize cipher suits */4799	wiphy->cipher_suites = mwifiex_cipher_suites;4800	wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);4801 4802	if (adapter->regd) {4803		wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |4804					   REGULATORY_DISABLE_BEACON_HINTS |4805					   REGULATORY_COUNTRY_IE_IGNORE;4806		wiphy_apply_custom_regulatory(wiphy, adapter->regd);4807	}4808 4809	ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);4810	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;4811	wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |4812			WIPHY_FLAG_AP_UAPSD |4813			WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |4814			WIPHY_FLAG_HAS_CHANNEL_SWITCH |4815			WIPHY_FLAG_NETNS_OK |4816			WIPHY_FLAG_PS_ON_BY_DEFAULT;4817 4818	if (adapter->host_mlme_enabled)4819		wiphy->flags |= WIPHY_FLAG_REPORTS_OBSS;4820	else4821		wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;4822 4823	if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))4824		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |4825				WIPHY_FLAG_TDLS_EXTERNAL_SETUP;4826 4827#ifdef CONFIG_PM4828	if (ISSUPP_FIRMWARE_SUPPLICANT(priv->adapter->fw_cap_info))4829		wiphy->wowlan = &mwifiex_wowlan_support;4830	else4831		wiphy->wowlan = &mwifiex_wowlan_support_no_gtk;4832#endif4833 4834	wiphy->coalesce = &mwifiex_coalesce_support;4835 4836	wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |4837				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |4838				    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;4839 4840	wiphy->max_sched_scan_reqs = 1;4841	wiphy->max_sched_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;4842	wiphy->max_sched_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;4843	wiphy->max_match_sets = MWIFIEX_MAX_SSID_LIST_LENGTH;4844 4845	wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;4846	wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;4847 4848	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER |4849			   NL80211_FEATURE_LOW_PRIORITY_SCAN |4850			   NL80211_FEATURE_NEED_OBSS_SCAN;4851 4852	if (adapter->host_mlme_enabled)4853		wiphy->features |= NL80211_FEATURE_SAE;4854 4855	if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))4856		wiphy->features |= NL80211_FEATURE_HT_IBSS;4857 4858	if (ISSUPP_RANDOM_MAC(adapter->fw_cap_info))4859		wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |4860				   NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |4861				   NL80211_FEATURE_ND_RANDOM_MAC_ADDR;4862 4863	if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))4864		wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;4865 4866	if (adapter->fw_api_ver == MWIFIEX_FW_V15)4867		wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;4868 4869	/* Reserve space for mwifiex specific private data for BSS */4870	wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);4871 4872	wiphy->reg_notifier = mwifiex_reg_notifier;4873 4874	/* Set struct mwifiex_adapter pointer in wiphy_priv */4875	wdev_priv = wiphy_priv(wiphy);4876	*(unsigned long *)wdev_priv = (unsigned long)adapter;4877 4878	set_wiphy_dev(wiphy, priv->adapter->dev);4879 4880	ret = wiphy_register(wiphy);4881	if (ret < 0) {4882		mwifiex_dbg(adapter, ERROR,4883			    "%s: wiphy_register failed: %d\n", __func__, ret);4884		goto err;4885	}4886 4887	if (!adapter->regd) {4888		if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {4889			mwifiex_dbg(adapter, INFO,4890				    "driver hint alpha2: %2.2s\n", reg_alpha2);4891			regulatory_hint(wiphy, reg_alpha2);4892		} else {4893			if (adapter->region_code == 0x00) {4894				mwifiex_dbg(adapter, WARN,4895					    "Ignore world regulatory domain\n");4896			} else {4897				wiphy->regulatory_flags |=4898					REGULATORY_DISABLE_BEACON_HINTS |4899					REGULATORY_COUNTRY_IE_IGNORE;4900				country_code =4901					mwifiex_11d_code_2_region(4902						adapter->region_code);4903				if (country_code &&4904				    regulatory_hint(wiphy, country_code))4905					mwifiex_dbg(priv->adapter, ERROR,4906						    "regulatory_hint() failed\n");4907			}4908		}4909	}4910 4911	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4912			 HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);4913	wiphy->frag_threshold = thr;4914	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4915			 HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);4916	wiphy->rts_threshold = thr;4917	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4918			 HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);4919	wiphy->retry_short = (u8) retry;4920	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,4921			 HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);4922	wiphy->retry_long = (u8) retry;4923 4924	adapter->wiphy = wiphy;4925	return ret;4926 4927err:4928	wiphy_free(wiphy);4929 4930	return ret;4931}4932