brintos

brintos / linux-shallow public Read only

0
0
Text · 47.0 KiB · eb37b22 Raw
1896 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.4 * All rights reserved.5 */6 7#include "cfg80211.h"8 9#define GO_NEG_REQ			0x0010#define GO_NEG_RSP			0x0111#define GO_NEG_CONF			0x0212#define P2P_INV_REQ			0x0313#define P2P_INV_RSP			0x0414 15#define WILC_INVALID_CHANNEL		016 17/* Operation at 2.4 GHz with channels 1-13 */18#define WILC_WLAN_OPERATING_CLASS_2_4GHZ		0x5119 20static const struct ieee80211_txrx_stypes21	wilc_wfi_cfg80211_mgmt_types[NUM_NL80211_IFTYPES] = {22	[NL80211_IFTYPE_STATION] = {23		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |24			BIT(IEEE80211_STYPE_AUTH >> 4),25		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |26			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |27			BIT(IEEE80211_STYPE_AUTH >> 4)28	},29	[NL80211_IFTYPE_AP] = {30		.tx = 0xffff,31		.rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |32			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |33			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |34			BIT(IEEE80211_STYPE_DISASSOC >> 4) |35			BIT(IEEE80211_STYPE_AUTH >> 4) |36			BIT(IEEE80211_STYPE_DEAUTH >> 4) |37			BIT(IEEE80211_STYPE_ACTION >> 4)38	},39	[NL80211_IFTYPE_P2P_CLIENT] = {40		.tx = 0xffff,41		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |42			BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |43			BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |44			BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |45			BIT(IEEE80211_STYPE_DISASSOC >> 4) |46			BIT(IEEE80211_STYPE_AUTH >> 4) |47			BIT(IEEE80211_STYPE_DEAUTH >> 4)48	}49};50 51#ifdef CONFIG_PM52static const struct wiphy_wowlan_support wowlan_support = {53	.flags = WIPHY_WOWLAN_ANY54};55#endif56 57struct wilc_p2p_mgmt_data {58	int size;59	u8 *buff;60};61 62struct wilc_p2p_pub_act_frame {63	u8 category;64	u8 action;65	u8 oui[3];66	u8 oui_type;67	u8 oui_subtype;68	u8 dialog_token;69	u8 elem[];70} __packed;71 72struct wilc_vendor_specific_ie {73	u8 tag_number;74	u8 tag_len;75	u8 oui[3];76	u8 oui_type;77	u8 attr[];78} __packed;79 80struct wilc_attr_entry {81	u8  attr_type;82	__le16 attr_len;83	u8 val[];84} __packed;85 86struct wilc_attr_oper_ch {87	u8 attr_type;88	__le16 attr_len;89	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];90	u8 op_class;91	u8 op_channel;92} __packed;93 94struct wilc_attr_ch_list {95	u8 attr_type;96	__le16 attr_len;97	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];98	u8 elem[];99} __packed;100 101struct wilc_ch_list_elem {102	u8 op_class;103	u8 no_of_channels;104	u8 ch_list[];105} __packed;106 107static void cfg_scan_result(enum scan_event scan_event,108			    struct wilc_rcvd_net_info *info,109			    struct wilc_priv *priv)110{111	if (!priv->cfg_scanning)112		return;113 114	if (scan_event == SCAN_EVENT_NETWORK_FOUND) {115		s32 freq;116		struct ieee80211_channel *channel;117		struct cfg80211_bss *bss;118		struct wiphy *wiphy = priv->dev->ieee80211_ptr->wiphy;119 120		if (!wiphy || !info)121			return;122 123		freq = ieee80211_channel_to_frequency((s32)info->ch,124						      NL80211_BAND_2GHZ);125		channel = ieee80211_get_channel(wiphy, freq);126		if (!channel)127			return;128 129		bss = cfg80211_inform_bss_frame(wiphy, channel, info->mgmt,130						info->frame_len,131						(s32)info->rssi * 100,132						GFP_KERNEL);133		cfg80211_put_bss(wiphy, bss);134	} else if (scan_event == SCAN_EVENT_DONE) {135		mutex_lock(&priv->scan_req_lock);136 137		if (priv->scan_req) {138			struct cfg80211_scan_info info = {139				.aborted = false,140			};141 142			cfg80211_scan_done(priv->scan_req, &info);143			priv->cfg_scanning = false;144			priv->scan_req = NULL;145		}146		mutex_unlock(&priv->scan_req_lock);147	} else if (scan_event == SCAN_EVENT_ABORTED) {148		mutex_lock(&priv->scan_req_lock);149 150		if (priv->scan_req) {151			struct cfg80211_scan_info info = {152				.aborted = false,153			};154 155			cfg80211_scan_done(priv->scan_req, &info);156			priv->cfg_scanning = false;157			priv->scan_req = NULL;158		}159		mutex_unlock(&priv->scan_req_lock);160	}161}162 163static void cfg_connect_result(enum conn_event conn_disconn_evt, u8 mac_status,164			       struct wilc_priv *priv)165{166	struct net_device *dev = priv->dev;167	struct wilc_vif *vif = netdev_priv(dev);168	struct wilc *wl = vif->wilc;169	struct host_if_drv *wfi_drv = priv->hif_drv;170	struct wilc_conn_info *conn_info = &wfi_drv->conn_info;171	struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;172 173	vif->connecting = false;174 175	if (conn_disconn_evt == CONN_DISCONN_EVENT_CONN_RESP) {176		u16 connect_status = conn_info->status;177 178		if (mac_status == WILC_MAC_STATUS_DISCONNECTED &&179		    connect_status == WLAN_STATUS_SUCCESS) {180			connect_status = WLAN_STATUS_UNSPECIFIED_FAILURE;181			wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);182 183			if (vif->iftype != WILC_CLIENT_MODE)184				wl->sta_ch = WILC_INVALID_CHANNEL;185 186			netdev_err(dev, "Unspecified failure\n");187		}188 189		if (connect_status == WLAN_STATUS_SUCCESS)190			memcpy(priv->associated_bss, conn_info->bssid,191			       ETH_ALEN);192 193		cfg80211_ref_bss(wiphy, vif->bss);194		cfg80211_connect_bss(dev, conn_info->bssid, vif->bss,195				     conn_info->req_ies,196				     conn_info->req_ies_len,197				     conn_info->resp_ies,198				     conn_info->resp_ies_len,199				     connect_status, GFP_KERNEL,200				     NL80211_TIMEOUT_UNSPECIFIED);201 202		vif->bss = NULL;203	} else if (conn_disconn_evt == CONN_DISCONN_EVENT_DISCONN_NOTIF) {204		u16 reason = 0;205 206		eth_zero_addr(priv->associated_bss);207		wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);208 209		if (vif->iftype != WILC_CLIENT_MODE) {210			wl->sta_ch = WILC_INVALID_CHANNEL;211		} else {212			if (wfi_drv->ifc_up)213				reason = 3;214			else215				reason = 1;216		}217 218		cfg80211_disconnected(dev, reason, NULL, 0, false, GFP_KERNEL);219	}220}221 222struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)223{224	struct wilc_vif *vif;225 226	vif = list_first_or_null_rcu(&wl->vif_list, typeof(*vif), list);227	if (!vif)228		return ERR_PTR(-EINVAL);229 230	return vif;231}232 233static int set_channel(struct wiphy *wiphy,234		       struct cfg80211_chan_def *chandef)235{236	struct wilc *wl = wiphy_priv(wiphy);237	struct wilc_vif *vif;238	u32 channelnum;239	int result;240	int srcu_idx;241 242	srcu_idx = srcu_read_lock(&wl->srcu);243	vif = wilc_get_wl_to_vif(wl);244	if (IS_ERR(vif)) {245		srcu_read_unlock(&wl->srcu, srcu_idx);246		return PTR_ERR(vif);247	}248 249	channelnum = ieee80211_frequency_to_channel(chandef->chan->center_freq);250 251	wl->op_ch = channelnum;252	result = wilc_set_mac_chnl_num(vif, channelnum);253	if (result)254		netdev_err(vif->ndev, "Error in setting channel\n");255 256	srcu_read_unlock(&wl->srcu, srcu_idx);257	return result;258}259 260static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)261{262	struct wilc_vif *vif = netdev_priv(request->wdev->netdev);263	struct wilc_priv *priv = &vif->priv;264	u32 i;265	int ret = 0;266	u8 scan_ch_list[WILC_MAX_NUM_SCANNED_CH];267	u8 scan_type;268 269	if (request->n_channels > WILC_MAX_NUM_SCANNED_CH) {270		netdev_err(vif->ndev, "Requested scanned channels over\n");271		return -EINVAL;272	}273 274	priv->scan_req = request;275	priv->cfg_scanning = true;276	for (i = 0; i < request->n_channels; i++) {277		u16 freq = request->channels[i]->center_freq;278 279		scan_ch_list[i] = ieee80211_frequency_to_channel(freq);280	}281 282	if (request->n_ssids)283		scan_type = WILC_FW_ACTIVE_SCAN;284	else285		scan_type = WILC_FW_PASSIVE_SCAN;286 287	ret = wilc_scan(vif, WILC_FW_USER_SCAN, scan_type,288			scan_ch_list, cfg_scan_result, request);289 290	if (ret) {291		priv->scan_req = NULL;292		priv->cfg_scanning = false;293	}294 295	return ret;296}297 298static int connect(struct wiphy *wiphy, struct net_device *dev,299		   struct cfg80211_connect_params *sme)300{301	struct wilc_vif *vif = netdev_priv(dev);302	struct wilc_priv *priv = &vif->priv;303	struct host_if_drv *wfi_drv = priv->hif_drv;304	int ret;305	u32 i;306	u8 security = WILC_FW_SEC_NO;307	enum mfptype mfp_type = WILC_FW_MFP_NONE;308	enum authtype auth_type = WILC_FW_AUTH_ANY;309	u32 cipher_group;310	struct cfg80211_bss *bss;311	void *join_params;312	u8 ch;313 314	vif->connecting = true;315 316	cipher_group = sme->crypto.cipher_group;317	if (cipher_group != 0) {318		if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {319			if (cipher_group == WLAN_CIPHER_SUITE_TKIP)320				security = WILC_FW_SEC_WPA2_TKIP;321			else322				security = WILC_FW_SEC_WPA2_AES;323		} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {324			if (cipher_group == WLAN_CIPHER_SUITE_TKIP)325				security = WILC_FW_SEC_WPA_TKIP;326			else327				security = WILC_FW_SEC_WPA_AES;328		} else {329			ret = -ENOTSUPP;330			netdev_err(dev, "%s: Unsupported cipher\n",331				   __func__);332			goto out_error;333		}334	}335 336	if ((sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) ||337	    (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {338		for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) {339			u32 ciphers_pairwise = sme->crypto.ciphers_pairwise[i];340 341			if (ciphers_pairwise == WLAN_CIPHER_SUITE_TKIP)342				security |= WILC_FW_TKIP;343			else344				security |= WILC_FW_AES;345		}346	}347 348	switch (sme->auth_type) {349	case NL80211_AUTHTYPE_OPEN_SYSTEM:350		auth_type = WILC_FW_AUTH_OPEN_SYSTEM;351		break;352 353	case NL80211_AUTHTYPE_SAE:354		auth_type = WILC_FW_AUTH_SAE;355		if (sme->ssid_len) {356			memcpy(vif->auth.ssid.ssid, sme->ssid, sme->ssid_len);357			vif->auth.ssid.ssid_len = sme->ssid_len;358		}359		vif->auth.key_mgmt_suite = sme->crypto.akm_suites[0];360		ether_addr_copy(vif->auth.bssid, sme->bssid);361		break;362 363	default:364		break;365	}366 367	if (sme->crypto.n_akm_suites) {368		if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X)369			auth_type = WILC_FW_AUTH_IEEE8021;370		else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_PSK_SHA256)371			auth_type = WILC_FW_AUTH_OPEN_SYSTEM_SHA256;372		else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_8021X_SHA256)373			auth_type = WILC_FW_AUTH_IEE8021X_SHA256;374	}375 376	if (wfi_drv->usr_scan_req.scan_result) {377		netdev_err(vif->ndev, "%s: Scan in progress\n", __func__);378		ret = -EBUSY;379		goto out_error;380	}381 382	bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid,383			       sme->ssid_len, IEEE80211_BSS_TYPE_ANY,384			       IEEE80211_PRIVACY(sme->privacy));385	if (!bss) {386		ret = -EINVAL;387		goto out_error;388	}389 390	if (ether_addr_equal_unaligned(vif->bssid, bss->bssid)) {391		ret = -EALREADY;392		goto out_put_bss;393	}394 395	join_params = wilc_parse_join_bss_param(bss, &sme->crypto);396	if (!join_params) {397		netdev_err(dev, "%s: failed to construct join param\n",398			   __func__);399		ret = -EINVAL;400		goto out_put_bss;401	}402 403	ch = ieee80211_frequency_to_channel(bss->channel->center_freq);404	vif->wilc->op_ch = ch;405	if (vif->iftype != WILC_CLIENT_MODE)406		vif->wilc->sta_ch = ch;407 408	wilc_wlan_set_bssid(dev, bss->bssid, WILC_STATION_MODE);409 410	wfi_drv->conn_info.security = security;411	wfi_drv->conn_info.auth_type = auth_type;412	wfi_drv->conn_info.conn_result = cfg_connect_result;413	wfi_drv->conn_info.priv = priv;414	wfi_drv->conn_info.param = join_params;415 416	if (sme->mfp == NL80211_MFP_OPTIONAL)417		mfp_type = WILC_FW_MFP_OPTIONAL;418	else if (sme->mfp == NL80211_MFP_REQUIRED)419		mfp_type = WILC_FW_MFP_REQUIRED;420 421	wfi_drv->conn_info.mfp_type = mfp_type;422 423	ret = wilc_set_join_req(vif, bss->bssid, sme->ie, sme->ie_len);424	if (ret) {425		netdev_err(dev, "wilc_set_join_req(): Error\n");426		ret = -ENOENT;427		if (vif->iftype != WILC_CLIENT_MODE)428			vif->wilc->sta_ch = WILC_INVALID_CHANNEL;429		wilc_wlan_set_bssid(dev, NULL, WILC_STATION_MODE);430		wfi_drv->conn_info.conn_result = NULL;431		kfree(join_params);432		goto out_put_bss;433	}434	kfree(join_params);435	vif->bss = bss;436	cfg80211_put_bss(wiphy, bss);437	return 0;438 439out_put_bss:440	cfg80211_put_bss(wiphy, bss);441 442out_error:443	vif->connecting = false;444	return ret;445}446 447static int disconnect(struct wiphy *wiphy, struct net_device *dev,448		      u16 reason_code)449{450	struct wilc_vif *vif = netdev_priv(dev);451	struct wilc_priv *priv = &vif->priv;452	struct wilc *wilc = vif->wilc;453	int ret;454 455	vif->connecting = false;456 457	if (!wilc)458		return -EIO;459 460	if (wilc->close) {461		/* already disconnected done */462		cfg80211_disconnected(dev, 0, NULL, 0, true, GFP_KERNEL);463		return 0;464	}465 466	if (vif->iftype != WILC_CLIENT_MODE)467		wilc->sta_ch = WILC_INVALID_CHANNEL;468	wilc_wlan_set_bssid(priv->dev, NULL, WILC_STATION_MODE);469 470	priv->hif_drv->p2p_timeout = 0;471 472	ret = wilc_disconnect(vif);473	if (ret != 0) {474		netdev_err(priv->dev, "Error in disconnecting\n");475		ret = -EINVAL;476	}477 478	vif->bss = NULL;479 480	return ret;481}482 483static int wilc_wfi_cfg_allocate_wpa_entry(struct wilc_priv *priv, u8 idx)484{485	if (!priv->wilc_gtk[idx]) {486		priv->wilc_gtk[idx] = kzalloc(sizeof(*priv->wilc_gtk[idx]),487					      GFP_KERNEL);488		if (!priv->wilc_gtk[idx])489			return -ENOMEM;490	}491 492	if (!priv->wilc_ptk[idx]) {493		priv->wilc_ptk[idx] = kzalloc(sizeof(*priv->wilc_ptk[idx]),494					      GFP_KERNEL);495		if (!priv->wilc_ptk[idx])496			return -ENOMEM;497	}498 499	return 0;500}501 502static int wilc_wfi_cfg_allocate_wpa_igtk_entry(struct wilc_priv *priv, u8 idx)503{504	idx -= 4;505	if (!priv->wilc_igtk[idx]) {506		priv->wilc_igtk[idx] = kzalloc(sizeof(*priv->wilc_igtk[idx]),507					       GFP_KERNEL);508		if (!priv->wilc_igtk[idx])509			return -ENOMEM;510	}511	return 0;512}513 514static int wilc_wfi_cfg_copy_wpa_info(struct wilc_wfi_key *key_info,515				      struct key_params *params)516{517	kfree(key_info->key);518 519	key_info->key = kmemdup(params->key, params->key_len, GFP_KERNEL);520	if (!key_info->key)521		return -ENOMEM;522 523	kfree(key_info->seq);524 525	if (params->seq_len > 0) {526		key_info->seq = kmemdup(params->seq, params->seq_len,527					GFP_KERNEL);528		if (!key_info->seq)529			return -ENOMEM;530	}531 532	key_info->cipher = params->cipher;533	key_info->key_len = params->key_len;534	key_info->seq_len = params->seq_len;535 536	return 0;537}538 539static int add_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,540		   u8 key_index, bool pairwise, const u8 *mac_addr,541		   struct key_params *params)542 543{544	int ret = 0, keylen = params->key_len;545	const u8 *rx_mic = NULL;546	const u8 *tx_mic = NULL;547	u8 mode = WILC_FW_SEC_NO;548	u8 op_mode;549	struct wilc_vif *vif = netdev_priv(netdev);550	struct wilc_priv *priv = &vif->priv;551	struct wilc_wfi_key *key;552 553	switch (params->cipher) {554	case WLAN_CIPHER_SUITE_TKIP:555	case WLAN_CIPHER_SUITE_CCMP:556		if (priv->wdev.iftype == NL80211_IFTYPE_AP ||557		    priv->wdev.iftype == NL80211_IFTYPE_P2P_GO) {558			struct wilc_wfi_key *key;559 560			ret = wilc_wfi_cfg_allocate_wpa_entry(priv, key_index);561			if (ret)562				return -ENOMEM;563 564			if (params->key_len > 16 &&565			    params->cipher == WLAN_CIPHER_SUITE_TKIP) {566				tx_mic = params->key + 24;567				rx_mic = params->key + 16;568				keylen = params->key_len - 16;569			}570 571			if (!pairwise) {572				if (params->cipher == WLAN_CIPHER_SUITE_TKIP)573					mode = WILC_FW_SEC_WPA_TKIP;574				else575					mode = WILC_FW_SEC_WPA2_AES;576 577				priv->wilc_groupkey = mode;578 579				key = priv->wilc_gtk[key_index];580			} else {581				if (params->cipher == WLAN_CIPHER_SUITE_TKIP)582					mode = WILC_FW_SEC_WPA_TKIP;583				else584					mode = priv->wilc_groupkey | WILC_FW_AES;585 586				key = priv->wilc_ptk[key_index];587			}588			ret = wilc_wfi_cfg_copy_wpa_info(key, params);589			if (ret)590				return -ENOMEM;591 592			op_mode = WILC_AP_MODE;593		} else {594			if (params->key_len > 16 &&595			    params->cipher == WLAN_CIPHER_SUITE_TKIP) {596				rx_mic = params->key + 24;597				tx_mic = params->key + 16;598				keylen = params->key_len - 16;599			}600 601			op_mode = WILC_STATION_MODE;602		}603 604		if (!pairwise)605			ret = wilc_add_rx_gtk(vif, params->key, keylen,606					      key_index, params->seq_len,607					      params->seq, rx_mic, tx_mic,608					      op_mode, mode);609		else610			ret = wilc_add_ptk(vif, params->key, keylen, mac_addr,611					   rx_mic, tx_mic, op_mode, mode,612					   key_index);613 614		break;615	case WLAN_CIPHER_SUITE_AES_CMAC:616		ret = wilc_wfi_cfg_allocate_wpa_igtk_entry(priv, key_index);617		if (ret)618			return -ENOMEM;619 620		key = priv->wilc_igtk[key_index - 4];621		ret = wilc_wfi_cfg_copy_wpa_info(key, params);622		if (ret)623			return -ENOMEM;624 625		if (priv->wdev.iftype == NL80211_IFTYPE_AP ||626		    priv->wdev.iftype == NL80211_IFTYPE_P2P_GO)627			op_mode = WILC_AP_MODE;628		else629			op_mode = WILC_STATION_MODE;630 631		ret = wilc_add_igtk(vif, params->key, keylen, params->seq,632				    params->seq_len, mac_addr, op_mode,633				    key_index);634		break;635 636	default:637		netdev_err(netdev, "%s: Unsupported cipher\n", __func__);638		ret = -ENOTSUPP;639	}640 641	return ret;642}643 644static int del_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,645		   u8 key_index,646		   bool pairwise,647		   const u8 *mac_addr)648{649	struct wilc_vif *vif = netdev_priv(netdev);650	struct wilc_priv *priv = &vif->priv;651 652	if (!pairwise && (key_index == 4 || key_index == 5)) {653		key_index -= 4;654		if (priv->wilc_igtk[key_index]) {655			kfree(priv->wilc_igtk[key_index]->key);656			priv->wilc_igtk[key_index]->key = NULL;657			kfree(priv->wilc_igtk[key_index]->seq);658			priv->wilc_igtk[key_index]->seq = NULL;659			kfree(priv->wilc_igtk[key_index]);660			priv->wilc_igtk[key_index] = NULL;661		}662	} else {663		if (priv->wilc_gtk[key_index]) {664			kfree(priv->wilc_gtk[key_index]->key);665			priv->wilc_gtk[key_index]->key = NULL;666			kfree(priv->wilc_gtk[key_index]->seq);667			priv->wilc_gtk[key_index]->seq = NULL;668 669			kfree(priv->wilc_gtk[key_index]);670			priv->wilc_gtk[key_index] = NULL;671		}672		if (priv->wilc_ptk[key_index]) {673			kfree(priv->wilc_ptk[key_index]->key);674			priv->wilc_ptk[key_index]->key = NULL;675			kfree(priv->wilc_ptk[key_index]->seq);676			priv->wilc_ptk[key_index]->seq = NULL;677			kfree(priv->wilc_ptk[key_index]);678			priv->wilc_ptk[key_index] = NULL;679		}680	}681 682	return 0;683}684 685static int get_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,686		   u8 key_index, bool pairwise, const u8 *mac_addr,687		   void *cookie,688		   void (*callback)(void *cookie, struct key_params *))689{690	struct wilc_vif *vif = netdev_priv(netdev);691	struct wilc_priv *priv = &vif->priv;692	struct  key_params key_params;693 694	if (!pairwise) {695		if (key_index == 4 || key_index == 5) {696			key_index -= 4;697			key_params.key = priv->wilc_igtk[key_index]->key;698			key_params.cipher = priv->wilc_igtk[key_index]->cipher;699			key_params.key_len = priv->wilc_igtk[key_index]->key_len;700			key_params.seq = priv->wilc_igtk[key_index]->seq;701			key_params.seq_len = priv->wilc_igtk[key_index]->seq_len;702		} else {703			key_params.key = priv->wilc_gtk[key_index]->key;704			key_params.cipher = priv->wilc_gtk[key_index]->cipher;705			key_params.key_len = priv->wilc_gtk[key_index]->key_len;706			key_params.seq = priv->wilc_gtk[key_index]->seq;707			key_params.seq_len = priv->wilc_gtk[key_index]->seq_len;708		}709	} else {710		key_params.key = priv->wilc_ptk[key_index]->key;711		key_params.cipher = priv->wilc_ptk[key_index]->cipher;712		key_params.key_len = priv->wilc_ptk[key_index]->key_len;713		key_params.seq = priv->wilc_ptk[key_index]->seq;714		key_params.seq_len = priv->wilc_ptk[key_index]->seq_len;715	}716 717	callback(cookie, &key_params);718 719	return 0;720}721 722/* wiphy_new_nm() will WARNON if not present */723static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,724			   int link_id, u8 key_index, bool unicast,725			   bool multicast)726{727	return 0;728}729 730static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev,731				int link_id, u8 key_index)732{733	struct wilc_vif *vif = netdev_priv(netdev);734 735	return wilc_set_default_mgmt_key_index(vif, key_index);736}737 738static int get_station(struct wiphy *wiphy, struct net_device *dev,739		       const u8 *mac, struct station_info *sinfo)740{741	struct wilc_vif *vif = netdev_priv(dev);742	struct wilc_priv *priv = &vif->priv;743	struct wilc *wilc = vif->wilc;744	u32 i = 0;745	u32 associatedsta = ~0;746	u32 inactive_time = 0;747 748	if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {749		for (i = 0; i < NUM_STA_ASSOCIATED; i++) {750			if (!(memcmp(mac,751				     priv->assoc_stainfo.sta_associated_bss[i],752				     ETH_ALEN))) {753				associatedsta = i;754				break;755			}756		}757 758		if (associatedsta == ~0) {759			netdev_err(dev, "sta required is not associated\n");760			return -ENOENT;761		}762 763		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME);764 765		wilc_get_inactive_time(vif, mac, &inactive_time);766		sinfo->inactive_time = 1000 * inactive_time;767	} else if (vif->iftype == WILC_STATION_MODE) {768		struct rf_info stats;769 770		if (!wilc->initialized)771			return -EBUSY;772 773		wilc_get_statistics(vif, &stats);774 775		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL) |776				 BIT_ULL(NL80211_STA_INFO_RX_PACKETS) |777				 BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |778				 BIT_ULL(NL80211_STA_INFO_TX_FAILED) |779				 BIT_ULL(NL80211_STA_INFO_TX_BITRATE);780 781		sinfo->signal = stats.rssi;782		sinfo->rx_packets = stats.rx_cnt;783		sinfo->tx_packets = stats.tx_cnt + stats.tx_fail_cnt;784		sinfo->tx_failed = stats.tx_fail_cnt;785		sinfo->txrate.legacy = stats.link_speed * 10;786 787		if (stats.link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&788		    stats.link_speed != DEFAULT_LINK_SPEED)789			wilc_enable_tcp_ack_filter(vif, true);790		else if (stats.link_speed != DEFAULT_LINK_SPEED)791			wilc_enable_tcp_ack_filter(vif, false);792	}793	return 0;794}795 796static int change_bss(struct wiphy *wiphy, struct net_device *dev,797		      struct bss_parameters *params)798{799	return 0;800}801 802static int set_wiphy_params(struct wiphy *wiphy, u32 changed)803{804	int ret = -EINVAL;805	struct cfg_param_attr cfg_param_val;806	struct wilc *wl = wiphy_priv(wiphy);807	struct wilc_vif *vif;808	struct wilc_priv *priv;809	int srcu_idx;810 811	srcu_idx = srcu_read_lock(&wl->srcu);812	vif = wilc_get_wl_to_vif(wl);813	if (IS_ERR(vif))814		goto out;815 816	priv = &vif->priv;817	cfg_param_val.flag = 0;818 819	if (changed & WIPHY_PARAM_RETRY_SHORT) {820		netdev_dbg(vif->ndev,821			   "Setting WIPHY_PARAM_RETRY_SHORT %d\n",822			   wiphy->retry_short);823		cfg_param_val.flag  |= WILC_CFG_PARAM_RETRY_SHORT;824		cfg_param_val.short_retry_limit = wiphy->retry_short;825	}826	if (changed & WIPHY_PARAM_RETRY_LONG) {827		netdev_dbg(vif->ndev,828			   "Setting WIPHY_PARAM_RETRY_LONG %d\n",829			   wiphy->retry_long);830		cfg_param_val.flag |= WILC_CFG_PARAM_RETRY_LONG;831		cfg_param_val.long_retry_limit = wiphy->retry_long;832	}833	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {834		if (wiphy->frag_threshold > 255 &&835		    wiphy->frag_threshold < 7937) {836			netdev_dbg(vif->ndev,837				   "Setting WIPHY_PARAM_FRAG_THRESHOLD %d\n",838				   wiphy->frag_threshold);839			cfg_param_val.flag |= WILC_CFG_PARAM_FRAG_THRESHOLD;840			cfg_param_val.frag_threshold = wiphy->frag_threshold;841		} else {842			netdev_err(vif->ndev,843				   "Fragmentation threshold out of range\n");844			goto out;845		}846	}847 848	if (changed & WIPHY_PARAM_RTS_THRESHOLD) {849		if (wiphy->rts_threshold > 255) {850			netdev_dbg(vif->ndev,851				   "Setting WIPHY_PARAM_RTS_THRESHOLD %d\n",852				   wiphy->rts_threshold);853			cfg_param_val.flag |= WILC_CFG_PARAM_RTS_THRESHOLD;854			cfg_param_val.rts_threshold = wiphy->rts_threshold;855		} else {856			netdev_err(vif->ndev, "RTS threshold out of range\n");857			goto out;858		}859	}860 861	ret = wilc_hif_set_cfg(vif, &cfg_param_val);862	if (ret)863		netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n");864 865out:866	srcu_read_unlock(&wl->srcu, srcu_idx);867	return ret;868}869 870static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev,871		     struct cfg80211_pmksa *pmksa)872{873	struct wilc_vif *vif = netdev_priv(netdev);874	struct wilc_priv *priv = &vif->priv;875	u32 i;876	int ret = 0;877	u8 flag = 0;878 879	for (i = 0; i < priv->pmkid_list.numpmkid; i++)	{880		if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,881			    ETH_ALEN)) {882			flag = PMKID_FOUND;883			break;884		}885	}886	if (i < WILC_MAX_NUM_PMKIDS) {887		memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,888		       ETH_ALEN);889		memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,890		       WLAN_PMKID_LEN);891		if (!(flag == PMKID_FOUND))892			priv->pmkid_list.numpmkid++;893	} else {894		netdev_err(netdev, "Invalid PMKID index\n");895		ret = -EINVAL;896	}897 898	if (!ret)899		ret = wilc_set_pmkid_info(vif, &priv->pmkid_list);900 901	return ret;902}903 904static int del_pmksa(struct wiphy *wiphy, struct net_device *netdev,905		     struct cfg80211_pmksa *pmksa)906{907	u32 i;908	struct wilc_vif *vif = netdev_priv(netdev);909	struct wilc_priv *priv = &vif->priv;910 911	for (i = 0; i < priv->pmkid_list.numpmkid; i++)	{912		if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,913			    ETH_ALEN)) {914			memset(&priv->pmkid_list.pmkidlist[i], 0,915			       sizeof(struct wilc_pmkid));916			break;917		}918	}919 920	if (i == priv->pmkid_list.numpmkid)921		return -EINVAL;922 923	for (; i < (priv->pmkid_list.numpmkid - 1); i++) {924		memcpy(priv->pmkid_list.pmkidlist[i].bssid,925		       priv->pmkid_list.pmkidlist[i + 1].bssid,926		       ETH_ALEN);927		memcpy(priv->pmkid_list.pmkidlist[i].pmkid,928		       priv->pmkid_list.pmkidlist[i + 1].pmkid,929		       WLAN_PMKID_LEN);930	}931	priv->pmkid_list.numpmkid--;932 933	return 0;934}935 936static int flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)937{938	struct wilc_vif *vif = netdev_priv(netdev);939 940	memset(&vif->priv.pmkid_list, 0, sizeof(struct wilc_pmkid_attr));941 942	return 0;943}944 945static inline void wilc_wfi_cfg_parse_ch_attr(u8 *buf, u32 len, u8 sta_ch)946{947	struct wilc_attr_entry *e;948	struct wilc_attr_ch_list *ch_list;949	struct wilc_attr_oper_ch *op_ch;950	u32 index = 0;951	u8 ch_list_idx = 0;952	u8 op_ch_idx = 0;953 954	if (sta_ch == WILC_INVALID_CHANNEL)955		return;956 957	while (index + sizeof(*e) <= len) {958		u16 attr_size;959 960		e = (struct wilc_attr_entry *)&buf[index];961		attr_size = le16_to_cpu(e->attr_len);962 963		if (index + sizeof(*e) + attr_size > len)964			return;965 966		if (e->attr_type == IEEE80211_P2P_ATTR_CHANNEL_LIST &&967		    attr_size >= (sizeof(struct wilc_attr_ch_list) - sizeof(*e)))968			ch_list_idx = index;969		else if (e->attr_type == IEEE80211_P2P_ATTR_OPER_CHANNEL &&970			 attr_size == (sizeof(struct wilc_attr_oper_ch) - sizeof(*e)))971			op_ch_idx = index;972 973		if (ch_list_idx && op_ch_idx)974			break;975 976		index += sizeof(*e) + attr_size;977	}978 979	if (ch_list_idx) {980		u16 elem_size;981 982		ch_list = (struct wilc_attr_ch_list *)&buf[ch_list_idx];983		/* the number of bytes following the final 'elem' member */984		elem_size = le16_to_cpu(ch_list->attr_len) -985			(sizeof(*ch_list) - sizeof(struct wilc_attr_entry));986		for (unsigned int i = 0; i < elem_size;) {987			struct wilc_ch_list_elem *e;988 989			e = (struct wilc_ch_list_elem *)(ch_list->elem + i);990 991			i += sizeof(*e);992			if (i > elem_size)993				break;994 995			i += e->no_of_channels;996			if (i > elem_size)997				break;998 999			if (e->op_class == WILC_WLAN_OPERATING_CLASS_2_4GHZ) {1000				memset(e->ch_list, sta_ch, e->no_of_channels);1001				break;1002			}1003		}1004	}1005 1006	if (op_ch_idx) {1007		op_ch = (struct wilc_attr_oper_ch *)&buf[op_ch_idx];1008		op_ch->op_class = WILC_WLAN_OPERATING_CLASS_2_4GHZ;1009		op_ch->op_channel = sta_ch;1010	}1011}1012 1013bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size)1014{1015	struct wilc *wl = vif->wilc;1016	struct wilc_priv *priv = &vif->priv;1017	int freq;1018 1019	freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);1020 1021	return cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);1022}1023 1024void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)1025{1026	struct wilc *wl = vif->wilc;1027	struct wilc_priv *priv = &vif->priv;1028	struct host_if_drv *wfi_drv = priv->hif_drv;1029	struct ieee80211_mgmt *mgmt;1030	struct wilc_vendor_specific_ie *p;1031	struct wilc_p2p_pub_act_frame *d;1032	int ie_offset = offsetof(struct ieee80211_mgmt, u) + sizeof(*d);1033	const u8 *vendor_ie;1034	u32 header, pkt_offset;1035	s32 freq;1036 1037	header = get_unaligned_le32(buff - HOST_HDR_OFFSET);1038	pkt_offset = FIELD_GET(WILC_PKT_HDR_OFFSET_FIELD, header);1039 1040	if (pkt_offset & IS_MANAGMEMENT_CALLBACK) {1041		bool ack = false;1042		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)buff;1043 1044		if (ieee80211_is_probe_resp(hdr->frame_control) ||1045		    pkt_offset & IS_MGMT_STATUS_SUCCES)1046			ack = true;1047 1048		cfg80211_mgmt_tx_status(&priv->wdev, priv->tx_cookie, buff,1049					size, ack, GFP_KERNEL);1050		return;1051	}1052 1053	freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);1054 1055	mgmt = (struct ieee80211_mgmt *)buff;1056	if (!ieee80211_is_action(mgmt->frame_control))1057		goto out_rx_mgmt;1058 1059	if (priv->cfg_scanning &&1060	    time_after_eq(jiffies, (unsigned long)wfi_drv->p2p_timeout)) {1061		netdev_dbg(vif->ndev, "Receiving action wrong ch\n");1062		return;1063	}1064 1065	if (!ieee80211_is_public_action((struct ieee80211_hdr *)buff, size))1066		goto out_rx_mgmt;1067 1068	d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);1069	if (d->oui_subtype != GO_NEG_REQ && d->oui_subtype != GO_NEG_RSP &&1070	    d->oui_subtype != P2P_INV_REQ && d->oui_subtype != P2P_INV_RSP)1071		goto out_rx_mgmt;1072 1073	vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,1074					    buff + ie_offset, size - ie_offset);1075	if (!vendor_ie)1076		goto out_rx_mgmt;1077 1078	p = (struct wilc_vendor_specific_ie *)vendor_ie;1079	wilc_wfi_cfg_parse_ch_attr(p->attr, p->tag_len - 4, vif->wilc->sta_ch);1080 1081out_rx_mgmt:1082	cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);1083}1084 1085static void wilc_wfi_mgmt_tx_complete(void *priv, int status)1086{1087	struct wilc_p2p_mgmt_data *pv_data = priv;1088 1089	kfree(pv_data->buff);1090	kfree(pv_data);1091}1092 1093static void wilc_wfi_remain_on_channel_expired(struct wilc_vif *vif, u64 cookie)1094{1095	struct wilc_priv *priv = &vif->priv;1096	struct wilc_wfi_p2p_listen_params *params = &priv->remain_on_ch_params;1097 1098	if (cookie != params->listen_cookie)1099		return;1100 1101	priv->p2p_listen_state = false;1102 1103	cfg80211_remain_on_channel_expired(&priv->wdev, params->listen_cookie,1104					   params->listen_ch, GFP_KERNEL);1105}1106 1107static int remain_on_channel(struct wiphy *wiphy,1108			     struct wireless_dev *wdev,1109			     struct ieee80211_channel *chan,1110			     unsigned int duration, u64 *cookie)1111{1112	int ret = 0;1113	struct wilc_vif *vif = netdev_priv(wdev->netdev);1114	struct wilc_priv *priv = &vif->priv;1115	u64 id;1116 1117	if (wdev->iftype == NL80211_IFTYPE_AP) {1118		netdev_dbg(vif->ndev, "Required while in AP mode\n");1119		return ret;1120	}1121 1122	id = ++priv->inc_roc_cookie;1123	if (id == 0)1124		id = ++priv->inc_roc_cookie;1125 1126	ret = wilc_remain_on_channel(vif, id, chan->hw_value,1127				     wilc_wfi_remain_on_channel_expired);1128	if (ret)1129		return ret;1130 1131	vif->wilc->op_ch = chan->hw_value;1132 1133	priv->remain_on_ch_params.listen_ch = chan;1134	priv->remain_on_ch_params.listen_cookie = id;1135	*cookie = id;1136	priv->p2p_listen_state = true;1137	priv->remain_on_ch_params.listen_duration = duration;1138 1139	cfg80211_ready_on_channel(wdev, *cookie, chan, duration, GFP_KERNEL);1140	mod_timer(&vif->hif_drv->remain_on_ch_timer,1141		  jiffies + msecs_to_jiffies(duration + 1000));1142 1143	return ret;1144}1145 1146static int cancel_remain_on_channel(struct wiphy *wiphy,1147				    struct wireless_dev *wdev,1148				    u64 cookie)1149{1150	struct wilc_vif *vif = netdev_priv(wdev->netdev);1151	struct wilc_priv *priv = &vif->priv;1152 1153	if (cookie != priv->remain_on_ch_params.listen_cookie)1154		return -ENOENT;1155 1156	return wilc_listen_state_expired(vif, cookie);1157}1158 1159static int mgmt_tx(struct wiphy *wiphy,1160		   struct wireless_dev *wdev,1161		   struct cfg80211_mgmt_tx_params *params,1162		   u64 *cookie)1163{1164	struct ieee80211_channel *chan = params->chan;1165	unsigned int wait = params->wait;1166	const u8 *buf = params->buf;1167	size_t len = params->len;1168	const struct ieee80211_mgmt *mgmt;1169	struct wilc_p2p_mgmt_data *mgmt_tx;1170	struct wilc_vif *vif = netdev_priv(wdev->netdev);1171	struct wilc_priv *priv = &vif->priv;1172	struct host_if_drv *wfi_drv = priv->hif_drv;1173	struct wilc_vendor_specific_ie *p;1174	struct wilc_p2p_pub_act_frame *d;1175	int ie_offset = offsetof(struct ieee80211_mgmt, u) + sizeof(*d);1176	const u8 *vendor_ie;1177	int ret = 0;1178 1179	*cookie = get_random_u32();1180	priv->tx_cookie = *cookie;1181	mgmt = (const struct ieee80211_mgmt *)buf;1182 1183	if (!ieee80211_is_mgmt(mgmt->frame_control))1184		goto out;1185 1186	mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_KERNEL);1187	if (!mgmt_tx) {1188		ret = -ENOMEM;1189		goto out;1190	}1191 1192	mgmt_tx->buff = kmemdup(buf, len, GFP_KERNEL);1193	if (!mgmt_tx->buff) {1194		ret = -ENOMEM;1195		kfree(mgmt_tx);1196		goto out;1197	}1198 1199	mgmt_tx->size = len;1200 1201	if (ieee80211_is_probe_resp(mgmt->frame_control)) {1202		wilc_set_mac_chnl_num(vif, chan->hw_value);1203		vif->wilc->op_ch = chan->hw_value;1204		goto out_txq_add_pkt;1205	}1206 1207	if (!ieee80211_is_public_action((struct ieee80211_hdr *)buf, len)) {1208		if (chan)1209			wilc_set_mac_chnl_num(vif, chan->hw_value);1210		else1211			wilc_set_mac_chnl_num(vif, vif->wilc->op_ch);1212 1213		goto out_set_timeout;1214	}1215 1216	d = (struct wilc_p2p_pub_act_frame *)(&mgmt->u.action);1217	if (d->oui_type != WLAN_OUI_TYPE_WFA_P2P ||1218	    d->oui_subtype != GO_NEG_CONF) {1219		wilc_set_mac_chnl_num(vif, chan->hw_value);1220		vif->wilc->op_ch = chan->hw_value;1221	}1222 1223	if (d->oui_subtype != P2P_INV_REQ && d->oui_subtype != P2P_INV_RSP)1224		goto out_set_timeout;1225 1226	vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P,1227					    mgmt_tx->buff + ie_offset,1228					    len - ie_offset);1229	if (!vendor_ie)1230		goto out_set_timeout;1231 1232	p = (struct wilc_vendor_specific_ie *)vendor_ie;1233	wilc_wfi_cfg_parse_ch_attr(p->attr, p->tag_len - 4, vif->wilc->sta_ch);1234 1235out_set_timeout:1236	wfi_drv->p2p_timeout = (jiffies + msecs_to_jiffies(wait));1237 1238out_txq_add_pkt:1239 1240	wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx,1241				   mgmt_tx->buff, mgmt_tx->size,1242				   wilc_wfi_mgmt_tx_complete);1243 1244out:1245 1246	return ret;1247}1248 1249static int mgmt_tx_cancel_wait(struct wiphy *wiphy,1250			       struct wireless_dev *wdev,1251			       u64 cookie)1252{1253	struct wilc_vif *vif = netdev_priv(wdev->netdev);1254	struct wilc_priv *priv = &vif->priv;1255	struct host_if_drv *wfi_drv = priv->hif_drv;1256 1257	wfi_drv->p2p_timeout = jiffies;1258 1259	if (!priv->p2p_listen_state) {1260		struct wilc_wfi_p2p_listen_params *params;1261 1262		params = &priv->remain_on_ch_params;1263 1264		cfg80211_remain_on_channel_expired(wdev,1265						   params->listen_cookie,1266						   params->listen_ch,1267						   GFP_KERNEL);1268	}1269 1270	return 0;1271}1272 1273void wilc_update_mgmt_frame_registrations(struct wiphy *wiphy,1274					  struct wireless_dev *wdev,1275					  struct mgmt_frame_regs *upd)1276{1277	struct wilc *wl = wiphy_priv(wiphy);1278	struct wilc_vif *vif = netdev_priv(wdev->netdev);1279	u32 presp_bit = BIT(IEEE80211_STYPE_PROBE_REQ >> 4);1280	u32 action_bit = BIT(IEEE80211_STYPE_ACTION >> 4);1281	u32 pauth_bit = BIT(IEEE80211_STYPE_AUTH >> 4);1282 1283	if (wl->initialized) {1284		bool prev = vif->mgmt_reg_stypes & presp_bit;1285		bool now = upd->interface_stypes & presp_bit;1286 1287		if (now != prev)1288			wilc_frame_register(vif, IEEE80211_STYPE_PROBE_REQ, now);1289 1290		prev = vif->mgmt_reg_stypes & action_bit;1291		now = upd->interface_stypes & action_bit;1292 1293		if (now != prev)1294			wilc_frame_register(vif, IEEE80211_STYPE_ACTION, now);1295 1296		prev = vif->mgmt_reg_stypes & pauth_bit;1297		now = upd->interface_stypes & pauth_bit;1298		if (now != prev)1299			wilc_frame_register(vif, IEEE80211_STYPE_AUTH, now);1300	}1301 1302	vif->mgmt_reg_stypes =1303		upd->interface_stypes & (presp_bit | action_bit | pauth_bit);1304}1305 1306static int external_auth(struct wiphy *wiphy, struct net_device *dev,1307			 struct cfg80211_external_auth_params *auth)1308{1309	struct wilc_vif *vif = netdev_priv(dev);1310 1311	if (auth->status == WLAN_STATUS_SUCCESS)1312		wilc_set_external_auth_param(vif, auth);1313 1314	return 0;1315}1316 1317static int set_cqm_rssi_config(struct wiphy *wiphy, struct net_device *dev,1318			       s32 rssi_thold, u32 rssi_hyst)1319{1320	return 0;1321}1322 1323static int dump_station(struct wiphy *wiphy, struct net_device *dev,1324			int idx, u8 *mac, struct station_info *sinfo)1325{1326	struct wilc_vif *vif = netdev_priv(dev);1327	int ret;1328 1329	if (idx != 0)1330		return -ENOENT;1331 1332	ret = wilc_get_rssi(vif, &sinfo->signal);1333	if (ret)1334		return ret;1335 1336	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);1337	memcpy(mac, vif->priv.associated_bss, ETH_ALEN);1338	return 0;1339}1340 1341static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,1342			  bool enabled, int timeout)1343{1344	struct wilc_vif *vif = netdev_priv(dev);1345	struct wilc_priv *priv = &vif->priv;1346 1347	if (!priv->hif_drv)1348		return -EIO;1349 1350	wilc_set_power_mgmt(vif, enabled, timeout);1351 1352	return 0;1353}1354 1355static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev,1356			       enum nl80211_iftype type,1357			       struct vif_params *params)1358{1359	struct wilc *wl = wiphy_priv(wiphy);1360	struct wilc_vif *vif = netdev_priv(dev);1361	struct wilc_priv *priv = &vif->priv;1362 1363	switch (type) {1364	case NL80211_IFTYPE_STATION:1365		vif->connecting = false;1366		dev->ieee80211_ptr->iftype = type;1367		priv->wdev.iftype = type;1368		vif->monitor_flag = 0;1369		if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE)1370			wilc_wfi_deinit_mon_interface(wl, true);1371		vif->iftype = WILC_STATION_MODE;1372 1373		if (wl->initialized)1374			wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1375						WILC_STATION_MODE, vif->idx);1376 1377		memset(priv->assoc_stainfo.sta_associated_bss, 0,1378		       WILC_MAX_NUM_STA * ETH_ALEN);1379		break;1380 1381	case NL80211_IFTYPE_P2P_CLIENT:1382		vif->connecting = false;1383		dev->ieee80211_ptr->iftype = type;1384		priv->wdev.iftype = type;1385		vif->monitor_flag = 0;1386		vif->iftype = WILC_CLIENT_MODE;1387 1388		if (wl->initialized)1389			wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1390						WILC_STATION_MODE, vif->idx);1391		break;1392 1393	case NL80211_IFTYPE_AP:1394		dev->ieee80211_ptr->iftype = type;1395		priv->wdev.iftype = type;1396		vif->iftype = WILC_AP_MODE;1397 1398		if (wl->initialized)1399			wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1400						WILC_AP_MODE, vif->idx);1401		break;1402 1403	case NL80211_IFTYPE_P2P_GO:1404		dev->ieee80211_ptr->iftype = type;1405		priv->wdev.iftype = type;1406		vif->iftype = WILC_GO_MODE;1407 1408		if (wl->initialized)1409			wilc_set_operation_mode(vif, wilc_get_vif_idx(vif),1410						WILC_AP_MODE, vif->idx);1411		break;1412 1413	default:1414		netdev_err(dev, "Unknown interface type= %d\n", type);1415		return -EINVAL;1416	}1417 1418	return 0;1419}1420 1421static int start_ap(struct wiphy *wiphy, struct net_device *dev,1422		    struct cfg80211_ap_settings *settings)1423{1424	struct wilc_vif *vif = netdev_priv(dev);1425	int ret;1426 1427	ret = set_channel(wiphy, &settings->chandef);1428	if (ret != 0)1429		netdev_err(dev, "Error in setting channel\n");1430 1431	wilc_wlan_set_bssid(dev, dev->dev_addr, WILC_AP_MODE);1432 1433	return wilc_add_beacon(vif, settings->beacon_interval,1434				   settings->dtim_period, &settings->beacon);1435}1436 1437static int change_beacon(struct wiphy *wiphy, struct net_device *dev,1438			 struct cfg80211_ap_update *params)1439{1440	struct wilc_vif *vif = netdev_priv(dev);1441 1442	return wilc_add_beacon(vif, 0, 0, &params->beacon);1443}1444 1445static int stop_ap(struct wiphy *wiphy, struct net_device *dev,1446		   unsigned int link_id)1447{1448	int ret;1449	struct wilc_vif *vif = netdev_priv(dev);1450 1451	wilc_wlan_set_bssid(dev, NULL, WILC_AP_MODE);1452 1453	ret = wilc_del_beacon(vif);1454 1455	if (ret)1456		netdev_err(dev, "Host delete beacon fail\n");1457 1458	return ret;1459}1460 1461static int add_station(struct wiphy *wiphy, struct net_device *dev,1462		       const u8 *mac, struct station_parameters *params)1463{1464	int ret = 0;1465	struct wilc_vif *vif = netdev_priv(dev);1466	struct wilc_priv *priv = &vif->priv;1467 1468	if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {1469		memcpy(priv->assoc_stainfo.sta_associated_bss[params->aid], mac,1470		       ETH_ALEN);1471 1472		ret = wilc_add_station(vif, mac, params);1473		if (ret)1474			netdev_err(dev, "Host add station fail\n");1475	}1476 1477	return ret;1478}1479 1480static int del_station(struct wiphy *wiphy, struct net_device *dev,1481		       struct station_del_parameters *params)1482{1483	const u8 *mac = params->mac;1484	int ret = 0;1485	struct wilc_vif *vif = netdev_priv(dev);1486	struct wilc_priv *priv = &vif->priv;1487	struct sta_info *info;1488 1489	if (!(vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE))1490		return ret;1491 1492	info = &priv->assoc_stainfo;1493 1494	if (!mac)1495		ret = wilc_del_allstation(vif, info->sta_associated_bss);1496 1497	ret = wilc_del_station(vif, mac);1498	if (ret)1499		netdev_err(dev, "Host delete station fail\n");1500	return ret;1501}1502 1503static int change_station(struct wiphy *wiphy, struct net_device *dev,1504			  const u8 *mac, struct station_parameters *params)1505{1506	int ret = 0;1507	struct wilc_vif *vif = netdev_priv(dev);1508 1509	if (vif->iftype == WILC_AP_MODE || vif->iftype == WILC_GO_MODE) {1510		ret = wilc_edit_station(vif, mac, params);1511		if (ret)1512			netdev_err(dev, "Host edit station fail\n");1513	}1514	return ret;1515}1516 1517static struct wilc_vif *wilc_get_vif_from_type(struct wilc *wl, int type)1518{1519	struct wilc_vif *vif;1520 1521	wilc_for_each_vif(wl, vif) {1522		if (vif->iftype == type)1523			return vif;1524	}1525 1526	return NULL;1527}1528 1529static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy,1530					     const char *name,1531					     unsigned char name_assign_type,1532					     enum nl80211_iftype type,1533					     struct vif_params *params)1534{1535	struct wilc *wl = wiphy_priv(wiphy);1536	struct wilc_vif *vif;1537	struct wireless_dev *wdev;1538	int iftype;1539 1540	if (type == NL80211_IFTYPE_MONITOR) {1541		struct net_device *ndev;1542		int srcu_idx;1543 1544		srcu_idx = srcu_read_lock(&wl->srcu);1545		vif = wilc_get_vif_from_type(wl, WILC_AP_MODE);1546		if (!vif) {1547			vif = wilc_get_vif_from_type(wl, WILC_GO_MODE);1548			if (!vif) {1549				srcu_read_unlock(&wl->srcu, srcu_idx);1550				goto validate_interface;1551			}1552		}1553 1554		if (vif->monitor_flag) {1555			srcu_read_unlock(&wl->srcu, srcu_idx);1556			goto validate_interface;1557		}1558 1559		ndev = wilc_wfi_init_mon_interface(wl, name, vif->ndev);1560		if (ndev) {1561			vif->monitor_flag = 1;1562		} else {1563			srcu_read_unlock(&wl->srcu, srcu_idx);1564			return ERR_PTR(-EINVAL);1565		}1566 1567		wdev = &vif->priv.wdev;1568		srcu_read_unlock(&wl->srcu, srcu_idx);1569		return wdev;1570	}1571 1572validate_interface:1573	mutex_lock(&wl->vif_mutex);1574	if (wl->vif_num == WILC_NUM_CONCURRENT_IFC) {1575		pr_err("Reached maximum number of interface\n");1576		mutex_unlock(&wl->vif_mutex);1577		return ERR_PTR(-EINVAL);1578	}1579	mutex_unlock(&wl->vif_mutex);1580 1581	switch (type) {1582	case NL80211_IFTYPE_STATION:1583		iftype = WILC_STATION_MODE;1584		break;1585	case NL80211_IFTYPE_AP:1586		iftype = WILC_AP_MODE;1587		break;1588	default:1589		return ERR_PTR(-EOPNOTSUPP);1590	}1591 1592	vif = wilc_netdev_ifc_init(wl, name, iftype, type, true);1593	if (IS_ERR(vif))1594		return ERR_CAST(vif);1595 1596	return &vif->priv.wdev;1597}1598 1599static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)1600{1601	struct wilc *wl = wiphy_priv(wiphy);1602	struct wilc_vif *vif;1603 1604	if (wdev->iftype == NL80211_IFTYPE_AP ||1605	    wdev->iftype == NL80211_IFTYPE_P2P_GO)1606		wilc_wfi_deinit_mon_interface(wl, true);1607	vif = netdev_priv(wdev->netdev);1608	cfg80211_stop_iface(wiphy, wdev, GFP_KERNEL);1609	cfg80211_unregister_netdevice(vif->ndev);1610	vif->monitor_flag = 0;1611 1612	mutex_lock(&wl->vif_mutex);1613	list_del_rcu(&vif->list);1614	wl->vif_num--;1615	mutex_unlock(&wl->vif_mutex);1616	synchronize_srcu(&wl->srcu);1617	return 0;1618}1619 1620static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled)1621{1622	struct wilc *wl = wiphy_priv(wiphy);1623	struct wilc_vif *vif;1624	int srcu_idx;1625 1626	srcu_idx = srcu_read_lock(&wl->srcu);1627	vif = wilc_get_wl_to_vif(wl);1628	if (IS_ERR(vif)) {1629		srcu_read_unlock(&wl->srcu, srcu_idx);1630		return;1631	}1632 1633	netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled);1634	wilc_set_wowlan_trigger(vif, enabled);1635	srcu_read_unlock(&wl->srcu, srcu_idx);1636}1637 1638static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,1639			enum nl80211_tx_power_setting type, int mbm)1640{1641	int ret;1642	int srcu_idx;1643	s32 tx_power = MBM_TO_DBM(mbm);1644	struct wilc *wl = wiphy_priv(wiphy);1645	struct wilc_vif *vif;1646 1647	if (!wl->initialized)1648		return -EIO;1649 1650	srcu_idx = srcu_read_lock(&wl->srcu);1651	vif = wilc_get_wl_to_vif(wl);1652	if (IS_ERR(vif)) {1653		srcu_read_unlock(&wl->srcu, srcu_idx);1654		return -EINVAL;1655	}1656 1657	netdev_info(vif->ndev, "Setting tx power %d\n", tx_power);1658	if (tx_power < 0)1659		tx_power = 0;1660	else if (tx_power > 18)1661		tx_power = 18;1662	ret = wilc_set_tx_power(vif, tx_power);1663	if (ret)1664		netdev_err(vif->ndev, "Failed to set tx power\n");1665	srcu_read_unlock(&wl->srcu, srcu_idx);1666 1667	return ret;1668}1669 1670static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,1671			int *dbm)1672{1673	int ret;1674	struct wilc_vif *vif = netdev_priv(wdev->netdev);1675	struct wilc *wl = vif->wilc;1676 1677	/* If firmware is not started, return. */1678	if (!wl->initialized)1679		return -EIO;1680 1681	ret = wilc_get_tx_power(vif, (u8 *)dbm);1682	if (ret)1683		netdev_err(vif->ndev, "Failed to get tx power\n");1684 1685	return ret;1686}1687 1688static const struct cfg80211_ops wilc_cfg80211_ops = {1689	.set_monitor_channel = set_channel,1690	.scan = scan,1691	.connect = connect,1692	.disconnect = disconnect,1693	.add_key = add_key,1694	.del_key = del_key,1695	.get_key = get_key,1696	.set_default_key = set_default_key,1697	.set_default_mgmt_key = set_default_mgmt_key,1698	.add_virtual_intf = add_virtual_intf,1699	.del_virtual_intf = del_virtual_intf,1700	.change_virtual_intf = change_virtual_intf,1701 1702	.start_ap = start_ap,1703	.change_beacon = change_beacon,1704	.stop_ap = stop_ap,1705	.add_station = add_station,1706	.del_station = del_station,1707	.change_station = change_station,1708	.get_station = get_station,1709	.dump_station = dump_station,1710	.change_bss = change_bss,1711	.set_wiphy_params = set_wiphy_params,1712 1713	.external_auth = external_auth,1714	.set_pmksa = set_pmksa,1715	.del_pmksa = del_pmksa,1716	.flush_pmksa = flush_pmksa,1717	.remain_on_channel = remain_on_channel,1718	.cancel_remain_on_channel = cancel_remain_on_channel,1719	.mgmt_tx_cancel_wait = mgmt_tx_cancel_wait,1720	.mgmt_tx = mgmt_tx,1721	.update_mgmt_frame_registrations = wilc_update_mgmt_frame_registrations,1722	.set_power_mgmt = set_power_mgmt,1723	.set_cqm_rssi_config = set_cqm_rssi_config,1724 1725	.set_wakeup = wilc_set_wakeup,1726	.set_tx_power = set_tx_power,1727	.get_tx_power = get_tx_power,1728 1729};1730 1731static void wlan_init_locks(struct wilc *wl)1732{1733	mutex_init(&wl->hif_cs);1734	mutex_init(&wl->rxq_cs);1735	mutex_init(&wl->cfg_cmd_lock);1736	mutex_init(&wl->vif_mutex);1737	mutex_init(&wl->deinit_lock);1738 1739	spin_lock_init(&wl->txq_spinlock);1740	mutex_init(&wl->txq_add_to_head_cs);1741 1742	init_completion(&wl->txq_event);1743	init_completion(&wl->cfg_event);1744	init_completion(&wl->sync_event);1745	init_completion(&wl->txq_thread_started);1746	init_srcu_struct(&wl->srcu);1747}1748 1749void wlan_deinit_locks(struct wilc *wilc)1750{1751	mutex_destroy(&wilc->hif_cs);1752	mutex_destroy(&wilc->rxq_cs);1753	mutex_destroy(&wilc->cfg_cmd_lock);1754	mutex_destroy(&wilc->txq_add_to_head_cs);1755	mutex_destroy(&wilc->vif_mutex);1756	mutex_destroy(&wilc->deinit_lock);1757	cleanup_srcu_struct(&wilc->srcu);1758}1759 1760int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,1761		       const struct wilc_hif_func *ops)1762{1763	struct wilc *wl;1764	int ret, i;1765 1766	wl = wilc_create_wiphy(dev);1767	if (!wl)1768		return -EINVAL;1769 1770	wlan_init_locks(wl);1771 1772	ret = wilc_wlan_cfg_init(wl);1773	if (ret)1774		goto free_wl;1775 1776	*wilc = wl;1777	wl->io_type = io_type;1778	wl->hif_func = ops;1779 1780	for (i = 0; i < NQUEUES; i++)1781		INIT_LIST_HEAD(&wl->txq[i].txq_head.list);1782 1783	INIT_LIST_HEAD(&wl->rxq_head.list);1784	INIT_LIST_HEAD(&wl->vif_list);1785 1786	wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,1787						    wiphy_name(wl->wiphy));1788	if (!wl->hif_workqueue) {1789		ret = -ENOMEM;1790		goto free_cfg;1791	}1792 1793	return 0;1794 1795free_cfg:1796	wilc_wlan_cfg_deinit(wl);1797 1798free_wl:1799	wlan_deinit_locks(wl);1800	wiphy_unregister(wl->wiphy);1801	wiphy_free(wl->wiphy);1802	return ret;1803}1804EXPORT_SYMBOL_GPL(wilc_cfg80211_init);1805 1806struct wilc *wilc_create_wiphy(struct device *dev)1807{1808	struct wiphy *wiphy;1809	struct wilc *wl;1810	int ret;1811 1812	wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(*wl));1813	if (!wiphy)1814		return NULL;1815 1816	wl = wiphy_priv(wiphy);1817 1818	memcpy(wl->bitrates, wilc_bitrates, sizeof(wilc_bitrates));1819	memcpy(wl->channels, wilc_2ghz_channels, sizeof(wilc_2ghz_channels));1820	wl->band.bitrates = wl->bitrates;1821	wl->band.n_bitrates = ARRAY_SIZE(wl->bitrates);1822	wl->band.channels = wl->channels;1823	wl->band.n_channels = ARRAY_SIZE(wilc_2ghz_channels);1824 1825	wl->band.ht_cap.ht_supported = 1;1826	wl->band.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);1827	wl->band.ht_cap.mcs.rx_mask[0] = 0xff;1828	wl->band.ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K;1829	wl->band.ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;1830 1831	wiphy->bands[NL80211_BAND_2GHZ] = &wl->band;1832 1833	wiphy->max_scan_ssids = WILC_MAX_NUM_PROBED_SSID;1834#ifdef CONFIG_PM1835	wiphy->wowlan = &wowlan_support;1836#endif1837	wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS;1838	wiphy->max_scan_ie_len = 1000;1839	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;1840	memcpy(wl->cipher_suites, wilc_cipher_suites,1841	       sizeof(wilc_cipher_suites));1842	wiphy->cipher_suites = wl->cipher_suites;1843	wiphy->n_cipher_suites = ARRAY_SIZE(wilc_cipher_suites);1844	wiphy->mgmt_stypes = wilc_wfi_cfg80211_mgmt_types;1845 1846	wiphy->max_remain_on_channel_duration = 500;1847	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |1848				BIT(NL80211_IFTYPE_AP) |1849				BIT(NL80211_IFTYPE_MONITOR) |1850				BIT(NL80211_IFTYPE_P2P_GO) |1851				BIT(NL80211_IFTYPE_P2P_CLIENT);1852	wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;1853	wiphy->features |= NL80211_FEATURE_SAE;1854	set_wiphy_dev(wiphy, dev);1855	wl->wiphy = wiphy;1856	ret = wiphy_register(wiphy);1857	if (ret) {1858		wiphy_free(wiphy);1859		return NULL;1860	}1861	return wl;1862}1863 1864int wilc_init_host_int(struct net_device *net)1865{1866	int ret;1867	struct wilc_vif *vif = netdev_priv(net);1868	struct wilc_priv *priv = &vif->priv;1869 1870	priv->p2p_listen_state = false;1871 1872	mutex_init(&priv->scan_req_lock);1873	ret = wilc_init(net, &priv->hif_drv);1874	if (ret)1875		netdev_err(net, "Error while initializing hostinterface\n");1876 1877	return ret;1878}1879 1880void wilc_deinit_host_int(struct net_device *net)1881{1882	int ret;1883	struct wilc_vif *vif = netdev_priv(net);1884	struct wilc_priv *priv = &vif->priv;1885 1886	priv->p2p_listen_state = false;1887 1888	flush_workqueue(vif->wilc->hif_workqueue);1889	mutex_destroy(&priv->scan_req_lock);1890	ret = wilc_deinit(vif);1891 1892	if (ret)1893		netdev_err(net, "Error while deinitializing host interface\n");1894}1895 1896