File Index
Files and directories
Sign in
FILE

hif.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/microchip/wilc1000/hif.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
   4 * All rights reserved.
   5 */
   6
   7#include "netdev.h"
   8
   9#define WILC_HIF_SCAN_TIMEOUT_MS                5000
  10#define WILC_HIF_CONNECT_TIMEOUT_MS             9500
  11
  12#define WILC_FALSE_FRMWR_CHANNEL		100
  13
  14#define WILC_SCAN_WID_LIST_SIZE		6
  15
  16struct wilc_rcvd_mac_info {
  17	u8 status;
  18};
  19
  20struct wilc_set_multicast {
  21	u32 enabled;
  22	u32 cnt;
  23	u8 *mc_list;
  24};
  25
  26struct host_if_wowlan_trigger {
  27	u8 wowlan_trigger;
  28};
  29
  30struct wilc_del_all_sta {
  31	u8 assoc_sta;
  32	u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
  33};
  34
  35union wilc_message_body {
  36	struct wilc_rcvd_net_info net_info;
  37	struct wilc_rcvd_mac_info mac_info;
  38	struct wilc_set_multicast mc_info;
  39	struct wilc_remain_ch remain_on_ch;
  40	char *data;
  41	struct host_if_wowlan_trigger wow_trigger;
  42};
  43
  44struct host_if_msg {
  45	union wilc_message_body body;
  46	struct wilc_vif *vif;
  47	struct work_struct work;
  48	void (*fn)(struct work_struct *ws);
  49	struct completion work_comp;
  50	bool is_sync;
  51};
  52
  53/* 'msg' should be free by the caller for syc */
  54static struct host_if_msg*
  55wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
  56		bool is_sync)
  57{
  58	struct host_if_msg *msg;
  59
  60	if (!work_fun)
  61		return ERR_PTR(-EINVAL);
  62
  63	msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
  64	if (!msg)
  65		return ERR_PTR(-ENOMEM);
  66	msg->fn = work_fun;
  67	msg->vif = vif;
  68	msg->is_sync = is_sync;
  69	if (is_sync)
  70		init_completion(&msg->work_comp);
  71
  72	return msg;
  73}
  74
  75static int wilc_enqueue_work(struct host_if_msg *msg)
  76{
  77	INIT_WORK(&msg->work, msg->fn);
  78
  79	if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
  80		return -EINVAL;
  81
  82	if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
  83		return -EINVAL;
  84
  85	return 0;
  86}
  87
  88/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
  89 * special purpose in wilc device, so we add 1 to the index to starts from 1.
  90 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
  91 */
  92int wilc_get_vif_idx(struct wilc_vif *vif)
  93{
  94	return vif->idx + 1;
  95}
  96
  97/* We need to minus 1 from idx which is from wilc device to get real index
  98 * of wilc->vif[], because we add 1 when pass to wilc device in the function
  99 * wilc_get_vif_idx.
 100 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
 101 */
 102static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
 103{
 104	int index = idx - 1;
 105	struct wilc_vif *vif;
 106
 107	if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
 108		return NULL;
 109
 110	wilc_for_each_vif(wilc, vif) {
 111		if (vif->idx == index)
 112			return vif;
 113	}
 114
 115	return NULL;
 116}
 117
 118static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
 119{
 120	int result = 0;
 121	u8 abort_running_scan;
 122	struct wid wid;
 123	struct host_if_drv *hif_drv = vif->hif_drv;
 124	struct wilc_user_scan_req *scan_req;
 125
 126	if (evt == SCAN_EVENT_ABORTED) {
 127		abort_running_scan = 1;
 128		wid.id = WID_ABORT_RUNNING_SCAN;
 129		wid.type = WID_CHAR;
 130		wid.val = (s8 *)&abort_running_scan;
 131		wid.size = sizeof(char);
 132
 133		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 134		if (result) {
 135			netdev_err(vif->ndev, "Failed to set abort running\n");
 136			result = -EFAULT;
 137		}
 138	}
 139
 140	if (!hif_drv) {
 141		netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 142		return result;
 143	}
 144
 145	scan_req = &hif_drv->usr_scan_req;
 146	if (scan_req->scan_result) {
 147		scan_req->scan_result(evt, NULL, scan_req->priv);
 148		scan_req->scan_result = NULL;
 149	}
 150
 151	return result;
 152}
 153
 154int wilc_scan(struct wilc_vif *vif, u8 scan_source,
 155	      u8 scan_type, u8 *ch_freq_list,
 156	      void (*scan_result_fn)(enum scan_event,
 157				     struct wilc_rcvd_net_info *,
 158				     struct wilc_priv *),
 159	      struct cfg80211_scan_request *request)
 160{
 161	int result = 0;
 162	struct wid wid_list[WILC_SCAN_WID_LIST_SIZE];
 163	u32 index = 0;
 164	u32 i, scan_timeout;
 165	u8 *buffer;
 166	u32 valuesize = 0;
 167	u8 *search_ssid_vals = NULL;
 168	const u8 ch_list_len = request->n_channels;
 169	struct host_if_drv *hif_drv = vif->hif_drv;
 170
 171	if (hif_drv->hif_state >= HOST_IF_SCANNING &&
 172	    hif_drv->hif_state < HOST_IF_CONNECTED) {
 173		netdev_err(vif->ndev, "Already scan\n");
 174		result = -EBUSY;
 175		goto error;
 176	}
 177
 178	if (vif->connecting) {
 179		netdev_err(vif->ndev, "Don't do obss scan\n");
 180		result = -EBUSY;
 181		goto error;
 182	}
 183
 184	hif_drv->usr_scan_req.ch_cnt = 0;
 185
 186	if (request->n_ssids) {
 187		for (i = 0; i < request->n_ssids; i++)
 188			valuesize += ((request->ssids[i].ssid_len) + 1);
 189		search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
 190		if (search_ssid_vals) {
 191			wid_list[index].id = WID_SSID_PROBE_REQ;
 192			wid_list[index].type = WID_STR;
 193			wid_list[index].val = search_ssid_vals;
 194			buffer = wid_list[index].val;
 195
 196			*buffer++ = request->n_ssids;
 197
 198			for (i = 0; i < request->n_ssids; i++) {
 199				*buffer++ = request->ssids[i].ssid_len;
 200				memcpy(buffer, request->ssids[i].ssid,
 201				       request->ssids[i].ssid_len);
 202				buffer += request->ssids[i].ssid_len;
 203			}
 204			wid_list[index].size = (s32)(valuesize + 1);
 205			index++;
 206		}
 207	}
 208
 209	wid_list[index].id = WID_INFO_ELEMENT_PROBE;
 210	wid_list[index].type = WID_BIN_DATA;
 211	wid_list[index].val = (s8 *)request->ie;
 212	wid_list[index].size = request->ie_len;
 213	index++;
 214
 215	wid_list[index].id = WID_SCAN_TYPE;
 216	wid_list[index].type = WID_CHAR;
 217	wid_list[index].size = sizeof(char);
 218	wid_list[index].val = (s8 *)&scan_type;
 219	index++;
 220
 221	if (scan_type == WILC_FW_PASSIVE_SCAN && request->duration) {
 222		wid_list[index].id = WID_PASSIVE_SCAN_TIME;
 223		wid_list[index].type = WID_SHORT;
 224		wid_list[index].size = sizeof(u16);
 225		wid_list[index].val = (s8 *)&request->duration;
 226		index++;
 227
 228		scan_timeout = (request->duration * ch_list_len) + 500;
 229	} else {
 230		scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
 231	}
 232
 233	wid_list[index].id = WID_SCAN_CHANNEL_LIST;
 234	wid_list[index].type = WID_BIN_DATA;
 235
 236	if (ch_freq_list && ch_list_len > 0) {
 237		for (i = 0; i < ch_list_len; i++) {
 238			if (ch_freq_list[i] > 0)
 239				ch_freq_list[i] -= 1;
 240		}
 241	}
 242
 243	wid_list[index].val = ch_freq_list;
 244	wid_list[index].size = ch_list_len;
 245	index++;
 246
 247	wid_list[index].id = WID_START_SCAN_REQ;
 248	wid_list[index].type = WID_CHAR;
 249	wid_list[index].size = sizeof(char);
 250	wid_list[index].val = (s8 *)&scan_source;
 251	index++;
 252
 253	hif_drv->usr_scan_req.scan_result = scan_result_fn;
 254	hif_drv->usr_scan_req.priv = &vif->priv;
 255
 256	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, index);
 257	if (result) {
 258		netdev_err(vif->ndev, "Failed to send scan parameters\n");
 259		goto error;
 260	}
 261
 262	hif_drv->scan_timer_vif = vif;
 263	mod_timer(&hif_drv->scan_timer,
 264		  jiffies + msecs_to_jiffies(scan_timeout));
 265
 266error:
 267
 268	kfree(search_ssid_vals);
 269
 270	return result;
 271}
 272
 273static int wilc_send_connect_wid(struct wilc_vif *vif)
 274{
 275	int result = 0;
 276	struct wid wid_list[5];
 277	u32 wid_cnt = 0;
 278	struct host_if_drv *hif_drv = vif->hif_drv;
 279	struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
 280	struct wilc_join_bss_param *bss_param = conn_attr->param;
 281
 282
 283        wid_list[wid_cnt].id = WID_SET_MFP;
 284        wid_list[wid_cnt].type = WID_CHAR;
 285        wid_list[wid_cnt].size = sizeof(char);
 286        wid_list[wid_cnt].val = (s8 *)&conn_attr->mfp_type;
 287        wid_cnt++;
 288
 289	wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
 290	wid_list[wid_cnt].type = WID_BIN_DATA;
 291	wid_list[wid_cnt].val = conn_attr->req_ies;
 292	wid_list[wid_cnt].size = conn_attr->req_ies_len;
 293	wid_cnt++;
 294
 295	wid_list[wid_cnt].id = WID_11I_MODE;
 296	wid_list[wid_cnt].type = WID_CHAR;
 297	wid_list[wid_cnt].size = sizeof(char);
 298	wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
 299	wid_cnt++;
 300
 301	wid_list[wid_cnt].id = WID_AUTH_TYPE;
 302	wid_list[wid_cnt].type = WID_CHAR;
 303	wid_list[wid_cnt].size = sizeof(char);
 304	wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
 305	wid_cnt++;
 306
 307	wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
 308	wid_list[wid_cnt].type = WID_STR;
 309	wid_list[wid_cnt].size = sizeof(*bss_param);
 310	wid_list[wid_cnt].val = (u8 *)bss_param;
 311	wid_cnt++;
 312
 313	result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, wid_cnt);
 314	if (result) {
 315		netdev_err(vif->ndev, "failed to send config packet\n");
 316		goto error;
 317	} else {
 318                if (conn_attr->auth_type == WILC_FW_AUTH_SAE)
 319                        hif_drv->hif_state = HOST_IF_EXTERNAL_AUTH;
 320                else
 321                        hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
 322	}
 323
 324	return 0;
 325
 326error:
 327
 328	kfree(conn_attr->req_ies);
 329	conn_attr->req_ies = NULL;
 330
 331	return result;
 332}
 333
 334static void handle_connect_timeout(struct work_struct *work)
 335{
 336	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 337	struct wilc_vif *vif = msg->vif;
 338	int result;
 339	struct wid wid;
 340	u16 dummy_reason_code = 0;
 341	struct host_if_drv *hif_drv = vif->hif_drv;
 342
 343	if (!hif_drv) {
 344		netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 345		goto out;
 346	}
 347
 348	hif_drv->hif_state = HOST_IF_IDLE;
 349
 350	if (hif_drv->conn_info.conn_result) {
 351		hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
 352					       WILC_MAC_STATUS_DISCONNECTED,
 353					       hif_drv->conn_info.priv);
 354
 355	} else {
 356		netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 357	}
 358
 359	wid.id = WID_DISCONNECT;
 360	wid.type = WID_CHAR;
 361	wid.val = (s8 *)&dummy_reason_code;
 362	wid.size = sizeof(char);
 363
 364	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 365	if (result)
 366		netdev_err(vif->ndev, "Failed to send disconnect\n");
 367
 368	hif_drv->conn_info.req_ies_len = 0;
 369	kfree(hif_drv->conn_info.req_ies);
 370	hif_drv->conn_info.req_ies = NULL;
 371
 372out:
 373	kfree(msg);
 374}
 375
 376struct wilc_join_bss_param *
 377wilc_parse_join_bss_param(struct cfg80211_bss *bss,
 378			  struct cfg80211_crypto_settings *crypto)
 379{
 380	const u8 *ies_data, *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
 381	const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
 382	struct ieee80211_p2p_noa_attr noa_attr;
 383	const struct cfg80211_bss_ies *ies;
 384	struct wilc_join_bss_param *param;
 385	u8 rates_len = 0;
 386	int ies_len;
 387	u64 ies_tsf;
 388	int ret;
 389
 390	param = kzalloc(sizeof(*param), GFP_KERNEL);
 391	if (!param)
 392		return NULL;
 393
 394	rcu_read_lock();
 395	ies = rcu_dereference(bss->ies);
 396	ies_data = kmemdup(ies->data, ies->len, GFP_ATOMIC);
 397	if (!ies_data) {
 398		rcu_read_unlock();
 399		kfree(param);
 400		return NULL;
 401	}
 402	ies_len = ies->len;
 403	ies_tsf = ies->tsf;
 404	rcu_read_unlock();
 405
 406	param->beacon_period = cpu_to_le16(bss->beacon_interval);
 407	param->cap_info = cpu_to_le16(bss->capability);
 408	param->bss_type = WILC_FW_BSS_TYPE_INFRA;
 409	param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
 410	ether_addr_copy(param->bssid, bss->bssid);
 411
 412	ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies_data, ies_len);
 413	if (ssid_elm) {
 414		if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
 415			memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
 416	}
 417
 418	tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies_data, ies_len);
 419	if (tim_elm && tim_elm[1] >= 2)
 420		param->dtim_period = tim_elm[3];
 421
 422	memset(param->p_suites, 0xFF, 3);
 423	memset(param->akm_suites, 0xFF, 3);
 424
 425	rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies_data, ies_len);
 426	if (rates_ie) {
 427		rates_len = rates_ie[1];
 428		if (rates_len > WILC_MAX_RATES_SUPPORTED)
 429			rates_len = WILC_MAX_RATES_SUPPORTED;
 430		param->supp_rates[0] = rates_len;
 431		memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
 432	}
 433
 434	if (rates_len < WILC_MAX_RATES_SUPPORTED) {
 435		supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
 436						 ies_data, ies_len);
 437		if (supp_rates_ie) {
 438			u8 ext_rates = supp_rates_ie[1];
 439
 440			if (ext_rates > (WILC_MAX_RATES_SUPPORTED - rates_len))
 441				param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
 442			else
 443				param->supp_rates[0] += ext_rates;
 444
 445			memcpy(&param->supp_rates[rates_len + 1],
 446			       supp_rates_ie + 2,
 447			       (param->supp_rates[0] - rates_len));
 448		}
 449	}
 450
 451	ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies_data, ies_len);
 452	if (ht_ie)
 453		param->ht_capable = true;
 454
 455	ret = cfg80211_get_p2p_attr(ies_data, ies_len,
 456				    IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
 457				    (u8 *)&noa_attr, sizeof(noa_attr));
 458	if (ret > 0) {
 459		param->tsf_lo = cpu_to_le32(ies_tsf);
 460		param->noa_enabled = 1;
 461		param->idx = noa_attr.index;
 462		if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
 463			param->opp_enabled = 1;
 464			param->opp_en.ct_window = noa_attr.oppps_ctwindow;
 465			param->opp_en.cnt = noa_attr.desc[0].count;
 466			param->opp_en.duration = noa_attr.desc[0].duration;
 467			param->opp_en.interval = noa_attr.desc[0].interval;
 468			param->opp_en.start_time = noa_attr.desc[0].start_time;
 469		} else {
 470			param->opp_enabled = 0;
 471			param->opp_dis.cnt = noa_attr.desc[0].count;
 472			param->opp_dis.duration = noa_attr.desc[0].duration;
 473			param->opp_dis.interval = noa_attr.desc[0].interval;
 474			param->opp_dis.start_time = noa_attr.desc[0].start_time;
 475		}
 476	}
 477	wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 478					 WLAN_OUI_TYPE_MICROSOFT_WMM,
 479					 ies_data, ies_len);
 480	if (wmm_ie) {
 481		struct ieee80211_wmm_param_ie *ie;
 482
 483		ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
 484		if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
 485		    ie->version == 1) {
 486			param->wmm_cap = true;
 487			if (ie->qos_info & BIT(7))
 488				param->uapsd_cap = true;
 489		}
 490	}
 491
 492	wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
 493					 WLAN_OUI_TYPE_MICROSOFT_WPA,
 494					 ies_data, ies_len);
 495	if (wpa_ie) {
 496		param->mode_802_11i = 1;
 497		param->rsn_found = true;
 498	}
 499
 500	rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies_data, ies_len);
 501	if (rsn_ie) {
 502		int rsn_ie_len = sizeof(struct element) + rsn_ie[1];
 503		int offset = 8;
 504
 505		param->mode_802_11i = 2;
 506		param->rsn_found = true;
 507
 508		/* extract RSN capabilities */
 509		if (offset < rsn_ie_len) {
 510			/* skip over pairwise suites */
 511			offset += (rsn_ie[offset] * 4) + 2;
 512
 513			if (offset < rsn_ie_len) {
 514				/* skip over authentication suites */
 515				offset += (rsn_ie[offset] * 4) + 2;
 516
 517				if (offset + 1 < rsn_ie_len)
 518					memcpy(param->rsn_cap, &rsn_ie[offset], 2);
 519			}
 520		}
 521	}
 522
 523	if (param->rsn_found) {
 524		int i;
 525
 526		param->rsn_grp_policy = crypto->cipher_group & 0xFF;
 527		for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
 528			param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
 529
 530		for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
 531			param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
 532	}
 533
 534	kfree(ies_data);
 535	return (void *)param;
 536}
 537
 538static void handle_rcvd_ntwrk_info(struct work_struct *work)
 539{
 540	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 541	struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
 542	struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
 543	const u8 *ch_elm;
 544	u8 *ies;
 545	int ies_len;
 546	size_t offset;
 547
 548	if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
 549		offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
 550	else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
 551		offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
 552	else
 553		goto done;
 554
 555	ies = rcvd_info->mgmt->u.beacon.variable;
 556	ies_len = rcvd_info->frame_len - offset;
 557	if (ies_len <= 0)
 558		goto done;
 559
 560	ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
 561	if (ch_elm && ch_elm[1] > 0)
 562		rcvd_info->ch = ch_elm[2];
 563
 564	if (scan_req->scan_result)
 565		scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info,
 566				      scan_req->priv);
 567
 568done:
 569	kfree(rcvd_info->mgmt);
 570	kfree(msg);
 571}
 572
 573static void host_int_get_assoc_res_info(struct wilc_vif *vif,
 574					u8 *assoc_resp_info,
 575					u32 max_assoc_resp_info_len,
 576					u32 *rcvd_assoc_resp_info_len)
 577{
 578	int result;
 579	struct wid wid;
 580
 581	wid.id = WID_ASSOC_RES_INFO;
 582	wid.type = WID_STR;
 583	wid.val = assoc_resp_info;
 584	wid.size = max_assoc_resp_info_len;
 585
 586	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
 587	if (result) {
 588		*rcvd_assoc_resp_info_len = 0;
 589		netdev_err(vif->ndev, "Failed to send association response\n");
 590		return;
 591	}
 592
 593	*rcvd_assoc_resp_info_len = wid.size;
 594}
 595
 596static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
 597				      struct wilc_conn_info *ret_conn_info)
 598{
 599	u8 *ies;
 600	u16 ies_len;
 601	struct wilc_assoc_resp *res = (struct wilc_assoc_resp *)buffer;
 602
 603	ret_conn_info->status = le16_to_cpu(res->status_code);
 604	if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
 605		ies = &buffer[sizeof(*res)];
 606		ies_len = buffer_len - sizeof(*res);
 607
 608		ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
 609		if (!ret_conn_info->resp_ies)
 610			return -ENOMEM;
 611
 612		ret_conn_info->resp_ies_len = ies_len;
 613	}
 614
 615	return 0;
 616}
 617
 618static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
 619						  u8 mac_status)
 620{
 621	struct host_if_drv *hif_drv = vif->hif_drv;
 622	struct wilc_conn_info *conn_info = &hif_drv->conn_info;
 623
 624	if (mac_status == WILC_MAC_STATUS_CONNECTED) {
 625		u32 assoc_resp_info_len;
 626
 627		memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
 628
 629		host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
 630					    WILC_MAX_ASSOC_RESP_FRAME_SIZE,
 631					    &assoc_resp_info_len);
 632
 633		if (assoc_resp_info_len != 0) {
 634			s32 err = 0;
 635
 636			err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
 637							 assoc_resp_info_len,
 638							 conn_info);
 639			if (err)
 640				netdev_err(vif->ndev,
 641					   "wilc_parse_assoc_resp_info() returned error %d\n",
 642					   err);
 643		}
 644	}
 645
 646	timer_delete(&hif_drv->connect_timer);
 647	conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status,
 648			       hif_drv->conn_info.priv);
 649
 650	if (mac_status == WILC_MAC_STATUS_CONNECTED &&
 651	    conn_info->status == WLAN_STATUS_SUCCESS) {
 652		ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
 653		hif_drv->hif_state = HOST_IF_CONNECTED;
 654	} else {
 655		hif_drv->hif_state = HOST_IF_IDLE;
 656	}
 657
 658	kfree(conn_info->resp_ies);
 659	conn_info->resp_ies = NULL;
 660	conn_info->resp_ies_len = 0;
 661
 662	kfree(conn_info->req_ies);
 663	conn_info->req_ies = NULL;
 664	conn_info->req_ies_len = 0;
 665}
 666
 667void wilc_handle_disconnect(struct wilc_vif *vif)
 668{
 669	struct host_if_drv *hif_drv = vif->hif_drv;
 670
 671	if (hif_drv->usr_scan_req.scan_result) {
 672		timer_delete(&hif_drv->scan_timer);
 673		handle_scan_done(vif, SCAN_EVENT_ABORTED);
 674	}
 675
 676	if (hif_drv->conn_info.conn_result)
 677		hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
 678					       0, hif_drv->conn_info.priv);
 679
 680	eth_zero_addr(hif_drv->assoc_bssid);
 681
 682	hif_drv->conn_info.req_ies_len = 0;
 683	kfree(hif_drv->conn_info.req_ies);
 684	hif_drv->conn_info.req_ies = NULL;
 685	hif_drv->hif_state = HOST_IF_IDLE;
 686}
 687
 688static void handle_rcvd_gnrl_async_info(struct work_struct *work)
 689{
 690	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 691	struct wilc_vif *vif = msg->vif;
 692	struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
 693	struct host_if_drv *hif_drv = vif->hif_drv;
 694
 695	if (!hif_drv) {
 696		netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
 697		goto free_msg;
 698	}
 699
 700	if (!hif_drv->conn_info.conn_result) {
 701		netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 702		goto free_msg;
 703	}
 704
 705
 706        if (hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH) {
 707                cfg80211_external_auth_request(vif->ndev, &vif->auth,
 708					       GFP_KERNEL);
 709                hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
 710        } else if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
 711		host_int_parse_assoc_resp_info(vif, mac_info->status);
 712	} else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
 713		if (hif_drv->hif_state == HOST_IF_CONNECTED) {
 714			wilc_handle_disconnect(vif);
 715		} else if (hif_drv->usr_scan_req.scan_result) {
 716			timer_delete(&hif_drv->scan_timer);
 717			handle_scan_done(vif, SCAN_EVENT_ABORTED);
 718		}
 719	}
 720
 721free_msg:
 722	kfree(msg);
 723}
 724
 725int wilc_disconnect(struct wilc_vif *vif)
 726{
 727	struct wid wid;
 728	struct host_if_drv *hif_drv = vif->hif_drv;
 729	struct wilc_user_scan_req *scan_req;
 730	struct wilc_conn_info *conn_info;
 731	int result;
 732	u16 dummy_reason_code = 0;
 733
 734	wid.id = WID_DISCONNECT;
 735	wid.type = WID_CHAR;
 736	wid.val = (s8 *)&dummy_reason_code;
 737	wid.size = sizeof(char);
 738
 739	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 740	if (result) {
 741		netdev_err(vif->ndev, "Failed to send disconnect\n");
 742		return result;
 743	}
 744
 745	scan_req = &hif_drv->usr_scan_req;
 746	conn_info = &hif_drv->conn_info;
 747
 748	if (scan_req->scan_result) {
 749		timer_delete(&hif_drv->scan_timer);
 750		scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->priv);
 751		scan_req->scan_result = NULL;
 752	}
 753
 754	if (conn_info->conn_result) {
 755		if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP ||
 756		    hif_drv->hif_state == HOST_IF_EXTERNAL_AUTH)
 757			timer_delete(&hif_drv->connect_timer);
 758
 759		conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
 760				       conn_info->priv);
 761	} else {
 762		netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
 763	}
 764
 765	hif_drv->hif_state = HOST_IF_IDLE;
 766
 767	eth_zero_addr(hif_drv->assoc_bssid);
 768
 769	conn_info->req_ies_len = 0;
 770	kfree(conn_info->req_ies);
 771	conn_info->req_ies = NULL;
 772
 773	return 0;
 774}
 775
 776int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
 777{
 778	struct wid wid_list[5];
 779	u32 wid_cnt = 0, result;
 780
 781	wid_list[wid_cnt].id = WID_LINKSPEED;
 782	wid_list[wid_cnt].type = WID_CHAR;
 783	wid_list[wid_cnt].size = sizeof(char);
 784	wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
 785	wid_cnt++;
 786
 787	wid_list[wid_cnt].id = WID_RSSI;
 788	wid_list[wid_cnt].type = WID_CHAR;
 789	wid_list[wid_cnt].size = sizeof(char);
 790	wid_list[wid_cnt].val = (s8 *)&stats->rssi;
 791	wid_cnt++;
 792
 793	wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
 794	wid_list[wid_cnt].type = WID_INT;
 795	wid_list[wid_cnt].size = sizeof(u32);
 796	wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
 797	wid_cnt++;
 798
 799	wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
 800	wid_list[wid_cnt].type = WID_INT;
 801	wid_list[wid_cnt].size = sizeof(u32);
 802	wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
 803	wid_cnt++;
 804
 805	wid_list[wid_cnt].id = WID_FAILED_COUNT;
 806	wid_list[wid_cnt].type = WID_INT;
 807	wid_list[wid_cnt].size = sizeof(u32);
 808	wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
 809	wid_cnt++;
 810
 811	result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list, wid_cnt);
 812	if (result) {
 813		netdev_err(vif->ndev, "Failed to send scan parameters\n");
 814		return result;
 815	}
 816
 817	if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
 818	    stats->link_speed != DEFAULT_LINK_SPEED)
 819		wilc_enable_tcp_ack_filter(vif, true);
 820	else if (stats->link_speed != DEFAULT_LINK_SPEED)
 821		wilc_enable_tcp_ack_filter(vif, false);
 822
 823	return result;
 824}
 825
 826static void handle_get_statistics(struct work_struct *work)
 827{
 828	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 829	struct wilc_vif *vif = msg->vif;
 830	struct rf_info *stats = (struct rf_info *)msg->body.data;
 831
 832	wilc_get_statistics(vif, stats);
 833
 834	kfree(msg);
 835}
 836
 837static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
 838				    struct station_parameters *params)
 839{
 840	ether_addr_copy(cur_byte, mac);
 841	cur_byte += ETH_ALEN;
 842
 843	put_unaligned_le16(params->aid, cur_byte);
 844	cur_byte += 2;
 845
 846	*cur_byte++ = params->link_sta_params.supported_rates_len;
 847	if (params->link_sta_params.supported_rates_len > 0)
 848		memcpy(cur_byte, params->link_sta_params.supported_rates,
 849		       params->link_sta_params.supported_rates_len);
 850	cur_byte += params->link_sta_params.supported_rates_len;
 851
 852	if (params->link_sta_params.ht_capa) {
 853		*cur_byte++ = true;
 854		memcpy(cur_byte, params->link_sta_params.ht_capa,
 855		       sizeof(struct ieee80211_ht_cap));
 856	} else {
 857		*cur_byte++ = false;
 858	}
 859	cur_byte += sizeof(struct ieee80211_ht_cap);
 860
 861	put_unaligned_le16(params->sta_flags_mask, cur_byte);
 862	cur_byte += 2;
 863	put_unaligned_le16(params->sta_flags_set, cur_byte);
 864}
 865
 866static int handle_remain_on_chan(struct wilc_vif *vif,
 867				 struct wilc_remain_ch *hif_remain_ch)
 868{
 869	int result;
 870	u8 remain_on_chan_flag;
 871	struct wid wid;
 872	struct host_if_drv *hif_drv = vif->hif_drv;
 873
 874	if (hif_drv->usr_scan_req.scan_result)
 875		return -EBUSY;
 876
 877	if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
 878		return -EBUSY;
 879
 880	if (vif->connecting)
 881		return -EBUSY;
 882
 883	remain_on_chan_flag = true;
 884	wid.id = WID_REMAIN_ON_CHAN;
 885	wid.type = WID_STR;
 886	wid.size = 2;
 887	wid.val = kmalloc(wid.size, GFP_KERNEL);
 888	if (!wid.val)
 889		return -ENOMEM;
 890
 891	wid.val[0] = remain_on_chan_flag;
 892	wid.val[1] = (s8)hif_remain_ch->ch;
 893
 894	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 895	kfree(wid.val);
 896	if (result)
 897		return -EBUSY;
 898
 899	hif_drv->remain_on_ch.vif = hif_remain_ch->vif;
 900	hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
 901	hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
 902	hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
 903	hif_drv->remain_on_ch_timer_vif = vif;
 904
 905	return 0;
 906}
 907
 908static int wilc_handle_roc_expired(struct wilc_vif *vif, u64 cookie)
 909{
 910	u8 remain_on_chan_flag;
 911	struct wid wid;
 912	int result;
 913	struct host_if_drv *hif_drv = vif->hif_drv;
 914
 915	if (vif->priv.p2p_listen_state) {
 916		remain_on_chan_flag = false;
 917		wid.id = WID_REMAIN_ON_CHAN;
 918		wid.type = WID_STR;
 919		wid.size = 2;
 920
 921		wid.val = kmalloc(wid.size, GFP_KERNEL);
 922		if (!wid.val)
 923			return -ENOMEM;
 924
 925		wid.val[0] = remain_on_chan_flag;
 926		wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
 927
 928		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
 929		kfree(wid.val);
 930		if (result != 0) {
 931			netdev_err(vif->ndev, "Failed to set remain channel\n");
 932			return -EINVAL;
 933		}
 934
 935		if (hif_drv->remain_on_ch.expired) {
 936			hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.vif,
 937						      cookie);
 938		}
 939	} else {
 940		netdev_dbg(vif->ndev, "Not in listen state\n");
 941	}
 942
 943	return 0;
 944}
 945
 946static void wilc_handle_listen_state_expired(struct work_struct *work)
 947{
 948	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 949
 950	wilc_handle_roc_expired(msg->vif, msg->body.remain_on_ch.cookie);
 951	kfree(msg);
 952}
 953
 954static void listen_timer_cb(struct timer_list *t)
 955{
 956	struct host_if_drv *hif_drv = timer_container_of(hif_drv, t,
 957							 remain_on_ch_timer);
 958	struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
 959	int result;
 960	struct host_if_msg *msg;
 961
 962	timer_delete(&vif->hif_drv->remain_on_ch_timer);
 963
 964	msg = wilc_alloc_work(vif, wilc_handle_listen_state_expired, false);
 965	if (IS_ERR(msg))
 966		return;
 967
 968	msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
 969
 970	result = wilc_enqueue_work(msg);
 971	if (result) {
 972		netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
 973		kfree(msg);
 974	}
 975}
 976
 977static void handle_set_mcast_filter(struct work_struct *work)
 978{
 979	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
 980	struct wilc_vif *vif = msg->vif;
 981	struct wilc_set_multicast *set_mc = &msg->body.mc_info;
 982	int result;
 983	struct wid wid;
 984	u8 *cur_byte;
 985
 986	wid.id = WID_SETUP_MULTICAST_FILTER;
 987	wid.type = WID_BIN;
 988	wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
 989	wid.val = kmalloc(wid.size, GFP_KERNEL);
 990	if (!wid.val)
 991		goto error;
 992
 993	cur_byte = wid.val;
 994	put_unaligned_le32(set_mc->enabled, cur_byte);
 995	cur_byte += 4;
 996
 997	put_unaligned_le32(set_mc->cnt, cur_byte);
 998	cur_byte += 4;
 999
1000	if (set_mc->cnt > 0 && set_mc->mc_list)
1001		memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
1002
1003	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1004	if (result)
1005		netdev_err(vif->ndev, "Failed to send setup multicast\n");
1006
1007error:
1008	kfree(set_mc->mc_list);
1009	kfree(wid.val);
1010	kfree(msg);
1011}
1012
1013void wilc_set_wowlan_trigger(struct wilc_vif *vif, bool enabled)
1014{
1015	int ret;
1016	struct wid wid;
1017	u8 wowlan_trigger = 0;
1018
1019	if (enabled)
1020		wowlan_trigger = 1;
1021
1022	wid.id = WID_WOWLAN_TRIGGER;
1023	wid.type = WID_CHAR;
1024	wid.val = &wowlan_trigger;
1025	wid.size = sizeof(char);
1026
1027	ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1028	if (ret)
1029		pr_err("Failed to send wowlan trigger config packet\n");
1030}
1031
1032int wilc_set_external_auth_param(struct wilc_vif *vif,
1033				 struct cfg80211_external_auth_params *auth)
1034{
1035	int ret;
1036	struct wid wid;
1037	struct wilc_external_auth_param *param;
1038
1039	wid.id = WID_EXTERNAL_AUTH_PARAM;
1040	wid.type = WID_BIN_DATA;
1041	wid.size = sizeof(*param);
1042	param = kzalloc(sizeof(*param), GFP_KERNEL);
1043	if (!param)
1044		return -EINVAL;
1045
1046	wid.val = (u8 *)param;
1047	param->action = auth->action;
1048	ether_addr_copy(param->bssid, auth->bssid);
1049	memcpy(param->ssid, auth->ssid.ssid, auth->ssid.ssid_len);
1050	param->ssid_len = auth->ssid.ssid_len;
1051	ret = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1052
1053	kfree(param);
1054	return ret;
1055}
1056
1057static void handle_scan_timer(struct work_struct *work)
1058{
1059	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1060
1061	handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
1062	kfree(msg);
1063}
1064
1065static void handle_scan_complete(struct work_struct *work)
1066{
1067	struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
1068
1069	timer_delete(&msg->vif->hif_drv->scan_timer);
1070
1071	handle_scan_done(msg->vif, SCAN_EVENT_DONE);
1072
1073	kfree(msg);
1074}
1075
1076static void timer_scan_cb(struct timer_list *t)
1077{
1078	struct host_if_drv *hif_drv = timer_container_of(hif_drv, t,
1079						         scan_timer);
1080	struct wilc_vif *vif = hif_drv->scan_timer_vif;
1081	struct host_if_msg *msg;
1082	int result;
1083
1084	msg = wilc_alloc_work(vif, handle_scan_timer, false);
1085	if (IS_ERR(msg))
1086		return;
1087
1088	result = wilc_enqueue_work(msg);
1089	if (result)
1090		kfree(msg);
1091}
1092
1093static void timer_connect_cb(struct timer_list *t)
1094{
1095	struct host_if_drv *hif_drv = timer_container_of(hif_drv, t,
1096						         connect_timer);
1097	struct wilc_vif *vif = hif_drv->connect_timer_vif;
1098	struct host_if_msg *msg;
1099	int result;
1100
1101	msg = wilc_alloc_work(vif, handle_connect_timeout, false);
1102	if (IS_ERR(msg))
1103		return;
1104
1105	result = wilc_enqueue_work(msg);
1106	if (result)
1107		kfree(msg);
1108}
1109
1110int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
1111		 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
1112		 u8 mode, u8 cipher_mode, u8 index)
1113{
1114	int result = 0;
1115	u8 t_key_len  = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1116
1117	if (mode == WILC_AP_MODE) {
1118		struct wid wid_list[2];
1119		struct wilc_ap_wpa_ptk *key_buf;
1120
1121		wid_list[0].id = WID_11I_MODE;
1122		wid_list[0].type = WID_CHAR;
1123		wid_list[0].size = sizeof(char);
1124		wid_list[0].val = (s8 *)&cipher_mode;
1125
1126		key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1127		if (!key_buf)
1128			return -ENOMEM;
1129
1130		ether_addr_copy(key_buf->mac_addr, mac_addr);
1131		key_buf->index = index;
1132		key_buf->key_len = t_key_len;
1133		memcpy(&key_buf->key[0], ptk, ptk_key_len);
1134
1135		if (rx_mic)
1136			memcpy(&key_buf->key[ptk_key_len], rx_mic,
1137			       WILC_RX_MIC_KEY_LEN);
1138
1139		if (tx_mic)
1140			memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1141			       tx_mic, WILC_TX_MIC_KEY_LEN);
1142
1143		wid_list[1].id = WID_ADD_PTK;
1144		wid_list[1].type = WID_STR;
1145		wid_list[1].size = sizeof(*key_buf) + t_key_len;
1146		wid_list[1].val = (u8 *)key_buf;
1147		result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1148					      ARRAY_SIZE(wid_list));
1149		kfree(key_buf);
1150	} else if (mode == WILC_STATION_MODE) {
1151		struct wid wid;
1152		struct wilc_sta_wpa_ptk *key_buf;
1153
1154		key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1155		if (!key_buf)
1156			return -ENOMEM;
1157
1158		ether_addr_copy(key_buf->mac_addr, mac_addr);
1159		key_buf->key_len = t_key_len;
1160		memcpy(&key_buf->key[0], ptk, ptk_key_len);
1161
1162		if (rx_mic)
1163			memcpy(&key_buf->key[ptk_key_len], rx_mic,
1164			       WILC_RX_MIC_KEY_LEN);
1165
1166		if (tx_mic)
1167			memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1168			       tx_mic, WILC_TX_MIC_KEY_LEN);
1169
1170		wid.id = WID_ADD_PTK;
1171		wid.type = WID_STR;
1172		wid.size = sizeof(*key_buf) + t_key_len;
1173		wid.val = (s8 *)key_buf;
1174		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1175		kfree(key_buf);
1176	}
1177
1178	return result;
1179}
1180
1181int wilc_add_igtk(struct wilc_vif *vif, const u8 *igtk, u8 igtk_key_len,
1182		  const u8 *pn, u8 pn_len, const u8 *mac_addr, u8 mode, u8 index)
1183{
1184	int result = 0;
1185	u8 t_key_len = igtk_key_len;
1186	struct wid wid;
1187	struct wilc_wpa_igtk *key_buf;
1188
1189	key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1190	if (!key_buf)
1191		return -ENOMEM;
1192
1193	key_buf->index = index;
1194
1195	memcpy(&key_buf->pn[0], pn, pn_len);
1196	key_buf->pn_len = pn_len;
1197
1198	memcpy(&key_buf->key[0], igtk, igtk_key_len);
1199	key_buf->key_len = t_key_len;
1200
1201	wid.id = WID_ADD_IGTK;
1202	wid.type = WID_STR;
1203	wid.size = sizeof(*key_buf) + t_key_len;
1204	wid.val = (s8 *)key_buf;
1205	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1206	kfree(key_buf);
1207
1208	return result;
1209}
1210
1211int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
1212		    u8 index, u32 key_rsc_len, const u8 *key_rsc,
1213		    const u8 *rx_mic, const u8 *tx_mic, u8 mode,
1214		    u8 cipher_mode)
1215{
1216	int result = 0;
1217	struct wilc_gtk_key *gtk_key;
1218	int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
1219
1220	gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
1221	if (!gtk_key)
1222		return -ENOMEM;
1223
1224	/* fill bssid value only in station mode */
1225	if (mode == WILC_STATION_MODE &&
1226	    vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1227		memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
1228
1229	if (key_rsc)
1230		memcpy(gtk_key->rsc, key_rsc, 8);
1231	gtk_key->index = index;
1232	gtk_key->key_len = t_key_len;
1233	memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
1234
1235	if (rx_mic)
1236		memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
1237
1238	if (tx_mic)
1239		memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
1240		       tx_mic, WILC_TX_MIC_KEY_LEN);
1241
1242	if (mode == WILC_AP_MODE) {
1243		struct wid wid_list[2];
1244
1245		wid_list[0].id = WID_11I_MODE;
1246		wid_list[0].type = WID_CHAR;
1247		wid_list[0].size = sizeof(char);
1248		wid_list[0].val = (s8 *)&cipher_mode;
1249
1250		wid_list[1].id = WID_ADD_RX_GTK;
1251		wid_list[1].type = WID_STR;
1252		wid_list[1].size = sizeof(*gtk_key) + t_key_len;
1253		wid_list[1].val = (u8 *)gtk_key;
1254
1255		result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
1256					      ARRAY_SIZE(wid_list));
1257	} else if (mode == WILC_STATION_MODE) {
1258		struct wid wid;
1259
1260		wid.id = WID_ADD_RX_GTK;
1261		wid.type = WID_STR;
1262		wid.size = sizeof(*gtk_key) + t_key_len;
1263		wid.val = (u8 *)gtk_key;
1264		result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1265	}
1266
1267	kfree(gtk_key);
1268	return result;
1269}
1270
1271int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
1272{
1273	struct wid wid;
1274
1275	wid.id = WID_PMKID_INFO;
1276	wid.type = WID_STR;
1277	wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
1278	wid.val = (u8 *)pmkid;
1279
1280	return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1281}
1282
1283int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
1284{
1285	int result;
1286	struct wid wid;
1287
1288	wid.id = WID_MAC_ADDR;
1289	wid.type = WID_STR;
1290	wid.size = ETH_ALEN;
1291	wid.val = mac_addr;
1292
1293	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1294	if (result)
1295		netdev_err(vif->ndev, "Failed to get mac address\n");
1296
1297	return result;
1298}
1299
1300int wilc_set_mac_address(struct wilc_vif *vif, const u8 *mac_addr)
1301{
1302	struct wid wid;
1303	int result;
1304
1305	wid.id = WID_MAC_ADDR;
1306	wid.type = WID_STR;
1307	wid.size = ETH_ALEN;
1308	wid.val = (u8 *)mac_addr;
1309
1310	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1311	if (result)
1312		netdev_err(vif->ndev, "Failed to set mac address\n");
1313
1314	return result;
1315}
1316
1317int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
1318		      size_t ies_len)
1319{
1320	int result;
1321	struct host_if_drv *hif_drv = vif->hif_drv;
1322	struct wilc_conn_info *conn_info = &hif_drv->conn_info;
1323
1324	if (bssid)
1325		ether_addr_copy(conn_info->bssid, bssid);
1326
1327	if (ies) {
1328		conn_info->req_ies_len = ies_len;
1329		conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
1330		if (!conn_info->req_ies)
1331			return -ENOMEM;
1332	}
1333
1334	result = wilc_send_connect_wid(vif);
1335	if (result)
1336		goto free_ies;
1337
1338	hif_drv->connect_timer_vif = vif;
1339	mod_timer(&hif_drv->connect_timer,
1340		  jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
1341
1342	return 0;
1343
1344free_ies:
1345	kfree(conn_info->req_ies);
1346
1347	return result;
1348}
1349
1350int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
1351{
1352	struct wid wid;
1353	int result;
1354
1355	wid.id = WID_CURRENT_CHANNEL;
1356	wid.type = WID_CHAR;
1357	wid.size = sizeof(char);
1358	wid.val = &channel;
1359
1360	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1361	if (result)
1362		netdev_err(vif->ndev, "Failed to set channel\n");
1363
1364	return result;
1365}
1366
1367int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode,
1368			    u8 ifc_id)
1369{
1370	struct wid wid;
1371	int result;
1372	struct wilc_drv_handler drv;
1373
1374	wid.id = WID_SET_OPERATION_MODE;
1375	wid.type = WID_STR;
1376	wid.size = sizeof(drv);
1377	wid.val = (u8 *)&drv;
1378
1379	drv.handler = cpu_to_le32(index);
1380	drv.mode = (ifc_id | (mode << 1));
1381
1382	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1383	if (result)
1384		netdev_err(vif->ndev, "Failed to set driver handler\n");
1385
1386	return result;
1387}
1388
1389s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
1390{
1391	struct wid wid;
1392	s32 result;
1393
1394	wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
1395	wid.type = WID_STR;
1396	wid.size = ETH_ALEN;
1397	wid.val = kzalloc(wid.size, GFP_KERNEL);
1398	if (!wid.val)
1399		return -ENOMEM;
1400
1401	ether_addr_copy(wid.val, mac);
1402	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1403	kfree(wid.val);
1404	if (result) {
1405		netdev_err(vif->ndev, "Failed to set inactive mac\n");
1406		return result;
1407	}
1408
1409	wid.id = WID_GET_INACTIVE_TIME;
1410	wid.type = WID_INT;
1411	wid.val = (s8 *)out_val;
1412	wid.size = sizeof(u32);
1413	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1414	if (result)
1415		netdev_err(vif->ndev, "Failed to get inactive time\n");
1416
1417	return result;
1418}
1419
1420int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
1421{
1422	struct wid wid;
1423	int result;
1424
1425	if (!rssi_level) {
1426		netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
1427		return -EFAULT;
1428	}
1429
1430	wid.id = WID_RSSI;
1431	wid.type = WID_CHAR;
1432	wid.size = sizeof(char);
1433	wid.val = rssi_level;
1434	result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
1435	if (result)
1436		netdev_err(vif->ndev, "Failed to get RSSI value\n");
1437
1438	return result;
1439}
1440
1441static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
1442{
1443	int result;
1444	struct host_if_msg *msg;
1445
1446	msg = wilc_alloc_work(vif, handle_get_statistics, false);
1447	if (IS_ERR(msg))
1448		return PTR_ERR(msg);
1449
1450	msg->body.data = (char *)stats;
1451
1452	result = wilc_enqueue_work(msg);
1453	if (result) {
1454		netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1455		kfree(msg);
1456		return result;
1457	}
1458
1459	return result;
1460}
1461
1462int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
1463{
1464	struct wid wid_list[4];
1465	int i = 0;
1466
1467	if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
1468		wid_list[i].id = WID_SHORT_RETRY_LIMIT;
1469		wid_list[i].val = (s8 *)&param->short_retry_limit;
1470		wid_list[i].type = WID_SHORT;
1471		wid_list[i].size = sizeof(u16);
1472		i++;
1473	}
1474	if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
1475		wid_list[i].id = WID_LONG_RETRY_LIMIT;
1476		wid_list[i].val = (s8 *)&param->long_retry_limit;
1477		wid_list[i].type = WID_SHORT;
1478		wid_list[i].size = sizeof(u16);
1479		i++;
1480	}
1481	if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
1482		wid_list[i].id = WID_FRAG_THRESHOLD;
1483		wid_list[i].val = (s8 *)&param->frag_threshold;
1484		wid_list[i].type = WID_SHORT;
1485		wid_list[i].size = sizeof(u16);
1486		i++;
1487	}
1488	if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
1489		wid_list[i].id = WID_RTS_THRESHOLD;
1490		wid_list[i].val = (s8 *)&param->rts_threshold;
1491		wid_list[i].type = WID_SHORT;
1492		wid_list[i].size = sizeof(u16);
1493		i++;
1494	}
1495
1496	return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, i);
1497}
1498
1499static void get_periodic_rssi(struct timer_list *t)
1500{
1501	struct wilc_vif *vif = timer_container_of(vif, t, periodic_rssi);
1502
1503	if (!vif->hif_drv) {
1504		netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1505		return;
1506	}
1507
1508	if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1509		wilc_get_stats_async(vif, &vif->periodic_stat);
1510
1511	mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1512}
1513
1514int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
1515{
1516	struct host_if_drv *hif_drv;
1517	struct wilc_vif *vif = netdev_priv(dev);
1518
1519	hif_drv  = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
1520	if (!hif_drv)
1521		return -ENOMEM;
1522
1523	*hif_drv_handler = hif_drv;
1524
1525	vif->hif_drv = hif_drv;
1526
1527	timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
1528	mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1529
1530	timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
1531	timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
1532	timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
1533
1534	hif_drv->hif_state = HOST_IF_IDLE;
1535
1536	hif_drv->p2p_timeout = 0;
1537
1538	return 0;
1539}
1540
1541int wilc_deinit(struct wilc_vif *vif)
1542{
1543	int result = 0;
1544	struct host_if_drv *hif_drv = vif->hif_drv;
1545
1546	if (!hif_drv) {
1547		netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1548		return -EFAULT;
1549	}
1550
1551	mutex_lock(&vif->wilc->deinit_lock);
1552
1553	timer_shutdown_sync(&hif_drv->scan_timer);
1554	timer_shutdown_sync(&hif_drv->connect_timer);
1555	timer_delete_sync(&vif->periodic_rssi);
1556	timer_shutdown_sync(&hif_drv->remain_on_ch_timer);
1557
1558	if (hif_drv->usr_scan_req.scan_result) {
1559		hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
1560						  hif_drv->usr_scan_req.priv);
1561		hif_drv->usr_scan_req.scan_result = NULL;
1562	}
1563
1564	hif_drv->hif_state = HOST_IF_IDLE;
1565
1566	kfree(hif_drv);
1567	vif->hif_drv = NULL;
1568	mutex_unlock(&vif->wilc->deinit_lock);
1569	return result;
1570}
1571
1572void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1573{
1574	struct host_if_drv *hif_drv;
1575	struct host_if_msg *msg;
1576	struct wilc_vif *vif;
1577	int srcu_idx;
1578	int result;
1579	int id;
1580
1581	id = get_unaligned_le32(&buffer[length - 4]);
1582	srcu_idx = srcu_read_lock(&wilc->srcu);
1583	vif = wilc_get_vif_from_idx(wilc, id);
1584	if (!vif)
1585		goto out;
1586
1587	hif_drv = vif->hif_drv;
1588	if (!hif_drv) {
1589		netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
1590		goto out;
1591	}
1592
1593	msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
1594	if (IS_ERR(msg))
1595		goto out;
1596
1597	msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
1598	msg->body.net_info.rssi = buffer[8];
1599	msg->body.net_info.mgmt = kmemdup(&buffer[9],
1600					  msg->body.net_info.frame_len,
1601					  GFP_KERNEL);
1602	if (!msg->body.net_info.mgmt) {
1603		kfree(msg);
1604		goto out;
1605	}
1606
1607	result = wilc_enqueue_work(msg);
1608	if (result) {
1609		netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1610		kfree(msg->body.net_info.mgmt);
1611		kfree(msg);
1612	}
1613out:
1614	srcu_read_unlock(&wilc->srcu, srcu_idx);
1615}
1616
1617void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
1618{
1619	struct host_if_drv *hif_drv;
1620	struct host_if_msg *msg;
1621	struct wilc_vif *vif;
1622	int srcu_idx;
1623	int result;
1624	int id;
1625
1626	mutex_lock(&wilc->deinit_lock);
1627
1628	id = get_unaligned_le32(&buffer[length - 4]);
1629	srcu_idx = srcu_read_lock(&wilc->srcu);
1630	vif = wilc_get_vif_from_idx(wilc, id);
1631	if (!vif)
1632		goto out;
1633
1634	hif_drv = vif->hif_drv;
1635
1636	if (!hif_drv) {
1637		goto out;
1638	}
1639
1640	if (!hif_drv->conn_info.conn_result) {
1641		netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
1642		goto out;
1643	}
1644
1645	msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
1646	if (IS_ERR(msg))
1647		goto out;
1648
1649	msg->body.mac_info.status = buffer[7];
1650	result = wilc_enqueue_work(msg);
1651	if (result) {
1652		netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1653		kfree(msg);
1654	}
1655out:
1656	srcu_read_unlock(&wilc->srcu, srcu_idx);
1657	mutex_unlock(&wilc->deinit_lock);
1658}
1659
1660void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
1661{
1662	struct host_if_drv *hif_drv;
1663	struct wilc_vif *vif;
1664	int srcu_idx;
1665	int result;
1666	int id;
1667
1668	id = get_unaligned_le32(&buffer[length - 4]);
1669	srcu_idx = srcu_read_lock(&wilc->srcu);
1670	vif = wilc_get_vif_from_idx(wilc, id);
1671	if (!vif)
1672		goto out;
1673
1674	hif_drv = vif->hif_drv;
1675	if (!hif_drv) {
1676		goto out;
1677	}
1678
1679	if (hif_drv->usr_scan_req.scan_result) {
1680		struct host_if_msg *msg;
1681
1682		msg = wilc_alloc_work(vif, handle_scan_complete, false);
1683		if (IS_ERR(msg))
1684			goto out;
1685
1686		result = wilc_enqueue_work(msg);
1687		if (result) {
1688			netdev_err(vif->ndev, "%s: enqueue work failed\n",
1689				   __func__);
1690			kfree(msg);
1691		}
1692	}
1693out:
1694	srcu_read_unlock(&wilc->srcu, srcu_idx);
1695}
1696
1697int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie, u16 chan,
1698			   void (*expired)(struct wilc_vif *, u64))
1699{
1700	struct wilc_remain_ch roc;
1701	int result;
1702
1703	roc.ch = chan;
1704	roc.expired = expired;
1705	roc.vif = vif;
1706	roc.cookie = cookie;
1707	result = handle_remain_on_chan(vif, &roc);
1708	if (result)
1709		netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
1710			   __func__);
1711
1712	return result;
1713}
1714
1715int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
1716{
1717	if (!vif->hif_drv) {
1718		netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
1719		return -EFAULT;
1720	}
1721
1722	timer_delete(&vif->hif_drv->remain_on_ch_timer);
1723
1724	return wilc_handle_roc_expired(vif, cookie);
1725}
1726
1727void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
1728{
1729	struct wid wid;
1730	int result;
1731	struct wilc_reg_frame reg_frame;
1732
1733	wid.id = WID_REGISTER_FRAME;
1734	wid.type = WID_STR;
1735	wid.size = sizeof(reg_frame);
1736	wid.val = (u8 *)&reg_frame;
1737
1738	memset(&reg_frame, 0x0, sizeof(reg_frame));
1739
1740	if (reg)
1741		reg_frame.reg = 1;
1742
1743	switch (frame_type) {
1744	case IEEE80211_STYPE_ACTION:
1745		reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
1746		break;
1747
1748	case IEEE80211_STYPE_PROBE_REQ:
1749		reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
1750		break;
1751
1752        case IEEE80211_STYPE_AUTH:
1753                reg_frame.reg_id = WILC_FW_AUTH_REQ_IDX;
1754                break;
1755
1756	default:
1757		break;
1758	}
1759	reg_frame.frame_type = cpu_to_le16(frame_type);
1760	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1761	if (result)
1762		netdev_err(vif->ndev, "Failed to frame register\n");
1763}
1764
1765int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
1766		    struct cfg80211_beacon_data *params)
1767{
1768	struct wid wid;
1769	int result;
1770	u8 *cur_byte;
1771
1772	wid.id = WID_ADD_BEACON;
1773	wid.type = WID_BIN;
1774	wid.size = params->head_len + params->tail_len + 16;
1775	wid.val = kzalloc(wid.size, GFP_KERNEL);
1776	if (!wid.val)
1777		return -ENOMEM;
1778
1779	cur_byte = wid.val;
1780	put_unaligned_le32(interval, cur_byte);
1781	cur_byte += 4;
1782	put_unaligned_le32(dtim_period, cur_byte);
1783	cur_byte += 4;
1784	put_unaligned_le32(params->head_len, cur_byte);
1785	cur_byte += 4;
1786
1787	if (params->head_len > 0)
1788		memcpy(cur_byte, params->head, params->head_len);
1789	cur_byte += params->head_len;
1790
1791	put_unaligned_le32(params->tail_len, cur_byte);
1792	cur_byte += 4;
1793
1794	if (params->tail_len > 0)
1795		memcpy(cur_byte, params->tail, params->tail_len);
1796
1797	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1798	if (result)
1799		netdev_err(vif->ndev, "Failed to send add beacon\n");
1800
1801	kfree(wid.val);
1802
1803	return result;
1804}
1805
1806int wilc_del_beacon(struct wilc_vif *vif)
1807{
1808	int result;
1809	struct wid wid;
1810	u8 del_beacon = 0;
1811
1812	wid.id = WID_DEL_BEACON;
1813	wid.type = WID_CHAR;
1814	wid.size = sizeof(char);
1815	wid.val = &del_beacon;
1816
1817	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1818	if (result)
1819		netdev_err(vif->ndev, "Failed to send delete beacon\n");
1820
1821	return result;
1822}
1823
1824int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
1825		     struct station_parameters *params)
1826{
1827	struct wid wid;
1828	int result;
1829	u8 *cur_byte;
1830
1831	wid.id = WID_ADD_STA;
1832	wid.type = WID_BIN;
1833	wid.size = WILC_ADD_STA_LENGTH +
1834		   params->link_sta_params.supported_rates_len;
1835	wid.val = kmalloc(wid.size, GFP_KERNEL);
1836	if (!wid.val)
1837		return -ENOMEM;
1838
1839	cur_byte = wid.val;
1840	wilc_hif_pack_sta_param(cur_byte, mac, params);
1841
1842	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1843	if (result != 0)
1844		netdev_err(vif->ndev, "Failed to send add station\n");
1845
1846	kfree(wid.val);
1847
1848	return result;
1849}
1850
1851int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
1852{
1853	struct wid wid;
1854	int result;
1855
1856	wid.id = WID_REMOVE_STA;
1857	wid.type = WID_BIN;
1858	wid.size = ETH_ALEN;
1859	wid.val = kzalloc(wid.size, GFP_KERNEL);
1860	if (!wid.val)
1861		return -ENOMEM;
1862
1863	if (!mac_addr)
1864		eth_broadcast_addr(wid.val);
1865	else
1866		ether_addr_copy(wid.val, mac_addr);
1867
1868	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1869	if (result)
1870		netdev_err(vif->ndev, "Failed to del station\n");
1871
1872	kfree(wid.val);
1873
1874	return result;
1875}
1876
1877int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
1878{
1879	struct wid wid;
1880	int result;
1881	int i;
1882	u8 assoc_sta = 0;
1883	struct wilc_del_all_sta del_sta;
1884
1885	memset(&del_sta, 0x0, sizeof(del_sta));
1886	for (i = 0; i < WILC_MAX_NUM_STA; i++) {
1887		if (!is_zero_ether_addr(mac_addr[i])) {
1888			assoc_sta++;
1889			ether_addr_copy(del_sta.mac[i], mac_addr[i]);
1890		}
1891	}
1892
1893	if (!assoc_sta)
1894		return 0;
1895
1896	del_sta.assoc_sta = assoc_sta;
1897
1898	wid.id = WID_DEL_ALL_STA;
1899	wid.type = WID_STR;
1900	wid.size = (assoc_sta * ETH_ALEN) + 1;
1901	wid.val = (u8 *)&del_sta;
1902
1903	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1904	if (result)
1905		netdev_err(vif->ndev, "Failed to send delete all station\n");
1906
1907	return result;
1908}
1909
1910int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
1911		      struct station_parameters *params)
1912{
1913	struct wid wid;
1914	int result;
1915	u8 *cur_byte;
1916
1917	wid.id = WID_EDIT_STA;
1918	wid.type = WID_BIN;
1919	wid.size = WILC_ADD_STA_LENGTH +
1920		   params->link_sta_params.supported_rates_len;
1921	wid.val = kmalloc(wid.size, GFP_KERNEL);
1922	if (!wid.val)
1923		return -ENOMEM;
1924
1925	cur_byte = wid.val;
1926	wilc_hif_pack_sta_param(cur_byte, mac, params);
1927
1928	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1929	if (result)
1930		netdev_err(vif->ndev, "Failed to send edit station\n");
1931
1932	kfree(wid.val);
1933	return result;
1934}
1935
1936int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
1937{
1938	struct wilc *wilc = vif->wilc;
1939	struct wid wid;
1940	int result;
1941	s8 power_mode;
1942
1943	if (enabled)
1944		power_mode = WILC_FW_MIN_FAST_PS;
1945	else
1946		power_mode = WILC_FW_NO_POWERSAVE;
1947
1948	wid.id = WID_POWER_MANAGEMENT;
1949	wid.val = &power_mode;
1950	wid.size = sizeof(char);
1951	result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1952	if (result)
1953		netdev_err(vif->ndev, "Failed to send power management\n");
1954	else
1955		wilc->power_save_mode = enabled;
1956
1957	return result;
1958}
1959
1960int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
1961				u8 *mc_list)
1962{
1963	int result;
1964	struct host_if_msg *msg;
1965
1966	msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
1967	if (IS_ERR(msg))
1968		return PTR_ERR(msg);
1969
1970	msg->body.mc_info.enabled = enabled;
1971	msg->body.mc_info.cnt = count;
1972	msg->body.mc_info.mc_list = mc_list;
1973
1974	result = wilc_enqueue_work(msg);
1975	if (result) {
1976		netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
1977		kfree(msg);
1978	}
1979	return result;
1980}
1981
1982int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
1983{
1984	struct wid wid;
1985
1986	wid.id = WID_TX_POWER;
1987	wid.type = WID_CHAR;
1988	wid.val = &tx_power;
1989	wid.size = sizeof(char);
1990
1991	return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
1992}
1993
1994int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
1995{
1996	struct wid wid;
1997
1998	wid.id = WID_TX_POWER;
1999	wid.type = WID_CHAR;
2000	wid.val = tx_power;
2001	wid.size = sizeof(char);
2002
2003	return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
2004}
2005
2006int wilc_set_default_mgmt_key_index(struct wilc_vif *vif, u8 index)
2007{
2008        struct wid wid;
2009        int result;
2010
2011        wid.id = WID_DEFAULT_MGMT_KEY_ID;
2012        wid.type = WID_CHAR;
2013        wid.size = sizeof(char);
2014        wid.val = &index;
2015        result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
2016        if (result)
2017                netdev_err(vif->ndev,
2018                           "Failed to send default mgmt key index\n");
2019
2020        return result;
2021}
~/ Read-only file preview.