cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hif.c (48827B)


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