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