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