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