blob: d025a30930157ae694b97a2db276dc97a13adddf [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Ajay Singhe61c7a12018-08-03 16:26:13 +05302/*
3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
4 * All rights reserved.
5 */
6
Ajay Singh6cecbb22019-11-05 09:51:25 +00007#include "netdev.h"
Johnny Kimc5c77ba2015-05-11 14:30:56 +09008
Adham Abozaeidf5a3cb92019-06-20 19:54:55 +00009#define WILC_HIF_SCAN_TIMEOUT_MS 5000
Ajay Singhb36b9732019-02-02 19:17:05 +000010#define WILC_HIF_CONNECT_TIMEOUT_MS 9500
Johnny Kimc5c77ba2015-05-11 14:30:56 +090011
Ajay Singhf5436ed2019-02-07 11:29:01 +000012#define WILC_FALSE_FRMWR_CHANNEL 100
Johnny Kimc5c77ba2015-05-11 14:30:56 +090013
Oscar Cartera4338ed2020-05-04 17:09:11 +020014#define WILC_SCAN_WID_LIST_SIZE 6
15
Ajay Singh94bb6d32019-01-17 13:21:35 +000016struct wilc_rcvd_mac_info {
17 u8 status;
Tony Chof23a9ea2015-09-21 12:16:39 +090018};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090019
Ajay Singha0c6a322019-01-17 13:21:41 +000020struct wilc_set_multicast {
21 u32 enabled;
Leo Kimadab2f72015-10-13 20:02:05 +090022 u32 cnt;
Ajay Singhe624c582018-09-04 12:09:26 +053023 u8 *mc_list;
Tony Cho641210a2015-09-21 12:16:52 +090024};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090025
Ajay Singhf5436ed2019-02-07 11:29:01 +000026struct wilc_del_all_sta {
Leo Kim8ba18032015-10-13 19:50:10 +090027 u8 assoc_sta;
Ajay Singh9f1bdb72018-12-02 18:02:40 +000028 u8 mac[WILC_MAX_NUM_STA][ETH_ALEN];
Tony Chofb93a1e2015-09-21 12:16:57 +090029};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090030
Ajay Singhf5436ed2019-02-07 11:29:01 +000031union wilc_message_body {
Ajay Singh6cd4fa52019-01-17 13:21:21 +000032 struct wilc_rcvd_net_info net_info;
Ajay Singh94bb6d32019-01-17 13:21:35 +000033 struct wilc_rcvd_mac_info mac_info;
Ajay Singha0c6a322019-01-17 13:21:41 +000034 struct wilc_set_multicast mc_info;
Ajay Singhf5436ed2019-02-07 11:29:01 +000035 struct wilc_remain_ch remain_on_ch;
Tony Choe60831e2015-10-05 13:50:45 +090036 char *data;
Tony Chodfc76632015-09-21 12:16:34 +090037};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090038
Tony Cho3a8c41b2015-09-18 18:11:04 +090039struct host_if_msg {
Ajay Singhf5436ed2019-02-07 11:29:01 +000040 union wilc_message_body body;
Glen Leecf601062015-12-21 14:18:39 +090041 struct wilc_vif *vif;
Binoy Jayan2518ac52016-06-23 11:11:51 +053042 struct work_struct work;
Ajay Singh7233be32018-06-26 11:37:03 +053043 void (*fn)(struct work_struct *ws);
Ajay Singh5e6f8a82018-06-26 11:37:06 +053044 struct completion work_comp;
45 bool is_sync;
Tony Cho3a8c41b2015-09-18 18:11:04 +090046};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090047
Ajay Singh5e6f8a82018-06-26 11:37:06 +053048/* 'msg' should be free by the caller for syc */
Ajay Singhff52a572018-06-26 11:37:05 +053049static struct host_if_msg*
Ajay Singh5e6f8a82018-06-26 11:37:06 +053050wilc_alloc_work(struct wilc_vif *vif, void (*work_fun)(struct work_struct *),
51 bool is_sync)
Ajay Singhff52a572018-06-26 11:37:05 +053052{
53 struct host_if_msg *msg;
54
55 if (!work_fun)
56 return ERR_PTR(-EINVAL);
57
58 msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
59 if (!msg)
60 return ERR_PTR(-ENOMEM);
61 msg->fn = work_fun;
62 msg->vif = vif;
Ajay Singh5e6f8a82018-06-26 11:37:06 +053063 msg->is_sync = is_sync;
64 if (is_sync)
65 init_completion(&msg->work_comp);
Ajay Singhff52a572018-06-26 11:37:05 +053066
67 return msg;
68}
69
Ajay Singhc6a358d2018-06-26 11:37:08 +053070static int wilc_enqueue_work(struct host_if_msg *msg)
Binoy Jayanc6bb38a2016-06-23 11:11:50 +053071{
Ajay Singhff52a572018-06-26 11:37:05 +053072 INIT_WORK(&msg->work, msg->fn);
Ajay Singh87de37f2018-09-04 12:09:27 +053073
74 if (!msg->vif || !msg->vif->wilc || !msg->vif->wilc->hif_workqueue)
75 return -EINVAL;
76
77 if (!queue_work(msg->vif->wilc->hif_workqueue, &msg->work))
Ajay Singhff52a572018-06-26 11:37:05 +053078 return -EINVAL;
Binoy Jayanc6bb38a2016-06-23 11:11:50 +053079
Binoy Jayanc6bb38a2016-06-23 11:11:50 +053080 return 0;
81}
82
Ajay Singhf131bbe2018-07-29 11:36:51 +053083/* The idx starts from 0 to (NUM_CONCURRENT_IFC - 1), but 0 index used as
Glen Leeeb9939b2015-12-21 14:18:43 +090084 * special purpose in wilc device, so we add 1 to the index to starts from 1.
85 * As a result, the returned index will be 1 to NUM_CONCURRENT_IFC.
86 */
Glen Lee31f0f692015-12-21 14:18:44 +090087int wilc_get_vif_idx(struct wilc_vif *vif)
Johnny Kimd42ab082015-08-20 16:32:52 +090088{
Leo Kim67501402016-02-04 18:15:39 +090089 return vif->idx + 1;
Glen Leeeb9939b2015-12-21 14:18:43 +090090}
91
92/* We need to minus 1 from idx which is from wilc device to get real index
93 * of wilc->vif[], because we add 1 when pass to wilc device in the function
94 * wilc_get_vif_idx.
Ajay Singhf131bbe2018-07-29 11:36:51 +053095 * As a result, the index should be between 0 and (NUM_CONCURRENT_IFC - 1).
Glen Leeeb9939b2015-12-21 14:18:43 +090096 */
97static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx)
98{
99 int index = idx - 1;
Ajay Singh83999182019-09-26 15:14:59 +0000100 struct wilc_vif *vif;
Glen Leeeb9939b2015-12-21 14:18:43 +0900101
Ajay Singhd0e41ef2018-11-12 05:45:29 +0000102 if (index < 0 || index >= WILC_NUM_CONCURRENT_IFC)
Johnny Kimd42ab082015-08-20 16:32:52 +0900103 return NULL;
Glen Leeeb9939b2015-12-21 14:18:43 +0900104
Ajay Singh83999182019-09-26 15:14:59 +0000105 list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
106 if (vif->idx == index)
107 return vif;
108 }
109
110 return NULL;
Johnny Kimd42ab082015-08-20 16:32:52 +0900111}
112
Ajay Singh82120ec2018-07-19 04:15:17 +0530113static int handle_scan_done(struct wilc_vif *vif, enum scan_event evt)
Ajay Singh2653aad2018-07-19 04:15:13 +0530114{
Ajay Singh82120ec2018-07-19 04:15:17 +0530115 int result = 0;
Ajay Singh2653aad2018-07-19 04:15:13 +0530116 u8 abort_running_scan;
117 struct wid wid;
118 struct host_if_drv *hif_drv = vif->hif_drv;
Ajay Singhf5436ed2019-02-07 11:29:01 +0000119 struct wilc_user_scan_req *scan_req;
Ajay Singh2653aad2018-07-19 04:15:13 +0530120
121 if (evt == SCAN_EVENT_ABORTED) {
122 abort_running_scan = 1;
123 wid.id = WID_ABORT_RUNNING_SCAN;
124 wid.type = WID_CHAR;
125 wid.val = (s8 *)&abort_running_scan;
126 wid.size = sizeof(char);
127
Ajay Singh93592a62019-06-26 12:41:04 +0000128 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh2653aad2018-07-19 04:15:13 +0530129 if (result) {
130 netdev_err(vif->ndev, "Failed to set abort running\n");
131 result = -EFAULT;
132 }
133 }
134
135 if (!hif_drv) {
Ajay Singha120adb82018-07-29 11:36:53 +0530136 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
Ajay Singh2653aad2018-07-19 04:15:13 +0530137 return result;
138 }
139
140 scan_req = &hif_drv->usr_scan_req;
141 if (scan_req->scan_result) {
Ajay Singh6c2cfb42019-01-17 13:21:18 +0000142 scan_req->scan_result(evt, NULL, scan_req->arg);
Ajay Singh2653aad2018-07-19 04:15:13 +0530143 scan_req->scan_result = NULL;
144 }
145
146 return result;
147}
148
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000149int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type,
Adham Abozaeidac118d82019-03-25 22:27:26 +0000150 u8 *ch_freq_list, u8 ch_list_len,
Ajay Singh65af8872019-01-17 13:21:44 +0000151 void (*scan_result_fn)(enum scan_event,
152 struct wilc_rcvd_net_info *, void *),
Adham Abozaeidac118d82019-03-25 22:27:26 +0000153 void *user_arg, struct cfg80211_scan_request *request)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900154{
Ajay Singh82120ec2018-07-19 04:15:17 +0530155 int result = 0;
Oscar Cartera4338ed2020-05-04 17:09:11 +0200156 struct wid wid_list[WILC_SCAN_WID_LIST_SIZE];
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900157 u32 index = 0;
Adham Abozaeidf5a3cb92019-06-20 19:54:55 +0000158 u32 i, scan_timeout;
Chaehyun Lim2f27ad12016-04-04 20:04:50 +0900159 u8 *buffer;
Greg Kroah-Hartman63d03e42015-06-02 14:16:04 +0900160 u8 valuesize = 0;
Ajay Singhf47e59e2019-01-17 13:21:30 +0000161 u8 *search_ssid_vals = NULL;
Glen Lee71130e82015-12-21 14:18:41 +0900162 struct host_if_drv *hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900163
Ajay Singh7bf02422018-01-22 15:52:14 +0530164 if (hif_drv->hif_state >= HOST_IF_SCANNING &&
165 hif_drv->hif_state < HOST_IF_CONNECTED) {
Chris Parkb92f9302016-02-22 13:12:02 +0900166 netdev_err(vif->ndev, "Already scan\n");
Leo Kim31390ee2015-10-19 18:26:08 +0900167 result = -EBUSY;
Ajay Singh3e488a92018-03-07 07:43:52 +0530168 goto error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900169 }
170
Adham Abozaeid5a28d3f2019-07-25 21:31:34 +0000171 if (vif->connecting) {
Chris Parkb92f9302016-02-22 13:12:02 +0900172 netdev_err(vif->ndev, "Don't do obss scan\n");
Leo Kim31390ee2015-10-19 18:26:08 +0900173 result = -EBUSY;
Ajay Singh3e488a92018-03-07 07:43:52 +0530174 goto error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900175 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900176
Ajay Singh49328072018-07-29 11:36:55 +0530177 hif_drv->usr_scan_req.ch_cnt = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900178
Adham Abozaeidac118d82019-03-25 22:27:26 +0000179 if (request->n_ssids) {
180 for (i = 0; i < request->n_ssids; i++)
181 valuesize += ((request->ssids[i].ssid_len) + 1);
Ajay Singhf47e59e2019-01-17 13:21:30 +0000182 search_ssid_vals = kmalloc(valuesize + 1, GFP_KERNEL);
183 if (search_ssid_vals) {
184 wid_list[index].id = WID_SSID_PROBE_REQ;
185 wid_list[index].type = WID_STR;
186 wid_list[index].val = search_ssid_vals;
Ajay Singh0b7b9b62018-12-15 02:32:29 +0000187 buffer = wid_list[index].val;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900188
Adham Abozaeidac118d82019-03-25 22:27:26 +0000189 *buffer++ = request->n_ssids;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900190
Adham Abozaeidac118d82019-03-25 22:27:26 +0000191 for (i = 0; i < request->n_ssids; i++) {
192 *buffer++ = request->ssids[i].ssid_len;
193 memcpy(buffer, request->ssids[i].ssid,
194 request->ssids[i].ssid_len);
195 buffer += request->ssids[i].ssid_len;
Ajay Singh0b7b9b62018-12-15 02:32:29 +0000196 }
Ajay Singh0b7b9b62018-12-15 02:32:29 +0000197 wid_list[index].size = (s32)(valuesize + 1);
198 index++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900199 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900200 }
201
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900202 wid_list[index].id = WID_INFO_ELEMENT_PROBE;
203 wid_list[index].type = WID_BIN_DATA;
Adham Abozaeidac118d82019-03-25 22:27:26 +0000204 wid_list[index].val = (s8 *)request->ie;
205 wid_list[index].size = request->ie_len;
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900206 index++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900207
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900208 wid_list[index].id = WID_SCAN_TYPE;
209 wid_list[index].type = WID_CHAR;
210 wid_list[index].size = sizeof(char);
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000211 wid_list[index].val = (s8 *)&scan_type;
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900212 index++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900213
Adham Abozaeidf5a3cb92019-06-20 19:54:55 +0000214 if (scan_type == WILC_FW_PASSIVE_SCAN && request->duration) {
215 wid_list[index].id = WID_PASSIVE_SCAN_TIME;
216 wid_list[index].type = WID_SHORT;
217 wid_list[index].size = sizeof(u16);
218 wid_list[index].val = (s8 *)&request->duration;
219 index++;
220
221 scan_timeout = (request->duration * ch_list_len) + 500;
222 } else {
223 scan_timeout = WILC_HIF_SCAN_TIMEOUT_MS;
224 }
225
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900226 wid_list[index].id = WID_SCAN_CHANNEL_LIST;
227 wid_list[index].type = WID_BIN_DATA;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900228
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000229 if (ch_freq_list && ch_list_len > 0) {
230 for (i = 0; i < ch_list_len; i++) {
231 if (ch_freq_list[i] > 0)
232 ch_freq_list[i] -= 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900233 }
234 }
235
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000236 wid_list[index].val = ch_freq_list;
237 wid_list[index].size = ch_list_len;
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900238 index++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900239
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900240 wid_list[index].id = WID_START_SCAN_REQ;
241 wid_list[index].type = WID_CHAR;
242 wid_list[index].size = sizeof(char);
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000243 wid_list[index].val = (s8 *)&scan_source;
Chaehyun Lim87b16cb2016-04-04 20:04:49 +0900244 index++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900245
Adham Abozaeideab07542019-03-27 20:28:34 +0000246 hif_drv->usr_scan_req.scan_result = scan_result_fn;
247 hif_drv->usr_scan_req.arg = user_arg;
248
Ajay Singh93592a62019-06-26 12:41:04 +0000249 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, index);
Leo Kim31390ee2015-10-19 18:26:08 +0900250 if (result) {
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000251 netdev_err(vif->ndev, "Failed to send scan parameters\n");
252 goto error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900253 }
254
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000255 hif_drv->scan_timer_vif = vif;
256 mod_timer(&hif_drv->scan_timer,
Adham Abozaeidf5a3cb92019-06-20 19:54:55 +0000257 jiffies + msecs_to_jiffies(scan_timeout));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900258
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000259error:
Adham Abozaeidac118d82019-03-25 22:27:26 +0000260
261 kfree(search_ssid_vals);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900262
Ajay Singh8f1a0ac2018-12-02 18:03:38 +0000263 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900264}
265
Ajay Singha343cf52018-12-02 18:03:34 +0000266static int wilc_send_connect_wid(struct wilc_vif *vif)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900267{
Ajay Singh82120ec2018-07-19 04:15:17 +0530268 int result = 0;
Adham Abozaeid59fb8052019-01-29 18:46:42 +0000269 struct wid wid_list[4];
270 u32 wid_cnt = 0;
Glen Lee71130e82015-12-21 14:18:41 +0900271 struct host_if_drv *hif_drv = vif->hif_drv;
Ajay Singh734c3192019-01-17 13:21:32 +0000272 struct wilc_conn_info *conn_attr = &hif_drv->conn_info;
273 struct wilc_join_bss_param *bss_param = conn_attr->param;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900274
Ajay Singh54300bfb2018-03-07 07:43:54 +0530275 wid_list[wid_cnt].id = WID_INFO_ELEMENT_ASSOCIATE;
276 wid_list[wid_cnt].type = WID_BIN_DATA;
Ajay Singh734c3192019-01-17 13:21:32 +0000277 wid_list[wid_cnt].val = conn_attr->req_ies;
278 wid_list[wid_cnt].size = conn_attr->req_ies_len;
Ajay Singh54300bfb2018-03-07 07:43:54 +0530279 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900280
Ajay Singh674650f2018-07-19 04:15:12 +0530281 wid_list[wid_cnt].id = WID_11I_MODE;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530282 wid_list[wid_cnt].type = WID_CHAR;
283 wid_list[wid_cnt].size = sizeof(char);
Ajay Singha343cf52018-12-02 18:03:34 +0000284 wid_list[wid_cnt].val = (s8 *)&conn_attr->security;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530285 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900286
Ajay Singh674650f2018-07-19 04:15:12 +0530287 wid_list[wid_cnt].id = WID_AUTH_TYPE;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530288 wid_list[wid_cnt].type = WID_CHAR;
289 wid_list[wid_cnt].size = sizeof(char);
Ajay Singha343cf52018-12-02 18:03:34 +0000290 wid_list[wid_cnt].val = (s8 *)&conn_attr->auth_type;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530291 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900292
Ajay Singh674650f2018-07-19 04:15:12 +0530293 wid_list[wid_cnt].id = WID_JOIN_REQ_EXTENDED;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530294 wid_list[wid_cnt].type = WID_STR;
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000295 wid_list[wid_cnt].size = sizeof(*bss_param);
296 wid_list[wid_cnt].val = (u8 *)bss_param;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530297 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900298
Ajay Singh93592a62019-06-26 12:41:04 +0000299 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, wid_cnt);
Leo Kim31390ee2015-10-19 18:26:08 +0900300 if (result) {
Chris Parkb92f9302016-02-22 13:12:02 +0900301 netdev_err(vif->ndev, "failed to send config packet\n");
Ajay Singh3e488a92018-03-07 07:43:52 +0530302 goto error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900303 } else {
Leo Kimb60005a2015-10-29 11:58:24 +0900304 hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900305 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900306
Ajay Singha343cf52018-12-02 18:03:34 +0000307 return 0;
308
Ajay Singh3e488a92018-03-07 07:43:52 +0530309error:
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900310
Ajay Singh734c3192019-01-17 13:21:32 +0000311 kfree(conn_attr->req_ies);
312 conn_attr->req_ies = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900313
Ajay Singhe5596812018-12-02 18:03:31 +0000314 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900315}
316
Ajay Singh7233be32018-06-26 11:37:03 +0530317static void handle_connect_timeout(struct work_struct *work)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900318{
Ajay Singh7233be32018-06-26 11:37:03 +0530319 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
320 struct wilc_vif *vif = msg->vif;
Ajay Singh82120ec2018-07-19 04:15:17 +0530321 int result;
Leo Kim45102f82015-10-28 15:59:28 +0900322 struct wid wid;
Ajay Singh87ae3a52018-03-02 19:52:47 +0530323 u16 dummy_reason_code = 0;
Glen Lee71130e82015-12-21 14:18:41 +0900324 struct host_if_drv *hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900325
Tony Choa4ab1ad2015-10-12 16:56:05 +0900326 if (!hif_drv) {
Ajay Singha120adb82018-07-29 11:36:53 +0530327 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
Ajay Singh7233be32018-06-26 11:37:03 +0530328 goto out;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900329 }
330
Leo Kimb60005a2015-10-29 11:58:24 +0900331 hif_drv->hif_state = HOST_IF_IDLE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900332
Ajay Singh734c3192019-01-17 13:21:32 +0000333 if (hif_drv->conn_info.conn_result) {
334 hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_CONN_RESP,
335 WILC_MAC_STATUS_DISCONNECTED,
Ajay Singh03cf31c42019-01-17 13:21:38 +0000336 hif_drv->conn_info.arg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900337
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900338 } else {
Ajay Singha120adb82018-07-29 11:36:53 +0530339 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900340 }
341
Ajay Singh674650f2018-07-19 04:15:12 +0530342 wid.id = WID_DISCONNECT;
Leo Kim45102f82015-10-28 15:59:28 +0900343 wid.type = WID_CHAR;
Ajay Singh87ae3a52018-03-02 19:52:47 +0530344 wid.val = (s8 *)&dummy_reason_code;
Leo Kim45102f82015-10-28 15:59:28 +0900345 wid.size = sizeof(char);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900346
Ajay Singh93592a62019-06-26 12:41:04 +0000347 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Leo Kim31390ee2015-10-19 18:26:08 +0900348 if (result)
Colin Ian Kinge171da02017-06-27 10:29:06 +0100349 netdev_err(vif->ndev, "Failed to send disconnect\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900350
Ajay Singh734c3192019-01-17 13:21:32 +0000351 hif_drv->conn_info.req_ies_len = 0;
352 kfree(hif_drv->conn_info.req_ies);
353 hif_drv->conn_info.req_ies = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900354
Ajay Singh7233be32018-06-26 11:37:03 +0530355out:
356 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900357}
358
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000359void *wilc_parse_join_bss_param(struct cfg80211_bss *bss,
360 struct cfg80211_crypto_settings *crypto)
Ajay Singh448d0782018-07-19 04:15:15 +0530361{
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000362 struct wilc_join_bss_param *param;
363 struct ieee80211_p2p_noa_attr noa_attr;
364 u8 rates_len = 0;
365 const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
366 const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
367 int ret;
Bo YUc4604952019-02-27 09:52:36 -0500368 const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
Ajay Singh448d0782018-07-19 04:15:15 +0530369
370 param = kzalloc(sizeof(*param), GFP_KERNEL);
371 if (!param)
372 return NULL;
373
Bo YU1d4ccf22019-02-26 02:25:56 -0500374 param->beacon_period = cpu_to_le16(bss->beacon_interval);
375 param->cap_info = cpu_to_le16(bss->capability);
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000376 param->bss_type = WILC_FW_BSS_TYPE_INFRA;
377 param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
Ajay Singh6c2cfb42019-01-17 13:21:18 +0000378 ether_addr_copy(param->bssid, bss->bssid);
379
380 ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
381 if (ssid_elm) {
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000382 if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
383 memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
Ajay Singh6c2cfb42019-01-17 13:21:18 +0000384 }
385
386 tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
387 if (tim_elm && tim_elm[1] >= 2)
388 param->dtim_period = tim_elm[3];
389
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000390 memset(param->p_suites, 0xFF, 3);
391 memset(param->akm_suites, 0xFF, 3);
Ajay Singh448d0782018-07-19 04:15:15 +0530392
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000393 rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
394 if (rates_ie) {
395 rates_len = rates_ie[1];
Dan Carpenterd59dc922019-10-17 12:18:32 +0300396 if (rates_len > WILC_MAX_RATES_SUPPORTED)
397 rates_len = WILC_MAX_RATES_SUPPORTED;
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000398 param->supp_rates[0] = rates_len;
399 memcpy(&param->supp_rates[1], rates_ie + 2, rates_len);
400 }
401
Ajay Singhc7e621b2019-11-07 15:58:54 +0000402 if (rates_len < WILC_MAX_RATES_SUPPORTED) {
403 supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
404 ies->data, ies->len);
405 if (supp_rates_ie) {
406 u8 ext_rates = supp_rates_ie[1];
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000407
Ajay Singhc7e621b2019-11-07 15:58:54 +0000408 if (ext_rates > (WILC_MAX_RATES_SUPPORTED - rates_len))
409 param->supp_rates[0] = WILC_MAX_RATES_SUPPORTED;
410 else
411 param->supp_rates[0] += ext_rates;
412
413 memcpy(&param->supp_rates[rates_len + 1],
414 supp_rates_ie + 2,
415 (param->supp_rates[0] - rates_len));
416 }
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000417 }
418
419 ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
420 if (ht_ie)
421 param->ht_capable = true;
422
423 ret = cfg80211_get_p2p_attr(ies->data, ies->len,
424 IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
425 (u8 *)&noa_attr, sizeof(noa_attr));
426 if (ret > 0) {
427 param->tsf_lo = cpu_to_le32(ies->tsf);
428 param->noa_enabled = 1;
429 param->idx = noa_attr.index;
430 if (noa_attr.oppps_ctwindow & IEEE80211_P2P_OPPPS_ENABLE_BIT) {
431 param->opp_enabled = 1;
432 param->opp_en.ct_window = noa_attr.oppps_ctwindow;
433 param->opp_en.cnt = noa_attr.desc[0].count;
434 param->opp_en.duration = noa_attr.desc[0].duration;
435 param->opp_en.interval = noa_attr.desc[0].interval;
436 param->opp_en.start_time = noa_attr.desc[0].start_time;
437 } else {
438 param->opp_enabled = 0;
439 param->opp_dis.cnt = noa_attr.desc[0].count;
440 param->opp_dis.duration = noa_attr.desc[0].duration;
441 param->opp_dis.interval = noa_attr.desc[0].interval;
442 param->opp_dis.start_time = noa_attr.desc[0].start_time;
443 }
444 }
445 wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
446 WLAN_OUI_TYPE_MICROSOFT_WMM,
447 ies->data, ies->len);
448 if (wmm_ie) {
449 struct ieee80211_wmm_param_ie *ie;
450
451 ie = (struct ieee80211_wmm_param_ie *)wmm_ie;
452 if ((ie->oui_subtype == 0 || ie->oui_subtype == 1) &&
453 ie->version == 1) {
454 param->wmm_cap = true;
455 if (ie->qos_info & BIT(7))
456 param->uapsd_cap = true;
457 }
458 }
459
460 wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
461 WLAN_OUI_TYPE_MICROSOFT_WPA,
462 ies->data, ies->len);
463 if (wpa_ie) {
464 param->mode_802_11i = 1;
465 param->rsn_found = true;
466 }
467
468 rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
469 if (rsn_ie) {
470 int offset = 8;
471
472 param->mode_802_11i = 2;
473 param->rsn_found = true;
Ajay Singhf1f24262019-11-05 09:51:30 +0000474 /* extract RSN capabilities */
Ajay Singh4e0b0f42019-01-17 13:21:27 +0000475 offset += (rsn_ie[offset] * 4) + 2;
476 offset += (rsn_ie[offset] * 4) + 2;
477 memcpy(param->rsn_cap, &rsn_ie[offset], 2);
478 }
479
480 if (param->rsn_found) {
481 int i;
482
483 param->rsn_grp_policy = crypto->cipher_group & 0xFF;
484 for (i = 0; i < crypto->n_ciphers_pairwise && i < 3; i++)
485 param->p_suites[i] = crypto->ciphers_pairwise[i] & 0xFF;
486
487 for (i = 0; i < crypto->n_akm_suites && i < 3; i++)
488 param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
489 }
Ajay Singh448d0782018-07-19 04:15:15 +0530490
491 return (void *)param;
492}
493
Ajay Singh7233be32018-06-26 11:37:03 +0530494static void handle_rcvd_ntwrk_info(struct work_struct *work)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900495{
Ajay Singh7233be32018-06-26 11:37:03 +0530496 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
Ajay Singh6cd4fa52019-01-17 13:21:21 +0000497 struct wilc_rcvd_net_info *rcvd_info = &msg->body.net_info;
Ajay Singhf5436ed2019-02-07 11:29:01 +0000498 struct wilc_user_scan_req *scan_req = &msg->vif->hif_drv->usr_scan_req;
Ajay Singh6cd4fa52019-01-17 13:21:21 +0000499 const u8 *ch_elm;
500 u8 *ies;
501 int ies_len;
502 size_t offset;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900503
Ajay Singh6cd4fa52019-01-17 13:21:21 +0000504 if (ieee80211_is_probe_resp(rcvd_info->mgmt->frame_control))
505 offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
506 else if (ieee80211_is_beacon(rcvd_info->mgmt->frame_control))
507 offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
508 else
Ajay Singh3b9ccd32018-03-02 19:52:48 +0530509 goto done;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900510
Ajay Singh6cd4fa52019-01-17 13:21:21 +0000511 ies = rcvd_info->mgmt->u.beacon.variable;
512 ies_len = rcvd_info->frame_len - offset;
513 if (ies_len <= 0)
Ajay Singh3b9ccd32018-03-02 19:52:48 +0530514 goto done;
Ajay Singh3b9ccd32018-03-02 19:52:48 +0530515
Ajay Singh6cd4fa52019-01-17 13:21:21 +0000516 ch_elm = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ies, ies_len);
517 if (ch_elm && ch_elm[1] > 0)
518 rcvd_info->ch = ch_elm[2];
519
520 if (scan_req->scan_result)
521 scan_req->scan_result(SCAN_EVENT_NETWORK_FOUND, rcvd_info,
522 scan_req->arg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900523
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900524done:
Ajay Singh6cd4fa52019-01-17 13:21:21 +0000525 kfree(rcvd_info->mgmt);
Ajay Singh7233be32018-06-26 11:37:03 +0530526 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900527}
528
Ajay Singhabffb392018-09-25 11:53:21 +0530529static void host_int_get_assoc_res_info(struct wilc_vif *vif,
530 u8 *assoc_resp_info,
531 u32 max_assoc_resp_info_len,
532 u32 *rcvd_assoc_resp_info_len)
Ajay Singh8bdc6bb2018-07-19 04:15:14 +0530533{
Ajay Singh82120ec2018-07-19 04:15:17 +0530534 int result;
Ajay Singh8bdc6bb2018-07-19 04:15:14 +0530535 struct wid wid;
536
537 wid.id = WID_ASSOC_RES_INFO;
538 wid.type = WID_STR;
539 wid.val = assoc_resp_info;
540 wid.size = max_assoc_resp_info_len;
541
Ajay Singh93592a62019-06-26 12:41:04 +0000542 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
Ajay Singh8bdc6bb2018-07-19 04:15:14 +0530543 if (result) {
544 *rcvd_assoc_resp_info_len = 0;
545 netdev_err(vif->ndev, "Failed to send association response\n");
Ajay Singhabffb392018-09-25 11:53:21 +0530546 return;
Ajay Singh8bdc6bb2018-07-19 04:15:14 +0530547 }
548
549 *rcvd_assoc_resp_info_len = wid.size;
Ajay Singh8bdc6bb2018-07-19 04:15:14 +0530550}
Arnd Bergmann1608c402015-11-16 15:04:53 +0100551
Ajay Singh1116468b2018-11-01 16:45:23 +0000552static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
Ajay Singh734c3192019-01-17 13:21:32 +0000553 struct wilc_conn_info *ret_conn_info)
Ajay Singh1116468b2018-11-01 16:45:23 +0000554{
555 u8 *ies;
556 u16 ies_len;
Ajay Singh1d58fec2020-01-17 10:31:26 +0000557 struct wilc_assoc_resp *res = (struct wilc_assoc_resp *)buffer;
Ajay Singh1116468b2018-11-01 16:45:23 +0000558
559 ret_conn_info->status = le16_to_cpu(res->status_code);
560 if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
561 ies = &buffer[sizeof(*res)];
562 ies_len = buffer_len - sizeof(*res);
563
564 ret_conn_info->resp_ies = kmemdup(ies, ies_len, GFP_KERNEL);
565 if (!ret_conn_info->resp_ies)
566 return -ENOMEM;
567
568 ret_conn_info->resp_ies_len = ies_len;
569 }
570
571 return 0;
572}
573
Ajay Singh158152b2018-03-26 17:16:02 +0530574static inline void host_int_parse_assoc_resp_info(struct wilc_vif *vif,
575 u8 mac_status)
576{
Ajay Singh158152b2018-03-26 17:16:02 +0530577 struct host_if_drv *hif_drv = vif->hif_drv;
Ajay Singh734c3192019-01-17 13:21:32 +0000578 struct wilc_conn_info *conn_info = &hif_drv->conn_info;
Ajay Singh158152b2018-03-26 17:16:02 +0530579
Ajay Singh8c4574d2018-11-12 05:45:14 +0000580 if (mac_status == WILC_MAC_STATUS_CONNECTED) {
Ajay Singh9aef8232018-05-11 13:43:08 +0530581 u32 assoc_resp_info_len;
Ajay Singh158152b2018-03-26 17:16:02 +0530582
Ajay Singhd0e41ef2018-11-12 05:45:29 +0000583 memset(hif_drv->assoc_resp, 0, WILC_MAX_ASSOC_RESP_FRAME_SIZE);
Ajay Singh158152b2018-03-26 17:16:02 +0530584
Ajay Singh83a953e22018-09-04 12:09:30 +0530585 host_int_get_assoc_res_info(vif, hif_drv->assoc_resp,
Ajay Singhd0e41ef2018-11-12 05:45:29 +0000586 WILC_MAX_ASSOC_RESP_FRAME_SIZE,
Ajay Singh9aef8232018-05-11 13:43:08 +0530587 &assoc_resp_info_len);
Ajay Singh158152b2018-03-26 17:16:02 +0530588
Ajay Singh9aef8232018-05-11 13:43:08 +0530589 if (assoc_resp_info_len != 0) {
Ajay Singh158152b2018-03-26 17:16:02 +0530590 s32 err = 0;
591
Ajay Singh83a953e22018-09-04 12:09:30 +0530592 err = wilc_parse_assoc_resp_info(hif_drv->assoc_resp,
Ajay Singh9aef8232018-05-11 13:43:08 +0530593 assoc_resp_info_len,
Ajay Singh734c3192019-01-17 13:21:32 +0000594 conn_info);
Ajay Singh49bf6652018-05-11 13:43:31 +0530595 if (err)
Ajay Singh158152b2018-03-26 17:16:02 +0530596 netdev_err(vif->ndev,
597 "wilc_parse_assoc_resp_info() returned error %d\n",
598 err);
Ajay Singh158152b2018-03-26 17:16:02 +0530599 }
600 }
601
Ajay Singh158152b2018-03-26 17:16:02 +0530602 del_timer(&hif_drv->connect_timer);
Ajay Singh03cf31c42019-01-17 13:21:38 +0000603 conn_info->conn_result(CONN_DISCONN_EVENT_CONN_RESP, mac_status,
Ajay Singh734c3192019-01-17 13:21:32 +0000604 hif_drv->conn_info.arg);
Ajay Singh158152b2018-03-26 17:16:02 +0530605
Ajay Singh8c4574d2018-11-12 05:45:14 +0000606 if (mac_status == WILC_MAC_STATUS_CONNECTED &&
Ajay Singh734c3192019-01-17 13:21:32 +0000607 conn_info->status == WLAN_STATUS_SUCCESS) {
608 ether_addr_copy(hif_drv->assoc_bssid, conn_info->bssid);
Ajay Singh158152b2018-03-26 17:16:02 +0530609 hif_drv->hif_state = HOST_IF_CONNECTED;
Ajay Singh158152b2018-03-26 17:16:02 +0530610 } else {
611 hif_drv->hif_state = HOST_IF_IDLE;
Ajay Singh158152b2018-03-26 17:16:02 +0530612 }
613
Ajay Singh734c3192019-01-17 13:21:32 +0000614 kfree(conn_info->resp_ies);
615 conn_info->resp_ies = NULL;
616 conn_info->resp_ies_len = 0;
Ajay Singh158152b2018-03-26 17:16:02 +0530617
Ajay Singh734c3192019-01-17 13:21:32 +0000618 kfree(conn_info->req_ies);
619 conn_info->req_ies = NULL;
620 conn_info->req_ies_len = 0;
Ajay Singh158152b2018-03-26 17:16:02 +0530621}
622
623static inline void host_int_handle_disconnect(struct wilc_vif *vif)
624{
Ajay Singh158152b2018-03-26 17:16:02 +0530625 struct host_if_drv *hif_drv = vif->hif_drv;
626
Ajay Singh158152b2018-03-26 17:16:02 +0530627 if (hif_drv->usr_scan_req.scan_result) {
628 del_timer(&hif_drv->scan_timer);
629 handle_scan_done(vif, SCAN_EVENT_ABORTED);
630 }
631
Adham Abozaeidded11ab2019-07-25 21:31:35 +0000632 if (hif_drv->conn_info.conn_result)
Ajay Singh734c3192019-01-17 13:21:32 +0000633 hif_drv->conn_info.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF,
Ajay Singh03cf31c42019-01-17 13:21:38 +0000634 0, hif_drv->conn_info.arg);
Adham Abozaeidded11ab2019-07-25 21:31:35 +0000635 else
Ajay Singha120adb82018-07-29 11:36:53 +0530636 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
Ajay Singh158152b2018-03-26 17:16:02 +0530637
638 eth_zero_addr(hif_drv->assoc_bssid);
639
Ajay Singh734c3192019-01-17 13:21:32 +0000640 hif_drv->conn_info.req_ies_len = 0;
641 kfree(hif_drv->conn_info.req_ies);
642 hif_drv->conn_info.req_ies = NULL;
Ajay Singh158152b2018-03-26 17:16:02 +0530643 hif_drv->hif_state = HOST_IF_IDLE;
Ajay Singh158152b2018-03-26 17:16:02 +0530644}
645
Ajay Singh7233be32018-06-26 11:37:03 +0530646static void handle_rcvd_gnrl_async_info(struct work_struct *work)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900647{
Ajay Singh7233be32018-06-26 11:37:03 +0530648 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
649 struct wilc_vif *vif = msg->vif;
Ajay Singh94bb6d32019-01-17 13:21:35 +0000650 struct wilc_rcvd_mac_info *mac_info = &msg->body.mac_info;
Glen Lee71130e82015-12-21 14:18:41 +0900651 struct host_if_drv *hif_drv = vif->hif_drv;
Luis de Bethencourt78c87592015-06-26 16:45:14 +0200652
Tony Choa4ab1ad2015-10-12 16:56:05 +0900653 if (!hif_drv) {
Ajay Singha120adb82018-07-29 11:36:53 +0530654 netdev_err(vif->ndev, "%s: hif driver is NULL\n", __func__);
Ajay Singh94bb6d32019-01-17 13:21:35 +0000655 goto free_msg;
Leo Kim234837d2015-09-22 14:34:43 +0900656 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900657
Ajay Singh94bb6d32019-01-17 13:21:35 +0000658 if (!hif_drv->conn_info.conn_result) {
659 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
660 goto free_msg;
661 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900662
Ajay Singh94bb6d32019-01-17 13:21:35 +0000663 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) {
664 host_int_parse_assoc_resp_info(vif, mac_info->status);
665 } else if (mac_info->status == WILC_MAC_STATUS_DISCONNECTED) {
666 if (hif_drv->hif_state == HOST_IF_CONNECTED) {
Ajay Singh158152b2018-03-26 17:16:02 +0530667 host_int_handle_disconnect(vif);
Ajay Singh94bb6d32019-01-17 13:21:35 +0000668 } else if (hif_drv->usr_scan_req.scan_result) {
Leo Kim13b313e2015-10-29 11:58:34 +0900669 del_timer(&hif_drv->scan_timer);
Ajay Singh94bb6d32019-01-17 13:21:35 +0000670 handle_scan_done(vif, SCAN_EVENT_ABORTED);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900671 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900672 }
673
Ajay Singh7233be32018-06-26 11:37:03 +0530674free_msg:
675 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900676}
677
Ajay Singh8e6d6cf2018-12-02 18:03:28 +0000678int wilc_disconnect(struct wilc_vif *vif)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900679{
Leo Kim45102f82015-10-28 15:59:28 +0900680 struct wid wid;
Glen Lee71130e82015-12-21 14:18:41 +0900681 struct host_if_drv *hif_drv = vif->hif_drv;
Ajay Singhf5436ed2019-02-07 11:29:01 +0000682 struct wilc_user_scan_req *scan_req;
Ajay Singh734c3192019-01-17 13:21:32 +0000683 struct wilc_conn_info *conn_info;
Ajay Singh82120ec2018-07-19 04:15:17 +0530684 int result;
Ajay Singhe7893672018-03-02 19:52:49 +0530685 u16 dummy_reason_code = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900686
Ajay Singh674650f2018-07-19 04:15:12 +0530687 wid.id = WID_DISCONNECT;
Leo Kim45102f82015-10-28 15:59:28 +0900688 wid.type = WID_CHAR;
Ajay Singhe7893672018-03-02 19:52:49 +0530689 wid.val = (s8 *)&dummy_reason_code;
Leo Kim45102f82015-10-28 15:59:28 +0900690 wid.size = sizeof(char);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900691
Ajay Singh93592a62019-06-26 12:41:04 +0000692 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Leo Kim31390ee2015-10-19 18:26:08 +0900693 if (result) {
Colin Ian Kinge2e89d42019-04-15 17:33:30 +0100694 netdev_err(vif->ndev, "Failed to send disconnect\n");
Ajay Singh8e6d6cf2018-12-02 18:03:28 +0000695 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900696 }
697
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530698 scan_req = &hif_drv->usr_scan_req;
Ajay Singh734c3192019-01-17 13:21:32 +0000699 conn_info = &hif_drv->conn_info;
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530700
701 if (scan_req->scan_result) {
702 del_timer(&hif_drv->scan_timer);
Ajay Singh6c2cfb42019-01-17 13:21:18 +0000703 scan_req->scan_result(SCAN_EVENT_ABORTED, NULL, scan_req->arg);
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530704 scan_req->scan_result = NULL;
705 }
706
Ajay Singh734c3192019-01-17 13:21:32 +0000707 if (conn_info->conn_result) {
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530708 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
709 del_timer(&hif_drv->connect_timer);
710
Ajay Singh03cf31c42019-01-17 13:21:38 +0000711 conn_info->conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, 0,
712 conn_info->arg);
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530713 } else {
Ajay Singha120adb82018-07-29 11:36:53 +0530714 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530715 }
716
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530717 hif_drv->hif_state = HOST_IF_IDLE;
718
719 eth_zero_addr(hif_drv->assoc_bssid);
720
Ajay Singh734c3192019-01-17 13:21:32 +0000721 conn_info->req_ies_len = 0;
722 kfree(conn_info->req_ies);
723 conn_info->req_ies = NULL;
Ajay Singh0e7ba8eb2018-03-07 07:43:55 +0530724
Ajay Singh8e6d6cf2018-12-02 18:03:28 +0000725 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900726}
727
Ajay Singh19cb25e12018-12-02 18:03:25 +0000728int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900729{
Ajay Singh173508b2018-01-30 22:20:29 +0530730 struct wid wid_list[5];
Ajay Singhd2418772018-07-19 04:15:16 +0530731 u32 wid_cnt = 0, result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900732
Ajay Singhcdbdae12018-01-30 22:20:30 +0530733 wid_list[wid_cnt].id = WID_LINKSPEED;
734 wid_list[wid_cnt].type = WID_CHAR;
735 wid_list[wid_cnt].size = sizeof(char);
Ajay Singhfcc70102018-02-20 20:27:56 +0530736 wid_list[wid_cnt].val = (s8 *)&stats->link_speed;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530737 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900738
Ajay Singhcdbdae12018-01-30 22:20:30 +0530739 wid_list[wid_cnt].id = WID_RSSI;
740 wid_list[wid_cnt].type = WID_CHAR;
741 wid_list[wid_cnt].size = sizeof(char);
Ajay Singhfcc70102018-02-20 20:27:56 +0530742 wid_list[wid_cnt].val = (s8 *)&stats->rssi;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530743 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900744
Ajay Singhcdbdae12018-01-30 22:20:30 +0530745 wid_list[wid_cnt].id = WID_SUCCESS_FRAME_COUNT;
746 wid_list[wid_cnt].type = WID_INT;
747 wid_list[wid_cnt].size = sizeof(u32);
Ajay Singhfcc70102018-02-20 20:27:56 +0530748 wid_list[wid_cnt].val = (s8 *)&stats->tx_cnt;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530749 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900750
Ajay Singhcdbdae12018-01-30 22:20:30 +0530751 wid_list[wid_cnt].id = WID_RECEIVED_FRAGMENT_COUNT;
752 wid_list[wid_cnt].type = WID_INT;
753 wid_list[wid_cnt].size = sizeof(u32);
Ajay Singhfcc70102018-02-20 20:27:56 +0530754 wid_list[wid_cnt].val = (s8 *)&stats->rx_cnt;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530755 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900756
Ajay Singhcdbdae12018-01-30 22:20:30 +0530757 wid_list[wid_cnt].id = WID_FAILED_COUNT;
758 wid_list[wid_cnt].type = WID_INT;
759 wid_list[wid_cnt].size = sizeof(u32);
Ajay Singhfcc70102018-02-20 20:27:56 +0530760 wid_list[wid_cnt].val = (s8 *)&stats->tx_fail_cnt;
Ajay Singhcdbdae12018-01-30 22:20:30 +0530761 wid_cnt++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900762
Ajay Singh93592a62019-06-26 12:41:04 +0000763 result = wilc_send_config_pkt(vif, WILC_GET_CFG, wid_list, wid_cnt);
Ajay Singh19cb25e12018-12-02 18:03:25 +0000764 if (result) {
Chris Parkb92f9302016-02-22 13:12:02 +0900765 netdev_err(vif->ndev, "Failed to send scan parameters\n");
Ajay Singh19cb25e12018-12-02 18:03:25 +0000766 return result;
767 }
Leo Kim24db7132015-09-16 18:36:01 +0900768
Ajay Singhfcc70102018-02-20 20:27:56 +0530769 if (stats->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH &&
770 stats->link_speed != DEFAULT_LINK_SPEED)
Ajay Singh95e05b42018-09-04 12:09:33 +0530771 wilc_enable_tcp_ack_filter(vif, true);
Ajay Singhfcc70102018-02-20 20:27:56 +0530772 else if (stats->link_speed != DEFAULT_LINK_SPEED)
Ajay Singh95e05b42018-09-04 12:09:33 +0530773 wilc_enable_tcp_ack_filter(vif, false);
Glen Lee4fd62292016-02-04 18:15:24 +0900774
Ajay Singh19cb25e12018-12-02 18:03:25 +0000775 return result;
776}
777
778static void handle_get_statistics(struct work_struct *work)
779{
780 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
781 struct wilc_vif *vif = msg->vif;
782 struct rf_info *stats = (struct rf_info *)msg->body.data;
783
784 wilc_get_statistics(vif, stats);
785
786 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900787}
788
Ajay Singh6133ed92018-12-02 18:02:36 +0000789static void wilc_hif_pack_sta_param(u8 *cur_byte, const u8 *mac,
790 struct station_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900791{
Ajay Singh78c0c4e2018-12-02 18:02:34 +0000792 ether_addr_copy(cur_byte, mac);
793 cur_byte += ETH_ALEN;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900794
Ajay Singh78c0c4e2018-12-02 18:02:34 +0000795 put_unaligned_le16(params->aid, cur_byte);
796 cur_byte += 2;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900797
Ajay Singh78c0c4e2018-12-02 18:02:34 +0000798 *cur_byte++ = params->supported_rates_len;
799 if (params->supported_rates_len > 0)
800 memcpy(cur_byte, params->supported_rates,
801 params->supported_rates_len);
802 cur_byte += params->supported_rates_len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900803
Ajay Singh78c0c4e2018-12-02 18:02:34 +0000804 if (params->ht_capa) {
805 *cur_byte++ = true;
Ajay Singhefabc442020-03-02 16:22:35 +0000806 memcpy(cur_byte, params->ht_capa,
Ajay Singh78c0c4e2018-12-02 18:02:34 +0000807 sizeof(struct ieee80211_ht_cap));
808 } else {
809 *cur_byte++ = false;
810 }
Ajay Singhe33ff512018-01-30 22:20:31 +0530811 cur_byte += sizeof(struct ieee80211_ht_cap);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900812
Ajay Singh78c0c4e2018-12-02 18:02:34 +0000813 put_unaligned_le16(params->sta_flags_mask, cur_byte);
814 cur_byte += 2;
815 put_unaligned_le16(params->sta_flags_set, cur_byte);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900816}
817
Ajay Singh3ccff332018-02-19 20:59:39 +0530818static int handle_remain_on_chan(struct wilc_vif *vif,
Ajay Singhf5436ed2019-02-07 11:29:01 +0000819 struct wilc_remain_ch *hif_remain_ch)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900820{
Ajay Singh82120ec2018-07-19 04:15:17 +0530821 int result;
Ajay Singhd9568392018-03-07 07:43:56 +0530822 u8 remain_on_chan_flag;
Leo Kim45102f82015-10-28 15:59:28 +0900823 struct wid wid;
Glen Lee71130e82015-12-21 14:18:41 +0900824 struct host_if_drv *hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900825
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000826 if (hif_drv->usr_scan_req.scan_result)
827 return -EBUSY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900828
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000829 if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP)
830 return -EBUSY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900831
Adham Abozaeid5a28d3f2019-07-25 21:31:34 +0000832 if (vif->connecting)
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000833 return -EBUSY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900834
Ajay Singhd9568392018-03-07 07:43:56 +0530835 remain_on_chan_flag = true;
Ajay Singh674650f2018-07-19 04:15:12 +0530836 wid.id = WID_REMAIN_ON_CHAN;
Leo Kim45102f82015-10-28 15:59:28 +0900837 wid.type = WID_STR;
838 wid.size = 2;
839 wid.val = kmalloc(wid.size, GFP_KERNEL);
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000840 if (!wid.val)
841 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900842
Ajay Singhd9568392018-03-07 07:43:56 +0530843 wid.val[0] = remain_on_chan_flag;
Ajay Singh9f248362018-02-19 20:59:34 +0530844 wid.val[1] = (s8)hif_remain_ch->ch;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900845
Ajay Singh93592a62019-06-26 12:41:04 +0000846 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh8d5b5e62018-03-26 17:15:59 +0530847 kfree(wid.val);
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000848 if (result)
849 return -EBUSY;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900850
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000851 hif_drv->remain_on_ch.arg = hif_remain_ch->arg;
852 hif_drv->remain_on_ch.expired = hif_remain_ch->expired;
853 hif_drv->remain_on_ch.ch = hif_remain_ch->ch;
854 hif_drv->remain_on_ch.cookie = hif_remain_ch->cookie;
Ajay Singh198fd7e2018-04-25 22:48:24 +0530855 hif_drv->remain_on_ch_timer_vif = vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900856
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000857 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900858}
859
Ajay Singh424a6112019-06-26 12:40:45 +0000860static int wilc_handle_roc_expired(struct wilc_vif *vif, u64 cookie)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900861{
Ajay Singhd9568392018-03-07 07:43:56 +0530862 u8 remain_on_chan_flag;
Leo Kim45102f82015-10-28 15:59:28 +0900863 struct wid wid;
Ajay Singh82120ec2018-07-19 04:15:17 +0530864 int result;
Glen Lee71130e82015-12-21 14:18:41 +0900865 struct host_if_drv *hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900866
Ajay Singh0f4f67b2020-02-11 09:57:09 +0000867 if (vif->priv.p2p_listen_state) {
Ajay Singhd9568392018-03-07 07:43:56 +0530868 remain_on_chan_flag = false;
Ajay Singh674650f2018-07-19 04:15:12 +0530869 wid.id = WID_REMAIN_ON_CHAN;
Leo Kim45102f82015-10-28 15:59:28 +0900870 wid.type = WID_STR;
871 wid.size = 2;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900872
Ajay Singh424a6112019-06-26 12:40:45 +0000873 wid.val = kmalloc(wid.size, GFP_KERNEL);
Dilek Uzulmez98b65942016-10-09 22:27:53 +0300874 if (!wid.val)
Ajay Singh424a6112019-06-26 12:40:45 +0000875 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900876
Ajay Singhd9568392018-03-07 07:43:56 +0530877 wid.val[0] = remain_on_chan_flag;
Ajay Singhf5436ed2019-02-07 11:29:01 +0000878 wid.val[1] = WILC_FALSE_FRMWR_CHANNEL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900879
Ajay Singh93592a62019-06-26 12:41:04 +0000880 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh8d5b5e62018-03-26 17:15:59 +0530881 kfree(wid.val);
Leo Kim31390ee2015-10-19 18:26:08 +0900882 if (result != 0) {
Chris Parkb92f9302016-02-22 13:12:02 +0900883 netdev_err(vif->ndev, "Failed to set remain channel\n");
Ajay Singh424a6112019-06-26 12:40:45 +0000884 return -EINVAL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900885 }
886
Leo Kimbfb62ab2015-10-29 11:58:42 +0900887 if (hif_drv->remain_on_ch.expired) {
Leo Kimc5cc4b12015-10-29 11:58:44 +0900888 hif_drv->remain_on_ch.expired(hif_drv->remain_on_ch.arg,
Ajay Singh424a6112019-06-26 12:40:45 +0000889 cookie);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900890 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900891 } else {
Chris Parke3f16962016-02-04 18:24:30 +0900892 netdev_dbg(vif->ndev, "Not in listen state\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900893 }
894
Ajay Singh424a6112019-06-26 12:40:45 +0000895 return 0;
896}
897
898static void wilc_handle_listen_state_expired(struct work_struct *work)
899{
900 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
901
902 wilc_handle_roc_expired(msg->vif, msg->body.remain_on_ch.cookie);
Ajay Singh7233be32018-06-26 11:37:03 +0530903 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900904}
905
Ajay Singhb44c3862018-02-19 20:59:41 +0530906static void listen_timer_cb(struct timer_list *t)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900907{
Kees Cook1f233192017-10-16 16:24:32 -0700908 struct host_if_drv *hif_drv = from_timer(hif_drv, t,
909 remain_on_ch_timer);
910 struct wilc_vif *vif = hif_drv->remain_on_ch_timer_vif;
Ajay Singh82120ec2018-07-19 04:15:17 +0530911 int result;
Ajay Singhff52a572018-06-26 11:37:05 +0530912 struct host_if_msg *msg;
Leo Kimae4dfa52015-10-13 19:49:26 +0900913
Glen Lee71130e82015-12-21 14:18:41 +0900914 del_timer(&vif->hif_drv->remain_on_ch_timer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900915
Ajay Singh424a6112019-06-26 12:40:45 +0000916 msg = wilc_alloc_work(vif, wilc_handle_listen_state_expired, false);
Ajay Singhff52a572018-06-26 11:37:05 +0530917 if (IS_ERR(msg))
918 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900919
Ajay Singhb6c6cd12019-02-05 07:15:39 +0000920 msg->body.remain_on_ch.cookie = vif->hif_drv->remain_on_ch.cookie;
Ajay Singhff52a572018-06-26 11:37:05 +0530921
Ajay Singhc6a358d2018-06-26 11:37:08 +0530922 result = wilc_enqueue_work(msg);
Ajay Singhff52a572018-06-26 11:37:05 +0530923 if (result) {
Ajay Singha120adb82018-07-29 11:36:53 +0530924 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
Ajay Singhff52a572018-06-26 11:37:05 +0530925 kfree(msg);
926 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900927}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900928
Ajay Singh7233be32018-06-26 11:37:03 +0530929static void handle_set_mcast_filter(struct work_struct *work)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900930{
Ajay Singh7233be32018-06-26 11:37:03 +0530931 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
932 struct wilc_vif *vif = msg->vif;
Ajay Singha0c6a322019-01-17 13:21:41 +0000933 struct wilc_set_multicast *set_mc = &msg->body.mc_info;
Ajay Singh82120ec2018-07-19 04:15:17 +0530934 int result;
Leo Kim45102f82015-10-28 15:59:28 +0900935 struct wid wid;
Ajay Singhe33ff512018-01-30 22:20:31 +0530936 u8 *cur_byte;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900937
Ajay Singh674650f2018-07-19 04:15:12 +0530938 wid.id = WID_SETUP_MULTICAST_FILTER;
Leo Kim45102f82015-10-28 15:59:28 +0900939 wid.type = WID_BIN;
Ajay Singha0c6a322019-01-17 13:21:41 +0000940 wid.size = sizeof(struct wilc_set_multicast) + (set_mc->cnt * ETH_ALEN);
Leo Kim45102f82015-10-28 15:59:28 +0900941 wid.val = kmalloc(wid.size, GFP_KERNEL);
942 if (!wid.val)
Ajay Singh3e488a92018-03-07 07:43:52 +0530943 goto error;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900944
Ajay Singhe33ff512018-01-30 22:20:31 +0530945 cur_byte = wid.val;
Ajay Singha0c6a322019-01-17 13:21:41 +0000946 put_unaligned_le32(set_mc->enabled, cur_byte);
947 cur_byte += 4;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900948
Ajay Singha0c6a322019-01-17 13:21:41 +0000949 put_unaligned_le32(set_mc->cnt, cur_byte);
950 cur_byte += 4;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900951
Ajay Singha0c6a322019-01-17 13:21:41 +0000952 if (set_mc->cnt > 0 && set_mc->mc_list)
953 memcpy(cur_byte, set_mc->mc_list, set_mc->cnt * ETH_ALEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900954
Ajay Singh93592a62019-06-26 12:41:04 +0000955 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Leo Kim31390ee2015-10-19 18:26:08 +0900956 if (result)
Chris Parkb92f9302016-02-22 13:12:02 +0900957 netdev_err(vif->ndev, "Failed to send setup multicast\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900958
Ajay Singh3e488a92018-03-07 07:43:52 +0530959error:
Ajay Singha0c6a322019-01-17 13:21:41 +0000960 kfree(set_mc->mc_list);
Leo Kim45102f82015-10-28 15:59:28 +0900961 kfree(wid.val);
Ajay Singh7233be32018-06-26 11:37:03 +0530962 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900963}
964
Ajay Singh7233be32018-06-26 11:37:03 +0530965static void handle_scan_timer(struct work_struct *work)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900966{
Ajay Singh7233be32018-06-26 11:37:03 +0530967 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900968
Ajay Singh7233be32018-06-26 11:37:03 +0530969 handle_scan_done(msg->vif, SCAN_EVENT_ABORTED);
970 kfree(msg);
Ajay Singh7233be32018-06-26 11:37:03 +0530971}
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900972
Ajay Singh7233be32018-06-26 11:37:03 +0530973static void handle_scan_complete(struct work_struct *work)
974{
975 struct host_if_msg *msg = container_of(work, struct host_if_msg, work);
Binoy Jayana5c84b22016-06-23 11:11:52 +0530976
Ajay Singh7233be32018-06-26 11:37:03 +0530977 del_timer(&msg->vif->hif_drv->scan_timer);
Binoy Jayana5c84b22016-06-23 11:11:52 +0530978
Ajay Singh7233be32018-06-26 11:37:03 +0530979 handle_scan_done(msg->vif, SCAN_EVENT_DONE);
Binoy Jayana5c84b22016-06-23 11:11:52 +0530980
Binoy Jayan2518ac52016-06-23 11:11:51 +0530981 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900982}
983
Ajay Singh4189eb52018-02-19 20:59:40 +0530984static void timer_scan_cb(struct timer_list *t)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900985{
Kees Cook1f233192017-10-16 16:24:32 -0700986 struct host_if_drv *hif_drv = from_timer(hif_drv, t, scan_timer);
987 struct wilc_vif *vif = hif_drv->scan_timer_vif;
Ajay Singhff52a572018-06-26 11:37:05 +0530988 struct host_if_msg *msg;
989 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900990
Ajay Singh5e6f8a82018-06-26 11:37:06 +0530991 msg = wilc_alloc_work(vif, handle_scan_timer, false);
Ajay Singhff52a572018-06-26 11:37:05 +0530992 if (IS_ERR(msg))
993 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900994
Ajay Singhc6a358d2018-06-26 11:37:08 +0530995 result = wilc_enqueue_work(msg);
Ajay Singhff52a572018-06-26 11:37:05 +0530996 if (result)
997 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900998}
999
Ajay Singh4189eb52018-02-19 20:59:40 +05301000static void timer_connect_cb(struct timer_list *t)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001001{
Kees Cook1f233192017-10-16 16:24:32 -07001002 struct host_if_drv *hif_drv = from_timer(hif_drv, t,
1003 connect_timer);
1004 struct wilc_vif *vif = hif_drv->connect_timer_vif;
Ajay Singhff52a572018-06-26 11:37:05 +05301005 struct host_if_msg *msg;
1006 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001007
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301008 msg = wilc_alloc_work(vif, handle_connect_timeout, false);
Ajay Singhff52a572018-06-26 11:37:05 +05301009 if (IS_ERR(msg))
1010 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001011
Ajay Singhc6a358d2018-06-26 11:37:08 +05301012 result = wilc_enqueue_work(msg);
Ajay Singhff52a572018-06-26 11:37:05 +05301013 if (result)
1014 kfree(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001015}
1016
Glen Leefbf53792015-12-21 14:18:40 +09001017int wilc_remove_wep_key(struct wilc_vif *vif, u8 index)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001018{
Ajay Singhb61c8062018-12-02 18:03:11 +00001019 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301020 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001021
Ajay Singhb61c8062018-12-02 18:03:11 +00001022 wid.id = WID_REMOVE_WEP_KEY;
1023 wid.type = WID_STR;
1024 wid.size = sizeof(char);
1025 wid.val = &index;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001026
Ajay Singh93592a62019-06-26 12:41:04 +00001027 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301028 if (result)
Ajay Singhb61c8062018-12-02 18:03:11 +00001029 netdev_err(vif->ndev,
1030 "Failed to send remove wep key config packet\n");
Chaehyun Lim9e5e8b42015-10-05 19:35:00 +09001031 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001032}
1033
Glen Leefbf53792015-12-21 14:18:40 +09001034int wilc_set_wep_default_keyid(struct wilc_vif *vif, u8 index)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001035{
Ajay Singhb61c8062018-12-02 18:03:11 +00001036 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301037 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001038
Ajay Singhb61c8062018-12-02 18:03:11 +00001039 wid.id = WID_KEY_ID;
1040 wid.type = WID_CHAR;
1041 wid.size = sizeof(char);
1042 wid.val = &index;
Ajay Singh93592a62019-06-26 12:41:04 +00001043 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301044 if (result)
Ajay Singhb61c8062018-12-02 18:03:11 +00001045 netdev_err(vif->ndev,
1046 "Failed to send wep default key config packet\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001047
Leo Kim31390ee2015-10-19 18:26:08 +09001048 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001049}
1050
Glen Leefbf53792015-12-21 14:18:40 +09001051int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len,
1052 u8 index)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001053{
Ajay Singhb61c8062018-12-02 18:03:11 +00001054 struct wid wid;
Ajay Singhc26bdea2018-03-26 17:15:58 +05301055 int result;
Ajay Singhb61c8062018-12-02 18:03:11 +00001056 struct wilc_wep_key *wep_key;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001057
Ajay Singhb61c8062018-12-02 18:03:11 +00001058 wid.id = WID_ADD_WEP_KEY;
1059 wid.type = WID_STR;
1060 wid.size = sizeof(*wep_key) + len;
1061 wep_key = kzalloc(wid.size, GFP_KERNEL);
1062 if (!wep_key)
1063 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001064
Ajay Singhb61c8062018-12-02 18:03:11 +00001065 wid.val = (u8 *)wep_key;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001066
Ajay Singhb61c8062018-12-02 18:03:11 +00001067 wep_key->index = index;
1068 wep_key->key_len = len;
1069 memcpy(wep_key->key, key, len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001070
Ajay Singh93592a62019-06-26 12:41:04 +00001071 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singhff52a572018-06-26 11:37:05 +05301072 if (result)
Ajay Singhb61c8062018-12-02 18:03:11 +00001073 netdev_err(vif->ndev,
1074 "Failed to add wep key config packet\n");
Ajay Singhff52a572018-06-26 11:37:05 +05301075
Ajay Singhb61c8062018-12-02 18:03:11 +00001076 kfree(wep_key);
Ajay Singhff52a572018-06-26 11:37:05 +05301077 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001078}
1079
Glen Leefbf53792015-12-21 14:18:40 +09001080int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len,
Ajay Singhecba6b72018-07-19 04:15:04 +05301081 u8 index, u8 mode, enum authtype auth_type)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001082{
Ajay Singhb61c8062018-12-02 18:03:11 +00001083 struct wid wid_list[3];
Ajay Singhc26bdea2018-03-26 17:15:58 +05301084 int result;
Ajay Singhb61c8062018-12-02 18:03:11 +00001085 struct wilc_wep_key *wep_key;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001086
Ajay Singhb61c8062018-12-02 18:03:11 +00001087 wid_list[0].id = WID_11I_MODE;
1088 wid_list[0].type = WID_CHAR;
1089 wid_list[0].size = sizeof(char);
1090 wid_list[0].val = &mode;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001091
Ajay Singhb61c8062018-12-02 18:03:11 +00001092 wid_list[1].id = WID_AUTH_TYPE;
1093 wid_list[1].type = WID_CHAR;
1094 wid_list[1].size = sizeof(char);
1095 wid_list[1].val = (s8 *)&auth_type;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001096
Ajay Singhb61c8062018-12-02 18:03:11 +00001097 wid_list[2].id = WID_WEP_KEY_VALUE;
1098 wid_list[2].type = WID_STR;
1099 wid_list[2].size = sizeof(*wep_key) + len;
1100 wep_key = kzalloc(wid_list[2].size, GFP_KERNEL);
1101 if (!wep_key)
1102 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001103
Ajay Singhb61c8062018-12-02 18:03:11 +00001104 wid_list[2].val = (u8 *)wep_key;
Ajay Singhff52a572018-06-26 11:37:05 +05301105
Ajay Singhb61c8062018-12-02 18:03:11 +00001106 wep_key->index = index;
1107 wep_key->key_len = len;
1108 memcpy(wep_key->key, key, len);
1109 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
Ajay Singh93592a62019-06-26 12:41:04 +00001110 ARRAY_SIZE(wid_list));
Ajay Singhff52a572018-06-26 11:37:05 +05301111 if (result)
Ajay Singhb61c8062018-12-02 18:03:11 +00001112 netdev_err(vif->ndev,
1113 "Failed to add wep ap key config packet\n");
Ajay Singhff52a572018-06-26 11:37:05 +05301114
Ajay Singhb61c8062018-12-02 18:03:11 +00001115 kfree(wep_key);
Ajay Singhff52a572018-06-26 11:37:05 +05301116 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001117}
Glen Lee108b3432015-09-16 18:53:20 +09001118
Glen Leefbf53792015-12-21 14:18:40 +09001119int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len,
1120 const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic,
1121 u8 mode, u8 cipher_mode, u8 index)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001122{
Ajay Singhb61c8062018-12-02 18:03:11 +00001123 int result = 0;
Ajay Singhf5436ed2019-02-07 11:29:01 +00001124 u8 t_key_len = ptk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
Luis de Bethencourt78c87592015-06-26 16:45:14 +02001125
Ajay Singhd0e41ef2018-11-12 05:45:29 +00001126 if (mode == WILC_AP_MODE) {
Ajay Singhb61c8062018-12-02 18:03:11 +00001127 struct wid wid_list[2];
1128 struct wilc_ap_wpa_ptk *key_buf;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001129
Ajay Singhb61c8062018-12-02 18:03:11 +00001130 wid_list[0].id = WID_11I_MODE;
1131 wid_list[0].type = WID_CHAR;
1132 wid_list[0].size = sizeof(char);
1133 wid_list[0].val = (s8 *)&cipher_mode;
1134
1135 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1136 if (!key_buf)
1137 return -ENOMEM;
1138
1139 ether_addr_copy(key_buf->mac_addr, mac_addr);
1140 key_buf->index = index;
1141 key_buf->key_len = t_key_len;
1142 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1143
1144 if (rx_mic)
1145 memcpy(&key_buf->key[ptk_key_len], rx_mic,
Ajay Singhf5436ed2019-02-07 11:29:01 +00001146 WILC_RX_MIC_KEY_LEN);
Ajay Singhb61c8062018-12-02 18:03:11 +00001147
1148 if (tx_mic)
Ajay Singhf5436ed2019-02-07 11:29:01 +00001149 memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1150 tx_mic, WILC_TX_MIC_KEY_LEN);
Ajay Singhb61c8062018-12-02 18:03:11 +00001151
1152 wid_list[1].id = WID_ADD_PTK;
1153 wid_list[1].type = WID_STR;
1154 wid_list[1].size = sizeof(*key_buf) + t_key_len;
1155 wid_list[1].val = (u8 *)key_buf;
1156 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
Ajay Singh93592a62019-06-26 12:41:04 +00001157 ARRAY_SIZE(wid_list));
Ajay Singhb61c8062018-12-02 18:03:11 +00001158 kfree(key_buf);
1159 } else if (mode == WILC_STATION_MODE) {
1160 struct wid wid;
1161 struct wilc_sta_wpa_ptk *key_buf;
1162
1163 key_buf = kzalloc(sizeof(*key_buf) + t_key_len, GFP_KERNEL);
1164 if (!key_buf)
1165 return -ENOMEM;
1166
1167 ether_addr_copy(key_buf->mac_addr, mac_addr);
1168 key_buf->key_len = t_key_len;
1169 memcpy(&key_buf->key[0], ptk, ptk_key_len);
1170
1171 if (rx_mic)
1172 memcpy(&key_buf->key[ptk_key_len], rx_mic,
Ajay Singhf5436ed2019-02-07 11:29:01 +00001173 WILC_RX_MIC_KEY_LEN);
Ajay Singhb61c8062018-12-02 18:03:11 +00001174
1175 if (tx_mic)
Ajay Singhf5436ed2019-02-07 11:29:01 +00001176 memcpy(&key_buf->key[ptk_key_len + WILC_RX_MIC_KEY_LEN],
1177 tx_mic, WILC_TX_MIC_KEY_LEN);
Ajay Singhb61c8062018-12-02 18:03:11 +00001178
1179 wid.id = WID_ADD_PTK;
1180 wid.type = WID_STR;
1181 wid.size = sizeof(*key_buf) + t_key_len;
1182 wid.val = (s8 *)key_buf;
Ajay Singh93592a62019-06-26 12:41:04 +00001183 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singhb61c8062018-12-02 18:03:11 +00001184 kfree(key_buf);
Ajay Singhff52a572018-06-26 11:37:05 +05301185 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001186
Ajay Singhff52a572018-06-26 11:37:05 +05301187 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001188}
1189
Glen Leefbf53792015-12-21 14:18:40 +09001190int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
1191 u8 index, u32 key_rsc_len, const u8 *key_rsc,
1192 const u8 *rx_mic, const u8 *tx_mic, u8 mode,
1193 u8 cipher_mode)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001194{
Ajay Singhb61c8062018-12-02 18:03:11 +00001195 int result = 0;
1196 struct wilc_gtk_key *gtk_key;
Ajay Singhf5436ed2019-02-07 11:29:01 +00001197 int t_key_len = gtk_key_len + WILC_RX_MIC_KEY_LEN + WILC_TX_MIC_KEY_LEN;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001198
Ajay Singhb61c8062018-12-02 18:03:11 +00001199 gtk_key = kzalloc(sizeof(*gtk_key) + t_key_len, GFP_KERNEL);
1200 if (!gtk_key)
1201 return -ENOMEM;
Ajay Singhff52a572018-06-26 11:37:05 +05301202
Ajay Singhb61c8062018-12-02 18:03:11 +00001203 /* fill bssid value only in station mode */
1204 if (mode == WILC_STATION_MODE &&
1205 vif->hif_drv->hif_state == HOST_IF_CONNECTED)
1206 memcpy(gtk_key->mac_addr, vif->hif_drv->assoc_bssid, ETH_ALEN);
1207
1208 if (key_rsc)
1209 memcpy(gtk_key->rsc, key_rsc, 8);
1210 gtk_key->index = index;
1211 gtk_key->key_len = t_key_len;
1212 memcpy(&gtk_key->key[0], rx_gtk, gtk_key_len);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001213
Chaehyun Lim6d36c272015-11-08 16:49:12 +09001214 if (rx_mic)
Ajay Singhf5436ed2019-02-07 11:29:01 +00001215 memcpy(&gtk_key->key[gtk_key_len], rx_mic, WILC_RX_MIC_KEY_LEN);
Leo Kim91109e12015-10-19 18:26:13 +09001216
Chaehyun Lim2f797582015-11-08 16:49:13 +09001217 if (tx_mic)
Ajay Singhf5436ed2019-02-07 11:29:01 +00001218 memcpy(&gtk_key->key[gtk_key_len + WILC_RX_MIC_KEY_LEN],
1219 tx_mic, WILC_TX_MIC_KEY_LEN);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001220
Ajay Singhd0e41ef2018-11-12 05:45:29 +00001221 if (mode == WILC_AP_MODE) {
Ajay Singhb61c8062018-12-02 18:03:11 +00001222 struct wid wid_list[2];
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001223
Ajay Singhb61c8062018-12-02 18:03:11 +00001224 wid_list[0].id = WID_11I_MODE;
1225 wid_list[0].type = WID_CHAR;
1226 wid_list[0].size = sizeof(char);
1227 wid_list[0].val = (s8 *)&cipher_mode;
1228
1229 wid_list[1].id = WID_ADD_RX_GTK;
1230 wid_list[1].type = WID_STR;
1231 wid_list[1].size = sizeof(*gtk_key) + t_key_len;
1232 wid_list[1].val = (u8 *)gtk_key;
1233
1234 result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
Ajay Singh93592a62019-06-26 12:41:04 +00001235 ARRAY_SIZE(wid_list));
Ajay Singhb61c8062018-12-02 18:03:11 +00001236 } else if (mode == WILC_STATION_MODE) {
1237 struct wid wid;
1238
1239 wid.id = WID_ADD_RX_GTK;
1240 wid.type = WID_STR;
1241 wid.size = sizeof(*gtk_key) + t_key_len;
1242 wid.val = (u8 *)gtk_key;
Ajay Singh93592a62019-06-26 12:41:04 +00001243 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh3b5f10d2018-03-26 17:16:01 +05301244 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001245
Gustavo A. R. Silvafe2570f2018-12-22 03:08:15 -06001246 kfree(gtk_key);
Ajay Singhff52a572018-06-26 11:37:05 +05301247 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001248}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001249
Ajay Singhb61c8062018-12-02 18:03:11 +00001250int wilc_set_pmkid_info(struct wilc_vif *vif, struct wilc_pmkid_attr *pmkid)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001251{
Ajay Singhb61c8062018-12-02 18:03:11 +00001252 struct wid wid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001253
Ajay Singhb61c8062018-12-02 18:03:11 +00001254 wid.id = WID_PMKID_INFO;
1255 wid.type = WID_STR;
1256 wid.size = (pmkid->numpmkid * sizeof(struct wilc_pmkid)) + 1;
1257 wid.val = (u8 *)pmkid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001258
Ajay Singh93592a62019-06-26 12:41:04 +00001259 return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001260}
1261
Chaehyun Lim1eabfe32015-12-22 09:49:07 +09001262int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001263{
Ajay Singhd2418772018-07-19 04:15:16 +05301264 int result;
Ajay Singh153068b2018-12-02 18:03:17 +00001265 struct wid wid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001266
Ajay Singh153068b2018-12-02 18:03:17 +00001267 wid.id = WID_MAC_ADDR;
1268 wid.type = WID_STR;
1269 wid.size = ETH_ALEN;
1270 wid.val = mac_addr;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001271
Ajay Singh93592a62019-06-26 12:41:04 +00001272 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301273 if (result)
Ajay Singh153068b2018-12-02 18:03:17 +00001274 netdev_err(vif->ndev, "Failed to get mac address\n");
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301275
Leo Kim31390ee2015-10-19 18:26:08 +09001276 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001277}
1278
Ajay Singh734c3192019-01-17 13:21:32 +00001279int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ies,
1280 size_t ies_len)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001281{
Ajay Singhd2418772018-07-19 04:15:16 +05301282 int result;
Glen Leefbf53792015-12-21 14:18:40 +09001283 struct host_if_drv *hif_drv = vif->hif_drv;
Ajay Singh734c3192019-01-17 13:21:32 +00001284 struct wilc_conn_info *conn_info = &hif_drv->conn_info;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001285
Ajay Singh734c3192019-01-17 13:21:32 +00001286 if (bssid)
1287 ether_addr_copy(conn_info->bssid, bssid);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001288
Chaehyun Lim88c94212015-12-24 16:52:24 +09001289 if (ies) {
Ajay Singh734c3192019-01-17 13:21:32 +00001290 conn_info->req_ies_len = ies_len;
1291 conn_info->req_ies = kmemdup(ies, ies_len, GFP_KERNEL);
Nishka Dasgupta953137522019-03-22 01:25:55 +05301292 if (!conn_info->req_ies)
1293 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001294 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001295
Ajay Singhe5596812018-12-02 18:03:31 +00001296 result = wilc_send_connect_wid(vif);
1297 if (result)
Ajay Singhff52a572018-06-26 11:37:05 +05301298 goto free_ies;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001299
Kees Cook1f233192017-10-16 16:24:32 -07001300 hif_drv->connect_timer_vif = vif;
Leo Kim81a59502015-10-29 11:58:35 +09001301 mod_timer(&hif_drv->connect_timer,
Ajay Singhb36b9732019-02-02 19:17:05 +00001302 jiffies + msecs_to_jiffies(WILC_HIF_CONNECT_TIMEOUT_MS));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001303
Ajay Singhff52a572018-06-26 11:37:05 +05301304 return 0;
1305
1306free_ies:
Ajay Singh734c3192019-01-17 13:21:32 +00001307 kfree(conn_info->req_ies);
Ajay Singhff52a572018-06-26 11:37:05 +05301308
Leo Kim31390ee2015-10-19 18:26:08 +09001309 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001310}
1311
Glen Leefbf53792015-12-21 14:18:40 +09001312int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001313{
Ajay Singh77506d42018-12-02 18:02:54 +00001314 struct wid wid;
Chaehyun Lim792fb252015-10-05 11:07:22 +09001315 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001316
Ajay Singh77506d42018-12-02 18:02:54 +00001317 wid.id = WID_CURRENT_CHANNEL;
1318 wid.type = WID_CHAR;
1319 wid.size = sizeof(char);
1320 wid.val = &channel;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001321
Ajay Singh93592a62019-06-26 12:41:04 +00001322 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh77506d42018-12-02 18:02:54 +00001323 if (result)
1324 netdev_err(vif->ndev, "Failed to set channel\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001325
Ajay Singhff52a572018-06-26 11:37:05 +05301326 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001327}
1328
Adham Abozaeid4b1b8b02019-08-01 20:15:11 +00001329int wilc_set_operation_mode(struct wilc_vif *vif, int index, u8 mode,
1330 u8 ifc_id)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001331{
Ajay Singh04a61fb2018-12-02 18:03:05 +00001332 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301333 int result;
Ajay Singh04a61fb2018-12-02 18:03:05 +00001334 struct wilc_drv_handler drv;
Leo Kimc09389a2015-10-28 15:59:24 +09001335
Adham Abozaeid4b1b8b02019-08-01 20:15:11 +00001336 wid.id = WID_SET_OPERATION_MODE;
Ajay Singh04a61fb2018-12-02 18:03:05 +00001337 wid.type = WID_STR;
1338 wid.size = sizeof(drv);
1339 wid.val = (u8 *)&drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001340
Ajay Singh04a61fb2018-12-02 18:03:05 +00001341 drv.handler = cpu_to_le32(index);
1342 drv.mode = (ifc_id | (mode << 1));
Ajay Singhff52a572018-06-26 11:37:05 +05301343
Ajay Singh93592a62019-06-26 12:41:04 +00001344 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh04a61fb2018-12-02 18:03:05 +00001345 if (result)
1346 netdev_err(vif->ndev, "Failed to set driver handler\n");
Ajay Singh39996812018-09-25 11:53:34 +05301347
Chaehyun Lima0941012015-10-05 19:34:47 +09001348 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001349}
1350
Ajay Singh98651ca2018-12-02 18:03:08 +00001351s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *out_val)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001352{
Ajay Singh98651ca2018-12-02 18:03:08 +00001353 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301354 s32 result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001355
Ajay Singh98651ca2018-12-02 18:03:08 +00001356 wid.id = WID_SET_STA_MAC_INACTIVE_TIME;
1357 wid.type = WID_STR;
1358 wid.size = ETH_ALEN;
1359 wid.val = kzalloc(wid.size, GFP_KERNEL);
1360 if (!wid.val)
1361 return -ENOMEM;
1362
1363 ether_addr_copy(wid.val, mac);
Ajay Singh93592a62019-06-26 12:41:04 +00001364 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh98651ca2018-12-02 18:03:08 +00001365 kfree(wid.val);
1366 if (result) {
1367 netdev_err(vif->ndev, "Failed to set inactive mac\n");
1368 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001369 }
1370
Ajay Singh98651ca2018-12-02 18:03:08 +00001371 wid.id = WID_GET_INACTIVE_TIME;
1372 wid.type = WID_INT;
1373 wid.val = (s8 *)out_val;
1374 wid.size = sizeof(u32);
Ajay Singh93592a62019-06-26 12:41:04 +00001375 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301376 if (result)
Ajay Singh98651ca2018-12-02 18:03:08 +00001377 netdev_err(vif->ndev, "Failed to get inactive time\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001378
Leo Kim31390ee2015-10-19 18:26:08 +09001379 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001380}
Glen Lee108b3432015-09-16 18:53:20 +09001381
Chaehyun Lim652bb5e2015-12-24 16:52:37 +09001382int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001383{
Ajay Singhdaf04832018-12-02 18:02:59 +00001384 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301385 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001386
Chaehyun Lim652bb5e2015-12-24 16:52:37 +09001387 if (!rssi_level) {
Ajay Singha120adb82018-07-29 11:36:53 +05301388 netdev_err(vif->ndev, "%s: RSSI level is NULL\n", __func__);
Leo Kime6e12662015-09-16 18:36:03 +09001389 return -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001390 }
1391
Ajay Singhdaf04832018-12-02 18:02:59 +00001392 wid.id = WID_RSSI;
1393 wid.type = WID_CHAR;
1394 wid.size = sizeof(char);
1395 wid.val = rssi_level;
Ajay Singh93592a62019-06-26 12:41:04 +00001396 result = wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
Ajay Singhdaf04832018-12-02 18:02:59 +00001397 if (result)
1398 netdev_err(vif->ndev, "Failed to get RSSI value\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001399
Leo Kim31390ee2015-10-19 18:26:08 +09001400 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001401}
1402
Marko Stankovic2f6fa4c2018-12-25 23:35:31 +01001403static int wilc_get_stats_async(struct wilc_vif *vif, struct rf_info *stats)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001404{
Ajay Singhd2418772018-07-19 04:15:16 +05301405 int result;
Ajay Singhff52a572018-06-26 11:37:05 +05301406 struct host_if_msg *msg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001407
Ajay Singh19cb25e12018-12-02 18:03:25 +00001408 msg = wilc_alloc_work(vif, handle_get_statistics, false);
Ajay Singhff52a572018-06-26 11:37:05 +05301409 if (IS_ERR(msg))
1410 return PTR_ERR(msg);
Leo Kimae4dfa52015-10-13 19:49:26 +09001411
Ajay Singhff52a572018-06-26 11:37:05 +05301412 msg->body.data = (char *)stats;
1413
Ajay Singhc6a358d2018-06-26 11:37:08 +05301414 result = wilc_enqueue_work(msg);
Leo Kim31390ee2015-10-19 18:26:08 +09001415 if (result) {
Ajay Singha120adb82018-07-29 11:36:53 +05301416 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
Ajay Singhff52a572018-06-26 11:37:05 +05301417 kfree(msg);
1418 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001419 }
1420
Leo Kim31390ee2015-10-19 18:26:08 +09001421 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001422}
1423
Ajay Singh53239172018-12-02 18:02:57 +00001424int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_attr *param)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001425{
Ajay Singh53239172018-12-02 18:02:57 +00001426 struct wid wid_list[4];
1427 int i = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001428
Ajay Singh53239172018-12-02 18:02:57 +00001429 if (param->flag & WILC_CFG_PARAM_RETRY_SHORT) {
1430 wid_list[i].id = WID_SHORT_RETRY_LIMIT;
1431 wid_list[i].val = (s8 *)&param->short_retry_limit;
1432 wid_list[i].type = WID_SHORT;
1433 wid_list[i].size = sizeof(u16);
1434 i++;
1435 }
1436 if (param->flag & WILC_CFG_PARAM_RETRY_LONG) {
1437 wid_list[i].id = WID_LONG_RETRY_LIMIT;
1438 wid_list[i].val = (s8 *)&param->long_retry_limit;
1439 wid_list[i].type = WID_SHORT;
1440 wid_list[i].size = sizeof(u16);
1441 i++;
1442 }
1443 if (param->flag & WILC_CFG_PARAM_FRAG_THRESHOLD) {
1444 wid_list[i].id = WID_FRAG_THRESHOLD;
1445 wid_list[i].val = (s8 *)&param->frag_threshold;
1446 wid_list[i].type = WID_SHORT;
1447 wid_list[i].size = sizeof(u16);
1448 i++;
1449 }
1450 if (param->flag & WILC_CFG_PARAM_RTS_THRESHOLD) {
1451 wid_list[i].id = WID_RTS_THRESHOLD;
1452 wid_list[i].val = (s8 *)&param->rts_threshold;
1453 wid_list[i].type = WID_SHORT;
1454 wid_list[i].size = sizeof(u16);
1455 i++;
Leo Kim24db7132015-09-16 18:36:01 +09001456 }
Leo Kimae4dfa52015-10-13 19:49:26 +09001457
Ajay Singh93592a62019-06-26 12:41:04 +00001458 return wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list, i);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001459}
1460
Ajay Singh5fefe582018-09-04 12:09:28 +05301461static void get_periodic_rssi(struct timer_list *t)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001462{
Ajay Singh5fefe582018-09-04 12:09:28 +05301463 struct wilc_vif *vif = from_timer(vif, t, periodic_rssi);
Luis de Bethencourt78c87592015-06-26 16:45:14 +02001464
Glen Lee71130e82015-12-21 14:18:41 +09001465 if (!vif->hif_drv) {
Ajay Singha120adb82018-07-29 11:36:53 +05301466 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001467 return;
1468 }
1469
Glen Lee4fd62292016-02-04 18:15:24 +09001470 if (vif->hif_drv->hif_state == HOST_IF_CONNECTED)
Ajay Singh19cb25e12018-12-02 18:03:25 +00001471 wilc_get_stats_async(vif, &vif->periodic_stat);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001472
Ajay Singh5fefe582018-09-04 12:09:28 +05301473 mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001474}
1475
Chaehyun Lim1e995c12016-01-05 23:06:57 +09001476int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001477{
Tony Choa4ab1ad2015-10-12 16:56:05 +09001478 struct host_if_drv *hif_drv;
Ajay Singh6bcba962018-07-19 04:15:19 +05301479 struct wilc_vif *vif = netdev_priv(dev);
1480 struct wilc *wilc = vif->wilc;
Glen Leed53822192015-10-27 18:27:49 +09001481
sayli karnikfaa48ea2016-09-16 16:23:02 +05301482 hif_drv = kzalloc(sizeof(*hif_drv), GFP_KERNEL);
Ajay Singh4b255c62018-04-23 22:03:31 +05301483 if (!hif_drv)
1484 return -ENOMEM;
1485
Tony Choa4ab1ad2015-10-12 16:56:05 +09001486 *hif_drv_handler = hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001487
Ajay Singh264a4722019-06-26 12:40:58 +00001488 vif->hif_drv = hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001489
Ajay Singh39996812018-09-25 11:53:34 +05301490 if (wilc->clients_count == 0)
Ajay Singh98f83d32019-02-05 07:15:54 +00001491 mutex_init(&wilc->deinit_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001492
Ajay Singh5fefe582018-09-04 12:09:28 +05301493 timer_setup(&vif->periodic_rssi, get_periodic_rssi, 0);
1494 mod_timer(&vif->periodic_rssi, jiffies + msecs_to_jiffies(5000));
1495
Ajay Singh4189eb52018-02-19 20:59:40 +05301496 timer_setup(&hif_drv->scan_timer, timer_scan_cb, 0);
1497 timer_setup(&hif_drv->connect_timer, timer_connect_cb, 0);
Ajay Singhb44c3862018-02-19 20:59:41 +05301498 timer_setup(&hif_drv->remain_on_ch_timer, listen_timer_cb, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001499
Leo Kimb60005a2015-10-29 11:58:24 +09001500 hif_drv->hif_state = HOST_IF_IDLE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001501
Leo Kim1229b1a2015-10-29 12:05:39 +09001502 hif_drv->p2p_timeout = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001503
Ajay Singh0b683342018-09-04 12:09:25 +05301504 wilc->clients_count++;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001505
Ajay Singh4b255c62018-04-23 22:03:31 +05301506 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001507}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001508
Chaehyun Lim127a27c2016-02-05 10:35:13 +09001509int wilc_deinit(struct wilc_vif *vif)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001510{
Chaehyun Lim127a27c2016-02-05 10:35:13 +09001511 int result = 0;
Glen Leefbf53792015-12-21 14:18:40 +09001512 struct host_if_drv *hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001513
Ajay Singh74cffaf2018-07-19 04:15:11 +05301514 if (!hif_drv) {
Ajay Singha120adb82018-07-29 11:36:53 +05301515 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
Chaehyun Lim8eb62f32016-02-05 10:35:14 +09001516 return -EFAULT;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001517 }
1518
Ajay Singh98f83d32019-02-05 07:15:54 +00001519 mutex_lock(&vif->wilc->deinit_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001520
Chris Parkc4f97522016-02-04 18:24:04 +09001521 del_timer_sync(&hif_drv->scan_timer);
1522 del_timer_sync(&hif_drv->connect_timer);
Ajay Singh5fefe582018-09-04 12:09:28 +05301523 del_timer_sync(&vif->periodic_rssi);
Leo Kimcc2d7e92015-10-29 11:58:36 +09001524 del_timer_sync(&hif_drv->remain_on_ch_timer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001525
Leo Kimbc801852015-10-29 11:58:50 +09001526 if (hif_drv->usr_scan_req.scan_result) {
1527 hif_drv->usr_scan_req.scan_result(SCAN_EVENT_ABORTED, NULL,
Ajay Singh6c2cfb42019-01-17 13:21:18 +00001528 hif_drv->usr_scan_req.arg);
Leo Kimbc801852015-10-29 11:58:50 +09001529 hif_drv->usr_scan_req.scan_result = NULL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001530 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001531
Leo Kimb60005a2015-10-29 11:58:24 +09001532 hif_drv->hif_state = HOST_IF_IDLE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001533
Tony Choa4ab1ad2015-10-12 16:56:05 +09001534 kfree(hif_drv);
Ajay Singh3c55a242019-02-05 07:15:31 +00001535 vif->hif_drv = NULL;
Ajay Singh0b683342018-09-04 12:09:25 +05301536 vif->wilc->clients_count--;
Ajay Singh98f83d32019-02-05 07:15:54 +00001537 mutex_unlock(&vif->wilc->deinit_lock);
Leo Kim31390ee2015-10-19 18:26:08 +09001538 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001539}
1540
Tahia Khanbdb27e62017-03-07 19:26:41 -05001541void wilc_network_info_received(struct wilc *wilc, u8 *buffer, u32 length)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001542{
Ajay Singh82120ec2018-07-19 04:15:17 +05301543 int result;
Ajay Singhff52a572018-06-26 11:37:05 +05301544 struct host_if_msg *msg;
Johnny Kimd42ab082015-08-20 16:32:52 +09001545 int id;
Ajay Singhd2418772018-07-19 04:15:16 +05301546 struct host_if_drv *hif_drv;
Glen Leeeb9939b2015-12-21 14:18:43 +09001547 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001548
Ajay Singh92f6de42019-01-17 13:21:10 +00001549 id = get_unaligned_le32(&buffer[length - 4]);
Glen Leeeb9939b2015-12-21 14:18:43 +09001550 vif = wilc_get_vif_from_idx(wilc, id);
1551 if (!vif)
1552 return;
1553 hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001554
Ajay Singh3c55a242019-02-05 07:15:31 +00001555 if (!hif_drv) {
Chris Parkb92f9302016-02-22 13:12:02 +09001556 netdev_err(vif->ndev, "driver not init[%p]\n", hif_drv);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001557 return;
1558 }
1559
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301560 msg = wilc_alloc_work(vif, handle_rcvd_ntwrk_info, false);
Ajay Singhff52a572018-06-26 11:37:05 +05301561 if (IS_ERR(msg))
Ajay Singh25b951332018-03-26 17:15:56 +05301562 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001563
Ajay Singh6cd4fa52019-01-17 13:21:21 +00001564 msg->body.net_info.frame_len = get_unaligned_le16(&buffer[6]) - 1;
1565 msg->body.net_info.rssi = buffer[8];
1566 msg->body.net_info.mgmt = kmemdup(&buffer[9],
1567 msg->body.net_info.frame_len,
1568 GFP_KERNEL);
1569 if (!msg->body.net_info.mgmt) {
Ajay Singhff52a572018-06-26 11:37:05 +05301570 kfree(msg);
1571 return;
1572 }
1573
Ajay Singhc6a358d2018-06-26 11:37:08 +05301574 result = wilc_enqueue_work(msg);
Ajay Singh25b951332018-03-26 17:15:56 +05301575 if (result) {
Ajay Singha120adb82018-07-29 11:36:53 +05301576 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
Ajay Singh6cd4fa52019-01-17 13:21:21 +00001577 kfree(msg->body.net_info.mgmt);
Ajay Singhff52a572018-06-26 11:37:05 +05301578 kfree(msg);
Ajay Singh25b951332018-03-26 17:15:56 +05301579 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001580}
1581
Tahia Khan28c82852017-03-07 19:26:44 -05001582void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *buffer, u32 length)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001583{
Ajay Singh82120ec2018-07-19 04:15:17 +05301584 int result;
Ajay Singhff52a572018-06-26 11:37:05 +05301585 struct host_if_msg *msg;
Johnny Kimd42ab082015-08-20 16:32:52 +09001586 int id;
Ajay Singhd2418772018-07-19 04:15:16 +05301587 struct host_if_drv *hif_drv;
Glen Leeeb9939b2015-12-21 14:18:43 +09001588 struct wilc_vif *vif;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001589
Ajay Singh98f83d32019-02-05 07:15:54 +00001590 mutex_lock(&wilc->deinit_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001591
Ajay Singh92f6de42019-01-17 13:21:10 +00001592 id = get_unaligned_le32(&buffer[length - 4]);
Glen Leeeb9939b2015-12-21 14:18:43 +09001593 vif = wilc_get_vif_from_idx(wilc, id);
1594 if (!vif) {
Ajay Singh98f83d32019-02-05 07:15:54 +00001595 mutex_unlock(&wilc->deinit_lock);
Glen Leeeb9939b2015-12-21 14:18:43 +09001596 return;
1597 }
1598
1599 hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001600
Ajay Singh3c55a242019-02-05 07:15:31 +00001601 if (!hif_drv) {
Ajay Singh98f83d32019-02-05 07:15:54 +00001602 mutex_unlock(&wilc->deinit_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001603 return;
1604 }
1605
Ajay Singh734c3192019-01-17 13:21:32 +00001606 if (!hif_drv->conn_info.conn_result) {
Ajay Singha120adb82018-07-29 11:36:53 +05301607 netdev_err(vif->ndev, "%s: conn_result is NULL\n", __func__);
Ajay Singh98f83d32019-02-05 07:15:54 +00001608 mutex_unlock(&wilc->deinit_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001609 return;
1610 }
1611
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301612 msg = wilc_alloc_work(vif, handle_rcvd_gnrl_async_info, false);
Ajay Singhff52a572018-06-26 11:37:05 +05301613 if (IS_ERR(msg)) {
Ajay Singh98f83d32019-02-05 07:15:54 +00001614 mutex_unlock(&wilc->deinit_lock);
Ajay Singhfe014d42018-03-26 17:16:03 +05301615 return;
1616 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001617
Ajay Singh94bb6d32019-01-17 13:21:35 +00001618 msg->body.mac_info.status = buffer[7];
Ajay Singhc6a358d2018-06-26 11:37:08 +05301619 result = wilc_enqueue_work(msg);
Ajay Singhfe014d42018-03-26 17:16:03 +05301620 if (result) {
Ajay Singha120adb82018-07-29 11:36:53 +05301621 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
Ajay Singhff52a572018-06-26 11:37:05 +05301622 kfree(msg);
Ajay Singhfe014d42018-03-26 17:16:03 +05301623 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001624
Ajay Singh98f83d32019-02-05 07:15:54 +00001625 mutex_unlock(&wilc->deinit_lock);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001626}
1627
Tahia Khandade3c62017-03-07 19:26:37 -05001628void wilc_scan_complete_received(struct wilc *wilc, u8 *buffer, u32 length)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001629{
Ajay Singh82120ec2018-07-19 04:15:17 +05301630 int result;
Johnny Kimd42ab082015-08-20 16:32:52 +09001631 int id;
Ajay Singhd2418772018-07-19 04:15:16 +05301632 struct host_if_drv *hif_drv;
Glen Leeeb9939b2015-12-21 14:18:43 +09001633 struct wilc_vif *vif;
Luis de Bethencourt78c87592015-06-26 16:45:14 +02001634
Ajay Singh92f6de42019-01-17 13:21:10 +00001635 id = get_unaligned_le32(&buffer[length - 4]);
Glen Leeeb9939b2015-12-21 14:18:43 +09001636 vif = wilc_get_vif_from_idx(wilc, id);
1637 if (!vif)
1638 return;
1639 hif_drv = vif->hif_drv;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001640
Ajay Singh3c55a242019-02-05 07:15:31 +00001641 if (!hif_drv)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001642 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001643
Leo Kimbc801852015-10-29 11:58:50 +09001644 if (hif_drv->usr_scan_req.scan_result) {
Ajay Singhff52a572018-06-26 11:37:05 +05301645 struct host_if_msg *msg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001646
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301647 msg = wilc_alloc_work(vif, handle_scan_complete, false);
Ajay Singhff52a572018-06-26 11:37:05 +05301648 if (IS_ERR(msg))
1649 return;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001650
Ajay Singhc6a358d2018-06-26 11:37:08 +05301651 result = wilc_enqueue_work(msg);
Ajay Singhff52a572018-06-26 11:37:05 +05301652 if (result) {
Ajay Singha120adb82018-07-29 11:36:53 +05301653 netdev_err(vif->ndev, "%s: enqueue work failed\n",
1654 __func__);
Ajay Singhff52a572018-06-26 11:37:05 +05301655 kfree(msg);
1656 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001657 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001658}
1659
Ajay Singhb6c6cd12019-02-05 07:15:39 +00001660int wilc_remain_on_channel(struct wilc_vif *vif, u64 cookie,
Chaehyun Limd44cd452016-01-03 17:35:36 +09001661 u32 duration, u16 chan,
Ajay Singhb6c6cd12019-02-05 07:15:39 +00001662 void (*expired)(void *, u64),
Chaehyun Lim482c4332016-01-03 17:35:39 +09001663 void *user_arg)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001664{
Ajay Singhf5436ed2019-02-07 11:29:01 +00001665 struct wilc_remain_ch roc;
Ajay Singhd2418772018-07-19 04:15:16 +05301666 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001667
Ajay Singh05d3bcb2018-12-02 18:03:22 +00001668 roc.ch = chan;
1669 roc.expired = expired;
Ajay Singh05d3bcb2018-12-02 18:03:22 +00001670 roc.arg = user_arg;
1671 roc.duration = duration;
Ajay Singhb6c6cd12019-02-05 07:15:39 +00001672 roc.cookie = cookie;
Ajay Singh05d3bcb2018-12-02 18:03:22 +00001673 result = handle_remain_on_chan(vif, &roc);
1674 if (result)
1675 netdev_err(vif->ndev, "%s: failed to set remain on channel\n",
1676 __func__);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001677
Leo Kim31390ee2015-10-19 18:26:08 +09001678 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001679}
1680
Ajay Singhb6c6cd12019-02-05 07:15:39 +00001681int wilc_listen_state_expired(struct wilc_vif *vif, u64 cookie)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001682{
Ajay Singh424a6112019-06-26 12:40:45 +00001683 if (!vif->hif_drv) {
Ajay Singha120adb82018-07-29 11:36:53 +05301684 netdev_err(vif->ndev, "%s: hif driver is NULL", __func__);
Leo Kim24db7132015-09-16 18:36:01 +09001685 return -EFAULT;
1686 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001687
Ajay Singh424a6112019-06-26 12:40:45 +00001688 del_timer(&vif->hif_drv->remain_on_ch_timer);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001689
Ajay Singh424a6112019-06-26 12:40:45 +00001690 return wilc_handle_roc_expired(vif, cookie);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001691}
1692
Ajay Singhe8de0ac2018-09-25 11:53:16 +05301693void wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001694{
Ajay Singh147ccfd2018-12-02 18:02:51 +00001695 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301696 int result;
Ajay Singh147ccfd2018-12-02 18:02:51 +00001697 struct wilc_reg_frame reg_frame;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001698
Ajay Singh147ccfd2018-12-02 18:02:51 +00001699 wid.id = WID_REGISTER_FRAME;
1700 wid.type = WID_STR;
1701 wid.size = sizeof(reg_frame);
1702 wid.val = (u8 *)&reg_frame;
1703
1704 memset(&reg_frame, 0x0, sizeof(reg_frame));
Ajay Singh5e3bafb2019-11-05 09:51:22 +00001705
1706 if (reg)
1707 reg_frame.reg = 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001708
Chaehyun Lim2a8432f2015-12-30 21:15:26 +09001709 switch (frame_type) {
Ajay Singh2bae2932018-11-12 05:45:03 +00001710 case IEEE80211_STYPE_ACTION:
Ajay Singh147ccfd2018-12-02 18:02:51 +00001711 reg_frame.reg_id = WILC_FW_ACTION_FRM_IDX;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001712 break;
1713
Ajay Singh2bae2932018-11-12 05:45:03 +00001714 case IEEE80211_STYPE_PROBE_REQ:
Ajay Singh147ccfd2018-12-02 18:02:51 +00001715 reg_frame.reg_id = WILC_FW_PROBE_REQ_IDX;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001716 break;
1717
1718 default:
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001719 break;
1720 }
Ajay Singh147ccfd2018-12-02 18:02:51 +00001721 reg_frame.frame_type = cpu_to_le16(frame_type);
Ajay Singh93592a62019-06-26 12:41:04 +00001722 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh147ccfd2018-12-02 18:02:51 +00001723 if (result)
1724 netdev_err(vif->ndev, "Failed to frame register\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001725}
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001726
Chaehyun Lim916935f2016-01-03 17:35:57 +09001727int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period,
Ajay Singh976c89b2018-12-02 18:02:48 +00001728 struct cfg80211_beacon_data *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001729{
Ajay Singh976c89b2018-12-02 18:02:48 +00001730 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301731 int result;
Ajay Singh976c89b2018-12-02 18:02:48 +00001732 u8 *cur_byte;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001733
Ajay Singh976c89b2018-12-02 18:02:48 +00001734 wid.id = WID_ADD_BEACON;
1735 wid.type = WID_BIN;
1736 wid.size = params->head_len + params->tail_len + 16;
1737 wid.val = kzalloc(wid.size, GFP_KERNEL);
1738 if (!wid.val)
1739 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001740
Ajay Singh976c89b2018-12-02 18:02:48 +00001741 cur_byte = wid.val;
1742 put_unaligned_le32(interval, cur_byte);
1743 cur_byte += 4;
1744 put_unaligned_le32(dtim_period, cur_byte);
1745 cur_byte += 4;
1746 put_unaligned_le32(params->head_len, cur_byte);
1747 cur_byte += 4;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001748
Ajay Singh976c89b2018-12-02 18:02:48 +00001749 if (params->head_len > 0)
1750 memcpy(cur_byte, params->head, params->head_len);
1751 cur_byte += params->head_len;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001752
Ajay Singh976c89b2018-12-02 18:02:48 +00001753 put_unaligned_le32(params->tail_len, cur_byte);
1754 cur_byte += 4;
1755
1756 if (params->tail_len > 0)
1757 memcpy(cur_byte, params->tail, params->tail_len);
1758
Ajay Singh93592a62019-06-26 12:41:04 +00001759 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Leo Kim31390ee2015-10-19 18:26:08 +09001760 if (result)
Ajay Singh976c89b2018-12-02 18:02:48 +00001761 netdev_err(vif->ndev, "Failed to send add beacon\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001762
Ajay Singh976c89b2018-12-02 18:02:48 +00001763 kfree(wid.val);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001764
Leo Kim31390ee2015-10-19 18:26:08 +09001765 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001766}
1767
Glen Leefbf53792015-12-21 14:18:40 +09001768int wilc_del_beacon(struct wilc_vif *vif)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001769{
Ajay Singhd2418772018-07-19 04:15:16 +05301770 int result;
Ajay Singh38b3ffa2018-12-02 18:02:45 +00001771 struct wid wid;
1772 u8 del_beacon = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001773
Ajay Singh38b3ffa2018-12-02 18:02:45 +00001774 wid.id = WID_DEL_BEACON;
1775 wid.type = WID_CHAR;
1776 wid.size = sizeof(char);
1777 wid.val = &del_beacon;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001778
Ajay Singh93592a62019-06-26 12:41:04 +00001779 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh38b3ffa2018-12-02 18:02:45 +00001780 if (result)
1781 netdev_err(vif->ndev, "Failed to send delete beacon\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001782
Leo Kim31390ee2015-10-19 18:26:08 +09001783 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001784}
1785
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001786int wilc_add_station(struct wilc_vif *vif, const u8 *mac,
1787 struct station_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001788{
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001789 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301790 int result;
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001791 u8 *cur_byte;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001792
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001793 wid.id = WID_ADD_STA;
1794 wid.type = WID_BIN;
1795 wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
1796 wid.val = kmalloc(wid.size, GFP_KERNEL);
1797 if (!wid.val)
1798 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001799
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001800 cur_byte = wid.val;
Ajay Singh6133ed92018-12-02 18:02:36 +00001801 wilc_hif_pack_sta_param(cur_byte, mac, params);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001802
Ajay Singh93592a62019-06-26 12:41:04 +00001803 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001804 if (result != 0)
1805 netdev_err(vif->ndev, "Failed to send add station\n");
1806
1807 kfree(wid.val);
1808
Leo Kim31390ee2015-10-19 18:26:08 +09001809 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001810}
1811
Glen Leefbf53792015-12-21 14:18:40 +09001812int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001813{
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001814 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301815 int result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001816
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001817 wid.id = WID_REMOVE_STA;
1818 wid.type = WID_BIN;
1819 wid.size = ETH_ALEN;
1820 wid.val = kzalloc(wid.size, GFP_KERNEL);
1821 if (!wid.val)
1822 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001823
Chaehyun Limc9c4eb42015-11-06 19:11:14 +09001824 if (!mac_addr)
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001825 eth_broadcast_addr(wid.val);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001826 else
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001827 ether_addr_copy(wid.val, mac_addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001828
Ajay Singh93592a62019-06-26 12:41:04 +00001829 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001830 if (result)
1831 netdev_err(vif->ndev, "Failed to del station\n");
1832
1833 kfree(wid.val);
1834
Leo Kim31390ee2015-10-19 18:26:08 +09001835 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001836}
Leo Kimae4dfa52015-10-13 19:49:26 +09001837
Chaehyun Lim2092374d2016-01-03 17:35:50 +09001838int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN])
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001839{
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001840 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301841 int result;
Chaehyun Limcc971ee2016-01-03 17:35:53 +09001842 int i;
Chaehyun Lim9d6cec92016-01-03 17:35:54 +09001843 u8 assoc_sta = 0;
Ajay Singhf5436ed2019-02-07 11:29:01 +00001844 struct wilc_del_all_sta del_sta;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001845
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001846 memset(&del_sta, 0x0, sizeof(del_sta));
Ajay Singhd0e41ef2018-11-12 05:45:29 +00001847 for (i = 0; i < WILC_MAX_NUM_STA; i++) {
Ajay Singh4c00f702018-12-02 18:02:43 +00001848 if (!is_zero_ether_addr(mac_addr[i])) {
Chaehyun Lim9d6cec92016-01-03 17:35:54 +09001849 assoc_sta++;
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001850 ether_addr_copy(del_sta.mac[i], mac_addr[i]);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001851 }
1852 }
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001853
1854 if (!assoc_sta)
Ajay Singhff52a572018-06-26 11:37:05 +05301855 return 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001856
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001857 del_sta.assoc_sta = assoc_sta;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001858
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001859 wid.id = WID_DEL_ALL_STA;
1860 wid.type = WID_STR;
1861 wid.size = (assoc_sta * ETH_ALEN) + 1;
1862 wid.val = (u8 *)&del_sta;
1863
Ajay Singh93592a62019-06-26 12:41:04 +00001864 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301865 if (result)
Ajay Singh9f1bdb72018-12-02 18:02:40 +00001866 netdev_err(vif->ndev, "Failed to send delete all station\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001867
Leo Kim31390ee2015-10-19 18:26:08 +09001868 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001869}
1870
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001871int wilc_edit_station(struct wilc_vif *vif, const u8 *mac,
1872 struct station_parameters *params)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001873{
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001874 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301875 int result;
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001876 u8 *cur_byte;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001877
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001878 wid.id = WID_EDIT_STA;
1879 wid.type = WID_BIN;
1880 wid.size = WILC_ADD_STA_LENGTH + params->supported_rates_len;
1881 wid.val = kmalloc(wid.size, GFP_KERNEL);
1882 if (!wid.val)
1883 return -ENOMEM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001884
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001885 cur_byte = wid.val;
Ajay Singh6133ed92018-12-02 18:02:36 +00001886 wilc_hif_pack_sta_param(cur_byte, mac, params);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001887
Ajay Singh93592a62019-06-26 12:41:04 +00001888 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001889 if (result)
1890 netdev_err(vif->ndev, "Failed to send edit station\n");
Leo Kim24db7132015-09-16 18:36:01 +09001891
Ajay Singh78c0c4e2018-12-02 18:02:34 +00001892 kfree(wid.val);
Leo Kim31390ee2015-10-19 18:26:08 +09001893 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001894}
Glen Lee108b3432015-09-16 18:53:20 +09001895
Chaehyun Limecd27502015-12-30 21:15:32 +09001896int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001897{
Ajay Singhcf6d0602018-12-02 18:02:31 +00001898 struct wid wid;
Ajay Singhd2418772018-07-19 04:15:16 +05301899 int result;
Ajay Singhcf6d0602018-12-02 18:02:31 +00001900 s8 power_mode;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001901
Ajay Singhcf6d0602018-12-02 18:02:31 +00001902 if (enabled)
1903 power_mode = WILC_FW_MIN_FAST_PS;
1904 else
1905 power_mode = WILC_FW_NO_POWERSAVE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001906
Ajay Singhcf6d0602018-12-02 18:02:31 +00001907 wid.id = WID_POWER_MANAGEMENT;
1908 wid.val = &power_mode;
1909 wid.size = sizeof(char);
Ajay Singh93592a62019-06-26 12:41:04 +00001910 result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Ajay Singhcf6d0602018-12-02 18:02:31 +00001911 if (result)
1912 netdev_err(vif->ndev, "Failed to send power management\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001913
Leo Kim31390ee2015-10-19 18:26:08 +09001914 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001915}
1916
Ajay Singha0c6a322019-01-17 13:21:41 +00001917int wilc_setup_multicast_filter(struct wilc_vif *vif, u32 enabled, u32 count,
Ajay Singhe624c582018-09-04 12:09:26 +05301918 u8 *mc_list)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001919{
Ajay Singhd2418772018-07-19 04:15:16 +05301920 int result;
Ajay Singhff52a572018-06-26 11:37:05 +05301921 struct host_if_msg *msg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001922
Ajay Singh5e6f8a82018-06-26 11:37:06 +05301923 msg = wilc_alloc_work(vif, handle_set_mcast_filter, false);
Ajay Singhff52a572018-06-26 11:37:05 +05301924 if (IS_ERR(msg))
1925 return PTR_ERR(msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001926
Ajay Singha0c6a322019-01-17 13:21:41 +00001927 msg->body.mc_info.enabled = enabled;
1928 msg->body.mc_info.cnt = count;
1929 msg->body.mc_info.mc_list = mc_list;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001930
Ajay Singhc6a358d2018-06-26 11:37:08 +05301931 result = wilc_enqueue_work(msg);
Ajay Singhff52a572018-06-26 11:37:05 +05301932 if (result) {
Ajay Singha120adb82018-07-29 11:36:53 +05301933 netdev_err(vif->ndev, "%s: enqueue work failed\n", __func__);
Ajay Singhff52a572018-06-26 11:37:05 +05301934 kfree(msg);
1935 }
Leo Kim31390ee2015-10-19 18:26:08 +09001936 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001937}
1938
Glen Lee70418792016-02-04 18:15:27 +09001939int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power)
1940{
Ajay Singh430d0ec2018-12-02 18:02:28 +00001941 struct wid wid;
Glen Lee70418792016-02-04 18:15:27 +09001942
Ajay Singh430d0ec2018-12-02 18:02:28 +00001943 wid.id = WID_TX_POWER;
1944 wid.type = WID_CHAR;
1945 wid.val = &tx_power;
1946 wid.size = sizeof(char);
Glen Lee70418792016-02-04 18:15:27 +09001947
Ajay Singh93592a62019-06-26 12:41:04 +00001948 return wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1);
Glen Lee70418792016-02-04 18:15:27 +09001949}
1950
1951int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power)
1952{
Ajay Singh430d0ec2018-12-02 18:02:28 +00001953 struct wid wid;
Glen Lee70418792016-02-04 18:15:27 +09001954
Ajay Singh430d0ec2018-12-02 18:02:28 +00001955 wid.id = WID_TX_POWER;
1956 wid.type = WID_CHAR;
1957 wid.val = tx_power;
1958 wid.size = sizeof(char);
Glen Lee70418792016-02-04 18:15:27 +09001959
Ajay Singh93592a62019-06-26 12:41:04 +00001960 return wilc_send_config_pkt(vif, WILC_GET_CFG, &wid, 1);
Glen Lee70418792016-02-04 18:15:27 +09001961}