Merge remote-tracking branches 'asoc/fix/adsp', 'asoc/fix/arizona', 'asoc/fix/atmel...
[linux-drm-fsl-dcu.git] / drivers / net / wireless / ath / wcn36xx / smd.c
1 /*
2  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19 #include <linux/etherdevice.h>
20 #include <linux/firmware.h>
21 #include <linux/bitops.h>
22 #include "smd.h"
23
24 static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
25 {
26         struct wcn36xx_hal_cfg *entry;
27         u32 *val;
28
29         if (*len + sizeof(*entry) + sizeof(u32) >= WCN36XX_HAL_BUF_SIZE) {
30                 wcn36xx_err("Not enough room for TLV entry\n");
31                 return -ENOMEM;
32         }
33
34         entry = (struct wcn36xx_hal_cfg *) (wcn->hal_buf + *len);
35         entry->id = id;
36         entry->len = sizeof(u32);
37         entry->pad_bytes = 0;
38         entry->reserve = 0;
39
40         val = (u32 *) (entry + 1);
41         *val = value;
42
43         *len += sizeof(*entry) + sizeof(u32);
44
45         return 0;
46 }
47
48 static void wcn36xx_smd_set_bss_nw_type(struct wcn36xx *wcn,
49                 struct ieee80211_sta *sta,
50                 struct wcn36xx_hal_config_bss_params *bss_params)
51 {
52         if (IEEE80211_BAND_5GHZ == WCN36XX_BAND(wcn))
53                 bss_params->nw_type = WCN36XX_HAL_11A_NW_TYPE;
54         else if (sta && sta->ht_cap.ht_supported)
55                 bss_params->nw_type = WCN36XX_HAL_11N_NW_TYPE;
56         else if (sta && (sta->supp_rates[IEEE80211_BAND_2GHZ] & 0x7f))
57                 bss_params->nw_type = WCN36XX_HAL_11G_NW_TYPE;
58         else
59                 bss_params->nw_type = WCN36XX_HAL_11B_NW_TYPE;
60 }
61
62 static inline u8 is_cap_supported(unsigned long caps, unsigned long flag)
63 {
64         return caps & flag ? 1 : 0;
65 }
66 static void wcn36xx_smd_set_bss_ht_params(struct ieee80211_vif *vif,
67                 struct ieee80211_sta *sta,
68                 struct wcn36xx_hal_config_bss_params *bss_params)
69 {
70         if (sta && sta->ht_cap.ht_supported) {
71                 unsigned long caps = sta->ht_cap.cap;
72                 bss_params->ht = sta->ht_cap.ht_supported;
73                 bss_params->tx_channel_width_set = is_cap_supported(caps,
74                         IEEE80211_HT_CAP_SUP_WIDTH_20_40);
75                 bss_params->lsig_tx_op_protection_full_support =
76                         is_cap_supported(caps,
77                                          IEEE80211_HT_CAP_LSIG_TXOP_PROT);
78
79                 bss_params->ht_oper_mode = vif->bss_conf.ht_operation_mode;
80                 bss_params->lln_non_gf_coexist =
81                         !!(vif->bss_conf.ht_operation_mode &
82                            IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
83                 /* IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT */
84                 bss_params->dual_cts_protection = 0;
85                 /* IEEE80211_HT_OP_MODE_PROTECTION_20MHZ */
86                 bss_params->ht20_coexist = 0;
87         }
88 }
89
90 static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
91                 struct wcn36xx_hal_config_sta_params *sta_params)
92 {
93         if (sta->ht_cap.ht_supported) {
94                 unsigned long caps = sta->ht_cap.cap;
95                 sta_params->ht_capable = sta->ht_cap.ht_supported;
96                 sta_params->tx_channel_width_set = is_cap_supported(caps,
97                         IEEE80211_HT_CAP_SUP_WIDTH_20_40);
98                 sta_params->lsig_txop_protection = is_cap_supported(caps,
99                         IEEE80211_HT_CAP_LSIG_TXOP_PROT);
100
101                 sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
102                 sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
103                 sta_params->max_amsdu_size = is_cap_supported(caps,
104                         IEEE80211_HT_CAP_MAX_AMSDU);
105                 sta_params->sgi_20Mhz = is_cap_supported(caps,
106                         IEEE80211_HT_CAP_SGI_20);
107                 sta_params->sgi_40mhz = is_cap_supported(caps,
108                         IEEE80211_HT_CAP_SGI_40);
109                 sta_params->green_field_capable = is_cap_supported(caps,
110                         IEEE80211_HT_CAP_GRN_FLD);
111                 sta_params->delayed_ba_support = is_cap_supported(caps,
112                         IEEE80211_HT_CAP_DELAY_BA);
113                 sta_params->dsss_cck_mode_40mhz = is_cap_supported(caps,
114                         IEEE80211_HT_CAP_DSSSCCK40);
115         }
116 }
117
118 static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
119                 struct ieee80211_vif *vif,
120                 struct ieee80211_sta *sta,
121                 struct wcn36xx_hal_config_sta_params *sta_params)
122 {
123         struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
124         struct wcn36xx_sta *priv_sta = NULL;
125         if (vif->type == NL80211_IFTYPE_ADHOC ||
126             vif->type == NL80211_IFTYPE_AP ||
127             vif->type == NL80211_IFTYPE_MESH_POINT) {
128                 sta_params->type = 1;
129                 sta_params->sta_index = 0xFF;
130         } else {
131                 sta_params->type = 0;
132                 sta_params->sta_index = 1;
133         }
134
135         sta_params->listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
136
137         /*
138          * In STA mode ieee80211_sta contains bssid and ieee80211_vif
139          * contains our mac address. In  AP mode we are bssid so vif
140          * contains bssid and ieee80211_sta contains mac.
141          */
142         if (NL80211_IFTYPE_STATION == vif->type)
143                 memcpy(&sta_params->mac, vif->addr, ETH_ALEN);
144         else
145                 memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
146
147         sta_params->encrypt_type = priv_vif->encrypt_type;
148         sta_params->short_preamble_supported =
149                 !(WCN36XX_FLAGS(wcn) &
150                   IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE);
151
152         sta_params->rifs_mode = 0;
153         sta_params->rmf = 0;
154         sta_params->action = 0;
155         sta_params->uapsd = 0;
156         sta_params->mimo_ps = WCN36XX_HAL_HT_MIMO_PS_STATIC;
157         sta_params->max_ampdu_duration = 0;
158         sta_params->bssid_index = priv_vif->bss_index;
159         sta_params->p2p = 0;
160
161         if (sta) {
162                 priv_sta = (struct wcn36xx_sta *)sta->drv_priv;
163                 if (NL80211_IFTYPE_STATION == vif->type)
164                         memcpy(&sta_params->bssid, sta->addr, ETH_ALEN);
165                 else
166                         memcpy(&sta_params->mac, sta->addr, ETH_ALEN);
167                 sta_params->wmm_enabled = sta->wme;
168                 sta_params->max_sp_len = sta->max_sp;
169                 sta_params->aid = priv_sta->aid;
170                 wcn36xx_smd_set_sta_ht_params(sta, sta_params);
171                 memcpy(&sta_params->supported_rates, &priv_sta->supported_rates,
172                         sizeof(priv_sta->supported_rates));
173         } else {
174                 wcn36xx_set_default_rates(&sta_params->supported_rates);
175         }
176 }
177
178 static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len)
179 {
180         int ret = 0;
181         wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len);
182
183         init_completion(&wcn->hal_rsp_compl);
184         ret = wcn->ctrl_ops->tx(wcn->hal_buf, len);
185         if (ret) {
186                 wcn36xx_err("HAL TX failed\n");
187                 goto out;
188         }
189         if (wait_for_completion_timeout(&wcn->hal_rsp_compl,
190                 msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) {
191                 wcn36xx_err("Timeout while waiting SMD response\n");
192                 ret = -ETIME;
193                 goto out;
194         }
195 out:
196         return ret;
197 }
198
199 #define INIT_HAL_MSG(msg_body, type) \
200         do {                                                            \
201                 memset(&msg_body, 0, sizeof(msg_body));                 \
202                 msg_body.header.msg_type = type;                        \
203                 msg_body.header.msg_version = WCN36XX_HAL_MSG_VERSION0; \
204                 msg_body.header.len = sizeof(msg_body);                 \
205         } while (0)                                                     \
206
207 #define PREPARE_HAL_BUF(send_buf, msg_body) \
208         do {                                                    \
209                 memset(send_buf, 0, msg_body.header.len);       \
210                 memcpy(send_buf, &msg_body, sizeof(msg_body));  \
211         } while (0)                                             \
212
213 static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
214 {
215         struct wcn36xx_fw_msg_status_rsp *rsp;
216
217         if (len < sizeof(struct wcn36xx_hal_msg_header) +
218             sizeof(struct wcn36xx_fw_msg_status_rsp))
219                 return -EIO;
220
221         rsp = (struct wcn36xx_fw_msg_status_rsp *)
222                 (buf + sizeof(struct wcn36xx_hal_msg_header));
223
224         if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
225                 return rsp->status;
226
227         return 0;
228 }
229
230 int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
231 {
232         const struct firmware *nv;
233         struct nv_data *nv_d;
234         struct wcn36xx_hal_nv_img_download_req_msg msg_body;
235         int fw_bytes_left;
236         int ret;
237         u16 fm_offset = 0;
238
239         ret = request_firmware(&nv, WLAN_NV_FILE, wcn->dev);
240         if (ret) {
241                 wcn36xx_err("Failed to load nv file %s: %d\n",
242                               WLAN_NV_FILE, ret);
243                 goto out_free_nv;
244         }
245
246         nv_d = (struct nv_data *)nv->data;
247         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DOWNLOAD_NV_REQ);
248
249         msg_body.header.len += WCN36XX_NV_FRAGMENT_SIZE;
250
251         msg_body.frag_number = 0;
252         /* hal_buf must be protected with  mutex */
253         mutex_lock(&wcn->hal_mutex);
254
255         do {
256                 fw_bytes_left = nv->size - fm_offset - 4;
257                 if (fw_bytes_left > WCN36XX_NV_FRAGMENT_SIZE) {
258                         msg_body.last_fragment = 0;
259                         msg_body.nv_img_buffer_size = WCN36XX_NV_FRAGMENT_SIZE;
260                 } else {
261                         msg_body.last_fragment = 1;
262                         msg_body.nv_img_buffer_size = fw_bytes_left;
263
264                         /* Do not forget update general message len */
265                         msg_body.header.len = sizeof(msg_body) + fw_bytes_left;
266
267                 }
268
269                 /* Add load NV request message header */
270                 memcpy(wcn->hal_buf, &msg_body, sizeof(msg_body));
271
272                 /* Add NV body itself */
273                 memcpy(wcn->hal_buf + sizeof(msg_body),
274                        &nv_d->table + fm_offset,
275                        msg_body.nv_img_buffer_size);
276
277                 ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
278                 if (ret)
279                         goto out_unlock;
280                 ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf,
281                                                    wcn->hal_rsp_len);
282                 if (ret) {
283                         wcn36xx_err("hal_load_nv response failed err=%d\n",
284                                     ret);
285                         goto out_unlock;
286                 }
287                 msg_body.frag_number++;
288                 fm_offset += WCN36XX_NV_FRAGMENT_SIZE;
289
290         } while (msg_body.last_fragment != 1);
291
292 out_unlock:
293         mutex_unlock(&wcn->hal_mutex);
294 out_free_nv:
295         release_firmware(nv);
296
297         return ret;
298 }
299
300 static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
301 {
302         struct wcn36xx_hal_mac_start_rsp_msg *rsp;
303
304         if (len < sizeof(*rsp))
305                 return -EIO;
306
307         rsp = (struct wcn36xx_hal_mac_start_rsp_msg *)buf;
308
309         if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->start_rsp_params.status)
310                 return -EIO;
311
312         memcpy(wcn->crm_version, rsp->start_rsp_params.crm_version,
313                WCN36XX_HAL_VERSION_LENGTH);
314         memcpy(wcn->wlan_version, rsp->start_rsp_params.wlan_version,
315                WCN36XX_HAL_VERSION_LENGTH);
316
317         /* null terminate the strings, just in case */
318         wcn->crm_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
319         wcn->wlan_version[WCN36XX_HAL_VERSION_LENGTH] = '\0';
320
321         wcn->fw_revision = rsp->start_rsp_params.version.revision;
322         wcn->fw_version = rsp->start_rsp_params.version.version;
323         wcn->fw_minor = rsp->start_rsp_params.version.minor;
324         wcn->fw_major = rsp->start_rsp_params.version.major;
325
326         wcn36xx_info("firmware WLAN version '%s' and CRM version '%s'\n",
327                      wcn->wlan_version, wcn->crm_version);
328
329         wcn36xx_info("firmware API %u.%u.%u.%u, %u stations, %u bssids\n",
330                      wcn->fw_major, wcn->fw_minor,
331                      wcn->fw_version, wcn->fw_revision,
332                      rsp->start_rsp_params.stations,
333                      rsp->start_rsp_params.bssids);
334
335         return 0;
336 }
337
338 int wcn36xx_smd_start(struct wcn36xx *wcn)
339 {
340         struct wcn36xx_hal_mac_start_req_msg msg_body;
341         int ret = 0;
342
343         mutex_lock(&wcn->hal_mutex);
344         INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
345
346         msg_body.params.type = DRIVER_TYPE_PRODUCTION;
347         msg_body.params.len = 0;
348
349         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
350
351         wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
352                     msg_body.params.type);
353
354         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
355         if (ret) {
356                 wcn36xx_err("Sending hal_start failed\n");
357                 goto out;
358         }
359
360         ret = wcn36xx_smd_start_rsp(wcn, wcn->hal_buf, wcn->hal_rsp_len);
361         if (ret) {
362                 wcn36xx_err("hal_start response failed err=%d\n", ret);
363                 goto out;
364         }
365
366 out:
367         mutex_unlock(&wcn->hal_mutex);
368         return ret;
369 }
370
371 int wcn36xx_smd_stop(struct wcn36xx *wcn)
372 {
373         struct wcn36xx_hal_mac_stop_req_msg msg_body;
374         int ret = 0;
375
376         mutex_lock(&wcn->hal_mutex);
377         INIT_HAL_MSG(msg_body, WCN36XX_HAL_STOP_REQ);
378
379         msg_body.stop_req_params.reason = HAL_STOP_TYPE_RF_KILL;
380
381         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
382
383         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
384         if (ret) {
385                 wcn36xx_err("Sending hal_stop failed\n");
386                 goto out;
387         }
388         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
389         if (ret) {
390                 wcn36xx_err("hal_stop response failed err=%d\n", ret);
391                 goto out;
392         }
393 out:
394         mutex_unlock(&wcn->hal_mutex);
395         return ret;
396 }
397
398 int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode)
399 {
400         struct wcn36xx_hal_init_scan_req_msg msg_body;
401         int ret = 0;
402
403         mutex_lock(&wcn->hal_mutex);
404         INIT_HAL_MSG(msg_body, WCN36XX_HAL_INIT_SCAN_REQ);
405
406         msg_body.mode = mode;
407
408         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
409
410         wcn36xx_dbg(WCN36XX_DBG_HAL, "hal init scan mode %d\n", msg_body.mode);
411
412         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
413         if (ret) {
414                 wcn36xx_err("Sending hal_init_scan failed\n");
415                 goto out;
416         }
417         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
418         if (ret) {
419                 wcn36xx_err("hal_init_scan response failed err=%d\n", ret);
420                 goto out;
421         }
422 out:
423         mutex_unlock(&wcn->hal_mutex);
424         return ret;
425 }
426
427 int wcn36xx_smd_start_scan(struct wcn36xx *wcn)
428 {
429         struct wcn36xx_hal_start_scan_req_msg msg_body;
430         int ret = 0;
431
432         mutex_lock(&wcn->hal_mutex);
433         INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ);
434
435         msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
436
437         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
438
439         wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start scan channel %d\n",
440                     msg_body.scan_channel);
441
442         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
443         if (ret) {
444                 wcn36xx_err("Sending hal_start_scan failed\n");
445                 goto out;
446         }
447         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
448         if (ret) {
449                 wcn36xx_err("hal_start_scan response failed err=%d\n", ret);
450                 goto out;
451         }
452 out:
453         mutex_unlock(&wcn->hal_mutex);
454         return ret;
455 }
456
457 int wcn36xx_smd_end_scan(struct wcn36xx *wcn)
458 {
459         struct wcn36xx_hal_end_scan_req_msg msg_body;
460         int ret = 0;
461
462         mutex_lock(&wcn->hal_mutex);
463         INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ);
464
465         msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn);
466
467         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
468
469         wcn36xx_dbg(WCN36XX_DBG_HAL, "hal end scan channel %d\n",
470                     msg_body.scan_channel);
471
472         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
473         if (ret) {
474                 wcn36xx_err("Sending hal_end_scan failed\n");
475                 goto out;
476         }
477         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
478         if (ret) {
479                 wcn36xx_err("hal_end_scan response failed err=%d\n", ret);
480                 goto out;
481         }
482 out:
483         mutex_unlock(&wcn->hal_mutex);
484         return ret;
485 }
486
487 int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
488                             enum wcn36xx_hal_sys_mode mode)
489 {
490         struct wcn36xx_hal_finish_scan_req_msg msg_body;
491         int ret = 0;
492
493         mutex_lock(&wcn->hal_mutex);
494         INIT_HAL_MSG(msg_body, WCN36XX_HAL_FINISH_SCAN_REQ);
495
496         msg_body.mode = mode;
497
498         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
499
500         wcn36xx_dbg(WCN36XX_DBG_HAL, "hal finish scan mode %d\n",
501                     msg_body.mode);
502
503         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
504         if (ret) {
505                 wcn36xx_err("Sending hal_finish_scan failed\n");
506                 goto out;
507         }
508         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
509         if (ret) {
510                 wcn36xx_err("hal_finish_scan response failed err=%d\n", ret);
511                 goto out;
512         }
513 out:
514         mutex_unlock(&wcn->hal_mutex);
515         return ret;
516 }
517
518 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
519 {
520         struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
521         int ret = 0;
522
523         ret = wcn36xx_smd_rsp_status_check(buf, len);
524         if (ret)
525                 return ret;
526         rsp = (struct wcn36xx_hal_switch_channel_rsp_msg *)buf;
527         wcn36xx_dbg(WCN36XX_DBG_HAL, "channel switched to: %d, status: %d\n",
528                     rsp->channel_number, rsp->status);
529         return ret;
530 }
531
532 int wcn36xx_smd_switch_channel(struct wcn36xx *wcn,
533                                struct ieee80211_vif *vif, int ch)
534 {
535         struct wcn36xx_hal_switch_channel_req_msg msg_body;
536         int ret = 0;
537
538         mutex_lock(&wcn->hal_mutex);
539         INIT_HAL_MSG(msg_body, WCN36XX_HAL_CH_SWITCH_REQ);
540
541         msg_body.channel_number = (u8)ch;
542         msg_body.tx_mgmt_power = 0xbf;
543         msg_body.max_tx_power = 0xbf;
544         memcpy(msg_body.self_sta_mac_addr, vif->addr, ETH_ALEN);
545
546         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
547
548         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
549         if (ret) {
550                 wcn36xx_err("Sending hal_switch_channel failed\n");
551                 goto out;
552         }
553         ret = wcn36xx_smd_switch_channel_rsp(wcn->hal_buf, wcn->hal_rsp_len);
554         if (ret) {
555                 wcn36xx_err("hal_switch_channel response failed err=%d\n", ret);
556                 goto out;
557         }
558 out:
559         mutex_unlock(&wcn->hal_mutex);
560         return ret;
561 }
562
563 static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
564 {
565         struct wcn36xx_hal_update_scan_params_resp *rsp;
566
567         rsp = (struct wcn36xx_hal_update_scan_params_resp *)buf;
568
569         /* Remove the PNO version bit */
570         rsp->status &= (~(WCN36XX_FW_MSG_PNO_VERSION_MASK));
571
572         if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status) {
573                 wcn36xx_warn("error response from update scan\n");
574                 return rsp->status;
575         }
576
577         return 0;
578 }
579
580 int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
581 {
582         struct wcn36xx_hal_update_scan_params_req msg_body;
583         int ret = 0;
584
585         mutex_lock(&wcn->hal_mutex);
586         INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
587
588         msg_body.dot11d_enabled = 0;
589         msg_body.dot11d_resolved = 0;
590         msg_body.channel_count = 26;
591         msg_body.active_min_ch_time = 60;
592         msg_body.active_max_ch_time = 120;
593         msg_body.passive_min_ch_time = 60;
594         msg_body.passive_max_ch_time = 110;
595         msg_body.state = 0;
596
597         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
598
599         wcn36xx_dbg(WCN36XX_DBG_HAL,
600                     "hal update scan params channel_count %d\n",
601                     msg_body.channel_count);
602
603         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
604         if (ret) {
605                 wcn36xx_err("Sending hal_update_scan_params failed\n");
606                 goto out;
607         }
608         ret = wcn36xx_smd_update_scan_params_rsp(wcn->hal_buf,
609                                                  wcn->hal_rsp_len);
610         if (ret) {
611                 wcn36xx_err("hal_update_scan_params response failed err=%d\n",
612                             ret);
613                 goto out;
614         }
615 out:
616         mutex_unlock(&wcn->hal_mutex);
617         return ret;
618 }
619
620 static int wcn36xx_smd_add_sta_self_rsp(struct wcn36xx *wcn,
621                                         struct ieee80211_vif *vif,
622                                         void *buf,
623                                         size_t len)
624 {
625         struct wcn36xx_hal_add_sta_self_rsp_msg *rsp;
626         struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
627
628         if (len < sizeof(*rsp))
629                 return -EINVAL;
630
631         rsp = (struct wcn36xx_hal_add_sta_self_rsp_msg *)buf;
632
633         if (rsp->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
634                 wcn36xx_warn("hal add sta self failure: %d\n",
635                              rsp->status);
636                 return rsp->status;
637         }
638
639         wcn36xx_dbg(WCN36XX_DBG_HAL,
640                     "hal add sta self status %d self_sta_index %d dpu_index %d\n",
641                     rsp->status, rsp->self_sta_index, rsp->dpu_index);
642
643         priv_vif->self_sta_index = rsp->self_sta_index;
644         priv_vif->self_dpu_desc_index = rsp->dpu_index;
645
646         return 0;
647 }
648
649 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif)
650 {
651         struct wcn36xx_hal_add_sta_self_req msg_body;
652         int ret = 0;
653
654         mutex_lock(&wcn->hal_mutex);
655         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_STA_SELF_REQ);
656
657         memcpy(&msg_body.self_addr, vif->addr, ETH_ALEN);
658
659         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
660
661         wcn36xx_dbg(WCN36XX_DBG_HAL,
662                     "hal add sta self self_addr %pM status %d\n",
663                     msg_body.self_addr, msg_body.status);
664
665         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
666         if (ret) {
667                 wcn36xx_err("Sending hal_add_sta_self failed\n");
668                 goto out;
669         }
670         ret = wcn36xx_smd_add_sta_self_rsp(wcn,
671                                            vif,
672                                            wcn->hal_buf,
673                                            wcn->hal_rsp_len);
674         if (ret) {
675                 wcn36xx_err("hal_add_sta_self response failed err=%d\n", ret);
676                 goto out;
677         }
678 out:
679         mutex_unlock(&wcn->hal_mutex);
680         return ret;
681 }
682
683 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr)
684 {
685         struct wcn36xx_hal_del_sta_self_req_msg msg_body;
686         int ret = 0;
687
688         mutex_lock(&wcn->hal_mutex);
689         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_STA_SELF_REQ);
690
691         memcpy(&msg_body.self_addr, addr, ETH_ALEN);
692
693         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
694
695         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
696         if (ret) {
697                 wcn36xx_err("Sending hal_delete_sta_self failed\n");
698                 goto out;
699         }
700         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
701         if (ret) {
702                 wcn36xx_err("hal_delete_sta_self response failed err=%d\n",
703                             ret);
704                 goto out;
705         }
706 out:
707         mutex_unlock(&wcn->hal_mutex);
708         return ret;
709 }
710
711 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index)
712 {
713         struct wcn36xx_hal_delete_sta_req_msg msg_body;
714         int ret = 0;
715
716         mutex_lock(&wcn->hal_mutex);
717         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_STA_REQ);
718
719         msg_body.sta_index = sta_index;
720
721         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
722
723         wcn36xx_dbg(WCN36XX_DBG_HAL,
724                     "hal delete sta sta_index %d\n",
725                     msg_body.sta_index);
726
727         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
728         if (ret) {
729                 wcn36xx_err("Sending hal_delete_sta failed\n");
730                 goto out;
731         }
732         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
733         if (ret) {
734                 wcn36xx_err("hal_delete_sta response failed err=%d\n", ret);
735                 goto out;
736         }
737 out:
738         mutex_unlock(&wcn->hal_mutex);
739         return ret;
740 }
741
742 static int wcn36xx_smd_join_rsp(void *buf, size_t len)
743 {
744         struct wcn36xx_hal_join_rsp_msg *rsp;
745
746         if (wcn36xx_smd_rsp_status_check(buf, len))
747                 return -EIO;
748
749         rsp = (struct wcn36xx_hal_join_rsp_msg *)buf;
750
751         wcn36xx_dbg(WCN36XX_DBG_HAL,
752                     "hal rsp join status %d tx_mgmt_power %d\n",
753                     rsp->status, rsp->tx_mgmt_power);
754
755         return 0;
756 }
757
758 int wcn36xx_smd_join(struct wcn36xx *wcn, const u8 *bssid, u8 *vif, u8 ch)
759 {
760         struct wcn36xx_hal_join_req_msg msg_body;
761         int ret = 0;
762
763         mutex_lock(&wcn->hal_mutex);
764         INIT_HAL_MSG(msg_body, WCN36XX_HAL_JOIN_REQ);
765
766         memcpy(&msg_body.bssid, bssid, ETH_ALEN);
767         memcpy(&msg_body.self_sta_mac_addr, vif, ETH_ALEN);
768         msg_body.channel = ch;
769
770         if (conf_is_ht40_minus(&wcn->hw->conf))
771                 msg_body.secondary_channel_offset =
772                         PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
773         else if (conf_is_ht40_plus(&wcn->hw->conf))
774                 msg_body.secondary_channel_offset =
775                         PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
776         else
777                 msg_body.secondary_channel_offset =
778                         PHY_SINGLE_CHANNEL_CENTERED;
779
780         msg_body.link_state = WCN36XX_HAL_LINK_PREASSOC_STATE;
781
782         msg_body.max_tx_power = 0xbf;
783         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
784
785         wcn36xx_dbg(WCN36XX_DBG_HAL,
786                     "hal join req bssid %pM self_sta_mac_addr %pM channel %d link_state %d\n",
787                     msg_body.bssid, msg_body.self_sta_mac_addr,
788                     msg_body.channel, msg_body.link_state);
789
790         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
791         if (ret) {
792                 wcn36xx_err("Sending hal_join failed\n");
793                 goto out;
794         }
795         ret = wcn36xx_smd_join_rsp(wcn->hal_buf, wcn->hal_rsp_len);
796         if (ret) {
797                 wcn36xx_err("hal_join response failed err=%d\n", ret);
798                 goto out;
799         }
800 out:
801         mutex_unlock(&wcn->hal_mutex);
802         return ret;
803 }
804
805 int wcn36xx_smd_set_link_st(struct wcn36xx *wcn, const u8 *bssid,
806                             const u8 *sta_mac,
807                             enum wcn36xx_hal_link_state state)
808 {
809         struct wcn36xx_hal_set_link_state_req_msg msg_body;
810         int ret = 0;
811
812         mutex_lock(&wcn->hal_mutex);
813         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_LINK_ST_REQ);
814
815         memcpy(&msg_body.bssid, bssid, ETH_ALEN);
816         memcpy(&msg_body.self_mac_addr, sta_mac, ETH_ALEN);
817         msg_body.state = state;
818
819         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
820
821         wcn36xx_dbg(WCN36XX_DBG_HAL,
822                     "hal set link state bssid %pM self_mac_addr %pM state %d\n",
823                     msg_body.bssid, msg_body.self_mac_addr, msg_body.state);
824
825         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
826         if (ret) {
827                 wcn36xx_err("Sending hal_set_link_st failed\n");
828                 goto out;
829         }
830         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
831         if (ret) {
832                 wcn36xx_err("hal_set_link_st response failed err=%d\n", ret);
833                 goto out;
834         }
835 out:
836         mutex_unlock(&wcn->hal_mutex);
837         return ret;
838 }
839
840 static void wcn36xx_smd_convert_sta_to_v1(struct wcn36xx *wcn,
841                         const struct wcn36xx_hal_config_sta_params *orig,
842                         struct wcn36xx_hal_config_sta_params_v1 *v1)
843 {
844         /* convert orig to v1 format */
845         memcpy(&v1->bssid, orig->bssid, ETH_ALEN);
846         memcpy(&v1->mac, orig->mac, ETH_ALEN);
847         v1->aid = orig->aid;
848         v1->type = orig->type;
849         v1->listen_interval = orig->listen_interval;
850         v1->ht_capable = orig->ht_capable;
851
852         v1->max_ampdu_size = orig->max_ampdu_size;
853         v1->max_ampdu_density = orig->max_ampdu_density;
854         v1->sgi_40mhz = orig->sgi_40mhz;
855         v1->sgi_20Mhz = orig->sgi_20Mhz;
856
857         memcpy(&v1->supported_rates, &orig->supported_rates,
858                sizeof(orig->supported_rates));
859         v1->sta_index = orig->sta_index;
860 }
861
862 static int wcn36xx_smd_config_sta_rsp(struct wcn36xx *wcn,
863                                       struct ieee80211_sta *sta,
864                                       void *buf,
865                                       size_t len)
866 {
867         struct wcn36xx_hal_config_sta_rsp_msg *rsp;
868         struct config_sta_rsp_params *params;
869         struct wcn36xx_sta *sta_priv = (struct wcn36xx_sta *)sta->drv_priv;
870
871         if (len < sizeof(*rsp))
872                 return -EINVAL;
873
874         rsp = (struct wcn36xx_hal_config_sta_rsp_msg *)buf;
875         params = &rsp->params;
876
877         if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
878                 wcn36xx_warn("hal config sta response failure: %d\n",
879                              params->status);
880                 return -EIO;
881         }
882
883         sta_priv->sta_index = params->sta_index;
884         sta_priv->dpu_desc_index = params->dpu_index;
885
886         wcn36xx_dbg(WCN36XX_DBG_HAL,
887                     "hal config sta rsp status %d sta_index %d bssid_index %d p2p %d\n",
888                     params->status, params->sta_index, params->bssid_index,
889                     params->p2p);
890
891         return 0;
892 }
893
894 static int wcn36xx_smd_config_sta_v1(struct wcn36xx *wcn,
895                      const struct wcn36xx_hal_config_sta_req_msg *orig)
896 {
897         struct wcn36xx_hal_config_sta_req_msg_v1 msg_body;
898         struct wcn36xx_hal_config_sta_params_v1 *sta = &msg_body.sta_params;
899
900         INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_STA_REQ);
901
902         wcn36xx_smd_convert_sta_to_v1(wcn, &orig->sta_params,
903                                       &msg_body.sta_params);
904
905         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
906
907         wcn36xx_dbg(WCN36XX_DBG_HAL,
908                     "hal config sta v1 action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
909                     sta->action, sta->sta_index, sta->bssid_index,
910                     sta->bssid, sta->type, sta->mac, sta->aid);
911
912         return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
913 }
914
915 int wcn36xx_smd_config_sta(struct wcn36xx *wcn, struct ieee80211_vif *vif,
916                            struct ieee80211_sta *sta)
917 {
918         struct wcn36xx_hal_config_sta_req_msg msg;
919         struct wcn36xx_hal_config_sta_params *sta_params;
920         int ret = 0;
921
922         mutex_lock(&wcn->hal_mutex);
923         INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_STA_REQ);
924
925         sta_params = &msg.sta_params;
926
927         wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
928
929         if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
930                 ret = wcn36xx_smd_config_sta_v1(wcn, &msg);
931         } else {
932                 PREPARE_HAL_BUF(wcn->hal_buf, msg);
933
934                 wcn36xx_dbg(WCN36XX_DBG_HAL,
935                             "hal config sta action %d sta_index %d bssid_index %d bssid %pM type %d mac %pM aid %d\n",
936                             sta_params->action, sta_params->sta_index,
937                             sta_params->bssid_index, sta_params->bssid,
938                             sta_params->type, sta_params->mac, sta_params->aid);
939
940                 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
941         }
942         if (ret) {
943                 wcn36xx_err("Sending hal_config_sta failed\n");
944                 goto out;
945         }
946         ret = wcn36xx_smd_config_sta_rsp(wcn,
947                                          sta,
948                                          wcn->hal_buf,
949                                          wcn->hal_rsp_len);
950         if (ret) {
951                 wcn36xx_err("hal_config_sta response failed err=%d\n", ret);
952                 goto out;
953         }
954 out:
955         mutex_unlock(&wcn->hal_mutex);
956         return ret;
957 }
958
959 static int wcn36xx_smd_config_bss_v1(struct wcn36xx *wcn,
960                         const struct wcn36xx_hal_config_bss_req_msg *orig)
961 {
962         struct wcn36xx_hal_config_bss_req_msg_v1 msg_body;
963         struct wcn36xx_hal_config_bss_params_v1 *bss = &msg_body.bss_params;
964         struct wcn36xx_hal_config_sta_params_v1 *sta = &bss->sta;
965
966         INIT_HAL_MSG(msg_body, WCN36XX_HAL_CONFIG_BSS_REQ);
967
968         /* convert orig to v1 */
969         memcpy(&msg_body.bss_params.bssid,
970                &orig->bss_params.bssid, ETH_ALEN);
971         memcpy(&msg_body.bss_params.self_mac_addr,
972                &orig->bss_params.self_mac_addr, ETH_ALEN);
973
974         msg_body.bss_params.bss_type = orig->bss_params.bss_type;
975         msg_body.bss_params.oper_mode = orig->bss_params.oper_mode;
976         msg_body.bss_params.nw_type = orig->bss_params.nw_type;
977
978         msg_body.bss_params.short_slot_time_supported =
979                 orig->bss_params.short_slot_time_supported;
980         msg_body.bss_params.lla_coexist = orig->bss_params.lla_coexist;
981         msg_body.bss_params.llb_coexist = orig->bss_params.llb_coexist;
982         msg_body.bss_params.llg_coexist = orig->bss_params.llg_coexist;
983         msg_body.bss_params.ht20_coexist = orig->bss_params.ht20_coexist;
984         msg_body.bss_params.lln_non_gf_coexist =
985                 orig->bss_params.lln_non_gf_coexist;
986
987         msg_body.bss_params.lsig_tx_op_protection_full_support =
988                 orig->bss_params.lsig_tx_op_protection_full_support;
989         msg_body.bss_params.rifs_mode = orig->bss_params.rifs_mode;
990         msg_body.bss_params.beacon_interval = orig->bss_params.beacon_interval;
991         msg_body.bss_params.dtim_period = orig->bss_params.dtim_period;
992         msg_body.bss_params.tx_channel_width_set =
993                 orig->bss_params.tx_channel_width_set;
994         msg_body.bss_params.oper_channel = orig->bss_params.oper_channel;
995         msg_body.bss_params.ext_channel = orig->bss_params.ext_channel;
996
997         msg_body.bss_params.reserved = orig->bss_params.reserved;
998
999         memcpy(&msg_body.bss_params.ssid,
1000                &orig->bss_params.ssid,
1001                sizeof(orig->bss_params.ssid));
1002
1003         msg_body.bss_params.action = orig->bss_params.action;
1004         msg_body.bss_params.rateset = orig->bss_params.rateset;
1005         msg_body.bss_params.ht = orig->bss_params.ht;
1006         msg_body.bss_params.obss_prot_enabled =
1007                 orig->bss_params.obss_prot_enabled;
1008         msg_body.bss_params.rmf = orig->bss_params.rmf;
1009         msg_body.bss_params.ht_oper_mode = orig->bss_params.ht_oper_mode;
1010         msg_body.bss_params.dual_cts_protection =
1011                 orig->bss_params.dual_cts_protection;
1012
1013         msg_body.bss_params.max_probe_resp_retry_limit =
1014                 orig->bss_params.max_probe_resp_retry_limit;
1015         msg_body.bss_params.hidden_ssid = orig->bss_params.hidden_ssid;
1016         msg_body.bss_params.proxy_probe_resp =
1017                 orig->bss_params.proxy_probe_resp;
1018         msg_body.bss_params.edca_params_valid =
1019                 orig->bss_params.edca_params_valid;
1020
1021         memcpy(&msg_body.bss_params.acbe,
1022                &orig->bss_params.acbe,
1023                sizeof(orig->bss_params.acbe));
1024         memcpy(&msg_body.bss_params.acbk,
1025                &orig->bss_params.acbk,
1026                sizeof(orig->bss_params.acbk));
1027         memcpy(&msg_body.bss_params.acvi,
1028                &orig->bss_params.acvi,
1029                sizeof(orig->bss_params.acvi));
1030         memcpy(&msg_body.bss_params.acvo,
1031                &orig->bss_params.acvo,
1032                sizeof(orig->bss_params.acvo));
1033
1034         msg_body.bss_params.ext_set_sta_key_param_valid =
1035                 orig->bss_params.ext_set_sta_key_param_valid;
1036
1037         memcpy(&msg_body.bss_params.ext_set_sta_key_param,
1038                &orig->bss_params.ext_set_sta_key_param,
1039                sizeof(orig->bss_params.acvo));
1040
1041         msg_body.bss_params.wcn36xx_hal_persona =
1042                 orig->bss_params.wcn36xx_hal_persona;
1043         msg_body.bss_params.spectrum_mgt_enable =
1044                 orig->bss_params.spectrum_mgt_enable;
1045         msg_body.bss_params.tx_mgmt_power = orig->bss_params.tx_mgmt_power;
1046         msg_body.bss_params.max_tx_power = orig->bss_params.max_tx_power;
1047
1048         wcn36xx_smd_convert_sta_to_v1(wcn, &orig->bss_params.sta,
1049                                       &msg_body.bss_params.sta);
1050
1051         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1052
1053         wcn36xx_dbg(WCN36XX_DBG_HAL,
1054                     "hal config bss v1 bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1055                     bss->bssid, bss->self_mac_addr, bss->bss_type,
1056                     bss->oper_mode, bss->nw_type);
1057
1058         wcn36xx_dbg(WCN36XX_DBG_HAL,
1059                     "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1060                     sta->bssid, sta->action, sta->sta_index,
1061                     sta->bssid_index, sta->aid, sta->type, sta->mac);
1062
1063         return wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1064 }
1065
1066
1067 static int wcn36xx_smd_config_bss_rsp(struct wcn36xx *wcn,
1068                                       struct ieee80211_vif *vif,
1069                                       void *buf,
1070                                       size_t len)
1071 {
1072         struct wcn36xx_hal_config_bss_rsp_msg *rsp;
1073         struct wcn36xx_hal_config_bss_rsp_params *params;
1074         struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
1075
1076         if (len < sizeof(*rsp))
1077                 return -EINVAL;
1078
1079         rsp = (struct wcn36xx_hal_config_bss_rsp_msg *)buf;
1080         params = &rsp->bss_rsp_params;
1081
1082         if (params->status != WCN36XX_FW_MSG_RESULT_SUCCESS) {
1083                 wcn36xx_warn("hal config bss response failure: %d\n",
1084                              params->status);
1085                 return -EIO;
1086         }
1087
1088         wcn36xx_dbg(WCN36XX_DBG_HAL,
1089                     "hal config bss rsp status %d bss_idx %d dpu_desc_index %d"
1090                     " sta_idx %d self_idx %d bcast_idx %d mac %pM"
1091                     " power %d ucast_dpu_signature %d\n",
1092                     params->status, params->bss_index, params->dpu_desc_index,
1093                     params->bss_sta_index, params->bss_self_sta_index,
1094                     params->bss_bcast_sta_idx, params->mac,
1095                     params->tx_mgmt_power, params->ucast_dpu_signature);
1096
1097         priv_vif->bss_index = params->bss_index;
1098
1099         if (priv_vif->sta) {
1100                 priv_vif->sta->bss_sta_index =  params->bss_sta_index;
1101                 priv_vif->sta->bss_dpu_desc_index = params->dpu_desc_index;
1102         }
1103
1104         priv_vif->ucast_dpu_signature = params->ucast_dpu_signature;
1105
1106         return 0;
1107 }
1108
1109 int wcn36xx_smd_config_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1110                            struct ieee80211_sta *sta, const u8 *bssid,
1111                            bool update)
1112 {
1113         struct wcn36xx_hal_config_bss_req_msg msg;
1114         struct wcn36xx_hal_config_bss_params *bss;
1115         struct wcn36xx_hal_config_sta_params *sta_params;
1116         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1117         int ret = 0;
1118
1119         mutex_lock(&wcn->hal_mutex);
1120         INIT_HAL_MSG(msg, WCN36XX_HAL_CONFIG_BSS_REQ);
1121
1122         bss = &msg.bss_params;
1123         sta_params = &bss->sta;
1124
1125         WARN_ON(is_zero_ether_addr(bssid));
1126
1127         memcpy(&bss->bssid, bssid, ETH_ALEN);
1128
1129         memcpy(bss->self_mac_addr, vif->addr, ETH_ALEN);
1130
1131         if (vif->type == NL80211_IFTYPE_STATION) {
1132                 bss->bss_type = WCN36XX_HAL_INFRASTRUCTURE_MODE;
1133
1134                 /* STA */
1135                 bss->oper_mode = 1;
1136                 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_MODE;
1137         } else if (vif->type == NL80211_IFTYPE_AP) {
1138                 bss->bss_type = WCN36XX_HAL_INFRA_AP_MODE;
1139
1140                 /* AP */
1141                 bss->oper_mode = 0;
1142                 bss->wcn36xx_hal_persona = WCN36XX_HAL_STA_SAP_MODE;
1143         } else if (vif->type == NL80211_IFTYPE_ADHOC ||
1144                    vif->type == NL80211_IFTYPE_MESH_POINT) {
1145                 bss->bss_type = WCN36XX_HAL_IBSS_MODE;
1146
1147                 /* STA */
1148                 bss->oper_mode = 1;
1149         } else {
1150                 wcn36xx_warn("Unknown type for bss config: %d\n", vif->type);
1151         }
1152
1153         if (vif->type == NL80211_IFTYPE_STATION)
1154                 wcn36xx_smd_set_bss_nw_type(wcn, sta, bss);
1155         else
1156                 bss->nw_type = WCN36XX_HAL_11N_NW_TYPE;
1157
1158         bss->short_slot_time_supported = vif->bss_conf.use_short_slot;
1159         bss->lla_coexist = 0;
1160         bss->llb_coexist = 0;
1161         bss->llg_coexist = 0;
1162         bss->rifs_mode = 0;
1163         bss->beacon_interval = vif->bss_conf.beacon_int;
1164         bss->dtim_period = vif_priv->dtim_period;
1165
1166         wcn36xx_smd_set_bss_ht_params(vif, sta, bss);
1167
1168         bss->oper_channel = WCN36XX_HW_CHANNEL(wcn);
1169
1170         if (conf_is_ht40_minus(&wcn->hw->conf))
1171                 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
1172         else if (conf_is_ht40_plus(&wcn->hw->conf))
1173                 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
1174         else
1175                 bss->ext_channel = IEEE80211_HT_PARAM_CHA_SEC_NONE;
1176
1177         bss->reserved = 0;
1178         wcn36xx_smd_set_sta_params(wcn, vif, sta, sta_params);
1179
1180         /* wcn->ssid is only valid in AP and IBSS mode */
1181         bss->ssid.length = vif_priv->ssid.length;
1182         memcpy(bss->ssid.ssid, vif_priv->ssid.ssid, vif_priv->ssid.length);
1183
1184         bss->obss_prot_enabled = 0;
1185         bss->rmf = 0;
1186         bss->max_probe_resp_retry_limit = 0;
1187         bss->hidden_ssid = vif->bss_conf.hidden_ssid;
1188         bss->proxy_probe_resp = 0;
1189         bss->edca_params_valid = 0;
1190
1191         /* FIXME: set acbe, acbk, acvi and acvo */
1192
1193         bss->ext_set_sta_key_param_valid = 0;
1194
1195         /* FIXME: set ext_set_sta_key_param */
1196
1197         bss->spectrum_mgt_enable = 0;
1198         bss->tx_mgmt_power = 0;
1199         bss->max_tx_power = WCN36XX_MAX_POWER(wcn);
1200
1201         bss->action = update;
1202
1203         wcn36xx_dbg(WCN36XX_DBG_HAL,
1204                     "hal config bss bssid %pM self_mac_addr %pM bss_type %d oper_mode %d nw_type %d\n",
1205                     bss->bssid, bss->self_mac_addr, bss->bss_type,
1206                     bss->oper_mode, bss->nw_type);
1207
1208         wcn36xx_dbg(WCN36XX_DBG_HAL,
1209                     "- sta bssid %pM action %d sta_index %d bssid_index %d aid %d type %d mac %pM\n",
1210                     sta_params->bssid, sta_params->action,
1211                     sta_params->sta_index, sta_params->bssid_index,
1212                     sta_params->aid, sta_params->type,
1213                     sta_params->mac);
1214
1215         if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1216                 ret = wcn36xx_smd_config_bss_v1(wcn, &msg);
1217         } else {
1218                 PREPARE_HAL_BUF(wcn->hal_buf, msg);
1219
1220                 ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1221         }
1222         if (ret) {
1223                 wcn36xx_err("Sending hal_config_bss failed\n");
1224                 goto out;
1225         }
1226         ret = wcn36xx_smd_config_bss_rsp(wcn,
1227                                          vif,
1228                                          wcn->hal_buf,
1229                                          wcn->hal_rsp_len);
1230         if (ret) {
1231                 wcn36xx_err("hal_config_bss response failed err=%d\n", ret);
1232                 goto out;
1233         }
1234 out:
1235         mutex_unlock(&wcn->hal_mutex);
1236         return ret;
1237 }
1238
1239 int wcn36xx_smd_delete_bss(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1240 {
1241         struct wcn36xx_hal_delete_bss_req_msg msg_body;
1242         struct wcn36xx_vif *priv_vif = (struct wcn36xx_vif *)vif->drv_priv;
1243         int ret = 0;
1244
1245         mutex_lock(&wcn->hal_mutex);
1246         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DELETE_BSS_REQ);
1247
1248         msg_body.bss_index = priv_vif->bss_index;
1249
1250         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1251
1252         wcn36xx_dbg(WCN36XX_DBG_HAL, "hal delete bss %d\n", msg_body.bss_index);
1253
1254         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1255         if (ret) {
1256                 wcn36xx_err("Sending hal_delete_bss failed\n");
1257                 goto out;
1258         }
1259         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1260         if (ret) {
1261                 wcn36xx_err("hal_delete_bss response failed err=%d\n", ret);
1262                 goto out;
1263         }
1264 out:
1265         mutex_unlock(&wcn->hal_mutex);
1266         return ret;
1267 }
1268
1269 int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif,
1270                             struct sk_buff *skb_beacon, u16 tim_off,
1271                             u16 p2p_off)
1272 {
1273         struct wcn36xx_hal_send_beacon_req_msg msg_body;
1274         int ret = 0;
1275
1276         mutex_lock(&wcn->hal_mutex);
1277         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SEND_BEACON_REQ);
1278
1279         /* TODO need to find out why this is needed? */
1280         msg_body.beacon_length = skb_beacon->len + 6;
1281
1282         if (BEACON_TEMPLATE_SIZE > msg_body.beacon_length) {
1283                 memcpy(&msg_body.beacon, &skb_beacon->len, sizeof(u32));
1284                 memcpy(&(msg_body.beacon[4]), skb_beacon->data,
1285                        skb_beacon->len);
1286         } else {
1287                 wcn36xx_err("Beacon is to big: beacon size=%d\n",
1288                               msg_body.beacon_length);
1289                 ret = -ENOMEM;
1290                 goto out;
1291         }
1292         memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1293
1294         /* TODO need to find out why this is needed? */
1295         msg_body.tim_ie_offset = tim_off+4;
1296         msg_body.p2p_ie_offset = p2p_off;
1297         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1298
1299         wcn36xx_dbg(WCN36XX_DBG_HAL,
1300                     "hal send beacon beacon_length %d\n",
1301                     msg_body.beacon_length);
1302
1303         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1304         if (ret) {
1305                 wcn36xx_err("Sending hal_send_beacon failed\n");
1306                 goto out;
1307         }
1308         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1309         if (ret) {
1310                 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1311                 goto out;
1312         }
1313 out:
1314         mutex_unlock(&wcn->hal_mutex);
1315         return ret;
1316 }
1317
1318 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1319                                       struct ieee80211_vif *vif,
1320                                       struct sk_buff *skb)
1321 {
1322         struct wcn36xx_hal_send_probe_resp_req_msg msg;
1323         int ret = 0;
1324
1325         mutex_lock(&wcn->hal_mutex);
1326         INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1327
1328         if (skb->len > BEACON_TEMPLATE_SIZE) {
1329                 wcn36xx_warn("probe response template is too big: %d\n",
1330                              skb->len);
1331                 ret = -E2BIG;
1332                 goto out;
1333         }
1334
1335         msg.probe_resp_template_len = skb->len;
1336         memcpy(&msg.probe_resp_template, skb->data, skb->len);
1337
1338         memcpy(msg.bssid, vif->addr, ETH_ALEN);
1339
1340         PREPARE_HAL_BUF(wcn->hal_buf, msg);
1341
1342         wcn36xx_dbg(WCN36XX_DBG_HAL,
1343                     "hal update probe rsp len %d bssid %pM\n",
1344                     msg.probe_resp_template_len, msg.bssid);
1345
1346         ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1347         if (ret) {
1348                 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1349                 goto out;
1350         }
1351         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1352         if (ret) {
1353                 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1354                             ret);
1355                 goto out;
1356         }
1357 out:
1358         mutex_unlock(&wcn->hal_mutex);
1359         return ret;
1360 }
1361
1362 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
1363                            enum ani_ed_type enc_type,
1364                            u8 keyidx,
1365                            u8 keylen,
1366                            u8 *key,
1367                            u8 sta_index)
1368 {
1369         struct wcn36xx_hal_set_sta_key_req_msg msg_body;
1370         int ret = 0;
1371
1372         mutex_lock(&wcn->hal_mutex);
1373         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
1374
1375         msg_body.set_sta_key_params.sta_index = sta_index;
1376         msg_body.set_sta_key_params.enc_type = enc_type;
1377
1378         msg_body.set_sta_key_params.key[0].id = keyidx;
1379         msg_body.set_sta_key_params.key[0].unicast = 1;
1380         msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
1381         msg_body.set_sta_key_params.key[0].pae_role = 0;
1382         msg_body.set_sta_key_params.key[0].length = keylen;
1383         memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
1384         msg_body.set_sta_key_params.single_tid_rc = 1;
1385
1386         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1387
1388         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1389         if (ret) {
1390                 wcn36xx_err("Sending hal_set_stakey failed\n");
1391                 goto out;
1392         }
1393         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1394         if (ret) {
1395                 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
1396                 goto out;
1397         }
1398 out:
1399         mutex_unlock(&wcn->hal_mutex);
1400         return ret;
1401 }
1402
1403 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
1404                            enum ani_ed_type enc_type,
1405                            u8 keyidx,
1406                            u8 keylen,
1407                            u8 *key)
1408 {
1409         struct wcn36xx_hal_set_bss_key_req_msg msg_body;
1410         int ret = 0;
1411
1412         mutex_lock(&wcn->hal_mutex);
1413         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
1414         msg_body.bss_idx = 0;
1415         msg_body.enc_type = enc_type;
1416         msg_body.num_keys = 1;
1417         msg_body.keys[0].id = keyidx;
1418         msg_body.keys[0].unicast = 0;
1419         msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
1420         msg_body.keys[0].pae_role = 0;
1421         msg_body.keys[0].length = keylen;
1422         memcpy(msg_body.keys[0].key, key, keylen);
1423
1424         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1425
1426         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1427         if (ret) {
1428                 wcn36xx_err("Sending hal_set_bsskey failed\n");
1429                 goto out;
1430         }
1431         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1432         if (ret) {
1433                 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
1434                 goto out;
1435         }
1436 out:
1437         mutex_unlock(&wcn->hal_mutex);
1438         return ret;
1439 }
1440
1441 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
1442                               enum ani_ed_type enc_type,
1443                               u8 keyidx,
1444                               u8 sta_index)
1445 {
1446         struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
1447         int ret = 0;
1448
1449         mutex_lock(&wcn->hal_mutex);
1450         INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
1451
1452         msg_body.sta_idx = sta_index;
1453         msg_body.enc_type = enc_type;
1454         msg_body.key_id = keyidx;
1455
1456         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1457
1458         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1459         if (ret) {
1460                 wcn36xx_err("Sending hal_remove_stakey failed\n");
1461                 goto out;
1462         }
1463         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1464         if (ret) {
1465                 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
1466                 goto out;
1467         }
1468 out:
1469         mutex_unlock(&wcn->hal_mutex);
1470         return ret;
1471 }
1472
1473 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
1474                               enum ani_ed_type enc_type,
1475                               u8 keyidx)
1476 {
1477         struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
1478         int ret = 0;
1479
1480         mutex_lock(&wcn->hal_mutex);
1481         INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
1482         msg_body.bss_idx = 0;
1483         msg_body.enc_type = enc_type;
1484         msg_body.key_id = keyidx;
1485
1486         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1487
1488         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1489         if (ret) {
1490                 wcn36xx_err("Sending hal_remove_bsskey failed\n");
1491                 goto out;
1492         }
1493         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1494         if (ret) {
1495                 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
1496                 goto out;
1497         }
1498 out:
1499         mutex_unlock(&wcn->hal_mutex);
1500         return ret;
1501 }
1502
1503 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1504 {
1505         struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1506         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1507         int ret = 0;
1508
1509         mutex_lock(&wcn->hal_mutex);
1510         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
1511
1512         msg_body.bss_index = vif_priv->bss_index;
1513         msg_body.tbtt = vif->bss_conf.sync_tsf;
1514         msg_body.dtim_period = vif_priv->dtim_period;
1515
1516         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1517
1518         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1519         if (ret) {
1520                 wcn36xx_err("Sending hal_enter_bmps failed\n");
1521                 goto out;
1522         }
1523         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1524         if (ret) {
1525                 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
1526                 goto out;
1527         }
1528 out:
1529         mutex_unlock(&wcn->hal_mutex);
1530         return ret;
1531 }
1532
1533 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1534 {
1535         struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1536         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1537         int ret = 0;
1538
1539         mutex_lock(&wcn->hal_mutex);
1540         INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
1541
1542         msg_body.bss_index = vif_priv->bss_index;
1543
1544         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1545
1546         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1547         if (ret) {
1548                 wcn36xx_err("Sending hal_exit_bmps failed\n");
1549                 goto out;
1550         }
1551         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1552         if (ret) {
1553                 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1554                 goto out;
1555         }
1556 out:
1557         mutex_unlock(&wcn->hal_mutex);
1558         return ret;
1559 }
1560 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
1561 {
1562         struct wcn36xx_hal_set_power_params_req_msg msg_body;
1563         int ret = 0;
1564
1565         mutex_lock(&wcn->hal_mutex);
1566         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
1567
1568         /*
1569          * When host is down ignore every second dtim
1570          */
1571         if (ignore_dtim) {
1572                 msg_body.ignore_dtim = 1;
1573                 msg_body.dtim_period = 2;
1574         }
1575         msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
1576
1577         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1578
1579         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1580         if (ret) {
1581                 wcn36xx_err("Sending hal_set_power_params failed\n");
1582                 goto out;
1583         }
1584
1585 out:
1586         mutex_unlock(&wcn->hal_mutex);
1587         return ret;
1588 }
1589 /* Notice: This function should be called after associated, or else it
1590  * will be invalid
1591  */
1592 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
1593                                struct ieee80211_vif *vif,
1594                                int packet_type)
1595 {
1596         struct wcn36xx_hal_keep_alive_req_msg msg_body;
1597         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1598         int ret = 0;
1599
1600         mutex_lock(&wcn->hal_mutex);
1601         INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
1602
1603         if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
1604                 msg_body.bss_index = vif_priv->bss_index;
1605                 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
1606                 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
1607         } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
1608                 /* TODO: it also support ARP response type */
1609         } else {
1610                 wcn36xx_warn("unknow keep alive packet type %d\n", packet_type);
1611                 ret = -EINVAL;
1612                 goto out;
1613         }
1614
1615         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1616
1617         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1618         if (ret) {
1619                 wcn36xx_err("Sending hal_exit_bmps failed\n");
1620                 goto out;
1621         }
1622         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1623         if (ret) {
1624                 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1625                 goto out;
1626         }
1627 out:
1628         mutex_unlock(&wcn->hal_mutex);
1629         return ret;
1630 }
1631
1632 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
1633                              u32 arg3, u32 arg4, u32 arg5)
1634 {
1635         struct wcn36xx_hal_dump_cmd_req_msg msg_body;
1636         int ret = 0;
1637
1638         mutex_lock(&wcn->hal_mutex);
1639         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
1640
1641         msg_body.arg1 = arg1;
1642         msg_body.arg2 = arg2;
1643         msg_body.arg3 = arg3;
1644         msg_body.arg4 = arg4;
1645         msg_body.arg5 = arg5;
1646
1647         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1648
1649         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1650         if (ret) {
1651                 wcn36xx_err("Sending hal_dump_cmd failed\n");
1652                 goto out;
1653         }
1654         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1655         if (ret) {
1656                 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
1657                 goto out;
1658         }
1659 out:
1660         mutex_unlock(&wcn->hal_mutex);
1661         return ret;
1662 }
1663
1664 static inline void set_feat_caps(u32 *bitmap,
1665                                  enum place_holder_in_cap_bitmap cap)
1666 {
1667         int arr_idx, bit_idx;
1668
1669         if (cap < 0 || cap > 127) {
1670                 wcn36xx_warn("error cap idx %d\n", cap);
1671                 return;
1672         }
1673
1674         arr_idx = cap / 32;
1675         bit_idx = cap % 32;
1676         bitmap[arr_idx] |= (1 << bit_idx);
1677 }
1678
1679 static inline int get_feat_caps(u32 *bitmap,
1680                                 enum place_holder_in_cap_bitmap cap)
1681 {
1682         int arr_idx, bit_idx;
1683         int ret = 0;
1684
1685         if (cap < 0 || cap > 127) {
1686                 wcn36xx_warn("error cap idx %d\n", cap);
1687                 return -EINVAL;
1688         }
1689
1690         arr_idx = cap / 32;
1691         bit_idx = cap % 32;
1692         ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
1693         return ret;
1694 }
1695
1696 static inline void clear_feat_caps(u32 *bitmap,
1697                                 enum place_holder_in_cap_bitmap cap)
1698 {
1699         int arr_idx, bit_idx;
1700
1701         if (cap < 0 || cap > 127) {
1702                 wcn36xx_warn("error cap idx %d\n", cap);
1703                 return;
1704         }
1705
1706         arr_idx = cap / 32;
1707         bit_idx = cap % 32;
1708         bitmap[arr_idx] &= ~(1 << bit_idx);
1709 }
1710
1711 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
1712 {
1713         struct wcn36xx_hal_feat_caps_msg msg_body;
1714         int ret = 0;
1715
1716         mutex_lock(&wcn->hal_mutex);
1717         INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
1718
1719         set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
1720
1721         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1722
1723         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1724         if (ret) {
1725                 wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
1726                 goto out;
1727         }
1728         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1729         if (ret) {
1730                 wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n",
1731                             ret);
1732                 goto out;
1733         }
1734 out:
1735         mutex_unlock(&wcn->hal_mutex);
1736         return ret;
1737 }
1738
1739 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
1740                 struct ieee80211_sta *sta,
1741                 u16 tid,
1742                 u16 *ssn,
1743                 u8 direction,
1744                 u8 sta_index)
1745 {
1746         struct wcn36xx_hal_add_ba_session_req_msg msg_body;
1747         int ret = 0;
1748
1749         mutex_lock(&wcn->hal_mutex);
1750         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
1751
1752         msg_body.sta_index = sta_index;
1753         memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
1754         msg_body.dialog_token = 0x10;
1755         msg_body.tid = tid;
1756
1757         /* Immediate BA because Delayed BA is not supported */
1758         msg_body.policy = 1;
1759         msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
1760         msg_body.timeout = 0;
1761         if (ssn)
1762                 msg_body.ssn = *ssn;
1763         msg_body.direction = direction;
1764
1765         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1766
1767         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1768         if (ret) {
1769                 wcn36xx_err("Sending hal_add_ba_session failed\n");
1770                 goto out;
1771         }
1772         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1773         if (ret) {
1774                 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
1775                 goto out;
1776         }
1777 out:
1778         mutex_unlock(&wcn->hal_mutex);
1779         return ret;
1780 }
1781
1782 int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
1783 {
1784         struct wcn36xx_hal_add_ba_req_msg msg_body;
1785         int ret = 0;
1786
1787         mutex_lock(&wcn->hal_mutex);
1788         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
1789
1790         msg_body.session_id = 0;
1791         msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
1792
1793         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1794
1795         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1796         if (ret) {
1797                 wcn36xx_err("Sending hal_add_ba failed\n");
1798                 goto out;
1799         }
1800         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1801         if (ret) {
1802                 wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
1803                 goto out;
1804         }
1805 out:
1806         mutex_unlock(&wcn->hal_mutex);
1807         return ret;
1808 }
1809
1810 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
1811 {
1812         struct wcn36xx_hal_del_ba_req_msg msg_body;
1813         int ret = 0;
1814
1815         mutex_lock(&wcn->hal_mutex);
1816         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
1817
1818         msg_body.sta_index = sta_index;
1819         msg_body.tid = tid;
1820         msg_body.direction = 0;
1821         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1822
1823         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1824         if (ret) {
1825                 wcn36xx_err("Sending hal_del_ba failed\n");
1826                 goto out;
1827         }
1828         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1829         if (ret) {
1830                 wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
1831                 goto out;
1832         }
1833 out:
1834         mutex_unlock(&wcn->hal_mutex);
1835         return ret;
1836 }
1837
1838 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
1839 {
1840         struct wcn36xx_hal_trigger_ba_req_msg msg_body;
1841         struct wcn36xx_hal_trigget_ba_req_candidate *candidate;
1842         int ret = 0;
1843
1844         mutex_lock(&wcn->hal_mutex);
1845         INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
1846
1847         msg_body.session_id = 0;
1848         msg_body.candidate_cnt = 1;
1849         msg_body.header.len += sizeof(*candidate);
1850         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1851
1852         candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *)
1853                 (wcn->hal_buf + sizeof(msg_body));
1854         candidate->sta_index = sta_index;
1855         candidate->tid_bitmap = 1;
1856
1857         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1858         if (ret) {
1859                 wcn36xx_err("Sending hal_trigger_ba failed\n");
1860                 goto out;
1861         }
1862         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1863         if (ret) {
1864                 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
1865                 goto out;
1866         }
1867 out:
1868         mutex_unlock(&wcn->hal_mutex);
1869         return ret;
1870 }
1871
1872 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
1873 {
1874         struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
1875
1876         if (len != sizeof(*rsp)) {
1877                 wcn36xx_warn("Bad TX complete indication\n");
1878                 return -EIO;
1879         }
1880
1881         wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
1882
1883         return 0;
1884 }
1885
1886 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
1887                                          void *buf,
1888                                          size_t len)
1889 {
1890         struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
1891         struct ieee80211_vif *vif = NULL;
1892         struct wcn36xx_vif *tmp;
1893
1894         /* Old FW does not have bss index */
1895         if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1896                 list_for_each_entry(tmp, &wcn->vif_list, list) {
1897                         wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
1898                                     tmp->bss_index);
1899                         vif = container_of((void *)tmp,
1900                                                  struct ieee80211_vif,
1901                                                  drv_priv);
1902                         ieee80211_connection_loss(vif);
1903                 }
1904                 return 0;
1905         }
1906
1907         if (len != sizeof(*rsp)) {
1908                 wcn36xx_warn("Corrupted missed beacon indication\n");
1909                 return -EIO;
1910         }
1911
1912         list_for_each_entry(tmp, &wcn->vif_list, list) {
1913                 if (tmp->bss_index == rsp->bss_index) {
1914                         wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
1915                                     rsp->bss_index);
1916                         vif = container_of((void *)tmp,
1917                                                  struct ieee80211_vif,
1918                                                  drv_priv);
1919                         ieee80211_connection_loss(vif);
1920                         return 0;
1921                 }
1922         }
1923
1924         wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
1925         return -ENOENT;
1926 }
1927
1928 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
1929                                               void *buf,
1930                                               size_t len)
1931 {
1932         struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
1933         struct wcn36xx_vif *tmp;
1934         struct ieee80211_sta *sta = NULL;
1935
1936         if (len != sizeof(*rsp)) {
1937                 wcn36xx_warn("Corrupted delete sta indication\n");
1938                 return -EIO;
1939         }
1940
1941         list_for_each_entry(tmp, &wcn->vif_list, list) {
1942                 if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
1943                         sta = container_of((void *)tmp->sta,
1944                                                  struct ieee80211_sta,
1945                                                  drv_priv);
1946                         wcn36xx_dbg(WCN36XX_DBG_HAL,
1947                                     "delete station indication %pM index %d\n",
1948                                     rsp->addr2,
1949                                     rsp->sta_id);
1950                         ieee80211_report_low_ack(sta, 0);
1951                         return 0;
1952                 }
1953         }
1954
1955         wcn36xx_warn("STA with addr %pM and index %d not found\n",
1956                      rsp->addr2,
1957                      rsp->sta_id);
1958         return -ENOENT;
1959 }
1960
1961 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
1962 {
1963         struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
1964         size_t len;
1965         int ret = 0;
1966
1967         mutex_lock(&wcn->hal_mutex);
1968         INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
1969
1970         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1971
1972         body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
1973         len = msg_body.header.len;
1974
1975         put_cfg_tlv_u32(wcn, &len, cfg_id, value);
1976         body->header.len = len;
1977         body->len = len - sizeof(*body);
1978
1979         ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
1980         if (ret) {
1981                 wcn36xx_err("Sending hal_update_cfg failed\n");
1982                 goto out;
1983         }
1984         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1985         if (ret) {
1986                 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
1987                 goto out;
1988         }
1989 out:
1990         mutex_unlock(&wcn->hal_mutex);
1991         return ret;
1992 }
1993 static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
1994 {
1995         struct wcn36xx_hal_msg_header *msg_header = buf;
1996         struct wcn36xx_hal_ind_msg *msg_ind;
1997         wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
1998
1999         switch (msg_header->msg_type) {
2000         case WCN36XX_HAL_START_RSP:
2001         case WCN36XX_HAL_CONFIG_STA_RSP:
2002         case WCN36XX_HAL_CONFIG_BSS_RSP:
2003         case WCN36XX_HAL_ADD_STA_SELF_RSP:
2004         case WCN36XX_HAL_STOP_RSP:
2005         case WCN36XX_HAL_DEL_STA_SELF_RSP:
2006         case WCN36XX_HAL_DELETE_STA_RSP:
2007         case WCN36XX_HAL_INIT_SCAN_RSP:
2008         case WCN36XX_HAL_START_SCAN_RSP:
2009         case WCN36XX_HAL_END_SCAN_RSP:
2010         case WCN36XX_HAL_FINISH_SCAN_RSP:
2011         case WCN36XX_HAL_DOWNLOAD_NV_RSP:
2012         case WCN36XX_HAL_DELETE_BSS_RSP:
2013         case WCN36XX_HAL_SEND_BEACON_RSP:
2014         case WCN36XX_HAL_SET_LINK_ST_RSP:
2015         case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
2016         case WCN36XX_HAL_SET_BSSKEY_RSP:
2017         case WCN36XX_HAL_SET_STAKEY_RSP:
2018         case WCN36XX_HAL_RMV_STAKEY_RSP:
2019         case WCN36XX_HAL_RMV_BSSKEY_RSP:
2020         case WCN36XX_HAL_ENTER_BMPS_RSP:
2021         case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
2022         case WCN36XX_HAL_EXIT_BMPS_RSP:
2023         case WCN36XX_HAL_KEEP_ALIVE_RSP:
2024         case WCN36XX_HAL_DUMP_COMMAND_RSP:
2025         case WCN36XX_HAL_ADD_BA_SESSION_RSP:
2026         case WCN36XX_HAL_ADD_BA_RSP:
2027         case WCN36XX_HAL_DEL_BA_RSP:
2028         case WCN36XX_HAL_TRIGGER_BA_RSP:
2029         case WCN36XX_HAL_UPDATE_CFG_RSP:
2030         case WCN36XX_HAL_JOIN_RSP:
2031         case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
2032         case WCN36XX_HAL_CH_SWITCH_RSP:
2033         case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
2034                 memcpy(wcn->hal_buf, buf, len);
2035                 wcn->hal_rsp_len = len;
2036                 complete(&wcn->hal_rsp_compl);
2037                 break;
2038
2039         case WCN36XX_HAL_OTA_TX_COMPL_IND:
2040         case WCN36XX_HAL_MISSED_BEACON_IND:
2041         case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2042                 mutex_lock(&wcn->hal_ind_mutex);
2043                 msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
2044                 if (msg_ind) {
2045                         msg_ind->msg_len = len;
2046                         msg_ind->msg = kmalloc(len, GFP_KERNEL);
2047                         memcpy(msg_ind->msg, buf, len);
2048                         list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
2049                         queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
2050                         wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
2051                 }
2052                 mutex_unlock(&wcn->hal_ind_mutex);
2053                 if (msg_ind)
2054                         break;
2055                 /* FIXME: Do something smarter then just printing an error. */
2056                 wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n",
2057                             msg_header->msg_type);
2058                 break;
2059         default:
2060                 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2061                               msg_header->msg_type);
2062         }
2063 }
2064 static void wcn36xx_ind_smd_work(struct work_struct *work)
2065 {
2066         struct wcn36xx *wcn =
2067                 container_of(work, struct wcn36xx, hal_ind_work);
2068         struct wcn36xx_hal_msg_header *msg_header;
2069         struct wcn36xx_hal_ind_msg *hal_ind_msg;
2070
2071         mutex_lock(&wcn->hal_ind_mutex);
2072
2073         hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
2074                                        struct wcn36xx_hal_ind_msg,
2075                                        list);
2076
2077         msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
2078
2079         switch (msg_header->msg_type) {
2080         case WCN36XX_HAL_OTA_TX_COMPL_IND:
2081                 wcn36xx_smd_tx_compl_ind(wcn,
2082                                          hal_ind_msg->msg,
2083                                          hal_ind_msg->msg_len);
2084                 break;
2085         case WCN36XX_HAL_MISSED_BEACON_IND:
2086                 wcn36xx_smd_missed_beacon_ind(wcn,
2087                                               hal_ind_msg->msg,
2088                                               hal_ind_msg->msg_len);
2089                 break;
2090         case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2091                 wcn36xx_smd_delete_sta_context_ind(wcn,
2092                                                    hal_ind_msg->msg,
2093                                                    hal_ind_msg->msg_len);
2094                 break;
2095         default:
2096                 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2097                               msg_header->msg_type);
2098         }
2099         list_del(wcn->hal_ind_queue.next);
2100         kfree(hal_ind_msg->msg);
2101         kfree(hal_ind_msg);
2102         mutex_unlock(&wcn->hal_ind_mutex);
2103 }
2104 int wcn36xx_smd_open(struct wcn36xx *wcn)
2105 {
2106         int ret = 0;
2107         wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
2108         if (!wcn->hal_ind_wq) {
2109                 wcn36xx_err("failed to allocate wq\n");
2110                 ret = -ENOMEM;
2111                 goto out;
2112         }
2113         INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
2114         INIT_LIST_HEAD(&wcn->hal_ind_queue);
2115         mutex_init(&wcn->hal_ind_mutex);
2116
2117         ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
2118         if (ret) {
2119                 wcn36xx_err("failed to open control channel\n");
2120                 goto free_wq;
2121         }
2122
2123         return ret;
2124
2125 free_wq:
2126         destroy_workqueue(wcn->hal_ind_wq);
2127 out:
2128         return ret;
2129 }
2130
2131 void wcn36xx_smd_close(struct wcn36xx *wcn)
2132 {
2133         wcn->ctrl_ops->close();
2134         destroy_workqueue(wcn->hal_ind_wq);
2135         mutex_destroy(&wcn->hal_ind_mutex);
2136 }