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