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