]> Pileus Git - ~andy/linux/blob - drivers/net/wireless/ath/wcn36xx/smd.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
[~andy/linux] / 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                 return -ENOMEM;
1290         }
1291         memcpy(msg_body.bssid, vif->addr, ETH_ALEN);
1292
1293         /* TODO need to find out why this is needed? */
1294         msg_body.tim_ie_offset = tim_off+4;
1295         msg_body.p2p_ie_offset = p2p_off;
1296         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1297
1298         wcn36xx_dbg(WCN36XX_DBG_HAL,
1299                     "hal send beacon beacon_length %d\n",
1300                     msg_body.beacon_length);
1301
1302         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1303         if (ret) {
1304                 wcn36xx_err("Sending hal_send_beacon failed\n");
1305                 goto out;
1306         }
1307         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1308         if (ret) {
1309                 wcn36xx_err("hal_send_beacon response failed err=%d\n", ret);
1310                 goto out;
1311         }
1312 out:
1313         mutex_unlock(&wcn->hal_mutex);
1314         return ret;
1315 }
1316
1317 int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn,
1318                                       struct ieee80211_vif *vif,
1319                                       struct sk_buff *skb)
1320 {
1321         struct wcn36xx_hal_send_probe_resp_req_msg msg;
1322         int ret = 0;
1323
1324         mutex_lock(&wcn->hal_mutex);
1325         INIT_HAL_MSG(msg, WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_REQ);
1326
1327         if (skb->len > BEACON_TEMPLATE_SIZE) {
1328                 wcn36xx_warn("probe response template is too big: %d\n",
1329                              skb->len);
1330                 return -E2BIG;
1331         }
1332
1333         msg.probe_resp_template_len = skb->len;
1334         memcpy(&msg.probe_resp_template, skb->data, skb->len);
1335
1336         memcpy(msg.bssid, vif->addr, ETH_ALEN);
1337
1338         PREPARE_HAL_BUF(wcn->hal_buf, msg);
1339
1340         wcn36xx_dbg(WCN36XX_DBG_HAL,
1341                     "hal update probe rsp len %d bssid %pM\n",
1342                     msg.probe_resp_template_len, msg.bssid);
1343
1344         ret = wcn36xx_smd_send_and_wait(wcn, msg.header.len);
1345         if (ret) {
1346                 wcn36xx_err("Sending hal_update_proberesp_tmpl failed\n");
1347                 goto out;
1348         }
1349         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1350         if (ret) {
1351                 wcn36xx_err("hal_update_proberesp_tmpl response failed err=%d\n",
1352                             ret);
1353                 goto out;
1354         }
1355 out:
1356         mutex_unlock(&wcn->hal_mutex);
1357         return ret;
1358 }
1359
1360 int wcn36xx_smd_set_stakey(struct wcn36xx *wcn,
1361                            enum ani_ed_type enc_type,
1362                            u8 keyidx,
1363                            u8 keylen,
1364                            u8 *key,
1365                            u8 sta_index)
1366 {
1367         struct wcn36xx_hal_set_sta_key_req_msg msg_body;
1368         int ret = 0;
1369
1370         mutex_lock(&wcn->hal_mutex);
1371         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_STAKEY_REQ);
1372
1373         msg_body.set_sta_key_params.sta_index = sta_index;
1374         msg_body.set_sta_key_params.enc_type = enc_type;
1375
1376         msg_body.set_sta_key_params.key[0].id = keyidx;
1377         msg_body.set_sta_key_params.key[0].unicast = 1;
1378         msg_body.set_sta_key_params.key[0].direction = WCN36XX_HAL_TX_RX;
1379         msg_body.set_sta_key_params.key[0].pae_role = 0;
1380         msg_body.set_sta_key_params.key[0].length = keylen;
1381         memcpy(msg_body.set_sta_key_params.key[0].key, key, keylen);
1382         msg_body.set_sta_key_params.single_tid_rc = 1;
1383
1384         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1385
1386         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1387         if (ret) {
1388                 wcn36xx_err("Sending hal_set_stakey failed\n");
1389                 goto out;
1390         }
1391         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1392         if (ret) {
1393                 wcn36xx_err("hal_set_stakey response failed err=%d\n", ret);
1394                 goto out;
1395         }
1396 out:
1397         mutex_unlock(&wcn->hal_mutex);
1398         return ret;
1399 }
1400
1401 int wcn36xx_smd_set_bsskey(struct wcn36xx *wcn,
1402                            enum ani_ed_type enc_type,
1403                            u8 keyidx,
1404                            u8 keylen,
1405                            u8 *key)
1406 {
1407         struct wcn36xx_hal_set_bss_key_req_msg msg_body;
1408         int ret = 0;
1409
1410         mutex_lock(&wcn->hal_mutex);
1411         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_BSSKEY_REQ);
1412         msg_body.bss_idx = 0;
1413         msg_body.enc_type = enc_type;
1414         msg_body.num_keys = 1;
1415         msg_body.keys[0].id = keyidx;
1416         msg_body.keys[0].unicast = 0;
1417         msg_body.keys[0].direction = WCN36XX_HAL_RX_ONLY;
1418         msg_body.keys[0].pae_role = 0;
1419         msg_body.keys[0].length = keylen;
1420         memcpy(msg_body.keys[0].key, key, keylen);
1421
1422         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1423
1424         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1425         if (ret) {
1426                 wcn36xx_err("Sending hal_set_bsskey failed\n");
1427                 goto out;
1428         }
1429         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1430         if (ret) {
1431                 wcn36xx_err("hal_set_bsskey response failed err=%d\n", ret);
1432                 goto out;
1433         }
1434 out:
1435         mutex_unlock(&wcn->hal_mutex);
1436         return ret;
1437 }
1438
1439 int wcn36xx_smd_remove_stakey(struct wcn36xx *wcn,
1440                               enum ani_ed_type enc_type,
1441                               u8 keyidx,
1442                               u8 sta_index)
1443 {
1444         struct wcn36xx_hal_remove_sta_key_req_msg msg_body;
1445         int ret = 0;
1446
1447         mutex_lock(&wcn->hal_mutex);
1448         INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_STAKEY_REQ);
1449
1450         msg_body.sta_idx = sta_index;
1451         msg_body.enc_type = enc_type;
1452         msg_body.key_id = keyidx;
1453
1454         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1455
1456         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1457         if (ret) {
1458                 wcn36xx_err("Sending hal_remove_stakey failed\n");
1459                 goto out;
1460         }
1461         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1462         if (ret) {
1463                 wcn36xx_err("hal_remove_stakey response failed err=%d\n", ret);
1464                 goto out;
1465         }
1466 out:
1467         mutex_unlock(&wcn->hal_mutex);
1468         return ret;
1469 }
1470
1471 int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
1472                               enum ani_ed_type enc_type,
1473                               u8 keyidx)
1474 {
1475         struct wcn36xx_hal_remove_bss_key_req_msg msg_body;
1476         int ret = 0;
1477
1478         mutex_lock(&wcn->hal_mutex);
1479         INIT_HAL_MSG(msg_body, WCN36XX_HAL_RMV_BSSKEY_REQ);
1480         msg_body.bss_idx = 0;
1481         msg_body.enc_type = enc_type;
1482         msg_body.key_id = keyidx;
1483
1484         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1485
1486         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1487         if (ret) {
1488                 wcn36xx_err("Sending hal_remove_bsskey failed\n");
1489                 goto out;
1490         }
1491         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1492         if (ret) {
1493                 wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
1494                 goto out;
1495         }
1496 out:
1497         mutex_unlock(&wcn->hal_mutex);
1498         return ret;
1499 }
1500
1501 int wcn36xx_smd_enter_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1502 {
1503         struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1504         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1505         int ret = 0;
1506
1507         mutex_lock(&wcn->hal_mutex);
1508         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ENTER_BMPS_REQ);
1509
1510         msg_body.bss_index = vif_priv->bss_index;
1511         msg_body.tbtt = vif->bss_conf.sync_tsf;
1512         msg_body.dtim_period = vif_priv->dtim_period;
1513
1514         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1515
1516         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1517         if (ret) {
1518                 wcn36xx_err("Sending hal_enter_bmps failed\n");
1519                 goto out;
1520         }
1521         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1522         if (ret) {
1523                 wcn36xx_err("hal_enter_bmps response failed err=%d\n", ret);
1524                 goto out;
1525         }
1526 out:
1527         mutex_unlock(&wcn->hal_mutex);
1528         return ret;
1529 }
1530
1531 int wcn36xx_smd_exit_bmps(struct wcn36xx *wcn, struct ieee80211_vif *vif)
1532 {
1533         struct wcn36xx_hal_enter_bmps_req_msg msg_body;
1534         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1535         int ret = 0;
1536
1537         mutex_lock(&wcn->hal_mutex);
1538         INIT_HAL_MSG(msg_body, WCN36XX_HAL_EXIT_BMPS_REQ);
1539
1540         msg_body.bss_index = vif_priv->bss_index;
1541
1542         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1543
1544         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1545         if (ret) {
1546                 wcn36xx_err("Sending hal_exit_bmps failed\n");
1547                 goto out;
1548         }
1549         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1550         if (ret) {
1551                 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1552                 goto out;
1553         }
1554 out:
1555         mutex_unlock(&wcn->hal_mutex);
1556         return ret;
1557 }
1558 int wcn36xx_smd_set_power_params(struct wcn36xx *wcn, bool ignore_dtim)
1559 {
1560         struct wcn36xx_hal_set_power_params_req_msg msg_body;
1561         int ret = 0;
1562
1563         mutex_lock(&wcn->hal_mutex);
1564         INIT_HAL_MSG(msg_body, WCN36XX_HAL_SET_POWER_PARAMS_REQ);
1565
1566         /*
1567          * When host is down ignore every second dtim
1568          */
1569         if (ignore_dtim) {
1570                 msg_body.ignore_dtim = 1;
1571                 msg_body.dtim_period = 2;
1572         }
1573         msg_body.listen_interval = WCN36XX_LISTEN_INTERVAL(wcn);
1574
1575         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1576
1577         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1578         if (ret) {
1579                 wcn36xx_err("Sending hal_set_power_params failed\n");
1580                 goto out;
1581         }
1582
1583 out:
1584         mutex_unlock(&wcn->hal_mutex);
1585         return ret;
1586 }
1587 /* Notice: This function should be called after associated, or else it
1588  * will be invalid
1589  */
1590 int wcn36xx_smd_keep_alive_req(struct wcn36xx *wcn,
1591                                struct ieee80211_vif *vif,
1592                                int packet_type)
1593 {
1594         struct wcn36xx_hal_keep_alive_req_msg msg_body;
1595         struct wcn36xx_vif *vif_priv = (struct wcn36xx_vif *)vif->drv_priv;
1596         int ret = 0;
1597
1598         mutex_lock(&wcn->hal_mutex);
1599         INIT_HAL_MSG(msg_body, WCN36XX_HAL_KEEP_ALIVE_REQ);
1600
1601         if (packet_type == WCN36XX_HAL_KEEP_ALIVE_NULL_PKT) {
1602                 msg_body.bss_index = vif_priv->bss_index;
1603                 msg_body.packet_type = WCN36XX_HAL_KEEP_ALIVE_NULL_PKT;
1604                 msg_body.time_period = WCN36XX_KEEP_ALIVE_TIME_PERIOD;
1605         } else if (packet_type == WCN36XX_HAL_KEEP_ALIVE_UNSOLICIT_ARP_RSP) {
1606                 /* TODO: it also support ARP response type */
1607         } else {
1608                 wcn36xx_warn("unknow keep alive packet type %d\n", packet_type);
1609                 return -EINVAL;
1610         }
1611
1612         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1613
1614         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1615         if (ret) {
1616                 wcn36xx_err("Sending hal_exit_bmps failed\n");
1617                 goto out;
1618         }
1619         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1620         if (ret) {
1621                 wcn36xx_err("hal_exit_bmps response failed err=%d\n", ret);
1622                 goto out;
1623         }
1624 out:
1625         mutex_unlock(&wcn->hal_mutex);
1626         return ret;
1627 }
1628
1629 int wcn36xx_smd_dump_cmd_req(struct wcn36xx *wcn, u32 arg1, u32 arg2,
1630                              u32 arg3, u32 arg4, u32 arg5)
1631 {
1632         struct wcn36xx_hal_dump_cmd_req_msg msg_body;
1633         int ret = 0;
1634
1635         mutex_lock(&wcn->hal_mutex);
1636         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DUMP_COMMAND_REQ);
1637
1638         msg_body.arg1 = arg1;
1639         msg_body.arg2 = arg2;
1640         msg_body.arg3 = arg3;
1641         msg_body.arg4 = arg4;
1642         msg_body.arg5 = arg5;
1643
1644         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1645
1646         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1647         if (ret) {
1648                 wcn36xx_err("Sending hal_dump_cmd failed\n");
1649                 goto out;
1650         }
1651         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1652         if (ret) {
1653                 wcn36xx_err("hal_dump_cmd response failed err=%d\n", ret);
1654                 goto out;
1655         }
1656 out:
1657         mutex_unlock(&wcn->hal_mutex);
1658         return ret;
1659 }
1660
1661 static inline void set_feat_caps(u32 *bitmap,
1662                                  enum place_holder_in_cap_bitmap cap)
1663 {
1664         int arr_idx, bit_idx;
1665
1666         if (cap < 0 || cap > 127) {
1667                 wcn36xx_warn("error cap idx %d\n", cap);
1668                 return;
1669         }
1670
1671         arr_idx = cap / 32;
1672         bit_idx = cap % 32;
1673         bitmap[arr_idx] |= (1 << bit_idx);
1674 }
1675
1676 static inline int get_feat_caps(u32 *bitmap,
1677                                 enum place_holder_in_cap_bitmap cap)
1678 {
1679         int arr_idx, bit_idx;
1680         int ret = 0;
1681
1682         if (cap < 0 || cap > 127) {
1683                 wcn36xx_warn("error cap idx %d\n", cap);
1684                 return -EINVAL;
1685         }
1686
1687         arr_idx = cap / 32;
1688         bit_idx = cap % 32;
1689         ret = (bitmap[arr_idx] & (1 << bit_idx)) ? 1 : 0;
1690         return ret;
1691 }
1692
1693 static inline void clear_feat_caps(u32 *bitmap,
1694                                 enum place_holder_in_cap_bitmap cap)
1695 {
1696         int arr_idx, bit_idx;
1697
1698         if (cap < 0 || cap > 127) {
1699                 wcn36xx_warn("error cap idx %d\n", cap);
1700                 return;
1701         }
1702
1703         arr_idx = cap / 32;
1704         bit_idx = cap % 32;
1705         bitmap[arr_idx] &= ~(1 << bit_idx);
1706 }
1707
1708 int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
1709 {
1710         struct wcn36xx_hal_feat_caps_msg msg_body;
1711         int ret = 0;
1712
1713         mutex_lock(&wcn->hal_mutex);
1714         INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
1715
1716         set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
1717
1718         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1719
1720         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1721         if (ret) {
1722                 wcn36xx_err("Sending hal_feature_caps_exchange failed\n");
1723                 goto out;
1724         }
1725         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1726         if (ret) {
1727                 wcn36xx_err("hal_feature_caps_exchange response failed err=%d\n",
1728                             ret);
1729                 goto out;
1730         }
1731 out:
1732         mutex_unlock(&wcn->hal_mutex);
1733         return ret;
1734 }
1735
1736 int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn,
1737                 struct ieee80211_sta *sta,
1738                 u16 tid,
1739                 u16 *ssn,
1740                 u8 direction,
1741                 u8 sta_index)
1742 {
1743         struct wcn36xx_hal_add_ba_session_req_msg msg_body;
1744         int ret = 0;
1745
1746         mutex_lock(&wcn->hal_mutex);
1747         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_SESSION_REQ);
1748
1749         msg_body.sta_index = sta_index;
1750         memcpy(&msg_body.mac_addr, sta->addr, ETH_ALEN);
1751         msg_body.dialog_token = 0x10;
1752         msg_body.tid = tid;
1753
1754         /* Immediate BA because Delayed BA is not supported */
1755         msg_body.policy = 1;
1756         msg_body.buffer_size = WCN36XX_AGGR_BUFFER_SIZE;
1757         msg_body.timeout = 0;
1758         if (ssn)
1759                 msg_body.ssn = *ssn;
1760         msg_body.direction = direction;
1761
1762         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1763
1764         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1765         if (ret) {
1766                 wcn36xx_err("Sending hal_add_ba_session failed\n");
1767                 goto out;
1768         }
1769         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1770         if (ret) {
1771                 wcn36xx_err("hal_add_ba_session response failed err=%d\n", ret);
1772                 goto out;
1773         }
1774 out:
1775         mutex_unlock(&wcn->hal_mutex);
1776         return ret;
1777 }
1778
1779 int wcn36xx_smd_add_ba(struct wcn36xx *wcn)
1780 {
1781         struct wcn36xx_hal_add_ba_req_msg msg_body;
1782         int ret = 0;
1783
1784         mutex_lock(&wcn->hal_mutex);
1785         INIT_HAL_MSG(msg_body, WCN36XX_HAL_ADD_BA_REQ);
1786
1787         msg_body.session_id = 0;
1788         msg_body.win_size = WCN36XX_AGGR_BUFFER_SIZE;
1789
1790         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1791
1792         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1793         if (ret) {
1794                 wcn36xx_err("Sending hal_add_ba failed\n");
1795                 goto out;
1796         }
1797         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1798         if (ret) {
1799                 wcn36xx_err("hal_add_ba response failed err=%d\n", ret);
1800                 goto out;
1801         }
1802 out:
1803         mutex_unlock(&wcn->hal_mutex);
1804         return ret;
1805 }
1806
1807 int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index)
1808 {
1809         struct wcn36xx_hal_del_ba_req_msg msg_body;
1810         int ret = 0;
1811
1812         mutex_lock(&wcn->hal_mutex);
1813         INIT_HAL_MSG(msg_body, WCN36XX_HAL_DEL_BA_REQ);
1814
1815         msg_body.sta_index = sta_index;
1816         msg_body.tid = tid;
1817         msg_body.direction = 0;
1818         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1819
1820         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1821         if (ret) {
1822                 wcn36xx_err("Sending hal_del_ba failed\n");
1823                 goto out;
1824         }
1825         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1826         if (ret) {
1827                 wcn36xx_err("hal_del_ba response failed err=%d\n", ret);
1828                 goto out;
1829         }
1830 out:
1831         mutex_unlock(&wcn->hal_mutex);
1832         return ret;
1833 }
1834
1835 int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
1836 {
1837         struct wcn36xx_hal_trigger_ba_req_msg msg_body;
1838         struct wcn36xx_hal_trigget_ba_req_candidate *candidate;
1839         int ret = 0;
1840
1841         mutex_lock(&wcn->hal_mutex);
1842         INIT_HAL_MSG(msg_body, WCN36XX_HAL_TRIGGER_BA_REQ);
1843
1844         msg_body.session_id = 0;
1845         msg_body.candidate_cnt = 1;
1846         msg_body.header.len += sizeof(*candidate);
1847         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1848
1849         candidate = (struct wcn36xx_hal_trigget_ba_req_candidate *)
1850                 (wcn->hal_buf + sizeof(msg_body));
1851         candidate->sta_index = sta_index;
1852         candidate->tid_bitmap = 1;
1853
1854         ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
1855         if (ret) {
1856                 wcn36xx_err("Sending hal_trigger_ba failed\n");
1857                 goto out;
1858         }
1859         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1860         if (ret) {
1861                 wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
1862                 goto out;
1863         }
1864 out:
1865         mutex_unlock(&wcn->hal_mutex);
1866         return ret;
1867 }
1868
1869 static int wcn36xx_smd_tx_compl_ind(struct wcn36xx *wcn, void *buf, size_t len)
1870 {
1871         struct wcn36xx_hal_tx_compl_ind_msg *rsp = buf;
1872
1873         if (len != sizeof(*rsp)) {
1874                 wcn36xx_warn("Bad TX complete indication\n");
1875                 return -EIO;
1876         }
1877
1878         wcn36xx_dxe_tx_ack_ind(wcn, rsp->status);
1879
1880         return 0;
1881 }
1882
1883 static int wcn36xx_smd_missed_beacon_ind(struct wcn36xx *wcn,
1884                                          void *buf,
1885                                          size_t len)
1886 {
1887         struct wcn36xx_hal_missed_beacon_ind_msg *rsp = buf;
1888         struct ieee80211_vif *vif = NULL;
1889         struct wcn36xx_vif *tmp;
1890
1891         /* Old FW does not have bss index */
1892         if (wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
1893                 list_for_each_entry(tmp, &wcn->vif_list, list) {
1894                         wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
1895                                     tmp->bss_index);
1896                         vif = container_of((void *)tmp,
1897                                                  struct ieee80211_vif,
1898                                                  drv_priv);
1899                         ieee80211_connection_loss(vif);
1900                 }
1901                 return 0;
1902         }
1903
1904         if (len != sizeof(*rsp)) {
1905                 wcn36xx_warn("Corrupted missed beacon indication\n");
1906                 return -EIO;
1907         }
1908
1909         list_for_each_entry(tmp, &wcn->vif_list, list) {
1910                 if (tmp->bss_index == rsp->bss_index) {
1911                         wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
1912                                     rsp->bss_index);
1913                         vif = container_of((void *)tmp,
1914                                                  struct ieee80211_vif,
1915                                                  drv_priv);
1916                         ieee80211_connection_loss(vif);
1917                         return 0;
1918                 }
1919         }
1920
1921         wcn36xx_warn("BSS index %d not found\n", rsp->bss_index);
1922         return -ENOENT;
1923 }
1924
1925 static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn,
1926                                               void *buf,
1927                                               size_t len)
1928 {
1929         struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
1930         struct wcn36xx_vif *tmp;
1931         struct ieee80211_sta *sta = NULL;
1932
1933         if (len != sizeof(*rsp)) {
1934                 wcn36xx_warn("Corrupted delete sta indication\n");
1935                 return -EIO;
1936         }
1937
1938         list_for_each_entry(tmp, &wcn->vif_list, list) {
1939                 if (sta && (tmp->sta->sta_index == rsp->sta_id)) {
1940                         sta = container_of((void *)tmp->sta,
1941                                                  struct ieee80211_sta,
1942                                                  drv_priv);
1943                         wcn36xx_dbg(WCN36XX_DBG_HAL,
1944                                     "delete station indication %pM index %d\n",
1945                                     rsp->addr2,
1946                                     rsp->sta_id);
1947                         ieee80211_report_low_ack(sta, 0);
1948                         return 0;
1949                 }
1950         }
1951
1952         wcn36xx_warn("STA with addr %pM and index %d not found\n",
1953                      rsp->addr2,
1954                      rsp->sta_id);
1955         return -ENOENT;
1956 }
1957
1958 int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value)
1959 {
1960         struct wcn36xx_hal_update_cfg_req_msg msg_body, *body;
1961         size_t len;
1962         int ret = 0;
1963
1964         mutex_lock(&wcn->hal_mutex);
1965         INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_CFG_REQ);
1966
1967         PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
1968
1969         body = (struct wcn36xx_hal_update_cfg_req_msg *) wcn->hal_buf;
1970         len = msg_body.header.len;
1971
1972         put_cfg_tlv_u32(wcn, &len, cfg_id, value);
1973         body->header.len = len;
1974         body->len = len - sizeof(*body);
1975
1976         ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
1977         if (ret) {
1978                 wcn36xx_err("Sending hal_update_cfg failed\n");
1979                 goto out;
1980         }
1981         ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
1982         if (ret) {
1983                 wcn36xx_err("hal_update_cfg response failed err=%d\n", ret);
1984                 goto out;
1985         }
1986 out:
1987         mutex_unlock(&wcn->hal_mutex);
1988         return ret;
1989 }
1990 static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
1991 {
1992         struct wcn36xx_hal_msg_header *msg_header = buf;
1993         struct wcn36xx_hal_ind_msg *msg_ind;
1994         wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len);
1995
1996         switch (msg_header->msg_type) {
1997         case WCN36XX_HAL_START_RSP:
1998         case WCN36XX_HAL_CONFIG_STA_RSP:
1999         case WCN36XX_HAL_CONFIG_BSS_RSP:
2000         case WCN36XX_HAL_ADD_STA_SELF_RSP:
2001         case WCN36XX_HAL_STOP_RSP:
2002         case WCN36XX_HAL_DEL_STA_SELF_RSP:
2003         case WCN36XX_HAL_DELETE_STA_RSP:
2004         case WCN36XX_HAL_INIT_SCAN_RSP:
2005         case WCN36XX_HAL_START_SCAN_RSP:
2006         case WCN36XX_HAL_END_SCAN_RSP:
2007         case WCN36XX_HAL_FINISH_SCAN_RSP:
2008         case WCN36XX_HAL_DOWNLOAD_NV_RSP:
2009         case WCN36XX_HAL_DELETE_BSS_RSP:
2010         case WCN36XX_HAL_SEND_BEACON_RSP:
2011         case WCN36XX_HAL_SET_LINK_ST_RSP:
2012         case WCN36XX_HAL_UPDATE_PROBE_RSP_TEMPLATE_RSP:
2013         case WCN36XX_HAL_SET_BSSKEY_RSP:
2014         case WCN36XX_HAL_SET_STAKEY_RSP:
2015         case WCN36XX_HAL_RMV_STAKEY_RSP:
2016         case WCN36XX_HAL_RMV_BSSKEY_RSP:
2017         case WCN36XX_HAL_ENTER_BMPS_RSP:
2018         case WCN36XX_HAL_SET_POWER_PARAMS_RSP:
2019         case WCN36XX_HAL_EXIT_BMPS_RSP:
2020         case WCN36XX_HAL_KEEP_ALIVE_RSP:
2021         case WCN36XX_HAL_DUMP_COMMAND_RSP:
2022         case WCN36XX_HAL_ADD_BA_SESSION_RSP:
2023         case WCN36XX_HAL_ADD_BA_RSP:
2024         case WCN36XX_HAL_DEL_BA_RSP:
2025         case WCN36XX_HAL_TRIGGER_BA_RSP:
2026         case WCN36XX_HAL_UPDATE_CFG_RSP:
2027         case WCN36XX_HAL_JOIN_RSP:
2028         case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP:
2029         case WCN36XX_HAL_CH_SWITCH_RSP:
2030         case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP:
2031                 memcpy(wcn->hal_buf, buf, len);
2032                 wcn->hal_rsp_len = len;
2033                 complete(&wcn->hal_rsp_compl);
2034                 break;
2035
2036         case WCN36XX_HAL_OTA_TX_COMPL_IND:
2037         case WCN36XX_HAL_MISSED_BEACON_IND:
2038         case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2039                 mutex_lock(&wcn->hal_ind_mutex);
2040                 msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
2041                 msg_ind->msg_len = len;
2042                 msg_ind->msg = kmalloc(len, GFP_KERNEL);
2043                 memcpy(msg_ind->msg, buf, len);
2044                 list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
2045                 queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
2046                 wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
2047                 mutex_unlock(&wcn->hal_ind_mutex);
2048                 break;
2049         default:
2050                 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2051                               msg_header->msg_type);
2052         }
2053 }
2054 static void wcn36xx_ind_smd_work(struct work_struct *work)
2055 {
2056         struct wcn36xx *wcn =
2057                 container_of(work, struct wcn36xx, hal_ind_work);
2058         struct wcn36xx_hal_msg_header *msg_header;
2059         struct wcn36xx_hal_ind_msg *hal_ind_msg;
2060
2061         mutex_lock(&wcn->hal_ind_mutex);
2062
2063         hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
2064                                        struct wcn36xx_hal_ind_msg,
2065                                        list);
2066
2067         msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
2068
2069         switch (msg_header->msg_type) {
2070         case WCN36XX_HAL_OTA_TX_COMPL_IND:
2071                 wcn36xx_smd_tx_compl_ind(wcn,
2072                                          hal_ind_msg->msg,
2073                                          hal_ind_msg->msg_len);
2074                 break;
2075         case WCN36XX_HAL_MISSED_BEACON_IND:
2076                 wcn36xx_smd_missed_beacon_ind(wcn,
2077                                               hal_ind_msg->msg,
2078                                               hal_ind_msg->msg_len);
2079                 break;
2080         case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
2081                 wcn36xx_smd_delete_sta_context_ind(wcn,
2082                                                    hal_ind_msg->msg,
2083                                                    hal_ind_msg->msg_len);
2084                 break;
2085         default:
2086                 wcn36xx_err("SMD_EVENT (%d) not supported\n",
2087                               msg_header->msg_type);
2088         }
2089         list_del(wcn->hal_ind_queue.next);
2090         kfree(hal_ind_msg->msg);
2091         kfree(hal_ind_msg);
2092         mutex_unlock(&wcn->hal_ind_mutex);
2093 }
2094 int wcn36xx_smd_open(struct wcn36xx *wcn)
2095 {
2096         int ret = 0;
2097         wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind");
2098         if (!wcn->hal_ind_wq) {
2099                 wcn36xx_err("failed to allocate wq\n");
2100                 ret = -ENOMEM;
2101                 goto out;
2102         }
2103         INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
2104         INIT_LIST_HEAD(&wcn->hal_ind_queue);
2105         mutex_init(&wcn->hal_ind_mutex);
2106
2107         ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
2108         if (ret) {
2109                 wcn36xx_err("failed to open control channel\n");
2110                 goto free_wq;
2111         }
2112
2113         return ret;
2114
2115 free_wq:
2116         destroy_workqueue(wcn->hal_ind_wq);
2117 out:
2118         return ret;
2119 }
2120
2121 void wcn36xx_smd_close(struct wcn36xx *wcn)
2122 {
2123         wcn->ctrl_ops->close();
2124         destroy_workqueue(wcn->hal_ind_wq);
2125         mutex_destroy(&wcn->hal_ind_mutex);
2126 }